From bac9bd940b66833e02fbdf7841fe50dfe0daffd0 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Wed, 3 Dec 2025 11:58:39 +0100 Subject: [PATCH 01/55] feat: add config-registry-controller package --- .../config-registry-controller/CHANGELOG.md | 10 + packages/config-registry-controller/LICENSE | 20 ++ packages/config-registry-controller/README.md | 15 ++ .../config-registry-controller/jest.config.js | 26 +++ .../config-registry-controller/package.json | 73 +++++++ .../src/ConfigRegistryController.ts | 195 ++++++++++++++++++ .../config-registry-controller/src/index.ts | 14 ++ .../tsconfig.build.json | 13 ++ .../config-registry-controller/tsconfig.json | 11 + .../config-registry-controller/typedoc.json | 7 + 10 files changed, 384 insertions(+) create mode 100644 packages/config-registry-controller/CHANGELOG.md create mode 100644 packages/config-registry-controller/LICENSE create mode 100644 packages/config-registry-controller/README.md create mode 100644 packages/config-registry-controller/jest.config.js create mode 100644 packages/config-registry-controller/package.json create mode 100644 packages/config-registry-controller/src/ConfigRegistryController.ts create mode 100644 packages/config-registry-controller/src/index.ts create mode 100644 packages/config-registry-controller/tsconfig.build.json create mode 100644 packages/config-registry-controller/tsconfig.json create mode 100644 packages/config-registry-controller/typedoc.json diff --git a/packages/config-registry-controller/CHANGELOG.md b/packages/config-registry-controller/CHANGELOG.md new file mode 100644 index 00000000000..b518709c7b8 --- /dev/null +++ b/packages/config-registry-controller/CHANGELOG.md @@ -0,0 +1,10 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +[Unreleased]: https://github.com/MetaMask/core/ diff --git a/packages/config-registry-controller/LICENSE b/packages/config-registry-controller/LICENSE new file mode 100644 index 00000000000..7d002dced3a --- /dev/null +++ b/packages/config-registry-controller/LICENSE @@ -0,0 +1,20 @@ +MIT License + +Copyright (c) 2025 MetaMask + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE diff --git a/packages/config-registry-controller/README.md b/packages/config-registry-controller/README.md new file mode 100644 index 00000000000..1f849943f62 --- /dev/null +++ b/packages/config-registry-controller/README.md @@ -0,0 +1,15 @@ +# `@metamask/config-registry-controller` + +Manages configuration registry for MetaMask + +## Installation + +`yarn add @metamask/config-registry-controller` + +or + +`npm install @metamask/config-registry-controller` + +## Contributing + +This package is part of a monorepo. Instructions for contributing can be found in the [monorepo README](https://github.com/MetaMask/core#readme). diff --git a/packages/config-registry-controller/jest.config.js b/packages/config-registry-controller/jest.config.js new file mode 100644 index 00000000000..ca084133399 --- /dev/null +++ b/packages/config-registry-controller/jest.config.js @@ -0,0 +1,26 @@ +/* + * For a detailed explanation regarding each configuration property and type check, visit: + * https://jestjs.io/docs/configuration + */ + +const merge = require('deepmerge'); +const path = require('path'); + +const baseConfig = require('../../jest.config.packages'); + +const displayName = path.basename(__dirname); + +module.exports = merge(baseConfig, { + // The display name when running multiple projects + displayName, + + // An object that configures minimum threshold enforcement for coverage results + coverageThreshold: { + global: { + branches: 100, + functions: 100, + lines: 100, + statements: 100, + }, + }, +}); diff --git a/packages/config-registry-controller/package.json b/packages/config-registry-controller/package.json new file mode 100644 index 00000000000..b63861f4bb1 --- /dev/null +++ b/packages/config-registry-controller/package.json @@ -0,0 +1,73 @@ +{ + "name": "@metamask/config-registry-controller", + "version": "0.0.1", + "description": "Manages configuration registry for MetaMask", + "keywords": [ + "MetaMask", + "Ethereum" + ], + "homepage": "https://github.com/MetaMask/core/tree/main/packages/config-registry-controller#readme", + "bugs": { + "url": "https://github.com/MetaMask/core/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/MetaMask/core.git" + }, + "license": "MIT", + "sideEffects": false, + "exports": { + ".": { + "import": { + "types": "./dist/index.d.mts", + "default": "./dist/index.mjs" + }, + "require": { + "types": "./dist/index.d.cts", + "default": "./dist/index.cjs" + } + }, + "./package.json": "./package.json" + }, + "main": "./dist/index.cjs", + "types": "./dist/index.d.cts", + "files": [ + "dist/" + ], + "scripts": { + "build": "ts-bridge --project tsconfig.build.json --verbose --clean --no-references", + "build:all": "ts-bridge --project tsconfig.build.json --verbose --clean", + "build:docs": "typedoc", + "changelog:update": "../../scripts/update-changelog.sh @metamask/config-registry-controller", + "changelog:validate": "../../scripts/validate-changelog.sh @metamask/config-registry-controller", + "publish:preview": "yarn npm publish --tag preview", + "since-latest-release": "../../scripts/since-latest-release.sh", + "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", + "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", + "test:verbose": "NODE_OPTIONS=--experimental-vm-modules jest --verbose", + "test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch" + }, + "dependencies": { + "@metamask/base-controller": "^9.0.0", + "@metamask/messenger": "^0.3.0" + }, + "devDependencies": { + "@lavamoat/allow-scripts": "^3.0.4", + "@metamask/auto-changelog": "^3.4.4", + "@ts-bridge/cli": "^0.6.4", + "@types/jest": "^27.4.1", + "deepmerge": "^4.2.2", + "jest": "^27.5.1", + "ts-jest": "^27.1.4", + "typedoc": "^0.24.8", + "typedoc-plugin-missing-exports": "^2.0.0", + "typescript": "~5.3.3" + }, + "engines": { + "node": "^18.18 || >=20" + }, + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org/" + } +} diff --git a/packages/config-registry-controller/src/ConfigRegistryController.ts b/packages/config-registry-controller/src/ConfigRegistryController.ts new file mode 100644 index 00000000000..16db4159b84 --- /dev/null +++ b/packages/config-registry-controller/src/ConfigRegistryController.ts @@ -0,0 +1,195 @@ +import { + BaseController, + type ControllerGetStateAction, + type ControllerStateChangeEvent, +} from '@metamask/base-controller'; +import type { Messenger } from '@metamask/messenger'; +import type { Json } from '@metamask/utils'; + +const controllerName = 'ConfigRegistryController'; + +/** + * Configuration entry in the registry. + */ +export type RegistryConfigEntry = { + key: string; + value: Json; + metadata?: Json; +}; + +/** + * The state of the {@link ConfigRegistryController}. + * + * @property configs - A map of configuration keys to their entries. + */ +export type ConfigRegistryState = { + configs: Record; +}; + +const stateMetadata = { + configs: { + persist: true, + anonymous: false, + includeInStateLogs: false, + includeInDebugSnapshot: true, + usedInUi: true, + }, +}; + +export type ConfigRegistryControllerStateChangeEvent = + ControllerStateChangeEvent; + +export type ConfigRegistryControllerGetStateAction = ControllerGetStateAction< + typeof controllerName, + ConfigRegistryState +>; + +export type ConfigRegistryControllerGetConfigAction = { + type: `${typeof controllerName}:getConfig`; + handler: ConfigRegistryController['getConfig']; +}; + +export type ConfigRegistryControllerSetConfigAction = { + type: `${typeof controllerName}:setConfig`; + handler: ConfigRegistryController['setConfig']; +}; + +export type ConfigRegistryControllerGetAllConfigsAction = { + type: `${typeof controllerName}:getAllConfigs`; + handler: ConfigRegistryController['getAllConfigs']; +}; + +export type ConfigRegistryControllerActions = + | ConfigRegistryControllerGetStateAction + | ConfigRegistryControllerGetConfigAction + | ConfigRegistryControllerSetConfigAction + | ConfigRegistryControllerGetAllConfigsAction; + +export type ConfigRegistryControllerEvents = + ConfigRegistryControllerStateChangeEvent; + +export type ConfigRegistryMessenger = Messenger< + typeof controllerName, + ConfigRegistryControllerActions, + ConfigRegistryControllerEvents +>; + +/** + * Options for constructing a ConfigRegistryController. + */ +export type ConfigRegistryControllerOptions = { + messenger: ConfigRegistryMessenger; + state?: Partial; +}; + +/** + * Controller for managing a configuration registry. + */ +export class ConfigRegistryController extends BaseController< + typeof controllerName, + ConfigRegistryState, + ConfigRegistryMessenger +> { + /** + * Creates a ConfigRegistryController instance. + * + * @param options - Constructor options. + * @param options.messenger - A reference to the messaging system. + * @param options.state - Initial state to set on this controller. + */ + constructor({ messenger, state = {} }: ConfigRegistryControllerOptions) { + super({ + name: controllerName, + metadata: stateMetadata, + messenger, + state: { + configs: {}, + ...state, + }, + }); + + this.messenger.registerActionHandler( + `${controllerName}:getConfig`, + (key: string) => this.getConfig(key), + ); + + this.messenger.registerActionHandler( + `${controllerName}:setConfig`, + (key: string, value: Json, metadata?: Json) => + this.setConfig(key, value, metadata), + ); + + this.messenger.registerActionHandler( + `${controllerName}:getAllConfigs`, + () => this.getAllConfigs(), + ); + } + + /** + * Gets a specific configuration entry by key. + * + * @param key - The configuration key. + * @returns The configuration entry, or undefined if not found. + */ + getConfig(key: string): RegistryConfigEntry | undefined { + return this.state.configs[key]; + } + + /** + * Gets all configuration entries. + * + * @returns A copy of all configuration entries. + */ + getAllConfigs(): Record { + return { ...this.state.configs }; + } + + /** + * Gets the value of a specific configuration entry by key. + * + * @param key - The configuration key. + * @returns The configuration value, or undefined if not found. + */ + getConfigValue(key: string): T | undefined { + const entry = this.state.configs[key]; + return entry?.value as T | undefined; + } + + /** + * Sets a configuration entry in the registry. + * + * @param key - The configuration key. + * @param value - The configuration value. + * @param metadata - Optional metadata for the configuration entry. + */ + setConfig(key: string, value: Json, metadata?: Json): void { + this.update((state) => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (state.configs as any)[key] = { + key, + value, + metadata, + }; + }); + } + + /** + * Removes a configuration entry from the registry. + * + * @param key - The configuration key. + */ + removeConfig(key: string): void { + this.update((state) => { + delete state.configs[key]; + }); + } + + /** + * Clears all configuration entries from the registry. + */ + clearConfigs(): void { + this.update((state) => { + state.configs = {}; + }); + } +} diff --git a/packages/config-registry-controller/src/index.ts b/packages/config-registry-controller/src/index.ts new file mode 100644 index 00000000000..88693a16f3c --- /dev/null +++ b/packages/config-registry-controller/src/index.ts @@ -0,0 +1,14 @@ +export type { + RegistryConfigEntry, + ConfigRegistryState, + ConfigRegistryControllerOptions, + ConfigRegistryControllerActions, + ConfigRegistryControllerGetConfigAction, + ConfigRegistryControllerSetConfigAction, + ConfigRegistryControllerGetAllConfigsAction, + ConfigRegistryControllerGetStateAction, + ConfigRegistryControllerEvents, + ConfigRegistryControllerStateChangeEvent, + ConfigRegistryMessenger, +} from './ConfigRegistryController'; +export { ConfigRegistryController } from './ConfigRegistryController'; diff --git a/packages/config-registry-controller/tsconfig.build.json b/packages/config-registry-controller/tsconfig.build.json new file mode 100644 index 00000000000..931c4d6594b --- /dev/null +++ b/packages/config-registry-controller/tsconfig.build.json @@ -0,0 +1,13 @@ +{ + "extends": "../../tsconfig.packages.build.json", + "compilerOptions": { + "baseUrl": "./", + "outDir": "./dist", + "rootDir": "./src" + }, + "references": [ + { "path": "../base-controller/tsconfig.build.json" }, + { "path": "../messenger/tsconfig.build.json" } + ], + "include": ["../../types", "./src"] +} diff --git a/packages/config-registry-controller/tsconfig.json b/packages/config-registry-controller/tsconfig.json new file mode 100644 index 00000000000..8af2380112d --- /dev/null +++ b/packages/config-registry-controller/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.packages.json", + "compilerOptions": { + "baseUrl": "./" + }, + "references": [ + { "path": "../base-controller" }, + { "path": "../messenger" } + ], + "include": ["../../types", "./src"] +} diff --git a/packages/config-registry-controller/typedoc.json b/packages/config-registry-controller/typedoc.json new file mode 100644 index 00000000000..c9da015dbf8 --- /dev/null +++ b/packages/config-registry-controller/typedoc.json @@ -0,0 +1,7 @@ +{ + "entryPoints": ["./src/index.ts"], + "excludePrivate": true, + "hideGenerator": true, + "out": "docs", + "tsconfig": "./tsconfig.build.json" +} From c36c531122f2e6ca066c98e3f7adaf2e28eb45f5 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Wed, 3 Dec 2025 15:04:47 +0100 Subject: [PATCH 02/55] chore: continue adding config registry controller --- README.md | 8 ++++++++ tsconfig.build.json | 1 + tsconfig.json | 1 + yarn.lock | 20 ++++++++++++++++++++ 4 files changed, 30 insertions(+) diff --git a/README.md b/README.md index 1063ee58d1b..123b1626765 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ Each package in this repository has its own README where you can find installati - [`@metamask/chain-agnostic-permission`](packages/chain-agnostic-permission) - [`@metamask/claims-controller`](packages/claims-controller) - [`@metamask/composable-controller`](packages/composable-controller) +- [`@metamask/config-registry-controller`](packages/config-registry-controller) - [`@metamask/controller-utils`](packages/controller-utils) - [`@metamask/core-backend`](packages/core-backend) - [`@metamask/delegation-controller`](packages/delegation-controller) @@ -78,6 +79,7 @@ Each package in this repository has its own README where you can find installati - [`@metamask/selected-network-controller`](packages/selected-network-controller) - [`@metamask/shield-controller`](packages/shield-controller) - [`@metamask/signature-controller`](packages/signature-controller) +- [`@metamask/storage-service`](packages/storage-service) - [`@metamask/subscription-controller`](packages/subscription-controller) - [`@metamask/token-search-discovery-controller`](packages/token-search-discovery-controller) - [`@metamask/transaction-controller`](packages/transaction-controller) @@ -107,6 +109,7 @@ linkStyle default opacity:0.5 chain_agnostic_permission(["@metamask/chain-agnostic-permission"]); claims_controller(["@metamask/claims-controller"]); composable_controller(["@metamask/composable-controller"]); + config_registry_controller(["@metamask/config-registry-controller"]); controller_utils(["@metamask/controller-utils"]); core_backend(["@metamask/core-backend"]); delegation_controller(["@metamask/delegation-controller"]); @@ -150,6 +153,7 @@ linkStyle default opacity:0.5 selected_network_controller(["@metamask/selected-network-controller"]); shield_controller(["@metamask/shield-controller"]); signature_controller(["@metamask/signature-controller"]); + storage_service(["@metamask/storage-service"]); subscription_controller(["@metamask/subscription-controller"]); token_search_discovery_controller(["@metamask/token-search-discovery-controller"]); transaction_controller(["@metamask/transaction-controller"]); @@ -343,9 +347,12 @@ linkStyle default opacity:0.5 preferences_controller --> controller_utils; preferences_controller --> keyring_controller; preferences_controller --> messenger; + profile_metrics_controller --> accounts_controller; profile_metrics_controller --> base_controller; profile_metrics_controller --> controller_utils; + profile_metrics_controller --> keyring_controller; profile_metrics_controller --> messenger; + profile_metrics_controller --> polling_controller; profile_metrics_controller --> profile_sync_controller; profile_sync_controller --> address_book_controller; profile_sync_controller --> base_controller; @@ -382,6 +389,7 @@ linkStyle default opacity:0.5 signature_controller --> logging_controller; signature_controller --> messenger; signature_controller --> network_controller; + storage_service --> messenger; subscription_controller --> base_controller; subscription_controller --> controller_utils; subscription_controller --> messenger; diff --git a/tsconfig.build.json b/tsconfig.build.json index 10a7c244911..ce71fd900f6 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -23,6 +23,7 @@ { "path": "./packages/chain-agnostic-permission/tsconfig.build.json" }, { "path": "./packages/claims-controller/tsconfig.build.json" }, { "path": "./packages/composable-controller/tsconfig.build.json" }, + { "path": "./packages/config-registry-controller/tsconfig.build.json" }, { "path": "./packages/controller-utils/tsconfig.build.json" }, { "path": "./packages/delegation-controller/tsconfig.build.json" }, { "path": "./packages/earn-controller/tsconfig.build.json" }, diff --git a/tsconfig.json b/tsconfig.json index 34a9641f246..6314d7d5bd1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -23,6 +23,7 @@ { "path": "./packages/chain-agnostic-permission" }, { "path": "./packages/claims-controller" }, { "path": "./packages/composable-controller" }, + { "path": "./packages/config-registry-controller" }, { "path": "./packages/controller-utils" }, { "path": "./packages/core-backend" }, { "path": "./packages/delegation-controller" }, diff --git a/yarn.lock b/yarn.lock index e47b96e3860..64dd1ccd37a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2964,6 +2964,26 @@ __metadata: languageName: unknown linkType: soft +"@metamask/config-registry-controller@workspace:packages/config-registry-controller": + version: 0.0.0-use.local + resolution: "@metamask/config-registry-controller@workspace:packages/config-registry-controller" + dependencies: + "@lavamoat/allow-scripts": "npm:^3.0.4" + "@metamask/auto-changelog": "npm:^3.4.4" + "@metamask/base-controller": "npm:^9.0.0" + "@metamask/controller-utils": "npm:^11.16.0" + "@metamask/messenger": "npm:^0.3.0" + "@ts-bridge/cli": "npm:^0.6.4" + "@types/jest": "npm:^27.4.1" + deepmerge: "npm:^4.2.2" + jest: "npm:^27.5.1" + ts-jest: "npm:^27.1.4" + typedoc: "npm:^0.24.8" + typedoc-plugin-missing-exports: "npm:^2.0.0" + typescript: "npm:~5.3.3" + languageName: unknown + linkType: soft + "@metamask/contract-metadata@npm:^2.4.0": version: 2.5.0 resolution: "@metamask/contract-metadata@npm:2.5.0" From be2165aca6661b810ce597e076010838d5dea736 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Thu, 4 Dec 2025 18:27:36 +0100 Subject: [PATCH 03/55] feat: add polling and fallback support --- .../config-registry-controller/package.json | 3 +- .../src/ConfigRegistryController.ts | 167 +++++++++++- .../config-registry-controller/src/index.ts | 2 + .../tsconfig.build.json | 3 +- .../config-registry-controller/tsconfig.json | 3 +- yarn.lock | 255 +++++++++++++++++- 6 files changed, 419 insertions(+), 14 deletions(-) diff --git a/packages/config-registry-controller/package.json b/packages/config-registry-controller/package.json index b63861f4bb1..8ffb4c459fe 100644 --- a/packages/config-registry-controller/package.json +++ b/packages/config-registry-controller/package.json @@ -49,7 +49,8 @@ }, "dependencies": { "@metamask/base-controller": "^9.0.0", - "@metamask/messenger": "^0.3.0" + "@metamask/messenger": "^0.3.0", + "@metamask/polling-controller": "^1.0.0" }, "devDependencies": { "@lavamoat/allow-scripts": "^3.0.4", diff --git a/packages/config-registry-controller/src/ConfigRegistryController.ts b/packages/config-registry-controller/src/ConfigRegistryController.ts index 16db4159b84..2da6c653b99 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.ts @@ -1,13 +1,16 @@ import { - BaseController, type ControllerGetStateAction, type ControllerStateChangeEvent, } from '@metamask/base-controller'; import type { Messenger } from '@metamask/messenger'; +import { StaticIntervalPollingController } from '@metamask/polling-controller'; import type { Json } from '@metamask/utils'; const controllerName = 'ConfigRegistryController'; +// 24 hours in milliseconds +const DEFAULT_POLLING_INTERVAL = 24 * 60 * 60 * 1000; // 86400000ms + /** * Configuration entry in the registry. */ @@ -21,9 +24,15 @@ export type RegistryConfigEntry = { * The state of the {@link ConfigRegistryController}. * * @property configs - A map of configuration keys to their entries. + * @property version - The version of the configuration from the API. + * @property lastFetched - Timestamp of the last successful fetch. + * @property fetchError - Error message if the last fetch failed, null otherwise. */ export type ConfigRegistryState = { configs: Record; + version: string | null; + lastFetched: number | null; + fetchError: string | null; }; const stateMetadata = { @@ -34,8 +43,41 @@ const stateMetadata = { includeInDebugSnapshot: true, usedInUi: true, }, + version: { + persist: true, + anonymous: false, + includeInStateLogs: true, + includeInDebugSnapshot: true, + usedInUi: false, + }, + lastFetched: { + persist: true, + anonymous: false, + includeInStateLogs: true, + includeInDebugSnapshot: true, + usedInUi: false, + }, + fetchError: { + persist: true, + anonymous: false, + includeInStateLogs: true, + includeInDebugSnapshot: true, + usedInUi: false, + }, }; +/** + * Default fallback configuration. + * This will be used when the API is unavailable. + */ +const DEFAULT_FALLBACK_CONFIG: Record = {}; + +/** + * Polling input type for the controller. + * For now, it's empty, but can be extended later if needed. + */ +type ConfigRegistryPollingInput = Record; + export type ConfigRegistryControllerStateChangeEvent = ControllerStateChangeEvent; @@ -59,11 +101,23 @@ export type ConfigRegistryControllerGetAllConfigsAction = { handler: ConfigRegistryController['getAllConfigs']; }; +export type ConfigRegistryControllerStartPollingAction = { + type: `${typeof controllerName}:startPolling`; + handler: (input: ConfigRegistryPollingInput) => string; +}; + +export type ConfigRegistryControllerStopPollingAction = { + type: `${typeof controllerName}:stopPolling`; + handler: () => void; +}; + export type ConfigRegistryControllerActions = | ConfigRegistryControllerGetStateAction | ConfigRegistryControllerGetConfigAction | ConfigRegistryControllerSetConfigAction - | ConfigRegistryControllerGetAllConfigsAction; + | ConfigRegistryControllerGetAllConfigsAction + | ConfigRegistryControllerStartPollingAction + | ConfigRegistryControllerStopPollingAction; export type ConfigRegistryControllerEvents = ConfigRegistryControllerStateChangeEvent; @@ -80,34 +134,51 @@ export type ConfigRegistryMessenger = Messenger< export type ConfigRegistryControllerOptions = { messenger: ConfigRegistryMessenger; state?: Partial; + pollingInterval?: number; + fallbackConfig?: Record; }; /** - * Controller for managing a configuration registry. + * Controller for managing a configuration registry with dynamic updates from a remote API. */ -export class ConfigRegistryController extends BaseController< +export class ConfigRegistryController extends StaticIntervalPollingController()< typeof controllerName, ConfigRegistryState, ConfigRegistryMessenger > { + readonly #fallbackConfig: Record; + /** * Creates a ConfigRegistryController instance. * * @param options - Constructor options. * @param options.messenger - A reference to the messaging system. * @param options.state - Initial state to set on this controller. + * @param options.pollingInterval - Polling interval in milliseconds. Defaults to 24 hours. + * @param options.fallbackConfig - Fallback configuration to use when API fails. */ - constructor({ messenger, state = {} }: ConfigRegistryControllerOptions) { + constructor({ + messenger, + state = {}, + pollingInterval = DEFAULT_POLLING_INTERVAL, + fallbackConfig = DEFAULT_FALLBACK_CONFIG, + }: ConfigRegistryControllerOptions) { super({ name: controllerName, metadata: stateMetadata, messenger, state: { configs: {}, + version: null, + lastFetched: null, + fetchError: null, ...state, }, }); + this.setIntervalLength(pollingInterval); + this.#fallbackConfig = fallbackConfig; + this.messenger.registerActionHandler( `${controllerName}:getConfig`, (key: string) => this.getConfig(key), @@ -123,6 +194,75 @@ export class ConfigRegistryController extends BaseController< `${controllerName}:getAllConfigs`, () => this.getAllConfigs(), ); + + this.messenger.registerActionHandler( + `${controllerName}:startPolling`, + (input: ConfigRegistryPollingInput) => this.startPolling(input), + ); + + this.messenger.registerActionHandler(`${controllerName}:stopPolling`, () => + this.stopPolling(), + ); + } + + /** + * Executes a poll to fetch configuration from the API. + * This method is called automatically by the polling controller. + * + * @param _input - Polling input (unused for now). + */ + async _executePoll(_input: ConfigRegistryPollingInput): Promise { + // TODO: This will be implemented in Task 2 (API service fetcher) + // For now, this is a placeholder that will use fallback + try { + // Placeholder: Will call API service here + // const apiResponse = await this.#apiService.fetchConfig(); + // Once implemented in Task 2, will update state with: + // this.update((state) => { + // state.configs = apiResponse.configs; + // state.version = apiResponse.version; + // state.lastFetched = Date.now(); + // state.fetchError = null; + // }); + + // For now, if we have no configs, use fallback + if (Object.keys(this.state.configs).length === 0) { + this.#useFallbackConfig(); + } + } catch (error) { + this.#handleFetchError(error); + } + } + + /** + * Uses the fallback configuration when API fails. + */ + #useFallbackConfig(): void { + this.update((state) => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (state.configs as any) = { ...this.#fallbackConfig }; + state.fetchError = 'Using fallback configuration - API unavailable'; + // Don't update lastFetched when using fallback + }); + } + + /** + * Handles errors during configuration fetch. + * + * @param error - The error that occurred. + */ + #handleFetchError(error: unknown): void { + const errorMessage = + error instanceof Error ? error.message : 'Unknown error occurred'; + + this.update((state) => { + state.fetchError = errorMessage; + // Use fallback if we have no configs + if (Object.keys(state.configs).length === 0) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (state.configs as any) = { ...this.#fallbackConfig }; + } + }); } /** @@ -192,4 +332,21 @@ export class ConfigRegistryController extends BaseController< state.configs = {}; }); } + + /** + * Starts polling for configuration updates. + * + * @param input - Polling input (empty object for now). + * @returns A polling token that can be used to stop polling. + */ + startPolling(input: ConfigRegistryPollingInput = {}): string { + return super.startPolling(input); + } + + /** + * Stops polling for configuration updates. + */ + stopPolling(): void { + this.stopAllPolling(); + } } diff --git a/packages/config-registry-controller/src/index.ts b/packages/config-registry-controller/src/index.ts index 88693a16f3c..0bea3bf4e34 100644 --- a/packages/config-registry-controller/src/index.ts +++ b/packages/config-registry-controller/src/index.ts @@ -7,6 +7,8 @@ export type { ConfigRegistryControllerSetConfigAction, ConfigRegistryControllerGetAllConfigsAction, ConfigRegistryControllerGetStateAction, + ConfigRegistryControllerStartPollingAction, + ConfigRegistryControllerStopPollingAction, ConfigRegistryControllerEvents, ConfigRegistryControllerStateChangeEvent, ConfigRegistryMessenger, diff --git a/packages/config-registry-controller/tsconfig.build.json b/packages/config-registry-controller/tsconfig.build.json index 931c4d6594b..85c1ead8f42 100644 --- a/packages/config-registry-controller/tsconfig.build.json +++ b/packages/config-registry-controller/tsconfig.build.json @@ -7,7 +7,8 @@ }, "references": [ { "path": "../base-controller/tsconfig.build.json" }, - { "path": "../messenger/tsconfig.build.json" } + { "path": "../messenger/tsconfig.build.json" }, + { "path": "../polling-controller/tsconfig.build.json" } ], "include": ["../../types", "./src"] } diff --git a/packages/config-registry-controller/tsconfig.json b/packages/config-registry-controller/tsconfig.json index 8af2380112d..6e5d9ecd045 100644 --- a/packages/config-registry-controller/tsconfig.json +++ b/packages/config-registry-controller/tsconfig.json @@ -5,7 +5,8 @@ }, "references": [ { "path": "../base-controller" }, - { "path": "../messenger" } + { "path": "../messenger" }, + { "path": "../polling-controller" } ], "include": ["../../types", "./src"] } diff --git a/yarn.lock b/yarn.lock index 64dd1ccd37a..05f68519f65 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2385,7 +2385,7 @@ __metadata: languageName: node linkType: hard -"@metamask/abi-utils@npm:^2.0.3": +"@metamask/abi-utils@npm:^2.0.3, @metamask/abi-utils@npm:^2.0.4": version: 2.0.4 resolution: "@metamask/abi-utils@npm:2.0.4" dependencies: @@ -2761,6 +2761,16 @@ __metadata: languageName: node linkType: hard +"@metamask/base-controller@npm:^3.2.3": + version: 3.2.3 + resolution: "@metamask/base-controller@npm:3.2.3" + dependencies: + "@metamask/utils": "npm:^8.1.0" + immer: "npm:^9.0.6" + checksum: 10/1a3005f4143f0a3e37094ce389ae9c2010194672d67c1b115a401379c1b712fb3d7ce8f1cbc8a4d21cffba61aafba6dc1aaae12172e57b9f14021a2505fadafe + languageName: node + linkType: hard + "@metamask/base-controller@npm:^8.0.1, @metamask/base-controller@npm:^8.4.2": version: 8.4.2 resolution: "@metamask/base-controller@npm:8.4.2" @@ -2971,8 +2981,8 @@ __metadata: "@lavamoat/allow-scripts": "npm:^3.0.4" "@metamask/auto-changelog": "npm:^3.4.4" "@metamask/base-controller": "npm:^9.0.0" - "@metamask/controller-utils": "npm:^11.16.0" "@metamask/messenger": "npm:^0.3.0" + "@metamask/polling-controller": "npm:^1.0.0" "@ts-bridge/cli": "npm:^0.6.4" "@types/jest": "npm:^27.4.1" deepmerge: "npm:^4.2.2" @@ -3025,6 +3035,21 @@ __metadata: languageName: unknown linkType: soft +"@metamask/controller-utils@npm:^5.0.2": + version: 5.0.2 + resolution: "@metamask/controller-utils@npm:5.0.2" + dependencies: + "@metamask/eth-query": "npm:^3.0.1" + "@metamask/utils": "npm:^8.1.0" + "@spruceid/siwe-parser": "npm:1.1.3" + eth-ens-namehash: "npm:^2.0.8" + ethereumjs-util: "npm:^7.0.10" + ethjs-unit: "npm:^0.1.6" + fast-deep-equal: "npm:^3.1.3" + checksum: 10/fde3d4893ddd408e1b6138180d53568e27626b5884a404473a3e75d4615ba4525aa33deb21a24a438ff0928431d278efd9c084e9aca7eeaaf2a1c300691318d5 + languageName: node + linkType: hard + "@metamask/core-backend@npm:^5.0.0, @metamask/core-backend@workspace:packages/core-backend": version: 0.0.0-use.local resolution: "@metamask/core-backend@workspace:packages/core-backend" @@ -3392,6 +3417,19 @@ __metadata: languageName: unknown linkType: soft +"@metamask/eth-block-tracker@npm:^9.0.3": + version: 9.0.3 + resolution: "@metamask/eth-block-tracker@npm:9.0.3" + dependencies: + "@metamask/eth-json-rpc-provider": "npm:^3.0.2" + "@metamask/safe-event-emitter": "npm:^3.0.0" + "@metamask/utils": "npm:^8.1.0" + json-rpc-random-id: "npm:^1.0.1" + pify: "npm:^5.0.0" + checksum: 10/f49bb158b2c9669e91813a1f34948a6c2a2d1f8507ea0b1afae9a003a4d276d892b5cde4c183f970fcec32f253a14f1abf39b6411beabeb113eeed75cd7e29b8 + languageName: node + linkType: hard + "@metamask/eth-hd-keyring@npm:^13.0.0": version: 13.0.0 resolution: "@metamask/eth-hd-keyring@npm:13.0.0" @@ -3432,6 +3470,36 @@ __metadata: languageName: node linkType: hard +"@metamask/eth-json-rpc-infura@npm:^9.0.0": + version: 9.1.0 + resolution: "@metamask/eth-json-rpc-infura@npm:9.1.0" + dependencies: + "@metamask/eth-json-rpc-provider": "npm:^2.1.0" + "@metamask/json-rpc-engine": "npm:^7.1.1" + "@metamask/rpc-errors": "npm:^6.0.0" + "@metamask/utils": "npm:^8.1.0" + node-fetch: "npm:^2.7.0" + checksum: 10/9e01b3eb76d3f1b4989ba368f11acb124eb846321020e2fba8c7ff77dc5258fa2df1556f40812d736d63ee159a944beab6a761a661f72e722badcb4f78b5f0f6 + languageName: node + linkType: hard + +"@metamask/eth-json-rpc-middleware@npm:^12.0.1": + version: 12.1.2 + resolution: "@metamask/eth-json-rpc-middleware@npm:12.1.2" + dependencies: + "@metamask/eth-block-tracker": "npm:^9.0.3" + "@metamask/eth-json-rpc-provider": "npm:^3.0.2" + "@metamask/eth-sig-util": "npm:^7.0.0" + "@metamask/json-rpc-engine": "npm:^8.0.2" + "@metamask/rpc-errors": "npm:^6.0.0" + "@metamask/utils": "npm:^8.1.0" + klona: "npm:^2.0.6" + pify: "npm:^5.0.0" + safe-stable-stringify: "npm:^2.4.3" + checksum: 10/1c0f186a35765394a28695bcade84c636b0c92cf3252219d1e9cbdd31231ad09fea5ec7bff7d31e2c7fe4d2158f15b54a5e42166549b69af1f7e475a1c7ae536 + languageName: node + linkType: hard + "@metamask/eth-json-rpc-middleware@npm:^22.0.0, @metamask/eth-json-rpc-middleware@workspace:packages/eth-json-rpc-middleware": version: 0.0.0-use.local resolution: "@metamask/eth-json-rpc-middleware@workspace:packages/eth-json-rpc-middleware" @@ -3463,6 +3531,28 @@ __metadata: languageName: unknown linkType: soft +"@metamask/eth-json-rpc-provider@npm:^2.1.0, @metamask/eth-json-rpc-provider@npm:^2.3.0": + version: 2.3.2 + resolution: "@metamask/eth-json-rpc-provider@npm:2.3.2" + dependencies: + "@metamask/json-rpc-engine": "npm:^7.3.2" + "@metamask/safe-event-emitter": "npm:^3.0.0" + "@metamask/utils": "npm:^8.3.0" + checksum: 10/e6731271aad3b972d85b9230c26d35a9b88722f3bd3024675ad2f568e634e9fdfef4717ef2892f3cc512d381cf17a4e20dbd5eb808ced765082bea3379ad6ddc + languageName: node + linkType: hard + +"@metamask/eth-json-rpc-provider@npm:^3.0.2": + version: 3.0.2 + resolution: "@metamask/eth-json-rpc-provider@npm:3.0.2" + dependencies: + "@metamask/json-rpc-engine": "npm:^8.0.2" + "@metamask/safe-event-emitter": "npm:^3.0.0" + "@metamask/utils": "npm:^8.3.0" + checksum: 10/63778defd3055633cbf0aed2d6fd0f8a1d866908be7b16b516fdb26ae6dcd34b2aefdfed80828c2af105a30ec3c16d7d0894bc6a73e2661515bcad6b6b6be4e2 + languageName: node + linkType: hard + "@metamask/eth-json-rpc-provider@npm:^5.0.0": version: 5.0.1 resolution: "@metamask/eth-json-rpc-provider@npm:5.0.1" @@ -3500,6 +3590,16 @@ __metadata: languageName: unknown linkType: soft +"@metamask/eth-query@npm:^3.0.1": + version: 3.0.1 + resolution: "@metamask/eth-query@npm:3.0.1" + dependencies: + json-rpc-random-id: "npm:^1.0.0" + xtend: "npm:^4.0.1" + checksum: 10/d463aff018ae3f1229331177e9efa0eb62958c6fcc30039c22d151ee64da17d55153ef4861060aecec674f764aa9074341bef53fdf86c2258d3cb2682976e835 + languageName: node + linkType: hard + "@metamask/eth-query@npm:^4.0.0": version: 4.0.0 resolution: "@metamask/eth-query@npm:4.0.0" @@ -3510,6 +3610,20 @@ __metadata: languageName: node linkType: hard +"@metamask/eth-sig-util@npm:^7.0.0": + version: 7.0.3 + resolution: "@metamask/eth-sig-util@npm:7.0.3" + dependencies: + "@ethereumjs/util": "npm:^8.1.0" + "@metamask/abi-utils": "npm:^2.0.4" + "@metamask/utils": "npm:^9.0.0" + "@scure/base": "npm:~1.1.3" + ethereum-cryptography: "npm:^2.1.2" + tweetnacl: "npm:^1.0.3" + checksum: 10/a71b28607b0815d609cf27ab2d8535393d0a7e7f2c6b7a23d92669b770c664c14e2f539129351147339172b0bb865bb977e7cfb30624870eedab5d7ab700beff + languageName: node + linkType: hard + "@metamask/eth-sig-util@npm:^8.2.0": version: 8.2.0 resolution: "@metamask/eth-sig-util@npm:8.2.0" @@ -3818,6 +3932,28 @@ __metadata: languageName: unknown linkType: soft +"@metamask/json-rpc-engine@npm:^7.1.1, @metamask/json-rpc-engine@npm:^7.3.0, @metamask/json-rpc-engine@npm:^7.3.2": + version: 7.3.3 + resolution: "@metamask/json-rpc-engine@npm:7.3.3" + dependencies: + "@metamask/rpc-errors": "npm:^6.2.1" + "@metamask/safe-event-emitter": "npm:^3.0.0" + "@metamask/utils": "npm:^8.3.0" + checksum: 10/116664c974c522d280335d9a02cba731e4f08562c2980415f7535513cd308c7e612e52618086996e5ac2b67db7f1e6ac1bd8201aba7825163db17a25f2874cc9 + languageName: node + linkType: hard + +"@metamask/json-rpc-engine@npm:^8.0.2": + version: 8.0.2 + resolution: "@metamask/json-rpc-engine@npm:8.0.2" + dependencies: + "@metamask/rpc-errors": "npm:^6.2.1" + "@metamask/safe-event-emitter": "npm:^3.0.0" + "@metamask/utils": "npm:^8.3.0" + checksum: 10/f088f4b648b9b55875b56e8237853e7282f13302a9db6a1f9bba06314dfd6cd0a23b3d27f8fde05a157b97ebb03b67bc2699ba455c99553dfb2ecccd73ab3474 + languageName: node + linkType: hard + "@metamask/json-rpc-middleware-stream@npm:^8.0.6, @metamask/json-rpc-middleware-stream@npm:^8.0.7, @metamask/json-rpc-middleware-stream@workspace:packages/json-rpc-middleware-stream": version: 0.0.0-use.local resolution: "@metamask/json-rpc-middleware-stream@workspace:packages/json-rpc-middleware-stream" @@ -4202,6 +4338,28 @@ __metadata: languageName: unknown linkType: soft +"@metamask/network-controller@npm:^16.0.0": + version: 16.0.0 + resolution: "@metamask/network-controller@npm:16.0.0" + dependencies: + "@metamask/base-controller": "npm:^3.2.3" + "@metamask/controller-utils": "npm:^5.0.2" + "@metamask/eth-json-rpc-infura": "npm:^9.0.0" + "@metamask/eth-json-rpc-middleware": "npm:^12.0.1" + "@metamask/eth-json-rpc-provider": "npm:^2.3.0" + "@metamask/eth-query": "npm:^4.0.0" + "@metamask/json-rpc-engine": "npm:^7.3.0" + "@metamask/rpc-errors": "npm:^6.1.0" + "@metamask/swappable-obj-proxy": "npm:^2.1.0" + "@metamask/utils": "npm:^8.2.0" + async-mutex: "npm:^0.2.6" + eth-block-tracker: "npm:^8.0.0" + immer: "npm:^9.0.6" + uuid: "npm:^8.3.2" + checksum: 10/9696b67efe1b4dbc4ced662ebce70294d19aae4f0ceed4a89382a4a78b69ec980c6832f32fae1a760af1f75b2118bb4d2a09c151bbca062a3d516c7194dee4a5 + languageName: node + linkType: hard + "@metamask/network-controller@npm:^27.0.0, @metamask/network-controller@workspace:packages/network-controller": version: 0.0.0-use.local resolution: "@metamask/network-controller@workspace:packages/network-controller" @@ -4454,6 +4612,23 @@ __metadata: languageName: unknown linkType: soft +"@metamask/polling-controller@npm:^1.0.0": + version: 1.0.2 + resolution: "@metamask/polling-controller@npm:1.0.2" + dependencies: + "@metamask/base-controller": "npm:^3.2.3" + "@metamask/controller-utils": "npm:^5.0.2" + "@metamask/network-controller": "npm:^16.0.0" + "@metamask/utils": "npm:^8.2.0" + "@types/uuid": "npm:^8.3.0" + fast-json-stable-stringify: "npm:^2.1.0" + uuid: "npm:^8.3.2" + peerDependencies: + "@metamask/network-controller": ^16.0.0 + checksum: 10/4bf2fbf4fdb4c90ce75ec952600a372b2214561f42730e028600deb790aaf3ff9a9358f4cb8a4c27abfd088d04bad16e4fffa4c9ba5de9d162c9324fe17aa515 + languageName: node + linkType: hard + "@metamask/polling-controller@npm:^16.0.0, @metamask/polling-controller@workspace:packages/polling-controller": version: 0.0.0-use.local resolution: "@metamask/polling-controller@workspace:packages/polling-controller" @@ -4643,6 +4818,16 @@ __metadata: languageName: unknown linkType: soft +"@metamask/rpc-errors@npm:^6.0.0, @metamask/rpc-errors@npm:^6.1.0, @metamask/rpc-errors@npm:^6.2.1": + version: 6.4.0 + resolution: "@metamask/rpc-errors@npm:6.4.0" + dependencies: + "@metamask/utils": "npm:^9.0.0" + fast-safe-stringify: "npm:^2.0.6" + checksum: 10/9a17525aa8ce9ac142a94c04000dba7f0635e8e155c6c045f57eca36cc78c255318cca2fad4571719a427dfd2df64b70bc6442989523a8de555480668d666ad5 + languageName: node + linkType: hard + "@metamask/rpc-errors@npm:^7.0.2": version: 7.0.2 resolution: "@metamask/rpc-errors@npm:7.0.2" @@ -4982,14 +5167,14 @@ __metadata: languageName: unknown linkType: soft -"@metamask/superstruct@npm:^3.1.0, @metamask/superstruct@npm:^3.2.1": +"@metamask/superstruct@npm:^3.0.0, @metamask/superstruct@npm:^3.1.0, @metamask/superstruct@npm:^3.2.1": version: 3.2.1 resolution: "@metamask/superstruct@npm:3.2.1" checksum: 10/9e29380f2cf8b129283ccb2b568296d92682b705109ba62dbd7739ffd6a1982fe38c7228cdcf3cbee94dbcdd5fcc1c846ab9d1dd3582167154f914422fcff547 languageName: node linkType: hard -"@metamask/swappable-obj-proxy@npm:^2.3.0": +"@metamask/swappable-obj-proxy@npm:^2.1.0, @metamask/swappable-obj-proxy@npm:^2.3.0": version: 2.3.0 resolution: "@metamask/swappable-obj-proxy@npm:2.3.0" checksum: 10/1255c599de9237f06df2390719d6dfcb1f168873df61bbaad5ce376efbc057e2030260b94855569313faeb412b7df9b062d209f4b0b163a3dc02f29d42139e1f @@ -5178,6 +5363,23 @@ __metadata: languageName: node linkType: hard +"@metamask/utils@npm:^8.1.0, @metamask/utils@npm:^8.2.0, @metamask/utils@npm:^8.3.0": + version: 8.5.0 + resolution: "@metamask/utils@npm:8.5.0" + dependencies: + "@ethereumjs/tx": "npm:^4.2.0" + "@metamask/superstruct": "npm:^3.0.0" + "@noble/hashes": "npm:^1.3.1" + "@scure/base": "npm:^1.1.3" + "@types/debug": "npm:^4.1.7" + debug: "npm:^4.3.4" + pony-cause: "npm:^2.1.10" + semver: "npm:^7.5.4" + uuid: "npm:^9.0.1" + checksum: 10/68a42a55f7dc750b75467fb7c05a496c20dac073a2753e0f4d9642c4d8dcb3f9ddf51a09d30337e11637f1777f3dfe22e15b5159dbafb0fdb7bd8c9236056153 + languageName: node + linkType: hard + "@metamask/utils@npm:^9.0.0": version: 9.3.0 resolution: "@metamask/utils@npm:9.3.0" @@ -5650,6 +5852,15 @@ __metadata: languageName: node linkType: hard +"@spruceid/siwe-parser@npm:1.1.3": + version: 1.1.3 + resolution: "@spruceid/siwe-parser@npm:1.1.3" + dependencies: + apg-js: "npm:^4.1.1" + checksum: 10/c953fa1e79c633a92f030b68a44225b28c71396553dc5eb8d4d5b263e8b2e5b988131720170df2eaf202ee5251d4369ccff99c130b691a1accca2a1ff93b1111 + languageName: node + linkType: hard + "@spruceid/siwe-parser@npm:2.1.0": version: 2.1.0 resolution: "@spruceid/siwe-parser@npm:2.1.0" @@ -6706,6 +6917,15 @@ __metadata: languageName: node linkType: hard +"async-mutex@npm:^0.2.6": + version: 0.2.6 + resolution: "async-mutex@npm:0.2.6" + dependencies: + tslib: "npm:^2.0.0" + checksum: 10/3cf676fc48b4686abf534cc02d4784bab3f35d7836a0a7476c96e57c3f6607dd3d94cc0989b29d33ce5ae5cde8be8e1a96f3e769ba3b0e1ba4a244f873aa5623 + languageName: node + linkType: hard + "async-mutex@npm:^0.3.1": version: 0.3.2 resolution: "async-mutex@npm:0.3.2" @@ -8587,6 +8807,19 @@ __metadata: languageName: node linkType: hard +"eth-block-tracker@npm:^8.0.0": + version: 8.1.0 + resolution: "eth-block-tracker@npm:8.1.0" + dependencies: + "@metamask/eth-json-rpc-provider": "npm:^2.1.0" + "@metamask/safe-event-emitter": "npm:^3.0.0" + "@metamask/utils": "npm:^8.1.0" + json-rpc-random-id: "npm:^1.0.1" + pify: "npm:^5.0.0" + checksum: 10/94d81a0f5ed62bb7fd70b99a3a6172f416a574dc9fcaa96c9bdedb4d98c52b257ee505957d4a5b248ce73220b96083420acdd2dd702a0330d016018a59bd0b2e + languageName: node + linkType: hard + "eth-ens-namehash@npm:^2.0.8": version: 2.0.8 resolution: "eth-ens-namehash@npm:2.0.8" @@ -8644,7 +8877,7 @@ __metadata: languageName: node linkType: hard -"ethereumjs-util@npm:^7.1.2": +"ethereumjs-util@npm:^7.0.10, ethereumjs-util@npm:^7.1.2": version: 7.1.5 resolution: "ethereumjs-util@npm:7.1.5" dependencies: @@ -8706,6 +8939,16 @@ __metadata: languageName: node linkType: hard +"ethjs-unit@npm:^0.1.6": + version: 0.1.6 + resolution: "ethjs-unit@npm:0.1.6" + dependencies: + bn.js: "npm:4.11.6" + number-to-bn: "npm:1.7.0" + checksum: 10/35086cb671806992ec36d5dd43ab67e68ad7a9237e42c0e963f9081c88e40147cda86c1a258b0a3180bf2b7bc1960e607c5bcaefdb2196e0f3564acf73276189 + languageName: node + linkType: hard + "event-target-shim@npm:^5.0.0": version: 5.0.1 resolution: "event-target-shim@npm:5.0.1" @@ -13715,7 +13958,7 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.1.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0, tslib@npm:^2.6.2, tslib@npm:^2.6.3": +"tslib@npm:^2.0.0, tslib@npm:^2.1.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0, tslib@npm:^2.6.2, tslib@npm:^2.6.3": version: 2.8.1 resolution: "tslib@npm:2.8.1" checksum: 10/3e2e043d5c2316461cb54e5c7fe02c30ef6dccb3384717ca22ae5c6b5bc95232a6241df19c622d9c73b809bea33b187f6dbc73030963e29950c2141bc32a79f7 From e82db653b5afb2000371f6fc1eb641d9c00c596c Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Thu, 11 Dec 2025 17:23:59 +0100 Subject: [PATCH 04/55] feat: add configregistryqpiservice and integrate with controller --- .../config-registry-controller/package.json | 3 + .../src/ConfigRegistryController.test.ts | 598 ++++++++++++++++++ .../src/ConfigRegistryController.ts | 186 +++--- .../abstract-config-registry-api-service.ts | 50 ++ .../config-registry-api-service.test.ts | 295 +++++++++ .../config-registry-api-service.ts | 170 +++++ .../src/config-registry-api-service/index.ts | 16 + .../config-registry-controller/src/index.ts | 19 +- .../tsconfig.build.json | 1 + .../config-registry-controller/tsconfig.json | 1 + yarn.lock | 1 + 11 files changed, 1224 insertions(+), 116 deletions(-) create mode 100644 packages/config-registry-controller/src/ConfigRegistryController.test.ts create mode 100644 packages/config-registry-controller/src/config-registry-api-service/abstract-config-registry-api-service.ts create mode 100644 packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts create mode 100644 packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts create mode 100644 packages/config-registry-controller/src/config-registry-api-service/index.ts diff --git a/packages/config-registry-controller/package.json b/packages/config-registry-controller/package.json index 8ffb4c459fe..cafcfd253ec 100644 --- a/packages/config-registry-controller/package.json +++ b/packages/config-registry-controller/package.json @@ -49,6 +49,7 @@ }, "dependencies": { "@metamask/base-controller": "^9.0.0", + "@metamask/controller-utils": "^11.16.0", "@metamask/messenger": "^0.3.0", "@metamask/polling-controller": "^1.0.0" }, @@ -59,6 +60,8 @@ "@types/jest": "^27.4.1", "deepmerge": "^4.2.2", "jest": "^27.5.1", + "nock": "^13.3.1", + "sinon": "^9.2.4", "ts-jest": "^27.1.4", "typedoc": "^0.24.8", "typedoc-plugin-missing-exports": "^2.0.0", diff --git a/packages/config-registry-controller/src/ConfigRegistryController.test.ts b/packages/config-registry-controller/src/ConfigRegistryController.test.ts new file mode 100644 index 00000000000..9bee2032e36 --- /dev/null +++ b/packages/config-registry-controller/src/ConfigRegistryController.test.ts @@ -0,0 +1,598 @@ +import { Messenger, type MockAnyNamespace } from '@metamask/messenger'; +import { useFakeTimers } from 'sinon'; + +import type { AbstractConfigRegistryApiService } from './config-registry-api-service'; +import { + ConfigRegistryController, + DEFAULT_POLLING_INTERVAL, +} from './ConfigRegistryController'; +import type { + ConfigRegistryMessenger, + ConfigRegistryState, + RegistryConfigEntry, +} from './ConfigRegistryController'; +import { advanceTime } from '../../../tests/helpers'; + +const namespace = 'ConfigRegistryController' as const; + +type RootMessenger = Messenger; + +/** + * Constructs a messenger for ConfigRegistryController. + * + * @returns A controller messenger. + */ +function getConfigRegistryControllerMessenger(): ConfigRegistryMessenger { + const configRegistryControllerMessenger = new Messenger< + typeof namespace, + never, + never, + RootMessenger + >({ + namespace, + }); + return configRegistryControllerMessenger; +} + +const MOCK_CONFIG_ENTRY: RegistryConfigEntry = { + key: 'test-key', + value: { test: 'value' }, + metadata: { source: 'test' }, +}; + +const MOCK_FALLBACK_CONFIG: Record = { + 'fallback-key': { + key: 'fallback-key', + value: { fallback: true }, + }, +}; + +/** + * Builds a mock API service. + * + * @param overrides - The properties of the API service you want to provide explicitly. + * @returns The built mock API service. + */ +function buildMockApiService( + overrides: Partial = {}, +): AbstractConfigRegistryApiService { + return { + async fetchConfig() { + return { + data: { + data: { + version: '1', + timestamp: Date.now(), + networks: [], + }, + }, + notModified: false, + }; + }, + onBreak: jest.fn(), + onDegraded: jest.fn(), + ...overrides, + }; +} + +describe('ConfigRegistryController', () => { + let clock: sinon.SinonFakeTimers; + let messenger: ConfigRegistryMessenger; + let apiService: AbstractConfigRegistryApiService; + + beforeEach(() => { + clock = useFakeTimers(); + messenger = getConfigRegistryControllerMessenger(); + apiService = buildMockApiService(); + }); + + afterEach(() => { + clock.restore(); + }); + + describe('constructor', () => { + it('should set default state', () => { + const controller = new ConfigRegistryController({ + messenger, + apiService, + }); + + expect(controller.state).toStrictEqual({ + configs: {}, + version: null, + lastFetched: null, + fetchError: null, + etag: null, + }); + }); + + it('should set initial state when provided', () => { + const initialState: Partial = { + configs: { + 'test-key': MOCK_CONFIG_ENTRY, + }, + version: 'v1.0.0', + lastFetched: 1234567890, + }; + + const controller = new ConfigRegistryController({ + messenger, + state: initialState, + apiService, + }); + + expect(controller.state.configs).toStrictEqual(initialState.configs); + expect(controller.state.version).toBe('v1.0.0'); + expect(controller.state.lastFetched).toBe(1234567890); + }); + + it('should set custom polling interval', () => { + const customInterval = 5000; + const controller = new ConfigRegistryController({ + apiService, + messenger, + pollingInterval: customInterval, + }); + + expect(controller.getIntervalLength()).toBe(customInterval); + }); + + it('should set fallback config', () => { + const controller = new ConfigRegistryController({ + apiService, + messenger, + fallbackConfig: MOCK_FALLBACK_CONFIG, + }); + + // Fallback config is private, but we can verify it's used when needed + expect(controller.state.configs).toStrictEqual({}); + }); + }); + + describe('getConfig', () => { + it('should return undefined for non-existent key', () => { + const controller = new ConfigRegistryController({ + apiService, + messenger, + }); + + expect(controller.getConfig('non-existent')).toBeUndefined(); + }); + + it('should return config entry for existing key', () => { + const controller = new ConfigRegistryController({ + apiService, + messenger, + state: { + configs: { + 'test-key': MOCK_CONFIG_ENTRY, + }, + }, + }); + + expect(controller.getConfig('test-key')).toStrictEqual(MOCK_CONFIG_ENTRY); + }); + + it('should work via messenger action', () => { + const testController = new ConfigRegistryController({ + apiService, + messenger, + state: { + configs: { + 'test-key': MOCK_CONFIG_ENTRY, + }, + }, + }); + + const result = messenger.call( + 'ConfigRegistryController:getConfig', + 'test-key', + ); + expect(result).toStrictEqual(MOCK_CONFIG_ENTRY); + expect(testController.getConfig('test-key')).toStrictEqual( + MOCK_CONFIG_ENTRY, + ); + }); + }); + + describe('getAllConfigs', () => { + it('should return empty object when no configs', () => { + const controller = new ConfigRegistryController({ + apiService, + messenger, + }); + + expect(controller.getAllConfigs()).toStrictEqual({}); + }); + + it('should return all configs', () => { + const configs = { + key1: { key: 'key1', value: 'value1' }, + key2: { key: 'key2', value: 'value2' }, + }; + + const controller = new ConfigRegistryController({ + apiService, + messenger, + state: { configs }, + }); + + expect(controller.getAllConfigs()).toStrictEqual(configs); + }); + + it('should return a copy, not a reference', () => { + const configs = { + key1: { key: 'key1', value: 'value1' }, + }; + + const controller = new ConfigRegistryController({ + apiService, + messenger, + state: { configs }, + }); + + const result = controller.getAllConfigs(); + result.key1 = { key: 'key1', value: 'modified' }; + + // Original should not be modified + expect(controller.state.configs.key1.value).toBe('value1'); + }); + + it('should work via messenger action', () => { + const configs = { + key1: { key: 'key1', value: 'value1' }, + }; + + const testController = new ConfigRegistryController({ + messenger, + apiService, + state: { configs }, + }); + + const result = messenger.call('ConfigRegistryController:getAllConfigs'); + expect(result).toStrictEqual(configs); + expect(testController.getAllConfigs()).toStrictEqual(configs); + }); + }); + + describe('getConfigValue', () => { + it('should return undefined for non-existent key', () => { + const controller = new ConfigRegistryController({ + apiService, + messenger, + }); + + expect(controller.getConfigValue('non-existent')).toBeUndefined(); + }); + + it('should return value for existing key', () => { + const controller = new ConfigRegistryController({ + apiService, + messenger, + state: { + configs: { + 'test-key': MOCK_CONFIG_ENTRY, + }, + }, + }); + + expect(controller.getConfigValue('test-key')).toStrictEqual({ + test: 'value', + }); + }); + + it('should return typed value', () => { + const controller = new ConfigRegistryController({ + apiService, + messenger, + state: { + configs: { + 'string-key': { key: 'string-key', value: 'string-value' }, + 'number-key': { key: 'number-key', value: 42 }, + }, + }, + }); + + expect(controller.getConfigValue('string-key')).toBe( + 'string-value', + ); + expect(controller.getConfigValue('number-key')).toBe(42); + }); + }); + + describe('setConfig', () => { + it('should set a new config entry', () => { + const controller = new ConfigRegistryController({ + messenger, + apiService, + }); + + controller.setConfig('new-key', { data: 'value' }); + + expect(controller.state.configs['new-key']).toStrictEqual({ + key: 'new-key', + value: { data: 'value' }, + metadata: undefined, + }); + }); + + it('should set config with metadata', () => { + const controller = new ConfigRegistryController({ + apiService, + messenger, + }); + + controller.setConfig('new-key', { data: 'value' }, { source: 'test' }); + + expect(controller.state.configs['new-key']).toStrictEqual({ + key: 'new-key', + value: { data: 'value' }, + metadata: { source: 'test' }, + }); + }); + + it('should update existing config', () => { + const controller = new ConfigRegistryController({ + messenger, + apiService, + state: { + configs: { + 'existing-key': { key: 'existing-key', value: 'old-value' }, + }, + }, + }); + + controller.setConfig('existing-key', 'new-value'); + + expect(controller.state.configs['existing-key'].value).toBe('new-value'); + }); + + it('should work via messenger action', () => { + const controller = new ConfigRegistryController({ + messenger, + apiService, + }); + + messenger.call( + 'ConfigRegistryController:setConfig', + 'test-key', + 'test-value', + ); + + expect(controller.getConfig('test-key')?.value).toBe('test-value'); + }); + }); + + describe('removeConfig', () => { + it('should remove existing config', () => { + const controller = new ConfigRegistryController({ + apiService, + messenger, + state: { + configs: { + key1: { key: 'key1', value: 'value1' }, + key2: { key: 'key2', value: 'value2' }, + }, + }, + }); + + controller.removeConfig('key1'); + + expect(controller.state.configs.key1).toBeUndefined(); + expect(controller.state.configs.key2).toBeDefined(); + }); + + it('should not throw when removing non-existent key', () => { + const controller = new ConfigRegistryController({ + messenger, + apiService, + }); + + expect(() => controller.removeConfig('non-existent')).not.toThrow(); + }); + }); + + describe('clearConfigs', () => { + it('should clear all configs', () => { + const controller = new ConfigRegistryController({ + messenger, + apiService, + state: { + configs: { + key1: { key: 'key1', value: 'value1' }, + key2: { key: 'key2', value: 'value2' }, + }, + }, + }); + + controller.clearConfigs(); + + expect(controller.state.configs).toStrictEqual({}); + }); + }); + + describe('polling', () => { + it('should start polling', async () => { + const controller = new ConfigRegistryController({ + apiService, + messenger, + }); + + const executePollSpy = jest.spyOn(controller, '_executePoll'); + controller.startPolling({}); + + await advanceTime({ clock, duration: 0 }); + + expect(executePollSpy).toHaveBeenCalledTimes(1); + controller.stopPolling(); + }); + + it('should poll at specified interval', async () => { + const pollingInterval = 1000; + const controller = new ConfigRegistryController({ + apiService, + messenger, + pollingInterval, + }); + + const executePollSpy = jest.spyOn(controller, '_executePoll'); + controller.startPolling({}); + + await advanceTime({ clock, duration: 0 }); + executePollSpy.mockClear(); + + await advanceTime({ clock, duration: pollingInterval }); + + expect(executePollSpy).toHaveBeenCalledTimes(1); + controller.stopPolling(); + }); + + it('should stop polling', async () => { + const controller = new ConfigRegistryController({ + apiService, + messenger, + }); + + const executePollSpy = jest.spyOn(controller, '_executePoll'); + controller.startPolling({}); + + await advanceTime({ clock, duration: 0 }); + executePollSpy.mockClear(); + + controller.stopPolling(); + + await advanceTime({ clock, duration: DEFAULT_POLLING_INTERVAL }); + + expect(executePollSpy).not.toHaveBeenCalled(); + }); + + it('should use fallback config when no configs exist', async () => { + const errorApiService = buildMockApiService({ + fetchConfig: jest.fn().mockRejectedValue(new Error('Network error')), + }); + + const controller = new ConfigRegistryController({ + apiService: errorApiService, + messenger, + fallbackConfig: MOCK_FALLBACK_CONFIG, + }); + + controller.startPolling({}); + await advanceTime({ clock, duration: 0 }); + + expect(controller.state.configs).toStrictEqual(MOCK_FALLBACK_CONFIG); + expect(controller.state.fetchError).toBe('Network error'); + + controller.stopPolling(); + }); + + it('should not use fallback when configs already exist', async () => { + const existingConfigs = { + 'existing-key': { key: 'existing-key', value: 'existing-value' }, + }; + + const errorApiService = buildMockApiService({ + fetchConfig: jest.fn().mockRejectedValue(new Error('Network error')), + }); + + const controller = new ConfigRegistryController({ + apiService: errorApiService, + messenger, + state: { configs: existingConfigs }, + fallbackConfig: MOCK_FALLBACK_CONFIG, + }); + + controller.startPolling({}); + await advanceTime({ clock, duration: 0 }); + + // Should keep existing configs, not use fallback + expect(controller.state.configs).toStrictEqual(existingConfigs); + expect(controller.state.fetchError).toBe('Network error'); + + controller.stopPolling(); + }); + + it('should handle errors during polling', async () => { + const errorApiService = buildMockApiService({ + fetchConfig: jest.fn().mockRejectedValue(new Error('Network error')), + }); + + const controller = new ConfigRegistryController({ + apiService: errorApiService, + messenger, + fallbackConfig: MOCK_FALLBACK_CONFIG, + }); + + // Call _executePoll directly to test error handling + await controller._executePoll({}); + + // Since we have no configs, it should use fallback + expect(controller.state.configs).toStrictEqual(MOCK_FALLBACK_CONFIG); + expect(controller.state.fetchError).toBe('Network error'); + }); + + it('should work via messenger actions', async () => { + const controller = new ConfigRegistryController({ + apiService, + messenger, + }); + + const executePollSpy = jest.spyOn(controller, '_executePoll'); + + const token = messenger.call('ConfigRegistryController:startPolling', {}); + expect(typeof token).toBe('string'); + + await advanceTime({ clock, duration: 0 }); + expect(executePollSpy).toHaveBeenCalledTimes(1); + + messenger.call('ConfigRegistryController:stopPolling'); + await advanceTime({ clock, duration: DEFAULT_POLLING_INTERVAL }); + expect(executePollSpy).toHaveBeenCalledTimes(1); + }); + }); + + describe('state persistence', () => { + it('should persist configs', () => { + const controller = new ConfigRegistryController({ + messenger, + apiService, + }); + + controller.setConfig('persist-key', 'persist-value'); + + // Verify state is updated + expect(controller.state.configs['persist-key']).toBeDefined(); + }); + + it('should persist version', () => { + const controller = new ConfigRegistryController({ + messenger, + apiService, + state: { version: 'v1.0.0' }, + }); + + expect(controller.state.version).toBe('v1.0.0'); + }); + + it('should persist lastFetched', () => { + const timestamp = Date.now(); + const controller = new ConfigRegistryController({ + messenger, + apiService, + state: { lastFetched: timestamp }, + }); + + expect(controller.state.lastFetched).toBe(timestamp); + }); + + it('should persist fetchError', () => { + const controller = new ConfigRegistryController({ + messenger, + apiService, + state: { fetchError: 'Test error' }, + }); + + expect(controller.state.fetchError).toBe('Test error'); + }); + }); +}); diff --git a/packages/config-registry-controller/src/ConfigRegistryController.ts b/packages/config-registry-controller/src/ConfigRegistryController.ts index 2da6c653b99..1ebdd196cd1 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.ts @@ -6,33 +6,28 @@ import type { Messenger } from '@metamask/messenger'; import { StaticIntervalPollingController } from '@metamask/polling-controller'; import type { Json } from '@metamask/utils'; +import type { AbstractConfigRegistryApiService } from './config-registry-api-service'; +import { + ConfigRegistryApiService, + type FetchConfigResult, +} from './config-registry-api-service'; + const controllerName = 'ConfigRegistryController'; -// 24 hours in milliseconds -const DEFAULT_POLLING_INTERVAL = 24 * 60 * 60 * 1000; // 86400000ms +export const DEFAULT_POLLING_INTERVAL = 24 * 60 * 60 * 1000; -/** - * Configuration entry in the registry. - */ export type RegistryConfigEntry = { key: string; value: Json; metadata?: Json; }; -/** - * The state of the {@link ConfigRegistryController}. - * - * @property configs - A map of configuration keys to their entries. - * @property version - The version of the configuration from the API. - * @property lastFetched - Timestamp of the last successful fetch. - * @property fetchError - Error message if the last fetch failed, null otherwise. - */ export type ConfigRegistryState = { configs: Record; version: string | null; lastFetched: number | null; fetchError: string | null; + etag: string | null; }; const stateMetadata = { @@ -64,18 +59,17 @@ const stateMetadata = { includeInDebugSnapshot: true, usedInUi: false, }, + etag: { + persist: true, + anonymous: false, + includeInStateLogs: false, + includeInDebugSnapshot: false, + usedInUi: false, + }, }; -/** - * Default fallback configuration. - * This will be used when the API is unavailable. - */ const DEFAULT_FALLBACK_CONFIG: Record = {}; -/** - * Polling input type for the controller. - * For now, it's empty, but can be extended later if needed. - */ type ConfigRegistryPollingInput = Record; export type ConfigRegistryControllerStateChangeEvent = @@ -128,19 +122,14 @@ export type ConfigRegistryMessenger = Messenger< ConfigRegistryControllerEvents >; -/** - * Options for constructing a ConfigRegistryController. - */ export type ConfigRegistryControllerOptions = { messenger: ConfigRegistryMessenger; state?: Partial; pollingInterval?: number; fallbackConfig?: Record; + apiService?: AbstractConfigRegistryApiService; }; -/** - * Controller for managing a configuration registry with dynamic updates from a remote API. - */ export class ConfigRegistryController extends StaticIntervalPollingController()< typeof controllerName, ConfigRegistryState, @@ -148,20 +137,22 @@ export class ConfigRegistryController extends StaticIntervalPollingController { readonly #fallbackConfig: Record; + readonly #apiService: AbstractConfigRegistryApiService; + /** - * Creates a ConfigRegistryController instance. - * - * @param options - Constructor options. - * @param options.messenger - A reference to the messaging system. - * @param options.state - Initial state to set on this controller. - * @param options.pollingInterval - Polling interval in milliseconds. Defaults to 24 hours. - * @param options.fallbackConfig - Fallback configuration to use when API fails. + * @param options - The controller options. + * @param options.messenger - The controller messenger. + * @param options.state - Initial state. + * @param options.pollingInterval - Polling interval in milliseconds. + * @param options.fallbackConfig - Fallback configuration. + * @param options.apiService - The API service. */ constructor({ messenger, state = {}, pollingInterval = DEFAULT_POLLING_INTERVAL, fallbackConfig = DEFAULT_FALLBACK_CONFIG, + apiService = new ConfigRegistryApiService(), }: ConfigRegistryControllerOptions) { super({ name: controllerName, @@ -172,12 +163,14 @@ export class ConfigRegistryController extends StaticIntervalPollingController { - // TODO: This will be implemented in Task 2 (API service fetcher) - // For now, this is a placeholder that will use fallback try { - // Placeholder: Will call API service here - // const apiResponse = await this.#apiService.fetchConfig(); - // Once implemented in Task 2, will update state with: - // this.update((state) => { - // state.configs = apiResponse.configs; - // state.version = apiResponse.version; - // state.lastFetched = Date.now(); - // state.fetchError = null; - // }); - - // For now, if we have no configs, use fallback - if (Object.keys(this.state.configs).length === 0) { - this.#useFallbackConfig(); + const result: FetchConfigResult = await this.#apiService.fetchConfig({ + etag: this.state.etag ?? undefined, + }); + + if (result.notModified) { + this.update((state) => { + state.fetchError = null; + }); + return; } + + const newConfigs: Record = {}; + for (const network of result.data.data.networks) { + newConfigs[network.chainId] = { + key: network.chainId, + value: network as unknown as Json, + metadata: { + name: network.name, + isTestnet: network.isTestnet, + isFeatured: network.isFeatured, + } as unknown as Json, + }; + } + + this.update((state) => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (state.configs as any) = newConfigs; + state.version = result.data.data.version; + state.lastFetched = Date.now(); + state.fetchError = null; + state.etag = result.etag ?? null; + }); } catch (error) { this.#handleFetchError(error); } } - /** - * Uses the fallback configuration when API fails. - */ - #useFallbackConfig(): void { + #useFallbackConfig(errorMessage?: string): void { this.update((state) => { // eslint-disable-next-line @typescript-eslint/no-explicit-any (state.configs as any) = { ...this.#fallbackConfig }; - state.fetchError = 'Using fallback configuration - API unavailable'; - // Don't update lastFetched when using fallback + state.fetchError = + errorMessage ?? 'Using fallback configuration - API unavailable'; + state.etag = null; }); } - /** - * Handles errors during configuration fetch. - * - * @param error - The error that occurred. - */ #handleFetchError(error: unknown): void { const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; - this.update((state) => { - state.fetchError = errorMessage; - // Use fallback if we have no configs - if (Object.keys(state.configs).length === 0) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (state.configs as any) = { ...this.#fallbackConfig }; - } - }); + const hasNoConfigs = Object.keys(this.state.configs).length === 0; + + if (hasNoConfigs) { + this.#useFallbackConfig(errorMessage); + } else { + this.update((state) => { + state.fetchError = errorMessage; + }); + } } - /** - * Gets a specific configuration entry by key. - * - * @param key - The configuration key. - * @returns The configuration entry, or undefined if not found. - */ getConfig(key: string): RegistryConfigEntry | undefined { return this.state.configs[key]; } - /** - * Gets all configuration entries. - * - * @returns A copy of all configuration entries. - */ getAllConfigs(): Record { return { ...this.state.configs }; } - /** - * Gets the value of a specific configuration entry by key. - * - * @param key - The configuration key. - * @returns The configuration value, or undefined if not found. - */ getConfigValue(key: string): T | undefined { const entry = this.state.configs[key]; return entry?.value as T | undefined; } - /** - * Sets a configuration entry in the registry. - * - * @param key - The configuration key. - * @param value - The configuration value. - * @param metadata - Optional metadata for the configuration entry. - */ setConfig(key: string, value: Json, metadata?: Json): void { this.update((state) => { // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -313,39 +286,22 @@ export class ConfigRegistryController extends StaticIntervalPollingController { delete state.configs[key]; }); } - /** - * Clears all configuration entries from the registry. - */ clearConfigs(): void { this.update((state) => { state.configs = {}; }); } - /** - * Starts polling for configuration updates. - * - * @param input - Polling input (empty object for now). - * @returns A polling token that can be used to stop polling. - */ startPolling(input: ConfigRegistryPollingInput = {}): string { return super.startPolling(input); } - /** - * Stops polling for configuration updates. - */ stopPolling(): void { this.stopAllPolling(); } diff --git a/packages/config-registry-controller/src/config-registry-api-service/abstract-config-registry-api-service.ts b/packages/config-registry-controller/src/config-registry-api-service/abstract-config-registry-api-service.ts new file mode 100644 index 00000000000..5673ab8cd7c --- /dev/null +++ b/packages/config-registry-controller/src/config-registry-api-service/abstract-config-registry-api-service.ts @@ -0,0 +1,50 @@ +import type { ServicePolicy } from '@metamask/controller-utils'; + +export type NetworkConfig = { + chainId: string; + name: string; + nativeCurrency: string; + rpcEndpoints: { + url: string; + type: string; + networkClientId: string; + failoverUrls: string[]; + }[]; + blockExplorerUrls: string[]; + defaultRpcEndpointIndex: number; + defaultBlockExplorerUrlIndex: number; + lastUpdatedAt?: number; + networkImageUrl?: string; + nativeTokenImageUrl?: string; + isActive: boolean; + isTestnet: boolean; + isDefault: boolean; + isFeatured: boolean; + isDeprecated: boolean; + priority: number; + isDeletable: boolean; +}; + +export type RegistryConfigApiResponse = { + data: { + version: string; + timestamp: number; + networks: NetworkConfig[]; + }; +}; + +export type FetchConfigOptions = { + etag?: string; +}; + +export type FetchConfigResult = { + data: RegistryConfigApiResponse; + etag?: string; + notModified: boolean; +}; + +export type AbstractConfigRegistryApiService = Partial< + Pick +> & { + fetchConfig(options?: FetchConfigOptions): Promise; +}; diff --git a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts new file mode 100644 index 00000000000..d64f38341ce --- /dev/null +++ b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts @@ -0,0 +1,295 @@ +import nock, { cleanAll } from 'nock'; +import { useFakeTimers } from 'sinon'; + +import type { RegistryConfigApiResponse } from './abstract-config-registry-api-service'; +import { + ConfigRegistryApiService, + DEFAULT_API_BASE_URL, + DEFAULT_ENDPOINT_PATH, +} from './config-registry-api-service'; + +const MOCK_API_RESPONSE: RegistryConfigApiResponse = { + data: { + version: '"24952800ba9dafbc5e2c91f57f386d28"', + timestamp: 1761829548000, + networks: [ + { + chainId: '0x1', + name: 'Ethereum Mainnet', + nativeCurrency: 'ETH', + rpcEndpoints: [ + { + url: 'https://mainnet.infura.io/v3/{infuraProjectId}', + type: 'infura', + networkClientId: 'mainnet', + failoverUrls: [], + }, + ], + blockExplorerUrls: ['https://etherscan.io'], + defaultRpcEndpointIndex: 0, + defaultBlockExplorerUrlIndex: 0, + isActive: true, + isTestnet: false, + isDefault: true, + isFeatured: true, + isDeprecated: false, + priority: 0, + isDeletable: false, + }, + ], + }, +}; + +describe('ConfigRegistryApiService', () => { + describe('constructor', () => { + it('should create instance with default options', () => { + const service = new ConfigRegistryApiService(); + expect(service).toBeInstanceOf(ConfigRegistryApiService); + }); + + it('should create instance with custom options', () => { + const customFetch = jest.fn(); + const service = new ConfigRegistryApiService({ + apiBaseUrl: 'https://custom-api.example.com', + endpointPath: '/custom/path', + timeout: 5000, + fetch: customFetch, + retries: 5, + }); + expect(service).toBeInstanceOf(ConfigRegistryApiService); + }); + }); + + describe('fetchConfig', () => { + beforeEach(() => { + cleanAll(); + }); + + afterEach(() => { + cleanAll(); + }); + + it('should successfully fetch config from API', async () => { + const scope = nock(DEFAULT_API_BASE_URL) + .get(DEFAULT_ENDPOINT_PATH) + .reply(200, MOCK_API_RESPONSE, { + ETag: '"test-etag-123"', + }); + + const service = new ConfigRegistryApiService(); + const result = await service.fetchConfig(); + + expect(result.notModified).toBe(false); + expect(result.etag).toBe('"test-etag-123"'); + expect(result.data).toStrictEqual(MOCK_API_RESPONSE); + expect(scope.isDone()).toBe(true); + }); + + it('should handle 304 Not Modified response', async () => { + const etag = '"test-etag-123"'; + const scope = nock(DEFAULT_API_BASE_URL) + .get(DEFAULT_ENDPOINT_PATH) + .matchHeader('If-None-Match', etag) + .reply(304); + + const service = new ConfigRegistryApiService(); + const result = await service.fetchConfig({ etag }); + + expect(result.notModified).toBe(true); + expect(scope.isDone()).toBe(true); + }); + + it('should include If-None-Match header when etag is provided', async () => { + const etag = '"test-etag-123"'; + const scope = nock(DEFAULT_API_BASE_URL) + .get(DEFAULT_ENDPOINT_PATH) + .matchHeader('If-None-Match', etag) + .reply(200, MOCK_API_RESPONSE); + + const service = new ConfigRegistryApiService(); + await service.fetchConfig({ etag }); + + expect(scope.isDone()).toBe(true); + }); + + it('should throw error on invalid response structure', async () => { + const invalidResponse = { invalid: 'data' }; + const scope = nock(DEFAULT_API_BASE_URL) + .get(DEFAULT_ENDPOINT_PATH) + .reply(200, invalidResponse); + + const service = new ConfigRegistryApiService(); + + await expect(service.fetchConfig()).rejects.toThrow( + 'Invalid response structure from config registry API', + ); + expect(scope.isDone()).toBe(true); + }); + + it('should throw error on HTTP error status', async () => { + const scope = nock(DEFAULT_API_BASE_URL) + .get(DEFAULT_ENDPOINT_PATH) + .reply(500, { error: 'Internal Server Error' }); + + const service = new ConfigRegistryApiService(); + + await expect(service.fetchConfig()).rejects.toThrow(expect.any(Error)); + expect(scope.isDone()).toBe(true); + }); + + it('should handle timeout', async () => { + const testTimeout = 1000; // Use shorter timeout for test + // Use a custom fetch that simulates timeout with AbortError + const customFetch = jest.fn().mockImplementation(() => { + const abortError = new Error('Request aborted'); + abortError.name = 'AbortError'; + return Promise.reject(abortError); + }); + + const service = new ConfigRegistryApiService({ + timeout: testTimeout, + fetch: customFetch, + }); + + await expect(service.fetchConfig()).rejects.toThrow( + `Request timeout after ${testTimeout}ms`, + ); + }, 10000); // Increase Jest timeout for this test + + it('should retry on failure', async () => { + nock(DEFAULT_API_BASE_URL) + .get(DEFAULT_ENDPOINT_PATH) + .replyWithError('Network error'); + nock(DEFAULT_API_BASE_URL) + .get(DEFAULT_ENDPOINT_PATH) + .replyWithError('Network error'); + const successScope = nock(DEFAULT_API_BASE_URL) + .get(DEFAULT_ENDPOINT_PATH) + .reply(200, MOCK_API_RESPONSE); + + const service = new ConfigRegistryApiService({ + retries: 2, + }); + + const result = await service.fetchConfig(); + + expect(result.data).toStrictEqual(MOCK_API_RESPONSE); + expect(successScope.isDone()).toBe(true); + }); + }); + + describe('onBreak', () => { + let clock: sinon.SinonFakeTimers; + + beforeEach(() => { + clock = useFakeTimers({ now: Date.now() }); + }); + + afterEach(() => { + clock.restore(); + }); + + it('should register and call onBreak handler', async () => { + const maximumConsecutiveFailures = 3; + const retries = 0; // No retries to simplify test + + // Create enough failures to trigger circuit break + for (let i = 0; i < maximumConsecutiveFailures; i++) { + nock(DEFAULT_API_BASE_URL) + .get(DEFAULT_ENDPOINT_PATH) + .replyWithError('Network error'); + } + + const onBreakHandler = jest.fn(); + const service = new ConfigRegistryApiService({ + retries, + maximumConsecutiveFailures, + circuitBreakDuration: 10000, + }); + + service.onBreak(onBreakHandler); + + // Trigger failures to break the circuit + for (let i = 0; i < maximumConsecutiveFailures; i++) { + await expect(service.fetchConfig()).rejects.toThrow(expect.any(Error)); + // Advance time slightly between calls + await clock.tickAsync(100); + } + + // Next call should trigger onBreak + const finalPromise = service.fetchConfig(); + finalPromise.catch(() => { + // Suppress unhandled promise rejection + }); + await clock.tickAsync(100); + + await expect(finalPromise).rejects.toThrow(expect.any(Error)); + expect(onBreakHandler).toHaveBeenCalled(); + }); + }); + + describe('onDegraded', () => { + it('should register onDegraded handler', () => { + const service = new ConfigRegistryApiService(); + const onDegradedHandler = jest.fn(); + + service.onDegraded(onDegradedHandler); + + expect(service.onDegraded).toBeDefined(); + }); + }); + + describe('custom fetch function', () => { + it('should use custom fetch function when provided', async () => { + const customFetch = jest.fn().mockResolvedValue({ + ok: true, + status: 200, + headers: new Headers({ ETag: '"custom-etag"' }), + json: async () => MOCK_API_RESPONSE, + } as Response); + + const service = new ConfigRegistryApiService({ + fetch: customFetch, + apiBaseUrl: 'https://custom-api.example.com', + endpointPath: '/custom/path', + }); + + const result = await service.fetchConfig(); + + expect(customFetch).toHaveBeenCalled(); + expect(result.data).toStrictEqual(MOCK_API_RESPONSE); + }); + }); + + describe('URL construction', () => { + it('should handle base URL ending with slash', async () => { + const scope = nock('https://test-api.example.com') + .get('/config/networks') + .reply(200, MOCK_API_RESPONSE); + + const service = new ConfigRegistryApiService({ + apiBaseUrl: 'https://test-api.example.com/', + endpointPath: '/config/networks', + }); + + await service.fetchConfig(); + + expect(scope.isDone()).toBe(true); + }); + + it('should handle endpoint path without leading slash', async () => { + const scope = nock('https://test-api.example.com') + .get('/config/networks') + .reply(200, MOCK_API_RESPONSE); + + const service = new ConfigRegistryApiService({ + apiBaseUrl: 'https://test-api.example.com', + endpointPath: 'config/networks', + }); + + await service.fetchConfig(); + + expect(scope.isDone()).toBe(true); + }); + }); +}); diff --git a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts new file mode 100644 index 00000000000..65b10f4fbe4 --- /dev/null +++ b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts @@ -0,0 +1,170 @@ +import { + createServicePolicy, + DEFAULT_CIRCUIT_BREAK_DURATION, + DEFAULT_DEGRADED_THRESHOLD, + DEFAULT_MAX_CONSECUTIVE_FAILURES, + DEFAULT_MAX_RETRIES, +} from '@metamask/controller-utils'; +import type { ServicePolicy } from '@metamask/controller-utils'; + +import type { + AbstractConfigRegistryApiService, + FetchConfigOptions, + FetchConfigResult, + RegistryConfigApiResponse, +} from './abstract-config-registry-api-service'; + +export const DEFAULT_API_BASE_URL = + 'https://client-config.uat-api.cx.metamask.io/v1'; + +export const DEFAULT_ENDPOINT_PATH = '/config/networks'; + +export const DEFAULT_TIMEOUT = 10 * 1000; + +export type ConfigRegistryApiServiceOptions = { + apiBaseUrl?: string; + endpointPath?: string; + timeout?: number; + fetch?: typeof fetch; + degradedThreshold?: number; + retries?: number; + maximumConsecutiveFailures?: number; + circuitBreakDuration?: number; +}; + +export class ConfigRegistryApiService + implements AbstractConfigRegistryApiService +{ + readonly #policy: ServicePolicy; + + readonly #apiBaseUrl: string; + + readonly #endpointPath: string; + + readonly #timeout: number; + + readonly #fetch: typeof fetch; + + /** + * Construct a Config Registry API Service. + * + * @param options - The options for constructing the service. + * @param options.apiBaseUrl - The base URL for the API. Defaults to the UAT API URL. + * @param options.endpointPath - The endpoint path. Defaults to '/config/networks'. + * @param options.timeout - Timeout for HTTP requests in milliseconds. Defaults to 10 seconds. + * @param options.fetch - Custom fetch function for testing or custom implementations. Defaults to the global fetch. + * @param options.degradedThreshold - The length of time (in milliseconds) that governs when the service is regarded as degraded. Defaults to 5 seconds. + * @param options.retries - Number of retry attempts for each fetch request. Defaults to 3. + * @param options.maximumConsecutiveFailures - The maximum number of consecutive failures allowed before breaking the circuit. Defaults to 3. + * @param options.circuitBreakDuration - The amount of time to wait when the circuit breaks from too many consecutive failures. Defaults to 2 minutes. + */ + constructor({ + apiBaseUrl = DEFAULT_API_BASE_URL, + endpointPath = DEFAULT_ENDPOINT_PATH, + timeout = DEFAULT_TIMEOUT, + fetch: customFetch = globalThis.fetch, + degradedThreshold = DEFAULT_DEGRADED_THRESHOLD, + retries = DEFAULT_MAX_RETRIES, + maximumConsecutiveFailures = DEFAULT_MAX_CONSECUTIVE_FAILURES, + circuitBreakDuration = DEFAULT_CIRCUIT_BREAK_DURATION, + }: ConfigRegistryApiServiceOptions = {}) { + this.#apiBaseUrl = apiBaseUrl; + this.#endpointPath = endpointPath; + this.#timeout = timeout; + this.#fetch = customFetch; + + this.#policy = createServicePolicy({ + maxRetries: retries, + maxConsecutiveFailures: maximumConsecutiveFailures, + circuitBreakDuration, + degradedThreshold, + }); + } + + onBreak(...args: Parameters) { + return this.#policy.onBreak(...args); + } + + onDegraded(...args: Parameters) { + return this.#policy.onDegraded(...args); + } + + async fetchConfig( + options: FetchConfigOptions = {}, + ): Promise { + const baseUrl = this.#apiBaseUrl.endsWith('/') + ? this.#apiBaseUrl.slice(0, -1) + : this.#apiBaseUrl; + const endpointPath = this.#endpointPath.startsWith('/') + ? this.#endpointPath + : `/${this.#endpointPath}`; + const url = new URL(`${baseUrl}${endpointPath}`); + + const headers: HeadersInit = { + 'Cache-Control': 'no-cache', + }; + + if (options.etag) { + headers['If-None-Match'] = options.etag; + } + + const fetchWithTimeout = async (): Promise => { + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), this.#timeout); + + try { + const response = await this.#fetch(url.toString(), { + headers, + signal: controller.signal, + }); + clearTimeout(timeoutId); + return response; + } catch (error) { + clearTimeout(timeoutId); + if (error instanceof Error && error.name === 'AbortError') { + throw new Error(`Request timeout after ${this.#timeout}ms`); + } + throw error; + } + }; + + const response = await this.#policy.execute(async () => { + const res = await fetchWithTimeout(); + + if (res.status === 304) { + return { + status: 304, + headers: res.headers, + } as unknown as Response; + } + + if (!res.ok) { + throw new Error( + `Failed to fetch config: ${res.status} ${res.statusText}`, + ); + } + + return res; + }); + + if ((response as unknown as { status?: number }).status === 304) { + return { + data: {} as RegistryConfigApiResponse, + notModified: true, + }; + } + + const etag = response.headers.get('ETag') ?? undefined; + const data = (await response.json()) as RegistryConfigApiResponse; + + if (!data?.data || !Array.isArray(data.data.networks)) { + throw new Error('Invalid response structure from config registry API'); + } + + return { + data, + etag, + notModified: false, + }; + } +} diff --git a/packages/config-registry-controller/src/config-registry-api-service/index.ts b/packages/config-registry-controller/src/config-registry-api-service/index.ts new file mode 100644 index 00000000000..abf5d4fe313 --- /dev/null +++ b/packages/config-registry-controller/src/config-registry-api-service/index.ts @@ -0,0 +1,16 @@ +export type { + AbstractConfigRegistryApiService, + FetchConfigOptions, + FetchConfigResult, + NetworkConfig, + RegistryConfigApiResponse, +} from './abstract-config-registry-api-service'; + +export { + ConfigRegistryApiService, + DEFAULT_API_BASE_URL, + DEFAULT_ENDPOINT_PATH, + DEFAULT_TIMEOUT, +} from './config-registry-api-service'; + +export type { ConfigRegistryApiServiceOptions } from './config-registry-api-service'; diff --git a/packages/config-registry-controller/src/index.ts b/packages/config-registry-controller/src/index.ts index 0bea3bf4e34..d3109cf2843 100644 --- a/packages/config-registry-controller/src/index.ts +++ b/packages/config-registry-controller/src/index.ts @@ -13,4 +13,21 @@ export type { ConfigRegistryControllerStateChangeEvent, ConfigRegistryMessenger, } from './ConfigRegistryController'; -export { ConfigRegistryController } from './ConfigRegistryController'; +export { + ConfigRegistryController, + DEFAULT_POLLING_INTERVAL, +} from './ConfigRegistryController'; +export type { + AbstractConfigRegistryApiService, + FetchConfigOptions, + FetchConfigResult, + NetworkConfig, + RegistryConfigApiResponse, + ConfigRegistryApiServiceOptions, +} from './config-registry-api-service'; +export { + ConfigRegistryApiService, + DEFAULT_API_BASE_URL, + DEFAULT_ENDPOINT_PATH, + DEFAULT_TIMEOUT, +} from './config-registry-api-service'; diff --git a/packages/config-registry-controller/tsconfig.build.json b/packages/config-registry-controller/tsconfig.build.json index 85c1ead8f42..78d820648df 100644 --- a/packages/config-registry-controller/tsconfig.build.json +++ b/packages/config-registry-controller/tsconfig.build.json @@ -7,6 +7,7 @@ }, "references": [ { "path": "../base-controller/tsconfig.build.json" }, + { "path": "../controller-utils/tsconfig.build.json" }, { "path": "../messenger/tsconfig.build.json" }, { "path": "../polling-controller/tsconfig.build.json" } ], diff --git a/packages/config-registry-controller/tsconfig.json b/packages/config-registry-controller/tsconfig.json index 6e5d9ecd045..e12d81cf396 100644 --- a/packages/config-registry-controller/tsconfig.json +++ b/packages/config-registry-controller/tsconfig.json @@ -5,6 +5,7 @@ }, "references": [ { "path": "../base-controller" }, + { "path": "../controller-utils" }, { "path": "../messenger" }, { "path": "../polling-controller" } ], diff --git a/yarn.lock b/yarn.lock index 05f68519f65..0a2f54695d2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2981,6 +2981,7 @@ __metadata: "@lavamoat/allow-scripts": "npm:^3.0.4" "@metamask/auto-changelog": "npm:^3.4.4" "@metamask/base-controller": "npm:^9.0.0" + "@metamask/controller-utils": "npm:^11.16.0" "@metamask/messenger": "npm:^0.3.0" "@metamask/polling-controller": "npm:^1.0.0" "@ts-bridge/cli": "npm:^0.6.4" From 798703280642af27d0fe848244ed573365a0c19a Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Mon, 15 Dec 2025 16:25:04 +0100 Subject: [PATCH 05/55] feat: add network transformer functions for API response processing --- .gitignore | 5 +- .../config-registry-controller/package.json | 1 + .../src/config-registry-api-service/index.ts | 12 + .../transformers.ts | 318 ++++++++++++++++++ .../config-registry-controller/src/index.ts | 7 + .../tsconfig.build.json | 1 + .../config-registry-controller/tsconfig.json | 1 + yarn.lock | 5 +- 8 files changed, 347 insertions(+), 3 deletions(-) create mode 100644 packages/config-registry-controller/src/config-registry-api-service/transformers.ts diff --git a/.gitignore b/.gitignore index 6c1e52eb80d..d6b7efbe92b 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,7 @@ scripts/coverage !.yarn/releases !.yarn/sdks !.yarn/versions - +.yalc +yalc.lock # typescript -packages/*/*.tsbuildinfo \ No newline at end of file +packages/*/*.tsbuildinfo diff --git a/packages/config-registry-controller/package.json b/packages/config-registry-controller/package.json index cafcfd253ec..52fe22acde8 100644 --- a/packages/config-registry-controller/package.json +++ b/packages/config-registry-controller/package.json @@ -56,6 +56,7 @@ "devDependencies": { "@lavamoat/allow-scripts": "^3.0.4", "@metamask/auto-changelog": "^3.4.4", + "@metamask/network-controller": "workspace:*", "@ts-bridge/cli": "^0.6.4", "@types/jest": "^27.4.1", "deepmerge": "^4.2.2", diff --git a/packages/config-registry-controller/src/config-registry-api-service/index.ts b/packages/config-registry-controller/src/config-registry-api-service/index.ts index abf5d4fe313..187bf9226c0 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/index.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/index.ts @@ -14,3 +14,15 @@ export { } from './config-registry-api-service'; export type { ConfigRegistryApiServiceOptions } from './config-registry-api-service'; + +export type { + NetworkFilterOptions, + NetworkComparisonOptions, + TransformedNetworkResult, +} from './transformers'; +export { + transformNetworkConfig, + filterNetworks, + compareWithExistingNetworks, + processNetworkConfigs, +} from './transformers'; diff --git a/packages/config-registry-controller/src/config-registry-api-service/transformers.ts b/packages/config-registry-controller/src/config-registry-api-service/transformers.ts new file mode 100644 index 00000000000..f0bc3fbf654 --- /dev/null +++ b/packages/config-registry-controller/src/config-registry-api-service/transformers.ts @@ -0,0 +1,318 @@ +import type { NetworkConfiguration } from '@metamask/network-controller'; +import { RpcEndpointType } from '@metamask/network-controller'; +import type { Hex } from '@metamask/utils'; + +import type { NetworkConfig } from './abstract-config-registry-api-service'; + +type RpcEndpoint = NetworkConfiguration['rpcEndpoints'][number]; + +export type NetworkFilterOptions = { + isFeatured?: boolean; + isTestnet?: boolean; + isActive?: boolean; + isDeprecated?: boolean; + isDefault?: boolean; +}; + +export type NetworkComparisonOptions = { + existingNetworks: Record; +}; + +export type TransformedNetworkResult = { + networksToAdd: NetworkConfiguration[]; + existingChainIds: Hex[]; +}; + +/** + * @param chainId - The chain ID as a string. + * @returns The chain ID as Hex, or null if invalid. + */ +function toHexChainId(chainId: string): Hex | null { + if (!chainId || typeof chainId !== 'string') { + return null; + } + + const trimmed = chainId.trim(); + + if (trimmed.startsWith('0x') || trimmed.startsWith('0X')) { + const hex = trimmed.toLowerCase(); + if (!/^0x[0-9a-f]+$/iu.test(hex)) { + return null; + } + return hex as Hex; + } + + const decimal = Number.parseInt(trimmed, 10); + if (Number.isNaN(decimal) || decimal < 0) { + return null; + } + + return `0x${decimal.toString(16)}` as Hex; +} + +/** + * @param endpoint - The RPC endpoint from the API. + * @returns The transformed RPC endpoint, or null if invalid. + */ +function transformRpcEndpoint( + endpoint: NetworkConfig['rpcEndpoints'][0], +): RpcEndpoint | null { + if (!endpoint || typeof endpoint !== 'object') { + return null; + } + + const { url, type, networkClientId, failoverUrls } = endpoint; + + if (!url || typeof url !== 'string') { + return null; + } + + if (!type || typeof type !== 'string') { + return null; + } + + if (!networkClientId || typeof networkClientId !== 'string') { + return null; + } + + const baseEndpoint = { + networkClientId: networkClientId as string, + failoverUrls: Array.isArray(failoverUrls) + ? failoverUrls.filter( + (failoverUrl): failoverUrl is string => + typeof failoverUrl === 'string', + ) + : undefined, + }; + + if (type === 'infura') { + return { + ...baseEndpoint, + type: RpcEndpointType.Infura, + url: url as `https://${string}.infura.io/v3/{infuraProjectId}`, + } as RpcEndpoint; + } + + if (type === 'custom') { + return { + ...baseEndpoint, + type: RpcEndpointType.Custom, + url, + } as RpcEndpoint; + } + + return null; +} + +/** + * @param networkConfig - The network configuration from the API. + * @returns The transformed network configuration, or null if invalid. + */ +export function transformNetworkConfig( + networkConfig: NetworkConfig, +): NetworkConfiguration | null { + if (!networkConfig || typeof networkConfig !== 'object') { + return null; + } + + const chainId = toHexChainId(networkConfig.chainId); + if (!chainId) { + return null; + } + + const { name, nativeCurrency, rpcEndpoints, blockExplorerUrls } = + networkConfig; + + if (!name || typeof name !== 'string') { + return null; + } + + if (!nativeCurrency || typeof nativeCurrency !== 'string') { + return null; + } + + if (!Array.isArray(rpcEndpoints) || rpcEndpoints.length === 0) { + return null; + } + + const transformedEndpoints = rpcEndpoints + .map(transformRpcEndpoint) + .filter((endpoint): endpoint is RpcEndpoint => endpoint !== null); + + if (transformedEndpoints.length === 0) { + return null; + } + + const defaultRpcEndpointIndex = networkConfig.defaultRpcEndpointIndex ?? 0; + if ( + defaultRpcEndpointIndex < 0 || + defaultRpcEndpointIndex >= transformedEndpoints.length + ) { + return null; + } + + if (!Array.isArray(blockExplorerUrls)) { + return null; + } + + const validBlockExplorerUrls = blockExplorerUrls.filter( + (blockExplorerUrl): blockExplorerUrl is string => + typeof blockExplorerUrl === 'string' && blockExplorerUrl.length > 0, + ); + + const { defaultBlockExplorerUrlIndex } = networkConfig; + if ( + defaultBlockExplorerUrlIndex !== undefined && + (defaultBlockExplorerUrlIndex < 0 || + defaultBlockExplorerUrlIndex >= validBlockExplorerUrls.length) + ) { + return null; + } + + return { + chainId, + name, + nativeCurrency, + rpcEndpoints: transformedEndpoints, + blockExplorerUrls: validBlockExplorerUrls, + defaultRpcEndpointIndex, + defaultBlockExplorerUrlIndex: + validBlockExplorerUrls.length > 0 + ? (defaultBlockExplorerUrlIndex ?? 0) + : undefined, + lastUpdatedAt: networkConfig.lastUpdatedAt, + }; +} + +/** + * @param networks - Array of network configurations to filter. + * @param options - Filter options. + * @returns Filtered array of network configurations. + */ +export function filterNetworks( + networks: NetworkConfig[], + options: NetworkFilterOptions = {}, +): NetworkConfig[] { + if (!Array.isArray(networks)) { + return []; + } + + return networks.filter((network) => { + if (!network || typeof network !== 'object') { + return false; + } + + if (options.isFeatured !== undefined) { + if (network.isFeatured !== options.isFeatured) { + return false; + } + } + + if (options.isTestnet !== undefined) { + if (network.isTestnet !== options.isTestnet) { + return false; + } + } + + if (options.isActive !== undefined) { + if (network.isActive !== options.isActive) { + return false; + } + } + + if (options.isDeprecated !== undefined) { + if (network.isDeprecated !== options.isDeprecated) { + return false; + } + } + + if (options.isDefault !== undefined) { + if (network.isDefault !== options.isDefault) { + return false; + } + } + + return true; + }); +} + +/** + * @param transformedNetworks - Array of transformed network configurations. + * @param options - Comparison options. + * @returns Result containing networks to add and existing chain IDs. + */ +export function compareWithExistingNetworks( + transformedNetworks: NetworkConfiguration[], + options: NetworkComparisonOptions, +): TransformedNetworkResult { + if (!Array.isArray(transformedNetworks)) { + return { + networksToAdd: [], + existingChainIds: [], + }; + } + + const { existingNetworks } = options; + + if (!existingNetworks || typeof existingNetworks !== 'object') { + return { + networksToAdd: transformedNetworks, + existingChainIds: [], + }; + } + + const existingChainIds = new Set(Object.keys(existingNetworks) as Hex[]); + const networksToAdd: NetworkConfiguration[] = []; + const foundExistingChainIds: Hex[] = []; + + for (const network of transformedNetworks) { + if (!network || !network.chainId) { + continue; + } + + if (existingChainIds.has(network.chainId)) { + foundExistingChainIds.push(network.chainId); + } else { + networksToAdd.push(network); + } + } + + return { + networksToAdd, + existingChainIds: foundExistingChainIds, + }; +} + +/** + * @param networks - Array of network configurations from the API. + * @param filterOptions - Options for filtering networks. + * @param comparisonOptions - Options for comparing with existing networks. + * @returns Result containing networks to add and existing chain IDs. + */ +export function processNetworkConfigs( + networks: NetworkConfig[], + filterOptions: NetworkFilterOptions = {}, + comparisonOptions?: NetworkComparisonOptions, +): TransformedNetworkResult { + if (!Array.isArray(networks) || networks.length === 0) { + return { + networksToAdd: [], + existingChainIds: [], + }; + } + + const filteredNetworks = filterNetworks(networks, filterOptions); + + const transformedNetworks = filteredNetworks + .map(transformNetworkConfig) + .filter((network): network is NetworkConfiguration => network !== null); + + if (comparisonOptions) { + return compareWithExistingNetworks(transformedNetworks, comparisonOptions); + } + + return { + networksToAdd: transformedNetworks, + existingChainIds: [], + }; +} diff --git a/packages/config-registry-controller/src/index.ts b/packages/config-registry-controller/src/index.ts index d3109cf2843..c41c3ed5497 100644 --- a/packages/config-registry-controller/src/index.ts +++ b/packages/config-registry-controller/src/index.ts @@ -24,10 +24,17 @@ export type { NetworkConfig, RegistryConfigApiResponse, ConfigRegistryApiServiceOptions, + NetworkFilterOptions, + NetworkComparisonOptions, + TransformedNetworkResult, } from './config-registry-api-service'; export { ConfigRegistryApiService, DEFAULT_API_BASE_URL, DEFAULT_ENDPOINT_PATH, DEFAULT_TIMEOUT, + transformNetworkConfig, + filterNetworks, + compareWithExistingNetworks, + processNetworkConfigs, } from './config-registry-api-service'; diff --git a/packages/config-registry-controller/tsconfig.build.json b/packages/config-registry-controller/tsconfig.build.json index 78d820648df..c393837e3e3 100644 --- a/packages/config-registry-controller/tsconfig.build.json +++ b/packages/config-registry-controller/tsconfig.build.json @@ -9,6 +9,7 @@ { "path": "../base-controller/tsconfig.build.json" }, { "path": "../controller-utils/tsconfig.build.json" }, { "path": "../messenger/tsconfig.build.json" }, + { "path": "../network-controller/tsconfig.build.json" }, { "path": "../polling-controller/tsconfig.build.json" } ], "include": ["../../types", "./src"] diff --git a/packages/config-registry-controller/tsconfig.json b/packages/config-registry-controller/tsconfig.json index e12d81cf396..87ff4a0e8c7 100644 --- a/packages/config-registry-controller/tsconfig.json +++ b/packages/config-registry-controller/tsconfig.json @@ -7,6 +7,7 @@ { "path": "../base-controller" }, { "path": "../controller-utils" }, { "path": "../messenger" }, + { "path": "../network-controller" }, { "path": "../polling-controller" } ], "include": ["../../types", "./src"] diff --git a/yarn.lock b/yarn.lock index 0a2f54695d2..ce5a2f6e7d6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2983,11 +2983,14 @@ __metadata: "@metamask/base-controller": "npm:^9.0.0" "@metamask/controller-utils": "npm:^11.16.0" "@metamask/messenger": "npm:^0.3.0" + "@metamask/network-controller": "workspace:*" "@metamask/polling-controller": "npm:^1.0.0" "@ts-bridge/cli": "npm:^0.6.4" "@types/jest": "npm:^27.4.1" deepmerge: "npm:^4.2.2" jest: "npm:^27.5.1" + nock: "npm:^13.3.1" + sinon: "npm:^9.2.4" ts-jest: "npm:^27.1.4" typedoc: "npm:^0.24.8" typedoc-plugin-missing-exports: "npm:^2.0.0" @@ -4361,7 +4364,7 @@ __metadata: languageName: node linkType: hard -"@metamask/network-controller@npm:^27.0.0, @metamask/network-controller@workspace:packages/network-controller": +"@metamask/network-controller@npm:^27.0.0, @metamask/network-controller@workspace:*, @metamask/network-controller@workspace:packages/network-controller": version: 0.0.0-use.local resolution: "@metamask/network-controller@workspace:packages/network-controller" dependencies: From a4dbfca5621b4b139876476dad69c5c4ce81fb89 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Tue, 16 Dec 2025 12:20:31 +0100 Subject: [PATCH 06/55] feat: add feature flag support --- .../config-registry-controller/package.json | 3 +- .../src/ConfigRegistryController.test.ts | 231 ++++- .../src/ConfigRegistryController.ts | 17 +- .../transformers.test.ts | 847 ++++++++++++++++++ .../config-registry-controller/src/index.ts | 1 + .../src/utils/feature-flags.ts | 29 + .../tsconfig.build.json | 3 +- .../config-registry-controller/tsconfig.json | 3 +- 8 files changed, 1123 insertions(+), 11 deletions(-) create mode 100644 packages/config-registry-controller/src/config-registry-api-service/transformers.test.ts create mode 100644 packages/config-registry-controller/src/utils/feature-flags.ts diff --git a/packages/config-registry-controller/package.json b/packages/config-registry-controller/package.json index 52fe22acde8..ac45ca96480 100644 --- a/packages/config-registry-controller/package.json +++ b/packages/config-registry-controller/package.json @@ -51,7 +51,8 @@ "@metamask/base-controller": "^9.0.0", "@metamask/controller-utils": "^11.16.0", "@metamask/messenger": "^0.3.0", - "@metamask/polling-controller": "^1.0.0" + "@metamask/polling-controller": "^1.0.0", + "@metamask/remote-feature-flag-controller": "workspace:*" }, "devDependencies": { "@lavamoat/allow-scripts": "^3.0.4", diff --git a/packages/config-registry-controller/src/ConfigRegistryController.test.ts b/packages/config-registry-controller/src/ConfigRegistryController.test.ts index 9bee2032e36..afefee9696d 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.test.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.test.ts @@ -1,4 +1,8 @@ -import { Messenger, type MockAnyNamespace } from '@metamask/messenger'; +import { + Messenger, + MOCK_ANY_NAMESPACE, + type MockAnyNamespace, +} from '@metamask/messenger'; import { useFakeTimers } from 'sinon'; import type { AbstractConfigRegistryApiService } from './config-registry-api-service'; @@ -15,23 +19,45 @@ import { advanceTime } from '../../../tests/helpers'; const namespace = 'ConfigRegistryController' as const; -type RootMessenger = Messenger; +type RootMessenger = Messenger< + MockAnyNamespace, + { type: 'RemoteFeatureFlagController:getState'; handler: () => unknown }, + never +>; /** * Constructs a messenger for ConfigRegistryController. * - * @returns A controller messenger. + * @returns A controller messenger and root messenger. */ -function getConfigRegistryControllerMessenger(): ConfigRegistryMessenger { +function getConfigRegistryControllerMessenger(): { + messenger: ConfigRegistryMessenger; + rootMessenger: RootMessenger; +} { + const rootMessenger = new Messenger< + MockAnyNamespace, + { type: 'RemoteFeatureFlagController:getState'; handler: () => unknown }, + never + >({ + namespace: MOCK_ANY_NAMESPACE, + }); + const configRegistryControllerMessenger = new Messenger< typeof namespace, never, never, - RootMessenger + typeof rootMessenger >({ namespace, + parent: rootMessenger, }); - return configRegistryControllerMessenger; + + rootMessenger.delegate({ + messenger: configRegistryControllerMessenger, + actions: ['RemoteFeatureFlagController:getState'] as never[], + }); + + return { messenger: configRegistryControllerMessenger, rootMessenger }; } const MOCK_CONFIG_ENTRY: RegistryConfigEntry = { @@ -78,12 +104,28 @@ function buildMockApiService( describe('ConfigRegistryController', () => { let clock: sinon.SinonFakeTimers; let messenger: ConfigRegistryMessenger; + let rootMessenger: RootMessenger; let apiService: AbstractConfigRegistryApiService; + let mockRemoteFeatureFlagGetState: jest.Mock; beforeEach(() => { clock = useFakeTimers(); - messenger = getConfigRegistryControllerMessenger(); + const messengers = getConfigRegistryControllerMessenger(); + messenger = messengers.messenger; + rootMessenger = messengers.rootMessenger; apiService = buildMockApiService(); + + mockRemoteFeatureFlagGetState = jest.fn().mockReturnValue({ + remoteFeatureFlags: { + config_registry_api_enabled: true, + }, + cacheTimestamp: Date.now(), + }); + + rootMessenger.registerActionHandler( + 'RemoteFeatureFlagController:getState', + mockRemoteFeatureFlagGetState, + ); }); afterEach(() => { @@ -467,6 +509,13 @@ describe('ConfigRegistryController', () => { }); it('should use fallback config when no configs exist', async () => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + config_registry_api_enabled: true, + }, + cacheTimestamp: Date.now(), + }); + const errorApiService = buildMockApiService({ fetchConfig: jest.fn().mockRejectedValue(new Error('Network error')), }); @@ -487,6 +536,13 @@ describe('ConfigRegistryController', () => { }); it('should not use fallback when configs already exist', async () => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + config_registry_api_enabled: true, + }, + cacheTimestamp: Date.now(), + }); + const existingConfigs = { 'existing-key': { key: 'existing-key', value: 'existing-value' }, }; @@ -513,6 +569,13 @@ describe('ConfigRegistryController', () => { }); it('should handle errors during polling', async () => { + mockRemoteFeatureFlagGetState.mockReturnValueOnce({ + remoteFeatureFlags: { + config_registry_api_enabled: true, + }, + cacheTimestamp: Date.now(), + }); + const errorApiService = buildMockApiService({ fetchConfig: jest.fn().mockRejectedValue(new Error('Network error')), }); @@ -529,6 +592,7 @@ describe('ConfigRegistryController', () => { // Since we have no configs, it should use fallback expect(controller.state.configs).toStrictEqual(MOCK_FALLBACK_CONFIG); expect(controller.state.fetchError).toBe('Network error'); + expect(mockRemoteFeatureFlagGetState).toHaveBeenCalled(); }); it('should work via messenger actions', async () => { @@ -595,4 +659,157 @@ describe('ConfigRegistryController', () => { expect(controller.state.fetchError).toBe('Test error'); }); }); + + describe('feature flag', () => { + it('should use fallback config when feature flag is disabled', async () => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + config_registry_api_enabled: false, + }, + cacheTimestamp: Date.now(), + }); + + const controller = new ConfigRegistryController({ + messenger, + apiService, + fallbackConfig: MOCK_FALLBACK_CONFIG, + }); + + const executePollSpy = jest.spyOn(controller, '_executePoll'); + controller.startPolling({}); + + await advanceTime({ clock, duration: 0 }); + + expect(executePollSpy).toHaveBeenCalledTimes(1); + expect(controller.state.configs).toStrictEqual(MOCK_FALLBACK_CONFIG); + expect(controller.state.fetchError).toBe( + 'Feature flag disabled - using fallback configuration', + ); + + controller.stopPolling(); + }); + + it('should use API when feature flag is enabled', async () => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + config_registry_api_enabled: true, + }, + cacheTimestamp: Date.now(), + }); + + const mockNetworks = [ + { + chainId: '0x1', + name: 'Ethereum Mainnet', + nativeCurrency: 'ETH', + rpcEndpoints: [ + { + url: 'https://mainnet.infura.io/v3/{infuraProjectId}', + type: 'infura', + networkClientId: 'mainnet', + failoverUrls: [], + }, + ], + blockExplorerUrls: ['https://etherscan.io'], + defaultRpcEndpointIndex: 0, + defaultBlockExplorerUrlIndex: 0, + isTestnet: false, + isFeatured: true, + isActive: true, + isDefault: false, + isDeprecated: false, + priority: 0, + isDeletable: false, + }, + ]; + + const fetchConfigSpy = jest.fn().mockResolvedValue({ + data: { + data: { + version: '1.0.0', + timestamp: Date.now(), + networks: mockNetworks, + }, + }, + notModified: false, + etag: 'test-etag', + }); + + const mockApiService = buildMockApiService({ + fetchConfig: fetchConfigSpy, + }); + + const controller = new ConfigRegistryController({ + messenger, + apiService: mockApiService, + }); + + controller.startPolling({}); + + await advanceTime({ clock, duration: 0 }); + // Wait for async operations to complete + await new Promise((resolve) => { + setTimeout(resolve, 10); + clock.tick(10); + }); + + expect(fetchConfigSpy).toHaveBeenCalled(); + expect(controller.state.configs['0x1']).toBeDefined(); + expect(controller.state.version).toBe('1.0.0'); + expect(controller.state.fetchError).toBeNull(); + + controller.stopPolling(); + }); + + it('should default to fallback when feature flag is not set', async () => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: {}, + cacheTimestamp: Date.now(), + }); + + const controller = new ConfigRegistryController({ + messenger, + apiService, + fallbackConfig: MOCK_FALLBACK_CONFIG, + }); + + const executePollSpy = jest.spyOn(controller, '_executePoll'); + controller.startPolling({}); + + await advanceTime({ clock, duration: 0 }); + + expect(executePollSpy).toHaveBeenCalledTimes(1); + expect(controller.state.configs).toStrictEqual(MOCK_FALLBACK_CONFIG); + expect(controller.state.fetchError).toBe( + 'Feature flag disabled - using fallback configuration', + ); + + controller.stopPolling(); + }); + + it('should default to fallback when RemoteFeatureFlagController is unavailable', async () => { + mockRemoteFeatureFlagGetState.mockImplementation(() => { + throw new Error('RemoteFeatureFlagController not available'); + }); + + const controller = new ConfigRegistryController({ + messenger, + apiService, + fallbackConfig: MOCK_FALLBACK_CONFIG, + }); + + const executePollSpy = jest.spyOn(controller, '_executePoll'); + controller.startPolling({}); + + await advanceTime({ clock, duration: 0 }); + + expect(executePollSpy).toHaveBeenCalledTimes(1); + expect(controller.state.configs).toStrictEqual(MOCK_FALLBACK_CONFIG); + expect(controller.state.fetchError).toBe( + 'Feature flag disabled - using fallback configuration', + ); + + controller.stopPolling(); + }); + }); }); diff --git a/packages/config-registry-controller/src/ConfigRegistryController.ts b/packages/config-registry-controller/src/ConfigRegistryController.ts index 1ebdd196cd1..a4ec6da0697 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.ts @@ -4,6 +4,7 @@ import { } from '@metamask/base-controller'; import type { Messenger } from '@metamask/messenger'; import { StaticIntervalPollingController } from '@metamask/polling-controller'; +import type { RemoteFeatureFlagControllerState } from '@metamask/remote-feature-flag-controller'; import type { Json } from '@metamask/utils'; import type { AbstractConfigRegistryApiService } from './config-registry-api-service'; @@ -11,6 +12,7 @@ import { ConfigRegistryApiService, type FetchConfigResult, } from './config-registry-api-service'; +import { isConfigRegistryApiEnabled } from './utils/feature-flags'; const controllerName = 'ConfigRegistryController'; @@ -111,7 +113,11 @@ export type ConfigRegistryControllerActions = | ConfigRegistryControllerSetConfigAction | ConfigRegistryControllerGetAllConfigsAction | ConfigRegistryControllerStartPollingAction - | ConfigRegistryControllerStopPollingAction; + | ConfigRegistryControllerStopPollingAction + | { + type: 'RemoteFeatureFlagController:getState'; + handler: () => RemoteFeatureFlagControllerState; + }; export type ConfigRegistryControllerEvents = ConfigRegistryControllerStateChangeEvent; @@ -199,6 +205,15 @@ export class ConfigRegistryController extends StaticIntervalPollingController { + const isApiEnabled = isConfigRegistryApiEnabled(this.messenger); + + if (!isApiEnabled) { + this.#useFallbackConfig( + 'Feature flag disabled - using fallback configuration', + ); + return; + } + try { const result: FetchConfigResult = await this.#apiService.fetchConfig({ etag: this.state.etag ?? undefined, diff --git a/packages/config-registry-controller/src/config-registry-api-service/transformers.test.ts b/packages/config-registry-controller/src/config-registry-api-service/transformers.test.ts new file mode 100644 index 00000000000..2cf20b4cd3c --- /dev/null +++ b/packages/config-registry-controller/src/config-registry-api-service/transformers.test.ts @@ -0,0 +1,847 @@ +import type { NetworkConfiguration } from '@metamask/network-controller'; +import { RpcEndpointType } from '@metamask/network-controller'; +import type { Hex } from '@metamask/utils'; + +import type { NetworkConfig } from './abstract-config-registry-api-service'; +import { + compareWithExistingNetworks, + filterNetworks, + processNetworkConfigs, + transformNetworkConfig, +} from './transformers'; + +const VALID_NETWORK_CONFIG: NetworkConfig = { + chainId: '0x1', + name: 'Ethereum Mainnet', + nativeCurrency: 'ETH', + rpcEndpoints: [ + { + url: 'https://mainnet.infura.io/v3/{infuraProjectId}', + type: 'infura', + networkClientId: 'mainnet', + failoverUrls: ['https://backup.infura.io/v3/{infuraProjectId}'], + }, + ], + blockExplorerUrls: ['https://etherscan.io'], + defaultRpcEndpointIndex: 0, + defaultBlockExplorerUrlIndex: 0, + isActive: true, + isTestnet: false, + isDefault: true, + isFeatured: true, + isDeprecated: false, + priority: 0, + isDeletable: false, +}; + +const VALID_CUSTOM_NETWORK_CONFIG: NetworkConfig = { + chainId: '0x89', + name: 'Polygon', + nativeCurrency: 'MATIC', + rpcEndpoints: [ + { + url: 'https://polygon-rpc.com', + type: 'custom', + networkClientId: 'custom-polygon', + failoverUrls: [], + }, + ], + blockExplorerUrls: ['https://polygonscan.com'], + defaultRpcEndpointIndex: 0, + defaultBlockExplorerUrlIndex: 0, + isActive: true, + isTestnet: false, + isDefault: false, + isFeatured: true, + isDeprecated: false, + priority: 1, + isDeletable: false, +}; + +describe('transformers', () => { + describe('transformNetworkConfig', () => { + it('should transform valid network config with infura endpoint', () => { + const result = transformNetworkConfig(VALID_NETWORK_CONFIG); + + expect(result).not.toBeNull(); + expect(result?.chainId).toBe('0x1'); + expect(result?.name).toBe('Ethereum Mainnet'); + expect(result?.nativeCurrency).toBe('ETH'); + expect(result?.rpcEndpoints).toHaveLength(1); + expect(result?.rpcEndpoints[0].type).toBe(RpcEndpointType.Infura); + expect(result?.rpcEndpoints[0].networkClientId).toBe('mainnet'); + expect(result?.rpcEndpoints[0].failoverUrls).toStrictEqual([ + 'https://backup.infura.io/v3/{infuraProjectId}', + ]); + expect(result?.blockExplorerUrls).toStrictEqual(['https://etherscan.io']); + expect(result?.defaultRpcEndpointIndex).toBe(0); + expect(result?.defaultBlockExplorerUrlIndex).toBe(0); + }); + + it('should transform valid network config with custom endpoint', () => { + const result = transformNetworkConfig(VALID_CUSTOM_NETWORK_CONFIG); + + expect(result).not.toBeNull(); + expect(result?.chainId).toBe('0x89'); + expect(result?.rpcEndpoints[0].type).toBe(RpcEndpointType.Custom); + expect(result?.rpcEndpoints[0].url).toBe('https://polygon-rpc.com'); + }); + + it('should convert decimal chain ID to hex', () => { + const config = { + ...VALID_NETWORK_CONFIG, + chainId: '1', + }; + + const result = transformNetworkConfig(config); + + expect(result?.chainId).toBe('0x1'); + }); + + it('should handle chain ID with 0x prefix', () => { + const config = { + ...VALID_NETWORK_CONFIG, + chainId: '0X1', + }; + + const result = transformNetworkConfig(config); + + expect(result?.chainId).toBe('0x1'); + }); + + it('should return null for invalid chain ID', () => { + const config = { + ...VALID_NETWORK_CONFIG, + chainId: 'invalid', + }; + + const result = transformNetworkConfig(config); + + expect(result).toBeNull(); + }); + + it('should return null for negative chain ID', () => { + const config = { + ...VALID_NETWORK_CONFIG, + chainId: '-1', + }; + + const result = transformNetworkConfig(config); + + expect(result).toBeNull(); + }); + + it('should return null for empty chain ID', () => { + const config = { + ...VALID_NETWORK_CONFIG, + chainId: '', + }; + + const result = transformNetworkConfig(config); + + expect(result).toBeNull(); + }); + + it('should return null for invalid hex chain ID', () => { + const config = { + ...VALID_NETWORK_CONFIG, + chainId: '0xinvalid', + }; + + const result = transformNetworkConfig(config); + + expect(result).toBeNull(); + }); + + it('should return null for missing name', () => { + const config = { + ...VALID_NETWORK_CONFIG, + name: '', + }; + + const result = transformNetworkConfig(config); + + expect(result).toBeNull(); + }); + + it('should return null for missing nativeCurrency', () => { + const config = { + ...VALID_NETWORK_CONFIG, + nativeCurrency: '', + }; + + const result = transformNetworkConfig(config); + + expect(result).toBeNull(); + }); + + it('should return null for empty rpcEndpoints', () => { + const config = { + ...VALID_NETWORK_CONFIG, + rpcEndpoints: [], + }; + + const result = transformNetworkConfig(config); + + expect(result).toBeNull(); + }); + + it('should return null for invalid rpcEndpoint', () => { + const config = { + ...VALID_NETWORK_CONFIG, + rpcEndpoints: [ + { + url: '', + type: 'infura', + networkClientId: 'mainnet', + failoverUrls: [], + }, + ], + }; + + const result = transformNetworkConfig(config); + + expect(result).toBeNull(); + }); + + it('should return null for invalid rpcEndpoint type', () => { + const config = { + ...VALID_NETWORK_CONFIG, + rpcEndpoints: [ + { + url: 'https://example.com', + type: 'invalid', + networkClientId: 'test', + failoverUrls: [], + }, + ], + }; + + const result = transformNetworkConfig(config); + + expect(result).toBeNull(); + }); + + it('should return null for null rpcEndpoint', () => { + const config = { + ...VALID_NETWORK_CONFIG, + rpcEndpoints: [null as unknown as NetworkConfig['rpcEndpoints'][0]], + }; + + const result = transformNetworkConfig(config); + + expect(result).toBeNull(); + }); + + it('should return null for rpcEndpoint with empty type', () => { + const config = { + ...VALID_NETWORK_CONFIG, + rpcEndpoints: [ + { + url: 'https://example.com', + type: '', + networkClientId: 'test', + failoverUrls: [], + }, + ], + }; + + const result = transformNetworkConfig(config); + + expect(result).toBeNull(); + }); + + it('should return null for rpcEndpoint with empty networkClientId', () => { + const config = { + ...VALID_NETWORK_CONFIG, + rpcEndpoints: [ + { + url: 'https://example.com', + type: 'custom', + networkClientId: '', + failoverUrls: [], + }, + ], + }; + + const result = transformNetworkConfig(config); + + expect(result).toBeNull(); + }); + + it('should filter invalid failoverUrls', () => { + const config = { + ...VALID_NETWORK_CONFIG, + rpcEndpoints: [ + { + url: 'https://mainnet.infura.io/v3/{infuraProjectId}', + type: 'infura', + networkClientId: 'mainnet', + failoverUrls: [ + 'valid-url', + null, + undefined, + 123, + ] as unknown as string[], + }, + ], + }; + + const result = transformNetworkConfig(config); + + expect(result?.rpcEndpoints[0].failoverUrls).toStrictEqual(['valid-url']); + }); + + it('should set failoverUrls to undefined when not an array', () => { + const config = { + ...VALID_NETWORK_CONFIG, + rpcEndpoints: [ + { + url: 'https://mainnet.infura.io/v3/{infuraProjectId}', + type: 'infura', + networkClientId: 'mainnet', + failoverUrls: 'not-an-array' as unknown as string[], + }, + ], + }; + + const result = transformNetworkConfig(config); + + expect(result?.rpcEndpoints[0].failoverUrls).toBeUndefined(); + }); + + it('should return null for invalid defaultRpcEndpointIndex', () => { + const config = { + ...VALID_NETWORK_CONFIG, + defaultRpcEndpointIndex: 10, + }; + + const result = transformNetworkConfig(config); + + expect(result).toBeNull(); + }); + + it('should return null for negative defaultRpcEndpointIndex', () => { + const config = { + ...VALID_NETWORK_CONFIG, + defaultRpcEndpointIndex: -1, + }; + + const result = transformNetworkConfig(config); + + expect(result).toBeNull(); + }); + + it('should filter invalid blockExplorerUrls', () => { + const config = { + ...VALID_NETWORK_CONFIG, + blockExplorerUrls: [ + 'https://etherscan.io', + '', + null, + undefined, + 123, + ] as unknown as string[], + }; + + const result = transformNetworkConfig(config); + + expect(result?.blockExplorerUrls).toStrictEqual(['https://etherscan.io']); + }); + + it('should return null for non-array blockExplorerUrls', () => { + const config = { + ...VALID_NETWORK_CONFIG, + blockExplorerUrls: 'not-an-array' as unknown as string[], + }; + + const result = transformNetworkConfig(config); + + expect(result).toBeNull(); + }); + + it('should return null for invalid defaultBlockExplorerUrlIndex', () => { + const config = { + ...VALID_NETWORK_CONFIG, + defaultBlockExplorerUrlIndex: 10, + }; + + const result = transformNetworkConfig(config); + + expect(result).toBeNull(); + }); + + it('should set defaultBlockExplorerUrlIndex to 0 when not provided and urls exist', () => { + const { defaultBlockExplorerUrlIndex, ...configWithoutIndex } = + VALID_NETWORK_CONFIG; + const config = { + ...configWithoutIndex, + } as NetworkConfig; + + const result = transformNetworkConfig(config); + + expect(result?.defaultBlockExplorerUrlIndex).toBe(0); + }); + + it('should set defaultBlockExplorerUrlIndex to undefined when no urls', () => { + const config = { + ...VALID_NETWORK_CONFIG, + blockExplorerUrls: [], + defaultBlockExplorerUrlIndex: 0, + }; + + const result = transformNetworkConfig(config); + + expect(result?.defaultBlockExplorerUrlIndex).toBeUndefined(); + }); + + it('should use defaultRpcEndpointIndex from config when provided', () => { + const config = { + ...VALID_NETWORK_CONFIG, + rpcEndpoints: [ + { + url: 'https://mainnet.infura.io/v3/{infuraProjectId}', + type: 'infura', + networkClientId: 'mainnet', + failoverUrls: [], + }, + { + url: 'https://backup.infura.io/v3/{infuraProjectId}', + type: 'infura', + networkClientId: 'mainnet', + failoverUrls: [], + }, + ], + defaultRpcEndpointIndex: 1, + }; + + const result = transformNetworkConfig(config); + + expect(result?.defaultRpcEndpointIndex).toBe(1); + }); + + it('should preserve lastUpdatedAt', () => { + const timestamp = 1234567890; + const config = { + ...VALID_NETWORK_CONFIG, + lastUpdatedAt: timestamp, + }; + + const result = transformNetworkConfig(config); + + expect(result?.lastUpdatedAt).toBe(timestamp); + }); + + it('should return null for null input', () => { + const result = transformNetworkConfig(null as unknown as NetworkConfig); + + expect(result).toBeNull(); + }); + + it('should return null for non-object input', () => { + const result = transformNetworkConfig( + 'invalid' as unknown as NetworkConfig, + ); + + expect(result).toBeNull(); + }); + }); + + describe('filterNetworks', () => { + const networks: NetworkConfig[] = [ + { + ...VALID_NETWORK_CONFIG, + isFeatured: true, + isTestnet: false, + isActive: true, + isDeprecated: false, + isDefault: true, + }, + { + ...VALID_NETWORK_CONFIG, + chainId: '0x5', + isFeatured: false, + isTestnet: true, + isActive: true, + isDeprecated: false, + isDefault: false, + }, + { + ...VALID_NETWORK_CONFIG, + chainId: '0x2a', + isFeatured: true, + isTestnet: false, + isActive: false, + isDeprecated: true, + isDefault: false, + }, + ]; + + it('should return all networks when no filters applied', () => { + const result = filterNetworks(networks); + + expect(result).toHaveLength(3); + }); + + it('should filter by isFeatured', () => { + const result = filterNetworks(networks, { isFeatured: true }); + + expect(result).toHaveLength(2); + expect(result.every((n) => n.isFeatured)).toBe(true); + }); + + it('should filter by isTestnet', () => { + const result = filterNetworks(networks, { isTestnet: true }); + + expect(result).toHaveLength(1); + expect(result[0].chainId).toBe('0x5'); + }); + + it('should filter by isActive', () => { + const result = filterNetworks(networks, { isActive: true }); + + expect(result).toHaveLength(2); + expect(result.every((n) => n.isActive)).toBe(true); + }); + + it('should filter by isDeprecated', () => { + const result = filterNetworks(networks, { isDeprecated: true }); + + expect(result).toHaveLength(1); + expect(result[0].chainId).toBe('0x2a'); + }); + + it('should filter by isDefault', () => { + const result = filterNetworks(networks, { isDefault: true }); + + expect(result).toHaveLength(1); + expect(result[0].chainId).toBe('0x1'); + }); + + it('should filter by multiple criteria', () => { + const result = filterNetworks(networks, { + isFeatured: true, + isActive: true, + isTestnet: false, + }); + + expect(result).toHaveLength(1); + expect(result[0].chainId).toBe('0x1'); + }); + + it('should return empty array for non-array input', () => { + const result = filterNetworks(null as unknown as NetworkConfig[]); + + expect(result).toStrictEqual([]); + }); + + it('should filter out invalid network objects', () => { + const invalidNetworks = [ + null, + undefined, + 'invalid', + 123, + ...networks, + ] as unknown as NetworkConfig[]; + + const result = filterNetworks(invalidNetworks); + + expect(result).toHaveLength(3); + }); + + it('should return empty array for empty input', () => { + const result = filterNetworks([]); + + expect(result).toStrictEqual([]); + }); + }); + + describe('compareWithExistingNetworks', () => { + const existingNetworks: Record = { + '0x1': { + chainId: '0x1', + name: 'Ethereum Mainnet', + nativeCurrency: 'ETH', + rpcEndpoints: [], + blockExplorerUrls: [], + defaultRpcEndpointIndex: 0, + }, + '0x89': { + chainId: '0x89', + name: 'Polygon', + nativeCurrency: 'MATIC', + rpcEndpoints: [], + blockExplorerUrls: [], + defaultRpcEndpointIndex: 0, + }, + }; + + it('should identify new networks to add', () => { + const newNetwork: NetworkConfiguration = { + chainId: '0xa', + name: 'Optimism', + nativeCurrency: 'ETH', + rpcEndpoints: [], + blockExplorerUrls: [], + defaultRpcEndpointIndex: 0, + }; + + const result = compareWithExistingNetworks([newNetwork], { + existingNetworks, + }); + + expect(result.networksToAdd).toHaveLength(1); + expect(result.networksToAdd[0].chainId).toBe('0xa'); + expect(result.existingChainIds).toHaveLength(0); + }); + + it('should identify existing chain IDs', () => { + const existingNetwork: NetworkConfiguration = { + chainId: '0x1', + name: 'Ethereum Mainnet', + nativeCurrency: 'ETH', + rpcEndpoints: [], + blockExplorerUrls: [], + defaultRpcEndpointIndex: 0, + }; + + const result = compareWithExistingNetworks([existingNetwork], { + existingNetworks, + }); + + expect(result.networksToAdd).toHaveLength(0); + expect(result.existingChainIds).toContain('0x1'); + }); + + it('should handle mix of new and existing networks', () => { + const networks: NetworkConfiguration[] = [ + { + chainId: '0x1', + name: 'Ethereum Mainnet', + nativeCurrency: 'ETH', + rpcEndpoints: [], + blockExplorerUrls: [], + defaultRpcEndpointIndex: 0, + }, + { + chainId: '0xa', + name: 'Optimism', + nativeCurrency: 'ETH', + rpcEndpoints: [], + blockExplorerUrls: [], + defaultRpcEndpointIndex: 0, + }, + { + chainId: '0x89', + name: 'Polygon', + nativeCurrency: 'MATIC', + rpcEndpoints: [], + blockExplorerUrls: [], + defaultRpcEndpointIndex: 0, + }, + ]; + + const result = compareWithExistingNetworks(networks, { + existingNetworks, + }); + + expect(result.networksToAdd).toHaveLength(1); + expect(result.networksToAdd[0].chainId).toBe('0xa'); + expect(result.existingChainIds).toHaveLength(2); + expect(result.existingChainIds).toContain('0x1'); + expect(result.existingChainIds).toContain('0x89'); + }); + + it('should return all networks when no existing networks provided', () => { + const networks: NetworkConfiguration[] = [ + { + chainId: '0x1', + name: 'Ethereum Mainnet', + nativeCurrency: 'ETH', + rpcEndpoints: [], + blockExplorerUrls: [], + defaultRpcEndpointIndex: 0, + }, + ]; + + const result = compareWithExistingNetworks(networks, { + existingNetworks: {}, + }); + + expect(result.networksToAdd).toHaveLength(1); + expect(result.existingChainIds).toHaveLength(0); + }); + + it('should handle null existingNetworks', () => { + const networks: NetworkConfiguration[] = [ + { + chainId: '0x1', + name: 'Ethereum Mainnet', + nativeCurrency: 'ETH', + rpcEndpoints: [], + blockExplorerUrls: [], + defaultRpcEndpointIndex: 0, + }, + ]; + + const result = compareWithExistingNetworks(networks, { + existingNetworks: null as unknown as Record, + }); + + expect(result.networksToAdd).toHaveLength(1); + expect(result.existingChainIds).toHaveLength(0); + }); + + it('should skip networks without chainId', () => { + const networks: NetworkConfiguration[] = [ + { + chainId: '0x1' as Hex, + name: 'Ethereum Mainnet', + nativeCurrency: 'ETH', + rpcEndpoints: [], + blockExplorerUrls: [], + defaultRpcEndpointIndex: 0, + }, + null as unknown as NetworkConfiguration, + { + chainId: undefined as unknown as Hex, + name: 'Invalid', + nativeCurrency: 'ETH', + rpcEndpoints: [], + blockExplorerUrls: [], + defaultRpcEndpointIndex: 0, + }, + ]; + + const result = compareWithExistingNetworks(networks, { + existingNetworks, + }); + + expect(result.networksToAdd).toHaveLength(0); + expect(result.existingChainIds).toContain('0x1'); + }); + + it('should return empty arrays for non-array input', () => { + const result = compareWithExistingNetworks( + null as unknown as NetworkConfiguration[], + { + existingNetworks, + }, + ); + + expect(result.networksToAdd).toStrictEqual([]); + expect(result.existingChainIds).toStrictEqual([]); + }); + }); + + describe('processNetworkConfigs', () => { + it('should process networks without filtering or comparison', () => { + const networks = [VALID_NETWORK_CONFIG]; + + const result = processNetworkConfigs(networks); + + expect(result.networksToAdd).toHaveLength(1); + expect(result.existingChainIds).toHaveLength(0); + }); + + it('should filter networks before processing', () => { + const networks = [ + VALID_NETWORK_CONFIG, + { + ...VALID_NETWORK_CONFIG, + chainId: '0x5', + isFeatured: false, + }, + ]; + + const result = processNetworkConfigs(networks, { isFeatured: true }); + + expect(result.networksToAdd).toHaveLength(1); + expect(result.networksToAdd[0].chainId).toBe('0x1'); + }); + + it('should compare with existing networks', () => { + const existingNetworks: Record = { + '0x1': { + chainId: '0x1', + name: 'Ethereum Mainnet', + nativeCurrency: 'ETH', + rpcEndpoints: [], + blockExplorerUrls: [], + defaultRpcEndpointIndex: 0, + }, + }; + + const networks = [VALID_NETWORK_CONFIG, VALID_CUSTOM_NETWORK_CONFIG]; + + const result = processNetworkConfigs(networks, {}, { existingNetworks }); + + expect(result.networksToAdd).toHaveLength(1); + expect(result.networksToAdd[0].chainId).toBe('0x89'); + expect(result.existingChainIds).toContain('0x1'); + }); + + it('should filter invalid networks during transformation', () => { + const networks = [ + VALID_NETWORK_CONFIG, + { + ...VALID_NETWORK_CONFIG, + chainId: 'invalid', + }, + null as unknown as NetworkConfig, + ]; + + const result = processNetworkConfigs(networks); + + expect(result.networksToAdd).toHaveLength(1); + expect(result.networksToAdd[0].chainId).toBe('0x1'); + }); + + it('should return empty arrays for empty input', () => { + const result = processNetworkConfigs([]); + + expect(result.networksToAdd).toStrictEqual([]); + expect(result.existingChainIds).toStrictEqual([]); + }); + + it('should return empty arrays for non-array input', () => { + const result = processNetworkConfigs(null as unknown as NetworkConfig[]); + + expect(result.networksToAdd).toStrictEqual([]); + expect(result.existingChainIds).toStrictEqual([]); + }); + + it('should combine filtering and comparison', () => { + const existingNetworks: Record = { + '0x1': { + chainId: '0x1', + name: 'Ethereum Mainnet', + nativeCurrency: 'ETH', + rpcEndpoints: [], + blockExplorerUrls: [], + defaultRpcEndpointIndex: 0, + }, + }; + + const networks = [ + VALID_NETWORK_CONFIG, + { + ...VALID_NETWORK_CONFIG, + chainId: '0x5', + isFeatured: false, + }, + VALID_CUSTOM_NETWORK_CONFIG, + ]; + + const result = processNetworkConfigs( + networks, + { isFeatured: true }, + { existingNetworks }, + ); + + expect(result.networksToAdd).toHaveLength(1); + expect(result.networksToAdd[0].chainId).toBe('0x89'); + expect(result.existingChainIds).toContain('0x1'); + }); + }); +}); diff --git a/packages/config-registry-controller/src/index.ts b/packages/config-registry-controller/src/index.ts index c41c3ed5497..49a392b0938 100644 --- a/packages/config-registry-controller/src/index.ts +++ b/packages/config-registry-controller/src/index.ts @@ -38,3 +38,4 @@ export { compareWithExistingNetworks, processNetworkConfigs, } from './config-registry-api-service'; +export { isConfigRegistryApiEnabled } from './utils/feature-flags'; diff --git a/packages/config-registry-controller/src/utils/feature-flags.ts b/packages/config-registry-controller/src/utils/feature-flags.ts new file mode 100644 index 00000000000..af27b2e1976 --- /dev/null +++ b/packages/config-registry-controller/src/utils/feature-flags.ts @@ -0,0 +1,29 @@ +import type { ConfigRegistryMessenger } from '../ConfigRegistryController'; + +const FEATURE_FLAG_KEY = 'config_registry_api_enabled'; +const DEFAULT_FEATURE_FLAG_VALUE = false; + +/** + * Checks if the config registry API feature flag is enabled. + * + * @param messenger - The controller messenger. + * @returns True if the feature flag is enabled, false otherwise. + */ +export function isConfigRegistryApiEnabled( + messenger: ConfigRegistryMessenger, +): boolean { + try { + const state = messenger.call('RemoteFeatureFlagController:getState'); + const featureFlags = state.remoteFeatureFlags; + + const flagValue = featureFlags[FEATURE_FLAG_KEY]; + + if (typeof flagValue === 'boolean') { + return flagValue; + } + + return DEFAULT_FEATURE_FLAG_VALUE; + } catch { + return DEFAULT_FEATURE_FLAG_VALUE; + } +} diff --git a/packages/config-registry-controller/tsconfig.build.json b/packages/config-registry-controller/tsconfig.build.json index c393837e3e3..97065187fac 100644 --- a/packages/config-registry-controller/tsconfig.build.json +++ b/packages/config-registry-controller/tsconfig.build.json @@ -10,7 +10,8 @@ { "path": "../controller-utils/tsconfig.build.json" }, { "path": "../messenger/tsconfig.build.json" }, { "path": "../network-controller/tsconfig.build.json" }, - { "path": "../polling-controller/tsconfig.build.json" } + { "path": "../polling-controller/tsconfig.build.json" }, + { "path": "../remote-feature-flag-controller/tsconfig.build.json" } ], "include": ["../../types", "./src"] } diff --git a/packages/config-registry-controller/tsconfig.json b/packages/config-registry-controller/tsconfig.json index 87ff4a0e8c7..77180fee9e8 100644 --- a/packages/config-registry-controller/tsconfig.json +++ b/packages/config-registry-controller/tsconfig.json @@ -8,7 +8,8 @@ { "path": "../controller-utils" }, { "path": "../messenger" }, { "path": "../network-controller" }, - { "path": "../polling-controller" } + { "path": "../polling-controller" }, + { "path": "../remote-feature-flag-controller" } ], "include": ["../../types", "./src"] } From 3f3ce9c5b1758ef9dedc008f0c605954c73bda51 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Fri, 16 Jan 2026 11:38:13 +0100 Subject: [PATCH 07/55] fix: fix polling-controller version in config registry controller --- packages/config-registry-controller/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/config-registry-controller/package.json b/packages/config-registry-controller/package.json index ac45ca96480..933c303c529 100644 --- a/packages/config-registry-controller/package.json +++ b/packages/config-registry-controller/package.json @@ -51,7 +51,7 @@ "@metamask/base-controller": "^9.0.0", "@metamask/controller-utils": "^11.16.0", "@metamask/messenger": "^0.3.0", - "@metamask/polling-controller": "^1.0.0", + "@metamask/polling-controller": "^16.0.0", "@metamask/remote-feature-flag-controller": "workspace:*" }, "devDependencies": { From 6e2a12843e4ca6ed72e2f91df711226aaa5759d1 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Mon, 19 Jan 2026 23:57:49 +0100 Subject: [PATCH 08/55] chore: restructure state to nest networks under configs --- .../src/ConfigRegistryController.test.ts | 82 +++++++++++-------- .../src/ConfigRegistryController.ts | 36 +++++--- .../src/utils/feature-flags.ts | 2 +- 3 files changed, 76 insertions(+), 44 deletions(-) diff --git a/packages/config-registry-controller/src/ConfigRegistryController.test.ts b/packages/config-registry-controller/src/ConfigRegistryController.test.ts index afefee9696d..41bca1100df 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.test.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.test.ts @@ -140,7 +140,7 @@ describe('ConfigRegistryController', () => { }); expect(controller.state).toStrictEqual({ - configs: {}, + configs: { networks: {} }, version: null, lastFetched: null, fetchError: null, @@ -151,7 +151,9 @@ describe('ConfigRegistryController', () => { it('should set initial state when provided', () => { const initialState: Partial = { configs: { - 'test-key': MOCK_CONFIG_ENTRY, + networks: { + 'test-key': MOCK_CONFIG_ENTRY, + }, }, version: 'v1.0.0', lastFetched: 1234567890, @@ -163,7 +165,7 @@ describe('ConfigRegistryController', () => { apiService, }); - expect(controller.state.configs).toStrictEqual(initialState.configs); + expect(controller.state.configs.networks).toStrictEqual(initialState.configs?.networks); expect(controller.state.version).toBe('v1.0.0'); expect(controller.state.lastFetched).toBe(1234567890); }); @@ -187,7 +189,7 @@ describe('ConfigRegistryController', () => { }); // Fallback config is private, but we can verify it's used when needed - expect(controller.state.configs).toStrictEqual({}); + expect(controller.state.configs).toStrictEqual({ networks: {} }); }); }); @@ -207,7 +209,9 @@ describe('ConfigRegistryController', () => { messenger, state: { configs: { - 'test-key': MOCK_CONFIG_ENTRY, + networks: { + 'test-key': MOCK_CONFIG_ENTRY, + }, }, }, }); @@ -221,7 +225,9 @@ describe('ConfigRegistryController', () => { messenger, state: { configs: { - 'test-key': MOCK_CONFIG_ENTRY, + networks: { + 'test-key': MOCK_CONFIG_ENTRY, + }, }, }, }); @@ -256,7 +262,7 @@ describe('ConfigRegistryController', () => { const controller = new ConfigRegistryController({ apiService, messenger, - state: { configs }, + state: { configs: { networks: configs } }, }); expect(controller.getAllConfigs()).toStrictEqual(configs); @@ -270,14 +276,14 @@ describe('ConfigRegistryController', () => { const controller = new ConfigRegistryController({ apiService, messenger, - state: { configs }, + state: { configs: { networks: configs } }, }); const result = controller.getAllConfigs(); result.key1 = { key: 'key1', value: 'modified' }; // Original should not be modified - expect(controller.state.configs.key1.value).toBe('value1'); + expect(controller.state.configs.networks?.key1?.value).toBe('value1'); }); it('should work via messenger action', () => { @@ -288,7 +294,7 @@ describe('ConfigRegistryController', () => { const testController = new ConfigRegistryController({ messenger, apiService, - state: { configs }, + state: { configs: { networks: configs } }, }); const result = messenger.call('ConfigRegistryController:getAllConfigs'); @@ -313,7 +319,9 @@ describe('ConfigRegistryController', () => { messenger, state: { configs: { - 'test-key': MOCK_CONFIG_ENTRY, + networks: { + 'test-key': MOCK_CONFIG_ENTRY, + }, }, }, }); @@ -329,8 +337,10 @@ describe('ConfigRegistryController', () => { messenger, state: { configs: { - 'string-key': { key: 'string-key', value: 'string-value' }, - 'number-key': { key: 'number-key', value: 42 }, + networks: { + 'string-key': { key: 'string-key', value: 'string-value' }, + 'number-key': { key: 'number-key', value: 42 }, + }, }, }, }); @@ -351,7 +361,7 @@ describe('ConfigRegistryController', () => { controller.setConfig('new-key', { data: 'value' }); - expect(controller.state.configs['new-key']).toStrictEqual({ + expect(controller.state.configs.networks?.['new-key']).toStrictEqual({ key: 'new-key', value: { data: 'value' }, metadata: undefined, @@ -366,7 +376,7 @@ describe('ConfigRegistryController', () => { controller.setConfig('new-key', { data: 'value' }, { source: 'test' }); - expect(controller.state.configs['new-key']).toStrictEqual({ + expect(controller.state.configs.networks?.['new-key']).toStrictEqual({ key: 'new-key', value: { data: 'value' }, metadata: { source: 'test' }, @@ -379,14 +389,16 @@ describe('ConfigRegistryController', () => { apiService, state: { configs: { - 'existing-key': { key: 'existing-key', value: 'old-value' }, + networks: { + 'existing-key': { key: 'existing-key', value: 'old-value' }, + }, }, }, }); controller.setConfig('existing-key', 'new-value'); - expect(controller.state.configs['existing-key'].value).toBe('new-value'); + expect(controller.state.configs.networks?.['existing-key']?.value).toBe('new-value'); }); it('should work via messenger action', () => { @@ -412,16 +424,18 @@ describe('ConfigRegistryController', () => { messenger, state: { configs: { - key1: { key: 'key1', value: 'value1' }, - key2: { key: 'key2', value: 'value2' }, + networks: { + key1: { key: 'key1', value: 'value1' }, + key2: { key: 'key2', value: 'value2' }, + }, }, }, }); controller.removeConfig('key1'); - expect(controller.state.configs.key1).toBeUndefined(); - expect(controller.state.configs.key2).toBeDefined(); + expect(controller.state.configs.networks?.key1).toBeUndefined(); + expect(controller.state.configs.networks?.key2).toBeDefined(); }); it('should not throw when removing non-existent key', () => { @@ -441,15 +455,17 @@ describe('ConfigRegistryController', () => { apiService, state: { configs: { - key1: { key: 'key1', value: 'value1' }, - key2: { key: 'key2', value: 'value2' }, + networks: { + key1: { key: 'key1', value: 'value1' }, + key2: { key: 'key2', value: 'value2' }, + }, }, }, }); controller.clearConfigs(); - expect(controller.state.configs).toStrictEqual({}); + expect(controller.state.configs).toStrictEqual({ networks: {} }); }); }); @@ -529,7 +545,7 @@ describe('ConfigRegistryController', () => { controller.startPolling({}); await advanceTime({ clock, duration: 0 }); - expect(controller.state.configs).toStrictEqual(MOCK_FALLBACK_CONFIG); + expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG }); expect(controller.state.fetchError).toBe('Network error'); controller.stopPolling(); @@ -544,7 +560,9 @@ describe('ConfigRegistryController', () => { }); const existingConfigs = { - 'existing-key': { key: 'existing-key', value: 'existing-value' }, + networks: { + 'existing-key': { key: 'existing-key', value: 'existing-value' }, + }, }; const errorApiService = buildMockApiService({ @@ -590,7 +608,7 @@ describe('ConfigRegistryController', () => { await controller._executePoll({}); // Since we have no configs, it should use fallback - expect(controller.state.configs).toStrictEqual(MOCK_FALLBACK_CONFIG); + expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG }); expect(controller.state.fetchError).toBe('Network error'); expect(mockRemoteFeatureFlagGetState).toHaveBeenCalled(); }); @@ -625,7 +643,7 @@ describe('ConfigRegistryController', () => { controller.setConfig('persist-key', 'persist-value'); // Verify state is updated - expect(controller.state.configs['persist-key']).toBeDefined(); + expect(controller.state.configs.networks?.['persist-key']).toBeDefined(); }); it('should persist version', () => { @@ -681,7 +699,7 @@ describe('ConfigRegistryController', () => { await advanceTime({ clock, duration: 0 }); expect(executePollSpy).toHaveBeenCalledTimes(1); - expect(controller.state.configs).toStrictEqual(MOCK_FALLBACK_CONFIG); + expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG }); expect(controller.state.fetchError).toBe( 'Feature flag disabled - using fallback configuration', ); @@ -754,7 +772,7 @@ describe('ConfigRegistryController', () => { }); expect(fetchConfigSpy).toHaveBeenCalled(); - expect(controller.state.configs['0x1']).toBeDefined(); + expect(controller.state.configs.networks?.['0x1']).toBeDefined(); expect(controller.state.version).toBe('1.0.0'); expect(controller.state.fetchError).toBeNull(); @@ -779,7 +797,7 @@ describe('ConfigRegistryController', () => { await advanceTime({ clock, duration: 0 }); expect(executePollSpy).toHaveBeenCalledTimes(1); - expect(controller.state.configs).toStrictEqual(MOCK_FALLBACK_CONFIG); + expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG }); expect(controller.state.fetchError).toBe( 'Feature flag disabled - using fallback configuration', ); @@ -804,7 +822,7 @@ describe('ConfigRegistryController', () => { await advanceTime({ clock, duration: 0 }); expect(executePollSpy).toHaveBeenCalledTimes(1); - expect(controller.state.configs).toStrictEqual(MOCK_FALLBACK_CONFIG); + expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG }); expect(controller.state.fetchError).toBe( 'Feature flag disabled - using fallback configuration', ); diff --git a/packages/config-registry-controller/src/ConfigRegistryController.ts b/packages/config-registry-controller/src/ConfigRegistryController.ts index a4ec6da0697..ce6e910d806 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.ts @@ -25,7 +25,9 @@ export type RegistryConfigEntry = { }; export type ConfigRegistryState = { - configs: Record; + configs: { + networks?: Record; + }; version: string | null; lastFetched: number | null; fetchError: string | null; @@ -165,7 +167,7 @@ export class ConfigRegistryController extends StaticIntervalPollingController { // eslint-disable-next-line @typescript-eslint/no-explicit-any - (state.configs as any) = newConfigs; + (state.configs as any) = { networks: newConfigs }; state.version = result.data.data.version; state.lastFetched = Date.now(); state.fetchError = null; @@ -255,7 +257,7 @@ export class ConfigRegistryController extends StaticIntervalPollingController { // eslint-disable-next-line @typescript-eslint/no-explicit-any - (state.configs as any) = { ...this.#fallbackConfig }; + (state.configs as any) = { networks: { ...this.#fallbackConfig } }; state.fetchError = errorMessage ?? 'Using fallback configuration - API unavailable'; state.etag = null; @@ -266,7 +268,8 @@ export class ConfigRegistryController extends StaticIntervalPollingController { - return { ...this.state.configs }; + return { ...(this.state.configs?.networks || {}) }; } getConfigValue(key: string): T | undefined { - const entry = this.state.configs[key]; + const entry = this.state.configs?.networks?.[key]; return entry?.value as T | undefined; } setConfig(key: string, value: Json, metadata?: Json): void { this.update((state) => { + if (!state.configs) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (state.configs as any) = { networks: {} }; + } + if (!state.configs.networks) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (state.configs.networks as any) = {}; + } // eslint-disable-next-line @typescript-eslint/no-explicit-any - (state.configs as any)[key] = { + (state.configs.networks as any)[key] = { key, value, metadata, @@ -303,13 +314,16 @@ export class ConfigRegistryController extends StaticIntervalPollingController { - delete state.configs[key]; + if (state.configs?.networks) { + delete state.configs.networks[key]; + } }); } clearConfigs(): void { this.update((state) => { - state.configs = {}; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (state.configs as any) = { networks: {} }; }); } diff --git a/packages/config-registry-controller/src/utils/feature-flags.ts b/packages/config-registry-controller/src/utils/feature-flags.ts index af27b2e1976..c20f90e2eeb 100644 --- a/packages/config-registry-controller/src/utils/feature-flags.ts +++ b/packages/config-registry-controller/src/utils/feature-flags.ts @@ -1,6 +1,6 @@ import type { ConfigRegistryMessenger } from '../ConfigRegistryController'; -const FEATURE_FLAG_KEY = 'config_registry_api_enabled'; +const FEATURE_FLAG_KEY = 'configRegistryApiEnabled'; const DEFAULT_FEATURE_FLAG_VALUE = false; /** From 77e35fd1dc47d4b038cc5fc33c70d5e4e74592b2 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Tue, 20 Jan 2026 01:40:27 +0100 Subject: [PATCH 09/55] chore: remove metadat from config network response --- .../src/ConfigRegistryController.test.ts | 50 ++++++++++--------- .../src/ConfigRegistryController.ts | 5 -- 2 files changed, 26 insertions(+), 29 deletions(-) diff --git a/packages/config-registry-controller/src/ConfigRegistryController.test.ts b/packages/config-registry-controller/src/ConfigRegistryController.test.ts index 41bca1100df..275550d8fb6 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.test.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.test.ts @@ -50,7 +50,7 @@ function getConfigRegistryControllerMessenger(): { >({ namespace, parent: rootMessenger, - }); + }) as ConfigRegistryMessenger; rootMessenger.delegate({ messenger: configRegistryControllerMessenger, @@ -165,7 +165,9 @@ describe('ConfigRegistryController', () => { apiService, }); - expect(controller.state.configs.networks).toStrictEqual(initialState.configs?.networks); + expect(controller.state.configs.networks).toStrictEqual( + initialState.configs?.networks, + ); expect(controller.state.version).toBe('v1.0.0'); expect(controller.state.lastFetched).toBe(1234567890); }); @@ -398,7 +400,9 @@ describe('ConfigRegistryController', () => { controller.setConfig('existing-key', 'new-value'); - expect(controller.state.configs.networks?.['existing-key']?.value).toBe('new-value'); + expect(controller.state.configs.networks?.['existing-key']?.value).toBe( + 'new-value', + ); }); it('should work via messenger action', () => { @@ -542,13 +546,12 @@ describe('ConfigRegistryController', () => { fallbackConfig: MOCK_FALLBACK_CONFIG, }); - controller.startPolling({}); - await advanceTime({ clock, duration: 0 }); + await controller._executePoll({}); - expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG }); + expect(controller.state.configs).toStrictEqual({ + networks: MOCK_FALLBACK_CONFIG, + }); expect(controller.state.fetchError).toBe('Network error'); - - controller.stopPolling(); }); it('should not use fallback when configs already exist', async () => { @@ -576,14 +579,11 @@ describe('ConfigRegistryController', () => { fallbackConfig: MOCK_FALLBACK_CONFIG, }); - controller.startPolling({}); - await advanceTime({ clock, duration: 0 }); + await controller._executePoll({}); // Should keep existing configs, not use fallback expect(controller.state.configs).toStrictEqual(existingConfigs); expect(controller.state.fetchError).toBe('Network error'); - - controller.stopPolling(); }); it('should handle errors during polling', async () => { @@ -608,7 +608,9 @@ describe('ConfigRegistryController', () => { await controller._executePoll({}); // Since we have no configs, it should use fallback - expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG }); + expect(controller.state.configs).toStrictEqual({ + networks: MOCK_FALLBACK_CONFIG, + }); expect(controller.state.fetchError).toBe('Network error'); expect(mockRemoteFeatureFlagGetState).toHaveBeenCalled(); }); @@ -699,7 +701,9 @@ describe('ConfigRegistryController', () => { await advanceTime({ clock, duration: 0 }); expect(executePollSpy).toHaveBeenCalledTimes(1); - expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG }); + expect(controller.state.configs).toStrictEqual({ + networks: MOCK_FALLBACK_CONFIG, + }); expect(controller.state.fetchError).toBe( 'Feature flag disabled - using fallback configuration', ); @@ -762,14 +766,8 @@ describe('ConfigRegistryController', () => { apiService: mockApiService, }); - controller.startPolling({}); - - await advanceTime({ clock, duration: 0 }); - // Wait for async operations to complete - await new Promise((resolve) => { - setTimeout(resolve, 10); - clock.tick(10); - }); + const executePollPromise = controller._executePoll({}); + await executePollPromise; expect(fetchConfigSpy).toHaveBeenCalled(); expect(controller.state.configs.networks?.['0x1']).toBeDefined(); @@ -797,7 +795,9 @@ describe('ConfigRegistryController', () => { await advanceTime({ clock, duration: 0 }); expect(executePollSpy).toHaveBeenCalledTimes(1); - expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG }); + expect(controller.state.configs).toStrictEqual({ + networks: MOCK_FALLBACK_CONFIG, + }); expect(controller.state.fetchError).toBe( 'Feature flag disabled - using fallback configuration', ); @@ -822,7 +822,9 @@ describe('ConfigRegistryController', () => { await advanceTime({ clock, duration: 0 }); expect(executePollSpy).toHaveBeenCalledTimes(1); - expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG }); + expect(controller.state.configs).toStrictEqual({ + networks: MOCK_FALLBACK_CONFIG, + }); expect(controller.state.fetchError).toBe( 'Feature flag disabled - using fallback configuration', ); diff --git a/packages/config-registry-controller/src/ConfigRegistryController.ts b/packages/config-registry-controller/src/ConfigRegistryController.ts index ce6e910d806..fa2efb955a1 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.ts @@ -233,11 +233,6 @@ export class ConfigRegistryController extends StaticIntervalPollingController Date: Tue, 20 Jan 2026 16:53:35 +0100 Subject: [PATCH 10/55] fix: fix tests --- .../src/ConfigRegistryController.test.ts | 12 +- yarn.lock | 258 +----------------- 2 files changed, 14 insertions(+), 256 deletions(-) diff --git a/packages/config-registry-controller/src/ConfigRegistryController.test.ts b/packages/config-registry-controller/src/ConfigRegistryController.test.ts index 275550d8fb6..2d44ed3de04 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.test.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.test.ts @@ -117,7 +117,7 @@ describe('ConfigRegistryController', () => { mockRemoteFeatureFlagGetState = jest.fn().mockReturnValue({ remoteFeatureFlags: { - config_registry_api_enabled: true, + configRegistryApiEnabled: true, }, cacheTimestamp: Date.now(), }); @@ -531,7 +531,7 @@ describe('ConfigRegistryController', () => { it('should use fallback config when no configs exist', async () => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { - config_registry_api_enabled: true, + configRegistryApiEnabled: true, }, cacheTimestamp: Date.now(), }); @@ -557,7 +557,7 @@ describe('ConfigRegistryController', () => { it('should not use fallback when configs already exist', async () => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { - config_registry_api_enabled: true, + configRegistryApiEnabled: true, }, cacheTimestamp: Date.now(), }); @@ -589,7 +589,7 @@ describe('ConfigRegistryController', () => { it('should handle errors during polling', async () => { mockRemoteFeatureFlagGetState.mockReturnValueOnce({ remoteFeatureFlags: { - config_registry_api_enabled: true, + configRegistryApiEnabled: true, }, cacheTimestamp: Date.now(), }); @@ -684,7 +684,7 @@ describe('ConfigRegistryController', () => { it('should use fallback config when feature flag is disabled', async () => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { - config_registry_api_enabled: false, + configRegistryApiEnabled: false, }, cacheTimestamp: Date.now(), }); @@ -714,7 +714,7 @@ describe('ConfigRegistryController', () => { it('should use API when feature flag is enabled', async () => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { - config_registry_api_enabled: true, + configRegistryApiEnabled: true, }, cacheTimestamp: Date.now(), }); diff --git a/yarn.lock b/yarn.lock index ce5a2f6e7d6..2aba1d9b02a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2385,7 +2385,7 @@ __metadata: languageName: node linkType: hard -"@metamask/abi-utils@npm:^2.0.3, @metamask/abi-utils@npm:^2.0.4": +"@metamask/abi-utils@npm:^2.0.3": version: 2.0.4 resolution: "@metamask/abi-utils@npm:2.0.4" dependencies: @@ -2761,16 +2761,6 @@ __metadata: languageName: node linkType: hard -"@metamask/base-controller@npm:^3.2.3": - version: 3.2.3 - resolution: "@metamask/base-controller@npm:3.2.3" - dependencies: - "@metamask/utils": "npm:^8.1.0" - immer: "npm:^9.0.6" - checksum: 10/1a3005f4143f0a3e37094ce389ae9c2010194672d67c1b115a401379c1b712fb3d7ce8f1cbc8a4d21cffba61aafba6dc1aaae12172e57b9f14021a2505fadafe - languageName: node - linkType: hard - "@metamask/base-controller@npm:^8.0.1, @metamask/base-controller@npm:^8.4.2": version: 8.4.2 resolution: "@metamask/base-controller@npm:8.4.2" @@ -2984,7 +2974,8 @@ __metadata: "@metamask/controller-utils": "npm:^11.16.0" "@metamask/messenger": "npm:^0.3.0" "@metamask/network-controller": "workspace:*" - "@metamask/polling-controller": "npm:^1.0.0" + "@metamask/polling-controller": "npm:^16.0.0" + "@metamask/remote-feature-flag-controller": "workspace:*" "@ts-bridge/cli": "npm:^0.6.4" "@types/jest": "npm:^27.4.1" deepmerge: "npm:^4.2.2" @@ -3039,21 +3030,6 @@ __metadata: languageName: unknown linkType: soft -"@metamask/controller-utils@npm:^5.0.2": - version: 5.0.2 - resolution: "@metamask/controller-utils@npm:5.0.2" - dependencies: - "@metamask/eth-query": "npm:^3.0.1" - "@metamask/utils": "npm:^8.1.0" - "@spruceid/siwe-parser": "npm:1.1.3" - eth-ens-namehash: "npm:^2.0.8" - ethereumjs-util: "npm:^7.0.10" - ethjs-unit: "npm:^0.1.6" - fast-deep-equal: "npm:^3.1.3" - checksum: 10/fde3d4893ddd408e1b6138180d53568e27626b5884a404473a3e75d4615ba4525aa33deb21a24a438ff0928431d278efd9c084e9aca7eeaaf2a1c300691318d5 - languageName: node - linkType: hard - "@metamask/core-backend@npm:^5.0.0, @metamask/core-backend@workspace:packages/core-backend": version: 0.0.0-use.local resolution: "@metamask/core-backend@workspace:packages/core-backend" @@ -3421,19 +3397,6 @@ __metadata: languageName: unknown linkType: soft -"@metamask/eth-block-tracker@npm:^9.0.3": - version: 9.0.3 - resolution: "@metamask/eth-block-tracker@npm:9.0.3" - dependencies: - "@metamask/eth-json-rpc-provider": "npm:^3.0.2" - "@metamask/safe-event-emitter": "npm:^3.0.0" - "@metamask/utils": "npm:^8.1.0" - json-rpc-random-id: "npm:^1.0.1" - pify: "npm:^5.0.0" - checksum: 10/f49bb158b2c9669e91813a1f34948a6c2a2d1f8507ea0b1afae9a003a4d276d892b5cde4c183f970fcec32f253a14f1abf39b6411beabeb113eeed75cd7e29b8 - languageName: node - linkType: hard - "@metamask/eth-hd-keyring@npm:^13.0.0": version: 13.0.0 resolution: "@metamask/eth-hd-keyring@npm:13.0.0" @@ -3474,36 +3437,6 @@ __metadata: languageName: node linkType: hard -"@metamask/eth-json-rpc-infura@npm:^9.0.0": - version: 9.1.0 - resolution: "@metamask/eth-json-rpc-infura@npm:9.1.0" - dependencies: - "@metamask/eth-json-rpc-provider": "npm:^2.1.0" - "@metamask/json-rpc-engine": "npm:^7.1.1" - "@metamask/rpc-errors": "npm:^6.0.0" - "@metamask/utils": "npm:^8.1.0" - node-fetch: "npm:^2.7.0" - checksum: 10/9e01b3eb76d3f1b4989ba368f11acb124eb846321020e2fba8c7ff77dc5258fa2df1556f40812d736d63ee159a944beab6a761a661f72e722badcb4f78b5f0f6 - languageName: node - linkType: hard - -"@metamask/eth-json-rpc-middleware@npm:^12.0.1": - version: 12.1.2 - resolution: "@metamask/eth-json-rpc-middleware@npm:12.1.2" - dependencies: - "@metamask/eth-block-tracker": "npm:^9.0.3" - "@metamask/eth-json-rpc-provider": "npm:^3.0.2" - "@metamask/eth-sig-util": "npm:^7.0.0" - "@metamask/json-rpc-engine": "npm:^8.0.2" - "@metamask/rpc-errors": "npm:^6.0.0" - "@metamask/utils": "npm:^8.1.0" - klona: "npm:^2.0.6" - pify: "npm:^5.0.0" - safe-stable-stringify: "npm:^2.4.3" - checksum: 10/1c0f186a35765394a28695bcade84c636b0c92cf3252219d1e9cbdd31231ad09fea5ec7bff7d31e2c7fe4d2158f15b54a5e42166549b69af1f7e475a1c7ae536 - languageName: node - linkType: hard - "@metamask/eth-json-rpc-middleware@npm:^22.0.0, @metamask/eth-json-rpc-middleware@workspace:packages/eth-json-rpc-middleware": version: 0.0.0-use.local resolution: "@metamask/eth-json-rpc-middleware@workspace:packages/eth-json-rpc-middleware" @@ -3535,28 +3468,6 @@ __metadata: languageName: unknown linkType: soft -"@metamask/eth-json-rpc-provider@npm:^2.1.0, @metamask/eth-json-rpc-provider@npm:^2.3.0": - version: 2.3.2 - resolution: "@metamask/eth-json-rpc-provider@npm:2.3.2" - dependencies: - "@metamask/json-rpc-engine": "npm:^7.3.2" - "@metamask/safe-event-emitter": "npm:^3.0.0" - "@metamask/utils": "npm:^8.3.0" - checksum: 10/e6731271aad3b972d85b9230c26d35a9b88722f3bd3024675ad2f568e634e9fdfef4717ef2892f3cc512d381cf17a4e20dbd5eb808ced765082bea3379ad6ddc - languageName: node - linkType: hard - -"@metamask/eth-json-rpc-provider@npm:^3.0.2": - version: 3.0.2 - resolution: "@metamask/eth-json-rpc-provider@npm:3.0.2" - dependencies: - "@metamask/json-rpc-engine": "npm:^8.0.2" - "@metamask/safe-event-emitter": "npm:^3.0.0" - "@metamask/utils": "npm:^8.3.0" - checksum: 10/63778defd3055633cbf0aed2d6fd0f8a1d866908be7b16b516fdb26ae6dcd34b2aefdfed80828c2af105a30ec3c16d7d0894bc6a73e2661515bcad6b6b6be4e2 - languageName: node - linkType: hard - "@metamask/eth-json-rpc-provider@npm:^5.0.0": version: 5.0.1 resolution: "@metamask/eth-json-rpc-provider@npm:5.0.1" @@ -3594,16 +3505,6 @@ __metadata: languageName: unknown linkType: soft -"@metamask/eth-query@npm:^3.0.1": - version: 3.0.1 - resolution: "@metamask/eth-query@npm:3.0.1" - dependencies: - json-rpc-random-id: "npm:^1.0.0" - xtend: "npm:^4.0.1" - checksum: 10/d463aff018ae3f1229331177e9efa0eb62958c6fcc30039c22d151ee64da17d55153ef4861060aecec674f764aa9074341bef53fdf86c2258d3cb2682976e835 - languageName: node - linkType: hard - "@metamask/eth-query@npm:^4.0.0": version: 4.0.0 resolution: "@metamask/eth-query@npm:4.0.0" @@ -3614,20 +3515,6 @@ __metadata: languageName: node linkType: hard -"@metamask/eth-sig-util@npm:^7.0.0": - version: 7.0.3 - resolution: "@metamask/eth-sig-util@npm:7.0.3" - dependencies: - "@ethereumjs/util": "npm:^8.1.0" - "@metamask/abi-utils": "npm:^2.0.4" - "@metamask/utils": "npm:^9.0.0" - "@scure/base": "npm:~1.1.3" - ethereum-cryptography: "npm:^2.1.2" - tweetnacl: "npm:^1.0.3" - checksum: 10/a71b28607b0815d609cf27ab2d8535393d0a7e7f2c6b7a23d92669b770c664c14e2f539129351147339172b0bb865bb977e7cfb30624870eedab5d7ab700beff - languageName: node - linkType: hard - "@metamask/eth-sig-util@npm:^8.2.0": version: 8.2.0 resolution: "@metamask/eth-sig-util@npm:8.2.0" @@ -3936,28 +3823,6 @@ __metadata: languageName: unknown linkType: soft -"@metamask/json-rpc-engine@npm:^7.1.1, @metamask/json-rpc-engine@npm:^7.3.0, @metamask/json-rpc-engine@npm:^7.3.2": - version: 7.3.3 - resolution: "@metamask/json-rpc-engine@npm:7.3.3" - dependencies: - "@metamask/rpc-errors": "npm:^6.2.1" - "@metamask/safe-event-emitter": "npm:^3.0.0" - "@metamask/utils": "npm:^8.3.0" - checksum: 10/116664c974c522d280335d9a02cba731e4f08562c2980415f7535513cd308c7e612e52618086996e5ac2b67db7f1e6ac1bd8201aba7825163db17a25f2874cc9 - languageName: node - linkType: hard - -"@metamask/json-rpc-engine@npm:^8.0.2": - version: 8.0.2 - resolution: "@metamask/json-rpc-engine@npm:8.0.2" - dependencies: - "@metamask/rpc-errors": "npm:^6.2.1" - "@metamask/safe-event-emitter": "npm:^3.0.0" - "@metamask/utils": "npm:^8.3.0" - checksum: 10/f088f4b648b9b55875b56e8237853e7282f13302a9db6a1f9bba06314dfd6cd0a23b3d27f8fde05a157b97ebb03b67bc2699ba455c99553dfb2ecccd73ab3474 - languageName: node - linkType: hard - "@metamask/json-rpc-middleware-stream@npm:^8.0.6, @metamask/json-rpc-middleware-stream@npm:^8.0.7, @metamask/json-rpc-middleware-stream@workspace:packages/json-rpc-middleware-stream": version: 0.0.0-use.local resolution: "@metamask/json-rpc-middleware-stream@workspace:packages/json-rpc-middleware-stream" @@ -4342,28 +4207,6 @@ __metadata: languageName: unknown linkType: soft -"@metamask/network-controller@npm:^16.0.0": - version: 16.0.0 - resolution: "@metamask/network-controller@npm:16.0.0" - dependencies: - "@metamask/base-controller": "npm:^3.2.3" - "@metamask/controller-utils": "npm:^5.0.2" - "@metamask/eth-json-rpc-infura": "npm:^9.0.0" - "@metamask/eth-json-rpc-middleware": "npm:^12.0.1" - "@metamask/eth-json-rpc-provider": "npm:^2.3.0" - "@metamask/eth-query": "npm:^4.0.0" - "@metamask/json-rpc-engine": "npm:^7.3.0" - "@metamask/rpc-errors": "npm:^6.1.0" - "@metamask/swappable-obj-proxy": "npm:^2.1.0" - "@metamask/utils": "npm:^8.2.0" - async-mutex: "npm:^0.2.6" - eth-block-tracker: "npm:^8.0.0" - immer: "npm:^9.0.6" - uuid: "npm:^8.3.2" - checksum: 10/9696b67efe1b4dbc4ced662ebce70294d19aae4f0ceed4a89382a4a78b69ec980c6832f32fae1a760af1f75b2118bb4d2a09c151bbca062a3d516c7194dee4a5 - languageName: node - linkType: hard - "@metamask/network-controller@npm:^27.0.0, @metamask/network-controller@workspace:*, @metamask/network-controller@workspace:packages/network-controller": version: 0.0.0-use.local resolution: "@metamask/network-controller@workspace:packages/network-controller" @@ -4616,23 +4459,6 @@ __metadata: languageName: unknown linkType: soft -"@metamask/polling-controller@npm:^1.0.0": - version: 1.0.2 - resolution: "@metamask/polling-controller@npm:1.0.2" - dependencies: - "@metamask/base-controller": "npm:^3.2.3" - "@metamask/controller-utils": "npm:^5.0.2" - "@metamask/network-controller": "npm:^16.0.0" - "@metamask/utils": "npm:^8.2.0" - "@types/uuid": "npm:^8.3.0" - fast-json-stable-stringify: "npm:^2.1.0" - uuid: "npm:^8.3.2" - peerDependencies: - "@metamask/network-controller": ^16.0.0 - checksum: 10/4bf2fbf4fdb4c90ce75ec952600a372b2214561f42730e028600deb790aaf3ff9a9358f4cb8a4c27abfd088d04bad16e4fffa4c9ba5de9d162c9324fe17aa515 - languageName: node - linkType: hard - "@metamask/polling-controller@npm:^16.0.0, @metamask/polling-controller@workspace:packages/polling-controller": version: 0.0.0-use.local resolution: "@metamask/polling-controller@workspace:packages/polling-controller" @@ -4799,7 +4625,7 @@ __metadata: languageName: unknown linkType: soft -"@metamask/remote-feature-flag-controller@npm:^2.0.1, @metamask/remote-feature-flag-controller@workspace:packages/remote-feature-flag-controller": +"@metamask/remote-feature-flag-controller@npm:^2.0.1, @metamask/remote-feature-flag-controller@workspace:*, @metamask/remote-feature-flag-controller@workspace:packages/remote-feature-flag-controller": version: 0.0.0-use.local resolution: "@metamask/remote-feature-flag-controller@workspace:packages/remote-feature-flag-controller" dependencies: @@ -4822,16 +4648,6 @@ __metadata: languageName: unknown linkType: soft -"@metamask/rpc-errors@npm:^6.0.0, @metamask/rpc-errors@npm:^6.1.0, @metamask/rpc-errors@npm:^6.2.1": - version: 6.4.0 - resolution: "@metamask/rpc-errors@npm:6.4.0" - dependencies: - "@metamask/utils": "npm:^9.0.0" - fast-safe-stringify: "npm:^2.0.6" - checksum: 10/9a17525aa8ce9ac142a94c04000dba7f0635e8e155c6c045f57eca36cc78c255318cca2fad4571719a427dfd2df64b70bc6442989523a8de555480668d666ad5 - languageName: node - linkType: hard - "@metamask/rpc-errors@npm:^7.0.2": version: 7.0.2 resolution: "@metamask/rpc-errors@npm:7.0.2" @@ -5171,14 +4987,14 @@ __metadata: languageName: unknown linkType: soft -"@metamask/superstruct@npm:^3.0.0, @metamask/superstruct@npm:^3.1.0, @metamask/superstruct@npm:^3.2.1": +"@metamask/superstruct@npm:^3.1.0, @metamask/superstruct@npm:^3.2.1": version: 3.2.1 resolution: "@metamask/superstruct@npm:3.2.1" checksum: 10/9e29380f2cf8b129283ccb2b568296d92682b705109ba62dbd7739ffd6a1982fe38c7228cdcf3cbee94dbcdd5fcc1c846ab9d1dd3582167154f914422fcff547 languageName: node linkType: hard -"@metamask/swappable-obj-proxy@npm:^2.1.0, @metamask/swappable-obj-proxy@npm:^2.3.0": +"@metamask/swappable-obj-proxy@npm:^2.3.0": version: 2.3.0 resolution: "@metamask/swappable-obj-proxy@npm:2.3.0" checksum: 10/1255c599de9237f06df2390719d6dfcb1f168873df61bbaad5ce376efbc057e2030260b94855569313faeb412b7df9b062d209f4b0b163a3dc02f29d42139e1f @@ -5367,23 +5183,6 @@ __metadata: languageName: node linkType: hard -"@metamask/utils@npm:^8.1.0, @metamask/utils@npm:^8.2.0, @metamask/utils@npm:^8.3.0": - version: 8.5.0 - resolution: "@metamask/utils@npm:8.5.0" - dependencies: - "@ethereumjs/tx": "npm:^4.2.0" - "@metamask/superstruct": "npm:^3.0.0" - "@noble/hashes": "npm:^1.3.1" - "@scure/base": "npm:^1.1.3" - "@types/debug": "npm:^4.1.7" - debug: "npm:^4.3.4" - pony-cause: "npm:^2.1.10" - semver: "npm:^7.5.4" - uuid: "npm:^9.0.1" - checksum: 10/68a42a55f7dc750b75467fb7c05a496c20dac073a2753e0f4d9642c4d8dcb3f9ddf51a09d30337e11637f1777f3dfe22e15b5159dbafb0fdb7bd8c9236056153 - languageName: node - linkType: hard - "@metamask/utils@npm:^9.0.0": version: 9.3.0 resolution: "@metamask/utils@npm:9.3.0" @@ -5856,15 +5655,6 @@ __metadata: languageName: node linkType: hard -"@spruceid/siwe-parser@npm:1.1.3": - version: 1.1.3 - resolution: "@spruceid/siwe-parser@npm:1.1.3" - dependencies: - apg-js: "npm:^4.1.1" - checksum: 10/c953fa1e79c633a92f030b68a44225b28c71396553dc5eb8d4d5b263e8b2e5b988131720170df2eaf202ee5251d4369ccff99c130b691a1accca2a1ff93b1111 - languageName: node - linkType: hard - "@spruceid/siwe-parser@npm:2.1.0": version: 2.1.0 resolution: "@spruceid/siwe-parser@npm:2.1.0" @@ -6921,15 +6711,6 @@ __metadata: languageName: node linkType: hard -"async-mutex@npm:^0.2.6": - version: 0.2.6 - resolution: "async-mutex@npm:0.2.6" - dependencies: - tslib: "npm:^2.0.0" - checksum: 10/3cf676fc48b4686abf534cc02d4784bab3f35d7836a0a7476c96e57c3f6607dd3d94cc0989b29d33ce5ae5cde8be8e1a96f3e769ba3b0e1ba4a244f873aa5623 - languageName: node - linkType: hard - "async-mutex@npm:^0.3.1": version: 0.3.2 resolution: "async-mutex@npm:0.3.2" @@ -8811,19 +8592,6 @@ __metadata: languageName: node linkType: hard -"eth-block-tracker@npm:^8.0.0": - version: 8.1.0 - resolution: "eth-block-tracker@npm:8.1.0" - dependencies: - "@metamask/eth-json-rpc-provider": "npm:^2.1.0" - "@metamask/safe-event-emitter": "npm:^3.0.0" - "@metamask/utils": "npm:^8.1.0" - json-rpc-random-id: "npm:^1.0.1" - pify: "npm:^5.0.0" - checksum: 10/94d81a0f5ed62bb7fd70b99a3a6172f416a574dc9fcaa96c9bdedb4d98c52b257ee505957d4a5b248ce73220b96083420acdd2dd702a0330d016018a59bd0b2e - languageName: node - linkType: hard - "eth-ens-namehash@npm:^2.0.8": version: 2.0.8 resolution: "eth-ens-namehash@npm:2.0.8" @@ -8881,7 +8649,7 @@ __metadata: languageName: node linkType: hard -"ethereumjs-util@npm:^7.0.10, ethereumjs-util@npm:^7.1.2": +"ethereumjs-util@npm:^7.1.2": version: 7.1.5 resolution: "ethereumjs-util@npm:7.1.5" dependencies: @@ -8943,16 +8711,6 @@ __metadata: languageName: node linkType: hard -"ethjs-unit@npm:^0.1.6": - version: 0.1.6 - resolution: "ethjs-unit@npm:0.1.6" - dependencies: - bn.js: "npm:4.11.6" - number-to-bn: "npm:1.7.0" - checksum: 10/35086cb671806992ec36d5dd43ab67e68ad7a9237e42c0e963f9081c88e40147cda86c1a258b0a3180bf2b7bc1960e607c5bcaefdb2196e0f3564acf73276189 - languageName: node - linkType: hard - "event-target-shim@npm:^5.0.0": version: 5.0.1 resolution: "event-target-shim@npm:5.0.1" @@ -13962,7 +13720,7 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.0.0, tslib@npm:^2.1.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0, tslib@npm:^2.6.2, tslib@npm:^2.6.3": +"tslib@npm:^2.1.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0, tslib@npm:^2.6.2, tslib@npm:^2.6.3": version: 2.8.1 resolution: "tslib@npm:2.8.1" checksum: 10/3e2e043d5c2316461cb54e5c7fe02c30ef6dccb3384717ca22ae5c6b5bc95232a6241df19c622d9c73b809bea33b187f6dbc73030963e29950c2141bc32a79f7 From d1f2251756c9e1def4178730511cb04ab8da4c13 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Tue, 20 Jan 2026 17:37:16 +0100 Subject: [PATCH 11/55] fix: fix cursor comments --- .../src/ConfigRegistryController.test.ts | 154 +++++++++++++++++- .../src/ConfigRegistryController.ts | 32 ++-- .../abstract-config-registry-api-service.ts | 15 +- .../config-registry-api-service.test.ts | 26 ++- .../config-registry-api-service.ts | 15 +- .../transformers.test.ts | 105 +++++++++++- .../transformers.ts | 89 ++++++---- 7 files changed, 370 insertions(+), 66 deletions(-) diff --git a/packages/config-registry-controller/src/ConfigRegistryController.test.ts b/packages/config-registry-controller/src/ConfigRegistryController.test.ts index 2d44ed3de04..5472dfea904 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.test.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.test.ts @@ -1,11 +1,11 @@ -import { - Messenger, - MOCK_ANY_NAMESPACE, - type MockAnyNamespace, -} from '@metamask/messenger'; +import type { MockAnyNamespace } from '@metamask/messenger'; +import { Messenger, MOCK_ANY_NAMESPACE } from '@metamask/messenger'; import { useFakeTimers } from 'sinon'; -import type { AbstractConfigRegistryApiService } from './config-registry-api-service'; +import type { + AbstractConfigRegistryApiService, + FetchConfigResult, +} from './config-registry-api-service'; import { ConfigRegistryController, DEFAULT_POLLING_INTERVAL, @@ -83,7 +83,7 @@ function buildMockApiService( overrides: Partial = {}, ): AbstractConfigRegistryApiService { return { - async fetchConfig() { + async fetchConfig(): Promise { return { data: { data: { @@ -777,6 +777,146 @@ describe('ConfigRegistryController', () => { controller.stopPolling(); }); + it('should filter networks to only include featured, active, non-testnet networks', async () => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); + + const mockNetworks = [ + { + // Should be included: featured, active, non-testnet + chainId: '0x1', + name: 'Ethereum Mainnet', + nativeCurrency: 'ETH', + rpcEndpoints: [ + { + url: 'https://mainnet.infura.io/v3/{infuraProjectId}', + type: 'infura', + networkClientId: 'mainnet', + failoverUrls: [], + }, + ], + blockExplorerUrls: ['https://etherscan.io'], + defaultRpcEndpointIndex: 0, + defaultBlockExplorerUrlIndex: 0, + isTestnet: false, + isFeatured: true, + isActive: true, + isDefault: false, + isDeprecated: false, + priority: 0, + isDeletable: false, + }, + { + // Should be excluded: testnet + chainId: '0x5', + name: 'Goerli', + nativeCurrency: 'ETH', + rpcEndpoints: [ + { + url: 'https://goerli.infura.io/v3/{infuraProjectId}', + type: 'infura', + networkClientId: 'goerli', + failoverUrls: [], + }, + ], + blockExplorerUrls: ['https://goerli.etherscan.io'], + defaultRpcEndpointIndex: 0, + defaultBlockExplorerUrlIndex: 0, + isTestnet: true, + isFeatured: true, + isActive: true, + isDefault: false, + isDeprecated: false, + priority: 0, + isDeletable: false, + }, + { + // Should be excluded: not featured + chainId: '0xa', + name: 'Optimism', + nativeCurrency: 'ETH', + rpcEndpoints: [ + { + url: 'https://optimism.infura.io/v3/{infuraProjectId}', + type: 'infura', + networkClientId: 'optimism', + failoverUrls: [], + }, + ], + blockExplorerUrls: ['https://optimistic.etherscan.io'], + defaultRpcEndpointIndex: 0, + defaultBlockExplorerUrlIndex: 0, + isTestnet: false, + isFeatured: false, + isActive: true, + isDefault: false, + isDeprecated: false, + priority: 0, + isDeletable: false, + }, + { + // Should be excluded: not active + chainId: '0x89', + name: 'Polygon', + nativeCurrency: 'MATIC', + rpcEndpoints: [ + { + url: 'https://polygon.infura.io/v3/{infuraProjectId}', + type: 'infura', + networkClientId: 'polygon', + failoverUrls: [], + }, + ], + blockExplorerUrls: ['https://polygonscan.com'], + defaultRpcEndpointIndex: 0, + defaultBlockExplorerUrlIndex: 0, + isTestnet: false, + isFeatured: true, + isActive: false, + isDefault: false, + isDeprecated: false, + priority: 0, + isDeletable: false, + }, + ]; + + const fetchConfigSpy = jest.fn().mockResolvedValue({ + data: { + data: { + version: '1.0.0', + timestamp: Date.now(), + networks: mockNetworks, + }, + }, + notModified: false, + etag: 'test-etag', + }); + + const mockApiService = buildMockApiService({ + fetchConfig: fetchConfigSpy, + }); + + const controller = new ConfigRegistryController({ + messenger, + apiService: mockApiService, + }); + + await controller._executePoll({}); + + // Only the first network (0x1) should be stored + expect(controller.state.configs.networks?.['0x1']).toBeDefined(); + expect(controller.state.configs.networks?.['0x5']).toBeUndefined(); + expect(controller.state.configs.networks?.['0xa']).toBeUndefined(); + expect(controller.state.configs.networks?.['0x89']).toBeUndefined(); + expect(Object.keys(controller.state.configs.networks ?? {})).toHaveLength( + 1, + ); + }); + it('should default to fallback when feature flag is not set', async () => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: {}, diff --git a/packages/config-registry-controller/src/ConfigRegistryController.ts b/packages/config-registry-controller/src/ConfigRegistryController.ts index fa2efb955a1..e0094319dba 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.ts @@ -1,16 +1,19 @@ -import { - type ControllerGetStateAction, - type ControllerStateChangeEvent, +import type { + ControllerGetStateAction, + ControllerStateChangeEvent, } from '@metamask/base-controller'; import type { Messenger } from '@metamask/messenger'; import { StaticIntervalPollingController } from '@metamask/polling-controller'; import type { RemoteFeatureFlagControllerState } from '@metamask/remote-feature-flag-controller'; import type { Json } from '@metamask/utils'; -import type { AbstractConfigRegistryApiService } from './config-registry-api-service'; +import type { + AbstractConfigRegistryApiService, + FetchConfigResult, +} from './config-registry-api-service'; import { ConfigRegistryApiService, - type FetchConfigResult, + filterNetworks, } from './config-registry-api-service'; import { isConfigRegistryApiEnabled } from './utils/feature-flags'; @@ -228,8 +231,15 @@ export class ConfigRegistryController extends StaticIntervalPollingController = {}; - for (const network of result.data.data.networks) { + for (const network of filteredNetworks) { newConfigs[network.chainId] = { key: network.chainId, value: network as unknown as Json, @@ -264,7 +274,7 @@ export class ConfigRegistryController extends StaticIntervalPollingController { - return { ...(this.state.configs?.networks || {}) }; + return { ...(this.state.configs?.networks ?? {}) }; } - getConfigValue(key: string): T | undefined { + getConfigValue(key: string): TValue | undefined { const entry = this.state.configs?.networks?.[key]; - return entry?.value as T | undefined; + return entry?.value as TValue | undefined; } setConfig(key: string, value: Json, metadata?: Json): void { @@ -327,6 +337,6 @@ export class ConfigRegistryController extends StaticIntervalPollingController diff --git a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts index d64f38341ce..e1baa0cf3d8 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts @@ -1,7 +1,10 @@ import nock, { cleanAll } from 'nock'; import { useFakeTimers } from 'sinon'; -import type { RegistryConfigApiResponse } from './abstract-config-registry-api-service'; +import type { + FetchConfigResult, + RegistryConfigApiResponse, +} from './abstract-config-registry-api-service'; import { ConfigRegistryApiService, DEFAULT_API_BASE_URL, @@ -81,7 +84,9 @@ describe('ConfigRegistryApiService', () => { expect(result.notModified).toBe(false); expect(result.etag).toBe('"test-etag-123"'); - expect(result.data).toStrictEqual(MOCK_API_RESPONSE); + expect( + (result as Extract).data, + ).toStrictEqual(MOCK_API_RESPONSE); expect(scope.isDone()).toBe(true); }); @@ -173,7 +178,10 @@ describe('ConfigRegistryApiService', () => { const result = await service.fetchConfig(); - expect(result.data).toStrictEqual(MOCK_API_RESPONSE); + expect(result.notModified).toBe(false); + expect( + (result as Extract).data, + ).toStrictEqual(MOCK_API_RESPONSE); expect(successScope.isDone()).toBe(true); }); }); @@ -241,12 +249,15 @@ describe('ConfigRegistryApiService', () => { describe('custom fetch function', () => { it('should use custom fetch function when provided', async () => { + const mockHeaders = { + get: jest.fn().mockReturnValue('"custom-etag"'), + }; const customFetch = jest.fn().mockResolvedValue({ ok: true, status: 200, - headers: new Headers({ ETag: '"custom-etag"' }), + headers: mockHeaders, json: async () => MOCK_API_RESPONSE, - } as Response); + } as unknown as Response); const service = new ConfigRegistryApiService({ fetch: customFetch, @@ -257,7 +268,10 @@ describe('ConfigRegistryApiService', () => { const result = await service.fetchConfig(); expect(customFetch).toHaveBeenCalled(); - expect(result.data).toStrictEqual(MOCK_API_RESPONSE); + expect(result.notModified).toBe(false); + expect( + (result as Extract).data, + ).toStrictEqual(MOCK_API_RESPONSE); }); }); diff --git a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts index 65b10f4fbe4..973cc06b8ac 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts @@ -32,9 +32,7 @@ export type ConfigRegistryApiServiceOptions = { circuitBreakDuration?: number; }; -export class ConfigRegistryApiService - implements AbstractConfigRegistryApiService -{ +export class ConfigRegistryApiService implements AbstractConfigRegistryApiService { readonly #policy: ServicePolicy; readonly #apiBaseUrl: string; @@ -81,11 +79,15 @@ export class ConfigRegistryApiService }); } - onBreak(...args: Parameters) { + onBreak( + ...args: Parameters + ): ReturnType { return this.#policy.onBreak(...args); } - onDegraded(...args: Parameters) { + onDegraded( + ...args: Parameters + ): ReturnType { return this.#policy.onDegraded(...args); } @@ -148,9 +150,10 @@ export class ConfigRegistryApiService }); if ((response as unknown as { status?: number }).status === 304) { + const etag = response.headers.get('ETag') ?? undefined; return { - data: {} as RegistryConfigApiResponse, notModified: true, + etag, }; } diff --git a/packages/config-registry-controller/src/config-registry-api-service/transformers.test.ts b/packages/config-registry-controller/src/config-registry-api-service/transformers.test.ts index 2cf20b4cd3c..cadd9d89e11 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/transformers.test.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/transformers.test.ts @@ -420,6 +420,107 @@ describe('transformers', () => { expect(result?.defaultRpcEndpointIndex).toBe(1); }); + it('should adjust defaultRpcEndpointIndex when invalid endpoints are filtered out', () => { + const config = { + ...VALID_NETWORK_CONFIG, + rpcEndpoints: [ + { + // Invalid endpoint (missing networkClientId) - will be filtered out + url: 'https://invalid.infura.io/v3/{infuraProjectId}', + type: 'infura', + networkClientId: '', + failoverUrls: [], + }, + { + // Valid endpoint at original index 1 + url: 'https://mainnet.infura.io/v3/{infuraProjectId}', + type: 'infura', + networkClientId: 'mainnet', + failoverUrls: [], + }, + { + // Valid endpoint at original index 2 + url: 'https://backup.infura.io/v3/{infuraProjectId}', + type: 'infura', + networkClientId: 'mainnet', + failoverUrls: [], + }, + ], + defaultRpcEndpointIndex: 1, // Points to mainnet endpoint + }; + + const result = transformNetworkConfig(config); + + // After filtering, the array becomes [mainnet, backup] + // Original index 1 (mainnet) should now be at index 0 + expect(result?.defaultRpcEndpointIndex).toBe(0); + expect(result?.rpcEndpoints[result.defaultRpcEndpointIndex].url).toBe( + 'https://mainnet.infura.io/v3/{infuraProjectId}', + ); + }); + + it('should return null when defaultRpcEndpointIndex points to invalid endpoint', () => { + const config = { + ...VALID_NETWORK_CONFIG, + rpcEndpoints: [ + { + url: 'https://mainnet.infura.io/v3/{infuraProjectId}', + type: 'infura', + networkClientId: 'mainnet', + failoverUrls: [], + }, + { + // Invalid endpoint (missing networkClientId) - will be filtered out + url: 'https://invalid.infura.io/v3/{infuraProjectId}', + type: 'infura', + networkClientId: '', + failoverUrls: [], + }, + ], + defaultRpcEndpointIndex: 1, // Points to invalid endpoint + }; + + const result = transformNetworkConfig(config); + + expect(result).toBeNull(); + }); + + it('should adjust defaultBlockExplorerUrlIndex when invalid URLs are filtered out', () => { + const config = { + ...VALID_NETWORK_CONFIG, + blockExplorerUrls: [ + '', // Invalid empty URL - will be filtered out + 'https://etherscan.io', // Valid URL at original index 1 + 'https://blockscout.com', // Valid URL at original index 2 + ], + defaultBlockExplorerUrlIndex: 1, // Points to etherscan + }; + + const result = transformNetworkConfig(config); + + // After filtering, the array becomes [etherscan, blockscout] + // Original index 1 (etherscan) should now be at index 0 + expect(result?.defaultBlockExplorerUrlIndex).toBe(0); + expect( + result?.blockExplorerUrls[result.defaultBlockExplorerUrlIndex ?? 0], + ).toBe('https://etherscan.io'); + }); + + it('should return null when defaultBlockExplorerUrlIndex points to invalid URL', () => { + const config = { + ...VALID_NETWORK_CONFIG, + blockExplorerUrls: [ + 'https://etherscan.io', + '', // Invalid empty URL - will be filtered out + ], + defaultBlockExplorerUrlIndex: 1, // Points to invalid URL + }; + + const result = transformNetworkConfig(config); + + expect(result).toBeNull(); + }); + it('should preserve lastUpdatedAt', () => { const timestamp = 1234567890; const config = { @@ -487,7 +588,7 @@ describe('transformers', () => { const result = filterNetworks(networks, { isFeatured: true }); expect(result).toHaveLength(2); - expect(result.every((n) => n.isFeatured)).toBe(true); + expect(result.every((network) => network.isFeatured)).toBe(true); }); it('should filter by isTestnet', () => { @@ -501,7 +602,7 @@ describe('transformers', () => { const result = filterNetworks(networks, { isActive: true }); expect(result).toHaveLength(2); - expect(result.every((n) => n.isActive)).toBe(true); + expect(result.every((network) => network.isActive)).toBe(true); }); it('should filter by isDeprecated', () => { diff --git a/packages/config-registry-controller/src/config-registry-api-service/transformers.ts b/packages/config-registry-controller/src/config-registry-api-service/transformers.ts index f0bc3fbf654..ee374bf4900 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/transformers.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/transformers.ts @@ -35,11 +35,11 @@ function toHexChainId(chainId: string): Hex | null { const trimmed = chainId.trim(); if (trimmed.startsWith('0x') || trimmed.startsWith('0X')) { - const hex = trimmed.toLowerCase(); - if (!/^0x[0-9a-f]+$/iu.test(hex)) { + const hexValue = trimmed.toLowerCase(); + if (!/^0x[0-9a-f]+$/iu.test(hexValue)) { return null; } - return hex as Hex; + return hexValue as Hex; } const decimal = Number.parseInt(trimmed, 10); @@ -47,7 +47,7 @@ function toHexChainId(chainId: string): Hex | null { return null; } - return `0x${decimal.toString(16)}` as Hex; + return `0x${decimal.toString(16)}`; } /** @@ -76,7 +76,7 @@ function transformRpcEndpoint( } const baseEndpoint = { - networkClientId: networkClientId as string, + networkClientId, failoverUrls: Array.isArray(failoverUrls) ? failoverUrls.filter( (failoverUrl): failoverUrl is string => @@ -135,19 +135,34 @@ export function transformNetworkConfig( return null; } - const transformedEndpoints = rpcEndpoints - .map(transformRpcEndpoint) - .filter((endpoint): endpoint is RpcEndpoint => endpoint !== null); + // Transform endpoints and track original indices to filtered indices mapping + const transformedEndpoints: RpcEndpoint[] = []; + const originalToFilteredIndexMap = new Map(); + + rpcEndpoints.forEach((endpoint, originalIndex) => { + const transformed = transformRpcEndpoint(endpoint); + if (transformed !== null) { + originalToFilteredIndexMap.set( + originalIndex, + transformedEndpoints.length, + ); + transformedEndpoints.push(transformed); + } + }); if (transformedEndpoints.length === 0) { return null; } - const defaultRpcEndpointIndex = networkConfig.defaultRpcEndpointIndex ?? 0; - if ( - defaultRpcEndpointIndex < 0 || - defaultRpcEndpointIndex >= transformedEndpoints.length - ) { + // Adjust defaultRpcEndpointIndex to account for filtered endpoints + const originalDefaultRpcEndpointIndex = + networkConfig.defaultRpcEndpointIndex ?? 0; + const adjustedDefaultRpcEndpointIndex = originalToFilteredIndexMap.get( + originalDefaultRpcEndpointIndex, + ); + + if (adjustedDefaultRpcEndpointIndex === undefined) { + // The original default index pointed to an invalid endpoint return null; } @@ -155,18 +170,37 @@ export function transformNetworkConfig( return null; } - const validBlockExplorerUrls = blockExplorerUrls.filter( - (blockExplorerUrl): blockExplorerUrl is string => - typeof blockExplorerUrl === 'string' && blockExplorerUrl.length > 0, - ); + // Filter block explorer URLs and track original indices to filtered indices mapping + const validBlockExplorerUrls: string[] = []; + const blockExplorerOriginalToFilteredIndexMap = new Map(); + + blockExplorerUrls.forEach((blockExplorerUrl, originalIndex) => { + if (typeof blockExplorerUrl === 'string' && blockExplorerUrl.length > 0) { + blockExplorerOriginalToFilteredIndexMap.set( + originalIndex, + validBlockExplorerUrls.length, + ); + validBlockExplorerUrls.push(blockExplorerUrl); + } + }); + // Adjust defaultBlockExplorerUrlIndex to account for filtered URLs const { defaultBlockExplorerUrlIndex } = networkConfig; - if ( - defaultBlockExplorerUrlIndex !== undefined && - (defaultBlockExplorerUrlIndex < 0 || - defaultBlockExplorerUrlIndex >= validBlockExplorerUrls.length) - ) { - return null; + let adjustedDefaultBlockExplorerUrlIndex: number | undefined; + + if (defaultBlockExplorerUrlIndex !== undefined) { + const adjusted = blockExplorerOriginalToFilteredIndexMap.get( + defaultBlockExplorerUrlIndex, + ); + + if (adjusted === undefined) { + // The original default index pointed to an invalid URL + return null; + } + + adjustedDefaultBlockExplorerUrlIndex = adjusted; + } else if (validBlockExplorerUrls.length > 0) { + adjustedDefaultBlockExplorerUrlIndex = 0; } return { @@ -175,11 +209,8 @@ export function transformNetworkConfig( nativeCurrency, rpcEndpoints: transformedEndpoints, blockExplorerUrls: validBlockExplorerUrls, - defaultRpcEndpointIndex, - defaultBlockExplorerUrlIndex: - validBlockExplorerUrls.length > 0 - ? (defaultBlockExplorerUrlIndex ?? 0) - : undefined, + defaultRpcEndpointIndex: adjustedDefaultRpcEndpointIndex, + defaultBlockExplorerUrlIndex: adjustedDefaultBlockExplorerUrlIndex, lastUpdatedAt: networkConfig.lastUpdatedAt, }; } @@ -266,7 +297,7 @@ export function compareWithExistingNetworks( const foundExistingChainIds: Hex[] = []; for (const network of transformedNetworks) { - if (!network || !network.chainId) { + if (!network?.chainId) { continue; } From 416e8e9a5ccac9e75b53e9c9864978c59bceea34 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Tue, 20 Jan 2026 17:46:58 +0100 Subject: [PATCH 12/55] chore: update changelog --- .../config-registry-controller/CHANGELOG.md | 11 + yarn.lock | 4711 +++++++++-------- 2 files changed, 2613 insertions(+), 2109 deletions(-) diff --git a/packages/config-registry-controller/CHANGELOG.md b/packages/config-registry-controller/CHANGELOG.md index b518709c7b8..fa33519f175 100644 --- a/packages/config-registry-controller/CHANGELOG.md +++ b/packages/config-registry-controller/CHANGELOG.md @@ -7,4 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Initial release of `@metamask/config-registry-controller` ([#7668](https://github.com/MetaMask/core/pull/7668)) + - Controller for fetching and managing network configurations from a remote API + - ConfigRegistryApiService with ETag support, retries, circuit breaker, and timeout handling + - Network filtering to only include featured, active, non-testnet networks + - Feature flag integration using `config_registry_api_enabled` to enable/disable API fetching + - Fallback configuration support when API is unavailable or feature flag is disabled + - State persistence for configs, version, lastFetched, and etag + - Uses StaticIntervalPollingController for periodic updates (default: 24 hours) + [Unreleased]: https://github.com/MetaMask/core/ diff --git a/yarn.lock b/yarn.lock index a39dcc22acc..02f75937c43 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,230 +12,217 @@ __metadata: languageName: node linkType: hard -"@ampproject/remapping@npm:^2.2.0": - version: 2.3.0 - resolution: "@ampproject/remapping@npm:2.3.0" - dependencies: - "@jridgewell/gen-mapping": "npm:^0.3.5" - "@jridgewell/trace-mapping": "npm:^0.3.24" - checksum: 10/f3451525379c68a73eb0a1e65247fbf28c0cccd126d93af21c75fceff77773d43c0d4a2d51978fb131aff25b5f2cb41a9fe48cc296e61ae65e679c4f6918b0ab - languageName: node - linkType: hard - -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.25.9, @babel/code-frame@npm:^7.26.0, @babel/code-frame@npm:^7.26.2": - version: 7.26.2 - resolution: "@babel/code-frame@npm:7.26.2" +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.27.1, @babel/code-frame@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/code-frame@npm:7.28.6" dependencies: - "@babel/helper-validator-identifier": "npm:^7.25.9" + "@babel/helper-validator-identifier": "npm:^7.28.5" js-tokens: "npm:^4.0.0" - picocolors: "npm:^1.0.0" - checksum: 10/db2c2122af79d31ca916755331bb4bac96feb2b334cdaca5097a6b467fdd41963b89b14b6836a14f083de7ff887fc78fa1b3c10b14e743d33e12dbfe5ee3d223 + picocolors: "npm:^1.1.1" + checksum: 10/93e7ed9e039e3cb661bdb97c26feebafacc6ec13d745881dae5c7e2708f579475daebe7a3b5d23b183bb940b30744f52f4a5bcb65b4df03b79d82fcb38495784 languageName: node linkType: hard -"@babel/compat-data@npm:^7.25.9": - version: 7.26.3 - resolution: "@babel/compat-data@npm:7.26.3" - checksum: 10/0bf4e491680722aa0eac26f770f2fae059f92e2ac083900b241c90a2c10f0fc80e448b1feccc2b332687fab4c3e33e9f83dee9ef56badca1fb9f3f71266d9ebf +"@babel/compat-data@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/compat-data@npm:7.28.6" + checksum: 10/dc17dfb55711a15f006e34c4610c49b7335fc11b23e192f9e5f625e8ea0f48805e61a57b6b4f5550879332782c93af0b5d6952825fffbb8d4e604b14d698249f languageName: node linkType: hard "@babel/core@npm:^7.1.0, @babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.23.2, @babel/core@npm:^7.23.5, @babel/core@npm:^7.7.2, @babel/core@npm:^7.8.0": - version: 7.26.0 - resolution: "@babel/core@npm:7.26.0" - dependencies: - "@ampproject/remapping": "npm:^2.2.0" - "@babel/code-frame": "npm:^7.26.0" - "@babel/generator": "npm:^7.26.0" - "@babel/helper-compilation-targets": "npm:^7.25.9" - "@babel/helper-module-transforms": "npm:^7.26.0" - "@babel/helpers": "npm:^7.26.0" - "@babel/parser": "npm:^7.26.0" - "@babel/template": "npm:^7.25.9" - "@babel/traverse": "npm:^7.25.9" - "@babel/types": "npm:^7.26.0" + version: 7.28.6 + resolution: "@babel/core@npm:7.28.6" + dependencies: + "@babel/code-frame": "npm:^7.28.6" + "@babel/generator": "npm:^7.28.6" + "@babel/helper-compilation-targets": "npm:^7.28.6" + "@babel/helper-module-transforms": "npm:^7.28.6" + "@babel/helpers": "npm:^7.28.6" + "@babel/parser": "npm:^7.28.6" + "@babel/template": "npm:^7.28.6" + "@babel/traverse": "npm:^7.28.6" + "@babel/types": "npm:^7.28.6" + "@jridgewell/remapping": "npm:^2.3.5" convert-source-map: "npm:^2.0.0" debug: "npm:^4.1.0" gensync: "npm:^1.0.0-beta.2" json5: "npm:^2.2.3" semver: "npm:^6.3.1" - checksum: 10/65767bfdb1f02e80d3af4f138066670ef8fdd12293de85ef151758a901c191c797e86d2e99b11c4cdfca33c72385ecaf38bbd7fa692791ec44c77763496b9b93 + checksum: 10/1a150a69c547daf13c457be1fdaf1a0935d02b94605e777e049537ec2f279b4bb442ffbe1c2d8ff62c688878b1d5530a5784daf72ece950d1917fb78717f51d2 languageName: node linkType: hard -"@babel/generator@npm:^7.26.0, @babel/generator@npm:^7.26.3, @babel/generator@npm:^7.7.2": - version: 7.26.3 - resolution: "@babel/generator@npm:7.26.3" +"@babel/generator@npm:^7.28.6, @babel/generator@npm:^7.7.2": + version: 7.28.6 + resolution: "@babel/generator@npm:7.28.6" dependencies: - "@babel/parser": "npm:^7.26.3" - "@babel/types": "npm:^7.26.3" - "@jridgewell/gen-mapping": "npm:^0.3.5" - "@jridgewell/trace-mapping": "npm:^0.3.25" + "@babel/parser": "npm:^7.28.6" + "@babel/types": "npm:^7.28.6" + "@jridgewell/gen-mapping": "npm:^0.3.12" + "@jridgewell/trace-mapping": "npm:^0.3.28" jsesc: "npm:^3.0.2" - checksum: 10/c1d8710cc1c52af9d8d67f7d8ea775578aa500887b327d2a81e27494764a6ef99e438dd7e14cf7cd3153656492ee27a8362980dc438087c0ca39d4e75532c638 + checksum: 10/ef2af927e8e0985d02ec4321a242da761a934e927539147c59fdd544034dc7f0e9846f6bf86209aca7a28aee2243ed0fad668adccd48f96d7d6866215173f9af languageName: node linkType: hard -"@babel/helper-annotate-as-pure@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-annotate-as-pure@npm:7.24.7" +"@babel/helper-annotate-as-pure@npm:^7.27.3": + version: 7.27.3 + resolution: "@babel/helper-annotate-as-pure@npm:7.27.3" dependencies: - "@babel/types": "npm:^7.24.7" - checksum: 10/a9017bfc1c4e9f2225b967fbf818004703de7cf29686468b54002ffe8d6b56e0808afa20d636819fcf3a34b89ba72f52c11bdf1d69f303928ee10d92752cad95 + "@babel/types": "npm:^7.27.3" + checksum: 10/63863a5c936ef82b546ca289c9d1b18fabfc24da5c4ee382830b124e2e79b68d626207febc8d4bffc720f50b2ee65691d7d12cc0308679dee2cd6bdc926b7190 languageName: node linkType: hard -"@babel/helper-compilation-targets@npm:^7.25.9": - version: 7.25.9 - resolution: "@babel/helper-compilation-targets@npm:7.25.9" +"@babel/helper-compilation-targets@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/helper-compilation-targets@npm:7.28.6" dependencies: - "@babel/compat-data": "npm:^7.25.9" - "@babel/helper-validator-option": "npm:^7.25.9" + "@babel/compat-data": "npm:^7.28.6" + "@babel/helper-validator-option": "npm:^7.27.1" browserslist: "npm:^4.24.0" lru-cache: "npm:^5.1.1" semver: "npm:^6.3.1" - checksum: 10/8053fbfc21e8297ab55c8e7f9f119e4809fa7e505268691e1bedc2cf5e7a5a7de8c60ad13da2515378621b7601c42e101d2d679904da395fa3806a1edef6b92e + checksum: 10/f512a5aeee4dfc6ea8807f521d085fdca8d66a7d068a6dd5e5b37da10a6081d648c0bbf66791a081e4e8e6556758da44831b331540965dfbf4f5275f3d0a8788 languageName: node linkType: hard -"@babel/helper-create-class-features-plugin@npm:^7.25.0": - version: 7.25.4 - resolution: "@babel/helper-create-class-features-plugin@npm:7.25.4" +"@babel/helper-create-class-features-plugin@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/helper-create-class-features-plugin@npm:7.28.6" dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.24.7" - "@babel/helper-member-expression-to-functions": "npm:^7.24.8" - "@babel/helper-optimise-call-expression": "npm:^7.24.7" - "@babel/helper-replace-supers": "npm:^7.25.0" - "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.24.7" - "@babel/traverse": "npm:^7.25.4" + "@babel/helper-annotate-as-pure": "npm:^7.27.3" + "@babel/helper-member-expression-to-functions": "npm:^7.28.5" + "@babel/helper-optimise-call-expression": "npm:^7.27.1" + "@babel/helper-replace-supers": "npm:^7.28.6" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.27.1" + "@babel/traverse": "npm:^7.28.6" semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10/47218da9fd964af30d41f0635d9e33eed7518e03aa8f10c3eb8a563bb2c14f52be3e3199db5912ae0e26058c23bb511c811e565c55ecec09427b04b867ed13c2 + checksum: 10/11f55607fcf66827ade745c0616aa3c6086aa655c0fab665dd3c4961829752e4c94c942262db30c4831ef9bce37ad444722e85ef1b7136587e28c6b1ef8ad43c + languageName: node + linkType: hard + +"@babel/helper-globals@npm:^7.28.0": + version: 7.28.0 + resolution: "@babel/helper-globals@npm:7.28.0" + checksum: 10/91445f7edfde9b65dcac47f4f858f68dc1661bf73332060ab67ad7cc7b313421099a2bfc4bda30c3db3842cfa1e86fffbb0d7b2c5205a177d91b22c8d7d9cb47 languageName: node linkType: hard -"@babel/helper-member-expression-to-functions@npm:^7.24.8": - version: 7.24.8 - resolution: "@babel/helper-member-expression-to-functions@npm:7.24.8" +"@babel/helper-member-expression-to-functions@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/helper-member-expression-to-functions@npm:7.28.5" dependencies: - "@babel/traverse": "npm:^7.24.8" - "@babel/types": "npm:^7.24.8" - checksum: 10/ac878761cfd0a46c081cda0da75cc186f922cf16e8ecdd0c4fb6dca4330d9fe4871b41a9976224cf9669c9e7fe0421b5c27349f2e99c125fa0be871b327fa770 + "@babel/traverse": "npm:^7.28.5" + "@babel/types": "npm:^7.28.5" + checksum: 10/05e0857cf7913f03d88ca62952d3888693c21a4f4d7cfc141c630983f71fc0a64393e05cecceb7701dfe98298f7cc38fcb735d892e3c8c6f56f112c85ee1b154 languageName: node linkType: hard -"@babel/helper-module-imports@npm:^7.25.9": - version: 7.25.9 - resolution: "@babel/helper-module-imports@npm:7.25.9" +"@babel/helper-module-imports@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/helper-module-imports@npm:7.28.6" dependencies: - "@babel/traverse": "npm:^7.25.9" - "@babel/types": "npm:^7.25.9" - checksum: 10/e090be5dee94dda6cd769972231b21ddfae988acd76b703a480ac0c96f3334557d70a965bf41245d6ee43891e7571a8b400ccf2b2be5803351375d0f4e5bcf08 + "@babel/traverse": "npm:^7.28.6" + "@babel/types": "npm:^7.28.6" + checksum: 10/64b1380d74425566a3c288074d7ce4dea56d775d2d3325a3d4a6df1dca702916c1d268133b6f385de9ba5b822b3c6e2af5d3b11ac88e5453d5698d77264f0ec0 languageName: node linkType: hard -"@babel/helper-module-transforms@npm:^7.24.8, @babel/helper-module-transforms@npm:^7.26.0": - version: 7.26.0 - resolution: "@babel/helper-module-transforms@npm:7.26.0" +"@babel/helper-module-transforms@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/helper-module-transforms@npm:7.28.6" dependencies: - "@babel/helper-module-imports": "npm:^7.25.9" - "@babel/helper-validator-identifier": "npm:^7.25.9" - "@babel/traverse": "npm:^7.25.9" + "@babel/helper-module-imports": "npm:^7.28.6" + "@babel/helper-validator-identifier": "npm:^7.28.5" + "@babel/traverse": "npm:^7.28.6" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10/9841d2a62f61ad52b66a72d08264f23052d533afc4ce07aec2a6202adac0bfe43014c312f94feacb3291f4c5aafe681955610041ece2c276271adce3f570f2f5 + checksum: 10/2e421c7db743249819ee51e83054952709dc2e197c7d5d415b4bdddc718580195704bfcdf38544b3f674efc2eccd4d29a65d38678fc827ed3934a7690984cd8b languageName: node linkType: hard -"@babel/helper-optimise-call-expression@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-optimise-call-expression@npm:7.24.7" +"@babel/helper-optimise-call-expression@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/helper-optimise-call-expression@npm:7.27.1" dependencies: - "@babel/types": "npm:^7.24.7" - checksum: 10/da7a7f2d1bb1be4cffd5fa820bd605bc075c7dd014e0458f608bb6f34f450fe9412c8cea93e788227ab396e0e02c162d7b1db3fbcb755a6360e354c485d61df0 + "@babel/types": "npm:^7.27.1" + checksum: 10/0fb7ee824a384529d6b74f8a58279f9b56bfe3cce332168067dddeab2552d8eeb56dc8eaf86c04a3a09166a316cb92dfc79c4c623cd034ad4c563952c98b464f languageName: node linkType: hard -"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.24.7, @babel/helper-plugin-utils@npm:^7.24.8, @babel/helper-plugin-utils@npm:^7.8.0": - version: 7.24.8 - resolution: "@babel/helper-plugin-utils@npm:7.24.8" - checksum: 10/adbc9fc1142800a35a5eb0793296924ee8057fe35c61657774208670468a9fbfbb216f2d0bc46c680c5fefa785e5ff917cc1674b10bd75cdf9a6aa3444780630 +"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.27.1, @babel/helper-plugin-utils@npm:^7.28.6, @babel/helper-plugin-utils@npm:^7.8.0": + version: 7.28.6 + resolution: "@babel/helper-plugin-utils@npm:7.28.6" + checksum: 10/21c853bbc13dbdddf03309c9a0477270124ad48989e1ad6524b83e83a77524b333f92edd2caae645c5a7ecf264ec6d04a9ebe15aeb54c7f33c037b71ec521e4a languageName: node linkType: hard -"@babel/helper-replace-supers@npm:^7.25.0": - version: 7.25.0 - resolution: "@babel/helper-replace-supers@npm:7.25.0" +"@babel/helper-replace-supers@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/helper-replace-supers@npm:7.28.6" dependencies: - "@babel/helper-member-expression-to-functions": "npm:^7.24.8" - "@babel/helper-optimise-call-expression": "npm:^7.24.7" - "@babel/traverse": "npm:^7.25.0" + "@babel/helper-member-expression-to-functions": "npm:^7.28.5" + "@babel/helper-optimise-call-expression": "npm:^7.27.1" + "@babel/traverse": "npm:^7.28.6" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10/97c6c17780cb9692132f7243f5a21fb6420104cb8ff8752dc03cfc9a1912a243994c0290c77ff096637ab6f2a7363b63811cfc68c2bad44e6b39460ac2f6a63f - languageName: node - linkType: hard - -"@babel/helper-simple-access@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-simple-access@npm:7.24.7" - dependencies: - "@babel/traverse": "npm:^7.24.7" - "@babel/types": "npm:^7.24.7" - checksum: 10/5083e190186028e48fc358a192e4b93ab320bd016103caffcfda81302a13300ccce46c9cd255ae520c25d2a6a9b47671f93e5fe5678954a2329dc0a685465c49 + checksum: 10/ad2724713a4d983208f509e9607e8f950855f11bd97518a700057eb8bec69d687a8f90dc2da0c3c47281d2e3b79cf1d14ecf1fe3e1ee0a8e90b61aee6759c9a7 languageName: node linkType: hard -"@babel/helper-skip-transparent-expression-wrappers@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.24.7" +"@babel/helper-skip-transparent-expression-wrappers@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.27.1" dependencies: - "@babel/traverse": "npm:^7.24.7" - "@babel/types": "npm:^7.24.7" - checksum: 10/784a6fdd251a9a7e42ccd04aca087ecdab83eddc60fda76a2950e00eb239cc937d3c914266f0cc476298b52ac3f44ffd04c358e808bd17552a7e008d75494a77 + "@babel/traverse": "npm:^7.27.1" + "@babel/types": "npm:^7.27.1" + checksum: 10/4f380c5d0e0769fa6942a468b0c2d7c8f0c438f941aaa88f785f8752c103631d0904c7b4e76207a3b0e6588b2dec376595370d92ca8f8f1b422c14a69aa146d4 languageName: node linkType: hard -"@babel/helper-string-parser@npm:^7.25.9": - version: 7.25.9 - resolution: "@babel/helper-string-parser@npm:7.25.9" - checksum: 10/c28656c52bd48e8c1d9f3e8e68ecafd09d949c57755b0d353739eb4eae7ba4f7e67e92e4036f1cd43378cc1397a2c943ed7bcaf5949b04ab48607def0258b775 +"@babel/helper-string-parser@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/helper-string-parser@npm:7.27.1" + checksum: 10/0ae29cc2005084abdae2966afdb86ed14d41c9c37db02c3693d5022fba9f5d59b011d039380b8e537c34daf117c549f52b452398f576e908fb9db3c7abbb3a00 languageName: node linkType: hard -"@babel/helper-validator-identifier@npm:^7.25.9": - version: 7.25.9 - resolution: "@babel/helper-validator-identifier@npm:7.25.9" - checksum: 10/3f9b649be0c2fd457fa1957b694b4e69532a668866b8a0d81eabfa34ba16dbf3107b39e0e7144c55c3c652bf773ec816af8df4a61273a2bb4eb3145ca9cf478e +"@babel/helper-validator-identifier@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/helper-validator-identifier@npm:7.28.5" + checksum: 10/8e5d9b0133702cfacc7f368bf792f0f8ac0483794877c6dca5fcb73810ee138e27527701826fb58a40a004f3a5ec0a2f3c3dd5e326d262530b119918f3132ba7 languageName: node linkType: hard -"@babel/helper-validator-option@npm:^7.24.7, @babel/helper-validator-option@npm:^7.25.9": - version: 7.25.9 - resolution: "@babel/helper-validator-option@npm:7.25.9" - checksum: 10/9491b2755948ebbdd68f87da907283698e663b5af2d2b1b02a2765761974b1120d5d8d49e9175b167f16f72748ffceec8c9cf62acfbee73f4904507b246e2b3d +"@babel/helper-validator-option@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/helper-validator-option@npm:7.27.1" + checksum: 10/db73e6a308092531c629ee5de7f0d04390835b21a263be2644276cb27da2384b64676cab9f22cd8d8dbd854c92b1d7d56fc8517cf0070c35d1c14a8c828b0903 languageName: node linkType: hard -"@babel/helpers@npm:^7.26.0": - version: 7.26.0 - resolution: "@babel/helpers@npm:7.26.0" +"@babel/helpers@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/helpers@npm:7.28.6" dependencies: - "@babel/template": "npm:^7.25.9" - "@babel/types": "npm:^7.26.0" - checksum: 10/fd4757f65d10b64cfdbf4b3adb7ea6ffff9497c53e0786452f495d1f7794da7e0898261b4db65e1c62bbb9a360d7d78a1085635c23dfc3af2ab6dcba06585f86 + "@babel/template": "npm:^7.28.6" + "@babel/types": "npm:^7.28.6" + checksum: 10/213485cdfffc4deb81fc1bf2cefed61bc825049322590ef69690e223faa300a2a4d1e7d806c723bb1f1f538226b9b1b6c356ca94eb47fa7c6d9e9f251ee425e6 languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.0, @babel/parser@npm:^7.24.7, @babel/parser@npm:^7.25.9, @babel/parser@npm:^7.26.0, @babel/parser@npm:^7.26.3": - version: 7.26.3 - resolution: "@babel/parser@npm:7.26.3" +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.0, @babel/parser@npm:^7.28.5, @babel/parser@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/parser@npm:7.28.6" dependencies: - "@babel/types": "npm:^7.26.3" + "@babel/types": "npm:^7.28.6" bin: parser: ./bin/babel-parser.js - checksum: 10/e7e3814b2dc9ee3ed605d38223471fa7d3a84cbe9474d2b5fa7ac57dc1ddf75577b1fd3a93bf7db8f41f28869bda795cddd80223f980be23623b6434bf4c88a8 + checksum: 10/483a6fb5f9876ec9cbbb98816f2c94f39ae4d1158d35f87e1c4bf19a1f56027c96a1a3962ff0c8c46e8322a6d9e1c80d26b7f9668410df13d5b5769d9447b010 languageName: node linkType: hard @@ -284,13 +271,13 @@ __metadata: linkType: hard "@babel/plugin-syntax-import-attributes@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-syntax-import-attributes@npm:7.24.7" + version: 7.28.6 + resolution: "@babel/plugin-syntax-import-attributes@npm:7.28.6" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.28.6" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10/22fc50bd85a491bb8d22065f330a41f60d66f2f2d7a1deb73e80c8a4b5d7a42a092a03f8da18800650eca0fc14585167cc4e5c9fab351f0d390d1592347162ae + checksum: 10/6c8c6a5988dbb9799d6027360d1a5ba64faabf551f2ef11ba4eade0c62253b5c85d44ddc8eb643c74b9acb2bcaa664a950bd5de9a5d4aef291c4f2a48223bb4b languageName: node linkType: hard @@ -316,14 +303,14 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-jsx@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-syntax-jsx@npm:7.24.7" +"@babel/plugin-syntax-jsx@npm:^7.27.1": + version: 7.28.6 + resolution: "@babel/plugin-syntax-jsx@npm:7.28.6" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.28.6" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10/a93516ae5b34868ab892a95315027d4e5e38e8bd1cfca6158f2974b0901cbb32bbe64ea10ad5b25f919ddc40c6d8113c4823372909c9c9922170c12b0b1acecb + checksum: 10/572e38f5c1bb4b8124300e7e3dd13e82ae84a21f90d3f0786c98cd05e63c78ca1f32d1cfe462dfbaf5e7d5102fa7cd8fd741dfe4f3afc2e01a3b2877dcc8c866 languageName: node linkType: hard @@ -415,102 +402,99 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-typescript@npm:^7.24.7, @babel/plugin-syntax-typescript@npm:^7.7.2": - version: 7.25.4 - resolution: "@babel/plugin-syntax-typescript@npm:7.25.4" +"@babel/plugin-syntax-typescript@npm:^7.28.6, @babel/plugin-syntax-typescript@npm:^7.7.2": + version: 7.28.6 + resolution: "@babel/plugin-syntax-typescript@npm:7.28.6" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.8" + "@babel/helper-plugin-utils": "npm:^7.28.6" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10/0771b45a35fd536cd3b3a48e5eda0f53e2d4f4a0ca07377cc247efa39eaf6002ed1c478106aad2650e54aefaebcb4f34f3284c4ae9252695dbd944bf66addfb0 + checksum: 10/5c55f9c63bd36cf3d7e8db892294c8f85000f9c1526c3a1cc310d47d1e174f5c6f6605e5cc902c4636d885faba7a9f3d5e5edc6b35e4f3b1fd4c2d58d0304fa5 languageName: node linkType: hard -"@babel/plugin-transform-modules-commonjs@npm:^7.23.3, @babel/plugin-transform-modules-commonjs@npm:^7.24.7": - version: 7.24.8 - resolution: "@babel/plugin-transform-modules-commonjs@npm:7.24.8" +"@babel/plugin-transform-modules-commonjs@npm:^7.23.3, @babel/plugin-transform-modules-commonjs@npm:^7.27.1": + version: 7.28.6 + resolution: "@babel/plugin-transform-modules-commonjs@npm:7.28.6" dependencies: - "@babel/helper-module-transforms": "npm:^7.24.8" - "@babel/helper-plugin-utils": "npm:^7.24.8" - "@babel/helper-simple-access": "npm:^7.24.7" + "@babel/helper-module-transforms": "npm:^7.28.6" + "@babel/helper-plugin-utils": "npm:^7.28.6" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10/18e5d229767c7b5b6ff0cbf1a8d2d555965b90201839d0ac2dc043b56857624ea344e59f733f028142a8c1d54923b82e2a0185694ef36f988d797bfbaf59819c + checksum: 10/ec6ea2958e778a7e0220f4a75cb5816cecddc6bd98efa10499fff7baabaa29a594d50d787a4ebf8a8ba66fefcf76ca2ded602be0b4554ae3317e53b3b3375b37 languageName: node linkType: hard -"@babel/plugin-transform-typescript@npm:^7.24.7": - version: 7.25.2 - resolution: "@babel/plugin-transform-typescript@npm:7.25.2" +"@babel/plugin-transform-typescript@npm:^7.28.5": + version: 7.28.6 + resolution: "@babel/plugin-transform-typescript@npm:7.28.6" dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.24.7" - "@babel/helper-create-class-features-plugin": "npm:^7.25.0" - "@babel/helper-plugin-utils": "npm:^7.24.8" - "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.24.7" - "@babel/plugin-syntax-typescript": "npm:^7.24.7" + "@babel/helper-annotate-as-pure": "npm:^7.27.3" + "@babel/helper-create-class-features-plugin": "npm:^7.28.6" + "@babel/helper-plugin-utils": "npm:^7.28.6" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.27.1" + "@babel/plugin-syntax-typescript": "npm:^7.28.6" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10/50e017ffd131c08661daa22b6c759999bb7a6cdfbf683291ee4bcbea4ae839440b553d2f8896bcf049aca1d267b39f3b09e8336059e919e83149b5ad859671f6 + checksum: 10/a0bccc531fa8710a45b0b593140273741e0e4a0721b1ef6ef9dfefae0bbe61528440d65aab7936929551fd76793272257d74f60cf66891352f793294930a4b67 languageName: node linkType: hard "@babel/preset-typescript@npm:^7.23.3": - version: 7.24.7 - resolution: "@babel/preset-typescript@npm:7.24.7" + version: 7.28.5 + resolution: "@babel/preset-typescript@npm:7.28.5" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" - "@babel/helper-validator-option": "npm:^7.24.7" - "@babel/plugin-syntax-jsx": "npm:^7.24.7" - "@babel/plugin-transform-modules-commonjs": "npm:^7.24.7" - "@babel/plugin-transform-typescript": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.27.1" + "@babel/helper-validator-option": "npm:^7.27.1" + "@babel/plugin-syntax-jsx": "npm:^7.27.1" + "@babel/plugin-transform-modules-commonjs": "npm:^7.27.1" + "@babel/plugin-transform-typescript": "npm:^7.28.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10/995e9783f8e474581e7533d6b10ec1fbea69528cc939ad8582b5937e13548e5215d25a8e2c845e7b351fdaa13139896b5e42ab3bde83918ea4e41773f10861ac + checksum: 10/72c03e01c34906041b1813542761a283c52da1751e7ddf63191bc5fb2a0354eca30a00537c5a92951688bec3975bdc0e50ef4516b5e94cfd6d4cf947f2125bdc languageName: node linkType: hard "@babel/runtime@npm:^7.23.9": - version: 7.25.4 - resolution: "@babel/runtime@npm:7.25.4" - dependencies: - regenerator-runtime: "npm:^0.14.0" - checksum: 10/70d2a420c24a3289ea6c4addaf3a1c4186bc3d001c92445faa3cd7601d7d2fbdb32c63b3a26b9771e20ff2f511fa76b726bf256f823cdb95bc37b8eadbd02f70 + version: 7.28.6 + resolution: "@babel/runtime@npm:7.28.6" + checksum: 10/fbcd439cb74d4a681958eb064c509829e3f46d8a4bfaaf441baa81bb6733d1e680bccc676c813883d7741bcaada1d0d04b15aa320ef280b5734e2192b50decf9 languageName: node linkType: hard -"@babel/template@npm:^7.25.9, @babel/template@npm:^7.3.3": - version: 7.25.9 - resolution: "@babel/template@npm:7.25.9" +"@babel/template@npm:^7.28.6, @babel/template@npm:^7.3.3": + version: 7.28.6 + resolution: "@babel/template@npm:7.28.6" dependencies: - "@babel/code-frame": "npm:^7.25.9" - "@babel/parser": "npm:^7.25.9" - "@babel/types": "npm:^7.25.9" - checksum: 10/e861180881507210150c1335ad94aff80fd9e9be6202e1efa752059c93224e2d5310186ddcdd4c0f0b0fc658ce48cb47823f15142b5c00c8456dde54f5de80b2 + "@babel/code-frame": "npm:^7.28.6" + "@babel/parser": "npm:^7.28.6" + "@babel/types": "npm:^7.28.6" + checksum: 10/0ad6e32bf1e7e31bf6b52c20d15391f541ddd645cbd488a77fe537a15b280ee91acd3a777062c52e03eedbc2e1f41548791f6a3697c02476ec5daf49faa38533 languageName: node linkType: hard -"@babel/traverse@npm:^7.23.2, @babel/traverse@npm:^7.24.7, @babel/traverse@npm:^7.24.8, @babel/traverse@npm:^7.25.0, @babel/traverse@npm:^7.25.4, @babel/traverse@npm:^7.25.9, @babel/traverse@npm:^7.7.2": - version: 7.26.4 - resolution: "@babel/traverse@npm:7.26.4" +"@babel/traverse@npm:^7.23.2, @babel/traverse@npm:^7.27.1, @babel/traverse@npm:^7.28.5, @babel/traverse@npm:^7.28.6, @babel/traverse@npm:^7.7.2": + version: 7.28.6 + resolution: "@babel/traverse@npm:7.28.6" dependencies: - "@babel/code-frame": "npm:^7.26.2" - "@babel/generator": "npm:^7.26.3" - "@babel/parser": "npm:^7.26.3" - "@babel/template": "npm:^7.25.9" - "@babel/types": "npm:^7.26.3" + "@babel/code-frame": "npm:^7.28.6" + "@babel/generator": "npm:^7.28.6" + "@babel/helper-globals": "npm:^7.28.0" + "@babel/parser": "npm:^7.28.6" + "@babel/template": "npm:^7.28.6" + "@babel/types": "npm:^7.28.6" debug: "npm:^4.3.1" - globals: "npm:^11.1.0" - checksum: 10/30c81a80d66fc39842814bc2e847f4705d30f3859156f130d90a0334fe1d53aa81eed877320141a528ecbc36448acc0f14f544a7d410fa319d1c3ab63b50b58f + checksum: 10/dd71efe9412433169b805d5c346a6473e539ce30f605752a0d40a0733feba37259bd72bb4ad2ab591e2eaff1ee56633de160c1e98efdc8f373cf33a4a8660275 languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.23.0, @babel/types@npm:^7.24.7, @babel/types@npm:^7.24.8, @babel/types@npm:^7.25.9, @babel/types@npm:^7.26.0, @babel/types@npm:^7.26.3, @babel/types@npm:^7.3.3": - version: 7.26.3 - resolution: "@babel/types@npm:7.26.3" +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.23.0, @babel/types@npm:^7.27.1, @babel/types@npm:^7.27.3, @babel/types@npm:^7.28.2, @babel/types@npm:^7.28.5, @babel/types@npm:^7.28.6, @babel/types@npm:^7.3.3": + version: 7.28.6 + resolution: "@babel/types@npm:7.28.6" dependencies: - "@babel/helper-string-parser": "npm:^7.25.9" - "@babel/helper-validator-identifier": "npm:^7.25.9" - checksum: 10/c31d0549630a89abfa11410bf82a318b0c87aa846fbf5f9905e47ba5e2aa44f41cc746442f105d622c519e4dc532d35a8d8080460ff4692f9fc7485fbf3a00eb + "@babel/helper-string-parser": "npm:^7.27.1" + "@babel/helper-validator-identifier": "npm:^7.28.5" + checksum: 10/f9c6e52b451065aae5654686ecfc7de2d27dd0fbbc204ee2bd912a71daa359521a32f378981b1cf333ace6c8f86928814452cb9f388a7da59ad468038deb6b5f languageName: node linkType: hard @@ -522,29 +506,57 @@ __metadata: linkType: hard "@contentful/content-source-maps@npm:^0.11.0": - version: 0.11.1 - resolution: "@contentful/content-source-maps@npm:0.11.1" + version: 0.11.44 + resolution: "@contentful/content-source-maps@npm:0.11.44" dependencies: "@vercel/stega": "npm:^0.1.2" json-pointer: "npm:^0.6.2" - checksum: 10/598e88349210aed21c9ee871250353ae15cb4130180ade9cf283261e192a80c72f8674c5533c490ad1358850e45578ed6ed4ac997b32c23b029ae4d096fa5646 + checksum: 10/30c5334c9921853e3a2ec71b4e572fd0f361fd2d6da3378c6345c9f8a2693ffda1f88bcc84243dba1a514562ef9a766315b9c8626f757dec8b000c6ace5a3d23 languageName: node linkType: hard "@contentful/rich-text-html-renderer@npm:^16.5.2": - version: 16.6.9 - resolution: "@contentful/rich-text-html-renderer@npm:16.6.9" + version: 16.6.10 + resolution: "@contentful/rich-text-html-renderer@npm:16.6.10" dependencies: - "@contentful/rich-text-types": "npm:^16.8.4" + "@contentful/rich-text-types": "npm:^16.8.5" escape-html: "npm:^1.0.3" - checksum: 10/10bdcee4c01b89e5ab54ccab592bad7d3658fdd32ee58e2d5d18628a59ca47c7393c8dec41e96172b4c171f7fb4d2d1d6b9da9d6eeebbe5ed83fc3de8c4c0c89 + checksum: 10/fdf5121524355c96cd8a4628b2cc50a61b9b9d37da167dd983cc8fa24fa822427809d00064ebca9b85b8f40d92719f0b86f0e4ea4eaa8d078656ed56c51df6bb + languageName: node + linkType: hard + +"@contentful/rich-text-types@npm:^16.0.2, @contentful/rich-text-types@npm:^16.8.5": + version: 16.8.5 + resolution: "@contentful/rich-text-types@npm:16.8.5" + checksum: 10/7c1ec7088cc39bbd8f5edc14867ed3d59d06a55f2c92e6c62913aa2312056e920528e6ca6d59780b32c6fe2ab89c429b9f0bce9a52f456be7260f458527ccc3b + languageName: node + linkType: hard + +"@emnapi/core@npm:^1.4.3": + version: 1.8.1 + resolution: "@emnapi/core@npm:1.8.1" + dependencies: + "@emnapi/wasi-threads": "npm:1.1.0" + tslib: "npm:^2.4.0" + checksum: 10/904ea60c91fc7d8aeb4a8f2c433b8cfb47c50618f2b6f37429fc5093c857c6381c60628a5cfbc3a7b0d75b0a288f21d4ed2d4533e82f92c043801ef255fd6a5c + languageName: node + linkType: hard + +"@emnapi/runtime@npm:^1.4.3": + version: 1.8.1 + resolution: "@emnapi/runtime@npm:1.8.1" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10/26725e202d4baefdc4a6ba770f703dfc80825a27c27a08c22bac1e1ce6f8f75c47b4fe9424d9b63239463c33ef20b650f08d710da18dfa1164a95e5acb865dba languageName: node linkType: hard -"@contentful/rich-text-types@npm:^16.0.2, @contentful/rich-text-types@npm:^16.8.4": - version: 16.8.4 - resolution: "@contentful/rich-text-types@npm:16.8.4" - checksum: 10/22e0a165545f32cc51d1e6231a9e7b617af98c452ecfb28ace9ba8a53b89bb2d940019ffae00ef2bc77c998630a66bfc88d01031e732afb11172f877064aa5b2 +"@emnapi/wasi-threads@npm:1.1.0": + version: 1.1.0 + resolution: "@emnapi/wasi-threads@npm:1.1.0" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10/0d557e75262d2f4c95cb2a456ba0785ef61f919ce488c1d76e5e3acfd26e00c753ef928cd80068363e0c166ba8cc0141305daf0f81aad5afcd421f38f11e0f4e languageName: node linkType: hard @@ -569,214 +581,216 @@ __metadata: languageName: node linkType: hard -"@es-joy/jsdoccomment@npm:~0.49.0": - version: 0.49.0 - resolution: "@es-joy/jsdoccomment@npm:0.49.0" +"@es-joy/jsdoccomment@npm:~0.50.2": + version: 0.50.2 + resolution: "@es-joy/jsdoccomment@npm:0.50.2" dependencies: + "@types/estree": "npm:^1.0.6" + "@typescript-eslint/types": "npm:^8.11.0" comment-parser: "npm:1.4.1" esquery: "npm:^1.6.0" jsdoc-type-pratt-parser: "npm:~4.1.0" - checksum: 10/d767cef9b09f22d1892b8bd544eee32aa7b55c585edf6b51452e6f377f205b06f46bd319174022f75794d39625b4b0f8ce75c8a4ea0b7fd0f773063506e0ef4d + checksum: 10/a309f01bd1691c6991e5efb78057ec9122ef33208fec2464d7b9e5838964b948fa46c9c944a09218a752b49267f05ac15b557018c8a1897fd8df47b944b4537f languageName: node linkType: hard -"@esbuild/aix-ppc64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/aix-ppc64@npm:0.25.9" +"@esbuild/aix-ppc64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/aix-ppc64@npm:0.27.2" conditions: os=aix & cpu=ppc64 languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/android-arm64@npm:0.25.9" +"@esbuild/android-arm64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/android-arm64@npm:0.27.2" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@esbuild/android-arm@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/android-arm@npm:0.25.9" +"@esbuild/android-arm@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/android-arm@npm:0.27.2" conditions: os=android & cpu=arm languageName: node linkType: hard -"@esbuild/android-x64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/android-x64@npm:0.25.9" +"@esbuild/android-x64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/android-x64@npm:0.27.2" conditions: os=android & cpu=x64 languageName: node linkType: hard -"@esbuild/darwin-arm64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/darwin-arm64@npm:0.25.9" +"@esbuild/darwin-arm64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/darwin-arm64@npm:0.27.2" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@esbuild/darwin-x64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/darwin-x64@npm:0.25.9" +"@esbuild/darwin-x64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/darwin-x64@npm:0.27.2" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@esbuild/freebsd-arm64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/freebsd-arm64@npm:0.25.9" +"@esbuild/freebsd-arm64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/freebsd-arm64@npm:0.27.2" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/freebsd-x64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/freebsd-x64@npm:0.25.9" +"@esbuild/freebsd-x64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/freebsd-x64@npm:0.27.2" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@esbuild/linux-arm64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/linux-arm64@npm:0.25.9" +"@esbuild/linux-arm64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-arm64@npm:0.27.2" conditions: os=linux & cpu=arm64 languageName: node linkType: hard -"@esbuild/linux-arm@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/linux-arm@npm:0.25.9" +"@esbuild/linux-arm@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-arm@npm:0.27.2" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@esbuild/linux-ia32@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/linux-ia32@npm:0.25.9" +"@esbuild/linux-ia32@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-ia32@npm:0.27.2" conditions: os=linux & cpu=ia32 languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/linux-loong64@npm:0.25.9" +"@esbuild/linux-loong64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-loong64@npm:0.27.2" conditions: os=linux & cpu=loong64 languageName: node linkType: hard -"@esbuild/linux-mips64el@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/linux-mips64el@npm:0.25.9" +"@esbuild/linux-mips64el@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-mips64el@npm:0.27.2" conditions: os=linux & cpu=mips64el languageName: node linkType: hard -"@esbuild/linux-ppc64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/linux-ppc64@npm:0.25.9" +"@esbuild/linux-ppc64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-ppc64@npm:0.27.2" conditions: os=linux & cpu=ppc64 languageName: node linkType: hard -"@esbuild/linux-riscv64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/linux-riscv64@npm:0.25.9" +"@esbuild/linux-riscv64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-riscv64@npm:0.27.2" conditions: os=linux & cpu=riscv64 languageName: node linkType: hard -"@esbuild/linux-s390x@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/linux-s390x@npm:0.25.9" +"@esbuild/linux-s390x@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-s390x@npm:0.27.2" conditions: os=linux & cpu=s390x languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/linux-x64@npm:0.25.9" +"@esbuild/linux-x64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-x64@npm:0.27.2" conditions: os=linux & cpu=x64 languageName: node linkType: hard -"@esbuild/netbsd-arm64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/netbsd-arm64@npm:0.25.9" +"@esbuild/netbsd-arm64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/netbsd-arm64@npm:0.27.2" conditions: os=netbsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/netbsd-x64@npm:0.25.9" +"@esbuild/netbsd-x64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/netbsd-x64@npm:0.27.2" conditions: os=netbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/openbsd-arm64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/openbsd-arm64@npm:0.25.9" +"@esbuild/openbsd-arm64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/openbsd-arm64@npm:0.27.2" conditions: os=openbsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/openbsd-x64@npm:0.25.9" +"@esbuild/openbsd-x64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/openbsd-x64@npm:0.27.2" conditions: os=openbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/openharmony-arm64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/openharmony-arm64@npm:0.25.9" +"@esbuild/openharmony-arm64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/openharmony-arm64@npm:0.27.2" conditions: os=openharmony & cpu=arm64 languageName: node linkType: hard -"@esbuild/sunos-x64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/sunos-x64@npm:0.25.9" +"@esbuild/sunos-x64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/sunos-x64@npm:0.27.2" conditions: os=sunos & cpu=x64 languageName: node linkType: hard -"@esbuild/win32-arm64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/win32-arm64@npm:0.25.9" +"@esbuild/win32-arm64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/win32-arm64@npm:0.27.2" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@esbuild/win32-ia32@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/win32-ia32@npm:0.25.9" +"@esbuild/win32-ia32@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/win32-ia32@npm:0.27.2" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/win32-x64@npm:0.25.9" +"@esbuild/win32-x64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/win32-x64@npm:0.27.2" conditions: os=win32 & cpu=x64 languageName: node linkType: hard -"@eslint-community/eslint-utils@npm:^4.1.2, @eslint-community/eslint-utils@npm:^4.4.0, @eslint-community/eslint-utils@npm:^4.4.1, @eslint-community/eslint-utils@npm:^4.7.0, @eslint-community/eslint-utils@npm:^4.8.0": - version: 4.9.0 - resolution: "@eslint-community/eslint-utils@npm:4.9.0" +"@eslint-community/eslint-utils@npm:^4.1.2, @eslint-community/eslint-utils@npm:^4.4.0, @eslint-community/eslint-utils@npm:^4.5.0, @eslint-community/eslint-utils@npm:^4.8.0, @eslint-community/eslint-utils@npm:^4.9.1": + version: 4.9.1 + resolution: "@eslint-community/eslint-utils@npm:4.9.1" dependencies: eslint-visitor-keys: "npm:^3.4.3" peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - checksum: 10/89b1eb3137e14c379865e60573f524fcc0ee5c4b0c7cd21090673e75e5a720f14b92f05ab2d02704c2314b67e67b6f96f3bb209ded6b890ced7b667aa4bf1fa2 + checksum: 10/863b5467868551c9ae34d03eefe634633d08f623fc7b19d860f8f26eb6f303c1a5934253124163bee96181e45ed22bf27473dccc295937c3078493a4a8c9eddd languageName: node linkType: hard -"@eslint-community/regexpp@npm:^4.10.0, @eslint-community/regexpp@npm:^4.11.0, @eslint-community/regexpp@npm:^4.12.1": - version: 4.12.1 - resolution: "@eslint-community/regexpp@npm:4.12.1" - checksum: 10/c08f1dd7dd18fbb60bdd0d85820656d1374dd898af9be7f82cb00451313402a22d5e30569c150315b4385907cdbca78c22389b2a72ab78883b3173be317620cc +"@eslint-community/regexpp@npm:^4.11.0, @eslint-community/regexpp@npm:^4.12.1, @eslint-community/regexpp@npm:^4.12.2": + version: 4.12.2 + resolution: "@eslint-community/regexpp@npm:4.12.2" + checksum: 10/049b280fddf71dd325514e0a520024969431dc3a8b02fa77476e6820e9122f28ab4c9168c11821f91a27982d2453bcd7a66193356ea84e84fb7c8d793be1ba0c languageName: node linkType: hard @@ -810,8 +824,8 @@ __metadata: linkType: hard "@eslint/eslintrc@npm:^3.3.1": - version: 3.3.1 - resolution: "@eslint/eslintrc@npm:3.3.1" + version: 3.3.3 + resolution: "@eslint/eslintrc@npm:3.3.3" dependencies: ajv: "npm:^6.12.4" debug: "npm:^4.3.2" @@ -819,17 +833,17 @@ __metadata: globals: "npm:^14.0.0" ignore: "npm:^5.2.0" import-fresh: "npm:^3.2.1" - js-yaml: "npm:^4.1.0" + js-yaml: "npm:^4.1.1" minimatch: "npm:^3.1.2" strip-json-comments: "npm:^3.1.1" - checksum: 10/cc240addbab3c5fceaa65b2c8d5d4fd77ddbbf472c2f74f0270b9d33263dc9116840b6099c46b64c9680301146250439b044ed79278a1bcc557da412a4e3c1bb + checksum: 10/b586a364ff15ce1b68993aefc051ca330b1fece15fb5baf4a708d00113f9a14895cffd84a5f24c5a97bd4b4321130ab2314f90aa462a250f6b859c2da2cba1f3 languageName: node linkType: hard -"@eslint/js@npm:9.39.1, @eslint/js@npm:^9.11.0": - version: 9.39.1 - resolution: "@eslint/js@npm:9.39.1" - checksum: 10/b10b9b953212c0f3ffca475159bbe519e9e98847200c7432d1637d444fddcd7b712d2b7710a7dc20510f9cfbe8db330039b2aad09cb55d9545b116d940dbeed2 +"@eslint/js@npm:9.39.2, @eslint/js@npm:^9.11.0": + version: 9.39.2 + resolution: "@eslint/js@npm:9.39.2" + checksum: 10/6b7f676746f3111b5d1b23715319212ab9297868a0fa9980d483c3da8965d5841673aada2d5653e85a3f7156edee0893a7ae7035211b4efdcb2848154bb947f2 languageName: node linkType: hard @@ -932,24 +946,24 @@ __metadata: languageName: node linkType: hard -"@ethersproject/abi@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/abi@npm:5.7.0" +"@ethersproject/abi@npm:^5.7.0, @ethersproject/abi@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/abi@npm:5.8.0" dependencies: - "@ethersproject/address": "npm:^5.7.0" - "@ethersproject/bignumber": "npm:^5.7.0" - "@ethersproject/bytes": "npm:^5.7.0" - "@ethersproject/constants": "npm:^5.7.0" - "@ethersproject/hash": "npm:^5.7.0" - "@ethersproject/keccak256": "npm:^5.7.0" - "@ethersproject/logger": "npm:^5.7.0" - "@ethersproject/properties": "npm:^5.7.0" - "@ethersproject/strings": "npm:^5.7.0" - checksum: 10/6ed002cbc61a7e21bc0182702345659c1984f6f8e6bad166e43aee76ea8f74766dd0f6236574a868e1b4600af27972bf25b973fae7877ae8da3afa90d3965cac + "@ethersproject/address": "npm:^5.8.0" + "@ethersproject/bignumber": "npm:^5.8.0" + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/constants": "npm:^5.8.0" + "@ethersproject/hash": "npm:^5.8.0" + "@ethersproject/keccak256": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + "@ethersproject/properties": "npm:^5.8.0" + "@ethersproject/strings": "npm:^5.8.0" + checksum: 10/a63ebc2c8ea795ceca5289abaf817bb402c83c330cffd0ae2d355be70c54050a21ddd408abd4fd0dce4c3fd5c5f091707be2095011c233022a52f2110e7012d6 languageName: node linkType: hard -"@ethersproject/abstract-provider@npm:^5.7.0, @ethersproject/abstract-provider@npm:^5.8.0": +"@ethersproject/abstract-provider@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/abstract-provider@npm:5.8.0" dependencies: @@ -964,7 +978,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/abstract-signer@npm:^5.7.0, @ethersproject/abstract-signer@npm:^5.8.0": +"@ethersproject/abstract-signer@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/abstract-signer@npm:5.8.0" dependencies: @@ -990,7 +1004,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/base64@npm:^5.7.0, @ethersproject/base64@npm:^5.8.0": +"@ethersproject/base64@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/base64@npm:5.8.0" dependencies: @@ -999,7 +1013,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/basex@npm:^5.7.0, @ethersproject/basex@npm:^5.8.0": +"@ethersproject/basex@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/basex@npm:5.8.0" dependencies: @@ -1020,7 +1034,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/bytes@npm:^5.7.0, @ethersproject/bytes@npm:^5.8.0": +"@ethersproject/bytes@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/bytes@npm:5.8.0" dependencies: @@ -1039,24 +1053,24 @@ __metadata: linkType: hard "@ethersproject/contracts@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/contracts@npm:5.7.0" + version: 5.8.0 + resolution: "@ethersproject/contracts@npm:5.8.0" dependencies: - "@ethersproject/abi": "npm:^5.7.0" - "@ethersproject/abstract-provider": "npm:^5.7.0" - "@ethersproject/abstract-signer": "npm:^5.7.0" - "@ethersproject/address": "npm:^5.7.0" - "@ethersproject/bignumber": "npm:^5.7.0" - "@ethersproject/bytes": "npm:^5.7.0" - "@ethersproject/constants": "npm:^5.7.0" - "@ethersproject/logger": "npm:^5.7.0" - "@ethersproject/properties": "npm:^5.7.0" - "@ethersproject/transactions": "npm:^5.7.0" - checksum: 10/5df66179af242faabea287a83fd2f8f303a4244dc87a6ff802e1e3b643f091451295c8e3d088c7739970b7915a16a581c192d4e007d848f1fdf3cc9e49010053 + "@ethersproject/abi": "npm:^5.8.0" + "@ethersproject/abstract-provider": "npm:^5.8.0" + "@ethersproject/abstract-signer": "npm:^5.8.0" + "@ethersproject/address": "npm:^5.8.0" + "@ethersproject/bignumber": "npm:^5.8.0" + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/constants": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + "@ethersproject/properties": "npm:^5.8.0" + "@ethersproject/transactions": "npm:^5.8.0" + checksum: 10/839f8211f5e560f15468ae843ba316ffeacab5cebcece1eec76bc5714472ebfe3453484f283d3e46b9d3faaffef1e17cc3583cf24e01638a1fd52f69012cf8d4 languageName: node linkType: hard -"@ethersproject/hash@npm:^5.7.0, @ethersproject/hash@npm:^5.8.0": +"@ethersproject/hash@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/hash@npm:5.8.0" dependencies: @@ -1114,7 +1128,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/keccak256@npm:^5.7.0, @ethersproject/keccak256@npm:^5.8.0": +"@ethersproject/keccak256@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/keccak256@npm:5.8.0" dependencies: @@ -1124,14 +1138,14 @@ __metadata: languageName: node linkType: hard -"@ethersproject/logger@npm:^5.7.0, @ethersproject/logger@npm:^5.8.0": +"@ethersproject/logger@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/logger@npm:5.8.0" checksum: 10/dab862d6cc3a4312f4c49d62b4a603f4b60707da8b8ff0fee6bdfee3cbed48b34ec8f23fedfef04dd3d24f2fa2d7ad2be753c775aa00fe24dcd400631d65004a languageName: node linkType: hard -"@ethersproject/networks@npm:^5.7.0, @ethersproject/networks@npm:^5.8.0": +"@ethersproject/networks@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/networks@npm:5.8.0" dependencies: @@ -1150,7 +1164,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/properties@npm:^5.7.0, @ethersproject/properties@npm:^5.8.0": +"@ethersproject/properties@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/properties@npm:5.8.0" dependencies: @@ -1160,34 +1174,34 @@ __metadata: linkType: hard "@ethersproject/providers@npm:^5.7.0, @ethersproject/providers@npm:^5.7.2": - version: 5.7.2 - resolution: "@ethersproject/providers@npm:5.7.2" + version: 5.8.0 + resolution: "@ethersproject/providers@npm:5.8.0" dependencies: - "@ethersproject/abstract-provider": "npm:^5.7.0" - "@ethersproject/abstract-signer": "npm:^5.7.0" - "@ethersproject/address": "npm:^5.7.0" - "@ethersproject/base64": "npm:^5.7.0" - "@ethersproject/basex": "npm:^5.7.0" - "@ethersproject/bignumber": "npm:^5.7.0" - "@ethersproject/bytes": "npm:^5.7.0" - "@ethersproject/constants": "npm:^5.7.0" - "@ethersproject/hash": "npm:^5.7.0" - "@ethersproject/logger": "npm:^5.7.0" - "@ethersproject/networks": "npm:^5.7.0" - "@ethersproject/properties": "npm:^5.7.0" - "@ethersproject/random": "npm:^5.7.0" - "@ethersproject/rlp": "npm:^5.7.0" - "@ethersproject/sha2": "npm:^5.7.0" - "@ethersproject/strings": "npm:^5.7.0" - "@ethersproject/transactions": "npm:^5.7.0" - "@ethersproject/web": "npm:^5.7.0" + "@ethersproject/abstract-provider": "npm:^5.8.0" + "@ethersproject/abstract-signer": "npm:^5.8.0" + "@ethersproject/address": "npm:^5.8.0" + "@ethersproject/base64": "npm:^5.8.0" + "@ethersproject/basex": "npm:^5.8.0" + "@ethersproject/bignumber": "npm:^5.8.0" + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/constants": "npm:^5.8.0" + "@ethersproject/hash": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + "@ethersproject/networks": "npm:^5.8.0" + "@ethersproject/properties": "npm:^5.8.0" + "@ethersproject/random": "npm:^5.8.0" + "@ethersproject/rlp": "npm:^5.8.0" + "@ethersproject/sha2": "npm:^5.8.0" + "@ethersproject/strings": "npm:^5.8.0" + "@ethersproject/transactions": "npm:^5.8.0" + "@ethersproject/web": "npm:^5.8.0" bech32: "npm:1.1.4" - ws: "npm:7.4.6" - checksum: 10/8534a1896e61b9f0b66427a639df64a5fe76d0c08ec59b9f0cc64fdd1d0cc28d9fc3312838ae8d7817c8f5e2e76b7f228b689bc33d1cbb8e1b9517d4c4f678d8 + ws: "npm:8.18.0" + checksum: 10/7d40fc0abb78fc9e69b71cb560beb2a93cf1da2cf978a061031a34c0ed76c2f5936ed8c0bdb9aa1307fe5308d0159e429b83b779dbd550639a886a88d6d17817 languageName: node linkType: hard -"@ethersproject/random@npm:^5.7.0, @ethersproject/random@npm:^5.8.0": +"@ethersproject/random@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/random@npm:5.8.0" dependencies: @@ -1197,7 +1211,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/rlp@npm:^5.7.0, @ethersproject/rlp@npm:^5.8.0": +"@ethersproject/rlp@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/rlp@npm:5.8.0" dependencies: @@ -1207,7 +1221,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/sha2@npm:^5.7.0, @ethersproject/sha2@npm:^5.8.0": +"@ethersproject/sha2@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/sha2@npm:5.8.0" dependencies: @@ -1232,7 +1246,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/strings@npm:^5.7.0, @ethersproject/strings@npm:^5.8.0": +"@ethersproject/strings@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/strings@npm:5.8.0" dependencies: @@ -1243,7 +1257,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/transactions@npm:^5.7.0, @ethersproject/transactions@npm:^5.8.0": +"@ethersproject/transactions@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/transactions@npm:5.8.0" dependencies: @@ -1283,7 +1297,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/web@npm:^5.7.0, @ethersproject/web@npm:^5.8.0": +"@ethersproject/web@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/web@npm:5.8.0" dependencies: @@ -1309,18 +1323,34 @@ __metadata: languageName: node linkType: hard -"@firebase/analytics-compat@npm:0.2.17": - version: 0.2.17 - resolution: "@firebase/analytics-compat@npm:0.2.17" +"@firebase/ai@npm:1.4.1": + version: 1.4.1 + resolution: "@firebase/ai@npm:1.4.1" + dependencies: + "@firebase/app-check-interop-types": "npm:0.3.3" + "@firebase/component": "npm:0.6.18" + "@firebase/logger": "npm:0.4.4" + "@firebase/util": "npm:1.12.1" + tslib: "npm:^2.1.0" + peerDependencies: + "@firebase/app": 0.x + "@firebase/app-types": 0.x + checksum: 10/64b152365f3de9d12dc6691eebe673193a3a1034e9a2217c736a3b5d52e671f9cb61b35e85ecaf9a36c9667ce4c45fccaa4fc750b01fafcaeef757dc761ea971 + languageName: node + linkType: hard + +"@firebase/analytics-compat@npm:0.2.23": + version: 0.2.23 + resolution: "@firebase/analytics-compat@npm:0.2.23" dependencies: - "@firebase/analytics": "npm:0.10.11" + "@firebase/analytics": "npm:0.10.17" "@firebase/analytics-types": "npm:0.8.3" - "@firebase/component": "npm:0.6.12" - "@firebase/util": "npm:1.10.3" + "@firebase/component": "npm:0.6.18" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app-compat": 0.x - checksum: 10/3b048b41e0405a3975050f5d55afa923263ba3768d7b1b635d70892504cac03bd0bcf353b44819959dc6de7c04f1df818e34cec705c8ce18cf5c0866abe277b9 + checksum: 10/17414002039df8cfb5f1ed320b60b9d369ef2e9833cb4a4c485afff3ebad520e33aebda628556e940f5a2ad4741d56f58d3eaf754d1811dbd5fec9ed48a27fec languageName: node linkType: hard @@ -1331,34 +1361,34 @@ __metadata: languageName: node linkType: hard -"@firebase/analytics@npm:0.10.11": - version: 0.10.11 - resolution: "@firebase/analytics@npm:0.10.11" +"@firebase/analytics@npm:0.10.17": + version: 0.10.17 + resolution: "@firebase/analytics@npm:0.10.17" dependencies: - "@firebase/component": "npm:0.6.12" - "@firebase/installations": "npm:0.6.12" + "@firebase/component": "npm:0.6.18" + "@firebase/installations": "npm:0.6.18" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app": 0.x - checksum: 10/804083f61ffc57dabeb7a1b49e16f86969d1b2a37fafc23633c90324768ab849e52324b6a10928d789e038ec2f5d93248717f18d5f0d2a4b916850b86051c214 + checksum: 10/689c9e8ce0f86c606c1c8ffc1c44cee84c9eb0c767fdf8ef8ccc138515a81071011d958aa06f35a8fc6cdff8050d3e91cb559aebc42fa944ab79ffab2b8dc1d4 languageName: node linkType: hard -"@firebase/app-check-compat@npm:0.3.18": - version: 0.3.18 - resolution: "@firebase/app-check-compat@npm:0.3.18" +"@firebase/app-check-compat@npm:0.3.26": + version: 0.3.26 + resolution: "@firebase/app-check-compat@npm:0.3.26" dependencies: - "@firebase/app-check": "npm:0.8.11" + "@firebase/app-check": "npm:0.10.1" "@firebase/app-check-types": "npm:0.5.3" - "@firebase/component": "npm:0.6.12" + "@firebase/component": "npm:0.6.18" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app-compat": 0.x - checksum: 10/24b103fc309fa66d9830614c69bdf62810ecf0b77ad4fc9f318e05361a686cc3a684d84bddbd6afddc6a641739ead93ab1e8c28a75ed915750602b371aeb9b32 + checksum: 10/679cefa70e2c9b448e4c494a7e87f032b804777b0a4dde403ebdb9a1b3b2087e6d3248f3265a0083b32b24fbfd960b12ba171dd762f783a64fd47e0088583fa8 languageName: node linkType: hard @@ -1376,30 +1406,30 @@ __metadata: languageName: node linkType: hard -"@firebase/app-check@npm:0.8.11": - version: 0.8.11 - resolution: "@firebase/app-check@npm:0.8.11" +"@firebase/app-check@npm:0.10.1": + version: 0.10.1 + resolution: "@firebase/app-check@npm:0.10.1" dependencies: - "@firebase/component": "npm:0.6.12" + "@firebase/component": "npm:0.6.18" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app": 0.x - checksum: 10/e3f6a3940037c17a2faaf97a700d33b2c7821e07460e0a854d9f542acdcb589514bb4699df3adba1fb1d17ee75261006939b8ef60ec44bbe6c8c827b0797aa77 + checksum: 10/b10d72aa267799344a8f11539b427db27edfdcd9fd9810b94b54c980c509fe91af5cf2ca491c8aa28d312d72e27f162377bd0acd4ada28152c152a9b304209ba languageName: node linkType: hard -"@firebase/app-compat@npm:0.2.48": - version: 0.2.48 - resolution: "@firebase/app-compat@npm:0.2.48" +"@firebase/app-compat@npm:0.4.2": + version: 0.4.2 + resolution: "@firebase/app-compat@npm:0.4.2" dependencies: - "@firebase/app": "npm:0.10.18" - "@firebase/component": "npm:0.6.12" + "@firebase/app": "npm:0.13.2" + "@firebase/component": "npm:0.6.18" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" - checksum: 10/b74598b960ebb0a773b04e04d45dd59dbc8e09d1ae46c8ee7fd950632c95d357e8edab353df7032b798f2613884c96f3201eb5fbcdbfba67cb23757d66e63586 + checksum: 10/07547051fbd4164547f208907493db37c41d418e03436d1058dfcbaa4850125f937247edc5a0c29c661cbbc532357c9cde936ccb113ba5ca71c7544be88b3c00 languageName: node linkType: hard @@ -1410,31 +1440,31 @@ __metadata: languageName: node linkType: hard -"@firebase/app@npm:0.10.18": - version: 0.10.18 - resolution: "@firebase/app@npm:0.10.18" +"@firebase/app@npm:0.13.2": + version: 0.13.2 + resolution: "@firebase/app@npm:0.13.2" dependencies: - "@firebase/component": "npm:0.6.12" + "@firebase/component": "npm:0.6.18" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" idb: "npm:7.1.1" tslib: "npm:^2.1.0" - checksum: 10/ac215e594d66e933207263c4c11ff585ba3843a0e73ab6f02c85f504f7b5e166f407a9bef299f5a91893840c7f5c8978895c0f6103b361fb188c1cfdb8c35030 + checksum: 10/74ab96561490da7d0bd46be5bb04d43edb65aaf96e6c9b17a7bda15d43a299b8204908e14e1fc29d690cff5a59345cc9e4a598ec99b46a22c1416f304875bc5e languageName: node linkType: hard -"@firebase/auth-compat@npm:0.5.17": - version: 0.5.17 - resolution: "@firebase/auth-compat@npm:0.5.17" +"@firebase/auth-compat@npm:0.5.28": + version: 0.5.28 + resolution: "@firebase/auth-compat@npm:0.5.28" dependencies: - "@firebase/auth": "npm:1.8.2" - "@firebase/auth-types": "npm:0.12.3" - "@firebase/component": "npm:0.6.12" - "@firebase/util": "npm:1.10.3" + "@firebase/auth": "npm:1.10.8" + "@firebase/auth-types": "npm:0.13.0" + "@firebase/component": "npm:0.6.18" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app-compat": 0.x - checksum: 10/4c6d0fa6f76c398872627f49c427c810269c0284bdca1acddf82b154c9cda7131e8acecd961c2e0947f0340428b67349b7f9471bb1bd75bd82839ce89879ccad + checksum: 10/df87c841e8ce44510927df1f5d6387787cc9ca7119a72436e1960f08fb8a96f11caf0dd71f947062bac78c104fb9afa7c04e5ef5dfa343a08c4609fb4b9deabd languageName: node linkType: hard @@ -1445,23 +1475,23 @@ __metadata: languageName: node linkType: hard -"@firebase/auth-types@npm:0.12.3": - version: 0.12.3 - resolution: "@firebase/auth-types@npm:0.12.3" +"@firebase/auth-types@npm:0.13.0": + version: 0.13.0 + resolution: "@firebase/auth-types@npm:0.13.0" peerDependencies: "@firebase/app-types": 0.x "@firebase/util": 1.x - checksum: 10/5eda88380e9b33a6c91b0f8dd6a581895c2770aa5b46b1928a006a74d35c6a310bfe737141ff013764a4e02815efa530f1576d674f09f905fbe3b14050dc7fce + checksum: 10/57d8e4b80e58d3a9e453b4676a29e3b0e548ca9f4c2b465137007bb5753e3bde2f6537f0be9779df17859ebc4e6b1b59c88215cdd59a32106391cf117072372d languageName: node linkType: hard -"@firebase/auth@npm:1.8.2": - version: 1.8.2 - resolution: "@firebase/auth@npm:1.8.2" +"@firebase/auth@npm:1.10.8": + version: 1.10.8 + resolution: "@firebase/auth@npm:1.10.8" dependencies: - "@firebase/component": "npm:0.6.12" + "@firebase/component": "npm:0.6.18" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app": 0.x @@ -1469,86 +1499,86 @@ __metadata: peerDependenciesMeta: "@react-native-async-storage/async-storage": optional: true - checksum: 10/8cfe5e6d78ea555f52bffad6e4b21824a30040fd52ffeb3d60edf0c122f0cbb66fc012e708f49473f045fa3064a4ac760e8bc6b24d5ccdf4ae7087b07da61247 + checksum: 10/c319d9c39a746317556c879e174bc8e0c4b6d3c72b8226ca3d6c6fc146387f0ad05cbe0b1d84c675a5b7cf6769fe5e696fbb140249c10f6b77586414642c0b39 languageName: node linkType: hard -"@firebase/component@npm:0.6.12": - version: 0.6.12 - resolution: "@firebase/component@npm:0.6.12" +"@firebase/component@npm:0.6.18": + version: 0.6.18 + resolution: "@firebase/component@npm:0.6.18" dependencies: - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" - checksum: 10/4dfd201d3709ef5eed477e13d399611a78a186ca8911846e24361f9848c3b4eecc14c295a8f78ec40c88816329fde0ba6cc30dce9a444fa43a619b7ea744f0dc + checksum: 10/cc50bd7fba3219c1dc8049cb3eee513ff76c13c9750588db3acc5d0bce98cdc7e546c227c7d7a21a96a1eb9366d20243d5770c4582fc967d2856235bf47a2023 languageName: node linkType: hard -"@firebase/data-connect@npm:0.2.0": - version: 0.2.0 - resolution: "@firebase/data-connect@npm:0.2.0" +"@firebase/data-connect@npm:0.3.10": + version: 0.3.10 + resolution: "@firebase/data-connect@npm:0.3.10" dependencies: "@firebase/auth-interop-types": "npm:0.2.4" - "@firebase/component": "npm:0.6.12" + "@firebase/component": "npm:0.6.18" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app": 0.x - checksum: 10/7ba5886bc69b0a42757539a3de417d550ca3359f495a3d8a3974e799a21fbcc2ea15393c00e183dcd01a845d42cad15a914345b4bed63bd401089861e92b1b35 + checksum: 10/22ca29b05ef868355b5744ba895bd4df7225f21c22a2f60147096d9f4fb7c68985cd7949d7674bf481a7a135b0a52355bc997eacdd1c29b99e3f236b4e4ea676 languageName: node linkType: hard -"@firebase/database-compat@npm:2.0.2": - version: 2.0.2 - resolution: "@firebase/database-compat@npm:2.0.2" +"@firebase/database-compat@npm:2.0.11": + version: 2.0.11 + resolution: "@firebase/database-compat@npm:2.0.11" dependencies: - "@firebase/component": "npm:0.6.12" - "@firebase/database": "npm:1.0.11" - "@firebase/database-types": "npm:1.0.8" + "@firebase/component": "npm:0.6.18" + "@firebase/database": "npm:1.0.20" + "@firebase/database-types": "npm:1.0.15" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" - checksum: 10/5a341662c32f08f248ce9e8cecb940169f618c42a5a85de72247f13ffa32d5ca0a5619d0330f6ff8c7e1ea6952733534531e03e53e2746732bcfc6e851c031b3 + checksum: 10/fc85067ffbb3bf789353465e8f79b05d34a563cde909fc3057bcbdee002e07e26b99eba049f41c79385c71217db1d1207591415545a7b42e54318dc869bff7f2 languageName: node linkType: hard -"@firebase/database-types@npm:1.0.8": - version: 1.0.8 - resolution: "@firebase/database-types@npm:1.0.8" +"@firebase/database-types@npm:1.0.15": + version: 1.0.15 + resolution: "@firebase/database-types@npm:1.0.15" dependencies: "@firebase/app-types": "npm:0.9.3" - "@firebase/util": "npm:1.10.3" - checksum: 10/1b5483de082ff8d7551b21f087ba2f237bcd38ca9e3f48b1377b96213718e0a206437fe31a4e055c1b90d05a1f38f89fe1c92d50d907ca06c8727c73fc521c40 + "@firebase/util": "npm:1.12.1" + checksum: 10/b9e2ef2d4c51fa518e7ace10e990d8b0f449dc669537b6fe57dc2beca64c658703e7b06272ad5b0935f094f65abe870ef34793ee205aa6559f5404b886c835e6 languageName: node linkType: hard -"@firebase/database@npm:1.0.11": - version: 1.0.11 - resolution: "@firebase/database@npm:1.0.11" +"@firebase/database@npm:1.0.20": + version: 1.0.20 + resolution: "@firebase/database@npm:1.0.20" dependencies: "@firebase/app-check-interop-types": "npm:0.3.3" "@firebase/auth-interop-types": "npm:0.2.4" - "@firebase/component": "npm:0.6.12" + "@firebase/component": "npm:0.6.18" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" faye-websocket: "npm:0.11.4" tslib: "npm:^2.1.0" - checksum: 10/8df5c54a6e88ecd2f71fe5bf156d23132c92f698210e23f27144dd871ea518e2268dc0eac91152091c8b75dbdf66d18c0ca623e80d1d3a69af5a3ed956a26e59 + checksum: 10/337189b26ef27bfb31244ef230f4b3c26797dfd3c80004f5fac256ec276783c90ee3b78a4b3efc5d7feb1afcfe817f739c212ea3a94126849a26a0b4a4134dd7 languageName: node linkType: hard -"@firebase/firestore-compat@npm:0.3.41": - version: 0.3.41 - resolution: "@firebase/firestore-compat@npm:0.3.41" +"@firebase/firestore-compat@npm:0.3.53": + version: 0.3.53 + resolution: "@firebase/firestore-compat@npm:0.3.53" dependencies: - "@firebase/component": "npm:0.6.12" - "@firebase/firestore": "npm:4.7.6" + "@firebase/component": "npm:0.6.18" + "@firebase/firestore": "npm:4.8.0" "@firebase/firestore-types": "npm:3.0.3" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app-compat": 0.x - checksum: 10/a719fc6bd1150b5b1653053e73709b2b2edddb6c2a9274a896f9b38a6a09e92d650dbb5df55aceaf23c413445a8beb18073b8726247df9aadbe13d175154fff1 + checksum: 10/4ec87a5b060bd7111b0eaadd34f6f73a5ab5d8464fabc7e6cbc4df86d228ae4cbdb72fd214e328f9b6e6cd8614b54a88a1cbd41a6d468f4861429b6399e7a5f3 languageName: node linkType: hard @@ -1562,35 +1592,35 @@ __metadata: languageName: node linkType: hard -"@firebase/firestore@npm:4.7.6": - version: 4.7.6 - resolution: "@firebase/firestore@npm:4.7.6" +"@firebase/firestore@npm:4.8.0": + version: 4.8.0 + resolution: "@firebase/firestore@npm:4.8.0" dependencies: - "@firebase/component": "npm:0.6.12" + "@firebase/component": "npm:0.6.18" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" "@firebase/webchannel-wrapper": "npm:1.0.3" "@grpc/grpc-js": "npm:~1.9.0" "@grpc/proto-loader": "npm:^0.7.8" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app": 0.x - checksum: 10/76e879675b34212af74e3d294458e254c3f547d4168a377074671317b3bcfc07acdff1e853bd1f139b8e4a767e91749f00ee00aa52d968c67f190fe490256151 + checksum: 10/201f5c4773bcf1e87aacf248b9ea902402665c27670503f1f17e2ef4602b4eca371288c9f504e88a6ac23f97df0af1aab5e107ddb86b95b7a62adcfe0974dbf7 languageName: node linkType: hard -"@firebase/functions-compat@npm:0.3.18": - version: 0.3.18 - resolution: "@firebase/functions-compat@npm:0.3.18" +"@firebase/functions-compat@npm:0.3.26": + version: 0.3.26 + resolution: "@firebase/functions-compat@npm:0.3.26" dependencies: - "@firebase/component": "npm:0.6.12" - "@firebase/functions": "npm:0.12.1" + "@firebase/component": "npm:0.6.18" + "@firebase/functions": "npm:0.12.9" "@firebase/functions-types": "npm:0.6.3" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app-compat": 0.x - checksum: 10/224132bbd592c73c717fb8b065a8e718d43c1f72d05135313fd19f7efd566164217d13e65bf6f142973bc35b29ff792c414610a9ddcd708601ddf718d739d3c9 + checksum: 10/42a0c5914bbb9dfdb1630acc6e7fd0c05cee0b5965df6325fb0bc34c591e8d12c45151b0edef3f56180bc3f0131ed2d33552d6a2428ac6929f717e5f485149e4 languageName: node linkType: hard @@ -1601,34 +1631,34 @@ __metadata: languageName: node linkType: hard -"@firebase/functions@npm:0.12.1": - version: 0.12.1 - resolution: "@firebase/functions@npm:0.12.1" +"@firebase/functions@npm:0.12.9": + version: 0.12.9 + resolution: "@firebase/functions@npm:0.12.9" dependencies: "@firebase/app-check-interop-types": "npm:0.3.3" "@firebase/auth-interop-types": "npm:0.2.4" - "@firebase/component": "npm:0.6.12" + "@firebase/component": "npm:0.6.18" "@firebase/messaging-interop-types": "npm:0.2.3" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app": 0.x - checksum: 10/db32ed6297a1f187062c772f3134f19849e3f1e55345838ebf2256555f1d65648c018ead208909bafd9620deba1191385f4223835cdad5c1c4e9567cb9244721 + checksum: 10/5646363243e07451c568d7b471a1c895a6b273d9cae168f70fa512a86916d85f9e2a73f9b378adef423a5e6b3af41cc2b5a8545458503f9956b1a5ebc93fd918 languageName: node linkType: hard -"@firebase/installations-compat@npm:0.2.12": - version: 0.2.12 - resolution: "@firebase/installations-compat@npm:0.2.12" +"@firebase/installations-compat@npm:0.2.18": + version: 0.2.18 + resolution: "@firebase/installations-compat@npm:0.2.18" dependencies: - "@firebase/component": "npm:0.6.12" - "@firebase/installations": "npm:0.6.12" + "@firebase/component": "npm:0.6.18" + "@firebase/installations": "npm:0.6.18" "@firebase/installations-types": "npm:0.5.3" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app-compat": 0.x - checksum: 10/ffd5e08e65e7067c06a4eb5601a09b017fce006b38108c10c412df8144e79bd08b4347998740425f312288b5a0839818e634486875857df5518c05a737c46ad8 + checksum: 10/5f5adc8384dcc6e1cee0c1f2e162134a38d3aac7a4152e5ee512da06174d79957c27bc49798dc79b28b668a233fb0b8eafb8d8dcd90c077357383329e7acf8a0 languageName: node linkType: hard @@ -1641,17 +1671,17 @@ __metadata: languageName: node linkType: hard -"@firebase/installations@npm:0.6.12": - version: 0.6.12 - resolution: "@firebase/installations@npm:0.6.12" +"@firebase/installations@npm:0.6.18": + version: 0.6.18 + resolution: "@firebase/installations@npm:0.6.18" dependencies: - "@firebase/component": "npm:0.6.12" - "@firebase/util": "npm:1.10.3" + "@firebase/component": "npm:0.6.18" + "@firebase/util": "npm:1.12.1" idb: "npm:7.1.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app": 0.x - checksum: 10/093295de087b4c9287d06243eb19814e25674047aafa4f5db9a222d8e64283d0362f37edf8cfbe882a80eac1d2d9fc52b821fbb01151ac925f023765251dd1de + checksum: 10/70d9036c6aa9c5ed79d1e66221ab38badbdcc2ff745d0bba4bede2d857c50e5678da6bea8862f8c31a74cb924778f6d0916286c4e5a9cb851decea3884ad6f56 languageName: node linkType: hard @@ -1664,17 +1694,17 @@ __metadata: languageName: node linkType: hard -"@firebase/messaging-compat@npm:0.2.16": - version: 0.2.16 - resolution: "@firebase/messaging-compat@npm:0.2.16" +"@firebase/messaging-compat@npm:0.2.22": + version: 0.2.22 + resolution: "@firebase/messaging-compat@npm:0.2.22" dependencies: - "@firebase/component": "npm:0.6.12" - "@firebase/messaging": "npm:0.12.16" - "@firebase/util": "npm:1.10.3" + "@firebase/component": "npm:0.6.18" + "@firebase/messaging": "npm:0.12.22" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app-compat": 0.x - checksum: 10/1887599e3f7d7db5a70f923118eda769130aa134c6a6ba0a9f599c541d78b2e00b9548fc51c12f430c60a6e902221fe951a4beeddd674f1c042ffa32d1593dc9 + checksum: 10/67f266689f6889fa169188e276d483f546565ee895481ba890a549bc27977a1ef08066a320c3099b77cc695086c9f5f2d90a4b7d9a2e0e4293de01397b38c956 languageName: node linkType: hard @@ -1685,35 +1715,35 @@ __metadata: languageName: node linkType: hard -"@firebase/messaging@npm:0.12.16": - version: 0.12.16 - resolution: "@firebase/messaging@npm:0.12.16" +"@firebase/messaging@npm:0.12.22": + version: 0.12.22 + resolution: "@firebase/messaging@npm:0.12.22" dependencies: - "@firebase/component": "npm:0.6.12" - "@firebase/installations": "npm:0.6.12" + "@firebase/component": "npm:0.6.18" + "@firebase/installations": "npm:0.6.18" "@firebase/messaging-interop-types": "npm:0.2.3" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" idb: "npm:7.1.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app": 0.x - checksum: 10/e237f35c4b179a521a6a37255fa719784ec73f30b76d179c059f21bf1e7ee6f907299c137a7b55496134dc5c3578d365c62b2e44988323edd3d96e5468f016d6 + checksum: 10/0639961d0cd695a44cb8f80a44a7e3d030a3746e6586db4a8d730623ac5d2a238d0a721fbd77cdaf3873f775881aee234e0e312c9bdcf70b65eb57be3ad5d58a languageName: node linkType: hard -"@firebase/performance-compat@npm:0.2.12": - version: 0.2.12 - resolution: "@firebase/performance-compat@npm:0.2.12" +"@firebase/performance-compat@npm:0.2.20": + version: 0.2.20 + resolution: "@firebase/performance-compat@npm:0.2.20" dependencies: - "@firebase/component": "npm:0.6.12" + "@firebase/component": "npm:0.6.18" "@firebase/logger": "npm:0.4.4" - "@firebase/performance": "npm:0.6.12" + "@firebase/performance": "npm:0.7.7" "@firebase/performance-types": "npm:0.2.3" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app-compat": 0.x - checksum: 10/c171273df3994da6687a8e02dd7f046cd749d80d18e1bc241e1e8fd55f4d05578bcdd3924153fbf7175da2a0b88dc8fb6e7de98afe72dd1a36e54f96e807dea1 + checksum: 10/5589470cfc1952a53fa81885b9d061eacab431f1875d858ff25632f2287d789d0d6641bd1c08f54c93681e58d37104acf895c07583898c6e9ec7184a03460ff3 languageName: node linkType: hard @@ -1724,34 +1754,35 @@ __metadata: languageName: node linkType: hard -"@firebase/performance@npm:0.6.12": - version: 0.6.12 - resolution: "@firebase/performance@npm:0.6.12" +"@firebase/performance@npm:0.7.7": + version: 0.7.7 + resolution: "@firebase/performance@npm:0.7.7" dependencies: - "@firebase/component": "npm:0.6.12" - "@firebase/installations": "npm:0.6.12" + "@firebase/component": "npm:0.6.18" + "@firebase/installations": "npm:0.6.18" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" + web-vitals: "npm:^4.2.4" peerDependencies: "@firebase/app": 0.x - checksum: 10/68f802e2a1f0add51e2346049957487561d1f59f9ea57f8447d7ba771210aee875aaa144d7db56bb376bac3509d800e917e6c3560e3dbf19bdc60c6e1bc67766 + checksum: 10/c4ad40b795966cecec89de66f4da76b750215cd4c859fda84db00c3a11b0633749873ac71d2c2dee307239cfdf9e5d1f1e83ef54061f9f03995df4cddc724319 languageName: node linkType: hard -"@firebase/remote-config-compat@npm:0.2.12": - version: 0.2.12 - resolution: "@firebase/remote-config-compat@npm:0.2.12" +"@firebase/remote-config-compat@npm:0.2.18": + version: 0.2.18 + resolution: "@firebase/remote-config-compat@npm:0.2.18" dependencies: - "@firebase/component": "npm:0.6.12" + "@firebase/component": "npm:0.6.18" "@firebase/logger": "npm:0.4.4" - "@firebase/remote-config": "npm:0.5.0" + "@firebase/remote-config": "npm:0.6.5" "@firebase/remote-config-types": "npm:0.4.0" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app-compat": 0.x - checksum: 10/931c4739c2b11b2719076630f09f5aa18f9edf8e89cf35c9b9a3a8cc5afc497c86e68cca165e1416afcb0b8040ed04363c676d31118fdcf4bf3823ef9172785c + checksum: 10/ba4311b295a35bfa27628698cf06b46d8debaa2e0a0dae147baa28f72340809e94132eaa793df3fd3973b00b6713cc89ccaf4bd33f6c5bcd1f68064f35a563f2 languageName: node linkType: hard @@ -1762,33 +1793,33 @@ __metadata: languageName: node linkType: hard -"@firebase/remote-config@npm:0.5.0": - version: 0.5.0 - resolution: "@firebase/remote-config@npm:0.5.0" +"@firebase/remote-config@npm:0.6.5": + version: 0.6.5 + resolution: "@firebase/remote-config@npm:0.6.5" dependencies: - "@firebase/component": "npm:0.6.12" - "@firebase/installations": "npm:0.6.12" + "@firebase/component": "npm:0.6.18" + "@firebase/installations": "npm:0.6.18" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app": 0.x - checksum: 10/58a6fad255d3975700e65d4d19ec3360703f920bcbd3bd2ff21f239367af7405bfec5fddf3f800fb405dd4e4456f73cdf0c5cbf624a9512d77293f7cf14b64d8 + checksum: 10/50e14afd65f9f4abb2dc3a268b3b82e522a9591123a1154b42a157228b71c661d7a7b77c81a3de59eec38c6ee278d5479516114f8d0e46162959e7af52bd6e2e languageName: node linkType: hard -"@firebase/storage-compat@npm:0.3.15": - version: 0.3.15 - resolution: "@firebase/storage-compat@npm:0.3.15" +"@firebase/storage-compat@npm:0.3.24": + version: 0.3.24 + resolution: "@firebase/storage-compat@npm:0.3.24" dependencies: - "@firebase/component": "npm:0.6.12" - "@firebase/storage": "npm:0.13.5" + "@firebase/component": "npm:0.6.18" + "@firebase/storage": "npm:0.13.14" "@firebase/storage-types": "npm:0.8.3" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app-compat": 0.x - checksum: 10/a4a4c64c44ea914a9509061ec373f33278f7096a547e7a9ed55c9100562bd688ca4f14f15eb3a798d5075b0e18dc15801bb95b23eddb2da600d855ee6c69e745 + checksum: 10/5445c8165d3732e31b77ca616497f930ed17c70d45202709907a38e82605d96df083fd5682b0c1fb6b34e71cebae9f8aa084abe81fd80e362ef80410fefcd508 languageName: node linkType: hard @@ -1802,41 +1833,25 @@ __metadata: languageName: node linkType: hard -"@firebase/storage@npm:0.13.5": - version: 0.13.5 - resolution: "@firebase/storage@npm:0.13.5" +"@firebase/storage@npm:0.13.14": + version: 0.13.14 + resolution: "@firebase/storage@npm:0.13.14" dependencies: - "@firebase/component": "npm:0.6.12" - "@firebase/util": "npm:1.10.3" + "@firebase/component": "npm:0.6.18" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app": 0.x - checksum: 10/89acbd41d3ed9bffe7a37e293b0dc572622c196665db2821d76690ee205397f3f331666c24b5c63c14caaadb3e519b3489400a6c5387e78d4fe0c97fe75128a9 + checksum: 10/e107960285ea7b0405e152e0da236c508d0b2b43f87a17accfd3fda5ea8b2d5fdad6a78a18b5e11b55817468afa3531b608bbb15ab83c54d3535aecd5a1e4ebd languageName: node linkType: hard -"@firebase/util@npm:1.10.3": - version: 1.10.3 - resolution: "@firebase/util@npm:1.10.3" +"@firebase/util@npm:1.12.1": + version: 1.12.1 + resolution: "@firebase/util@npm:1.12.1" dependencies: tslib: "npm:^2.1.0" - checksum: 10/8e5e1664a09798348abfa0cd138157943f8ee9c6e3804e6cb1dcff004b351a03f14f4b2711338133bb89f7f824546664af2c2aa98e229becbc9294cdddeecc99 - languageName: node - linkType: hard - -"@firebase/vertexai@npm:1.0.3": - version: 1.0.3 - resolution: "@firebase/vertexai@npm:1.0.3" - dependencies: - "@firebase/app-check-interop-types": "npm:0.3.3" - "@firebase/component": "npm:0.6.12" - "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.10.3" - tslib: "npm:^2.1.0" - peerDependencies: - "@firebase/app": 0.x - "@firebase/app-types": 0.x - checksum: 10/67b0ac231a547ac99bef3a549199fbaa67271fe93c1dc2af48bfebcf8ac1a7ea45bec6c633b8ac3ad28b089a6601e2b352c68c53065242dccac07a20a887d6cd + checksum: 10/31c608b4a614534366bec66dd699384467bf08b60b97801c33793025851f530cd1837ff00434aef49bfc1f35a1b38262ed0ac73d4393a3c4eab77dccb30a215f languageName: node linkType: hard @@ -1858,8 +1873,8 @@ __metadata: linkType: hard "@grpc/proto-loader@npm:^0.7.8": - version: 0.7.13 - resolution: "@grpc/proto-loader@npm:0.7.13" + version: 0.7.15 + resolution: "@grpc/proto-loader@npm:0.7.15" dependencies: lodash.camelcase: "npm:^4.3.0" long: "npm:^5.0.0" @@ -1867,7 +1882,7 @@ __metadata: yargs: "npm:^17.7.2" bin: proto-loader-gen-types: build/bin/proto-loader-gen-types.js - checksum: 10/7e2d842c2061cbaf6450c71da0077263be3bab165454d5c8a3e1ae4d3c6d2915f02fd27da63ff01f05e127b1221acd40705273f5d29303901e60514e852992f4 + checksum: 10/2e2b33ace8bc34211522751a9e654faf9ac997577a9e9291b1619b4c05d7878a74d2101c3bc43b2b2b92bca7509001678fb191d4eb100684cc2910d66f36c373 languageName: node linkType: hard @@ -1879,12 +1894,12 @@ __metadata: linkType: hard "@humanfs/node@npm:^0.16.6": - version: 0.16.6 - resolution: "@humanfs/node@npm:0.16.6" + version: 0.16.7 + resolution: "@humanfs/node@npm:0.16.7" dependencies: "@humanfs/core": "npm:^0.19.1" - "@humanwhocodes/retry": "npm:^0.3.0" - checksum: 10/6d43c6727463772d05610aa05c83dab2bfbe78291022ee7a92cb50999910b8c720c76cc312822e2dea2b497aa1b3fef5fe9f68803fc45c9d4ed105874a65e339 + "@humanwhocodes/retry": "npm:^0.4.0" + checksum: 10/b3633d3dce898592cac515ba5e6693c78e6be92863541d3eaf2c009b10f52b2fa62ff6e6e06f240f2447ddbe7b5f1890bc34e9308470675c876eee207553a08d languageName: node linkType: hard @@ -1895,14 +1910,7 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/retry@npm:^0.3.0": - version: 0.3.1 - resolution: "@humanwhocodes/retry@npm:0.3.1" - checksum: 10/eb457f699529de7f07649679ec9e0353055eebe443c2efe71c6dd950258892475a038e13c6a8c5e13ed1fb538cdd0a8794faa96b24b6ffc4c87fb1fc9f70ad7f - languageName: node - linkType: hard - -"@humanwhocodes/retry@npm:^0.4.2": +"@humanwhocodes/retry@npm:^0.4.0, @humanwhocodes/retry@npm:^0.4.2": version: 0.4.3 resolution: "@humanwhocodes/retry@npm:0.4.3" checksum: 10/0b32cfd362bea7a30fbf80bb38dcaf77fee9c2cae477ee80b460871d03590110ac9c77d654f04ec5beaf71b6f6a89851bdf6c1e34ccdf2f686bd86fcd97d9e61 @@ -1947,6 +1955,22 @@ __metadata: languageName: node linkType: hard +"@isaacs/balanced-match@npm:^4.0.1": + version: 4.0.1 + resolution: "@isaacs/balanced-match@npm:4.0.1" + checksum: 10/102fbc6d2c0d5edf8f6dbf2b3feb21695a21bc850f11bc47c4f06aa83bd8884fde3fe9d6d797d619901d96865fdcb4569ac2a54c937992c48885c5e3d9967fe8 + languageName: node + linkType: hard + +"@isaacs/brace-expansion@npm:^5.0.0": + version: 5.0.0 + resolution: "@isaacs/brace-expansion@npm:5.0.0" + dependencies: + "@isaacs/balanced-match": "npm:^4.0.1" + checksum: 10/cf3b7f206aff12128214a1df764ac8cdbc517c110db85249b945282407e3dfc5c6e66286383a7c9391a059fc8e6e6a8ca82262fc9d2590bd615376141fbebd2d + languageName: node + linkType: hard + "@isaacs/cliui@npm:^8.0.2": version: 8.0.2 resolution: "@isaacs/cliui@npm:8.0.2" @@ -2045,6 +2069,13 @@ __metadata: languageName: node linkType: hard +"@jest/diff-sequences@npm:30.0.1": + version: 30.0.1 + resolution: "@jest/diff-sequences@npm:30.0.1" + checksum: 10/0ddb7c7ba92d6057a2ee51a9cfc2155b77cca707fe959167466ea02dcb0687018cc3c22b9622f25f3a417d6ad370e2d4dcfedf9f1410dc9c02954a7484423cc7 + languageName: node + linkType: hard + "@jest/environment@npm:^27.5.1": version: 27.5.1 resolution: "@jest/environment@npm:27.5.1" @@ -2057,12 +2088,12 @@ __metadata: languageName: node linkType: hard -"@jest/expect-utils@npm:^29.7.0": - version: 29.7.0 - resolution: "@jest/expect-utils@npm:29.7.0" +"@jest/expect-utils@npm:30.2.0": + version: 30.2.0 + resolution: "@jest/expect-utils@npm:30.2.0" dependencies: - jest-get-type: "npm:^29.6.3" - checksum: 10/ef8d379778ef574a17bde2801a6f4469f8022a46a5f9e385191dc73bb1fc318996beaed4513fbd7055c2847227a1bed2469977821866534593a6e52a281499ee + "@jest/get-type": "npm:30.1.0" + checksum: 10/f2442f1bceb3411240d0f16fd0074377211b4373d3b8b2dc28929e861b6527a6deb403a362c25afa511d933cda4dfbdc98d4a08eeb51ee4968f7cb0299562349 languageName: node linkType: hard @@ -2080,6 +2111,13 @@ __metadata: languageName: node linkType: hard +"@jest/get-type@npm:30.1.0": + version: 30.1.0 + resolution: "@jest/get-type@npm:30.1.0" + checksum: 10/e2a95fbb49ce2d15547db8af5602626caf9b05f62a5e583b4a2de9bd93a2bfe7175f9bbb2b8a5c3909ce261d467b6991d7265bb1d547cb60e7e97f571f361a70 + languageName: node + linkType: hard + "@jest/globals@npm:^27.5.1": version: 27.5.1 resolution: "@jest/globals@npm:27.5.1" @@ -2091,6 +2129,16 @@ __metadata: languageName: node linkType: hard +"@jest/pattern@npm:30.0.1": + version: 30.0.1 + resolution: "@jest/pattern@npm:30.0.1" + dependencies: + "@types/node": "npm:*" + jest-regex-util: "npm:30.0.1" + checksum: 10/afd03b4d3eadc9c9970cf924955dee47984a7e767901fe6fa463b17b246f0ddeec07b3e82c09715c54bde3c8abb92074160c0d79967bd23778724f184e7f5b7b + languageName: node + linkType: hard + "@jest/reporters@npm:^27.5.1": version: 27.5.1 resolution: "@jest/reporters@npm:27.5.1" @@ -2129,6 +2177,15 @@ __metadata: languageName: node linkType: hard +"@jest/schemas@npm:30.0.5": + version: 30.0.5 + resolution: "@jest/schemas@npm:30.0.5" + dependencies: + "@sinclair/typebox": "npm:^0.34.0" + checksum: 10/40df4db55d4aeed09d1c7e19caf23788309cea34490a1c5d584c913494195e698b9967e996afc27226cac6d76e7512fe73ae6b9584480695c60dd18a5459cdba + languageName: node + linkType: hard + "@jest/schemas@npm:^29.6.3": version: 29.6.3 resolution: "@jest/schemas@npm:29.6.3" @@ -2219,6 +2276,21 @@ __metadata: languageName: node linkType: hard +"@jest/types@npm:30.2.0": + version: 30.2.0 + resolution: "@jest/types@npm:30.2.0" + dependencies: + "@jest/pattern": "npm:30.0.1" + "@jest/schemas": "npm:30.0.5" + "@types/istanbul-lib-coverage": "npm:^2.0.6" + "@types/istanbul-reports": "npm:^3.0.4" + "@types/node": "npm:*" + "@types/yargs": "npm:^17.0.33" + chalk: "npm:^4.1.2" + checksum: 10/f50fcaea56f873a51d19254ab16762f2ea8ca88e3e08da2e496af5da2b67c322915a4fcd0153803cc05063ffe87ebef2ab4330e0a1b06ab984a26c916cbfc26b + languageName: node + linkType: hard + "@jest/types@npm:^26.6.2": version: 26.6.2 resolution: "@jest/types@npm:26.6.2" @@ -2259,14 +2331,23 @@ __metadata: languageName: node linkType: hard -"@jridgewell/gen-mapping@npm:^0.3.5": - version: 0.3.5 - resolution: "@jridgewell/gen-mapping@npm:0.3.5" +"@jridgewell/gen-mapping@npm:^0.3.12, @jridgewell/gen-mapping@npm:^0.3.5": + version: 0.3.13 + resolution: "@jridgewell/gen-mapping@npm:0.3.13" dependencies: - "@jridgewell/set-array": "npm:^1.2.1" - "@jridgewell/sourcemap-codec": "npm:^1.4.10" + "@jridgewell/sourcemap-codec": "npm:^1.5.0" + "@jridgewell/trace-mapping": "npm:^0.3.24" + checksum: 10/902f8261dcf450b4af7b93f9656918e02eec80a2169e155000cb2059f90113dd98f3ccf6efc6072cee1dd84cac48cade51da236972d942babc40e4c23da4d62a + languageName: node + linkType: hard + +"@jridgewell/remapping@npm:^2.3.5": + version: 2.3.5 + resolution: "@jridgewell/remapping@npm:2.3.5" + dependencies: + "@jridgewell/gen-mapping": "npm:^0.3.5" "@jridgewell/trace-mapping": "npm:^0.3.24" - checksum: 10/81587b3c4dd8e6c60252122937cea0c637486311f4ed208b52b62aae2e7a87598f63ec330e6cd0984af494bfb16d3f0d60d3b21d7e5b4aedd2602ff3fe9d32e2 + checksum: 10/c2bb01856e65b506d439455f28aceacf130d6c023d1d4e3b48705e88def3571753e1a887daa04b078b562316c92d26ce36408a60534bceca3f830aec88a339ad languageName: node linkType: hard @@ -2277,27 +2358,20 @@ __metadata: languageName: node linkType: hard -"@jridgewell/set-array@npm:^1.2.1": - version: 1.2.1 - resolution: "@jridgewell/set-array@npm:1.2.1" - checksum: 10/832e513a85a588f8ed4f27d1279420d8547743cc37fcad5a5a76fc74bb895b013dfe614d0eed9cb860048e6546b798f8f2652020b4b2ba0561b05caa8c654b10 - languageName: node - linkType: hard - -"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.5.0": - version: 1.5.0 - resolution: "@jridgewell/sourcemap-codec@npm:1.5.0" - checksum: 10/4ed6123217569a1484419ac53f6ea0d9f3b57e5b57ab30d7c267bdb27792a27eb0e4b08e84a2680aa55cc2f2b411ffd6ec3db01c44fdc6dc43aca4b55f8374fd +"@jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.5.0, @jridgewell/sourcemap-codec@npm:^1.5.5": + version: 1.5.5 + resolution: "@jridgewell/sourcemap-codec@npm:1.5.5" + checksum: 10/5d9d207b462c11e322d71911e55e21a4e2772f71ffe8d6f1221b8eb5ae6774458c1d242f897fb0814e8714ca9a6b498abfa74dfe4f434493342902b1a48b33a5 languageName: node linkType: hard -"@jridgewell/trace-mapping@npm:^0.3.18, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25": - version: 0.3.25 - resolution: "@jridgewell/trace-mapping@npm:0.3.25" +"@jridgewell/trace-mapping@npm:^0.3.18, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.28": + version: 0.3.31 + resolution: "@jridgewell/trace-mapping@npm:0.3.31" dependencies: "@jridgewell/resolve-uri": "npm:^3.1.0" "@jridgewell/sourcemap-codec": "npm:^1.4.14" - checksum: 10/dced32160a44b49d531b80a4a2159dceab6b3ddf0c8e95a0deae4b0e894b172defa63d5ac52a19c2068e1fe7d31ea4ba931fbeec103233ecb4208953967120fc + checksum: 10/da0283270e691bdb5543806077548532791608e52386cfbbf3b9e8fb00457859d1bd01d512851161c886eb3a2f3ce6fd9bcf25db8edf3bddedd275bd4a88d606 languageName: node linkType: hard @@ -2327,9 +2401,9 @@ __metadata: linkType: hard "@json-schema-tools/meta-schema@npm:^1.7.5": - version: 1.7.5 - resolution: "@json-schema-tools/meta-schema@npm:1.7.5" - checksum: 10/707dc3a285c26c37d00f418e9d0ef8a2ad1c23d4936ad5aab0ce94c9ae36a7a6125c4ca5048513af64b7e6e527b5472a1701d1f709c379acdd7ad12f6409d2cd + version: 1.8.0 + resolution: "@json-schema-tools/meta-schema@npm:1.8.0" + checksum: 10/c6c9c3e6504299126c65bcf4bb7e6d28bfe5ab46d3c4fdc9b856204581edb0f088b15e790759e6357e91468d8a5213192fbe9b027a4811b988c19bbbb8d8f617 languageName: node linkType: hard @@ -2344,44 +2418,43 @@ __metadata: linkType: hard "@json-schema-tools/traverse@npm:^1.10.4": - version: 1.10.4 - resolution: "@json-schema-tools/traverse@npm:1.10.4" - checksum: 10/0027bc90df01c5eeee0833e722b7320b53be8b5ce3f4e0e4a6e45713a38e6f88f21aba31e3dd973093ef75cd21a40c07fe8f112da8f49a7919b1c0e44c904d20 + version: 1.11.0 + resolution: "@json-schema-tools/traverse@npm:1.11.0" + checksum: 10/1dd81baf29fd6de164f30376d2b9ca9e68778255a872dd78f81cf6f610127e9f4eba2507244c35189078839ed4aa453a876c169681eb9028954c0148355c2fcb languageName: node linkType: hard -"@lavamoat/aa@npm:^4.3.0": - version: 4.3.0 - resolution: "@lavamoat/aa@npm:4.3.0" +"@lavamoat/aa@npm:^4.3.5": + version: 4.3.5 + resolution: "@lavamoat/aa@npm:4.3.5" dependencies: - resolve: "npm:1.22.8" + resolve: "npm:1.22.10" bin: lavamoat-ls: src/cli.js - checksum: 10/c6c24ea88194ad06a83cc2a9e0b6918ee41ab40abcc5c889e1a33f214e48eb160dd0c4cea7b0e299f86d472810ef80e7caf0b2600499222b108690516d9f8123 + checksum: 10/253140c38b25455df8c64f236c8fb97db9406bacc9518f9282ddf593dd9c7ae61aa59ccdeb70bd47e68acb24ed902cf700f215e0acf86b7ac3278490932d5a75 languageName: node linkType: hard "@lavamoat/allow-scripts@npm:^3.0.4": - version: 3.2.0 - resolution: "@lavamoat/allow-scripts@npm:3.2.0" + version: 3.4.2 + resolution: "@lavamoat/allow-scripts@npm:3.4.2" dependencies: - "@lavamoat/aa": "npm:^4.3.0" - "@npmcli/run-script": "npm:8.1.0" + "@lavamoat/aa": "npm:^4.3.5" + "@npmcli/run-script": "npm:10.0.3" bin-links: "npm:4.0.4" npm-normalize-package-bin: "npm:3.0.1" + type-fest: "npm:4.41.0" yargs: "npm:17.7.2" - peerDependencies: - "@lavamoat/preinstall-always-fail": "*" bin: allow-scripts: src/cli.js - checksum: 10/21afb11ce25c0b2c9763bfb8f1127bb89f304ed83f64e00955c4d3007216a0ee553b777359e9ded874c61b3d7fa8d19ff8a35881cd3816985adab4d6b58bcb07 + checksum: 10/99a408f2d85362b2b2804b921c6c04738a41ac1836937ea624d42bd788465ba678b9d02b5df63d97794f1bb41f77e304cda12889e9a8686575c2e2fe95381d0f languageName: node linkType: hard "@lavamoat/preinstall-always-fail@npm:^2.1.0": - version: 2.1.0 - resolution: "@lavamoat/preinstall-always-fail@npm:2.1.0" - checksum: 10/385c3fac828b9edff2d8b5825bd29ea475206046984cdb3217518ad655f145ff37046414041534960d92cbe0759f0dc675f7c7dcf39a95003ae715a834fbd750 + version: 2.1.1 + resolution: "@lavamoat/preinstall-always-fail@npm:2.1.1" + checksum: 10/679cfd6b981326bf6f7cce63af4062b1e1e2ffaefd4db316e918ec41ac089c835aafd7f2bb5193cd25538e084d3df1375cd2ac5a52c3e7777aedeb2ee507dd29 languageName: node linkType: hard @@ -2758,8 +2831,8 @@ __metadata: linkType: hard "@metamask/auto-changelog@npm:^4.0.0": - version: 4.0.0 - resolution: "@metamask/auto-changelog@npm:4.0.0" + version: 4.1.0 + resolution: "@metamask/auto-changelog@npm:4.1.0" dependencies: diff: "npm:^5.0.0" execa: "npm:^5.1.1" @@ -2769,7 +2842,7 @@ __metadata: prettier: ">=3.0.0" bin: auto-changelog: dist/cli.js - checksum: 10/4968d316411e5f4820092391f79078839f49e0e26ecd0c48266b5a1e0e32614b75dad5f36b76e632a7a22a2f2eeeb762a693ae390b0373bff29081ff2a7eefda + checksum: 10/fe31a9eb364939c83bc5098482b761ca93593081680c4cba17b221150b4d32636cb25fd708e3692c198feddc95d8bcf524e19fa93567fb5aa30b03ea93249250 languageName: node linkType: hard @@ -2976,6 +3049,19 @@ __metadata: "@metamask/network-controller": "workspace:*" "@metamask/polling-controller": "npm:^16.0.0" "@metamask/remote-feature-flag-controller": "workspace:*" + "@ts-bridge/cli": "npm:^0.6.4" + "@types/jest": "npm:^27.4.1" + deepmerge: "npm:^4.2.2" + jest: "npm:^27.5.1" + nock: "npm:^13.3.1" + sinon: "npm:^9.2.4" + ts-jest: "npm:^27.1.4" + typedoc: "npm:^0.24.8" + typedoc-plugin-missing-exports: "npm:^2.0.0" + typescript: "npm:~5.3.3" + languageName: unknown + linkType: soft + "@metamask/connectivity-controller@npm:^0.1.0, @metamask/connectivity-controller@workspace:packages/connectivity-controller": version: 0.0.0-use.local resolution: "@metamask/connectivity-controller@workspace:packages/connectivity-controller" @@ -2987,8 +3073,6 @@ __metadata: "@types/jest": "npm:^27.4.1" deepmerge: "npm:^4.2.2" jest: "npm:^27.5.1" - nock: "npm:^13.3.1" - sinon: "npm:^9.2.4" ts-jest: "npm:^27.1.4" typedoc: "npm:^0.24.8" typedoc-plugin-missing-exports: "npm:^2.0.0" @@ -3003,7 +3087,7 @@ __metadata: languageName: node linkType: hard -"@metamask/controller-utils@npm:^11.15.0, @metamask/controller-utils@npm:^11.18.0, @metamask/controller-utils@workspace:packages/controller-utils": +"@metamask/controller-utils@npm:^11.16.0, @metamask/controller-utils@npm:^11.18.0, @metamask/controller-utils@workspace:packages/controller-utils": version: 0.0.0-use.local resolution: "@metamask/controller-utils@workspace:packages/controller-utils" dependencies: @@ -3551,15 +3635,15 @@ __metadata: linkType: hard "@metamask/eth-snap-keyring@npm:^18.0.0": - version: 18.0.0 - resolution: "@metamask/eth-snap-keyring@npm:18.0.0" + version: 18.0.2 + resolution: "@metamask/eth-snap-keyring@npm:18.0.2" dependencies: "@ethereumjs/tx": "npm:^5.4.0" "@metamask/eth-sig-util": "npm:^8.2.0" - "@metamask/keyring-api": "npm:^21.1.0" - "@metamask/keyring-internal-api": "npm:^9.1.0" - "@metamask/keyring-internal-snap-client": "npm:^8.0.0" - "@metamask/keyring-snap-sdk": "npm:^7.1.0" + "@metamask/keyring-api": "npm:^21.2.0" + "@metamask/keyring-internal-api": "npm:^9.1.1" + "@metamask/keyring-internal-snap-client": "npm:^8.0.1" + "@metamask/keyring-snap-sdk": "npm:^7.1.1" "@metamask/keyring-utils": "npm:^3.1.0" "@metamask/messenger": "npm:^0.3.0" "@metamask/superstruct": "npm:^3.1.0" @@ -3567,8 +3651,8 @@ __metadata: "@types/uuid": "npm:^9.0.8" uuid: "npm:^9.0.1" peerDependencies: - "@metamask/keyring-api": ^21.1.0 - checksum: 10/39a6380e351997e53776c8db9d1558769517a1a12ec1431c40cedb516d90ae447a81b7b1c21bc8d8ffcbc31188cf52f17057a1416d509013cfe8b2f46b314e02 + "@metamask/keyring-api": ^21.2.0 + checksum: 10/2c37e55cf4b56089fb5a081d3809b9004b8bbe2822267fbe5b8884cd687da4a43e122b053ebbc418173353232066a4763edc90002f51ce55a84e53a7009c16e6 languageName: node linkType: hard @@ -3867,15 +3951,15 @@ __metadata: languageName: node linkType: hard -"@metamask/keyring-api@npm:^21.0.0, @metamask/keyring-api@npm:^21.1.0": - version: 21.1.0 - resolution: "@metamask/keyring-api@npm:21.1.0" +"@metamask/keyring-api@npm:^21.0.0, @metamask/keyring-api@npm:^21.2.0": + version: 21.3.0 + resolution: "@metamask/keyring-api@npm:21.3.0" dependencies: "@metamask/keyring-utils": "npm:^3.1.0" "@metamask/superstruct": "npm:^3.1.0" "@metamask/utils": "npm:^11.1.0" bitcoin-address-validation: "npm:^2.2.3" - checksum: 10/3371a5ab0e9ba0e9b23b30b03a7d83d029e223def5485ab1aa2ec793ba18ff3738422dbe3c47f9cf82411d2ca6ca918928bf998741f0977055071b7bf3042314 + checksum: 10/5d1f2705d76d8cfc70378f740e054fca163735b7b77b86b092cfd311d1befb27fac16f81b210ef2c719ce32010e1db55916b7b78d1f7a84239e47b771e5d84cc languageName: node linkType: hard @@ -3919,35 +4003,35 @@ __metadata: languageName: unknown linkType: soft -"@metamask/keyring-internal-api@npm:^9.0.0, @metamask/keyring-internal-api@npm:^9.1.0": - version: 9.1.0 - resolution: "@metamask/keyring-internal-api@npm:9.1.0" +"@metamask/keyring-internal-api@npm:^9.0.0, @metamask/keyring-internal-api@npm:^9.1.1": + version: 9.1.1 + resolution: "@metamask/keyring-internal-api@npm:9.1.1" dependencies: - "@metamask/keyring-api": "npm:^21.1.0" + "@metamask/keyring-api": "npm:^21.2.0" "@metamask/keyring-utils": "npm:^3.1.0" "@metamask/superstruct": "npm:^3.1.0" - checksum: 10/6b19f35f57bc1b5dc73957d7f3185236780c93e6292678e22d84f9eb2fe92e15a98437a9bc4fbe5e5e10143d4db36afa2c420636f2cca4bd984e8455ca4332c6 + checksum: 10/ab0fb8e153a02d3d0acf739d77356a1c60e0a7bf998dcbba9468f9f231605beaed472d8bff27dc56323d0a2529167336499e23dcad911fa8c3e37999ed14d2d1 languageName: node linkType: hard -"@metamask/keyring-internal-snap-client@npm:^8.0.0": - version: 8.0.0 - resolution: "@metamask/keyring-internal-snap-client@npm:8.0.0" +"@metamask/keyring-internal-snap-client@npm:^8.0.1": + version: 8.0.1 + resolution: "@metamask/keyring-internal-snap-client@npm:8.0.1" dependencies: - "@metamask/keyring-api": "npm:^21.1.0" - "@metamask/keyring-internal-api": "npm:^9.1.0" - "@metamask/keyring-snap-client": "npm:^8.1.0" + "@metamask/keyring-api": "npm:^21.2.0" + "@metamask/keyring-internal-api": "npm:^9.1.1" + "@metamask/keyring-snap-client": "npm:^8.1.1" "@metamask/keyring-utils": "npm:^3.1.0" "@metamask/messenger": "npm:^0.3.0" - checksum: 10/7a4aa08ac6ac1bda064182420af01b785aaaff37068d14577007ce40e53f4da33b3bbc1a18625ebd75cee6d08c34de8dc860e6c927477335d5f1df72328b563a + checksum: 10/40a686cd3d1f49accde83bb2a983ac9e897498e1de5a0ccb0768e382d44dd4c273230db95bcd6eace4ad8a184e7ab4fc780770f617994a2ca29b4302890f31b6 languageName: node linkType: hard -"@metamask/keyring-snap-client@npm:^8.0.0, @metamask/keyring-snap-client@npm:^8.1.0": - version: 8.1.0 - resolution: "@metamask/keyring-snap-client@npm:8.1.0" +"@metamask/keyring-snap-client@npm:^8.0.0, @metamask/keyring-snap-client@npm:^8.1.1": + version: 8.1.1 + resolution: "@metamask/keyring-snap-client@npm:8.1.1" dependencies: - "@metamask/keyring-api": "npm:^21.1.0" + "@metamask/keyring-api": "npm:^21.2.0" "@metamask/keyring-utils": "npm:^3.1.0" "@metamask/superstruct": "npm:^3.1.0" "@types/uuid": "npm:^9.0.8" @@ -3955,13 +4039,13 @@ __metadata: webextension-polyfill: "npm:^0.12.0" peerDependencies: "@metamask/providers": ^19.0.0 - checksum: 10/e92aa7f6e1454150870e8e0a6d9cf4fac7bbc22280d85a252ca7ee428842dfbaaaccae78dfc5ad773e21d757febfcbe6933a72b966c4478f1a2b3fc0088419a1 + checksum: 10/dcdc9a286137a4ae884b709e565b988fb2e555a8a80db5d2ed3e93ee5262c81567a4efac6ff663b6751caf5b1173f92bc8437a395696058018a3b6e93fc30b35 languageName: node linkType: hard -"@metamask/keyring-snap-sdk@npm:^7.1.0": - version: 7.1.0 - resolution: "@metamask/keyring-snap-sdk@npm:7.1.0" +"@metamask/keyring-snap-sdk@npm:^7.1.1": + version: 7.1.1 + resolution: "@metamask/keyring-snap-sdk@npm:7.1.1" dependencies: "@metamask/keyring-utils": "npm:^3.1.0" "@metamask/snaps-sdk": "npm:^9.0.0" @@ -3969,9 +4053,9 @@ __metadata: "@metamask/utils": "npm:^11.1.0" webextension-polyfill: "npm:^0.12.0" peerDependencies: - "@metamask/keyring-api": ^21.1.0 + "@metamask/keyring-api": ^21.2.0 "@metamask/providers": ^19.0.0 - checksum: 10/1a1809733c1f21af87f3491d292c499c5441afa0780e848718ec2b6aff50d76bb03ea44ee93ecaa80d79453a98926d84cd13ff406256ab6a2136d9e31250faa8 + checksum: 10/ac4ce050f4647096ef66ebd04d99d1423c002ca0fb05bd83e11caec59754b56d73bb8a95ac3a76f64472713256205e889d6785003dfe2c35f5f1d67c2f2efd12 languageName: node linkType: hard @@ -4214,7 +4298,7 @@ __metadata: languageName: unknown linkType: soft -"@metamask/network-controller@npm:^29.0.0, @metamask/network-controller@workspace:packages/network-controller": +"@metamask/network-controller@npm:^29.0.0, @metamask/network-controller@workspace:*, @metamask/network-controller@workspace:packages/network-controller": version: 0.0.0-use.local resolution: "@metamask/network-controller@workspace:packages/network-controller" dependencies: @@ -4290,14 +4374,12 @@ __metadata: linkType: soft "@metamask/nonce-tracker@npm:^6.0.0": - version: 6.0.0 - resolution: "@metamask/nonce-tracker@npm:6.0.0" + version: 6.1.0 + resolution: "@metamask/nonce-tracker@npm:6.1.0" dependencies: "@ethersproject/providers": "npm:^5.7.2" - async-mutex: "npm:^0.3.1" - peerDependencies: - "@metamask/eth-block-tracker": ">=9" - checksum: 10/e62edd38eeaba6d917bc3aed38017294f2bfdb59120a9fb4f093fe96a46d8d9214453a802fe782faaf4a007f4cd5f393607c70a2ff8479ecd7ef18827cad067a + async-mutex: "npm:^0.5.0" + checksum: 10/a20cf7084348ef7bdcd9e57e873ca34bf8e04ee43a2ab08634a3ad47fddb632d0e170c1dff03b4ca5bac34a24c35c542fcec509f3c23ce483834082f41b50e4a languageName: node linkType: hard @@ -4356,7 +4438,7 @@ __metadata: languageName: node linkType: hard -"@metamask/permission-controller@npm:^12.1.0, @metamask/permission-controller@npm:^12.1.1, @metamask/permission-controller@npm:^12.2.0, @metamask/permission-controller@workspace:packages/permission-controller": +"@metamask/permission-controller@npm:^12.1.0, @metamask/permission-controller@npm:^12.2.0, @metamask/permission-controller@workspace:packages/permission-controller": version: 0.0.0-use.local resolution: "@metamask/permission-controller@workspace:packages/permission-controller" dependencies: @@ -4426,24 +4508,6 @@ __metadata: languageName: unknown linkType: soft -"@metamask/phishing-controller@npm:^15.0.0": - version: 15.0.1 - resolution: "@metamask/phishing-controller@npm:15.0.1" - dependencies: - "@metamask/base-controller": "npm:^9.0.0" - "@metamask/controller-utils": "npm:^11.15.0" - "@metamask/messenger": "npm:^0.3.0" - "@noble/hashes": "npm:^1.8.0" - "@types/punycode": "npm:^2.1.0" - ethereum-cryptography: "npm:^2.1.2" - fastest-levenshtein: "npm:^1.0.16" - punycode: "npm:^2.1.1" - peerDependencies: - "@metamask/transaction-controller": ^61.0.0 - checksum: 10/2f3bc2946f8231256c4a17af8369637f9fc4e3beef31b30b45372059e899fedfa22261cf7b526db62fe607e752e74c63de4a0dea6bd811fae046aa677e4929d0 - languageName: node - linkType: hard - "@metamask/phishing-controller@npm:^16.1.0, @metamask/phishing-controller@workspace:packages/phishing-controller": version: 0.0.0-use.local resolution: "@metamask/phishing-controller@workspace:packages/phishing-controller" @@ -4471,7 +4535,7 @@ __metadata: languageName: unknown linkType: soft -"@metamask/polling-controller@npm:^16.0.2, @metamask/polling-controller@workspace:packages/polling-controller": +"@metamask/polling-controller@npm:^16.0.0, @metamask/polling-controller@npm:^16.0.2, @metamask/polling-controller@workspace:packages/polling-controller": version: 0.0.0-use.local resolution: "@metamask/polling-controller@workspace:packages/polling-controller" dependencies: @@ -4661,7 +4725,7 @@ __metadata: languageName: unknown linkType: soft -"@metamask/remote-feature-flag-controller@npm:^4.0.0, @metamask/remote-feature-flag-controller@workspace:packages/remote-feature-flag-controller": +"@metamask/remote-feature-flag-controller@npm:^4.0.0, @metamask/remote-feature-flag-controller@workspace:*, @metamask/remote-feature-flag-controller@workspace:packages/remote-feature-flag-controller": version: 0.0.0-use.local resolution: "@metamask/remote-feature-flag-controller@workspace:packages/remote-feature-flag-controller" dependencies: @@ -4695,9 +4759,9 @@ __metadata: linkType: hard "@metamask/safe-event-emitter@npm:^3.0.0, @metamask/safe-event-emitter@npm:^3.1.1": - version: 3.1.1 - resolution: "@metamask/safe-event-emitter@npm:3.1.1" - checksum: 10/e24db4d7c20764bfc5b025065f92518c805f0ffb1da4820078b8cff7dcae964c0f354cf053fcb7ac659de015d5ffdf21aae5e8d44e191ee8faa9066855f22653 + version: 3.1.2 + resolution: "@metamask/safe-event-emitter@npm:3.1.2" + checksum: 10/8ef7579f9317eb5c94ecf3e6abb8d13b119af274b678805eac76abe4c0667bfdf539f385e552bb973e96333b71b77aa7c787cb3fce9cd5fb4b00f1dbbabf880d languageName: node linkType: hard @@ -4860,8 +4924,8 @@ __metadata: linkType: hard "@metamask/snaps-controllers@npm:^17.2.0": - version: 17.2.0 - resolution: "@metamask/snaps-controllers@npm:17.2.0" + version: 17.2.1 + resolution: "@metamask/snaps-controllers@npm:17.2.1" dependencies: "@metamask/approval-controller": "npm:^8.0.0" "@metamask/base-controller": "npm:^9.0.0" @@ -4870,16 +4934,16 @@ __metadata: "@metamask/key-tree": "npm:^10.1.1" "@metamask/messenger": "npm:^0.3.0" "@metamask/object-multiplex": "npm:^2.1.0" - "@metamask/permission-controller": "npm:^12.1.1" - "@metamask/phishing-controller": "npm:^15.0.0" + "@metamask/permission-controller": "npm:^12.2.0" + "@metamask/phishing-controller": "npm:^16.1.0" "@metamask/post-message-stream": "npm:^10.0.0" "@metamask/rpc-errors": "npm:^7.0.3" "@metamask/snaps-registry": "npm:^4.0.0" "@metamask/snaps-rpc-methods": "npm:^14.1.1" "@metamask/snaps-sdk": "npm:^10.3.0" - "@metamask/snaps-utils": "npm:^11.7.0" + "@metamask/snaps-utils": "npm:^11.7.1" "@metamask/superstruct": "npm:^3.2.1" - "@metamask/utils": "npm:^11.8.1" + "@metamask/utils": "npm:^11.9.0" "@xstate/fsm": "npm:^2.0.0" async-mutex: "npm:^0.5.0" concat-stream: "npm:^2.0.0" @@ -4898,7 +4962,7 @@ __metadata: peerDependenciesMeta: "@metamask/snaps-execution-environments": optional: true - checksum: 10/03bfdf0fd7aa11e20b8d1d60cc4a8216175ceb18fb9edb85a313a2ebeb07b5f81059879951551396683862d00d6f368b001f996824db681e9315d6614cf1122f + checksum: 10/867f23054e2c08c0ca67d35a6853a1700ac7f0bab3f7d17b3dbcd10f0043331a5063a6086fa787ee4cb8dfebd4ec54ee9bbfdd1a2b6d7ac75ba31ce2d0957f89 languageName: node linkType: hard @@ -4946,34 +5010,33 @@ __metadata: linkType: hard "@metamask/snaps-sdk@npm:^9.0.0": - version: 9.0.0 - resolution: "@metamask/snaps-sdk@npm:9.0.0" + version: 9.3.0 + resolution: "@metamask/snaps-sdk@npm:9.3.0" dependencies: "@metamask/key-tree": "npm:^10.1.1" "@metamask/providers": "npm:^22.1.0" - "@metamask/rpc-errors": "npm:^7.0.2" + "@metamask/rpc-errors": "npm:^7.0.3" "@metamask/superstruct": "npm:^3.2.1" - "@metamask/utils": "npm:^11.4.0" - checksum: 10/a71e0f748109b6624bdb3cb572067500caa159caf71d2e673bb9e931b284334284581cc09db71c0d35e9537cfb0dba7e3beb2011a20c954263c5b9d751360495 + "@metamask/utils": "npm:^11.4.2" + checksum: 10/1e84195a568553d1d7929b9140469204611d2504ab5bc63a6bdad7edc70150765795d402d6d8263bc8d665f9d6656e60da64e4530c240287d8d9ae51cf6d2843 languageName: node linkType: hard -"@metamask/snaps-utils@npm:^11.6.1, @metamask/snaps-utils@npm:^11.7.0": - version: 11.7.0 - resolution: "@metamask/snaps-utils@npm:11.7.0" +"@metamask/snaps-utils@npm:^11.6.1, @metamask/snaps-utils@npm:^11.7.0, @metamask/snaps-utils@npm:^11.7.1": + version: 11.7.1 + resolution: "@metamask/snaps-utils@npm:11.7.1" dependencies: "@babel/core": "npm:^7.23.2" "@babel/types": "npm:^7.23.0" "@metamask/key-tree": "npm:^10.1.1" "@metamask/messenger": "npm:^0.3.0" - "@metamask/permission-controller": "npm:^12.1.1" + "@metamask/permission-controller": "npm:^12.2.0" "@metamask/rpc-errors": "npm:^7.0.3" "@metamask/slip44": "npm:^4.3.0" "@metamask/snaps-registry": "npm:^4.0.0" "@metamask/snaps-sdk": "npm:^10.3.0" "@metamask/superstruct": "npm:^3.2.1" - "@metamask/utils": "npm:^11.8.1" - "@noble/hashes": "npm:^1.7.1" + "@metamask/utils": "npm:^11.9.0" "@scure/base": "npm:^1.1.1" chalk: "npm:^4.1.2" cron-parser: "npm:^4.5.0" @@ -4986,14 +5049,14 @@ __metadata: semver: "npm:^7.5.4" ses: "npm:^1.14.0" validate-npm-package-name: "npm:^5.0.0" - checksum: 10/015102a678e3bc4a6609f29d6818dc47d6c70a798c52d7fde2cc030fa32d7978bd7f7cad18dc4e64be7ef02e2bf6a8dd4419064c0eb3e9eb80a77d0166d147dc + checksum: 10/4f1ebf14df5eef4344aef8367923176b02f68c58a76c2776aef3015e36f1f889f6463a6b991c78e5810424cf117e20972511a12fcc3436839b0f6100cbb8f09e languageName: node linkType: hard "@metamask/stake-sdk@npm:^3.2.1": - version: 3.2.1 - resolution: "@metamask/stake-sdk@npm:3.2.1" - checksum: 10/7404ac54e2bd426158b0ae92a2f4c420ef551d18d8a14293c5760b1da1c48cab88df9a7dcce7133f91bbe7899f6c2016642f0e41e170353b6b9ae4c6423d2ad5 + version: 3.4.0 + resolution: "@metamask/stake-sdk@npm:3.4.0" + checksum: 10/32241bf7a904b0b12568467482b28f550eae1a4d97ffb7487a1cd1614d43f3b584d78dc96df72ece024a0402d3591c19d79f370a3955ea4b11369f000c309a08 languageName: node linkType: hard @@ -5253,6 +5316,17 @@ __metadata: languageName: node linkType: hard +"@napi-rs/wasm-runtime@npm:^0.2.11": + version: 0.2.12 + resolution: "@napi-rs/wasm-runtime@npm:0.2.12" + dependencies: + "@emnapi/core": "npm:^1.4.3" + "@emnapi/runtime": "npm:^1.4.3" + "@tybys/wasm-util": "npm:^0.10.0" + checksum: 10/5fd518182427980c28bc724adf06c5f32f9a8915763ef560b5f7d73607d30cd15ac86d0cbd2eb80d4cfab23fc80d0876d89ca36a9daadcb864bc00917c94187c + languageName: node + linkType: hard + "@noble/ciphers@npm:^1.2.1, @noble/ciphers@npm:^1.3.0": version: 1.3.0 resolution: "@noble/ciphers@npm:1.3.0" @@ -5279,11 +5353,11 @@ __metadata: linkType: hard "@noble/curves@npm:^1.2.0, @noble/curves@npm:^1.8.1, @noble/curves@npm:^1.9.2": - version: 1.9.2 - resolution: "@noble/curves@npm:1.9.2" + version: 1.9.7 + resolution: "@noble/curves@npm:1.9.7" dependencies: "@noble/hashes": "npm:1.8.0" - checksum: 10/f60f00ad86296054566b67be08fd659999bb64b692bfbf11dbe3be1f422ad4d826bf5ebb2015ce2e246538eab2b677707e0a46ffa8323a6fae7a9a30ec1fe318 + checksum: 10/3cfe2735ea94972988ca9e217e0ebb2044372a7160b2079bf885da789492a6291fc8bf76ca3d8bf8dee477847ee2d6fac267d1e6c4f555054059f5e8c4865d44 languageName: node linkType: hard @@ -5349,87 +5423,86 @@ __metadata: languageName: node linkType: hard -"@npmcli/agent@npm:^2.0.0": - version: 2.2.2 - resolution: "@npmcli/agent@npm:2.2.2" +"@npmcli/agent@npm:^4.0.0": + version: 4.0.0 + resolution: "@npmcli/agent@npm:4.0.0" dependencies: agent-base: "npm:^7.1.0" http-proxy-agent: "npm:^7.0.0" https-proxy-agent: "npm:^7.0.1" - lru-cache: "npm:^10.0.1" + lru-cache: "npm:^11.2.1" socks-proxy-agent: "npm:^8.0.3" - checksum: 10/96fc0036b101bae5032dc2a4cd832efb815ce9b33f9ee2f29909ee49d96a0026b3565f73c507a69eb8603f5cb32e0ae45a70cab1e2655990a4e06ae99f7f572a + checksum: 10/1a81573becc60515031accc696e6405e9b894e65c12b98ef4aeee03b5617c41948633159dbf6caf5dde5b47367eeb749bdc7b7dfb21960930a9060a935c6f636 languageName: node linkType: hard -"@npmcli/fs@npm:^3.1.0": - version: 3.1.1 - resolution: "@npmcli/fs@npm:3.1.1" +"@npmcli/fs@npm:^5.0.0": + version: 5.0.0 + resolution: "@npmcli/fs@npm:5.0.0" dependencies: semver: "npm:^7.3.5" - checksum: 10/1e0e04087049b24b38bc0b30d87a9388ee3ca1d3fdfc347c2f77d84fcfe6a51f250bc57ba2c1f614d7e4285c6c62bf8c769bc19aa0949ea39e5b043ee023b0bd + checksum: 10/4935c7719d17830d0f9fa46c50be17b2a3c945cec61760f6d0909bce47677c42e1810ca673305890f9e84f008ec4d8e841182f371e42100a8159d15f22249208 languageName: node linkType: hard -"@npmcli/git@npm:^5.0.0": - version: 5.0.8 - resolution: "@npmcli/git@npm:5.0.8" - dependencies: - "@npmcli/promise-spawn": "npm:^7.0.0" - ini: "npm:^4.1.3" - lru-cache: "npm:^10.0.1" - npm-pick-manifest: "npm:^9.0.0" - proc-log: "npm:^4.0.0" - promise-inflight: "npm:^1.0.1" +"@npmcli/git@npm:^7.0.0": + version: 7.0.1 + resolution: "@npmcli/git@npm:7.0.1" + dependencies: + "@npmcli/promise-spawn": "npm:^9.0.0" + ini: "npm:^6.0.0" + lru-cache: "npm:^11.2.1" + npm-pick-manifest: "npm:^11.0.1" + proc-log: "npm:^6.0.0" promise-retry: "npm:^2.0.1" semver: "npm:^7.3.5" - which: "npm:^4.0.0" - checksum: 10/e6f94175fb9dde13d84849b29b32ffb4c4df968822cc85df2aebfca13bf8ca76f33b1d281911f5bcddc95bccba2f9e795669c736a38de4d9c76efb5047ffb4fb + which: "npm:^6.0.0" + checksum: 10/dc2c7558fa034be6123b6a049091fd4fcdf79bf497ab8ff3213ac99e0c7a4f968e3cf747322af5d1d70e41ed21b8189f8e12d7b3f1a6143793d056dd8c8b50c5 languageName: node linkType: hard -"@npmcli/node-gyp@npm:^3.0.0": - version: 3.0.0 - resolution: "@npmcli/node-gyp@npm:3.0.0" - checksum: 10/dd9fed3e80df8fbb20443f28651a8ed7235f2c15286ecc010e2d3cd392c85912e59ef29218c0b02f098defb4cbc8cdf045aab1d32d5cef6ace289913196ed5df +"@npmcli/node-gyp@npm:^5.0.0": + version: 5.0.0 + resolution: "@npmcli/node-gyp@npm:5.0.0" + checksum: 10/31488b0a0a6293efc4ab1bd87ba483d1000f8720c5f068d4c28cf49e39a045cd122960ba2a166a376fc9767f457f6124d99ec673ebcb19015cd29835bb038e46 languageName: node linkType: hard -"@npmcli/package-json@npm:^5.0.0": - version: 5.2.0 - resolution: "@npmcli/package-json@npm:5.2.0" - dependencies: - "@npmcli/git": "npm:^5.0.0" - glob: "npm:^10.2.2" - hosted-git-info: "npm:^7.0.0" - json-parse-even-better-errors: "npm:^3.0.0" - normalize-package-data: "npm:^6.0.0" - proc-log: "npm:^4.0.0" +"@npmcli/package-json@npm:^7.0.0": + version: 7.0.4 + resolution: "@npmcli/package-json@npm:7.0.4" + dependencies: + "@npmcli/git": "npm:^7.0.0" + glob: "npm:^13.0.0" + hosted-git-info: "npm:^9.0.0" + json-parse-even-better-errors: "npm:^5.0.0" + proc-log: "npm:^6.0.0" semver: "npm:^7.5.3" - checksum: 10/c3d2218877bfc005bca3b7a11f53825bf16a68811b8e8ed0c9b219cceb8e8e646d70efab8c5d6decbd8007f286076468b3f456dab4d41d648aff73a5f3a6fce2 + validate-npm-package-license: "npm:^3.0.4" + checksum: 10/757b343c035dbf6831ecdde3503053bf5f26399768c9ab95e24bdd5518ef61d9e71e69fa9e99ff816b178dbc174db2826939b2654c48180ba1e0dccfb7f22f22 languageName: node linkType: hard -"@npmcli/promise-spawn@npm:^7.0.0": - version: 7.0.2 - resolution: "@npmcli/promise-spawn@npm:7.0.2" +"@npmcli/promise-spawn@npm:^9.0.0": + version: 9.0.1 + resolution: "@npmcli/promise-spawn@npm:9.0.1" dependencies: - which: "npm:^4.0.0" - checksum: 10/94cbbbeeb20342026c3b68fc8eb09e1600b7645d4e509f2588ef5ea7cff977eb01e628cc8e014595d04a6af4b4bc5c467c950a8135920f39f7c7b57fba43f4e9 + which: "npm:^6.0.0" + checksum: 10/93f539f12813dacf0084c5f444982d44c67f2016f417f2e937afb81c3fd228cf330abeabdffc95ca3e8315a4a9b9e732be7e7870c926d7dfc6c458549fcd11ea languageName: node linkType: hard -"@npmcli/run-script@npm:8.1.0": - version: 8.1.0 - resolution: "@npmcli/run-script@npm:8.1.0" +"@npmcli/run-script@npm:10.0.3": + version: 10.0.3 + resolution: "@npmcli/run-script@npm:10.0.3" dependencies: - "@npmcli/node-gyp": "npm:^3.0.0" - "@npmcli/package-json": "npm:^5.0.0" - "@npmcli/promise-spawn": "npm:^7.0.0" - node-gyp: "npm:^10.0.0" - proc-log: "npm:^4.0.0" - which: "npm:^4.0.0" - checksum: 10/256bd580f82b98db93e54065bf9bcc94946be4f2d668a062cf756cb8ea091f58ef7154b3d2450d79738081a150f25cc48f6075351911e672f24ffd34350f02f2 + "@npmcli/node-gyp": "npm:^5.0.0" + "@npmcli/package-json": "npm:^7.0.0" + "@npmcli/promise-spawn": "npm:^9.0.0" + node-gyp: "npm:^12.1.0" + proc-log: "npm:^6.0.0" + which: "npm:^6.0.0" + checksum: 10/3b2b6b02a40c7470a900e8d77d23e2239608c08e919d6ddee7849fc7093be0999d9eb2c9dec871988e80165a64f9d8c55430f0a699690e555ebd3e81bf1dbd35 languageName: node linkType: hard @@ -5441,20 +5514,28 @@ __metadata: linkType: hard "@open-rpc/schema-utils-js@npm:^2.0.5": - version: 2.0.5 - resolution: "@open-rpc/schema-utils-js@npm:2.0.5" + version: 2.1.2 + resolution: "@open-rpc/schema-utils-js@npm:2.1.2" dependencies: "@json-schema-tools/dereferencer": "npm:^1.6.3" "@json-schema-tools/meta-schema": "npm:^1.7.5" "@json-schema-tools/reference-resolver": "npm:^1.2.6" "@open-rpc/meta-schema": "npm:^1.14.9" + "@open-rpc/specification-extension-spec": "npm:^1.0.2" ajv: "npm:^6.10.0" detect-node: "npm:^2.0.4" fast-safe-stringify: "npm:^2.0.7" fs-extra: "npm:^10.1.0" is-url: "npm:^1.2.4" isomorphic-fetch: "npm:^3.0.0" - checksum: 10/9e10215606e9a00a47b082c9cfd70d05bf0d38de6cf1c147246c545c6997375d94cd3caafe919b71178df58b5facadfd0dcc8b6857bf5e79c40e5e33683dd3d5 + checksum: 10/0f38a403c696ee74319503cfba9656cdb2ff6dbd84dfba3c6ce5c3d010dfd72bc396bfb6dacf39de01d523ee7e3b0d5637657a48e5f2c7e74ae33b9354b2c4c1 + languageName: node + linkType: hard + +"@open-rpc/specification-extension-spec@npm:^1.0.2": + version: 1.0.2 + resolution: "@open-rpc/specification-extension-spec@npm:1.0.2" + checksum: 10/04111d8ce84deb45358c504b425f8d3e5c0b8991c739708b6b2662de665002da541fc7b39065d2394a9509866f580c3a5aaedc56b42c0d679fe6054eda034b9b languageName: node linkType: hard @@ -5465,10 +5546,10 @@ __metadata: languageName: node linkType: hard -"@pkgr/core@npm:^0.1.0": - version: 0.1.1 - resolution: "@pkgr/core@npm:0.1.1" - checksum: 10/6f25fd2e3008f259c77207ac9915b02f1628420403b2630c92a07ff963129238c9262afc9e84344c7a23b5cc1f3965e2cd17e3798219f5fd78a63d144d3cceba +"@pkgr/core@npm:^0.2.9": + version: 0.2.9 + resolution: "@pkgr/core@npm:0.2.9" + checksum: 10/bb2fb86977d63f836f8f5b09015d74e6af6488f7a411dcd2bfdca79d76b5a681a9112f41c45bdf88a9069f049718efc6f3900d7f1de66a2ec966068308ae517f languageName: node linkType: hard @@ -5545,10 +5626,17 @@ __metadata: languageName: node linkType: hard -"@scure/base@npm:^1.0.0, @scure/base@npm:^1.1.1, @scure/base@npm:^1.1.3, @scure/base@npm:~1.1.3, @scure/base@npm:~1.1.6": - version: 1.1.7 - resolution: "@scure/base@npm:1.1.7" - checksum: 10/fc50ffaab36cb46ff9fa4dc5052a06089ab6a6707f63d596bb34aaaec76173c9a564ac312a0b981b5e7a5349d60097b8878673c75d6cbfc4da7012b63a82099b +"@scure/base@npm:^1.0.0, @scure/base@npm:^1.1.1, @scure/base@npm:^1.1.3": + version: 1.2.6 + resolution: "@scure/base@npm:1.2.6" + checksum: 10/c1a7bd5e0b0c8f94c36fbc220f4a67cc832b00e2d2065c7d8a404ed81ab1c94c5443def6d361a70fc382db3496e9487fb9941728f0584782b274c18a4bed4187 + languageName: node + linkType: hard + +"@scure/base@npm:~1.1.3, @scure/base@npm:~1.1.6": + version: 1.1.9 + resolution: "@scure/base@npm:1.1.9" + checksum: 10/f0ab7f687bbcdee2a01377fe3cd808bf63977999672751295b6a92625d5322f4754a96d40f6bd579bc367aad48ecf8a4e6d0390e70296e6ded1076f52adb16bb languageName: node linkType: hard @@ -5574,9 +5662,9 @@ __metadata: linkType: hard "@sentry/core@npm:^9.10.0, @sentry/core@npm:^9.22.0": - version: 9.23.0 - resolution: "@sentry/core@npm:9.23.0" - checksum: 10/4ee771098d4ce4f4d2f7bd62cacb41ee2993780f4cab0eea600e73de3a3803cb953ac47ac015c23bcd7a9919e2220fd6cdc5a9a22a3663440296336d8df959b7 + version: 9.47.1 + resolution: "@sentry/core@npm:9.47.1" + checksum: 10/62cc2a0f45d89e3b78f083fe365007e59aed54e20b55ae5b45931cfa8e4d79d457c0c57450c6c7f92cec71fa682cd9cb3b64414fa86273f08cf3d8d06bd99c24 languageName: node linkType: hard @@ -5587,6 +5675,13 @@ __metadata: languageName: node linkType: hard +"@sinclair/typebox@npm:^0.34.0": + version: 0.34.47 + resolution: "@sinclair/typebox@npm:0.34.47" + checksum: 10/a7f279020ae45ce21636424ec6439f0e302c28196ed7d2cddf2f80899580cb454f07ce3a033a1aea7ecbcfe47cefd9801c7514bf3adaaecfd1b7d9c83ca3eb9f + languageName: node + linkType: hard + "@sinonjs/commons@npm:^1.6.0, @sinonjs/commons@npm:^1.7.0, @sinonjs/commons@npm:^1.8.1": version: 1.8.6 resolution: "@sinonjs/commons@npm:1.8.6" @@ -5633,78 +5728,88 @@ __metadata: linkType: hard "@solana/addresses@npm:^2.0.0": - version: 2.0.0 - resolution: "@solana/addresses@npm:2.0.0" + version: 2.3.0 + resolution: "@solana/addresses@npm:2.3.0" dependencies: - "@solana/assertions": "npm:2.0.0" - "@solana/codecs-core": "npm:2.0.0" - "@solana/codecs-strings": "npm:2.0.0" - "@solana/errors": "npm:2.0.0" + "@solana/assertions": "npm:2.3.0" + "@solana/codecs-core": "npm:2.3.0" + "@solana/codecs-strings": "npm:2.3.0" + "@solana/errors": "npm:2.3.0" + "@solana/nominal-types": "npm:2.3.0" peerDependencies: - typescript: ">=5" - checksum: 10/f99d09c72046c73858aa8b7bc323e634a60b1023a4d280036bc94489e431075c7f29d2889e8787e33a04cfdecbe77cd8ca26c31ded73f735dc98e49c3151cc17 + typescript: ">=5.3.3" + checksum: 10/11ee6774f938dd2fe5174375b02c4e52063173ce80a895dd35beb84635dcf3e2ba2e3fe7c74a614b2322da10906abceab758c91a13415a9cda53faf91a8ea722 languageName: node linkType: hard -"@solana/assertions@npm:2.0.0": - version: 2.0.0 - resolution: "@solana/assertions@npm:2.0.0" +"@solana/assertions@npm:2.3.0": + version: 2.3.0 + resolution: "@solana/assertions@npm:2.3.0" dependencies: - "@solana/errors": "npm:2.0.0" + "@solana/errors": "npm:2.3.0" peerDependencies: - typescript: ">=5" - checksum: 10/c1af37ae1bd79b1657395d9315ac261dabc9908a64af6ed80e3b7e5140909cd8c8c757f0c41fff084e26fbb4d32f091c89c092a8c1ed5e6f4565dfe7426c0979 + typescript: ">=5.3.3" + checksum: 10/3b430f01d5991569059fea3e6679a4548a624ff5da6db0c2eb2eba757a9ff774c9d90941a0a2335148599aaef8e8fc004a9c5996eb3627b25dca108b05591d02 languageName: node linkType: hard -"@solana/codecs-core@npm:2.0.0": - version: 2.0.0 - resolution: "@solana/codecs-core@npm:2.0.0" +"@solana/codecs-core@npm:2.3.0": + version: 2.3.0 + resolution: "@solana/codecs-core@npm:2.3.0" dependencies: - "@solana/errors": "npm:2.0.0" + "@solana/errors": "npm:2.3.0" peerDependencies: - typescript: ">=5" - checksum: 10/e58a72e67bee3e5da60201eecda345c604b49138d5298e39b8e7d4d57a4dee47be3b0ecc8fc3429a2a60a42c952eaf860d43d3df1eb2b1d857e35368eca9c820 + typescript: ">=5.3.3" + checksum: 10/d9bba1eaa3ee38fef04e1cbfa43defeea16729a1cf1628a71cb72340558a3f2296279899680e1dda4b1756ab2b280b5f1502330c21c35e167e554f3d0c9d193d languageName: node linkType: hard -"@solana/codecs-numbers@npm:2.0.0": - version: 2.0.0 - resolution: "@solana/codecs-numbers@npm:2.0.0" +"@solana/codecs-numbers@npm:2.3.0": + version: 2.3.0 + resolution: "@solana/codecs-numbers@npm:2.3.0" dependencies: - "@solana/codecs-core": "npm:2.0.0" - "@solana/errors": "npm:2.0.0" + "@solana/codecs-core": "npm:2.3.0" + "@solana/errors": "npm:2.3.0" peerDependencies: - typescript: ">=5" - checksum: 10/500144d549ea0292c2f672300610df9054339a31cb6a4e61b29623308ef3b14f15eb587ee6139cf3334d2e0f29db1da053522da244b12184bb8fbdb097b7102b + typescript: ">=5.3.3" + checksum: 10/e661338b5eb04268a104ff2189b5d001bd2f99e1a3726deaa7157d5acbc3b24740bc25ca03b2028c52ad21fd71d5d5aa64957411c895a9dc1c132aa3bc97b336 languageName: node linkType: hard -"@solana/codecs-strings@npm:2.0.0": - version: 2.0.0 - resolution: "@solana/codecs-strings@npm:2.0.0" +"@solana/codecs-strings@npm:2.3.0": + version: 2.3.0 + resolution: "@solana/codecs-strings@npm:2.3.0" dependencies: - "@solana/codecs-core": "npm:2.0.0" - "@solana/codecs-numbers": "npm:2.0.0" - "@solana/errors": "npm:2.0.0" + "@solana/codecs-core": "npm:2.3.0" + "@solana/codecs-numbers": "npm:2.3.0" + "@solana/errors": "npm:2.3.0" peerDependencies: fastestsmallesttextencoderdecoder: ^1.0.22 - typescript: ">=5" - checksum: 10/4380136e2603c2cee12a28438817beb34b0fe45da222b8c38342c5b3680f02086ec7868cde0bb7b4e5dd459af5988613af1d97230c6a193db3be1c45122aba39 + typescript: ">=5.3.3" + checksum: 10/a553a891ce149a87f37ff338587980e81f9752e13039cb0d02f0fc6f21ce27af8548ad10f4c9e63f9ef74786ea0e498c91a2f5e3e996a930f581f2977bb1c215 languageName: node linkType: hard -"@solana/errors@npm:2.0.0": - version: 2.0.0 - resolution: "@solana/errors@npm:2.0.0" +"@solana/errors@npm:2.3.0": + version: 2.3.0 + resolution: "@solana/errors@npm:2.3.0" dependencies: - chalk: "npm:^5.3.0" - commander: "npm:^12.1.0" + chalk: "npm:^5.4.1" + commander: "npm:^14.0.0" peerDependencies: - typescript: ">=5" + typescript: ">=5.3.3" bin: errors: bin/cli.mjs - checksum: 10/4191f96cad47c64266ec501ae1911a6245fd02b2f68a2c53c3dabbc63eb7c5462f170a765b584348b195da2387e7ca02096d792c67352c2c30a4f3a3cc7e4270 + checksum: 10/0e8a329790b7d38b4bfe1fa6ec2ac60be20562a610d992031395fe9886da28b578a9d0aebb318f5357ae0d4cbc8f3d323c12b9520da2cf6adc9038f96afc3fe1 + languageName: node + linkType: hard + +"@solana/nominal-types@npm:2.3.0": + version: 2.3.0 + resolution: "@solana/nominal-types@npm:2.3.0" + peerDependencies: + typescript: ">=5.3.3" + checksum: 10/0594893661f4ff2f8587689cd4b61ee15c38c455fe5cbaa7ae7e416f3a483fac97cc3f5a5b3d0a7526bfb89d7da91bc2c72e7b1790bbe59b986579ef2f76689b languageName: node linkType: hard @@ -5871,6 +5976,15 @@ __metadata: languageName: node linkType: hard +"@tybys/wasm-util@npm:^0.10.0": + version: 0.10.1 + resolution: "@tybys/wasm-util@npm:0.10.1" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10/7fe0d239397aebb002ac4855d30c197c06a05ea8df8511350a3a5b1abeefe26167c60eda8a5508337571161e4c4b53d7c1342296123f9607af8705369de9fa7f + languageName: node + linkType: hard + "@types/babel__core@npm:^7.0.0, @types/babel__core@npm:^7.1.14": version: 7.20.5 resolution: "@types/babel__core@npm:7.20.5" @@ -5885,11 +5999,11 @@ __metadata: linkType: hard "@types/babel__generator@npm:*": - version: 7.6.8 - resolution: "@types/babel__generator@npm:7.6.8" + version: 7.27.0 + resolution: "@types/babel__generator@npm:7.27.0" dependencies: "@babel/types": "npm:^7.0.0" - checksum: 10/b53c215e9074c69d212402990b0ca8fa57595d09e10d94bda3130aa22b55d796e50449199867879e4ea0ee968f3a2099e009cfb21a726a53324483abbf25cd30 + checksum: 10/f572e67a9a39397664350a4437d8a7fbd34acc83ff4887a8cf08349e39f8aeb5ad2f70fb78a0a0a23a280affe3a5f4c25f50966abdce292bcf31237af1c27b1a languageName: node linkType: hard @@ -5904,20 +6018,20 @@ __metadata: linkType: hard "@types/babel__traverse@npm:*, @types/babel__traverse@npm:^7.0.4, @types/babel__traverse@npm:^7.0.6": - version: 7.20.6 - resolution: "@types/babel__traverse@npm:7.20.6" + version: 7.28.0 + resolution: "@types/babel__traverse@npm:7.28.0" dependencies: - "@babel/types": "npm:^7.20.7" - checksum: 10/63d13a3789aa1e783b87a8b03d9fb2c2c90078de7782422feff1631b8c2a25db626e63a63ac5a1465d47359201c73069dacb4b52149d17c568187625da3064ae + "@babel/types": "npm:^7.28.2" + checksum: 10/371c5e1b40399ef17570e630b2943617b84fafde2860a56f0ebc113d8edb1d0534ade0175af89eda1ae35160903c33057ed42457e165d4aa287fedab2c82abcf languageName: node linkType: hard "@types/bn.js@npm:*, @types/bn.js@npm:^5.1.0, @types/bn.js@npm:^5.1.5": - version: 5.1.6 - resolution: "@types/bn.js@npm:5.1.6" + version: 5.2.0 + resolution: "@types/bn.js@npm:5.2.0" dependencies: "@types/node": "npm:*" - checksum: 10/db565b5a2af59b09459d74441153bf23a0e80f1fb2d070330786054e7ce1a7285dc40afcd8f289426c61a83166bdd70814f70e2d439744686aac5d3ea75daf13 + checksum: 10/06c93841f74e4a5e5b81b74427d56303b223c9af36389b4cd3c562bda93f43c425c7e241aee1b0b881dde57238dc2e07f21d30d412b206a7dae4435af4c054e8 languageName: node linkType: hard @@ -5937,13 +6051,6 @@ __metadata: languageName: node linkType: hard -"@types/doctrine@npm:^0.0.9": - version: 0.0.9 - resolution: "@types/doctrine@npm:0.0.9" - checksum: 10/64ef06e6eea2f4f9684d259fedbcb8bf21c954630b96ea2e04875ca42763552b0ba3b01b3dd27ec0f9ea6f8b3b0dba4965d31d5a925cd4c6225fd13a93ae9354 - languageName: node - linkType: hard - "@types/elliptic@npm:^6": version: 6.4.18 resolution: "@types/elliptic@npm:6.4.18" @@ -5974,9 +6081,9 @@ __metadata: linkType: hard "@types/estree@npm:*, @types/estree@npm:^1.0.6": - version: 1.0.6 - resolution: "@types/estree@npm:1.0.6" - checksum: 10/9d35d475095199c23e05b431bcdd1f6fec7380612aed068b14b2a08aa70494de8a9026765a5a91b1073f636fb0368f6d8973f518a31391d519e20c59388ed88d + version: 1.0.8 + resolution: "@types/estree@npm:1.0.8" + checksum: 10/25a4c16a6752538ffde2826c2cc0c6491d90e69cd6187bef4a006dd2c3c45469f049e643d7e516c515f21484dc3d48fd5c870be158a5beb72f5baf3dc43e4099 languageName: node linkType: hard @@ -5989,7 +6096,7 @@ __metadata: languageName: node linkType: hard -"@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.0, @types/istanbul-lib-coverage@npm:^2.0.1": +"@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.0, @types/istanbul-lib-coverage@npm:^2.0.1, @types/istanbul-lib-coverage@npm:^2.0.6": version: 2.0.6 resolution: "@types/istanbul-lib-coverage@npm:2.0.6" checksum: 10/3feac423fd3e5449485afac999dcfcb3d44a37c830af898b689fadc65d26526460bedb889db278e0d4d815a670331796494d073a10ee6e3a6526301fe7415778 @@ -6005,7 +6112,7 @@ __metadata: languageName: node linkType: hard -"@types/istanbul-reports@npm:^3.0.0": +"@types/istanbul-reports@npm:^3.0.0, @types/istanbul-reports@npm:^3.0.4": version: 3.0.4 resolution: "@types/istanbul-reports@npm:3.0.4" dependencies: @@ -6024,12 +6131,12 @@ __metadata: linkType: hard "@types/jest@npm:*": - version: 29.5.12 - resolution: "@types/jest@npm:29.5.12" + version: 30.0.0 + resolution: "@types/jest@npm:30.0.0" dependencies: - expect: "npm:^29.0.0" - pretty-format: "npm:^29.0.0" - checksum: 10/312e8dcf92cdd5a5847d6426f0940829bca6fe6b5a917248f3d7f7ef5d85c9ce78ef05e47d2bbabc40d41a930e0e36db2d443d2610a9e3db9062da2d5c904211 + expect: "npm:^30.0.0" + pretty-format: "npm:^30.0.0" + checksum: 10/cdeaa924c68b5233d9ff92861a89e7042df2b0f197633729bcf3a31e65bd4e9426e751c5665b5ac2de0b222b33f100a5502da22aefce3d2c62931c715e88f209 languageName: node linkType: hard @@ -6065,9 +6172,9 @@ __metadata: linkType: hard "@types/lodash@npm:^4.14.191, @types/lodash@npm:^4.17.20": - version: 4.17.20 - resolution: "@types/lodash@npm:4.17.20" - checksum: 10/8cd8ad3bd78d2e06a93ae8d6c9907981d5673655fec7cb274a4d9a59549aab5bb5b3017361280773b8990ddfccf363e14d1b37c97af8a9fe363de677f9a61524 + version: 4.17.23 + resolution: "@types/lodash@npm:4.17.23" + checksum: 10/05935534a44aadef67c2158b2fb4a042a226970088106a40ddc67e4f063783149fe5cf02279d7dd4a1e72c98d9189b9430face659645dbf77270f8c4c3e387f5 languageName: node linkType: hard @@ -6086,42 +6193,44 @@ __metadata: linkType: hard "@types/ms@npm:*": - version: 0.7.34 - resolution: "@types/ms@npm:0.7.34" - checksum: 10/f38d36e7b6edecd9badc9cf50474159e9da5fa6965a75186cceaf883278611b9df6669dc3a3cc122b7938d317b68a9e3d573d316fcb35d1be47ec9e468c6bd8a + version: 2.1.0 + resolution: "@types/ms@npm:2.1.0" + checksum: 10/532d2ebb91937ccc4a89389715e5b47d4c66e708d15942fe6cc25add6dc37b2be058230a327dd50f43f89b8b6d5d52b74685a9e8f70516edfc9bdd6be910eff4 languageName: node linkType: hard "@types/node-fetch@npm:^2.6.12": - version: 2.6.12 - resolution: "@types/node-fetch@npm:2.6.12" + version: 2.6.13 + resolution: "@types/node-fetch@npm:2.6.13" dependencies: "@types/node": "npm:*" - form-data: "npm:^4.0.0" - checksum: 10/8107c479da83a3114fcbfa882eba95ee5175cccb5e4dd53f737a96f2559ae6262f662176b8457c1656de09ec393cc7b20a266c077e4bfb21e929976e1cf4d0f9 + form-data: "npm:^4.0.4" + checksum: 10/944d52214791ebba482ca1393a4f0d62b0dbac5f7343ff42c128b75d5356d8bcefd4df77771b55c1acd19d118e16e9bd5d2792819c51bc13402d1c87c0975435 languageName: node linkType: hard "@types/node@npm:*, @types/node@npm:>=12.12.47, @types/node@npm:>=13.7.0": - version: 22.5.0 - resolution: "@types/node@npm:22.5.0" + version: 25.0.9 + resolution: "@types/node@npm:25.0.9" dependencies: - undici-types: "npm:~6.19.2" - checksum: 10/89af3bd217b1559b645a9ed16d4ae3add75749814cbd8eefddd1b96003d1973afb1c8a2b23d69f3a8cc6c532e3aa185eaf5cc29a6e7c42c311a2aad4c99430ae + undici-types: "npm:~7.16.0" + checksum: 10/2c16f137ed3a952903b7641df5ce16663ad00911dc6a9010156602251420da127bf7dbd32d22aac9eda0cc430381164d55a36240039b7d06ab693b9aad5c3f23 languageName: node linkType: hard -"@types/node@npm:18.15.13": - version: 18.15.13 - resolution: "@types/node@npm:18.15.13" - checksum: 10/b9bbe923573797ef7c5fd2641a6793489e25d9369c32aeadcaa5c7c175c85b42eb12d6fe173f6781ab6f42eaa1ebd9576a419eeaa2a1ec810094adb8adaa9a54 +"@types/node@npm:22.7.5": + version: 22.7.5 + resolution: "@types/node@npm:22.7.5" + dependencies: + undici-types: "npm:~6.19.2" + checksum: 10/e8ba102f8c1aa7623787d625389be68d64e54fcbb76d41f6c2c64e8cf4c9f4a2370e7ef5e5f1732f3c57529d3d26afdcb2edc0101c5e413a79081449825c57ac languageName: node linkType: hard "@types/node@npm:^16.18.54": - version: 16.18.106 - resolution: "@types/node@npm:16.18.106" - checksum: 10/1970719a048bfc56554f8e132e8e5292c197d6e023d334190b0d3817a05a12bfb6537eaa24778ddb695d2073195f0545e5a4b6bcaf81b656994bbca39f349c3b + version: 16.18.126 + resolution: "@types/node@npm:16.18.126" + checksum: 10/33e0fa9209a4a96459a8fdf6b078ca9590eb67a8d51899180cfac8afecb9aa133c755d1c38a8b947b9f384f2faa184cabf4e567f5f6dded285be1b31588ec199 languageName: node linkType: hard @@ -6180,18 +6289,18 @@ __metadata: linkType: hard "@types/secp256k1@npm:^4.0.1": - version: 4.0.6 - resolution: "@types/secp256k1@npm:4.0.6" + version: 4.0.7 + resolution: "@types/secp256k1@npm:4.0.7" dependencies: "@types/node": "npm:*" - checksum: 10/211f823be990b55612e604d620acf0dc3bc942d3836bdd8da604269effabc86d98161e5947487b4e4e128f9180fc1682daae2f89ea7a4d9648fdfe52fba365fc + checksum: 10/bcf7adbd953d2cb829ae98a3cd2f8eeb1e2316f4f6de720ee3863da90bd98899c08fa8c42748e8701cad16ede0898df69a6e7f22660d1fb3cb276d5c771069db languageName: node linkType: hard "@types/semver@npm:^7, @types/semver@npm:^7.3.6": - version: 7.5.8 - resolution: "@types/semver@npm:7.5.8" - checksum: 10/3496808818ddb36deabfe4974fd343a78101fa242c4690044ccdc3b95dcf8785b494f5d628f2f47f38a702f8db9c53c67f47d7818f2be1b79f2efb09692e1178 + version: 7.7.1 + resolution: "@types/semver@npm:7.7.1" + checksum: 10/8f09e7e6ca3ded67d78ba7a8f7535c8d9cf8ced83c52e7f3ac3c281fe8c689c3fe475d199d94390dc04fc681d51f2358b430bb7b2e21c62de24f2bee2c719068 languageName: node linkType: hard @@ -6205,13 +6314,13 @@ __metadata: linkType: hard "@types/sinonjs__fake-timers@npm:*": - version: 8.1.5 - resolution: "@types/sinonjs__fake-timers@npm:8.1.5" - checksum: 10/3a0b285fcb8e1eca435266faa27ffff206608b69041022a42857274e44d9305822e85af5e7a43a9fae78d2ab7dc0fcb49f3ae3bda1fa81f0203064dbf5afd4f6 + version: 15.0.1 + resolution: "@types/sinonjs__fake-timers@npm:15.0.1" + checksum: 10/9fa7a129742262ef4ea9c3253683453c42c2e210cdff1456e233bc9b59f6d60ef8121b32a00209a1c8c7759f88511862dab1ce340081e432515418fc44d8ec35 languageName: node linkType: hard -"@types/stack-utils@npm:^2.0.0": +"@types/stack-utils@npm:^2.0.0, @types/stack-utils@npm:^2.0.3": version: 2.0.3 resolution: "@types/stack-utils@npm:2.0.3" checksum: 10/72576cc1522090fe497337c2b99d9838e320659ac57fa5560fcbdcbafcf5d0216c6b3a0a8a4ee4fdb3b1f5e3420aa4f6223ab57b82fef3578bec3206425c6cf5 @@ -6249,165 +6358,299 @@ __metadata: linkType: hard "@types/yargs@npm:^15.0.0": - version: 15.0.19 - resolution: "@types/yargs@npm:15.0.19" + version: 15.0.20 + resolution: "@types/yargs@npm:15.0.20" dependencies: "@types/yargs-parser": "npm:*" - checksum: 10/c3abcd3472c32c02702f365dc1702a0728562deb8a8c61f3ce2161958d756cc033f7d78567565b4eba62f5869e9b5eac93d4c1dcb2c97af17aafda8f9f892b4b + checksum: 10/f348069c4a0cf5b365e72507f67c6569b12a4af44346c08288319d522272dbe1e3f3acde3ff9ab72bd9f894676624d10fff21096d44bad33e390d092cd409aeb languageName: node linkType: hard "@types/yargs@npm:^16.0.0": - version: 16.0.9 - resolution: "@types/yargs@npm:16.0.9" + version: 16.0.11 + resolution: "@types/yargs@npm:16.0.11" dependencies: "@types/yargs-parser": "npm:*" - checksum: 10/8f31cbfcd5c3ac67c27e26026d8b9af0c37770fb2421b661939ba06d136f5a4fa61528a5d0f495d5802fbf1d9244b499e664d8d884e3eb3c36d556fb7c278f18 + checksum: 10/b083eb4e377a9488b67d5767053a3ef531c142478d04b227529db29f5f3ccc98bc555dbe842b47edadd9901cdae03ce0b75828abfd7e70f8db614b5eabf9db9f languageName: node linkType: hard -"@types/yargs@npm:^17.0.32, @types/yargs@npm:^17.0.8": - version: 17.0.33 - resolution: "@types/yargs@npm:17.0.33" +"@types/yargs@npm:^17.0.32, @types/yargs@npm:^17.0.33, @types/yargs@npm:^17.0.8": + version: 17.0.35 + resolution: "@types/yargs@npm:17.0.35" dependencies: "@types/yargs-parser": "npm:*" - checksum: 10/16f6681bf4d99fb671bf56029141ed01db2862e3db9df7fc92d8bea494359ac96a1b4b1c35a836d1e95e665fb18ad753ab2015fc0db663454e8fd4e5d5e2ef91 + checksum: 10/47bcd4476a4194ea11617ea71cba8a1eddf5505fc39c44336c1a08d452a0de4486aedbc13f47a017c8efbcb5a8aa358d976880663732ebcbc6dbcbbecadb0581 languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:8.48.0, @typescript-eslint/eslint-plugin@npm:^8.48.0": - version: 8.48.0 - resolution: "@typescript-eslint/eslint-plugin@npm:8.48.0" +"@typescript-eslint/eslint-plugin@npm:8.53.0, @typescript-eslint/eslint-plugin@npm:^8.48.0": + version: 8.53.0 + resolution: "@typescript-eslint/eslint-plugin@npm:8.53.0" dependencies: - "@eslint-community/regexpp": "npm:^4.10.0" - "@typescript-eslint/scope-manager": "npm:8.48.0" - "@typescript-eslint/type-utils": "npm:8.48.0" - "@typescript-eslint/utils": "npm:8.48.0" - "@typescript-eslint/visitor-keys": "npm:8.48.0" - graphemer: "npm:^1.4.0" - ignore: "npm:^7.0.0" + "@eslint-community/regexpp": "npm:^4.12.2" + "@typescript-eslint/scope-manager": "npm:8.53.0" + "@typescript-eslint/type-utils": "npm:8.53.0" + "@typescript-eslint/utils": "npm:8.53.0" + "@typescript-eslint/visitor-keys": "npm:8.53.0" + ignore: "npm:^7.0.5" natural-compare: "npm:^1.4.0" - ts-api-utils: "npm:^2.1.0" + ts-api-utils: "npm:^2.4.0" peerDependencies: - "@typescript-eslint/parser": ^8.48.0 + "@typescript-eslint/parser": ^8.53.0 eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10/c9cd87c72da7bb7f6175fdb53a4c08a26e61a3d9d1024960d193276217b37ca1e8e12328a57751ed9380475e11e198f9715e172126ea7d3b3da9948d225db92b + checksum: 10/2cbfa92d21018d53b33db102500f121cedd67405939a11c20d04a0fdc535412f1e554479a9994a244127a151609fe16ae8bce810749261f243eac13360df1ab1 languageName: node linkType: hard -"@typescript-eslint/parser@npm:8.48.0, @typescript-eslint/parser@npm:^8.48.0": - version: 8.48.0 - resolution: "@typescript-eslint/parser@npm:8.48.0" +"@typescript-eslint/parser@npm:8.53.0, @typescript-eslint/parser@npm:^8.48.0": + version: 8.53.0 + resolution: "@typescript-eslint/parser@npm:8.53.0" dependencies: - "@typescript-eslint/scope-manager": "npm:8.48.0" - "@typescript-eslint/types": "npm:8.48.0" - "@typescript-eslint/typescript-estree": "npm:8.48.0" - "@typescript-eslint/visitor-keys": "npm:8.48.0" - debug: "npm:^4.3.4" + "@typescript-eslint/scope-manager": "npm:8.53.0" + "@typescript-eslint/types": "npm:8.53.0" + "@typescript-eslint/typescript-estree": "npm:8.53.0" + "@typescript-eslint/visitor-keys": "npm:8.53.0" + debug: "npm:^4.4.3" peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10/5919642345c79a43e57a85e0e69d1f56b5756b3fdb3586ec6371969604f589adc188338c8f12a787456edc3b38c70586d8209cffcf45e35e5a5ebd497c5f4257 + checksum: 10/5337f472aeb3d04041a3c9c9e9d9884e685ba7e4f722ab2963f1054087a62a42946dd0d39993e60506efef0d2a4cc1b0619b34e49261913d6f4d8cdbf3490d56 languageName: node linkType: hard -"@typescript-eslint/project-service@npm:8.48.0": - version: 8.48.0 - resolution: "@typescript-eslint/project-service@npm:8.48.0" +"@typescript-eslint/project-service@npm:8.53.0": + version: 8.53.0 + resolution: "@typescript-eslint/project-service@npm:8.53.0" dependencies: - "@typescript-eslint/tsconfig-utils": "npm:^8.48.0" - "@typescript-eslint/types": "npm:^8.48.0" - debug: "npm:^4.3.4" + "@typescript-eslint/tsconfig-utils": "npm:^8.53.0" + "@typescript-eslint/types": "npm:^8.53.0" + debug: "npm:^4.4.3" peerDependencies: typescript: ">=4.8.4 <6.0.0" - checksum: 10/5853a2f57bf8a26b70c1fe5a906c1890ad4f0fca127218a7805161fc9ad547af97f4a600f32f5acdf2f2312b156affca2bea84af9a433215cbcc2056b6a27c77 + checksum: 10/2f232f241f57c0f42194a8bcb8c207e4ed4345d7cc097434d394c2904338e64f386903931395ef97cd2cf3ae33d98645f0d6164660d794e33259e2c3978052ff languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:8.48.0, @typescript-eslint/scope-manager@npm:^8.1.0": - version: 8.48.0 - resolution: "@typescript-eslint/scope-manager@npm:8.48.0" +"@typescript-eslint/scope-manager@npm:8.53.0": + version: 8.53.0 + resolution: "@typescript-eslint/scope-manager@npm:8.53.0" dependencies: - "@typescript-eslint/types": "npm:8.48.0" - "@typescript-eslint/visitor-keys": "npm:8.48.0" - checksum: 10/963af7af235e940467504969c565b359ca454a156eba0d5af2e4fd9cca4294947187e1a85107ff05801688ac85b5767d2566414cbef47a03c23f7b46527decca + "@typescript-eslint/types": "npm:8.53.0" + "@typescript-eslint/visitor-keys": "npm:8.53.0" + checksum: 10/40a651cfc16f9464f92b5a58492207c1f89a1ff98cfedd2d33d1dbe8234ce50c3a543267f1b489f903b001e0abcaf1568e7c9b70c009871c34af6ef3602ac0bf languageName: node linkType: hard -"@typescript-eslint/tsconfig-utils@npm:8.48.0, @typescript-eslint/tsconfig-utils@npm:^8.48.0": - version: 8.48.0 - resolution: "@typescript-eslint/tsconfig-utils@npm:8.48.0" +"@typescript-eslint/tsconfig-utils@npm:8.53.0, @typescript-eslint/tsconfig-utils@npm:^8.53.0": + version: 8.53.0 + resolution: "@typescript-eslint/tsconfig-utils@npm:8.53.0" peerDependencies: typescript: ">=4.8.4 <6.0.0" - checksum: 10/e480cd80498c4119a8c5bc413a22abf4bf365b3674ff95f5513292ede31e4fd8118f50d76a786de702696396a43c0c7a4d0c2ccd1c2c7db61bd941ba74495021 + checksum: 10/91f1f02ec8a3daf7d3dc9e43a847ef834444a6e073e3a4a07a311d898b225124d9c4abb4b48266d821f0ea4225614266084e5157182e7ba7aaecafefbae00c7e languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:8.48.0": - version: 8.48.0 - resolution: "@typescript-eslint/type-utils@npm:8.48.0" +"@typescript-eslint/type-utils@npm:8.53.0": + version: 8.53.0 + resolution: "@typescript-eslint/type-utils@npm:8.53.0" dependencies: - "@typescript-eslint/types": "npm:8.48.0" - "@typescript-eslint/typescript-estree": "npm:8.48.0" - "@typescript-eslint/utils": "npm:8.48.0" - debug: "npm:^4.3.4" - ts-api-utils: "npm:^2.1.0" + "@typescript-eslint/types": "npm:8.53.0" + "@typescript-eslint/typescript-estree": "npm:8.53.0" + "@typescript-eslint/utils": "npm:8.53.0" + debug: "npm:^4.4.3" + ts-api-utils: "npm:^2.4.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10/dfda42624d534f9fed270bd5c76c9c0bb879cccd3dfbfc2977c84489860fbc204f10bca5c69f3ac856cc4342c12f8947293e7449d3391af289620d7ec79ced0d + checksum: 10/5be4036b475bbc4bb9a834beefe8114286bbe2dee54c96c65c02d6ceabac3422605802dcbefdbf20ae9ede3c85bf2f650eda2acc7ed1a3bf75f02ed478e7cdd1 languageName: node linkType: hard -"@typescript-eslint/types@npm:8.48.0, @typescript-eslint/types@npm:^8.48.0": - version: 8.48.0 - resolution: "@typescript-eslint/types@npm:8.48.0" - checksum: 10/cd14a7ecd1cb6af94e059a713357b9521ffab08b2793a7d33abda7006816e77f634d49d1ec6f1b99b47257a605347d691bd02b2b11477c9c328f2a27f52a664f +"@typescript-eslint/types@npm:8.53.0, @typescript-eslint/types@npm:^8.11.0, @typescript-eslint/types@npm:^8.35.0, @typescript-eslint/types@npm:^8.53.0": + version: 8.53.0 + resolution: "@typescript-eslint/types@npm:8.53.0" + checksum: 10/36ee696a92ed575385b5c1ccc46e3fec9c5d9aa6f3640f8ad0234ed5a763c9ab78c7d3419fd3d462a966f6b95472390b8040055e4e73c75c52671478e90749ff languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:8.48.0": - version: 8.48.0 - resolution: "@typescript-eslint/typescript-estree@npm:8.48.0" +"@typescript-eslint/typescript-estree@npm:8.53.0": + version: 8.53.0 + resolution: "@typescript-eslint/typescript-estree@npm:8.53.0" dependencies: - "@typescript-eslint/project-service": "npm:8.48.0" - "@typescript-eslint/tsconfig-utils": "npm:8.48.0" - "@typescript-eslint/types": "npm:8.48.0" - "@typescript-eslint/visitor-keys": "npm:8.48.0" - debug: "npm:^4.3.4" - minimatch: "npm:^9.0.4" - semver: "npm:^7.6.0" + "@typescript-eslint/project-service": "npm:8.53.0" + "@typescript-eslint/tsconfig-utils": "npm:8.53.0" + "@typescript-eslint/types": "npm:8.53.0" + "@typescript-eslint/visitor-keys": "npm:8.53.0" + debug: "npm:^4.4.3" + minimatch: "npm:^9.0.5" + semver: "npm:^7.7.3" tinyglobby: "npm:^0.2.15" - ts-api-utils: "npm:^2.1.0" + ts-api-utils: "npm:^2.4.0" peerDependencies: typescript: ">=4.8.4 <6.0.0" - checksum: 10/8ee6b9e98dd72d567b8842a695578b2098bd8cdcf5628d2819407a52b533a5a139ba9a5620976641bc4553144a1b971d75f2df218a7c281fe674df25835e9e22 + checksum: 10/bdacb2f3ffde535c3955bbfbd062d2010943f7693034cde4019ccde699e826e7ef91d7e1d2f3652c30584c013924410dae5056417909e8169f1e3d7272636bd9 languageName: node linkType: hard -"@typescript-eslint/utils@npm:8.48.0, @typescript-eslint/utils@npm:^6.0.0 || ^7.0.0 || ^8.0.0, @typescript-eslint/utils@npm:^8.1.0": - version: 8.48.0 - resolution: "@typescript-eslint/utils@npm:8.48.0" +"@typescript-eslint/utils@npm:8.53.0, @typescript-eslint/utils@npm:^6.0.0 || ^7.0.0 || ^8.0.0": + version: 8.53.0 + resolution: "@typescript-eslint/utils@npm:8.53.0" dependencies: - "@eslint-community/eslint-utils": "npm:^4.7.0" - "@typescript-eslint/scope-manager": "npm:8.48.0" - "@typescript-eslint/types": "npm:8.48.0" - "@typescript-eslint/typescript-estree": "npm:8.48.0" + "@eslint-community/eslint-utils": "npm:^4.9.1" + "@typescript-eslint/scope-manager": "npm:8.53.0" + "@typescript-eslint/types": "npm:8.53.0" + "@typescript-eslint/typescript-estree": "npm:8.53.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10/980b9faeaae0357bd7c002b15ab3bbcb7d5e4558be5df7980cf5221b41570a1a7b7d71ea2fcc8b1387f6c0db948d01468e6dcb31230d6757e28ac2ee5d8be4cf + checksum: 10/ef123c8531de793d8d4f5fa51076402bfe809481feaee605086986c370c94361c525ec550b2c4c6703cf60e026e87862428c044c763ead3ea9bf9bce8ad79310 languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:8.48.0": - version: 8.48.0 - resolution: "@typescript-eslint/visitor-keys@npm:8.48.0" +"@typescript-eslint/visitor-keys@npm:8.53.0": + version: 8.53.0 + resolution: "@typescript-eslint/visitor-keys@npm:8.53.0" dependencies: - "@typescript-eslint/types": "npm:8.48.0" + "@typescript-eslint/types": "npm:8.53.0" eslint-visitor-keys: "npm:^4.2.1" - checksum: 10/f9eaff8225b3b00e486e0221bd596b08a3ed463f31fab88221256908f6208c48f745281b7b92e6358d25e1dbdc37c6c2f4b42503403c24b071165bafd9a35d52 + checksum: 10/879e1dfbd002059c0eb59f9660c26eb71a1643622906e4af444dbe5297e95ad210d763b53308b6372b55d85159a161982a8848352706a7d361fd3e17d6ba96d0 + languageName: node + linkType: hard + +"@unrs/resolver-binding-android-arm-eabi@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-android-arm-eabi@npm:1.11.1" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@unrs/resolver-binding-android-arm64@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-android-arm64@npm:1.11.1" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-darwin-arm64@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-darwin-arm64@npm:1.11.1" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-darwin-x64@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-darwin-x64@npm:1.11.1" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-freebsd-x64@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-freebsd-x64@npm:1.11.1" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm-gnueabihf@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-arm-gnueabihf@npm:1.11.1" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm-musleabihf@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-arm-musleabihf@npm:1.11.1" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm64-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-arm64-gnu@npm:1.11.1" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm64-musl@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-arm64-musl@npm:1.11.1" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-ppc64-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-ppc64-gnu@npm:1.11.1" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-riscv64-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-riscv64-gnu@npm:1.11.1" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-riscv64-musl@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-riscv64-musl@npm:1.11.1" + conditions: os=linux & cpu=riscv64 & libc=musl + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-s390x-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-s390x-gnu@npm:1.11.1" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-x64-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-x64-gnu@npm:1.11.1" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-x64-musl@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-x64-musl@npm:1.11.1" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@unrs/resolver-binding-wasm32-wasi@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-wasm32-wasi@npm:1.11.1" + dependencies: + "@napi-rs/wasm-runtime": "npm:^0.2.11" + conditions: cpu=wasm32 + languageName: node + linkType: hard + +"@unrs/resolver-binding-win32-arm64-msvc@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-win32-arm64-msvc@npm:1.11.1" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-win32-ia32-msvc@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-win32-ia32-msvc@npm:1.11.1" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@unrs/resolver-binding-win32-x64-msvc@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-win32-x64-msvc@npm:1.11.1" + conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -6418,60 +6661,60 @@ __metadata: languageName: node linkType: hard -"@vue/compiler-core@npm:3.4.38": - version: 3.4.38 - resolution: "@vue/compiler-core@npm:3.4.38" +"@vue/compiler-core@npm:3.5.26": + version: 3.5.26 + resolution: "@vue/compiler-core@npm:3.5.26" dependencies: - "@babel/parser": "npm:^7.24.7" - "@vue/shared": "npm:3.4.38" - entities: "npm:^4.5.0" + "@babel/parser": "npm:^7.28.5" + "@vue/shared": "npm:3.5.26" + entities: "npm:^7.0.0" estree-walker: "npm:^2.0.2" - source-map-js: "npm:^1.2.0" - checksum: 10/16449e9083c290e6c13e1cc0cb0a0a457817a52533d10902388c872fb1337ba0fa29fb7b8394df5a10f5ed3bad264d6c386f9eaf47c07982a543f277dbee9b8a + source-map-js: "npm:^1.2.1" + checksum: 10/45267d1dbe67ae81116651eb9a6d1151de248533d53dc5216a7a4952952ac2e297201838d12e4fd1283acf5f3d7672fe2a49da59e2711bf68d2bf9ca5567dd9a languageName: node linkType: hard -"@vue/compiler-dom@npm:3.4.38": - version: 3.4.38 - resolution: "@vue/compiler-dom@npm:3.4.38" +"@vue/compiler-dom@npm:3.5.26": + version: 3.5.26 + resolution: "@vue/compiler-dom@npm:3.5.26" dependencies: - "@vue/compiler-core": "npm:3.4.38" - "@vue/shared": "npm:3.4.38" - checksum: 10/4012fab212dc0628ef72f5ae13aa2dd551efb8be7f2aa8abe2a1db15058ddda29912a1e3aa1fc6712e2d8efe84724f16a907ad2cda987631bfc79330afc8d451 + "@vue/compiler-core": "npm:3.5.26" + "@vue/shared": "npm:3.5.26" + checksum: 10/505e15422fa15ac20c1de4d0270b5537fa8de3fbad5221b7686e67ec2c4d41a3990842c56ae8daa94939d92b3dc0e03f5e639b0cadd32ece6dc453565f1c4eef languageName: node linkType: hard "@vue/compiler-sfc@npm:^3.3.4": - version: 3.4.38 - resolution: "@vue/compiler-sfc@npm:3.4.38" - dependencies: - "@babel/parser": "npm:^7.24.7" - "@vue/compiler-core": "npm:3.4.38" - "@vue/compiler-dom": "npm:3.4.38" - "@vue/compiler-ssr": "npm:3.4.38" - "@vue/shared": "npm:3.4.38" + version: 3.5.26 + resolution: "@vue/compiler-sfc@npm:3.5.26" + dependencies: + "@babel/parser": "npm:^7.28.5" + "@vue/compiler-core": "npm:3.5.26" + "@vue/compiler-dom": "npm:3.5.26" + "@vue/compiler-ssr": "npm:3.5.26" + "@vue/shared": "npm:3.5.26" estree-walker: "npm:^2.0.2" - magic-string: "npm:^0.30.10" - postcss: "npm:^8.4.40" - source-map-js: "npm:^1.2.0" - checksum: 10/3eec1ddc03e06a162087dbbff9679f941ff34c43e553006aa2717c6a396445f488b62b89afa9cf65688468a05d8517bf1ee64936ad78d7ba6647a850a089e0e0 + magic-string: "npm:^0.30.21" + postcss: "npm:^8.5.6" + source-map-js: "npm:^1.2.1" + checksum: 10/7cd07434ad8b88523018780cc5c5d8cd81396629a1a020d462830a42ecb26942fafd436cb39698c33ae8aa9e9c7645f7b551e5f96bb6948bfe6442d222473d5c languageName: node linkType: hard -"@vue/compiler-ssr@npm:3.4.38": - version: 3.4.38 - resolution: "@vue/compiler-ssr@npm:3.4.38" +"@vue/compiler-ssr@npm:3.5.26": + version: 3.5.26 + resolution: "@vue/compiler-ssr@npm:3.5.26" dependencies: - "@vue/compiler-dom": "npm:3.4.38" - "@vue/shared": "npm:3.4.38" - checksum: 10/3ee052c8f10bf18db5d6788df21105698c139fac1de6c82532878cca86be4d052510a216184b3ea73331d84befcefd3f9ada11470c862f03696fed96ce1005cb + "@vue/compiler-dom": "npm:3.5.26" + "@vue/shared": "npm:3.5.26" + checksum: 10/4958299402773c09ffa439a98c15286f07401f03e15736f7c15194cc49f1881a0bc5aec7d21712ba37e2528119e439a20d8dce1ceb7fc2640687002d47af61da languageName: node linkType: hard -"@vue/shared@npm:3.4.38": - version: 3.4.38 - resolution: "@vue/shared@npm:3.4.38" - checksum: 10/46bfc1f3932fd154ff84dcd267cae4db730c98db433c848d40c9c0dc23dcabdb5efe96a3a378c9ed3b7e8281ca17e2753f0ce98ae43b54b315550dfaccb56868 +"@vue/shared@npm:3.5.26": + version: 3.5.26 + resolution: "@vue/shared@npm:3.5.26" + checksum: 10/9b480f1210e546dcdc94addfe5b2770424a286546078944cf48b4b21c3cbf377b515de4e857f6f435c823e5759e012b75d9e58b4cedc981a6aa6c8372d83c002 languageName: node linkType: hard @@ -6483,11 +6726,11 @@ __metadata: linkType: hard "@yarnpkg/types@npm:^4.0.0": - version: 4.0.0 - resolution: "@yarnpkg/types@npm:4.0.0" + version: 4.0.1 + resolution: "@yarnpkg/types@npm:4.0.1" dependencies: tslib: "npm:^2.4.0" - checksum: 10/f9670e120761a4d17461df2f01aa4b92213fbdd063501a36145d11ea01bd87ba01d44615cba3d6bc8f9bfc39a03a9a6452bf0436c7fb0c9c5311352b975349e6 + checksum: 10/f391763cd955356e9aad551b29e8de7bbf68a6c8992af7cdc950ccf53f8aff6695ad81aa4c8a8e7c582786a840a4f30617732e2cb49f4109b971a9242c31c9fc languageName: node linkType: hard @@ -6498,10 +6741,10 @@ __metadata: languageName: node linkType: hard -"abbrev@npm:^2.0.0": - version: 2.0.0 - resolution: "abbrev@npm:2.0.0" - checksum: 10/ca0a54e35bea4ece0ecb68a47b312e1a9a6f772408d5bcb9051230aaa94b0460671c5b5c9cb3240eb5b7bc94c52476550eb221f65a0bbd0145bdc9f3113a6707 +"abbrev@npm:^4.0.0": + version: 4.0.0 + resolution: "abbrev@npm:4.0.0" + checksum: 10/e2f0c6a6708ad738b3e8f50233f4800de31ad41a6cdc50e0cbe51b76fed69fd0213516d92c15ce1a9985fca71a14606a9be22bf00f8475a58987b9bfb671c582 languageName: node linkType: hard @@ -6598,22 +6841,10 @@ __metadata: languageName: node linkType: hard -"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0, agent-base@npm:^7.1.1": - version: 7.1.1 - resolution: "agent-base@npm:7.1.1" - dependencies: - debug: "npm:^4.3.4" - checksum: 10/c478fec8f79953f118704d007a38f2a185458853f5c45579b9669372bd0e12602e88dc2ad0233077831504f7cd6fcc8251c383375bba5eaaf563b102938bda26 - languageName: node - linkType: hard - -"aggregate-error@npm:^3.0.0": - version: 3.1.0 - resolution: "aggregate-error@npm:3.1.0" - dependencies: - clean-stack: "npm:^2.0.0" - indent-string: "npm:^4.0.0" - checksum: 10/1101a33f21baa27a2fa8e04b698271e64616b886795fd43c31068c07533c7b3facfcaf4e9e0cab3624bd88f729a592f1c901a1a229c9e490eafce411a8644b79 +"agent-base@npm:^7.1.0, agent-base@npm:^7.1.2": + version: 7.1.4 + resolution: "agent-base@npm:7.1.4" + checksum: 10/79bef167247789f955aaba113bae74bf64aa1e1acca4b1d6bb444bdf91d82c3e07e9451ef6a6e2e35e8f71a6f97ce33e3d855a5328eb9fad1bc3cc4cfd031ed8 languageName: node linkType: hard @@ -6653,16 +6884,16 @@ __metadata: linkType: hard "ansi-regex@npm:^6.0.1": - version: 6.0.1 - resolution: "ansi-regex@npm:6.0.1" - checksum: 10/1ff8b7667cded1de4fa2c9ae283e979fc87036864317da86a2e546725f96406746411d0d85e87a2d12fa5abd715d90006de7fa4fa0477c92321ad3b4c7d4e169 + version: 6.2.2 + resolution: "ansi-regex@npm:6.2.2" + checksum: 10/9b17ce2c6daecc75bcd5966b9ad672c23b184dc3ed9bf3c98a0702f0d2f736c15c10d461913568f2cf527a5e64291c7473358885dd493305c84a1cfed66ba94f languageName: node linkType: hard "ansi-sequence-parser@npm:^1.1.0": - version: 1.1.1 - resolution: "ansi-sequence-parser@npm:1.1.1" - checksum: 10/9ce30f257badc2ef62cac8028a7e26c368d22bf26650427192e8ffd102da42e377e3affe90fae58062eecc963b0b055f510dde3b677c7e0c433c67069b5a8ee5 + version: 1.1.3 + resolution: "ansi-sequence-parser@npm:1.1.3" + checksum: 10/0f298aad5c9429dc71fc85668b4b502a5c0670c6dc1253b6e9ed5fc7d457a05ede5b10fd0d69a33a1435e41c0a841360bec9131053bdce04a2367c475acb97d6 languageName: node linkType: hard @@ -6675,7 +6906,7 @@ __metadata: languageName: node linkType: hard -"ansi-styles@npm:^5.0.0": +"ansi-styles@npm:^5.0.0, ansi-styles@npm:^5.2.0": version: 5.2.0 resolution: "ansi-styles@npm:5.2.0" checksum: 10/d7f4e97ce0623aea6bc0d90dcd28881ee04cba06c570b97fd3391bd7a268eedfd9d5e2dd4fdcbdd82b8105df5faf6f24aaedc08eaf3da898e702db5948f63469 @@ -6683,9 +6914,9 @@ __metadata: linkType: hard "ansi-styles@npm:^6.1.0": - version: 6.2.1 - resolution: "ansi-styles@npm:6.2.1" - checksum: 10/70fdf883b704d17a5dfc9cde206e698c16bcd74e7f196ab821511651aee4f9f76c9514bdfa6ca3a27b5e49138b89cb222a28caf3afe4567570139577f991df32 + version: 6.2.3 + resolution: "ansi-styles@npm:6.2.3" + checksum: 10/c49dad7639f3e48859bd51824c93b9eb0db628afc243c51c3dd2410c4a15ede1a83881c6c7341aa2b159c4f90c11befb38f2ba848c07c66c9f9de4bcd7cb9f30 languageName: node linkType: hard @@ -6771,12 +7002,17 @@ __metadata: languageName: node linkType: hard -"async-mutex@npm:^0.3.1": - version: 0.3.2 - resolution: "async-mutex@npm:0.3.2" - dependencies: - tslib: "npm:^2.3.1" - checksum: 10/cf0b02f7f916d202a727e15a64d51110c3258a719588ca263875024172aa9368efa5dbec6dc4f4fd10e35744e238e1075306a93ce86549de642d5f7d0c06bc23 +"async-function@npm:^1.0.0": + version: 1.0.0 + resolution: "async-function@npm:1.0.0" + checksum: 10/1a09379937d846f0ce7614e75071c12826945d4e417db634156bf0e4673c495989302f52186dfa9767a1d9181794554717badd193ca2bbab046ef1da741d8efd + languageName: node + linkType: hard + +"async-generator-function@npm:^1.0.0": + version: 1.0.0 + resolution: "async-generator-function@npm:1.0.0" + checksum: 10/3d49e7acbeee9e84537f4cb0e0f91893df8eba976759875ae8ee9e3d3c82f6ecdebdb347c2fad9926b92596d93cdfc78ecc988bcdf407e40433e8e8e6fe5d78e languageName: node linkType: hard @@ -6796,21 +7032,35 @@ __metadata: languageName: node linkType: hard +"available-typed-arrays@npm:^1.0.7": + version: 1.0.7 + resolution: "available-typed-arrays@npm:1.0.7" + dependencies: + possible-typed-array-names: "npm:^1.0.0" + checksum: 10/6c9da3a66caddd83c875010a1ca8ef11eac02ba15fb592dc9418b2b5e7b77b645fa7729380a92d9835c2f05f2ca1b6251f39b993e0feb3f1517c74fa1af02cab + languageName: node + linkType: hard + "axios@npm:^1.7.4": - version: 1.7.5 - resolution: "axios@npm:1.7.5" + version: 1.13.2 + resolution: "axios@npm:1.13.2" dependencies: follow-redirects: "npm:^1.15.6" - form-data: "npm:^4.0.0" + form-data: "npm:^4.0.4" proxy-from-env: "npm:^1.1.0" - checksum: 10/6cbcfe943a84089f420a900a3a3aeb54ee94dcc9c2b81b150434896357be5d1079eff0b1bbb628597371e79f896b1bc5776df04184756ba99656ff31df9a75bf + checksum: 10/ae4e06dcd18289f2fd18179256d550d27f9a53ecb2f9c59f2ccc4efd1d7151839ba8c3e0fb533dac793e4a59a576ca8689a19244dce5c396680837674a47a867 languageName: node linkType: hard "b4a@npm:^1.6.4": - version: 1.6.6 - resolution: "b4a@npm:1.6.6" - checksum: 10/6154a36bd78b53ecd2843a829352532a1bf9fc8081dab339ba06ca3c9ffcf25d340c3b18fe4ba0fc17a546a54c1ed814cea92cd6b895f6bd2837ca4ee0fc9f52 + version: 1.7.3 + resolution: "b4a@npm:1.7.3" + peerDependencies: + react-native-b4a: "*" + peerDependenciesMeta: + react-native-b4a: + optional: true + checksum: 10/048ddd0eeec6a75e6f8dee07d52354e759032f0ef678b556e05bf5a137d7a4102002cadb953b3fb37a635995a1013875d715d115dbafaf12bcad6528d2166054 languageName: node linkType: hard @@ -6887,8 +7137,8 @@ __metadata: linkType: hard "babel-preset-current-node-syntax@npm:^1.0.0": - version: 1.1.0 - resolution: "babel-preset-current-node-syntax@npm:1.1.0" + version: 1.2.0 + resolution: "babel-preset-current-node-syntax@npm:1.2.0" dependencies: "@babel/plugin-syntax-async-generators": "npm:^7.8.4" "@babel/plugin-syntax-bigint": "npm:^7.8.3" @@ -6906,8 +7156,8 @@ __metadata: "@babel/plugin-syntax-private-property-in-object": "npm:^7.14.5" "@babel/plugin-syntax-top-level-await": "npm:^7.14.5" peerDependencies: - "@babel/core": ^7.0.0 - checksum: 10/46331111ae72b7121172fd9e6a4a7830f651ad44bf26dbbf77b3c8a60a18009411a3eacb5e72274004290c110371230272109957d5224d155436b4794ead2f1b + "@babel/core": ^7.0.0 || ^8.0.0-0 + checksum: 10/3608fa671cfa46364ea6ec704b8fcdd7514b7b70e6ec09b1199e13ae73ed346c51d5ce2cb6d4d5b295f6a3f2cad1fdeec2308aa9e037002dd7c929194cc838ea languageName: node linkType: hard @@ -6952,19 +7202,24 @@ __metadata: languageName: node linkType: hard -"bare-events@npm:^2.2.0": - version: 2.4.2 - resolution: "bare-events@npm:2.4.2" - checksum: 10/c1006ad13b7e62a412466d4eac8466b4ceb46ce84a5e2fc164cd4b10edaaa5016adc684147134b67a6a3865aaf5aa007191647bdb5dbf859b1d5735d2a9ddf3b +"bare-events@npm:^2.7.0": + version: 2.8.2 + resolution: "bare-events@npm:2.8.2" + peerDependencies: + bare-abort-controller: "*" + peerDependenciesMeta: + bare-abort-controller: + optional: true + checksum: 10/f31848ea2f5627c3a50aadfc17e518a602629f7a6671da1352975cc6c8a520441fcc9d93c0a21f8f95de65b1a5133fcd5f766d312f3d5a326dde4fe7d2fc575f languageName: node linkType: hard "base-x@npm:^3.0.2": - version: 3.0.10 - resolution: "base-x@npm:3.0.10" + version: 3.0.11 + resolution: "base-x@npm:3.0.11" dependencies: safe-buffer: "npm:^5.0.1" - checksum: 10/52307739559e81d9980889de2359cb4f816cc0eb9a463028fa3ab239ab913d9044a1b47b4520f98e68453df32a457b8ba58b8d0ee7e757fc3fb971f3fa7a1482 + checksum: 10/c2e3c443fd07cb9b9d3e179a9e9c581daa31881005841fe8d6a834e534505890fedf03465ccf14512da60e3f7be00fe66167806b159ba076d2c03952ae7460c4 languageName: node linkType: hard @@ -6982,6 +7237,15 @@ __metadata: languageName: node linkType: hard +"baseline-browser-mapping@npm:^2.9.0": + version: 2.9.15 + resolution: "baseline-browser-mapping@npm:2.9.15" + bin: + baseline-browser-mapping: dist/cli.js + checksum: 10/ff303d989833084798f89ad9962004a8a39f4f93d06a2d092036d063f126c4a78d00b1137ce9d78ced10b8cf7304e59ef58508af51f0a4d3e001e8a579cda146 + languageName: node + linkType: hard + "bech32@npm:1.1.4": version: 1.1.4 resolution: "bech32@npm:1.1.4" @@ -6997,9 +7261,9 @@ __metadata: linkType: hard "bignumber.js@npm:^9.1.2": - version: 9.1.2 - resolution: "bignumber.js@npm:9.1.2" - checksum: 10/d89b8800a987225d2c00dcbf8a69dc08e92aa0880157c851c287b307d31ceb2fc2acb0c62c3e3a3d42b6c5fcae9b004035f13eb4386e56d529d7edac18d5c9d8 + version: 9.3.1 + resolution: "bignumber.js@npm:9.3.1" + checksum: 10/1be0372bf0d6d29d0a49b9e6a9cefbd54dad9918232ad21fcd4ec39030260773abf0c76af960c6b3b98d3115a3a71e61c6a111812d1395040a039cfa178e0245 languageName: node linkType: hard @@ -7055,9 +7319,9 @@ __metadata: linkType: hard "bn.js@npm:^4.11.9": - version: 4.12.0 - resolution: "bn.js@npm:4.12.0" - checksum: 10/10f8db196d3da5adfc3207d35d0a42aa29033eb33685f20ba2c36cadfe2de63dad05df0a20ab5aae01b418d1c4b3d4d205273085262fa020d17e93ff32b67527 + version: 4.12.2 + resolution: "bn.js@npm:4.12.2" + checksum: 10/5803983405c087443e0e6c9bb5d0bc863d9f987d77e710f81b14c55616494f5a274e1650ee892531acb3529d52c0e0ea48aa12d2873dd80a75dde9d73a2ec518 languageName: node linkType: hard @@ -7068,42 +7332,42 @@ __metadata: languageName: node linkType: hard -"body-parser@npm:1.20.3": - version: 1.20.3 - resolution: "body-parser@npm:1.20.3" +"body-parser@npm:~1.20.3": + version: 1.20.4 + resolution: "body-parser@npm:1.20.4" dependencies: - bytes: "npm:3.1.2" + bytes: "npm:~3.1.2" content-type: "npm:~1.0.5" debug: "npm:2.6.9" depd: "npm:2.0.0" - destroy: "npm:1.2.0" - http-errors: "npm:2.0.0" - iconv-lite: "npm:0.4.24" - on-finished: "npm:2.4.1" - qs: "npm:6.13.0" - raw-body: "npm:2.5.2" + destroy: "npm:~1.2.0" + http-errors: "npm:~2.0.1" + iconv-lite: "npm:~0.4.24" + on-finished: "npm:~2.4.1" + qs: "npm:~6.14.0" + raw-body: "npm:~2.5.3" type-is: "npm:~1.6.18" - unpipe: "npm:1.0.0" - checksum: 10/8723e3d7a672eb50854327453bed85ac48d045f4958e81e7d470c56bf111f835b97e5b73ae9f6393d0011cc9e252771f46fd281bbabc57d33d3986edf1e6aeca + unpipe: "npm:~1.0.0" + checksum: 10/ff67e28d3f426707be8697a75fdf8d564dc50c341b41f054264d8ab6e2924e519c7ce8acc9d0de05328fdc41e1d9f3f200aec9c1cfb1867d6b676a410d97c689 languageName: node linkType: hard "brace-expansion@npm:^1.1.7": - version: 1.1.11 - resolution: "brace-expansion@npm:1.1.11" + version: 1.1.12 + resolution: "brace-expansion@npm:1.1.12" dependencies: balanced-match: "npm:^1.0.0" concat-map: "npm:0.0.1" - checksum: 10/faf34a7bb0c3fcf4b59c7808bc5d2a96a40988addf2e7e09dfbb67a2251800e0d14cd2bfc1aa79174f2f5095c54ff27f46fb1289fe2d77dac755b5eb3434cc07 + checksum: 10/12cb6d6310629e3048cadb003e1aca4d8c9bb5c67c3c321bafdd7e7a50155de081f78ea3e0ed92ecc75a9015e784f301efc8132383132f4f7904ad1ac529c562 languageName: node linkType: hard "brace-expansion@npm:^2.0.1": - version: 2.0.1 - resolution: "brace-expansion@npm:2.0.1" + version: 2.0.2 + resolution: "brace-expansion@npm:2.0.2" dependencies: balanced-match: "npm:^1.0.0" - checksum: 10/a61e7cd2e8a8505e9f0036b3b6108ba5e926b4b55089eeb5550cd04a471fe216c96d4fe7e4c7f995c728c554ae20ddfc4244cad10aef255e72b62930afd233d1 + checksum: 10/01dff195e3646bc4b0d27b63d9bab84d2ebc06121ff5013ad6e5356daa5a9d6b60fa26cf73c74797f2dc3fbec112af13578d51f75228c1112b26c790a87b0488 languageName: node linkType: hard @@ -7145,16 +7409,17 @@ __metadata: linkType: hard "browserslist@npm:^4.24.0": - version: 4.24.4 - resolution: "browserslist@npm:4.24.4" - dependencies: - caniuse-lite: "npm:^1.0.30001688" - electron-to-chromium: "npm:^1.5.73" - node-releases: "npm:^2.0.19" - update-browserslist-db: "npm:^1.1.1" + version: 4.28.1 + resolution: "browserslist@npm:4.28.1" + dependencies: + baseline-browser-mapping: "npm:^2.9.0" + caniuse-lite: "npm:^1.0.30001759" + electron-to-chromium: "npm:^1.5.263" + node-releases: "npm:^2.0.27" + update-browserslist-db: "npm:^1.2.0" bin: browserslist: cli.js - checksum: 10/11fda105e803d891311a21a1f962d83599319165faf471c2d70e045dff82a12128f5b50b1fcba665a2352ad66147aaa248a9d2355a80aadc3f53375eb3de2e48 + checksum: 10/64f2a97de4bce8473c0e5ae0af8d76d1ead07a5b05fc6bc87b848678bb9c3a91ae787b27aa98cdd33fc00779607e6c156000bed58fefb9cf8e4c5a183b994cdb languageName: node linkType: hard @@ -7229,30 +7494,29 @@ __metadata: languageName: node linkType: hard -"bytes@npm:3.1.2": +"bytes@npm:~3.1.2": version: 3.1.2 resolution: "bytes@npm:3.1.2" checksum: 10/a10abf2ba70c784471d6b4f58778c0beeb2b5d405148e66affa91f23a9f13d07603d0a0354667310ae1d6dc141474ffd44e2a074be0f6e2254edb8fc21445388 languageName: node linkType: hard -"cacache@npm:^18.0.0": - version: 18.0.4 - resolution: "cacache@npm:18.0.4" +"cacache@npm:^20.0.1": + version: 20.0.3 + resolution: "cacache@npm:20.0.3" dependencies: - "@npmcli/fs": "npm:^3.1.0" + "@npmcli/fs": "npm:^5.0.0" fs-minipass: "npm:^3.0.0" - glob: "npm:^10.2.2" - lru-cache: "npm:^10.0.1" + glob: "npm:^13.0.0" + lru-cache: "npm:^11.1.0" minipass: "npm:^7.0.3" minipass-collect: "npm:^2.0.1" minipass-flush: "npm:^1.0.5" minipass-pipeline: "npm:^1.2.4" - p-map: "npm:^4.0.0" - ssri: "npm:^10.0.0" - tar: "npm:^6.1.11" - unique-filename: "npm:^3.0.0" - checksum: 10/ca2f7b2d3003f84d362da9580b5561058ccaecd46cba661cbcff0375c90734b610520d46b472a339fd032d91597ad6ed12dde8af81571197f3c9772b5d35b104 + p-map: "npm:^7.0.2" + ssri: "npm:^13.0.0" + unique-filename: "npm:^5.0.0" + checksum: 10/388a0169970df9d051da30437f93f81b7e91efb570ad0ff2b8fde33279fbe726c1bc8e8e2b9c05053ffb4f563854c73db395e8712e3b62347a1bc4f7fb8899ff languageName: node linkType: hard @@ -7266,7 +7530,7 @@ __metadata: languageName: node linkType: hard -"call-bind@npm:^1.0.7": +"call-bind@npm:^1.0.8": version: 1.0.8 resolution: "call-bind@npm:1.0.8" dependencies: @@ -7278,6 +7542,16 @@ __metadata: languageName: node linkType: hard +"call-bound@npm:^1.0.2, call-bound@npm:^1.0.3, call-bound@npm:^1.0.4": + version: 1.0.4 + resolution: "call-bound@npm:1.0.4" + dependencies: + call-bind-apply-helpers: "npm:^1.0.2" + get-intrinsic: "npm:^1.3.0" + checksum: 10/ef2b96e126ec0e58a7ff694db43f4d0d44f80e641370c21549ed911fecbdbc2df3ebc9bddad918d6bbdefeafb60bb3337902006d5176d72bcd2da74820991af7 + languageName: node + linkType: hard + "callsite@npm:^1.0.0": version: 1.0.0 resolution: "callsite@npm:1.0.0" @@ -7317,10 +7591,10 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.30001688": - version: 1.0.30001690 - resolution: "caniuse-lite@npm:1.0.30001690" - checksum: 10/9fb4659eb09a298601b9593739072c481e2f5cc524bd0530e5e0f002e66246da5e866669854dfc0d53195ee36b201dab02f7933a7cdf60ccba7adb2d4a304caf +"caniuse-lite@npm:^1.0.30001759": + version: 1.0.30001764 + resolution: "caniuse-lite@npm:1.0.30001764" + checksum: 10/24c6f402902181faa997a6da1cb63410f9376e9e8a33d733121862e7665d200a54d70e551c5626748f78078401c0744496a58d0451fceb8f7fa12498ae12ff20 languageName: node linkType: hard @@ -7334,10 +7608,10 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^5.3.0": - version: 5.3.0 - resolution: "chalk@npm:5.3.0" - checksum: 10/6373caaab21bd64c405bfc4bd9672b145647fc9482657b5ea1d549b3b2765054e9d3d928870cdf764fb4aad67555f5061538ff247b8310f110c5c888d92397ea +"chalk@npm:^5.3.0, chalk@npm:^5.4.1": + version: 5.6.2 + resolution: "chalk@npm:5.6.2" + checksum: 10/1b2f48f6fba1370670d5610f9cd54c391d6ede28f4b7062dd38244ea5768777af72e5be6b74fb6c6d54cb84c4a2dff3f3afa9b7cb5948f7f022cfd3d087989e0 languageName: node linkType: hard @@ -7348,13 +7622,6 @@ __metadata: languageName: node linkType: hard -"chownr@npm:^2.0.0": - version: 2.0.0 - resolution: "chownr@npm:2.0.0" - checksum: 10/c57cf9dd0791e2f18a5ee9c1a299ae6e801ff58fee96dc8bfd0dcb4738a6ce58dd252a3605b1c93c6418fe4f9d5093b28ffbf4d66648cb2a9c67eaef9679be2f - languageName: node - linkType: hard - "chownr@npm:^3.0.0": version: 3.0.0 resolution: "chownr@npm:3.0.0" @@ -7376,27 +7643,28 @@ __metadata: languageName: node linkType: hard -"cipher-base@npm:^1.0.0, cipher-base@npm:^1.0.1, cipher-base@npm:^1.0.3": - version: 1.0.4 - resolution: "cipher-base@npm:1.0.4" - dependencies: - inherits: "npm:^2.0.1" - safe-buffer: "npm:^5.0.1" - checksum: 10/3d5d6652ca499c3f7c5d7fdc2932a357ec1e5aa84f2ad766d850efd42e89753c97b795c3a104a8e7ae35b4e293f5363926913de3bf8181af37067d9d541ca0db +"ci-info@npm:^4.2.0": + version: 4.3.1 + resolution: "ci-info@npm:4.3.1" + checksum: 10/9dc952bef67e665ccde2e7a552d42d5d095529d21829ece060a00925ede2dfa136160c70ef2471ea6ed6c9b133218b47c007f56955c0f1734a2e57f240aa7445 languageName: node linkType: hard -"cjs-module-lexer@npm:^1.0.0, cjs-module-lexer@npm:^1.3.1": - version: 1.4.0 - resolution: "cjs-module-lexer@npm:1.4.0" - checksum: 10/b041096749792526120d8b8756929f8ef5dd4596502a0e1013f857e3027acd6091915fea77037921d70ee1a99988a100d994d3d3c2e323b04dd4c5ffd516cf13 +"cipher-base@npm:^1.0.0, cipher-base@npm:^1.0.1, cipher-base@npm:^1.0.3": + version: 1.0.7 + resolution: "cipher-base@npm:1.0.7" + dependencies: + inherits: "npm:^2.0.4" + safe-buffer: "npm:^5.2.1" + to-buffer: "npm:^1.2.2" + checksum: 10/9501d2241b7968aaae74fc3db1d6a69a804e0b14117a8fd5d811edf351fcd39a1807bfd98e090a799cfe98b183fbf2e01ebb57f1239080850db07b68dcd9ba02 languageName: node linkType: hard -"clean-stack@npm:^2.0.0": - version: 2.2.0 - resolution: "clean-stack@npm:2.2.0" - checksum: 10/2ac8cd2b2f5ec986a3c743935ec85b07bc174d5421a5efc8017e1f146a1cf5f781ae962618f416352103b32c9cd7e203276e8c28241bbe946160cab16149fb68 +"cjs-module-lexer@npm:^1.0.0, cjs-module-lexer@npm:^1.3.1": + version: 1.4.3 + resolution: "cjs-module-lexer@npm:1.4.3" + checksum: 10/d2b92f919a2dedbfd61d016964fce8da0035f827182ed6839c97cac56e8a8077cfa6a59388adfe2bc588a19cef9bbe830d683a76a6e93c51f65852062cfe2591 languageName: node linkType: hard @@ -7458,9 +7726,9 @@ __metadata: linkType: hard "collect-v8-coverage@npm:^1.0.0": - version: 1.0.2 - resolution: "collect-v8-coverage@npm:1.0.2" - checksum: 10/30ea7d5c9ee51f2fdba4901d4186c5b7114a088ef98fd53eda3979da77eed96758a2cae81cc6d97e239aaea6065868cf908b24980663f7b7e96aa291b3e12fa4 + version: 1.0.3 + resolution: "collect-v8-coverage@npm:1.0.3" + checksum: 10/656443261fb7b79cf79e89cba4b55622b07c1d4976c630829d7c5c585c73cda1c2ff101f316bfb19bb9e2c58d724c7db1f70a21e213dcd14099227c5e6019860 languageName: node linkType: hard @@ -7489,10 +7757,10 @@ __metadata: languageName: node linkType: hard -"commander@npm:^12.1.0": - version: 12.1.0 - resolution: "commander@npm:12.1.0" - checksum: 10/cdaeb672d979816853a4eed7f1310a9319e8b976172485c2a6b437ed0db0a389a44cfb222bfbde772781efa9f215bdd1b936f80d6b249485b465c6cb906e1f93 +"commander@npm:^14.0.0": + version: 14.0.2 + resolution: "commander@npm:14.0.2" + checksum: 10/2d202db5e5f9bb770112a3c1579b893d17ac6f6d932183077308bdd96d0f87f0bbe6a68b5b9ed2cf3b2514be6bb7de637480703c0e2db9741ee1b383237deb26 languageName: node linkType: hard @@ -7521,6 +7789,13 @@ __metadata: languageName: node linkType: hard +"comment-parser@npm:^1.4.1": + version: 1.4.3 + resolution: "comment-parser@npm:1.4.3" + checksum: 10/9e82c5653625f1d4ea86049f371446882d572aac2b4e5762efe5cbaab6b60eccbd3163fe9d4b8c768a6c9f5e5697d88c870d446c0bf72433635772dbde53013b + languageName: node + linkType: hard + "concat-map@npm:0.0.1": version: 0.0.1 resolution: "concat-map@npm:0.0.1" @@ -7540,7 +7815,7 @@ __metadata: languageName: node linkType: hard -"content-disposition@npm:0.5.4": +"content-disposition@npm:~0.5.4": version: 0.5.4 resolution: "content-disposition@npm:0.5.4" dependencies: @@ -7557,30 +7832,30 @@ __metadata: linkType: hard "contentful-resolve-response@npm:^1.9.0": - version: 1.9.0 - resolution: "contentful-resolve-response@npm:1.9.0" + version: 1.9.5 + resolution: "contentful-resolve-response@npm:1.9.5" dependencies: - fast-copy: "npm:^2.1.7" - checksum: 10/0c5daa59a3a6b020f9b5316812e3f14e62833b4aead008527c5bfde6549365e8e8e9f373af8836f06ca7b2023d861fdd2c241d3e74d3797133d18983be8bb3b3 + fast-copy: "npm:^3.0.2" + checksum: 10/8484dc1a7ef3700fb4a414a965ad8c6035990b16ca395143db41901a70dfac9676290baa7f93baa4d58869800eb1a3846b76f64c7595976b312419a0b1ed14bb languageName: node linkType: hard "contentful-sdk-core@npm:^8.3.1": - version: 8.3.1 - resolution: "contentful-sdk-core@npm:8.3.1" + version: 8.3.2 + resolution: "contentful-sdk-core@npm:8.3.2" dependencies: fast-copy: "npm:^2.1.7" lodash.isplainobject: "npm:^4.0.6" lodash.isstring: "npm:^4.0.1" p-throttle: "npm:^4.1.1" qs: "npm:^6.11.2" - checksum: 10/645d3a5d296d0e2a5ce87cceb04cf1ddf572183b5946cb1b3b717436bc7be96864216225fb845e61850d580436021c6284e7c95da0600a16c89c0af81a5f0d2c + checksum: 10/4af0aba2bb7e3db3ebf260fea74843de89f150f5af883134c370eb695fd8b2587cf94d4524d03020286f565eb3bff7b12d42f2a38718b62eb75cb28556e40f42 languageName: node linkType: hard "contentful@npm:^10.15.0": - version: 10.15.0 - resolution: "contentful@npm:10.15.0" + version: 10.15.1 + resolution: "contentful@npm:10.15.1" dependencies: "@contentful/content-source-maps": "npm:^0.11.0" "@contentful/rich-text-types": "npm:^16.0.2" @@ -7589,7 +7864,7 @@ __metadata: contentful-sdk-core: "npm:^8.3.1" json-stringify-safe: "npm:^5.0.1" type-fest: "npm:^4.0.0" - checksum: 10/b57c51faa99074a2f60c930c4827d1f8fe9867a359e53738532bbe859f5d72e750645fa4e195e65ad015811f344d95a0b3cebe6debef7d4e92ce9510bd55939e + checksum: 10/eb913a79e38d87bc7fb3a79952e4d7c5a1de5cccfbe0a012e8131c9c1e5a0a525cfcb7eaea971b02fb9e57b9e49c71ce96dd7096c3f65483992017ef70de80e5 languageName: node linkType: hard @@ -7607,17 +7882,17 @@ __metadata: languageName: node linkType: hard -"cookie-signature@npm:1.0.6": - version: 1.0.6 - resolution: "cookie-signature@npm:1.0.6" - checksum: 10/f4e1b0a98a27a0e6e66fd7ea4e4e9d8e038f624058371bf4499cfcd8f3980be9a121486995202ba3fca74fbed93a407d6d54d43a43f96fd28d0bd7a06761591a +"cookie-signature@npm:~1.0.6": + version: 1.0.7 + resolution: "cookie-signature@npm:1.0.7" + checksum: 10/1a62808cd30d15fb43b70e19829b64d04b0802d8ef00275b57d152de4ae6a3208ca05c197b6668d104c4d9de389e53ccc2d3bc6bcaaffd9602461417d8c40710 languageName: node linkType: hard -"cookie@npm:0.7.1": - version: 0.7.1 - resolution: "cookie@npm:0.7.1" - checksum: 10/aec6a6aa0781761bf55d60447d6be08861d381136a0fe94aa084fddd4f0300faa2b064df490c6798adfa1ebaef9e0af9b08a189c823e0811b8b313b3d9a03380 +"cookie@npm:~0.7.1": + version: 0.7.2 + resolution: "cookie@npm:0.7.2" + checksum: 10/24b286c556420d4ba4e9bc09120c9d3db7d28ace2bd0f8ccee82422ce42322f73c8312441271e5eefafbead725980e5996cc02766dbb89a90ac7f5636ede608f languageName: node linkType: hard @@ -7670,7 +7945,7 @@ __metadata: languageName: node linkType: hard -"create-hmac@npm:^1.1.4, create-hmac@npm:^1.1.7": +"create-hmac@npm:^1.1.7": version: 1.1.7 resolution: "create-hmac@npm:1.1.7" dependencies: @@ -7693,7 +7968,7 @@ __metadata: languageName: node linkType: hard -"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.3, cross-spawn@npm:^7.0.6": +"cross-spawn@npm:^7.0.3, cross-spawn@npm:^7.0.6": version: 7.0.6 resolution: "cross-spawn@npm:7.0.6" dependencies: @@ -7747,24 +8022,15 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.3.6, debug@npm:^4.3.7": - version: 4.4.0 - resolution: "debug@npm:4.4.0" +"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.4.0, debug@npm:^4.4.1, debug@npm:^4.4.3": + version: 4.4.3 + resolution: "debug@npm:4.4.3" dependencies: ms: "npm:^2.1.3" peerDependenciesMeta: supports-color: optional: true - checksum: 10/1847944c2e3c2c732514b93d11886575625686056cd765336212dc15de2d2b29612b6cd80e1afba767bb8e1803b778caf9973e98169ef1a24a7a7009e1820367 - languageName: node - linkType: hard - -"debug@npm:^3.2.7": - version: 3.2.7 - resolution: "debug@npm:3.2.7" - dependencies: - ms: "npm:^2.1.1" - checksum: 10/d86fd7be2b85462297ea16f1934dc219335e802f629ca9a69b63ed8ed041dda492389bb2ee039217c02e5b54792b1c51aa96ae954cf28634d363a2360c7a1639 + checksum: 10/9ada3434ea2993800bd9a1e320bd4aa7af69659fb51cca685d390949434bc0a8873c21ed7c9b852af6f2455a55c6d050aa3937d52b3c69f796dab666f762acad languageName: node linkType: hard @@ -7786,9 +8052,9 @@ __metadata: linkType: hard "decimal.js@npm:^10.2.1": - version: 10.4.3 - resolution: "decimal.js@npm:10.4.3" - checksum: 10/de663a7bc4d368e3877db95fcd5c87b965569b58d16cdc4258c063d231ca7118748738df17cd638f7e9dd0be8e34cec08d7234b20f1f2a756a52fc5a38b188d0 + version: 10.6.0 + resolution: "decimal.js@npm:10.6.0" + checksum: 10/c0d45842d47c311d11b38ce7ccc911121953d4df3ebb1465d92b31970eb4f6738a065426a06094af59bee4b0d64e42e7c8984abd57b6767c64ea90cf90bb4a69 languageName: node linkType: hard @@ -7821,19 +8087,19 @@ __metadata: linkType: hard "default-browser-id@npm:^5.0.0": - version: 5.0.0 - resolution: "default-browser-id@npm:5.0.0" - checksum: 10/185bfaecec2c75fa423544af722a3469b20704c8d1942794a86e4364fe7d9e8e9f63241a5b769d61c8151993bc65833a5b959026fa1ccea343b3db0a33aa6deb + version: 5.0.1 + resolution: "default-browser-id@npm:5.0.1" + checksum: 10/52c637637bcd76bfe974462a2f1dd75cb04784c2852935575760f82e1fd338e5e80d3c45a9b01fdbb1e450553a830bb163b004d2eca223c5573989f82232a072 languageName: node linkType: hard "default-browser@npm:^5.2.1": - version: 5.2.1 - resolution: "default-browser@npm:5.2.1" + version: 5.4.0 + resolution: "default-browser@npm:5.4.0" dependencies: bundle-name: "npm:^4.1.0" default-browser-id: "npm:^5.0.0" - checksum: 10/afab7eff7b7f5f7a94d9114d1ec67273d3fbc539edf8c0f80019879d53aa71e867303c6f6d7cffeb10a6f3cfb59d4f963dba3f9c96830b4540cc7339a1bf9840 + checksum: 10/cac0222ca5c9a3387d25337228689652ab33679a6566995c7194a75af7e554e91ec9ac92a70bfaa8e8089eae9f466ae99267bb38601282aade89b200f50a765c languageName: node linkType: hard @@ -7895,7 +8161,7 @@ __metadata: languageName: node linkType: hard -"depd@npm:2.0.0": +"depd@npm:2.0.0, depd@npm:~2.0.0": version: 2.0.0 resolution: "depd@npm:2.0.0" checksum: 10/c0c8ff36079ce5ada64f46cc9d6fd47ebcf38241105b6e0c98f412e8ad91f084bcf906ff644cc3a4bd876ca27a62accb8b0fff72ea6ed1a414b89d8506f4a5ca @@ -7909,7 +8175,7 @@ __metadata: languageName: node linkType: hard -"destroy@npm:1.2.0": +"destroy@npm:1.2.0, destroy@npm:~1.2.0": version: 1.2.0 resolution: "destroy@npm:1.2.0" checksum: 10/0acb300b7478a08b92d810ab229d5afe0d2f4399272045ab22affa0d99dbaf12637659411530a6fcd597a9bdac718fc94373a61a95b4651bbc7b83684a565e38 @@ -7931,9 +8197,9 @@ __metadata: linkType: hard "detect-indent@npm:^7.0.1": - version: 7.0.1 - resolution: "detect-indent@npm:7.0.1" - checksum: 10/cbf3f0b1c3c881934ca94428e1179b26ab2a587e0d719031d37a67fb506d49d067de54ff057cb1e772e75975fed5155c01cd4518306fee60988b1486e3fc7768 + version: 7.0.2 + resolution: "detect-indent@npm:7.0.2" + checksum: 10/ef215d1b55a14f677ce03e840973b25362b6f8cd3f566bc82831fa1abb2be6a95423729bc573dc2334b1371ad7be18d9ec67e1a9611b71a04cb6d63f0d8e54cc languageName: node linkType: hard @@ -7944,7 +8210,7 @@ __metadata: languageName: node linkType: hard -"detect-newline@npm:^4.0.0": +"detect-newline@npm:^4.0.1": version: 4.0.1 resolution: "detect-newline@npm:4.0.1" checksum: 10/0409ecdfb93419591ccff24fccfe2ddddad29b66637d1ed898872125b25af05014fdeedc9306339577060f69f59fe6e9830cdd80948597f136dfbffefa60599c @@ -7995,15 +8261,6 @@ __metadata: languageName: node linkType: hard -"doctrine@npm:^3.0.0": - version: 3.0.0 - resolution: "doctrine@npm:3.0.0" - dependencies: - esutils: "npm:^2.0.2" - checksum: 10/b4b28f1df5c563f7d876e7461254a4597b8cabe915abe94d7c5d1633fed263fcf9a85e8d3836591fc2d040108e822b0d32758e5ec1fe31c590dc7e08086e3e48 - languageName: node - linkType: hard - "domexception@npm:^2.0.1": version: 2.0.1 resolution: "domexception@npm:2.0.1" @@ -8047,10 +8304,10 @@ __metadata: languageName: node linkType: hard -"electron-to-chromium@npm:^1.5.73": - version: 1.5.79 - resolution: "electron-to-chromium@npm:1.5.79" - checksum: 10/c5b25ba04b4f4b46c4024b96e00e43adcd6c321b48c74c8d2660f69704901da5a6592009cbf96c36c89e3f6b53d7742e2b89514477fddbccf4e5c4caebed9d49 +"electron-to-chromium@npm:^1.5.263": + version: 1.5.267 + resolution: "electron-to-chromium@npm:1.5.267" + checksum: 10/05e55e810cb6a3cda8d29dfdeec7ac0e59727a77a796a157f1a1d65edac16d45eed69ed5c99e354872ab16c48967c2d0a0600653051ae380a3b7a4d6210b1e60 languageName: node linkType: hard @@ -8090,13 +8347,6 @@ __metadata: languageName: node linkType: hard -"encodeurl@npm:~1.0.2": - version: 1.0.2 - resolution: "encodeurl@npm:1.0.2" - checksum: 10/e50e3d508cdd9c4565ba72d2012e65038e5d71bdc9198cb125beb6237b5b1ade6c0d343998da9e170fb2eae52c1bed37d4d6d98a46ea423a0cddbed5ac3f780c - languageName: node - linkType: hard - "encodeurl@npm:~2.0.0": version: 2.0.0 resolution: "encodeurl@npm:2.0.0" @@ -8113,20 +8363,20 @@ __metadata: languageName: node linkType: hard -"enhanced-resolve@npm:^5.15.0, enhanced-resolve@npm:^5.17.1": - version: 5.18.0 - resolution: "enhanced-resolve@npm:5.18.0" +"enhanced-resolve@npm:^5.17.1": + version: 5.18.4 + resolution: "enhanced-resolve@npm:5.18.4" dependencies: graceful-fs: "npm:^4.2.4" tapable: "npm:^2.2.0" - checksum: 10/e88463ef97b68d40d0da0cd0c572e23f43dba0be622d6d44eae5cafed05f0c5dac43e463a83a86c4f70186d029357f82b56d9e1e47e8fc91dce3d6602f8bd6ce + checksum: 10/dcd477cb694d9cc84109a03269c13d3da0851d50099fd3fa7c56b2867dd720d59c7f1431bd47c9cad2825ad52588bd71d3a68cf1e5ee0bc57551d8a3fab4e6f2 languageName: node linkType: hard -"entities@npm:^4.5.0": - version: 4.5.0 - resolution: "entities@npm:4.5.0" - checksum: 10/ede2a35c9bce1aeccd055a1b445d41c75a14a2bb1cd22e242f20cf04d236cdcd7f9c859eb83f76885327bfae0c25bf03303665ee1ce3d47c5927b98b0e3e3d48 +"entities@npm:^7.0.0": + version: 7.0.0 + resolution: "entities@npm:7.0.0" + checksum: 10/048cae50a2988411aa28db596392b04cb591f73cbc86d623383fe3cb9c307d666d045a2d1efe97bc07f5ffc8d8579408a4a2e867a005a8d7770cf83aad6eab70 languageName: node linkType: hard @@ -8145,11 +8395,11 @@ __metadata: linkType: hard "error-ex@npm:^1.3.1": - version: 1.3.2 - resolution: "error-ex@npm:1.3.2" + version: 1.3.4 + resolution: "error-ex@npm:1.3.4" dependencies: is-arrayish: "npm:^0.2.1" - checksum: 10/d547740aa29c34e753fb6fed2c5de81802438529c12b3673bd37b6bb1fe49b9b7abdc3c11e6062fe625d8a296b3cf769a80f878865e25e685f787763eede3ffb + checksum: 10/ae3939fd4a55b1404e877df2080c6b59acc516d5b7f08a181040f78f38b4e2399633bfed2d9a21b91c803713fff7295ac70bebd8f3657ef352a95c2cd9aa2e4b languageName: node linkType: hard @@ -8167,13 +8417,6 @@ __metadata: languageName: node linkType: hard -"es-module-lexer@npm:^1.5.3": - version: 1.6.0 - resolution: "es-module-lexer@npm:1.6.0" - checksum: 10/807ee7020cc46a9c970c78cad1f2f3fc139877e5ebad7f66dbfbb124d451189ba1c48c1c632bd5f8ce1b8af2caef3fca340ba044a410fa890d17b080a59024bb - languageName: node - linkType: hard - "es-object-atoms@npm:^1.0.0, es-object-atoms@npm:^1.1.1": version: 1.1.1 resolution: "es-object-atoms@npm:1.1.1" @@ -8183,36 +8426,48 @@ __metadata: languageName: node linkType: hard -"esbuild@npm:~0.25.0": - version: 0.25.9 - resolution: "esbuild@npm:0.25.9" - dependencies: - "@esbuild/aix-ppc64": "npm:0.25.9" - "@esbuild/android-arm": "npm:0.25.9" - "@esbuild/android-arm64": "npm:0.25.9" - "@esbuild/android-x64": "npm:0.25.9" - "@esbuild/darwin-arm64": "npm:0.25.9" - "@esbuild/darwin-x64": "npm:0.25.9" - "@esbuild/freebsd-arm64": "npm:0.25.9" - "@esbuild/freebsd-x64": "npm:0.25.9" - "@esbuild/linux-arm": "npm:0.25.9" - "@esbuild/linux-arm64": "npm:0.25.9" - "@esbuild/linux-ia32": "npm:0.25.9" - "@esbuild/linux-loong64": "npm:0.25.9" - "@esbuild/linux-mips64el": "npm:0.25.9" - "@esbuild/linux-ppc64": "npm:0.25.9" - "@esbuild/linux-riscv64": "npm:0.25.9" - "@esbuild/linux-s390x": "npm:0.25.9" - "@esbuild/linux-x64": "npm:0.25.9" - "@esbuild/netbsd-arm64": "npm:0.25.9" - "@esbuild/netbsd-x64": "npm:0.25.9" - "@esbuild/openbsd-arm64": "npm:0.25.9" - "@esbuild/openbsd-x64": "npm:0.25.9" - "@esbuild/openharmony-arm64": "npm:0.25.9" - "@esbuild/sunos-x64": "npm:0.25.9" - "@esbuild/win32-arm64": "npm:0.25.9" - "@esbuild/win32-ia32": "npm:0.25.9" - "@esbuild/win32-x64": "npm:0.25.9" +"es-set-tostringtag@npm:^2.1.0": + version: 2.1.0 + resolution: "es-set-tostringtag@npm:2.1.0" + dependencies: + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.6" + has-tostringtag: "npm:^1.0.2" + hasown: "npm:^2.0.2" + checksum: 10/86814bf8afbcd8966653f731415888019d4bc4aca6b6c354132a7a75bb87566751e320369654a101d23a91c87a85c79b178bcf40332839bd347aff437c4fb65f + languageName: node + linkType: hard + +"esbuild@npm:~0.27.0": + version: 0.27.2 + resolution: "esbuild@npm:0.27.2" + dependencies: + "@esbuild/aix-ppc64": "npm:0.27.2" + "@esbuild/android-arm": "npm:0.27.2" + "@esbuild/android-arm64": "npm:0.27.2" + "@esbuild/android-x64": "npm:0.27.2" + "@esbuild/darwin-arm64": "npm:0.27.2" + "@esbuild/darwin-x64": "npm:0.27.2" + "@esbuild/freebsd-arm64": "npm:0.27.2" + "@esbuild/freebsd-x64": "npm:0.27.2" + "@esbuild/linux-arm": "npm:0.27.2" + "@esbuild/linux-arm64": "npm:0.27.2" + "@esbuild/linux-ia32": "npm:0.27.2" + "@esbuild/linux-loong64": "npm:0.27.2" + "@esbuild/linux-mips64el": "npm:0.27.2" + "@esbuild/linux-ppc64": "npm:0.27.2" + "@esbuild/linux-riscv64": "npm:0.27.2" + "@esbuild/linux-s390x": "npm:0.27.2" + "@esbuild/linux-x64": "npm:0.27.2" + "@esbuild/netbsd-arm64": "npm:0.27.2" + "@esbuild/netbsd-x64": "npm:0.27.2" + "@esbuild/openbsd-arm64": "npm:0.27.2" + "@esbuild/openbsd-x64": "npm:0.27.2" + "@esbuild/openharmony-arm64": "npm:0.27.2" + "@esbuild/sunos-x64": "npm:0.27.2" + "@esbuild/win32-arm64": "npm:0.27.2" + "@esbuild/win32-ia32": "npm:0.27.2" + "@esbuild/win32-x64": "npm:0.27.2" dependenciesMeta: "@esbuild/aix-ppc64": optional: true @@ -8268,7 +8523,7 @@ __metadata: optional: true bin: esbuild: bin/esbuild - checksum: 10/fc174ae7f646ad413adb641c7e46f16be575e462ed209866b55d5954d382e5da839e3f3f89a8e42e2b71d48895cc636ba43523011249fe5ff9c63d8d39d3a364 + checksum: 10/7f1229328b0efc63c4184a61a7eb303df1e99818cc1d9e309fb92600703008e69821e8e984e9e9f54a627da14e0960d561db3a93029482ef96dc82dd267a60c2 languageName: node linkType: hard @@ -8330,13 +8585,13 @@ __metadata: linkType: hard "eslint-config-prettier@npm:^9.1.0": - version: 9.1.0 - resolution: "eslint-config-prettier@npm:9.1.0" + version: 9.1.2 + resolution: "eslint-config-prettier@npm:9.1.2" peerDependencies: eslint: ">=7.0.0" bin: eslint-config-prettier: bin/cli.js - checksum: 10/411e3b3b1c7aa04e3e0f20d561271b3b909014956c4dba51c878bf1a23dbb8c800a3be235c46c4732c70827276e540b6eed4636d9b09b444fd0a8e07f0fcd830 + checksum: 10/e4bba2d76df9dc6e2adca2866e544bfd1ff32232fc483743c04cedd93918a90a327b56d4a7e3f9d3fa32d90bd50b034d09df987860260064b18c026b8bbd15aa languageName: node linkType: hard @@ -8356,29 +8611,32 @@ __metadata: languageName: node linkType: hard -"eslint-import-resolver-node@npm:^0.3.9": - version: 0.3.9 - resolution: "eslint-import-resolver-node@npm:0.3.9" +"eslint-import-context@npm:^0.1.9": + version: 0.1.9 + resolution: "eslint-import-context@npm:0.1.9" dependencies: - debug: "npm:^3.2.7" - is-core-module: "npm:^2.13.0" - resolve: "npm:^1.22.4" - checksum: 10/d52e08e1d96cf630957272e4f2644dcfb531e49dcfd1edd2e07e43369eb2ec7a7d4423d417beee613201206ff2efa4eb9a582b5825ee28802fc7c71fcd53ca83 + get-tsconfig: "npm:^4.10.1" + stable-hash-x: "npm:^0.2.0" + peerDependencies: + unrs-resolver: ^1.0.0 + peerDependenciesMeta: + unrs-resolver: + optional: true + checksum: 10/f0778126bb3aae57c8c68946c71c4418927e9d39f72099b799d9c47a3b5712d6c9166b63ee8be58a020961dcc9216df09c856b825336af375ccbbdeedfc82a99 languageName: node linkType: hard "eslint-import-resolver-typescript@npm:^3.6.3": - version: 3.7.0 - resolution: "eslint-import-resolver-typescript@npm:3.7.0" + version: 3.10.1 + resolution: "eslint-import-resolver-typescript@npm:3.10.1" dependencies: "@nolyfill/is-core-module": "npm:1.0.39" - debug: "npm:^4.3.7" - enhanced-resolve: "npm:^5.15.0" - fast-glob: "npm:^3.3.2" - get-tsconfig: "npm:^4.7.5" - is-bun-module: "npm:^1.0.2" - is-glob: "npm:^4.0.3" - stable-hash: "npm:^0.0.4" + debug: "npm:^4.4.0" + get-tsconfig: "npm:^4.10.0" + is-bun-module: "npm:^2.0.0" + stable-hash: "npm:^0.0.5" + tinyglobby: "npm:^0.2.13" + unrs-resolver: "npm:^1.6.2" peerDependencies: eslint: "*" eslint-plugin-import: "*" @@ -8388,7 +8646,7 @@ __metadata: optional: true eslint-plugin-import-x: optional: true - checksum: 10/8158730c11e562c56ed9bf7236dc75bce35b6992dc32c39ac2f4177ab77fca97b95999850204a6458054243607b54aee88c028a61fed4184f24f425fa1afff01 + checksum: 10/b8d6a9b2045c70f043f722f78c9e65bc0283126f0ad92c8f07473f7647d77f7b1562f765a472f17e06b81897b407091c0ec9f2e4592b158c9fd92d0b0c33de89 languageName: node linkType: hard @@ -8406,31 +8664,34 @@ __metadata: linkType: hard "eslint-plugin-import-x@npm:^4.3.0": - version: 4.6.1 - resolution: "eslint-plugin-import-x@npm:4.6.1" + version: 4.16.1 + resolution: "eslint-plugin-import-x@npm:4.16.1" dependencies: - "@types/doctrine": "npm:^0.0.9" - "@typescript-eslint/scope-manager": "npm:^8.1.0" - "@typescript-eslint/utils": "npm:^8.1.0" - debug: "npm:^4.3.4" - doctrine: "npm:^3.0.0" - enhanced-resolve: "npm:^5.17.1" - eslint-import-resolver-node: "npm:^0.3.9" - get-tsconfig: "npm:^4.7.3" + "@typescript-eslint/types": "npm:^8.35.0" + comment-parser: "npm:^1.4.1" + debug: "npm:^4.4.1" + eslint-import-context: "npm:^0.1.9" is-glob: "npm:^4.0.3" - minimatch: "npm:^9.0.3" - semver: "npm:^7.6.3" - stable-hash: "npm:^0.0.4" - tslib: "npm:^2.6.3" + minimatch: "npm:^9.0.3 || ^10.0.1" + semver: "npm:^7.7.2" + stable-hash-x: "npm:^0.2.0" + unrs-resolver: "npm:^1.9.2" peerDependencies: + "@typescript-eslint/utils": ^8.0.0 eslint: ^8.57.0 || ^9.0.0 - checksum: 10/514d8147f7bdff4accbeb06c294b68670287ecdaada9b2fbd3a2ba89d35860095cadd5a4175894fc8e75ba3b2be83dc172eba5cc71b823fd0dd846b7d49877ff + eslint-import-resolver-node: "*" + peerDependenciesMeta: + "@typescript-eslint/utils": + optional: true + eslint-import-resolver-node: + optional: true + checksum: 10/d1390d49499b613c1334e48fe8b104221584a1473fbec8974584002561aacef5347c4450c559df6fe24c3abe3b0d167eefdc5510e794e96a4ea4f9cb1d501515 languageName: node linkType: hard "eslint-plugin-jest@npm:^28.8.3": - version: 28.10.0 - resolution: "eslint-plugin-jest@npm:28.10.0" + version: 28.14.0 + resolution: "eslint-plugin-jest@npm:28.14.0" dependencies: "@typescript-eslint/utils": "npm:^6.0.0 || ^7.0.0 || ^8.0.0" peerDependencies: @@ -8442,66 +8703,66 @@ __metadata: optional: true jest: optional: true - checksum: 10/cb19f2171e93873d9207425c4fa52ec49018579d73ece23a1ffea90f3ffd284b0e48f74ff4f50b15ff31882b06b03fec0e48c9c6ca830acdeff8931802ef0a9e + checksum: 10/6032497bd97d6dd010450d5fdf535b8613a2789f4f83764ae04361c48d06d92f3d9b2e4350914b8fd857b6e611ba2b5282a1133ab8ec51b3e7053f9d336058e6 languageName: node linkType: hard "eslint-plugin-jsdoc@npm:^50.2.4": - version: 50.6.1 - resolution: "eslint-plugin-jsdoc@npm:50.6.1" + version: 50.8.0 + resolution: "eslint-plugin-jsdoc@npm:50.8.0" dependencies: - "@es-joy/jsdoccomment": "npm:~0.49.0" + "@es-joy/jsdoccomment": "npm:~0.50.2" are-docs-informative: "npm:^0.0.2" comment-parser: "npm:1.4.1" - debug: "npm:^4.3.6" + debug: "npm:^4.4.1" escape-string-regexp: "npm:^4.0.0" - espree: "npm:^10.1.0" + espree: "npm:^10.3.0" esquery: "npm:^1.6.0" - parse-imports: "npm:^2.1.1" - semver: "npm:^7.6.3" + parse-imports-exports: "npm:^0.2.4" + semver: "npm:^7.7.2" spdx-expression-parse: "npm:^4.0.0" - synckit: "npm:^0.9.1" peerDependencies: eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 - checksum: 10/53fceff38a5317bb7c42c15a622100515aec89aea0d2bbf07e7d2d07eacdaa10ce625232a1bc7c1497f7bbe044675123d30cd3e123fa52fe5c7a9c336a59709c + checksum: 10/8857bb6583e04af0a1949e602e2b5b2abc5a951583bdc5a3baa0cc24f7c16db367cbc44e008c45b06dc2029685f0eb1ff6a0bb91e90fd82710ce30952d878d5d languageName: node linkType: hard "eslint-plugin-n@npm:^17.10.3": - version: 17.15.1 - resolution: "eslint-plugin-n@npm:17.15.1" + version: 17.23.2 + resolution: "eslint-plugin-n@npm:17.23.2" dependencies: - "@eslint-community/eslint-utils": "npm:^4.4.1" + "@eslint-community/eslint-utils": "npm:^4.5.0" enhanced-resolve: "npm:^5.17.1" eslint-plugin-es-x: "npm:^7.8.0" get-tsconfig: "npm:^4.8.1" globals: "npm:^15.11.0" + globrex: "npm:^0.1.2" ignore: "npm:^5.3.2" - minimatch: "npm:^9.0.5" semver: "npm:^7.6.3" + ts-declaration-location: "npm:^1.0.6" peerDependencies: eslint: ">=8.23.0" - checksum: 10/43fc161949fa0346ac7063a30580cd0db27e216b8e6a48d73d0bf4f10b88e9b65f263399843b3fe2087f766f264d16f0cbe8f2f898591516842201dc115a2d21 + checksum: 10/67a15908b27fe5f9aee97d280c3e869debef58fc941b285ace6dab0baabe5263086f90d72a059f9e6efe0a427b77d42912892146eb8c882d085733c7cb068ead languageName: node linkType: hard "eslint-plugin-prettier@npm:^5.2.1": - version: 5.2.1 - resolution: "eslint-plugin-prettier@npm:5.2.1" + version: 5.5.5 + resolution: "eslint-plugin-prettier@npm:5.5.5" dependencies: - prettier-linter-helpers: "npm:^1.0.0" - synckit: "npm:^0.9.1" + prettier-linter-helpers: "npm:^1.0.1" + synckit: "npm:^0.11.12" peerDependencies: "@types/eslint": ">=8.0.0" eslint: ">=8.0.0" - eslint-config-prettier: "*" + eslint-config-prettier: ">= 7.0.0 <10.0.0 || >=10.1.0" prettier: ">=3.0.0" peerDependenciesMeta: "@types/eslint": optional: true eslint-config-prettier: optional: true - checksum: 10/10ddf68215237e327af09a47adab4c63f3885fda4fb28c4c42d1fc5f47d8a0cc45df6484799360ff1417a0aa3c77c3aaac49d7e9dfd145557b17e2d7ecc2a27c + checksum: 10/36c22c2fa2fd7c61ed292af1280e1d8f94dfe1671eacc5a503a249ca4b27fd226dbf6a1820457d611915926946f42729488d2dc7a5c320601e6cf1fad0d28f66 languageName: node linkType: hard @@ -8548,8 +8809,8 @@ __metadata: linkType: hard "eslint@npm:^9.39.1": - version: 9.39.1 - resolution: "eslint@npm:9.39.1" + version: 9.39.2 + resolution: "eslint@npm:9.39.2" dependencies: "@eslint-community/eslint-utils": "npm:^4.8.0" "@eslint-community/regexpp": "npm:^4.12.1" @@ -8557,7 +8818,7 @@ __metadata: "@eslint/config-helpers": "npm:^0.4.2" "@eslint/core": "npm:^0.17.0" "@eslint/eslintrc": "npm:^3.3.1" - "@eslint/js": "npm:9.39.1" + "@eslint/js": "npm:9.39.2" "@eslint/plugin-kit": "npm:^0.4.1" "@humanfs/node": "npm:^0.16.6" "@humanwhocodes/module-importer": "npm:^1.0.1" @@ -8592,11 +8853,11 @@ __metadata: optional: true bin: eslint: bin/eslint.js - checksum: 10/c85fefe4a81a1a476e62087366907af830b62a6565ac153f6d50a100a42a946aeb049c3af8f06c0e091105ba0fe97ac109f379f32755a67f66ecb7d4d1e4dca3 + checksum: 10/53ff0e9c8264e7e8d40d50fdc0c0df0b701cfc5289beedfb686c214e3e7b199702f894bbd1bb48653727bb1ecbd1147cf5f555a4ae71e1daf35020cdc9072d9f languageName: node linkType: hard -"espree@npm:^10.0.1, espree@npm:^10.1.0, espree@npm:^10.4.0": +"espree@npm:^10.0.1, espree@npm:^10.3.0, espree@npm:^10.4.0": version: 10.4.0 resolution: "espree@npm:10.4.0" dependencies: @@ -8618,11 +8879,11 @@ __metadata: linkType: hard "esquery@npm:^1.5.0, esquery@npm:^1.6.0": - version: 1.6.0 - resolution: "esquery@npm:1.6.0" + version: 1.7.0 + resolution: "esquery@npm:1.7.0" dependencies: estraverse: "npm:^5.1.0" - checksum: 10/c587fb8ec9ed83f2b1bc97cf2f6854cc30bf784a79d62ba08c6e358bf22280d69aee12827521cf38e69ae9761d23fb7fde593ce315610f85655c139d99b05e5a + checksum: 10/4afaf3089367e1f5885caa116ef386dffd8bfd64da21fd3d0e56e938d2667cfb2e5400ab4a825aa70e799bb3741e5b5d63c0b94d86e2d4cf3095c9e64b2f5a15 languageName: node linkType: hard @@ -8750,17 +9011,17 @@ __metadata: linkType: hard "ethers@npm:^6.12.0": - version: 6.13.2 - resolution: "ethers@npm:6.13.2" + version: 6.16.0 + resolution: "ethers@npm:6.16.0" dependencies: "@adraffy/ens-normalize": "npm:1.10.1" "@noble/curves": "npm:1.2.0" "@noble/hashes": "npm:1.3.2" - "@types/node": "npm:18.15.13" + "@types/node": "npm:22.7.5" aes-js: "npm:4.0.0-beta.5" - tslib: "npm:2.4.0" + tslib: "npm:2.7.0" ws: "npm:8.17.1" - checksum: 10/e611c2e2c5340982dfd1f004895f55abda11748a7edec9e6315226dec42d58aa61b827dd389ec904db5f9a244c475ae795e528da579251fdf62e914bde12809e + checksum: 10/7e980f0a77963fbe14321a3b9746c3ca3cad44932e28bb3506406a66c4b4d9dc1e60ed68d9d784224e9f2582a53d6a0a2e55a7c9559659681f4ad1f70e00e325 languageName: node linkType: hard @@ -8789,6 +9050,15 @@ __metadata: languageName: node linkType: hard +"events-universal@npm:^1.0.0": + version: 1.0.1 + resolution: "events-universal@npm:1.0.1" + dependencies: + bare-events: "npm:^2.7.0" + checksum: 10/71b2e6079b4dc030c613ef73d99f1acb369dd3ddb6034f49fd98b3e2c6632cde9f61c15fb1351004339d7c79672252a4694ecc46a6124dc794b558be50a83867 + languageName: node + linkType: hard + "events@npm:^3.3.0": version: 3.3.0 resolution: "events@npm:3.3.0" @@ -8869,62 +9139,63 @@ __metadata: languageName: node linkType: hard -"expect@npm:^29.0.0": - version: 29.7.0 - resolution: "expect@npm:29.7.0" +"expect@npm:^30.0.0": + version: 30.2.0 + resolution: "expect@npm:30.2.0" dependencies: - "@jest/expect-utils": "npm:^29.7.0" - jest-get-type: "npm:^29.6.3" - jest-matcher-utils: "npm:^29.7.0" - jest-message-util: "npm:^29.7.0" - jest-util: "npm:^29.7.0" - checksum: 10/63f97bc51f56a491950fb525f9ad94f1916e8a014947f8d8445d3847a665b5471b768522d659f5e865db20b6c2033d2ac10f35fcbd881a4d26407a4f6f18451a + "@jest/expect-utils": "npm:30.2.0" + "@jest/get-type": "npm:30.1.0" + jest-matcher-utils: "npm:30.2.0" + jest-message-util: "npm:30.2.0" + jest-mock: "npm:30.2.0" + jest-util: "npm:30.2.0" + checksum: 10/cf98ab45ab2e9f2fb9943a3ae0097f72d63a94be179a19fd2818d8fdc3b7681d31cc8ef540606eb8dd967d9c44d73fef263a614e9de260c22943ffb122ad66fd languageName: node linkType: hard "exponential-backoff@npm:^3.1.1": - version: 3.1.1 - resolution: "exponential-backoff@npm:3.1.1" - checksum: 10/2d9bbb6473de7051f96790d5f9a678f32e60ed0aa70741dc7fdc96fec8d631124ec3374ac144387604f05afff9500f31a1d45bd9eee4cdc2e4f9ad2d9b9d5dbd + version: 3.1.3 + resolution: "exponential-backoff@npm:3.1.3" + checksum: 10/ca25962b4bbab943b7c4ed0b5228e263833a5063c65e1cdeac4be9afad350aae5466e8e619b5051f4f8d37b2144a2d6e8fcc771b6cc82934f7dade2f964f652c languageName: node linkType: hard "express@npm:^4.21.2": - version: 4.21.2 - resolution: "express@npm:4.21.2" + version: 4.22.1 + resolution: "express@npm:4.22.1" dependencies: accepts: "npm:~1.3.8" array-flatten: "npm:1.1.1" - body-parser: "npm:1.20.3" - content-disposition: "npm:0.5.4" + body-parser: "npm:~1.20.3" + content-disposition: "npm:~0.5.4" content-type: "npm:~1.0.4" - cookie: "npm:0.7.1" - cookie-signature: "npm:1.0.6" + cookie: "npm:~0.7.1" + cookie-signature: "npm:~1.0.6" debug: "npm:2.6.9" depd: "npm:2.0.0" encodeurl: "npm:~2.0.0" escape-html: "npm:~1.0.3" etag: "npm:~1.8.1" - finalhandler: "npm:1.3.1" - fresh: "npm:0.5.2" - http-errors: "npm:2.0.0" + finalhandler: "npm:~1.3.1" + fresh: "npm:~0.5.2" + http-errors: "npm:~2.0.0" merge-descriptors: "npm:1.0.3" methods: "npm:~1.1.2" - on-finished: "npm:2.4.1" + on-finished: "npm:~2.4.1" parseurl: "npm:~1.3.3" - path-to-regexp: "npm:0.1.12" + path-to-regexp: "npm:~0.1.12" proxy-addr: "npm:~2.0.7" - qs: "npm:6.13.0" + qs: "npm:~6.14.0" range-parser: "npm:~1.2.1" safe-buffer: "npm:5.2.1" - send: "npm:0.19.0" - serve-static: "npm:1.16.2" + send: "npm:~0.19.0" + serve-static: "npm:~1.16.2" setprototypeof: "npm:1.2.0" - statuses: "npm:2.0.1" + statuses: "npm:~2.0.1" type-is: "npm:~1.6.18" utils-merge: "npm:1.0.1" vary: "npm:~1.1.2" - checksum: 10/34571c442fc8c9f2c4b442d2faa10ea1175cf8559237fc6a278f5ce6254a8ffdbeb9a15d99f77c1a9f2926ab183e3b7ba560e3261f1ad4149799e3412ab66bd1 + checksum: 10/f33c1bd0c7d36e2a1f18de9cdc176469d32f68e20258d2941b8d296ab9a4fd9011872c246391bf87714f009fac5114c832ec5ac65cbee39421f1258801eb8470 languageName: node linkType: hard @@ -8956,6 +9227,13 @@ __metadata: languageName: node linkType: hard +"fast-copy@npm:^3.0.2": + version: 3.0.2 + resolution: "fast-copy@npm:3.0.2" + checksum: 10/97e1022e2aaa27acf4a986d679310bfd66bfb87fe8da9dd33b698e3e50189484001cf1eeb9670e19b59d9d299828ed86c8da354c954f125995ab2a6331c5f290 + languageName: node + linkType: hard + "fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3": version: 3.1.3 resolution: "fast-deep-equal@npm:3.1.3" @@ -8977,7 +9255,7 @@ __metadata: languageName: node linkType: hard -"fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.0, fast-glob@npm:^3.3.2": +"fast-glob@npm:^3.2.9": version: 3.3.3 resolution: "fast-glob@npm:3.3.3" dependencies: @@ -9019,13 +9297,13 @@ __metadata: linkType: hard "fast-xml-parser@npm:^4.4.1": - version: 4.4.1 - resolution: "fast-xml-parser@npm:4.4.1" + version: 4.5.3 + resolution: "fast-xml-parser@npm:4.5.3" dependencies: - strnum: "npm:^1.0.5" + strnum: "npm:^1.1.1" bin: fxparser: src/cli/cli.js - checksum: 10/0c05ab8703630d8c857fafadbd78d0020d3a8e54310c3842179cd4a0d9d97e96d209ce885e91241f4aa9dd8dfc2fd924a682741a423d65153cad34da2032ec44 + checksum: 10/ca22bf9d65c10b8447c1034c13403e90ecee210e2b3852690df3d8a42b8a46ec655fae7356096abd98a15b89ddaf11878587b1773e0c3be4cbc2ac4af4c7bf95 languageName: node linkType: hard @@ -9037,11 +9315,11 @@ __metadata: linkType: hard "fastq@npm:^1.6.0": - version: 1.17.1 - resolution: "fastq@npm:1.17.1" + version: 1.20.1 + resolution: "fastq@npm:1.20.1" dependencies: reusify: "npm:^1.0.4" - checksum: 10/a443180068b527dd7b3a63dc7f2a47ceca2f3e97b9c00a1efe5538757e6cc4056a3526df94308075d7727561baf09ebaa5b67da8dcbddb913a021c5ae69d1f69 + checksum: 10/ab2fe3a7a108112e7752cfe7fc11683c21e595913a6a593ad0b4415f31dddbfc283775ab66f2c8ccea6ab7cfc116157cbddcfae9798d9de98d08fe0a2c3e97b2 languageName: node linkType: hard @@ -9093,18 +9371,18 @@ __metadata: languageName: node linkType: hard -"finalhandler@npm:1.3.1": - version: 1.3.1 - resolution: "finalhandler@npm:1.3.1" +"finalhandler@npm:~1.3.1": + version: 1.3.2 + resolution: "finalhandler@npm:1.3.2" dependencies: debug: "npm:2.6.9" encodeurl: "npm:~2.0.0" escape-html: "npm:~1.0.3" - on-finished: "npm:2.4.1" + on-finished: "npm:~2.4.1" parseurl: "npm:~1.3.3" - statuses: "npm:2.0.1" + statuses: "npm:~2.0.2" unpipe: "npm:~1.0.0" - checksum: 10/4babe72969b7373b5842bc9f75c3a641a4d0f8eb53af6b89fa714d4460ce03fb92b28de751d12ba415e96e7e02870c436d67412120555e2b382640535697305b + checksum: 10/6cb4f9f80eaeb5a0fac4fdbd27a65d39271f040a0034df16556d896bfd855fd42f09da886781b3102117ea8fceba97b903c1f8b08df1fb5740576d5e0f481eed languageName: node linkType: hard @@ -9141,38 +9419,38 @@ __metadata: linkType: hard "firebase@npm:^11.2.0": - version: 11.2.0 - resolution: "firebase@npm:11.2.0" - dependencies: - "@firebase/analytics": "npm:0.10.11" - "@firebase/analytics-compat": "npm:0.2.17" - "@firebase/app": "npm:0.10.18" - "@firebase/app-check": "npm:0.8.11" - "@firebase/app-check-compat": "npm:0.3.18" - "@firebase/app-compat": "npm:0.2.48" + version: 11.10.0 + resolution: "firebase@npm:11.10.0" + dependencies: + "@firebase/ai": "npm:1.4.1" + "@firebase/analytics": "npm:0.10.17" + "@firebase/analytics-compat": "npm:0.2.23" + "@firebase/app": "npm:0.13.2" + "@firebase/app-check": "npm:0.10.1" + "@firebase/app-check-compat": "npm:0.3.26" + "@firebase/app-compat": "npm:0.4.2" "@firebase/app-types": "npm:0.9.3" - "@firebase/auth": "npm:1.8.2" - "@firebase/auth-compat": "npm:0.5.17" - "@firebase/data-connect": "npm:0.2.0" - "@firebase/database": "npm:1.0.11" - "@firebase/database-compat": "npm:2.0.2" - "@firebase/firestore": "npm:4.7.6" - "@firebase/firestore-compat": "npm:0.3.41" - "@firebase/functions": "npm:0.12.1" - "@firebase/functions-compat": "npm:0.3.18" - "@firebase/installations": "npm:0.6.12" - "@firebase/installations-compat": "npm:0.2.12" - "@firebase/messaging": "npm:0.12.16" - "@firebase/messaging-compat": "npm:0.2.16" - "@firebase/performance": "npm:0.6.12" - "@firebase/performance-compat": "npm:0.2.12" - "@firebase/remote-config": "npm:0.5.0" - "@firebase/remote-config-compat": "npm:0.2.12" - "@firebase/storage": "npm:0.13.5" - "@firebase/storage-compat": "npm:0.3.15" - "@firebase/util": "npm:1.10.3" - "@firebase/vertexai": "npm:1.0.3" - checksum: 10/9a3a8f6be4b34e76428cf6ae11bff8141772b7b3ec8a8fe0ef69188fdf2a602bd6e542a663133f90845d5a358daadeadf760841cf3ea8ec726475ee84a694ea4 + "@firebase/auth": "npm:1.10.8" + "@firebase/auth-compat": "npm:0.5.28" + "@firebase/data-connect": "npm:0.3.10" + "@firebase/database": "npm:1.0.20" + "@firebase/database-compat": "npm:2.0.11" + "@firebase/firestore": "npm:4.8.0" + "@firebase/firestore-compat": "npm:0.3.53" + "@firebase/functions": "npm:0.12.9" + "@firebase/functions-compat": "npm:0.3.26" + "@firebase/installations": "npm:0.6.18" + "@firebase/installations-compat": "npm:0.2.18" + "@firebase/messaging": "npm:0.12.22" + "@firebase/messaging-compat": "npm:0.2.22" + "@firebase/performance": "npm:0.7.7" + "@firebase/performance-compat": "npm:0.2.20" + "@firebase/remote-config": "npm:0.6.5" + "@firebase/remote-config-compat": "npm:0.2.18" + "@firebase/storage": "npm:0.13.14" + "@firebase/storage-compat": "npm:0.3.24" + "@firebase/util": "npm:1.12.1" + checksum: 10/ec78a2e079ff3d18ce7579a56a646d2979e619e504d74066d33bfea4941a87eb8b0ebea67e99fa1a3d76fd2b858c92958304b05b5a3bab60b662fa70821b12b1 languageName: node linkType: hard @@ -9187,19 +9465,28 @@ __metadata: linkType: hard "flatted@npm:^3.2.9": - version: 3.3.1 - resolution: "flatted@npm:3.3.1" - checksum: 10/7b8376061d5be6e0d3658bbab8bde587647f68797cf6bfeae9dea0e5137d9f27547ab92aaff3512dd9d1299086a6d61be98e9d48a56d17531b634f77faadbc49 + version: 3.3.3 + resolution: "flatted@npm:3.3.3" + checksum: 10/8c96c02fbeadcf4e8ffd0fa24983241e27698b0781295622591fc13585e2f226609d95e422bcf2ef044146ffacb6b68b1f20871454eddf75ab3caa6ee5f4a1fe languageName: node linkType: hard "follow-redirects@npm:^1.15.6": - version: 1.15.6 - resolution: "follow-redirects@npm:1.15.6" + version: 1.15.11 + resolution: "follow-redirects@npm:1.15.11" peerDependenciesMeta: debug: optional: true - checksum: 10/70c7612c4cab18e546e36b991bbf8009a1a41cf85354afe04b113d1117569abf760269409cb3eb842d9f7b03d62826687086b081c566ea7b1e6613cf29030bf7 + checksum: 10/07372fd74b98c78cf4d417d68d41fdaa0be4dcacafffb9e67b1e3cf090bc4771515e65020651528faab238f10f9b9c0d9707d6c1574a6c0387c5de1042cde9ba + languageName: node + linkType: hard + +"for-each@npm:^0.3.5": + version: 0.3.5 + resolution: "for-each@npm:0.3.5" + dependencies: + is-callable: "npm:^1.2.7" + checksum: 10/330cc2439f85c94f4609de3ee1d32c5693ae15cdd7fe3d112c4fd9efd4ce7143f2c64ef6c2c9e0cfdb0058437f33ef05b5bdae5b98fcc903fb2143fbaf0fea0f languageName: node linkType: hard @@ -9211,34 +9498,38 @@ __metadata: linkType: hard "foreground-child@npm:^3.1.0": - version: 3.3.0 - resolution: "foreground-child@npm:3.3.0" + version: 3.3.1 + resolution: "foreground-child@npm:3.3.1" dependencies: - cross-spawn: "npm:^7.0.0" + cross-spawn: "npm:^7.0.6" signal-exit: "npm:^4.0.1" - checksum: 10/e3a60480f3a09b12273ce2c5fcb9514d98dd0e528f58656a1b04680225f918d60a2f81f6a368f2f3b937fcee9cfc0cbf16f1ad9a0bc6a3a6e103a84c9a90087e + checksum: 10/427b33f997a98073c0424e5c07169264a62cda806d8d2ded159b5b903fdfc8f0a1457e06b5fc35506497acb3f1e353f025edee796300209ac6231e80edece835 languageName: node linkType: hard "form-data@npm:^3.0.0": - version: 3.0.1 - resolution: "form-data@npm:3.0.1" + version: 3.0.4 + resolution: "form-data@npm:3.0.4" dependencies: asynckit: "npm:^0.4.0" combined-stream: "npm:^1.0.8" - mime-types: "npm:^2.1.12" - checksum: 10/944b40ff63b9cb1ca7a97e70f72104c548e0b0263e3e817e49919015a0d687453086259b93005389896dbffd3777cccea2e67c51f4e827590e5979b14ff91bf7 + es-set-tostringtag: "npm:^2.1.0" + hasown: "npm:^2.0.2" + mime-types: "npm:^2.1.35" + checksum: 10/68e4598e55cb193ef80304bff4d7513bf81ed4116d57b29c6c9a4c28c6f7ce57d46ddd60ba1a80aadf26703a722551e660bca2acaf9212d8b6e1f2e180d9e668 languageName: node linkType: hard -"form-data@npm:^4.0.0": - version: 4.0.0 - resolution: "form-data@npm:4.0.0" +"form-data@npm:^4.0.4": + version: 4.0.5 + resolution: "form-data@npm:4.0.5" dependencies: asynckit: "npm:^0.4.0" combined-stream: "npm:^1.0.8" + es-set-tostringtag: "npm:^2.1.0" + hasown: "npm:^2.0.2" mime-types: "npm:^2.1.12" - checksum: 10/7264aa760a8cf09482816d8300f1b6e2423de1b02bba612a136857413fdc96d7178298ced106817655facc6b89036c6e12ae31c9eb5bdc16aabf502ae8a5d805 + checksum: 10/52ecd6e927c8c4e215e68a7ad5e0f7c1031397439672fd9741654b4a94722c4182e74cc815b225dcb5be3f4180f36428f67c6dd39eaa98af0dcfdd26c00c19cd languageName: node linkType: hard @@ -9249,7 +9540,7 @@ __metadata: languageName: node linkType: hard -"fresh@npm:0.5.2": +"fresh@npm:~0.5.2": version: 0.5.2 resolution: "fresh@npm:0.5.2" checksum: 10/64c88e489b5d08e2f29664eb3c79c705ff9a8eb15d3e597198ef76546d4ade295897a44abb0abd2700e7ef784b2e3cbf1161e4fbf16f59129193fd1030d16da1 @@ -9268,22 +9559,13 @@ __metadata: linkType: hard "fs-extra@npm:^11.2.0": - version: 11.3.0 - resolution: "fs-extra@npm:11.3.0" + version: 11.3.3 + resolution: "fs-extra@npm:11.3.3" dependencies: graceful-fs: "npm:^4.2.0" jsonfile: "npm:^6.0.1" universalify: "npm:^2.0.0" - checksum: 10/c9fe7b23dded1efe7bbae528d685c3206477e20cc60e9aaceb3f024f9b9ff2ee1f62413c161cb88546cc564009ab516dec99e9781ba782d869bb37e4fe04a97f - languageName: node - linkType: hard - -"fs-minipass@npm:^2.0.0": - version: 2.1.0 - resolution: "fs-minipass@npm:2.1.0" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10/03191781e94bc9a54bd376d3146f90fe8e082627c502185dbf7b9b3032f66b0b142c1115f3b2cc5936575fc1b44845ce903dd4c21bec2a8d69f3bd56f9cee9ec + checksum: 10/daeaefafbebe8fa6efd2fb96fc926f2c952be5877811f00a6794f0d64e0128e3d0d93368cd328f8f063b45deacf385c40e3d931aa46014245431cd2f4f89c67a languageName: node linkType: hard @@ -9329,6 +9611,13 @@ __metadata: languageName: node linkType: hard +"generator-function@npm:^2.0.0": + version: 2.0.1 + resolution: "generator-function@npm:2.0.1" + checksum: 10/eb7e7eb896c5433f3d40982b2ccacdb3dd990dd3499f14040e002b5d54572476513be8a2e6f9609f6e41ab29f2c4469307611ddbfc37ff4e46b765c326663805 + languageName: node + linkType: hard + "gensync@npm:^1.0.0-beta.2": version: 1.0.0-beta.2 resolution: "gensync@npm:1.0.0-beta.2" @@ -9343,21 +9632,24 @@ __metadata: languageName: node linkType: hard -"get-intrinsic@npm:^1.2.4": - version: 1.3.0 - resolution: "get-intrinsic@npm:1.3.0" +"get-intrinsic@npm:^1.2.4, get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.2.6, get-intrinsic@npm:^1.3.0": + version: 1.3.1 + resolution: "get-intrinsic@npm:1.3.1" dependencies: + async-function: "npm:^1.0.0" + async-generator-function: "npm:^1.0.0" call-bind-apply-helpers: "npm:^1.0.2" es-define-property: "npm:^1.0.1" es-errors: "npm:^1.3.0" es-object-atoms: "npm:^1.1.1" function-bind: "npm:^1.1.2" + generator-function: "npm:^2.0.0" get-proto: "npm:^1.0.1" gopd: "npm:^1.2.0" has-symbols: "npm:^1.1.0" hasown: "npm:^2.0.2" math-intrinsics: "npm:^1.1.0" - checksum: 10/6e9dd920ff054147b6f44cb98104330e87caafae051b6d37b13384a45ba15e71af33c3baeac7cb630a0aaa23142718dcf25b45cfdd86c184c5dcb4e56d953a10 + checksum: 10/bb579dda84caa4a3a41611bdd483dade7f00f246f2a7992eb143c5861155290df3fdb48a8406efa3dfb0b434e2c8fafa4eebd469e409d0439247f85fc3fa2cc1 languageName: node linkType: hard @@ -9385,13 +9677,6 @@ __metadata: languageName: node linkType: hard -"get-stdin@npm:^9.0.0": - version: 9.0.0 - resolution: "get-stdin@npm:9.0.0" - checksum: 10/5972bc34d05932b45512c8e2d67b040f1c1ca8afb95c56cbc480985f2d761b7e37fe90dc8abd22527f062cc5639a6930ff346e9952ae4c11a2d4275869459594 - languageName: node - linkType: hard - "get-stream@npm:^6.0.0": version: 6.0.1 resolution: "get-stream@npm:6.0.1" @@ -9406,19 +9691,19 @@ __metadata: languageName: node linkType: hard -"get-tsconfig@npm:^4.7.3, get-tsconfig@npm:^4.7.5, get-tsconfig@npm:^4.8.1": - version: 4.8.1 - resolution: "get-tsconfig@npm:4.8.1" +"get-tsconfig@npm:^4.10.0, get-tsconfig@npm:^4.10.1, get-tsconfig@npm:^4.7.5, get-tsconfig@npm:^4.8.1": + version: 4.13.0 + resolution: "get-tsconfig@npm:4.13.0" dependencies: resolve-pkg-maps: "npm:^1.0.0" - checksum: 10/3fb5a8ad57b9633eaea085d81661e9e5c9f78b35d8f8689eaf8b8b45a2a3ebf3b3422266d4d7df765e308cc1e6231648d114803ab3d018332e29916f2c1de036 + checksum: 10/3603c6da30e312636e4c20461e779114c9126601d1eca70ee4e36e3e3c00e3c21892d2d920027333afa2cc9e20998a436b14abe03a53cde40742581cb0e9ceb2 languageName: node linkType: hard -"git-hooks-list@npm:^3.0.0": - version: 3.1.0 - resolution: "git-hooks-list@npm:3.1.0" - checksum: 10/05cbdb29e1e14f3b6fde78c876a34383e4476b1be32e8486ad03293f01add884c1a8df8c2dce2ca5d99119c94951b2ff9fa9cbd51d834ae6477b6813cefb998f +"git-hooks-list@npm:^4.0.0": + version: 4.1.1 + resolution: "git-hooks-list@npm:4.1.1" + checksum: 10/a56c8cc3dab505bde2c6de032164a9113968ab7f249dfe2c9f2f23be872165f88c91e097994e009d31e56dd1e81c1f714d0972133314d8d3c6bd92a847ba562f languageName: node linkType: hard @@ -9440,9 +9725,9 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7": - version: 10.4.5 - resolution: "glob@npm:10.4.5" +"glob@npm:^10.3.7": + version: 10.5.0 + resolution: "glob@npm:10.5.0" dependencies: foreground-child: "npm:^3.1.0" jackspeak: "npm:^3.1.2" @@ -9452,7 +9737,18 @@ __metadata: path-scurry: "npm:^1.11.1" bin: glob: dist/esm/bin.mjs - checksum: 10/698dfe11828b7efd0514cd11e573eaed26b2dff611f0400907281ce3eab0c1e56143ef9b35adc7c77ecc71fba74717b510c7c223d34ca8a98ec81777b293d4ac + checksum: 10/ab3bccfefcc0afaedbd1f480cd0c4a2c0e322eb3f0aa7ceaa31b3f00b825069f17cf0f1fc8b6f256795074b903f37c0ade37ddda6a176aa57f1c2bbfe7240653 + languageName: node + linkType: hard + +"glob@npm:^13.0.0": + version: 13.0.0 + resolution: "glob@npm:13.0.0" + dependencies: + minimatch: "npm:^10.1.1" + minipass: "npm:^7.1.2" + path-scurry: "npm:^2.0.0" + checksum: 10/de390721d29ee1c9ea41e40ec2aa0de2cabafa68022e237dc4297665a5e4d650776f2573191984ea1640aba1bf0ea34eddef2d8cbfbfc2ad24b5fb0af41d8846 languageName: node linkType: hard @@ -9494,13 +9790,6 @@ __metadata: languageName: node linkType: hard -"globals@npm:^11.1.0": - version: 11.12.0 - resolution: "globals@npm:11.12.0" - checksum: 10/9f054fa38ff8de8fa356502eb9d2dae0c928217b8b5c8de1f09f5c9b6c8a96d8b9bd3afc49acbcd384a98a81fea713c859e1b09e214c60509517bb8fc2bc13c2 - languageName: node - linkType: hard - "globals@npm:^14.0.0": version: 14.0.0 resolution: "globals@npm:14.0.0" @@ -9509,9 +9798,9 @@ __metadata: linkType: hard "globals@npm:^15.11.0, globals@npm:^15.9.0": - version: 15.14.0 - resolution: "globals@npm:15.14.0" - checksum: 10/e35ffbdbc024d6381efca906f67211a7bbf935db2af8c14a65155785479e28b3e475950e5933bb6b296eed54b6dcd924e25b26dbc8579b1bde9d5d25916e1c5f + version: 15.15.0 + resolution: "globals@npm:15.15.0" + checksum: 10/7f561c87b2fd381b27fc2db7df8a4ea7a9bb378667b8a7193e61fd2ca3a876479174e2a303a74345fbea6e1242e16db48915c1fd3bf35adcf4060a795b425e18 languageName: node linkType: hard @@ -9529,16 +9818,10 @@ __metadata: languageName: node linkType: hard -"globby@npm:^13.1.2": - version: 13.2.2 - resolution: "globby@npm:13.2.2" - dependencies: - dir-glob: "npm:^3.0.1" - fast-glob: "npm:^3.3.0" - ignore: "npm:^5.2.4" - merge2: "npm:^1.4.1" - slash: "npm:^4.0.0" - checksum: 10/4494a9d2162a7e4d327988b26be66d8eab87d7f59a83219e74b065e2c3ced23698f68fb10482bf9337133819281803fb886d6ae06afbb2affa743623eb0b1949 +"globrex@npm:^0.1.2": + version: 0.1.2 + resolution: "globrex@npm:0.1.2" + checksum: 10/81ce62ee6f800d823d6b7da7687f841676d60ee8f51f934ddd862e4057316d26665c4edc0358d4340a923ac00a514f8b67c787e28fe693aae16350f4e60d55e9 languageName: node linkType: hard @@ -9549,20 +9832,13 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.2, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": +"graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.11, graceful-fs@npm:^4.2.2, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" checksum: 10/bf152d0ed1dc159239db1ba1f74fdbc40cb02f626770dcd5815c427ce0688c2635a06ed69af364396da4636d0408fcf7d4afdf7881724c3307e46aff30ca49e2 languageName: node linkType: hard -"graphemer@npm:^1.4.0": - version: 1.4.0 - resolution: "graphemer@npm:1.4.0" - checksum: 10/6dd60dba97007b21e3a829fab3f771803cc1292977fe610e240ea72afd67e5690ac9eeaafc4a99710e78962e5936ab5a460787c2a1180f1cb0ccfac37d29f897 - languageName: node - linkType: hard - "hard-rejection@npm:^2.1.0": version: 2.1.0 resolution: "hard-rejection@npm:2.1.0" @@ -9586,21 +9862,31 @@ __metadata: languageName: node linkType: hard -"has-symbols@npm:^1.1.0": +"has-symbols@npm:^1.0.3, has-symbols@npm:^1.1.0": version: 1.1.0 resolution: "has-symbols@npm:1.1.0" checksum: 10/959385c98696ebbca51e7534e0dc723ada325efa3475350951363cce216d27373e0259b63edb599f72eb94d6cde8577b4b2375f080b303947e560f85692834fa languageName: node linkType: hard -"hash-base@npm:^3.0.0": - version: 3.1.0 - resolution: "hash-base@npm:3.1.0" +"has-tostringtag@npm:^1.0.2": + version: 1.0.2 + resolution: "has-tostringtag@npm:1.0.2" + dependencies: + has-symbols: "npm:^1.0.3" + checksum: 10/c74c5f5ceee3c8a5b8bc37719840dc3749f5b0306d818974141dda2471a1a2ca6c8e46b9d6ac222c5345df7a901c9b6f350b1e6d62763fec877e26609a401bfe + languageName: node + linkType: hard + +"hash-base@npm:^3.0.0, hash-base@npm:^3.1.2": + version: 3.1.2 + resolution: "hash-base@npm:3.1.2" dependencies: inherits: "npm:^2.0.4" - readable-stream: "npm:^3.6.0" - safe-buffer: "npm:^5.2.0" - checksum: 10/26b7e97ac3de13cb23fc3145e7e3450b0530274a9562144fc2bf5c1e2983afd0e09ed7cc3b20974ba66039fad316db463da80eb452e7373e780cbee9a0d2f2dc + readable-stream: "npm:^2.3.8" + safe-buffer: "npm:^5.2.1" + to-buffer: "npm:^1.2.1" + checksum: 10/f2100420521ec77736ebd9279f2c0b3ab2820136a2fa408ea36f3201d3f6984cda166806e6a0287f92adf179430bedfbdd74348ac351e24a3eff9f01a8c406b0 languageName: node linkType: hard @@ -9659,12 +9945,12 @@ __metadata: languageName: node linkType: hard -"hosted-git-info@npm:^7.0.0": - version: 7.0.2 - resolution: "hosted-git-info@npm:7.0.2" +"hosted-git-info@npm:^9.0.0": + version: 9.0.2 + resolution: "hosted-git-info@npm:9.0.2" dependencies: - lru-cache: "npm:^10.0.1" - checksum: 10/8f085df8a4a637d995f357f48b1e3f6fc1f9f92e82b33fb406415b5741834ed431a510a09141071001e8deea2eee43ce72786463e2aa5e5a70db8648c0eedeab + lru-cache: "npm:^11.1.0" + checksum: 10/0619c284ca7fc35322735e03fece90ed3ded67a2cf68e855e688d1bffd47078515d98ab8dff4bd08fb78d68d1a72ab8892180e15c7f23f24c922a6dfa601dbad languageName: node linkType: hard @@ -9685,29 +9971,29 @@ __metadata: linkType: hard "http-cache-semantics@npm:^4.1.1": - version: 4.1.1 - resolution: "http-cache-semantics@npm:4.1.1" - checksum: 10/362d5ed66b12ceb9c0a328fb31200b590ab1b02f4a254a697dc796850cc4385603e75f53ec59f768b2dad3bfa1464bd229f7de278d2899a0e3beffc634b6683f + version: 4.2.0 + resolution: "http-cache-semantics@npm:4.2.0" + checksum: 10/4efd2dfcfeea9d5e88c84af450b9980be8a43c2c8179508b1c57c7b4421c855f3e8efe92fa53e0b3f4a43c85824ada930eabbc306d1b3beab750b6dcc5187693 languageName: node linkType: hard -"http-errors@npm:2.0.0": - version: 2.0.0 - resolution: "http-errors@npm:2.0.0" +"http-errors@npm:~2.0.0, http-errors@npm:~2.0.1": + version: 2.0.1 + resolution: "http-errors@npm:2.0.1" dependencies: - depd: "npm:2.0.0" - inherits: "npm:2.0.4" - setprototypeof: "npm:1.2.0" - statuses: "npm:2.0.1" - toidentifier: "npm:1.0.1" - checksum: 10/0e7f76ee8ff8a33e58a3281a469815b893c41357378f408be8f6d4aa7d1efafb0da064625518e7078381b6a92325949b119dc38fcb30bdbc4e3a35f78c44c439 + depd: "npm:~2.0.0" + inherits: "npm:~2.0.4" + setprototypeof: "npm:~1.2.0" + statuses: "npm:~2.0.2" + toidentifier: "npm:~1.0.1" + checksum: 10/9fe31bc0edf36566c87048aed1d3d0cbe03552564adc3541626a0613f542d753fbcb13bdfcec0a3a530dbe1714bb566c89d46244616b66bddd26ac413b06a207 languageName: node linkType: hard "http-parser-js@npm:>=0.5.1": - version: 0.5.8 - resolution: "http-parser-js@npm:0.5.8" - checksum: 10/2a78a567ee6366dae0129d819b799dce1f95ec9732c5ab164a78ee69804ffb984abfa0660274e94e890fc54af93546eb9f12b6d10edbaed017e2d41c29b7cf29 + version: 0.5.10 + resolution: "http-parser-js@npm:0.5.10" + checksum: 10/33c53b458cfdf7e43f1517f9bcb6bed1c614b1c7c5d65581a84304110eb9eb02a48f998c7504b8bee432ef4a8ec9318e7009406b506b28b5610fed516242b20a languageName: node linkType: hard @@ -9743,12 +10029,12 @@ __metadata: linkType: hard "https-proxy-agent@npm:^7.0.1": - version: 7.0.5 - resolution: "https-proxy-agent@npm:7.0.5" + version: 7.0.6 + resolution: "https-proxy-agent@npm:7.0.6" dependencies: - agent-base: "npm:^7.0.2" + agent-base: "npm:^7.1.2" debug: "npm:4" - checksum: 10/6679d46159ab3f9a5509ee80c3a3fc83fba3a920a5e18d32176c3327852c3c00ad640c0c4210a8fd70ea3c4a6d3a1b375bf01942516e7df80e2646bdc77658ab + checksum: 10/784b628cbd55b25542a9d85033bdfd03d4eda630fb8b3c9477959367f3be95dc476ed2ecbb9836c359c7c698027fc7b45723a302324433590f45d6c1706e8c13 languageName: node linkType: hard @@ -9766,7 +10052,7 @@ __metadata: languageName: node linkType: hard -"iconv-lite@npm:0.4.24": +"iconv-lite@npm:0.4.24, iconv-lite@npm:~0.4.24": version: 0.4.24 resolution: "iconv-lite@npm:0.4.24" dependencies: @@ -9814,7 +10100,7 @@ __metadata: languageName: node linkType: hard -"ignore@npm:^7.0.0": +"ignore@npm:^7.0.5": version: 7.0.5 resolution: "ignore@npm:7.0.5" checksum: 10/f134b96a4de0af419196f52c529d5c6120c4456ff8a6b5a14ceaaa399f883e15d58d2ce651c9b69b9388491d4669dda47285d307e827de9304a53a1824801bc6 @@ -9829,12 +10115,12 @@ __metadata: linkType: hard "import-fresh@npm:^3.2.1": - version: 3.3.0 - resolution: "import-fresh@npm:3.3.0" + version: 3.3.1 + resolution: "import-fresh@npm:3.3.1" dependencies: parent-module: "npm:^1.0.0" resolve-from: "npm:^4.0.0" - checksum: 10/2cacfad06e652b1edc50be650f7ec3be08c5e5a6f6d12d035c440a42a8cc028e60a5b99ca08a77ab4d6b1346da7d971915828f33cdab730d3d42f08242d09baa + checksum: 10/a06b19461b4879cc654d46f8a6244eb55eb053437afd4cbb6613cad6be203811849ed3e4ea038783092879487299fda24af932b86bdfff67c9055ba3612b8c87 languageName: node linkType: hard @@ -9874,7 +10160,7 @@ __metadata: languageName: node linkType: hard -"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3": +"inherits@npm:2, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3, inherits@npm:~2.0.4": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 10/cd45e923bee15186c07fa4c89db0aace24824c482fb887b528304694b2aa6ff8a898da8657046a5dcf3e46cd6db6c61629551f9215f208d7c3f157cf9b290521 @@ -9888,20 +10174,17 @@ __metadata: languageName: node linkType: hard -"ini@npm:^4.1.3": - version: 4.1.3 - resolution: "ini@npm:4.1.3" - checksum: 10/f536b414d1442e5b233429e2b56efcdb354109b2d65ddd489e5939d8f0f5ad23c88aa2b19c92987249d0dd63ba8192e9aeb1a02b0459549c5a9ff31acd729a5d +"ini@npm:^6.0.0": + version: 6.0.0 + resolution: "ini@npm:6.0.0" + checksum: 10/e87d8cde86d091ddb104580d42dfdc8306593627269990ca0f5176ccc60c936268bad56856398fef924cdf0af33b1a9c21e84f85914820037e003ee45443cc85 languageName: node linkType: hard -"ip-address@npm:^9.0.5": - version: 9.0.5 - resolution: "ip-address@npm:9.0.5" - dependencies: - jsbn: "npm:1.1.0" - sprintf-js: "npm:^1.1.3" - checksum: 10/1ed81e06721af012306329b31f532b5e24e00cb537be18ddc905a84f19fe8f83a09a1699862bf3a1ec4b9dea93c55a3fa5faf8b5ea380431469df540f38b092c +"ip-address@npm:^10.0.1": + version: 10.1.0 + resolution: "ip-address@npm:10.1.0" + checksum: 10/a6979629d1ad9c1fb424bc25182203fad739b40225aebc55ec6243bbff5035faf7b9ed6efab3a097de6e713acbbfde944baacfa73e11852bb43989c45a68d79e languageName: node linkType: hard @@ -9926,12 +10209,19 @@ __metadata: languageName: node linkType: hard -"is-bun-module@npm:^1.0.2": - version: 1.3.0 - resolution: "is-bun-module@npm:1.3.0" +"is-bun-module@npm:^2.0.0": + version: 2.0.0 + resolution: "is-bun-module@npm:2.0.0" dependencies: - semver: "npm:^7.6.3" - checksum: 10/b23d9ec7b4d4bfd89e4e72b5cd52e1bc153facad59fdd7394c656f8859a78740ef35996a2066240a32f39cc9a9da4b4eb69e68df3c71755a61ebbaf56d3daef0 + semver: "npm:^7.7.1" + checksum: 10/cded5a1a58368b847872d08617975d620ad94426d76a932f3e08d55b4574d199e0a62a4fb024fa2dc444200b71719eb0bffc5d3d1e1cc82e29b293bb8d66a990 + languageName: node + linkType: hard + +"is-callable@npm:^1.2.7": + version: 1.2.7 + resolution: "is-callable@npm:1.2.7" + checksum: 10/48a9297fb92c99e9df48706241a189da362bff3003354aea4048bd5f7b2eb0d823cd16d0a383cece3d76166ba16d85d9659165ac6fcce1ac12e6c649d66dbdb9 languageName: node linkType: hard @@ -9946,7 +10236,7 @@ __metadata: languageName: node linkType: hard -"is-core-module@npm:^2.12.0, is-core-module@npm:^2.13.0, is-core-module@npm:^2.16.0, is-core-module@npm:^2.5.0": +"is-core-module@npm:^2.12.0, is-core-module@npm:^2.16.0, is-core-module@npm:^2.16.1, is-core-module@npm:^2.5.0": version: 2.16.1 resolution: "is-core-module@npm:2.16.1" dependencies: @@ -10019,13 +10309,6 @@ __metadata: languageName: node linkType: hard -"is-lambda@npm:^1.0.1": - version: 1.0.1 - resolution: "is-lambda@npm:1.0.1" - checksum: 10/93a32f01940220532e5948538699ad610d5924ac86093fcee83022252b363eb0cc99ba53ab084a04e4fb62bf7b5731f55496257a4c38adf87af9c4d352c71c35 - languageName: node - linkType: hard - "is-number@npm:^7.0.0": version: 7.0.0 resolution: "is-number@npm:7.0.0" @@ -10068,6 +10351,15 @@ __metadata: languageName: node linkType: hard +"is-typed-array@npm:^1.1.14": + version: 1.1.15 + resolution: "is-typed-array@npm:1.1.15" + dependencies: + which-typed-array: "npm:^1.1.16" + checksum: 10/e8cf60b9ea85667097a6ad68c209c9722cfe8c8edf04d6218366469e51944c5cc25bae45ffb845c23f811d262e4314d3b0168748eb16711aa34d12724cdf0735 + languageName: node + linkType: hard + "is-typedarray@npm:^1.0.0": version: 1.0.0 resolution: "is-typedarray@npm:1.0.0" @@ -10112,6 +10404,13 @@ __metadata: languageName: node linkType: hard +"isarray@npm:^2.0.5": + version: 2.0.5 + resolution: "isarray@npm:2.0.5" + checksum: 10/1d8bc7911e13bb9f105b1b3e0b396c787a9e63046af0b8fe0ab1414488ab06b2b099b87a2d8a9e31d21c9a6fad773c7fc8b257c4880f2d957274479d28ca3414 + languageName: node + linkType: hard + "isarray@npm:~1.0.0": version: 1.0.0 resolution: "isarray@npm:1.0.0" @@ -10186,12 +10485,12 @@ __metadata: linkType: hard "istanbul-reports@npm:^3.1.3": - version: 3.1.7 - resolution: "istanbul-reports@npm:3.1.7" + version: 3.2.0 + resolution: "istanbul-reports@npm:3.2.0" dependencies: html-escaper: "npm:^2.0.0" istanbul-lib-report: "npm:^3.0.0" - checksum: 10/f1faaa4684efaf57d64087776018d7426312a59aa6eeb4e0e3a777347d23cd286ad18f427e98f0e3dee666103d7404c9d7abc5f240406a912fa16bd6695437fa + checksum: 10/6773a1d5c7d47eeec75b317144fe2a3b1da84a44b6282bebdc856e09667865e58c9b025b75b3d87f5bc62939126cbba4c871ee84254537d934ba5da5d4c4ec4e languageName: node linkType: hard @@ -10310,6 +10609,18 @@ __metadata: languageName: node linkType: hard +"jest-diff@npm:30.2.0": + version: 30.2.0 + resolution: "jest-diff@npm:30.2.0" + dependencies: + "@jest/diff-sequences": "npm:30.0.1" + "@jest/get-type": "npm:30.1.0" + chalk: "npm:^4.1.2" + pretty-format: "npm:30.2.0" + checksum: 10/1fb9e4fb7dff81814b4f69eaa7db28e184d62306a3a8ea2447d02ca53d2cfa771e83ede513f67ec5239dffacfaac32ff2b49866d211e4c7516f51c1fc06ede42 + languageName: node + linkType: hard + "jest-diff@npm:^27.5.1": version: 27.5.1 resolution: "jest-diff@npm:27.5.1" @@ -10322,7 +10633,7 @@ __metadata: languageName: node linkType: hard -"jest-diff@npm:^29.0.3, jest-diff@npm:^29.7.0": +"jest-diff@npm:^29.0.3": version: 29.7.0 resolution: "jest-diff@npm:29.7.0" dependencies: @@ -10494,6 +10805,18 @@ __metadata: languageName: node linkType: hard +"jest-matcher-utils@npm:30.2.0": + version: 30.2.0 + resolution: "jest-matcher-utils@npm:30.2.0" + dependencies: + "@jest/get-type": "npm:30.1.0" + chalk: "npm:^4.1.2" + jest-diff: "npm:30.2.0" + pretty-format: "npm:30.2.0" + checksum: 10/f3f1ecf68ca63c9d1d80a175637a8fc655edfd1ee83220f6e3f6bd464ecbe2f93148fdd440a5a5e5a2b0b2cc8ee84ddc3dcef58a6dbc66821c792f48d260c6d4 + languageName: node + linkType: hard + "jest-matcher-utils@npm:^27.0.0, jest-matcher-utils@npm:^27.5.1": version: 27.5.1 resolution: "jest-matcher-utils@npm:27.5.1" @@ -10506,15 +10829,20 @@ __metadata: languageName: node linkType: hard -"jest-matcher-utils@npm:^29.7.0": - version: 29.7.0 - resolution: "jest-matcher-utils@npm:29.7.0" +"jest-message-util@npm:30.2.0": + version: 30.2.0 + resolution: "jest-message-util@npm:30.2.0" dependencies: - chalk: "npm:^4.0.0" - jest-diff: "npm:^29.7.0" - jest-get-type: "npm:^29.6.3" - pretty-format: "npm:^29.7.0" - checksum: 10/981904a494299cf1e3baed352f8a3bd8b50a8c13a662c509b6a53c31461f94ea3bfeffa9d5efcfeb248e384e318c87de7e3baa6af0f79674e987482aa189af40 + "@babel/code-frame": "npm:^7.27.1" + "@jest/types": "npm:30.2.0" + "@types/stack-utils": "npm:^2.0.3" + chalk: "npm:^4.1.2" + graceful-fs: "npm:^4.2.11" + micromatch: "npm:^4.0.8" + pretty-format: "npm:30.2.0" + slash: "npm:^3.0.0" + stack-utils: "npm:^2.0.6" + checksum: 10/e29ec76e8c8e4da5f5b25198be247535626ccf3a940e93fdd51fc6a6bcf70feaa2921baae3806182a090431d90b08c939eb13fb64249b171d2e9ae3a452a8fd2 languageName: node linkType: hard @@ -10535,20 +10863,14 @@ __metadata: languageName: node linkType: hard -"jest-message-util@npm:^29.7.0": - version: 29.7.0 - resolution: "jest-message-util@npm:29.7.0" +"jest-mock@npm:30.2.0": + version: 30.2.0 + resolution: "jest-mock@npm:30.2.0" dependencies: - "@babel/code-frame": "npm:^7.12.13" - "@jest/types": "npm:^29.6.3" - "@types/stack-utils": "npm:^2.0.0" - chalk: "npm:^4.0.0" - graceful-fs: "npm:^4.2.9" - micromatch: "npm:^4.0.4" - pretty-format: "npm:^29.7.0" - slash: "npm:^3.0.0" - stack-utils: "npm:^2.0.3" - checksum: 10/31d53c6ed22095d86bab9d14c0fa70c4a92c749ea6ceece82cf30c22c9c0e26407acdfbdb0231435dc85a98d6d65ca0d9cbcd25cd1abb377fe945e843fb770b9 + "@jest/types": "npm:30.2.0" + "@types/node": "npm:*" + jest-util: "npm:30.2.0" + checksum: 10/cde9b56805f90bf811a9231873ee88a0fb83bf4bf50972ae76960725da65220fcb119688f2e90e1ef33fbfd662194858d7f43809d881f1c41bb55d94e62adeab languageName: node linkType: hard @@ -10574,6 +10896,13 @@ __metadata: languageName: node linkType: hard +"jest-regex-util@npm:30.0.1": + version: 30.0.1 + resolution: "jest-regex-util@npm:30.0.1" + checksum: 10/fa8dac80c3e94db20d5e1e51d1bdf101cf5ede8f4e0b8f395ba8b8ea81e71804ffd747452a6bb6413032865de98ac656ef8ae43eddd18d980b6442a2764ed562 + languageName: node + linkType: hard + "jest-regex-util@npm:^27.5.1": version: 27.5.1 resolution: "jest-regex-util@npm:27.5.1" @@ -10726,6 +11055,20 @@ __metadata: languageName: node linkType: hard +"jest-util@npm:30.2.0": + version: 30.2.0 + resolution: "jest-util@npm:30.2.0" + dependencies: + "@jest/types": "npm:30.2.0" + "@types/node": "npm:*" + chalk: "npm:^4.1.2" + ci-info: "npm:^4.2.0" + graceful-fs: "npm:^4.2.11" + picomatch: "npm:^4.0.2" + checksum: 10/cf2f2fb83417ea69f9992121561c95cf4e9aad7946819b771b8b52addf78811101b33b51d0a39fa0c305f2751dab262feed7699de052659ff03d51827c8862f5 + languageName: node + linkType: hard + "jest-util@npm:^26.0.0": version: 26.6.2 resolution: "jest-util@npm:26.6.2" @@ -10798,11 +11141,11 @@ __metadata: linkType: hard "jest-when@npm:^3.4.2": - version: 3.6.0 - resolution: "jest-when@npm:3.6.0" + version: 3.7.0 + resolution: "jest-when@npm:3.7.0" peerDependencies: jest: ">= 25" - checksum: 10/0cb92738ccfa5711a685107f4437f18aefbe3cda120c912a9d49b612eeef03a910481ab40fe753fd42c4e617ffbb3d84c6bd66a76d963dac7f1ad9e9e5059359 + checksum: 10/b5b88d077ed467aab220c71c885dbc5f448604f06e68f761ce9f479c99bb74e0dbf553d1cc980751d88401b034a578e1c44eec5e4095743b7586f02bb7c6313d languageName: node linkType: hard @@ -10883,32 +11226,25 @@ __metadata: linkType: hard "js-yaml@npm:^3.13.1, js-yaml@npm:^3.14.1": - version: 3.14.1 - resolution: "js-yaml@npm:3.14.1" + version: 3.14.2 + resolution: "js-yaml@npm:3.14.2" dependencies: argparse: "npm:^1.0.7" esprima: "npm:^4.0.0" bin: js-yaml: bin/js-yaml.js - checksum: 10/9e22d80b4d0105b9899135365f746d47466ed53ef4223c529b3c0f7a39907743fdbd3c4379f94f1106f02755b5e90b2faaf84801a891135544e1ea475d1a1379 + checksum: 10/172e0b6007b0bf0fc8d2469c94424f7dd765c64a047d2b790831fecef2204a4054eabf4d911eb73ab8c9a3256ab8ba1ee8d655b789bf24bf059c772acc2075a1 languageName: node linkType: hard -"js-yaml@npm:^4.1.0": - version: 4.1.0 - resolution: "js-yaml@npm:4.1.0" +"js-yaml@npm:^4.1.1": + version: 4.1.1 + resolution: "js-yaml@npm:4.1.1" dependencies: argparse: "npm:^2.0.1" bin: js-yaml: bin/js-yaml.js - checksum: 10/c138a34a3fd0d08ebaf71273ad4465569a483b8a639e0b118ff65698d257c2791d3199e3f303631f2cb98213fa7b5f5d6a4621fd0fff819421b990d30d967140 - languageName: node - linkType: hard - -"jsbn@npm:1.1.0": - version: 1.1.0 - resolution: "jsbn@npm:1.1.0" - checksum: 10/bebe7ae829bbd586ce8cbe83501dd8cb8c282c8902a8aeeed0a073a89dc37e8103b1244f3c6acd60278bcbfe12d93a3f83c9ac396868a3b3bbc3c5e5e3b648ef + checksum: 10/a52d0519f0f4ef5b4adc1cde466cb54c50d56e2b4a983b9d5c9c0f2f99462047007a6274d7e95617a21d3c91fde3ee6115536ed70991cd645ba8521058b78f77 languageName: node linkType: hard @@ -10982,10 +11318,10 @@ __metadata: languageName: node linkType: hard -"json-parse-even-better-errors@npm:^3.0.0": - version: 3.0.2 - resolution: "json-parse-even-better-errors@npm:3.0.2" - checksum: 10/6f04ea6c9ccb783630a59297959247e921cc90b917b8351197ca7fd058fccc7079268fd9362be21ba876fc26aa5039369dd0a2280aae49aae425784794a94927 +"json-parse-even-better-errors@npm:^5.0.0": + version: 5.0.0 + resolution: "json-parse-even-better-errors@npm:5.0.0" + checksum: 10/b5aeaa65e072bc3bda2cb1da50bf1822814b4aa7c568e7c2bed25af89d730f113dcb74393da574c0a32e889eeba4a826db600b8a6ecef917c59c8c6b38f2efaa languageName: node linkType: hard @@ -11043,22 +11379,22 @@ __metadata: linkType: hard "jsonfile@npm:^6.0.1": - version: 6.1.0 - resolution: "jsonfile@npm:6.1.0" + version: 6.2.0 + resolution: "jsonfile@npm:6.2.0" dependencies: graceful-fs: "npm:^4.1.6" universalify: "npm:^2.0.0" dependenciesMeta: graceful-fs: optional: true - checksum: 10/03014769e7dc77d4cf05fa0b534907270b60890085dd5e4d60a382ff09328580651da0b8b4cdf44d91e4c8ae64d91791d965f05707beff000ed494a38b6fec85 + checksum: 10/513aac94a6eff070767cafc8eb4424b35d523eec0fcd8019fe5b975f4de5b10a54640c8d5961491ddd8e6f562588cf62435c5ddaf83aaf0986cd2ee789e0d7b9 languageName: node linkType: hard "jsonschema@npm:^1.4.1": - version: 1.4.1 - resolution: "jsonschema@npm:1.4.1" - checksum: 10/d7a188da7a3100a2caa362b80e98666d46607b7a7153aac405b8e758132961911c6df02d444d4700691330874e21a62639f550e856b21ddd28423690751ca9c6 + version: 1.5.0 + resolution: "jsonschema@npm:1.5.0" + checksum: 10/46bf49b388ba922073bcb3c8d5e90af9d29fc8303dc866fd440182c88d6b4fd2807679fd39cdefb4113156d104ea47da9c0ff4bbcb0032c9fa29461cb1a92182 languageName: node linkType: hard @@ -11220,19 +11556,26 @@ __metadata: linkType: hard "long@npm:^5.0.0": - version: 5.2.3 - resolution: "long@npm:5.2.3" - checksum: 10/9167ec6947a825b827c30da169a7384eec6c0c9ec2f0b9c74da2e93d81159bbe39fb09c3f13dae9721d4b807ccfa09797a7dd1012f5d478e3e33ca3c78b608e6 + version: 5.3.2 + resolution: "long@npm:5.3.2" + checksum: 10/b6b55ddae56fcce2864d37119d6b02fe28f6dd6d9e44fd22705f86a9254b9321bd69e9ffe35263b4846d54aba197c64882adcb8c543f2383c1e41284b321ea64 languageName: node linkType: hard -"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": +"lru-cache@npm:^10.2.0": version: 10.4.3 resolution: "lru-cache@npm:10.4.3" checksum: 10/e6e90267360476720fa8e83cc168aa2bf0311f3f2eea20a6ba78b90a885ae72071d9db132f40fda4129c803e7dcec3a6b6a6fbb44ca90b081630b810b5d6a41a languageName: node linkType: hard +"lru-cache@npm:^11.0.0, lru-cache@npm:^11.1.0, lru-cache@npm:^11.2.1": + version: 11.2.4 + resolution: "lru-cache@npm:11.2.4" + checksum: 10/3b2da74c0b6653767f8164c38c4c4f4d7f0cc10c62bfa512663d94a830191ae6a5af742a8d88a8b30d5f9974652d3adae53931f32069139ad24fa2a18a199aca + languageName: node + linkType: hard + "lru-cache@npm:^5.1.1": version: 5.1.1 resolution: "lru-cache@npm:5.1.1" @@ -11259,18 +11602,18 @@ __metadata: linkType: hard "luxon@npm:^3.2.1, luxon@npm:^3.5.0": - version: 3.5.0 - resolution: "luxon@npm:3.5.0" - checksum: 10/48f86e6c1c96815139f8559456a3354a276ba79bcef0ae0d4f2172f7652f3ba2be2237b0e103b8ea0b79b47715354ac9fac04eb1db3485dcc72d5110491dd47f + version: 3.7.2 + resolution: "luxon@npm:3.7.2" + checksum: 10/b24cd205ed306ce7415991687897dcc4027921ae413c9116590bc33a95f93b86ce52cf74ba72b4f5c5ab1c10090517f54ac8edfb127c049e0bf55b90dc2260be languageName: node linkType: hard -"magic-string@npm:^0.30.10": - version: 0.30.11 - resolution: "magic-string@npm:0.30.11" +"magic-string@npm:^0.30.21": + version: 0.30.21 + resolution: "magic-string@npm:0.30.21" dependencies: - "@jridgewell/sourcemap-codec": "npm:^1.5.0" - checksum: 10/b784d2240252f5b1e755d487354ada4c672cbca16f045144f7185a75b059210e5fcca7be7be03ef1bac2ca754c4428b21d36ae64a9057ba429916f06b8c54eb2 + "@jridgewell/sourcemap-codec": "npm:^1.5.5" + checksum: 10/57d5691f41ed40d962d8bd300148114f53db67fadbff336207db10a99f2bdf4a1be9cac3a68ee85dba575912ee1d4402e4396408196ec2d3afd043b076156221 languageName: node linkType: hard @@ -11290,23 +11633,22 @@ __metadata: languageName: node linkType: hard -"make-fetch-happen@npm:^13.0.0": - version: 13.0.1 - resolution: "make-fetch-happen@npm:13.0.1" +"make-fetch-happen@npm:^15.0.0": + version: 15.0.3 + resolution: "make-fetch-happen@npm:15.0.3" dependencies: - "@npmcli/agent": "npm:^2.0.0" - cacache: "npm:^18.0.0" + "@npmcli/agent": "npm:^4.0.0" + cacache: "npm:^20.0.1" http-cache-semantics: "npm:^4.1.1" - is-lambda: "npm:^1.0.1" minipass: "npm:^7.0.2" - minipass-fetch: "npm:^3.0.0" + minipass-fetch: "npm:^5.0.0" minipass-flush: "npm:^1.0.5" minipass-pipeline: "npm:^1.2.4" - negotiator: "npm:^0.6.3" - proc-log: "npm:^4.2.0" + negotiator: "npm:^1.0.0" + proc-log: "npm:^6.0.0" promise-retry: "npm:^2.0.1" - ssri: "npm:^10.0.0" - checksum: 10/11bae5ad6ac59b654dbd854f30782f9de052186c429dfce308eda42374528185a100ee40ac9ffdc36a2b6c821ecaba43913e4730a12f06f15e895ea9cb23fa59 + ssri: "npm:^13.0.0" + checksum: 10/78da4fc1df83cb596e2bae25aa0653b8a9c6cbdd6674a104894e03be3acfcd08c70b78f06ef6407fbd6b173f6a60672480d78641e693d05eb71c09c13ee35278 languageName: node linkType: hard @@ -11448,7 +11790,7 @@ __metadata: languageName: node linkType: hard -"mime-types@npm:^2.1.12, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": +"mime-types@npm:^2.1.12, mime-types@npm:^2.1.35, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": version: 2.1.35 resolution: "mime-types@npm:2.1.35" dependencies: @@ -11501,6 +11843,15 @@ __metadata: languageName: node linkType: hard +"minimatch@npm:^10.1.1, minimatch@npm:^9.0.3 || ^10.0.1": + version: 10.1.1 + resolution: "minimatch@npm:10.1.1" + dependencies: + "@isaacs/brace-expansion": "npm:^5.0.0" + checksum: 10/110f38921ea527022e90f7a5f43721838ac740d0a0c26881c03b57c261354fb9a0430e40b2c56dfcea2ef3c773768f27210d1106f1f2be19cde3eea93f26f45e + languageName: node + linkType: hard + "minimatch@npm:^3.0.4, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": version: 3.1.2 resolution: "minimatch@npm:3.1.2" @@ -11519,7 +11870,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^9.0.0, minimatch@npm:^9.0.3, minimatch@npm:^9.0.4, minimatch@npm:^9.0.5": +"minimatch@npm:^9.0.0, minimatch@npm:^9.0.4, minimatch@npm:^9.0.5": version: 9.0.5 resolution: "minimatch@npm:9.0.5" dependencies: @@ -11548,18 +11899,18 @@ __metadata: languageName: node linkType: hard -"minipass-fetch@npm:^3.0.0": - version: 3.0.5 - resolution: "minipass-fetch@npm:3.0.5" +"minipass-fetch@npm:^5.0.0": + version: 5.0.0 + resolution: "minipass-fetch@npm:5.0.0" dependencies: encoding: "npm:^0.1.13" minipass: "npm:^7.0.3" minipass-sized: "npm:^1.0.3" - minizlib: "npm:^2.1.2" + minizlib: "npm:^3.0.1" dependenciesMeta: encoding: optional: true - checksum: 10/c669948bec1373313aaa8f104b962a3ced9f45c49b26366a4b0ae27ccdfa9c5740d72c8a84d3f8623d7a61c5fc7afdfda44789008c078f61a62441142efc4a97 + checksum: 10/4fb7dca630a64e6970a8211dade505bfe260d0b8d60beb348dcdfb95fe35ef91d977b29963929c9017ae0805686aa3f413107dc6bc5deac9b9e26b0b41c3b86c languageName: node linkType: hard @@ -11599,13 +11950,6 @@ __metadata: languageName: node linkType: hard -"minipass@npm:^5.0.0": - version: 5.0.0 - resolution: "minipass@npm:5.0.0" - checksum: 10/61682162d29f45d3152b78b08bab7fb32ca10899bc5991ffe98afc18c9e9543bd1e3be94f8b8373ba6262497db63607079dc242ea62e43e7b2270837b7347c93 - languageName: node - linkType: hard - "minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4, minipass@npm:^7.1.2": version: 7.1.2 resolution: "minipass@npm:7.1.2" @@ -11613,40 +11957,12 @@ __metadata: languageName: node linkType: hard -"minizlib@npm:^2.1.1, minizlib@npm:^2.1.2": - version: 2.1.2 - resolution: "minizlib@npm:2.1.2" - dependencies: - minipass: "npm:^3.0.0" - yallist: "npm:^4.0.0" - checksum: 10/ae0f45436fb51344dcb87938446a32fbebb540d0e191d63b35e1c773d47512e17307bf54aa88326cc6d176594d00e4423563a091f7266c2f9a6872cdc1e234d1 - languageName: node - linkType: hard - -"minizlib@npm:^3.0.1": - version: 3.0.2 - resolution: "minizlib@npm:3.0.2" +"minizlib@npm:^3.0.1, minizlib@npm:^3.1.0": + version: 3.1.0 + resolution: "minizlib@npm:3.1.0" dependencies: minipass: "npm:^7.1.2" - checksum: 10/c075bed1594f68dcc8c35122333520112daefd4d070e5d0a228bd4cf5580e9eed3981b96c0ae1d62488e204e80fd27b2b9d0068ca9a5ef3993e9565faf63ca41 - languageName: node - linkType: hard - -"mkdirp@npm:^1.0.3": - version: 1.0.4 - resolution: "mkdirp@npm:1.0.4" - bin: - mkdirp: bin/cmd.js - checksum: 10/d71b8dcd4b5af2fe13ecf3bd24070263489404fe216488c5ba7e38ece1f54daf219e72a833a3a2dc404331e870e9f44963a33399589490956bff003a3404d3b2 - languageName: node - linkType: hard - -"mkdirp@npm:^3.0.1": - version: 3.0.1 - resolution: "mkdirp@npm:3.0.1" - bin: - mkdirp: dist/cjs/src/bin.js - checksum: 10/16fd79c28645759505914561e249b9a1f5fe3362279ad95487a4501e4467abeb714fd35b95307326b8fd03f3c7719065ef11a6f97b7285d7888306d1bd2232ba + checksum: 10/f47365cc2cb7f078cbe7e046eb52655e2e7e97f8c0a9a674f4da60d94fb0624edfcec9b5db32e8ba5a99a5f036f595680ae6fe02a262beaa73026e505cc52f99 languageName: node linkType: hard @@ -11657,7 +11973,7 @@ __metadata: languageName: node linkType: hard -"ms@npm:2.1.3, ms@npm:^2.1.1, ms@npm:^2.1.3": +"ms@npm:2.1.3, ms@npm:^2.1.3": version: 2.1.3 resolution: "ms@npm:2.1.3" checksum: 10/aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d @@ -11691,7 +12007,7 @@ __metadata: languageName: node linkType: hard -"nanoid@npm:^3.3.10, nanoid@npm:^3.3.7, nanoid@npm:^3.3.8": +"nanoid@npm:^3.3.10, nanoid@npm:^3.3.11, nanoid@npm:^3.3.8": version: 3.3.11 resolution: "nanoid@npm:3.3.11" bin: @@ -11700,6 +12016,15 @@ __metadata: languageName: node linkType: hard +"napi-postinstall@npm:^0.3.0": + version: 0.3.4 + resolution: "napi-postinstall@npm:0.3.4" + bin: + napi-postinstall: lib/cli.js + checksum: 10/5541381508f9e1051ff3518701c7130ebac779abb3a1ffe9391fcc3cab4cc0569b0ba0952357db3f6b12909c3bb508359a7a60261ffd795feebbdab967175832 + languageName: node + linkType: hard + "natural-compare@npm:^1.4.0": version: 1.4.0 resolution: "natural-compare@npm:1.4.0" @@ -11707,13 +12032,20 @@ __metadata: languageName: node linkType: hard -"negotiator@npm:0.6.3, negotiator@npm:^0.6.3": +"negotiator@npm:0.6.3": version: 0.6.3 resolution: "negotiator@npm:0.6.3" checksum: 10/2723fb822a17ad55c93a588a4bc44d53b22855bf4be5499916ca0cab1e7165409d0b288ba2577d7b029f10ce18cf2ed8e703e5af31c984e1e2304277ef979837 languageName: node linkType: hard +"negotiator@npm:^1.0.0": + version: 1.0.0 + resolution: "negotiator@npm:1.0.0" + checksum: 10/b5734e87295324fabf868e36fb97c84b7d7f3156ec5f4ee5bf6e488079c11054f818290fc33804cef7b1ee21f55eeb14caea83e7dafae6492a409b3e573153e5 + languageName: node + linkType: hard + "nise@npm:^4.0.4": version: 4.1.0 resolution: "nise@npm:4.1.0" @@ -11728,13 +12060,13 @@ __metadata: linkType: hard "nock@npm:^13.3.1": - version: 13.5.5 - resolution: "nock@npm:13.5.5" + version: 13.5.6 + resolution: "nock@npm:13.5.6" dependencies: debug: "npm:^4.1.0" json-stringify-safe: "npm:^5.0.1" propagate: "npm:^2.0.0" - checksum: 10/c19d7bf9654db056357a22b00127bb5606c1bbdff188a5b6c469825e580e31cd0cb0701bce8dd8b4876dbbd36a145fdb681fd69fd59308d6db4923ce8ab2439e + checksum: 10/a57c265b75e5f7767e2f8baf058773cdbf357c31c5fea2761386ec03a008a657f9df921899fe2a9502773b47145b708863b32345aef529b3c45cba4019120f88 languageName: node linkType: hard @@ -11771,33 +12103,33 @@ __metadata: linkType: hard "node-gyp-build@npm:^4.2.0": - version: 4.8.1 - resolution: "node-gyp-build@npm:4.8.1" + version: 4.8.4 + resolution: "node-gyp-build@npm:4.8.4" bin: node-gyp-build: bin.js node-gyp-build-optional: optional.js node-gyp-build-test: build-test.js - checksum: 10/b9297770f96a92e5f2b854f3fd5e4bd418df81d7785a81ab60cec5cf2e5e72dc2c3319808978adc572cfa3885e6b12338cb5f4034bed2cab35f0d76a4b75ccdf + checksum: 10/6a7d62289d1afc419fc8fc9bd00aa4e554369e50ca0acbc215cb91446148b75ff7e2a3b53c2c5b2c09a39d416d69f3d3237937860373104b5fe429bf30ad9ac5 languageName: node linkType: hard -"node-gyp@npm:^10.0.0, node-gyp@npm:latest": - version: 10.2.0 - resolution: "node-gyp@npm:10.2.0" +"node-gyp@npm:^12.1.0, node-gyp@npm:latest": + version: 12.1.0 + resolution: "node-gyp@npm:12.1.0" dependencies: env-paths: "npm:^2.2.0" exponential-backoff: "npm:^3.1.1" - glob: "npm:^10.3.10" graceful-fs: "npm:^4.2.6" - make-fetch-happen: "npm:^13.0.0" - nopt: "npm:^7.0.0" - proc-log: "npm:^4.1.0" + make-fetch-happen: "npm:^15.0.0" + nopt: "npm:^9.0.0" + proc-log: "npm:^6.0.0" semver: "npm:^7.3.5" - tar: "npm:^6.2.1" - which: "npm:^4.0.0" + tar: "npm:^7.5.2" + tinyglobby: "npm:^0.2.12" + which: "npm:^6.0.0" bin: node-gyp: bin/node-gyp.js - checksum: 10/41773093b1275751dec942b985982fd4e7a69b88cae719b868babcef3880ee6168aaec8dcaa8cd0b9fa7c84873e36cc549c6cac6a124ee65ba4ce1f1cc108cfe + checksum: 10/d93079236cef1dd7fa4df683708d8708ad255c55865f6656664c8959e4d3963d908ac48e8f9f341705432e979dbbf502a40d68d65a17fe35956a5a05ba6c1cb4 languageName: node linkType: hard @@ -11808,21 +12140,21 @@ __metadata: languageName: node linkType: hard -"node-releases@npm:^2.0.19": - version: 2.0.19 - resolution: "node-releases@npm:2.0.19" - checksum: 10/c2b33b4f0c40445aee56141f13ca692fa6805db88510e5bbb3baadb2da13e1293b738e638e15e4a8eb668bb9e97debb08e7a35409b477b5cc18f171d35a83045 +"node-releases@npm:^2.0.27": + version: 2.0.27 + resolution: "node-releases@npm:2.0.27" + checksum: 10/f6c78ddb392ae500719644afcbe68a9ea533242c02312eb6a34e8478506eb7482a3fb709c70235b01c32fe65625b68dfa9665113f816d87f163bc3819b62b106 languageName: node linkType: hard -"nopt@npm:^7.0.0": - version: 7.2.1 - resolution: "nopt@npm:7.2.1" +"nopt@npm:^9.0.0": + version: 9.0.0 + resolution: "nopt@npm:9.0.0" dependencies: - abbrev: "npm:^2.0.0" + abbrev: "npm:^4.0.0" bin: nopt: bin/nopt.js - checksum: 10/95a1f6dec8a81cd18cdc2fed93e6f0b4e02cf6bdb4501c848752c6e34f9883d9942f036a5e3b21a699047d8a448562d891e67492df68ec9c373e6198133337ae + checksum: 10/56a1ccd2ad711fb5115918e2c96828703cddbe12ba2c3bd00591758f6fa30e6f47dd905c59dbfcf9b773f3a293b45996609fb6789ae29d6bfcc3cf3a6f7d9fda languageName: node linkType: hard @@ -11850,17 +12182,6 @@ __metadata: languageName: node linkType: hard -"normalize-package-data@npm:^6.0.0": - version: 6.0.2 - resolution: "normalize-package-data@npm:6.0.2" - dependencies: - hosted-git-info: "npm:^7.0.0" - semver: "npm:^7.3.5" - validate-npm-package-license: "npm:^3.0.4" - checksum: 10/7c4216a2426aa76c0197f8372f06b23a0484d62b3518fb5c0f6ebccb16376bdfab29ceba96f95c75f60506473198f1337fe337b945c8df0541fe32b8049ab4c9 - languageName: node - linkType: hard - "normalize-path@npm:^3.0.0": version: 3.0.0 resolution: "normalize-path@npm:3.0.0" @@ -11868,12 +12189,12 @@ __metadata: languageName: node linkType: hard -"npm-install-checks@npm:^6.0.0": - version: 6.3.0 - resolution: "npm-install-checks@npm:6.3.0" +"npm-install-checks@npm:^8.0.0": + version: 8.0.0 + resolution: "npm-install-checks@npm:8.0.0" dependencies: semver: "npm:^7.1.1" - checksum: 10/6c20dadb878a0d2f1f777405217b6b63af1299d0b43e556af9363ee6eefaa98a17dfb7b612a473a473e96faf7e789c58b221e0d8ffdc1d34903c4f71618df3b4 + checksum: 10/eb4df6c3270ce6efcebcbc1a02997b3b4bcfa906ac2129ccef80eeffcf062d2e6dcbed02327109296725c1eb138ad93973303e025d2e0115f718fa4c09ed013f languageName: node linkType: hard @@ -11884,27 +12205,34 @@ __metadata: languageName: node linkType: hard -"npm-package-arg@npm:^11.0.0": - version: 11.0.3 - resolution: "npm-package-arg@npm:11.0.3" +"npm-normalize-package-bin@npm:^5.0.0": + version: 5.0.0 + resolution: "npm-normalize-package-bin@npm:5.0.0" + checksum: 10/969bc042d7bb029b5da7eb733e7642b238e3cb071ad57b56a3f128069bc1a3cbc2a4f4af30ee75b11660c368d60b89811ecd1430cf2ea1a7ff36f30052a4aeda + languageName: node + linkType: hard + +"npm-package-arg@npm:^13.0.0": + version: 13.0.2 + resolution: "npm-package-arg@npm:13.0.2" dependencies: - hosted-git-info: "npm:^7.0.0" - proc-log: "npm:^4.0.0" + hosted-git-info: "npm:^9.0.0" + proc-log: "npm:^6.0.0" semver: "npm:^7.3.5" - validate-npm-package-name: "npm:^5.0.0" - checksum: 10/bacc863907edf98940286edc2fd80327901c1e8b34426d538cdc708ed66bc6567f06d742d838eaf35db6804347bb4ba56ca9cef032c4b52743b33e7a22a2678e + validate-npm-package-name: "npm:^7.0.0" + checksum: 10/810868f4b8c666fc1979f33c5b45606f541be97e82958af486e8d3f5ff2c91f96cea56f22c4665a92dc9a23698cf831cba2e09691387d473f910f9e6590638b3 languageName: node linkType: hard -"npm-pick-manifest@npm:^9.0.0": - version: 9.1.0 - resolution: "npm-pick-manifest@npm:9.1.0" +"npm-pick-manifest@npm:^11.0.1": + version: 11.0.3 + resolution: "npm-pick-manifest@npm:11.0.3" dependencies: - npm-install-checks: "npm:^6.0.0" - npm-normalize-package-bin: "npm:^3.0.0" - npm-package-arg: "npm:^11.0.0" + npm-install-checks: "npm:^8.0.0" + npm-normalize-package-bin: "npm:^5.0.0" + npm-package-arg: "npm:^13.0.0" semver: "npm:^7.3.5" - checksum: 10/e759e4fe4076da9169cf522964a80bbc096d50cd24c8c44b50b44706c4479bd9d9d018fbdb76c6ea0c6037e012e07c6c917a1ecaa7ae1a1169cddfae1c0f24b6 + checksum: 10/189872190af34f7eccf3c586ad2e21e8c093f90a8f716db80887e8defa2bfb3ea917f61f339908ce0487a4cb1df40fe592aee3e8fe76a180a5b15a887850921a languageName: node linkType: hard @@ -11937,20 +12265,20 @@ __metadata: linkType: hard "nwsapi@npm:^2.2.0": - version: 2.2.16 - resolution: "nwsapi@npm:2.2.16" - checksum: 10/1e5e086cdd4ca4a45f414d37f49bf0ca81d84ed31c6871ac68f531917d2910845db61f77c6d844430dc90fda202d43fce9603024e74038675de95229eb834dba + version: 2.2.23 + resolution: "nwsapi@npm:2.2.23" + checksum: 10/aa4a570039c33d70b51436d1bb533f3e2c33c488ccbe9b09285c46a6cee5ef266fd60103461085c6954ba52460786a8138f042958328c7c1b4763898eb3dadfa languageName: node linkType: hard -"object-inspect@npm:^1.13.1": - version: 1.13.2 - resolution: "object-inspect@npm:1.13.2" - checksum: 10/7ef65583b6397570a17c56f0c1841e0920e83900f2c94638927abb7b81ac08a19c7aae135bd9dcca96208cac0c7332b4650fb927f027b0cf92d71df2990d0561 +"object-inspect@npm:^1.13.3": + version: 1.13.4 + resolution: "object-inspect@npm:1.13.4" + checksum: 10/aa13b1190ad3e366f6c83ad8a16ed37a19ed57d267385aa4bfdccda833d7b90465c057ff6c55d035a6b2e52c1a2295582b294217a0a3a1ae7abdd6877ef781fb languageName: node linkType: hard -"on-finished@npm:2.4.1": +"on-finished@npm:~2.4.1": version: 2.4.1 resolution: "on-finished@npm:2.4.1" dependencies: @@ -11987,14 +12315,14 @@ __metadata: linkType: hard "open@npm:^10.1.0": - version: 10.1.0 - resolution: "open@npm:10.1.0" + version: 10.2.0 + resolution: "open@npm:10.2.0" dependencies: default-browser: "npm:^5.2.1" define-lazy-prop: "npm:^3.0.0" is-inside-container: "npm:^1.0.0" - is-wsl: "npm:^3.1.0" - checksum: 10/a9c4105243a1b3c5312bf2aeb678f78d31f00618b5100088ee01eed2769963ea1f2dd464ac8d93cef51bba2d911e1a9c0c34a753ec7b91d6b22795903ea6647a + wsl-utils: "npm:^0.1.0" + checksum: 10/e6ad9474734eac3549dcc7d85e952394856ccaee48107c453bd6a725b82e3b8ed5f427658935df27efa76b411aeef62888edea8a9e347e8e7c82632ec966b30e languageName: node linkType: hard @@ -12048,12 +12376,10 @@ __metadata: languageName: node linkType: hard -"p-map@npm:^4.0.0": - version: 4.0.0 - resolution: "p-map@npm:4.0.0" - dependencies: - aggregate-error: "npm:^3.0.0" - checksum: 10/7ba4a2b1e24c05e1fc14bbaea0fc6d85cf005ae7e9c9425d4575550f37e2e584b1af97bcde78eacd7559208f20995988d52881334db16cf77bc1bcf68e48ed7c +"p-map@npm:^7.0.2": + version: 7.0.4 + resolution: "p-map@npm:7.0.4" + checksum: 10/ef48c3b2e488f31c693c9fcc0df0ef76518cf6426a495cf9486ebbb0fd7f31aef7f90e96f72e0070c0ff6e3177c9318f644b512e2c29e3feee8d7153fcb6782e languageName: node linkType: hard @@ -12072,9 +12398,9 @@ __metadata: linkType: hard "package-json-from-dist@npm:^1.0.0": - version: 1.0.0 - resolution: "package-json-from-dist@npm:1.0.0" - checksum: 10/ac706ec856a5a03f5261e4e48fa974f24feb044d51f84f8332e2af0af04fbdbdd5bbbfb9cbbe354190409bc8307c83a9e38c6672c3c8855f709afb0006a009ea + version: 1.0.1 + resolution: "package-json-from-dist@npm:1.0.1" + checksum: 10/58ee9538f2f762988433da00e26acc788036914d57c71c246bf0be1b60cdbd77dd60b6a3e1a30465f0b248aeb80079e0b34cb6050b1dfa18c06953bb1cbc7602 languageName: node linkType: hard @@ -12087,13 +12413,12 @@ __metadata: languageName: node linkType: hard -"parse-imports@npm:^2.1.1": - version: 2.2.1 - resolution: "parse-imports@npm:2.2.1" +"parse-imports-exports@npm:^0.2.4": + version: 0.2.4 + resolution: "parse-imports-exports@npm:0.2.4" dependencies: - es-module-lexer: "npm:^1.5.3" - slashes: "npm:^3.0.12" - checksum: 10/db1d98077587d23bfa1f136abae158ea08e1e588d0260dfc0769092be86b842c798ae47466742b1d9bc106d3430cebbd9730fc34872a2c0e72b9ff720986e82e + parse-statements: "npm:1.0.11" + checksum: 10/144d459771d1aeaa80eebffe43a2074c34e5b79a86d326c907efea90b62ff41af9555600b8e117e6cab717654d8e20b440e9ab09cdbbc9092f352cb0a9e1f3a3 languageName: node linkType: hard @@ -12116,6 +12441,13 @@ __metadata: languageName: node linkType: hard +"parse-statements@npm:1.0.11": + version: 1.0.11 + resolution: "parse-statements@npm:1.0.11" + checksum: 10/287c2739f4cbffa08e28a95ea2d3ff4a8a51ddb367df6212ae2cd80580a1189e09c6edcb8277fc05d0fdbcb93c86ad16b591f317e2fe12ac4189de738863e514 + languageName: node + linkType: hard + "parse5@npm:6.0.1": version: 6.0.1 resolution: "parse5@npm:6.0.1" @@ -12175,10 +12507,13 @@ __metadata: languageName: node linkType: hard -"path-to-regexp@npm:0.1.12": - version: 0.1.12 - resolution: "path-to-regexp@npm:0.1.12" - checksum: 10/2e30f6a0144679c1f95c98e166b96e6acd1e72be9417830fefc8de7ac1992147eb9a4c7acaa59119fb1b3c34eec393b2129ef27e24b2054a3906fc4fb0d1398e +"path-scurry@npm:^2.0.0": + version: 2.0.1 + resolution: "path-scurry@npm:2.0.1" + dependencies: + lru-cache: "npm:^11.0.0" + minipass: "npm:^7.1.2" + checksum: 10/1e9c74e9ccf94d7c16056a5cb2dba9fa23eec1bc221ab15c44765486b9b9975b4cd9a4d55da15b96eadf67d5202e9a2f1cec9023fbb35fe7d9ccd0ff1891f88b languageName: node linkType: hard @@ -12191,6 +12526,13 @@ __metadata: languageName: node linkType: hard +"path-to-regexp@npm:~0.1.12": + version: 0.1.12 + resolution: "path-to-regexp@npm:0.1.12" + checksum: 10/2e30f6a0144679c1f95c98e166b96e6acd1e72be9417830fefc8de7ac1992147eb9a4c7acaa59119fb1b3c34eec393b2129ef27e24b2054a3906fc4fb0d1398e + languageName: node + linkType: hard + "path-type@npm:^4.0.0": version: 4.0.0 resolution: "path-type@npm:4.0.0" @@ -12199,19 +12541,20 @@ __metadata: linkType: hard "pbkdf2@npm:^3.0.17": - version: 3.1.2 - resolution: "pbkdf2@npm:3.1.2" + version: 3.1.5 + resolution: "pbkdf2@npm:3.1.5" dependencies: - create-hash: "npm:^1.1.2" - create-hmac: "npm:^1.1.4" - ripemd160: "npm:^2.0.1" - safe-buffer: "npm:^5.0.1" - sha.js: "npm:^2.4.8" - checksum: 10/40bdf30df1c9bb1ae41ec50c11e480cf0d36484b7c7933bf55e4451d1d0e3f09589df70935c56e7fccc5702779a0d7b842d012be8c08a187b44eb24d55bb9460 + create-hash: "npm:^1.2.0" + create-hmac: "npm:^1.1.7" + ripemd160: "npm:^2.0.3" + safe-buffer: "npm:^5.2.1" + sha.js: "npm:^2.4.12" + to-buffer: "npm:^1.2.1" + checksum: 10/ce1c9a2ebbc843c86090ec6cac6d07429dece7c1fdb87437ce6cf869d0429cc39cab61bc34215585f4a00d8009862df45e197fbd54f3508ccba8ff312a88261b languageName: node linkType: hard -"picocolors@npm:^1.0.0, picocolors@npm:^1.0.1, picocolors@npm:^1.1.1": +"picocolors@npm:^1.1.1": version: 1.1.1 resolution: "picocolors@npm:1.1.1" checksum: 10/e1cf46bf84886c79055fdfa9dcb3e4711ad259949e3565154b004b260cd356c5d54b31a1437ce9782624bf766272fe6b0154f5f0c744fb7af5d454d2b60db045 @@ -12225,7 +12568,7 @@ __metadata: languageName: node linkType: hard -"picomatch@npm:^4.0.3": +"picomatch@npm:^4.0.2, picomatch@npm:^4.0.3": version: 4.0.3 resolution: "picomatch@npm:4.0.3" checksum: 10/57b99055f40b16798f2802916d9c17e9744e620a0db136554af01d19598b96e45e2f00014c91d1b8b13874b80caa8c295b3d589a3f72373ec4aaf54baa5962d5 @@ -12240,9 +12583,9 @@ __metadata: linkType: hard "pirates@npm:^4.0.4": - version: 4.0.6 - resolution: "pirates@npm:4.0.6" - checksum: 10/d02dda76f4fec1cbdf395c36c11cf26f76a644f9f9a1bfa84d3167d0d3154d5289aacc72677aa20d599bb4a6937a471de1b65c995e2aea2d8687cbcd7e43ea5f + version: 4.0.7 + resolution: "pirates@npm:4.0.7" + checksum: 10/2427f371366081ae42feb58214f04805d6b41d6b84d74480ebcc9e0ddbd7105a139f7c653daeaf83ad8a1a77214cf07f64178e76de048128fec501eab3305a96 languageName: node linkType: hard @@ -12280,14 +12623,21 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^8.4.40": - version: 8.4.41 - resolution: "postcss@npm:8.4.41" +"possible-typed-array-names@npm:^1.0.0": + version: 1.1.0 + resolution: "possible-typed-array-names@npm:1.1.0" + checksum: 10/2f44137b8d3dd35f4a7ba7469eec1cd9cfbb46ec164b93a5bc1f4c3d68599c9910ee3b91da1d28b4560e9cc8414c3cd56fedc07259c67e52cc774476270d3302 + languageName: node + linkType: hard + +"postcss@npm:^8.5.6": + version: 8.5.6 + resolution: "postcss@npm:8.5.6" dependencies: - nanoid: "npm:^3.3.7" - picocolors: "npm:^1.0.1" - source-map-js: "npm:^1.2.0" - checksum: 10/6e6176c2407eff60493ca60a706c6b7def20a722c3adda94ea1ece38345eb99964191336fd62b62652279cec6938e79e0b1e1d477142c8d3516e7a725a74ee37 + nanoid: "npm:^3.3.11" + picocolors: "npm:^1.1.1" + source-map-js: "npm:^1.2.1" + checksum: 10/9e4fbe97574091e9736d0e82a591e29aa100a0bf60276a926308f8c57249698935f35c5d2f4e80de778d0cbb8dcffab4f383d85fd50c5649aca421c3df729b86 languageName: node linkType: hard @@ -12307,36 +12657,46 @@ __metadata: languageName: node linkType: hard -"prettier-linter-helpers@npm:^1.0.0": - version: 1.0.0 - resolution: "prettier-linter-helpers@npm:1.0.0" +"prettier-linter-helpers@npm:^1.0.1": + version: 1.0.1 + resolution: "prettier-linter-helpers@npm:1.0.1" dependencies: fast-diff: "npm:^1.1.2" - checksum: 10/00ce8011cf6430158d27f9c92cfea0a7699405633f7f1d4a45f07e21bf78e99895911cbcdc3853db3a824201a7c745bd49bfea8abd5fb9883e765a90f74f8392 + checksum: 10/2dc35f5036a35f4c4f5e645887edda1436acb63687a7f12b2383e0a6f3c1f76b8a0a4709fe4d82e19157210feb5984b159bb714d43290022911ab53d606474ec languageName: node linkType: hard "prettier-plugin-packagejson@npm:^2.4.5": - version: 2.5.2 - resolution: "prettier-plugin-packagejson@npm:2.5.2" + version: 2.5.21 + resolution: "prettier-plugin-packagejson@npm:2.5.21" dependencies: - sort-package-json: "npm:2.10.1" - synckit: "npm:0.9.1" + sort-package-json: "npm:3.5.0" peerDependencies: prettier: ">= 1.16.0" peerDependenciesMeta: prettier: optional: true - checksum: 10/f280d69327a468cd104c72a81134258d3573e56d697a88a5c4498c8d02cecda9a27d9eb3f1d29cc726491782eb3f279c9d41ecf8364a197e20b239c5ccfd0269 + checksum: 10/04d10f1a5dada1e4179588dcd0d52ec13680554b26e73fd260c02f8f29ae9d6e78d7458203dd553c6b02237928dab119475415598cd487288a79921126373122 languageName: node linkType: hard "prettier@npm:^3.3.3": - version: 3.4.2 - resolution: "prettier@npm:3.4.2" + version: 3.8.0 + resolution: "prettier@npm:3.8.0" bin: prettier: bin/prettier.cjs - checksum: 10/a3e806fb0b635818964d472d35d27e21a4e17150c679047f5501e1f23bd4aa806adf660f0c0d35214a210d5d440da6896c2e86156da55f221a57938278dc326e + checksum: 10/a643c62f095c2987a34cea4fceddce8dea12cc3ee024494aff690cfac22ef20be835e212b39b718c833014fd22890ae156be67b75a26e2bc9b7acde9a34d31fa + languageName: node + linkType: hard + +"pretty-format@npm:30.2.0, pretty-format@npm:^30.0.0": + version: 30.2.0 + resolution: "pretty-format@npm:30.2.0" + dependencies: + "@jest/schemas": "npm:30.0.5" + ansi-styles: "npm:^5.2.0" + react-is: "npm:^18.3.1" + checksum: 10/725890d648e3400575eebc99a334a4cd1498e0d36746313913706bbeea20ada27e17c184a3cd45c50f705c16111afa829f3450233fc0fda5eed293c69757e926 languageName: node linkType: hard @@ -12351,7 +12711,7 @@ __metadata: languageName: node linkType: hard -"pretty-format@npm:^29.0.0, pretty-format@npm:^29.7.0": +"pretty-format@npm:^29.7.0": version: 29.7.0 resolution: "pretty-format@npm:29.7.0" dependencies: @@ -12362,10 +12722,10 @@ __metadata: languageName: node linkType: hard -"proc-log@npm:^4.0.0, proc-log@npm:^4.1.0, proc-log@npm:^4.2.0": - version: 4.2.0 - resolution: "proc-log@npm:4.2.0" - checksum: 10/4e1394491b717f6c1ade15c570ecd4c2b681698474d3ae2d303c1e4b6ab9455bd5a81566211e82890d5a5ae9859718cc6954d5150bb18b09b72ecb297beae90a +"proc-log@npm:^6.0.0": + version: 6.1.0 + resolution: "proc-log@npm:6.1.0" + checksum: 10/9033f30f168ed5a0991b773d0c50ff88384c4738e9a0a67d341de36bf7293771eed648ab6a0562f62276da12fde91f3bbfc75ffff6e71ad49aafd74fc646be66 languageName: node linkType: hard @@ -12383,13 +12743,6 @@ __metadata: languageName: node linkType: hard -"promise-inflight@npm:^1.0.1": - version: 1.0.1 - resolution: "promise-inflight@npm:1.0.1" - checksum: 10/1560d413ea20c5a74f3631d39ba8cbd1972b9228072a755d01e1f5ca5110382d9af76a1582d889445adc6e75bb5ac4886b56dc4b6eae51b30145d7bb1ac7505b - languageName: node - linkType: hard - "promise-retry@npm:^2.0.1": version: 2.0.1 resolution: "promise-retry@npm:2.0.1" @@ -12428,8 +12781,8 @@ __metadata: linkType: hard "protobufjs@npm:^7.2.5": - version: 7.4.0 - resolution: "protobufjs@npm:7.4.0" + version: 7.5.4 + resolution: "protobufjs@npm:7.5.4" dependencies: "@protobufjs/aspromise": "npm:^1.1.2" "@protobufjs/base64": "npm:^1.1.2" @@ -12443,7 +12796,7 @@ __metadata: "@protobufjs/utf8": "npm:^1.1.0" "@types/node": "npm:>=13.7.0" long: "npm:^5.0.0" - checksum: 10/408423506610f70858d7593632f4a6aa4f05796c90fd632be9b9252457c795acc71aa6d3b54bb7f48a890141728fee4ca3906723ccea6c202ad71f21b3879b8b + checksum: 10/88d677bb6f11a2ecec63fdd053dfe6d31120844d04e865efa9c8fbe0674cd077d6624ecfdf014018a20dcb114ae2a59c1b21966dd8073e920650c71370966439 languageName: node linkType: hard @@ -12465,9 +12818,11 @@ __metadata: linkType: hard "psl@npm:^1.1.33": - version: 1.9.0 - resolution: "psl@npm:1.9.0" - checksum: 10/d07879d4bfd0ac74796306a8e5a36a93cfb9c4f4e8ee8e63fbb909066c192fe1008cd8f12abd8ba2f62ca28247949a20c8fb32e1d18831d9e71285a1569720f9 + version: 1.15.0 + resolution: "psl@npm:1.15.0" + dependencies: + punycode: "npm:^2.3.1" + checksum: 10/5e7467eb5196eb7900d156783d12907d445c0122f76c73203ce96b148a6ccf8c5450cc805887ffada38ff92d634afcf33720c24053cb01d5b6598d1c913c5caf languageName: node linkType: hard @@ -12478,19 +12833,19 @@ __metadata: languageName: node linkType: hard -"punycode@npm:^2.1.0, punycode@npm:^2.1.1": +"punycode@npm:^2.1.0, punycode@npm:^2.1.1, punycode@npm:^2.3.1": version: 2.3.1 resolution: "punycode@npm:2.3.1" checksum: 10/febdc4362bead22f9e2608ff0171713230b57aff9dddc1c273aa2a651fbd366f94b7d6a71d78342a7c0819906750351ca7f2edd26ea41b626d87d6a13d1bd059 languageName: node linkType: hard -"qs@npm:6.13.0, qs@npm:^6.11.2": - version: 6.13.0 - resolution: "qs@npm:6.13.0" +"qs@npm:^6.11.2, qs@npm:~6.14.0": + version: 6.14.1 + resolution: "qs@npm:6.14.1" dependencies: - side-channel: "npm:^1.0.6" - checksum: 10/f548b376e685553d12e461409f0d6e5c59ec7c7d76f308e2a888fd9db3e0c5e89902bedd0754db3a9038eda5f27da2331a6f019c8517dc5e0a16b3c9a6e9cef8 + side-channel: "npm:^1.1.0" + checksum: 10/34b5ab00a910df432d55180ef39c1d1375e550f098b5ec153b41787f1a6a6d7e5f9495593c3b112b77dbc6709d0ae18e55b82847a4c2bbbb0de1e8ccbb1794c5 languageName: node linkType: hard @@ -12508,13 +12863,6 @@ __metadata: languageName: node linkType: hard -"queue-tick@npm:^1.0.1": - version: 1.0.1 - resolution: "queue-tick@npm:1.0.1" - checksum: 10/f447926c513b64a857906f017a3b350f7d11277e3c8d2a21a42b7998fa1a613d7a829091e12d142bb668905c8f68d8103416c7197856efb0c72fa835b8e254b5 - languageName: node - linkType: hard - "quick-lru@npm:^4.0.1": version: 4.0.1 resolution: "quick-lru@npm:4.0.1" @@ -12538,15 +12886,15 @@ __metadata: languageName: node linkType: hard -"raw-body@npm:2.5.2": - version: 2.5.2 - resolution: "raw-body@npm:2.5.2" +"raw-body@npm:~2.5.3": + version: 2.5.3 + resolution: "raw-body@npm:2.5.3" dependencies: - bytes: "npm:3.1.2" - http-errors: "npm:2.0.0" - iconv-lite: "npm:0.4.24" - unpipe: "npm:1.0.0" - checksum: 10/863b5171e140546a4d99f349b720abac4410338e23df5e409cfcc3752538c9caf947ce382c89129ba976f71894bd38b5806c774edac35ebf168d02aa1ac11a95 + bytes: "npm:~3.1.2" + http-errors: "npm:~2.0.1" + iconv-lite: "npm:~0.4.24" + unpipe: "npm:~1.0.0" + checksum: 10/f35759fe5a6548e7c529121ead1de4dd163f899749a5896c42e278479df2d9d7f98b5bb17312737c03617765e5a1433e586f717616e5cfbebc13b4738b820601 languageName: node linkType: hard @@ -12557,7 +12905,7 @@ __metadata: languageName: node linkType: hard -"react-is@npm:^18.0.0": +"react-is@npm:^18.0.0, react-is@npm:^18.3.1": version: 18.3.1 resolution: "react-is@npm:18.3.1" checksum: 10/d5f60c87d285af24b1e1e7eaeb123ec256c3c8bdea7061ab3932e3e14685708221bf234ec50b21e10dd07f008f1b966a2730a0ce4ff67905b3872ff2042aec22 @@ -12605,7 +12953,7 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^2.0.2": +"readable-stream@npm:^2.0.2, readable-stream@npm:^2.3.8": version: 2.3.8 resolution: "readable-stream@npm:2.3.8" dependencies: @@ -12620,25 +12968,25 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^3.6.2 || ^4.4.2": - version: 4.5.2 - resolution: "readable-stream@npm:4.5.2" +"readable-stream@npm:^3.6.2 || ^4.4.2, readable-stream@npm:^4.7.0": + version: 4.7.0 + resolution: "readable-stream@npm:4.7.0" dependencies: abort-controller: "npm:^3.0.0" buffer: "npm:^6.0.3" events: "npm:^3.3.0" process: "npm:^0.11.10" string_decoder: "npm:^1.3.0" - checksum: 10/01b128a559c5fd76a898495f858cf0a8839f135e6a69e3409f986e88460134791657eb46a2ff16826f331682a3c4d0c5a75cef5e52ef259711021ba52b1c2e82 + checksum: 10/bdf096c8ff59452ce5d08f13da9597f9fcfe400b4facfaa88e74ec057e5ad1fdfa140ffe28e5ed806cf4d2055f0b812806e962bca91dce31bc4cef08e53be3a4 languageName: node linkType: hard "readable-web-to-node-stream@npm:^3.0.2": - version: 3.0.2 - resolution: "readable-web-to-node-stream@npm:3.0.2" + version: 3.0.4 + resolution: "readable-web-to-node-stream@npm:3.0.4" dependencies: - readable-stream: "npm:^3.6.0" - checksum: 10/d3a5bf9d707c01183d546a64864aa63df4d9cb835dfd2bf89ac8305e17389feef2170c4c14415a10d38f9b9bfddf829a57aaef7c53c8b40f11d499844bf8f1a4 + readable-stream: "npm:^4.7.0" + checksum: 10/d8fb3de7579d70ea1e9efdfb2f02e2965ae62a1e1d9e9b0bdce493cb3b98090bd4a34526a9ab6c793bb833b89ffd31a5ab06117a3ae2a3df21363651b2131da9 languageName: node linkType: hard @@ -12668,13 +13016,6 @@ __metadata: languageName: node linkType: hard -"regenerator-runtime@npm:^0.14.0": - version: 0.14.1 - resolution: "regenerator-runtime@npm:0.14.1" - checksum: 10/5db3161abb311eef8c45bcf6565f4f378f785900ed3945acf740a9888c792f75b98ecb77f0775f3bf95502ff423529d23e94f41d80c8256e8fa05ed4b07cf471 - languageName: node - linkType: hard - "require-directory@npm:^2.1.1": version: 2.1.1 resolution: "require-directory@npm:2.1.1" @@ -12750,20 +13091,7 @@ __metadata: languageName: node linkType: hard -"resolve@npm:1.22.8": - version: 1.22.8 - resolution: "resolve@npm:1.22.8" - dependencies: - is-core-module: "npm:^2.13.0" - path-parse: "npm:^1.0.7" - supports-preserve-symlinks-flag: "npm:^1.0.0" - bin: - resolve: bin/resolve - checksum: 10/c473506ee01eb45cbcfefb68652ae5759e092e6b0fb64547feadf9736a6394f258fbc6f88e00c5ca36d5477fbb65388b272432a3600fa223062e54333c156753 - languageName: node - linkType: hard - -"resolve@npm:^1.10.0, resolve@npm:^1.20.0, resolve@npm:^1.22.3, resolve@npm:^1.22.4": +"resolve@npm:1.22.10": version: 1.22.10 resolution: "resolve@npm:1.22.10" dependencies: @@ -12776,20 +13104,20 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@npm%3A1.22.8#optional!builtin": - version: 1.22.8 - resolution: "resolve@patch:resolve@npm%3A1.22.8#optional!builtin::version=1.22.8&hash=c3c19d" +"resolve@npm:^1.10.0, resolve@npm:^1.20.0, resolve@npm:^1.22.3": + version: 1.22.11 + resolution: "resolve@npm:1.22.11" dependencies: - is-core-module: "npm:^2.13.0" + is-core-module: "npm:^2.16.1" path-parse: "npm:^1.0.7" supports-preserve-symlinks-flag: "npm:^1.0.0" bin: resolve: bin/resolve - checksum: 10/f345cd37f56a2c0275e3fe062517c650bb673815d885e7507566df589375d165bbbf4bdb6aa95600a9bc55f4744b81f452b5a63f95b9f10a72787dba3c90890a + checksum: 10/e1b2e738884a08de03f97ee71494335eba8c2b0feb1de9ae065e82c48997f349f77a2b10e8817e147cf610bfabc4b1cb7891ee8eaf5bf80d4ad514a34c4fab0a languageName: node linkType: hard -"resolve@patch:resolve@npm%3A^1.10.0#optional!builtin, resolve@patch:resolve@npm%3A^1.20.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.3#optional!builtin, resolve@patch:resolve@npm%3A^1.22.4#optional!builtin": +"resolve@patch:resolve@npm%3A1.22.10#optional!builtin": version: 1.22.10 resolution: "resolve@patch:resolve@npm%3A1.22.10#optional!builtin::version=1.22.10&hash=c3c19d" dependencies: @@ -12802,6 +13130,19 @@ __metadata: languageName: node linkType: hard +"resolve@patch:resolve@npm%3A^1.10.0#optional!builtin, resolve@patch:resolve@npm%3A^1.20.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.3#optional!builtin": + version: 1.22.11 + resolution: "resolve@patch:resolve@npm%3A1.22.11#optional!builtin::version=1.22.11&hash=c3c19d" + dependencies: + is-core-module: "npm:^2.16.1" + path-parse: "npm:^1.0.7" + supports-preserve-symlinks-flag: "npm:^1.0.0" + bin: + resolve: bin/resolve + checksum: 10/fd342cad25e52cd6f4f3d1716e189717f2522bfd6641109fe7aa372f32b5714a296ed7c238ddbe7ebb0c1ddfe0b7f71c9984171024c97cf1b2073e3e40ff71a8 + languageName: node + linkType: hard + "retry@npm:^0.12.0": version: 0.12.0 resolution: "retry@npm:0.12.0" @@ -12810,9 +13151,9 @@ __metadata: linkType: hard "reusify@npm:^1.0.4": - version: 1.0.4 - resolution: "reusify@npm:1.0.4" - checksum: 10/14222c9e1d3f9ae01480c50d96057228a8524706db79cdeb5a2ce5bb7070dd9f409a6f84a02cbef8cdc80d39aef86f2dd03d155188a1300c599b05437dcd2ffb + version: 1.1.0 + resolution: "reusify@npm:1.1.0" + checksum: 10/af47851b547e8a8dc89af144fceee17b80d5beaf5e6f57ed086432d79943434ff67ca526e92275be6f54b6189f6920a24eace75c2657eed32d02c400312b21ec languageName: node linkType: hard @@ -12845,13 +13186,13 @@ __metadata: languageName: node linkType: hard -"ripemd160@npm:^2.0.0, ripemd160@npm:^2.0.1": - version: 2.0.2 - resolution: "ripemd160@npm:2.0.2" +"ripemd160@npm:^2.0.0, ripemd160@npm:^2.0.1, ripemd160@npm:^2.0.3": + version: 2.0.3 + resolution: "ripemd160@npm:2.0.3" dependencies: - hash-base: "npm:^3.0.0" - inherits: "npm:^2.0.1" - checksum: 10/006accc40578ee2beae382757c4ce2908a826b27e2b079efdcd2959ee544ddf210b7b5d7d5e80467807604244e7388427330f5c6d4cd61e6edaddc5773ccc393 + hash-base: "npm:^3.1.2" + inherits: "npm:^2.0.4" + checksum: 10/d15d42ea0460426675e5320f86d3468ab408af95b1761cf35f8d32c0c97b4d3bb72b7226e990e643b96e1637a8ad26b343a6c7666e1a297bcab4f305a1d9d3e3 languageName: node linkType: hard @@ -12867,9 +13208,9 @@ __metadata: linkType: hard "run-applescript@npm:^7.0.0": - version: 7.0.0 - resolution: "run-applescript@npm:7.0.0" - checksum: 10/b02462454d8b182ad4117e5d4626e9e6782eb2072925c9fac582170b0627ae3c1ea92ee9b2df7daf84b5e9ffe14eb1cf5fb70bc44b15c8a0bfcdb47987e2410c + version: 7.1.0 + resolution: "run-applescript@npm:7.1.0" + checksum: 10/8659fb5f2717b2b37a68cbfe5f678254cf24b5a82a6df3372b180c80c7c137dcd757a4166c3887e459f59a090ca414e8ea7ca97cf3ee5123db54b3b4006d7b7a languageName: node linkType: hard @@ -12889,7 +13230,7 @@ __metadata: languageName: node linkType: hard -"safe-buffer@npm:5.2.1, safe-buffer@npm:>=5.1.0, safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.1.1, safe-buffer@npm:^5.1.2, safe-buffer@npm:^5.2.0, safe-buffer@npm:~5.2.0": +"safe-buffer@npm:5.2.1, safe-buffer@npm:>=5.1.0, safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.1.1, safe-buffer@npm:^5.1.2, safe-buffer@npm:^5.2.1, safe-buffer@npm:~5.2.0": version: 5.2.1 resolution: "safe-buffer@npm:5.2.1" checksum: 10/32872cd0ff68a3ddade7a7617b8f4c2ae8764d8b7d884c651b74457967a9e0e886267d3ecc781220629c44a865167b61c375d2da6c720c840ecd73f45d5d9451 @@ -12961,7 +13302,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:7.x, semver@npm:^7.1.1, semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0, semver@npm:^7.6.3": +"semver@npm:7.x, semver@npm:^7.1.1, semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.3, semver@npm:^7.7.1, semver@npm:^7.7.2, semver@npm:^7.7.3": version: 7.7.3 resolution: "semver@npm:7.7.3" bin: @@ -12979,36 +13320,36 @@ __metadata: languageName: node linkType: hard -"send@npm:0.19.0": - version: 0.19.0 - resolution: "send@npm:0.19.0" +"send@npm:~0.19.0, send@npm:~0.19.1": + version: 0.19.2 + resolution: "send@npm:0.19.2" dependencies: debug: "npm:2.6.9" depd: "npm:2.0.0" destroy: "npm:1.2.0" - encodeurl: "npm:~1.0.2" + encodeurl: "npm:~2.0.0" escape-html: "npm:~1.0.3" etag: "npm:~1.8.1" - fresh: "npm:0.5.2" - http-errors: "npm:2.0.0" + fresh: "npm:~0.5.2" + http-errors: "npm:~2.0.1" mime: "npm:1.6.0" ms: "npm:2.1.3" - on-finished: "npm:2.4.1" + on-finished: "npm:~2.4.1" range-parser: "npm:~1.2.1" - statuses: "npm:2.0.1" - checksum: 10/1f6064dea0ae4cbe4878437aedc9270c33f2a6650a77b56a16b62d057527f2766d96ee282997dd53ec0339082f2aad935bc7d989b46b48c82fc610800dc3a1d0 + statuses: "npm:~2.0.2" + checksum: 10/e932a592f62c58560b608a402d52333a8ae98a5ada076feb5db1d03adaa77c3ca32a7befa1c4fd6dedc186e88f342725b0cb4b3d86835eaf834688b259bef18d languageName: node linkType: hard -"serve-static@npm:1.16.2": - version: 1.16.2 - resolution: "serve-static@npm:1.16.2" +"serve-static@npm:~1.16.2": + version: 1.16.3 + resolution: "serve-static@npm:1.16.3" dependencies: encodeurl: "npm:~2.0.0" escape-html: "npm:~1.0.3" parseurl: "npm:~1.3.3" - send: "npm:0.19.0" - checksum: 10/7fa9d9c68090f6289976b34fc13c50ac8cd7f16ae6bce08d16459300f7fc61fbc2d7ebfa02884c073ec9d6ab9e7e704c89561882bbe338e99fcacb2912fde737 + send: "npm:~0.19.1" + checksum: 10/149d6718dd9e53166784d0a65535e21a7c01249d9c51f57224b786a7306354c6807e7811a9f6c143b45c863b1524721fca2f52b5c81a8b5194e3dde034a03b9c languageName: node linkType: hard @@ -13051,22 +13392,23 @@ __metadata: languageName: node linkType: hard -"setprototypeof@npm:1.2.0": +"setprototypeof@npm:1.2.0, setprototypeof@npm:~1.2.0": version: 1.2.0 resolution: "setprototypeof@npm:1.2.0" checksum: 10/fde1630422502fbbc19e6844346778f99d449986b2f9cdcceb8326730d2f3d9964dbcb03c02aaadaefffecd0f2c063315ebea8b3ad895914bf1afc1747fc172e languageName: node linkType: hard -"sha.js@npm:^2.4.0, sha.js@npm:^2.4.8": - version: 2.4.11 - resolution: "sha.js@npm:2.4.11" +"sha.js@npm:^2.4.0, sha.js@npm:^2.4.12, sha.js@npm:^2.4.8": + version: 2.4.12 + resolution: "sha.js@npm:2.4.12" dependencies: - inherits: "npm:^2.0.1" - safe-buffer: "npm:^5.0.1" + inherits: "npm:^2.0.4" + safe-buffer: "npm:^5.2.1" + to-buffer: "npm:^1.2.0" bin: - sha.js: ./bin.js - checksum: 10/d833bfa3e0a67579a6ce6e1bc95571f05246e0a441dd8c76e3057972f2a3e098465687a4369b07e83a0375a88703577f71b5b2e966809e67ebc340dbedb478c7 + sha.js: bin.js + checksum: 10/39c0993592c2ab34eb2daae2199a2a1d502713765aecb611fd97c0c4ab7cd53e902d628e1962aaf384bafd28f55951fef46dcc78799069ce41d74b03aa13b5a7 languageName: node linkType: hard @@ -13105,15 +13447,51 @@ __metadata: languageName: node linkType: hard -"side-channel@npm:^1.0.6": - version: 1.0.6 - resolution: "side-channel@npm:1.0.6" +"side-channel-list@npm:^1.0.0": + version: 1.0.0 + resolution: "side-channel-list@npm:1.0.0" dependencies: - call-bind: "npm:^1.0.7" es-errors: "npm:^1.3.0" - get-intrinsic: "npm:^1.2.4" - object-inspect: "npm:^1.13.1" - checksum: 10/eb10944f38cebad8ad643dd02657592fa41273ce15b8bfa928d3291aff2d30c20ff777cfe908f76ccc4551ace2d1245822fdc576657cce40e9066c638ca8fa4d + object-inspect: "npm:^1.13.3" + checksum: 10/603b928997abd21c5a5f02ae6b9cc36b72e3176ad6827fab0417ead74580cc4fb4d5c7d0a8a2ff4ead34d0f9e35701ed7a41853dac8a6d1a664fcce1a044f86f + languageName: node + linkType: hard + +"side-channel-map@npm:^1.0.1": + version: 1.0.1 + resolution: "side-channel-map@npm:1.0.1" + dependencies: + call-bound: "npm:^1.0.2" + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.5" + object-inspect: "npm:^1.13.3" + checksum: 10/5771861f77feefe44f6195ed077a9e4f389acc188f895f570d56445e251b861754b547ea9ef73ecee4e01fdada6568bfe9020d2ec2dfc5571e9fa1bbc4a10615 + languageName: node + linkType: hard + +"side-channel-weakmap@npm:^1.0.2": + version: 1.0.2 + resolution: "side-channel-weakmap@npm:1.0.2" + dependencies: + call-bound: "npm:^1.0.2" + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.5" + object-inspect: "npm:^1.13.3" + side-channel-map: "npm:^1.0.1" + checksum: 10/a815c89bc78c5723c714ea1a77c938377ea710af20d4fb886d362b0d1f8ac73a17816a5f6640f354017d7e292a43da9c5e876c22145bac00b76cfb3468001736 + languageName: node + linkType: hard + +"side-channel@npm:^1.1.0": + version: 1.1.0 + resolution: "side-channel@npm:1.1.0" + dependencies: + es-errors: "npm:^1.3.0" + object-inspect: "npm:^1.13.3" + side-channel-list: "npm:^1.0.0" + side-channel-map: "npm:^1.0.1" + side-channel-weakmap: "npm:^1.0.2" + checksum: 10/7d53b9db292c6262f326b6ff3bc1611db84ece36c2c7dc0e937954c13c73185b0406c56589e2bb8d071d6fee468e14c39fb5d203ee39be66b7b8174f179afaba languageName: node linkType: hard @@ -13132,11 +13510,11 @@ __metadata: linkType: hard "simple-git-hooks@npm:^2.8.0": - version: 2.11.1 - resolution: "simple-git-hooks@npm:2.11.1" + version: 2.13.1 + resolution: "simple-git-hooks@npm:2.13.1" bin: simple-git-hooks: cli.js - checksum: 10/b19b1edaca3af95442a35e3963fa54955ddd58f481dde25da4f7a48353ae5e35bc875ae381e214fe2889be494e6fe01cc1c5f24aebb9558cee496deda3d026a4 + checksum: 10/a315ab71dcc5da1552970051c8b05ab745496e95667501e6961165f9946b58119ed8c3aa0e97748ca04c61b891936e3464c5feb4c5fb2d70a79e8f431809453d languageName: node linkType: hard @@ -13189,20 +13567,6 @@ __metadata: languageName: node linkType: hard -"slash@npm:^4.0.0": - version: 4.0.0 - resolution: "slash@npm:4.0.0" - checksum: 10/da8e4af73712253acd21b7853b7e0dbba776b786e82b010a5bfc8b5051a1db38ed8aba8e1e8f400dd2c9f373be91eb1c42b66e91abb407ff42b10feece5e1d2d - languageName: node - linkType: hard - -"slashes@npm:^3.0.12": - version: 3.0.12 - resolution: "slashes@npm:3.0.12" - checksum: 10/c221d73765013db64f3eaf49dacc6b99a5d5477e63720c1bb71d1af647965dda23ab100ca1eb622e080f11ffe68e1e0a233b7b908073260bed4ec819ff1d3e42 - languageName: node - linkType: hard - "smart-buffer@npm:^4.2.0": version: 4.2.0 resolution: "smart-buffer@npm:4.2.0" @@ -13211,55 +13575,54 @@ __metadata: linkType: hard "socks-proxy-agent@npm:^8.0.3": - version: 8.0.4 - resolution: "socks-proxy-agent@npm:8.0.4" + version: 8.0.5 + resolution: "socks-proxy-agent@npm:8.0.5" dependencies: - agent-base: "npm:^7.1.1" + agent-base: "npm:^7.1.2" debug: "npm:^4.3.4" socks: "npm:^2.8.3" - checksum: 10/c8e7c2b398338b49a0a0f4d2bae5c0602aeeca6b478b99415927b6c5db349ca258448f2c87c6958ebf83eea17d42cbc5d1af0bfecb276cac10b9658b0f07f7d7 + checksum: 10/ee99e1dacab0985b52cbe5a75640be6e604135e9489ebdc3048635d186012fbaecc20fbbe04b177dee434c319ba20f09b3e7dfefb7d932466c0d707744eac05c languageName: node linkType: hard "socks@npm:^2.8.3": - version: 2.8.3 - resolution: "socks@npm:2.8.3" + version: 2.8.7 + resolution: "socks@npm:2.8.7" dependencies: - ip-address: "npm:^9.0.5" + ip-address: "npm:^10.0.1" smart-buffer: "npm:^4.2.0" - checksum: 10/ffcb622c22481dfcd7589aae71fbfd71ca34334064d181df64bf8b7feaeee19706aba4cffd1de35cc7bbaeeaa0af96be2d7f40fcbc7bc0ab69533a7ae9ffc4fb + checksum: 10/d19366c95908c19db154f329bbe94c2317d315dc933a7c2b5101e73f32a555c84fb199b62174e1490082a593a4933d8d5a9b297bde7d1419c14a11a965f51356 languageName: node linkType: hard -"sort-object-keys@npm:^1.1.3": - version: 1.1.3 - resolution: "sort-object-keys@npm:1.1.3" - checksum: 10/abea944d6722a1710a1aa6e4f9509da085d93d5fc0db23947cb411eedc7731f80022ce8fa68ed83a53dd2ac7441fcf72a3f38c09b3d9bbc4ff80546aa2e151ad +"sort-object-keys@npm:^2.0.0": + version: 2.1.0 + resolution: "sort-object-keys@npm:2.1.0" + checksum: 10/a0a18a6f4ab601adb889204a83e2664a4810042dd9680e588cabb47fffd40473939ce3fda5a28fdb58bac0762a7b45ad442815465b978d4b243bab840df3d7cd languageName: node linkType: hard -"sort-package-json@npm:2.10.1": - version: 2.10.1 - resolution: "sort-package-json@npm:2.10.1" +"sort-package-json@npm:3.5.0": + version: 3.5.0 + resolution: "sort-package-json@npm:3.5.0" dependencies: detect-indent: "npm:^7.0.1" - detect-newline: "npm:^4.0.0" - get-stdin: "npm:^9.0.0" - git-hooks-list: "npm:^3.0.0" - globby: "npm:^13.1.2" + detect-newline: "npm:^4.0.1" + git-hooks-list: "npm:^4.0.0" is-plain-obj: "npm:^4.1.0" - semver: "npm:^7.6.0" - sort-object-keys: "npm:^1.1.3" + semver: "npm:^7.7.1" + sort-object-keys: "npm:^2.0.0" + tinyglobby: "npm:^0.2.12" bin: sort-package-json: cli.js - checksum: 10/3a08cb9227c244d51bfb0eaaa5a9ea82fd3c96ea299c040365700b3f445d46a98411df4237f4e3c96ba67be4dcd53931747eab3b799f0335d278b36d64f1061d + checksum: 10/902ac1524c85a9c512170aad6e77e471e7237c91ba3d1e6653dcd0f05a6fd786efce276a79f82283828f2f7ee8ac28b8d17c97e3d5dfd688f629b4696a712d85 languageName: node linkType: hard -"source-map-js@npm:^1.2.0": - version: 1.2.0 - resolution: "source-map-js@npm:1.2.0" - checksum: 10/74f331cfd2d121c50790c8dd6d3c9de6be21926de80583b23b37029b0f37aefc3e019fa91f9a10a5e120c08135297e1ecf312d561459c45908cb1e0e365f49e5 +"source-map-js@npm:^1.2.1": + version: 1.2.1 + resolution: "source-map-js@npm:1.2.1" + checksum: 10/ff9d8c8bf096d534a5b7707e0382ef827b4dd360a577d3f34d2b9f48e12c9d230b5747974ee7c607f0df65113732711bb701fe9ece3c7edbd43cb2294d707df3 languageName: node linkType: hard @@ -13281,9 +13644,9 @@ __metadata: linkType: hard "source-map@npm:^0.7.3": - version: 0.7.4 - resolution: "source-map@npm:0.7.4" - checksum: 10/a0f7c9b797eda93139842fd28648e868a9a03ea0ad0d9fa6602a0c1f17b7fb6a7dcca00c144476cccaeaae5042e99a285723b1a201e844ad67221bf5d428f1dc + version: 0.7.6 + resolution: "source-map@npm:0.7.6" + checksum: 10/c8d2da7c57c14f3fd7568f764b39ad49bbf9dd7632b86df3542b31fed117d4af2fb74a4f886fc06baf7a510fee68e37998efc3080aacdac951c36211dc29a7a3 languageName: node linkType: hard @@ -13325,16 +13688,9 @@ __metadata: linkType: hard "spdx-license-ids@npm:^3.0.0": - version: 3.0.20 - resolution: "spdx-license-ids@npm:3.0.20" - checksum: 10/30e566ea74b04232c64819d1f5313c00d92e9c73d054541650331fc794499b3bcc4991bcd90fa3c2fc4d040006f58f63104706255266e87a9d452e6574afc60c - languageName: node - linkType: hard - -"sprintf-js@npm:^1.1.3": - version: 1.1.3 - resolution: "sprintf-js@npm:1.1.3" - checksum: 10/e7587128c423f7e43cc625fe2f87e6affdf5ca51c1cc468e910d8aaca46bb44a7fbcfa552f787b1d3987f7043aeb4527d1b99559e6621e01b42b3f45e5a24cbb + version: 3.0.22 + resolution: "spdx-license-ids@npm:3.0.22" + checksum: 10/a2f214aaf74c21a0172232367ce785157cef45d78617ee4d12aa1246350af566968e28b511e2096b707611566ac3959b85d8bf2d53a65bc6b66580735d3e1965 languageName: node linkType: hard @@ -13345,23 +13701,30 @@ __metadata: languageName: node linkType: hard -"ssri@npm:^10.0.0": - version: 10.0.6 - resolution: "ssri@npm:10.0.6" +"ssri@npm:^13.0.0": + version: 13.0.0 + resolution: "ssri@npm:13.0.0" dependencies: minipass: "npm:^7.0.3" - checksum: 10/f92c1b3cc9bfd0a925417412d07d999935917bc87049f43ebec41074661d64cf720315661844106a77da9f8204b6d55ae29f9514e673083cae39464343af2a8b + checksum: 10/fd59bfedf0659c1b83f6e15459162da021f08ec0f5834dd9163296f8b77ee82f9656aa1d415c3d3848484293e0e6aefdd482e863e52ddb53d520bb73da1eeec1 + languageName: node + linkType: hard + +"stable-hash-x@npm:^0.2.0": + version: 0.2.0 + resolution: "stable-hash-x@npm:0.2.0" + checksum: 10/136f05d0e4d441876012b423541476ff5b695c93b56d1959560be858b9e324ea6de6c16ecbd735a040ee8396427dd867bed0bf90b2cdb1fc422566747b91a0e5 languageName: node linkType: hard -"stable-hash@npm:^0.0.4": - version: 0.0.4 - resolution: "stable-hash@npm:0.0.4" - checksum: 10/21c039d21c1cb739cf8342561753a5e007cb95ea682ccd452e76310bbb9c6987a89de8eda023e320b019f3e4691aabda75079cdbb7dadf7ab9013e931f2f23cd +"stable-hash@npm:^0.0.5": + version: 0.0.5 + resolution: "stable-hash@npm:0.0.5" + checksum: 10/9222ea2c558e37c4a576cb4e406966b9e6aa05b93f5c4f09ef4aaabe3577439b9b8fbff407b16840b63e2ae83de74290c7b1c2da7360d571e480e46a4aec0a56 languageName: node linkType: hard -"stack-utils@npm:^2.0.3": +"stack-utils@npm:^2.0.3, stack-utils@npm:^2.0.6": version: 2.0.6 resolution: "stack-utils@npm:2.0.6" dependencies: @@ -13370,25 +13733,21 @@ __metadata: languageName: node linkType: hard -"statuses@npm:2.0.1": - version: 2.0.1 - resolution: "statuses@npm:2.0.1" - checksum: 10/18c7623fdb8f646fb213ca4051be4df7efb3484d4ab662937ca6fbef7ced9b9e12842709872eb3020cc3504b93bde88935c9f6417489627a7786f24f8031cbcb +"statuses@npm:~2.0.1, statuses@npm:~2.0.2": + version: 2.0.2 + resolution: "statuses@npm:2.0.2" + checksum: 10/6927feb50c2a75b2a4caab2c565491f7a93ad3d8dbad7b1398d52359e9243a20e2ebe35e33726dee945125ef7a515e9097d8a1b910ba2bbd818265a2f6c39879 languageName: node linkType: hard "streamx@npm:^2.15.0": - version: 2.19.0 - resolution: "streamx@npm:2.19.0" + version: 2.23.0 + resolution: "streamx@npm:2.23.0" dependencies: - bare-events: "npm:^2.2.0" + events-universal: "npm:^1.0.0" fast-fifo: "npm:^1.3.2" - queue-tick: "npm:^1.0.1" text-decoder: "npm:^1.1.0" - dependenciesMeta: - bare-events: - optional: true - checksum: 10/3e57a12402200cce347bd0658b5e7ef14a41636341256d2a9f43100e5c4f5d82166a4df77aef92082686150805a1b14f74370f3c96b4ed3d6d9889da1e3b3c21 + checksum: 10/4969d7032b16497172afa2f8ac889d137764963ae564daf1611a03225dd62d9316d51de8098b5866d21722babde71353067184e7a3e9795d6dc17c902904a780 languageName: node linkType: hard @@ -13452,11 +13811,11 @@ __metadata: linkType: hard "strip-ansi@npm:^7.0.1": - version: 7.1.0 - resolution: "strip-ansi@npm:7.1.0" + version: 7.1.2 + resolution: "strip-ansi@npm:7.1.2" dependencies: ansi-regex: "npm:^6.0.1" - checksum: 10/475f53e9c44375d6e72807284024ac5d668ee1d06010740dec0b9744f2ddf47de8d7151f80e5f6190fc8f384e802fdf9504b76a7e9020c9faee7103623338be2 + checksum: 10/db0e3f9654e519c8a33c50fc9304d07df5649388e7da06d3aabf66d29e5ad65d5e6315d8519d409c15b32fa82c1df7e11ed6f8cd50b0e4404463f0c9d77c8d0b languageName: node linkType: hard @@ -13506,10 +13865,10 @@ __metadata: languageName: node linkType: hard -"strnum@npm:^1.0.5": - version: 1.0.5 - resolution: "strnum@npm:1.0.5" - checksum: 10/d3117975db8372d4d7b2c07601ed2f65bf21cc48d741f37a8617b76370d228f2ec26336e53791ebc3638264d23ca54e6c241f57f8c69bd4941c63c79440525ca +"strnum@npm:^1.1.1": + version: 1.1.2 + resolution: "strnum@npm:1.1.2" + checksum: 10/ccd6297a1fdaf0fc8ea0ea904acdae76878d49a4b0d98a70155df4bc081fd88eac5ec99fb150f3d1d1af065c1898d38420705259ba6c39aa850c671bcd54e35d languageName: node linkType: hard @@ -13555,30 +13914,19 @@ __metadata: languageName: node linkType: hard -"synckit@npm:0.9.1": - version: 0.9.1 - resolution: "synckit@npm:0.9.1" - dependencies: - "@pkgr/core": "npm:^0.1.0" - tslib: "npm:^2.6.2" - checksum: 10/bff3903976baf8b699b5483228116d70223781a93b17c70e685c277ee960cdfd1a09cb5a741e6a9ec35e2428f14f4664baec41ccc99a598f267608b2a54f529b - languageName: node - linkType: hard - -"synckit@npm:^0.9.1": - version: 0.9.2 - resolution: "synckit@npm:0.9.2" +"synckit@npm:^0.11.12": + version: 0.11.12 + resolution: "synckit@npm:0.11.12" dependencies: - "@pkgr/core": "npm:^0.1.0" - tslib: "npm:^2.6.2" - checksum: 10/d45c4288be9c0232343650643892a7edafb79152c0c08d7ae5d33ca2c296b67a0e15f8cb5c9153969612c4ea5cd5686297542384aab977db23cfa6653fe02027 + "@pkgr/core": "npm:^0.2.9" + checksum: 10/2f51978bfed81aaf0b093f596709a72c49b17909020f42b43c5549f9c0fe18b1fe29f82e41ef771172d729b32e9ce82900a85d2b87fa14d59f886d4df8d7a329 languageName: node linkType: hard "tapable@npm:^2.2.0": - version: 2.2.1 - resolution: "tapable@npm:2.2.1" - checksum: 10/1769336dd21481ae6347611ca5fca47add0962fd8e80466515032125eca0084a4f0ede11e65341b9c0018ef4e1cf1ad820adbb0fba7cc99865c6005734000b0a + version: 2.3.0 + resolution: "tapable@npm:2.3.0" + checksum: 10/496a841039960533bb6e44816a01fffc2a1eb428bb2051ecab9e87adf07f19e1f937566cbbbb09dceff31163c0ffd81baafcad84db900b601f0155dd0b37e9f2 languageName: node linkType: hard @@ -13593,31 +13941,16 @@ __metadata: languageName: node linkType: hard -"tar@npm:^6.1.11, tar@npm:^6.2.1": - version: 6.2.1 - resolution: "tar@npm:6.2.1" - dependencies: - chownr: "npm:^2.0.0" - fs-minipass: "npm:^2.0.0" - minipass: "npm:^5.0.0" - minizlib: "npm:^2.1.1" - mkdirp: "npm:^1.0.3" - yallist: "npm:^4.0.0" - checksum: 10/bfbfbb2861888077fc1130b84029cdc2721efb93d1d1fb80f22a7ac3a98ec6f8972f29e564103bbebf5e97be67ebc356d37fa48dbc4960600a1eb7230fbd1ea0 - languageName: node - linkType: hard - -"tar@npm:^7.4.3": - version: 7.4.3 - resolution: "tar@npm:7.4.3" +"tar@npm:^7.4.3, tar@npm:^7.5.2": + version: 7.5.3 + resolution: "tar@npm:7.5.3" dependencies: "@isaacs/fs-minipass": "npm:^4.0.0" chownr: "npm:^3.0.0" minipass: "npm:^7.1.2" - minizlib: "npm:^3.0.1" - mkdirp: "npm:^3.0.1" + minizlib: "npm:^3.1.0" yallist: "npm:^5.0.0" - checksum: 10/12a2a4fc6dee23e07cc47f1aeb3a14a1afd3f16397e1350036a8f4cdfee8dcac7ef5978337a4e7b2ac2c27a9a6d46388fc2088ea7c80cb6878c814b1425f8ecf + checksum: 10/106b85ef799eb9c2a5d91278b14cdd9486551a5d889a7d88f719513dd7e04b7bd77417df27d3fcb43ef54dda5acc15730e627259164ce245dd968d86fd6ee517 languageName: node linkType: hard @@ -13643,11 +13976,11 @@ __metadata: linkType: hard "text-decoder@npm:^1.1.0": - version: 1.1.1 - resolution: "text-decoder@npm:1.1.1" + version: 1.2.3 + resolution: "text-decoder@npm:1.2.3" dependencies: b4a: "npm:^1.6.4" - checksum: 10/c6981b93850daeafc8bd1dbd8f984d4fb2d14632f450de0892692b5bbee2d2f4cbef8a807142527370649fd357f58491ede4915d43669eca624cb52b8dd247b6 + checksum: 10/bcdec33c0f070aeac38e46e4cafdcd567a58473ed308bdf75260bfbd8f7dc76acbc0b13226afaec4a169d0cb44cec2ab89c57b6395ccf02e941eaebbe19e124a languageName: node linkType: hard @@ -13658,7 +13991,7 @@ __metadata: languageName: node linkType: hard -"tinyglobby@npm:^0.2.15": +"tinyglobby@npm:^0.2.12, tinyglobby@npm:^0.2.13, tinyglobby@npm:^0.2.15": version: 0.2.15 resolution: "tinyglobby@npm:0.2.15" dependencies: @@ -13675,6 +14008,17 @@ __metadata: languageName: node linkType: hard +"to-buffer@npm:^1.2.0, to-buffer@npm:^1.2.1, to-buffer@npm:^1.2.2": + version: 1.2.2 + resolution: "to-buffer@npm:1.2.2" + dependencies: + isarray: "npm:^2.0.5" + safe-buffer: "npm:^5.2.1" + typed-array-buffer: "npm:^1.0.3" + checksum: 10/69d806c20524ff1e4c44d49276bc96ff282dcae484780a3974e275dabeb75651ea430b074a2a4023701e63b3e1d87811cd82c0972f35280fe5461710e4872aba + languageName: node + linkType: hard + "to-regex-range@npm:^5.0.1": version: 5.0.1 resolution: "to-regex-range@npm:5.0.1" @@ -13684,7 +14028,7 @@ __metadata: languageName: node linkType: hard -"toidentifier@npm:1.0.1": +"toidentifier@npm:~1.0.1": version: 1.0.1 resolution: "toidentifier@npm:1.0.1" checksum: 10/952c29e2a85d7123239b5cfdd889a0dde47ab0497f0913d70588f19c53f7e0b5327c95f4651e413c74b785147f9637b17410ac8c846d5d4a20a5a33eb6dc3a45 @@ -13726,12 +14070,23 @@ __metadata: languageName: node linkType: hard -"ts-api-utils@npm:^2.1.0": - version: 2.1.0 - resolution: "ts-api-utils@npm:2.1.0" +"ts-api-utils@npm:^2.4.0": + version: 2.4.0 + resolution: "ts-api-utils@npm:2.4.0" peerDependencies: typescript: ">=4.8.4" - checksum: 10/02e55b49d9617c6eebf8aadfa08d3ca03ca0cd2f0586ad34117fdfc7aa3cd25d95051843fde9df86665ad907f99baed179e7a117b11021417f379e4d2614eacd + checksum: 10/d6b2b3b6caad8d2f4ddc0c3785d22bb1a6041773335a1c71d73a5d67d11d993763fe8e4faefc4a4d03bb42b26c6126bbcf2e34826baed1def5369d0ebad358fa + languageName: node + linkType: hard + +"ts-declaration-location@npm:^1.0.6": + version: 1.0.7 + resolution: "ts-declaration-location@npm:1.0.7" + dependencies: + picomatch: "npm:^4.0.2" + peerDependencies: + typescript: ">=4.0.0" + checksum: 10/a7932fc75d41f10c16089f8f5a5c1ea49d6afca30f09c91c1df14d0a8510f72bcb9f8a395c04f060b66b855b6bd7ea4df81b335fb9d21bef402969a672a4afa7 languageName: node linkType: hard @@ -13785,14 +14140,14 @@ __metadata: languageName: node linkType: hard -"tslib@npm:2.4.0": - version: 2.4.0 - resolution: "tslib@npm:2.4.0" - checksum: 10/d8379e68b36caf082c1905ec25d17df8261e1d68ddc1abfd6c91158a064f6e4402039ae7c02cf4c81d12e3a2a2c7cd8ea2f57b233eb80136a2e3e7279daf2911 +"tslib@npm:2.7.0": + version: 2.7.0 + resolution: "tslib@npm:2.7.0" + checksum: 10/9a5b47ddac65874fa011c20ff76db69f97cf90c78cff5934799ab8894a5342db2d17b4e7613a087046bc1d133d21547ddff87ac558abeec31ffa929c88b7fce6 languageName: node linkType: hard -"tslib@npm:^2.1.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0, tslib@npm:^2.6.2, tslib@npm:^2.6.3": +"tslib@npm:^2.1.0, tslib@npm:^2.4.0": version: 2.8.1 resolution: "tslib@npm:2.8.1" checksum: 10/3e2e043d5c2316461cb54e5c7fe02c30ef6dccb3384717ca22ae5c6b5bc95232a6241df19c622d9c73b809bea33b187f6dbc73030963e29950c2141bc32a79f7 @@ -13800,10 +14155,10 @@ __metadata: linkType: hard "tsx@npm:^4.20.5": - version: 4.20.5 - resolution: "tsx@npm:4.20.5" + version: 4.21.0 + resolution: "tsx@npm:4.21.0" dependencies: - esbuild: "npm:~0.25.0" + esbuild: "npm:~0.27.0" fsevents: "npm:~2.3.3" get-tsconfig: "npm:^4.7.5" dependenciesMeta: @@ -13811,7 +14166,7 @@ __metadata: optional: true bin: tsx: dist/cli.mjs - checksum: 10/161420678027c43d07b60b7b6b512cc67ff86ae3cca0641a19b0d3e742c5e262bca57034c4bff6d9346f9269e9ada24b6030e1d2bc890df5e1a9754865d3c08a + checksum: 10/7afedeff855ba98c47dc28b33d7e8e253c4dc1f791938db402d79c174bdf806b897c1a5f91e5b1259c112520c816f826b4c5d98f0bad7e95b02dec66fedb64d2 languageName: node linkType: hard @@ -13845,6 +14200,13 @@ __metadata: languageName: node linkType: hard +"type-fest@npm:4.41.0, type-fest@npm:^4.0.0": + version: 4.41.0 + resolution: "type-fest@npm:4.41.0" + checksum: 10/617ace794ac0893c2986912d28b3065ad1afb484cad59297835a0807dc63286c39e8675d65f7de08fafa339afcb8fe06a36e9a188b9857756ae1e92ee8bda212 + languageName: node + linkType: hard + "type-fest@npm:^0.18.0": version: 0.18.1 resolution: "type-fest@npm:0.18.1" @@ -13873,13 +14235,6 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^4.0.0": - version: 4.25.0 - resolution: "type-fest@npm:4.25.0" - checksum: 10/16ddf51dbfeef45e6f0a139c16f06d6cd05b61be76b048c41e79997f150a66422219d7ec10a2717ab926505402d59b1ddc8560f5f6c245e1b8a35971c2f1b754 - languageName: node - linkType: hard - "type-is@npm:~1.6.18": version: 1.6.18 resolution: "type-is@npm:1.6.18" @@ -13890,6 +14245,17 @@ __metadata: languageName: node linkType: hard +"typed-array-buffer@npm:^1.0.3": + version: 1.0.3 + resolution: "typed-array-buffer@npm:1.0.3" + dependencies: + call-bound: "npm:^1.0.3" + es-errors: "npm:^1.3.0" + is-typed-array: "npm:^1.1.14" + checksum: 10/3fb91f0735fb413b2bbaaca9fabe7b8fc14a3fa5a5a7546bab8a57e755be0e3788d893195ad9c2b842620592de0e68d4c077d4c2c41f04ec25b8b5bb82fa9a80 + languageName: node + linkType: hard + "typedarray-to-buffer@npm:^3.1.5": version: 3.1.5 resolution: "typedarray-to-buffer@npm:3.1.5" @@ -13932,17 +14298,17 @@ __metadata: linkType: hard "typescript-eslint@npm:^8.48.0": - version: 8.48.0 - resolution: "typescript-eslint@npm:8.48.0" + version: 8.53.0 + resolution: "typescript-eslint@npm:8.53.0" dependencies: - "@typescript-eslint/eslint-plugin": "npm:8.48.0" - "@typescript-eslint/parser": "npm:8.48.0" - "@typescript-eslint/typescript-estree": "npm:8.48.0" - "@typescript-eslint/utils": "npm:8.48.0" + "@typescript-eslint/eslint-plugin": "npm:8.53.0" + "@typescript-eslint/parser": "npm:8.53.0" + "@typescript-eslint/typescript-estree": "npm:8.53.0" + "@typescript-eslint/utils": "npm:8.53.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10/9be54df60faf3b5a6d255032b4478170b6f64e38b8396475a2049479d1e3c1f5a23a18bb4d2d6ff685ef92ff8f2af28215772fe33b48148a8cf83a724d0778d1 + checksum: 10/b4731161a4fec6ce9110e54407a50733e15b0eb48cb9636906a54068af10f8102a7018b9e5db6264604050955a03d3649a79c4869d43bcce215358a8a8a03f96 languageName: node linkType: hard @@ -13967,11 +14333,11 @@ __metadata: linkType: hard "ulid@npm:^2.3.0": - version: 2.3.0 - resolution: "ulid@npm:2.3.0" + version: 2.4.0 + resolution: "ulid@npm:2.4.0" bin: - ulid: ./bin/cli.js - checksum: 10/11d7dd35072b863effb1249f66fb03070142a625610f00e5afd99af7e909b5de9cc7ebca6ede621a6bb1b7479b2489d6f064db6742b55c14bff6496ac60f290f + ulid: bin/cli.js + checksum: 10/409ad0a703ea9f25d2a35cf790b767030a2c7b5ca0df6acb73669628156ab63bb97925a3fd7aaaf0b2384d39bd3ed2f7cd2c2de9f1171df6bc79b8c097865d92 languageName: node linkType: hard @@ -13982,21 +14348,28 @@ __metadata: languageName: node linkType: hard -"unique-filename@npm:^3.0.0": - version: 3.0.0 - resolution: "unique-filename@npm:3.0.0" +"undici-types@npm:~7.16.0": + version: 7.16.0 + resolution: "undici-types@npm:7.16.0" + checksum: 10/db43439f69c2d94cc29f75cbfe9de86df87061d6b0c577ebe9bb3255f49b22c50162a7d7eb413b0458b6510b8ca299ac7cff38c3a29fbd31af9f504bcf7fbc0d + languageName: node + linkType: hard + +"unique-filename@npm:^5.0.0": + version: 5.0.0 + resolution: "unique-filename@npm:5.0.0" dependencies: - unique-slug: "npm:^4.0.0" - checksum: 10/8e2f59b356cb2e54aab14ff98a51ac6c45781d15ceaab6d4f1c2228b780193dc70fae4463ce9e1df4479cb9d3304d7c2043a3fb905bdeca71cc7e8ce27e063df + unique-slug: "npm:^6.0.0" + checksum: 10/a5f67085caef74bdd2a6869a200ed5d68d171f5cc38435a836b5fd12cce4e4eb55e6a190298035c325053a5687ed7a3c96f0a91e82215fd14729769d9ac57d9b languageName: node linkType: hard -"unique-slug@npm:^4.0.0": - version: 4.0.0 - resolution: "unique-slug@npm:4.0.0" +"unique-slug@npm:^6.0.0": + version: 6.0.0 + resolution: "unique-slug@npm:6.0.0" dependencies: imurmurhash: "npm:^0.1.4" - checksum: 10/40912a8963fc02fb8b600cf50197df4a275c602c60de4cac4f75879d3c48558cfac48de08a25cc10df8112161f7180b3bbb4d662aadb711568602f9eddee54f0 + checksum: 10/b78ed9d5b01ff465f80975f17387750ed3639909ac487fa82c4ae4326759f6de87c2131c0c39eca4c68cf06c537a8d104fba1dfc8a30308f99bc505345e1eba3 languageName: node linkType: hard @@ -14014,13 +14387,80 @@ __metadata: languageName: node linkType: hard -"unpipe@npm:1.0.0, unpipe@npm:~1.0.0": +"unpipe@npm:~1.0.0": version: 1.0.0 resolution: "unpipe@npm:1.0.0" checksum: 10/4fa18d8d8d977c55cb09715385c203197105e10a6d220087ec819f50cb68870f02942244f1017565484237f1f8c5d3cd413631b1ae104d3096f24fdfde1b4aa2 languageName: node linkType: hard +"unrs-resolver@npm:^1.6.2, unrs-resolver@npm:^1.9.2": + version: 1.11.1 + resolution: "unrs-resolver@npm:1.11.1" + dependencies: + "@unrs/resolver-binding-android-arm-eabi": "npm:1.11.1" + "@unrs/resolver-binding-android-arm64": "npm:1.11.1" + "@unrs/resolver-binding-darwin-arm64": "npm:1.11.1" + "@unrs/resolver-binding-darwin-x64": "npm:1.11.1" + "@unrs/resolver-binding-freebsd-x64": "npm:1.11.1" + "@unrs/resolver-binding-linux-arm-gnueabihf": "npm:1.11.1" + "@unrs/resolver-binding-linux-arm-musleabihf": "npm:1.11.1" + "@unrs/resolver-binding-linux-arm64-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-arm64-musl": "npm:1.11.1" + "@unrs/resolver-binding-linux-ppc64-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-riscv64-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-riscv64-musl": "npm:1.11.1" + "@unrs/resolver-binding-linux-s390x-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-x64-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-x64-musl": "npm:1.11.1" + "@unrs/resolver-binding-wasm32-wasi": "npm:1.11.1" + "@unrs/resolver-binding-win32-arm64-msvc": "npm:1.11.1" + "@unrs/resolver-binding-win32-ia32-msvc": "npm:1.11.1" + "@unrs/resolver-binding-win32-x64-msvc": "npm:1.11.1" + napi-postinstall: "npm:^0.3.0" + dependenciesMeta: + "@unrs/resolver-binding-android-arm-eabi": + optional: true + "@unrs/resolver-binding-android-arm64": + optional: true + "@unrs/resolver-binding-darwin-arm64": + optional: true + "@unrs/resolver-binding-darwin-x64": + optional: true + "@unrs/resolver-binding-freebsd-x64": + optional: true + "@unrs/resolver-binding-linux-arm-gnueabihf": + optional: true + "@unrs/resolver-binding-linux-arm-musleabihf": + optional: true + "@unrs/resolver-binding-linux-arm64-gnu": + optional: true + "@unrs/resolver-binding-linux-arm64-musl": + optional: true + "@unrs/resolver-binding-linux-ppc64-gnu": + optional: true + "@unrs/resolver-binding-linux-riscv64-gnu": + optional: true + "@unrs/resolver-binding-linux-riscv64-musl": + optional: true + "@unrs/resolver-binding-linux-s390x-gnu": + optional: true + "@unrs/resolver-binding-linux-x64-gnu": + optional: true + "@unrs/resolver-binding-linux-x64-musl": + optional: true + "@unrs/resolver-binding-wasm32-wasi": + optional: true + "@unrs/resolver-binding-win32-arm64-msvc": + optional: true + "@unrs/resolver-binding-win32-ia32-msvc": + optional: true + "@unrs/resolver-binding-win32-x64-msvc": + optional: true + checksum: 10/4de653508cbaae47883a896bd5cdfef0e5e87b428d62620d16fd35cd534beaebf08ebf0cf2f8b4922aa947b2fe745180facf6cc3f39ba364f7ce0f974cb06a70 + languageName: node + linkType: hard + "unzipper@npm:^0.12.3": version: 0.12.3 resolution: "unzipper@npm:0.12.3" @@ -14034,9 +14474,9 @@ __metadata: languageName: node linkType: hard -"update-browserslist-db@npm:^1.1.1": - version: 1.1.2 - resolution: "update-browserslist-db@npm:1.1.2" +"update-browserslist-db@npm:^1.2.0": + version: 1.2.3 + resolution: "update-browserslist-db@npm:1.2.3" dependencies: escalade: "npm:^3.2.0" picocolors: "npm:^1.1.1" @@ -14044,7 +14484,7 @@ __metadata: browserslist: ">= 4.21.0" bin: update-browserslist-db: cli.js - checksum: 10/e7bf8221dfb21eba4a770cd803df94625bb04f65a706aa94c567de9600fe4eb6133fda016ec471dad43b9e7959c1bffb6580b5e20a87808d2e8a13e3892699a9 + checksum: 10/059f774300efb4b084a49293143c511f3ae946d40397b5c30914e900cd5691a12b8e61b41dd54ed73d3b56c8204165a0333107dd784ccf8f8c81790bcc423175 languageName: node linkType: hard @@ -14141,6 +14581,13 @@ __metadata: languageName: node linkType: hard +"validate-npm-package-name@npm:^7.0.0": + version: 7.0.2 + resolution: "validate-npm-package-name@npm:7.0.2" + checksum: 10/2a9bdc6fd5e4284c8e02279446bfd3c38c0c01222555fd3b00b4765d9d47b217d4a200910be71b80b958f6baf40d2d32e812a8632633a2ce376a9b3b74811072 + languageName: node + linkType: hard + "vary@npm:~1.1.2": version: 1.1.2 resolution: "vary@npm:1.1.2" @@ -14189,6 +14636,13 @@ __metadata: languageName: node linkType: hard +"web-vitals@npm:^4.2.4": + version: 4.2.4 + resolution: "web-vitals@npm:4.2.4" + checksum: 10/68cd1c2625a04b26e7eab67110623396afc6c9ef8c3a76f4e780aefe5b7d4ca1691737a0b99119e1d1ca9a463c4d468c0f0090b1875b6d784589d3a4a8503313 + languageName: node + linkType: hard + "webextension-polyfill-ts@npm:^0.26.0": version: 0.26.0 resolution: "webextension-polyfill-ts@npm:0.26.0" @@ -14295,6 +14749,21 @@ __metadata: languageName: node linkType: hard +"which-typed-array@npm:^1.1.16": + version: 1.1.20 + resolution: "which-typed-array@npm:1.1.20" + dependencies: + available-typed-arrays: "npm:^1.0.7" + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.4" + for-each: "npm:^0.3.5" + get-proto: "npm:^1.0.1" + gopd: "npm:^1.2.0" + has-tostringtag: "npm:^1.0.2" + checksum: 10/e56da3fc995d330ff012f682476f7883c16b12d36c6717c87c7ca23eb5a5ef957fa89115dacb389b11a9b4e99d5dbe2d12689b4d5d08c050b5aed0eae385b840 + languageName: node + linkType: hard + "which@npm:^1.2.14": version: 1.3.1 resolution: "which@npm:1.3.1" @@ -14328,14 +14797,14 @@ __metadata: languageName: node linkType: hard -"which@npm:^4.0.0": - version: 4.0.0 - resolution: "which@npm:4.0.0" +"which@npm:^6.0.0": + version: 6.0.0 + resolution: "which@npm:6.0.0" dependencies: isexe: "npm:^3.1.1" bin: node-which: bin/which.js - checksum: 10/f17e84c042592c21e23c8195108cff18c64050b9efb8459589116999ea9da6dd1509e6a1bac3aeebefd137be00fabbb61b5c2bc0aa0f8526f32b58ee2f545651 + checksum: 10/df19b2cd8aac94b333fa29b42e8e371a21e634a742a3b156716f7752a5afe1d73fb5d8bce9b89326f453d96879e8fe626eb421e0117eb1a3ce9fd8c97f6b7db9 languageName: node linkType: hard @@ -14422,7 +14891,22 @@ __metadata: languageName: node linkType: hard -"ws@npm:^7.4.6, ws@npm:^7.5.10": +"ws@npm:8.18.0": + version: 8.18.0 + resolution: "ws@npm:8.18.0" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 10/70dfe53f23ff4368d46e4c0b1d4ca734db2c4149c6f68bc62cb16fc21f753c47b35fcc6e582f3bdfba0eaeb1c488cddab3c2255755a5c3eecb251431e42b3ff6 + languageName: node + linkType: hard + +"ws@npm:^7.4.6": version: 7.5.10 resolution: "ws@npm:7.5.10" peerDependencies: @@ -14437,6 +14921,15 @@ __metadata: languageName: node linkType: hard +"wsl-utils@npm:^0.1.0": + version: 0.1.0 + resolution: "wsl-utils@npm:0.1.0" + dependencies: + is-wsl: "npm:^3.1.0" + checksum: 10/de4c92187e04c3c27b4478f410a02e81c351dc85efa3447bf1666f34fc80baacd890a6698ec91995631714086992036013286aea3d77e6974020d40a08e00aec + languageName: node + linkType: hard + "xhr2@npm:0.2.1": version: 0.2.1 resolution: "xhr2@npm:0.2.1" @@ -14501,11 +14994,11 @@ __metadata: linkType: hard "yaml@npm:^2.2.2, yaml@npm:^2.3.4": - version: 2.8.0 - resolution: "yaml@npm:2.8.0" + version: 2.8.2 + resolution: "yaml@npm:2.8.2" bin: yaml: bin.mjs - checksum: 10/7d4bd9c10d0e467601f496193f2ac254140f8e36f96f5ff7f852b9ce37974168eb7354f4c36dc8837dde527a2043d004b6aff48818ec24a69ab2dd3c6b6c381c + checksum: 10/4eab0074da6bc5a5bffd25b9b359cf7061b771b95d1b3b571852098380db3b1b8f96e0f1f354b56cc7216aa97cea25163377ccbc33a2e9ce00316fe8d02f4539 languageName: node linkType: hard From 61d99420fbc42c00437090b339ae54223be39042 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Wed, 21 Jan 2026 16:29:30 +0100 Subject: [PATCH 13/55] fix: update yarn.lock --- package.json | 3 +- .../config-registry-controller/package.json | 2 +- .../config-registry-api-service.ts | 4 +- yarn.lock | 44 +++++++++---------- 4 files changed, 28 insertions(+), 25 deletions(-) diff --git a/package.json b/package.json index 3c3fce1e66f..e226d412f54 100644 --- a/package.json +++ b/package.json @@ -112,7 +112,8 @@ "@keystonehq/bc-ur-registry-eth>hdkey>secp256k1": true, "babel-runtime>core-js": false, "simple-git-hooks": false, - "tsx>esbuild": false + "tsx>esbuild": false, + "eslint-plugin-import-x>unrs-resolver": false } } } diff --git a/packages/config-registry-controller/package.json b/packages/config-registry-controller/package.json index 933c303c529..db9ba5f0b0b 100644 --- a/packages/config-registry-controller/package.json +++ b/packages/config-registry-controller/package.json @@ -51,13 +51,13 @@ "@metamask/base-controller": "^9.0.0", "@metamask/controller-utils": "^11.16.0", "@metamask/messenger": "^0.3.0", + "@metamask/network-controller": "workspace:*", "@metamask/polling-controller": "^16.0.0", "@metamask/remote-feature-flag-controller": "workspace:*" }, "devDependencies": { "@lavamoat/allow-scripts": "^3.0.4", "@metamask/auto-changelog": "^3.4.4", - "@metamask/network-controller": "workspace:*", "@ts-bridge/cli": "^0.6.4", "@types/jest": "^27.4.1", "deepmerge": "^4.2.2", diff --git a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts index 973cc06b8ac..dcf4c6a2491 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts @@ -32,7 +32,9 @@ export type ConfigRegistryApiServiceOptions = { circuitBreakDuration?: number; }; -export class ConfigRegistryApiService implements AbstractConfigRegistryApiService { +export class ConfigRegistryApiService + implements AbstractConfigRegistryApiService +{ readonly #policy: ServicePolicy; readonly #apiBaseUrl: string; diff --git a/yarn.lock b/yarn.lock index 02f75937c43..b956e460f54 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7790,9 +7790,9 @@ __metadata: linkType: hard "comment-parser@npm:^1.4.1": - version: 1.4.3 - resolution: "comment-parser@npm:1.4.3" - checksum: 10/9e82c5653625f1d4ea86049f371446882d572aac2b4e5762efe5cbaab6b60eccbd3163fe9d4b8c768a6c9f5e5697d88c870d446c0bf72433635772dbde53013b + version: 1.4.4 + resolution: "comment-parser@npm:1.4.4" + checksum: 10/e2480c88288ad479525c81eca0b1711a4b5157e756ed723e7ae95c1da4468266a621a2f46097abf30553ba0373557e2467adb2490368f0aac12093d0e2ef4633 languageName: node linkType: hard @@ -8196,7 +8196,7 @@ __metadata: languageName: node linkType: hard -"detect-indent@npm:^7.0.1": +"detect-indent@npm:^7.0.2": version: 7.0.2 resolution: "detect-indent@npm:7.0.2" checksum: 10/ef215d1b55a14f677ce03e840973b25362b6f8cd3f566bc82831fa1abb2be6a95423729bc573dc2334b1371ad7be18d9ec67e1a9611b71a04cb6d63f0d8e54cc @@ -9700,10 +9700,10 @@ __metadata: languageName: node linkType: hard -"git-hooks-list@npm:^4.0.0": - version: 4.1.1 - resolution: "git-hooks-list@npm:4.1.1" - checksum: 10/a56c8cc3dab505bde2c6de032164a9113968ab7f249dfe2c9f2f23be872165f88c91e097994e009d31e56dd1e81c1f714d0972133314d8d3c6bd92a847ba562f +"git-hooks-list@npm:^4.1.1": + version: 4.2.1 + resolution: "git-hooks-list@npm:4.2.1" + checksum: 10/39449520045539c03b1d45d3a010424849152d6f723b638c6f19cb8c8b0993bb30ed5ef09653f4d1c1356f5fb51a396059096d8bdfcb6ca7ccb54f6e26efc338 languageName: node linkType: hard @@ -12667,16 +12667,16 @@ __metadata: linkType: hard "prettier-plugin-packagejson@npm:^2.4.5": - version: 2.5.21 - resolution: "prettier-plugin-packagejson@npm:2.5.21" + version: 2.5.22 + resolution: "prettier-plugin-packagejson@npm:2.5.22" dependencies: - sort-package-json: "npm:3.5.0" + sort-package-json: "npm:3.6.0" peerDependencies: prettier: ">= 1.16.0" peerDependenciesMeta: prettier: optional: true - checksum: 10/04d10f1a5dada1e4179588dcd0d52ec13680554b26e73fd260c02f8f29ae9d6e78d7458203dd553c6b02237928dab119475415598cd487288a79921126373122 + checksum: 10/874ba785d6c3c32abca23470cebfd7b80de7b546c0b3752a83cf5aea7a8030885f0c3a91ef40c52373c1be144b46983d1e5bc6d492096d79604441eae6ed1be0 languageName: node linkType: hard @@ -13595,27 +13595,27 @@ __metadata: languageName: node linkType: hard -"sort-object-keys@npm:^2.0.0": +"sort-object-keys@npm:^2.0.1": version: 2.1.0 resolution: "sort-object-keys@npm:2.1.0" checksum: 10/a0a18a6f4ab601adb889204a83e2664a4810042dd9680e588cabb47fffd40473939ce3fda5a28fdb58bac0762a7b45ad442815465b978d4b243bab840df3d7cd languageName: node linkType: hard -"sort-package-json@npm:3.5.0": - version: 3.5.0 - resolution: "sort-package-json@npm:3.5.0" +"sort-package-json@npm:3.6.0": + version: 3.6.0 + resolution: "sort-package-json@npm:3.6.0" dependencies: - detect-indent: "npm:^7.0.1" + detect-indent: "npm:^7.0.2" detect-newline: "npm:^4.0.1" - git-hooks-list: "npm:^4.0.0" + git-hooks-list: "npm:^4.1.1" is-plain-obj: "npm:^4.1.0" - semver: "npm:^7.7.1" - sort-object-keys: "npm:^2.0.0" - tinyglobby: "npm:^0.2.12" + semver: "npm:^7.7.3" + sort-object-keys: "npm:^2.0.1" + tinyglobby: "npm:^0.2.15" bin: sort-package-json: cli.js - checksum: 10/902ac1524c85a9c512170aad6e77e471e7237c91ba3d1e6653dcd0f05a6fd786efce276a79f82283828f2f7ee8ac28b8d17c97e3d5dfd688f629b4696a712d85 + checksum: 10/1489edd177dc325c1e5fbfa55e9583dfea8caa950363b43f797d99986f00b722644275f4dfd5491265519365d6394a5fec9fe5d360ed83b74317fdc9fc071ba1 languageName: node linkType: hard From 980ac4e9d8e12af13cbd969bfa4c26347df502bf Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Wed, 21 Jan 2026 16:40:47 +0100 Subject: [PATCH 14/55] chore: update yarn.lock --- yarn.lock | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/yarn.lock b/yarn.lock index 40a76951d28..f7de217dbb3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2972,6 +2972,31 @@ __metadata: languageName: unknown linkType: soft +"@metamask/config-registry-controller@workspace:packages/config-registry-controller": + version: 0.0.0-use.local + resolution: "@metamask/config-registry-controller@workspace:packages/config-registry-controller" + dependencies: + "@lavamoat/allow-scripts": "npm:^3.0.4" + "@metamask/auto-changelog": "npm:^3.4.4" + "@metamask/base-controller": "npm:^9.0.0" + "@metamask/controller-utils": "npm:^11.16.0" + "@metamask/messenger": "npm:^0.3.0" + "@metamask/network-controller": "workspace:*" + "@metamask/polling-controller": "npm:^16.0.0" + "@metamask/remote-feature-flag-controller": "workspace:*" + "@ts-bridge/cli": "npm:^0.6.4" + "@types/jest": "npm:^27.4.1" + deepmerge: "npm:^4.2.2" + jest: "npm:^27.5.1" + nock: "npm:^13.3.1" + sinon: "npm:^9.2.4" + ts-jest: "npm:^27.1.4" + typedoc: "npm:^0.24.8" + typedoc-plugin-missing-exports: "npm:^2.0.0" + typescript: "npm:~5.3.3" + languageName: unknown + linkType: soft + "@metamask/connectivity-controller@npm:^0.1.0, @metamask/connectivity-controller@workspace:packages/connectivity-controller": version: 0.0.0-use.local resolution: "@metamask/connectivity-controller@workspace:packages/connectivity-controller" @@ -2997,7 +3022,7 @@ __metadata: languageName: node linkType: hard -"@metamask/controller-utils@npm:^11.15.0, @metamask/controller-utils@npm:^11.18.0, @metamask/controller-utils@workspace:packages/controller-utils": +"@metamask/controller-utils@npm:^11.15.0, @metamask/controller-utils@npm:^11.16.0, @metamask/controller-utils@npm:^11.18.0, @metamask/controller-utils@workspace:packages/controller-utils": version: 0.0.0-use.local resolution: "@metamask/controller-utils@workspace:packages/controller-utils" dependencies: @@ -4209,7 +4234,7 @@ __metadata: languageName: unknown linkType: soft -"@metamask/network-controller@npm:^29.0.0, @metamask/network-controller@workspace:packages/network-controller": +"@metamask/network-controller@npm:^29.0.0, @metamask/network-controller@workspace:*, @metamask/network-controller@workspace:packages/network-controller": version: 0.0.0-use.local resolution: "@metamask/network-controller@workspace:packages/network-controller" dependencies: @@ -4466,7 +4491,7 @@ __metadata: languageName: unknown linkType: soft -"@metamask/polling-controller@npm:^16.0.2, @metamask/polling-controller@workspace:packages/polling-controller": +"@metamask/polling-controller@npm:^16.0.0, @metamask/polling-controller@npm:^16.0.2, @metamask/polling-controller@workspace:packages/polling-controller": version: 0.0.0-use.local resolution: "@metamask/polling-controller@workspace:packages/polling-controller" dependencies: @@ -4656,7 +4681,7 @@ __metadata: languageName: unknown linkType: soft -"@metamask/remote-feature-flag-controller@npm:^4.0.0, @metamask/remote-feature-flag-controller@workspace:packages/remote-feature-flag-controller": +"@metamask/remote-feature-flag-controller@npm:^4.0.0, @metamask/remote-feature-flag-controller@workspace:*, @metamask/remote-feature-flag-controller@workspace:packages/remote-feature-flag-controller": version: 0.0.0-use.local resolution: "@metamask/remote-feature-flag-controller@workspace:packages/remote-feature-flag-controller" dependencies: From 945154ab7233af70dbef7f47c37c1e28ea58213a Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Wed, 21 Jan 2026 16:43:57 +0100 Subject: [PATCH 15/55] chore: update config-registry-controller package.json --- packages/config-registry-controller/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/config-registry-controller/package.json b/packages/config-registry-controller/package.json index db9ba5f0b0b..75f441ae159 100644 --- a/packages/config-registry-controller/package.json +++ b/packages/config-registry-controller/package.json @@ -51,9 +51,9 @@ "@metamask/base-controller": "^9.0.0", "@metamask/controller-utils": "^11.16.0", "@metamask/messenger": "^0.3.0", - "@metamask/network-controller": "workspace:*", + "@metamask/network-controller": "^29.0.0", "@metamask/polling-controller": "^16.0.0", - "@metamask/remote-feature-flag-controller": "workspace:*" + "@metamask/remote-feature-flag-controller": "^4.0.0" }, "devDependencies": { "@lavamoat/allow-scripts": "^3.0.4", From ab102d8609b19200ed8d06f590eee91047b499c1 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Thu, 22 Jan 2026 09:29:54 +0100 Subject: [PATCH 16/55] chore: update yarn.lock --- yarn.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/yarn.lock b/yarn.lock index f7de217dbb3..b1c61d37185 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2981,9 +2981,9 @@ __metadata: "@metamask/base-controller": "npm:^9.0.0" "@metamask/controller-utils": "npm:^11.16.0" "@metamask/messenger": "npm:^0.3.0" - "@metamask/network-controller": "workspace:*" + "@metamask/network-controller": "npm:^29.0.0" "@metamask/polling-controller": "npm:^16.0.0" - "@metamask/remote-feature-flag-controller": "workspace:*" + "@metamask/remote-feature-flag-controller": "npm:^4.0.0" "@ts-bridge/cli": "npm:^0.6.4" "@types/jest": "npm:^27.4.1" deepmerge: "npm:^4.2.2" @@ -4234,7 +4234,7 @@ __metadata: languageName: unknown linkType: soft -"@metamask/network-controller@npm:^29.0.0, @metamask/network-controller@workspace:*, @metamask/network-controller@workspace:packages/network-controller": +"@metamask/network-controller@npm:^29.0.0, @metamask/network-controller@workspace:packages/network-controller": version: 0.0.0-use.local resolution: "@metamask/network-controller@workspace:packages/network-controller" dependencies: @@ -4681,7 +4681,7 @@ __metadata: languageName: unknown linkType: soft -"@metamask/remote-feature-flag-controller@npm:^4.0.0, @metamask/remote-feature-flag-controller@workspace:*, @metamask/remote-feature-flag-controller@workspace:packages/remote-feature-flag-controller": +"@metamask/remote-feature-flag-controller@npm:^4.0.0, @metamask/remote-feature-flag-controller@workspace:packages/remote-feature-flag-controller": version: 0.0.0-use.local resolution: "@metamask/remote-feature-flag-controller@workspace:packages/remote-feature-flag-controller" dependencies: From 5f11236600515f01066dc82055b0bc79f640909e Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Thu, 22 Jan 2026 09:47:53 +0100 Subject: [PATCH 17/55] fix: fix lint --- tsconfig.build.json | 4 ++-- tsconfig.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tsconfig.build.json b/tsconfig.build.json index 58df49a51be..0007719e7db 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -55,8 +55,8 @@ { "path": "./packages/composable-controller/tsconfig.build.json" }, - { - "path": "./packages/config-registry-controller/tsconfig.build.json" + { + "path": "./packages/config-registry-controller/tsconfig.build.json" }, { "path": "./packages/connectivity-controller/tsconfig.build.json" diff --git a/tsconfig.json b/tsconfig.json index f6e63f4c26d..cd3599de835 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -56,8 +56,8 @@ { "path": "./packages/composable-controller" }, - { - "path": "./packages/config-registry-controller" + { + "path": "./packages/config-registry-controller" }, { "path": "./packages/connectivity-controller" From 0503c7d0d8c341c085d73556f32c9aee3b1b26bf Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Thu, 22 Jan 2026 11:26:39 +0100 Subject: [PATCH 18/55] feat: add test coverage --- .../src/ConfigRegistryController.test.ts | 219 +++++++++++- .../src/ConfigRegistryController.ts | 6 +- .../config-registry-api-service.test.ts | 332 +++++++++++++++++- .../transformers.test.ts | 64 +++- 4 files changed, 573 insertions(+), 48 deletions(-) diff --git a/packages/config-registry-controller/src/ConfigRegistryController.test.ts b/packages/config-registry-controller/src/ConfigRegistryController.test.ts index 5472dfea904..677db5becad 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.test.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.test.ts @@ -190,9 +190,22 @@ describe('ConfigRegistryController', () => { fallbackConfig: MOCK_FALLBACK_CONFIG, }); - // Fallback config is private, but we can verify it's used when needed expect(controller.state.configs).toStrictEqual({ networks: {} }); }); + + it('should use default ConfigRegistryApiService when apiService is not provided', () => { + const controller = new ConfigRegistryController({ + messenger, + }); + + expect(controller.state).toStrictEqual({ + configs: { networks: {} }, + version: null, + lastFetched: null, + fetchError: null, + etag: null, + }); + }); }); describe('getConfig', () => { @@ -284,7 +297,6 @@ describe('ConfigRegistryController', () => { const result = controller.getAllConfigs(); result.key1 = { key: 'key1', value: 'modified' }; - // Original should not be modified expect(controller.state.configs.networks?.key1?.value).toBe('value1'); }); @@ -303,6 +315,32 @@ describe('ConfigRegistryController', () => { expect(result).toStrictEqual(configs); expect(testController.getAllConfigs()).toStrictEqual(configs); }); + + it('should return empty object when state.configs is undefined', () => { + const controller = new ConfigRegistryController({ + apiService, + messenger, + state: { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + configs: undefined as any, + }, + }); + + expect(controller.getAllConfigs()).toStrictEqual({}); + }); + + it('should return empty object when state.configs.networks is undefined', () => { + const controller = new ConfigRegistryController({ + apiService, + messenger, + state: { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + configs: {} as any, + }, + }); + + expect(controller.getAllConfigs()).toStrictEqual({}); + }); }); describe('getConfigValue', () => { @@ -419,6 +457,42 @@ describe('ConfigRegistryController', () => { expect(controller.getConfig('test-key')?.value).toBe('test-value'); }); + + it('should initialize configs when state.configs is undefined', () => { + const controller = new ConfigRegistryController({ + messenger, + apiService, + state: { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + configs: undefined as any, + }, + }); + + controller.setConfig('new-key', 'value'); + + expect(controller.state.configs?.networks?.['new-key']).toBeDefined(); + expect(controller.state.configs?.networks?.['new-key']?.value).toBe( + 'value', + ); + }); + + it('should initialize networks when state.configs.networks is undefined', () => { + const controller = new ConfigRegistryController({ + messenger, + apiService, + state: { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + configs: {} as any, + }, + }); + + controller.setConfig('new-key', 'value'); + + expect(controller.state.configs?.networks?.['new-key']).toBeDefined(); + expect(controller.state.configs?.networks?.['new-key']?.value).toBe( + 'value', + ); + }); }); describe('removeConfig', () => { @@ -554,7 +628,7 @@ describe('ConfigRegistryController', () => { expect(controller.state.fetchError).toBe('Network error'); }); - it('should not use fallback when configs already exist', async () => { + it('should set fetchError when configs already exist (not use fallback)', async () => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { configRegistryApiEnabled: true, @@ -581,7 +655,6 @@ describe('ConfigRegistryController', () => { await controller._executePoll({}); - // Should keep existing configs, not use fallback expect(controller.state.configs).toStrictEqual(existingConfigs); expect(controller.state.fetchError).toBe('Network error'); }); @@ -604,10 +677,8 @@ describe('ConfigRegistryController', () => { fallbackConfig: MOCK_FALLBACK_CONFIG, }); - // Call _executePoll directly to test error handling await controller._executePoll({}); - // Since we have no configs, it should use fallback expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG, }); @@ -615,6 +686,89 @@ describe('ConfigRegistryController', () => { expect(mockRemoteFeatureFlagGetState).toHaveBeenCalled(); }); + it('should handle notModified response and clear fetchError', async () => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); + + const notModifiedApiService = buildMockApiService({ + fetchConfig: jest.fn().mockResolvedValue({ + notModified: true, + etag: '"test-etag"', + }), + }); + + const controller = new ConfigRegistryController({ + apiService: notModifiedApiService, + messenger, + state: { + fetchError: 'Previous error', + }, + }); + + await controller._executePoll({}); + + expect(controller.state.fetchError).toBeNull(); + expect(controller.state.etag).toBeNull(); + }); + + it('should handle non-Error exceptions', async () => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); + + const errorApiService = buildMockApiService({ + fetchConfig: jest.fn().mockRejectedValue('String error'), // Not an Error instance + }); + + const controller = new ConfigRegistryController({ + apiService: errorApiService, + messenger, + fallbackConfig: MOCK_FALLBACK_CONFIG, + }); + + await controller._executePoll({}); + + expect(controller.state.configs).toStrictEqual({ + networks: MOCK_FALLBACK_CONFIG, + }); + expect(controller.state.fetchError).toBe('Unknown error occurred'); + }); + + it('should handle error when state.configs is null', async () => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); + + const errorApiService = buildMockApiService({ + fetchConfig: jest.fn().mockRejectedValue(new Error('Network error')), + }); + + const controller = new ConfigRegistryController({ + apiService: errorApiService, + messenger, + fallbackConfig: MOCK_FALLBACK_CONFIG, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + state: { configs: null as any }, + }); + + await controller._executePoll({}); + + expect(controller.state.configs).toStrictEqual({ + networks: MOCK_FALLBACK_CONFIG, + }); + expect(controller.state.fetchError).toBe('Network error'); + }); + it('should work via messenger actions', async () => { const controller = new ConfigRegistryController({ apiService, @@ -644,7 +798,6 @@ describe('ConfigRegistryController', () => { controller.setConfig('persist-key', 'persist-value'); - // Verify state is updated expect(controller.state.configs.networks?.['persist-key']).toBeDefined(); }); @@ -678,6 +831,53 @@ describe('ConfigRegistryController', () => { expect(controller.state.fetchError).toBe('Test error'); }); + + it('should use default error message when useFallbackConfig is called without errorMessage', () => { + const controller = new ConfigRegistryController({ + messenger, + apiService, + fallbackConfig: MOCK_FALLBACK_CONFIG, + }); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (controller as any).useFallbackConfig(); + + expect(controller.state.configs).toStrictEqual({ + networks: MOCK_FALLBACK_CONFIG, + }); + expect(controller.state.fetchError).toBe( + 'Using fallback configuration - API unavailable', + ); + expect(controller.state.etag).toBeNull(); + }); + }); + + describe('startPolling', () => { + it('should return a polling token string', () => { + const controller = new ConfigRegistryController({ + messenger, + apiService, + }); + + const token = controller.startPolling({}); + expect(typeof token).toBe('string'); + expect(token.length).toBeGreaterThan(0); + + controller.stopPolling(); + }); + + it('should return a polling token string when called without input', () => { + const controller = new ConfigRegistryController({ + messenger, + apiService, + }); + + const token = controller.startPolling(); + expect(typeof token).toBe('string'); + expect(token.length).toBeGreaterThan(0); + + controller.stopPolling(); + }); }); describe('feature flag', () => { @@ -787,7 +987,6 @@ describe('ConfigRegistryController', () => { const mockNetworks = [ { - // Should be included: featured, active, non-testnet chainId: '0x1', name: 'Ethereum Mainnet', nativeCurrency: 'ETH', @@ -811,7 +1010,6 @@ describe('ConfigRegistryController', () => { isDeletable: false, }, { - // Should be excluded: testnet chainId: '0x5', name: 'Goerli', nativeCurrency: 'ETH', @@ -835,7 +1033,6 @@ describe('ConfigRegistryController', () => { isDeletable: false, }, { - // Should be excluded: not featured chainId: '0xa', name: 'Optimism', nativeCurrency: 'ETH', @@ -859,7 +1056,6 @@ describe('ConfigRegistryController', () => { isDeletable: false, }, { - // Should be excluded: not active chainId: '0x89', name: 'Polygon', nativeCurrency: 'MATIC', @@ -907,7 +1103,6 @@ describe('ConfigRegistryController', () => { await controller._executePoll({}); - // Only the first network (0x1) should be stored expect(controller.state.configs.networks?.['0x1']).toBeDefined(); expect(controller.state.configs.networks?.['0x5']).toBeUndefined(); expect(controller.state.configs.networks?.['0xa']).toBeUndefined(); diff --git a/packages/config-registry-controller/src/ConfigRegistryController.ts b/packages/config-registry-controller/src/ConfigRegistryController.ts index e0094319dba..09bdcc8e83e 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.ts @@ -213,7 +213,7 @@ export class ConfigRegistryController extends StaticIntervalPollingController { // eslint-disable-next-line @typescript-eslint/no-explicit-any (state.configs as any) = { networks: { ...this.#fallbackConfig } }; @@ -277,7 +277,7 @@ export class ConfigRegistryController extends StaticIntervalPollingController { state.fetchError = errorMessage; diff --git a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts index e1baa0cf3d8..47f847c0827 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts @@ -61,6 +61,26 @@ describe('ConfigRegistryApiService', () => { }); expect(service).toBeInstanceOf(ConfigRegistryApiService); }); + + it('should create instance with empty options object', () => { + const service = new ConfigRegistryApiService({}); + expect(service).toBeInstanceOf(ConfigRegistryApiService); + }); + + it('should use default values for unspecified options', () => { + const service = new ConfigRegistryApiService({ + apiBaseUrl: 'https://test.com', + }); + expect(service).toBeInstanceOf(ConfigRegistryApiService); + }); + + it('should use default fetch when not provided', () => { + const service = new ConfigRegistryApiService({ + apiBaseUrl: 'https://test.com', + endpointPath: '/test', + }); + expect(service).toBeInstanceOf(ConfigRegistryApiService); + }); }); describe('fetchConfig', () => { @@ -90,6 +110,48 @@ describe('ConfigRegistryApiService', () => { expect(scope.isDone()).toBe(true); }); + it('should execute fetchWithTimeout function and call clearTimeout on success', async () => { + const mockHeaders = { + get: jest.fn().mockReturnValue('"test-etag"'), + }; + const clearTimeoutSpy = jest.spyOn(global, 'clearTimeout'); + const setTimeoutSpy = jest.spyOn(global, 'setTimeout'); + const customFetch = jest.fn().mockResolvedValue({ + ok: true, + status: 200, + headers: mockHeaders, + json: async () => MOCK_API_RESPONSE, + } as unknown as Response); + + const service = new ConfigRegistryApiService({ + fetch: customFetch, + timeout: 1000, + }); + + await service.fetchConfig(); + + expect(setTimeoutSpy).toHaveBeenCalled(); + expect(clearTimeoutSpy).toHaveBeenCalled(); + clearTimeoutSpy.mockRestore(); + setTimeoutSpy.mockRestore(); + }); + + it('should successfully fetch config from API without ETag header', async () => { + const scope = nock(DEFAULT_API_BASE_URL) + .get(DEFAULT_ENDPOINT_PATH) + .reply(200, MOCK_API_RESPONSE); + + const service = new ConfigRegistryApiService(); + const result = await service.fetchConfig(); + + expect(result.notModified).toBe(false); + expect(result.etag).toBeUndefined(); + expect( + (result as Extract).data, + ).toStrictEqual(MOCK_API_RESPONSE); + expect(scope.isDone()).toBe(true); + }); + it('should handle 304 Not Modified response', async () => { const etag = '"test-etag-123"'; const scope = nock(DEFAULT_API_BASE_URL) @@ -104,6 +166,26 @@ describe('ConfigRegistryApiService', () => { expect(scope.isDone()).toBe(true); }); + it('should handle 304 Not Modified response without ETag header', async () => { + const mockHeaders = { + get: jest.fn().mockReturnValue(null), + }; + const customFetch = jest.fn().mockResolvedValue({ + ok: true, + status: 304, + headers: mockHeaders, + } as unknown as Response); + + const service = new ConfigRegistryApiService({ + fetch: customFetch, + }); + + const result = await service.fetchConfig(); + + expect(result.notModified).toBe(true); + expect(result.etag).toBeUndefined(); + }); + it('should include If-None-Match header when etag is provided', async () => { const etag = '"test-etag-123"'; const scope = nock(DEFAULT_API_BASE_URL) @@ -117,6 +199,29 @@ describe('ConfigRegistryApiService', () => { expect(scope.isDone()).toBe(true); }); + it('should not include If-None-Match header when etag is undefined', async () => { + const scope = nock(DEFAULT_API_BASE_URL) + .get(DEFAULT_ENDPOINT_PATH) + .reply(200, MOCK_API_RESPONSE); + + const service = new ConfigRegistryApiService(); + await service.fetchConfig({ etag: undefined }); + + expect(scope.isDone()).toBe(true); + }); + + it('should handle fetchConfig called with undefined options', async () => { + const scope = nock(DEFAULT_API_BASE_URL) + .get(DEFAULT_ENDPOINT_PATH) + .reply(200, MOCK_API_RESPONSE); + + const service = new ConfigRegistryApiService(); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + await service.fetchConfig(undefined as any); + + expect(scope.isDone()).toBe(true); + }); + it('should throw error on invalid response structure', async () => { const invalidResponse = { invalid: 'data' }; const scope = nock(DEFAULT_API_BASE_URL) @@ -131,20 +236,88 @@ describe('ConfigRegistryApiService', () => { expect(scope.isDone()).toBe(true); }); + it('should throw error when data is null', async () => { + const mockHeaders = { + get: jest.fn().mockReturnValue(null), + }; + const customFetch = jest.fn().mockResolvedValue({ + ok: true, + status: 200, + headers: mockHeaders, + json: async () => null, + } as unknown as Response); + + const service = new ConfigRegistryApiService({ + fetch: customFetch, + }); + + await expect(service.fetchConfig()).rejects.toThrow( + 'Invalid response structure from config registry API', + ); + }); + + it('should throw error when data.data is null', async () => { + const mockHeaders = { + get: jest.fn().mockReturnValue(null), + }; + const customFetch = jest.fn().mockResolvedValue({ + ok: true, + status: 200, + headers: mockHeaders, + json: async () => ({ data: null }), + } as unknown as Response); + + const service = new ConfigRegistryApiService({ + fetch: customFetch, + }); + + await expect(service.fetchConfig()).rejects.toThrow( + 'Invalid response structure from config registry API', + ); + }); + + it('should throw error when data.data.networks is not an array', async () => { + const mockHeaders = { + get: jest.fn().mockReturnValue(null), + }; + const customFetch = jest.fn().mockResolvedValue({ + ok: true, + status: 200, + headers: mockHeaders, + json: async () => ({ data: { networks: 'not-an-array' } }), + } as unknown as Response); + + const service = new ConfigRegistryApiService({ + fetch: customFetch, + }); + + await expect(service.fetchConfig()).rejects.toThrow( + 'Invalid response structure from config registry API', + ); + }); + it('should throw error on HTTP error status', async () => { - const scope = nock(DEFAULT_API_BASE_URL) - .get(DEFAULT_ENDPOINT_PATH) - .reply(500, { error: 'Internal Server Error' }); + const mockHeaders = { + get: jest.fn().mockReturnValue(null), + }; + const customFetch = jest.fn().mockResolvedValue({ + ok: false, + status: 500, + statusText: 'Internal Server Error', + headers: mockHeaders, + } as unknown as Response); - const service = new ConfigRegistryApiService(); + const service = new ConfigRegistryApiService({ + fetch: customFetch, + }); - await expect(service.fetchConfig()).rejects.toThrow(expect.any(Error)); - expect(scope.isDone()).toBe(true); + await expect(service.fetchConfig()).rejects.toThrow( + 'Failed to fetch config: 500 Internal Server Error', + ); }); it('should handle timeout', async () => { - const testTimeout = 1000; // Use shorter timeout for test - // Use a custom fetch that simulates timeout with AbortError + const testTimeout = 1000; const customFetch = jest.fn().mockImplementation(() => { const abortError = new Error('Request aborted'); abortError.name = 'AbortError'; @@ -161,6 +334,56 @@ describe('ConfigRegistryApiService', () => { ); }, 10000); // Increase Jest timeout for this test + it('should trigger setTimeout callback when request exceeds timeout', async () => { + const testTimeout = 50; + + const customFetch = jest + .fn() + .mockImplementation((_url: string, options?: RequestInit) => { + const signal = options?.signal as AbortSignal; + return new Promise((_resolve, reject) => { + if (signal?.aborted) { + const abortError = new Error('Request aborted'); + abortError.name = 'AbortError'; + reject(abortError); + return; + } + + if (signal) { + signal.addEventListener('abort', () => { + const abortError = new Error('Request aborted'); + abortError.name = 'AbortError'; + reject(abortError); + }); + } + }); + }); + + const service = new ConfigRegistryApiService({ + timeout: testTimeout, + fetch: customFetch, + }); + + await expect(service.fetchConfig()).rejects.toThrow( + `Request timeout after ${testTimeout}ms`, + ); + }, 10000); // Increase Jest timeout for this test + + it('should handle non-AbortError in fetchWithTimeout', async () => { + const customFetch = jest + .fn() + .mockRejectedValue(new Error('Network connection failed')); + + const service = new ConfigRegistryApiService({ + fetch: customFetch, + timeout: 1000, + }); + + await expect(service.fetchConfig()).rejects.toThrow( + 'Network connection failed', + ); + }); + it('should retry on failure', async () => { nock(DEFAULT_API_BASE_URL) .get(DEFAULT_ENDPOINT_PATH) @@ -199,9 +422,8 @@ describe('ConfigRegistryApiService', () => { it('should register and call onBreak handler', async () => { const maximumConsecutiveFailures = 3; - const retries = 0; // No retries to simplify test + const retries = 0; - // Create enough failures to trigger circuit break for (let i = 0; i < maximumConsecutiveFailures; i++) { nock(DEFAULT_API_BASE_URL) .get(DEFAULT_ENDPOINT_PATH) @@ -217,23 +439,27 @@ describe('ConfigRegistryApiService', () => { service.onBreak(onBreakHandler); - // Trigger failures to break the circuit for (let i = 0; i < maximumConsecutiveFailures; i++) { await expect(service.fetchConfig()).rejects.toThrow(expect.any(Error)); - // Advance time slightly between calls await clock.tickAsync(100); } - // Next call should trigger onBreak const finalPromise = service.fetchConfig(); finalPromise.catch(() => { - // Suppress unhandled promise rejection + // Expected rejection }); await clock.tickAsync(100); await expect(finalPromise).rejects.toThrow(expect.any(Error)); expect(onBreakHandler).toHaveBeenCalled(); }); + + it('should return the result from policy.onBreak', () => { + const service = new ConfigRegistryApiService(); + const handler = jest.fn(); + const result = service.onBreak(handler); + expect(result).toBeDefined(); + }); }); describe('onDegraded', () => { @@ -245,6 +471,54 @@ describe('ConfigRegistryApiService', () => { expect(service.onDegraded).toBeDefined(); }); + + it('should call onDegraded handler when service becomes degraded', async () => { + const degradedThreshold = 2000; // 2 seconds + const service = new ConfigRegistryApiService({ + degradedThreshold, + retries: 0, + }); + + const onDegradedHandler = jest.fn(); + service.onDegraded(onDegradedHandler); + + const slowFetch = jest.fn().mockImplementation( + () => + new Promise((resolve) => { + setTimeout( + () => + resolve({ + ok: true, + status: 200, + headers: { + get: jest.fn().mockReturnValue('"custom-etag"'), + } as unknown as Headers, + json: async () => MOCK_API_RESPONSE, + } as Response), + degradedThreshold + 100, + ); + }), + ); + + const slowService = new ConfigRegistryApiService({ + fetch: slowFetch, + degradedThreshold, + retries: 0, + }); + + slowService.onDegraded(onDegradedHandler); + + await slowService.fetchConfig(); + + expect(slowService.onDegraded).toBeDefined(); + }); + + it('should return the result from policy.onDegraded', () => { + const service = new ConfigRegistryApiService(); + const handler = jest.fn(); + const result = service.onDegraded(handler); + expect(result).toBeDefined(); + }); }); describe('custom fetch function', () => { @@ -276,6 +550,21 @@ describe('ConfigRegistryApiService', () => { }); describe('URL construction', () => { + it('should handle base URL not ending with slash', async () => { + const scope = nock('https://test-api.example.com') + .get('/config/networks') + .reply(200, MOCK_API_RESPONSE); + + const service = new ConfigRegistryApiService({ + apiBaseUrl: 'https://test-api.example.com', + endpointPath: '/config/networks', + }); + + await service.fetchConfig(); + + expect(scope.isDone()).toBe(true); + }); + it('should handle base URL ending with slash', async () => { const scope = nock('https://test-api.example.com') .get('/config/networks') @@ -305,5 +594,20 @@ describe('ConfigRegistryApiService', () => { expect(scope.isDone()).toBe(true); }); + + it('should handle endpoint path with leading slash', async () => { + const scope = nock('https://test-api.example.com') + .get('/config/networks') + .reply(200, MOCK_API_RESPONSE); + + const service = new ConfigRegistryApiService({ + apiBaseUrl: 'https://test-api.example.com', + endpointPath: '/config/networks', + }); + + await service.fetchConfig(); + + expect(scope.isDone()).toBe(true); + }); }); }); diff --git a/packages/config-registry-controller/src/config-registry-api-service/transformers.test.ts b/packages/config-registry-controller/src/config-registry-api-service/transformers.test.ts index cadd9d89e11..41fca6763d0 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/transformers.test.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/transformers.test.ts @@ -420,39 +420,71 @@ describe('transformers', () => { expect(result?.defaultRpcEndpointIndex).toBe(1); }); + it('should default defaultRpcEndpointIndex to 0 when not provided', () => { + const config = { + ...VALID_NETWORK_CONFIG, + rpcEndpoints: [ + { + url: 'https://mainnet.infura.io/v3/{infuraProjectId}', + type: 'infura', + networkClientId: 'mainnet', + failoverUrls: [], + }, + ], + } as NetworkConfig; + + const result = transformNetworkConfig(config); + + expect(result?.defaultRpcEndpointIndex).toBe(0); + }); + + it('should default defaultRpcEndpointIndex to 0 when undefined at runtime', () => { + const config = { + ...VALID_NETWORK_CONFIG, + rpcEndpoints: [ + { + url: 'https://mainnet.infura.io/v3/{infuraProjectId}', + type: 'infura', + networkClientId: 'mainnet', + failoverUrls: [], + }, + ], + defaultRpcEndpointIndex: undefined, + } as unknown as NetworkConfig; + + const result = transformNetworkConfig(config); + + expect(result?.defaultRpcEndpointIndex).toBe(0); + }); + it('should adjust defaultRpcEndpointIndex when invalid endpoints are filtered out', () => { const config = { ...VALID_NETWORK_CONFIG, rpcEndpoints: [ { - // Invalid endpoint (missing networkClientId) - will be filtered out url: 'https://invalid.infura.io/v3/{infuraProjectId}', type: 'infura', networkClientId: '', failoverUrls: [], }, { - // Valid endpoint at original index 1 url: 'https://mainnet.infura.io/v3/{infuraProjectId}', type: 'infura', networkClientId: 'mainnet', failoverUrls: [], }, { - // Valid endpoint at original index 2 url: 'https://backup.infura.io/v3/{infuraProjectId}', type: 'infura', networkClientId: 'mainnet', failoverUrls: [], }, ], - defaultRpcEndpointIndex: 1, // Points to mainnet endpoint + defaultRpcEndpointIndex: 1, }; const result = transformNetworkConfig(config); - // After filtering, the array becomes [mainnet, backup] - // Original index 1 (mainnet) should now be at index 0 expect(result?.defaultRpcEndpointIndex).toBe(0); expect(result?.rpcEndpoints[result.defaultRpcEndpointIndex].url).toBe( 'https://mainnet.infura.io/v3/{infuraProjectId}', @@ -470,14 +502,13 @@ describe('transformers', () => { failoverUrls: [], }, { - // Invalid endpoint (missing networkClientId) - will be filtered out url: 'https://invalid.infura.io/v3/{infuraProjectId}', type: 'infura', networkClientId: '', failoverUrls: [], }, ], - defaultRpcEndpointIndex: 1, // Points to invalid endpoint + defaultRpcEndpointIndex: 1, }; const result = transformNetworkConfig(config); @@ -489,17 +520,15 @@ describe('transformers', () => { const config = { ...VALID_NETWORK_CONFIG, blockExplorerUrls: [ - '', // Invalid empty URL - will be filtered out - 'https://etherscan.io', // Valid URL at original index 1 - 'https://blockscout.com', // Valid URL at original index 2 + '', + 'https://etherscan.io', + 'https://blockscout.com', ], - defaultBlockExplorerUrlIndex: 1, // Points to etherscan + defaultBlockExplorerUrlIndex: 1, }; const result = transformNetworkConfig(config); - // After filtering, the array becomes [etherscan, blockscout] - // Original index 1 (etherscan) should now be at index 0 expect(result?.defaultBlockExplorerUrlIndex).toBe(0); expect( result?.blockExplorerUrls[result.defaultBlockExplorerUrlIndex ?? 0], @@ -509,11 +538,8 @@ describe('transformers', () => { it('should return null when defaultBlockExplorerUrlIndex points to invalid URL', () => { const config = { ...VALID_NETWORK_CONFIG, - blockExplorerUrls: [ - 'https://etherscan.io', - '', // Invalid empty URL - will be filtered out - ], - defaultBlockExplorerUrlIndex: 1, // Points to invalid URL + blockExplorerUrls: ['https://etherscan.io', ''], + defaultBlockExplorerUrlIndex: 1, }; const result = transformNetworkConfig(config); From 339d97548259f350733a6b51f1c0272dac2b0ce6 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Thu, 22 Jan 2026 11:42:19 +0100 Subject: [PATCH 19/55] fix: add missing CODEOWNER --- .github/CODEOWNERS | 1 + packages/config-registry-controller/package.json | 4 ++-- teams.json | 3 ++- yarn.lock | 8 ++++---- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 6910a0f8952..f64b04da0a7 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -72,6 +72,7 @@ /packages/build-utils @MetaMask/core-platform /packages/composable-controller @MetaMask/core-platform /packages/connectivity-controller @MetaMask/core-platform +/packages/config-registry-controller @MetaMask/core-platform /packages/controller-utils @MetaMask/core-platform /packages/error-reporting-service @MetaMask/core-platform /packages/eth-json-rpc-middleware @MetaMask/core-platform diff --git a/packages/config-registry-controller/package.json b/packages/config-registry-controller/package.json index 75f441ae159..f46967201d1 100644 --- a/packages/config-registry-controller/package.json +++ b/packages/config-registry-controller/package.json @@ -49,10 +49,10 @@ }, "dependencies": { "@metamask/base-controller": "^9.0.0", - "@metamask/controller-utils": "^11.16.0", + "@metamask/controller-utils": "^11.18.0", "@metamask/messenger": "^0.3.0", "@metamask/network-controller": "^29.0.0", - "@metamask/polling-controller": "^16.0.0", + "@metamask/polling-controller": "^16.0.2", "@metamask/remote-feature-flag-controller": "^4.0.0" }, "devDependencies": { diff --git a/teams.json b/teams.json index c3010cd8223..ee30fd15717 100644 --- a/teams.json +++ b/teams.json @@ -66,5 +66,6 @@ "metamask/permission-log-controller": "team-wallet-integrations,team-core-platform", "metamask/analytics-controller": "team-extension-platform,team-mobile-platform", "metamask/remote-feature-flag-controller": "team-extension-platform,team-mobile-platform", - "metamask/storage-service": "team-extension-platform,team-mobile-platform" + "metamask/storage-service": "team-extension-platform,team-mobile-platform", + "metamask/config-registry-controller": "team-core-platform" } diff --git a/yarn.lock b/yarn.lock index b1c61d37185..b0bd58910a4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2979,10 +2979,10 @@ __metadata: "@lavamoat/allow-scripts": "npm:^3.0.4" "@metamask/auto-changelog": "npm:^3.4.4" "@metamask/base-controller": "npm:^9.0.0" - "@metamask/controller-utils": "npm:^11.16.0" + "@metamask/controller-utils": "npm:^11.18.0" "@metamask/messenger": "npm:^0.3.0" "@metamask/network-controller": "npm:^29.0.0" - "@metamask/polling-controller": "npm:^16.0.0" + "@metamask/polling-controller": "npm:^16.0.2" "@metamask/remote-feature-flag-controller": "npm:^4.0.0" "@ts-bridge/cli": "npm:^0.6.4" "@types/jest": "npm:^27.4.1" @@ -3022,7 +3022,7 @@ __metadata: languageName: node linkType: hard -"@metamask/controller-utils@npm:^11.15.0, @metamask/controller-utils@npm:^11.16.0, @metamask/controller-utils@npm:^11.18.0, @metamask/controller-utils@workspace:packages/controller-utils": +"@metamask/controller-utils@npm:^11.15.0, @metamask/controller-utils@npm:^11.18.0, @metamask/controller-utils@workspace:packages/controller-utils": version: 0.0.0-use.local resolution: "@metamask/controller-utils@workspace:packages/controller-utils" dependencies: @@ -4491,7 +4491,7 @@ __metadata: languageName: unknown linkType: soft -"@metamask/polling-controller@npm:^16.0.0, @metamask/polling-controller@npm:^16.0.2, @metamask/polling-controller@workspace:packages/polling-controller": +"@metamask/polling-controller@npm:^16.0.2, @metamask/polling-controller@workspace:packages/polling-controller": version: 0.0.0-use.local resolution: "@metamask/polling-controller@workspace:packages/polling-controller" dependencies: From 01aabb359a464c2f7b079072dc5c3bb4b456b27d Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Fri, 23 Jan 2026 09:58:52 +0100 Subject: [PATCH 20/55] fix: fix feedbacks --- .../config-registry-controller/package.json | 3 +- .../src/ConfigRegistryController.test.ts | 680 +++++++----------- .../src/ConfigRegistryController.ts | 189 ++--- .../config-registry-controller/src/index.ts | 3 - .../tsconfig.build.json | 1 + .../config-registry-controller/tsconfig.json | 1 + yarn.lock | 1 + 7 files changed, 321 insertions(+), 557 deletions(-) diff --git a/packages/config-registry-controller/package.json b/packages/config-registry-controller/package.json index f46967201d1..80482e717dd 100644 --- a/packages/config-registry-controller/package.json +++ b/packages/config-registry-controller/package.json @@ -53,7 +53,8 @@ "@metamask/messenger": "^0.3.0", "@metamask/network-controller": "^29.0.0", "@metamask/polling-controller": "^16.0.2", - "@metamask/remote-feature-flag-controller": "^4.0.0" + "@metamask/remote-feature-flag-controller": "^4.0.0", + "@metamask/utils": "^11.9.0" }, "devDependencies": { "@lavamoat/allow-scripts": "^3.0.4", diff --git a/packages/config-registry-controller/src/ConfigRegistryController.test.ts b/packages/config-registry-controller/src/ConfigRegistryController.test.ts index 677db5becad..c452f4409b3 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.test.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.test.ts @@ -5,6 +5,7 @@ import { useFakeTimers } from 'sinon'; import type { AbstractConfigRegistryApiService, FetchConfigResult, + NetworkConfig, } from './config-registry-api-service'; import { ConfigRegistryController, @@ -13,7 +14,7 @@ import { import type { ConfigRegistryMessenger, ConfigRegistryState, - RegistryConfigEntry, + NetworkConfigEntry, } from './ConfigRegistryController'; import { advanceTime } from '../../../tests/helpers'; @@ -21,8 +22,17 @@ const namespace = 'ConfigRegistryController' as const; type RootMessenger = Messenger< MockAnyNamespace, - { type: 'RemoteFeatureFlagController:getState'; handler: () => unknown }, - never + | { type: 'RemoteFeatureFlagController:getState'; handler: () => unknown } + | { + type: 'KeyringController:getState'; + handler: () => { isUnlocked: boolean }; + } + | { + type: 'ConfigRegistryApiService:fetchConfig'; + handler: (options?: { etag?: string }) => Promise; + }, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] } >; /** @@ -36,8 +46,17 @@ function getConfigRegistryControllerMessenger(): { } { const rootMessenger = new Messenger< MockAnyNamespace, - { type: 'RemoteFeatureFlagController:getState'; handler: () => unknown }, - never + | { type: 'RemoteFeatureFlagController:getState'; handler: () => unknown } + | { + type: 'KeyringController:getState'; + handler: () => { isUnlocked: boolean }; + } + | { + type: 'ConfigRegistryApiService:fetchConfig'; + handler: (options?: { etag?: string }) => Promise; + }, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] } >({ namespace: MOCK_ANY_NAMESPACE, }); @@ -45,7 +64,8 @@ function getConfigRegistryControllerMessenger(): { const configRegistryControllerMessenger = new Messenger< typeof namespace, never, - never, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] }, typeof rootMessenger >({ namespace, @@ -54,35 +74,78 @@ function getConfigRegistryControllerMessenger(): { rootMessenger.delegate({ messenger: configRegistryControllerMessenger, - actions: ['RemoteFeatureFlagController:getState'] as never[], + actions: [ + 'RemoteFeatureFlagController:getState', + 'KeyringController:getState', + 'ConfigRegistryApiService:fetchConfig', + ] as never[], + events: ['KeyringController:unlock', 'KeyringController:lock'] as never[], }); return { messenger: configRegistryControllerMessenger, rootMessenger }; } -const MOCK_CONFIG_ENTRY: RegistryConfigEntry = { +/** + * Creates a mock NetworkConfig for testing. + * + * @param overrides - Optional properties to override in the default NetworkConfig. + * @returns A mock NetworkConfig object. + */ +function createMockNetworkConfig( + overrides: Partial = {}, +): NetworkConfig { + return { + chainId: '0x1', + name: 'Ethereum Mainnet', + nativeCurrency: 'ETH', + rpcEndpoints: [ + { + url: 'https://mainnet.infura.io/v3/{infuraProjectId}', + type: 'infura', + networkClientId: 'mainnet', + failoverUrls: [], + }, + ], + blockExplorerUrls: ['https://etherscan.io'], + defaultRpcEndpointIndex: 0, + defaultBlockExplorerUrlIndex: 0, + isActive: true, + isTestnet: false, + isDefault: true, + isFeatured: true, + isDeprecated: false, + priority: 0, + isDeletable: false, + ...overrides, + }; +} + +const MOCK_CONFIG_ENTRY: NetworkConfigEntry = { key: 'test-key', - value: { test: 'value' }, + value: createMockNetworkConfig({ chainId: '0x1', name: 'Test Network' }), metadata: { source: 'test' }, }; -const MOCK_FALLBACK_CONFIG: Record = { +const MOCK_FALLBACK_CONFIG: Record = { 'fallback-key': { key: 'fallback-key', - value: { fallback: true }, + value: createMockNetworkConfig({ + chainId: '0x2', + name: 'Fallback Network', + }), }, }; /** - * Builds a mock API service. + * Builds a mock API service fetch handler. * * @param overrides - The properties of the API service you want to provide explicitly. - * @returns The built mock API service. + * @returns A handler function for the fetchConfig action. */ -function buildMockApiService( +function buildMockApiServiceHandler( overrides: Partial = {}, -): AbstractConfigRegistryApiService { - return { +): (options?: { etag?: string }) => Promise { + const defaultService: AbstractConfigRegistryApiService = { async fetchConfig(): Promise { return { data: { @@ -97,23 +160,31 @@ function buildMockApiService( }, onBreak: jest.fn(), onDegraded: jest.fn(), - ...overrides, }; + + const service = { ...defaultService, ...overrides }; + return (options?: { etag?: string }) => service.fetchConfig(options); } describe('ConfigRegistryController', () => { let clock: sinon.SinonFakeTimers; let messenger: ConfigRegistryMessenger; let rootMessenger: RootMessenger; - let apiService: AbstractConfigRegistryApiService; + let mockApiServiceHandler: jest.Mock; let mockRemoteFeatureFlagGetState: jest.Mock; + let mockKeyringControllerGetState: jest.Mock; beforeEach(() => { clock = useFakeTimers(); const messengers = getConfigRegistryControllerMessenger(); messenger = messengers.messenger; rootMessenger = messengers.rootMessenger; - apiService = buildMockApiService(); + mockApiServiceHandler = jest.fn(buildMockApiServiceHandler()); + + rootMessenger.registerActionHandler( + 'ConfigRegistryApiService:fetchConfig', + mockApiServiceHandler, + ); mockRemoteFeatureFlagGetState = jest.fn().mockReturnValue({ remoteFeatureFlags: { @@ -126,17 +197,26 @@ describe('ConfigRegistryController', () => { 'RemoteFeatureFlagController:getState', mockRemoteFeatureFlagGetState, ); + + mockKeyringControllerGetState = jest.fn().mockReturnValue({ + isUnlocked: false, + }); + + rootMessenger.registerActionHandler( + 'KeyringController:getState', + mockKeyringControllerGetState, + ); }); afterEach(() => { clock.restore(); + mockApiServiceHandler.mockReset(); }); describe('constructor', () => { it('should set default state', () => { const controller = new ConfigRegistryController({ messenger, - apiService, }); expect(controller.state).toStrictEqual({ @@ -162,7 +242,6 @@ describe('ConfigRegistryController', () => { const controller = new ConfigRegistryController({ messenger, state: initialState, - apiService, }); expect(controller.state.configs.networks).toStrictEqual( @@ -175,7 +254,6 @@ describe('ConfigRegistryController', () => { it('should set custom polling interval', () => { const customInterval = 5000; const controller = new ConfigRegistryController({ - apiService, messenger, pollingInterval: customInterval, }); @@ -185,7 +263,6 @@ describe('ConfigRegistryController', () => { it('should set fallback config', () => { const controller = new ConfigRegistryController({ - apiService, messenger, fallbackConfig: MOCK_FALLBACK_CONFIG, }); @@ -193,7 +270,7 @@ describe('ConfigRegistryController', () => { expect(controller.state.configs).toStrictEqual({ networks: {} }); }); - it('should use default ConfigRegistryApiService when apiService is not provided', () => { + it('should work when API service is registered on messenger', () => { const controller = new ConfigRegistryController({ messenger, }); @@ -208,354 +285,14 @@ describe('ConfigRegistryController', () => { }); }); - describe('getConfig', () => { - it('should return undefined for non-existent key', () => { - const controller = new ConfigRegistryController({ - apiService, - messenger, - }); - - expect(controller.getConfig('non-existent')).toBeUndefined(); - }); - - it('should return config entry for existing key', () => { - const controller = new ConfigRegistryController({ - apiService, - messenger, - state: { - configs: { - networks: { - 'test-key': MOCK_CONFIG_ENTRY, - }, - }, - }, - }); - - expect(controller.getConfig('test-key')).toStrictEqual(MOCK_CONFIG_ENTRY); - }); - - it('should work via messenger action', () => { - const testController = new ConfigRegistryController({ - apiService, - messenger, - state: { - configs: { - networks: { - 'test-key': MOCK_CONFIG_ENTRY, - }, - }, - }, - }); - - const result = messenger.call( - 'ConfigRegistryController:getConfig', - 'test-key', - ); - expect(result).toStrictEqual(MOCK_CONFIG_ENTRY); - expect(testController.getConfig('test-key')).toStrictEqual( - MOCK_CONFIG_ENTRY, - ); - }); - }); - - describe('getAllConfigs', () => { - it('should return empty object when no configs', () => { - const controller = new ConfigRegistryController({ - apiService, - messenger, - }); - - expect(controller.getAllConfigs()).toStrictEqual({}); - }); - - it('should return all configs', () => { - const configs = { - key1: { key: 'key1', value: 'value1' }, - key2: { key: 'key2', value: 'value2' }, - }; - - const controller = new ConfigRegistryController({ - apiService, - messenger, - state: { configs: { networks: configs } }, - }); - - expect(controller.getAllConfigs()).toStrictEqual(configs); - }); - - it('should return a copy, not a reference', () => { - const configs = { - key1: { key: 'key1', value: 'value1' }, - }; - - const controller = new ConfigRegistryController({ - apiService, - messenger, - state: { configs: { networks: configs } }, - }); - - const result = controller.getAllConfigs(); - result.key1 = { key: 'key1', value: 'modified' }; - - expect(controller.state.configs.networks?.key1?.value).toBe('value1'); - }); - - it('should work via messenger action', () => { - const configs = { - key1: { key: 'key1', value: 'value1' }, - }; - - const testController = new ConfigRegistryController({ - messenger, - apiService, - state: { configs: { networks: configs } }, - }); - - const result = messenger.call('ConfigRegistryController:getAllConfigs'); - expect(result).toStrictEqual(configs); - expect(testController.getAllConfigs()).toStrictEqual(configs); - }); - - it('should return empty object when state.configs is undefined', () => { - const controller = new ConfigRegistryController({ - apiService, - messenger, - state: { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - configs: undefined as any, - }, - }); - - expect(controller.getAllConfigs()).toStrictEqual({}); - }); - - it('should return empty object when state.configs.networks is undefined', () => { - const controller = new ConfigRegistryController({ - apiService, - messenger, - state: { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - configs: {} as any, - }, - }); - - expect(controller.getAllConfigs()).toStrictEqual({}); - }); - }); - - describe('getConfigValue', () => { - it('should return undefined for non-existent key', () => { - const controller = new ConfigRegistryController({ - apiService, - messenger, - }); - - expect(controller.getConfigValue('non-existent')).toBeUndefined(); - }); - - it('should return value for existing key', () => { - const controller = new ConfigRegistryController({ - apiService, - messenger, - state: { - configs: { - networks: { - 'test-key': MOCK_CONFIG_ENTRY, - }, - }, - }, - }); - - expect(controller.getConfigValue('test-key')).toStrictEqual({ - test: 'value', - }); - }); - - it('should return typed value', () => { - const controller = new ConfigRegistryController({ - apiService, - messenger, - state: { - configs: { - networks: { - 'string-key': { key: 'string-key', value: 'string-value' }, - 'number-key': { key: 'number-key', value: 42 }, - }, - }, - }, - }); - - expect(controller.getConfigValue('string-key')).toBe( - 'string-value', - ); - expect(controller.getConfigValue('number-key')).toBe(42); - }); - }); - - describe('setConfig', () => { - it('should set a new config entry', () => { - const controller = new ConfigRegistryController({ - messenger, - apiService, - }); - - controller.setConfig('new-key', { data: 'value' }); - - expect(controller.state.configs.networks?.['new-key']).toStrictEqual({ - key: 'new-key', - value: { data: 'value' }, - metadata: undefined, - }); - }); - - it('should set config with metadata', () => { - const controller = new ConfigRegistryController({ - apiService, - messenger, - }); - - controller.setConfig('new-key', { data: 'value' }, { source: 'test' }); - - expect(controller.state.configs.networks?.['new-key']).toStrictEqual({ - key: 'new-key', - value: { data: 'value' }, - metadata: { source: 'test' }, - }); - }); - - it('should update existing config', () => { - const controller = new ConfigRegistryController({ - messenger, - apiService, - state: { - configs: { - networks: { - 'existing-key': { key: 'existing-key', value: 'old-value' }, - }, - }, - }, - }); - - controller.setConfig('existing-key', 'new-value'); - - expect(controller.state.configs.networks?.['existing-key']?.value).toBe( - 'new-value', - ); - }); - - it('should work via messenger action', () => { - const controller = new ConfigRegistryController({ - messenger, - apiService, - }); - - messenger.call( - 'ConfigRegistryController:setConfig', - 'test-key', - 'test-value', - ); - - expect(controller.getConfig('test-key')?.value).toBe('test-value'); - }); - - it('should initialize configs when state.configs is undefined', () => { - const controller = new ConfigRegistryController({ - messenger, - apiService, - state: { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - configs: undefined as any, - }, - }); - - controller.setConfig('new-key', 'value'); - - expect(controller.state.configs?.networks?.['new-key']).toBeDefined(); - expect(controller.state.configs?.networks?.['new-key']?.value).toBe( - 'value', - ); - }); - - it('should initialize networks when state.configs.networks is undefined', () => { - const controller = new ConfigRegistryController({ - messenger, - apiService, - state: { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - configs: {} as any, - }, - }); - - controller.setConfig('new-key', 'value'); - - expect(controller.state.configs?.networks?.['new-key']).toBeDefined(); - expect(controller.state.configs?.networks?.['new-key']?.value).toBe( - 'value', - ); - }); - }); - - describe('removeConfig', () => { - it('should remove existing config', () => { - const controller = new ConfigRegistryController({ - apiService, - messenger, - state: { - configs: { - networks: { - key1: { key: 'key1', value: 'value1' }, - key2: { key: 'key2', value: 'value2' }, - }, - }, - }, - }); - - controller.removeConfig('key1'); - - expect(controller.state.configs.networks?.key1).toBeUndefined(); - expect(controller.state.configs.networks?.key2).toBeDefined(); - }); - - it('should not throw when removing non-existent key', () => { - const controller = new ConfigRegistryController({ - messenger, - apiService, - }); - - expect(() => controller.removeConfig('non-existent')).not.toThrow(); - }); - }); - - describe('clearConfigs', () => { - it('should clear all configs', () => { - const controller = new ConfigRegistryController({ - messenger, - apiService, - state: { - configs: { - networks: { - key1: { key: 'key1', value: 'value1' }, - key2: { key: 'key2', value: 'value2' }, - }, - }, - }, - }); - - controller.clearConfigs(); - - expect(controller.state.configs).toStrictEqual({ networks: {} }); - }); - }); - describe('polling', () => { it('should start polling', async () => { const controller = new ConfigRegistryController({ - apiService, messenger, }); const executePollSpy = jest.spyOn(controller, '_executePoll'); - controller.startPolling({}); + controller.startPolling(null); await advanceTime({ clock, duration: 0 }); @@ -566,13 +303,12 @@ describe('ConfigRegistryController', () => { it('should poll at specified interval', async () => { const pollingInterval = 1000; const controller = new ConfigRegistryController({ - apiService, messenger, pollingInterval, }); const executePollSpy = jest.spyOn(controller, '_executePoll'); - controller.startPolling({}); + controller.startPolling(null); await advanceTime({ clock, duration: 0 }); executePollSpy.mockClear(); @@ -585,12 +321,11 @@ describe('ConfigRegistryController', () => { it('should stop polling', async () => { const controller = new ConfigRegistryController({ - apiService, messenger, }); const executePollSpy = jest.spyOn(controller, '_executePoll'); - controller.startPolling({}); + controller.startPolling(null); await advanceTime({ clock, duration: 0 }); executePollSpy.mockClear(); @@ -610,17 +345,16 @@ describe('ConfigRegistryController', () => { cacheTimestamp: Date.now(), }); - const errorApiService = buildMockApiService({ - fetchConfig: jest.fn().mockRejectedValue(new Error('Network error')), - }); + mockApiServiceHandler.mockRejectedValue(new Error('Network error')); const controller = new ConfigRegistryController({ - apiService: errorApiService, messenger, fallbackConfig: MOCK_FALLBACK_CONFIG, }); - await controller._executePoll({}); + await expect(controller._executePoll(null)).rejects.toThrow( + 'Network error', + ); expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG, @@ -638,22 +372,27 @@ describe('ConfigRegistryController', () => { const existingConfigs = { networks: { - 'existing-key': { key: 'existing-key', value: 'existing-value' }, + 'existing-key': { + key: 'existing-key', + value: createMockNetworkConfig({ + chainId: '0x3', + name: 'Existing Network', + }), + }, }, }; - const errorApiService = buildMockApiService({ - fetchConfig: jest.fn().mockRejectedValue(new Error('Network error')), - }); + mockApiServiceHandler.mockRejectedValue(new Error('Network error')); const controller = new ConfigRegistryController({ - apiService: errorApiService, messenger, state: { configs: existingConfigs }, fallbackConfig: MOCK_FALLBACK_CONFIG, }); - await controller._executePoll({}); + await expect(controller._executePoll(null)).rejects.toThrow( + 'Network error', + ); expect(controller.state.configs).toStrictEqual(existingConfigs); expect(controller.state.fetchError).toBe('Network error'); @@ -667,17 +406,16 @@ describe('ConfigRegistryController', () => { cacheTimestamp: Date.now(), }); - const errorApiService = buildMockApiService({ - fetchConfig: jest.fn().mockRejectedValue(new Error('Network error')), - }); + mockApiServiceHandler.mockRejectedValue(new Error('Network error')); const controller = new ConfigRegistryController({ - apiService: errorApiService, messenger, fallbackConfig: MOCK_FALLBACK_CONFIG, }); - await controller._executePoll({}); + await expect(controller._executePoll(null)).rejects.toThrow( + 'Network error', + ); expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG, @@ -694,22 +432,19 @@ describe('ConfigRegistryController', () => { cacheTimestamp: Date.now(), }); - const notModifiedApiService = buildMockApiService({ - fetchConfig: jest.fn().mockResolvedValue({ - notModified: true, - etag: '"test-etag"', - }), + mockApiServiceHandler.mockResolvedValue({ + notModified: true, + etag: '"test-etag"', }); const controller = new ConfigRegistryController({ - apiService: notModifiedApiService, messenger, state: { fetchError: 'Previous error', }, }); - await controller._executePoll({}); + await controller._executePoll(null); expect(controller.state.fetchError).toBeNull(); expect(controller.state.etag).toBeNull(); @@ -723,17 +458,14 @@ describe('ConfigRegistryController', () => { cacheTimestamp: Date.now(), }); - const errorApiService = buildMockApiService({ - fetchConfig: jest.fn().mockRejectedValue('String error'), // Not an Error instance - }); + mockApiServiceHandler.mockRejectedValue('String error'); // Not an Error instance const controller = new ConfigRegistryController({ - apiService: errorApiService, messenger, fallbackConfig: MOCK_FALLBACK_CONFIG, }); - await controller._executePoll({}); + await expect(controller._executePoll(null)).rejects.toBe('String error'); expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG, @@ -749,19 +481,18 @@ describe('ConfigRegistryController', () => { cacheTimestamp: Date.now(), }); - const errorApiService = buildMockApiService({ - fetchConfig: jest.fn().mockRejectedValue(new Error('Network error')), - }); + mockApiServiceHandler.mockRejectedValue(new Error('Network error')); const controller = new ConfigRegistryController({ - apiService: errorApiService, messenger, fallbackConfig: MOCK_FALLBACK_CONFIG, // eslint-disable-next-line @typescript-eslint/no-explicit-any state: { configs: null as any }, }); - await controller._executePoll({}); + await expect(controller._executePoll(null)).rejects.toThrow( + 'Network error', + ); expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG, @@ -771,13 +502,15 @@ describe('ConfigRegistryController', () => { it('should work via messenger actions', async () => { const controller = new ConfigRegistryController({ - apiService, messenger, }); const executePollSpy = jest.spyOn(controller, '_executePoll'); - const token = messenger.call('ConfigRegistryController:startPolling', {}); + const token = messenger.call( + 'ConfigRegistryController:startPolling', + null, + ); expect(typeof token).toBe('string'); await advanceTime({ clock, duration: 0 }); @@ -790,21 +523,9 @@ describe('ConfigRegistryController', () => { }); describe('state persistence', () => { - it('should persist configs', () => { - const controller = new ConfigRegistryController({ - messenger, - apiService, - }); - - controller.setConfig('persist-key', 'persist-value'); - - expect(controller.state.configs.networks?.['persist-key']).toBeDefined(); - }); - it('should persist version', () => { const controller = new ConfigRegistryController({ messenger, - apiService, state: { version: 'v1.0.0' }, }); @@ -815,7 +536,6 @@ describe('ConfigRegistryController', () => { const timestamp = Date.now(); const controller = new ConfigRegistryController({ messenger, - apiService, state: { lastFetched: timestamp }, }); @@ -825,7 +545,6 @@ describe('ConfigRegistryController', () => { it('should persist fetchError', () => { const controller = new ConfigRegistryController({ messenger, - apiService, state: { fetchError: 'Test error' }, }); @@ -835,7 +554,6 @@ describe('ConfigRegistryController', () => { it('should use default error message when useFallbackConfig is called without errorMessage', () => { const controller = new ConfigRegistryController({ messenger, - apiService, fallbackConfig: MOCK_FALLBACK_CONFIG, }); @@ -856,10 +574,9 @@ describe('ConfigRegistryController', () => { it('should return a polling token string', () => { const controller = new ConfigRegistryController({ messenger, - apiService, }); - const token = controller.startPolling({}); + const token = controller.startPolling(null); expect(typeof token).toBe('string'); expect(token.length).toBeGreaterThan(0); @@ -869,10 +586,9 @@ describe('ConfigRegistryController', () => { it('should return a polling token string when called without input', () => { const controller = new ConfigRegistryController({ messenger, - apiService, }); - const token = controller.startPolling(); + const token = controller.startPolling(null); expect(typeof token).toBe('string'); expect(token.length).toBeGreaterThan(0); @@ -891,12 +607,11 @@ describe('ConfigRegistryController', () => { const controller = new ConfigRegistryController({ messenger, - apiService, fallbackConfig: MOCK_FALLBACK_CONFIG, }); const executePollSpy = jest.spyOn(controller, '_executePoll'); - controller.startPolling({}); + controller.startPolling(null); await advanceTime({ clock, duration: 0 }); @@ -957,16 +672,13 @@ describe('ConfigRegistryController', () => { etag: 'test-etag', }); - const mockApiService = buildMockApiService({ - fetchConfig: fetchConfigSpy, - }); + mockApiServiceHandler.mockImplementation(fetchConfigSpy); const controller = new ConfigRegistryController({ messenger, - apiService: mockApiService, }); - const executePollPromise = controller._executePoll({}); + const executePollPromise = controller._executePoll(null); await executePollPromise; expect(fetchConfigSpy).toHaveBeenCalled(); @@ -1092,16 +804,13 @@ describe('ConfigRegistryController', () => { etag: 'test-etag', }); - const mockApiService = buildMockApiService({ - fetchConfig: fetchConfigSpy, - }); + mockApiServiceHandler.mockImplementation(fetchConfigSpy); const controller = new ConfigRegistryController({ messenger, - apiService: mockApiService, }); - await controller._executePoll({}); + await controller._executePoll(null); expect(controller.state.configs.networks?.['0x1']).toBeDefined(); expect(controller.state.configs.networks?.['0x5']).toBeUndefined(); @@ -1120,12 +829,11 @@ describe('ConfigRegistryController', () => { const controller = new ConfigRegistryController({ messenger, - apiService, fallbackConfig: MOCK_FALLBACK_CONFIG, }); const executePollSpy = jest.spyOn(controller, '_executePoll'); - controller.startPolling({}); + controller.startPolling(null); await advanceTime({ clock, duration: 0 }); @@ -1147,12 +855,11 @@ describe('ConfigRegistryController', () => { const controller = new ConfigRegistryController({ messenger, - apiService, fallbackConfig: MOCK_FALLBACK_CONFIG, }); const executePollSpy = jest.spyOn(controller, '_executePoll'); - controller.startPolling({}); + controller.startPolling(null); await advanceTime({ clock, duration: 0 }); @@ -1167,4 +874,99 @@ describe('ConfigRegistryController', () => { controller.stopPolling(); }); }); + + describe('KeyringController event listeners', () => { + it('should start polling when KeyringController is already unlocked on initialization', async () => { + mockKeyringControllerGetState.mockReturnValue({ + isUnlocked: true, + }); + + const controller = new ConfigRegistryController({ + messenger, + }); + + const executePollSpy = jest.spyOn(controller, '_executePoll'); + + await advanceTime({ clock, duration: 0 }); + + expect(mockKeyringControllerGetState).toHaveBeenCalled(); + // Verify polling started by checking if _executePoll was called + expect(executePollSpy).toHaveBeenCalledTimes(1); + + controller.stopPolling(); + }); + + it('should handle KeyringController:getState error gracefully when KeyringController is unavailable', () => { + mockKeyringControllerGetState.mockImplementation(() => { + throw new Error('KeyringController not available'); + }); + + const controller = new ConfigRegistryController({ + messenger, + }); + + // Should not have started polling + expect(controller.state.lastFetched).toBeNull(); + }); + + it('should start polling when KeyringController:unlock event is published', async () => { + const controller = new ConfigRegistryController({ + messenger, + }); + + const executePollSpy = jest.spyOn(controller, '_executePoll'); + const startPollingSpy = jest.spyOn(controller, 'startPolling'); + + // Initially locked, so polling should not have started + expect(startPollingSpy).not.toHaveBeenCalled(); + + // Publish unlock event on root messenger + rootMessenger.publish('KeyringController:unlock'); + + await advanceTime({ clock, duration: 0 }); + + expect(startPollingSpy).toHaveBeenCalledWith(null); + expect(executePollSpy).toHaveBeenCalledTimes(1); + + controller.stopPolling(); + }); + + it('should stop polling when KeyringController:lock event is published', async () => { + mockKeyringControllerGetState.mockReturnValue({ + isUnlocked: true, + }); + + const controller = new ConfigRegistryController({ + messenger, + }); + + const stopPollingSpy = jest.spyOn(controller, 'stopPolling'); + + // Polling should have started + await advanceTime({ clock, duration: 0 }); + expect(stopPollingSpy).not.toHaveBeenCalled(); + + // Publish lock event on root messenger + rootMessenger.publish('KeyringController:lock'); + + expect(stopPollingSpy).toHaveBeenCalled(); + }); + + it('should call startPolling with default parameter when called without arguments', async () => { + const controller = new ConfigRegistryController({ + messenger, + }); + + const executePollSpy = jest.spyOn(controller, '_executePoll'); + + // Call startPolling without arguments to test default parameter + controller.startPolling(); + + // Verify polling started by checking if _executePoll is called + await advanceTime({ clock, duration: 0 }); + expect(executePollSpy).toHaveBeenCalledTimes(1); + + controller.stopPolling(); + }); + }); }); diff --git a/packages/config-registry-controller/src/ConfigRegistryController.ts b/packages/config-registry-controller/src/ConfigRegistryController.ts index 09bdcc8e83e..0196a6b3a7c 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.ts @@ -1,25 +1,29 @@ import type { ControllerGetStateAction, ControllerStateChangeEvent, + StateMetadata, } from '@metamask/base-controller'; +import type { + KeyringControllerLockEvent, + KeyringControllerUnlockEvent, +} from '@metamask/keyring-controller'; import type { Messenger } from '@metamask/messenger'; import { StaticIntervalPollingController } from '@metamask/polling-controller'; import type { RemoteFeatureFlagControllerState } from '@metamask/remote-feature-flag-controller'; +import { Duration, inMilliseconds } from '@metamask/utils'; import type { Json } from '@metamask/utils'; import type { - AbstractConfigRegistryApiService, + FetchConfigOptions, FetchConfigResult, + NetworkConfig, } from './config-registry-api-service'; -import { - ConfigRegistryApiService, - filterNetworks, -} from './config-registry-api-service'; +import { filterNetworks } from './config-registry-api-service'; import { isConfigRegistryApiEnabled } from './utils/feature-flags'; const controllerName = 'ConfigRegistryController'; -export const DEFAULT_POLLING_INTERVAL = 24 * 60 * 60 * 1000; +export const DEFAULT_POLLING_INTERVAL = inMilliseconds(1, Duration.Day); export type RegistryConfigEntry = { key: string; @@ -27,9 +31,15 @@ export type RegistryConfigEntry = { metadata?: Json; }; +export type NetworkConfigEntry = { + key: string; + value: NetworkConfig; + metadata?: Json; +}; + export type ConfigRegistryState = { configs: { - networks?: Record; + networks?: Record; }; version: string | null; lastFetched: number | null; @@ -40,44 +50,37 @@ export type ConfigRegistryState = { const stateMetadata = { configs: { persist: true, - anonymous: false, includeInStateLogs: false, includeInDebugSnapshot: true, usedInUi: true, }, version: { persist: true, - anonymous: false, includeInStateLogs: true, includeInDebugSnapshot: true, usedInUi: false, }, lastFetched: { persist: true, - anonymous: false, includeInStateLogs: true, includeInDebugSnapshot: true, usedInUi: false, }, fetchError: { persist: true, - anonymous: false, includeInStateLogs: true, includeInDebugSnapshot: true, usedInUi: false, }, etag: { persist: true, - anonymous: false, includeInStateLogs: false, includeInDebugSnapshot: false, usedInUi: false, }, -}; +} satisfies StateMetadata; -const DEFAULT_FALLBACK_CONFIG: Record = {}; - -type ConfigRegistryPollingInput = Record; +const DEFAULT_FALLBACK_CONFIG: Record = {}; export type ConfigRegistryControllerStateChangeEvent = ControllerStateChangeEvent; @@ -87,24 +90,9 @@ export type ConfigRegistryControllerGetStateAction = ControllerGetStateAction< ConfigRegistryState >; -export type ConfigRegistryControllerGetConfigAction = { - type: `${typeof controllerName}:getConfig`; - handler: ConfigRegistryController['getConfig']; -}; - -export type ConfigRegistryControllerSetConfigAction = { - type: `${typeof controllerName}:setConfig`; - handler: ConfigRegistryController['setConfig']; -}; - -export type ConfigRegistryControllerGetAllConfigsAction = { - type: `${typeof controllerName}:getAllConfigs`; - handler: ConfigRegistryController['getAllConfigs']; -}; - export type ConfigRegistryControllerStartPollingAction = { type: `${typeof controllerName}:startPolling`; - handler: (input: ConfigRegistryPollingInput) => string; + handler: (input: null) => string; }; export type ConfigRegistryControllerStopPollingAction = { @@ -114,18 +102,25 @@ export type ConfigRegistryControllerStopPollingAction = { export type ConfigRegistryControllerActions = | ConfigRegistryControllerGetStateAction - | ConfigRegistryControllerGetConfigAction - | ConfigRegistryControllerSetConfigAction - | ConfigRegistryControllerGetAllConfigsAction | ConfigRegistryControllerStartPollingAction | ConfigRegistryControllerStopPollingAction | { type: 'RemoteFeatureFlagController:getState'; handler: () => RemoteFeatureFlagControllerState; + } + | { + type: 'KeyringController:getState'; + handler: () => { isUnlocked: boolean }; + } + | { + type: 'ConfigRegistryApiService:fetchConfig'; + handler: (options?: FetchConfigOptions) => Promise; }; export type ConfigRegistryControllerEvents = - ConfigRegistryControllerStateChangeEvent; + | KeyringControllerUnlockEvent + | KeyringControllerLockEvent + | ConfigRegistryControllerStateChangeEvent; export type ConfigRegistryMessenger = Messenger< typeof controllerName, @@ -137,33 +132,29 @@ export type ConfigRegistryControllerOptions = { messenger: ConfigRegistryMessenger; state?: Partial; pollingInterval?: number; - fallbackConfig?: Record; - apiService?: AbstractConfigRegistryApiService; + fallbackConfig?: Record; }; -export class ConfigRegistryController extends StaticIntervalPollingController()< +export class ConfigRegistryController extends StaticIntervalPollingController()< typeof controllerName, ConfigRegistryState, ConfigRegistryMessenger > { - readonly #fallbackConfig: Record; - - readonly #apiService: AbstractConfigRegistryApiService; + readonly #fallbackConfig: Record; /** * @param options - The controller options. - * @param options.messenger - The controller messenger. + * @param options.messenger - The controller messenger. Must have + * `ConfigRegistryApiService:fetchConfig` action handler registered. * @param options.state - Initial state. * @param options.pollingInterval - Polling interval in milliseconds. * @param options.fallbackConfig - Fallback configuration. - * @param options.apiService - The API service. */ constructor({ messenger, state = {}, pollingInterval = DEFAULT_POLLING_INTERVAL, fallbackConfig = DEFAULT_FALLBACK_CONFIG, - apiService = new ConfigRegistryApiService(), }: ConfigRegistryControllerOptions) { super({ name: controllerName, @@ -181,35 +172,20 @@ export class ConfigRegistryController extends StaticIntervalPollingController this.getConfig(key), - ); - - this.messenger.registerActionHandler( - `${controllerName}:setConfig`, - (key: string, value: Json, metadata?: Json) => - this.setConfig(key, value, metadata), - ); - - this.messenger.registerActionHandler( - `${controllerName}:getAllConfigs`, - () => this.getAllConfigs(), - ); this.messenger.registerActionHandler( `${controllerName}:startPolling`, - (input: ConfigRegistryPollingInput) => this.startPolling(input), + (input: null) => this.startPolling(input), ); this.messenger.registerActionHandler(`${controllerName}:stopPolling`, () => this.stopPolling(), ); + + this.#registerKeyringEventListeners(); } - async _executePoll(_input: ConfigRegistryPollingInput): Promise { + async _executePoll(_input: null): Promise { const isApiEnabled = isConfigRegistryApiEnabled(this.messenger); if (!isApiEnabled) { @@ -220,9 +196,12 @@ export class ConfigRegistryController extends StaticIntervalPollingController { @@ -238,17 +217,18 @@ export class ConfigRegistryController extends StaticIntervalPollingController = {}; + const newConfigs: Record = {}; for (const network of filteredNetworks) { newConfigs[network.chainId] = { key: network.chainId, - value: network as unknown as Json, + value: network, }; } this.update((state) => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (state.configs as any) = { networks: newConfigs }; + (state.configs as ConfigRegistryState['configs']) = { + networks: newConfigs, + }; state.version = result.data.data.version; state.lastFetched = Date.now(); state.fetchError = null; @@ -256,13 +236,15 @@ export class ConfigRegistryController extends StaticIntervalPollingController { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (state.configs as any) = { networks: { ...this.#fallbackConfig } }; + (state.configs as ConfigRegistryState['configs']) = { + networks: { ...this.#fallbackConfig }, + }; state.fetchError = errorMessage ?? 'Using fallback configuration - API unavailable'; state.etag = null; @@ -285,54 +267,33 @@ export class ConfigRegistryController extends StaticIntervalPollingController { - return { ...(this.state.configs?.networks ?? {}) }; - } - - getConfigValue(key: string): TValue | undefined { - const entry = this.state.configs?.networks?.[key]; - return entry?.value as TValue | undefined; - } - - setConfig(key: string, value: Json, metadata?: Json): void { - this.update((state) => { - if (!state.configs) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (state.configs as any) = { networks: {} }; - } - if (!state.configs.networks) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (state.configs.networks as any) = {}; + /** + * Registers event listeners for KeyringController unlock/lock events. + * Automatically starts polling when unlocked and stops when locked. + */ + #registerKeyringEventListeners(): void { + // Check initial unlock state and start polling if already unlocked + try { + const { isUnlocked } = this.messenger.call('KeyringController:getState'); + if (isUnlocked) { + this.startPolling(null); } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (state.configs.networks as any)[key] = { - key, - value, - metadata, - }; - }); - } + } catch { + // KeyringController may not be available, silently handle + } - removeConfig(key: string): void { - this.update((state) => { - if (state.configs?.networks) { - delete state.configs.networks[key]; - } + // Subscribe to unlock event - start polling + this.messenger.subscribe('KeyringController:unlock', () => { + this.startPolling(null); }); - } - clearConfigs(): void { - this.update((state) => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (state.configs as any) = { networks: {} }; + // Subscribe to lock event - stop polling + this.messenger.subscribe('KeyringController:lock', () => { + this.stopPolling(); }); } - startPolling(input: ConfigRegistryPollingInput = {}): string { + startPolling(input: null = null): string { return super.startPolling(input); } diff --git a/packages/config-registry-controller/src/index.ts b/packages/config-registry-controller/src/index.ts index 49a392b0938..3ff45670d84 100644 --- a/packages/config-registry-controller/src/index.ts +++ b/packages/config-registry-controller/src/index.ts @@ -3,9 +3,6 @@ export type { ConfigRegistryState, ConfigRegistryControllerOptions, ConfigRegistryControllerActions, - ConfigRegistryControllerGetConfigAction, - ConfigRegistryControllerSetConfigAction, - ConfigRegistryControllerGetAllConfigsAction, ConfigRegistryControllerGetStateAction, ConfigRegistryControllerStartPollingAction, ConfigRegistryControllerStopPollingAction, diff --git a/packages/config-registry-controller/tsconfig.build.json b/packages/config-registry-controller/tsconfig.build.json index 97065187fac..82ca2753631 100644 --- a/packages/config-registry-controller/tsconfig.build.json +++ b/packages/config-registry-controller/tsconfig.build.json @@ -8,6 +8,7 @@ "references": [ { "path": "../base-controller/tsconfig.build.json" }, { "path": "../controller-utils/tsconfig.build.json" }, + { "path": "../keyring-controller/tsconfig.build.json" }, { "path": "../messenger/tsconfig.build.json" }, { "path": "../network-controller/tsconfig.build.json" }, { "path": "../polling-controller/tsconfig.build.json" }, diff --git a/packages/config-registry-controller/tsconfig.json b/packages/config-registry-controller/tsconfig.json index 77180fee9e8..3110ea21c05 100644 --- a/packages/config-registry-controller/tsconfig.json +++ b/packages/config-registry-controller/tsconfig.json @@ -6,6 +6,7 @@ "references": [ { "path": "../base-controller" }, { "path": "../controller-utils" }, + { "path": "../keyring-controller" }, { "path": "../messenger" }, { "path": "../network-controller" }, { "path": "../polling-controller" }, diff --git a/yarn.lock b/yarn.lock index b0bd58910a4..c9ef2240e03 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2984,6 +2984,7 @@ __metadata: "@metamask/network-controller": "npm:^29.0.0" "@metamask/polling-controller": "npm:^16.0.2" "@metamask/remote-feature-flag-controller": "npm:^4.0.0" + "@metamask/utils": "npm:^11.9.0" "@ts-bridge/cli": "npm:^0.6.4" "@types/jest": "npm:^27.4.1" deepmerge: "npm:^4.2.2" From d628f08ffccb358067d7a76658a0bbdf7ba69d3e Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Fri, 23 Jan 2026 12:02:52 +0100 Subject: [PATCH 21/55] fix: fix feedbacks --- .../src/ConfigRegistryController.test.ts | 733 +++++++++++++++++- .../src/ConfigRegistryController.ts | 33 +- .../config-registry-api-service.ts | 7 +- .../config-registry-controller/src/index.ts | 5 - 4 files changed, 748 insertions(+), 30 deletions(-) diff --git a/packages/config-registry-controller/src/ConfigRegistryController.test.ts b/packages/config-registry-controller/src/ConfigRegistryController.test.ts index c452f4409b3..7b03c8c84dc 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.test.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.test.ts @@ -347,15 +347,76 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockRejectedValue(new Error('Network error')); + const captureExceptionSpy = jest.fn(); + const testRootMessenger = new Messenger< + MockAnyNamespace, + | { + type: 'RemoteFeatureFlagController:getState'; + handler: () => unknown; + } + | { + type: 'KeyringController:getState'; + handler: () => { isUnlocked: boolean }; + } + | { + type: 'ConfigRegistryApiService:fetchConfig'; + handler: (options?: { + etag?: string; + }) => Promise; + }, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] } + >({ + namespace: MOCK_ANY_NAMESPACE, + captureException: captureExceptionSpy, + }); + + const testMessenger = new Messenger< + typeof namespace, + never, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] }, + typeof testRootMessenger + >({ + namespace, + parent: testRootMessenger, + }) as ConfigRegistryMessenger; + + testRootMessenger.registerActionHandler( + 'ConfigRegistryApiService:fetchConfig', + mockApiServiceHandler, + ); + testRootMessenger.registerActionHandler( + 'RemoteFeatureFlagController:getState', + mockRemoteFeatureFlagGetState, + ); + testRootMessenger.registerActionHandler( + 'KeyringController:getState', + mockKeyringControllerGetState, + ); + testRootMessenger.delegate({ + messenger: testMessenger, + actions: [ + 'RemoteFeatureFlagController:getState', + 'KeyringController:getState', + 'ConfigRegistryApiService:fetchConfig', + ] as never[], + events: [ + 'KeyringController:unlock', + 'KeyringController:lock', + ] as never[], + }); + const controller = new ConfigRegistryController({ - messenger, + messenger: testMessenger, fallbackConfig: MOCK_FALLBACK_CONFIG, }); - await expect(controller._executePoll(null)).rejects.toThrow( - 'Network error', - ); + await controller._executePoll(null); + expect(captureExceptionSpy).toHaveBeenCalledWith( + expect.objectContaining({ message: 'Network error' }), + ); expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG, }); @@ -384,16 +445,77 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockRejectedValue(new Error('Network error')); + const captureExceptionSpy = jest.fn(); + const testRootMessenger = new Messenger< + MockAnyNamespace, + | { + type: 'RemoteFeatureFlagController:getState'; + handler: () => unknown; + } + | { + type: 'KeyringController:getState'; + handler: () => { isUnlocked: boolean }; + } + | { + type: 'ConfigRegistryApiService:fetchConfig'; + handler: (options?: { + etag?: string; + }) => Promise; + }, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] } + >({ + namespace: MOCK_ANY_NAMESPACE, + captureException: captureExceptionSpy, + }); + + const testMessenger = new Messenger< + typeof namespace, + never, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] }, + typeof testRootMessenger + >({ + namespace, + parent: testRootMessenger, + }) as ConfigRegistryMessenger; + + testRootMessenger.registerActionHandler( + 'ConfigRegistryApiService:fetchConfig', + mockApiServiceHandler, + ); + testRootMessenger.registerActionHandler( + 'RemoteFeatureFlagController:getState', + mockRemoteFeatureFlagGetState, + ); + testRootMessenger.registerActionHandler( + 'KeyringController:getState', + mockKeyringControllerGetState, + ); + testRootMessenger.delegate({ + messenger: testMessenger, + actions: [ + 'RemoteFeatureFlagController:getState', + 'KeyringController:getState', + 'ConfigRegistryApiService:fetchConfig', + ] as never[], + events: [ + 'KeyringController:unlock', + 'KeyringController:lock', + ] as never[], + }); + const controller = new ConfigRegistryController({ - messenger, + messenger: testMessenger, state: { configs: existingConfigs }, fallbackConfig: MOCK_FALLBACK_CONFIG, }); - await expect(controller._executePoll(null)).rejects.toThrow( - 'Network error', - ); + await controller._executePoll(null); + expect(captureExceptionSpy).toHaveBeenCalledWith( + expect.objectContaining({ message: 'Network error' }), + ); expect(controller.state.configs).toStrictEqual(existingConfigs); expect(controller.state.fetchError).toBe('Network error'); }); @@ -408,15 +530,76 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockRejectedValue(new Error('Network error')); + const captureExceptionSpy = jest.fn(); + const testRootMessenger = new Messenger< + MockAnyNamespace, + | { + type: 'RemoteFeatureFlagController:getState'; + handler: () => unknown; + } + | { + type: 'KeyringController:getState'; + handler: () => { isUnlocked: boolean }; + } + | { + type: 'ConfigRegistryApiService:fetchConfig'; + handler: (options?: { + etag?: string; + }) => Promise; + }, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] } + >({ + namespace: MOCK_ANY_NAMESPACE, + captureException: captureExceptionSpy, + }); + + const testMessenger = new Messenger< + typeof namespace, + never, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] }, + typeof testRootMessenger + >({ + namespace, + parent: testRootMessenger, + }) as ConfigRegistryMessenger; + + testRootMessenger.registerActionHandler( + 'ConfigRegistryApiService:fetchConfig', + mockApiServiceHandler, + ); + testRootMessenger.registerActionHandler( + 'RemoteFeatureFlagController:getState', + mockRemoteFeatureFlagGetState, + ); + testRootMessenger.registerActionHandler( + 'KeyringController:getState', + mockKeyringControllerGetState, + ); + testRootMessenger.delegate({ + messenger: testMessenger, + actions: [ + 'RemoteFeatureFlagController:getState', + 'KeyringController:getState', + 'ConfigRegistryApiService:fetchConfig', + ] as never[], + events: [ + 'KeyringController:unlock', + 'KeyringController:lock', + ] as never[], + }); + const controller = new ConfigRegistryController({ - messenger, + messenger: testMessenger, fallbackConfig: MOCK_FALLBACK_CONFIG, }); - await expect(controller._executePoll(null)).rejects.toThrow( - 'Network error', - ); + await controller._executePoll(null); + expect(captureExceptionSpy).toHaveBeenCalledWith( + expect.objectContaining({ message: 'Network error' }), + ); expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG, }); @@ -446,11 +629,339 @@ describe('ConfigRegistryController', () => { await controller._executePoll(null); + expect(controller.state.fetchError).toBeNull(); + expect(controller.state.etag).toBe('"test-etag"'); + }); + + it('should handle notModified response and preserve existing etag when not provided', async () => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); + + mockApiServiceHandler.mockResolvedValue({ + notModified: true, + }); + + const controller = new ConfigRegistryController({ + messenger, + state: { + fetchError: 'Previous error', + etag: '"existing-etag"', + }, + }); + + await controller._executePoll(null); + + expect(controller.state.fetchError).toBeNull(); + expect(controller.state.etag).toBe('"existing-etag"'); + }); + + it('should handle notModified response and set etag to null when explicitly null', async () => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); + + mockApiServiceHandler.mockResolvedValue({ + notModified: true, + etag: null, + }); + + const controller = new ConfigRegistryController({ + messenger, + state: { + fetchError: 'Previous error', + etag: '"existing-etag"', + }, + }); + + await controller._executePoll(null); + expect(controller.state.fetchError).toBeNull(); expect(controller.state.etag).toBeNull(); }); - it('should handle non-Error exceptions', async () => { + it('should throw error when result.data is missing', async () => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); + + mockApiServiceHandler.mockResolvedValue({ + notModified: false, + }); + + const captureExceptionSpy = jest.fn(); + const testRootMessenger = new Messenger< + MockAnyNamespace, + | { + type: 'RemoteFeatureFlagController:getState'; + handler: () => unknown; + } + | { + type: 'KeyringController:getState'; + handler: () => { isUnlocked: boolean }; + } + | { + type: 'ConfigRegistryApiService:fetchConfig'; + handler: (options?: { + etag?: string; + }) => Promise; + }, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] } + >({ + namespace: MOCK_ANY_NAMESPACE, + captureException: captureExceptionSpy, + }); + + const testMessenger = new Messenger< + typeof namespace, + never, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] }, + typeof testRootMessenger + >({ + namespace, + parent: testRootMessenger, + }) as ConfigRegistryMessenger; + + testRootMessenger.registerActionHandler( + 'ConfigRegistryApiService:fetchConfig', + mockApiServiceHandler, + ); + testRootMessenger.registerActionHandler( + 'RemoteFeatureFlagController:getState', + mockRemoteFeatureFlagGetState, + ); + testRootMessenger.registerActionHandler( + 'KeyringController:getState', + mockKeyringControllerGetState, + ); + + testRootMessenger.delegate({ + messenger: testMessenger, + actions: [ + 'RemoteFeatureFlagController:getState', + 'KeyringController:getState', + 'ConfigRegistryApiService:fetchConfig', + ] as never[], + events: [ + 'KeyringController:unlock', + 'KeyringController:lock', + ] as never[], + }); + + const controller = new ConfigRegistryController({ + messenger: testMessenger, + }); + + await controller._executePoll(null); + + expect(captureExceptionSpy).toHaveBeenCalledWith( + expect.objectContaining({ + message: + 'Invalid response structure from config registry API: missing or malformed data', + }), + ); + expect(controller.state.fetchError).toBe( + 'Invalid response structure from config registry API: missing or malformed data', + ); + }); + + it('should throw error when result.data.data is missing', async () => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); + + mockApiServiceHandler.mockResolvedValue({ + notModified: false, + data: {}, + }); + + const controller = new ConfigRegistryController({ + messenger, + }); + + await controller._executePoll(null); + + expect(controller.state.fetchError).toBe( + 'Invalid response structure from config registry API: missing or malformed data', + ); + }); + + it('should throw error when result.data.data.networks is not an array', async () => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); + + mockApiServiceHandler.mockResolvedValue({ + notModified: false, + data: { + data: { + version: '1', + networks: 'not-an-array', + }, + }, + }); + + const controller = new ConfigRegistryController({ + messenger, + }); + + await controller._executePoll(null); + + expect(controller.state.fetchError).toBe( + 'Invalid response structure from config registry API: missing or malformed data', + ); + }); + + it('should throw error when result.data.data.version is not a string', async () => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); + + mockApiServiceHandler.mockResolvedValue({ + notModified: false, + data: { + data: { + version: 123, + networks: [], + }, + }, + }); + + const controller = new ConfigRegistryController({ + messenger, + }); + + await controller._executePoll(null); + + expect(controller.state.fetchError).toBe( + 'Invalid response structure from config registry API: missing or malformed data', + ); + }); + + it('should skip fetch when lastFetched is within polling interval', async () => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); + + const recentTimestamp = Date.now() - 1000; // 1 second ago + const controller = new ConfigRegistryController({ + messenger, + state: { + lastFetched: recentTimestamp, + }, + }); + + const fetchConfigSpy = jest.spyOn(messenger, 'call') as jest.SpyInstance; + + await controller._executePoll(null); + + // Should not call fetchConfig because not enough time has passed + expect(fetchConfigSpy).not.toHaveBeenCalledWith( + 'ConfigRegistryApiService:fetchConfig', + expect.anything(), + ); + }); + + it('should proceed with fetch when lastFetched is null', async () => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); + + mockApiServiceHandler.mockResolvedValue({ + data: { + data: { + networks: [ + createMockNetworkConfig({ + chainId: '0x1', + name: 'Ethereum Mainnet', + }), + ], + version: '1.0.0', + }, + }, + etag: '"test-etag"', + }); + + const controller = new ConfigRegistryController({ + messenger, + state: { + lastFetched: null, + }, + }); + + await controller._executePoll(null); + + // Should proceed with fetch when lastFetched is null + expect(mockApiServiceHandler).toHaveBeenCalled(); + expect(controller.state.lastFetched).not.toBeNull(); + }); + + it('should proceed with fetch when enough time has passed since lastFetched', async () => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); + + mockApiServiceHandler.mockResolvedValue({ + data: { + data: { + networks: [ + createMockNetworkConfig({ + chainId: '0x1', + name: 'Ethereum Mainnet', + }), + ], + version: '1.0.0', + }, + }, + etag: '"test-etag"', + }); + + // Set lastFetched to be older than the polling interval + const oldTimestamp = Date.now() - DEFAULT_POLLING_INTERVAL - 1000; // 1 second past interval + const controller = new ConfigRegistryController({ + messenger, + state: { + lastFetched: oldTimestamp, + }, + }); + + await controller._executePoll(null); + + // Should proceed with fetch when enough time has passed + expect(mockApiServiceHandler).toHaveBeenCalled(); + expect(controller.state.lastFetched).not.toBe(oldTimestamp); + }); + + it('should use custom polling interval when checking lastFetched', async () => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { configRegistryApiEnabled: true, @@ -458,15 +969,138 @@ describe('ConfigRegistryController', () => { cacheTimestamp: Date.now(), }); - mockApiServiceHandler.mockRejectedValue('String error'); // Not an Error instance + const customInterval = 5000; // 5 seconds + const recentTimestamp = Date.now() - 3000; // 3 seconds ago (within custom interval) + + const controller = new ConfigRegistryController({ + messenger, + pollingInterval: customInterval, + state: { + lastFetched: recentTimestamp, + }, + }); + + const fetchConfigSpy = jest.spyOn(messenger, 'call') as jest.SpyInstance; + + await controller._executePoll(null); + + // Should not call fetchConfig because not enough time has passed (3s < 5s) + expect(fetchConfigSpy).not.toHaveBeenCalledWith( + 'ConfigRegistryApiService:fetchConfig', + expect.anything(), + ); + }); + + it('should use DEFAULT_POLLING_INTERVAL when getIntervalLength returns undefined', async () => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); + const recentTimestamp = Date.now() - 1000; // 1 second ago const controller = new ConfigRegistryController({ messenger, + state: { + lastFetched: recentTimestamp, + }, + }); + + // Mock getIntervalLength to return undefined to test the fallback branch + jest.spyOn(controller, 'getIntervalLength').mockReturnValue(undefined); + + const fetchConfigSpy = jest.spyOn(messenger, 'call') as jest.SpyInstance; + + await controller._executePoll(null); + + // Should not call fetchConfig because not enough time has passed + expect(fetchConfigSpy).not.toHaveBeenCalledWith( + 'ConfigRegistryApiService:fetchConfig', + expect.anything(), + ); + }); + + it('should handle non-Error exceptions', async () => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); + + mockApiServiceHandler.mockRejectedValue('String error'); + + const captureExceptionSpy = jest.fn(); + const testRootMessenger = new Messenger< + MockAnyNamespace, + | { + type: 'RemoteFeatureFlagController:getState'; + handler: () => unknown; + } + | { + type: 'KeyringController:getState'; + handler: () => { isUnlocked: boolean }; + } + | { + type: 'ConfigRegistryApiService:fetchConfig'; + handler: (options?: { + etag?: string; + }) => Promise; + }, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] } + >({ + namespace: MOCK_ANY_NAMESPACE, + captureException: captureExceptionSpy, + }); + + const testMessenger = new Messenger< + typeof namespace, + never, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] }, + typeof testRootMessenger + >({ + namespace, + parent: testRootMessenger, + }) as ConfigRegistryMessenger; + + testRootMessenger.registerActionHandler( + 'ConfigRegistryApiService:fetchConfig', + mockApiServiceHandler, + ); + testRootMessenger.registerActionHandler( + 'RemoteFeatureFlagController:getState', + mockRemoteFeatureFlagGetState, + ); + testRootMessenger.registerActionHandler( + 'KeyringController:getState', + mockKeyringControllerGetState, + ); + testRootMessenger.delegate({ + messenger: testMessenger, + actions: [ + 'RemoteFeatureFlagController:getState', + 'KeyringController:getState', + 'ConfigRegistryApiService:fetchConfig', + ] as never[], + events: [ + 'KeyringController:unlock', + 'KeyringController:lock', + ] as never[], + }); + + const controller = new ConfigRegistryController({ + messenger: testMessenger, fallbackConfig: MOCK_FALLBACK_CONFIG, }); - await expect(controller._executePoll(null)).rejects.toBe('String error'); + await controller._executePoll(null); + expect(captureExceptionSpy).toHaveBeenCalledWith( + expect.objectContaining({ message: 'String error' }), + ); expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG, }); @@ -483,17 +1117,78 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockRejectedValue(new Error('Network error')); + const captureExceptionSpy = jest.fn(); + const testRootMessenger = new Messenger< + MockAnyNamespace, + | { + type: 'RemoteFeatureFlagController:getState'; + handler: () => unknown; + } + | { + type: 'KeyringController:getState'; + handler: () => { isUnlocked: boolean }; + } + | { + type: 'ConfigRegistryApiService:fetchConfig'; + handler: (options?: { + etag?: string; + }) => Promise; + }, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] } + >({ + namespace: MOCK_ANY_NAMESPACE, + captureException: captureExceptionSpy, + }); + + const testMessenger = new Messenger< + typeof namespace, + never, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] }, + typeof testRootMessenger + >({ + namespace, + parent: testRootMessenger, + }) as ConfigRegistryMessenger; + + testRootMessenger.registerActionHandler( + 'ConfigRegistryApiService:fetchConfig', + mockApiServiceHandler, + ); + testRootMessenger.registerActionHandler( + 'RemoteFeatureFlagController:getState', + mockRemoteFeatureFlagGetState, + ); + testRootMessenger.registerActionHandler( + 'KeyringController:getState', + mockKeyringControllerGetState, + ); + testRootMessenger.delegate({ + messenger: testMessenger, + actions: [ + 'RemoteFeatureFlagController:getState', + 'KeyringController:getState', + 'ConfigRegistryApiService:fetchConfig', + ] as never[], + events: [ + 'KeyringController:unlock', + 'KeyringController:lock', + ] as never[], + }); + const controller = new ConfigRegistryController({ - messenger, + messenger: testMessenger, fallbackConfig: MOCK_FALLBACK_CONFIG, // eslint-disable-next-line @typescript-eslint/no-explicit-any state: { configs: null as any }, }); - await expect(controller._executePoll(null)).rejects.toThrow( - 'Network error', - ); + await controller._executePoll(null); + expect(captureExceptionSpy).toHaveBeenCalledWith( + expect.objectContaining({ message: 'Network error' }), + ); expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG, }); diff --git a/packages/config-registry-controller/src/ConfigRegistryController.ts b/packages/config-registry-controller/src/ConfigRegistryController.ts index 0196a6b3a7c..3a1b18a1968 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.ts @@ -195,6 +195,17 @@ export class ConfigRegistryController extends StaticIntervalPollingController { state.fetchError = null; + if (result.etag !== undefined) { + state.etag = result.etag ?? null; + } }); return; } + // Validate API response structure to prevent runtime crashes + if ( + !result.data?.data || + !Array.isArray(result.data.data.networks) || + typeof result.data.data.version !== 'string' + ) { + throw new Error( + 'Invalid response structure from config registry API: missing or malformed data', + ); + } + // Filter networks: only featured, active, non-testnet networks const filteredNetworks = filterNetworks(result.data.data.networks, { isFeatured: true, @@ -235,8 +260,14 @@ export class ConfigRegistryController extends StaticIntervalPollingController Date: Sun, 25 Jan 2026 15:28:53 +0100 Subject: [PATCH 22/55] fix: fix feedbacks --- .../config-registry-controller/package.json | 2 + .../src/ConfigRegistryController.test.ts | 3754 +++++++++++------ .../src/ConfigRegistryController.ts | 221 +- .../abstract-config-registry-api-service.ts | 55 - .../config-registry-api-service.test.ts | 245 +- .../config-registry-api-service.ts | 101 +- .../src/config-registry-api-service/index.ts | 20 +- .../transformers.test.ts | 841 +--- .../transformers.ts | 290 +- .../src/config-registry-api-service/types.ts | 98 + .../config-registry-controller/src/index.ts | 6 +- .../tsconfig.build.json | 1 + .../config-registry-controller/tsconfig.json | 1 + yarn.lock | 2 + 14 files changed, 2927 insertions(+), 2710 deletions(-) delete mode 100644 packages/config-registry-controller/src/config-registry-api-service/abstract-config-registry-api-service.ts create mode 100644 packages/config-registry-controller/src/config-registry-api-service/types.ts diff --git a/packages/config-registry-controller/package.json b/packages/config-registry-controller/package.json index 80482e717dd..263aa46ec57 100644 --- a/packages/config-registry-controller/package.json +++ b/packages/config-registry-controller/package.json @@ -53,7 +53,9 @@ "@metamask/messenger": "^0.3.0", "@metamask/network-controller": "^29.0.0", "@metamask/polling-controller": "^16.0.2", + "@metamask/profile-sync-controller": "^27.0.0", "@metamask/remote-feature-flag-controller": "^4.0.0", + "@metamask/superstruct": "^3.1.0", "@metamask/utils": "^11.9.0" }, "devDependencies": { diff --git a/packages/config-registry-controller/src/ConfigRegistryController.test.ts b/packages/config-registry-controller/src/ConfigRegistryController.test.ts index 7b03c8c84dc..0a525136560 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.test.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.test.ts @@ -3,7 +3,6 @@ import { Messenger, MOCK_ANY_NAMESPACE } from '@metamask/messenger'; import { useFakeTimers } from 'sinon'; import type { - AbstractConfigRegistryApiService, FetchConfigResult, NetworkConfig, } from './config-registry-api-service'; @@ -139,92 +138,116 @@ const MOCK_FALLBACK_CONFIG: Record = { /** * Builds a mock API service fetch handler. * - * @param overrides - The properties of the API service you want to provide explicitly. + * @param overrides - Optional overrides object containing fetchConfig implementation. + * @param overrides.fetchConfig - Optional fetchConfig function override. * @returns A handler function for the fetchConfig action. */ -function buildMockApiServiceHandler( - overrides: Partial = {}, -): (options?: { etag?: string }) => Promise { - const defaultService: AbstractConfigRegistryApiService = { - async fetchConfig(): Promise { - return { +function buildMockApiServiceHandler(overrides?: { + fetchConfig?: (options?: { etag?: string }) => Promise; +}): (options?: { etag?: string }) => Promise { + const defaultFetchConfig = async (): Promise => { + return { + data: { data: { - data: { - version: '1', - timestamp: Date.now(), - networks: [], - }, + version: '1', + timestamp: Date.now(), + networks: [], }, - notModified: false, - }; - }, - onBreak: jest.fn(), - onDegraded: jest.fn(), + }, + modified: true, + }; }; - const service = { ...defaultService, ...overrides }; - return (options?: { etag?: string }) => service.fetchConfig(options); + return overrides?.fetchConfig ?? defaultFetchConfig; } -describe('ConfigRegistryController', () => { - let clock: sinon.SinonFakeTimers; - let messenger: ConfigRegistryMessenger; - let rootMessenger: RootMessenger; - let mockApiServiceHandler: jest.Mock; - let mockRemoteFeatureFlagGetState: jest.Mock; - let mockKeyringControllerGetState: jest.Mock; - - beforeEach(() => { - clock = useFakeTimers(); - const messengers = getConfigRegistryControllerMessenger(); - messenger = messengers.messenger; - rootMessenger = messengers.rootMessenger; - mockApiServiceHandler = jest.fn(buildMockApiServiceHandler()); - - rootMessenger.registerActionHandler( - 'ConfigRegistryApiService:fetchConfig', - mockApiServiceHandler, - ); +type WithControllerCallback = (args: { + controller: ConfigRegistryController; + clock: sinon.SinonFakeTimers; + rootMessenger: RootMessenger; + messenger: ConfigRegistryMessenger; + mockApiServiceHandler: jest.Mock; + mockRemoteFeatureFlagGetState: jest.Mock; + mockKeyringControllerGetState: jest.Mock; +}) => Promise | ReturnValue; - mockRemoteFeatureFlagGetState = jest.fn().mockReturnValue({ - remoteFeatureFlags: { - configRegistryApiEnabled: true, - }, - cacheTimestamp: Date.now(), - }); +type WithControllerOptions = { + options?: Partial[0]>; +}; - rootMessenger.registerActionHandler( - 'RemoteFeatureFlagController:getState', - mockRemoteFeatureFlagGetState, - ); +async function withController( + ...args: + | [WithControllerCallback] + | [WithControllerOptions, WithControllerCallback] +): Promise { + const [{ options = {} }, testFunction] = + args.length === 2 ? args : [{}, args[0]]; + + const clock = useFakeTimers(); + const messengers = getConfigRegistryControllerMessenger(); + const messenger = messengers.messenger; + const rootMessenger = messengers.rootMessenger; + const mockApiServiceHandler = jest.fn(buildMockApiServiceHandler()); + + rootMessenger.registerActionHandler( + 'ConfigRegistryApiService:fetchConfig', + mockApiServiceHandler, + ); + + const mockRemoteFeatureFlagGetState = jest.fn().mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); - mockKeyringControllerGetState = jest.fn().mockReturnValue({ - isUnlocked: false, - }); + rootMessenger.registerActionHandler( + 'RemoteFeatureFlagController:getState', + mockRemoteFeatureFlagGetState, + ); - rootMessenger.registerActionHandler( - 'KeyringController:getState', - mockKeyringControllerGetState, - ); + const mockKeyringControllerGetState = jest.fn().mockReturnValue({ + isUnlocked: false, + }); + + rootMessenger.registerActionHandler( + 'KeyringController:getState', + mockKeyringControllerGetState, + ); + + const controller = new ConfigRegistryController({ + messenger, + ...options, }); - afterEach(() => { + try { + return await testFunction({ + controller, + clock, + rootMessenger, + messenger, + mockApiServiceHandler, + mockRemoteFeatureFlagGetState, + mockKeyringControllerGetState, + }); + } finally { clock.restore(); mockApiServiceHandler.mockReset(); - }); + } +} + +describe('ConfigRegistryController', () => { describe('constructor', () => { it('should set default state', () => { - const controller = new ConfigRegistryController({ - messenger, - }); - - expect(controller.state).toStrictEqual({ - configs: { networks: {} }, - version: null, - lastFetched: null, - fetchError: null, - etag: null, + return withController(({ controller }) => { + expect(controller.state).toStrictEqual({ + configs: { networks: {} }, + version: null, + lastFetched: null, + fetchError: null, + etag: null, + }); }); }); @@ -239,198 +262,197 @@ describe('ConfigRegistryController', () => { lastFetched: 1234567890, }; - const controller = new ConfigRegistryController({ - messenger, - state: initialState, - }); - - expect(controller.state.configs.networks).toStrictEqual( - initialState.configs?.networks, + return withController( + { options: { state: initialState } }, + ({ controller }) => { + expect(controller.state.configs.networks).toStrictEqual( + initialState.configs?.networks, + ); + expect(controller.state.version).toBe('v1.0.0'); + expect(controller.state.lastFetched).toBe(1234567890); + }, ); - expect(controller.state.version).toBe('v1.0.0'); - expect(controller.state.lastFetched).toBe(1234567890); }); it('should set custom polling interval', () => { const customInterval = 5000; - const controller = new ConfigRegistryController({ - messenger, - pollingInterval: customInterval, - }); - - expect(controller.getIntervalLength()).toBe(customInterval); + return withController( + { options: { pollingInterval: customInterval } }, + ({ controller }) => { + expect(controller.getIntervalLength()).toBe(customInterval); + }, + ); }); it('should set fallback config', () => { - const controller = new ConfigRegistryController({ - messenger, - fallbackConfig: MOCK_FALLBACK_CONFIG, - }); - - expect(controller.state.configs).toStrictEqual({ networks: {} }); + return withController( + { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, + ({ controller }) => { + expect(controller.state.configs).toStrictEqual({ + networks: MOCK_FALLBACK_CONFIG, + }); + }, + ); }); it('should work when API service is registered on messenger', () => { - const controller = new ConfigRegistryController({ - messenger, - }); - - expect(controller.state).toStrictEqual({ - configs: { networks: {} }, - version: null, - lastFetched: null, - fetchError: null, - etag: null, + return withController(({ controller }) => { + expect(controller.state).toStrictEqual({ + configs: { networks: {} }, + version: null, + lastFetched: null, + fetchError: null, + etag: null, + }); }); }); }); describe('polling', () => { it('should start polling', async () => { - const controller = new ConfigRegistryController({ - messenger, - }); + return withController(async ({ controller, clock }) => { + const executePollSpy = jest.spyOn(controller, '_executePoll'); + controller.startPolling(null); - const executePollSpy = jest.spyOn(controller, '_executePoll'); - controller.startPolling(null); + await advanceTime({ clock, duration: 0 }); - await advanceTime({ clock, duration: 0 }); - - expect(executePollSpy).toHaveBeenCalledTimes(1); - controller.stopPolling(); + expect(executePollSpy).toHaveBeenCalledTimes(1); + controller.stopPolling(); + }); }); it('should poll at specified interval', async () => { const pollingInterval = 1000; - const controller = new ConfigRegistryController({ - messenger, - pollingInterval, - }); - - const executePollSpy = jest.spyOn(controller, '_executePoll'); - controller.startPolling(null); + return withController( + { options: { pollingInterval } }, + async ({ controller, clock }) => { + const executePollSpy = jest.spyOn(controller, '_executePoll'); + controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); - executePollSpy.mockClear(); + await advanceTime({ clock, duration: 0 }); + executePollSpy.mockClear(); - await advanceTime({ clock, duration: pollingInterval }); + await advanceTime({ clock, duration: pollingInterval }); - expect(executePollSpy).toHaveBeenCalledTimes(1); - controller.stopPolling(); + expect(executePollSpy).toHaveBeenCalledTimes(1); + controller.stopPolling(); + }, + ); }); it('should stop polling', async () => { - const controller = new ConfigRegistryController({ - messenger, - }); - - const executePollSpy = jest.spyOn(controller, '_executePoll'); - controller.startPolling(null); + return withController(async ({ controller, clock }) => { + const executePollSpy = jest.spyOn(controller, '_executePoll'); + controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); - executePollSpy.mockClear(); + await advanceTime({ clock, duration: 0 }); + executePollSpy.mockClear(); - controller.stopPolling(); + controller.stopPolling(); - await advanceTime({ clock, duration: DEFAULT_POLLING_INTERVAL }); + await advanceTime({ clock, duration: DEFAULT_POLLING_INTERVAL }); - expect(executePollSpy).not.toHaveBeenCalled(); + expect(executePollSpy).not.toHaveBeenCalled(); + }); }); it('should use fallback config when no configs exist', async () => { - mockRemoteFeatureFlagGetState.mockReturnValue({ - remoteFeatureFlags: { - configRegistryApiEnabled: true, + return withController( + { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, + async ({ + controller, + mockRemoteFeatureFlagGetState, + mockApiServiceHandler, + rootMessenger, + }) => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); + + mockApiServiceHandler.mockRejectedValue(new Error('Network error')); + + const captureExceptionSpy = jest.fn(); + const testRootMessenger = new Messenger< + MockAnyNamespace, + | { + type: 'RemoteFeatureFlagController:getState'; + handler: () => unknown; + } + | { + type: 'KeyringController:getState'; + handler: () => { isUnlocked: boolean }; + } + | { + type: 'ConfigRegistryApiService:fetchConfig'; + handler: (options?: { + etag?: string; + }) => Promise; + }, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] } + >({ + namespace: MOCK_ANY_NAMESPACE, + captureException: captureExceptionSpy, + }); + + const testMessenger = new Messenger< + typeof namespace, + never, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] }, + typeof testRootMessenger + >({ + namespace, + parent: testRootMessenger, + }) as ConfigRegistryMessenger; + + testRootMessenger.registerActionHandler( + 'ConfigRegistryApiService:fetchConfig', + mockApiServiceHandler, + ); + testRootMessenger.registerActionHandler( + 'RemoteFeatureFlagController:getState', + mockRemoteFeatureFlagGetState, + ); + testRootMessenger.registerActionHandler( + 'KeyringController:getState', + jest.fn().mockReturnValue({ isUnlocked: false }), + ); + testRootMessenger.delegate({ + messenger: testMessenger, + actions: [ + 'RemoteFeatureFlagController:getState', + 'KeyringController:getState', + 'ConfigRegistryApiService:fetchConfig', + ] as never[], + events: [ + 'KeyringController:unlock', + 'KeyringController:lock', + ] as never[], + }); + + const testController = new ConfigRegistryController({ + messenger: testMessenger, + fallbackConfig: MOCK_FALLBACK_CONFIG, + }); + + await testController._executePoll(null); + + expect(captureExceptionSpy).toHaveBeenCalledWith( + expect.objectContaining({ message: 'Network error' }), + ); + expect(testController.state.configs).toStrictEqual({ + networks: MOCK_FALLBACK_CONFIG, + }); + expect(testController.state.fetchError).toBe('Network error'); }, - cacheTimestamp: Date.now(), - }); - - mockApiServiceHandler.mockRejectedValue(new Error('Network error')); - - const captureExceptionSpy = jest.fn(); - const testRootMessenger = new Messenger< - MockAnyNamespace, - | { - type: 'RemoteFeatureFlagController:getState'; - handler: () => unknown; - } - | { - type: 'KeyringController:getState'; - handler: () => { isUnlocked: boolean }; - } - | { - type: 'ConfigRegistryApiService:fetchConfig'; - handler: (options?: { - etag?: string; - }) => Promise; - }, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] } - >({ - namespace: MOCK_ANY_NAMESPACE, - captureException: captureExceptionSpy, - }); - - const testMessenger = new Messenger< - typeof namespace, - never, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] }, - typeof testRootMessenger - >({ - namespace, - parent: testRootMessenger, - }) as ConfigRegistryMessenger; - - testRootMessenger.registerActionHandler( - 'ConfigRegistryApiService:fetchConfig', - mockApiServiceHandler, - ); - testRootMessenger.registerActionHandler( - 'RemoteFeatureFlagController:getState', - mockRemoteFeatureFlagGetState, ); - testRootMessenger.registerActionHandler( - 'KeyringController:getState', - mockKeyringControllerGetState, - ); - testRootMessenger.delegate({ - messenger: testMessenger, - actions: [ - 'RemoteFeatureFlagController:getState', - 'KeyringController:getState', - 'ConfigRegistryApiService:fetchConfig', - ] as never[], - events: [ - 'KeyringController:unlock', - 'KeyringController:lock', - ] as never[], - }); - - const controller = new ConfigRegistryController({ - messenger: testMessenger, - fallbackConfig: MOCK_FALLBACK_CONFIG, - }); - - await controller._executePoll(null); - - expect(captureExceptionSpy).toHaveBeenCalledWith( - expect.objectContaining({ message: 'Network error' }), - ); - expect(controller.state.configs).toStrictEqual({ - networks: MOCK_FALLBACK_CONFIG, - }); - expect(controller.state.fetchError).toBe('Network error'); }); it('should set fetchError when configs already exist (not use fallback)', async () => { - mockRemoteFeatureFlagGetState.mockReturnValue({ - remoteFeatureFlags: { - configRegistryApiEnabled: true, - }, - cacheTimestamp: Date.now(), - }); - const existingConfigs = { networks: { 'existing-key': { @@ -443,1225 +465,2517 @@ describe('ConfigRegistryController', () => { }, }; - mockApiServiceHandler.mockRejectedValue(new Error('Network error')); - - const captureExceptionSpy = jest.fn(); - const testRootMessenger = new Messenger< - MockAnyNamespace, - | { - type: 'RemoteFeatureFlagController:getState'; - handler: () => unknown; - } - | { - type: 'KeyringController:getState'; - handler: () => { isUnlocked: boolean }; - } - | { - type: 'ConfigRegistryApiService:fetchConfig'; - handler: (options?: { - etag?: string; - }) => Promise; + return withController( + { + options: { + state: { configs: existingConfigs }, + fallbackConfig: MOCK_FALLBACK_CONFIG, }, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] } - >({ - namespace: MOCK_ANY_NAMESPACE, - captureException: captureExceptionSpy, - }); - - const testMessenger = new Messenger< - typeof namespace, - never, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] }, - typeof testRootMessenger - >({ - namespace, - parent: testRootMessenger, - }) as ConfigRegistryMessenger; - - testRootMessenger.registerActionHandler( - 'ConfigRegistryApiService:fetchConfig', - mockApiServiceHandler, - ); - testRootMessenger.registerActionHandler( - 'RemoteFeatureFlagController:getState', - mockRemoteFeatureFlagGetState, - ); - testRootMessenger.registerActionHandler( - 'KeyringController:getState', - mockKeyringControllerGetState, - ); - testRootMessenger.delegate({ - messenger: testMessenger, - actions: [ - 'RemoteFeatureFlagController:getState', - 'KeyringController:getState', - 'ConfigRegistryApiService:fetchConfig', - ] as never[], - events: [ - 'KeyringController:unlock', - 'KeyringController:lock', - ] as never[], - }); - - const controller = new ConfigRegistryController({ - messenger: testMessenger, - state: { configs: existingConfigs }, - fallbackConfig: MOCK_FALLBACK_CONFIG, - }); - - await controller._executePoll(null); - - expect(captureExceptionSpy).toHaveBeenCalledWith( - expect.objectContaining({ message: 'Network error' }), + }, + async ({ + mockRemoteFeatureFlagGetState, + mockApiServiceHandler, + rootMessenger, + }) => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); + + mockApiServiceHandler.mockRejectedValue(new Error('Network error')); + + const captureExceptionSpy = jest.fn(); + const testRootMessenger = new Messenger< + MockAnyNamespace, + | { + type: 'RemoteFeatureFlagController:getState'; + handler: () => unknown; + } + | { + type: 'KeyringController:getState'; + handler: () => { isUnlocked: boolean }; + } + | { + type: 'ConfigRegistryApiService:fetchConfig'; + handler: (options?: { + etag?: string; + }) => Promise; + }, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] } + >({ + namespace: MOCK_ANY_NAMESPACE, + captureException: captureExceptionSpy, + }); + + const testMessenger = new Messenger< + typeof namespace, + never, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] }, + typeof testRootMessenger + >({ + namespace, + parent: testRootMessenger, + }) as ConfigRegistryMessenger; + + testRootMessenger.registerActionHandler( + 'ConfigRegistryApiService:fetchConfig', + mockApiServiceHandler, + ); + testRootMessenger.registerActionHandler( + 'RemoteFeatureFlagController:getState', + mockRemoteFeatureFlagGetState, + ); + testRootMessenger.registerActionHandler( + 'KeyringController:getState', + jest.fn().mockReturnValue({ isUnlocked: false }), + ); + testRootMessenger.delegate({ + messenger: testMessenger, + actions: [ + 'RemoteFeatureFlagController:getState', + 'KeyringController:getState', + 'ConfigRegistryApiService:fetchConfig', + ] as never[], + events: [ + 'KeyringController:unlock', + 'KeyringController:lock', + ] as never[], + }); + + const testController = new ConfigRegistryController({ + messenger: testMessenger, + state: { configs: existingConfigs }, + fallbackConfig: MOCK_FALLBACK_CONFIG, + }); + + await testController._executePoll(null); + + expect(captureExceptionSpy).toHaveBeenCalledWith( + expect.objectContaining({ message: 'Network error' }), + ); + expect(testController.state.configs).toStrictEqual(existingConfigs); + expect(testController.state.fetchError).toBe('Network error'); + }, ); - expect(controller.state.configs).toStrictEqual(existingConfigs); - expect(controller.state.fetchError).toBe('Network error'); }); it('should handle errors during polling', async () => { - mockRemoteFeatureFlagGetState.mockReturnValueOnce({ - remoteFeatureFlags: { - configRegistryApiEnabled: true, + return withController( + { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, + async ({ + mockRemoteFeatureFlagGetState, + mockApiServiceHandler, + }) => { + mockRemoteFeatureFlagGetState.mockReturnValueOnce({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); + + mockApiServiceHandler.mockRejectedValue(new Error('Network error')); + + const captureExceptionSpy = jest.fn(); + const testRootMessenger = new Messenger< + MockAnyNamespace, + | { + type: 'RemoteFeatureFlagController:getState'; + handler: () => unknown; + } + | { + type: 'KeyringController:getState'; + handler: () => { isUnlocked: boolean }; + } + | { + type: 'ConfigRegistryApiService:fetchConfig'; + handler: (options?: { + etag?: string; + }) => Promise; + }, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] } + >({ + namespace: MOCK_ANY_NAMESPACE, + captureException: captureExceptionSpy, + }); + + const testMessenger = new Messenger< + typeof namespace, + never, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] }, + typeof testRootMessenger + >({ + namespace, + parent: testRootMessenger, + }) as ConfigRegistryMessenger; + + testRootMessenger.registerActionHandler( + 'ConfigRegistryApiService:fetchConfig', + mockApiServiceHandler, + ); + testRootMessenger.registerActionHandler( + 'RemoteFeatureFlagController:getState', + mockRemoteFeatureFlagGetState, + ); + testRootMessenger.registerActionHandler( + 'KeyringController:getState', + jest.fn().mockReturnValue({ isUnlocked: false }), + ); + testRootMessenger.delegate({ + messenger: testMessenger, + actions: [ + 'RemoteFeatureFlagController:getState', + 'KeyringController:getState', + 'ConfigRegistryApiService:fetchConfig', + ] as never[], + events: [ + 'KeyringController:unlock', + 'KeyringController:lock', + ] as never[], + }); + + const testController = new ConfigRegistryController({ + messenger: testMessenger, + fallbackConfig: MOCK_FALLBACK_CONFIG, + }); + + await testController._executePoll(null); + + expect(captureExceptionSpy).toHaveBeenCalledWith( + expect.objectContaining({ message: 'Network error' }), + ); + expect(testController.state.configs).toStrictEqual({ + networks: MOCK_FALLBACK_CONFIG, + }); + expect(testController.state.fetchError).toBe('Network error'); + expect(mockRemoteFeatureFlagGetState).toHaveBeenCalled(); }, - cacheTimestamp: Date.now(), - }); - - mockApiServiceHandler.mockRejectedValue(new Error('Network error')); - - const captureExceptionSpy = jest.fn(); - const testRootMessenger = new Messenger< - MockAnyNamespace, - | { - type: 'RemoteFeatureFlagController:getState'; - handler: () => unknown; - } - | { - type: 'KeyringController:getState'; - handler: () => { isUnlocked: boolean }; - } - | { - type: 'ConfigRegistryApiService:fetchConfig'; - handler: (options?: { - etag?: string; - }) => Promise; - }, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] } - >({ - namespace: MOCK_ANY_NAMESPACE, - captureException: captureExceptionSpy, - }); - - const testMessenger = new Messenger< - typeof namespace, - never, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] }, - typeof testRootMessenger - >({ - namespace, - parent: testRootMessenger, - }) as ConfigRegistryMessenger; - - testRootMessenger.registerActionHandler( - 'ConfigRegistryApiService:fetchConfig', - mockApiServiceHandler, - ); - testRootMessenger.registerActionHandler( - 'RemoteFeatureFlagController:getState', - mockRemoteFeatureFlagGetState, ); - testRootMessenger.registerActionHandler( - 'KeyringController:getState', - mockKeyringControllerGetState, - ); - testRootMessenger.delegate({ - messenger: testMessenger, - actions: [ - 'RemoteFeatureFlagController:getState', - 'KeyringController:getState', - 'ConfigRegistryApiService:fetchConfig', - ] as never[], - events: [ - 'KeyringController:unlock', - 'KeyringController:lock', - ] as never[], - }); - - const controller = new ConfigRegistryController({ - messenger: testMessenger, - fallbackConfig: MOCK_FALLBACK_CONFIG, - }); - - await controller._executePoll(null); + }); - expect(captureExceptionSpy).toHaveBeenCalledWith( - expect.objectContaining({ message: 'Network error' }), + it('should handle unmodified response and clear fetchError', async () => { + return withController( + { + options: { + state: { + fetchError: 'Previous error', + }, + }, + }, + async ({ + controller, + mockRemoteFeatureFlagGetState, + mockApiServiceHandler, + }) => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); + + mockApiServiceHandler.mockResolvedValue({ + modified: false, + etag: '"test-etag"', + }); + + const beforeTimestamp = Date.now(); + await controller._executePoll(null); + const afterTimestamp = Date.now(); + + expect(controller.state.fetchError).toBeNull(); + expect(controller.state.etag).toBe('"test-etag"'); + expect(controller.state.lastFetched).not.toBeNull(); + expect(controller.state.lastFetched).toBeGreaterThanOrEqual( + beforeTimestamp, + ); + expect(controller.state.lastFetched).toBeLessThanOrEqual( + afterTimestamp, + ); + }, ); - expect(controller.state.configs).toStrictEqual({ - networks: MOCK_FALLBACK_CONFIG, - }); - expect(controller.state.fetchError).toBe('Network error'); - expect(mockRemoteFeatureFlagGetState).toHaveBeenCalled(); }); - it('should handle notModified response and clear fetchError', async () => { - mockRemoteFeatureFlagGetState.mockReturnValue({ - remoteFeatureFlags: { - configRegistryApiEnabled: true, + it('should handle unmodified response and preserve existing etag when not provided', async () => { + return withController( + { + options: { + state: { + fetchError: 'Previous error', + etag: '"existing-etag"', + }, + }, }, - cacheTimestamp: Date.now(), - }); - - mockApiServiceHandler.mockResolvedValue({ - notModified: true, - etag: '"test-etag"', - }); - - const controller = new ConfigRegistryController({ - messenger, - state: { - fetchError: 'Previous error', + async ({ + controller, + mockRemoteFeatureFlagGetState, + mockApiServiceHandler, + }) => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); + + mockApiServiceHandler.mockResolvedValue({ + modified: false, + }); + + const beforeTimestamp = Date.now(); + await controller._executePoll(null); + const afterTimestamp = Date.now(); + + expect(controller.state.fetchError).toBeNull(); + expect(controller.state.etag).toBe('"existing-etag"'); + expect(controller.state.lastFetched).not.toBeNull(); + expect(controller.state.lastFetched).toBeGreaterThanOrEqual( + beforeTimestamp, + ); + expect(controller.state.lastFetched).toBeLessThanOrEqual( + afterTimestamp, + ); }, - }); - - await controller._executePoll(null); - - expect(controller.state.fetchError).toBeNull(); - expect(controller.state.etag).toBe('"test-etag"'); + ); }); - it('should handle notModified response and preserve existing etag when not provided', async () => { - mockRemoteFeatureFlagGetState.mockReturnValue({ - remoteFeatureFlags: { - configRegistryApiEnabled: true, + it('should handle unmodified response and set etag to null when explicitly null', async () => { + return withController( + { + options: { + state: { + fetchError: 'Previous error', + etag: '"existing-etag"', + }, + }, }, - cacheTimestamp: Date.now(), - }); - - mockApiServiceHandler.mockResolvedValue({ - notModified: true, - }); - - const controller = new ConfigRegistryController({ - messenger, - state: { - fetchError: 'Previous error', - etag: '"existing-etag"', + async ({ + controller, + mockRemoteFeatureFlagGetState, + mockApiServiceHandler, + }) => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); + + mockApiServiceHandler.mockResolvedValue({ + modified: false, + etag: null, + }); + + const beforeTimestamp = Date.now(); + await controller._executePoll(null); + const afterTimestamp = Date.now(); + + expect(controller.state.fetchError).toBeNull(); + expect(controller.state.etag).toBeNull(); + expect(controller.state.lastFetched).not.toBeNull(); + expect(controller.state.lastFetched).toBeGreaterThanOrEqual( + beforeTimestamp, + ); + expect(controller.state.lastFetched).toBeLessThanOrEqual( + afterTimestamp, + ); }, - }); - - await controller._executePoll(null); - - expect(controller.state.fetchError).toBeNull(); - expect(controller.state.etag).toBe('"existing-etag"'); + ); }); - it('should handle notModified response and set etag to null when explicitly null', async () => { - mockRemoteFeatureFlagGetState.mockReturnValue({ - remoteFeatureFlags: { - configRegistryApiEnabled: true, + it('should handle validation error from service', async () => { + return withController( + async ({ mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); + + const validationError = new Error('Validation error from superstruct'); + mockApiServiceHandler.mockRejectedValue(validationError); + + const captureExceptionSpy = jest.fn(); + const testRootMessenger = new Messenger< + MockAnyNamespace, + | { + type: 'RemoteFeatureFlagController:getState'; + handler: () => unknown; + } + | { + type: 'KeyringController:getState'; + handler: () => { isUnlocked: boolean }; + } + | { + type: 'ConfigRegistryApiService:fetchConfig'; + handler: (options?: { + etag?: string; + }) => Promise; + }, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] } + >({ + namespace: MOCK_ANY_NAMESPACE, + captureException: captureExceptionSpy, + }); + + const testMessenger = new Messenger< + typeof namespace, + never, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] }, + typeof testRootMessenger + >({ + namespace, + parent: testRootMessenger, + }) as ConfigRegistryMessenger; + + testRootMessenger.registerActionHandler( + 'ConfigRegistryApiService:fetchConfig', + mockApiServiceHandler, + ); + testRootMessenger.registerActionHandler( + 'RemoteFeatureFlagController:getState', + mockRemoteFeatureFlagGetState, + ); + testRootMessenger.registerActionHandler( + 'KeyringController:getState', + jest.fn().mockReturnValue({ isUnlocked: false }), + ); + + testRootMessenger.delegate({ + messenger: testMessenger, + actions: [ + 'RemoteFeatureFlagController:getState', + 'KeyringController:getState', + 'ConfigRegistryApiService:fetchConfig', + ] as never[], + events: [ + 'KeyringController:unlock', + 'KeyringController:lock', + ] as never[], + }); + + const testController = new ConfigRegistryController({ + messenger: testMessenger, + }); + + await testController._executePoll(null); + + expect(captureExceptionSpy).toHaveBeenCalledWith( + expect.objectContaining({ + message: 'Validation error from superstruct', + }), + ); + expect(testController.state.fetchError).toBe( + 'Validation error from superstruct', + ); }, - cacheTimestamp: Date.now(), - }); + ); + }); - mockApiServiceHandler.mockResolvedValue({ - notModified: true, - etag: null, - }); + it('should handle validation error when result.data.data is missing', async () => { + return withController( + async ({ controller, mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); - const controller = new ConfigRegistryController({ - messenger, - state: { - fetchError: 'Previous error', - etag: '"existing-etag"', - }, - }); + const validationError = new Error('Validation error: data.data is missing'); + mockApiServiceHandler.mockRejectedValue(validationError); - await controller._executePoll(null); + await controller._executePoll(null); - expect(controller.state.fetchError).toBeNull(); - expect(controller.state.etag).toBeNull(); + expect(controller.state.fetchError).toBe( + 'Validation error: data.data is missing', + ); + }, + ); }); - it('should throw error when result.data is missing', async () => { - mockRemoteFeatureFlagGetState.mockReturnValue({ - remoteFeatureFlags: { - configRegistryApiEnabled: true, - }, - cacheTimestamp: Date.now(), - }); + it('should handle validation error when result.data.data.networks is not an array', async () => { + return withController( + async ({ controller, mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); - mockApiServiceHandler.mockResolvedValue({ - notModified: false, - }); + const validationError = new Error( + 'Validation error: data.data.networks is not an array', + ); + mockApiServiceHandler.mockRejectedValue(validationError); - const captureExceptionSpy = jest.fn(); - const testRootMessenger = new Messenger< - MockAnyNamespace, - | { - type: 'RemoteFeatureFlagController:getState'; - handler: () => unknown; - } - | { - type: 'KeyringController:getState'; - handler: () => { isUnlocked: boolean }; - } - | { - type: 'ConfigRegistryApiService:fetchConfig'; - handler: (options?: { - etag?: string; - }) => Promise; - }, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] } - >({ - namespace: MOCK_ANY_NAMESPACE, - captureException: captureExceptionSpy, - }); + await controller._executePoll(null); - const testMessenger = new Messenger< - typeof namespace, - never, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] }, - typeof testRootMessenger - >({ - namespace, - parent: testRootMessenger, - }) as ConfigRegistryMessenger; - - testRootMessenger.registerActionHandler( - 'ConfigRegistryApiService:fetchConfig', - mockApiServiceHandler, - ); - testRootMessenger.registerActionHandler( - 'RemoteFeatureFlagController:getState', - mockRemoteFeatureFlagGetState, - ); - testRootMessenger.registerActionHandler( - 'KeyringController:getState', - mockKeyringControllerGetState, + expect(controller.state.fetchError).toBe( + 'Validation error: data.data.networks is not an array', + ); + }, ); + }); - testRootMessenger.delegate({ - messenger: testMessenger, - actions: [ - 'RemoteFeatureFlagController:getState', - 'KeyringController:getState', - 'ConfigRegistryApiService:fetchConfig', - ] as never[], - events: [ - 'KeyringController:unlock', - 'KeyringController:lock', - ] as never[], - }); + it('should handle validation error when result.data.data.version is not a string', async () => { + return withController( + async ({ controller, mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); - const controller = new ConfigRegistryController({ - messenger: testMessenger, - }); + const validationError = new Error( + 'Validation error: data.data.version is not a string', + ); + mockApiServiceHandler.mockRejectedValue(validationError); - await controller._executePoll(null); + await controller._executePoll(null); - expect(captureExceptionSpy).toHaveBeenCalledWith( - expect.objectContaining({ - message: - 'Invalid response structure from config registry API: missing or malformed data', - }), - ); - expect(controller.state.fetchError).toBe( - 'Invalid response structure from config registry API: missing or malformed data', + expect(controller.state.fetchError).toBe( + 'Validation error: data.data.version is not a string', + ); + }, ); }); - it('should throw error when result.data.data is missing', async () => { - mockRemoteFeatureFlagGetState.mockReturnValue({ - remoteFeatureFlags: { - configRegistryApiEnabled: true, + it('should skip fetch when lastFetched is within polling interval', async () => { + const recentTimestamp = Date.now() - 1000; + return withController( + { + options: { + state: { + lastFetched: recentTimestamp, + }, + }, }, - cacheTimestamp: Date.now(), - }); - - mockApiServiceHandler.mockResolvedValue({ - notModified: false, - data: {}, - }); + async ({ controller, messenger, mockRemoteFeatureFlagGetState }) => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); - const controller = new ConfigRegistryController({ - messenger, - }); + const fetchConfigSpy = jest.spyOn(messenger, 'call') as jest.SpyInstance; - await controller._executePoll(null); + await controller._executePoll(null); - expect(controller.state.fetchError).toBe( - 'Invalid response structure from config registry API: missing or malformed data', + expect(fetchConfigSpy).not.toHaveBeenCalledWith( + 'ConfigRegistryApiService:fetchConfig', + expect.anything(), + ); + }, ); }); - it('should throw error when result.data.data.networks is not an array', async () => { - mockRemoteFeatureFlagGetState.mockReturnValue({ - remoteFeatureFlags: { - configRegistryApiEnabled: true, + it('should proceed with fetch when lastFetched is null', async () => { + return withController( + { + options: { + state: { + lastFetched: null, + }, + }, + }, + async ({ + controller, + mockRemoteFeatureFlagGetState, + mockApiServiceHandler, + }) => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); + + mockApiServiceHandler.mockResolvedValue({ + data: { + data: { + networks: [ + createMockNetworkConfig({ + chainId: '0x1', + name: 'Ethereum Mainnet', + }), + ], + version: '1.0.0', + }, + }, + etag: '"test-etag"', + modified: true, + }); + + await controller._executePoll(null); + + expect(mockApiServiceHandler).toHaveBeenCalled(); + expect(controller.state.lastFetched).not.toBeNull(); }, - cacheTimestamp: Date.now(), - }); + ); + }); - mockApiServiceHandler.mockResolvedValue({ - notModified: false, - data: { - data: { - version: '1', - networks: 'not-an-array', + it('should proceed with fetch when enough time has passed since lastFetched', async () => { + const now = Date.now(); + const oldTimestamp = now - DEFAULT_POLLING_INTERVAL - 1000; + return withController( + { + options: { + state: { + lastFetched: oldTimestamp, + }, }, }, - }); + async ({ + controller, + mockRemoteFeatureFlagGetState, + mockApiServiceHandler, + }) => { + jest.spyOn(Date, 'now').mockReturnValue(now); + + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: now, + }); + + mockApiServiceHandler.mockResolvedValue({ + data: { + data: { + networks: [ + createMockNetworkConfig({ + chainId: '0x1', + name: 'Ethereum Mainnet', + }), + ], + version: '1.0.0', + }, + }, + etag: '"test-etag"', + modified: true, + }); - const controller = new ConfigRegistryController({ - messenger, - }); + await controller._executePoll(null); - await controller._executePoll(null); + expect(mockApiServiceHandler).toHaveBeenCalled(); + expect(controller.state.lastFetched).not.toBe(oldTimestamp); - expect(controller.state.fetchError).toBe( - 'Invalid response structure from config registry API: missing or malformed data', + jest.restoreAllMocks(); + }, ); }); - it('should throw error when result.data.data.version is not a string', async () => { - mockRemoteFeatureFlagGetState.mockReturnValue({ - remoteFeatureFlags: { - configRegistryApiEnabled: true, - }, - cacheTimestamp: Date.now(), - }); - - mockApiServiceHandler.mockResolvedValue({ - notModified: false, - data: { - data: { - version: 123, - networks: [], + it('should use custom polling interval when checking lastFetched', async () => { + const customInterval = 5000; + const recentTimestamp = Date.now() - 3000; + return withController( + { + options: { + pollingInterval: customInterval, + state: { + lastFetched: recentTimestamp, + }, }, }, - }); + async ({ controller, messenger, mockRemoteFeatureFlagGetState }) => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); - const controller = new ConfigRegistryController({ - messenger, - }); + const fetchConfigSpy = jest.spyOn(messenger, 'call') as jest.SpyInstance; - await controller._executePoll(null); + await controller._executePoll(null); - expect(controller.state.fetchError).toBe( - 'Invalid response structure from config registry API: missing or malformed data', + expect(fetchConfigSpy).not.toHaveBeenCalledWith( + 'ConfigRegistryApiService:fetchConfig', + expect.anything(), + ); + }, ); }); - it('should skip fetch when lastFetched is within polling interval', async () => { - mockRemoteFeatureFlagGetState.mockReturnValue({ - remoteFeatureFlags: { - configRegistryApiEnabled: true, + it('should use DEFAULT_POLLING_INTERVAL when getIntervalLength returns undefined', async () => { + const recentTimestamp = Date.now() - 1000; + return withController( + { + options: { + state: { + lastFetched: recentTimestamp, + }, + }, }, - cacheTimestamp: Date.now(), - }); + async ({ controller, messenger, mockRemoteFeatureFlagGetState }) => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); - const recentTimestamp = Date.now() - 1000; // 1 second ago - const controller = new ConfigRegistryController({ - messenger, - state: { - lastFetched: recentTimestamp, - }, - }); + jest.spyOn(controller, 'getIntervalLength').mockReturnValue(undefined); - const fetchConfigSpy = jest.spyOn(messenger, 'call') as jest.SpyInstance; + const fetchConfigSpy = jest.spyOn(messenger, 'call') as jest.SpyInstance; - await controller._executePoll(null); + await controller._executePoll(null); - // Should not call fetchConfig because not enough time has passed - expect(fetchConfigSpy).not.toHaveBeenCalledWith( - 'ConfigRegistryApiService:fetchConfig', - expect.anything(), + expect(fetchConfigSpy).not.toHaveBeenCalledWith( + 'ConfigRegistryApiService:fetchConfig', + expect.anything(), + ); + }, ); }); - it('should proceed with fetch when lastFetched is null', async () => { - mockRemoteFeatureFlagGetState.mockReturnValue({ - remoteFeatureFlags: { - configRegistryApiEnabled: true, + it('should handle non-Error exceptions', async () => { + return withController( + { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, + async ({ mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); + + mockApiServiceHandler.mockRejectedValue('String error'); + + const captureExceptionSpy = jest.fn(); + const testRootMessenger = new Messenger< + MockAnyNamespace, + | { + type: 'RemoteFeatureFlagController:getState'; + handler: () => unknown; + } + | { + type: 'KeyringController:getState'; + handler: () => { isUnlocked: boolean }; + } + | { + type: 'ConfigRegistryApiService:fetchConfig'; + handler: (options?: { + etag?: string; + }) => Promise; + }, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] } + >({ + namespace: MOCK_ANY_NAMESPACE, + captureException: captureExceptionSpy, + }); + + const testMessenger = new Messenger< + typeof namespace, + never, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] }, + typeof testRootMessenger + >({ + namespace, + parent: testRootMessenger, + }) as ConfigRegistryMessenger; + + testRootMessenger.registerActionHandler( + 'ConfigRegistryApiService:fetchConfig', + mockApiServiceHandler, + ); + testRootMessenger.registerActionHandler( + 'RemoteFeatureFlagController:getState', + mockRemoteFeatureFlagGetState, + ); + testRootMessenger.registerActionHandler( + 'KeyringController:getState', + jest.fn().mockReturnValue({ isUnlocked: false }), + ); + testRootMessenger.delegate({ + messenger: testMessenger, + actions: [ + 'RemoteFeatureFlagController:getState', + 'KeyringController:getState', + 'ConfigRegistryApiService:fetchConfig', + ] as never[], + events: [ + 'KeyringController:unlock', + 'KeyringController:lock', + ] as never[], + }); + + const testController = new ConfigRegistryController({ + messenger: testMessenger, + fallbackConfig: MOCK_FALLBACK_CONFIG, + }); + + await testController._executePoll(null); + + expect(captureExceptionSpy).toHaveBeenCalledWith( + expect.objectContaining({ message: 'String error' }), + ); + expect(testController.state.configs).toStrictEqual({ + networks: MOCK_FALLBACK_CONFIG, + }); + expect(testController.state.fetchError).toBe('Unknown error occurred'); }, - cacheTimestamp: Date.now(), - }); + ); + }); - mockApiServiceHandler.mockResolvedValue({ - data: { - data: { - networks: [ - createMockNetworkConfig({ - chainId: '0x1', - name: 'Ethereum Mainnet', - }), - ], - version: '1.0.0', + it('should handle error when state.configs is null', async () => { + return withController( + { + options: { + fallbackConfig: MOCK_FALLBACK_CONFIG, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + state: { configs: null as any }, }, }, - etag: '"test-etag"', - }); - - const controller = new ConfigRegistryController({ - messenger, - state: { - lastFetched: null, + async ({ mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); + + mockApiServiceHandler.mockRejectedValue(new Error('Network error')); + + const captureExceptionSpy = jest.fn(); + const testRootMessenger = new Messenger< + MockAnyNamespace, + | { + type: 'RemoteFeatureFlagController:getState'; + handler: () => unknown; + } + | { + type: 'KeyringController:getState'; + handler: () => { isUnlocked: boolean }; + } + | { + type: 'ConfigRegistryApiService:fetchConfig'; + handler: (options?: { + etag?: string; + }) => Promise; + }, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] } + >({ + namespace: MOCK_ANY_NAMESPACE, + captureException: captureExceptionSpy, + }); + + const testMessenger = new Messenger< + typeof namespace, + never, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] }, + typeof testRootMessenger + >({ + namespace, + parent: testRootMessenger, + }) as ConfigRegistryMessenger; + + testRootMessenger.registerActionHandler( + 'ConfigRegistryApiService:fetchConfig', + mockApiServiceHandler, + ); + testRootMessenger.registerActionHandler( + 'RemoteFeatureFlagController:getState', + mockRemoteFeatureFlagGetState, + ); + testRootMessenger.registerActionHandler( + 'KeyringController:getState', + jest.fn().mockReturnValue({ isUnlocked: false }), + ); + testRootMessenger.delegate({ + messenger: testMessenger, + actions: [ + 'RemoteFeatureFlagController:getState', + 'KeyringController:getState', + 'ConfigRegistryApiService:fetchConfig', + ] as never[], + events: [ + 'KeyringController:unlock', + 'KeyringController:lock', + ] as never[], + }); + + const testController = new ConfigRegistryController({ + messenger: testMessenger, + fallbackConfig: MOCK_FALLBACK_CONFIG, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + state: { configs: null as any }, + }); + + await testController._executePoll(null); + + expect(captureExceptionSpy).toHaveBeenCalledWith( + expect.objectContaining({ message: 'Network error' }), + ); + expect(testController.state.configs).toStrictEqual({ + networks: MOCK_FALLBACK_CONFIG, + }); + expect(testController.state.fetchError).toBe('Network error'); }, - }); + ); + }); - await controller._executePoll(null); + it('should work via messenger actions', async () => { + return withController(async ({ controller, messenger, clock }) => { + const executePollSpy = jest.spyOn(controller, '_executePoll'); - // Should proceed with fetch when lastFetched is null - expect(mockApiServiceHandler).toHaveBeenCalled(); - expect(controller.state.lastFetched).not.toBeNull(); - }); + const token = messenger.call( + 'ConfigRegistryController:startPolling', + null, + ); + expect(typeof token).toBe('string'); - it('should proceed with fetch when enough time has passed since lastFetched', async () => { - mockRemoteFeatureFlagGetState.mockReturnValue({ - remoteFeatureFlags: { - configRegistryApiEnabled: true, - }, - cacheTimestamp: Date.now(), - }); + await advanceTime({ clock, duration: 0 }); + expect(executePollSpy).toHaveBeenCalledTimes(1); - mockApiServiceHandler.mockResolvedValue({ - data: { - data: { - networks: [ - createMockNetworkConfig({ - chainId: '0x1', - name: 'Ethereum Mainnet', - }), - ], - version: '1.0.0', - }, - }, - etag: '"test-etag"', + messenger.call('ConfigRegistryController:stopPolling'); + await advanceTime({ clock, duration: DEFAULT_POLLING_INTERVAL }); + expect(executePollSpy).toHaveBeenCalledTimes(1); }); - - // Set lastFetched to be older than the polling interval - const oldTimestamp = Date.now() - DEFAULT_POLLING_INTERVAL - 1000; // 1 second past interval - const controller = new ConfigRegistryController({ - messenger, - state: { - lastFetched: oldTimestamp, - }, - }); - - await controller._executePoll(null); - - // Should proceed with fetch when enough time has passed - expect(mockApiServiceHandler).toHaveBeenCalled(); - expect(controller.state.lastFetched).not.toBe(oldTimestamp); }); + }); - it('should use custom polling interval when checking lastFetched', async () => { - mockRemoteFeatureFlagGetState.mockReturnValue({ - remoteFeatureFlags: { - configRegistryApiEnabled: true, + describe('state persistence', () => { + it('should persist version', () => { + return withController( + { options: { state: { version: 'v1.0.0' } } }, + ({ controller }) => { + expect(controller.state.version).toBe('v1.0.0'); }, - cacheTimestamp: Date.now(), - }); - - const customInterval = 5000; // 5 seconds - const recentTimestamp = Date.now() - 3000; // 3 seconds ago (within custom interval) + ); + }); - const controller = new ConfigRegistryController({ - messenger, - pollingInterval: customInterval, - state: { - lastFetched: recentTimestamp, + it('should persist lastFetched', () => { + const timestamp = Date.now(); + return withController( + { options: { state: { lastFetched: timestamp } } }, + ({ controller }) => { + expect(controller.state.lastFetched).toBe(timestamp); }, - }); - - const fetchConfigSpy = jest.spyOn(messenger, 'call') as jest.SpyInstance; - - await controller._executePoll(null); - - // Should not call fetchConfig because not enough time has passed (3s < 5s) - expect(fetchConfigSpy).not.toHaveBeenCalledWith( - 'ConfigRegistryApiService:fetchConfig', - expect.anything(), ); }); - it('should use DEFAULT_POLLING_INTERVAL when getIntervalLength returns undefined', async () => { - mockRemoteFeatureFlagGetState.mockReturnValue({ - remoteFeatureFlags: { - configRegistryApiEnabled: true, + it('should persist fetchError', () => { + return withController( + { options: { state: { fetchError: 'Test error' } } }, + ({ controller }) => { + expect(controller.state.fetchError).toBe('Test error'); }, - cacheTimestamp: Date.now(), - }); + ); + }); - const recentTimestamp = Date.now() - 1000; // 1 second ago - const controller = new ConfigRegistryController({ - messenger, - state: { - lastFetched: recentTimestamp, + it('should use default error message when useFallbackConfig is called without errorMessage', () => { + return withController( + { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, + ({ controller }) => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (controller as any).useFallbackConfig(); + + expect(controller.state.configs).toStrictEqual({ + networks: MOCK_FALLBACK_CONFIG, + }); + expect(controller.state.fetchError).toBe( + 'Using fallback configuration - API unavailable', + ); + expect(controller.state.etag).toBeNull(); }, - }); - - // Mock getIntervalLength to return undefined to test the fallback branch - jest.spyOn(controller, 'getIntervalLength').mockReturnValue(undefined); - - const fetchConfigSpy = jest.spyOn(messenger, 'call') as jest.SpyInstance; - - await controller._executePoll(null); - - // Should not call fetchConfig because not enough time has passed - expect(fetchConfigSpy).not.toHaveBeenCalledWith( - 'ConfigRegistryApiService:fetchConfig', - expect.anything(), ); }); + }); - it('should handle non-Error exceptions', async () => { - mockRemoteFeatureFlagGetState.mockReturnValue({ - remoteFeatureFlags: { - configRegistryApiEnabled: true, - }, - cacheTimestamp: Date.now(), - }); + describe('startPolling', () => { + it('should return a polling token string', () => { + return withController(({ controller }) => { + const token = controller.startPolling(null); + expect(typeof token).toBe('string'); + expect(token.length).toBeGreaterThan(0); - mockApiServiceHandler.mockRejectedValue('String error'); - - const captureExceptionSpy = jest.fn(); - const testRootMessenger = new Messenger< - MockAnyNamespace, - | { - type: 'RemoteFeatureFlagController:getState'; - handler: () => unknown; - } - | { - type: 'KeyringController:getState'; - handler: () => { isUnlocked: boolean }; - } - | { - type: 'ConfigRegistryApiService:fetchConfig'; - handler: (options?: { - etag?: string; - }) => Promise; - }, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] } - >({ - namespace: MOCK_ANY_NAMESPACE, - captureException: captureExceptionSpy, + controller.stopPolling(); }); + }); - const testMessenger = new Messenger< - typeof namespace, - never, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] }, - typeof testRootMessenger - >({ - namespace, - parent: testRootMessenger, - }) as ConfigRegistryMessenger; - - testRootMessenger.registerActionHandler( - 'ConfigRegistryApiService:fetchConfig', - mockApiServiceHandler, - ); - testRootMessenger.registerActionHandler( - 'RemoteFeatureFlagController:getState', - mockRemoteFeatureFlagGetState, - ); - testRootMessenger.registerActionHandler( - 'KeyringController:getState', - mockKeyringControllerGetState, - ); - testRootMessenger.delegate({ - messenger: testMessenger, - actions: [ - 'RemoteFeatureFlagController:getState', - 'KeyringController:getState', - 'ConfigRegistryApiService:fetchConfig', - ] as never[], - events: [ - 'KeyringController:unlock', - 'KeyringController:lock', - ] as never[], - }); + it('should return a polling token string when called without input', () => { + return withController(({ controller }) => { + const token = controller.startPolling(null); + expect(typeof token).toBe('string'); + expect(token.length).toBeGreaterThan(0); - const controller = new ConfigRegistryController({ - messenger: testMessenger, - fallbackConfig: MOCK_FALLBACK_CONFIG, + controller.stopPolling(); }); + }); - await controller._executePoll(null); + it('should delay first poll when lastFetched is recent', async () => { + const pollingInterval = 10000; + const recentTimestamp = Date.now() - 2000; + const remainingTime = pollingInterval - 2000; + return withController( + { + options: { + pollingInterval, + state: { + lastFetched: recentTimestamp, + }, + }, + }, + async ({ controller, clock }) => { + const executePollSpy = jest.spyOn(controller, '_executePoll'); + controller.startPolling(null); - expect(captureExceptionSpy).toHaveBeenCalledWith( - expect.objectContaining({ message: 'String error' }), + await advanceTime({ clock, duration: 0 }); + expect(executePollSpy).not.toHaveBeenCalled(); + + await advanceTime({ clock, duration: remainingTime + 1 }); + expect(executePollSpy).toHaveBeenCalledTimes(1); + + controller.stopPolling(); + }, ); - expect(controller.state.configs).toStrictEqual({ - networks: MOCK_FALLBACK_CONFIG, - }); - expect(controller.state.fetchError).toBe('Unknown error occurred'); }); - it('should handle error when state.configs is null', async () => { - mockRemoteFeatureFlagGetState.mockReturnValue({ - remoteFeatureFlags: { - configRegistryApiEnabled: true, + it('should proceed immediately when lastFetched is null', async () => { + return withController( + { + options: { + state: { + lastFetched: null, + }, + }, }, - cacheTimestamp: Date.now(), - }); + async ({ controller, clock }) => { + const executePollSpy = jest.spyOn(controller, '_executePoll'); + controller.startPolling(null); - mockApiServiceHandler.mockRejectedValue(new Error('Network error')); - - const captureExceptionSpy = jest.fn(); - const testRootMessenger = new Messenger< - MockAnyNamespace, - | { - type: 'RemoteFeatureFlagController:getState'; - handler: () => unknown; - } - | { - type: 'KeyringController:getState'; - handler: () => { isUnlocked: boolean }; - } - | { - type: 'ConfigRegistryApiService:fetchConfig'; - handler: (options?: { - etag?: string; - }) => Promise; - }, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] } - >({ - namespace: MOCK_ANY_NAMESPACE, - captureException: captureExceptionSpy, - }); + await advanceTime({ clock, duration: 0 }); + expect(executePollSpy).toHaveBeenCalledTimes(1); - const testMessenger = new Messenger< - typeof namespace, - never, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] }, - typeof testRootMessenger - >({ - namespace, - parent: testRootMessenger, - }) as ConfigRegistryMessenger; - - testRootMessenger.registerActionHandler( - 'ConfigRegistryApiService:fetchConfig', - mockApiServiceHandler, - ); - testRootMessenger.registerActionHandler( - 'RemoteFeatureFlagController:getState', - mockRemoteFeatureFlagGetState, - ); - testRootMessenger.registerActionHandler( - 'KeyringController:getState', - mockKeyringControllerGetState, + controller.stopPolling(); + }, ); - testRootMessenger.delegate({ - messenger: testMessenger, - actions: [ - 'RemoteFeatureFlagController:getState', - 'KeyringController:getState', - 'ConfigRegistryApiService:fetchConfig', - ] as never[], - events: [ - 'KeyringController:unlock', - 'KeyringController:lock', - ] as never[], - }); + }); - const controller = new ConfigRegistryController({ - messenger: testMessenger, - fallbackConfig: MOCK_FALLBACK_CONFIG, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - state: { configs: null as any }, - }); + it('should proceed immediately when lastFetched is old enough', async () => { + const pollingInterval = 10000; + const now = Date.now(); + const oldTimestamp = now - pollingInterval - 1000; + return withController( + { + options: { + pollingInterval, + state: { + lastFetched: oldTimestamp, + }, + }, + }, + async ({ controller, clock }) => { + jest.spyOn(Date, 'now').mockReturnValue(now); + const executePollSpy = jest.spyOn(controller, '_executePoll'); + controller.startPolling(null); - await controller._executePoll(null); + await advanceTime({ clock, duration: 1 }); + expect(executePollSpy).toHaveBeenCalledTimes(1); - expect(captureExceptionSpy).toHaveBeenCalledWith( - expect.objectContaining({ message: 'Network error' }), + controller.stopPolling(); + jest.restoreAllMocks(); + }, ); - expect(controller.state.configs).toStrictEqual({ - networks: MOCK_FALLBACK_CONFIG, - }); - expect(controller.state.fetchError).toBe('Network error'); }); - it('should work via messenger actions', async () => { - const controller = new ConfigRegistryController({ - messenger, - }); + it('should proceed immediately when lastFetched is exactly at polling interval', async () => { + const pollingInterval = 10000; + const now = Date.now(); + const exactTimestamp = now - pollingInterval - 1; + return withController( + { + options: { + pollingInterval, + state: { + lastFetched: exactTimestamp, + }, + }, + }, + async ({ controller, clock }) => { + jest.spyOn(Date, 'now').mockReturnValue(now); + const executePollSpy = jest.spyOn(controller, '_executePoll'); + controller.startPolling(null); - const executePollSpy = jest.spyOn(controller, '_executePoll'); + await advanceTime({ clock, duration: 1 }); + expect(executePollSpy).toHaveBeenCalledTimes(1); - const token = messenger.call( - 'ConfigRegistryController:startPolling', - null, + controller.stopPolling(); + jest.restoreAllMocks(); + }, ); - expect(typeof token).toBe('string'); + }); - await advanceTime({ clock, duration: 0 }); - expect(executePollSpy).toHaveBeenCalledTimes(1); + it('should use DEFAULT_POLLING_INTERVAL when getIntervalLength returns undefined', async () => { + const recentTimestamp = Date.now() - 1000; + return withController( + { + options: { + state: { + lastFetched: recentTimestamp, + }, + }, + }, + async ({ controller, clock }) => { + jest.spyOn(controller, 'getIntervalLength').mockReturnValue(undefined); - messenger.call('ConfigRegistryController:stopPolling'); - await advanceTime({ clock, duration: DEFAULT_POLLING_INTERVAL }); - expect(executePollSpy).toHaveBeenCalledTimes(1); - }); - }); + const executePollSpy = jest.spyOn(controller, '_executePoll'); + controller.startPolling(null); - describe('state persistence', () => { - it('should persist version', () => { - const controller = new ConfigRegistryController({ - messenger, - state: { version: 'v1.0.0' }, - }); + await advanceTime({ clock, duration: 0 }); + expect(executePollSpy).not.toHaveBeenCalled(); - expect(controller.state.version).toBe('v1.0.0'); + controller.stopPolling(); + }, + ); }); - it('should persist lastFetched', () => { - const timestamp = Date.now(); - const controller = new ConfigRegistryController({ - messenger, - state: { lastFetched: timestamp }, - }); - - expect(controller.state.lastFetched).toBe(timestamp); + it('should clear existing timeout when startPolling is called multiple times', async () => { + const pollingInterval = 10000; + const recentTimestamp = Date.now() - 2000; + return withController( + { + options: { + pollingInterval, + state: { + lastFetched: recentTimestamp, + }, + }, + }, + async ({ controller, clock }) => { + const executePollSpy = jest.spyOn(controller, '_executePoll'); + const clearTimeoutSpy = jest.spyOn(global, 'clearTimeout'); + + // First call sets a timeout + controller.startPolling(null); + await advanceTime({ clock, duration: 0 }); + expect(executePollSpy).not.toHaveBeenCalled(); + + const clearTimeoutCallCountBefore = clearTimeoutSpy.mock.calls.length; + + // Second call should clear the existing timeout (from first call) and set a new one + // This tests the defensive check that clears any existing timeout + controller.startPolling(null); + await advanceTime({ clock, duration: 0 }); + expect(executePollSpy).not.toHaveBeenCalled(); + + // Verify clearTimeout was called to clear the previous timeout + expect(clearTimeoutSpy.mock.calls.length).toBeGreaterThan(clearTimeoutCallCountBefore); + + controller.stopPolling(); + }, + ); }); + }); - it('should persist fetchError', () => { - const controller = new ConfigRegistryController({ - messenger, - state: { fetchError: 'Test error' }, - }); + describe('feature flag', () => { + it('should use fallback config when feature flag is disabled', async () => { + return withController( + { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, + async ({ controller, clock, mockRemoteFeatureFlagGetState }) => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: false, + }, + cacheTimestamp: Date.now(), + }); - expect(controller.state.fetchError).toBe('Test error'); - }); + const executePollSpy = jest.spyOn(controller, '_executePoll'); + controller.startPolling(null); - it('should use default error message when useFallbackConfig is called without errorMessage', () => { - const controller = new ConfigRegistryController({ - messenger, - fallbackConfig: MOCK_FALLBACK_CONFIG, - }); + await advanceTime({ clock, duration: 0 }); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (controller as any).useFallbackConfig(); + expect(executePollSpy).toHaveBeenCalledTimes(1); + expect(controller.state.configs).toStrictEqual({ + networks: MOCK_FALLBACK_CONFIG, + }); + expect(controller.state.fetchError).toBe( + 'Feature flag disabled - using fallback configuration', + ); - expect(controller.state.configs).toStrictEqual({ - networks: MOCK_FALLBACK_CONFIG, - }); - expect(controller.state.fetchError).toBe( - 'Using fallback configuration - API unavailable', + controller.stopPolling(); + }, ); - expect(controller.state.etag).toBeNull(); }); - }); - describe('startPolling', () => { - it('should return a polling token string', () => { - const controller = new ConfigRegistryController({ - messenger, - }); + it('should use API when feature flag is enabled', async () => { + return withController( + async ({ controller, mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); - const token = controller.startPolling(null); - expect(typeof token).toBe('string'); - expect(token.length).toBeGreaterThan(0); + const mockNetworks = [ + { + chainId: '0x1', + name: 'Ethereum Mainnet', + nativeCurrency: 'ETH', + rpcEndpoints: [ + { + url: 'https://mainnet.infura.io/v3/{infuraProjectId}', + type: 'infura', + networkClientId: 'mainnet', + failoverUrls: [], + }, + ], + blockExplorerUrls: ['https://etherscan.io'], + defaultRpcEndpointIndex: 0, + defaultBlockExplorerUrlIndex: 0, + isTestnet: false, + isFeatured: true, + isActive: true, + isDefault: false, + isDeprecated: false, + priority: 0, + isDeletable: false, + }, + ]; + + const fetchConfigSpy = jest.fn().mockResolvedValue({ + data: { + data: { + version: '1.0.0', + timestamp: Date.now(), + networks: mockNetworks, + }, + }, + modified: true, + etag: 'test-etag', + }); - controller.stopPolling(); - }); + mockApiServiceHandler.mockImplementation(fetchConfigSpy); - it('should return a polling token string when called without input', () => { - const controller = new ConfigRegistryController({ - messenger, - }); + await controller._executePoll(null); - const token = controller.startPolling(null); - expect(typeof token).toBe('string'); - expect(token.length).toBeGreaterThan(0); + expect(fetchConfigSpy).toHaveBeenCalled(); + expect(controller.state.configs.networks?.['0x1']).toBeDefined(); + expect(controller.state.version).toBe('1.0.0'); + expect(controller.state.fetchError).toBeNull(); - controller.stopPolling(); + controller.stopPolling(); + }, + ); }); - }); - describe('feature flag', () => { - it('should use fallback config when feature flag is disabled', async () => { - mockRemoteFeatureFlagGetState.mockReturnValue({ - remoteFeatureFlags: { - configRegistryApiEnabled: false, - }, - cacheTimestamp: Date.now(), - }); + it('should filter networks to only include featured, active, non-testnet networks', async () => { + return withController( + async ({ controller, mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); - const controller = new ConfigRegistryController({ - messenger, - fallbackConfig: MOCK_FALLBACK_CONFIG, - }); + const mockNetworks = [ + { + chainId: '0x1', + name: 'Ethereum Mainnet', + nativeCurrency: 'ETH', + rpcEndpoints: [ + { + url: 'https://mainnet.infura.io/v3/{infuraProjectId}', + type: 'infura', + networkClientId: 'mainnet', + failoverUrls: [], + }, + ], + blockExplorerUrls: ['https://etherscan.io'], + defaultRpcEndpointIndex: 0, + defaultBlockExplorerUrlIndex: 0, + isTestnet: false, + isFeatured: true, + isActive: true, + isDefault: false, + isDeprecated: false, + priority: 0, + isDeletable: false, + }, + { + chainId: '0x5', + name: 'Goerli', + nativeCurrency: 'ETH', + rpcEndpoints: [ + { + url: 'https://goerli.infura.io/v3/{infuraProjectId}', + type: 'infura', + networkClientId: 'goerli', + failoverUrls: [], + }, + ], + blockExplorerUrls: ['https://goerli.etherscan.io'], + defaultRpcEndpointIndex: 0, + defaultBlockExplorerUrlIndex: 0, + isTestnet: true, + isFeatured: true, + isActive: true, + isDefault: false, + isDeprecated: false, + priority: 0, + isDeletable: false, + }, + { + chainId: '0xa', + name: 'Optimism', + nativeCurrency: 'ETH', + rpcEndpoints: [ + { + url: 'https://optimism.infura.io/v3/{infuraProjectId}', + type: 'infura', + networkClientId: 'optimism', + failoverUrls: [], + }, + ], + blockExplorerUrls: ['https://optimistic.etherscan.io'], + defaultRpcEndpointIndex: 0, + defaultBlockExplorerUrlIndex: 0, + isTestnet: false, + isFeatured: false, + isActive: true, + isDefault: false, + isDeprecated: false, + priority: 0, + isDeletable: false, + }, + { + chainId: '0x89', + name: 'Polygon', + nativeCurrency: 'MATIC', + rpcEndpoints: [ + { + url: 'https://polygon.infura.io/v3/{infuraProjectId}', + type: 'infura', + networkClientId: 'polygon', + failoverUrls: [], + }, + ], + blockExplorerUrls: ['https://polygonscan.com'], + defaultRpcEndpointIndex: 0, + defaultBlockExplorerUrlIndex: 0, + isTestnet: false, + isFeatured: true, + isActive: false, + isDefault: false, + isDeprecated: false, + priority: 0, + isDeletable: false, + }, + ]; + + const fetchConfigSpy = jest.fn().mockResolvedValue({ + data: { + data: { + version: '1.0.0', + timestamp: Date.now(), + networks: mockNetworks, + }, + }, + modified: true, + etag: 'test-etag', + }); - const executePollSpy = jest.spyOn(controller, '_executePoll'); - controller.startPolling(null); + mockApiServiceHandler.mockImplementation(fetchConfigSpy); - await advanceTime({ clock, duration: 0 }); + await controller._executePoll(null); - expect(executePollSpy).toHaveBeenCalledTimes(1); - expect(controller.state.configs).toStrictEqual({ - networks: MOCK_FALLBACK_CONFIG, - }); - expect(controller.state.fetchError).toBe( - 'Feature flag disabled - using fallback configuration', + expect(controller.state.configs.networks?.['0x1']).toBeDefined(); + expect(controller.state.configs.networks?.['0x5']).toBeUndefined(); + expect(controller.state.configs.networks?.['0xa']).toBeUndefined(); + expect(controller.state.configs.networks?.['0x89']).toBeUndefined(); + expect(Object.keys(controller.state.configs.networks ?? {})).toHaveLength( + 1, + ); + }, ); - - controller.stopPolling(); }); - it('should use API when feature flag is enabled', async () => { - mockRemoteFeatureFlagGetState.mockReturnValue({ - remoteFeatureFlags: { - configRegistryApiEnabled: true, + it('should handle duplicate chainIds by keeping highest priority network and logging warning', async () => { + return withController( + async ({ mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); + + const captureExceptionSpy = jest.fn(); + const testRootMessenger = new Messenger< + MockAnyNamespace, + | { + type: 'RemoteFeatureFlagController:getState'; + handler: () => unknown; + } + | { + type: 'KeyringController:getState'; + handler: () => { isUnlocked: boolean }; + } + | { + type: 'ConfigRegistryApiService:fetchConfig'; + handler: (options?: { + etag?: string; + }) => Promise; + }, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] } + >({ + namespace: MOCK_ANY_NAMESPACE, + captureException: captureExceptionSpy, + }); + + const testMessenger = new Messenger< + typeof namespace, + never, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] }, + typeof testRootMessenger + >({ + namespace, + parent: testRootMessenger, + }) as ConfigRegistryMessenger; + + testRootMessenger.registerActionHandler( + 'ConfigRegistryApiService:fetchConfig', + mockApiServiceHandler, + ); + testRootMessenger.registerActionHandler( + 'RemoteFeatureFlagController:getState', + mockRemoteFeatureFlagGetState, + ); + testRootMessenger.registerActionHandler( + 'KeyringController:getState', + jest.fn().mockReturnValue({ isUnlocked: false }), + ); + testRootMessenger.delegate({ + messenger: testMessenger, + actions: [ + 'RemoteFeatureFlagController:getState', + 'KeyringController:getState', + 'ConfigRegistryApiService:fetchConfig', + ] as never[], + events: [ + 'KeyringController:unlock', + 'KeyringController:lock', + ] as never[], + }); + + const testController = new ConfigRegistryController({ + messenger: testMessenger, + }); + + // Mock API response with duplicate chainIds + const mockNetworks = [ + { + chainId: '0x1', + name: 'Ethereum Mainnet (Low Priority)', + nativeCurrency: 'ETH', + rpcEndpoints: [ + { + url: 'https://mainnet.infura.io/v3/{infuraProjectId}', + type: 'infura', + networkClientId: 'mainnet', + failoverUrls: [], + }, + ], + blockExplorerUrls: ['https://etherscan.io'], + defaultRpcEndpointIndex: 0, + defaultBlockExplorerUrlIndex: 0, + isTestnet: false, + isFeatured: true, + isActive: true, + isDefault: false, + isDeprecated: false, + priority: 10, // Lower priority (higher number) + isDeletable: false, + }, + { + chainId: '0x1', + name: 'Ethereum Mainnet (High Priority)', + nativeCurrency: 'ETH', + rpcEndpoints: [ + { + url: 'https://mainnet.alchemy.io/v2/{alchemyApiKey}', + type: 'alchemy', + networkClientId: 'mainnet-alchemy', + failoverUrls: [], + }, + ], + blockExplorerUrls: ['https://etherscan.io'], + defaultRpcEndpointIndex: 0, + defaultBlockExplorerUrlIndex: 0, + isTestnet: false, + isFeatured: true, + isActive: true, + isDefault: false, + isDeprecated: false, + priority: 0, // Higher priority (lower number) + isDeletable: false, + }, + { + chainId: '0x89', + name: 'Polygon', + nativeCurrency: 'MATIC', + rpcEndpoints: [ + { + url: 'https://polygon.infura.io/v3/{infuraProjectId}', + type: 'infura', + networkClientId: 'polygon', + failoverUrls: [], + }, + ], + blockExplorerUrls: ['https://polygonscan.com'], + defaultRpcEndpointIndex: 0, + defaultBlockExplorerUrlIndex: 0, + isTestnet: false, + isFeatured: true, + isActive: true, + isDefault: false, + isDeprecated: false, + priority: 0, + isDeletable: false, + }, + ]; + + mockApiServiceHandler.mockResolvedValue({ + data: { + data: { + version: '1.0.0', + timestamp: Date.now(), + networks: mockNetworks, + }, + }, + modified: true, + etag: 'test-etag', + }); + + await testController._executePoll(null); + + // Verify warning was logged + expect(captureExceptionSpy).toHaveBeenCalled(); + const warningCall = captureExceptionSpy.mock.calls.find((call) => + call[0]?.message?.includes('Duplicate chainId 0x1'), + ); + expect(warningCall).toBeDefined(); + expect(warningCall?.[0]?.message).toContain( + 'Ethereum Mainnet (Low Priority), Ethereum Mainnet (High Priority)', + ); + + // Verify highest priority network was kept + expect(testController.state.configs.networks?.['0x1']).toBeDefined(); + expect(testController.state.configs.networks?.['0x1']?.value.name).toBe( + 'Ethereum Mainnet (High Priority)', + ); + expect( + testController.state.configs.networks?.['0x1']?.value.rpcEndpoints[0] + .type, + ).toBe('alchemy'); + + // Verify other networks are still present + expect(testController.state.configs.networks?.['0x89']).toBeDefined(); }, - cacheTimestamp: Date.now(), - }); + ); + }); - const mockNetworks = [ - { - chainId: '0x1', - name: 'Ethereum Mainnet', - nativeCurrency: 'ETH', - rpcEndpoints: [ + it('should handle duplicate chainIds with same priority by keeping first occurrence', async () => { + return withController( + async ({ mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); + + const captureExceptionSpy = jest.fn(); + const testRootMessenger = new Messenger< + MockAnyNamespace, + | { + type: 'RemoteFeatureFlagController:getState'; + handler: () => unknown; + } + | { + type: 'KeyringController:getState'; + handler: () => { isUnlocked: boolean }; + } + | { + type: 'ConfigRegistryApiService:fetchConfig'; + handler: (options?: { + etag?: string; + }) => Promise; + }, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] } + >({ + namespace: MOCK_ANY_NAMESPACE, + captureException: captureExceptionSpy, + }); + + const testMessenger = new Messenger< + typeof namespace, + never, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] }, + typeof testRootMessenger + >({ + namespace, + parent: testRootMessenger, + }) as ConfigRegistryMessenger; + + testRootMessenger.registerActionHandler( + 'ConfigRegistryApiService:fetchConfig', + mockApiServiceHandler, + ); + testRootMessenger.registerActionHandler( + 'RemoteFeatureFlagController:getState', + mockRemoteFeatureFlagGetState, + ); + testRootMessenger.registerActionHandler( + 'KeyringController:getState', + jest.fn().mockReturnValue({ isUnlocked: false }), + ); + testRootMessenger.delegate({ + messenger: testMessenger, + actions: [ + 'RemoteFeatureFlagController:getState', + 'KeyringController:getState', + 'ConfigRegistryApiService:fetchConfig', + ] as never[], + events: [ + 'KeyringController:unlock', + 'KeyringController:lock', + ] as never[], + }); + + const testController = new ConfigRegistryController({ + messenger: testMessenger, + }); + + // Mock API response with duplicate chainIds having same priority + const mockNetworks = [ { - url: 'https://mainnet.infura.io/v3/{infuraProjectId}', - type: 'infura', - networkClientId: 'mainnet', - failoverUrls: [], - }, - ], - blockExplorerUrls: ['https://etherscan.io'], - defaultRpcEndpointIndex: 0, - defaultBlockExplorerUrlIndex: 0, - isTestnet: false, - isFeatured: true, - isActive: true, - isDefault: false, - isDeprecated: false, - priority: 0, - isDeletable: false, - }, - ]; - - const fetchConfigSpy = jest.fn().mockResolvedValue({ - data: { - data: { - version: '1.0.0', - timestamp: Date.now(), - networks: mockNetworks, - }, + chainId: '0x1', + name: 'Ethereum Mainnet (First)', + nativeCurrency: 'ETH', + rpcEndpoints: [ + { + url: 'https://mainnet.infura.io/v3/{infuraProjectId}', + type: 'infura', + networkClientId: 'mainnet', + failoverUrls: [], + }, + ], + blockExplorerUrls: ['https://etherscan.io'], + defaultRpcEndpointIndex: 0, + defaultBlockExplorerUrlIndex: 0, + isTestnet: false, + isFeatured: true, + isActive: true, + isDefault: false, + isDeprecated: false, + priority: 5, // Same priority + isDeletable: false, + }, + { + chainId: '0x1', + name: 'Ethereum Mainnet (Second)', + nativeCurrency: 'ETH', + rpcEndpoints: [ + { + url: 'https://mainnet.alchemy.io/v2/{alchemyApiKey}', + type: 'alchemy', + networkClientId: 'mainnet-alchemy', + failoverUrls: [], + }, + ], + blockExplorerUrls: ['https://etherscan.io'], + defaultRpcEndpointIndex: 0, + defaultBlockExplorerUrlIndex: 0, + isTestnet: false, + isFeatured: true, + isActive: true, + isDefault: false, + isDeprecated: false, + priority: 5, // Same priority + isDeletable: false, + }, + ]; + + mockApiServiceHandler.mockResolvedValue({ + data: { + data: { + version: '1.0.0', + timestamp: Date.now(), + networks: mockNetworks, + }, + }, + modified: true, + etag: 'test-etag', + }); + + await testController._executePoll(null); + + // Verify warning was logged + expect(captureExceptionSpy).toHaveBeenCalled(); + const warningCall = captureExceptionSpy.mock.calls.find((call) => + call[0]?.message?.includes('Duplicate chainId 0x1'), + ); + expect(warningCall).toBeDefined(); + + // Verify first occurrence was kept (since priorities are equal) + expect(testController.state.configs.networks?.['0x1']).toBeDefined(); + expect(testController.state.configs.networks?.['0x1']?.value.name).toBe( + 'Ethereum Mainnet (First)', + ); }, - notModified: false, - etag: 'test-etag', - }); - - mockApiServiceHandler.mockImplementation(fetchConfigSpy); - - const controller = new ConfigRegistryController({ - messenger, - }); - - const executePollPromise = controller._executePoll(null); - await executePollPromise; - - expect(fetchConfigSpy).toHaveBeenCalled(); - expect(controller.state.configs.networks?.['0x1']).toBeDefined(); - expect(controller.state.version).toBe('1.0.0'); - expect(controller.state.fetchError).toBeNull(); - - controller.stopPolling(); + ); }); - it('should filter networks to only include featured, active, non-testnet networks', async () => { - mockRemoteFeatureFlagGetState.mockReturnValue({ - remoteFeatureFlags: { - configRegistryApiEnabled: true, + it('should handle duplicate chainIds by keeping highest priority network and logging warning', async () => { + return withController( + async ({ controller, mockRemoteFeatureFlagGetState, mockApiServiceHandler, rootMessenger }) => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); + + const captureExceptionSpy = jest.fn(); + const testRootMessenger = new Messenger< + MockAnyNamespace, + | { + type: 'RemoteFeatureFlagController:getState'; + handler: () => unknown; + } + | { + type: 'KeyringController:getState'; + handler: () => { isUnlocked: boolean }; + } + | { + type: 'ConfigRegistryApiService:fetchConfig'; + handler: (options?: { + etag?: string; + }) => Promise; + }, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] } + >({ + namespace: MOCK_ANY_NAMESPACE, + captureException: captureExceptionSpy, + }); + + const testMessenger = new Messenger< + typeof namespace, + never, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] }, + typeof testRootMessenger + >({ + namespace, + parent: testRootMessenger, + }) as ConfigRegistryMessenger; + + testRootMessenger.registerActionHandler( + 'ConfigRegistryApiService:fetchConfig', + mockApiServiceHandler, + ); + testRootMessenger.registerActionHandler( + 'RemoteFeatureFlagController:getState', + mockRemoteFeatureFlagGetState, + ); + testRootMessenger.registerActionHandler( + 'KeyringController:getState', + jest.fn().mockReturnValue({ isUnlocked: false }), + ); + testRootMessenger.delegate({ + messenger: testMessenger, + actions: [ + 'RemoteFeatureFlagController:getState', + 'KeyringController:getState', + 'ConfigRegistryApiService:fetchConfig', + ] as never[], + events: [ + 'KeyringController:unlock', + 'KeyringController:lock', + ] as never[], + }); + + const testController = new ConfigRegistryController({ + messenger: testMessenger, + }); + + // Mock API response with duplicate chainIds + const mockNetworks = [ + { + chainId: '0x1', + name: 'Ethereum Mainnet (Low Priority)', + nativeCurrency: 'ETH', + rpcEndpoints: [ + { + url: 'https://mainnet.infura.io/v3/{infuraProjectId}', + type: 'infura', + networkClientId: 'mainnet', + failoverUrls: [], + }, + ], + blockExplorerUrls: ['https://etherscan.io'], + defaultRpcEndpointIndex: 0, + defaultBlockExplorerUrlIndex: 0, + isTestnet: false, + isFeatured: true, + isActive: true, + isDefault: false, + isDeprecated: false, + priority: 10, // Lower priority (higher number) + isDeletable: false, + }, + { + chainId: '0x1', + name: 'Ethereum Mainnet (High Priority)', + nativeCurrency: 'ETH', + rpcEndpoints: [ + { + url: 'https://mainnet.alchemy.io/v2/{alchemyApiKey}', + type: 'alchemy', + networkClientId: 'mainnet-alchemy', + failoverUrls: [], + }, + ], + blockExplorerUrls: ['https://etherscan.io'], + defaultRpcEndpointIndex: 0, + defaultBlockExplorerUrlIndex: 0, + isTestnet: false, + isFeatured: true, + isActive: true, + isDefault: false, + isDeprecated: false, + priority: 0, // Higher priority (lower number) + isDeletable: false, + }, + { + chainId: '0x89', + name: 'Polygon', + nativeCurrency: 'MATIC', + rpcEndpoints: [ + { + url: 'https://polygon.infura.io/v3/{infuraProjectId}', + type: 'infura', + networkClientId: 'polygon', + failoverUrls: [], + }, + ], + blockExplorerUrls: ['https://polygonscan.com'], + defaultRpcEndpointIndex: 0, + defaultBlockExplorerUrlIndex: 0, + isTestnet: false, + isFeatured: true, + isActive: true, + isDefault: false, + isDeprecated: false, + priority: 0, + isDeletable: false, + }, + ]; + + mockApiServiceHandler.mockResolvedValue({ + data: { + data: { + version: '1.0.0', + timestamp: Date.now(), + networks: mockNetworks, + }, + }, + modified: true, + etag: 'test-etag', + }); + + await testController._executePoll(null); + + // Verify warning was logged + expect(captureExceptionSpy).toHaveBeenCalled(); + const warningCall = captureExceptionSpy.mock.calls.find((call) => + call[0]?.message?.includes('Duplicate chainId 0x1'), + ); + expect(warningCall).toBeDefined(); + expect(warningCall?.[0]?.message).toContain( + 'Ethereum Mainnet (Low Priority), Ethereum Mainnet (High Priority)', + ); + + // Verify highest priority network was kept + expect(testController.state.configs.networks?.['0x1']).toBeDefined(); + expect(testController.state.configs.networks?.['0x1']?.value.name).toBe( + 'Ethereum Mainnet (High Priority)', + ); + expect( + testController.state.configs.networks?.['0x1']?.value.rpcEndpoints[0] + .type, + ).toBe('alchemy'); + + // Verify other networks are still present + expect(testController.state.configs.networks?.['0x89']).toBeDefined(); }, - cacheTimestamp: Date.now(), - }); + ); + }); - const mockNetworks = [ - { - chainId: '0x1', - name: 'Ethereum Mainnet', - nativeCurrency: 'ETH', - rpcEndpoints: [ + it('should handle duplicate chainIds with same priority by keeping first occurrence', async () => { + return withController( + async ({ controller, mockRemoteFeatureFlagGetState, mockApiServiceHandler, rootMessenger }) => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }); + + const captureExceptionSpy = jest.fn(); + const testRootMessenger = new Messenger< + MockAnyNamespace, + | { + type: 'RemoteFeatureFlagController:getState'; + handler: () => unknown; + } + | { + type: 'KeyringController:getState'; + handler: () => { isUnlocked: boolean }; + } + | { + type: 'ConfigRegistryApiService:fetchConfig'; + handler: (options?: { + etag?: string; + }) => Promise; + }, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] } + >({ + namespace: MOCK_ANY_NAMESPACE, + captureException: captureExceptionSpy, + }); + + const testMessenger = new Messenger< + typeof namespace, + never, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] }, + typeof testRootMessenger + >({ + namespace, + parent: testRootMessenger, + }) as ConfigRegistryMessenger; + + testRootMessenger.registerActionHandler( + 'ConfigRegistryApiService:fetchConfig', + mockApiServiceHandler, + ); + testRootMessenger.registerActionHandler( + 'RemoteFeatureFlagController:getState', + mockRemoteFeatureFlagGetState, + ); + testRootMessenger.registerActionHandler( + 'KeyringController:getState', + jest.fn().mockReturnValue({ isUnlocked: false }), + ); + testRootMessenger.delegate({ + messenger: testMessenger, + actions: [ + 'RemoteFeatureFlagController:getState', + 'KeyringController:getState', + 'ConfigRegistryApiService:fetchConfig', + ] as never[], + events: [ + 'KeyringController:unlock', + 'KeyringController:lock', + ] as never[], + }); + + const testController = new ConfigRegistryController({ + messenger: testMessenger, + }); + + // Mock API response with duplicate chainIds having same priority + const mockNetworks = [ { - url: 'https://mainnet.infura.io/v3/{infuraProjectId}', - type: 'infura', - networkClientId: 'mainnet', - failoverUrls: [], - }, - ], - blockExplorerUrls: ['https://etherscan.io'], - defaultRpcEndpointIndex: 0, - defaultBlockExplorerUrlIndex: 0, - isTestnet: false, - isFeatured: true, - isActive: true, - isDefault: false, - isDeprecated: false, - priority: 0, - isDeletable: false, - }, - { - chainId: '0x5', - name: 'Goerli', - nativeCurrency: 'ETH', - rpcEndpoints: [ + chainId: '0x1', + name: 'Ethereum Mainnet (First)', + nativeCurrency: 'ETH', + rpcEndpoints: [ + { + url: 'https://mainnet.infura.io/v3/{infuraProjectId}', + type: 'infura', + networkClientId: 'mainnet', + failoverUrls: [], + }, + ], + blockExplorerUrls: ['https://etherscan.io'], + defaultRpcEndpointIndex: 0, + defaultBlockExplorerUrlIndex: 0, + isTestnet: false, + isFeatured: true, + isActive: true, + isDefault: false, + isDeprecated: false, + priority: 5, // Same priority + isDeletable: false, + }, { - url: 'https://goerli.infura.io/v3/{infuraProjectId}', - type: 'infura', - networkClientId: 'goerli', - failoverUrls: [], - }, - ], - blockExplorerUrls: ['https://goerli.etherscan.io'], - defaultRpcEndpointIndex: 0, - defaultBlockExplorerUrlIndex: 0, - isTestnet: true, - isFeatured: true, - isActive: true, - isDefault: false, - isDeprecated: false, - priority: 0, - isDeletable: false, + chainId: '0x1', + name: 'Ethereum Mainnet (Second)', + nativeCurrency: 'ETH', + rpcEndpoints: [ + { + url: 'https://mainnet.alchemy.io/v2/{alchemyApiKey}', + type: 'alchemy', + networkClientId: 'mainnet-alchemy', + failoverUrls: [], + }, + ], + blockExplorerUrls: ['https://etherscan.io'], + defaultRpcEndpointIndex: 0, + defaultBlockExplorerUrlIndex: 0, + isTestnet: false, + isFeatured: true, + isActive: true, + isDefault: false, + isDeprecated: false, + priority: 5, // Same priority + isDeletable: false, + }, + ]; + + mockApiServiceHandler.mockResolvedValue({ + data: { + data: { + version: '1.0.0', + timestamp: Date.now(), + networks: mockNetworks, + }, + }, + modified: true, + etag: 'test-etag', + }); + + await testController._executePoll(null); + + // Verify warning was logged + expect(captureExceptionSpy).toHaveBeenCalled(); + const warningCall = captureExceptionSpy.mock.calls.find((call) => + call[0]?.message?.includes('Duplicate chainId 0x1'), + ); + expect(warningCall).toBeDefined(); + + // Verify first occurrence was kept (since priorities are equal) + expect(testController.state.configs.networks?.['0x1']).toBeDefined(); + expect(testController.state.configs.networks?.['0x1']?.value.name).toBe( + 'Ethereum Mainnet (First)', + ); }, + ); + }); + + it('should use custom isConfigRegistryApiEnabled function when provided', async () => { + const customIsEnabled = jest.fn().mockReturnValue(true); + return withController( { - chainId: '0xa', - name: 'Optimism', - nativeCurrency: 'ETH', - rpcEndpoints: [ + options: { + isConfigRegistryApiEnabled: customIsEnabled, + }, + }, + async ({ controller, messenger, mockApiServiceHandler }) => { + const mockNetworks = [ { - url: 'https://optimism.infura.io/v3/{infuraProjectId}', - type: 'infura', - networkClientId: 'optimism', - failoverUrls: [], - }, - ], - blockExplorerUrls: ['https://optimistic.etherscan.io'], - defaultRpcEndpointIndex: 0, - defaultBlockExplorerUrlIndex: 0, - isTestnet: false, - isFeatured: false, - isActive: true, - isDefault: false, - isDeprecated: false, - priority: 0, - isDeletable: false, + chainId: '0x1', + name: 'Ethereum Mainnet', + nativeCurrency: 'ETH', + rpcEndpoints: [ + { + url: 'https://mainnet.infura.io/v3/{infuraProjectId}', + type: 'infura', + networkClientId: 'mainnet', + failoverUrls: [], + }, + ], + blockExplorerUrls: ['https://etherscan.io'], + defaultRpcEndpointIndex: 0, + defaultBlockExplorerUrlIndex: 0, + isTestnet: false, + isFeatured: true, + isActive: true, + isDefault: false, + isDeprecated: false, + priority: 0, + isDeletable: false, + }, + ]; + + mockApiServiceHandler.mockResolvedValue({ + data: { + data: { + version: '1.0.0', + timestamp: Date.now(), + networks: mockNetworks, + }, + }, + modified: true, + etag: 'test-etag', + }); + + await controller._executePoll(null); + + expect(customIsEnabled).toHaveBeenCalledWith(messenger); + expect(mockApiServiceHandler).toHaveBeenCalled(); + expect(controller.state.configs.networks?.['0x1']).toBeDefined(); + expect(controller.state.version).toBe('1.0.0'); }, + ); + }); + + it('should use custom isConfigRegistryApiEnabled function returning false', async () => { + const customIsEnabled = jest.fn().mockReturnValue(false); + return withController( { - chainId: '0x89', - name: 'Polygon', - nativeCurrency: 'MATIC', - rpcEndpoints: [ - { - url: 'https://polygon.infura.io/v3/{infuraProjectId}', - type: 'infura', - networkClientId: 'polygon', - failoverUrls: [], - }, - ], - blockExplorerUrls: ['https://polygonscan.com'], - defaultRpcEndpointIndex: 0, - defaultBlockExplorerUrlIndex: 0, - isTestnet: false, - isFeatured: true, - isActive: false, - isDefault: false, - isDeprecated: false, - priority: 0, - isDeletable: false, - }, - ]; - - const fetchConfigSpy = jest.fn().mockResolvedValue({ - data: { - data: { - version: '1.0.0', - timestamp: Date.now(), - networks: mockNetworks, + options: { + fallbackConfig: MOCK_FALLBACK_CONFIG, + isConfigRegistryApiEnabled: customIsEnabled, }, }, - notModified: false, - etag: 'test-etag', + async ({ controller, messenger, mockApiServiceHandler }) => { + await controller._executePoll(null); + + expect(customIsEnabled).toHaveBeenCalledWith(messenger); + expect(mockApiServiceHandler).not.toHaveBeenCalled(); + expect(controller.state.configs).toStrictEqual({ + networks: MOCK_FALLBACK_CONFIG, + }); + expect(controller.state.fetchError).toBe( + 'Feature flag disabled - using fallback configuration', + ); + }, + ); + }); + + it('should default to fallback when feature flag is not set', async () => { + return withController( + { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, + async ({ + controller, + clock, + mockRemoteFeatureFlagGetState, + }) => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: {}, + cacheTimestamp: Date.now(), + }); + + const executePollSpy = jest.spyOn(controller, '_executePoll'); + controller.startPolling(null); + + await advanceTime({ clock, duration: 0 }); + + expect(executePollSpy).toHaveBeenCalledTimes(1); + expect(controller.state.configs).toStrictEqual({ + networks: MOCK_FALLBACK_CONFIG, + }); + expect(controller.state.fetchError).toBe( + 'Feature flag disabled - using fallback configuration', + ); + + controller.stopPolling(); + }, + ); + }); + + it('should default to fallback when RemoteFeatureFlagController is unavailable', async () => { + return withController( + { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, + async ({ controller, clock, mockRemoteFeatureFlagGetState }) => { + mockRemoteFeatureFlagGetState.mockImplementation(() => { + throw new Error('RemoteFeatureFlagController not available'); + }); + + const executePollSpy = jest.spyOn(controller, '_executePoll'); + controller.startPolling(null); + + await advanceTime({ clock, duration: 0 }); + + expect(executePollSpy).toHaveBeenCalledTimes(1); + expect(controller.state.configs).toStrictEqual({ + networks: MOCK_FALLBACK_CONFIG, + }); + expect(controller.state.fetchError).toBe( + 'Feature flag disabled - using fallback configuration', + ); + + controller.stopPolling(); + }, + ); + }); + }); + + describe('KeyringController event listeners', () => { + it('should start polling when KeyringController is already unlocked on initialization', async () => { + return withController(async ({ clock }) => { + const mockKeyringControllerGetState = jest.fn().mockReturnValue({ + isUnlocked: true, + }); + + const testRootMessenger = new Messenger< + MockAnyNamespace, + | { + type: 'RemoteFeatureFlagController:getState'; + handler: () => unknown; + } + | { + type: 'KeyringController:getState'; + handler: () => { isUnlocked: boolean }; + } + | { + type: 'ConfigRegistryApiService:fetchConfig'; + handler: (options?: { + etag?: string; + }) => Promise; + }, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] } + >({ + namespace: MOCK_ANY_NAMESPACE, + }); + + const testMessenger = new Messenger< + typeof namespace, + never, + | { type: 'KeyringController:unlock'; payload: [] } + | { type: 'KeyringController:lock'; payload: [] }, + typeof testRootMessenger + >({ + namespace, + parent: testRootMessenger, + }) as ConfigRegistryMessenger; + + testRootMessenger.registerActionHandler( + 'ConfigRegistryApiService:fetchConfig', + jest.fn(buildMockApiServiceHandler()), + ); + testRootMessenger.registerActionHandler( + 'RemoteFeatureFlagController:getState', + jest.fn().mockReturnValue({ + remoteFeatureFlags: { + configRegistryApiEnabled: true, + }, + cacheTimestamp: Date.now(), + }), + ); + testRootMessenger.registerActionHandler( + 'KeyringController:getState', + mockKeyringControllerGetState, + ); + testRootMessenger.delegate({ + messenger: testMessenger, + actions: [ + 'RemoteFeatureFlagController:getState', + 'KeyringController:getState', + 'ConfigRegistryApiService:fetchConfig', + ] as never[], + events: [ + 'KeyringController:unlock', + 'KeyringController:lock', + ] as never[], + }); + + const controller = new ConfigRegistryController({ + messenger: testMessenger, + }); + + const executePollSpy = jest.spyOn(controller, '_executePoll'); + + await advanceTime({ clock, duration: 100 }); + + expect(mockKeyringControllerGetState).toHaveBeenCalled(); + expect(executePollSpy).toHaveBeenCalledTimes(1); + + controller.stopPolling(); }); + }); - mockApiServiceHandler.mockImplementation(fetchConfigSpy); + it('should handle KeyringController:getState error gracefully when KeyringController is unavailable', () => { + return withController(({ controller, mockKeyringControllerGetState }) => { + mockKeyringControllerGetState.mockImplementation(() => { + throw new Error('KeyringController not available'); + }); - const controller = new ConfigRegistryController({ - messenger, + expect(controller.state.lastFetched).toBeNull(); }); + }); + + it('should start polling when KeyringController:unlock event is published', async () => { + return withController( + async ({ controller, clock, rootMessenger }) => { + const executePollSpy = jest.spyOn(controller, '_executePoll'); + const startPollingSpy = jest.spyOn(controller, 'startPolling'); + + expect(startPollingSpy).not.toHaveBeenCalled(); + + rootMessenger.publish('KeyringController:unlock'); + + await advanceTime({ clock, duration: 0 }); - await controller._executePoll(null); + expect(startPollingSpy).toHaveBeenCalledWith(null); + expect(executePollSpy).toHaveBeenCalledTimes(1); - expect(controller.state.configs.networks?.['0x1']).toBeDefined(); - expect(controller.state.configs.networks?.['0x5']).toBeUndefined(); - expect(controller.state.configs.networks?.['0xa']).toBeUndefined(); - expect(controller.state.configs.networks?.['0x89']).toBeUndefined(); - expect(Object.keys(controller.state.configs.networks ?? {})).toHaveLength( - 1, + controller.stopPolling(); + }, ); }); - it('should default to fallback when feature flag is not set', async () => { - mockRemoteFeatureFlagGetState.mockReturnValue({ - remoteFeatureFlags: {}, - cacheTimestamp: Date.now(), - }); + it('should stop polling when KeyringController:lock event is published', async () => { + return withController( + async ({ controller, clock, rootMessenger, mockKeyringControllerGetState }) => { + mockKeyringControllerGetState.mockReturnValue({ + isUnlocked: true, + }); - const controller = new ConfigRegistryController({ - messenger, - fallbackConfig: MOCK_FALLBACK_CONFIG, - }); + const stopPollingSpy = jest.spyOn(controller, 'stopPolling'); - const executePollSpy = jest.spyOn(controller, '_executePoll'); - controller.startPolling(null); + await advanceTime({ clock, duration: 0 }); + expect(stopPollingSpy).not.toHaveBeenCalled(); - await advanceTime({ clock, duration: 0 }); + rootMessenger.publish('KeyringController:lock'); - expect(executePollSpy).toHaveBeenCalledTimes(1); - expect(controller.state.configs).toStrictEqual({ - networks: MOCK_FALLBACK_CONFIG, - }); - expect(controller.state.fetchError).toBe( - 'Feature flag disabled - using fallback configuration', + expect(stopPollingSpy).toHaveBeenCalled(); + }, ); - - controller.stopPolling(); }); - it('should default to fallback when RemoteFeatureFlagController is unavailable', async () => { - mockRemoteFeatureFlagGetState.mockImplementation(() => { - throw new Error('RemoteFeatureFlagController not available'); - }); + it('should call startPolling with default parameter when called without arguments', async () => { + return withController(async ({ controller, clock }) => { + const executePollSpy = jest.spyOn(controller, '_executePoll'); + + controller.startPolling(); + + await advanceTime({ clock, duration: 0 }); + expect(executePollSpy).toHaveBeenCalledTimes(1); - const controller = new ConfigRegistryController({ - messenger, - fallbackConfig: MOCK_FALLBACK_CONFIG, + controller.stopPolling(); }); + }); + }); - const executePollSpy = jest.spyOn(controller, '_executePoll'); - controller.startPolling(null); + describe('stopPolling', () => { + it('should clear pending delayed poll timeout when stopping', async () => { + const pollingInterval = 10000; + const recentTimestamp = Date.now() - 2000; + return withController( + { + options: { + pollingInterval, + state: { + lastFetched: recentTimestamp, + }, + }, + }, + async ({ controller, clock }) => { + const executePollSpy = jest.spyOn(controller, '_executePoll'); + controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + // Verify timeout was set (poll should not execute immediately) + await advanceTime({ clock, duration: 0 }); + expect(executePollSpy).not.toHaveBeenCalled(); - expect(executePollSpy).toHaveBeenCalledTimes(1); - expect(controller.state.configs).toStrictEqual({ - networks: MOCK_FALLBACK_CONFIG, - }); - expect(controller.state.fetchError).toBe( - 'Feature flag disabled - using fallback configuration', - ); + // Stop polling should clear the timeout + controller.stopPolling(); - controller.stopPolling(); + // Advance time past when the timeout would have fired + await advanceTime({ clock, duration: pollingInterval }); + expect(executePollSpy).not.toHaveBeenCalled(); + }, + ); }); - }); - describe('KeyringController event listeners', () => { - it('should start polling when KeyringController is already unlocked on initialization', async () => { - mockKeyringControllerGetState.mockReturnValue({ - isUnlocked: true, + it('should handle clearing timeout when no timeout exists', () => { + return withController(({ controller }) => { + // Should not throw when stopping without a pending timeout + expect(() => controller.stopPolling()).not.toThrow(); }); + }); - const controller = new ConfigRegistryController({ - messenger, - }); + it('should stop all polling when called without token (backward compatible)', async () => { + return withController(async ({ controller, clock }) => { + const executePollSpy = jest.spyOn(controller, '_executePoll'); - const executePollSpy = jest.spyOn(controller, '_executePoll'); + // Start polling from multiple consumers + const token1 = controller.startPolling(null); + const token2 = controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await advanceTime({ clock, duration: 0 }); + expect(executePollSpy).toHaveBeenCalledTimes(1); + executePollSpy.mockClear(); - expect(mockKeyringControllerGetState).toHaveBeenCalled(); - // Verify polling started by checking if _executePoll was called - expect(executePollSpy).toHaveBeenCalledTimes(1); + // Stop without token should stop all polling + controller.stopPolling(); - controller.stopPolling(); + await advanceTime({ clock, duration: DEFAULT_POLLING_INTERVAL }); + expect(executePollSpy).not.toHaveBeenCalled(); + }); }); - it('should handle KeyringController:getState error gracefully when KeyringController is unavailable', () => { - mockKeyringControllerGetState.mockImplementation(() => { - throw new Error('KeyringController not available'); - }); + it('should stop specific polling session when called with token', async () => { + return withController(async ({ controller, clock }) => { + const executePollSpy = jest.spyOn(controller, '_executePoll'); - const controller = new ConfigRegistryController({ - messenger, - }); + // Start polling from consumer A + const tokenA = controller.startPolling(null); + await advanceTime({ clock, duration: 0 }); + expect(executePollSpy).toHaveBeenCalledTimes(1); + executePollSpy.mockClear(); - // Should not have started polling - expect(controller.state.lastFetched).toBeNull(); - }); + // Start polling from consumer B (should reuse same polling session) + const tokenB = controller.startPolling(null); + await advanceTime({ clock, duration: 0 }); + // Since both use same input (null), they share the same polling session + // So stopping one token should stop the shared session + expect(executePollSpy).toHaveBeenCalledTimes(0); + executePollSpy.mockClear(); - it('should start polling when KeyringController:unlock event is published', async () => { - const controller = new ConfigRegistryController({ - messenger, + // Stop consumer A's polling session + controller.stopPolling(tokenA); + + // Polling should stop for both since they share the same session + await advanceTime({ clock, duration: DEFAULT_POLLING_INTERVAL }); + expect(executePollSpy).not.toHaveBeenCalled(); }); + }); - const executePollSpy = jest.spyOn(controller, '_executePoll'); - const startPollingSpy = jest.spyOn(controller, 'startPolling'); + it('should work via messenger action with token', async () => { + return withController(async ({ controller, messenger, clock }) => { + const executePollSpy = jest.spyOn(controller, '_executePoll'); - // Initially locked, so polling should not have started - expect(startPollingSpy).not.toHaveBeenCalled(); + const token = messenger.call( + 'ConfigRegistryController:startPolling', + null, + ); + expect(typeof token).toBe('string'); - // Publish unlock event on root messenger - rootMessenger.publish('KeyringController:unlock'); + await advanceTime({ clock, duration: 0 }); + expect(executePollSpy).toHaveBeenCalledTimes(1); + executePollSpy.mockClear(); - await advanceTime({ clock, duration: 0 }); + // Stop with token via messenger + messenger.call('ConfigRegistryController:stopPolling', token); + await advanceTime({ clock, duration: DEFAULT_POLLING_INTERVAL }); + expect(executePollSpy).not.toHaveBeenCalled(); + }); + }); - expect(startPollingSpy).toHaveBeenCalledWith(null); - expect(executePollSpy).toHaveBeenCalledTimes(1); + it('should work via messenger action without token (backward compatible)', async () => { + return withController(async ({ controller, messenger, clock }) => { + const executePollSpy = jest.spyOn(controller, '_executePoll'); - controller.stopPolling(); - }); + const token = messenger.call( + 'ConfigRegistryController:startPolling', + null, + ); + expect(typeof token).toBe('string'); - it('should stop polling when KeyringController:lock event is published', async () => { - mockKeyringControllerGetState.mockReturnValue({ - isUnlocked: true, - }); + await advanceTime({ clock, duration: 0 }); + expect(executePollSpy).toHaveBeenCalledTimes(1); + executePollSpy.mockClear(); - const controller = new ConfigRegistryController({ - messenger, + // Stop without token via messenger (backward compatible) + messenger.call('ConfigRegistryController:stopPolling'); + await advanceTime({ clock, duration: DEFAULT_POLLING_INTERVAL }); + expect(executePollSpy).not.toHaveBeenCalled(); }); + }); + }); - const stopPollingSpy = jest.spyOn(controller, 'stopPolling'); - - // Polling should have started - await advanceTime({ clock, duration: 0 }); - expect(stopPollingSpy).not.toHaveBeenCalled(); + describe('destroy', () => { + it('should clean up event listeners and action handlers', () => { + return withController(({ controller, messenger, rootMessenger }) => { + const unsubscribeSpy = jest.spyOn(messenger, 'unsubscribe'); + const unregisterActionHandlerSpy = jest.spyOn( + messenger, + 'unregisterActionHandler', + ); + const stopPollingSpy = jest.spyOn(controller, 'stopPolling'); - // Publish lock event on root messenger - rootMessenger.publish('KeyringController:lock'); + controller.destroy(); - expect(stopPollingSpy).toHaveBeenCalled(); + expect(stopPollingSpy).toHaveBeenCalled(); + expect(unsubscribeSpy).toHaveBeenCalledWith( + 'KeyringController:unlock', + expect.any(Function), + ); + expect(unsubscribeSpy).toHaveBeenCalledWith( + 'KeyringController:lock', + expect.any(Function), + ); + expect(unregisterActionHandlerSpy).toHaveBeenCalledWith( + 'ConfigRegistryController:startPolling', + ); + expect(unregisterActionHandlerSpy).toHaveBeenCalledWith( + 'ConfigRegistryController:stopPolling', + ); + }); }); - it('should call startPolling with default parameter when called without arguments', async () => { - const controller = new ConfigRegistryController({ - messenger, + it('should handle unsubscribe errors gracefully', () => { + return withController(({ controller, messenger }) => { + jest + .spyOn(messenger, 'unsubscribe') + .mockImplementation(() => { + throw new Error('Handler not subscribed'); + }); + + // Should not throw even if unsubscribe fails + expect(() => controller.destroy()).not.toThrow(); }); + }); - const executePollSpy = jest.spyOn(controller, '_executePoll'); + it('should clear pending timeout when destroying', async () => { + const pollingInterval = 10000; + const recentTimestamp = Date.now() - 2000; + return withController( + { + options: { + pollingInterval, + state: { + lastFetched: recentTimestamp, + }, + }, + }, + async ({ controller, clock }) => { + const executePollSpy = jest.spyOn(controller, '_executePoll'); + controller.startPolling(null); - // Call startPolling without arguments to test default parameter - controller.startPolling(); + // Verify timeout was set + await advanceTime({ clock, duration: 0 }); + expect(executePollSpy).not.toHaveBeenCalled(); - // Verify polling started by checking if _executePoll is called - await advanceTime({ clock, duration: 0 }); - expect(executePollSpy).toHaveBeenCalledTimes(1); + // Destroy should clear the timeout + controller.destroy(); - controller.stopPolling(); + // Advance time past when the timeout would have fired + await advanceTime({ clock, duration: pollingInterval }); + expect(executePollSpy).not.toHaveBeenCalled(); + }, + ); }); }); }); diff --git a/packages/config-registry-controller/src/ConfigRegistryController.ts b/packages/config-registry-controller/src/ConfigRegistryController.ts index 3a1b18a1968..fccec443cd9 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.ts @@ -19,18 +19,12 @@ import type { NetworkConfig, } from './config-registry-api-service'; import { filterNetworks } from './config-registry-api-service'; -import { isConfigRegistryApiEnabled } from './utils/feature-flags'; +import { isConfigRegistryApiEnabled as defaultIsConfigRegistryApiEnabled } from './utils/feature-flags'; const controllerName = 'ConfigRegistryController'; export const DEFAULT_POLLING_INTERVAL = inMilliseconds(1, Duration.Day); -export type RegistryConfigEntry = { - key: string; - value: Json; - metadata?: Json; -}; - export type NetworkConfigEntry = { key: string; value: NetworkConfig; @@ -68,8 +62,8 @@ const stateMetadata = { }, fetchError: { persist: true, - includeInStateLogs: true, - includeInDebugSnapshot: true, + includeInStateLogs: false, + includeInDebugSnapshot: false, usedInUi: false, }, etag: { @@ -97,7 +91,7 @@ export type ConfigRegistryControllerStartPollingAction = { export type ConfigRegistryControllerStopPollingAction = { type: `${typeof controllerName}:stopPolling`; - handler: () => void; + handler: (token?: string) => void; }; export type ConfigRegistryControllerActions = @@ -133,6 +127,7 @@ export type ConfigRegistryControllerOptions = { state?: Partial; pollingInterval?: number; fallbackConfig?: Record; + isConfigRegistryApiEnabled?: (messenger: ConfigRegistryMessenger) => boolean; }; export class ConfigRegistryController extends StaticIntervalPollingController()< @@ -142,6 +137,16 @@ export class ConfigRegistryController extends StaticIntervalPollingController { readonly #fallbackConfig: Record; + readonly #isConfigRegistryApiEnabled: ( + messenger: ConfigRegistryMessenger, + ) => boolean; + + readonly #unlockHandler: () => void; + + readonly #lockHandler: () => void; + + #delayedPollTimeoutId: ReturnType | null = null; + /** * @param options - The controller options. * @param options.messenger - The controller messenger. Must have @@ -149,44 +154,59 @@ export class ConfigRegistryController extends StaticIntervalPollingController { + this.startPolling(null); + }; + + this.#lockHandler = (): void => { + this.stopPolling(); + }; this.messenger.registerActionHandler( `${controllerName}:startPolling`, (input: null) => this.startPolling(input), ); - this.messenger.registerActionHandler(`${controllerName}:stopPolling`, () => - this.stopPolling(), + this.messenger.registerActionHandler( + `${controllerName}:stopPolling`, + (token?: string) => this.stopPolling(token), ); this.#registerKeyringEventListeners(); } async _executePoll(_input: null): Promise { - const isApiEnabled = isConfigRegistryApiEnabled(this.messenger); + const isApiEnabled = this.#isConfigRegistryApiEnabled(this.messenger); if (!isApiEnabled) { this.useFallbackConfig( @@ -214,9 +234,10 @@ export class ConfigRegistryController extends StaticIntervalPollingController { state.fetchError = null; + state.lastFetched = Date.now(); if (result.etag !== undefined) { state.etag = result.etag ?? null; } @@ -224,17 +245,6 @@ export class ConfigRegistryController extends StaticIntervalPollingController(); + filteredNetworks.forEach((network, index) => { + const existing = networksByChainId.get(network.chainId) ?? []; + existing.push({ network, index }); + networksByChainId.set(network.chainId, existing); + }); + + // Build configs, handling duplicates by keeping highest priority network const newConfigs: Record = {}; - for (const network of filteredNetworks) { - newConfigs[network.chainId] = { - key: network.chainId, - value: network, + for (const [chainId, networks] of networksByChainId) { + if (networks.length > 1) { + // Duplicate chainIds detected - log warning and keep highest priority + const duplicateNames = networks + .map((networkEntry) => networkEntry.network.name) + .join(', '); + const warningMessage = `Duplicate chainId ${chainId} detected in config registry API response. Networks: ${duplicateNames}. Keeping network with highest priority.`; + + if (this.messenger.captureException) { + this.messenger.captureException(new Error(warningMessage)); + } + + // Sort by priority (lower number = higher priority), then by index (first occurrence) + networks.sort((a, b) => { + const priorityDiff = a.network.priority - b.network.priority; + if (priorityDiff === 0) { + return a.index - b.index; + } + return priorityDiff; + }); + } + + // Use the first network (highest priority if duplicates existed) + const selectedNetwork = networks[0].network; + newConfigs[chainId] = { + key: chainId, + value: selectedNetwork, }; } @@ -286,16 +331,10 @@ export class ConfigRegistryController extends StaticIntervalPollingController { - state.fetchError = errorMessage; - }); - } + this.update((state) => { + state.fetchError = errorMessage; + state.lastFetched = Date.now(); + }); } /** @@ -314,21 +353,95 @@ export class ConfigRegistryController extends StaticIntervalPollingController { - this.startPolling(null); - }); + this.messenger.subscribe('KeyringController:unlock', this.#unlockHandler); // Subscribe to lock event - stop polling - this.messenger.subscribe('KeyringController:lock', () => { - this.stopPolling(); - }); + this.messenger.subscribe('KeyringController:lock', this.#lockHandler); } startPolling(input: null = null): string { - return super.startPolling(input); + const token = super.startPolling(input); + + // Calculate delay based on lastFetched to respect 24-hour interval + const pollingInterval = + this.getIntervalLength() ?? DEFAULT_POLLING_INTERVAL; + const now = Date.now(); + const { lastFetched } = this.state; + + if (lastFetched !== null) { + const timeSinceLastFetch = now - lastFetched; + const remainingTime = pollingInterval - timeSinceLastFetch; + + if (remainingTime > 0) { + // Not enough time has passed, delay the first poll + // Clear any existing timeout before stopping polling + if (this.#delayedPollTimeoutId !== null) { + clearTimeout(this.#delayedPollTimeoutId); + this.#delayedPollTimeoutId = null; + } + + // Stop the immediate poll that was just started + this.stopPolling(); + + // Schedule the first poll after the remaining time + this.#delayedPollTimeoutId = setTimeout(() => { + this.#delayedPollTimeoutId = null; + super.startPolling(input); + }, remainingTime); + + return token; + } + } + + // Enough time has passed or first time, proceed with normal polling + return token; + } + + stopPolling(token?: string): void { + // Clear any pending delayed poll timeout + if (this.#delayedPollTimeoutId !== null) { + clearTimeout(this.#delayedPollTimeoutId); + this.#delayedPollTimeoutId = null; + } + + if (token) { + // Stop specific polling session by token + super.stopPollingByPollingToken(token); + } else { + // Stop all polling (backward compatible) + super.stopAllPolling(); + } } - stopPolling(): void { - super.stopAllPolling(); + /** + * Prepares the controller for garbage collection by cleaning up event listeners, + * action handlers, and timers. + */ + override destroy(): void { + // Stop polling and clear any pending timeouts + this.stopPolling(); + + // Unsubscribe from event listeners + try { + this.messenger.unsubscribe( + 'KeyringController:unlock', + this.#unlockHandler, + ); + } catch { + // Handler may not be subscribed, silently handle + } + + try { + this.messenger.unsubscribe('KeyringController:lock', this.#lockHandler); + } catch { + // Handler may not be subscribed, silently handle + } + + // Unregister action handlers + this.messenger.unregisterActionHandler(`${controllerName}:startPolling`); + this.messenger.unregisterActionHandler(`${controllerName}:stopPolling`); + + // Call parent destroy to clean up base controller subscriptions + super.destroy(); } } diff --git a/packages/config-registry-controller/src/config-registry-api-service/abstract-config-registry-api-service.ts b/packages/config-registry-controller/src/config-registry-api-service/abstract-config-registry-api-service.ts deleted file mode 100644 index e71fb6cf412..00000000000 --- a/packages/config-registry-controller/src/config-registry-api-service/abstract-config-registry-api-service.ts +++ /dev/null @@ -1,55 +0,0 @@ -import type { ServicePolicy } from '@metamask/controller-utils'; - -export type NetworkConfig = { - chainId: string; - name: string; - nativeCurrency: string; - rpcEndpoints: { - url: string; - type: string; - networkClientId: string; - failoverUrls: string[]; - }[]; - blockExplorerUrls: string[]; - defaultRpcEndpointIndex: number; - defaultBlockExplorerUrlIndex: number; - lastUpdatedAt?: number; - networkImageUrl?: string; - nativeTokenImageUrl?: string; - isActive: boolean; - isTestnet: boolean; - isDefault: boolean; - isFeatured: boolean; - isDeprecated: boolean; - priority: number; - isDeletable: boolean; -}; - -export type RegistryConfigApiResponse = { - data: { - version: string; - timestamp: number; - networks: NetworkConfig[]; - }; -}; - -export type FetchConfigOptions = { - etag?: string; -}; - -export type FetchConfigResult = - | { - notModified: true; - etag?: string; - } - | { - notModified: false; - data: RegistryConfigApiResponse; - etag?: string; - }; - -export type AbstractConfigRegistryApiService = Partial< - Pick -> & { - fetchConfig(options?: FetchConfigOptions): Promise; -}; diff --git a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts index 47f847c0827..22c3d3c0e9f 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts @@ -1,15 +1,12 @@ +import { SDK } from '@metamask/profile-sync-controller'; import nock, { cleanAll } from 'nock'; import { useFakeTimers } from 'sinon'; -import type { - FetchConfigResult, - RegistryConfigApiResponse, -} from './abstract-config-registry-api-service'; import { ConfigRegistryApiService, - DEFAULT_API_BASE_URL, - DEFAULT_ENDPOINT_PATH, + getConfigRegistryUrl, } from './config-registry-api-service'; +import type { FetchConfigResult, RegistryConfigApiResponse } from './types'; const MOCK_API_RESPONSE: RegistryConfigApiResponse = { data: { @@ -44,6 +41,29 @@ const MOCK_API_RESPONSE: RegistryConfigApiResponse = { }; describe('ConfigRegistryApiService', () => { + describe('getConfigRegistryUrl', () => { + it('should return UAT URL for UAT environment', () => { + const url = getConfigRegistryUrl(SDK.Env.UAT); + expect(url).toBe( + 'https://client-config.uat-api.cx.metamask.io/v1/config/networks', + ); + }); + + it('should return DEV URL for DEV environment', () => { + const url = getConfigRegistryUrl(SDK.Env.DEV); + expect(url).toBe( + 'https://client-config.dev-api.cx.metamask.io/v1/config/networks', + ); + }); + + it('should return PRD URL for PRD environment', () => { + const url = getConfigRegistryUrl(SDK.Env.PRD); + expect(url).toBe( + 'https://client-config.api.cx.metamask.io/v1/config/networks', + ); + }); + }); + describe('constructor', () => { it('should create instance with default options', () => { const service = new ConfigRegistryApiService(); @@ -53,9 +73,7 @@ describe('ConfigRegistryApiService', () => { it('should create instance with custom options', () => { const customFetch = jest.fn(); const service = new ConfigRegistryApiService({ - apiBaseUrl: 'https://custom-api.example.com', - endpointPath: '/custom/path', - timeout: 5000, + env: SDK.Env.DEV, fetch: customFetch, retries: 5, }); @@ -69,15 +87,14 @@ describe('ConfigRegistryApiService', () => { it('should use default values for unspecified options', () => { const service = new ConfigRegistryApiService({ - apiBaseUrl: 'https://test.com', + env: SDK.Env.PRD, }); expect(service).toBeInstanceOf(ConfigRegistryApiService); }); it('should use default fetch when not provided', () => { const service = new ConfigRegistryApiService({ - apiBaseUrl: 'https://test.com', - endpointPath: '/test', + env: SDK.Env.DEV, }); expect(service).toBeInstanceOf(ConfigRegistryApiService); }); @@ -93,8 +110,8 @@ describe('ConfigRegistryApiService', () => { }); it('should successfully fetch config from API', async () => { - const scope = nock(DEFAULT_API_BASE_URL) - .get(DEFAULT_ENDPOINT_PATH) + const scope = nock('https://client-config.uat-api.cx.metamask.io') + .get('/v1/config/networks') .reply(200, MOCK_API_RESPONSE, { ETag: '"test-etag-123"', }); @@ -102,67 +119,41 @@ describe('ConfigRegistryApiService', () => { const service = new ConfigRegistryApiService(); const result = await service.fetchConfig(); - expect(result.notModified).toBe(false); + expect(result.modified).toBe(true); expect(result.etag).toBe('"test-etag-123"'); expect( - (result as Extract).data, + (result as Extract).data, ).toStrictEqual(MOCK_API_RESPONSE); expect(scope.isDone()).toBe(true); }); - it('should execute fetchWithTimeout function and call clearTimeout on success', async () => { - const mockHeaders = { - get: jest.fn().mockReturnValue('"test-etag"'), - }; - const clearTimeoutSpy = jest.spyOn(global, 'clearTimeout'); - const setTimeoutSpy = jest.spyOn(global, 'setTimeout'); - const customFetch = jest.fn().mockResolvedValue({ - ok: true, - status: 200, - headers: mockHeaders, - json: async () => MOCK_API_RESPONSE, - } as unknown as Response); - - const service = new ConfigRegistryApiService({ - fetch: customFetch, - timeout: 1000, - }); - - await service.fetchConfig(); - - expect(setTimeoutSpy).toHaveBeenCalled(); - expect(clearTimeoutSpy).toHaveBeenCalled(); - clearTimeoutSpy.mockRestore(); - setTimeoutSpy.mockRestore(); - }); - it('should successfully fetch config from API without ETag header', async () => { - const scope = nock(DEFAULT_API_BASE_URL) - .get(DEFAULT_ENDPOINT_PATH) + const scope = nock('https://client-config.uat-api.cx.metamask.io') + .get('/v1/config/networks') .reply(200, MOCK_API_RESPONSE); const service = new ConfigRegistryApiService(); const result = await service.fetchConfig(); - expect(result.notModified).toBe(false); + expect(result.modified).toBe(true); expect(result.etag).toBeUndefined(); expect( - (result as Extract).data, + (result as Extract).data, ).toStrictEqual(MOCK_API_RESPONSE); expect(scope.isDone()).toBe(true); }); it('should handle 304 Not Modified response', async () => { const etag = '"test-etag-123"'; - const scope = nock(DEFAULT_API_BASE_URL) - .get(DEFAULT_ENDPOINT_PATH) + const scope = nock('https://client-config.uat-api.cx.metamask.io') + .get('/v1/config/networks') .matchHeader('If-None-Match', etag) .reply(304); const service = new ConfigRegistryApiService(); const result = await service.fetchConfig({ etag }); - expect(result.notModified).toBe(true); + expect(result.modified).toBe(false); expect(scope.isDone()).toBe(true); }); @@ -182,14 +173,14 @@ describe('ConfigRegistryApiService', () => { const result = await service.fetchConfig(); - expect(result.notModified).toBe(true); + expect(result.modified).toBe(false); expect(result.etag).toBeUndefined(); }); it('should include If-None-Match header when etag is provided', async () => { const etag = '"test-etag-123"'; - const scope = nock(DEFAULT_API_BASE_URL) - .get(DEFAULT_ENDPOINT_PATH) + const scope = nock('https://client-config.uat-api.cx.metamask.io') + .get('/v1/config/networks') .matchHeader('If-None-Match', etag) .reply(200, MOCK_API_RESPONSE); @@ -200,8 +191,8 @@ describe('ConfigRegistryApiService', () => { }); it('should not include If-None-Match header when etag is undefined', async () => { - const scope = nock(DEFAULT_API_BASE_URL) - .get(DEFAULT_ENDPOINT_PATH) + const scope = nock('https://client-config.uat-api.cx.metamask.io') + .get('/v1/config/networks') .reply(200, MOCK_API_RESPONSE); const service = new ConfigRegistryApiService(); @@ -211,8 +202,8 @@ describe('ConfigRegistryApiService', () => { }); it('should handle fetchConfig called with undefined options', async () => { - const scope = nock(DEFAULT_API_BASE_URL) - .get(DEFAULT_ENDPOINT_PATH) + const scope = nock('https://client-config.uat-api.cx.metamask.io') + .get('/v1/config/networks') .reply(200, MOCK_API_RESPONSE); const service = new ConfigRegistryApiService(); @@ -224,15 +215,13 @@ describe('ConfigRegistryApiService', () => { it('should throw error on invalid response structure', async () => { const invalidResponse = { invalid: 'data' }; - const scope = nock(DEFAULT_API_BASE_URL) - .get(DEFAULT_ENDPOINT_PATH) + const scope = nock('https://client-config.uat-api.cx.metamask.io') + .get('/v1/config/networks') .reply(200, invalidResponse); const service = new ConfigRegistryApiService(); - await expect(service.fetchConfig()).rejects.toThrow( - 'Invalid response structure from config registry API', - ); + await expect(service.fetchConfig()).rejects.toThrow(expect.any(Error)); expect(scope.isDone()).toBe(true); }); @@ -251,9 +240,7 @@ describe('ConfigRegistryApiService', () => { fetch: customFetch, }); - await expect(service.fetchConfig()).rejects.toThrow( - 'Invalid response structure from config registry API', - ); + await expect(service.fetchConfig()).rejects.toThrow(expect.any(Error)); }); it('should throw error when data.data is null', async () => { @@ -271,9 +258,7 @@ describe('ConfigRegistryApiService', () => { fetch: customFetch, }); - await expect(service.fetchConfig()).rejects.toThrow( - 'Invalid response structure from config registry API', - ); + await expect(service.fetchConfig()).rejects.toThrow(expect.any(Error)); }); it('should throw error when data.data.networks is not an array', async () => { @@ -291,9 +276,7 @@ describe('ConfigRegistryApiService', () => { fetch: customFetch, }); - await expect(service.fetchConfig()).rejects.toThrow( - 'Invalid response structure from config registry API', - ); + await expect(service.fetchConfig()).rejects.toThrow(expect.any(Error)); }); it('should throw error on HTTP error status', async () => { @@ -316,67 +299,13 @@ describe('ConfigRegistryApiService', () => { ); }); - it('should handle timeout', async () => { - const testTimeout = 1000; - const customFetch = jest.fn().mockImplementation(() => { - const abortError = new Error('Request aborted'); - abortError.name = 'AbortError'; - return Promise.reject(abortError); - }); - - const service = new ConfigRegistryApiService({ - timeout: testTimeout, - fetch: customFetch, - }); - - await expect(service.fetchConfig()).rejects.toThrow( - `Request timeout after ${testTimeout}ms`, - ); - }, 10000); // Increase Jest timeout for this test - - it('should trigger setTimeout callback when request exceeds timeout', async () => { - const testTimeout = 50; - - const customFetch = jest - .fn() - .mockImplementation((_url: string, options?: RequestInit) => { - const signal = options?.signal as AbortSignal; - return new Promise((_resolve, reject) => { - if (signal?.aborted) { - const abortError = new Error('Request aborted'); - abortError.name = 'AbortError'; - reject(abortError); - return; - } - - if (signal) { - signal.addEventListener('abort', () => { - const abortError = new Error('Request aborted'); - abortError.name = 'AbortError'; - reject(abortError); - }); - } - }); - }); - - const service = new ConfigRegistryApiService({ - timeout: testTimeout, - fetch: customFetch, - }); - - await expect(service.fetchConfig()).rejects.toThrow( - `Request timeout after ${testTimeout}ms`, - ); - }, 10000); // Increase Jest timeout for this test - - it('should handle non-AbortError in fetchWithTimeout', async () => { + it('should handle network errors', async () => { const customFetch = jest .fn() .mockRejectedValue(new Error('Network connection failed')); const service = new ConfigRegistryApiService({ fetch: customFetch, - timeout: 1000, }); await expect(service.fetchConfig()).rejects.toThrow( @@ -385,14 +314,14 @@ describe('ConfigRegistryApiService', () => { }); it('should retry on failure', async () => { - nock(DEFAULT_API_BASE_URL) - .get(DEFAULT_ENDPOINT_PATH) + nock('https://client-config.uat-api.cx.metamask.io') + .get('/v1/config/networks') .replyWithError('Network error'); - nock(DEFAULT_API_BASE_URL) - .get(DEFAULT_ENDPOINT_PATH) + nock('https://client-config.uat-api.cx.metamask.io') + .get('/v1/config/networks') .replyWithError('Network error'); - const successScope = nock(DEFAULT_API_BASE_URL) - .get(DEFAULT_ENDPOINT_PATH) + const successScope = nock('https://client-config.uat-api.cx.metamask.io') + .get('/v1/config/networks') .reply(200, MOCK_API_RESPONSE); const service = new ConfigRegistryApiService({ @@ -401,9 +330,9 @@ describe('ConfigRegistryApiService', () => { const result = await service.fetchConfig(); - expect(result.notModified).toBe(false); + expect(result.modified).toBe(true); expect( - (result as Extract).data, + (result as Extract).data, ).toStrictEqual(MOCK_API_RESPONSE); expect(successScope.isDone()).toBe(true); }); @@ -425,8 +354,8 @@ describe('ConfigRegistryApiService', () => { const retries = 0; for (let i = 0; i < maximumConsecutiveFailures; i++) { - nock(DEFAULT_API_BASE_URL) - .get(DEFAULT_ENDPOINT_PATH) + nock('https://client-config.uat-api.cx.metamask.io') + .get('/v1/config/networks') .replyWithError('Network error'); } @@ -535,29 +464,26 @@ describe('ConfigRegistryApiService', () => { const service = new ConfigRegistryApiService({ fetch: customFetch, - apiBaseUrl: 'https://custom-api.example.com', - endpointPath: '/custom/path', }); const result = await service.fetchConfig(); expect(customFetch).toHaveBeenCalled(); - expect(result.notModified).toBe(false); + expect(result.modified).toBe(true); expect( - (result as Extract).data, + (result as Extract).data, ).toStrictEqual(MOCK_API_RESPONSE); }); }); - describe('URL construction', () => { - it('should handle base URL not ending with slash', async () => { - const scope = nock('https://test-api.example.com') - .get('/config/networks') + describe('environment configuration', () => { + it('should use DEV environment URL when env is DEV', async () => { + const scope = nock('https://client-config.dev-api.cx.metamask.io') + .get('/v1/config/networks') .reply(200, MOCK_API_RESPONSE); const service = new ConfigRegistryApiService({ - apiBaseUrl: 'https://test-api.example.com', - endpointPath: '/config/networks', + env: SDK.Env.DEV, }); await service.fetchConfig(); @@ -565,14 +491,13 @@ describe('ConfigRegistryApiService', () => { expect(scope.isDone()).toBe(true); }); - it('should handle base URL ending with slash', async () => { - const scope = nock('https://test-api.example.com') - .get('/config/networks') + it('should use UAT environment URL when env is UAT', async () => { + const scope = nock('https://client-config.uat-api.cx.metamask.io') + .get('/v1/config/networks') .reply(200, MOCK_API_RESPONSE); const service = new ConfigRegistryApiService({ - apiBaseUrl: 'https://test-api.example.com/', - endpointPath: '/config/networks', + env: SDK.Env.UAT, }); await service.fetchConfig(); @@ -580,14 +505,13 @@ describe('ConfigRegistryApiService', () => { expect(scope.isDone()).toBe(true); }); - it('should handle endpoint path without leading slash', async () => { - const scope = nock('https://test-api.example.com') - .get('/config/networks') + it('should use PRD environment URL when env is PRD', async () => { + const scope = nock('https://client-config.api.cx.metamask.io') + .get('/v1/config/networks') .reply(200, MOCK_API_RESPONSE); const service = new ConfigRegistryApiService({ - apiBaseUrl: 'https://test-api.example.com', - endpointPath: 'config/networks', + env: SDK.Env.PRD, }); await service.fetchConfig(); @@ -595,15 +519,12 @@ describe('ConfigRegistryApiService', () => { expect(scope.isDone()).toBe(true); }); - it('should handle endpoint path with leading slash', async () => { - const scope = nock('https://test-api.example.com') - .get('/config/networks') + it('should default to UAT environment', async () => { + const scope = nock('https://client-config.uat-api.cx.metamask.io') + .get('/v1/config/networks') .reply(200, MOCK_API_RESPONSE); - const service = new ConfigRegistryApiService({ - apiBaseUrl: 'https://test-api.example.com', - endpointPath: '/config/networks', - }); + const service = new ConfigRegistryApiService(); await service.fetchConfig(); diff --git a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts index 574199622fb..c3c5540bccf 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts @@ -6,25 +6,26 @@ import { DEFAULT_MAX_RETRIES, } from '@metamask/controller-utils'; import type { ServicePolicy } from '@metamask/controller-utils'; - -import type { - AbstractConfigRegistryApiService, - FetchConfigOptions, - FetchConfigResult, - RegistryConfigApiResponse, -} from './abstract-config-registry-api-service'; - -export const DEFAULT_API_BASE_URL = - 'https://client-config.uat-api.cx.metamask.io/v1'; - -export const DEFAULT_ENDPOINT_PATH = '/config/networks'; - -export const DEFAULT_TIMEOUT = 10 * 1000; +import { SDK } from '@metamask/profile-sync-controller'; + +import { validateRegistryConfigApiResponse } from './types'; +import type { FetchConfigOptions, FetchConfigResult } from './types'; + +const ENDPOINT_PATH = '/config/networks'; + +/** + * Returns the base URL for the config registry API for the given environment. + * + * @param env - The environment to get the URL for. + * @returns The base URL for the environment. + */ +export function getConfigRegistryUrl(env: SDK.Env): string { + const envPrefix = env === SDK.Env.PRD ? '' : `${env}-`; + return `https://client-config.${envPrefix}api.cx.metamask.io/v1${ENDPOINT_PATH}`; +} export type ConfigRegistryApiServiceOptions = { - apiBaseUrl?: string; - endpointPath?: string; - timeout?: number; + env?: SDK.Env; fetch?: typeof fetch; degradedThreshold?: number; retries?: number; @@ -32,16 +33,10 @@ export type ConfigRegistryApiServiceOptions = { circuitBreakDuration?: number; }; -export class ConfigRegistryApiService - implements AbstractConfigRegistryApiService -{ +export class ConfigRegistryApiService { readonly #policy: ServicePolicy; - readonly #apiBaseUrl: string; - - readonly #endpointPath: string; - - readonly #timeout: number; + readonly #url: string; readonly #fetch: typeof fetch; @@ -49,9 +44,7 @@ export class ConfigRegistryApiService * Construct a Config Registry API Service. * * @param options - The options for constructing the service. - * @param options.apiBaseUrl - The base URL for the API. Defaults to the UAT API URL. - * @param options.endpointPath - The endpoint path. Defaults to '/config/networks'. - * @param options.timeout - Timeout for HTTP requests in milliseconds. Defaults to 10 seconds. + * @param options.env - The environment to determine the correct API endpoints. Defaults to UAT. * @param options.fetch - Custom fetch function for testing or custom implementations. Defaults to the global fetch. * @param options.degradedThreshold - The length of time (in milliseconds) that governs when the service is regarded as degraded. Defaults to 5 seconds. * @param options.retries - Number of retry attempts for each fetch request. Defaults to 3. @@ -59,18 +52,14 @@ export class ConfigRegistryApiService * @param options.circuitBreakDuration - The amount of time to wait when the circuit breaks from too many consecutive failures. Defaults to 2 minutes. */ constructor({ - apiBaseUrl = DEFAULT_API_BASE_URL, - endpointPath = DEFAULT_ENDPOINT_PATH, - timeout = DEFAULT_TIMEOUT, + env = SDK.Env.UAT, fetch: customFetch = globalThis.fetch, degradedThreshold = DEFAULT_DEGRADED_THRESHOLD, retries = DEFAULT_MAX_RETRIES, maximumConsecutiveFailures = DEFAULT_MAX_CONSECUTIVE_FAILURES, circuitBreakDuration = DEFAULT_CIRCUIT_BREAK_DURATION, }: ConfigRegistryApiServiceOptions = {}) { - this.#apiBaseUrl = apiBaseUrl; - this.#endpointPath = endpointPath; - this.#timeout = timeout; + this.#url = getConfigRegistryUrl(env); this.#fetch = customFetch; this.#policy = createServicePolicy({ @@ -96,14 +85,6 @@ export class ConfigRegistryApiService async fetchConfig( options: FetchConfigOptions = {}, ): Promise { - const baseUrl = this.#apiBaseUrl.endsWith('/') - ? this.#apiBaseUrl.slice(0, -1) - : this.#apiBaseUrl; - const endpointPath = this.#endpointPath.startsWith('/') - ? this.#endpointPath - : `/${this.#endpointPath}`; - const url = new URL(`${baseUrl}${endpointPath}`); - const headers: HeadersInit = { 'Cache-Control': 'no-cache', }; @@ -112,28 +93,10 @@ export class ConfigRegistryApiService headers['If-None-Match'] = options.etag; } - const fetchWithTimeout = async (): Promise => { - const controller = new AbortController(); - const timeoutId = setTimeout(() => controller.abort(), this.#timeout); - - try { - const response = await this.#fetch(url.toString(), { - headers, - signal: controller.signal, - }); - clearTimeout(timeoutId); - return response; - } catch (error) { - clearTimeout(timeoutId); - if (error instanceof Error && error.name === 'AbortError') { - throw new Error(`Request timeout after ${this.#timeout}ms`); - } - throw error; - } - }; - const response = await this.#policy.execute(async () => { - const res = await fetchWithTimeout(); + const res = await this.#fetch(this.#url, { + headers, + }); if (res.status === 304) { return res; @@ -151,22 +114,20 @@ export class ConfigRegistryApiService if (response.status === 304) { const etag = response.headers.get('ETag') ?? undefined; return { - notModified: true, + modified: false, etag, }; } const etag = response.headers.get('ETag') ?? undefined; - const data = (await response.json()) as RegistryConfigApiResponse; + const jsonData = await response.json(); - if (!data?.data || !Array.isArray(data.data.networks)) { - throw new Error('Invalid response structure from config registry API'); - } + validateRegistryConfigApiResponse(jsonData); return { - data, + data: jsonData, etag, - notModified: false, + modified: true, }; } } diff --git a/packages/config-registry-controller/src/config-registry-api-service/index.ts b/packages/config-registry-controller/src/config-registry-api-service/index.ts index 187bf9226c0..830d2597965 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/index.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/index.ts @@ -1,28 +1,16 @@ export type { - AbstractConfigRegistryApiService, FetchConfigOptions, FetchConfigResult, NetworkConfig, RegistryConfigApiResponse, -} from './abstract-config-registry-api-service'; +} from './types'; export { ConfigRegistryApiService, - DEFAULT_API_BASE_URL, - DEFAULT_ENDPOINT_PATH, - DEFAULT_TIMEOUT, + getConfigRegistryUrl, } from './config-registry-api-service'; export type { ConfigRegistryApiServiceOptions } from './config-registry-api-service'; -export type { - NetworkFilterOptions, - NetworkComparisonOptions, - TransformedNetworkResult, -} from './transformers'; -export { - transformNetworkConfig, - filterNetworks, - compareWithExistingNetworks, - processNetworkConfigs, -} from './transformers'; +export type { NetworkFilterOptions } from './transformers'; +export { filterNetworks } from './transformers'; diff --git a/packages/config-registry-controller/src/config-registry-api-service/transformers.test.ts b/packages/config-registry-controller/src/config-registry-api-service/transformers.test.ts index 41fca6763d0..1ca61ff9ab5 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/transformers.test.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/transformers.test.ts @@ -1,14 +1,5 @@ -import type { NetworkConfiguration } from '@metamask/network-controller'; -import { RpcEndpointType } from '@metamask/network-controller'; -import type { Hex } from '@metamask/utils'; - -import type { NetworkConfig } from './abstract-config-registry-api-service'; -import { - compareWithExistingNetworks, - filterNetworks, - processNetworkConfigs, - transformNetworkConfig, -} from './transformers'; +import { filterNetworks } from './transformers'; +import type { NetworkConfig } from './types'; const VALID_NETWORK_CONFIG: NetworkConfig = { chainId: '0x1', @@ -34,546 +25,7 @@ const VALID_NETWORK_CONFIG: NetworkConfig = { isDeletable: false, }; -const VALID_CUSTOM_NETWORK_CONFIG: NetworkConfig = { - chainId: '0x89', - name: 'Polygon', - nativeCurrency: 'MATIC', - rpcEndpoints: [ - { - url: 'https://polygon-rpc.com', - type: 'custom', - networkClientId: 'custom-polygon', - failoverUrls: [], - }, - ], - blockExplorerUrls: ['https://polygonscan.com'], - defaultRpcEndpointIndex: 0, - defaultBlockExplorerUrlIndex: 0, - isActive: true, - isTestnet: false, - isDefault: false, - isFeatured: true, - isDeprecated: false, - priority: 1, - isDeletable: false, -}; - describe('transformers', () => { - describe('transformNetworkConfig', () => { - it('should transform valid network config with infura endpoint', () => { - const result = transformNetworkConfig(VALID_NETWORK_CONFIG); - - expect(result).not.toBeNull(); - expect(result?.chainId).toBe('0x1'); - expect(result?.name).toBe('Ethereum Mainnet'); - expect(result?.nativeCurrency).toBe('ETH'); - expect(result?.rpcEndpoints).toHaveLength(1); - expect(result?.rpcEndpoints[0].type).toBe(RpcEndpointType.Infura); - expect(result?.rpcEndpoints[0].networkClientId).toBe('mainnet'); - expect(result?.rpcEndpoints[0].failoverUrls).toStrictEqual([ - 'https://backup.infura.io/v3/{infuraProjectId}', - ]); - expect(result?.blockExplorerUrls).toStrictEqual(['https://etherscan.io']); - expect(result?.defaultRpcEndpointIndex).toBe(0); - expect(result?.defaultBlockExplorerUrlIndex).toBe(0); - }); - - it('should transform valid network config with custom endpoint', () => { - const result = transformNetworkConfig(VALID_CUSTOM_NETWORK_CONFIG); - - expect(result).not.toBeNull(); - expect(result?.chainId).toBe('0x89'); - expect(result?.rpcEndpoints[0].type).toBe(RpcEndpointType.Custom); - expect(result?.rpcEndpoints[0].url).toBe('https://polygon-rpc.com'); - }); - - it('should convert decimal chain ID to hex', () => { - const config = { - ...VALID_NETWORK_CONFIG, - chainId: '1', - }; - - const result = transformNetworkConfig(config); - - expect(result?.chainId).toBe('0x1'); - }); - - it('should handle chain ID with 0x prefix', () => { - const config = { - ...VALID_NETWORK_CONFIG, - chainId: '0X1', - }; - - const result = transformNetworkConfig(config); - - expect(result?.chainId).toBe('0x1'); - }); - - it('should return null for invalid chain ID', () => { - const config = { - ...VALID_NETWORK_CONFIG, - chainId: 'invalid', - }; - - const result = transformNetworkConfig(config); - - expect(result).toBeNull(); - }); - - it('should return null for negative chain ID', () => { - const config = { - ...VALID_NETWORK_CONFIG, - chainId: '-1', - }; - - const result = transformNetworkConfig(config); - - expect(result).toBeNull(); - }); - - it('should return null for empty chain ID', () => { - const config = { - ...VALID_NETWORK_CONFIG, - chainId: '', - }; - - const result = transformNetworkConfig(config); - - expect(result).toBeNull(); - }); - - it('should return null for invalid hex chain ID', () => { - const config = { - ...VALID_NETWORK_CONFIG, - chainId: '0xinvalid', - }; - - const result = transformNetworkConfig(config); - - expect(result).toBeNull(); - }); - - it('should return null for missing name', () => { - const config = { - ...VALID_NETWORK_CONFIG, - name: '', - }; - - const result = transformNetworkConfig(config); - - expect(result).toBeNull(); - }); - - it('should return null for missing nativeCurrency', () => { - const config = { - ...VALID_NETWORK_CONFIG, - nativeCurrency: '', - }; - - const result = transformNetworkConfig(config); - - expect(result).toBeNull(); - }); - - it('should return null for empty rpcEndpoints', () => { - const config = { - ...VALID_NETWORK_CONFIG, - rpcEndpoints: [], - }; - - const result = transformNetworkConfig(config); - - expect(result).toBeNull(); - }); - - it('should return null for invalid rpcEndpoint', () => { - const config = { - ...VALID_NETWORK_CONFIG, - rpcEndpoints: [ - { - url: '', - type: 'infura', - networkClientId: 'mainnet', - failoverUrls: [], - }, - ], - }; - - const result = transformNetworkConfig(config); - - expect(result).toBeNull(); - }); - - it('should return null for invalid rpcEndpoint type', () => { - const config = { - ...VALID_NETWORK_CONFIG, - rpcEndpoints: [ - { - url: 'https://example.com', - type: 'invalid', - networkClientId: 'test', - failoverUrls: [], - }, - ], - }; - - const result = transformNetworkConfig(config); - - expect(result).toBeNull(); - }); - - it('should return null for null rpcEndpoint', () => { - const config = { - ...VALID_NETWORK_CONFIG, - rpcEndpoints: [null as unknown as NetworkConfig['rpcEndpoints'][0]], - }; - - const result = transformNetworkConfig(config); - - expect(result).toBeNull(); - }); - - it('should return null for rpcEndpoint with empty type', () => { - const config = { - ...VALID_NETWORK_CONFIG, - rpcEndpoints: [ - { - url: 'https://example.com', - type: '', - networkClientId: 'test', - failoverUrls: [], - }, - ], - }; - - const result = transformNetworkConfig(config); - - expect(result).toBeNull(); - }); - - it('should return null for rpcEndpoint with empty networkClientId', () => { - const config = { - ...VALID_NETWORK_CONFIG, - rpcEndpoints: [ - { - url: 'https://example.com', - type: 'custom', - networkClientId: '', - failoverUrls: [], - }, - ], - }; - - const result = transformNetworkConfig(config); - - expect(result).toBeNull(); - }); - - it('should filter invalid failoverUrls', () => { - const config = { - ...VALID_NETWORK_CONFIG, - rpcEndpoints: [ - { - url: 'https://mainnet.infura.io/v3/{infuraProjectId}', - type: 'infura', - networkClientId: 'mainnet', - failoverUrls: [ - 'valid-url', - null, - undefined, - 123, - ] as unknown as string[], - }, - ], - }; - - const result = transformNetworkConfig(config); - - expect(result?.rpcEndpoints[0].failoverUrls).toStrictEqual(['valid-url']); - }); - - it('should set failoverUrls to undefined when not an array', () => { - const config = { - ...VALID_NETWORK_CONFIG, - rpcEndpoints: [ - { - url: 'https://mainnet.infura.io/v3/{infuraProjectId}', - type: 'infura', - networkClientId: 'mainnet', - failoverUrls: 'not-an-array' as unknown as string[], - }, - ], - }; - - const result = transformNetworkConfig(config); - - expect(result?.rpcEndpoints[0].failoverUrls).toBeUndefined(); - }); - - it('should return null for invalid defaultRpcEndpointIndex', () => { - const config = { - ...VALID_NETWORK_CONFIG, - defaultRpcEndpointIndex: 10, - }; - - const result = transformNetworkConfig(config); - - expect(result).toBeNull(); - }); - - it('should return null for negative defaultRpcEndpointIndex', () => { - const config = { - ...VALID_NETWORK_CONFIG, - defaultRpcEndpointIndex: -1, - }; - - const result = transformNetworkConfig(config); - - expect(result).toBeNull(); - }); - - it('should filter invalid blockExplorerUrls', () => { - const config = { - ...VALID_NETWORK_CONFIG, - blockExplorerUrls: [ - 'https://etherscan.io', - '', - null, - undefined, - 123, - ] as unknown as string[], - }; - - const result = transformNetworkConfig(config); - - expect(result?.blockExplorerUrls).toStrictEqual(['https://etherscan.io']); - }); - - it('should return null for non-array blockExplorerUrls', () => { - const config = { - ...VALID_NETWORK_CONFIG, - blockExplorerUrls: 'not-an-array' as unknown as string[], - }; - - const result = transformNetworkConfig(config); - - expect(result).toBeNull(); - }); - - it('should return null for invalid defaultBlockExplorerUrlIndex', () => { - const config = { - ...VALID_NETWORK_CONFIG, - defaultBlockExplorerUrlIndex: 10, - }; - - const result = transformNetworkConfig(config); - - expect(result).toBeNull(); - }); - - it('should set defaultBlockExplorerUrlIndex to 0 when not provided and urls exist', () => { - const { defaultBlockExplorerUrlIndex, ...configWithoutIndex } = - VALID_NETWORK_CONFIG; - const config = { - ...configWithoutIndex, - } as NetworkConfig; - - const result = transformNetworkConfig(config); - - expect(result?.defaultBlockExplorerUrlIndex).toBe(0); - }); - - it('should set defaultBlockExplorerUrlIndex to undefined when no urls', () => { - const config = { - ...VALID_NETWORK_CONFIG, - blockExplorerUrls: [], - defaultBlockExplorerUrlIndex: 0, - }; - - const result = transformNetworkConfig(config); - - expect(result?.defaultBlockExplorerUrlIndex).toBeUndefined(); - }); - - it('should use defaultRpcEndpointIndex from config when provided', () => { - const config = { - ...VALID_NETWORK_CONFIG, - rpcEndpoints: [ - { - url: 'https://mainnet.infura.io/v3/{infuraProjectId}', - type: 'infura', - networkClientId: 'mainnet', - failoverUrls: [], - }, - { - url: 'https://backup.infura.io/v3/{infuraProjectId}', - type: 'infura', - networkClientId: 'mainnet', - failoverUrls: [], - }, - ], - defaultRpcEndpointIndex: 1, - }; - - const result = transformNetworkConfig(config); - - expect(result?.defaultRpcEndpointIndex).toBe(1); - }); - - it('should default defaultRpcEndpointIndex to 0 when not provided', () => { - const config = { - ...VALID_NETWORK_CONFIG, - rpcEndpoints: [ - { - url: 'https://mainnet.infura.io/v3/{infuraProjectId}', - type: 'infura', - networkClientId: 'mainnet', - failoverUrls: [], - }, - ], - } as NetworkConfig; - - const result = transformNetworkConfig(config); - - expect(result?.defaultRpcEndpointIndex).toBe(0); - }); - - it('should default defaultRpcEndpointIndex to 0 when undefined at runtime', () => { - const config = { - ...VALID_NETWORK_CONFIG, - rpcEndpoints: [ - { - url: 'https://mainnet.infura.io/v3/{infuraProjectId}', - type: 'infura', - networkClientId: 'mainnet', - failoverUrls: [], - }, - ], - defaultRpcEndpointIndex: undefined, - } as unknown as NetworkConfig; - - const result = transformNetworkConfig(config); - - expect(result?.defaultRpcEndpointIndex).toBe(0); - }); - - it('should adjust defaultRpcEndpointIndex when invalid endpoints are filtered out', () => { - const config = { - ...VALID_NETWORK_CONFIG, - rpcEndpoints: [ - { - url: 'https://invalid.infura.io/v3/{infuraProjectId}', - type: 'infura', - networkClientId: '', - failoverUrls: [], - }, - { - url: 'https://mainnet.infura.io/v3/{infuraProjectId}', - type: 'infura', - networkClientId: 'mainnet', - failoverUrls: [], - }, - { - url: 'https://backup.infura.io/v3/{infuraProjectId}', - type: 'infura', - networkClientId: 'mainnet', - failoverUrls: [], - }, - ], - defaultRpcEndpointIndex: 1, - }; - - const result = transformNetworkConfig(config); - - expect(result?.defaultRpcEndpointIndex).toBe(0); - expect(result?.rpcEndpoints[result.defaultRpcEndpointIndex].url).toBe( - 'https://mainnet.infura.io/v3/{infuraProjectId}', - ); - }); - - it('should return null when defaultRpcEndpointIndex points to invalid endpoint', () => { - const config = { - ...VALID_NETWORK_CONFIG, - rpcEndpoints: [ - { - url: 'https://mainnet.infura.io/v3/{infuraProjectId}', - type: 'infura', - networkClientId: 'mainnet', - failoverUrls: [], - }, - { - url: 'https://invalid.infura.io/v3/{infuraProjectId}', - type: 'infura', - networkClientId: '', - failoverUrls: [], - }, - ], - defaultRpcEndpointIndex: 1, - }; - - const result = transformNetworkConfig(config); - - expect(result).toBeNull(); - }); - - it('should adjust defaultBlockExplorerUrlIndex when invalid URLs are filtered out', () => { - const config = { - ...VALID_NETWORK_CONFIG, - blockExplorerUrls: [ - '', - 'https://etherscan.io', - 'https://blockscout.com', - ], - defaultBlockExplorerUrlIndex: 1, - }; - - const result = transformNetworkConfig(config); - - expect(result?.defaultBlockExplorerUrlIndex).toBe(0); - expect( - result?.blockExplorerUrls[result.defaultBlockExplorerUrlIndex ?? 0], - ).toBe('https://etherscan.io'); - }); - - it('should return null when defaultBlockExplorerUrlIndex points to invalid URL', () => { - const config = { - ...VALID_NETWORK_CONFIG, - blockExplorerUrls: ['https://etherscan.io', ''], - defaultBlockExplorerUrlIndex: 1, - }; - - const result = transformNetworkConfig(config); - - expect(result).toBeNull(); - }); - - it('should preserve lastUpdatedAt', () => { - const timestamp = 1234567890; - const config = { - ...VALID_NETWORK_CONFIG, - lastUpdatedAt: timestamp, - }; - - const result = transformNetworkConfig(config); - - expect(result?.lastUpdatedAt).toBe(timestamp); - }); - - it('should return null for null input', () => { - const result = transformNetworkConfig(null as unknown as NetworkConfig); - - expect(result).toBeNull(); - }); - - it('should return null for non-object input', () => { - const result = transformNetworkConfig( - 'invalid' as unknown as NetworkConfig, - ); - - expect(result).toBeNull(); - }); - }); - describe('filterNetworks', () => { const networks: NetworkConfig[] = [ { @@ -682,293 +134,4 @@ describe('transformers', () => { expect(result).toStrictEqual([]); }); }); - - describe('compareWithExistingNetworks', () => { - const existingNetworks: Record = { - '0x1': { - chainId: '0x1', - name: 'Ethereum Mainnet', - nativeCurrency: 'ETH', - rpcEndpoints: [], - blockExplorerUrls: [], - defaultRpcEndpointIndex: 0, - }, - '0x89': { - chainId: '0x89', - name: 'Polygon', - nativeCurrency: 'MATIC', - rpcEndpoints: [], - blockExplorerUrls: [], - defaultRpcEndpointIndex: 0, - }, - }; - - it('should identify new networks to add', () => { - const newNetwork: NetworkConfiguration = { - chainId: '0xa', - name: 'Optimism', - nativeCurrency: 'ETH', - rpcEndpoints: [], - blockExplorerUrls: [], - defaultRpcEndpointIndex: 0, - }; - - const result = compareWithExistingNetworks([newNetwork], { - existingNetworks, - }); - - expect(result.networksToAdd).toHaveLength(1); - expect(result.networksToAdd[0].chainId).toBe('0xa'); - expect(result.existingChainIds).toHaveLength(0); - }); - - it('should identify existing chain IDs', () => { - const existingNetwork: NetworkConfiguration = { - chainId: '0x1', - name: 'Ethereum Mainnet', - nativeCurrency: 'ETH', - rpcEndpoints: [], - blockExplorerUrls: [], - defaultRpcEndpointIndex: 0, - }; - - const result = compareWithExistingNetworks([existingNetwork], { - existingNetworks, - }); - - expect(result.networksToAdd).toHaveLength(0); - expect(result.existingChainIds).toContain('0x1'); - }); - - it('should handle mix of new and existing networks', () => { - const networks: NetworkConfiguration[] = [ - { - chainId: '0x1', - name: 'Ethereum Mainnet', - nativeCurrency: 'ETH', - rpcEndpoints: [], - blockExplorerUrls: [], - defaultRpcEndpointIndex: 0, - }, - { - chainId: '0xa', - name: 'Optimism', - nativeCurrency: 'ETH', - rpcEndpoints: [], - blockExplorerUrls: [], - defaultRpcEndpointIndex: 0, - }, - { - chainId: '0x89', - name: 'Polygon', - nativeCurrency: 'MATIC', - rpcEndpoints: [], - blockExplorerUrls: [], - defaultRpcEndpointIndex: 0, - }, - ]; - - const result = compareWithExistingNetworks(networks, { - existingNetworks, - }); - - expect(result.networksToAdd).toHaveLength(1); - expect(result.networksToAdd[0].chainId).toBe('0xa'); - expect(result.existingChainIds).toHaveLength(2); - expect(result.existingChainIds).toContain('0x1'); - expect(result.existingChainIds).toContain('0x89'); - }); - - it('should return all networks when no existing networks provided', () => { - const networks: NetworkConfiguration[] = [ - { - chainId: '0x1', - name: 'Ethereum Mainnet', - nativeCurrency: 'ETH', - rpcEndpoints: [], - blockExplorerUrls: [], - defaultRpcEndpointIndex: 0, - }, - ]; - - const result = compareWithExistingNetworks(networks, { - existingNetworks: {}, - }); - - expect(result.networksToAdd).toHaveLength(1); - expect(result.existingChainIds).toHaveLength(0); - }); - - it('should handle null existingNetworks', () => { - const networks: NetworkConfiguration[] = [ - { - chainId: '0x1', - name: 'Ethereum Mainnet', - nativeCurrency: 'ETH', - rpcEndpoints: [], - blockExplorerUrls: [], - defaultRpcEndpointIndex: 0, - }, - ]; - - const result = compareWithExistingNetworks(networks, { - existingNetworks: null as unknown as Record, - }); - - expect(result.networksToAdd).toHaveLength(1); - expect(result.existingChainIds).toHaveLength(0); - }); - - it('should skip networks without chainId', () => { - const networks: NetworkConfiguration[] = [ - { - chainId: '0x1' as Hex, - name: 'Ethereum Mainnet', - nativeCurrency: 'ETH', - rpcEndpoints: [], - blockExplorerUrls: [], - defaultRpcEndpointIndex: 0, - }, - null as unknown as NetworkConfiguration, - { - chainId: undefined as unknown as Hex, - name: 'Invalid', - nativeCurrency: 'ETH', - rpcEndpoints: [], - blockExplorerUrls: [], - defaultRpcEndpointIndex: 0, - }, - ]; - - const result = compareWithExistingNetworks(networks, { - existingNetworks, - }); - - expect(result.networksToAdd).toHaveLength(0); - expect(result.existingChainIds).toContain('0x1'); - }); - - it('should return empty arrays for non-array input', () => { - const result = compareWithExistingNetworks( - null as unknown as NetworkConfiguration[], - { - existingNetworks, - }, - ); - - expect(result.networksToAdd).toStrictEqual([]); - expect(result.existingChainIds).toStrictEqual([]); - }); - }); - - describe('processNetworkConfigs', () => { - it('should process networks without filtering or comparison', () => { - const networks = [VALID_NETWORK_CONFIG]; - - const result = processNetworkConfigs(networks); - - expect(result.networksToAdd).toHaveLength(1); - expect(result.existingChainIds).toHaveLength(0); - }); - - it('should filter networks before processing', () => { - const networks = [ - VALID_NETWORK_CONFIG, - { - ...VALID_NETWORK_CONFIG, - chainId: '0x5', - isFeatured: false, - }, - ]; - - const result = processNetworkConfigs(networks, { isFeatured: true }); - - expect(result.networksToAdd).toHaveLength(1); - expect(result.networksToAdd[0].chainId).toBe('0x1'); - }); - - it('should compare with existing networks', () => { - const existingNetworks: Record = { - '0x1': { - chainId: '0x1', - name: 'Ethereum Mainnet', - nativeCurrency: 'ETH', - rpcEndpoints: [], - blockExplorerUrls: [], - defaultRpcEndpointIndex: 0, - }, - }; - - const networks = [VALID_NETWORK_CONFIG, VALID_CUSTOM_NETWORK_CONFIG]; - - const result = processNetworkConfigs(networks, {}, { existingNetworks }); - - expect(result.networksToAdd).toHaveLength(1); - expect(result.networksToAdd[0].chainId).toBe('0x89'); - expect(result.existingChainIds).toContain('0x1'); - }); - - it('should filter invalid networks during transformation', () => { - const networks = [ - VALID_NETWORK_CONFIG, - { - ...VALID_NETWORK_CONFIG, - chainId: 'invalid', - }, - null as unknown as NetworkConfig, - ]; - - const result = processNetworkConfigs(networks); - - expect(result.networksToAdd).toHaveLength(1); - expect(result.networksToAdd[0].chainId).toBe('0x1'); - }); - - it('should return empty arrays for empty input', () => { - const result = processNetworkConfigs([]); - - expect(result.networksToAdd).toStrictEqual([]); - expect(result.existingChainIds).toStrictEqual([]); - }); - - it('should return empty arrays for non-array input', () => { - const result = processNetworkConfigs(null as unknown as NetworkConfig[]); - - expect(result.networksToAdd).toStrictEqual([]); - expect(result.existingChainIds).toStrictEqual([]); - }); - - it('should combine filtering and comparison', () => { - const existingNetworks: Record = { - '0x1': { - chainId: '0x1', - name: 'Ethereum Mainnet', - nativeCurrency: 'ETH', - rpcEndpoints: [], - blockExplorerUrls: [], - defaultRpcEndpointIndex: 0, - }, - }; - - const networks = [ - VALID_NETWORK_CONFIG, - { - ...VALID_NETWORK_CONFIG, - chainId: '0x5', - isFeatured: false, - }, - VALID_CUSTOM_NETWORK_CONFIG, - ]; - - const result = processNetworkConfigs( - networks, - { isFeatured: true }, - { existingNetworks }, - ); - - expect(result.networksToAdd).toHaveLength(1); - expect(result.networksToAdd[0].chainId).toBe('0x89'); - expect(result.existingChainIds).toContain('0x1'); - }); - }); }); diff --git a/packages/config-registry-controller/src/config-registry-api-service/transformers.ts b/packages/config-registry-controller/src/config-registry-api-service/transformers.ts index ee374bf4900..225411522b0 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/transformers.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/transformers.ts @@ -1,10 +1,4 @@ -import type { NetworkConfiguration } from '@metamask/network-controller'; -import { RpcEndpointType } from '@metamask/network-controller'; -import type { Hex } from '@metamask/utils'; - -import type { NetworkConfig } from './abstract-config-registry-api-service'; - -type RpcEndpoint = NetworkConfiguration['rpcEndpoints'][number]; +import type { NetworkConfig } from './types'; export type NetworkFilterOptions = { isFeatured?: boolean; @@ -14,207 +8,6 @@ export type NetworkFilterOptions = { isDefault?: boolean; }; -export type NetworkComparisonOptions = { - existingNetworks: Record; -}; - -export type TransformedNetworkResult = { - networksToAdd: NetworkConfiguration[]; - existingChainIds: Hex[]; -}; - -/** - * @param chainId - The chain ID as a string. - * @returns The chain ID as Hex, or null if invalid. - */ -function toHexChainId(chainId: string): Hex | null { - if (!chainId || typeof chainId !== 'string') { - return null; - } - - const trimmed = chainId.trim(); - - if (trimmed.startsWith('0x') || trimmed.startsWith('0X')) { - const hexValue = trimmed.toLowerCase(); - if (!/^0x[0-9a-f]+$/iu.test(hexValue)) { - return null; - } - return hexValue as Hex; - } - - const decimal = Number.parseInt(trimmed, 10); - if (Number.isNaN(decimal) || decimal < 0) { - return null; - } - - return `0x${decimal.toString(16)}`; -} - -/** - * @param endpoint - The RPC endpoint from the API. - * @returns The transformed RPC endpoint, or null if invalid. - */ -function transformRpcEndpoint( - endpoint: NetworkConfig['rpcEndpoints'][0], -): RpcEndpoint | null { - if (!endpoint || typeof endpoint !== 'object') { - return null; - } - - const { url, type, networkClientId, failoverUrls } = endpoint; - - if (!url || typeof url !== 'string') { - return null; - } - - if (!type || typeof type !== 'string') { - return null; - } - - if (!networkClientId || typeof networkClientId !== 'string') { - return null; - } - - const baseEndpoint = { - networkClientId, - failoverUrls: Array.isArray(failoverUrls) - ? failoverUrls.filter( - (failoverUrl): failoverUrl is string => - typeof failoverUrl === 'string', - ) - : undefined, - }; - - if (type === 'infura') { - return { - ...baseEndpoint, - type: RpcEndpointType.Infura, - url: url as `https://${string}.infura.io/v3/{infuraProjectId}`, - } as RpcEndpoint; - } - - if (type === 'custom') { - return { - ...baseEndpoint, - type: RpcEndpointType.Custom, - url, - } as RpcEndpoint; - } - - return null; -} - -/** - * @param networkConfig - The network configuration from the API. - * @returns The transformed network configuration, or null if invalid. - */ -export function transformNetworkConfig( - networkConfig: NetworkConfig, -): NetworkConfiguration | null { - if (!networkConfig || typeof networkConfig !== 'object') { - return null; - } - - const chainId = toHexChainId(networkConfig.chainId); - if (!chainId) { - return null; - } - - const { name, nativeCurrency, rpcEndpoints, blockExplorerUrls } = - networkConfig; - - if (!name || typeof name !== 'string') { - return null; - } - - if (!nativeCurrency || typeof nativeCurrency !== 'string') { - return null; - } - - if (!Array.isArray(rpcEndpoints) || rpcEndpoints.length === 0) { - return null; - } - - // Transform endpoints and track original indices to filtered indices mapping - const transformedEndpoints: RpcEndpoint[] = []; - const originalToFilteredIndexMap = new Map(); - - rpcEndpoints.forEach((endpoint, originalIndex) => { - const transformed = transformRpcEndpoint(endpoint); - if (transformed !== null) { - originalToFilteredIndexMap.set( - originalIndex, - transformedEndpoints.length, - ); - transformedEndpoints.push(transformed); - } - }); - - if (transformedEndpoints.length === 0) { - return null; - } - - // Adjust defaultRpcEndpointIndex to account for filtered endpoints - const originalDefaultRpcEndpointIndex = - networkConfig.defaultRpcEndpointIndex ?? 0; - const adjustedDefaultRpcEndpointIndex = originalToFilteredIndexMap.get( - originalDefaultRpcEndpointIndex, - ); - - if (adjustedDefaultRpcEndpointIndex === undefined) { - // The original default index pointed to an invalid endpoint - return null; - } - - if (!Array.isArray(blockExplorerUrls)) { - return null; - } - - // Filter block explorer URLs and track original indices to filtered indices mapping - const validBlockExplorerUrls: string[] = []; - const blockExplorerOriginalToFilteredIndexMap = new Map(); - - blockExplorerUrls.forEach((blockExplorerUrl, originalIndex) => { - if (typeof blockExplorerUrl === 'string' && blockExplorerUrl.length > 0) { - blockExplorerOriginalToFilteredIndexMap.set( - originalIndex, - validBlockExplorerUrls.length, - ); - validBlockExplorerUrls.push(blockExplorerUrl); - } - }); - - // Adjust defaultBlockExplorerUrlIndex to account for filtered URLs - const { defaultBlockExplorerUrlIndex } = networkConfig; - let adjustedDefaultBlockExplorerUrlIndex: number | undefined; - - if (defaultBlockExplorerUrlIndex !== undefined) { - const adjusted = blockExplorerOriginalToFilteredIndexMap.get( - defaultBlockExplorerUrlIndex, - ); - - if (adjusted === undefined) { - // The original default index pointed to an invalid URL - return null; - } - - adjustedDefaultBlockExplorerUrlIndex = adjusted; - } else if (validBlockExplorerUrls.length > 0) { - adjustedDefaultBlockExplorerUrlIndex = 0; - } - - return { - chainId, - name, - nativeCurrency, - rpcEndpoints: transformedEndpoints, - blockExplorerUrls: validBlockExplorerUrls, - defaultRpcEndpointIndex: adjustedDefaultRpcEndpointIndex, - defaultBlockExplorerUrlIndex: adjustedDefaultBlockExplorerUrlIndex, - lastUpdatedAt: networkConfig.lastUpdatedAt, - }; -} - /** * @param networks - Array of network configurations to filter. * @param options - Filter options. @@ -266,84 +59,3 @@ export function filterNetworks( return true; }); } - -/** - * @param transformedNetworks - Array of transformed network configurations. - * @param options - Comparison options. - * @returns Result containing networks to add and existing chain IDs. - */ -export function compareWithExistingNetworks( - transformedNetworks: NetworkConfiguration[], - options: NetworkComparisonOptions, -): TransformedNetworkResult { - if (!Array.isArray(transformedNetworks)) { - return { - networksToAdd: [], - existingChainIds: [], - }; - } - - const { existingNetworks } = options; - - if (!existingNetworks || typeof existingNetworks !== 'object') { - return { - networksToAdd: transformedNetworks, - existingChainIds: [], - }; - } - - const existingChainIds = new Set(Object.keys(existingNetworks) as Hex[]); - const networksToAdd: NetworkConfiguration[] = []; - const foundExistingChainIds: Hex[] = []; - - for (const network of transformedNetworks) { - if (!network?.chainId) { - continue; - } - - if (existingChainIds.has(network.chainId)) { - foundExistingChainIds.push(network.chainId); - } else { - networksToAdd.push(network); - } - } - - return { - networksToAdd, - existingChainIds: foundExistingChainIds, - }; -} - -/** - * @param networks - Array of network configurations from the API. - * @param filterOptions - Options for filtering networks. - * @param comparisonOptions - Options for comparing with existing networks. - * @returns Result containing networks to add and existing chain IDs. - */ -export function processNetworkConfigs( - networks: NetworkConfig[], - filterOptions: NetworkFilterOptions = {}, - comparisonOptions?: NetworkComparisonOptions, -): TransformedNetworkResult { - if (!Array.isArray(networks) || networks.length === 0) { - return { - networksToAdd: [], - existingChainIds: [], - }; - } - - const filteredNetworks = filterNetworks(networks, filterOptions); - - const transformedNetworks = filteredNetworks - .map(transformNetworkConfig) - .filter((network): network is NetworkConfiguration => network !== null); - - if (comparisonOptions) { - return compareWithExistingNetworks(transformedNetworks, comparisonOptions); - } - - return { - networksToAdd: transformedNetworks, - existingChainIds: [], - }; -} diff --git a/packages/config-registry-controller/src/config-registry-api-service/types.ts b/packages/config-registry-controller/src/config-registry-api-service/types.ts new file mode 100644 index 00000000000..1021404c259 --- /dev/null +++ b/packages/config-registry-controller/src/config-registry-api-service/types.ts @@ -0,0 +1,98 @@ +import { + array, + assert, + boolean, + number, + optional, + string, + type, +} from '@metamask/superstruct'; + +const RpcEndpointSchema = type({ + url: string(), + type: string(), + networkClientId: string(), + failoverUrls: array(string()), +}); + +export const NetworkConfigSchema = type({ + chainId: string(), + name: string(), + nativeCurrency: string(), + rpcEndpoints: array(RpcEndpointSchema), + blockExplorerUrls: array(string()), + defaultRpcEndpointIndex: number(), + defaultBlockExplorerUrlIndex: number(), + lastUpdatedAt: optional(number()), + networkImageUrl: optional(string()), + nativeTokenImageUrl: optional(string()), + isActive: boolean(), + isTestnet: boolean(), + isDefault: boolean(), + isFeatured: boolean(), + isDeprecated: boolean(), + priority: number(), + isDeletable: boolean(), +}); + +export const RegistryConfigApiResponseSchema = type({ + data: type({ + version: string(), + timestamp: number(), + networks: array(NetworkConfigSchema), + }), +}); + +export type NetworkConfig = { + chainId: string; + name: string; + nativeCurrency: string; + rpcEndpoints: { + url: string; + type: string; + networkClientId: string; + failoverUrls: string[]; + }[]; + blockExplorerUrls: string[]; + defaultRpcEndpointIndex: number; + defaultBlockExplorerUrlIndex: number; + lastUpdatedAt?: number; + networkImageUrl?: string; + nativeTokenImageUrl?: string; + isActive: boolean; + isTestnet: boolean; + isDefault: boolean; + isFeatured: boolean; + isDeprecated: boolean; + priority: number; + isDeletable: boolean; +}; + +export type RegistryConfigApiResponse = { + data: { + version: string; + timestamp: number; + networks: NetworkConfig[]; + }; +}; + +export function validateRegistryConfigApiResponse( + data: unknown, +): asserts data is RegistryConfigApiResponse { + assert(data, RegistryConfigApiResponseSchema); +} + +export type FetchConfigOptions = { + etag?: string; +}; + +export type FetchConfigResult = + | { + modified: false; + etag?: string; + } + | { + modified: true; + data: RegistryConfigApiResponse; + etag?: string; + }; diff --git a/packages/config-registry-controller/src/index.ts b/packages/config-registry-controller/src/index.ts index 69876346159..af49ffef6b5 100644 --- a/packages/config-registry-controller/src/index.ts +++ b/packages/config-registry-controller/src/index.ts @@ -1,5 +1,4 @@ export type { - RegistryConfigEntry, ConfigRegistryState, ConfigRegistryControllerOptions, ConfigRegistryControllerActions, @@ -15,7 +14,6 @@ export { DEFAULT_POLLING_INTERVAL, } from './ConfigRegistryController'; export type { - AbstractConfigRegistryApiService, FetchConfigOptions, FetchConfigResult, NetworkConfig, @@ -25,9 +23,7 @@ export type { } from './config-registry-api-service'; export { ConfigRegistryApiService, - DEFAULT_API_BASE_URL, - DEFAULT_ENDPOINT_PATH, - DEFAULT_TIMEOUT, + getConfigRegistryUrl, filterNetworks, } from './config-registry-api-service'; export { isConfigRegistryApiEnabled } from './utils/feature-flags'; diff --git a/packages/config-registry-controller/tsconfig.build.json b/packages/config-registry-controller/tsconfig.build.json index 82ca2753631..7121fac78a0 100644 --- a/packages/config-registry-controller/tsconfig.build.json +++ b/packages/config-registry-controller/tsconfig.build.json @@ -12,6 +12,7 @@ { "path": "../messenger/tsconfig.build.json" }, { "path": "../network-controller/tsconfig.build.json" }, { "path": "../polling-controller/tsconfig.build.json" }, + { "path": "../profile-sync-controller/tsconfig.build.json" }, { "path": "../remote-feature-flag-controller/tsconfig.build.json" } ], "include": ["../../types", "./src"] diff --git a/packages/config-registry-controller/tsconfig.json b/packages/config-registry-controller/tsconfig.json index 3110ea21c05..50680bda9f6 100644 --- a/packages/config-registry-controller/tsconfig.json +++ b/packages/config-registry-controller/tsconfig.json @@ -10,6 +10,7 @@ { "path": "../messenger" }, { "path": "../network-controller" }, { "path": "../polling-controller" }, + { "path": "../profile-sync-controller" }, { "path": "../remote-feature-flag-controller" } ], "include": ["../../types", "./src"] diff --git a/yarn.lock b/yarn.lock index c9ef2240e03..2944e96f5ef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2983,7 +2983,9 @@ __metadata: "@metamask/messenger": "npm:^0.3.0" "@metamask/network-controller": "npm:^29.0.0" "@metamask/polling-controller": "npm:^16.0.2" + "@metamask/profile-sync-controller": "npm:^27.0.0" "@metamask/remote-feature-flag-controller": "npm:^4.0.0" + "@metamask/superstruct": "npm:^3.1.0" "@metamask/utils": "npm:^11.9.0" "@ts-bridge/cli": "npm:^0.6.4" "@types/jest": "npm:^27.4.1" From e53de80cf14512a6f1aff8234b45e376c7a994db Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Sun, 25 Jan 2026 16:16:15 +0100 Subject: [PATCH 23/55] fix: fix lint --- .../src/ConfigRegistryController.test.ts | 721 ++++++------------ .../src/ConfigRegistryController.ts | 31 +- tests/fake-provider.ts | 55 +- 3 files changed, 285 insertions(+), 522 deletions(-) diff --git a/packages/config-registry-controller/src/ConfigRegistryController.test.ts b/packages/config-registry-controller/src/ConfigRegistryController.test.ts index 0a525136560..01f663fe6a7 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.test.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.test.ts @@ -184,9 +184,7 @@ async function withController( args.length === 2 ? args : [{}, args[0]]; const clock = useFakeTimers(); - const messengers = getConfigRegistryControllerMessenger(); - const messenger = messengers.messenger; - const rootMessenger = messengers.rootMessenger; + const { messenger, rootMessenger } = getConfigRegistryControllerMessenger(); const mockApiServiceHandler = jest.fn(buildMockApiServiceHandler()); rootMessenger.registerActionHandler( @@ -237,10 +235,9 @@ async function withController( } describe('ConfigRegistryController', () => { - describe('constructor', () => { - it('should set default state', () => { - return withController(({ controller }) => { + it('should set default state', async () => { + await withController(({ controller }) => { expect(controller.state).toStrictEqual({ configs: { networks: {} }, version: null, @@ -251,7 +248,7 @@ describe('ConfigRegistryController', () => { }); }); - it('should set initial state when provided', () => { + it('should set initial state when provided', async () => { const initialState: Partial = { configs: { networks: { @@ -262,7 +259,7 @@ describe('ConfigRegistryController', () => { lastFetched: 1234567890, }; - return withController( + await withController( { options: { state: initialState } }, ({ controller }) => { expect(controller.state.configs.networks).toStrictEqual( @@ -274,9 +271,9 @@ describe('ConfigRegistryController', () => { ); }); - it('should set custom polling interval', () => { + it('should set custom polling interval', async () => { const customInterval = 5000; - return withController( + await withController( { options: { pollingInterval: customInterval } }, ({ controller }) => { expect(controller.getIntervalLength()).toBe(customInterval); @@ -284,8 +281,8 @@ describe('ConfigRegistryController', () => { ); }); - it('should set fallback config', () => { - return withController( + it('should set fallback config', async () => { + await withController( { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, ({ controller }) => { expect(controller.state.configs).toStrictEqual({ @@ -295,8 +292,8 @@ describe('ConfigRegistryController', () => { ); }); - it('should work when API service is registered on messenger', () => { - return withController(({ controller }) => { + it('should work when API service is registered on messenger', async () => { + await withController(({ controller }) => { expect(controller.state).toStrictEqual({ configs: { networks: {} }, version: null, @@ -310,7 +307,7 @@ describe('ConfigRegistryController', () => { describe('polling', () => { it('should start polling', async () => { - return withController(async ({ controller, clock }) => { + await withController(async ({ controller, clock }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); controller.startPolling(null); @@ -323,7 +320,7 @@ describe('ConfigRegistryController', () => { it('should poll at specified interval', async () => { const pollingInterval = 1000; - return withController( + await withController( { options: { pollingInterval } }, async ({ controller, clock }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); @@ -341,7 +338,7 @@ describe('ConfigRegistryController', () => { }); it('should stop polling', async () => { - return withController(async ({ controller, clock }) => { + await withController(async ({ controller, clock }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); controller.startPolling(null); @@ -357,14 +354,9 @@ describe('ConfigRegistryController', () => { }); it('should use fallback config when no configs exist', async () => { - return withController( + await withController( { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, - async ({ - controller, - mockRemoteFeatureFlagGetState, - mockApiServiceHandler, - rootMessenger, - }) => { + async ({ mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { configRegistryApiEnabled: true, @@ -465,18 +457,14 @@ describe('ConfigRegistryController', () => { }, }; - return withController( + await withController( { options: { state: { configs: existingConfigs }, fallbackConfig: MOCK_FALLBACK_CONFIG, }, }, - async ({ - mockRemoteFeatureFlagGetState, - mockApiServiceHandler, - rootMessenger, - }) => { + async ({ mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { configRegistryApiEnabled: true, @@ -564,12 +552,9 @@ describe('ConfigRegistryController', () => { }); it('should handle errors during polling', async () => { - return withController( + await withController( { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, - async ({ - mockRemoteFeatureFlagGetState, - mockApiServiceHandler, - }) => { + async ({ mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { mockRemoteFeatureFlagGetState.mockReturnValueOnce({ remoteFeatureFlags: { configRegistryApiEnabled: true, @@ -659,7 +644,7 @@ describe('ConfigRegistryController', () => { }); it('should handle unmodified response and clear fetchError', async () => { - return withController( + await withController( { options: { state: { @@ -702,7 +687,7 @@ describe('ConfigRegistryController', () => { }); it('should handle unmodified response and preserve existing etag when not provided', async () => { - return withController( + await withController( { options: { state: { @@ -745,7 +730,7 @@ describe('ConfigRegistryController', () => { }); it('should handle unmodified response and set etag to null when explicitly null', async () => { - return withController( + await withController( { options: { state: { @@ -789,7 +774,7 @@ describe('ConfigRegistryController', () => { }); it('should handle validation error from service', async () => { - return withController( + await withController( async ({ mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { @@ -798,7 +783,9 @@ describe('ConfigRegistryController', () => { cacheTimestamp: Date.now(), }); - const validationError = new Error('Validation error from superstruct'); + const validationError = new Error( + 'Validation error from superstruct', + ); mockApiServiceHandler.mockRejectedValue(validationError); const captureExceptionSpy = jest.fn(); @@ -881,8 +868,12 @@ describe('ConfigRegistryController', () => { }); it('should handle validation error when result.data.data is missing', async () => { - return withController( - async ({ controller, mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { + await withController( + async ({ + controller, + mockRemoteFeatureFlagGetState, + mockApiServiceHandler, + }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { configRegistryApiEnabled: true, @@ -890,7 +881,9 @@ describe('ConfigRegistryController', () => { cacheTimestamp: Date.now(), }); - const validationError = new Error('Validation error: data.data is missing'); + const validationError = new Error( + 'Validation error: data.data is missing', + ); mockApiServiceHandler.mockRejectedValue(validationError); await controller._executePoll(null); @@ -903,8 +896,12 @@ describe('ConfigRegistryController', () => { }); it('should handle validation error when result.data.data.networks is not an array', async () => { - return withController( - async ({ controller, mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { + await withController( + async ({ + controller, + mockRemoteFeatureFlagGetState, + mockApiServiceHandler, + }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { configRegistryApiEnabled: true, @@ -927,8 +924,12 @@ describe('ConfigRegistryController', () => { }); it('should handle validation error when result.data.data.version is not a string', async () => { - return withController( - async ({ controller, mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { + await withController( + async ({ + controller, + mockRemoteFeatureFlagGetState, + mockApiServiceHandler, + }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { configRegistryApiEnabled: true, @@ -952,7 +953,7 @@ describe('ConfigRegistryController', () => { it('should skip fetch when lastFetched is within polling interval', async () => { const recentTimestamp = Date.now() - 1000; - return withController( + await withController( { options: { state: { @@ -968,7 +969,10 @@ describe('ConfigRegistryController', () => { cacheTimestamp: Date.now(), }); - const fetchConfigSpy = jest.spyOn(messenger, 'call') as jest.SpyInstance; + const fetchConfigSpy = jest.spyOn( + messenger, + 'call', + ) as jest.SpyInstance; await controller._executePoll(null); @@ -981,7 +985,7 @@ describe('ConfigRegistryController', () => { }); it('should proceed with fetch when lastFetched is null', async () => { - return withController( + await withController( { options: { state: { @@ -1028,7 +1032,7 @@ describe('ConfigRegistryController', () => { it('should proceed with fetch when enough time has passed since lastFetched', async () => { const now = Date.now(); const oldTimestamp = now - DEFAULT_POLLING_INTERVAL - 1000; - return withController( + await withController( { options: { state: { @@ -1079,7 +1083,7 @@ describe('ConfigRegistryController', () => { it('should use custom polling interval when checking lastFetched', async () => { const customInterval = 5000; const recentTimestamp = Date.now() - 3000; - return withController( + await withController( { options: { pollingInterval: customInterval, @@ -1096,7 +1100,10 @@ describe('ConfigRegistryController', () => { cacheTimestamp: Date.now(), }); - const fetchConfigSpy = jest.spyOn(messenger, 'call') as jest.SpyInstance; + const fetchConfigSpy = jest.spyOn( + messenger, + 'call', + ) as jest.SpyInstance; await controller._executePoll(null); @@ -1110,7 +1117,7 @@ describe('ConfigRegistryController', () => { it('should use DEFAULT_POLLING_INTERVAL when getIntervalLength returns undefined', async () => { const recentTimestamp = Date.now() - 1000; - return withController( + await withController( { options: { state: { @@ -1126,9 +1133,14 @@ describe('ConfigRegistryController', () => { cacheTimestamp: Date.now(), }); - jest.spyOn(controller, 'getIntervalLength').mockReturnValue(undefined); + jest + .spyOn(controller, 'getIntervalLength') + .mockReturnValue(undefined); - const fetchConfigSpy = jest.spyOn(messenger, 'call') as jest.SpyInstance; + const fetchConfigSpy = jest.spyOn( + messenger, + 'call', + ) as jest.SpyInstance; await controller._executePoll(null); @@ -1141,7 +1153,7 @@ describe('ConfigRegistryController', () => { }); it('should handle non-Error exceptions', async () => { - return withController( + await withController( { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, async ({ mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ @@ -1226,13 +1238,15 @@ describe('ConfigRegistryController', () => { expect(testController.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG, }); - expect(testController.state.fetchError).toBe('Unknown error occurred'); + expect(testController.state.fetchError).toBe( + 'Unknown error occurred', + ); }, ); }); it('should handle error when state.configs is null', async () => { - return withController( + await withController( { options: { fallbackConfig: MOCK_FALLBACK_CONFIG, @@ -1331,7 +1345,7 @@ describe('ConfigRegistryController', () => { }); it('should work via messenger actions', async () => { - return withController(async ({ controller, messenger, clock }) => { + await withController(async ({ controller, messenger, clock }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); const token = messenger.call( @@ -1351,8 +1365,8 @@ describe('ConfigRegistryController', () => { }); describe('state persistence', () => { - it('should persist version', () => { - return withController( + it('should persist version', async () => { + await withController( { options: { state: { version: 'v1.0.0' } } }, ({ controller }) => { expect(controller.state.version).toBe('v1.0.0'); @@ -1360,9 +1374,9 @@ describe('ConfigRegistryController', () => { ); }); - it('should persist lastFetched', () => { + it('should persist lastFetched', async () => { const timestamp = Date.now(); - return withController( + await withController( { options: { state: { lastFetched: timestamp } } }, ({ controller }) => { expect(controller.state.lastFetched).toBe(timestamp); @@ -1370,8 +1384,8 @@ describe('ConfigRegistryController', () => { ); }); - it('should persist fetchError', () => { - return withController( + it('should persist fetchError', async () => { + await withController( { options: { state: { fetchError: 'Test error' } } }, ({ controller }) => { expect(controller.state.fetchError).toBe('Test error'); @@ -1379,8 +1393,8 @@ describe('ConfigRegistryController', () => { ); }); - it('should use default error message when useFallbackConfig is called without errorMessage', () => { - return withController( + it('should use default error message when useFallbackConfig is called without errorMessage', async () => { + await withController( { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, ({ controller }) => { // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -1399,8 +1413,8 @@ describe('ConfigRegistryController', () => { }); describe('startPolling', () => { - it('should return a polling token string', () => { - return withController(({ controller }) => { + it('should return a polling token string', async () => { + await withController(({ controller }) => { const token = controller.startPolling(null); expect(typeof token).toBe('string'); expect(token.length).toBeGreaterThan(0); @@ -1409,8 +1423,8 @@ describe('ConfigRegistryController', () => { }); }); - it('should return a polling token string when called without input', () => { - return withController(({ controller }) => { + it('should return a polling token string when called without input', async () => { + await withController(({ controller }) => { const token = controller.startPolling(null); expect(typeof token).toBe('string'); expect(token.length).toBeGreaterThan(0); @@ -1423,7 +1437,7 @@ describe('ConfigRegistryController', () => { const pollingInterval = 10000; const recentTimestamp = Date.now() - 2000; const remainingTime = pollingInterval - 2000; - return withController( + await withController( { options: { pollingInterval, @@ -1448,7 +1462,7 @@ describe('ConfigRegistryController', () => { }); it('should proceed immediately when lastFetched is null', async () => { - return withController( + await withController( { options: { state: { @@ -1472,7 +1486,7 @@ describe('ConfigRegistryController', () => { const pollingInterval = 10000; const now = Date.now(); const oldTimestamp = now - pollingInterval - 1000; - return withController( + await withController( { options: { pollingInterval, @@ -1499,7 +1513,7 @@ describe('ConfigRegistryController', () => { const pollingInterval = 10000; const now = Date.now(); const exactTimestamp = now - pollingInterval - 1; - return withController( + await withController( { options: { pollingInterval, @@ -1524,7 +1538,7 @@ describe('ConfigRegistryController', () => { it('should use DEFAULT_POLLING_INTERVAL when getIntervalLength returns undefined', async () => { const recentTimestamp = Date.now() - 1000; - return withController( + await withController( { options: { state: { @@ -1533,7 +1547,9 @@ describe('ConfigRegistryController', () => { }, }, async ({ controller, clock }) => { - jest.spyOn(controller, 'getIntervalLength').mockReturnValue(undefined); + jest + .spyOn(controller, 'getIntervalLength') + .mockReturnValue(undefined); const executePollSpy = jest.spyOn(controller, '_executePoll'); controller.startPolling(null); @@ -1549,7 +1565,7 @@ describe('ConfigRegistryController', () => { it('should clear existing timeout when startPolling is called multiple times', async () => { const pollingInterval = 10000; const recentTimestamp = Date.now() - 2000; - return withController( + await withController( { options: { pollingInterval, @@ -1561,12 +1577,12 @@ describe('ConfigRegistryController', () => { async ({ controller, clock }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); const clearTimeoutSpy = jest.spyOn(global, 'clearTimeout'); - + // First call sets a timeout controller.startPolling(null); await advanceTime({ clock, duration: 0 }); expect(executePollSpy).not.toHaveBeenCalled(); - + const clearTimeoutCallCountBefore = clearTimeoutSpy.mock.calls.length; // Second call should clear the existing timeout (from first call) and set a new one @@ -1574,9 +1590,11 @@ describe('ConfigRegistryController', () => { controller.startPolling(null); await advanceTime({ clock, duration: 0 }); expect(executePollSpy).not.toHaveBeenCalled(); - + // Verify clearTimeout was called to clear the previous timeout - expect(clearTimeoutSpy.mock.calls.length).toBeGreaterThan(clearTimeoutCallCountBefore); + expect(clearTimeoutSpy.mock.calls.length).toBeGreaterThan( + clearTimeoutCallCountBefore, + ); controller.stopPolling(); }, @@ -1586,7 +1604,7 @@ describe('ConfigRegistryController', () => { describe('feature flag', () => { it('should use fallback config when feature flag is disabled', async () => { - return withController( + await withController( { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, async ({ controller, clock, mockRemoteFeatureFlagGetState }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ @@ -1615,8 +1633,12 @@ describe('ConfigRegistryController', () => { }); it('should use API when feature flag is enabled', async () => { - return withController( - async ({ controller, mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { + await withController( + async ({ + controller, + mockRemoteFeatureFlagGetState, + mockApiServiceHandler, + }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { configRegistryApiEnabled: true, @@ -1670,15 +1692,17 @@ describe('ConfigRegistryController', () => { expect(controller.state.configs.networks?.['0x1']).toBeDefined(); expect(controller.state.version).toBe('1.0.0'); expect(controller.state.fetchError).toBeNull(); - - controller.stopPolling(); }, ); }); it('should filter networks to only include featured, active, non-testnet networks', async () => { - return withController( - async ({ controller, mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { + await withController( + async ({ + controller, + mockRemoteFeatureFlagGetState, + mockApiServiceHandler, + }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { configRegistryApiEnabled: true, @@ -1801,15 +1825,15 @@ describe('ConfigRegistryController', () => { expect(controller.state.configs.networks?.['0x5']).toBeUndefined(); expect(controller.state.configs.networks?.['0xa']).toBeUndefined(); expect(controller.state.configs.networks?.['0x89']).toBeUndefined(); - expect(Object.keys(controller.state.configs.networks ?? {})).toHaveLength( - 1, - ); + expect( + Object.keys(controller.state.configs.networks ?? {}), + ).toHaveLength(1); }, ); }); it('should handle duplicate chainIds by keeping highest priority network and logging warning', async () => { - return withController( + await withController( async ({ mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { @@ -1981,12 +2005,12 @@ describe('ConfigRegistryController', () => { // Verify highest priority network was kept expect(testController.state.configs.networks?.['0x1']).toBeDefined(); - expect(testController.state.configs.networks?.['0x1']?.value.name).toBe( - 'Ethereum Mainnet (High Priority)', - ); expect( - testController.state.configs.networks?.['0x1']?.value.rpcEndpoints[0] - .type, + testController.state.configs.networks?.['0x1']?.value.name, + ).toBe('Ethereum Mainnet (High Priority)'); + expect( + testController.state.configs.networks?.['0x1']?.value + .rpcEndpoints[0].type, ).toBe('alchemy'); // Verify other networks are still present @@ -1996,7 +2020,7 @@ describe('ConfigRegistryController', () => { }); it('should handle duplicate chainIds with same priority by keeping first occurrence', async () => { - return withController( + await withController( async ({ mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { @@ -2142,357 +2166,17 @@ describe('ConfigRegistryController', () => { // Verify first occurrence was kept (since priorities are equal) expect(testController.state.configs.networks?.['0x1']).toBeDefined(); - expect(testController.state.configs.networks?.['0x1']?.value.name).toBe( - 'Ethereum Mainnet (First)', - ); - }, - ); - }); - - it('should handle duplicate chainIds by keeping highest priority network and logging warning', async () => { - return withController( - async ({ controller, mockRemoteFeatureFlagGetState, mockApiServiceHandler, rootMessenger }) => { - mockRemoteFeatureFlagGetState.mockReturnValue({ - remoteFeatureFlags: { - configRegistryApiEnabled: true, - }, - cacheTimestamp: Date.now(), - }); - - const captureExceptionSpy = jest.fn(); - const testRootMessenger = new Messenger< - MockAnyNamespace, - | { - type: 'RemoteFeatureFlagController:getState'; - handler: () => unknown; - } - | { - type: 'KeyringController:getState'; - handler: () => { isUnlocked: boolean }; - } - | { - type: 'ConfigRegistryApiService:fetchConfig'; - handler: (options?: { - etag?: string; - }) => Promise; - }, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] } - >({ - namespace: MOCK_ANY_NAMESPACE, - captureException: captureExceptionSpy, - }); - - const testMessenger = new Messenger< - typeof namespace, - never, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] }, - typeof testRootMessenger - >({ - namespace, - parent: testRootMessenger, - }) as ConfigRegistryMessenger; - - testRootMessenger.registerActionHandler( - 'ConfigRegistryApiService:fetchConfig', - mockApiServiceHandler, - ); - testRootMessenger.registerActionHandler( - 'RemoteFeatureFlagController:getState', - mockRemoteFeatureFlagGetState, - ); - testRootMessenger.registerActionHandler( - 'KeyringController:getState', - jest.fn().mockReturnValue({ isUnlocked: false }), - ); - testRootMessenger.delegate({ - messenger: testMessenger, - actions: [ - 'RemoteFeatureFlagController:getState', - 'KeyringController:getState', - 'ConfigRegistryApiService:fetchConfig', - ] as never[], - events: [ - 'KeyringController:unlock', - 'KeyringController:lock', - ] as never[], - }); - - const testController = new ConfigRegistryController({ - messenger: testMessenger, - }); - - // Mock API response with duplicate chainIds - const mockNetworks = [ - { - chainId: '0x1', - name: 'Ethereum Mainnet (Low Priority)', - nativeCurrency: 'ETH', - rpcEndpoints: [ - { - url: 'https://mainnet.infura.io/v3/{infuraProjectId}', - type: 'infura', - networkClientId: 'mainnet', - failoverUrls: [], - }, - ], - blockExplorerUrls: ['https://etherscan.io'], - defaultRpcEndpointIndex: 0, - defaultBlockExplorerUrlIndex: 0, - isTestnet: false, - isFeatured: true, - isActive: true, - isDefault: false, - isDeprecated: false, - priority: 10, // Lower priority (higher number) - isDeletable: false, - }, - { - chainId: '0x1', - name: 'Ethereum Mainnet (High Priority)', - nativeCurrency: 'ETH', - rpcEndpoints: [ - { - url: 'https://mainnet.alchemy.io/v2/{alchemyApiKey}', - type: 'alchemy', - networkClientId: 'mainnet-alchemy', - failoverUrls: [], - }, - ], - blockExplorerUrls: ['https://etherscan.io'], - defaultRpcEndpointIndex: 0, - defaultBlockExplorerUrlIndex: 0, - isTestnet: false, - isFeatured: true, - isActive: true, - isDefault: false, - isDeprecated: false, - priority: 0, // Higher priority (lower number) - isDeletable: false, - }, - { - chainId: '0x89', - name: 'Polygon', - nativeCurrency: 'MATIC', - rpcEndpoints: [ - { - url: 'https://polygon.infura.io/v3/{infuraProjectId}', - type: 'infura', - networkClientId: 'polygon', - failoverUrls: [], - }, - ], - blockExplorerUrls: ['https://polygonscan.com'], - defaultRpcEndpointIndex: 0, - defaultBlockExplorerUrlIndex: 0, - isTestnet: false, - isFeatured: true, - isActive: true, - isDefault: false, - isDeprecated: false, - priority: 0, - isDeletable: false, - }, - ]; - - mockApiServiceHandler.mockResolvedValue({ - data: { - data: { - version: '1.0.0', - timestamp: Date.now(), - networks: mockNetworks, - }, - }, - modified: true, - etag: 'test-etag', - }); - - await testController._executePoll(null); - - // Verify warning was logged - expect(captureExceptionSpy).toHaveBeenCalled(); - const warningCall = captureExceptionSpy.mock.calls.find((call) => - call[0]?.message?.includes('Duplicate chainId 0x1'), - ); - expect(warningCall).toBeDefined(); - expect(warningCall?.[0]?.message).toContain( - 'Ethereum Mainnet (Low Priority), Ethereum Mainnet (High Priority)', - ); - - // Verify highest priority network was kept - expect(testController.state.configs.networks?.['0x1']).toBeDefined(); - expect(testController.state.configs.networks?.['0x1']?.value.name).toBe( - 'Ethereum Mainnet (High Priority)', - ); expect( - testController.state.configs.networks?.['0x1']?.value.rpcEndpoints[0] - .type, - ).toBe('alchemy'); - - // Verify other networks are still present - expect(testController.state.configs.networks?.['0x89']).toBeDefined(); + testController.state.configs.networks?.['0x1']?.value.name, + ).toBe('Ethereum Mainnet (First)'); }, ); }); - it('should handle duplicate chainIds with same priority by keeping first occurrence', async () => { - return withController( - async ({ controller, mockRemoteFeatureFlagGetState, mockApiServiceHandler, rootMessenger }) => { - mockRemoteFeatureFlagGetState.mockReturnValue({ - remoteFeatureFlags: { - configRegistryApiEnabled: true, - }, - cacheTimestamp: Date.now(), - }); - - const captureExceptionSpy = jest.fn(); - const testRootMessenger = new Messenger< - MockAnyNamespace, - | { - type: 'RemoteFeatureFlagController:getState'; - handler: () => unknown; - } - | { - type: 'KeyringController:getState'; - handler: () => { isUnlocked: boolean }; - } - | { - type: 'ConfigRegistryApiService:fetchConfig'; - handler: (options?: { - etag?: string; - }) => Promise; - }, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] } - >({ - namespace: MOCK_ANY_NAMESPACE, - captureException: captureExceptionSpy, - }); - - const testMessenger = new Messenger< - typeof namespace, - never, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] }, - typeof testRootMessenger - >({ - namespace, - parent: testRootMessenger, - }) as ConfigRegistryMessenger; - - testRootMessenger.registerActionHandler( - 'ConfigRegistryApiService:fetchConfig', - mockApiServiceHandler, - ); - testRootMessenger.registerActionHandler( - 'RemoteFeatureFlagController:getState', - mockRemoteFeatureFlagGetState, - ); - testRootMessenger.registerActionHandler( - 'KeyringController:getState', - jest.fn().mockReturnValue({ isUnlocked: false }), - ); - testRootMessenger.delegate({ - messenger: testMessenger, - actions: [ - 'RemoteFeatureFlagController:getState', - 'KeyringController:getState', - 'ConfigRegistryApiService:fetchConfig', - ] as never[], - events: [ - 'KeyringController:unlock', - 'KeyringController:lock', - ] as never[], - }); - - const testController = new ConfigRegistryController({ - messenger: testMessenger, - }); - - // Mock API response with duplicate chainIds having same priority - const mockNetworks = [ - { - chainId: '0x1', - name: 'Ethereum Mainnet (First)', - nativeCurrency: 'ETH', - rpcEndpoints: [ - { - url: 'https://mainnet.infura.io/v3/{infuraProjectId}', - type: 'infura', - networkClientId: 'mainnet', - failoverUrls: [], - }, - ], - blockExplorerUrls: ['https://etherscan.io'], - defaultRpcEndpointIndex: 0, - defaultBlockExplorerUrlIndex: 0, - isTestnet: false, - isFeatured: true, - isActive: true, - isDefault: false, - isDeprecated: false, - priority: 5, // Same priority - isDeletable: false, - }, - { - chainId: '0x1', - name: 'Ethereum Mainnet (Second)', - nativeCurrency: 'ETH', - rpcEndpoints: [ - { - url: 'https://mainnet.alchemy.io/v2/{alchemyApiKey}', - type: 'alchemy', - networkClientId: 'mainnet-alchemy', - failoverUrls: [], - }, - ], - blockExplorerUrls: ['https://etherscan.io'], - defaultRpcEndpointIndex: 0, - defaultBlockExplorerUrlIndex: 0, - isTestnet: false, - isFeatured: true, - isActive: true, - isDefault: false, - isDeprecated: false, - priority: 5, // Same priority - isDeletable: false, - }, - ]; - - mockApiServiceHandler.mockResolvedValue({ - data: { - data: { - version: '1.0.0', - timestamp: Date.now(), - networks: mockNetworks, - }, - }, - modified: true, - etag: 'test-etag', - }); - - await testController._executePoll(null); - - // Verify warning was logged - expect(captureExceptionSpy).toHaveBeenCalled(); - const warningCall = captureExceptionSpy.mock.calls.find((call) => - call[0]?.message?.includes('Duplicate chainId 0x1'), - ); - expect(warningCall).toBeDefined(); - - // Verify first occurrence was kept (since priorities are equal) - expect(testController.state.configs.networks?.['0x1']).toBeDefined(); - expect(testController.state.configs.networks?.['0x1']?.value.name).toBe( - 'Ethereum Mainnet (First)', - ); - }, - ); - }); it('should use custom isConfigRegistryApiEnabled function when provided', async () => { const customIsEnabled = jest.fn().mockReturnValue(true); - return withController( + await withController( { options: { isConfigRegistryApiEnabled: customIsEnabled, @@ -2549,7 +2233,7 @@ describe('ConfigRegistryController', () => { it('should use custom isConfigRegistryApiEnabled function returning false', async () => { const customIsEnabled = jest.fn().mockReturnValue(false); - return withController( + await withController( { options: { fallbackConfig: MOCK_FALLBACK_CONFIG, @@ -2572,13 +2256,9 @@ describe('ConfigRegistryController', () => { }); it('should default to fallback when feature flag is not set', async () => { - return withController( + await withController( { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, - async ({ - controller, - clock, - mockRemoteFeatureFlagGetState, - }) => { + async ({ controller, clock, mockRemoteFeatureFlagGetState }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: {}, cacheTimestamp: Date.now(), @@ -2603,7 +2283,7 @@ describe('ConfigRegistryController', () => { }); it('should default to fallback when RemoteFeatureFlagController is unavailable', async () => { - return withController( + await withController( { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, async ({ controller, clock, mockRemoteFeatureFlagGetState }) => { mockRemoteFeatureFlagGetState.mockImplementation(() => { @@ -2631,7 +2311,7 @@ describe('ConfigRegistryController', () => { describe('KeyringController event listeners', () => { it('should start polling when KeyringController is already unlocked on initialization', async () => { - return withController(async ({ clock }) => { + await withController(async ({ clock }) => { const mockKeyringControllerGetState = jest.fn().mockReturnValue({ isUnlocked: true, }); @@ -2714,8 +2394,8 @@ describe('ConfigRegistryController', () => { }); }); - it('should handle KeyringController:getState error gracefully when KeyringController is unavailable', () => { - return withController(({ controller, mockKeyringControllerGetState }) => { + it('should handle KeyringController:getState error gracefully when KeyringController is unavailable', async () => { + await withController(({ controller, mockKeyringControllerGetState }) => { mockKeyringControllerGetState.mockImplementation(() => { throw new Error('KeyringController not available'); }); @@ -2725,28 +2405,31 @@ describe('ConfigRegistryController', () => { }); it('should start polling when KeyringController:unlock event is published', async () => { - return withController( - async ({ controller, clock, rootMessenger }) => { - const executePollSpy = jest.spyOn(controller, '_executePoll'); - const startPollingSpy = jest.spyOn(controller, 'startPolling'); + await withController(async ({ controller, clock, rootMessenger }) => { + const executePollSpy = jest.spyOn(controller, '_executePoll'); + const startPollingSpy = jest.spyOn(controller, 'startPolling'); - expect(startPollingSpy).not.toHaveBeenCalled(); + expect(startPollingSpy).not.toHaveBeenCalled(); - rootMessenger.publish('KeyringController:unlock'); + rootMessenger.publish('KeyringController:unlock'); - await advanceTime({ clock, duration: 0 }); + await advanceTime({ clock, duration: 0 }); - expect(startPollingSpy).toHaveBeenCalledWith(null); - expect(executePollSpy).toHaveBeenCalledTimes(1); + expect(startPollingSpy).toHaveBeenCalledWith(null); + expect(executePollSpy).toHaveBeenCalledTimes(1); - controller.stopPolling(); - }, - ); + controller.stopPolling(); + }); }); it('should stop polling when KeyringController:lock event is published', async () => { - return withController( - async ({ controller, clock, rootMessenger, mockKeyringControllerGetState }) => { + await withController( + async ({ + controller, + clock, + rootMessenger, + mockKeyringControllerGetState, + }) => { mockKeyringControllerGetState.mockReturnValue({ isUnlocked: true, }); @@ -2764,7 +2447,7 @@ describe('ConfigRegistryController', () => { }); it('should call startPolling with default parameter when called without arguments', async () => { - return withController(async ({ controller, clock }) => { + await withController(async ({ controller, clock }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); controller.startPolling(); @@ -2781,7 +2464,7 @@ describe('ConfigRegistryController', () => { it('should clear pending delayed poll timeout when stopping', async () => { const pollingInterval = 10000; const recentTimestamp = Date.now() - 2000; - return withController( + await withController( { options: { pollingInterval, @@ -2808,20 +2491,82 @@ describe('ConfigRegistryController', () => { ); }); - it('should handle clearing timeout when no timeout exists', () => { - return withController(({ controller }) => { + it('should handle clearing timeout when no timeout exists', async () => { + await withController(({ controller }) => { // Should not throw when stopping without a pending timeout expect(() => controller.stopPolling()).not.toThrow(); }); }); + it('should stop delayed poll using placeholder token', async () => { + const pollingInterval = 10000; + const recentTimestamp = Date.now() - 2000; + await withController( + { + options: { + pollingInterval, + state: { + lastFetched: recentTimestamp, + }, + }, + }, + async ({ controller, clock }) => { + const executePollSpy = jest.spyOn(controller, '_executePoll'); + const token = controller.startPolling(null); + + // Verify timeout was set (poll should not execute immediately) + await advanceTime({ clock, duration: 0 }); + expect(executePollSpy).not.toHaveBeenCalled(); + + // Stop polling using the placeholder token + controller.stopPolling(token); + + // Advance time past when the timeout would have fired + await advanceTime({ clock, duration: pollingInterval }); + expect(executePollSpy).not.toHaveBeenCalled(); + }, + ); + }); + + it('should stop delayed poll using placeholder token after timeout fires', async () => { + const pollingInterval = 10000; + const recentTimestamp = Date.now() - 2000; + const remainingTime = pollingInterval - 2000; + await withController( + { + options: { + pollingInterval, + state: { + lastFetched: recentTimestamp, + }, + }, + }, + async ({ controller, clock }) => { + const executePollSpy = jest.spyOn(controller, '_executePoll'); + const token = controller.startPolling(null); + + // Advance time to when the delayed poll starts + await advanceTime({ clock, duration: remainingTime + 1 }); + expect(executePollSpy).toHaveBeenCalledTimes(1); + executePollSpy.mockClear(); + + // Stop polling using the placeholder token (should map to actual token) + controller.stopPolling(token); + + // Advance time to verify polling stopped + await advanceTime({ clock, duration: pollingInterval }); + expect(executePollSpy).not.toHaveBeenCalled(); + }, + ); + }); + it('should stop all polling when called without token (backward compatible)', async () => { - return withController(async ({ controller, clock }) => { + await withController(async ({ controller, clock }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); // Start polling from multiple consumers - const token1 = controller.startPolling(null); - const token2 = controller.startPolling(null); + controller.startPolling(null); + controller.startPolling(null); await advanceTime({ clock, duration: 0 }); expect(executePollSpy).toHaveBeenCalledTimes(1); @@ -2836,7 +2581,7 @@ describe('ConfigRegistryController', () => { }); it('should stop specific polling session when called with token', async () => { - return withController(async ({ controller, clock }) => { + await withController(async ({ controller, clock }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); // Start polling from consumer A @@ -2846,7 +2591,7 @@ describe('ConfigRegistryController', () => { executePollSpy.mockClear(); // Start polling from consumer B (should reuse same polling session) - const tokenB = controller.startPolling(null); + controller.startPolling(null); await advanceTime({ clock, duration: 0 }); // Since both use same input (null), they share the same polling session // So stopping one token should stop the shared session @@ -2863,7 +2608,7 @@ describe('ConfigRegistryController', () => { }); it('should work via messenger action with token', async () => { - return withController(async ({ controller, messenger, clock }) => { + await withController(async ({ controller, messenger, clock }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); const token = messenger.call( @@ -2884,7 +2629,7 @@ describe('ConfigRegistryController', () => { }); it('should work via messenger action without token (backward compatible)', async () => { - return withController(async ({ controller, messenger, clock }) => { + await withController(async ({ controller, messenger, clock }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); const token = messenger.call( @@ -2906,8 +2651,8 @@ describe('ConfigRegistryController', () => { }); describe('destroy', () => { - it('should clean up event listeners and action handlers', () => { - return withController(({ controller, messenger, rootMessenger }) => { + it('should clean up event listeners and action handlers', async () => { + await withController(({ controller, messenger }) => { const unsubscribeSpy = jest.spyOn(messenger, 'unsubscribe'); const unregisterActionHandlerSpy = jest.spyOn( messenger, @@ -2935,13 +2680,11 @@ describe('ConfigRegistryController', () => { }); }); - it('should handle unsubscribe errors gracefully', () => { - return withController(({ controller, messenger }) => { - jest - .spyOn(messenger, 'unsubscribe') - .mockImplementation(() => { - throw new Error('Handler not subscribed'); - }); + it('should handle unsubscribe errors gracefully', async () => { + await withController(({ controller, messenger }) => { + jest.spyOn(messenger, 'unsubscribe').mockImplementation(() => { + throw new Error('Handler not subscribed'); + }); // Should not throw even if unsubscribe fails expect(() => controller.destroy()).not.toThrow(); @@ -2951,7 +2694,7 @@ describe('ConfigRegistryController', () => { it('should clear pending timeout when destroying', async () => { const pollingInterval = 10000; const recentTimestamp = Date.now() - 2000; - return withController( + await withController( { options: { pollingInterval, diff --git a/packages/config-registry-controller/src/ConfigRegistryController.ts b/packages/config-registry-controller/src/ConfigRegistryController.ts index fccec443cd9..8d133c81b6a 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.ts @@ -147,6 +147,8 @@ export class ConfigRegistryController extends StaticIntervalPollingController | null = null; + readonly #delayedPollTokenMap: Map = new Map(); + /** * @param options - The controller options. * @param options.messenger - The controller messenger. Must have @@ -360,8 +362,6 @@ export class ConfigRegistryController extends StaticIntervalPollingController 0) { // Not enough time has passed, delay the first poll - // Clear any existing timeout before stopping polling + // Clear any existing timeout before scheduling a new one if (this.#delayedPollTimeoutId !== null) { clearTimeout(this.#delayedPollTimeoutId); this.#delayedPollTimeoutId = null; } - // Stop the immediate poll that was just started - this.stopPolling(); + // Generate a placeholder token that will map to the actual token + const placeholderToken = `delayed-${Date.now()}-${Math.random()}`; // Schedule the first poll after the remaining time this.#delayedPollTimeoutId = setTimeout(() => { this.#delayedPollTimeoutId = null; - super.startPolling(input); + const actualToken = super.startPolling(input); + this.#delayedPollTokenMap.set(placeholderToken, actualToken); }, remainingTime); - return token; + return placeholderToken; } } // Enough time has passed or first time, proceed with normal polling - return token; + return super.startPolling(input); } stopPolling(token?: string): void { @@ -405,10 +406,19 @@ export class ConfigRegistryController extends StaticIntervalPollingController + > +>; + // Store this in case it gets stubbed later const originalSetTimeout = global.setTimeout; @@ -221,27 +227,30 @@ export class FakeProvider } throw new Error(message); - } else { - const stub = this.#stubs[index]; + } - if (stub.discardAfterMatching !== false) { - this.#stubs.splice(index, 1); - } + const stub = this.#stubs[index]; + if (stub === undefined) { + throw new Error('Stub not found at index'); + } - if (stub.delay) { - originalSetTimeout(() => { - // TODO: Either fix this lint violation or explain why it's necessary to ignore. - // eslint-disable-next-line @typescript-eslint/no-floating-promises - this.#handleRequest(stub, callback); - }, stub.delay); - } else { + if (stub.discardAfterMatching !== false) { + this.#stubs.splice(index, 1); + } + + if (stub.delay) { + originalSetTimeout(() => { // TODO: Either fix this lint violation or explain why it's necessary to ignore. // eslint-disable-next-line @typescript-eslint/no-floating-promises this.#handleRequest(stub, callback); - } - - this.calledStubs.push({ ...stub }); + }, stub.delay); + } else { + // TODO: Either fix this lint violation or explain why it's necessary to ignore. + // eslint-disable-next-line @typescript-eslint/no-floating-promises + this.#handleRequest(stub, callback); } + + this.calledStubs.push(stub); } async #handleRequest( From b6e620e2d1080b58ec1c11acfc104a9fcc2c2dc4 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Sun, 25 Jan 2026 16:34:28 +0100 Subject: [PATCH 24/55] fix: fix lint --- .../src/ConfigRegistryController.test.ts | 1 - tests/fake-provider.ts | 15 +++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/packages/config-registry-controller/src/ConfigRegistryController.test.ts b/packages/config-registry-controller/src/ConfigRegistryController.test.ts index 01f663fe6a7..e92f0c824c5 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.test.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.test.ts @@ -2173,7 +2173,6 @@ describe('ConfigRegistryController', () => { ); }); - it('should use custom isConfigRegistryApiEnabled function when provided', async () => { const customIsEnabled = jest.fn().mockReturnValue(true); await withController( diff --git a/tests/fake-provider.ts b/tests/fake-provider.ts index f84b851d0b2..a767ffb1c46 100644 --- a/tests/fake-provider.ts +++ b/tests/fake-provider.ts @@ -1,3 +1,10 @@ +import { InternalProvider } from '@metamask/eth-json-rpc-provider'; +import { JsonRpcEngineV2 } from '@metamask/json-rpc-engine/v2'; +import type { + JsonRpcMiddleware, + MiddlewareContext, + ResultConstraint, +} from '@metamask/json-rpc-engine/v2'; import type { Json, JsonRpcId, @@ -8,14 +15,6 @@ import type { } from '@metamask/utils'; import { inspect, isDeepStrictEqual } from 'util'; -import { InternalProvider } from '@metamask/eth-json-rpc-provider'; -import { JsonRpcEngineV2 } from '@metamask/json-rpc-engine/v2'; -import type { - JsonRpcMiddleware, - MiddlewareContext, - ResultConstraint, -} from '@metamask/json-rpc-engine/v2'; - type Provider = InternalProvider< MiddlewareContext< { origin: string; skipCache: boolean } & Record From aab4f56a8595c6eb2774e33b7511d95ad6ac4e02 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Sun, 25 Jan 2026 19:28:12 +0100 Subject: [PATCH 25/55] fix: fix lint --- package.json | 1 - packages/config-registry-controller/package.json | 1 - packages/config-registry-controller/tsconfig.build.json | 1 - packages/config-registry-controller/tsconfig.json | 1 - yarn.lock | 2 -- 5 files changed, 6 deletions(-) diff --git a/package.json b/package.json index b2af71acbad..68dcf8ded46 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,6 @@ "@metamask/eth-block-tracker": "^15.0.1", "@metamask/eth-json-rpc-provider": "^6.0.0", "@metamask/json-rpc-engine": "^10.2.1", - "@metamask/network-controller": "^29.0.0", "@metamask/utils": "^11.9.0", "@ts-bridge/cli": "^0.6.4", "@types/jest": "^27.4.1", diff --git a/packages/config-registry-controller/package.json b/packages/config-registry-controller/package.json index 263aa46ec57..5aeb58d9208 100644 --- a/packages/config-registry-controller/package.json +++ b/packages/config-registry-controller/package.json @@ -51,7 +51,6 @@ "@metamask/base-controller": "^9.0.0", "@metamask/controller-utils": "^11.18.0", "@metamask/messenger": "^0.3.0", - "@metamask/network-controller": "^29.0.0", "@metamask/polling-controller": "^16.0.2", "@metamask/profile-sync-controller": "^27.0.0", "@metamask/remote-feature-flag-controller": "^4.0.0", diff --git a/packages/config-registry-controller/tsconfig.build.json b/packages/config-registry-controller/tsconfig.build.json index 7121fac78a0..28e608feb56 100644 --- a/packages/config-registry-controller/tsconfig.build.json +++ b/packages/config-registry-controller/tsconfig.build.json @@ -10,7 +10,6 @@ { "path": "../controller-utils/tsconfig.build.json" }, { "path": "../keyring-controller/tsconfig.build.json" }, { "path": "../messenger/tsconfig.build.json" }, - { "path": "../network-controller/tsconfig.build.json" }, { "path": "../polling-controller/tsconfig.build.json" }, { "path": "../profile-sync-controller/tsconfig.build.json" }, { "path": "../remote-feature-flag-controller/tsconfig.build.json" } diff --git a/packages/config-registry-controller/tsconfig.json b/packages/config-registry-controller/tsconfig.json index 50680bda9f6..f6522b88f9c 100644 --- a/packages/config-registry-controller/tsconfig.json +++ b/packages/config-registry-controller/tsconfig.json @@ -8,7 +8,6 @@ { "path": "../controller-utils" }, { "path": "../keyring-controller" }, { "path": "../messenger" }, - { "path": "../network-controller" }, { "path": "../polling-controller" }, { "path": "../profile-sync-controller" }, { "path": "../remote-feature-flag-controller" } diff --git a/yarn.lock b/yarn.lock index 2944e96f5ef..01cbed0ea40 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2981,7 +2981,6 @@ __metadata: "@metamask/base-controller": "npm:^9.0.0" "@metamask/controller-utils": "npm:^11.18.0" "@metamask/messenger": "npm:^0.3.0" - "@metamask/network-controller": "npm:^29.0.0" "@metamask/polling-controller": "npm:^16.0.2" "@metamask/profile-sync-controller": "npm:^27.0.0" "@metamask/remote-feature-flag-controller": "npm:^4.0.0" @@ -3101,7 +3100,6 @@ __metadata: "@metamask/eth-block-tracker": "npm:^15.0.1" "@metamask/eth-json-rpc-provider": "npm:^6.0.0" "@metamask/json-rpc-engine": "npm:^10.2.1" - "@metamask/network-controller": "npm:^29.0.0" "@metamask/utils": "npm:^11.9.0" "@ts-bridge/cli": "npm:^0.6.4" "@types/jest": "npm:^27.4.1" From b5ebdd01f3ecbf499ef1d3ee9e96b9e6e9c1f75b Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Sun, 25 Jan 2026 19:33:17 +0100 Subject: [PATCH 26/55] fix: add missing export --- packages/config-registry-controller/src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/config-registry-controller/src/index.ts b/packages/config-registry-controller/src/index.ts index af49ffef6b5..f556286374f 100644 --- a/packages/config-registry-controller/src/index.ts +++ b/packages/config-registry-controller/src/index.ts @@ -8,6 +8,7 @@ export type { ConfigRegistryControllerEvents, ConfigRegistryControllerStateChangeEvent, ConfigRegistryMessenger, + NetworkConfigEntry, } from './ConfigRegistryController'; export { ConfigRegistryController, From 839e62c28b164dfaadb864d1acfb03c4abd38d04 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Mon, 26 Jan 2026 12:05:30 +0100 Subject: [PATCH 27/55] fix: fix feedbacks --- .../src/ConfigRegistryController.test.ts | 78 ++++++++--------- .../src/ConfigRegistryController.ts | 86 ++++++++++++++----- .../src/config-registry-api-service/index.ts | 2 +- .../transformers.test.ts | 26 +----- .../transformers.ts | 14 +-- .../src/config-registry-api-service/types.ts | 8 +- .../config-registry-controller/src/index.ts | 2 +- 7 files changed, 110 insertions(+), 106 deletions(-) diff --git a/packages/config-registry-controller/src/ConfigRegistryController.test.ts b/packages/config-registry-controller/src/ConfigRegistryController.test.ts index e92f0c824c5..446bcfc54c4 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.test.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.test.ts @@ -4,7 +4,7 @@ import { useFakeTimers } from 'sinon'; import type { FetchConfigResult, - NetworkConfig, + RegistryNetworkConfig, } from './config-registry-api-service'; import { ConfigRegistryController, @@ -85,14 +85,14 @@ function getConfigRegistryControllerMessenger(): { } /** - * Creates a mock NetworkConfig for testing. + * Creates a mock RegistryNetworkConfig for testing. * - * @param overrides - Optional properties to override in the default NetworkConfig. - * @returns A mock NetworkConfig object. + * @param overrides - Optional properties to override in the default RegistryNetworkConfig. + * @returns A mock RegistryNetworkConfig object. */ function createMockNetworkConfig( - overrides: Partial = {}, -): NetworkConfig { + overrides: Partial = {}, +): RegistryNetworkConfig { return { chainId: '0x1', name: 'Ethereum Mainnet', @@ -218,6 +218,9 @@ async function withController( ...options, }); + // Initialize the controller after creation + controller.init(); + try { return await testFunction({ controller, @@ -229,6 +232,8 @@ async function withController( mockKeyringControllerGetState, }); } finally { + controller.stopPolling(); + controller.destroy(); clock.restore(); mockApiServiceHandler.mockReset(); } @@ -1392,24 +1397,6 @@ describe('ConfigRegistryController', () => { }, ); }); - - it('should use default error message when useFallbackConfig is called without errorMessage', async () => { - await withController( - { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, - ({ controller }) => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (controller as any).useFallbackConfig(); - - expect(controller.state.configs).toStrictEqual({ - networks: MOCK_FALLBACK_CONFIG, - }); - expect(controller.state.fetchError).toBe( - 'Using fallback configuration - API unavailable', - ); - expect(controller.state.etag).toBeNull(); - }, - ); - }); }); describe('startPolling', () => { @@ -1689,7 +1676,7 @@ describe('ConfigRegistryController', () => { await controller._executePoll(null); expect(fetchConfigSpy).toHaveBeenCalled(); - expect(controller.state.configs.networks?.['0x1']).toBeDefined(); + expect(controller.state.configs.networks['0x1']).toBeDefined(); expect(controller.state.version).toBe('1.0.0'); expect(controller.state.fetchError).toBeNull(); }, @@ -1821,13 +1808,13 @@ describe('ConfigRegistryController', () => { await controller._executePoll(null); - expect(controller.state.configs.networks?.['0x1']).toBeDefined(); - expect(controller.state.configs.networks?.['0x5']).toBeUndefined(); - expect(controller.state.configs.networks?.['0xa']).toBeUndefined(); - expect(controller.state.configs.networks?.['0x89']).toBeUndefined(); - expect( - Object.keys(controller.state.configs.networks ?? {}), - ).toHaveLength(1); + expect(controller.state.configs.networks['0x1']).toBeDefined(); + expect(controller.state.configs.networks['0x5']).toBeUndefined(); + expect(controller.state.configs.networks['0xa']).toBeUndefined(); + expect(controller.state.configs.networks['0x89']).toBeUndefined(); + expect(Object.keys(controller.state.configs.networks)).toHaveLength( + 1, + ); }, ); }); @@ -2004,17 +1991,17 @@ describe('ConfigRegistryController', () => { ); // Verify highest priority network was kept - expect(testController.state.configs.networks?.['0x1']).toBeDefined(); - expect( - testController.state.configs.networks?.['0x1']?.value.name, - ).toBe('Ethereum Mainnet (High Priority)'); + expect(testController.state.configs.networks['0x1']).toBeDefined(); + expect(testController.state.configs.networks['0x1']?.value.name).toBe( + 'Ethereum Mainnet (High Priority)', + ); expect( - testController.state.configs.networks?.['0x1']?.value - .rpcEndpoints[0].type, + testController.state.configs.networks['0x1']?.value.rpcEndpoints[0] + .type, ).toBe('alchemy'); // Verify other networks are still present - expect(testController.state.configs.networks?.['0x89']).toBeDefined(); + expect(testController.state.configs.networks['0x89']).toBeDefined(); }, ); }); @@ -2165,10 +2152,10 @@ describe('ConfigRegistryController', () => { expect(warningCall).toBeDefined(); // Verify first occurrence was kept (since priorities are equal) - expect(testController.state.configs.networks?.['0x1']).toBeDefined(); - expect( - testController.state.configs.networks?.['0x1']?.value.name, - ).toBe('Ethereum Mainnet (First)'); + expect(testController.state.configs.networks['0x1']).toBeDefined(); + expect(testController.state.configs.networks['0x1']?.value.name).toBe( + 'Ethereum Mainnet (First)', + ); }, ); }); @@ -2224,7 +2211,7 @@ describe('ConfigRegistryController', () => { expect(customIsEnabled).toHaveBeenCalledWith(messenger); expect(mockApiServiceHandler).toHaveBeenCalled(); - expect(controller.state.configs.networks?.['0x1']).toBeDefined(); + expect(controller.state.configs.networks['0x1']).toBeDefined(); expect(controller.state.version).toBe('1.0.0'); }, ); @@ -2382,6 +2369,9 @@ describe('ConfigRegistryController', () => { messenger: testMessenger, }); + // Initialize the controller after creation + controller.init(); + const executePollSpy = jest.spyOn(controller, '_executePoll'); await advanceTime({ clock, duration: 100 }); diff --git a/packages/config-registry-controller/src/ConfigRegistryController.ts b/packages/config-registry-controller/src/ConfigRegistryController.ts index 8d133c81b6a..13d0bd096b1 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.ts @@ -16,7 +16,7 @@ import type { Json } from '@metamask/utils'; import type { FetchConfigOptions, FetchConfigResult, - NetworkConfig, + RegistryNetworkConfig, } from './config-registry-api-service'; import { filterNetworks } from './config-registry-api-service'; import { isConfigRegistryApiEnabled as defaultIsConfigRegistryApiEnabled } from './utils/feature-flags'; @@ -27,17 +27,49 @@ export const DEFAULT_POLLING_INTERVAL = inMilliseconds(1, Duration.Day); export type NetworkConfigEntry = { key: string; - value: NetworkConfig; + value: RegistryNetworkConfig; metadata?: Json; }; +/** + * State for the ConfigRegistryController. + * + * Tracks network configurations fetched from the config registry API, + * along with metadata about the fetch status and caching. + */ export type ConfigRegistryState = { + /** + * Network configurations organized by chain ID. + * Contains the actual network configuration data fetched from the API. + */ configs: { - networks?: Record; + networks: Record; }; + /** + * Semantic version string of the configuration data from the API. + * Indicates the version/schema of the configuration structure itself + * (e.g., "v1.0.0", "1.0.0"). + * This is different from `etag` which is used for HTTP cache validation. + */ version: string | null; + /** + * Timestamp (milliseconds since epoch) of when the configuration + * was last successfully fetched from the API. + */ lastFetched: number | null; + /** + * Error message if the last fetch attempt failed. + * Null if the last fetch was successful. + */ fetchError: string | null; + /** + * HTTP entity tag (ETag) used for cache validation. + * Sent as `If-None-Match` header in subsequent requests to check + * if the content has changed. If the server returns 304 Not Modified, + * the full response body is not downloaded, improving efficiency. + * This is different from `version` which is a semantic version string + * indicating the schema/version of the configuration data itself. + */ etag: string | null; }; @@ -207,11 +239,30 @@ export class ConfigRegistryController extends StaticIntervalPollingController { const isApiEnabled = this.#isConfigRegistryApiEnabled(this.messenger); if (!isApiEnabled) { - this.useFallbackConfig( + this.#useFallbackConfig( 'Feature flag disabled - using fallback configuration', ); return; @@ -257,7 +308,7 @@ export class ConfigRegistryController extends StaticIntervalPollingController(); filteredNetworks.forEach((network, index) => { const existing = networksByChainId.get(network.chainId) ?? []; @@ -298,6 +349,8 @@ export class ConfigRegistryController extends StaticIntervalPollingController { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore - Type instantiation is excessively deep (state.configs as ConfigRegistryState['configs']) = { networks: newConfigs, }; @@ -318,13 +371,12 @@ export class ConfigRegistryController extends StaticIntervalPollingController { - (state.configs as ConfigRegistryState['configs']) = { - networks: { ...this.#fallbackConfig }, - }; - state.fetchError = - errorMessage ?? 'Using fallback configuration - API unavailable'; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore - Type instantiation is excessively deep + state.configs.networks = { ...this.#fallbackConfig }; + state.fetchError = errorMessage; state.etag = null; }); } @@ -341,19 +393,9 @@ export class ConfigRegistryController extends StaticIntervalPollingController { describe('filterNetworks', () => { - const networks: NetworkConfig[] = [ + const networks: RegistryNetworkConfig[] = [ { ...VALID_NETWORK_CONFIG, isFeatured: true, @@ -108,26 +108,6 @@ describe('transformers', () => { expect(result[0].chainId).toBe('0x1'); }); - it('should return empty array for non-array input', () => { - const result = filterNetworks(null as unknown as NetworkConfig[]); - - expect(result).toStrictEqual([]); - }); - - it('should filter out invalid network objects', () => { - const invalidNetworks = [ - null, - undefined, - 'invalid', - 123, - ...networks, - ] as unknown as NetworkConfig[]; - - const result = filterNetworks(invalidNetworks); - - expect(result).toHaveLength(3); - }); - it('should return empty array for empty input', () => { const result = filterNetworks([]); diff --git a/packages/config-registry-controller/src/config-registry-api-service/transformers.ts b/packages/config-registry-controller/src/config-registry-api-service/transformers.ts index 225411522b0..150e10b51eb 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/transformers.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/transformers.ts @@ -1,4 +1,4 @@ -import type { NetworkConfig } from './types'; +import type { RegistryNetworkConfig } from './types'; export type NetworkFilterOptions = { isFeatured?: boolean; @@ -14,18 +14,10 @@ export type NetworkFilterOptions = { * @returns Filtered array of network configurations. */ export function filterNetworks( - networks: NetworkConfig[], + networks: RegistryNetworkConfig[], options: NetworkFilterOptions = {}, -): NetworkConfig[] { - if (!Array.isArray(networks)) { - return []; - } - +): RegistryNetworkConfig[] { return networks.filter((network) => { - if (!network || typeof network !== 'object') { - return false; - } - if (options.isFeatured !== undefined) { if (network.isFeatured !== options.isFeatured) { return false; diff --git a/packages/config-registry-controller/src/config-registry-api-service/types.ts b/packages/config-registry-controller/src/config-registry-api-service/types.ts index 1021404c259..fad9ae93af9 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/types.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/types.ts @@ -15,7 +15,7 @@ const RpcEndpointSchema = type({ failoverUrls: array(string()), }); -export const NetworkConfigSchema = type({ +export const RegistryNetworkConfigSchema = type({ chainId: string(), name: string(), nativeCurrency: string(), @@ -39,11 +39,11 @@ export const RegistryConfigApiResponseSchema = type({ data: type({ version: string(), timestamp: number(), - networks: array(NetworkConfigSchema), + networks: array(RegistryNetworkConfigSchema), }), }); -export type NetworkConfig = { +export type RegistryNetworkConfig = { chainId: string; name: string; nativeCurrency: string; @@ -72,7 +72,7 @@ export type RegistryConfigApiResponse = { data: { version: string; timestamp: number; - networks: NetworkConfig[]; + networks: RegistryNetworkConfig[]; }; }; diff --git a/packages/config-registry-controller/src/index.ts b/packages/config-registry-controller/src/index.ts index f556286374f..0e9bad06f22 100644 --- a/packages/config-registry-controller/src/index.ts +++ b/packages/config-registry-controller/src/index.ts @@ -17,7 +17,7 @@ export { export type { FetchConfigOptions, FetchConfigResult, - NetworkConfig, + RegistryNetworkConfig, RegistryConfigApiResponse, ConfigRegistryApiServiceOptions, NetworkFilterOptions, From c07d12a9cea51430081711d6c00fc4af5ce76859 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Wed, 28 Jan 2026 15:48:19 +0100 Subject: [PATCH 28/55] fix: small fix --- .../src/ConfigRegistryController.test.ts | 124 +++++++++--------- .../transformers.test.ts | 16 +-- 2 files changed, 70 insertions(+), 70 deletions(-) diff --git a/packages/config-registry-controller/src/ConfigRegistryController.test.ts b/packages/config-registry-controller/src/ConfigRegistryController.test.ts index 446bcfc54c4..c94312d15d5 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.test.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.test.ts @@ -241,7 +241,7 @@ async function withController( describe('ConfigRegistryController', () => { describe('constructor', () => { - it('should set default state', async () => { + it('sets default state', async () => { await withController(({ controller }) => { expect(controller.state).toStrictEqual({ configs: { networks: {} }, @@ -253,7 +253,7 @@ describe('ConfigRegistryController', () => { }); }); - it('should set initial state when provided', async () => { + it('sets initial state when provided', async () => { const initialState: Partial = { configs: { networks: { @@ -276,7 +276,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should set custom polling interval', async () => { + it('sets custom polling interval', async () => { const customInterval = 5000; await withController( { options: { pollingInterval: customInterval } }, @@ -286,7 +286,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should set fallback config', async () => { + it('sets fallback config', async () => { await withController( { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, ({ controller }) => { @@ -297,7 +297,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should work when API service is registered on messenger', async () => { + it('works when API service is registered on messenger', async () => { await withController(({ controller }) => { expect(controller.state).toStrictEqual({ configs: { networks: {} }, @@ -311,7 +311,7 @@ describe('ConfigRegistryController', () => { }); describe('polling', () => { - it('should start polling', async () => { + it('starts polling', async () => { await withController(async ({ controller, clock }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); controller.startPolling(null); @@ -323,7 +323,7 @@ describe('ConfigRegistryController', () => { }); }); - it('should poll at specified interval', async () => { + it('polls at specified interval', async () => { const pollingInterval = 1000; await withController( { options: { pollingInterval } }, @@ -342,7 +342,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should stop polling', async () => { + it('stops polling', async () => { await withController(async ({ controller, clock }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); controller.startPolling(null); @@ -358,7 +358,7 @@ describe('ConfigRegistryController', () => { }); }); - it('should use fallback config when no configs exist', async () => { + it('uses fallback config when no configs exist', async () => { await withController( { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, async ({ mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { @@ -449,7 +449,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should set fetchError when configs already exist (not use fallback)', async () => { + it('sets fetchError when configs already exist (not use fallback)', async () => { const existingConfigs = { networks: { 'existing-key': { @@ -556,7 +556,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should handle errors during polling', async () => { + it('handles errors during polling', async () => { await withController( { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, async ({ mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { @@ -648,7 +648,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should handle unmodified response and clear fetchError', async () => { + it('handles unmodified response and clears fetchError', async () => { await withController( { options: { @@ -691,7 +691,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should handle unmodified response and preserve existing etag when not provided', async () => { + it('handles unmodified response and preserves existing etag when not provided', async () => { await withController( { options: { @@ -734,7 +734,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should handle unmodified response and set etag to null when explicitly null', async () => { + it('handles unmodified response and sets etag to null when explicitly null', async () => { await withController( { options: { @@ -778,7 +778,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should handle validation error from service', async () => { + it('handles validation error from service', async () => { await withController( async ({ mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ @@ -872,7 +872,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should handle validation error when result.data.data is missing', async () => { + it('handles validation error when result.data.data is missing', async () => { await withController( async ({ controller, @@ -900,7 +900,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should handle validation error when result.data.data.networks is not an array', async () => { + it('handles validation error when result.data.data.networks is not an array', async () => { await withController( async ({ controller, @@ -928,7 +928,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should handle validation error when result.data.data.version is not a string', async () => { + it('handles validation error when result.data.data.version is not a string', async () => { await withController( async ({ controller, @@ -956,7 +956,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should skip fetch when lastFetched is within polling interval', async () => { + it('skips fetch when lastFetched is within polling interval', async () => { const recentTimestamp = Date.now() - 1000; await withController( { @@ -989,7 +989,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should proceed with fetch when lastFetched is null', async () => { + it('proceeds with fetch when lastFetched is null', async () => { await withController( { options: { @@ -1034,7 +1034,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should proceed with fetch when enough time has passed since lastFetched', async () => { + it('proceeds with fetch when enough time has passed since lastFetched', async () => { const now = Date.now(); const oldTimestamp = now - DEFAULT_POLLING_INTERVAL - 1000; await withController( @@ -1085,7 +1085,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should use custom polling interval when checking lastFetched', async () => { + it('uses custom polling interval when checking lastFetched', async () => { const customInterval = 5000; const recentTimestamp = Date.now() - 3000; await withController( @@ -1120,7 +1120,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should use DEFAULT_POLLING_INTERVAL when getIntervalLength returns undefined', async () => { + it('uses DEFAULT_POLLING_INTERVAL when getIntervalLength returns undefined', async () => { const recentTimestamp = Date.now() - 1000; await withController( { @@ -1157,7 +1157,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should handle non-Error exceptions', async () => { + it('handles non-Error exceptions', async () => { await withController( { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, async ({ mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { @@ -1250,7 +1250,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should handle error when state.configs is null', async () => { + it('handles error when state.configs is null', async () => { await withController( { options: { @@ -1349,7 +1349,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should work via messenger actions', async () => { + it('works via messenger actions', async () => { await withController(async ({ controller, messenger, clock }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); @@ -1370,7 +1370,7 @@ describe('ConfigRegistryController', () => { }); describe('state persistence', () => { - it('should persist version', async () => { + it('persists version', async () => { await withController( { options: { state: { version: 'v1.0.0' } } }, ({ controller }) => { @@ -1379,7 +1379,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should persist lastFetched', async () => { + it('persists lastFetched', async () => { const timestamp = Date.now(); await withController( { options: { state: { lastFetched: timestamp } } }, @@ -1389,7 +1389,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should persist fetchError', async () => { + it('persists fetchError', async () => { await withController( { options: { state: { fetchError: 'Test error' } } }, ({ controller }) => { @@ -1400,7 +1400,7 @@ describe('ConfigRegistryController', () => { }); describe('startPolling', () => { - it('should return a polling token string', async () => { + it('returns a polling token string', async () => { await withController(({ controller }) => { const token = controller.startPolling(null); expect(typeof token).toBe('string'); @@ -1410,7 +1410,7 @@ describe('ConfigRegistryController', () => { }); }); - it('should return a polling token string when called without input', async () => { + it('returns a polling token string when called without input', async () => { await withController(({ controller }) => { const token = controller.startPolling(null); expect(typeof token).toBe('string'); @@ -1420,7 +1420,7 @@ describe('ConfigRegistryController', () => { }); }); - it('should delay first poll when lastFetched is recent', async () => { + it('delays first poll when lastFetched is recent', async () => { const pollingInterval = 10000; const recentTimestamp = Date.now() - 2000; const remainingTime = pollingInterval - 2000; @@ -1448,7 +1448,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should proceed immediately when lastFetched is null', async () => { + it('proceeds immediately when lastFetched is null', async () => { await withController( { options: { @@ -1469,7 +1469,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should proceed immediately when lastFetched is old enough', async () => { + it('proceeds immediately when lastFetched is old enough', async () => { const pollingInterval = 10000; const now = Date.now(); const oldTimestamp = now - pollingInterval - 1000; @@ -1496,7 +1496,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should proceed immediately when lastFetched is exactly at polling interval', async () => { + it('proceeds immediately when lastFetched is exactly at polling interval', async () => { const pollingInterval = 10000; const now = Date.now(); const exactTimestamp = now - pollingInterval - 1; @@ -1523,7 +1523,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should use DEFAULT_POLLING_INTERVAL when getIntervalLength returns undefined', async () => { + it('uses DEFAULT_POLLING_INTERVAL when getIntervalLength returns undefined', async () => { const recentTimestamp = Date.now() - 1000; await withController( { @@ -1549,7 +1549,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should clear existing timeout when startPolling is called multiple times', async () => { + it('clears existing timeout when startPolling is called multiple times', async () => { const pollingInterval = 10000; const recentTimestamp = Date.now() - 2000; await withController( @@ -1590,7 +1590,7 @@ describe('ConfigRegistryController', () => { }); describe('feature flag', () => { - it('should use fallback config when feature flag is disabled', async () => { + it('uses fallback config when feature flag is disabled', async () => { await withController( { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, async ({ controller, clock, mockRemoteFeatureFlagGetState }) => { @@ -1619,7 +1619,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should use API when feature flag is enabled', async () => { + it('uses API when feature flag is enabled', async () => { await withController( async ({ controller, @@ -1683,7 +1683,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should filter networks to only include featured, active, non-testnet networks', async () => { + it('filters networks to only include featured, active, non-testnet networks', async () => { await withController( async ({ controller, @@ -1819,7 +1819,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should handle duplicate chainIds by keeping highest priority network and logging warning', async () => { + it('handles duplicate chainIds by keeping highest priority network and logging warning', async () => { await withController( async ({ mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ @@ -2006,7 +2006,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should handle duplicate chainIds with same priority by keeping first occurrence', async () => { + it('handles duplicate chainIds with same priority by keeping first occurrence', async () => { await withController( async ({ mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ @@ -2160,7 +2160,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should use custom isConfigRegistryApiEnabled function when provided', async () => { + it('uses custom isConfigRegistryApiEnabled function when provided', async () => { const customIsEnabled = jest.fn().mockReturnValue(true); await withController( { @@ -2217,7 +2217,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should use custom isConfigRegistryApiEnabled function returning false', async () => { + it('uses custom isConfigRegistryApiEnabled function returning false', async () => { const customIsEnabled = jest.fn().mockReturnValue(false); await withController( { @@ -2241,7 +2241,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should default to fallback when feature flag is not set', async () => { + it('defaults to fallback when feature flag is not set', async () => { await withController( { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, async ({ controller, clock, mockRemoteFeatureFlagGetState }) => { @@ -2268,7 +2268,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should default to fallback when RemoteFeatureFlagController is unavailable', async () => { + it('defaults to fallback when RemoteFeatureFlagController is unavailable', async () => { await withController( { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, async ({ controller, clock, mockRemoteFeatureFlagGetState }) => { @@ -2296,7 +2296,7 @@ describe('ConfigRegistryController', () => { }); describe('KeyringController event listeners', () => { - it('should start polling when KeyringController is already unlocked on initialization', async () => { + it('starts polling when KeyringController is already unlocked on initialization', async () => { await withController(async ({ clock }) => { const mockKeyringControllerGetState = jest.fn().mockReturnValue({ isUnlocked: true, @@ -2383,7 +2383,7 @@ describe('ConfigRegistryController', () => { }); }); - it('should handle KeyringController:getState error gracefully when KeyringController is unavailable', async () => { + it('handles KeyringController:getState error gracefully when KeyringController is unavailable', async () => { await withController(({ controller, mockKeyringControllerGetState }) => { mockKeyringControllerGetState.mockImplementation(() => { throw new Error('KeyringController not available'); @@ -2393,7 +2393,7 @@ describe('ConfigRegistryController', () => { }); }); - it('should start polling when KeyringController:unlock event is published', async () => { + it('starts polling when KeyringController:unlock event is published', async () => { await withController(async ({ controller, clock, rootMessenger }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); const startPollingSpy = jest.spyOn(controller, 'startPolling'); @@ -2411,7 +2411,7 @@ describe('ConfigRegistryController', () => { }); }); - it('should stop polling when KeyringController:lock event is published', async () => { + it('stops polling when KeyringController:lock event is published', async () => { await withController( async ({ controller, @@ -2435,7 +2435,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should call startPolling with default parameter when called without arguments', async () => { + it('calls startPolling with default parameter when called without arguments', async () => { await withController(async ({ controller, clock }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); @@ -2450,7 +2450,7 @@ describe('ConfigRegistryController', () => { }); describe('stopPolling', () => { - it('should clear pending delayed poll timeout when stopping', async () => { + it('clears pending delayed poll timeout when stopping', async () => { const pollingInterval = 10000; const recentTimestamp = Date.now() - 2000; await withController( @@ -2480,14 +2480,14 @@ describe('ConfigRegistryController', () => { ); }); - it('should handle clearing timeout when no timeout exists', async () => { + it('handles clearing timeout when no timeout exists', async () => { await withController(({ controller }) => { // Should not throw when stopping without a pending timeout expect(() => controller.stopPolling()).not.toThrow(); }); }); - it('should stop delayed poll using placeholder token', async () => { + it('stops delayed poll using placeholder token', async () => { const pollingInterval = 10000; const recentTimestamp = Date.now() - 2000; await withController( @@ -2517,7 +2517,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should stop delayed poll using placeholder token after timeout fires', async () => { + it('stops delayed poll using placeholder token after timeout fires', async () => { const pollingInterval = 10000; const recentTimestamp = Date.now() - 2000; const remainingTime = pollingInterval - 2000; @@ -2549,7 +2549,7 @@ describe('ConfigRegistryController', () => { ); }); - it('should stop all polling when called without token (backward compatible)', async () => { + it('stops all polling when called without token (backward compatible)', async () => { await withController(async ({ controller, clock }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); @@ -2569,7 +2569,7 @@ describe('ConfigRegistryController', () => { }); }); - it('should stop specific polling session when called with token', async () => { + it('stops specific polling session when called with token', async () => { await withController(async ({ controller, clock }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); @@ -2596,7 +2596,7 @@ describe('ConfigRegistryController', () => { }); }); - it('should work via messenger action with token', async () => { + it('works via messenger action with token', async () => { await withController(async ({ controller, messenger, clock }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); @@ -2617,7 +2617,7 @@ describe('ConfigRegistryController', () => { }); }); - it('should work via messenger action without token (backward compatible)', async () => { + it('works via messenger action without token (backward compatible)', async () => { await withController(async ({ controller, messenger, clock }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); @@ -2640,7 +2640,7 @@ describe('ConfigRegistryController', () => { }); describe('destroy', () => { - it('should clean up event listeners and action handlers', async () => { + it('cleans up event listeners and action handlers', async () => { await withController(({ controller, messenger }) => { const unsubscribeSpy = jest.spyOn(messenger, 'unsubscribe'); const unregisterActionHandlerSpy = jest.spyOn( @@ -2669,7 +2669,7 @@ describe('ConfigRegistryController', () => { }); }); - it('should handle unsubscribe errors gracefully', async () => { + it('handles unsubscribe errors gracefully', async () => { await withController(({ controller, messenger }) => { jest.spyOn(messenger, 'unsubscribe').mockImplementation(() => { throw new Error('Handler not subscribed'); @@ -2680,7 +2680,7 @@ describe('ConfigRegistryController', () => { }); }); - it('should clear pending timeout when destroying', async () => { + it('clears pending timeout when destroying', async () => { const pollingInterval = 10000; const recentTimestamp = Date.now() - 2000; await withController( diff --git a/packages/config-registry-controller/src/config-registry-api-service/transformers.test.ts b/packages/config-registry-controller/src/config-registry-api-service/transformers.test.ts index e19dbb96943..9e921d40adf 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/transformers.test.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/transformers.test.ts @@ -56,48 +56,48 @@ describe('transformers', () => { }, ]; - it('should return all networks when no filters applied', () => { + it('returns all networks when no filters applied', () => { const result = filterNetworks(networks); expect(result).toHaveLength(3); }); - it('should filter by isFeatured', () => { + it('filters by isFeatured', () => { const result = filterNetworks(networks, { isFeatured: true }); expect(result).toHaveLength(2); expect(result.every((network) => network.isFeatured)).toBe(true); }); - it('should filter by isTestnet', () => { + it('filters by isTestnet', () => { const result = filterNetworks(networks, { isTestnet: true }); expect(result).toHaveLength(1); expect(result[0].chainId).toBe('0x5'); }); - it('should filter by isActive', () => { + it('filters by isActive', () => { const result = filterNetworks(networks, { isActive: true }); expect(result).toHaveLength(2); expect(result.every((network) => network.isActive)).toBe(true); }); - it('should filter by isDeprecated', () => { + it('filters by isDeprecated', () => { const result = filterNetworks(networks, { isDeprecated: true }); expect(result).toHaveLength(1); expect(result[0].chainId).toBe('0x2a'); }); - it('should filter by isDefault', () => { + it('filters by isDefault', () => { const result = filterNetworks(networks, { isDefault: true }); expect(result).toHaveLength(1); expect(result[0].chainId).toBe('0x1'); }); - it('should filter by multiple criteria', () => { + it('filters by multiple criteria', () => { const result = filterNetworks(networks, { isFeatured: true, isActive: true, @@ -108,7 +108,7 @@ describe('transformers', () => { expect(result[0].chainId).toBe('0x1'); }); - it('should return empty array for empty input', () => { + it('returns empty array for empty input', () => { const result = filterNetworks([]); expect(result).toStrictEqual([]); From 181d1e2ed26d670619f1734126d44941543a0251 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Wed, 28 Jan 2026 17:35:19 +0100 Subject: [PATCH 29/55] fix: fix cursor bot feedbacks --- .../src/ConfigRegistryController.ts | 72 ++++++++++--------- .../config-registry-api-service.test.ts | 46 ++++++------ .../config-registry-api-service.ts | 2 +- .../src/config-registry-api-service/index.ts | 5 +- .../src/config-registry-api-service/types.ts | 36 ++-------- .../config-registry-controller/src/index.ts | 1 - 6 files changed, 70 insertions(+), 92 deletions(-) diff --git a/packages/config-registry-controller/src/ConfigRegistryController.ts b/packages/config-registry-controller/src/ConfigRegistryController.ts index 13d0bd096b1..e2ce7f5dd50 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.ts @@ -258,6 +258,23 @@ export class ConfigRegistryController extends StaticIntervalPollingController { const isApiEnabled = this.#isConfigRegistryApiEnabled(this.messenger); @@ -268,14 +285,7 @@ export class ConfigRegistryController extends StaticIntervalPollingController 0) { return; } @@ -377,6 +387,7 @@ export class ConfigRegistryController extends StaticIntervalPollingController 0) { - // Not enough time has passed, delay the first poll - // Clear any existing timeout before scheduling a new one - if (this.#delayedPollTimeoutId !== null) { - clearTimeout(this.#delayedPollTimeoutId); - this.#delayedPollTimeoutId = null; - } + const remainingTime = this.#getRemainingPollingDelayMs(); + + if (remainingTime > 0) { + // Not enough time has passed, delay the first poll + // Clear any existing timeout before scheduling a new one + if (this.#delayedPollTimeoutId !== null) { + clearTimeout(this.#delayedPollTimeoutId); + this.#delayedPollTimeoutId = null; + } - // Generate a placeholder token that will map to the actual token - const placeholderToken = `delayed-${Date.now()}-${Math.random()}`; + // Generate a placeholder token that will map to the actual token + const placeholderToken = `delayed-${Date.now()}-${Math.random()}`; - // Schedule the first poll after the remaining time - this.#delayedPollTimeoutId = setTimeout(() => { - this.#delayedPollTimeoutId = null; - const actualToken = super.startPolling(input); - this.#delayedPollTokenMap.set(placeholderToken, actualToken); - }, remainingTime); + // Schedule the first poll after the remaining time + this.#delayedPollTimeoutId = setTimeout(() => { + this.#delayedPollTimeoutId = null; + const actualToken = super.startPolling(input); + this.#delayedPollTokenMap.set(placeholderToken, actualToken); + }, remainingTime); - return placeholderToken; - } + return placeholderToken; } // Enough time has passed or first time, proceed with normal polling diff --git a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts index 22c3d3c0e9f..d61ca3f2164 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts @@ -2,10 +2,7 @@ import { SDK } from '@metamask/profile-sync-controller'; import nock, { cleanAll } from 'nock'; import { useFakeTimers } from 'sinon'; -import { - ConfigRegistryApiService, - getConfigRegistryUrl, -} from './config-registry-api-service'; +import { ConfigRegistryApiService } from './config-registry-api-service'; import type { FetchConfigResult, RegistryConfigApiResponse } from './types'; const MOCK_API_RESPONSE: RegistryConfigApiResponse = { @@ -41,26 +38,35 @@ const MOCK_API_RESPONSE: RegistryConfigApiResponse = { }; describe('ConfigRegistryApiService', () => { - describe('getConfigRegistryUrl', () => { - it('should return UAT URL for UAT environment', () => { - const url = getConfigRegistryUrl(SDK.Env.UAT); - expect(url).toBe( - 'https://client-config.uat-api.cx.metamask.io/v1/config/networks', - ); + describe('constructor URL by env', () => { + it('uses UAT URL when env is UAT', async () => { + const scope = nock('https://client-config.uat-api.cx.metamask.io') + .get('/v1/config/networks') + .reply(200, MOCK_API_RESPONSE); + + const service = new ConfigRegistryApiService({ env: SDK.Env.UAT }); + await service.fetchConfig(); + expect(scope.isDone()).toBe(true); }); - it('should return DEV URL for DEV environment', () => { - const url = getConfigRegistryUrl(SDK.Env.DEV); - expect(url).toBe( - 'https://client-config.dev-api.cx.metamask.io/v1/config/networks', - ); + it('uses DEV URL when env is DEV', async () => { + const scope = nock('https://client-config.dev-api.cx.metamask.io') + .get('/v1/config/networks') + .reply(200, MOCK_API_RESPONSE); + + const service = new ConfigRegistryApiService({ env: SDK.Env.DEV }); + await service.fetchConfig(); + expect(scope.isDone()).toBe(true); }); - it('should return PRD URL for PRD environment', () => { - const url = getConfigRegistryUrl(SDK.Env.PRD); - expect(url).toBe( - 'https://client-config.api.cx.metamask.io/v1/config/networks', - ); + it('uses PRD URL when env is PRD', async () => { + const scope = nock('https://client-config.api.cx.metamask.io') + .get('/v1/config/networks') + .reply(200, MOCK_API_RESPONSE); + + const service = new ConfigRegistryApiService({ env: SDK.Env.PRD }); + await service.fetchConfig(); + expect(scope.isDone()).toBe(true); }); }); diff --git a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts index c3c5540bccf..c2c1eaf94b6 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts @@ -19,7 +19,7 @@ const ENDPOINT_PATH = '/config/networks'; * @param env - The environment to get the URL for. * @returns The base URL for the environment. */ -export function getConfigRegistryUrl(env: SDK.Env): string { +function getConfigRegistryUrl(env: SDK.Env): string { const envPrefix = env === SDK.Env.PRD ? '' : `${env}-`; return `https://client-config.${envPrefix}api.cx.metamask.io/v1${ENDPOINT_PATH}`; } diff --git a/packages/config-registry-controller/src/config-registry-api-service/index.ts b/packages/config-registry-controller/src/config-registry-api-service/index.ts index 01a3a63ec7e..182571d2572 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/index.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/index.ts @@ -5,10 +5,7 @@ export type { RegistryConfigApiResponse, } from './types'; -export { - ConfigRegistryApiService, - getConfigRegistryUrl, -} from './config-registry-api-service'; +export { ConfigRegistryApiService } from './config-registry-api-service'; export type { ConfigRegistryApiServiceOptions } from './config-registry-api-service'; diff --git a/packages/config-registry-controller/src/config-registry-api-service/types.ts b/packages/config-registry-controller/src/config-registry-api-service/types.ts index fad9ae93af9..0cf33d4b8ec 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/types.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/types.ts @@ -1,3 +1,4 @@ +import type { Infer } from '@metamask/superstruct'; import { array, assert, @@ -43,38 +44,11 @@ export const RegistryConfigApiResponseSchema = type({ }), }); -export type RegistryNetworkConfig = { - chainId: string; - name: string; - nativeCurrency: string; - rpcEndpoints: { - url: string; - type: string; - networkClientId: string; - failoverUrls: string[]; - }[]; - blockExplorerUrls: string[]; - defaultRpcEndpointIndex: number; - defaultBlockExplorerUrlIndex: number; - lastUpdatedAt?: number; - networkImageUrl?: string; - nativeTokenImageUrl?: string; - isActive: boolean; - isTestnet: boolean; - isDefault: boolean; - isFeatured: boolean; - isDeprecated: boolean; - priority: number; - isDeletable: boolean; -}; +export type RegistryNetworkConfig = Infer; -export type RegistryConfigApiResponse = { - data: { - version: string; - timestamp: number; - networks: RegistryNetworkConfig[]; - }; -}; +export type RegistryConfigApiResponse = Infer< + typeof RegistryConfigApiResponseSchema +>; export function validateRegistryConfigApiResponse( data: unknown, diff --git a/packages/config-registry-controller/src/index.ts b/packages/config-registry-controller/src/index.ts index 0e9bad06f22..468f15ddaa7 100644 --- a/packages/config-registry-controller/src/index.ts +++ b/packages/config-registry-controller/src/index.ts @@ -24,7 +24,6 @@ export type { } from './config-registry-api-service'; export { ConfigRegistryApiService, - getConfigRegistryUrl, filterNetworks, } from './config-registry-api-service'; export { isConfigRegistryApiEnabled } from './utils/feature-flags'; From 464d78bc54905512027b68629290ef657e1e93d3 Mon Sep 17 00:00:00 2001 From: Michele Esposito <34438276+mikesposito@users.noreply.github.com> Date: Thu, 29 Jan 2026 13:43:57 +0100 Subject: [PATCH 30/55] refactor: remove `KeyringController:getState` dep, `init()` and `destroy()` (#7762) ## Explanation This is a proposal for refactors of changes made in #7668. Specifically, it removes the dependency on `KeyringController:getState`, and removes the now unnecessary `init()` method. `destroy()` is also being removed, as we usually don't manage controller disposal. Tests have been updated accordingly. ## References * Related to #7668 ## Checklist - [ ] I've updated the test suite for new or updated code as appropriate - [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate - [ ] I've communicated my changes to consumers by [updating changelogs for packages I've changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md) - [ ] I've introduced [breaking changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md) in this PR and have prepared draft pull requests for clients and consumer packages to resolve them --- > [!NOTE] > Removes the runtime dependency on `KeyringController:getState` and simplifies polling lifecycle management. > > - Controller now subscribes to `KeyringController:unlock`/`KeyringController:lock` in the constructor to start/stop polling; `init()` and `destroy()` (and their handlers) are removed > - Replaces direct feature-flag state typing with `RemoteFeatureFlagControllerGetStateAction` > - Tests updated: remove `KeyringController:getState` usage and init/destroy cases, simplify messenger typings and delegation > > Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 8e526e90aca5b53e67d2f0178bbe6c02cc30448d. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot). --- .../src/ConfigRegistryController.test.ts | 278 ++---------------- .../src/ConfigRegistryController.ts | 94 +----- 2 files changed, 38 insertions(+), 334 deletions(-) diff --git a/packages/config-registry-controller/src/ConfigRegistryController.test.ts b/packages/config-registry-controller/src/ConfigRegistryController.test.ts index c94312d15d5..687735c3698 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.test.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.test.ts @@ -1,4 +1,8 @@ -import type { MockAnyNamespace } from '@metamask/messenger'; +import type { + MockAnyNamespace, + MessengerActions, + MessengerEvents, +} from '@metamask/messenger'; import { Messenger, MOCK_ANY_NAMESPACE } from '@metamask/messenger'; import { useFakeTimers } from 'sinon'; @@ -19,20 +23,11 @@ import { advanceTime } from '../../../tests/helpers'; const namespace = 'ConfigRegistryController' as const; -type RootMessenger = Messenger< - MockAnyNamespace, - | { type: 'RemoteFeatureFlagController:getState'; handler: () => unknown } - | { - type: 'KeyringController:getState'; - handler: () => { isUnlocked: boolean }; - } - | { - type: 'ConfigRegistryApiService:fetchConfig'; - handler: (options?: { etag?: string }) => Promise; - }, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] } ->; +type AllActions = MessengerActions; + +type AllEvents = MessengerEvents; + +type RootMessenger = Messenger; /** * Constructs a messenger for ConfigRegistryController. @@ -43,42 +38,28 @@ function getConfigRegistryControllerMessenger(): { messenger: ConfigRegistryMessenger; rootMessenger: RootMessenger; } { - const rootMessenger = new Messenger< - MockAnyNamespace, - | { type: 'RemoteFeatureFlagController:getState'; handler: () => unknown } - | { - type: 'KeyringController:getState'; - handler: () => { isUnlocked: boolean }; - } - | { - type: 'ConfigRegistryApiService:fetchConfig'; - handler: (options?: { etag?: string }) => Promise; - }, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] } - >({ + const rootMessenger: RootMessenger = new Messenger({ namespace: MOCK_ANY_NAMESPACE, }); - const configRegistryControllerMessenger = new Messenger< - typeof namespace, - never, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] }, - typeof rootMessenger - >({ - namespace, - parent: rootMessenger, - }) as ConfigRegistryMessenger; + const configRegistryControllerMessenger: ConfigRegistryMessenger = + new Messenger< + typeof namespace, + AllActions, + AllEvents, + typeof rootMessenger + >({ + namespace, + parent: rootMessenger, + }); rootMessenger.delegate({ messenger: configRegistryControllerMessenger, actions: [ 'RemoteFeatureFlagController:getState', - 'KeyringController:getState', 'ConfigRegistryApiService:fetchConfig', - ] as never[], - events: ['KeyringController:unlock', 'KeyringController:lock'] as never[], + ], + events: ['KeyringController:unlock', 'KeyringController:lock'], }); return { messenger: configRegistryControllerMessenger, rootMessenger }; @@ -168,7 +149,6 @@ type WithControllerCallback = (args: { messenger: ConfigRegistryMessenger; mockApiServiceHandler: jest.Mock; mockRemoteFeatureFlagGetState: jest.Mock; - mockKeyringControllerGetState: jest.Mock; }) => Promise | ReturnValue; type WithControllerOptions = { @@ -204,23 +184,11 @@ async function withController( mockRemoteFeatureFlagGetState, ); - const mockKeyringControllerGetState = jest.fn().mockReturnValue({ - isUnlocked: false, - }); - - rootMessenger.registerActionHandler( - 'KeyringController:getState', - mockKeyringControllerGetState, - ); - const controller = new ConfigRegistryController({ messenger, ...options, }); - // Initialize the controller after creation - controller.init(); - try { return await testFunction({ controller, @@ -229,11 +197,9 @@ async function withController( messenger, mockApiServiceHandler, mockRemoteFeatureFlagGetState, - mockKeyringControllerGetState, }); } finally { controller.stopPolling(); - controller.destroy(); clock.restore(); mockApiServiceHandler.mockReset(); } @@ -522,10 +488,6 @@ describe('ConfigRegistryController', () => { 'RemoteFeatureFlagController:getState', mockRemoteFeatureFlagGetState, ); - testRootMessenger.registerActionHandler( - 'KeyringController:getState', - jest.fn().mockReturnValue({ isUnlocked: false }), - ); testRootMessenger.delegate({ messenger: testMessenger, actions: [ @@ -2296,103 +2258,6 @@ describe('ConfigRegistryController', () => { }); describe('KeyringController event listeners', () => { - it('starts polling when KeyringController is already unlocked on initialization', async () => { - await withController(async ({ clock }) => { - const mockKeyringControllerGetState = jest.fn().mockReturnValue({ - isUnlocked: true, - }); - - const testRootMessenger = new Messenger< - MockAnyNamespace, - | { - type: 'RemoteFeatureFlagController:getState'; - handler: () => unknown; - } - | { - type: 'KeyringController:getState'; - handler: () => { isUnlocked: boolean }; - } - | { - type: 'ConfigRegistryApiService:fetchConfig'; - handler: (options?: { - etag?: string; - }) => Promise; - }, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] } - >({ - namespace: MOCK_ANY_NAMESPACE, - }); - - const testMessenger = new Messenger< - typeof namespace, - never, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] }, - typeof testRootMessenger - >({ - namespace, - parent: testRootMessenger, - }) as ConfigRegistryMessenger; - - testRootMessenger.registerActionHandler( - 'ConfigRegistryApiService:fetchConfig', - jest.fn(buildMockApiServiceHandler()), - ); - testRootMessenger.registerActionHandler( - 'RemoteFeatureFlagController:getState', - jest.fn().mockReturnValue({ - remoteFeatureFlags: { - configRegistryApiEnabled: true, - }, - cacheTimestamp: Date.now(), - }), - ); - testRootMessenger.registerActionHandler( - 'KeyringController:getState', - mockKeyringControllerGetState, - ); - testRootMessenger.delegate({ - messenger: testMessenger, - actions: [ - 'RemoteFeatureFlagController:getState', - 'KeyringController:getState', - 'ConfigRegistryApiService:fetchConfig', - ] as never[], - events: [ - 'KeyringController:unlock', - 'KeyringController:lock', - ] as never[], - }); - - const controller = new ConfigRegistryController({ - messenger: testMessenger, - }); - - // Initialize the controller after creation - controller.init(); - - const executePollSpy = jest.spyOn(controller, '_executePoll'); - - await advanceTime({ clock, duration: 100 }); - - expect(mockKeyringControllerGetState).toHaveBeenCalled(); - expect(executePollSpy).toHaveBeenCalledTimes(1); - - controller.stopPolling(); - }); - }); - - it('handles KeyringController:getState error gracefully when KeyringController is unavailable', async () => { - await withController(({ controller, mockKeyringControllerGetState }) => { - mockKeyringControllerGetState.mockImplementation(() => { - throw new Error('KeyringController not available'); - }); - - expect(controller.state.lastFetched).toBeNull(); - }); - }); - it('starts polling when KeyringController:unlock event is published', async () => { await withController(async ({ controller, clock, rootMessenger }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); @@ -2412,27 +2277,16 @@ describe('ConfigRegistryController', () => { }); it('stops polling when KeyringController:lock event is published', async () => { - await withController( - async ({ - controller, - clock, - rootMessenger, - mockKeyringControllerGetState, - }) => { - mockKeyringControllerGetState.mockReturnValue({ - isUnlocked: true, - }); - - const stopPollingSpy = jest.spyOn(controller, 'stopPolling'); + await withController(async ({ controller, clock, rootMessenger }) => { + const stopPollingSpy = jest.spyOn(controller, 'stopPolling'); - await advanceTime({ clock, duration: 0 }); - expect(stopPollingSpy).not.toHaveBeenCalled(); + await advanceTime({ clock, duration: 0 }); + expect(stopPollingSpy).not.toHaveBeenCalled(); - rootMessenger.publish('KeyringController:lock'); + rootMessenger.publish('KeyringController:lock'); - expect(stopPollingSpy).toHaveBeenCalled(); - }, - ); + expect(stopPollingSpy).toHaveBeenCalled(); + }); }); it('calls startPolling with default parameter when called without arguments', async () => { @@ -2638,76 +2492,4 @@ describe('ConfigRegistryController', () => { }); }); }); - - describe('destroy', () => { - it('cleans up event listeners and action handlers', async () => { - await withController(({ controller, messenger }) => { - const unsubscribeSpy = jest.spyOn(messenger, 'unsubscribe'); - const unregisterActionHandlerSpy = jest.spyOn( - messenger, - 'unregisterActionHandler', - ); - const stopPollingSpy = jest.spyOn(controller, 'stopPolling'); - - controller.destroy(); - - expect(stopPollingSpy).toHaveBeenCalled(); - expect(unsubscribeSpy).toHaveBeenCalledWith( - 'KeyringController:unlock', - expect.any(Function), - ); - expect(unsubscribeSpy).toHaveBeenCalledWith( - 'KeyringController:lock', - expect.any(Function), - ); - expect(unregisterActionHandlerSpy).toHaveBeenCalledWith( - 'ConfigRegistryController:startPolling', - ); - expect(unregisterActionHandlerSpy).toHaveBeenCalledWith( - 'ConfigRegistryController:stopPolling', - ); - }); - }); - - it('handles unsubscribe errors gracefully', async () => { - await withController(({ controller, messenger }) => { - jest.spyOn(messenger, 'unsubscribe').mockImplementation(() => { - throw new Error('Handler not subscribed'); - }); - - // Should not throw even if unsubscribe fails - expect(() => controller.destroy()).not.toThrow(); - }); - }); - - it('clears pending timeout when destroying', async () => { - const pollingInterval = 10000; - const recentTimestamp = Date.now() - 2000; - await withController( - { - options: { - pollingInterval, - state: { - lastFetched: recentTimestamp, - }, - }, - }, - async ({ controller, clock }) => { - const executePollSpy = jest.spyOn(controller, '_executePoll'); - controller.startPolling(null); - - // Verify timeout was set - await advanceTime({ clock, duration: 0 }); - expect(executePollSpy).not.toHaveBeenCalled(); - - // Destroy should clear the timeout - controller.destroy(); - - // Advance time past when the timeout would have fired - await advanceTime({ clock, duration: pollingInterval }); - expect(executePollSpy).not.toHaveBeenCalled(); - }, - ); - }); - }); }); diff --git a/packages/config-registry-controller/src/ConfigRegistryController.ts b/packages/config-registry-controller/src/ConfigRegistryController.ts index e2ce7f5dd50..247f69fafbf 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.ts @@ -9,7 +9,7 @@ import type { } from '@metamask/keyring-controller'; import type { Messenger } from '@metamask/messenger'; import { StaticIntervalPollingController } from '@metamask/polling-controller'; -import type { RemoteFeatureFlagControllerState } from '@metamask/remote-feature-flag-controller'; +import { RemoteFeatureFlagControllerGetStateAction } from '@metamask/remote-feature-flag-controller'; import { Duration, inMilliseconds } from '@metamask/utils'; import type { Json } from '@metamask/utils'; @@ -130,14 +130,7 @@ export type ConfigRegistryControllerActions = | ConfigRegistryControllerGetStateAction | ConfigRegistryControllerStartPollingAction | ConfigRegistryControllerStopPollingAction - | { - type: 'RemoteFeatureFlagController:getState'; - handler: () => RemoteFeatureFlagControllerState; - } - | { - type: 'KeyringController:getState'; - handler: () => { isUnlocked: boolean }; - } + | RemoteFeatureFlagControllerGetStateAction | { type: 'ConfigRegistryApiService:fetchConfig'; handler: (options?: FetchConfigOptions) => Promise; @@ -173,10 +166,6 @@ export class ConfigRegistryController extends StaticIntervalPollingController boolean; - readonly #unlockHandler: () => void; - - readonly #lockHandler: () => void; - #delayedPollTimeoutId: ReturnType | null = null; readonly #delayedPollTokenMap: Map = new Map(); @@ -217,15 +206,6 @@ export class ConfigRegistryController extends StaticIntervalPollingController { - this.startPolling(null); - }; - - this.#lockHandler = (): void => { - this.stopPolling(); - }; - this.messenger.registerActionHandler( `${controllerName}:startPolling`, (input: null) => this.startPolling(input), @@ -236,26 +216,13 @@ export class ConfigRegistryController extends StaticIntervalPollingController this.stopPolling(token), ); - this.#registerKeyringEventListeners(); - } + this.messenger.subscribe('KeyringController:unlock', () => + this.startPolling(null), + ); - /** - * Initializes the controller by checking the KeyringController unlock state - * and starting polling if already unlocked. - * - * This method should be called after all controllers have been initialized - * to avoid runtime dependencies during construction. If KeyringController - * is not available, this method will silently skip initialization. - */ - init(): void { - try { - const { isUnlocked } = this.messenger.call('KeyringController:getState'); - if (isUnlocked) { - this.startPolling(null); - } - } catch { - // KeyringController may not be available, silently handle - } + this.messenger.subscribe('KeyringController:lock', () => + this.stopPolling(), + ); } /** @@ -402,18 +369,6 @@ export class ConfigRegistryController extends StaticIntervalPollingController Date: Fri, 6 Feb 2026 10:51:20 +0100 Subject: [PATCH 31/55] Mikesposito/refactor/simplify controller (#7809) --- .../config-registry-controller/CHANGELOG.md | 9 +- .../config-registry-controller/package.json | 3 +- .../src/ConfigRegistryController.test.ts | 344 +++++++----------- .../src/ConfigRegistryController.ts | 208 +---------- .../config-registry-api-service.test.ts | 119 +++--- .../{transformers.test.ts => filters.test.ts} | 44 +-- .../config-registry-api-service/filters.ts | 40 ++ .../src/config-registry-api-service/index.ts | 4 +- .../transformers.ts | 53 --- .../src/config-registry-api-service/types.ts | 5 + .../config-registry-controller/src/index.ts | 2 +- .../src/selectors.test.ts | 90 +++++ .../src/selectors.ts | 39 ++ .../src/test-helpers.ts | 36 ++ .../tsconfig.build.json | 1 + yarn.lock | 1 + 16 files changed, 426 insertions(+), 572 deletions(-) rename packages/config-registry-controller/src/config-registry-api-service/{transformers.test.ts => filters.test.ts} (72%) create mode 100644 packages/config-registry-controller/src/config-registry-api-service/filters.ts delete mode 100644 packages/config-registry-controller/src/config-registry-api-service/transformers.ts create mode 100644 packages/config-registry-controller/src/selectors.test.ts create mode 100644 packages/config-registry-controller/src/selectors.ts create mode 100644 packages/config-registry-controller/src/test-helpers.ts diff --git a/packages/config-registry-controller/CHANGELOG.md b/packages/config-registry-controller/CHANGELOG.md index fa33519f175..a006400c833 100644 --- a/packages/config-registry-controller/CHANGELOG.md +++ b/packages/config-registry-controller/CHANGELOG.md @@ -9,13 +9,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- Initial release of `@metamask/config-registry-controller` ([#7668](https://github.com/MetaMask/core/pull/7668)) - - Controller for fetching and managing network configurations from a remote API - - ConfigRegistryApiService with ETag support, retries, circuit breaker, and timeout handling - - Network filtering to only include featured, active, non-testnet networks - - Feature flag integration using `config_registry_api_enabled` to enable/disable API fetching - - Fallback configuration support when API is unavailable or feature flag is disabled - - State persistence for configs, version, lastFetched, and etag - - Uses StaticIntervalPollingController for periodic updates (default: 24 hours) +- Initial release ([#7668](https://github.com/MetaMask/core/pull/7668), [#7809](https://github.com/MetaMask/core/pull/7809)) [Unreleased]: https://github.com/MetaMask/core/ diff --git a/packages/config-registry-controller/package.json b/packages/config-registry-controller/package.json index 5aeb58d9208..ceb92b1b6c9 100644 --- a/packages/config-registry-controller/package.json +++ b/packages/config-registry-controller/package.json @@ -55,7 +55,8 @@ "@metamask/profile-sync-controller": "^27.0.0", "@metamask/remote-feature-flag-controller": "^4.0.0", "@metamask/superstruct": "^3.1.0", - "@metamask/utils": "^11.9.0" + "@metamask/utils": "^11.9.0", + "reselect": "^5.1.1" }, "devDependencies": { "@lavamoat/allow-scripts": "^3.0.4", diff --git a/packages/config-registry-controller/src/ConfigRegistryController.test.ts b/packages/config-registry-controller/src/ConfigRegistryController.test.ts index 687735c3698..8b98ef81ef8 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.test.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.test.ts @@ -6,19 +6,18 @@ import type { import { Messenger, MOCK_ANY_NAMESPACE } from '@metamask/messenger'; import { useFakeTimers } from 'sinon'; +import type { RegistryNetworkConfig } from './config-registry-api-service'; +import type { FetchConfigResult } from './config-registry-api-service'; import type { - FetchConfigResult, - RegistryNetworkConfig, -} from './config-registry-api-service'; + ConfigRegistryMessenger, + ConfigRegistryState, +} from './ConfigRegistryController'; import { ConfigRegistryController, DEFAULT_POLLING_INTERVAL, } from './ConfigRegistryController'; -import type { - ConfigRegistryMessenger, - ConfigRegistryState, - NetworkConfigEntry, -} from './ConfigRegistryController'; +import { selectFeaturedNetworks, selectNetworks } from './selectors'; +import { createMockNetworkConfig } from './test-helpers'; import { advanceTime } from '../../../tests/helpers'; const namespace = 'ConfigRegistryController' as const; @@ -40,6 +39,7 @@ function getConfigRegistryControllerMessenger(): { } { const rootMessenger: RootMessenger = new Messenger({ namespace: MOCK_ANY_NAMESPACE, + captureException: jest.fn(), }); const configRegistryControllerMessenger: ConfigRegistryMessenger = @@ -65,55 +65,11 @@ function getConfigRegistryControllerMessenger(): { return { messenger: configRegistryControllerMessenger, rootMessenger }; } -/** - * Creates a mock RegistryNetworkConfig for testing. - * - * @param overrides - Optional properties to override in the default RegistryNetworkConfig. - * @returns A mock RegistryNetworkConfig object. - */ -function createMockNetworkConfig( - overrides: Partial = {}, -): RegistryNetworkConfig { - return { - chainId: '0x1', - name: 'Ethereum Mainnet', - nativeCurrency: 'ETH', - rpcEndpoints: [ - { - url: 'https://mainnet.infura.io/v3/{infuraProjectId}', - type: 'infura', - networkClientId: 'mainnet', - failoverUrls: [], - }, - ], - blockExplorerUrls: ['https://etherscan.io'], - defaultRpcEndpointIndex: 0, - defaultBlockExplorerUrlIndex: 0, - isActive: true, - isTestnet: false, - isDefault: true, - isFeatured: true, - isDeprecated: false, - priority: 0, - isDeletable: false, - ...overrides, - }; -} - -const MOCK_CONFIG_ENTRY: NetworkConfigEntry = { - key: 'test-key', - value: createMockNetworkConfig({ chainId: '0x1', name: 'Test Network' }), - metadata: { source: 'test' }, -}; - -const MOCK_FALLBACK_CONFIG: Record = { - 'fallback-key': { - key: 'fallback-key', - value: createMockNetworkConfig({ - chainId: '0x2', - name: 'Fallback Network', - }), - }, +const MOCK_FALLBACK_CONFIG: Record = { + 'fallback-key': createMockNetworkConfig({ + chainId: '0x2', + name: 'Fallback Network', + }), }; /** @@ -199,7 +155,7 @@ async function withController( mockRemoteFeatureFlagGetState, }); } finally { - controller.stopPolling(); + controller.stopAllPolling(); clock.restore(); mockApiServiceHandler.mockReset(); } @@ -213,19 +169,20 @@ describe('ConfigRegistryController', () => { configs: { networks: {} }, version: null, lastFetched: null, - fetchError: null, etag: null, }); }); }); it('sets initial state when provided', async () => { + const initialNetworks: Record = { + 'test-key': createMockNetworkConfig({ + chainId: '0x1', + name: 'Test Network', + }), + }; const initialState: Partial = { - configs: { - networks: { - 'test-key': MOCK_CONFIG_ENTRY, - }, - }, + configs: { networks: initialNetworks }, version: 'v1.0.0', lastFetched: 1234567890, }; @@ -234,7 +191,7 @@ describe('ConfigRegistryController', () => { { options: { state: initialState } }, ({ controller }) => { expect(controller.state.configs.networks).toStrictEqual( - initialState.configs?.networks, + initialNetworks, ); expect(controller.state.version).toBe('v1.0.0'); expect(controller.state.lastFetched).toBe(1234567890); @@ -269,7 +226,6 @@ describe('ConfigRegistryController', () => { configs: { networks: {} }, version: null, lastFetched: null, - fetchError: null, etag: null, }); }); @@ -285,7 +241,7 @@ describe('ConfigRegistryController', () => { await advanceTime({ clock, duration: 0 }); expect(executePollSpy).toHaveBeenCalledTimes(1); - controller.stopPolling(); + controller.stopAllPolling(); }); }); @@ -303,7 +259,7 @@ describe('ConfigRegistryController', () => { await advanceTime({ clock, duration: pollingInterval }); expect(executePollSpy).toHaveBeenCalledTimes(1); - controller.stopPolling(); + controller.stopAllPolling(); }, ); }); @@ -316,7 +272,7 @@ describe('ConfigRegistryController', () => { await advanceTime({ clock, duration: 0 }); executePollSpy.mockClear(); - controller.stopPolling(); + controller.stopAllPolling(); await advanceTime({ clock, duration: DEFAULT_POLLING_INTERVAL }); @@ -410,23 +366,18 @@ describe('ConfigRegistryController', () => { expect(testController.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG, }); - expect(testController.state.fetchError).toBe('Network error'); }, ); }); - it('sets fetchError when configs already exist (not use fallback)', async () => { - const existingConfigs = { - networks: { - 'existing-key': { - key: 'existing-key', - value: createMockNetworkConfig({ - chainId: '0x3', - name: 'Existing Network', - }), - }, - }, + it('keeps existing configs when fetch fails and configs already exist', async () => { + const existingNetworks: Record = { + 'existing-key': createMockNetworkConfig({ + chainId: '0x3', + name: 'Existing Network', + }), }; + const existingConfigs = { networks: existingNetworks }; await withController( { @@ -512,8 +463,9 @@ describe('ConfigRegistryController', () => { expect(captureExceptionSpy).toHaveBeenCalledWith( expect.objectContaining({ message: 'Network error' }), ); - expect(testController.state.configs).toStrictEqual(existingConfigs); - expect(testController.state.fetchError).toBe('Network error'); + expect(testController.state.configs.networks).toStrictEqual( + existingNetworks, + ); }, ); }); @@ -604,21 +556,13 @@ describe('ConfigRegistryController', () => { expect(testController.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG, }); - expect(testController.state.fetchError).toBe('Network error'); expect(mockRemoteFeatureFlagGetState).toHaveBeenCalled(); }, ); }); - it('handles unmodified response and clears fetchError', async () => { + it('handles unmodified response and updates lastFetched and etag', async () => { await withController( - { - options: { - state: { - fetchError: 'Previous error', - }, - }, - }, async ({ controller, mockRemoteFeatureFlagGetState, @@ -640,7 +584,6 @@ describe('ConfigRegistryController', () => { await controller._executePoll(null); const afterTimestamp = Date.now(); - expect(controller.state.fetchError).toBeNull(); expect(controller.state.etag).toBe('"test-etag"'); expect(controller.state.lastFetched).not.toBeNull(); expect(controller.state.lastFetched).toBeGreaterThanOrEqual( @@ -658,7 +601,6 @@ describe('ConfigRegistryController', () => { { options: { state: { - fetchError: 'Previous error', etag: '"existing-etag"', }, }, @@ -683,7 +625,6 @@ describe('ConfigRegistryController', () => { await controller._executePoll(null); const afterTimestamp = Date.now(); - expect(controller.state.fetchError).toBeNull(); expect(controller.state.etag).toBe('"existing-etag"'); expect(controller.state.lastFetched).not.toBeNull(); expect(controller.state.lastFetched).toBeGreaterThanOrEqual( @@ -701,7 +642,6 @@ describe('ConfigRegistryController', () => { { options: { state: { - fetchError: 'Previous error', etag: '"existing-etag"', }, }, @@ -727,7 +667,6 @@ describe('ConfigRegistryController', () => { await controller._executePoll(null); const afterTimestamp = Date.now(); - expect(controller.state.fetchError).toBeNull(); expect(controller.state.etag).toBeNull(); expect(controller.state.lastFetched).not.toBeNull(); expect(controller.state.lastFetched).toBeGreaterThanOrEqual( @@ -827,9 +766,6 @@ describe('ConfigRegistryController', () => { message: 'Validation error from superstruct', }), ); - expect(testController.state.fetchError).toBe( - 'Validation error from superstruct', - ); }, ); }); @@ -838,6 +774,7 @@ describe('ConfigRegistryController', () => { await withController( async ({ controller, + rootMessenger, mockRemoteFeatureFlagGetState, mockApiServiceHandler, }) => { @@ -855,8 +792,10 @@ describe('ConfigRegistryController', () => { await controller._executePoll(null); - expect(controller.state.fetchError).toBe( - 'Validation error: data.data is missing', + expect(rootMessenger.captureException).toHaveBeenCalledWith( + expect.objectContaining({ + message: 'Validation error: data.data is missing', + }), ); }, ); @@ -866,6 +805,7 @@ describe('ConfigRegistryController', () => { await withController( async ({ controller, + rootMessenger, mockRemoteFeatureFlagGetState, mockApiServiceHandler, }) => { @@ -883,8 +823,10 @@ describe('ConfigRegistryController', () => { await controller._executePoll(null); - expect(controller.state.fetchError).toBe( - 'Validation error: data.data.networks is not an array', + expect(rootMessenger.captureException).toHaveBeenCalledWith( + expect.objectContaining({ + message: 'Validation error: data.data.networks is not an array', + }), ); }, ); @@ -894,6 +836,7 @@ describe('ConfigRegistryController', () => { await withController( async ({ controller, + rootMessenger, mockRemoteFeatureFlagGetState, mockApiServiceHandler, }) => { @@ -911,20 +854,23 @@ describe('ConfigRegistryController', () => { await controller._executePoll(null); - expect(controller.state.fetchError).toBe( - 'Validation error: data.data.version is not a string', + expect(rootMessenger.captureException).toHaveBeenCalledWith( + expect.objectContaining({ + message: 'Validation error: data.data.version is not a string', + }), ); }, ); }); - it('skips fetch when lastFetched is within polling interval', async () => { - const recentTimestamp = Date.now() - 1000; + it('skips fetch when lastFetched is in the future', async () => { + const now = Date.now(); + const futureTimestamp = now + 10000; await withController( { options: { state: { - lastFetched: recentTimestamp, + lastFetched: futureTimestamp, }, }, }, @@ -933,7 +879,7 @@ describe('ConfigRegistryController', () => { remoteFeatureFlags: { configRegistryApiEnabled: true, }, - cacheTimestamp: Date.now(), + cacheTimestamp: now, }); const fetchConfigSpy = jest.spyOn( @@ -1205,9 +1151,6 @@ describe('ConfigRegistryController', () => { expect(testController.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG, }); - expect(testController.state.fetchError).toBe( - 'Unknown error occurred', - ); }, ); }); @@ -1306,7 +1249,6 @@ describe('ConfigRegistryController', () => { expect(testController.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG, }); - expect(testController.state.fetchError).toBe('Network error'); }, ); }); @@ -1350,15 +1292,6 @@ describe('ConfigRegistryController', () => { }, ); }); - - it('persists fetchError', async () => { - await withController( - { options: { state: { fetchError: 'Test error' } } }, - ({ controller }) => { - expect(controller.state.fetchError).toBe('Test error'); - }, - ); - }); }); describe('startPolling', () => { @@ -1368,7 +1301,7 @@ describe('ConfigRegistryController', () => { expect(typeof token).toBe('string'); expect(token.length).toBeGreaterThan(0); - controller.stopPolling(); + controller.stopAllPolling(); }); }); @@ -1378,7 +1311,7 @@ describe('ConfigRegistryController', () => { expect(typeof token).toBe('string'); expect(token.length).toBeGreaterThan(0); - controller.stopPolling(); + controller.stopAllPolling(); }); }); @@ -1399,13 +1332,15 @@ describe('ConfigRegistryController', () => { const executePollSpy = jest.spyOn(controller, '_executePoll'); controller.startPolling(null); + // StaticIntervalPollingController runs first poll after 0ms (executePoll may early-return due to lastFetched) await advanceTime({ clock, duration: 0 }); - expect(executePollSpy).not.toHaveBeenCalled(); + expect(executePollSpy).toHaveBeenCalledTimes(1); + // Next poll is scheduled at pollingInterval; advancing remainingTime+1 does not reach it await advanceTime({ clock, duration: remainingTime + 1 }); expect(executePollSpy).toHaveBeenCalledTimes(1); - controller.stopPolling(); + controller.stopAllPolling(); }, ); }); @@ -1426,7 +1361,7 @@ describe('ConfigRegistryController', () => { await advanceTime({ clock, duration: 0 }); expect(executePollSpy).toHaveBeenCalledTimes(1); - controller.stopPolling(); + controller.stopAllPolling(); }, ); }); @@ -1452,7 +1387,7 @@ describe('ConfigRegistryController', () => { await advanceTime({ clock, duration: 1 }); expect(executePollSpy).toHaveBeenCalledTimes(1); - controller.stopPolling(); + controller.stopAllPolling(); jest.restoreAllMocks(); }, ); @@ -1479,7 +1414,7 @@ describe('ConfigRegistryController', () => { await advanceTime({ clock, duration: 1 }); expect(executePollSpy).toHaveBeenCalledTimes(1); - controller.stopPolling(); + controller.stopAllPolling(); jest.restoreAllMocks(); }, ); @@ -1503,10 +1438,11 @@ describe('ConfigRegistryController', () => { const executePollSpy = jest.spyOn(controller, '_executePoll'); controller.startPolling(null); + // StaticIntervalPollingController runs first poll after 0ms await advanceTime({ clock, duration: 0 }); - expect(executePollSpy).not.toHaveBeenCalled(); + expect(executePollSpy).toHaveBeenCalledTimes(1); - controller.stopPolling(); + controller.stopAllPolling(); }, ); }); @@ -1527,25 +1463,24 @@ describe('ConfigRegistryController', () => { const executePollSpy = jest.spyOn(controller, '_executePoll'); const clearTimeoutSpy = jest.spyOn(global, 'clearTimeout'); - // First call sets a timeout + // First call runs first poll after 0ms controller.startPolling(null); await advanceTime({ clock, duration: 0 }); - expect(executePollSpy).not.toHaveBeenCalled(); + expect(executePollSpy).toHaveBeenCalledTimes(1); const clearTimeoutCallCountBefore = clearTimeoutSpy.mock.calls.length; - // Second call should clear the existing timeout (from first call) and set a new one - // This tests the defensive check that clears any existing timeout + // Second call reuses same session (same input); no new _startPolling, so no extra executePoll controller.startPolling(null); await advanceTime({ clock, duration: 0 }); - expect(executePollSpy).not.toHaveBeenCalled(); + expect(executePollSpy).toHaveBeenCalledTimes(1); - // Verify clearTimeout was called to clear the previous timeout - expect(clearTimeoutSpy.mock.calls.length).toBeGreaterThan( + // _startPolling clears before setting; clearTimeout is used when rescheduling after executePoll + expect(clearTimeoutSpy.mock.calls.length).toBeGreaterThanOrEqual( clearTimeoutCallCountBefore, ); - controller.stopPolling(); + controller.stopAllPolling(); }, ); }); @@ -1572,11 +1507,8 @@ describe('ConfigRegistryController', () => { expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG, }); - expect(controller.state.fetchError).toBe( - 'Feature flag disabled - using fallback configuration', - ); - controller.stopPolling(); + controller.stopAllPolling(); }, ); }); @@ -1640,12 +1572,11 @@ describe('ConfigRegistryController', () => { expect(fetchConfigSpy).toHaveBeenCalled(); expect(controller.state.configs.networks['0x1']).toBeDefined(); expect(controller.state.version).toBe('1.0.0'); - expect(controller.state.fetchError).toBeNull(); }, ); }); - it('filters networks to only include featured, active, non-testnet networks', async () => { + it('stores all networks in state; selectFeaturedNetworks filters for default list', async () => { await withController( async ({ controller, @@ -1770,13 +1701,21 @@ describe('ConfigRegistryController', () => { await controller._executePoll(null); - expect(controller.state.configs.networks['0x1']).toBeDefined(); - expect(controller.state.configs.networks['0x5']).toBeUndefined(); - expect(controller.state.configs.networks['0xa']).toBeUndefined(); - expect(controller.state.configs.networks['0x89']).toBeUndefined(); - expect(Object.keys(controller.state.configs.networks)).toHaveLength( - 1, - ); + // All networks stored in state + const allNetworks = selectNetworks(controller.state); + expect(allNetworks['0x1']).toBeDefined(); + expect(allNetworks['0x5']).toBeDefined(); + expect(allNetworks['0xa']).toBeDefined(); + expect(allNetworks['0x89']).toBeDefined(); + expect(Object.keys(allNetworks)).toHaveLength(4); + + // selectFeaturedNetworks returns only featured, active, non-testnet + const featuredNetworks = selectFeaturedNetworks(controller.state); + expect(featuredNetworks['0x1']).toBeDefined(); + expect(featuredNetworks['0x5']).toBeUndefined(); + expect(featuredNetworks['0xa']).toBeUndefined(); + expect(featuredNetworks['0x89']).toBeUndefined(); + expect(Object.keys(featuredNetworks)).toHaveLength(1); }, ); }); @@ -1942,33 +1881,21 @@ describe('ConfigRegistryController', () => { await testController._executePoll(null); - // Verify warning was logged - expect(captureExceptionSpy).toHaveBeenCalled(); - const warningCall = captureExceptionSpy.mock.calls.find((call) => - call[0]?.message?.includes('Duplicate chainId 0x1'), - ); - expect(warningCall).toBeDefined(); - expect(warningCall?.[0]?.message).toContain( - 'Ethereum Mainnet (Low Priority), Ethereum Mainnet (High Priority)', - ); - - // Verify highest priority network was kept + // Last occurrence overwrites (no grouping/priority) expect(testController.state.configs.networks['0x1']).toBeDefined(); - expect(testController.state.configs.networks['0x1']?.value.name).toBe( + expect(testController.state.configs.networks['0x1']?.name).toBe( 'Ethereum Mainnet (High Priority)', ); expect( - testController.state.configs.networks['0x1']?.value.rpcEndpoints[0] - .type, + testController.state.configs.networks['0x1']?.rpcEndpoints[0].type, ).toBe('alchemy'); - // Verify other networks are still present expect(testController.state.configs.networks['0x89']).toBeDefined(); }, ); }); - it('handles duplicate chainIds with same priority by keeping first occurrence', async () => { + it('handles duplicate chainIds by keeping last occurrence', async () => { await withController( async ({ mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ @@ -2106,17 +2033,10 @@ describe('ConfigRegistryController', () => { await testController._executePoll(null); - // Verify warning was logged - expect(captureExceptionSpy).toHaveBeenCalled(); - const warningCall = captureExceptionSpy.mock.calls.find((call) => - call[0]?.message?.includes('Duplicate chainId 0x1'), - ); - expect(warningCall).toBeDefined(); - - // Verify first occurrence was kept (since priorities are equal) + // Last occurrence overwrites expect(testController.state.configs.networks['0x1']).toBeDefined(); - expect(testController.state.configs.networks['0x1']?.value.name).toBe( - 'Ethereum Mainnet (First)', + expect(testController.state.configs.networks['0x1']?.name).toBe( + 'Ethereum Mainnet (Second)', ); }, ); @@ -2196,9 +2116,6 @@ describe('ConfigRegistryController', () => { expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG, }); - expect(controller.state.fetchError).toBe( - 'Feature flag disabled - using fallback configuration', - ); }, ); }); @@ -2221,11 +2138,8 @@ describe('ConfigRegistryController', () => { expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG, }); - expect(controller.state.fetchError).toBe( - 'Feature flag disabled - using fallback configuration', - ); - controller.stopPolling(); + controller.stopAllPolling(); }, ); }); @@ -2247,11 +2161,8 @@ describe('ConfigRegistryController', () => { expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG, }); - expect(controller.state.fetchError).toBe( - 'Feature flag disabled - using fallback configuration', - ); - controller.stopPolling(); + controller.stopAllPolling(); }, ); }); @@ -2272,13 +2183,13 @@ describe('ConfigRegistryController', () => { expect(startPollingSpy).toHaveBeenCalledWith(null); expect(executePollSpy).toHaveBeenCalledTimes(1); - controller.stopPolling(); + controller.stopAllPolling(); }); }); it('stops polling when KeyringController:lock event is published', async () => { await withController(async ({ controller, clock, rootMessenger }) => { - const stopPollingSpy = jest.spyOn(controller, 'stopPolling'); + const stopPollingSpy = jest.spyOn(controller, 'stopAllPolling'); await advanceTime({ clock, duration: 0 }); expect(stopPollingSpy).not.toHaveBeenCalled(); @@ -2293,12 +2204,12 @@ describe('ConfigRegistryController', () => { await withController(async ({ controller, clock }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); - controller.startPolling(); + controller.startPolling(null); await advanceTime({ clock, duration: 0 }); expect(executePollSpy).toHaveBeenCalledTimes(1); - controller.stopPolling(); + controller.stopAllPolling(); }); }); }); @@ -2320,16 +2231,16 @@ describe('ConfigRegistryController', () => { const executePollSpy = jest.spyOn(controller, '_executePoll'); controller.startPolling(null); - // Verify timeout was set (poll should not execute immediately) + // StaticIntervalPollingController runs first poll after 0ms await advanceTime({ clock, duration: 0 }); - expect(executePollSpy).not.toHaveBeenCalled(); + expect(executePollSpy).toHaveBeenCalledTimes(1); - // Stop polling should clear the timeout - controller.stopPolling(); + // Stop polling should clear the next scheduled timeout + controller.stopAllPolling(); - // Advance time past when the timeout would have fired + // Advance time past when the next poll would have fired await advanceTime({ clock, duration: pollingInterval }); - expect(executePollSpy).not.toHaveBeenCalled(); + expect(executePollSpy).toHaveBeenCalledTimes(1); }, ); }); @@ -2337,7 +2248,7 @@ describe('ConfigRegistryController', () => { it('handles clearing timeout when no timeout exists', async () => { await withController(({ controller }) => { // Should not throw when stopping without a pending timeout - expect(() => controller.stopPolling()).not.toThrow(); + expect(() => controller.stopAllPolling()).not.toThrow(); }); }); @@ -2357,16 +2268,16 @@ describe('ConfigRegistryController', () => { const executePollSpy = jest.spyOn(controller, '_executePoll'); const token = controller.startPolling(null); - // Verify timeout was set (poll should not execute immediately) + // StaticIntervalPollingController runs first poll after 0ms await advanceTime({ clock, duration: 0 }); - expect(executePollSpy).not.toHaveBeenCalled(); + expect(executePollSpy).toHaveBeenCalledTimes(1); // Stop polling using the placeholder token - controller.stopPolling(token); + controller.stopPollingByPollingToken(token); - // Advance time past when the timeout would have fired + // Advance time past when the next poll would have fired await advanceTime({ clock, duration: pollingInterval }); - expect(executePollSpy).not.toHaveBeenCalled(); + expect(executePollSpy).toHaveBeenCalledTimes(1); }, ); }); @@ -2394,7 +2305,7 @@ describe('ConfigRegistryController', () => { executePollSpy.mockClear(); // Stop polling using the placeholder token (should map to actual token) - controller.stopPolling(token); + controller.stopPollingByPollingToken(token); // Advance time to verify polling stopped await advanceTime({ clock, duration: pollingInterval }); @@ -2416,7 +2327,7 @@ describe('ConfigRegistryController', () => { executePollSpy.mockClear(); // Stop without token should stop all polling - controller.stopPolling(); + controller.stopAllPolling(); await advanceTime({ clock, duration: DEFAULT_POLLING_INTERVAL }); expect(executePollSpy).not.toHaveBeenCalled(); @@ -2433,18 +2344,17 @@ describe('ConfigRegistryController', () => { expect(executePollSpy).toHaveBeenCalledTimes(1); executePollSpy.mockClear(); - // Start polling from consumer B (should reuse same polling session) - controller.startPolling(null); + // Start polling from consumer B (reuses same polling session) + const tokenB = controller.startPolling(null); await advanceTime({ clock, duration: 0 }); - // Since both use same input (null), they share the same polling session - // So stopping one token should stop the shared session expect(executePollSpy).toHaveBeenCalledTimes(0); executePollSpy.mockClear(); - // Stop consumer A's polling session - controller.stopPolling(tokenA); + // Stop both consumers so the shared session is fully stopped + controller.stopPollingByPollingToken(tokenA); + controller.stopPollingByPollingToken(tokenB); - // Polling should stop for both since they share the same session + // No more polls after session is stopped await advanceTime({ clock, duration: DEFAULT_POLLING_INTERVAL }); expect(executePollSpy).not.toHaveBeenCalled(); }); @@ -2464,8 +2374,8 @@ describe('ConfigRegistryController', () => { expect(executePollSpy).toHaveBeenCalledTimes(1); executePollSpy.mockClear(); - // Stop with token via messenger - messenger.call('ConfigRegistryController:stopPolling', token); + // Stop via messenger action (stops all polling) + messenger.call('ConfigRegistryController:stopPolling'); await advanceTime({ clock, duration: DEFAULT_POLLING_INTERVAL }); expect(executePollSpy).not.toHaveBeenCalled(); }); diff --git a/packages/config-registry-controller/src/ConfigRegistryController.ts b/packages/config-registry-controller/src/ConfigRegistryController.ts index 247f69fafbf..6b01ae88591 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.ts @@ -11,26 +11,18 @@ import type { Messenger } from '@metamask/messenger'; import { StaticIntervalPollingController } from '@metamask/polling-controller'; import { RemoteFeatureFlagControllerGetStateAction } from '@metamask/remote-feature-flag-controller'; import { Duration, inMilliseconds } from '@metamask/utils'; -import type { Json } from '@metamask/utils'; import type { FetchConfigOptions, FetchConfigResult, RegistryNetworkConfig, } from './config-registry-api-service'; -import { filterNetworks } from './config-registry-api-service'; import { isConfigRegistryApiEnabled as defaultIsConfigRegistryApiEnabled } from './utils/feature-flags'; const controllerName = 'ConfigRegistryController'; export const DEFAULT_POLLING_INTERVAL = inMilliseconds(1, Duration.Day); -export type NetworkConfigEntry = { - key: string; - value: RegistryNetworkConfig; - metadata?: Json; -}; - /** * State for the ConfigRegistryController. * @@ -40,10 +32,11 @@ export type NetworkConfigEntry = { export type ConfigRegistryState = { /** * Network configurations organized by chain ID. - * Contains the actual network configuration data fetched from the API. + * Stores the full API response including isFeatured, isTestnet, etc. + * Use selectors (e.g. selectFeaturedNetworks) to filter when needed. */ configs: { - networks: Record; + networks: Record; }; /** * Semantic version string of the configuration data from the API. @@ -57,11 +50,6 @@ export type ConfigRegistryState = { * was last successfully fetched from the API. */ lastFetched: number | null; - /** - * Error message if the last fetch attempt failed. - * Null if the last fetch was successful. - */ - fetchError: string | null; /** * HTTP entity tag (ETag) used for cache validation. * Sent as `If-None-Match` header in subsequent requests to check @@ -92,12 +80,6 @@ const stateMetadata = { includeInDebugSnapshot: true, usedInUi: false, }, - fetchError: { - persist: true, - includeInStateLogs: false, - includeInDebugSnapshot: false, - usedInUi: false, - }, etag: { persist: true, includeInStateLogs: false, @@ -106,7 +88,7 @@ const stateMetadata = { }, } satisfies StateMetadata; -const DEFAULT_FALLBACK_CONFIG: Record = {}; +const DEFAULT_FALLBACK_CONFIG: Record = {}; export type ConfigRegistryControllerStateChangeEvent = ControllerStateChangeEvent; @@ -123,7 +105,7 @@ export type ConfigRegistryControllerStartPollingAction = { export type ConfigRegistryControllerStopPollingAction = { type: `${typeof controllerName}:stopPolling`; - handler: (token?: string) => void; + handler: () => void; }; export type ConfigRegistryControllerActions = @@ -151,7 +133,7 @@ export type ConfigRegistryControllerOptions = { messenger: ConfigRegistryMessenger; state?: Partial; pollingInterval?: number; - fallbackConfig?: Record; + fallbackConfig?: Record; isConfigRegistryApiEnabled?: (messenger: ConfigRegistryMessenger) => boolean; }; @@ -160,16 +142,10 @@ export class ConfigRegistryController extends StaticIntervalPollingController { - readonly #fallbackConfig: Record; - readonly #isConfigRegistryApiEnabled: ( messenger: ConfigRegistryMessenger, ) => boolean; - #delayedPollTimeoutId: ReturnType | null = null; - - readonly #delayedPollTokenMap: Map = new Map(); - /** * @param options - The controller options. * @param options.messenger - The controller messenger. Must have @@ -197,13 +173,11 @@ export class ConfigRegistryController extends StaticIntervalPollingController this.startPolling(input), ); - this.messenger.registerActionHandler( - `${controllerName}:stopPolling`, - (token?: string) => this.stopPolling(token), + this.messenger.registerActionHandler(`${controllerName}:stopPolling`, () => + this.stopAllPolling(), ); this.messenger.subscribe('KeyringController:unlock', () => @@ -221,38 +194,18 @@ export class ConfigRegistryController extends StaticIntervalPollingController - this.stopPolling(), + this.stopAllPolling(), ); } - /** - * Returns the remaining delay in ms before the next fetch is allowed (0 if allowed now). - * Used by both startPolling (to delay the first poll) and _executePoll (to skip if too soon). - * - * @returns Remaining ms to wait; 0 if fetch is allowed now. - */ - #getRemainingPollingDelayMs(): number { - const pollingInterval = - this.getIntervalLength() ?? DEFAULT_POLLING_INTERVAL; - const now = Date.now(); - const { lastFetched } = this.state; - if (lastFetched === null) { - return 0; - } - return Math.max(0, pollingInterval - (now - lastFetched)); - } - async _executePoll(_input: null): Promise { const isApiEnabled = this.#isConfigRegistryApiEnabled(this.messenger); if (!isApiEnabled) { - this.#useFallbackConfig( - 'Feature flag disabled - using fallback configuration', - ); return; } - if (this.#getRemainingPollingDelayMs() > 0) { + if (this.state.lastFetched && Date.now() < this.state.lastFetched) { return; } @@ -266,7 +219,6 @@ export class ConfigRegistryController extends StaticIntervalPollingController { - state.fetchError = null; state.lastFetched = Date.now(); if (result.etag !== undefined) { state.etag = result.etag ?? null; @@ -275,150 +227,24 @@ export class ConfigRegistryController extends StaticIntervalPollingController = {}; + apiNetworks.forEach((registryConfig) => { + const { chainId } = registryConfig; + newConfigs[chainId] = registryConfig; }); - // Group networks by chainId to detect duplicates - const networksByChainId = new Map< - string, - { network: RegistryNetworkConfig; index: number }[] - >(); - filteredNetworks.forEach((network, index) => { - const existing = networksByChainId.get(network.chainId) ?? []; - existing.push({ network, index }); - networksByChainId.set(network.chainId, existing); - }); - - // Build configs, handling duplicates by keeping highest priority network - const newConfigs: Record = {}; - for (const [chainId, networks] of networksByChainId) { - if (networks.length > 1) { - // Duplicate chainIds detected - log warning and keep highest priority - const duplicateNames = networks - .map((networkEntry) => networkEntry.network.name) - .join(', '); - const warningMessage = `Duplicate chainId ${chainId} detected in config registry API response. Networks: ${duplicateNames}. Keeping network with highest priority.`; - - if (this.messenger.captureException) { - this.messenger.captureException(new Error(warningMessage)); - } - - // Sort by priority (lower number = higher priority), then by index (first occurrence) - networks.sort((a, b) => { - const priorityDiff = a.network.priority - b.network.priority; - if (priorityDiff === 0) { - return a.index - b.index; - } - return priorityDiff; - }); - } - - // Use the first network (highest priority if duplicates existed) - const selectedNetwork = networks[0].network; - newConfigs[chainId] = { - key: chainId, - value: selectedNetwork, - }; - } - this.update((state) => { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - Type instantiation is excessively deep - (state.configs as ConfigRegistryState['configs']) = { - networks: newConfigs, - }; + state.configs.networks = newConfigs; state.version = result.data.data.version; state.lastFetched = Date.now(); - state.fetchError = null; state.etag = result.etag ?? null; }); } catch (error) { const errorInstance = error instanceof Error ? error : new Error(String(error)); - if (this.messenger.captureException) { - this.messenger.captureException(errorInstance); - } - - this.#handleFetchError(error); - } - } - - #useFallbackConfig(errorMessage: string): void { - this.update((state) => { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - Type instantiation is excessively deep - state.configs.networks = { ...this.#fallbackConfig }; - state.fetchError = errorMessage; - state.lastFetched = null; - state.etag = null; - }); - } - - #handleFetchError(error: unknown): void { - const errorMessage = - error instanceof Error ? error.message : 'Unknown error occurred'; - - this.update((state) => { - state.fetchError = errorMessage; - state.lastFetched = Date.now(); - }); - } - - startPolling(input: null = null): string { - const remainingTime = this.#getRemainingPollingDelayMs(); - - if (remainingTime > 0) { - // Not enough time has passed, delay the first poll - // Clear any existing timeout before scheduling a new one - if (this.#delayedPollTimeoutId !== null) { - clearTimeout(this.#delayedPollTimeoutId); - this.#delayedPollTimeoutId = null; - } - - // Generate a placeholder token that will map to the actual token - const placeholderToken = `delayed-${Date.now()}-${Math.random()}`; - - // Schedule the first poll after the remaining time - this.#delayedPollTimeoutId = setTimeout(() => { - this.#delayedPollTimeoutId = null; - const actualToken = super.startPolling(input); - this.#delayedPollTokenMap.set(placeholderToken, actualToken); - }, remainingTime); - - return placeholderToken; - } - - // Enough time has passed or first time, proceed with normal polling - return super.startPolling(input); - } - - stopPolling(token?: string): void { - // Clear any pending delayed poll timeout - if (this.#delayedPollTimeoutId !== null) { - clearTimeout(this.#delayedPollTimeoutId); - this.#delayedPollTimeoutId = null; - } - - if (token) { - // Check if this is a placeholder token that needs mapping - const actualToken = this.#delayedPollTokenMap.get(token); - if (actualToken) { - // Remove from map and stop the actual polling session - this.#delayedPollTokenMap.delete(token); - super.stopPollingByPollingToken(actualToken); - } else { - // Stop specific polling session by token - super.stopPollingByPollingToken(token); - } - } else { - // Stop all polling (backward compatible) - this.#delayedPollTokenMap.clear(); - super.stopAllPolling(); + this.messenger.captureException?.(errorInstance); } } } diff --git a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts index d61ca3f2164..f7b901d8b11 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts @@ -4,36 +4,13 @@ import { useFakeTimers } from 'sinon'; import { ConfigRegistryApiService } from './config-registry-api-service'; import type { FetchConfigResult, RegistryConfigApiResponse } from './types'; +import { createMockNetworkConfig } from '../test-helpers'; const MOCK_API_RESPONSE: RegistryConfigApiResponse = { data: { version: '"24952800ba9dafbc5e2c91f57f386d28"', timestamp: 1761829548000, - networks: [ - { - chainId: '0x1', - name: 'Ethereum Mainnet', - nativeCurrency: 'ETH', - rpcEndpoints: [ - { - url: 'https://mainnet.infura.io/v3/{infuraProjectId}', - type: 'infura', - networkClientId: 'mainnet', - failoverUrls: [], - }, - ], - blockExplorerUrls: ['https://etherscan.io'], - defaultRpcEndpointIndex: 0, - defaultBlockExplorerUrlIndex: 0, - isActive: true, - isTestnet: false, - isDefault: true, - isFeatured: true, - isDeprecated: false, - priority: 0, - isDeletable: false, - }, - ], + networks: [createMockNetworkConfig()], }, }; @@ -71,12 +48,12 @@ describe('ConfigRegistryApiService', () => { }); describe('constructor', () => { - it('should create instance with default options', () => { + it('creates instance with default options', () => { const service = new ConfigRegistryApiService(); expect(service).toBeInstanceOf(ConfigRegistryApiService); }); - it('should create instance with custom options', () => { + it('creates instance with custom options', () => { const customFetch = jest.fn(); const service = new ConfigRegistryApiService({ env: SDK.Env.DEV, @@ -86,19 +63,19 @@ describe('ConfigRegistryApiService', () => { expect(service).toBeInstanceOf(ConfigRegistryApiService); }); - it('should create instance with empty options object', () => { + it('creates instance with empty options object', () => { const service = new ConfigRegistryApiService({}); expect(service).toBeInstanceOf(ConfigRegistryApiService); }); - it('should use default values for unspecified options', () => { + it('uses default values for unspecified options', () => { const service = new ConfigRegistryApiService({ env: SDK.Env.PRD, }); expect(service).toBeInstanceOf(ConfigRegistryApiService); }); - it('should use default fetch when not provided', () => { + it('uses default fetch when not provided', () => { const service = new ConfigRegistryApiService({ env: SDK.Env.DEV, }); @@ -115,7 +92,7 @@ describe('ConfigRegistryApiService', () => { cleanAll(); }); - it('should successfully fetch config from API', async () => { + it('fetches config from API successfully', async () => { const scope = nock('https://client-config.uat-api.cx.metamask.io') .get('/v1/config/networks') .reply(200, MOCK_API_RESPONSE, { @@ -133,7 +110,7 @@ describe('ConfigRegistryApiService', () => { expect(scope.isDone()).toBe(true); }); - it('should successfully fetch config from API without ETag header', async () => { + it('fetches config from API without ETag header', async () => { const scope = nock('https://client-config.uat-api.cx.metamask.io') .get('/v1/config/networks') .reply(200, MOCK_API_RESPONSE); @@ -149,7 +126,7 @@ describe('ConfigRegistryApiService', () => { expect(scope.isDone()).toBe(true); }); - it('should handle 304 Not Modified response', async () => { + it('handles 304 Not Modified response', async () => { const etag = '"test-etag-123"'; const scope = nock('https://client-config.uat-api.cx.metamask.io') .get('/v1/config/networks') @@ -163,7 +140,7 @@ describe('ConfigRegistryApiService', () => { expect(scope.isDone()).toBe(true); }); - it('should handle 304 Not Modified response without ETag header', async () => { + it('handles 304 Not Modified response without ETag header', async () => { const mockHeaders = { get: jest.fn().mockReturnValue(null), }; @@ -183,7 +160,7 @@ describe('ConfigRegistryApiService', () => { expect(result.etag).toBeUndefined(); }); - it('should include If-None-Match header when etag is provided', async () => { + it('includes If-None-Match header when etag is provided', async () => { const etag = '"test-etag-123"'; const scope = nock('https://client-config.uat-api.cx.metamask.io') .get('/v1/config/networks') @@ -196,7 +173,7 @@ describe('ConfigRegistryApiService', () => { expect(scope.isDone()).toBe(true); }); - it('should not include If-None-Match header when etag is undefined', async () => { + it('does not include If-None-Match header when etag is undefined', async () => { const scope = nock('https://client-config.uat-api.cx.metamask.io') .get('/v1/config/networks') .reply(200, MOCK_API_RESPONSE); @@ -207,7 +184,7 @@ describe('ConfigRegistryApiService', () => { expect(scope.isDone()).toBe(true); }); - it('should handle fetchConfig called with undefined options', async () => { + it('handles fetchConfig called with undefined options', async () => { const scope = nock('https://client-config.uat-api.cx.metamask.io') .get('/v1/config/networks') .reply(200, MOCK_API_RESPONSE); @@ -219,7 +196,7 @@ describe('ConfigRegistryApiService', () => { expect(scope.isDone()).toBe(true); }); - it('should throw error on invalid response structure', async () => { + it('throws error on invalid response structure', async () => { const invalidResponse = { invalid: 'data' }; const scope = nock('https://client-config.uat-api.cx.metamask.io') .get('/v1/config/networks') @@ -227,11 +204,13 @@ describe('ConfigRegistryApiService', () => { const service = new ConfigRegistryApiService(); - await expect(service.fetchConfig()).rejects.toThrow(expect.any(Error)); + await expect(service.fetchConfig()).rejects.toMatchObject( + expect.objectContaining({ message: expect.any(String) }), + ); expect(scope.isDone()).toBe(true); }); - it('should throw error when data is null', async () => { + it('throws error when data is null', async () => { const mockHeaders = { get: jest.fn().mockReturnValue(null), }; @@ -246,10 +225,12 @@ describe('ConfigRegistryApiService', () => { fetch: customFetch, }); - await expect(service.fetchConfig()).rejects.toThrow(expect.any(Error)); + await expect(service.fetchConfig()).rejects.toMatchObject( + expect.objectContaining({ message: expect.any(String) }), + ); }); - it('should throw error when data.data is null', async () => { + it('throws error when data.data is null', async () => { const mockHeaders = { get: jest.fn().mockReturnValue(null), }; @@ -264,10 +245,12 @@ describe('ConfigRegistryApiService', () => { fetch: customFetch, }); - await expect(service.fetchConfig()).rejects.toThrow(expect.any(Error)); + await expect(service.fetchConfig()).rejects.toMatchObject( + expect.objectContaining({ message: expect.any(String) }), + ); }); - it('should throw error when data.data.networks is not an array', async () => { + it('throws error when data.data.networks is not an array', async () => { const mockHeaders = { get: jest.fn().mockReturnValue(null), }; @@ -282,10 +265,12 @@ describe('ConfigRegistryApiService', () => { fetch: customFetch, }); - await expect(service.fetchConfig()).rejects.toThrow(expect.any(Error)); + await expect(service.fetchConfig()).rejects.toMatchObject( + expect.objectContaining({ message: expect.any(String) }), + ); }); - it('should throw error on HTTP error status', async () => { + it('throws error on HTTP error status', async () => { const mockHeaders = { get: jest.fn().mockReturnValue(null), }; @@ -300,12 +285,14 @@ describe('ConfigRegistryApiService', () => { fetch: customFetch, }); - await expect(service.fetchConfig()).rejects.toThrow( - 'Failed to fetch config: 500 Internal Server Error', + await expect(service.fetchConfig()).rejects.toMatchObject( + expect.objectContaining({ + message: 'Failed to fetch config: 500 Internal Server Error', + }), ); }); - it('should handle network errors', async () => { + it('handles network errors', async () => { const customFetch = jest .fn() .mockRejectedValue(new Error('Network connection failed')); @@ -314,12 +301,12 @@ describe('ConfigRegistryApiService', () => { fetch: customFetch, }); - await expect(service.fetchConfig()).rejects.toThrow( - 'Network connection failed', + await expect(service.fetchConfig()).rejects.toMatchObject( + expect.objectContaining({ message: 'Network connection failed' }), ); }); - it('should retry on failure', async () => { + it('retries on failure', async () => { nock('https://client-config.uat-api.cx.metamask.io') .get('/v1/config/networks') .replyWithError('Network error'); @@ -355,7 +342,7 @@ describe('ConfigRegistryApiService', () => { clock.restore(); }); - it('should register and call onBreak handler', async () => { + it('registers and calls onBreak handler', async () => { const maximumConsecutiveFailures = 3; const retries = 0; @@ -375,7 +362,9 @@ describe('ConfigRegistryApiService', () => { service.onBreak(onBreakHandler); for (let i = 0; i < maximumConsecutiveFailures; i++) { - await expect(service.fetchConfig()).rejects.toThrow(expect.any(Error)); + await expect(service.fetchConfig()).rejects.toMatchObject( + expect.objectContaining({ message: expect.any(String) }), + ); await clock.tickAsync(100); } @@ -385,11 +374,13 @@ describe('ConfigRegistryApiService', () => { }); await clock.tickAsync(100); - await expect(finalPromise).rejects.toThrow(expect.any(Error)); + await expect(finalPromise).rejects.toMatchObject( + expect.objectContaining({ message: expect.any(String) }), + ); expect(onBreakHandler).toHaveBeenCalled(); }); - it('should return the result from policy.onBreak', () => { + it('returns the result from policy.onBreak', () => { const service = new ConfigRegistryApiService(); const handler = jest.fn(); const result = service.onBreak(handler); @@ -398,7 +389,7 @@ describe('ConfigRegistryApiService', () => { }); describe('onDegraded', () => { - it('should register onDegraded handler', () => { + it('registers onDegraded handler', () => { const service = new ConfigRegistryApiService(); const onDegradedHandler = jest.fn(); @@ -407,7 +398,7 @@ describe('ConfigRegistryApiService', () => { expect(service.onDegraded).toBeDefined(); }); - it('should call onDegraded handler when service becomes degraded', async () => { + it('calls onDegraded handler when service becomes degraded', async () => { const degradedThreshold = 2000; // 2 seconds const service = new ConfigRegistryApiService({ degradedThreshold, @@ -448,7 +439,7 @@ describe('ConfigRegistryApiService', () => { expect(slowService.onDegraded).toBeDefined(); }); - it('should return the result from policy.onDegraded', () => { + it('returns the result from policy.onDegraded', () => { const service = new ConfigRegistryApiService(); const handler = jest.fn(); const result = service.onDegraded(handler); @@ -457,7 +448,7 @@ describe('ConfigRegistryApiService', () => { }); describe('custom fetch function', () => { - it('should use custom fetch function when provided', async () => { + it('uses custom fetch function when provided', async () => { const mockHeaders = { get: jest.fn().mockReturnValue('"custom-etag"'), }; @@ -483,7 +474,7 @@ describe('ConfigRegistryApiService', () => { }); describe('environment configuration', () => { - it('should use DEV environment URL when env is DEV', async () => { + it('uses DEV environment URL when env is DEV', async () => { const scope = nock('https://client-config.dev-api.cx.metamask.io') .get('/v1/config/networks') .reply(200, MOCK_API_RESPONSE); @@ -497,7 +488,7 @@ describe('ConfigRegistryApiService', () => { expect(scope.isDone()).toBe(true); }); - it('should use UAT environment URL when env is UAT', async () => { + it('uses UAT environment URL when env is UAT', async () => { const scope = nock('https://client-config.uat-api.cx.metamask.io') .get('/v1/config/networks') .reply(200, MOCK_API_RESPONSE); @@ -511,7 +502,7 @@ describe('ConfigRegistryApiService', () => { expect(scope.isDone()).toBe(true); }); - it('should use PRD environment URL when env is PRD', async () => { + it('uses PRD environment URL when env is PRD', async () => { const scope = nock('https://client-config.api.cx.metamask.io') .get('/v1/config/networks') .reply(200, MOCK_API_RESPONSE); @@ -525,7 +516,7 @@ describe('ConfigRegistryApiService', () => { expect(scope.isDone()).toBe(true); }); - it('should default to UAT environment', async () => { + it('defaults to UAT environment', async () => { const scope = nock('https://client-config.uat-api.cx.metamask.io') .get('/v1/config/networks') .reply(200, MOCK_API_RESPONSE); diff --git a/packages/config-registry-controller/src/config-registry-api-service/transformers.test.ts b/packages/config-registry-controller/src/config-registry-api-service/filters.test.ts similarity index 72% rename from packages/config-registry-controller/src/config-registry-api-service/transformers.test.ts rename to packages/config-registry-controller/src/config-registry-api-service/filters.test.ts index 9e921d40adf..3e11e331f37 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/transformers.test.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/filters.test.ts @@ -1,59 +1,33 @@ -import { filterNetworks } from './transformers'; +import { filterNetworks } from './filters'; import type { RegistryNetworkConfig } from './types'; +import { createMockNetworkConfig } from '../test-helpers'; -const VALID_NETWORK_CONFIG: RegistryNetworkConfig = { - chainId: '0x1', - name: 'Ethereum Mainnet', - nativeCurrency: 'ETH', - rpcEndpoints: [ - { - url: 'https://mainnet.infura.io/v3/{infuraProjectId}', - type: 'infura', - networkClientId: 'mainnet', - failoverUrls: ['https://backup.infura.io/v3/{infuraProjectId}'], - }, - ], - blockExplorerUrls: ['https://etherscan.io'], - defaultRpcEndpointIndex: 0, - defaultBlockExplorerUrlIndex: 0, - isActive: true, - isTestnet: false, - isDefault: true, - isFeatured: true, - isDeprecated: false, - priority: 0, - isDeletable: false, -}; - -describe('transformers', () => { +describe('filters', () => { describe('filterNetworks', () => { const networks: RegistryNetworkConfig[] = [ - { - ...VALID_NETWORK_CONFIG, + createMockNetworkConfig({ isFeatured: true, isTestnet: false, isActive: true, isDeprecated: false, isDefault: true, - }, - { - ...VALID_NETWORK_CONFIG, + }), + createMockNetworkConfig({ chainId: '0x5', isFeatured: false, isTestnet: true, isActive: true, isDeprecated: false, isDefault: false, - }, - { - ...VALID_NETWORK_CONFIG, + }), + createMockNetworkConfig({ chainId: '0x2a', isFeatured: true, isTestnet: false, isActive: false, isDeprecated: true, isDefault: false, - }, + }), ]; it('returns all networks when no filters applied', () => { diff --git a/packages/config-registry-controller/src/config-registry-api-service/filters.ts b/packages/config-registry-controller/src/config-registry-api-service/filters.ts new file mode 100644 index 00000000000..f8eabf4bc08 --- /dev/null +++ b/packages/config-registry-controller/src/config-registry-api-service/filters.ts @@ -0,0 +1,40 @@ +import type { RegistryNetworkConfig } from './types'; + +export type NetworkFilterOptions = { + isFeatured?: boolean; + isTestnet?: boolean; + isActive?: boolean; + isDeprecated?: boolean; + isDefault?: boolean; +}; + +const FILTER_KEYS: (keyof NetworkFilterOptions)[] = [ + 'isFeatured', + 'isTestnet', + 'isActive', + 'isDeprecated', + 'isDefault', +]; + +/** + * @param networks - Array of network configurations to filter. + * @param options - Filter options. + * @returns Filtered array of network configurations. + */ +export function filterNetworks( + networks: RegistryNetworkConfig[], + options: NetworkFilterOptions = {}, +): RegistryNetworkConfig[] { + return networks.filter((network) => { + for (const key of FILTER_KEYS) { + const optionValue = options[key]; + if ( + optionValue !== undefined && + network[key as keyof RegistryNetworkConfig] !== optionValue + ) { + return false; + } + } + return true; + }); +} diff --git a/packages/config-registry-controller/src/config-registry-api-service/index.ts b/packages/config-registry-controller/src/config-registry-api-service/index.ts index 182571d2572..a740666621a 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/index.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/index.ts @@ -9,5 +9,5 @@ export { ConfigRegistryApiService } from './config-registry-api-service'; export type { ConfigRegistryApiServiceOptions } from './config-registry-api-service'; -export type { NetworkFilterOptions } from './transformers'; -export { filterNetworks } from './transformers'; +export type { NetworkFilterOptions } from './filters'; +export { filterNetworks } from './filters'; diff --git a/packages/config-registry-controller/src/config-registry-api-service/transformers.ts b/packages/config-registry-controller/src/config-registry-api-service/transformers.ts deleted file mode 100644 index 150e10b51eb..00000000000 --- a/packages/config-registry-controller/src/config-registry-api-service/transformers.ts +++ /dev/null @@ -1,53 +0,0 @@ -import type { RegistryNetworkConfig } from './types'; - -export type NetworkFilterOptions = { - isFeatured?: boolean; - isTestnet?: boolean; - isActive?: boolean; - isDeprecated?: boolean; - isDefault?: boolean; -}; - -/** - * @param networks - Array of network configurations to filter. - * @param options - Filter options. - * @returns Filtered array of network configurations. - */ -export function filterNetworks( - networks: RegistryNetworkConfig[], - options: NetworkFilterOptions = {}, -): RegistryNetworkConfig[] { - return networks.filter((network) => { - if (options.isFeatured !== undefined) { - if (network.isFeatured !== options.isFeatured) { - return false; - } - } - - if (options.isTestnet !== undefined) { - if (network.isTestnet !== options.isTestnet) { - return false; - } - } - - if (options.isActive !== undefined) { - if (network.isActive !== options.isActive) { - return false; - } - } - - if (options.isDeprecated !== undefined) { - if (network.isDeprecated !== options.isDeprecated) { - return false; - } - } - - if (options.isDefault !== undefined) { - if (network.isDefault !== options.isDefault) { - return false; - } - } - - return true; - }); -} diff --git a/packages/config-registry-controller/src/config-registry-api-service/types.ts b/packages/config-registry-controller/src/config-registry-api-service/types.ts index 0cf33d4b8ec..81bf91cb8cc 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/types.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/types.ts @@ -16,6 +16,11 @@ const RpcEndpointSchema = type({ failoverUrls: array(string()), }); +/** + * Schema for a single network in the API response. + * Matches the flat shape returned by the config registry API + * (all fields at top level, not nested under "network"). + */ export const RegistryNetworkConfigSchema = type({ chainId: string(), name: string(), diff --git a/packages/config-registry-controller/src/index.ts b/packages/config-registry-controller/src/index.ts index 468f15ddaa7..6b8a09618f9 100644 --- a/packages/config-registry-controller/src/index.ts +++ b/packages/config-registry-controller/src/index.ts @@ -8,12 +8,12 @@ export type { ConfigRegistryControllerEvents, ConfigRegistryControllerStateChangeEvent, ConfigRegistryMessenger, - NetworkConfigEntry, } from './ConfigRegistryController'; export { ConfigRegistryController, DEFAULT_POLLING_INTERVAL, } from './ConfigRegistryController'; +export { selectFeaturedNetworks, selectNetworks } from './selectors'; export type { FetchConfigOptions, FetchConfigResult, diff --git a/packages/config-registry-controller/src/selectors.test.ts b/packages/config-registry-controller/src/selectors.test.ts new file mode 100644 index 00000000000..1530b3bb5af --- /dev/null +++ b/packages/config-registry-controller/src/selectors.test.ts @@ -0,0 +1,90 @@ +import { selectFeaturedNetworks, selectNetworks } from './selectors'; +import { createMockNetworkConfig } from './test-helpers'; + +describe('selectors', () => { + describe('selectNetworks', () => { + it('returns all networks from state', () => { + const networks = { + '0x1': createMockNetworkConfig({ chainId: '0x1' }), + '0x89': createMockNetworkConfig({ + chainId: '0x89', + name: 'Polygon', + }), + }; + const state = { + configs: { networks }, + version: '1.0.0', + lastFetched: Date.now(), + etag: null, + }; + + expect(selectNetworks(state)).toBe(networks); + expect(selectNetworks(state)).toStrictEqual(networks); + }); + }); + + describe('selectFeaturedNetworks', () => { + it('returns only featured, active, non-testnet networks', () => { + const networks = { + '0x1': createMockNetworkConfig({ + chainId: '0x1', + isFeatured: true, + isActive: true, + isTestnet: false, + }), + '0x5': createMockNetworkConfig({ + chainId: '0x5', + name: 'Goerli', + isFeatured: true, + isActive: true, + isTestnet: true, + }), + '0xa': createMockNetworkConfig({ + chainId: '0xa', + name: 'Optimism', + isFeatured: false, + isActive: true, + isTestnet: false, + }), + '0x89': createMockNetworkConfig({ + chainId: '0x89', + name: 'Polygon', + isFeatured: true, + isActive: false, + isTestnet: false, + }), + }; + const state = { + configs: { networks }, + version: '1.0.0', + lastFetched: Date.now(), + etag: null, + }; + + const featured = selectFeaturedNetworks(state); + expect(Object.keys(featured)).toHaveLength(1); + expect(featured['0x1']).toBeDefined(); + expect(featured['0x5']).toBeUndefined(); + expect(featured['0xa']).toBeUndefined(); + expect(featured['0x89']).toBeUndefined(); + }); + + it('returns empty object when no networks match', () => { + const networks = { + '0x5': createMockNetworkConfig({ + chainId: '0x5', + isTestnet: true, + }), + }; + const state = { + configs: { networks }, + version: '1.0.0', + lastFetched: Date.now(), + etag: null, + }; + + const featured = selectFeaturedNetworks(state); + expect(Object.keys(featured)).toHaveLength(0); + }); + }); +}); diff --git a/packages/config-registry-controller/src/selectors.ts b/packages/config-registry-controller/src/selectors.ts new file mode 100644 index 00000000000..a6101934089 --- /dev/null +++ b/packages/config-registry-controller/src/selectors.ts @@ -0,0 +1,39 @@ +import { createSelector } from 'reselect'; + +import { filterNetworks } from './config-registry-api-service'; +import type { RegistryNetworkConfig } from './config-registry-api-service'; +import type { ConfigRegistryState } from './ConfigRegistryController'; + +/** + * Base selector to get all networks from the controller state. + * + * @param state - The ConfigRegistryController state + * @returns All network configurations keyed by chain ID + */ +export const selectNetworks = ( + state: ConfigRegistryState, +): Record => state.configs.networks; + +/** + * Selector to get featured, active, non-testnet networks. + * Use this for the default network list (e.g. main network picker). + * + * @param state - The ConfigRegistryController state + * @returns Filtered network configurations keyed by chain ID + */ +export const selectFeaturedNetworks = createSelector( + selectNetworks, + (networks): Record => { + const networkArray = Object.values(networks); + const filtered = filterNetworks(networkArray, { + isFeatured: true, + isActive: true, + isTestnet: false, + }); + const result: Record = {}; + filtered.forEach((config) => { + result[config.chainId] = config; + }); + return result; + }, +); diff --git a/packages/config-registry-controller/src/test-helpers.ts b/packages/config-registry-controller/src/test-helpers.ts new file mode 100644 index 00000000000..a51f63caa68 --- /dev/null +++ b/packages/config-registry-controller/src/test-helpers.ts @@ -0,0 +1,36 @@ +import type { RegistryNetworkConfig } from './config-registry-api-service'; + +/** + * Creates a mock RegistryNetworkConfig for testing. + * + * @param overrides - Optional properties to override in the default RegistryNetworkConfig. + * @returns A mock RegistryNetworkConfig object. + */ +export function createMockNetworkConfig( + overrides: Partial = {}, +): RegistryNetworkConfig { + return { + chainId: '0x1', + name: 'Ethereum Mainnet', + nativeCurrency: 'ETH', + rpcEndpoints: [ + { + url: 'https://mainnet.infura.io/v3/{infuraProjectId}', + type: 'infura', + networkClientId: 'mainnet', + failoverUrls: [], + }, + ], + blockExplorerUrls: ['https://etherscan.io'], + defaultRpcEndpointIndex: 0, + defaultBlockExplorerUrlIndex: 0, + isActive: true, + isTestnet: false, + isDefault: true, + isFeatured: true, + isDeprecated: false, + priority: 0, + isDeletable: false, + ...overrides, + }; +} diff --git a/packages/config-registry-controller/tsconfig.build.json b/packages/config-registry-controller/tsconfig.build.json index 28e608feb56..70dd82381c2 100644 --- a/packages/config-registry-controller/tsconfig.build.json +++ b/packages/config-registry-controller/tsconfig.build.json @@ -5,6 +5,7 @@ "outDir": "./dist", "rootDir": "./src" }, + "exclude": ["**/*.test.ts", "./src/test-helpers.ts"], "references": [ { "path": "../base-controller/tsconfig.build.json" }, { "path": "../controller-utils/tsconfig.build.json" }, diff --git a/yarn.lock b/yarn.lock index 01cbed0ea40..53a1648da1b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2991,6 +2991,7 @@ __metadata: deepmerge: "npm:^4.2.2" jest: "npm:^27.5.1" nock: "npm:^13.3.1" + reselect: "npm:^5.1.1" sinon: "npm:^9.2.4" ts-jest: "npm:^27.1.4" typedoc: "npm:^0.24.8" From 6366d536e13d53a6f0fa952594da5fe09d287a1e Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Tue, 10 Feb 2026 12:23:06 +0100 Subject: [PATCH 32/55] fix: fix feedbacks --- .../src/ConfigRegistryController.test.ts | 18 +----- .../src/ConfigRegistryController.ts | 22 ++++++- .../config-registry-api-service.test.ts | 59 ++++--------------- .../config-registry-api-service.ts | 37 ++++-------- .../filters.test.ts | 2 +- 5 files changed, 46 insertions(+), 92 deletions(-) diff --git a/packages/config-registry-controller/src/ConfigRegistryController.test.ts b/packages/config-registry-controller/src/ConfigRegistryController.test.ts index 8b98ef81ef8..dd60fe8e518 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.test.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.test.ts @@ -8,10 +8,7 @@ import { useFakeTimers } from 'sinon'; import type { RegistryNetworkConfig } from './config-registry-api-service'; import type { FetchConfigResult } from './config-registry-api-service'; -import type { - ConfigRegistryMessenger, - ConfigRegistryState, -} from './ConfigRegistryController'; +import type { ConfigRegistryMessenger } from './ConfigRegistryController'; import { ConfigRegistryController, DEFAULT_POLLING_INTERVAL, @@ -181,7 +178,7 @@ describe('ConfigRegistryController', () => { name: 'Test Network', }), }; - const initialState: Partial = { + const initialState = { configs: { networks: initialNetworks }, version: 'v1.0.0', lastFetched: 1234567890, @@ -219,17 +216,6 @@ describe('ConfigRegistryController', () => { }, ); }); - - it('works when API service is registered on messenger', async () => { - await withController(({ controller }) => { - expect(controller.state).toStrictEqual({ - configs: { networks: {} }, - version: null, - lastFetched: null, - etag: null, - }); - }); - }); }); describe('polling', () => { diff --git a/packages/config-registry-controller/src/ConfigRegistryController.ts b/packages/config-registry-controller/src/ConfigRegistryController.ts index 6b01ae88591..dff37cbb477 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.ts @@ -88,11 +88,20 @@ const stateMetadata = { }, } satisfies StateMetadata; +/** + * Default fallback configuration when no configs are available. + */ const DEFAULT_FALLBACK_CONFIG: Record = {}; +/** + * Published when the state of {@link ConfigRegistryController} changes. + */ export type ConfigRegistryControllerStateChangeEvent = ControllerStateChangeEvent; +/** + * Retrieves the state of the {@link ConfigRegistryController}. + */ export type ConfigRegistryControllerGetStateAction = ControllerGetStateAction< typeof controllerName, ConfigRegistryState @@ -108,6 +117,9 @@ export type ConfigRegistryControllerStopPollingAction = { handler: () => void; }; +/** + * Actions that {@link ConfigRegistryControllerMessenger} exposes to other consumers. + */ export type ConfigRegistryControllerActions = | ConfigRegistryControllerGetStateAction | ConfigRegistryControllerStartPollingAction @@ -118,6 +130,9 @@ export type ConfigRegistryControllerActions = handler: (options?: FetchConfigOptions) => Promise; }; +/** + * Events that {@link ConfigRegistryControllerMessenger} exposes to other consumers. + */ export type ConfigRegistryControllerEvents = | KeyringControllerUnlockEvent | KeyringControllerLockEvent @@ -182,11 +197,12 @@ export class ConfigRegistryController extends StaticIntervalPollingController this.startPolling(input), + this.startPolling.bind(this), ); - this.messenger.registerActionHandler(`${controllerName}:stopPolling`, () => - this.stopAllPolling(), + this.messenger.registerActionHandler( + `${controllerName}:stopPolling`, + this.stopAllPolling.bind(this), ); this.messenger.subscribe('KeyringController:unlock', () => diff --git a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts index f7b901d8b11..1bc7b9eb961 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts @@ -1,5 +1,5 @@ import { SDK } from '@metamask/profile-sync-controller'; -import nock, { cleanAll } from 'nock'; +import nock from 'nock'; import { useFakeTimers } from 'sinon'; import { ConfigRegistryApiService } from './config-registry-api-service'; @@ -48,50 +48,16 @@ describe('ConfigRegistryApiService', () => { }); describe('constructor', () => { - it('creates instance with default options', () => { - const service = new ConfigRegistryApiService(); - expect(service).toBeInstanceOf(ConfigRegistryApiService); - }); - - it('creates instance with custom options', () => { - const customFetch = jest.fn(); - const service = new ConfigRegistryApiService({ - env: SDK.Env.DEV, - fetch: customFetch, - retries: 5, - }); - expect(service).toBeInstanceOf(ConfigRegistryApiService); - }); - - it('creates instance with empty options object', () => { - const service = new ConfigRegistryApiService({}); - expect(service).toBeInstanceOf(ConfigRegistryApiService); - }); - - it('uses default values for unspecified options', () => { - const service = new ConfigRegistryApiService({ - env: SDK.Env.PRD, - }); - expect(service).toBeInstanceOf(ConfigRegistryApiService); - }); - - it('uses default fetch when not provided', () => { + it('creates instance with policyOptions', () => { const service = new ConfigRegistryApiService({ env: SDK.Env.DEV, + policyOptions: { maxRetries: 5 }, }); expect(service).toBeInstanceOf(ConfigRegistryApiService); }); }); describe('fetchConfig', () => { - beforeEach(() => { - cleanAll(); - }); - - afterEach(() => { - cleanAll(); - }); - it('fetches config from API successfully', async () => { const scope = nock('https://client-config.uat-api.cx.metamask.io') .get('/v1/config/networks') @@ -190,8 +156,7 @@ describe('ConfigRegistryApiService', () => { .reply(200, MOCK_API_RESPONSE); const service = new ConfigRegistryApiService(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - await service.fetchConfig(undefined as any); + await service.fetchConfig(undefined); expect(scope.isDone()).toBe(true); }); @@ -318,7 +283,7 @@ describe('ConfigRegistryApiService', () => { .reply(200, MOCK_API_RESPONSE); const service = new ConfigRegistryApiService({ - retries: 2, + policyOptions: { maxRetries: 2 }, }); const result = await service.fetchConfig(); @@ -354,9 +319,11 @@ describe('ConfigRegistryApiService', () => { const onBreakHandler = jest.fn(); const service = new ConfigRegistryApiService({ - retries, - maximumConsecutiveFailures, - circuitBreakDuration: 10000, + policyOptions: { + maxRetries: retries, + maxConsecutiveFailures: maximumConsecutiveFailures, + circuitBreakDuration: 10000, + }, }); service.onBreak(onBreakHandler); @@ -401,8 +368,7 @@ describe('ConfigRegistryApiService', () => { it('calls onDegraded handler when service becomes degraded', async () => { const degradedThreshold = 2000; // 2 seconds const service = new ConfigRegistryApiService({ - degradedThreshold, - retries: 0, + policyOptions: { degradedThreshold, maxRetries: 0 }, }); const onDegradedHandler = jest.fn(); @@ -428,8 +394,7 @@ describe('ConfigRegistryApiService', () => { const slowService = new ConfigRegistryApiService({ fetch: slowFetch, - degradedThreshold, - retries: 0, + policyOptions: { degradedThreshold, maxRetries: 0 }, }); slowService.onDegraded(onDegradedHandler); diff --git a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts index c2c1eaf94b6..c520e53ed32 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts @@ -1,11 +1,8 @@ -import { - createServicePolicy, - DEFAULT_CIRCUIT_BREAK_DURATION, - DEFAULT_DEGRADED_THRESHOLD, - DEFAULT_MAX_CONSECUTIVE_FAILURES, - DEFAULT_MAX_RETRIES, +import { createServicePolicy } from '@metamask/controller-utils'; +import type { + CreateServicePolicyOptions, + ServicePolicy, } from '@metamask/controller-utils'; -import type { ServicePolicy } from '@metamask/controller-utils'; import { SDK } from '@metamask/profile-sync-controller'; import { validateRegistryConfigApiResponse } from './types'; @@ -27,10 +24,11 @@ function getConfigRegistryUrl(env: SDK.Env): string { export type ConfigRegistryApiServiceOptions = { env?: SDK.Env; fetch?: typeof fetch; - degradedThreshold?: number; - retries?: number; - maximumConsecutiveFailures?: number; - circuitBreakDuration?: number; + /** + * Options to pass to `createServicePolicy`, which wraps each request. + * See {@link CreateServicePolicyOptions}. + */ + policyOptions?: CreateServicePolicyOptions; }; export class ConfigRegistryApiService { @@ -46,28 +44,17 @@ export class ConfigRegistryApiService { * @param options - The options for constructing the service. * @param options.env - The environment to determine the correct API endpoints. Defaults to UAT. * @param options.fetch - Custom fetch function for testing or custom implementations. Defaults to the global fetch. - * @param options.degradedThreshold - The length of time (in milliseconds) that governs when the service is regarded as degraded. Defaults to 5 seconds. - * @param options.retries - Number of retry attempts for each fetch request. Defaults to 3. - * @param options.maximumConsecutiveFailures - The maximum number of consecutive failures allowed before breaking the circuit. Defaults to 3. - * @param options.circuitBreakDuration - The amount of time to wait when the circuit breaks from too many consecutive failures. Defaults to 2 minutes. + * @param options.policyOptions - Options to pass to `createServicePolicy`, which wraps each request. See {@link CreateServicePolicyOptions}. */ constructor({ env = SDK.Env.UAT, fetch: customFetch = globalThis.fetch, - degradedThreshold = DEFAULT_DEGRADED_THRESHOLD, - retries = DEFAULT_MAX_RETRIES, - maximumConsecutiveFailures = DEFAULT_MAX_CONSECUTIVE_FAILURES, - circuitBreakDuration = DEFAULT_CIRCUIT_BREAK_DURATION, + policyOptions = {}, }: ConfigRegistryApiServiceOptions = {}) { this.#url = getConfigRegistryUrl(env); this.#fetch = customFetch; - this.#policy = createServicePolicy({ - maxRetries: retries, - maxConsecutiveFailures: maximumConsecutiveFailures, - circuitBreakDuration, - degradedThreshold, - }); + this.#policy = createServicePolicy(policyOptions); } onBreak( diff --git a/packages/config-registry-controller/src/config-registry-api-service/filters.test.ts b/packages/config-registry-controller/src/config-registry-api-service/filters.test.ts index 3e11e331f37..a2979ade302 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/filters.test.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/filters.test.ts @@ -71,7 +71,7 @@ describe('filters', () => { expect(result[0].chainId).toBe('0x1'); }); - it('filters by multiple criteria', () => { + it('filters by multiple criteria (requiring all filters to match)', () => { const result = filterNetworks(networks, { isFeatured: true, isActive: true, From ef4ac4c7a6e5495a7d903334231972ee0afc6019 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Tue, 10 Feb 2026 13:05:15 +0100 Subject: [PATCH 33/55] fix: fix lint --- packages/config-registry-controller/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/config-registry-controller/package.json b/packages/config-registry-controller/package.json index ceb92b1b6c9..7e0b87eb7d2 100644 --- a/packages/config-registry-controller/package.json +++ b/packages/config-registry-controller/package.json @@ -52,7 +52,7 @@ "@metamask/controller-utils": "^11.18.0", "@metamask/messenger": "^0.3.0", "@metamask/polling-controller": "^16.0.2", - "@metamask/profile-sync-controller": "^27.0.0", + "@metamask/profile-sync-controller": "^27.1.0", "@metamask/remote-feature-flag-controller": "^4.0.0", "@metamask/superstruct": "^3.1.0", "@metamask/utils": "^11.9.0", From 8f134fd955960c88166200d7b33e2aa553126991 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Tue, 10 Feb 2026 13:10:45 +0100 Subject: [PATCH 34/55] chore: update yarn.lock --- yarn.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index 86a8951f74e..578f99deddb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3037,7 +3037,7 @@ __metadata: "@metamask/controller-utils": "npm:^11.18.0" "@metamask/messenger": "npm:^0.3.0" "@metamask/polling-controller": "npm:^16.0.2" - "@metamask/profile-sync-controller": "npm:^27.0.0" + "@metamask/profile-sync-controller": "npm:^27.1.0" "@metamask/remote-feature-flag-controller": "npm:^4.0.0" "@metamask/superstruct": "npm:^3.1.0" "@metamask/utils": "npm:^11.9.0" From 267b38e612105270795d2760a3ffd6c38b052d24 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Tue, 10 Feb 2026 13:30:58 +0100 Subject: [PATCH 35/55] fix: fix lint --- package.json | 1 - packages/config-registry-controller/package.json | 4 ++-- .../src/ConfigRegistryController.ts | 15 +++++++++------ packages/config-registry-controller/src/index.ts | 2 +- .../config-registry-controller/src/selectors.ts | 4 ++-- yarn.lock | 9 ++++----- 6 files changed, 18 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index 0ed5d6b8f0b..aeda719e4ff 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,6 @@ "@metamask/eth-block-tracker": "^15.0.1", "@metamask/eth-json-rpc-provider": "^6.0.0", "@metamask/json-rpc-engine": "^10.2.2", - "@metamask/network-controller": "^29.0.0", "@metamask/utils": "^11.9.0", "@ts-bridge/cli": "^0.6.4", "@types/jest": "^27.5.2", diff --git a/packages/config-registry-controller/package.json b/packages/config-registry-controller/package.json index 7e0b87eb7d2..7bb08e1ae3c 100644 --- a/packages/config-registry-controller/package.json +++ b/packages/config-registry-controller/package.json @@ -62,12 +62,12 @@ "@lavamoat/allow-scripts": "^3.0.4", "@metamask/auto-changelog": "^3.4.4", "@ts-bridge/cli": "^0.6.4", - "@types/jest": "^27.4.1", + "@types/jest": "^27.5.2", "deepmerge": "^4.2.2", "jest": "^27.5.1", "nock": "^13.3.1", "sinon": "^9.2.4", - "ts-jest": "^27.1.4", + "ts-jest": "^27.1.5", "typedoc": "^0.24.8", "typedoc-plugin-missing-exports": "^2.0.0", "typescript": "~5.3.3" diff --git a/packages/config-registry-controller/src/ConfigRegistryController.ts b/packages/config-registry-controller/src/ConfigRegistryController.ts index dff37cbb477..678314d3da1 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.ts @@ -29,7 +29,7 @@ export const DEFAULT_POLLING_INTERVAL = inMilliseconds(1, Duration.Day); * Tracks network configurations fetched from the config registry API, * along with metadata about the fetch status and caching. */ -export type ConfigRegistryState = { +export type ConfigRegistryControllerState = { /** * Network configurations organized by chain ID. * Stores the full API response including isFeatured, isTestnet, etc. @@ -86,7 +86,7 @@ const stateMetadata = { includeInDebugSnapshot: false, usedInUi: false, }, -} satisfies StateMetadata; +} satisfies StateMetadata; /** * Default fallback configuration when no configs are available. @@ -97,14 +97,17 @@ const DEFAULT_FALLBACK_CONFIG: Record = {}; * Published when the state of {@link ConfigRegistryController} changes. */ export type ConfigRegistryControllerStateChangeEvent = - ControllerStateChangeEvent; + ControllerStateChangeEvent< + typeof controllerName, + ConfigRegistryControllerState + >; /** * Retrieves the state of the {@link ConfigRegistryController}. */ export type ConfigRegistryControllerGetStateAction = ControllerGetStateAction< typeof controllerName, - ConfigRegistryState + ConfigRegistryControllerState >; export type ConfigRegistryControllerStartPollingAction = { @@ -146,7 +149,7 @@ export type ConfigRegistryMessenger = Messenger< export type ConfigRegistryControllerOptions = { messenger: ConfigRegistryMessenger; - state?: Partial; + state?: Partial; pollingInterval?: number; fallbackConfig?: Record; isConfigRegistryApiEnabled?: (messenger: ConfigRegistryMessenger) => boolean; @@ -154,7 +157,7 @@ export type ConfigRegistryControllerOptions = { export class ConfigRegistryController extends StaticIntervalPollingController()< typeof controllerName, - ConfigRegistryState, + ConfigRegistryControllerState, ConfigRegistryMessenger > { readonly #isConfigRegistryApiEnabled: ( diff --git a/packages/config-registry-controller/src/index.ts b/packages/config-registry-controller/src/index.ts index 6b8a09618f9..d67fd584e55 100644 --- a/packages/config-registry-controller/src/index.ts +++ b/packages/config-registry-controller/src/index.ts @@ -1,5 +1,5 @@ export type { - ConfigRegistryState, + ConfigRegistryControllerState, ConfigRegistryControllerOptions, ConfigRegistryControllerActions, ConfigRegistryControllerGetStateAction, diff --git a/packages/config-registry-controller/src/selectors.ts b/packages/config-registry-controller/src/selectors.ts index a6101934089..67bc9ea3fff 100644 --- a/packages/config-registry-controller/src/selectors.ts +++ b/packages/config-registry-controller/src/selectors.ts @@ -2,7 +2,7 @@ import { createSelector } from 'reselect'; import { filterNetworks } from './config-registry-api-service'; import type { RegistryNetworkConfig } from './config-registry-api-service'; -import type { ConfigRegistryState } from './ConfigRegistryController'; +import type { ConfigRegistryControllerState } from './ConfigRegistryController'; /** * Base selector to get all networks from the controller state. @@ -11,7 +11,7 @@ import type { ConfigRegistryState } from './ConfigRegistryController'; * @returns All network configurations keyed by chain ID */ export const selectNetworks = ( - state: ConfigRegistryState, + state: ConfigRegistryControllerState, ): Record => state.configs.networks; /** diff --git a/yarn.lock b/yarn.lock index 578f99deddb..5fed536f4c2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3042,13 +3042,13 @@ __metadata: "@metamask/superstruct": "npm:^3.1.0" "@metamask/utils": "npm:^11.9.0" "@ts-bridge/cli": "npm:^0.6.4" - "@types/jest": "npm:^27.4.1" + "@types/jest": "npm:^27.5.2" deepmerge: "npm:^4.2.2" jest: "npm:^27.5.1" nock: "npm:^13.3.1" reselect: "npm:^5.1.1" sinon: "npm:^9.2.4" - ts-jest: "npm:^27.1.4" + ts-jest: "npm:^27.1.5" typedoc: "npm:^0.24.8" typedoc-plugin-missing-exports: "npm:^2.0.0" typescript: "npm:~5.3.3" @@ -3172,7 +3172,6 @@ __metadata: "@metamask/eth-block-tracker": "npm:^15.0.1" "@metamask/eth-json-rpc-provider": "npm:^6.0.0" "@metamask/json-rpc-engine": "npm:^10.2.2" - "@metamask/network-controller": "npm:^29.0.0" "@metamask/utils": "npm:^11.9.0" "@ts-bridge/cli": "npm:^0.6.4" "@types/jest": "npm:^27.5.2" @@ -6122,7 +6121,7 @@ __metadata: languageName: node linkType: hard -"@types/jest@npm:^27.4.1, @types/jest@npm:^27.5.2": +"@types/jest@npm:^27.5.2": version: 27.5.2 resolution: "@types/jest@npm:27.5.2" dependencies: @@ -13824,7 +13823,7 @@ __metadata: languageName: node linkType: hard -"ts-jest@npm:^27.1.4, ts-jest@npm:^27.1.5": +"ts-jest@npm:^27.1.5": version: 27.1.5 resolution: "ts-jest@npm:27.1.5" dependencies: From fedc942f06ebf294aeca4ee02eeabe675e64c6fb Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Fri, 20 Feb 2026 16:50:39 +0100 Subject: [PATCH 36/55] fix: fix comments --- .gitignore | 11 +- package.json | 1 + .../config-registry-controller/package.json | 2 +- .../src/ConfigRegistryController.test.ts | 621 ++---------------- .../src/ConfigRegistryController.ts | 38 +- .../config-registry-api-service.test.ts | 338 ++++------ .../config-registry-api-service.ts | 40 +- .../src/config-registry-api-service/types.ts | 5 + .../config-registry-controller/src/index.ts | 1 + tests/fake-provider.ts | 68 +- 10 files changed, 298 insertions(+), 827 deletions(-) diff --git a/.gitignore b/.gitignore index 4135572bb1f..6c1e52eb80d 100644 --- a/.gitignore +++ b/.gitignore @@ -21,7 +21,6 @@ examples/*/docs packages/*/coverage packages/*/dist packages/*/docs -!packages/core-backend/docs scripts/coverage # yarn v3 (w/o zero-install) @@ -33,12 +32,6 @@ scripts/coverage !.yarn/releases !.yarn/sdks !.yarn/versions -.yalc -yalc.lock -# typescript -packages/*/*.tsbuildinfo -# Emacs -\#*\# -.#* -.~ +# typescript +packages/*/*.tsbuildinfo \ No newline at end of file diff --git a/package.json b/package.json index aeda719e4ff..0ed5d6b8f0b 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,7 @@ "@metamask/eth-block-tracker": "^15.0.1", "@metamask/eth-json-rpc-provider": "^6.0.0", "@metamask/json-rpc-engine": "^10.2.2", + "@metamask/network-controller": "^29.0.0", "@metamask/utils": "^11.9.0", "@ts-bridge/cli": "^0.6.4", "@types/jest": "^27.5.2", diff --git a/packages/config-registry-controller/package.json b/packages/config-registry-controller/package.json index 7bb08e1ae3c..39828d03c78 100644 --- a/packages/config-registry-controller/package.json +++ b/packages/config-registry-controller/package.json @@ -1,6 +1,6 @@ { "name": "@metamask/config-registry-controller", - "version": "0.0.1", + "version": "0.0.0", "description": "Manages configuration registry for MetaMask", "keywords": [ "MetaMask", diff --git a/packages/config-registry-controller/src/ConfigRegistryController.test.ts b/packages/config-registry-controller/src/ConfigRegistryController.test.ts index dd60fe8e518..81afa9f30ba 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.test.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.test.ts @@ -269,7 +269,12 @@ describe('ConfigRegistryController', () => { it('uses fallback config when no configs exist', async () => { await withController( { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, - async ({ mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { + async ({ + controller, + rootMessenger, + mockRemoteFeatureFlagGetState, + mockApiServiceHandler, + }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { configRegistryApiEnabled: true, @@ -279,77 +284,12 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockRejectedValue(new Error('Network error')); - const captureExceptionSpy = jest.fn(); - const testRootMessenger = new Messenger< - MockAnyNamespace, - | { - type: 'RemoteFeatureFlagController:getState'; - handler: () => unknown; - } - | { - type: 'KeyringController:getState'; - handler: () => { isUnlocked: boolean }; - } - | { - type: 'ConfigRegistryApiService:fetchConfig'; - handler: (options?: { - etag?: string; - }) => Promise; - }, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] } - >({ - namespace: MOCK_ANY_NAMESPACE, - captureException: captureExceptionSpy, - }); - - const testMessenger = new Messenger< - typeof namespace, - never, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] }, - typeof testRootMessenger - >({ - namespace, - parent: testRootMessenger, - }) as ConfigRegistryMessenger; - - testRootMessenger.registerActionHandler( - 'ConfigRegistryApiService:fetchConfig', - mockApiServiceHandler, - ); - testRootMessenger.registerActionHandler( - 'RemoteFeatureFlagController:getState', - mockRemoteFeatureFlagGetState, - ); - testRootMessenger.registerActionHandler( - 'KeyringController:getState', - jest.fn().mockReturnValue({ isUnlocked: false }), - ); - testRootMessenger.delegate({ - messenger: testMessenger, - actions: [ - 'RemoteFeatureFlagController:getState', - 'KeyringController:getState', - 'ConfigRegistryApiService:fetchConfig', - ] as never[], - events: [ - 'KeyringController:unlock', - 'KeyringController:lock', - ] as never[], - }); - - const testController = new ConfigRegistryController({ - messenger: testMessenger, - fallbackConfig: MOCK_FALLBACK_CONFIG, - }); - - await testController._executePoll(null); + await controller._executePoll(null); - expect(captureExceptionSpy).toHaveBeenCalledWith( + expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ message: 'Network error' }), ); - expect(testController.state.configs).toStrictEqual({ + expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG, }); }, @@ -372,7 +312,12 @@ describe('ConfigRegistryController', () => { fallbackConfig: MOCK_FALLBACK_CONFIG, }, }, - async ({ mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { + async ({ + controller, + rootMessenger, + mockRemoteFeatureFlagGetState, + mockApiServiceHandler, + }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { configRegistryApiEnabled: true, @@ -382,74 +327,12 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockRejectedValue(new Error('Network error')); - const captureExceptionSpy = jest.fn(); - const testRootMessenger = new Messenger< - MockAnyNamespace, - | { - type: 'RemoteFeatureFlagController:getState'; - handler: () => unknown; - } - | { - type: 'KeyringController:getState'; - handler: () => { isUnlocked: boolean }; - } - | { - type: 'ConfigRegistryApiService:fetchConfig'; - handler: (options?: { - etag?: string; - }) => Promise; - }, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] } - >({ - namespace: MOCK_ANY_NAMESPACE, - captureException: captureExceptionSpy, - }); - - const testMessenger = new Messenger< - typeof namespace, - never, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] }, - typeof testRootMessenger - >({ - namespace, - parent: testRootMessenger, - }) as ConfigRegistryMessenger; - - testRootMessenger.registerActionHandler( - 'ConfigRegistryApiService:fetchConfig', - mockApiServiceHandler, - ); - testRootMessenger.registerActionHandler( - 'RemoteFeatureFlagController:getState', - mockRemoteFeatureFlagGetState, - ); - testRootMessenger.delegate({ - messenger: testMessenger, - actions: [ - 'RemoteFeatureFlagController:getState', - 'KeyringController:getState', - 'ConfigRegistryApiService:fetchConfig', - ] as never[], - events: [ - 'KeyringController:unlock', - 'KeyringController:lock', - ] as never[], - }); - - const testController = new ConfigRegistryController({ - messenger: testMessenger, - state: { configs: existingConfigs }, - fallbackConfig: MOCK_FALLBACK_CONFIG, - }); - - await testController._executePoll(null); + await controller._executePoll(null); - expect(captureExceptionSpy).toHaveBeenCalledWith( + expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ message: 'Network error' }), ); - expect(testController.state.configs.networks).toStrictEqual( + expect(controller.state.configs.networks).toStrictEqual( existingNetworks, ); }, @@ -459,7 +342,12 @@ describe('ConfigRegistryController', () => { it('handles errors during polling', async () => { await withController( { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, - async ({ mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { + async ({ + controller, + rootMessenger, + mockRemoteFeatureFlagGetState, + mockApiServiceHandler, + }) => { mockRemoteFeatureFlagGetState.mockReturnValueOnce({ remoteFeatureFlags: { configRegistryApiEnabled: true, @@ -469,77 +357,12 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockRejectedValue(new Error('Network error')); - const captureExceptionSpy = jest.fn(); - const testRootMessenger = new Messenger< - MockAnyNamespace, - | { - type: 'RemoteFeatureFlagController:getState'; - handler: () => unknown; - } - | { - type: 'KeyringController:getState'; - handler: () => { isUnlocked: boolean }; - } - | { - type: 'ConfigRegistryApiService:fetchConfig'; - handler: (options?: { - etag?: string; - }) => Promise; - }, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] } - >({ - namespace: MOCK_ANY_NAMESPACE, - captureException: captureExceptionSpy, - }); - - const testMessenger = new Messenger< - typeof namespace, - never, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] }, - typeof testRootMessenger - >({ - namespace, - parent: testRootMessenger, - }) as ConfigRegistryMessenger; - - testRootMessenger.registerActionHandler( - 'ConfigRegistryApiService:fetchConfig', - mockApiServiceHandler, - ); - testRootMessenger.registerActionHandler( - 'RemoteFeatureFlagController:getState', - mockRemoteFeatureFlagGetState, - ); - testRootMessenger.registerActionHandler( - 'KeyringController:getState', - jest.fn().mockReturnValue({ isUnlocked: false }), - ); - testRootMessenger.delegate({ - messenger: testMessenger, - actions: [ - 'RemoteFeatureFlagController:getState', - 'KeyringController:getState', - 'ConfigRegistryApiService:fetchConfig', - ] as never[], - events: [ - 'KeyringController:unlock', - 'KeyringController:lock', - ] as never[], - }); - - const testController = new ConfigRegistryController({ - messenger: testMessenger, - fallbackConfig: MOCK_FALLBACK_CONFIG, - }); - - await testController._executePoll(null); + await controller._executePoll(null); - expect(captureExceptionSpy).toHaveBeenCalledWith( + expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ message: 'Network error' }), ); - expect(testController.state.configs).toStrictEqual({ + expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG, }); expect(mockRemoteFeatureFlagGetState).toHaveBeenCalled(); @@ -667,7 +490,12 @@ describe('ConfigRegistryController', () => { it('handles validation error from service', async () => { await withController( - async ({ mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { + async ({ + controller, + rootMessenger, + mockRemoteFeatureFlagGetState, + mockApiServiceHandler, + }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { configRegistryApiEnabled: true, @@ -680,74 +508,9 @@ describe('ConfigRegistryController', () => { ); mockApiServiceHandler.mockRejectedValue(validationError); - const captureExceptionSpy = jest.fn(); - const testRootMessenger = new Messenger< - MockAnyNamespace, - | { - type: 'RemoteFeatureFlagController:getState'; - handler: () => unknown; - } - | { - type: 'KeyringController:getState'; - handler: () => { isUnlocked: boolean }; - } - | { - type: 'ConfigRegistryApiService:fetchConfig'; - handler: (options?: { - etag?: string; - }) => Promise; - }, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] } - >({ - namespace: MOCK_ANY_NAMESPACE, - captureException: captureExceptionSpy, - }); - - const testMessenger = new Messenger< - typeof namespace, - never, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] }, - typeof testRootMessenger - >({ - namespace, - parent: testRootMessenger, - }) as ConfigRegistryMessenger; - - testRootMessenger.registerActionHandler( - 'ConfigRegistryApiService:fetchConfig', - mockApiServiceHandler, - ); - testRootMessenger.registerActionHandler( - 'RemoteFeatureFlagController:getState', - mockRemoteFeatureFlagGetState, - ); - testRootMessenger.registerActionHandler( - 'KeyringController:getState', - jest.fn().mockReturnValue({ isUnlocked: false }), - ); - - testRootMessenger.delegate({ - messenger: testMessenger, - actions: [ - 'RemoteFeatureFlagController:getState', - 'KeyringController:getState', - 'ConfigRegistryApiService:fetchConfig', - ] as never[], - events: [ - 'KeyringController:unlock', - 'KeyringController:lock', - ] as never[], - }); - - const testController = new ConfigRegistryController({ - messenger: testMessenger, - }); - - await testController._executePoll(null); + await controller._executePoll(null); - expect(captureExceptionSpy).toHaveBeenCalledWith( + expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ message: 'Validation error from superstruct', }), @@ -1054,7 +817,12 @@ describe('ConfigRegistryController', () => { it('handles non-Error exceptions', async () => { await withController( { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, - async ({ mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { + async ({ + controller, + rootMessenger, + mockRemoteFeatureFlagGetState, + mockApiServiceHandler, + }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { configRegistryApiEnabled: true, @@ -1064,77 +832,12 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockRejectedValue('String error'); - const captureExceptionSpy = jest.fn(); - const testRootMessenger = new Messenger< - MockAnyNamespace, - | { - type: 'RemoteFeatureFlagController:getState'; - handler: () => unknown; - } - | { - type: 'KeyringController:getState'; - handler: () => { isUnlocked: boolean }; - } - | { - type: 'ConfigRegistryApiService:fetchConfig'; - handler: (options?: { - etag?: string; - }) => Promise; - }, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] } - >({ - namespace: MOCK_ANY_NAMESPACE, - captureException: captureExceptionSpy, - }); - - const testMessenger = new Messenger< - typeof namespace, - never, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] }, - typeof testRootMessenger - >({ - namespace, - parent: testRootMessenger, - }) as ConfigRegistryMessenger; - - testRootMessenger.registerActionHandler( - 'ConfigRegistryApiService:fetchConfig', - mockApiServiceHandler, - ); - testRootMessenger.registerActionHandler( - 'RemoteFeatureFlagController:getState', - mockRemoteFeatureFlagGetState, - ); - testRootMessenger.registerActionHandler( - 'KeyringController:getState', - jest.fn().mockReturnValue({ isUnlocked: false }), - ); - testRootMessenger.delegate({ - messenger: testMessenger, - actions: [ - 'RemoteFeatureFlagController:getState', - 'KeyringController:getState', - 'ConfigRegistryApiService:fetchConfig', - ] as never[], - events: [ - 'KeyringController:unlock', - 'KeyringController:lock', - ] as never[], - }); - - const testController = new ConfigRegistryController({ - messenger: testMessenger, - fallbackConfig: MOCK_FALLBACK_CONFIG, - }); - - await testController._executePoll(null); + await controller._executePoll(null); - expect(captureExceptionSpy).toHaveBeenCalledWith( + expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ message: 'String error' }), ); - expect(testController.state.configs).toStrictEqual({ + expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG, }); }, @@ -1150,7 +853,12 @@ describe('ConfigRegistryController', () => { state: { configs: null as any }, }, }, - async ({ mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { + async ({ + controller, + rootMessenger, + mockRemoteFeatureFlagGetState, + mockApiServiceHandler, + }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { configRegistryApiEnabled: true, @@ -1160,79 +868,12 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockRejectedValue(new Error('Network error')); - const captureExceptionSpy = jest.fn(); - const testRootMessenger = new Messenger< - MockAnyNamespace, - | { - type: 'RemoteFeatureFlagController:getState'; - handler: () => unknown; - } - | { - type: 'KeyringController:getState'; - handler: () => { isUnlocked: boolean }; - } - | { - type: 'ConfigRegistryApiService:fetchConfig'; - handler: (options?: { - etag?: string; - }) => Promise; - }, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] } - >({ - namespace: MOCK_ANY_NAMESPACE, - captureException: captureExceptionSpy, - }); - - const testMessenger = new Messenger< - typeof namespace, - never, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] }, - typeof testRootMessenger - >({ - namespace, - parent: testRootMessenger, - }) as ConfigRegistryMessenger; - - testRootMessenger.registerActionHandler( - 'ConfigRegistryApiService:fetchConfig', - mockApiServiceHandler, - ); - testRootMessenger.registerActionHandler( - 'RemoteFeatureFlagController:getState', - mockRemoteFeatureFlagGetState, - ); - testRootMessenger.registerActionHandler( - 'KeyringController:getState', - jest.fn().mockReturnValue({ isUnlocked: false }), - ); - testRootMessenger.delegate({ - messenger: testMessenger, - actions: [ - 'RemoteFeatureFlagController:getState', - 'KeyringController:getState', - 'ConfigRegistryApiService:fetchConfig', - ] as never[], - events: [ - 'KeyringController:unlock', - 'KeyringController:lock', - ] as never[], - }); - - const testController = new ConfigRegistryController({ - messenger: testMessenger, - fallbackConfig: MOCK_FALLBACK_CONFIG, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - state: { configs: null as any }, - }); - - await testController._executePoll(null); + await controller._executePoll(null); - expect(captureExceptionSpy).toHaveBeenCalledWith( + expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ message: 'Network error' }), ); - expect(testController.state.configs).toStrictEqual({ + expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG, }); }, @@ -1708,7 +1349,11 @@ describe('ConfigRegistryController', () => { it('handles duplicate chainIds by keeping highest priority network and logging warning', async () => { await withController( - async ({ mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { + async ({ + controller, + mockRemoteFeatureFlagGetState, + mockApiServiceHandler, + }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { configRegistryApiEnabled: true, @@ -1716,70 +1361,6 @@ describe('ConfigRegistryController', () => { cacheTimestamp: Date.now(), }); - const captureExceptionSpy = jest.fn(); - const testRootMessenger = new Messenger< - MockAnyNamespace, - | { - type: 'RemoteFeatureFlagController:getState'; - handler: () => unknown; - } - | { - type: 'KeyringController:getState'; - handler: () => { isUnlocked: boolean }; - } - | { - type: 'ConfigRegistryApiService:fetchConfig'; - handler: (options?: { - etag?: string; - }) => Promise; - }, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] } - >({ - namespace: MOCK_ANY_NAMESPACE, - captureException: captureExceptionSpy, - }); - - const testMessenger = new Messenger< - typeof namespace, - never, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] }, - typeof testRootMessenger - >({ - namespace, - parent: testRootMessenger, - }) as ConfigRegistryMessenger; - - testRootMessenger.registerActionHandler( - 'ConfigRegistryApiService:fetchConfig', - mockApiServiceHandler, - ); - testRootMessenger.registerActionHandler( - 'RemoteFeatureFlagController:getState', - mockRemoteFeatureFlagGetState, - ); - testRootMessenger.registerActionHandler( - 'KeyringController:getState', - jest.fn().mockReturnValue({ isUnlocked: false }), - ); - testRootMessenger.delegate({ - messenger: testMessenger, - actions: [ - 'RemoteFeatureFlagController:getState', - 'KeyringController:getState', - 'ConfigRegistryApiService:fetchConfig', - ] as never[], - events: [ - 'KeyringController:unlock', - 'KeyringController:lock', - ] as never[], - }); - - const testController = new ConfigRegistryController({ - messenger: testMessenger, - }); - // Mock API response with duplicate chainIds const mockNetworks = [ { @@ -1865,25 +1446,29 @@ describe('ConfigRegistryController', () => { etag: 'test-etag', }); - await testController._executePoll(null); + await controller._executePoll(null); // Last occurrence overwrites (no grouping/priority) - expect(testController.state.configs.networks['0x1']).toBeDefined(); - expect(testController.state.configs.networks['0x1']?.name).toBe( + expect(controller.state.configs.networks['0x1']).toBeDefined(); + expect(controller.state.configs.networks['0x1']?.name).toBe( 'Ethereum Mainnet (High Priority)', ); expect( - testController.state.configs.networks['0x1']?.rpcEndpoints[0].type, + controller.state.configs.networks['0x1']?.rpcEndpoints[0].type, ).toBe('alchemy'); - expect(testController.state.configs.networks['0x89']).toBeDefined(); + expect(controller.state.configs.networks['0x89']).toBeDefined(); }, ); }); it('handles duplicate chainIds by keeping last occurrence', async () => { await withController( - async ({ mockRemoteFeatureFlagGetState, mockApiServiceHandler }) => { + async ({ + controller, + mockRemoteFeatureFlagGetState, + mockApiServiceHandler, + }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { configRegistryApiEnabled: true, @@ -1891,70 +1476,6 @@ describe('ConfigRegistryController', () => { cacheTimestamp: Date.now(), }); - const captureExceptionSpy = jest.fn(); - const testRootMessenger = new Messenger< - MockAnyNamespace, - | { - type: 'RemoteFeatureFlagController:getState'; - handler: () => unknown; - } - | { - type: 'KeyringController:getState'; - handler: () => { isUnlocked: boolean }; - } - | { - type: 'ConfigRegistryApiService:fetchConfig'; - handler: (options?: { - etag?: string; - }) => Promise; - }, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] } - >({ - namespace: MOCK_ANY_NAMESPACE, - captureException: captureExceptionSpy, - }); - - const testMessenger = new Messenger< - typeof namespace, - never, - | { type: 'KeyringController:unlock'; payload: [] } - | { type: 'KeyringController:lock'; payload: [] }, - typeof testRootMessenger - >({ - namespace, - parent: testRootMessenger, - }) as ConfigRegistryMessenger; - - testRootMessenger.registerActionHandler( - 'ConfigRegistryApiService:fetchConfig', - mockApiServiceHandler, - ); - testRootMessenger.registerActionHandler( - 'RemoteFeatureFlagController:getState', - mockRemoteFeatureFlagGetState, - ); - testRootMessenger.registerActionHandler( - 'KeyringController:getState', - jest.fn().mockReturnValue({ isUnlocked: false }), - ); - testRootMessenger.delegate({ - messenger: testMessenger, - actions: [ - 'RemoteFeatureFlagController:getState', - 'KeyringController:getState', - 'ConfigRegistryApiService:fetchConfig', - ] as never[], - events: [ - 'KeyringController:unlock', - 'KeyringController:lock', - ] as never[], - }); - - const testController = new ConfigRegistryController({ - messenger: testMessenger, - }); - // Mock API response with duplicate chainIds having same priority const mockNetworks = [ { @@ -2017,11 +1538,11 @@ describe('ConfigRegistryController', () => { etag: 'test-etag', }); - await testController._executePoll(null); + await controller._executePoll(null); // Last occurrence overwrites - expect(testController.state.configs.networks['0x1']).toBeDefined(); - expect(testController.state.configs.networks['0x1']?.name).toBe( + expect(controller.state.configs.networks['0x1']).toBeDefined(); + expect(controller.state.configs.networks['0x1']?.name).toBe( 'Ethereum Mainnet (Second)', ); }, diff --git a/packages/config-registry-controller/src/ConfigRegistryController.ts b/packages/config-registry-controller/src/ConfigRegistryController.ts index 678314d3da1..8f9da2809d8 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.ts @@ -110,11 +110,18 @@ export type ConfigRegistryControllerGetStateAction = ControllerGetStateAction< ConfigRegistryControllerState >; +/** + * Starts polling the config registry API. Returns a polling token that can be + * used to stop this polling session. + */ export type ConfigRegistryControllerStartPollingAction = { type: `${typeof controllerName}:startPolling`; handler: (input: null) => string; }; +/** + * Stops all config registry polling. + */ export type ConfigRegistryControllerStopPollingAction = { type: `${typeof controllerName}:stopPolling`; handler: () => void; @@ -126,7 +133,13 @@ export type ConfigRegistryControllerStopPollingAction = { export type ConfigRegistryControllerActions = | ConfigRegistryControllerGetStateAction | ConfigRegistryControllerStartPollingAction - | ConfigRegistryControllerStopPollingAction + | ConfigRegistryControllerStopPollingAction; + +/** + * Actions from other messengers that {@link ConfigRegistryControllerMessenger} + * calls. + */ +type AllowedActions = | RemoteFeatureFlagControllerGetStateAction | { type: 'ConfigRegistryApiService:fetchConfig'; @@ -137,16 +150,27 @@ export type ConfigRegistryControllerActions = * Events that {@link ConfigRegistryControllerMessenger} exposes to other consumers. */ export type ConfigRegistryControllerEvents = - | KeyringControllerUnlockEvent - | KeyringControllerLockEvent - | ConfigRegistryControllerStateChangeEvent; + ConfigRegistryControllerStateChangeEvent; -export type ConfigRegistryMessenger = Messenger< +/** + * Events from other messengers that {@link ConfigRegistryControllerMessenger} + * subscribes to. + */ +type AllowedEvents = KeyringControllerUnlockEvent | KeyringControllerLockEvent; + +/** + * The messenger restricted to actions and events accessed by + * {@link ConfigRegistryController}. + */ +export type ConfigRegistryControllerMessenger = Messenger< typeof controllerName, - ConfigRegistryControllerActions, - ConfigRegistryControllerEvents + ConfigRegistryControllerActions | AllowedActions, + ConfigRegistryControllerEvents | AllowedEvents >; +/** @deprecated Use {@link ConfigRegistryControllerMessenger} instead. */ +export type ConfigRegistryMessenger = ConfigRegistryControllerMessenger; + export type ConfigRegistryControllerOptions = { messenger: ConfigRegistryMessenger; state?: Partial; diff --git a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts index 1bc7b9eb961..62a1140f217 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts @@ -3,7 +3,7 @@ import nock from 'nock'; import { useFakeTimers } from 'sinon'; import { ConfigRegistryApiService } from './config-registry-api-service'; -import type { FetchConfigResult, RegistryConfigApiResponse } from './types'; +import type { RegistryConfigApiResponse } from './types'; import { createMockNetworkConfig } from '../test-helpers'; const MOCK_API_RESPONSE: RegistryConfigApiResponse = { @@ -15,49 +15,51 @@ const MOCK_API_RESPONSE: RegistryConfigApiResponse = { }; describe('ConfigRegistryApiService', () => { - describe('constructor URL by env', () => { - it('uses UAT URL when env is UAT', async () => { - const scope = nock('https://client-config.uat-api.cx.metamask.io') - .get('/v1/config/networks') - .reply(200, MOCK_API_RESPONSE); + describe('fetchConfig', () => { + describe('URL by env', () => { + it('uses UAT URL when env is UAT', async () => { + const scope = nock('https://client-config.uat-api.cx.metamask.io') + .get('/v1/config/networks') + .reply(200, MOCK_API_RESPONSE); - const service = new ConfigRegistryApiService({ env: SDK.Env.UAT }); - await service.fetchConfig(); - expect(scope.isDone()).toBe(true); - }); + const service = new ConfigRegistryApiService({ env: SDK.Env.UAT }); + await service.fetchConfig(); + expect(scope.isDone()).toBe(true); + }); - it('uses DEV URL when env is DEV', async () => { - const scope = nock('https://client-config.dev-api.cx.metamask.io') - .get('/v1/config/networks') - .reply(200, MOCK_API_RESPONSE); + it('uses DEV URL when env is DEV', async () => { + const scope = nock('https://client-config.dev-api.cx.metamask.io') + .get('/v1/config/networks') + .reply(200, MOCK_API_RESPONSE); - const service = new ConfigRegistryApiService({ env: SDK.Env.DEV }); - await service.fetchConfig(); - expect(scope.isDone()).toBe(true); - }); + const service = new ConfigRegistryApiService({ env: SDK.Env.DEV }); + await service.fetchConfig(); + expect(scope.isDone()).toBe(true); + }); - it('uses PRD URL when env is PRD', async () => { - const scope = nock('https://client-config.api.cx.metamask.io') - .get('/v1/config/networks') - .reply(200, MOCK_API_RESPONSE); + it('uses PRD URL when env is PRD', async () => { + const scope = nock('https://client-config.api.cx.metamask.io') + .get('/v1/config/networks') + .reply(200, MOCK_API_RESPONSE); - const service = new ConfigRegistryApiService({ env: SDK.Env.PRD }); - await service.fetchConfig(); - expect(scope.isDone()).toBe(true); - }); - }); + const service = new ConfigRegistryApiService({ env: SDK.Env.PRD }); + await service.fetchConfig(); + expect(scope.isDone()).toBe(true); + }); - describe('constructor', () => { - it('creates instance with policyOptions', () => { - const service = new ConfigRegistryApiService({ - env: SDK.Env.DEV, - policyOptions: { maxRetries: 5 }, + it('defaults to UAT environment', async () => { + const scope = nock('https://client-config.uat-api.cx.metamask.io') + .get('/v1/config/networks') + .reply(200, MOCK_API_RESPONSE); + + const service = new ConfigRegistryApiService(); + + await service.fetchConfig(); + + expect(scope.isDone()).toBe(true); }); - expect(service).toBeInstanceOf(ConfigRegistryApiService); }); - }); - describe('fetchConfig', () => { it('fetches config from API successfully', async () => { const scope = nock('https://client-config.uat-api.cx.metamask.io') .get('/v1/config/networks') @@ -68,11 +70,11 @@ describe('ConfigRegistryApiService', () => { const service = new ConfigRegistryApiService(); const result = await service.fetchConfig(); - expect(result.modified).toBe(true); - expect(result.etag).toBe('"test-etag-123"'); - expect( - (result as Extract).data, - ).toStrictEqual(MOCK_API_RESPONSE); + expect(result).toMatchObject({ + modified: true, + etag: '"test-etag-123"', + data: MOCK_API_RESPONSE, + }); expect(scope.isDone()).toBe(true); }); @@ -84,11 +86,8 @@ describe('ConfigRegistryApiService', () => { const service = new ConfigRegistryApiService(); const result = await service.fetchConfig(); - expect(result.modified).toBe(true); + expect(result).toMatchObject({ modified: true, data: MOCK_API_RESPONSE }); expect(result.etag).toBeUndefined(); - expect( - (result as Extract).data, - ).toStrictEqual(MOCK_API_RESPONSE); expect(scope.isDone()).toBe(true); }); @@ -103,27 +102,43 @@ describe('ConfigRegistryApiService', () => { const result = await service.fetchConfig({ etag }); expect(result.modified).toBe(false); + expect(result.data).toBeUndefined(); expect(scope.isDone()).toBe(true); }); - it('handles 304 Not Modified response without ETag header', async () => { - const mockHeaders = { - get: jest.fn().mockReturnValue(null), - }; - const customFetch = jest.fn().mockResolvedValue({ - ok: true, - status: 304, - headers: mockHeaders, - } as unknown as Response); + it('returns cached data when 304 is received and service has prior successful response', async () => { + const etag = '"test-etag-123"'; + const firstScope = nock('https://client-config.uat-api.cx.metamask.io') + .get('/v1/config/networks') + .reply(200, MOCK_API_RESPONSE, { ETag: etag }); - const service = new ConfigRegistryApiService({ - fetch: customFetch, - }); + const service = new ConfigRegistryApiService(); + await service.fetchConfig(); + expect(firstScope.isDone()).toBe(true); + + const secondScope = nock('https://client-config.uat-api.cx.metamask.io') + .get('/v1/config/networks') + .matchHeader('If-None-Match', etag) + .reply(304); + + const result = await service.fetchConfig({ etag }); + + expect(result.modified).toBe(false); + expect(result.data).toStrictEqual(MOCK_API_RESPONSE); + expect(secondScope.isDone()).toBe(true); + }); + it('handles 304 Not Modified response without ETag header', async () => { + const scope = nock('https://client-config.uat-api.cx.metamask.io') + .get('/v1/config/networks') + .reply(304); + + const service = new ConfigRegistryApiService(); const result = await service.fetchConfig(); expect(result.modified).toBe(false); expect(result.etag).toBeUndefined(); + expect(scope.isDone()).toBe(true); }); it('includes If-None-Match header when etag is provided', async () => { @@ -142,6 +157,7 @@ describe('ConfigRegistryApiService', () => { it('does not include If-None-Match header when etag is undefined', async () => { const scope = nock('https://client-config.uat-api.cx.metamask.io') .get('/v1/config/networks') + .matchHeader('If-None-Match', (val) => val === undefined) .reply(200, MOCK_API_RESPONSE); const service = new ConfigRegistryApiService(); @@ -176,78 +192,51 @@ describe('ConfigRegistryApiService', () => { }); it('throws error when data is null', async () => { - const mockHeaders = { - get: jest.fn().mockReturnValue(null), - }; - const customFetch = jest.fn().mockResolvedValue({ - ok: true, - status: 200, - headers: mockHeaders, - json: async () => null, - } as unknown as Response); + const scope = nock('https://client-config.uat-api.cx.metamask.io') + .get('/v1/config/networks') + .reply(200, 'null'); - const service = new ConfigRegistryApiService({ - fetch: customFetch, - }); + const service = new ConfigRegistryApiService(); await expect(service.fetchConfig()).rejects.toMatchObject( expect.objectContaining({ message: expect.any(String) }), ); + expect(scope.isDone()).toBe(true); }); it('throws error when data.data is null', async () => { - const mockHeaders = { - get: jest.fn().mockReturnValue(null), - }; - const customFetch = jest.fn().mockResolvedValue({ - ok: true, - status: 200, - headers: mockHeaders, - json: async () => ({ data: null }), - } as unknown as Response); + const scope = nock('https://client-config.uat-api.cx.metamask.io') + .get('/v1/config/networks') + .reply(200, { data: null }); - const service = new ConfigRegistryApiService({ - fetch: customFetch, - }); + const service = new ConfigRegistryApiService(); await expect(service.fetchConfig()).rejects.toMatchObject( expect.objectContaining({ message: expect.any(String) }), ); + expect(scope.isDone()).toBe(true); }); it('throws error when data.data.networks is not an array', async () => { - const mockHeaders = { - get: jest.fn().mockReturnValue(null), - }; - const customFetch = jest.fn().mockResolvedValue({ - ok: true, - status: 200, - headers: mockHeaders, - json: async () => ({ data: { networks: 'not-an-array' } }), - } as unknown as Response); + const scope = nock('https://client-config.uat-api.cx.metamask.io') + .get('/v1/config/networks') + .reply(200, { data: { networks: 'not-an-array' } }); - const service = new ConfigRegistryApiService({ - fetch: customFetch, - }); + const service = new ConfigRegistryApiService(); await expect(service.fetchConfig()).rejects.toMatchObject( expect.objectContaining({ message: expect.any(String) }), ); + expect(scope.isDone()).toBe(true); }); it('throws error on HTTP error status', async () => { - const mockHeaders = { - get: jest.fn().mockReturnValue(null), - }; - const customFetch = jest.fn().mockResolvedValue({ - ok: false, - status: 500, - statusText: 'Internal Server Error', - headers: mockHeaders, - } as unknown as Response); + const scope = nock('https://client-config.uat-api.cx.metamask.io') + .get('/v1/config/networks') + .reply(500, 'Internal Server Error'); const service = new ConfigRegistryApiService({ - fetch: customFetch, + policyOptions: { maxRetries: 0 }, }); await expect(service.fetchConfig()).rejects.toMatchObject( @@ -255,6 +244,7 @@ describe('ConfigRegistryApiService', () => { message: 'Failed to fetch config: 500 Internal Server Error', }), ); + expect(scope.isDone()).toBe(true); }); it('handles network errors', async () => { @@ -288,10 +278,7 @@ describe('ConfigRegistryApiService', () => { const result = await service.fetchConfig(); - expect(result.modified).toBe(true); - expect( - (result as Extract).data, - ).toStrictEqual(MOCK_API_RESPONSE); + expect(result).toMatchObject({ modified: true, data: MOCK_API_RESPONSE }); expect(successScope.isDone()).toBe(true); }); }); @@ -346,83 +333,49 @@ describe('ConfigRegistryApiService', () => { ); expect(onBreakHandler).toHaveBeenCalled(); }); - - it('returns the result from policy.onBreak', () => { - const service = new ConfigRegistryApiService(); - const handler = jest.fn(); - const result = service.onBreak(handler); - expect(result).toBeDefined(); - }); }); describe('onDegraded', () => { - it('registers onDegraded handler', () => { - const service = new ConfigRegistryApiService(); - const onDegradedHandler = jest.fn(); + let clock: sinon.SinonFakeTimers; - service.onDegraded(onDegradedHandler); + beforeEach(() => { + clock = useFakeTimers({ now: Date.now() }); + }); - expect(service.onDegraded).toBeDefined(); + afterEach(() => { + clock.restore(); }); it('calls onDegraded handler when service becomes degraded', async () => { const degradedThreshold = 2000; // 2 seconds + nock('https://client-config.uat-api.cx.metamask.io') + .get('/v1/config/networks') + .reply(200, () => { + clock.tick(degradedThreshold + 100); + return MOCK_API_RESPONSE; + }); + const service = new ConfigRegistryApiService({ policyOptions: { degradedThreshold, maxRetries: 0 }, }); - const onDegradedHandler = jest.fn(); service.onDegraded(onDegradedHandler); - const slowFetch = jest.fn().mockImplementation( - () => - new Promise((resolve) => { - setTimeout( - () => - resolve({ - ok: true, - status: 200, - headers: { - get: jest.fn().mockReturnValue('"custom-etag"'), - } as unknown as Headers, - json: async () => MOCK_API_RESPONSE, - } as Response), - degradedThreshold + 100, - ); - }), - ); - - const slowService = new ConfigRegistryApiService({ - fetch: slowFetch, - policyOptions: { degradedThreshold, maxRetries: 0 }, - }); - - slowService.onDegraded(onDegradedHandler); - - await slowService.fetchConfig(); - - expect(slowService.onDegraded).toBeDefined(); - }); + await service.fetchConfig(); - it('returns the result from policy.onDegraded', () => { - const service = new ConfigRegistryApiService(); - const handler = jest.fn(); - const result = service.onDegraded(handler); - expect(result).toBeDefined(); + expect(onDegradedHandler).toHaveBeenCalled(); }); }); describe('custom fetch function', () => { it('uses custom fetch function when provided', async () => { - const mockHeaders = { - get: jest.fn().mockReturnValue('"custom-etag"'), - }; - const customFetch = jest.fn().mockResolvedValue({ - ok: true, - status: 200, - headers: mockHeaders, - json: async () => MOCK_API_RESPONSE, - } as unknown as Response); + const customFetch = jest.fn().mockResolvedValue( + // eslint-disable-next-line no-restricted-globals + new Response(JSON.stringify(MOCK_API_RESPONSE), { + status: 200, + headers: { ETag: '"custom-etag"' }, + }), + ); const service = new ConfigRegistryApiService({ fetch: customFetch, @@ -431,66 +384,7 @@ describe('ConfigRegistryApiService', () => { const result = await service.fetchConfig(); expect(customFetch).toHaveBeenCalled(); - expect(result.modified).toBe(true); - expect( - (result as Extract).data, - ).toStrictEqual(MOCK_API_RESPONSE); - }); - }); - - describe('environment configuration', () => { - it('uses DEV environment URL when env is DEV', async () => { - const scope = nock('https://client-config.dev-api.cx.metamask.io') - .get('/v1/config/networks') - .reply(200, MOCK_API_RESPONSE); - - const service = new ConfigRegistryApiService({ - env: SDK.Env.DEV, - }); - - await service.fetchConfig(); - - expect(scope.isDone()).toBe(true); - }); - - it('uses UAT environment URL when env is UAT', async () => { - const scope = nock('https://client-config.uat-api.cx.metamask.io') - .get('/v1/config/networks') - .reply(200, MOCK_API_RESPONSE); - - const service = new ConfigRegistryApiService({ - env: SDK.Env.UAT, - }); - - await service.fetchConfig(); - - expect(scope.isDone()).toBe(true); - }); - - it('uses PRD environment URL when env is PRD', async () => { - const scope = nock('https://client-config.api.cx.metamask.io') - .get('/v1/config/networks') - .reply(200, MOCK_API_RESPONSE); - - const service = new ConfigRegistryApiService({ - env: SDK.Env.PRD, - }); - - await service.fetchConfig(); - - expect(scope.isDone()).toBe(true); - }); - - it('defaults to UAT environment', async () => { - const scope = nock('https://client-config.uat-api.cx.metamask.io') - .get('/v1/config/networks') - .reply(200, MOCK_API_RESPONSE); - - const service = new ConfigRegistryApiService(); - - await service.fetchConfig(); - - expect(scope.isDone()).toBe(true); + expect(result).toMatchObject({ modified: true, data: MOCK_API_RESPONSE }); }); }); }); diff --git a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts index c520e53ed32..fcf5d7003d8 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts @@ -5,8 +5,12 @@ import type { } from '@metamask/controller-utils'; import { SDK } from '@metamask/profile-sync-controller'; +import type { + FetchConfigOptions, + FetchConfigResult, + RegistryConfigApiResponse, +} from './types'; import { validateRegistryConfigApiResponse } from './types'; -import type { FetchConfigOptions, FetchConfigResult } from './types'; const ENDPOINT_PATH = '/config/networks'; @@ -38,6 +42,9 @@ export class ConfigRegistryApiService { readonly #fetch: typeof fetch; + /** Cached response from the last successful fetch. Used when server returns 304. */ + #cachedResponse: RegistryConfigApiResponse | null = null; + /** * Construct a Config Registry API Service. * @@ -57,12 +64,40 @@ export class ConfigRegistryApiService { this.#policy = createServicePolicy(policyOptions); } + /** + * Registers a handler that will be called after a set number of retry rounds + * prove that requests to the API endpoint consistently return a 5xx response. + * + * @param args - The arguments passed to the underlying policy's onBreak method + * (e.g. the listener to be called). + * @returns An object that can be used to unregister the handler. See + * {@link CockatielEvent}. + * @see {@link createServicePolicy} + */ onBreak( ...args: Parameters ): ReturnType { return this.#policy.onBreak(...args); } + /** + * Registers a handler that will be called under one of two circumstances: + * + * 1. After a set number of retries prove that requests to the API + * consistently result in one of the following failures: + * 1. A connection initiation error + * 2. A connection reset error + * 3. A timeout error + * 4. A non-JSON response + * 5. A 502, 503, or 504 response + * 2. After a successful request is made to the API, but the response takes + * longer than a set duration to return. + * + * @param args - The arguments passed to the underlying policy's onDegraded + * method (e.g. the listener to be called). + * @returns An object that can be used to unregister the handler. See + * {@link CockatielEvent}. + */ onDegraded( ...args: Parameters ): ReturnType { @@ -103,6 +138,7 @@ export class ConfigRegistryApiService { return { modified: false, etag, + ...(this.#cachedResponse !== null && { data: this.#cachedResponse }), }; } @@ -111,6 +147,8 @@ export class ConfigRegistryApiService { validateRegistryConfigApiResponse(jsonData); + this.#cachedResponse = jsonData; + return { data: jsonData, etag, diff --git a/packages/config-registry-controller/src/config-registry-api-service/types.ts b/packages/config-registry-controller/src/config-registry-api-service/types.ts index 81bf91cb8cc..4e6789d3d5f 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/types.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/types.ts @@ -69,6 +69,11 @@ export type FetchConfigResult = | { modified: false; etag?: string; + /** + * Cached data from the service when available (e.g. after a previous + * successful fetch). Omitted when the service has no cache yet. + */ + data?: RegistryConfigApiResponse; } | { modified: true; diff --git a/packages/config-registry-controller/src/index.ts b/packages/config-registry-controller/src/index.ts index d67fd584e55..081861fbdaf 100644 --- a/packages/config-registry-controller/src/index.ts +++ b/packages/config-registry-controller/src/index.ts @@ -7,6 +7,7 @@ export type { ConfigRegistryControllerStopPollingAction, ConfigRegistryControllerEvents, ConfigRegistryControllerStateChangeEvent, + ConfigRegistryControllerMessenger, ConfigRegistryMessenger, } from './ConfigRegistryController'; export { diff --git a/tests/fake-provider.ts b/tests/fake-provider.ts index a767ffb1c46..f46b314b03a 100644 --- a/tests/fake-provider.ts +++ b/tests/fake-provider.ts @@ -1,10 +1,11 @@ import { InternalProvider } from '@metamask/eth-json-rpc-provider'; -import { JsonRpcEngineV2 } from '@metamask/json-rpc-engine/v2'; -import type { - JsonRpcMiddleware, - MiddlewareContext, - ResultConstraint, +import { + JsonRpcEngineV2, + type JsonRpcMiddleware, + type MiddlewareContext, + type ResultConstraint, } from '@metamask/json-rpc-engine/v2'; +import type { Provider } from '@metamask/network-controller'; import type { Json, JsonRpcId, @@ -15,12 +16,6 @@ import type { } from '@metamask/utils'; import { inspect, isDeepStrictEqual } from 'util'; -type Provider = InternalProvider< - MiddlewareContext< - { origin: string; skipCache: boolean } & Record - > ->; - // Store this in case it gets stubbed later const originalSetTimeout = global.setTimeout; @@ -144,7 +139,7 @@ export class FakeProvider super({ engine: JsonRpcEngineV2.create({ middleware: [ - (): never => { + () => { throw new Error('FakeProvider received unstubbed method call'); }, ], @@ -161,8 +156,6 @@ export class FakeProvider return new Promise((resolve, reject) => { this.#handleSend(payload, (error, providerRes) => { if (error) { - // Error is `unknown`. - // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors reject(error); } else { resolve(providerRes.result); @@ -176,7 +169,7 @@ export class FakeProvider // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any callback: (error: unknown, providerRes?: any) => void, - ): void => { + ) => { return this.#handleSend(payload, callback); }; @@ -185,7 +178,7 @@ export class FakeProvider // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any callback: (error: unknown, providerRes?: any) => void, - ): void => { + ) => { return this.#handleSend(req, callback); }; @@ -194,7 +187,7 @@ export class FakeProvider // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any callback: (error: unknown, providerRes?: any) => void, - ): void { + ) { if (Array.isArray(req)) { throw new Error("Arrays aren't supported"); } @@ -226,36 +219,37 @@ export class FakeProvider } throw new Error(message); - } - - const stub = this.#stubs[index]; - if (stub === undefined) { - throw new Error('Stub not found at index'); - } + } else { + // We are already checking that this stub exists above. + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const stub = this.#stubs[index]!; - if (stub.discardAfterMatching !== false) { - this.#stubs.splice(index, 1); - } + if (stub.discardAfterMatching !== false) { + this.#stubs.splice(index, 1); + } - if (stub.delay) { - originalSetTimeout(() => { + if (stub.delay) { + originalSetTimeout(() => { + // TODO: Either fix this lint violation or explain why it's necessary to ignore. + // eslint-disable-next-line @typescript-eslint/no-floating-promises + this.#handleRequest(stub, callback); + }, stub.delay); + } else { // TODO: Either fix this lint violation or explain why it's necessary to ignore. // eslint-disable-next-line @typescript-eslint/no-floating-promises this.#handleRequest(stub, callback); - }, stub.delay); - } else { - // TODO: Either fix this lint violation or explain why it's necessary to ignore. - // eslint-disable-next-line @typescript-eslint/no-floating-promises - this.#handleRequest(stub, callback); - } + } - this.calledStubs.push(stub); + this.calledStubs.push({ ...stub }); + } } async #handleRequest( stub: FakeProviderStub, - callback: (error: unknown, response?: JsonRpcResponse) => void, - ): Promise { + // TODO: Replace `any` with type + // eslint-disable-next-line @typescript-eslint/no-explicit-any + callback: (error: unknown, response?: JsonRpcResponse) => void, + ) { if (stub.beforeCompleting) { await stub.beforeCompleting(); } From d42ed9f066fb790fcd9880306408a6f12bcabdff Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Fri, 20 Feb 2026 17:21:06 +0100 Subject: [PATCH 37/55] fix: fix comments --- .../src/ConfigRegistryController.test.ts | 162 ++++++++++++------ 1 file changed, 105 insertions(+), 57 deletions(-) diff --git a/packages/config-registry-controller/src/ConfigRegistryController.test.ts b/packages/config-registry-controller/src/ConfigRegistryController.test.ts index 81afa9f30ba..9ad4f0d9aed 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.test.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.test.ts @@ -220,50 +220,42 @@ describe('ConfigRegistryController', () => { describe('polling', () => { it('starts polling', async () => { - await withController(async ({ controller, clock }) => { - const executePollSpy = jest.spyOn(controller, '_executePoll'); - controller.startPolling(null); - - await advanceTime({ clock, duration: 0 }); - - expect(executePollSpy).toHaveBeenCalledTimes(1); - controller.stopAllPolling(); - }); + await withController( + async ({ controller, clock, mockApiServiceHandler }) => { + controller.startPolling(null); + await advanceTime({ clock, duration: 0 }); + expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); + controller.stopAllPolling(); + }, + ); }); it('polls at specified interval', async () => { const pollingInterval = 1000; await withController( { options: { pollingInterval } }, - async ({ controller, clock }) => { - const executePollSpy = jest.spyOn(controller, '_executePoll'); + async ({ controller, clock, mockApiServiceHandler }) => { controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); - executePollSpy.mockClear(); - + mockApiServiceHandler.mockClear(); await advanceTime({ clock, duration: pollingInterval }); - - expect(executePollSpy).toHaveBeenCalledTimes(1); + expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); controller.stopAllPolling(); }, ); }); it('stops polling', async () => { - await withController(async ({ controller, clock }) => { - const executePollSpy = jest.spyOn(controller, '_executePoll'); - controller.startPolling(null); - - await advanceTime({ clock, duration: 0 }); - executePollSpy.mockClear(); - - controller.stopAllPolling(); - - await advanceTime({ clock, duration: DEFAULT_POLLING_INTERVAL }); - - expect(executePollSpy).not.toHaveBeenCalled(); - }); + await withController( + async ({ controller, clock, mockApiServiceHandler }) => { + controller.startPolling(null); + await advanceTime({ clock, duration: 0 }); + mockApiServiceHandler.mockClear(); + controller.stopAllPolling(); + await advanceTime({ clock, duration: DEFAULT_POLLING_INTERVAL }); + expect(mockApiServiceHandler).not.toHaveBeenCalled(); + }, + ); }); it('uses fallback config when no configs exist', async () => { @@ -271,6 +263,7 @@ describe('ConfigRegistryController', () => { { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, async ({ controller, + clock, rootMessenger, mockRemoteFeatureFlagGetState, mockApiServiceHandler, @@ -284,7 +277,8 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockRejectedValue(new Error('Network error')); - await controller._executePoll(null); + controller.startPolling(null); + await advanceTime({ clock, duration: 0 }); expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ message: 'Network error' }), @@ -314,6 +308,7 @@ describe('ConfigRegistryController', () => { }, async ({ controller, + clock, rootMessenger, mockRemoteFeatureFlagGetState, mockApiServiceHandler, @@ -327,7 +322,8 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockRejectedValue(new Error('Network error')); - await controller._executePoll(null); + controller.startPolling(null); + await advanceTime({ clock, duration: 0 }); expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ message: 'Network error' }), @@ -344,6 +340,7 @@ describe('ConfigRegistryController', () => { { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, async ({ controller, + clock, rootMessenger, mockRemoteFeatureFlagGetState, mockApiServiceHandler, @@ -357,7 +354,8 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockRejectedValue(new Error('Network error')); - await controller._executePoll(null); + controller.startPolling(null); + await advanceTime({ clock, duration: 0 }); expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ message: 'Network error' }), @@ -374,6 +372,7 @@ describe('ConfigRegistryController', () => { await withController( async ({ controller, + clock, mockRemoteFeatureFlagGetState, mockApiServiceHandler, }) => { @@ -390,7 +389,8 @@ describe('ConfigRegistryController', () => { }); const beforeTimestamp = Date.now(); - await controller._executePoll(null); + controller.startPolling(null); + await advanceTime({ clock, duration: 0 }); const afterTimestamp = Date.now(); expect(controller.state.etag).toBe('"test-etag"'); @@ -416,6 +416,7 @@ describe('ConfigRegistryController', () => { }, async ({ controller, + clock, mockRemoteFeatureFlagGetState, mockApiServiceHandler, }) => { @@ -431,7 +432,8 @@ describe('ConfigRegistryController', () => { }); const beforeTimestamp = Date.now(); - await controller._executePoll(null); + controller.startPolling(null); + await advanceTime({ clock, duration: 0 }); const afterTimestamp = Date.now(); expect(controller.state.etag).toBe('"existing-etag"'); @@ -457,6 +459,7 @@ describe('ConfigRegistryController', () => { }, async ({ controller, + clock, mockRemoteFeatureFlagGetState, mockApiServiceHandler, }) => { @@ -473,7 +476,8 @@ describe('ConfigRegistryController', () => { }); const beforeTimestamp = Date.now(); - await controller._executePoll(null); + controller.startPolling(null); + await advanceTime({ clock, duration: 0 }); const afterTimestamp = Date.now(); expect(controller.state.etag).toBeNull(); @@ -492,6 +496,7 @@ describe('ConfigRegistryController', () => { await withController( async ({ controller, + clock, rootMessenger, mockRemoteFeatureFlagGetState, mockApiServiceHandler, @@ -508,7 +513,8 @@ describe('ConfigRegistryController', () => { ); mockApiServiceHandler.mockRejectedValue(validationError); - await controller._executePoll(null); + controller.startPolling(null); + await advanceTime({ clock, duration: 0 }); expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ @@ -523,6 +529,7 @@ describe('ConfigRegistryController', () => { await withController( async ({ controller, + clock, rootMessenger, mockRemoteFeatureFlagGetState, mockApiServiceHandler, @@ -539,7 +546,8 @@ describe('ConfigRegistryController', () => { ); mockApiServiceHandler.mockRejectedValue(validationError); - await controller._executePoll(null); + controller.startPolling(null); + await advanceTime({ clock, duration: 0 }); expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ @@ -554,6 +562,7 @@ describe('ConfigRegistryController', () => { await withController( async ({ controller, + clock, rootMessenger, mockRemoteFeatureFlagGetState, mockApiServiceHandler, @@ -570,7 +579,8 @@ describe('ConfigRegistryController', () => { ); mockApiServiceHandler.mockRejectedValue(validationError); - await controller._executePoll(null); + controller.startPolling(null); + await advanceTime({ clock, duration: 0 }); expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ @@ -585,6 +595,7 @@ describe('ConfigRegistryController', () => { await withController( async ({ controller, + clock, rootMessenger, mockRemoteFeatureFlagGetState, mockApiServiceHandler, @@ -601,7 +612,8 @@ describe('ConfigRegistryController', () => { ); mockApiServiceHandler.mockRejectedValue(validationError); - await controller._executePoll(null); + controller.startPolling(null); + await advanceTime({ clock, duration: 0 }); expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ @@ -623,7 +635,12 @@ describe('ConfigRegistryController', () => { }, }, }, - async ({ controller, messenger, mockRemoteFeatureFlagGetState }) => { + async ({ + controller, + clock, + messenger, + mockRemoteFeatureFlagGetState, + }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { configRegistryApiEnabled: true, @@ -636,7 +653,8 @@ describe('ConfigRegistryController', () => { 'call', ) as jest.SpyInstance; - await controller._executePoll(null); + controller.startPolling(null); + await advanceTime({ clock, duration: 0 }); expect(fetchConfigSpy).not.toHaveBeenCalledWith( 'ConfigRegistryApiService:fetchConfig', @@ -657,6 +675,7 @@ describe('ConfigRegistryController', () => { }, async ({ controller, + clock, mockRemoteFeatureFlagGetState, mockApiServiceHandler, }) => { @@ -683,7 +702,8 @@ describe('ConfigRegistryController', () => { modified: true, }); - await controller._executePoll(null); + controller.startPolling(null); + await advanceTime({ clock, duration: 0 }); expect(mockApiServiceHandler).toHaveBeenCalled(); expect(controller.state.lastFetched).not.toBeNull(); @@ -704,6 +724,7 @@ describe('ConfigRegistryController', () => { }, async ({ controller, + clock, mockRemoteFeatureFlagGetState, mockApiServiceHandler, }) => { @@ -732,7 +753,8 @@ describe('ConfigRegistryController', () => { modified: true, }); - await controller._executePoll(null); + controller.startPolling(null); + await advanceTime({ clock, duration: 0 }); expect(mockApiServiceHandler).toHaveBeenCalled(); expect(controller.state.lastFetched).not.toBe(oldTimestamp); @@ -754,7 +776,12 @@ describe('ConfigRegistryController', () => { }, }, }, - async ({ controller, messenger, mockRemoteFeatureFlagGetState }) => { + async ({ + controller, + clock, + messenger, + mockRemoteFeatureFlagGetState, + }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { configRegistryApiEnabled: true, @@ -767,7 +794,8 @@ describe('ConfigRegistryController', () => { 'call', ) as jest.SpyInstance; - await controller._executePoll(null); + controller.startPolling(null); + await advanceTime({ clock, duration: 0 }); expect(fetchConfigSpy).not.toHaveBeenCalledWith( 'ConfigRegistryApiService:fetchConfig', @@ -787,7 +815,12 @@ describe('ConfigRegistryController', () => { }, }, }, - async ({ controller, messenger, mockRemoteFeatureFlagGetState }) => { + async ({ + controller, + clock, + messenger, + mockRemoteFeatureFlagGetState, + }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { configRegistryApiEnabled: true, @@ -804,7 +837,8 @@ describe('ConfigRegistryController', () => { 'call', ) as jest.SpyInstance; - await controller._executePoll(null); + controller.startPolling(null); + await advanceTime({ clock, duration: 0 }); expect(fetchConfigSpy).not.toHaveBeenCalledWith( 'ConfigRegistryApiService:fetchConfig', @@ -819,6 +853,7 @@ describe('ConfigRegistryController', () => { { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, async ({ controller, + clock, rootMessenger, mockRemoteFeatureFlagGetState, mockApiServiceHandler, @@ -832,7 +867,8 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockRejectedValue('String error'); - await controller._executePoll(null); + controller.startPolling(null); + await advanceTime({ clock, duration: 0 }); expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ message: 'String error' }), @@ -855,6 +891,7 @@ describe('ConfigRegistryController', () => { }, async ({ controller, + clock, rootMessenger, mockRemoteFeatureFlagGetState, mockApiServiceHandler, @@ -868,7 +905,8 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockRejectedValue(new Error('Network error')); - await controller._executePoll(null); + controller.startPolling(null); + await advanceTime({ clock, duration: 0 }); expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ message: 'Network error' }), @@ -1144,6 +1182,7 @@ describe('ConfigRegistryController', () => { await withController( async ({ controller, + clock, mockRemoteFeatureFlagGetState, mockApiServiceHandler, }) => { @@ -1194,7 +1233,8 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockImplementation(fetchConfigSpy); - await controller._executePoll(null); + controller.startPolling(null); + await advanceTime({ clock, duration: 0 }); expect(fetchConfigSpy).toHaveBeenCalled(); expect(controller.state.configs.networks['0x1']).toBeDefined(); @@ -1207,6 +1247,7 @@ describe('ConfigRegistryController', () => { await withController( async ({ controller, + clock, mockRemoteFeatureFlagGetState, mockApiServiceHandler, }) => { @@ -1326,7 +1367,8 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockImplementation(fetchConfigSpy); - await controller._executePoll(null); + controller.startPolling(null); + await advanceTime({ clock, duration: 0 }); // All networks stored in state const allNetworks = selectNetworks(controller.state); @@ -1351,6 +1393,7 @@ describe('ConfigRegistryController', () => { await withController( async ({ controller, + clock, mockRemoteFeatureFlagGetState, mockApiServiceHandler, }) => { @@ -1446,7 +1489,8 @@ describe('ConfigRegistryController', () => { etag: 'test-etag', }); - await controller._executePoll(null); + controller.startPolling(null); + await advanceTime({ clock, duration: 0 }); // Last occurrence overwrites (no grouping/priority) expect(controller.state.configs.networks['0x1']).toBeDefined(); @@ -1466,6 +1510,7 @@ describe('ConfigRegistryController', () => { await withController( async ({ controller, + clock, mockRemoteFeatureFlagGetState, mockApiServiceHandler, }) => { @@ -1538,7 +1583,8 @@ describe('ConfigRegistryController', () => { etag: 'test-etag', }); - await controller._executePoll(null); + controller.startPolling(null); + await advanceTime({ clock, duration: 0 }); // Last occurrence overwrites expect(controller.state.configs.networks['0x1']).toBeDefined(); @@ -1557,7 +1603,7 @@ describe('ConfigRegistryController', () => { isConfigRegistryApiEnabled: customIsEnabled, }, }, - async ({ controller, messenger, mockApiServiceHandler }) => { + async ({ controller, clock, messenger, mockApiServiceHandler }) => { const mockNetworks = [ { chainId: '0x1', @@ -1596,7 +1642,8 @@ describe('ConfigRegistryController', () => { etag: 'test-etag', }); - await controller._executePoll(null); + controller.startPolling(null); + await advanceTime({ clock, duration: 0 }); expect(customIsEnabled).toHaveBeenCalledWith(messenger); expect(mockApiServiceHandler).toHaveBeenCalled(); @@ -1615,8 +1662,9 @@ describe('ConfigRegistryController', () => { isConfigRegistryApiEnabled: customIsEnabled, }, }, - async ({ controller, messenger, mockApiServiceHandler }) => { - await controller._executePoll(null); + async ({ controller, clock, messenger, mockApiServiceHandler }) => { + controller.startPolling(null); + await advanceTime({ clock, duration: 0 }); expect(customIsEnabled).toHaveBeenCalledWith(messenger); expect(mockApiServiceHandler).not.toHaveBeenCalled(); From e2917d0ff22303a6b6fe8af53929eac54eebf130 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Fri, 20 Feb 2026 17:42:08 +0100 Subject: [PATCH 38/55] chore: update yarn.lock --- yarn.lock | 1449 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 1414 insertions(+), 35 deletions(-) diff --git a/yarn.lock b/yarn.lock index 635244ea30e..6d6ffaa933e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -30,7 +30,7 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.23.2, @babel/core@npm:^7.23.9": +"@babel/core@npm:^7.1.0, @babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.23.2, @babel/core@npm:^7.23.9, @babel/core@npm:^7.7.2, @babel/core@npm:^7.8.0": version: 7.29.0 resolution: "@babel/core@npm:7.29.0" dependencies: @@ -365,7 +365,7 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.23.2, @babel/traverse@npm:^7.28.6, @babel/traverse@npm:^7.29.0": +"@babel/traverse@npm:^7.23.2, @babel/traverse@npm:^7.28.6, @babel/traverse@npm:^7.29.0, @babel/traverse@npm:^7.7.2": version: 7.29.0 resolution: "@babel/traverse@npm:7.29.0" dependencies: @@ -380,7 +380,7 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.23.0, @babel/types@npm:^7.28.6, @babel/types@npm:^7.29.0, @babel/types@npm:^7.3.3": +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.23.0, @babel/types@npm:^7.28.2, @babel/types@npm:^7.28.6, @babel/types@npm:^7.29.0, @babel/types@npm:^7.3.3": version: 7.29.0 resolution: "@babel/types@npm:7.29.0" dependencies: @@ -1866,6 +1866,20 @@ __metadata: languageName: node linkType: hard +"@jest/console@npm:^27.5.1": + version: 27.5.1 + resolution: "@jest/console@npm:27.5.1" + dependencies: + "@jest/types": "npm:^27.5.1" + "@types/node": "npm:*" + chalk: "npm:^4.0.0" + jest-message-util: "npm:^27.5.1" + jest-util: "npm:^27.5.1" + slash: "npm:^3.0.0" + checksum: 10/f724ff9693b09711fded8b87145c3446091bde87f572e210667c2b8290b5364c776f3a99c7d1fd6d5642f7f9424d5acc312c12e9cc4da2ef0260d34547869fdd + languageName: node + linkType: hard + "@jest/console@npm:^29.7.0": version: 29.7.0 resolution: "@jest/console@npm:29.7.0" @@ -1880,6 +1894,47 @@ __metadata: languageName: node linkType: hard +"@jest/core@npm:^27.5.1": + version: 27.5.1 + resolution: "@jest/core@npm:27.5.1" + dependencies: + "@jest/console": "npm:^27.5.1" + "@jest/reporters": "npm:^27.5.1" + "@jest/test-result": "npm:^27.5.1" + "@jest/transform": "npm:^27.5.1" + "@jest/types": "npm:^27.5.1" + "@types/node": "npm:*" + ansi-escapes: "npm:^4.2.1" + chalk: "npm:^4.0.0" + emittery: "npm:^0.8.1" + exit: "npm:^0.1.2" + graceful-fs: "npm:^4.2.9" + jest-changed-files: "npm:^27.5.1" + jest-config: "npm:^27.5.1" + jest-haste-map: "npm:^27.5.1" + jest-message-util: "npm:^27.5.1" + jest-regex-util: "npm:^27.5.1" + jest-resolve: "npm:^27.5.1" + jest-resolve-dependencies: "npm:^27.5.1" + jest-runner: "npm:^27.5.1" + jest-runtime: "npm:^27.5.1" + jest-snapshot: "npm:^27.5.1" + jest-util: "npm:^27.5.1" + jest-validate: "npm:^27.5.1" + jest-watcher: "npm:^27.5.1" + micromatch: "npm:^4.0.4" + rimraf: "npm:^3.0.0" + slash: "npm:^3.0.0" + strip-ansi: "npm:^6.0.0" + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + checksum: 10/79eb63c3197336c39de6a3341d3f5e7dbca7e20796bd4ee3d725e4ef2832f4d07242898a8af6c9de19ebd700983385a3df16c024b4497f8beb666c8ffe96ccb4 + languageName: node + linkType: hard + "@jest/core@npm:^29.7.0": version: 29.7.0 resolution: "@jest/core@npm:29.7.0" @@ -1921,6 +1976,18 @@ __metadata: languageName: node linkType: hard +"@jest/environment@npm:^27.5.1": + version: 27.5.1 + resolution: "@jest/environment@npm:27.5.1" + dependencies: + "@jest/fake-timers": "npm:^27.5.1" + "@jest/types": "npm:^27.5.1" + "@types/node": "npm:*" + jest-mock: "npm:^27.5.1" + checksum: 10/74a2a4427f82b096c4f7223c56a27f64487ee4639b017129f31e99ebb2e9a614eb365ec77c3701d6eedc1c8d711ad2dd4b31d6dfad72cbb6d73a4f1fdc4a86cb + languageName: node + linkType: hard + "@jest/environment@npm:^29.7.0": version: 29.7.0 resolution: "@jest/environment@npm:29.7.0" @@ -1952,6 +2019,20 @@ __metadata: languageName: node linkType: hard +"@jest/fake-timers@npm:^27.5.1": + version: 27.5.1 + resolution: "@jest/fake-timers@npm:27.5.1" + dependencies: + "@jest/types": "npm:^27.5.1" + "@sinonjs/fake-timers": "npm:^8.0.1" + "@types/node": "npm:*" + jest-message-util: "npm:^27.5.1" + jest-mock: "npm:^27.5.1" + jest-util: "npm:^27.5.1" + checksum: 10/dd8b736edbc8da77af3ca14ffaa2f331168618db7b879a3a07a4667af11ae4ff840f64a61e3828e217ee94f06d5a9ba30bf19e5103bb74e193b8216ce4c0708d + languageName: node + linkType: hard + "@jest/fake-timers@npm:^29.7.0": version: 29.7.0 resolution: "@jest/fake-timers@npm:29.7.0" @@ -1966,6 +2047,17 @@ __metadata: languageName: node linkType: hard +"@jest/globals@npm:^27.5.1": + version: 27.5.1 + resolution: "@jest/globals@npm:27.5.1" + dependencies: + "@jest/environment": "npm:^27.5.1" + "@jest/types": "npm:^27.5.1" + expect: "npm:^27.5.1" + checksum: 10/f3b06e9b81686d7a5dd7bafb229cba73bdc90d3e16815deebf302d3a402ac29a1e9bafa274d908caefe7083938402619974c89420d247ab8739acd652c11b16d + languageName: node + linkType: hard + "@jest/globals@npm:^29.7.0": version: 29.7.0 resolution: "@jest/globals@npm:29.7.0" @@ -1978,6 +2070,44 @@ __metadata: languageName: node linkType: hard +"@jest/reporters@npm:^27.5.1": + version: 27.5.1 + resolution: "@jest/reporters@npm:27.5.1" + dependencies: + "@bcoe/v8-coverage": "npm:^0.2.3" + "@jest/console": "npm:^27.5.1" + "@jest/test-result": "npm:^27.5.1" + "@jest/transform": "npm:^27.5.1" + "@jest/types": "npm:^27.5.1" + "@types/node": "npm:*" + chalk: "npm:^4.0.0" + collect-v8-coverage: "npm:^1.0.0" + exit: "npm:^0.1.2" + glob: "npm:^7.1.2" + graceful-fs: "npm:^4.2.9" + istanbul-lib-coverage: "npm:^3.0.0" + istanbul-lib-instrument: "npm:^5.1.0" + istanbul-lib-report: "npm:^3.0.0" + istanbul-lib-source-maps: "npm:^4.0.0" + istanbul-reports: "npm:^3.1.3" + jest-haste-map: "npm:^27.5.1" + jest-resolve: "npm:^27.5.1" + jest-util: "npm:^27.5.1" + jest-worker: "npm:^27.5.1" + slash: "npm:^3.0.0" + source-map: "npm:^0.6.0" + string-length: "npm:^4.0.1" + terminal-link: "npm:^2.0.0" + v8-to-istanbul: "npm:^8.1.0" + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + checksum: 10/d49aea4e5b09f9a316f0ff303d11f2db057cadaf370e3e706c024e4ea7f270899cccf7488711def4a930bc23e4f4676f406d1c646f8c6656de4c43dd40652877 + languageName: node + linkType: hard + "@jest/reporters@npm:^29.7.0": version: 29.7.0 resolution: "@jest/reporters@npm:29.7.0" @@ -2024,6 +2154,17 @@ __metadata: languageName: node linkType: hard +"@jest/source-map@npm:^27.5.1": + version: 27.5.1 + resolution: "@jest/source-map@npm:27.5.1" + dependencies: + callsites: "npm:^3.0.0" + graceful-fs: "npm:^4.2.9" + source-map: "npm:^0.6.0" + checksum: 10/90b1f4212b7191d594275c9b9aae18319b944e4ed018af74a1661fd9b783983074d00369a111274697b87193aa2b084f0f022a265d070f4a66d39d06d14a0336 + languageName: node + linkType: hard + "@jest/source-map@npm:^29.6.3": version: 29.6.3 resolution: "@jest/source-map@npm:29.6.3" @@ -2035,6 +2176,18 @@ __metadata: languageName: node linkType: hard +"@jest/test-result@npm:^27.5.1": + version: 27.5.1 + resolution: "@jest/test-result@npm:27.5.1" + dependencies: + "@jest/console": "npm:^27.5.1" + "@jest/types": "npm:^27.5.1" + "@types/istanbul-lib-coverage": "npm:^2.0.0" + collect-v8-coverage: "npm:^1.0.0" + checksum: 10/43cdc31b39857d4d6487345f1bfb9c97157ddfb7ff3e3b843f3999d4a3be5b1e7c1079302459ea627976fa9da7462426dfb26cf231ef2b6eb79bc80b67361c23 + languageName: node + linkType: hard + "@jest/test-result@npm:^29.7.0": version: 29.7.0 resolution: "@jest/test-result@npm:29.7.0" @@ -2047,6 +2200,18 @@ __metadata: languageName: node linkType: hard +"@jest/test-sequencer@npm:^27.5.1": + version: 27.5.1 + resolution: "@jest/test-sequencer@npm:27.5.1" + dependencies: + "@jest/test-result": "npm:^27.5.1" + graceful-fs: "npm:^4.2.9" + jest-haste-map: "npm:^27.5.1" + jest-runtime: "npm:^27.5.1" + checksum: 10/74c9c773eb0d8de581e17a7ea1d9173b835c0c91b40665caa42fd68931a2ee7429f9ed59c97a15855d3ad46024a17e7387ad4b900d4540890a7681d4a8a42bdd + languageName: node + linkType: hard + "@jest/test-sequencer@npm:^29.7.0": version: 29.7.0 resolution: "@jest/test-sequencer@npm:29.7.0" @@ -2059,6 +2224,29 @@ __metadata: languageName: node linkType: hard +"@jest/transform@npm:^27.5.1": + version: 27.5.1 + resolution: "@jest/transform@npm:27.5.1" + dependencies: + "@babel/core": "npm:^7.1.0" + "@jest/types": "npm:^27.5.1" + babel-plugin-istanbul: "npm:^6.1.1" + chalk: "npm:^4.0.0" + convert-source-map: "npm:^1.4.0" + fast-json-stable-stringify: "npm:^2.0.0" + graceful-fs: "npm:^4.2.9" + jest-haste-map: "npm:^27.5.1" + jest-regex-util: "npm:^27.5.1" + jest-util: "npm:^27.5.1" + micromatch: "npm:^4.0.4" + pirates: "npm:^4.0.4" + slash: "npm:^3.0.0" + source-map: "npm:^0.6.1" + write-file-atomic: "npm:^3.0.0" + checksum: 10/9e0bec99971d28fc205e5e282be384a0269760b8452aa94e3d400465819b6c790c862ec5597d8c9439f2da97e68c0c4cec071340ff3e4c4414a34e5b2a19074a + languageName: node + linkType: hard + "@jest/transform@npm:^29.7.0": version: 29.7.0 resolution: "@jest/transform@npm:29.7.0" @@ -2095,6 +2283,19 @@ __metadata: languageName: node linkType: hard +"@jest/types@npm:^27.5.1": + version: 27.5.1 + resolution: "@jest/types@npm:27.5.1" + dependencies: + "@types/istanbul-lib-coverage": "npm:^2.0.0" + "@types/istanbul-reports": "npm:^3.0.0" + "@types/node": "npm:*" + "@types/yargs": "npm:^16.0.0" + chalk: "npm:^4.0.0" + checksum: 10/d3ca1655673539c54665f3e9135dc70887feb6b667b956e712c38f42e513ae007d3593b8075aecea8f2db7119f911773010f17f93be070b1725fbc6225539b6e + languageName: node + linkType: hard + "@jest/types@npm:^29.6.3": version: 29.6.3 resolution: "@jest/types@npm:29.6.3" @@ -2980,7 +3181,7 @@ __metadata: languageName: node linkType: hard -"@metamask/controller-utils@npm:^11.19.0, @metamask/controller-utils@workspace:packages/controller-utils": +"@metamask/controller-utils@npm:^11.18.0, @metamask/controller-utils@npm:^11.19.0, @metamask/controller-utils@workspace:packages/controller-utils": version: 0.0.0-use.local resolution: "@metamask/controller-utils@workspace:packages/controller-utils" dependencies: @@ -4431,7 +4632,7 @@ __metadata: languageName: unknown linkType: soft -"@metamask/polling-controller@npm:^16.0.3, @metamask/polling-controller@workspace:packages/polling-controller": +"@metamask/polling-controller@npm:^16.0.2, @metamask/polling-controller@npm:^16.0.3, @metamask/polling-controller@workspace:packages/polling-controller": version: 0.0.0-use.local resolution: "@metamask/polling-controller@workspace:packages/polling-controller" dependencies: @@ -5550,6 +5751,15 @@ __metadata: languageName: node linkType: hard +"@sinonjs/commons@npm:^1.6.0, @sinonjs/commons@npm:^1.7.0, @sinonjs/commons@npm:^1.8.1": + version: 1.8.6 + resolution: "@sinonjs/commons@npm:1.8.6" + dependencies: + type-detect: "npm:4.0.8" + checksum: 10/51987338fd8b4d1e135822ad593dd23a3288764aa41d83c695124d512bc38b87eece859078008651ecc7f1df89a7e558a515dc6f02d21a93be4ba50b39a28914 + languageName: node + linkType: hard + "@sinonjs/commons@npm:^3.0.0": version: 3.0.1 resolution: "@sinonjs/commons@npm:3.0.1" @@ -5568,6 +5778,42 @@ __metadata: languageName: node linkType: hard +"@sinonjs/fake-timers@npm:^6.0.0, @sinonjs/fake-timers@npm:^6.0.1": + version: 6.0.1 + resolution: "@sinonjs/fake-timers@npm:6.0.1" + dependencies: + "@sinonjs/commons": "npm:^1.7.0" + checksum: 10/c7ee19f62bd0ca52553dd5fca9b3921373218c9fed0f02af2f8e5261f65ce9ff0a5e55ca612ded6daf4088a243e905d61bd6dce1c6d325794283b55c71708395 + languageName: node + linkType: hard + +"@sinonjs/fake-timers@npm:^8.0.1": + version: 8.1.0 + resolution: "@sinonjs/fake-timers@npm:8.1.0" + dependencies: + "@sinonjs/commons": "npm:^1.7.0" + checksum: 10/da50ddd68411617fcf72d9fb70b621aa2a6d17faa93a2769c7af390c88b40e045f84544db022dd1ac30a6db115d2a0f96473854d4a106b0174351f22d42910ce + languageName: node + linkType: hard + +"@sinonjs/samsam@npm:^5.3.1": + version: 5.3.1 + resolution: "@sinonjs/samsam@npm:5.3.1" + dependencies: + "@sinonjs/commons": "npm:^1.6.0" + lodash.get: "npm:^4.4.2" + type-detect: "npm:^4.0.8" + checksum: 10/6850b9980f042a844072a34ce3ca80b098d4550c8c7a83b2b2e7beb1e06ad19608699544b7a8b0c7db882528d8b74321dfd185d0651cff08cbe793cb73dd39d3 + languageName: node + linkType: hard + +"@sinonjs/text-encoding@npm:^0.7.1": + version: 0.7.3 + resolution: "@sinonjs/text-encoding@npm:0.7.3" + checksum: 10/f0cc89bae36e7ce159187dece7800b78831288f1913e9ae8cf8a878da5388232d2049740f6f4a43ec4b43b8ad1beb55f919f45eb9a577adb4a2a6eacb27b25fc + languageName: node + linkType: hard + "@solana/addresses@npm:^2.0.0": version: 2.0.0 resolution: "@solana/addresses@npm:2.0.0" @@ -5708,6 +5954,13 @@ __metadata: languageName: node linkType: hard +"@tootallnate/once@npm:1": + version: 1.1.2 + resolution: "@tootallnate/once@npm:1.1.2" + checksum: 10/e1fb1bbbc12089a0cb9433dc290f97bddd062deadb6178ce9bcb93bb7c1aecde5e60184bc7065aec42fe1663622a213493c48bbd4972d931aae48315f18e1be9 + languageName: node + linkType: hard + "@tootallnate/once@npm:2": version: 2.0.0 resolution: "@tootallnate/once@npm:2.0.0" @@ -5814,7 +6067,7 @@ __metadata: languageName: node linkType: hard -"@types/babel__core@npm:^7.1.14": +"@types/babel__core@npm:^7.0.0, @types/babel__core@npm:^7.1.14": version: 7.20.5 resolution: "@types/babel__core@npm:7.20.5" dependencies: @@ -5855,6 +6108,15 @@ __metadata: languageName: node linkType: hard +"@types/babel__traverse@npm:^7.0.4": + version: 7.28.0 + resolution: "@types/babel__traverse@npm:7.28.0" + dependencies: + "@babel/types": "npm:^7.28.2" + checksum: 10/371c5e1b40399ef17570e630b2943617b84fafde2860a56f0ebc113d8edb1d0534ade0175af89eda1ae35160903c33057ed42457e165d4aa287fedab2c82abcf + languageName: node + linkType: hard + "@types/bn.js@npm:*, @types/bn.js@npm:^5.1.0, @types/bn.js@npm:^5.1.5": version: 5.1.6 resolution: "@types/bn.js@npm:5.1.6" @@ -5923,7 +6185,7 @@ __metadata: languageName: node linkType: hard -"@types/graceful-fs@npm:^4.1.3": +"@types/graceful-fs@npm:^4.1.2, @types/graceful-fs@npm:^4.1.3": version: 4.1.9 resolution: "@types/graceful-fs@npm:4.1.9" dependencies: @@ -5976,6 +6238,16 @@ __metadata: languageName: node linkType: hard +"@types/jest@npm:^27.5.2": + version: 27.5.2 + resolution: "@types/jest@npm:27.5.2" + dependencies: + jest-matcher-utils: "npm:^27.0.0" + pretty-format: "npm:^27.0.0" + checksum: 10/8608696fbdea81bc9a600d1c5aeb290063357eaa55c0174e7db15087c4f483113b35f8b4c4ae364d2632cfed15a4dd674786254826b946c896de5612c8cb1a26 + languageName: node + linkType: hard + "@types/jsdom@npm:^20.0.0": version: 20.0.1 resolution: "@types/jsdom@npm:20.0.1" @@ -6099,6 +6371,13 @@ __metadata: languageName: node linkType: hard +"@types/prettier@npm:^2.1.5": + version: 2.7.3 + resolution: "@types/prettier@npm:2.7.3" + checksum: 10/cda84c19acc3bf327545b1ce71114a7d08efbd67b5030b9e8277b347fa57b05178045f70debe1d363ff7efdae62f237260713aafc2d7217e06fc99b048a88497 + languageName: node + linkType: hard + "@types/punycode@npm:^2.1.0": version: 2.1.4 resolution: "@types/punycode@npm:2.1.4" @@ -6185,6 +6464,15 @@ __metadata: languageName: node linkType: hard +"@types/yargs@npm:^16.0.0": + version: 16.0.11 + resolution: "@types/yargs@npm:16.0.11" + dependencies: + "@types/yargs-parser": "npm:*" + checksum: 10/b083eb4e377a9488b67d5767053a3ef531c142478d04b227529db29f5f3ccc98bc555dbe842b47edadd9901cdae03ce0b75828abfd7e70f8db614b5eabf9db9f + languageName: node + linkType: hard + "@types/yargs@npm:^17.0.32, @types/yargs@npm:^17.0.8": version: 17.0.33 resolution: "@types/yargs@npm:17.0.33" @@ -6409,7 +6697,7 @@ __metadata: languageName: node linkType: hard -"abab@npm:^2.0.6": +"abab@npm:^2.0.3, abab@npm:^2.0.5, abab@npm:^2.0.6": version: 2.0.6 resolution: "abab@npm:2.0.6" checksum: 10/ebe95d7278999e605823fc515a3b05d689bc72e7f825536e73c95ebf621636874c6de1b749b3c4bf866b96ccd4b3a2802efa313d0e45ad51a413c8c73247db20 @@ -6442,6 +6730,16 @@ __metadata: languageName: node linkType: hard +"acorn-globals@npm:^6.0.0": + version: 6.0.0 + resolution: "acorn-globals@npm:6.0.0" + dependencies: + acorn: "npm:^7.1.1" + acorn-walk: "npm:^7.1.1" + checksum: 10/72d95e5b5e585f9acd019b993ab8bbba68bb3cbc9d9b5c1ebb3c2f1fe5981f11deababfb4949f48e6262f9c57878837f5958c0cca396f81023814680ca878042 + languageName: node + linkType: hard + "acorn-globals@npm:^7.0.0": version: 7.0.1 resolution: "acorn-globals@npm:7.0.1" @@ -6461,6 +6759,13 @@ __metadata: languageName: node linkType: hard +"acorn-walk@npm:^7.1.1": + version: 7.2.0 + resolution: "acorn-walk@npm:7.2.0" + checksum: 10/4d3e186f729474aed3bc3d0df44692f2010c726582655b20a23347bef650867655521c48ada444cb4fda241ee713dcb792da363ec74c6282fa884fb7144171bb + languageName: node + linkType: hard + "acorn-walk@npm:^8.0.2": version: 8.3.4 resolution: "acorn-walk@npm:8.3.4" @@ -6470,7 +6775,16 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.1.0, acorn@npm:^8.11.0, acorn@npm:^8.15.0, acorn@npm:^8.8.1": +"acorn@npm:^7.1.1": + version: 7.4.1 + resolution: "acorn@npm:7.4.1" + bin: + acorn: bin/acorn + checksum: 10/8be2a40714756d713dfb62544128adce3b7102c6eb94bc312af196c2cc4af76e5b93079bd66b05e9ca31b35a9b0ce12171d16bc55f366cafdb794fdab9d753ec + languageName: node + linkType: hard + +"acorn@npm:^8.1.0, acorn@npm:^8.11.0, acorn@npm:^8.15.0, acorn@npm:^8.2.4, acorn@npm:^8.8.1": version: 8.15.0 resolution: "acorn@npm:8.15.0" bin: @@ -6682,6 +6996,20 @@ __metadata: languageName: node linkType: hard +"async-function@npm:^1.0.0": + version: 1.0.0 + resolution: "async-function@npm:1.0.0" + checksum: 10/1a09379937d846f0ce7614e75071c12826945d4e417db634156bf0e4673c495989302f52186dfa9767a1d9181794554717badd193ca2bbab046ef1da741d8efd + languageName: node + linkType: hard + +"async-generator-function@npm:^1.0.0": + version: 1.0.0 + resolution: "async-generator-function@npm:1.0.0" + checksum: 10/3d49e7acbeee9e84537f4cb0e0f91893df8eba976759875ae8ee9e3d3c82f6ecdebdb347c2fad9926b92596d93cdfc78ecc988bcdf407e40433e8e8e6fe5d78e + languageName: node + linkType: hard + "async-mutex@npm:^0.3.1": version: 0.3.2 resolution: "async-mutex@npm:0.3.2" @@ -6725,6 +7053,24 @@ __metadata: languageName: node linkType: hard +"babel-jest@npm:^27.5.1": + version: 27.5.1 + resolution: "babel-jest@npm:27.5.1" + dependencies: + "@jest/transform": "npm:^27.5.1" + "@jest/types": "npm:^27.5.1" + "@types/babel__core": "npm:^7.1.14" + babel-plugin-istanbul: "npm:^6.1.1" + babel-preset-jest: "npm:^27.5.1" + chalk: "npm:^4.0.0" + graceful-fs: "npm:^4.2.9" + slash: "npm:^3.0.0" + peerDependencies: + "@babel/core": ^7.8.0 + checksum: 10/d032823796072b3c269edaa623dd7fe6ecf2f72aff5b003066e7b16ad0ec4068ed04f3f569237183161d28b638936121975014bcb26ae539e669f2bdad5babe6 + languageName: node + linkType: hard + "babel-jest@npm:^29.7.0": version: 29.7.0 resolution: "babel-jest@npm:29.7.0" @@ -6755,6 +7101,18 @@ __metadata: languageName: node linkType: hard +"babel-plugin-jest-hoist@npm:^27.5.1": + version: 27.5.1 + resolution: "babel-plugin-jest-hoist@npm:27.5.1" + dependencies: + "@babel/template": "npm:^7.3.3" + "@babel/types": "npm:^7.3.3" + "@types/babel__core": "npm:^7.0.0" + "@types/babel__traverse": "npm:^7.0.6" + checksum: 10/9e334903433fd92ef9a65ea5c61f7d786238704b1327d9ca227ef40ef7142fba2bb8219bcb9b2d56eaf36ecfbcc50aa1e177db64508438569e98cfd67cce5043 + languageName: node + linkType: hard + "babel-plugin-jest-hoist@npm:^29.6.3": version: 29.6.3 resolution: "babel-plugin-jest-hoist@npm:29.6.3" @@ -6792,6 +7150,18 @@ __metadata: languageName: node linkType: hard +"babel-preset-jest@npm:^27.5.1": + version: 27.5.1 + resolution: "babel-preset-jest@npm:27.5.1" + dependencies: + babel-plugin-jest-hoist: "npm:^27.5.1" + babel-preset-current-node-syntax: "npm:^1.0.0" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10/251bcea11c18fd9672fec104eadb45b43f117ceeb326fa7345ced778d4c1feab29343cd7a87a1dcfae4997d6c851a8b386d7f7213792da6e23b74f4443a8976d + languageName: node + linkType: hard + "babel-preset-jest@npm:^29.6.3": version: 29.6.3 resolution: "babel-preset-jest@npm:29.6.3" @@ -6992,6 +7362,13 @@ __metadata: languageName: node linkType: hard +"browser-process-hrtime@npm:^1.0.0": + version: 1.0.0 + resolution: "browser-process-hrtime@npm:1.0.0" + checksum: 10/e30f868cdb770b1201afb714ad1575dd86366b6e861900884665fb627109b3cc757c40067d3bfee1ff2a29c835257ea30725a8018a9afd02ac1c24b408b1e45f + languageName: node + linkType: hard + "browserify-aes@npm:^1.2.0": version: 1.2.0 resolution: "browserify-aes@npm:1.2.0" @@ -7020,7 +7397,7 @@ __metadata: languageName: node linkType: hard -"bs-logger@npm:^0.2.6": +"bs-logger@npm:0.x, bs-logger@npm:^0.2.6": version: 0.2.6 resolution: "bs-logger@npm:0.2.6" dependencies: @@ -7455,6 +7832,13 @@ __metadata: languageName: node linkType: hard +"convert-source-map@npm:^1.4.0, convert-source-map@npm:^1.6.0": + version: 1.9.0 + resolution: "convert-source-map@npm:1.9.0" + checksum: 10/dc55a1f28ddd0e9485ef13565f8f756b342f9a46c4ae18b843fe3c30c675d058d6a4823eff86d472f187b176f0adf51ea7b69ea38be34be4a63cbbf91b0593c8 + languageName: node + linkType: hard + "convert-source-map@npm:^2.0.0": version: 2.0.0 resolution: "convert-source-map@npm:2.0.0" @@ -7576,6 +7960,13 @@ __metadata: languageName: node linkType: hard +"cssom@npm:^0.4.4": + version: 0.4.4 + resolution: "cssom@npm:0.4.4" + checksum: 10/6302c5f9b33a15f5430349f91553dd370f60707b1f2bb2c21954abe307b701d6095da134679fd0891a7814bc98061e1639bd0562d8f70c2dc529918111be8d2b + languageName: node + linkType: hard + "cssom@npm:^0.5.0": version: 0.5.0 resolution: "cssom@npm:0.5.0" @@ -7599,6 +7990,17 @@ __metadata: languageName: node linkType: hard +"data-urls@npm:^2.0.0": + version: 2.0.0 + resolution: "data-urls@npm:2.0.0" + dependencies: + abab: "npm:^2.0.3" + whatwg-mimetype: "npm:^2.3.0" + whatwg-url: "npm:^8.0.0" + checksum: 10/97caf828aac25e25e04ba6869db0f99c75e6859bb5b424ada28d3e7841941ebf08ddff3c1b1bb4585986bd507a5d54c2a716853ea6cb98af877400e637393e71 + languageName: node + linkType: hard + "data-urls@npm:^3.0.2": version: 3.0.2 resolution: "data-urls@npm:3.0.2" @@ -7657,13 +8059,20 @@ __metadata: languageName: node linkType: hard -"decimal.js@npm:^10.4.2": +"decimal.js@npm:^10.2.1, decimal.js@npm:^10.4.2": version: 10.6.0 resolution: "decimal.js@npm:10.6.0" checksum: 10/c0d45842d47c311d11b38ce7ccc911121953d4df3ebb1465d92b31970eb4f6738a065426a06094af59bee4b0d64e42e7c8984abd57b6767c64ea90cf90bb4a69 languageName: node linkType: hard +"dedent@npm:^0.7.0": + version: 0.7.0 + resolution: "dedent@npm:0.7.0" + checksum: 10/87de191050d9a40dd70cad01159a0bcf05ecb59750951242070b6abf9569088684880d00ba92a955b4058804f16eeaf91d604f283929b4f614d181cd7ae633d2 + languageName: node + linkType: hard + "dedent@npm:^1.0.0": version: 1.7.1 resolution: "dedent@npm:1.7.1" @@ -7835,6 +8244,13 @@ __metadata: languageName: node linkType: hard +"diff-sequences@npm:^27.5.1": + version: 27.5.1 + resolution: "diff-sequences@npm:27.5.1" + checksum: 10/34d852a13eb82735c39944a050613f952038614ce324256e1c3544948fa090f1ca7f329a4f1f57c31fe7ac982c17068d8915b633e300f040b97708c81ceb26cd + languageName: node + linkType: hard + "diff-sequences@npm:^29.6.3": version: 29.6.3 resolution: "diff-sequences@npm:29.6.3" @@ -7842,6 +8258,13 @@ __metadata: languageName: node linkType: hard +"diff@npm:^4.0.2": + version: 4.0.4 + resolution: "diff@npm:4.0.4" + checksum: 10/5019b3f5ae124ea9e95137119e1a83a59c252c75ddac873cc967832fd7a834570a58a4d58b941bdbd07832ebf98dcb232b27c561b7f5584357da6dae59bcac62 + languageName: node + linkType: hard + "diff@npm:^5.0.0": version: 5.2.0 resolution: "diff@npm:5.2.0" @@ -7867,6 +8290,15 @@ __metadata: languageName: node linkType: hard +"domexception@npm:^2.0.1": + version: 2.0.1 + resolution: "domexception@npm:2.0.1" + dependencies: + webidl-conversions: "npm:^5.0.0" + checksum: 10/d638e9cb05c52999f1b2eb87c374b03311ea5b1d69c2f875bc92da73e17db60c12142b45c950228642ff7f845c536b65305483350d080df59003a653da80b691 + languageName: node + linkType: hard + "domexception@npm:^4.0.0": version: 4.0.0 resolution: "domexception@npm:4.0.0" @@ -7939,6 +8371,13 @@ __metadata: languageName: node linkType: hard +"emittery@npm:^0.8.1": + version: 0.8.1 + resolution: "emittery@npm:0.8.1" + checksum: 10/3b882c0bdc3121b4e92b85315f87da0db8e965766d6c7ff70a8f45e0c38ed49d561936650afa32759d8fb320a458bc9e12631799a0a276e9e8a960ae16c1f6f1 + languageName: node + linkType: hard + "emoji-regex@npm:^8.0.0": version: 8.0.0 resolution: "emoji-regex@npm:8.0.0" @@ -8053,6 +8492,18 @@ __metadata: languageName: node linkType: hard +"es-set-tostringtag@npm:^2.1.0": + version: 2.1.0 + resolution: "es-set-tostringtag@npm:2.1.0" + dependencies: + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.6" + has-tostringtag: "npm:^1.0.2" + hasown: "npm:^2.0.2" + checksum: 10/86814bf8afbcd8966653f731415888019d4bc4aca6b6c354132a7a75bb87566751e320369654a101d23a91c87a85c79b178bcf40332839bd347aff437c4fb65f + languageName: node + linkType: hard + "esbuild@npm:~0.25.0": version: 0.25.9 resolution: "esbuild@npm:0.25.9" @@ -8727,6 +9178,18 @@ __metadata: languageName: node linkType: hard +"expect@npm:^27.5.1": + version: 27.5.1 + resolution: "expect@npm:27.5.1" + dependencies: + "@jest/types": "npm:^27.5.1" + jest-get-type: "npm:^27.5.1" + jest-matcher-utils: "npm:^27.5.1" + jest-message-util: "npm:^27.5.1" + checksum: 10/65152be11e791361bb8f74b2516b6ba83021ac4a280b16575340a7dbb72be7fb51b021119a3f40f309a36b375cfb05d4854d5d7af3c53a293a342afc7f86bdaa + languageName: node + linkType: hard + "expect@npm:^29.0.0, expect@npm:^29.7.0": version: 29.7.0 resolution: "expect@npm:29.7.0" @@ -9078,6 +9541,19 @@ __metadata: languageName: node linkType: hard +"form-data@npm:^3.0.0": + version: 3.0.4 + resolution: "form-data@npm:3.0.4" + dependencies: + asynckit: "npm:^0.4.0" + combined-stream: "npm:^1.0.8" + es-set-tostringtag: "npm:^2.1.0" + hasown: "npm:^2.0.2" + mime-types: "npm:^2.1.35" + checksum: 10/68e4598e55cb193ef80304bff4d7513bf81ed4116d57b29c6c9a4c28c6f7ce57d46ddd60ba1a80aadf26703a722551e660bca2acaf9212d8b6e1f2e180d9e668 + languageName: node + linkType: hard + "form-data@npm:^4.0.0": version: 4.0.0 resolution: "form-data@npm:4.0.0" @@ -9176,6 +9652,13 @@ __metadata: languageName: node linkType: hard +"generator-function@npm:^2.0.0": + version: 2.0.1 + resolution: "generator-function@npm:2.0.1" + checksum: 10/eb7e7eb896c5433f3d40982b2ccacdb3dd990dd3499f14040e002b5d54572476513be8a2e6f9609f6e41ab29f2c4469307611ddbfc37ff4e46b765c326663805 + languageName: node + linkType: hard + "gensync@npm:^1.0.0-beta.2": version: 1.0.0-beta.2 resolution: "gensync@npm:1.0.0-beta.2" @@ -9208,14 +9691,35 @@ __metadata: languageName: node linkType: hard -"get-npm-tarball-url@npm:^2.0.3": - version: 2.1.0 - resolution: "get-npm-tarball-url@npm:2.1.0" - checksum: 10/02b96993ad5a04cbd0ef0577ac3cc9e2e78a7c60db6bb5e6c8fe78950fc1fc3d093314987629a2fda3083228d91a93670bde321767ca2cf89ce7f463c9e44071 - languageName: node - linkType: hard - -"get-package-type@npm:^0.1.0": +"get-intrinsic@npm:^1.2.6": + version: 1.3.1 + resolution: "get-intrinsic@npm:1.3.1" + dependencies: + async-function: "npm:^1.0.0" + async-generator-function: "npm:^1.0.0" + call-bind-apply-helpers: "npm:^1.0.2" + es-define-property: "npm:^1.0.1" + es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.1.1" + function-bind: "npm:^1.1.2" + generator-function: "npm:^2.0.0" + get-proto: "npm:^1.0.1" + gopd: "npm:^1.2.0" + has-symbols: "npm:^1.1.0" + hasown: "npm:^2.0.2" + math-intrinsics: "npm:^1.1.0" + checksum: 10/bb579dda84caa4a3a41611bdd483dade7f00f246f2a7992eb143c5861155290df3fdb48a8406efa3dfb0b434e2c8fafa4eebd469e409d0439247f85fc3fa2cc1 + languageName: node + linkType: hard + +"get-npm-tarball-url@npm:^2.0.3": + version: 2.1.0 + resolution: "get-npm-tarball-url@npm:2.1.0" + checksum: 10/02b96993ad5a04cbd0ef0577ac3cc9e2e78a7c60db6bb5e6c8fe78950fc1fc3d093314987629a2fda3083228d91a93670bde321767ca2cf89ce7f463c9e44071 + languageName: node + linkType: hard + +"get-package-type@npm:^0.1.0": version: 0.1.0 resolution: "get-package-type@npm:0.1.0" checksum: 10/bba0811116d11e56d702682ddef7c73ba3481f114590e705fc549f4d868972263896af313c57a25c076e3c0d567e11d919a64ba1b30c879be985fc9d44f96148 @@ -9303,7 +9807,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.7": +"glob@npm:^7.1.1, glob@npm:^7.1.2, glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.7": version: 7.2.3 resolution: "glob@npm:7.2.3" dependencies: @@ -9437,13 +9941,22 @@ __metadata: languageName: node linkType: hard -"has-symbols@npm:^1.1.0": +"has-symbols@npm:^1.0.3, has-symbols@npm:^1.1.0": version: 1.1.0 resolution: "has-symbols@npm:1.1.0" checksum: 10/959385c98696ebbca51e7534e0dc723ada325efa3475350951363cce216d27373e0259b63edb599f72eb94d6cde8577b4b2375f080b303947e560f85692834fa languageName: node linkType: hard +"has-tostringtag@npm:^1.0.2": + version: 1.0.2 + resolution: "has-tostringtag@npm:1.0.2" + dependencies: + has-symbols: "npm:^1.0.3" + checksum: 10/c74c5f5ceee3c8a5b8bc37719840dc3749f5b0306d818974141dda2471a1a2ca6c8e46b9d6ac222c5345df7a901c9b6f350b1e6d62763fec877e26609a401bfe + languageName: node + linkType: hard + "hash-base@npm:^3.0.0": version: 3.1.0 resolution: "hash-base@npm:3.1.0" @@ -9519,6 +10032,15 @@ __metadata: languageName: node linkType: hard +"html-encoding-sniffer@npm:^2.0.1": + version: 2.0.1 + resolution: "html-encoding-sniffer@npm:2.0.1" + dependencies: + whatwg-encoding: "npm:^1.0.5" + checksum: 10/70365109cad69ee60376715fe0a56dd9ebb081327bf155cda93b2c276976c79cbedee2b988de6b0aefd0671a5d70597a35796e6e7d91feeb2c0aba46df059630 + languageName: node + linkType: hard + "html-encoding-sniffer@npm:^3.0.0": version: 3.0.0 resolution: "html-encoding-sniffer@npm:3.0.0" @@ -9562,6 +10084,17 @@ __metadata: languageName: node linkType: hard +"http-proxy-agent@npm:^4.0.1": + version: 4.0.1 + resolution: "http-proxy-agent@npm:4.0.1" + dependencies: + "@tootallnate/once": "npm:1" + agent-base: "npm:6" + debug: "npm:4" + checksum: 10/2e17f5519f2f2740b236d1d14911ea4be170c67419dc15b05ea9a860a22c5d9c6ff4da270972117067cc2cefeba9df5f7cd5e7818fdc6ae52b6acf2a533e5fdd + languageName: node + linkType: hard + "http-proxy-agent@npm:^5.0.0": version: 5.0.0 resolution: "http-proxy-agent@npm:5.0.0" @@ -9583,7 +10116,7 @@ __metadata: languageName: node linkType: hard -"https-proxy-agent@npm:^5.0.1": +"https-proxy-agent@npm:^5.0.0, https-proxy-agent@npm:^5.0.1": version: 5.0.1 resolution: "https-proxy-agent@npm:5.0.1" dependencies: @@ -9919,6 +10452,13 @@ __metadata: languageName: node linkType: hard +"is-typedarray@npm:^1.0.0": + version: 1.0.0 + resolution: "is-typedarray@npm:1.0.0" + checksum: 10/4b433bfb0f9026f079f4eb3fbaa4ed2de17c9995c3a0b5c800bec40799b4b2a8b4e051b1ada77749deb9ded4ae52fe2096973f3a93ff83df1a5a7184a669478c + languageName: node + linkType: hard + "is-unicode-supported@npm:^0.1.0": version: 0.1.0 resolution: "is-unicode-supported@npm:0.1.0" @@ -9949,6 +10489,13 @@ __metadata: languageName: node linkType: hard +"isarray@npm:0.0.1": + version: 0.0.1 + resolution: "isarray@npm:0.0.1" + checksum: 10/49191f1425681df4a18c2f0f93db3adb85573bcdd6a4482539d98eac9e705d8961317b01175627e860516a2fc45f8f9302db26e5a380a97a520e272e2a40a8d4 + languageName: node + linkType: hard + "isarray@npm:~1.0.0": version: 1.0.0 resolution: "isarray@npm:1.0.0" @@ -9987,7 +10534,7 @@ __metadata: languageName: node linkType: hard -"istanbul-lib-instrument@npm:^5.0.4": +"istanbul-lib-instrument@npm:^5.0.4, istanbul-lib-instrument@npm:^5.1.0": version: 5.2.1 resolution: "istanbul-lib-instrument@npm:5.2.1" dependencies: @@ -10058,6 +10605,17 @@ __metadata: languageName: node linkType: hard +"jest-changed-files@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-changed-files@npm:27.5.1" + dependencies: + "@jest/types": "npm:^27.5.1" + execa: "npm:^5.0.0" + throat: "npm:^6.0.1" + checksum: 10/fad21687f899e527bc23b3cabda1b1fa74acb8e17e81bca4d6ca10ab83ebf1d7555f38ba66dda148f97c45b816f941aa4694a09ed0d16a4d7fe3216abf1a222f + languageName: node + linkType: hard + "jest-changed-files@npm:^29.7.0": version: 29.7.0 resolution: "jest-changed-files@npm:29.7.0" @@ -10069,6 +10627,33 @@ __metadata: languageName: node linkType: hard +"jest-circus@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-circus@npm:27.5.1" + dependencies: + "@jest/environment": "npm:^27.5.1" + "@jest/test-result": "npm:^27.5.1" + "@jest/types": "npm:^27.5.1" + "@types/node": "npm:*" + chalk: "npm:^4.0.0" + co: "npm:^4.6.0" + dedent: "npm:^0.7.0" + expect: "npm:^27.5.1" + is-generator-fn: "npm:^2.0.0" + jest-each: "npm:^27.5.1" + jest-matcher-utils: "npm:^27.5.1" + jest-message-util: "npm:^27.5.1" + jest-runtime: "npm:^27.5.1" + jest-snapshot: "npm:^27.5.1" + jest-util: "npm:^27.5.1" + pretty-format: "npm:^27.5.1" + slash: "npm:^3.0.0" + stack-utils: "npm:^2.0.3" + throat: "npm:^6.0.1" + checksum: 10/cf8502d2c7669a89d6d9c309842a6bae1b336335f9a108b0ba3d555dcc635c6cc119d28627a5df455215a8bb04bdcdf18b1fee3441aca39c78c8b10053cd33f7 + languageName: node + linkType: hard + "jest-circus@npm:^29.7.0": version: 29.7.0 resolution: "jest-circus@npm:29.7.0" @@ -10097,6 +10682,33 @@ __metadata: languageName: node linkType: hard +"jest-cli@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-cli@npm:27.5.1" + dependencies: + "@jest/core": "npm:^27.5.1" + "@jest/test-result": "npm:^27.5.1" + "@jest/types": "npm:^27.5.1" + chalk: "npm:^4.0.0" + exit: "npm:^0.1.2" + graceful-fs: "npm:^4.2.9" + import-local: "npm:^3.0.2" + jest-config: "npm:^27.5.1" + jest-util: "npm:^27.5.1" + jest-validate: "npm:^27.5.1" + prompts: "npm:^2.0.1" + yargs: "npm:^16.2.0" + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + bin: + jest: bin/jest.js + checksum: 10/527be160786a14f541b3f75e6241da1bd9ba51894fc9f2ba6466dba7f6ffd3a03de02b40d172ad1d29edc725847f7dd4f6dbf71d304d2364b075ec81c9a53224 + languageName: node + linkType: hard + "jest-cli@npm:^29.7.0": version: 29.7.0 resolution: "jest-cli@npm:29.7.0" @@ -10123,6 +10735,43 @@ __metadata: languageName: node linkType: hard +"jest-config@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-config@npm:27.5.1" + dependencies: + "@babel/core": "npm:^7.8.0" + "@jest/test-sequencer": "npm:^27.5.1" + "@jest/types": "npm:^27.5.1" + babel-jest: "npm:^27.5.1" + chalk: "npm:^4.0.0" + ci-info: "npm:^3.2.0" + deepmerge: "npm:^4.2.2" + glob: "npm:^7.1.1" + graceful-fs: "npm:^4.2.9" + jest-circus: "npm:^27.5.1" + jest-environment-jsdom: "npm:^27.5.1" + jest-environment-node: "npm:^27.5.1" + jest-get-type: "npm:^27.5.1" + jest-jasmine2: "npm:^27.5.1" + jest-regex-util: "npm:^27.5.1" + jest-resolve: "npm:^27.5.1" + jest-runner: "npm:^27.5.1" + jest-util: "npm:^27.5.1" + jest-validate: "npm:^27.5.1" + micromatch: "npm:^4.0.4" + parse-json: "npm:^5.2.0" + pretty-format: "npm:^27.5.1" + slash: "npm:^3.0.0" + strip-json-comments: "npm:^3.1.1" + peerDependencies: + ts-node: ">=9.0.0" + peerDependenciesMeta: + ts-node: + optional: true + checksum: 10/63bc2dce50289ff921debedab766daa5122129671c77a9f4137d153a27b29ef77725db15d4809553b687c83495cd7ffefc8eadfd8dfa940d7ea878de57f428c2 + languageName: node + linkType: hard + "jest-config@npm:^29.7.0": version: 29.7.0 resolution: "jest-config@npm:29.7.0" @@ -10161,6 +10810,18 @@ __metadata: languageName: node linkType: hard +"jest-diff@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-diff@npm:27.5.1" + dependencies: + chalk: "npm:^4.0.0" + diff-sequences: "npm:^27.5.1" + jest-get-type: "npm:^27.5.1" + pretty-format: "npm:^27.5.1" + checksum: 10/af454f30f33af625832bdb02614e188a41e33ce79086b43f95dbcc515274dd36bf8443b8d0299e22c2416e7591da4321e6bc7f2b0aef56471d1133c6b6833221 + languageName: node + linkType: hard + "jest-diff@npm:^29.0.3, jest-diff@npm:^29.7.0": version: 29.7.0 resolution: "jest-diff@npm:29.7.0" @@ -10173,6 +10834,15 @@ __metadata: languageName: node linkType: hard +"jest-docblock@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-docblock@npm:27.5.1" + dependencies: + detect-newline: "npm:^3.0.0" + checksum: 10/65c765c5418986313685b7c49dcd844cd3bc281807a35f778d6ba479246b6ea070cdd98384582a9aed1a0d3ebf94b7fb14a33df5975aaae2eb20dc00281731f4 + languageName: node + linkType: hard + "jest-docblock@npm:^29.7.0": version: 29.7.0 resolution: "jest-docblock@npm:29.7.0" @@ -10182,6 +10852,19 @@ __metadata: languageName: node linkType: hard +"jest-each@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-each@npm:27.5.1" + dependencies: + "@jest/types": "npm:^27.5.1" + chalk: "npm:^4.0.0" + jest-get-type: "npm:^27.5.1" + jest-util: "npm:^27.5.1" + pretty-format: "npm:^27.5.1" + checksum: 10/d73e3c7bbcd3a073e9fa29bd1f200bb9757cbcc568460c1d0971fc21924800f2d3e421219a85e20c54ea2a0129d2da9e2dfc266b6014244c5901f3ca2de7a99e + languageName: node + linkType: hard + "jest-each@npm:^29.7.0": version: 29.7.0 resolution: "jest-each@npm:29.7.0" @@ -10195,6 +10878,21 @@ __metadata: languageName: node linkType: hard +"jest-environment-jsdom@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-environment-jsdom@npm:27.5.1" + dependencies: + "@jest/environment": "npm:^27.5.1" + "@jest/fake-timers": "npm:^27.5.1" + "@jest/types": "npm:^27.5.1" + "@types/node": "npm:*" + jest-mock: "npm:^27.5.1" + jest-util: "npm:^27.5.1" + jsdom: "npm:^16.6.0" + checksum: 10/bc104aef7d7530d0740402aa84ac812138b6d1e51fe58adecce679f82b99340ddab73e5ec68fa079f33f50c9ddec9728fc9f0ddcca2ad6f0b351eed2762cc555 + languageName: node + linkType: hard + "jest-environment-jsdom@npm:^29.7.0": version: 29.7.0 resolution: "jest-environment-jsdom@npm:29.7.0" @@ -10216,6 +10914,20 @@ __metadata: languageName: node linkType: hard +"jest-environment-node@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-environment-node@npm:27.5.1" + dependencies: + "@jest/environment": "npm:^27.5.1" + "@jest/fake-timers": "npm:^27.5.1" + "@jest/types": "npm:^27.5.1" + "@types/node": "npm:*" + jest-mock: "npm:^27.5.1" + jest-util: "npm:^27.5.1" + checksum: 10/0f988330c4f3eec092e3fb37ea753b0c6f702e83cd8f4d770af9c2bf964a70bc45fbd34ec6fdb6d71ce98a778d9f54afd673e63f222e4667fff289e8069dba39 + languageName: node + linkType: hard + "jest-environment-node@npm:^29.7.0": version: 29.7.0 resolution: "jest-environment-node@npm:29.7.0" @@ -10230,6 +10942,13 @@ __metadata: languageName: node linkType: hard +"jest-get-type@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-get-type@npm:27.5.1" + checksum: 10/63064ab70195c21007d897c1157bf88ff94a790824a10f8c890392e7d17eda9c3900513cb291ca1c8d5722cad79169764e9a1279f7c8a9c4cd6e9109ff04bbc0 + languageName: node + linkType: hard + "jest-get-type@npm:^29.6.3": version: 29.6.3 resolution: "jest-get-type@npm:29.6.3" @@ -10237,6 +10956,30 @@ __metadata: languageName: node linkType: hard +"jest-haste-map@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-haste-map@npm:27.5.1" + dependencies: + "@jest/types": "npm:^27.5.1" + "@types/graceful-fs": "npm:^4.1.2" + "@types/node": "npm:*" + anymatch: "npm:^3.0.3" + fb-watchman: "npm:^2.0.0" + fsevents: "npm:^2.3.2" + graceful-fs: "npm:^4.2.9" + jest-regex-util: "npm:^27.5.1" + jest-serializer: "npm:^27.5.1" + jest-util: "npm:^27.5.1" + jest-worker: "npm:^27.5.1" + micromatch: "npm:^4.0.4" + walker: "npm:^1.0.7" + dependenciesMeta: + fsevents: + optional: true + checksum: 10/cbf42e4a3d2b6fc8ad64d732c1bb8a230fe25ad3df7f9f93e8af2950691ef9a5241a9d48c5c88e365744a7467b8cb00ab21c01baee4ee0c2b62acc657782545f + languageName: node + linkType: hard + "jest-haste-map@npm:^29.7.0": version: 29.7.0 resolution: "jest-haste-map@npm:29.7.0" @@ -10273,6 +11016,41 @@ __metadata: languageName: node linkType: hard +"jest-jasmine2@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-jasmine2@npm:27.5.1" + dependencies: + "@jest/environment": "npm:^27.5.1" + "@jest/source-map": "npm:^27.5.1" + "@jest/test-result": "npm:^27.5.1" + "@jest/types": "npm:^27.5.1" + "@types/node": "npm:*" + chalk: "npm:^4.0.0" + co: "npm:^4.6.0" + expect: "npm:^27.5.1" + is-generator-fn: "npm:^2.0.0" + jest-each: "npm:^27.5.1" + jest-matcher-utils: "npm:^27.5.1" + jest-message-util: "npm:^27.5.1" + jest-runtime: "npm:^27.5.1" + jest-snapshot: "npm:^27.5.1" + jest-util: "npm:^27.5.1" + pretty-format: "npm:^27.5.1" + throat: "npm:^6.0.1" + checksum: 10/052d3c99c36295564a6688ae7e66cfd59997ca9589ccaaa2551d344d84699816a6b8c7bebf3a5f7bcdf691a07f7065c61f4a0770b810e5d887acd21f80a06304 + languageName: node + linkType: hard + +"jest-leak-detector@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-leak-detector@npm:27.5.1" + dependencies: + jest-get-type: "npm:^27.5.1" + pretty-format: "npm:^27.5.1" + checksum: 10/5c9689060960567ddaf16c570d87afa760a461885765d2c71ef4f4857bbc3af1482c34e3cce88e50beefde1bf35e33530b020480752057a7e3dbb1ca0bae359f + languageName: node + linkType: hard + "jest-leak-detector@npm:^29.7.0": version: 29.7.0 resolution: "jest-leak-detector@npm:29.7.0" @@ -10283,6 +11061,18 @@ __metadata: languageName: node linkType: hard +"jest-matcher-utils@npm:^27.0.0, jest-matcher-utils@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-matcher-utils@npm:27.5.1" + dependencies: + chalk: "npm:^4.0.0" + jest-diff: "npm:^27.5.1" + jest-get-type: "npm:^27.5.1" + pretty-format: "npm:^27.5.1" + checksum: 10/037f99878a0515581d7728ed3aed03707810f4da5a1c7ffb9d68a2c6c3180851a6ec40b559af37fbe891dde3ba12552b19e47b8188a27b6c5a53376be6907f32 + languageName: node + linkType: hard + "jest-matcher-utils@npm:^29.7.0": version: 29.7.0 resolution: "jest-matcher-utils@npm:29.7.0" @@ -10295,6 +11085,23 @@ __metadata: languageName: node linkType: hard +"jest-message-util@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-message-util@npm:27.5.1" + dependencies: + "@babel/code-frame": "npm:^7.12.13" + "@jest/types": "npm:^27.5.1" + "@types/stack-utils": "npm:^2.0.0" + chalk: "npm:^4.0.0" + graceful-fs: "npm:^4.2.9" + micromatch: "npm:^4.0.4" + pretty-format: "npm:^27.5.1" + slash: "npm:^3.0.0" + stack-utils: "npm:^2.0.3" + checksum: 10/8fbf39dc25a7ef328dab22efcb3b198cbc788e309bc93e39fdb42b5541dba201c76acf47df476a4ee3d3fc6a6898e77bfc02677c198a98af91db1af0a435ade6 + languageName: node + linkType: hard + "jest-message-util@npm:^29.7.0": version: 29.7.0 resolution: "jest-message-util@npm:29.7.0" @@ -10312,6 +11119,16 @@ __metadata: languageName: node linkType: hard +"jest-mock@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-mock@npm:27.5.1" + dependencies: + "@jest/types": "npm:^27.5.1" + "@types/node": "npm:*" + checksum: 10/be9a8777801659227d3bb85317a3aca617542779a290a6a45c9addec8bda29f494a524cb4af96c82b825ecb02171e320dfbfde3e3d9218672f9e38c9fac118f4 + languageName: node + linkType: hard + "jest-mock@npm:^29.7.0": version: 29.7.0 resolution: "jest-mock@npm:29.7.0" @@ -10335,6 +11152,13 @@ __metadata: languageName: node linkType: hard +"jest-regex-util@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-regex-util@npm:27.5.1" + checksum: 10/d45ca7a9543616a34f7f3079337439cf07566e677a096472baa2810e274b9808b76767c97b0a4029b8a5b82b9d256dee28ef9ad4138b2b9e5933f6fac106c418 + languageName: node + linkType: hard + "jest-regex-util@npm:^29.6.3": version: 29.6.3 resolution: "jest-regex-util@npm:29.6.3" @@ -10342,6 +11166,17 @@ __metadata: languageName: node linkType: hard +"jest-resolve-dependencies@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-resolve-dependencies@npm:27.5.1" + dependencies: + "@jest/types": "npm:^27.5.1" + jest-regex-util: "npm:^27.5.1" + jest-snapshot: "npm:^27.5.1" + checksum: 10/c67af97afad1da88f5530317c732bbd1262d1225f6cd7f4e4740a5db48f90ab0bd8564738ac70d1a43934894f9aef62205c1b8f8ee89e5c7a737e6a121ee4c25 + languageName: node + linkType: hard + "jest-resolve-dependencies@npm:^29.7.0": version: 29.7.0 resolution: "jest-resolve-dependencies@npm:29.7.0" @@ -10352,6 +11187,24 @@ __metadata: languageName: node linkType: hard +"jest-resolve@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-resolve@npm:27.5.1" + dependencies: + "@jest/types": "npm:^27.5.1" + chalk: "npm:^4.0.0" + graceful-fs: "npm:^4.2.9" + jest-haste-map: "npm:^27.5.1" + jest-pnp-resolver: "npm:^1.2.2" + jest-util: "npm:^27.5.1" + jest-validate: "npm:^27.5.1" + resolve: "npm:^1.20.0" + resolve.exports: "npm:^1.1.0" + slash: "npm:^3.0.0" + checksum: 10/93659a9d5ec365a9f2fd3fcaa8f799e3bd090318c48890951ca4325e863f4eb778bb7f7e8d1d8495eda4c157ee771d93fb31f37364ce1a36a09f77f1089e52a1 + languageName: node + linkType: hard + "jest-resolve@npm:^29.7.0": version: 29.7.0 resolution: "jest-resolve@npm:29.7.0" @@ -10369,6 +11222,35 @@ __metadata: languageName: node linkType: hard +"jest-runner@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-runner@npm:27.5.1" + dependencies: + "@jest/console": "npm:^27.5.1" + "@jest/environment": "npm:^27.5.1" + "@jest/test-result": "npm:^27.5.1" + "@jest/transform": "npm:^27.5.1" + "@jest/types": "npm:^27.5.1" + "@types/node": "npm:*" + chalk: "npm:^4.0.0" + emittery: "npm:^0.8.1" + graceful-fs: "npm:^4.2.9" + jest-docblock: "npm:^27.5.1" + jest-environment-jsdom: "npm:^27.5.1" + jest-environment-node: "npm:^27.5.1" + jest-haste-map: "npm:^27.5.1" + jest-leak-detector: "npm:^27.5.1" + jest-message-util: "npm:^27.5.1" + jest-resolve: "npm:^27.5.1" + jest-runtime: "npm:^27.5.1" + jest-util: "npm:^27.5.1" + jest-worker: "npm:^27.5.1" + source-map-support: "npm:^0.5.6" + throat: "npm:^6.0.1" + checksum: 10/97bd741f442ebbcebfdb5e8389c0df645448d0b4b634e4128b3387d6fe432cf0f93feb0ecfc3842fed20a35c43c24460ed5dd89d7501ca9e2fdba65e5a4edf37 + languageName: node + linkType: hard + "jest-runner@npm:^29.7.0": version: 29.7.0 resolution: "jest-runner@npm:29.7.0" @@ -10398,6 +11280,36 @@ __metadata: languageName: node linkType: hard +"jest-runtime@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-runtime@npm:27.5.1" + dependencies: + "@jest/environment": "npm:^27.5.1" + "@jest/fake-timers": "npm:^27.5.1" + "@jest/globals": "npm:^27.5.1" + "@jest/source-map": "npm:^27.5.1" + "@jest/test-result": "npm:^27.5.1" + "@jest/transform": "npm:^27.5.1" + "@jest/types": "npm:^27.5.1" + chalk: "npm:^4.0.0" + cjs-module-lexer: "npm:^1.0.0" + collect-v8-coverage: "npm:^1.0.0" + execa: "npm:^5.0.0" + glob: "npm:^7.1.3" + graceful-fs: "npm:^4.2.9" + jest-haste-map: "npm:^27.5.1" + jest-message-util: "npm:^27.5.1" + jest-mock: "npm:^27.5.1" + jest-regex-util: "npm:^27.5.1" + jest-resolve: "npm:^27.5.1" + jest-snapshot: "npm:^27.5.1" + jest-util: "npm:^27.5.1" + slash: "npm:^3.0.0" + strip-bom: "npm:^4.0.0" + checksum: 10/cc6cdce5bee4bc02935a4671394e19962f3469eeb6e823442ca99e5670fd87f60ed64b7c7156ac13d2799fc44fe9bb806454a3f17c8342bd35e564b1a40e3920 + languageName: node + linkType: hard + "jest-runtime@npm:^29.7.0": version: 29.7.0 resolution: "jest-runtime@npm:29.7.0" @@ -10428,6 +11340,16 @@ __metadata: languageName: node linkType: hard +"jest-serializer@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-serializer@npm:27.5.1" + dependencies: + "@types/node": "npm:*" + graceful-fs: "npm:^4.2.9" + checksum: 10/803e03a552278610edc6753c0dd9fa5bb5cd3ca47414a7b2918106efb62b79fd5e9ae785d0a21f12a299fa599fea8acc1fa6dd41283328cee43962cf7df9bb44 + languageName: node + linkType: hard + "jest-silent-reporter@npm:^0.5.0": version: 0.5.0 resolution: "jest-silent-reporter@npm:0.5.0" @@ -10438,6 +11360,36 @@ __metadata: languageName: node linkType: hard +"jest-snapshot@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-snapshot@npm:27.5.1" + dependencies: + "@babel/core": "npm:^7.7.2" + "@babel/generator": "npm:^7.7.2" + "@babel/plugin-syntax-typescript": "npm:^7.7.2" + "@babel/traverse": "npm:^7.7.2" + "@babel/types": "npm:^7.0.0" + "@jest/transform": "npm:^27.5.1" + "@jest/types": "npm:^27.5.1" + "@types/babel__traverse": "npm:^7.0.4" + "@types/prettier": "npm:^2.1.5" + babel-preset-current-node-syntax: "npm:^1.0.0" + chalk: "npm:^4.0.0" + expect: "npm:^27.5.1" + graceful-fs: "npm:^4.2.9" + jest-diff: "npm:^27.5.1" + jest-get-type: "npm:^27.5.1" + jest-haste-map: "npm:^27.5.1" + jest-matcher-utils: "npm:^27.5.1" + jest-message-util: "npm:^27.5.1" + jest-util: "npm:^27.5.1" + natural-compare: "npm:^1.4.0" + pretty-format: "npm:^27.5.1" + semver: "npm:^7.3.2" + checksum: 10/01b2c70c56980f21fc299fa68a1d1e3a9612f06d2fcdd1cf60f636c3dd427b814efc5f15aacc567e0c3b28fd32129be4a10fca34555f358534fc88e5cee4ffbb + languageName: node + linkType: hard + "jest-snapshot@npm:^29.7.0": version: 29.7.0 resolution: "jest-snapshot@npm:29.7.0" @@ -10480,6 +11432,20 @@ __metadata: languageName: node linkType: hard +"jest-util@npm:^27.0.0, jest-util@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-util@npm:27.5.1" + dependencies: + "@jest/types": "npm:^27.5.1" + "@types/node": "npm:*" + chalk: "npm:^4.0.0" + ci-info: "npm:^3.2.0" + graceful-fs: "npm:^4.2.9" + picomatch: "npm:^2.2.3" + checksum: 10/ecc7da41769558e57dbde544141ffceb536ee53b663de1e002d4b86784cea500a10f9a7f02e8b804e517aa0e34d3145118734c7e8b5071f9f18a153ede5b062d + languageName: node + linkType: hard + "jest-util@npm:^29.7.0": version: 29.7.0 resolution: "jest-util@npm:29.7.0" @@ -10494,6 +11460,20 @@ __metadata: languageName: node linkType: hard +"jest-validate@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-validate@npm:27.5.1" + dependencies: + "@jest/types": "npm:^27.5.1" + camelcase: "npm:^6.2.0" + chalk: "npm:^4.0.0" + jest-get-type: "npm:^27.5.1" + leven: "npm:^3.1.0" + pretty-format: "npm:^27.5.1" + checksum: 10/1fc4d46ecead311a0362bb8ea7767718b682e3d73b65c2bf55cb33722c13bb340e52d20f35d7af38918f8655a78ebbedf3d8a9eaba4ac067883cef006fcf9197 + languageName: node + linkType: hard + "jest-validate@npm:^29.7.0": version: 29.7.0 resolution: "jest-validate@npm:29.7.0" @@ -10508,6 +11488,21 @@ __metadata: languageName: node linkType: hard +"jest-watcher@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-watcher@npm:27.5.1" + dependencies: + "@jest/test-result": "npm:^27.5.1" + "@jest/types": "npm:^27.5.1" + "@types/node": "npm:*" + ansi-escapes: "npm:^4.2.1" + chalk: "npm:^4.0.0" + jest-util: "npm:^27.5.1" + string-length: "npm:^4.0.1" + checksum: 10/2c2f6cb4256d5cf90c4ae2d8400d5a40399aea9152c85b8b04c3fe4cbecb65e188462de1267d134a42c69d2ddb13a6e50a8ea1aef809b1e4c8fff7a0019ca2c4 + languageName: node + linkType: hard + "jest-watcher@npm:^29.7.0": version: 29.7.0 resolution: "jest-watcher@npm:29.7.0" @@ -10533,6 +11528,17 @@ __metadata: languageName: node linkType: hard +"jest-worker@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-worker@npm:27.5.1" + dependencies: + "@types/node": "npm:*" + merge-stream: "npm:^2.0.0" + supports-color: "npm:^8.0.0" + checksum: 10/06c6e2a84591d9ede704d5022fc13791e8876e83397c89d481b0063332abbb64c0f01ef4ca7de520b35c7a1058556078d6bdc3631376f4e9ffb42316c1a8488e + languageName: node + linkType: hard + "jest-worker@npm:^29.7.0": version: 29.7.0 resolution: "jest-worker@npm:29.7.0" @@ -10545,6 +11551,24 @@ __metadata: languageName: node linkType: hard +"jest@npm:^27.5.1": + version: 27.5.1 + resolution: "jest@npm:27.5.1" + dependencies: + "@jest/core": "npm:^27.5.1" + import-local: "npm:^3.0.2" + jest-cli: "npm:^27.5.1" + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + bin: + jest: bin/jest.js + checksum: 10/a1435098e1885e48d2a46c660176cd34d69bc80fa72966a1ea8781ab6d5355ee514d45cf871d2da2b5a54509979e53d39fbb9b149c94e430127f44ed0d70639c + languageName: node + linkType: hard + "jest@npm:^29.7.0": version: 29.7.0 resolution: "jest@npm:29.7.0" @@ -10636,6 +11660,46 @@ __metadata: languageName: node linkType: hard +"jsdom@npm:^16.6.0": + version: 16.7.0 + resolution: "jsdom@npm:16.7.0" + dependencies: + abab: "npm:^2.0.5" + acorn: "npm:^8.2.4" + acorn-globals: "npm:^6.0.0" + cssom: "npm:^0.4.4" + cssstyle: "npm:^2.3.0" + data-urls: "npm:^2.0.0" + decimal.js: "npm:^10.2.1" + domexception: "npm:^2.0.1" + escodegen: "npm:^2.0.0" + form-data: "npm:^3.0.0" + html-encoding-sniffer: "npm:^2.0.1" + http-proxy-agent: "npm:^4.0.1" + https-proxy-agent: "npm:^5.0.0" + is-potential-custom-element-name: "npm:^1.0.1" + nwsapi: "npm:^2.2.0" + parse5: "npm:6.0.1" + saxes: "npm:^5.0.1" + symbol-tree: "npm:^3.2.4" + tough-cookie: "npm:^4.0.0" + w3c-hr-time: "npm:^1.0.2" + w3c-xmlserializer: "npm:^2.0.0" + webidl-conversions: "npm:^6.1.0" + whatwg-encoding: "npm:^1.0.5" + whatwg-mimetype: "npm:^2.3.0" + whatwg-url: "npm:^8.5.0" + ws: "npm:^7.4.6" + xml-name-validator: "npm:^3.0.0" + peerDependencies: + canvas: ^2.5.0 + peerDependenciesMeta: + canvas: + optional: true + checksum: 10/c530c04b0e3718769a66e19b0b5c762126658bce384d6743b807a28a9d89beba4ad932e474f570323efe6ce832b3d9a8f94816fd6c4d386416d5ea0b64e07ebc + languageName: node + linkType: hard + "jsdom@npm:^20.0.0": version: 20.0.3 resolution: "jsdom@npm:20.0.3" @@ -10742,7 +11806,7 @@ __metadata: languageName: node linkType: hard -"json5@npm:^2.2.3": +"json5@npm:2.x, json5@npm:^2.2.3": version: 2.2.3 resolution: "json5@npm:2.2.3" bin: @@ -10778,6 +11842,13 @@ __metadata: languageName: node linkType: hard +"just-extend@npm:^4.0.2": + version: 4.2.1 + resolution: "just-extend@npm:4.2.1" + checksum: 10/375389c0847d56300873fa622fbc5c5e208933e372bbedb39c82f583299cdad4fe9c4773bc35fcd9c42cd85744f07474ca4163aa0f9125dd5be37bc09075eb49 + languageName: node + linkType: hard + "keccak@npm:^3.0.0": version: 3.0.4 resolution: "keccak@npm:3.0.4" @@ -10869,6 +11940,13 @@ __metadata: languageName: node linkType: hard +"lodash.get@npm:^4.4.2": + version: 4.4.2 + resolution: "lodash.get@npm:4.4.2" + checksum: 10/2a4925f6e89bc2c010a77a802d1ba357e17ed1ea03c2ddf6a146429f2856a216663e694a6aa3549a318cbbba3fd8b7decb392db457e6ac0b83dc745ed0a17380 + languageName: node + linkType: hard + "lodash.isplainobject@npm:^4.0.6": version: 4.0.6 resolution: "lodash.isplainobject@npm:4.0.6" @@ -10883,7 +11961,7 @@ __metadata: languageName: node linkType: hard -"lodash.memoize@npm:^4.1.2": +"lodash.memoize@npm:4.x, lodash.memoize@npm:^4.1.2": version: 4.1.2 resolution: "lodash.memoize@npm:4.1.2" checksum: 10/192b2168f310c86f303580b53acf81ab029761b9bd9caa9506a019ffea5f3363ea98d7e39e7e11e6b9917066c9d36a09a11f6fe16f812326390d8f3a54a1a6da @@ -10904,6 +11982,13 @@ __metadata: languageName: node linkType: hard +"lodash@npm:^4.7.0": + version: 4.17.23 + resolution: "lodash@npm:4.17.23" + checksum: 10/82504c88250f58da7a5a4289f57a4f759c44946c005dd232821c7688b5fcfbf4a6268f6a6cdde4b792c91edd2f3b5398c1d2a0998274432cff76def48735e233 + languageName: node + linkType: hard + "log-symbols@npm:^4.0.0": version: 4.1.0 resolution: "log-symbols@npm:4.1.0" @@ -10985,7 +12070,7 @@ __metadata: languageName: node linkType: hard -"make-error@npm:^1.3.6": +"make-error@npm:1.x, make-error@npm:^1.3.6": version: 1.3.6 resolution: "make-error@npm:1.3.6" checksum: 10/b86e5e0e25f7f777b77fabd8e2cbf15737972869d852a22b7e73c17623928fccb826d8e46b9951501d3f20e51ad74ba8c59ed584f610526a48f8ccf88aaec402 @@ -11150,7 +12235,7 @@ __metadata: languageName: node linkType: hard -"mime-types@npm:^2.1.12, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": +"mime-types@npm:^2.1.12, mime-types@npm:^2.1.35, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": version: 2.1.35 resolution: "mime-types@npm:2.1.35" dependencies: @@ -11221,7 +12306,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^9.0.3, minimatch@npm:^9.0.4, minimatch@npm:^9.0.5": +"minimatch@npm:^9.0.0, minimatch@npm:^9.0.3, minimatch@npm:^9.0.4, minimatch@npm:^9.0.5": version: 9.0.5 resolution: "minimatch@npm:9.0.5" dependencies: @@ -11430,6 +12515,19 @@ __metadata: languageName: node linkType: hard +"nise@npm:^4.0.4": + version: 4.1.0 + resolution: "nise@npm:4.1.0" + dependencies: + "@sinonjs/commons": "npm:^1.7.0" + "@sinonjs/fake-timers": "npm:^6.0.0" + "@sinonjs/text-encoding": "npm:^0.7.1" + just-extend: "npm:^4.0.2" + path-to-regexp: "npm:^1.7.0" + checksum: 10/ff7c2e316c8ae8327573417fefcc84070d9dcfa423b123d014d21db5f7de07580f76a85143c2f91eaf5f1a979f3f9a3721e3652753e58ddaa703aa8d65539b0b + languageName: node + linkType: hard + "nock@npm:^13.3.1": version: 13.5.5 resolution: "nock@npm:13.5.5" @@ -11639,7 +12737,7 @@ __metadata: languageName: node linkType: hard -"nwsapi@npm:^2.2.2": +"nwsapi@npm:^2.2.0, nwsapi@npm:^2.2.2": version: 2.2.23 resolution: "nwsapi@npm:2.2.23" checksum: 10/aa4a570039c33d70b51436d1bb533f3e2c33c488ccbe9b09285c46a6cee5ef266fd60103461085c6954ba52460786a8138f042958328c7c1b4763898eb3dadfa @@ -11819,6 +12917,13 @@ __metadata: languageName: node linkType: hard +"parse5@npm:6.0.1": + version: 6.0.1 + resolution: "parse5@npm:6.0.1" + checksum: 10/dfb110581f62bd1425725a7c784ae022a24669bd0efc24b58c71fc731c4d868193e2ebd85b74cde2dbb965e4dcf07059b1e651adbec1b3b5267531bd132fdb75 + languageName: node + linkType: hard + "parse5@npm:^7.0.0, parse5@npm:^7.1.1": version: 7.3.0 resolution: "parse5@npm:7.3.0" @@ -11887,6 +12992,15 @@ __metadata: languageName: node linkType: hard +"path-to-regexp@npm:^1.7.0": + version: 1.9.0 + resolution: "path-to-regexp@npm:1.9.0" + dependencies: + isarray: "npm:0.0.1" + checksum: 10/67f0f4823f7aab356523d93a83f9f8222bdd119fa0b27a8f8b587e8e6c9825294bb4ccd16ae619def111ff3fe5d15ff8f658cdd3b0d58b9c882de6fd15bc1b76 + languageName: node + linkType: hard + "path-type@npm:^4.0.0": version: 4.0.0 resolution: "path-type@npm:4.0.0" @@ -12036,6 +13150,17 @@ __metadata: languageName: node linkType: hard +"pretty-format@npm:^27.0.0, pretty-format@npm:^27.5.1": + version: 27.5.1 + resolution: "pretty-format@npm:27.5.1" + dependencies: + ansi-regex: "npm:^5.0.1" + ansi-styles: "npm:^5.0.0" + react-is: "npm:^17.0.1" + checksum: 10/248990cbef9e96fb36a3e1ae6b903c551ca4ddd733f8d0912b9cc5141d3d0b3f9f8dfb4d799fb1c6723382c9c2083ffbfa4ad43ff9a0e7535d32d41fd5f01da6 + languageName: node + linkType: hard + "pretty-format@npm:^29.0.0, pretty-format@npm:^29.7.0": version: 29.7.0 resolution: "pretty-format@npm:29.7.0" @@ -12242,6 +13367,13 @@ __metadata: languageName: node linkType: hard +"react-is@npm:^17.0.1": + version: 17.0.2 + resolution: "react-is@npm:17.0.2" + checksum: 10/73b36281e58eeb27c9cc6031301b6ae19ecdc9f18ae2d518bdb39b0ac564e65c5779405d623f1df9abf378a13858b79442480244bd579968afc1faf9a2ce5e05 + languageName: node + linkType: hard + "react-is@npm:^18.0.0": version: 18.3.1 resolution: "react-is@npm:18.3.1" @@ -12428,6 +13560,13 @@ __metadata: languageName: node linkType: hard +"resolve.exports@npm:^1.1.0": + version: 1.1.1 + resolution: "resolve.exports@npm:1.1.1" + checksum: 10/de58c30aca30883f0e29910e4ad1b7b9986ec5f69434ef2e957ddbe52d3250e138ddd2688e8cd67909b4ee9bf3437424c718a5962d59edd610f035b861ef8441 + languageName: node + linkType: hard + "resolve.exports@npm:^2.0.0": version: 2.0.3 resolution: "resolve.exports@npm:2.0.3" @@ -12508,6 +13647,17 @@ __metadata: languageName: node linkType: hard +"rimraf@npm:^3.0.0": + version: 3.0.2 + resolution: "rimraf@npm:3.0.2" + dependencies: + glob: "npm:^7.1.3" + bin: + rimraf: bin.js + checksum: 10/063ffaccaaaca2cfd0ef3beafb12d6a03dd7ff1260d752d62a6077b5dfff6ae81bea571f655bb6b589d366930ec1bdd285d40d560c0dae9b12f125e54eb743d5 + languageName: node + linkType: hard + "rimraf@npm:^5.0.5": version: 5.0.10 resolution: "rimraf@npm:5.0.10" @@ -12591,6 +13741,15 @@ __metadata: languageName: node linkType: hard +"saxes@npm:^5.0.1": + version: 5.0.1 + resolution: "saxes@npm:5.0.1" + dependencies: + xmlchars: "npm:^2.2.0" + checksum: 10/148b5f98fdd45df25fa1abef35d72cdf6457ac5aef3b7d59d60f770af09d8cf6e7e3a074197071222441d68670fd3198590aba9985e37c4738af2df2f44d0686 + languageName: node + linkType: hard + "saxes@npm:^6.0.0": version: 6.0.0 resolution: "saxes@npm:6.0.0" @@ -12635,6 +13794,15 @@ __metadata: languageName: node linkType: hard +"semver@npm:7.x, semver@npm:^7.3.2": + version: 7.7.4 + resolution: "semver@npm:7.7.4" + bin: + semver: bin/semver.js + checksum: 10/26bdc6d58b29528f4142d29afb8526bc335f4fc04c4a10f2b98b217f277a031c66736bf82d3d3bb354a2f6a3ae50f18fd62b053c4ac3f294a3d10a61f5075b75 + languageName: node + linkType: hard + "semver@npm:^6.3.0, semver@npm:^6.3.1": version: 6.3.1 resolution: "semver@npm:6.3.1" @@ -12767,7 +13935,7 @@ __metadata: languageName: node linkType: hard -"shiki@npm:^0.14.7": +"shiki@npm:^0.14.1, shiki@npm:^0.14.7": version: 0.14.7 resolution: "shiki@npm:0.14.7" dependencies: @@ -12791,7 +13959,7 @@ __metadata: languageName: node linkType: hard -"signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7": +"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" checksum: 10/a2f098f247adc367dffc27845853e9959b9e88b01cb301658cfe4194352d8d2bb32e18467c786a7fe15f1d44b233ea35633d076d5e737870b7139949d1ab6318 @@ -12821,6 +13989,20 @@ __metadata: languageName: node linkType: hard +"sinon@npm:^9.2.4": + version: 9.2.4 + resolution: "sinon@npm:9.2.4" + dependencies: + "@sinonjs/commons": "npm:^1.8.1" + "@sinonjs/fake-timers": "npm:^6.0.1" + "@sinonjs/samsam": "npm:^5.3.1" + diff: "npm:^4.0.2" + nise: "npm:^4.0.4" + supports-color: "npm:^7.1.0" + checksum: 10/4597c12e2490b22aaae5fb1edca169a10e71dee73c13d2d12d6d9fa7f3bdbdb53ec5ad52c631c301fb3eab79471a30b05be65155c30ca415169470ea4789eae6 + languageName: node + linkType: hard + "sisteransi@npm:^1.0.5": version: 1.0.5 resolution: "sisteransi@npm:1.0.5" @@ -12933,6 +14115,16 @@ __metadata: languageName: node linkType: hard +"source-map-support@npm:^0.5.6": + version: 0.5.21 + resolution: "source-map-support@npm:0.5.21" + dependencies: + buffer-from: "npm:^1.0.0" + source-map: "npm:^0.6.0" + checksum: 10/8317e12d84019b31e34b86d483dd41d6f832f389f7417faf8fc5c75a66a12d9686e47f589a0554a868b8482f037e23df9d040d29387eb16fa14cb85f091ba207 + languageName: node + linkType: hard + "source-map@npm:^0.6.0, source-map@npm:^0.6.1, source-map@npm:~0.6.1": version: 0.6.1 resolution: "source-map@npm:0.6.1" @@ -12940,6 +14132,13 @@ __metadata: languageName: node linkType: hard +"source-map@npm:^0.7.3": + version: 0.7.6 + resolution: "source-map@npm:0.7.6" + checksum: 10/c8d2da7c57c14f3fd7568f764b39ad49bbf9dd7632b86df3542b31fed117d4af2fb74a4f886fc06baf7a510fee68e37998efc3080aacdac951c36211dc29a7a3 + languageName: node + linkType: hard + "spdx-correct@npm:^3.0.0": version: 3.2.0 resolution: "spdx-correct@npm:3.2.0" @@ -13274,6 +14473,16 @@ __metadata: languageName: node linkType: hard +"terminal-link@npm:^2.0.0": + version: 2.1.1 + resolution: "terminal-link@npm:2.1.1" + dependencies: + ansi-escapes: "npm:^4.2.1" + supports-hyperlinks: "npm:^2.0.0" + checksum: 10/ce3d2cd3a438c4a9453947aa664581519173ea40e77e2534d08c088ee6dda449eabdbe0a76d2a516b8b73c33262fedd10d5270ccf7576ae316e3db170ce6562f + languageName: node + linkType: hard + "test-exclude@npm:^6.0.0": version: 6.0.0 resolution: "test-exclude@npm:6.0.0" @@ -13294,6 +14503,13 @@ __metadata: languageName: node linkType: hard +"throat@npm:^6.0.1": + version: 6.0.2 + resolution: "throat@npm:6.0.2" + checksum: 10/acd99f4b7362bcf6dcc517b01517165a00f7270d0c4fe2ca06c73b6217f022f76fb20e8ca98283b25ccb85d97a5f96dbcac5577d60bb0bda1eff92fa8e79fbd7 + languageName: node + linkType: hard + "tinyglobby@npm:^0.2.15": version: 0.2.15 resolution: "tinyglobby@npm:0.2.15" @@ -13327,7 +14543,7 @@ __metadata: languageName: node linkType: hard -"tough-cookie@npm:^4.1.2": +"tough-cookie@npm:^4.0.0, tough-cookie@npm:^4.1.2": version: 4.1.4 resolution: "tough-cookie@npm:4.1.4" dependencies: @@ -13339,6 +14555,15 @@ __metadata: languageName: node linkType: hard +"tr46@npm:^2.1.0": + version: 2.1.0 + resolution: "tr46@npm:2.1.0" + dependencies: + punycode: "npm:^2.1.1" + checksum: 10/302b13f458da713b2a6ff779a0c1d27361d369fdca6c19330536d31db61789b06b246968fc879fdac818a92d02643dca1a0f4da5618df86aea4a79fb3243d3f3 + languageName: node + linkType: hard + "tr46@npm:^3.0.0": version: 3.0.0 resolution: "tr46@npm:3.0.0" @@ -13371,6 +14596,39 @@ __metadata: languageName: node linkType: hard +"ts-jest@npm:^27.1.5": + version: 27.1.5 + resolution: "ts-jest@npm:27.1.5" + dependencies: + bs-logger: "npm:0.x" + fast-json-stable-stringify: "npm:2.x" + jest-util: "npm:^27.0.0" + json5: "npm:2.x" + lodash.memoize: "npm:4.x" + make-error: "npm:1.x" + semver: "npm:7.x" + yargs-parser: "npm:20.x" + peerDependencies: + "@babel/core": ">=7.0.0-beta.0 <8" + "@types/jest": ^27.0.0 + babel-jest: ">=27.0.0 <28" + jest: ^27.0.0 + typescript: ">=3.8 <5.0" + peerDependenciesMeta: + "@babel/core": + optional: true + "@types/jest": + optional: true + babel-jest: + optional: true + esbuild: + optional: true + bin: + ts-jest: cli.js + checksum: 10/7675946cefc8c652ec35f2fd600ffb99c8e5db5ac355ceb8317707862c586ee46f7ddd589bd206fa8be2598bc4a87c5a53eb4198af78723f5661c90e32200ba3 + languageName: node + linkType: hard + "ts-jest@npm:^29.2.5": version: 29.4.6 resolution: "ts-jest@npm:29.4.6" @@ -13481,6 +14739,13 @@ __metadata: languageName: node linkType: hard +"type-detect@npm:^4.0.8": + version: 4.1.0 + resolution: "type-detect@npm:4.1.0" + checksum: 10/e363bf0352427a79301f26a7795a27718624c49c576965076624eb5495d87515030b207217845f7018093adcbe169b2d119bb9b7f1a31a92bfbb1ab9639ca8dd + languageName: node + linkType: hard + "type-fest@npm:^0.18.0": version: 0.18.1 resolution: "type-fest@npm:0.18.1" @@ -13526,6 +14791,15 @@ __metadata: languageName: node linkType: hard +"typedarray-to-buffer@npm:^3.1.5": + version: 3.1.5 + resolution: "typedarray-to-buffer@npm:3.1.5" + dependencies: + is-typedarray: "npm:^1.0.0" + checksum: 10/7c850c3433fbdf4d04f04edfc751743b8f577828b8e1eb93b95a3bce782d156e267d83e20fb32b3b47813e69a69ab5e9b5342653332f7d21c7d1210661a7a72c + languageName: node + linkType: hard + "typedarray@npm:^0.0.6": version: 0.0.6 resolution: "typedarray@npm:0.0.6" @@ -13542,6 +14816,22 @@ __metadata: languageName: node linkType: hard +"typedoc@npm:^0.24.8": + version: 0.24.8 + resolution: "typedoc@npm:0.24.8" + dependencies: + lunr: "npm:^2.3.9" + marked: "npm:^4.3.0" + minimatch: "npm:^9.0.0" + shiki: "npm:^0.14.1" + peerDependencies: + typescript: 4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x + bin: + typedoc: bin/typedoc + checksum: 10/4f2f92ddde3f70a1a9666507f6bdf6620023599bd2c2a3ed3f8f909f9c28d92594c30ee6ee68f5a248ff70e09623acf1323bad633cb713b9f2e36bbd4fccf683 + languageName: node + linkType: hard + "typedoc@npm:^0.25.13": version: 0.25.13 resolution: "typedoc@npm:0.25.13" @@ -13742,6 +15032,17 @@ __metadata: languageName: node linkType: hard +"v8-to-istanbul@npm:^8.1.0": + version: 8.1.1 + resolution: "v8-to-istanbul@npm:8.1.1" + dependencies: + "@types/istanbul-lib-coverage": "npm:^2.0.1" + convert-source-map: "npm:^1.6.0" + source-map: "npm:^0.7.3" + checksum: 10/db5469f133a7cfb7680a28ddfb31aad2cc64f282fa7cf0c8e91f91bfd542bf61597260282be28c9648f0f2114963a24b273ed92af9a5cad6cb629c708ca72f8e + languageName: node + linkType: hard + "v8-to-istanbul@npm:^9.0.1": version: 9.3.0 resolution: "v8-to-istanbul@npm:9.3.0" @@ -13798,6 +15099,24 @@ __metadata: languageName: node linkType: hard +"w3c-hr-time@npm:^1.0.2": + version: 1.0.2 + resolution: "w3c-hr-time@npm:1.0.2" + dependencies: + browser-process-hrtime: "npm:^1.0.0" + checksum: 10/03851d90c236837c24c2983f5a8806a837c6515b21d52e5f29776b07cc08695779303d481454d768308489f00dd9d3232d595acaa5b2686d199465a4d9f7b283 + languageName: node + linkType: hard + +"w3c-xmlserializer@npm:^2.0.0": + version: 2.0.0 + resolution: "w3c-xmlserializer@npm:2.0.0" + dependencies: + xml-name-validator: "npm:^3.0.0" + checksum: 10/400c18b75ce6af269168f964e7d1eb196a7422e134032906540c69d83b802f38dc64e18fc259c02966a334687483f416398d2ad7ebe9d19ab434a7a0247c71c3 + languageName: node + linkType: hard + "w3c-xmlserializer@npm:^4.0.0": version: 4.0.0 resolution: "w3c-xmlserializer@npm:4.0.0" @@ -13807,7 +15126,7 @@ __metadata: languageName: node linkType: hard -"walker@npm:^1.0.8": +"walker@npm:^1.0.7, walker@npm:^1.0.8": version: 1.0.8 resolution: "walker@npm:1.0.8" dependencies: @@ -13846,6 +15165,20 @@ __metadata: languageName: node linkType: hard +"webidl-conversions@npm:^5.0.0": + version: 5.0.0 + resolution: "webidl-conversions@npm:5.0.0" + checksum: 10/cea864dd9cf1f2133d82169a446fb94427ba089e4676f5895273ea085f165649afe587ae3f19f2f0370751a724bba2d96e9956d652b3e41ac1feaaa4376e2d70 + languageName: node + linkType: hard + +"webidl-conversions@npm:^6.1.0": + version: 6.1.0 + resolution: "webidl-conversions@npm:6.1.0" + checksum: 10/4454b73060a6d83f7ec1f1db24c480b7ecda33880306dd32a3d62d85b36df4789a383489f1248387e5451737dca17054b8cbf2e792ba89e49d76247f0f4f6380 + languageName: node + linkType: hard + "webidl-conversions@npm:^7.0.0": version: 7.0.0 resolution: "webidl-conversions@npm:7.0.0" @@ -13871,6 +15204,15 @@ __metadata: languageName: node linkType: hard +"whatwg-encoding@npm:^1.0.5": + version: 1.0.5 + resolution: "whatwg-encoding@npm:1.0.5" + dependencies: + iconv-lite: "npm:0.4.24" + checksum: 10/5be4efe111dce29ddee3448d3915477fcc3b28f991d9cf1300b4e50d6d189010d47bca2f51140a844cf9b726e8f066f4aee72a04d687bfe4f2ee2767b2f5b1e6 + languageName: node + linkType: hard + "whatwg-encoding@npm:^2.0.0": version: 2.0.0 resolution: "whatwg-encoding@npm:2.0.0" @@ -13887,6 +15229,13 @@ __metadata: languageName: node linkType: hard +"whatwg-mimetype@npm:^2.3.0": + version: 2.3.0 + resolution: "whatwg-mimetype@npm:2.3.0" + checksum: 10/3582c1d74d708716013433bbab45cb9b31ef52d276adfbe2205d948be1ec9bb1a4ac05ce6d9045f3acc4104489e1344c857b14700002385a4b997a5673ff6416 + languageName: node + linkType: hard + "whatwg-mimetype@npm:^3.0.0": version: 3.0.0 resolution: "whatwg-mimetype@npm:3.0.0" @@ -13914,6 +15263,17 @@ __metadata: languageName: node linkType: hard +"whatwg-url@npm:^8.0.0, whatwg-url@npm:^8.5.0": + version: 8.7.0 + resolution: "whatwg-url@npm:8.7.0" + dependencies: + lodash: "npm:^4.7.0" + tr46: "npm:^2.1.0" + webidl-conversions: "npm:^6.1.0" + checksum: 10/512a8b2703dffbf13a9a247bf2fb27c3048a3ceb5ece09f88b737c8260afaba4b2f6775c2f1cfc29c2ba4859f2454a9de73fac08e239b00ae2b42cd6b8bb0d35 + languageName: node + linkType: hard + "which@npm:^1.2.14": version: 1.3.1 resolution: "which@npm:1.3.1" @@ -14001,6 +15361,18 @@ __metadata: languageName: node linkType: hard +"write-file-atomic@npm:^3.0.0": + version: 3.0.3 + resolution: "write-file-atomic@npm:3.0.3" + dependencies: + imurmurhash: "npm:^0.1.4" + is-typedarray: "npm:^1.0.0" + signal-exit: "npm:^3.0.2" + typedarray-to-buffer: "npm:^3.1.5" + checksum: 10/0955ab94308b74d32bc252afe69d8b42ba4b8a28b8d79f399f3f405969f82623f981e35d13129a52aa2973450f342107c06d86047572637584e85a1c0c246bf3 + languageName: node + linkType: hard + "write-file-atomic@npm:^4.0.2": version: 4.0.2 resolution: "write-file-atomic@npm:4.0.2" @@ -14036,7 +15408,7 @@ __metadata: languageName: node linkType: hard -"ws@npm:^7.5.10": +"ws@npm:^7.4.6, ws@npm:^7.5.10": version: 7.5.10 resolution: "ws@npm:7.5.10" peerDependencies: @@ -14073,6 +15445,13 @@ __metadata: languageName: node linkType: hard +"xml-name-validator@npm:^3.0.0": + version: 3.0.0 + resolution: "xml-name-validator@npm:3.0.0" + checksum: 10/24f5d38c777ad9239dfe99c4ca3cd155415b65ac583785d1514e04b9f86d6d09eaff983ed373e7a779ceefd1fca0fd893f2fc264999e9aeaac36b6e1afc397ed + languageName: node + linkType: hard + "xml-name-validator@npm:^4.0.0": version: 4.0.0 resolution: "xml-name-validator@npm:4.0.0" @@ -14138,7 +15517,7 @@ __metadata: languageName: node linkType: hard -"yargs-parser@npm:^20.2.2, yargs-parser@npm:^20.2.3": +"yargs-parser@npm:20.x, yargs-parser@npm:^20.2.2, yargs-parser@npm:^20.2.3": version: 20.2.9 resolution: "yargs-parser@npm:20.2.9" checksum: 10/0188f430a0f496551d09df6719a9132a3469e47fe2747208b1dd0ab2bb0c512a95d0b081628bbca5400fb20dbf2fabe63d22badb346cecadffdd948b049f3fcc From 9c4c263ee5ecdc477d72eaf3a702ec416eb354d4 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Fri, 20 Feb 2026 18:13:02 +0100 Subject: [PATCH 39/55] fix: fix failing test --- .../config-registry-controller/package.json | 6 +- .../src/ConfigRegistryController.test.ts | 236 ++- yarn.lock | 1308 +---------------- 3 files changed, 126 insertions(+), 1424 deletions(-) diff --git a/packages/config-registry-controller/package.json b/packages/config-registry-controller/package.json index 39828d03c78..f603d992359 100644 --- a/packages/config-registry-controller/package.json +++ b/packages/config-registry-controller/package.json @@ -62,12 +62,12 @@ "@lavamoat/allow-scripts": "^3.0.4", "@metamask/auto-changelog": "^3.4.4", "@ts-bridge/cli": "^0.6.4", - "@types/jest": "^27.5.2", + "@types/jest": "^29.5.14", "deepmerge": "^4.2.2", - "jest": "^27.5.1", + "jest": "^29.7.0", "nock": "^13.3.1", "sinon": "^9.2.4", - "ts-jest": "^27.1.5", + "ts-jest": "^29.2.5", "typedoc": "^0.24.8", "typedoc-plugin-missing-exports": "^2.0.0", "typescript": "~5.3.3" diff --git a/packages/config-registry-controller/src/ConfigRegistryController.test.ts b/packages/config-registry-controller/src/ConfigRegistryController.test.ts index 9ad4f0d9aed..8c6cf464541 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.test.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.test.ts @@ -4,7 +4,6 @@ import type { MessengerEvents, } from '@metamask/messenger'; import { Messenger, MOCK_ANY_NAMESPACE } from '@metamask/messenger'; -import { useFakeTimers } from 'sinon'; import type { RegistryNetworkConfig } from './config-registry-api-service'; import type { FetchConfigResult } from './config-registry-api-service'; @@ -15,7 +14,7 @@ import { } from './ConfigRegistryController'; import { selectFeaturedNetworks, selectNetworks } from './selectors'; import { createMockNetworkConfig } from './test-helpers'; -import { advanceTime } from '../../../tests/helpers'; +import { jestAdvanceTime } from '../../../tests/helpers'; const namespace = 'ConfigRegistryController' as const; @@ -97,7 +96,6 @@ function buildMockApiServiceHandler(overrides?: { type WithControllerCallback = (args: { controller: ConfigRegistryController; - clock: sinon.SinonFakeTimers; rootMessenger: RootMessenger; messenger: ConfigRegistryMessenger; mockApiServiceHandler: jest.Mock; @@ -116,7 +114,7 @@ async function withController( const [{ options = {} }, testFunction] = args.length === 2 ? args : [{}, args[0]]; - const clock = useFakeTimers(); + jest.useFakeTimers(); const { messenger, rootMessenger } = getConfigRegistryControllerMessenger(); const mockApiServiceHandler = jest.fn(buildMockApiServiceHandler()); @@ -145,7 +143,6 @@ async function withController( try { return await testFunction({ controller, - clock, rootMessenger, messenger, mockApiServiceHandler, @@ -153,7 +150,7 @@ async function withController( }); } finally { controller.stopAllPolling(); - clock.restore(); + jest.useRealTimers(); mockApiServiceHandler.mockReset(); } } @@ -220,25 +217,23 @@ describe('ConfigRegistryController', () => { describe('polling', () => { it('starts polling', async () => { - await withController( - async ({ controller, clock, mockApiServiceHandler }) => { - controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); - expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); - controller.stopAllPolling(); - }, - ); + await withController(async ({ controller, mockApiServiceHandler }) => { + controller.startPolling(null); + await jestAdvanceTime({ duration: 0 }); + expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); + controller.stopAllPolling(); + }); }); it('polls at specified interval', async () => { const pollingInterval = 1000; await withController( { options: { pollingInterval } }, - async ({ controller, clock, mockApiServiceHandler }) => { + async ({ controller, mockApiServiceHandler }) => { controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); mockApiServiceHandler.mockClear(); - await advanceTime({ clock, duration: pollingInterval }); + await jestAdvanceTime({ duration: pollingInterval }); expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); controller.stopAllPolling(); }, @@ -246,16 +241,14 @@ describe('ConfigRegistryController', () => { }); it('stops polling', async () => { - await withController( - async ({ controller, clock, mockApiServiceHandler }) => { - controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); - mockApiServiceHandler.mockClear(); - controller.stopAllPolling(); - await advanceTime({ clock, duration: DEFAULT_POLLING_INTERVAL }); - expect(mockApiServiceHandler).not.toHaveBeenCalled(); - }, - ); + await withController(async ({ controller, mockApiServiceHandler }) => { + controller.startPolling(null); + await jestAdvanceTime({ duration: 0 }); + mockApiServiceHandler.mockClear(); + controller.stopAllPolling(); + await jestAdvanceTime({ duration: DEFAULT_POLLING_INTERVAL }); + expect(mockApiServiceHandler).not.toHaveBeenCalled(); + }); }); it('uses fallback config when no configs exist', async () => { @@ -263,7 +256,6 @@ describe('ConfigRegistryController', () => { { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, async ({ controller, - clock, rootMessenger, mockRemoteFeatureFlagGetState, mockApiServiceHandler, @@ -278,7 +270,7 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockRejectedValue(new Error('Network error')); controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ message: 'Network error' }), @@ -308,7 +300,6 @@ describe('ConfigRegistryController', () => { }, async ({ controller, - clock, rootMessenger, mockRemoteFeatureFlagGetState, mockApiServiceHandler, @@ -323,7 +314,7 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockRejectedValue(new Error('Network error')); controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ message: 'Network error' }), @@ -340,7 +331,6 @@ describe('ConfigRegistryController', () => { { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, async ({ controller, - clock, rootMessenger, mockRemoteFeatureFlagGetState, mockApiServiceHandler, @@ -355,7 +345,7 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockRejectedValue(new Error('Network error')); controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ message: 'Network error' }), @@ -372,7 +362,6 @@ describe('ConfigRegistryController', () => { await withController( async ({ controller, - clock, mockRemoteFeatureFlagGetState, mockApiServiceHandler, }) => { @@ -390,7 +379,7 @@ describe('ConfigRegistryController', () => { const beforeTimestamp = Date.now(); controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); const afterTimestamp = Date.now(); expect(controller.state.etag).toBe('"test-etag"'); @@ -416,7 +405,6 @@ describe('ConfigRegistryController', () => { }, async ({ controller, - clock, mockRemoteFeatureFlagGetState, mockApiServiceHandler, }) => { @@ -433,7 +421,7 @@ describe('ConfigRegistryController', () => { const beforeTimestamp = Date.now(); controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); const afterTimestamp = Date.now(); expect(controller.state.etag).toBe('"existing-etag"'); @@ -459,7 +447,6 @@ describe('ConfigRegistryController', () => { }, async ({ controller, - clock, mockRemoteFeatureFlagGetState, mockApiServiceHandler, }) => { @@ -477,7 +464,7 @@ describe('ConfigRegistryController', () => { const beforeTimestamp = Date.now(); controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); const afterTimestamp = Date.now(); expect(controller.state.etag).toBeNull(); @@ -496,7 +483,6 @@ describe('ConfigRegistryController', () => { await withController( async ({ controller, - clock, rootMessenger, mockRemoteFeatureFlagGetState, mockApiServiceHandler, @@ -514,7 +500,7 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockRejectedValue(validationError); controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ @@ -529,7 +515,6 @@ describe('ConfigRegistryController', () => { await withController( async ({ controller, - clock, rootMessenger, mockRemoteFeatureFlagGetState, mockApiServiceHandler, @@ -547,7 +532,7 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockRejectedValue(validationError); controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ @@ -562,7 +547,6 @@ describe('ConfigRegistryController', () => { await withController( async ({ controller, - clock, rootMessenger, mockRemoteFeatureFlagGetState, mockApiServiceHandler, @@ -580,7 +564,7 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockRejectedValue(validationError); controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ @@ -595,7 +579,6 @@ describe('ConfigRegistryController', () => { await withController( async ({ controller, - clock, rootMessenger, mockRemoteFeatureFlagGetState, mockApiServiceHandler, @@ -613,7 +596,7 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockRejectedValue(validationError); controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ @@ -635,12 +618,7 @@ describe('ConfigRegistryController', () => { }, }, }, - async ({ - controller, - clock, - messenger, - mockRemoteFeatureFlagGetState, - }) => { + async ({ controller, messenger, mockRemoteFeatureFlagGetState }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { configRegistryApiEnabled: true, @@ -654,7 +632,7 @@ describe('ConfigRegistryController', () => { ) as jest.SpyInstance; controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(fetchConfigSpy).not.toHaveBeenCalledWith( 'ConfigRegistryApiService:fetchConfig', @@ -675,7 +653,6 @@ describe('ConfigRegistryController', () => { }, async ({ controller, - clock, mockRemoteFeatureFlagGetState, mockApiServiceHandler, }) => { @@ -703,7 +680,7 @@ describe('ConfigRegistryController', () => { }); controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(mockApiServiceHandler).toHaveBeenCalled(); expect(controller.state.lastFetched).not.toBeNull(); @@ -724,7 +701,6 @@ describe('ConfigRegistryController', () => { }, async ({ controller, - clock, mockRemoteFeatureFlagGetState, mockApiServiceHandler, }) => { @@ -754,7 +730,7 @@ describe('ConfigRegistryController', () => { }); controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(mockApiServiceHandler).toHaveBeenCalled(); expect(controller.state.lastFetched).not.toBe(oldTimestamp); @@ -776,12 +752,7 @@ describe('ConfigRegistryController', () => { }, }, }, - async ({ - controller, - clock, - messenger, - mockRemoteFeatureFlagGetState, - }) => { + async ({ controller, messenger, mockRemoteFeatureFlagGetState }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { configRegistryApiEnabled: true, @@ -795,7 +766,6 @@ describe('ConfigRegistryController', () => { ) as jest.SpyInstance; controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); expect(fetchConfigSpy).not.toHaveBeenCalledWith( 'ConfigRegistryApiService:fetchConfig', @@ -815,12 +785,7 @@ describe('ConfigRegistryController', () => { }, }, }, - async ({ - controller, - clock, - messenger, - mockRemoteFeatureFlagGetState, - }) => { + async ({ controller, messenger, mockRemoteFeatureFlagGetState }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { configRegistryApiEnabled: true, @@ -838,7 +803,6 @@ describe('ConfigRegistryController', () => { ) as jest.SpyInstance; controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); expect(fetchConfigSpy).not.toHaveBeenCalledWith( 'ConfigRegistryApiService:fetchConfig', @@ -853,7 +817,6 @@ describe('ConfigRegistryController', () => { { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, async ({ controller, - clock, rootMessenger, mockRemoteFeatureFlagGetState, mockApiServiceHandler, @@ -868,7 +831,7 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockRejectedValue('String error'); controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ message: 'String error' }), @@ -891,7 +854,6 @@ describe('ConfigRegistryController', () => { }, async ({ controller, - clock, rootMessenger, mockRemoteFeatureFlagGetState, mockApiServiceHandler, @@ -906,7 +868,7 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockRejectedValue(new Error('Network error')); controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ message: 'Network error' }), @@ -919,7 +881,7 @@ describe('ConfigRegistryController', () => { }); it('works via messenger actions', async () => { - await withController(async ({ controller, messenger, clock }) => { + await withController(async ({ controller, messenger }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); const token = messenger.call( @@ -928,11 +890,11 @@ describe('ConfigRegistryController', () => { ); expect(typeof token).toBe('string'); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(executePollSpy).toHaveBeenCalledTimes(1); messenger.call('ConfigRegistryController:stopPolling'); - await advanceTime({ clock, duration: DEFAULT_POLLING_INTERVAL }); + await jestAdvanceTime({ duration: DEFAULT_POLLING_INTERVAL }); expect(executePollSpy).toHaveBeenCalledTimes(1); }); }); @@ -993,16 +955,16 @@ describe('ConfigRegistryController', () => { }, }, }, - async ({ controller, clock }) => { + async ({ controller }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); controller.startPolling(null); // StaticIntervalPollingController runs first poll after 0ms (executePoll may early-return due to lastFetched) - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(executePollSpy).toHaveBeenCalledTimes(1); // Next poll is scheduled at pollingInterval; advancing remainingTime+1 does not reach it - await advanceTime({ clock, duration: remainingTime + 1 }); + await jestAdvanceTime({ duration: remainingTime + 1 }); expect(executePollSpy).toHaveBeenCalledTimes(1); controller.stopAllPolling(); @@ -1019,11 +981,11 @@ describe('ConfigRegistryController', () => { }, }, }, - async ({ controller, clock }) => { + async ({ controller }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(executePollSpy).toHaveBeenCalledTimes(1); controller.stopAllPolling(); @@ -1044,12 +1006,12 @@ describe('ConfigRegistryController', () => { }, }, }, - async ({ controller, clock }) => { + async ({ controller }) => { jest.spyOn(Date, 'now').mockReturnValue(now); const executePollSpy = jest.spyOn(controller, '_executePoll'); controller.startPolling(null); - await advanceTime({ clock, duration: 1 }); + await jestAdvanceTime({ duration: 1 }); expect(executePollSpy).toHaveBeenCalledTimes(1); controller.stopAllPolling(); @@ -1071,12 +1033,12 @@ describe('ConfigRegistryController', () => { }, }, }, - async ({ controller, clock }) => { + async ({ controller }) => { jest.spyOn(Date, 'now').mockReturnValue(now); const executePollSpy = jest.spyOn(controller, '_executePoll'); controller.startPolling(null); - await advanceTime({ clock, duration: 1 }); + await jestAdvanceTime({ duration: 1 }); expect(executePollSpy).toHaveBeenCalledTimes(1); controller.stopAllPolling(); @@ -1095,7 +1057,7 @@ describe('ConfigRegistryController', () => { }, }, }, - async ({ controller, clock }) => { + async ({ controller }) => { jest .spyOn(controller, 'getIntervalLength') .mockReturnValue(undefined); @@ -1104,7 +1066,7 @@ describe('ConfigRegistryController', () => { controller.startPolling(null); // StaticIntervalPollingController runs first poll after 0ms - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(executePollSpy).toHaveBeenCalledTimes(1); controller.stopAllPolling(); @@ -1124,20 +1086,20 @@ describe('ConfigRegistryController', () => { }, }, }, - async ({ controller, clock }) => { + async ({ controller }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); const clearTimeoutSpy = jest.spyOn(global, 'clearTimeout'); // First call runs first poll after 0ms controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(executePollSpy).toHaveBeenCalledTimes(1); const clearTimeoutCallCountBefore = clearTimeoutSpy.mock.calls.length; // Second call reuses same session (same input); no new _startPolling, so no extra executePoll controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(executePollSpy).toHaveBeenCalledTimes(1); // _startPolling clears before setting; clearTimeout is used when rescheduling after executePoll @@ -1155,7 +1117,7 @@ describe('ConfigRegistryController', () => { it('uses fallback config when feature flag is disabled', async () => { await withController( { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, - async ({ controller, clock, mockRemoteFeatureFlagGetState }) => { + async ({ controller, mockRemoteFeatureFlagGetState }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { configRegistryApiEnabled: false, @@ -1166,7 +1128,7 @@ describe('ConfigRegistryController', () => { const executePollSpy = jest.spyOn(controller, '_executePoll'); controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(executePollSpy).toHaveBeenCalledTimes(1); expect(controller.state.configs).toStrictEqual({ @@ -1182,7 +1144,6 @@ describe('ConfigRegistryController', () => { await withController( async ({ controller, - clock, mockRemoteFeatureFlagGetState, mockApiServiceHandler, }) => { @@ -1234,7 +1195,7 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockImplementation(fetchConfigSpy); controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(fetchConfigSpy).toHaveBeenCalled(); expect(controller.state.configs.networks['0x1']).toBeDefined(); @@ -1247,7 +1208,6 @@ describe('ConfigRegistryController', () => { await withController( async ({ controller, - clock, mockRemoteFeatureFlagGetState, mockApiServiceHandler, }) => { @@ -1368,7 +1328,7 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockImplementation(fetchConfigSpy); controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); // All networks stored in state const allNetworks = selectNetworks(controller.state); @@ -1393,7 +1353,6 @@ describe('ConfigRegistryController', () => { await withController( async ({ controller, - clock, mockRemoteFeatureFlagGetState, mockApiServiceHandler, }) => { @@ -1490,7 +1449,7 @@ describe('ConfigRegistryController', () => { }); controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); // Last occurrence overwrites (no grouping/priority) expect(controller.state.configs.networks['0x1']).toBeDefined(); @@ -1510,7 +1469,6 @@ describe('ConfigRegistryController', () => { await withController( async ({ controller, - clock, mockRemoteFeatureFlagGetState, mockApiServiceHandler, }) => { @@ -1584,7 +1542,7 @@ describe('ConfigRegistryController', () => { }); controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); // Last occurrence overwrites expect(controller.state.configs.networks['0x1']).toBeDefined(); @@ -1603,7 +1561,7 @@ describe('ConfigRegistryController', () => { isConfigRegistryApiEnabled: customIsEnabled, }, }, - async ({ controller, clock, messenger, mockApiServiceHandler }) => { + async ({ controller, messenger, mockApiServiceHandler }) => { const mockNetworks = [ { chainId: '0x1', @@ -1643,7 +1601,7 @@ describe('ConfigRegistryController', () => { }); controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(customIsEnabled).toHaveBeenCalledWith(messenger); expect(mockApiServiceHandler).toHaveBeenCalled(); @@ -1662,9 +1620,9 @@ describe('ConfigRegistryController', () => { isConfigRegistryApiEnabled: customIsEnabled, }, }, - async ({ controller, clock, messenger, mockApiServiceHandler }) => { + async ({ controller, messenger, mockApiServiceHandler }) => { controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(customIsEnabled).toHaveBeenCalledWith(messenger); expect(mockApiServiceHandler).not.toHaveBeenCalled(); @@ -1678,7 +1636,7 @@ describe('ConfigRegistryController', () => { it('defaults to fallback when feature flag is not set', async () => { await withController( { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, - async ({ controller, clock, mockRemoteFeatureFlagGetState }) => { + async ({ controller, mockRemoteFeatureFlagGetState }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: {}, cacheTimestamp: Date.now(), @@ -1687,7 +1645,7 @@ describe('ConfigRegistryController', () => { const executePollSpy = jest.spyOn(controller, '_executePoll'); controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(executePollSpy).toHaveBeenCalledTimes(1); expect(controller.state.configs).toStrictEqual({ @@ -1702,7 +1660,7 @@ describe('ConfigRegistryController', () => { it('defaults to fallback when RemoteFeatureFlagController is unavailable', async () => { await withController( { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, - async ({ controller, clock, mockRemoteFeatureFlagGetState }) => { + async ({ controller, mockRemoteFeatureFlagGetState }) => { mockRemoteFeatureFlagGetState.mockImplementation(() => { throw new Error('RemoteFeatureFlagController not available'); }); @@ -1710,7 +1668,7 @@ describe('ConfigRegistryController', () => { const executePollSpy = jest.spyOn(controller, '_executePoll'); controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(executePollSpy).toHaveBeenCalledTimes(1); expect(controller.state.configs).toStrictEqual({ @@ -1725,7 +1683,7 @@ describe('ConfigRegistryController', () => { describe('KeyringController event listeners', () => { it('starts polling when KeyringController:unlock event is published', async () => { - await withController(async ({ controller, clock, rootMessenger }) => { + await withController(async ({ controller, rootMessenger }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); const startPollingSpy = jest.spyOn(controller, 'startPolling'); @@ -1733,7 +1691,7 @@ describe('ConfigRegistryController', () => { rootMessenger.publish('KeyringController:unlock'); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(startPollingSpy).toHaveBeenCalledWith(null); expect(executePollSpy).toHaveBeenCalledTimes(1); @@ -1743,10 +1701,10 @@ describe('ConfigRegistryController', () => { }); it('stops polling when KeyringController:lock event is published', async () => { - await withController(async ({ controller, clock, rootMessenger }) => { + await withController(async ({ controller, rootMessenger }) => { const stopPollingSpy = jest.spyOn(controller, 'stopAllPolling'); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(stopPollingSpy).not.toHaveBeenCalled(); rootMessenger.publish('KeyringController:lock'); @@ -1756,12 +1714,12 @@ describe('ConfigRegistryController', () => { }); it('calls startPolling with default parameter when called without arguments', async () => { - await withController(async ({ controller, clock }) => { + await withController(async ({ controller }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(executePollSpy).toHaveBeenCalledTimes(1); controller.stopAllPolling(); @@ -1782,19 +1740,19 @@ describe('ConfigRegistryController', () => { }, }, }, - async ({ controller, clock }) => { + async ({ controller }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); controller.startPolling(null); // StaticIntervalPollingController runs first poll after 0ms - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(executePollSpy).toHaveBeenCalledTimes(1); // Stop polling should clear the next scheduled timeout controller.stopAllPolling(); // Advance time past when the next poll would have fired - await advanceTime({ clock, duration: pollingInterval }); + await jestAdvanceTime({ duration: pollingInterval }); expect(executePollSpy).toHaveBeenCalledTimes(1); }, ); @@ -1819,19 +1777,19 @@ describe('ConfigRegistryController', () => { }, }, }, - async ({ controller, clock }) => { + async ({ controller }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); const token = controller.startPolling(null); // StaticIntervalPollingController runs first poll after 0ms - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(executePollSpy).toHaveBeenCalledTimes(1); // Stop polling using the placeholder token controller.stopPollingByPollingToken(token); // Advance time past when the next poll would have fired - await advanceTime({ clock, duration: pollingInterval }); + await jestAdvanceTime({ duration: pollingInterval }); expect(executePollSpy).toHaveBeenCalledTimes(1); }, ); @@ -1850,12 +1808,12 @@ describe('ConfigRegistryController', () => { }, }, }, - async ({ controller, clock }) => { + async ({ controller }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); const token = controller.startPolling(null); // Advance time to when the delayed poll starts - await advanceTime({ clock, duration: remainingTime + 1 }); + await jestAdvanceTime({ duration: remainingTime + 1 }); expect(executePollSpy).toHaveBeenCalledTimes(1); executePollSpy.mockClear(); @@ -1863,45 +1821,45 @@ describe('ConfigRegistryController', () => { controller.stopPollingByPollingToken(token); // Advance time to verify polling stopped - await advanceTime({ clock, duration: pollingInterval }); + await jestAdvanceTime({ duration: pollingInterval }); expect(executePollSpy).not.toHaveBeenCalled(); }, ); }); it('stops all polling when called without token (backward compatible)', async () => { - await withController(async ({ controller, clock }) => { + await withController(async ({ controller }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); // Start polling from multiple consumers controller.startPolling(null); controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(executePollSpy).toHaveBeenCalledTimes(1); executePollSpy.mockClear(); // Stop without token should stop all polling controller.stopAllPolling(); - await advanceTime({ clock, duration: DEFAULT_POLLING_INTERVAL }); + await jestAdvanceTime({ duration: DEFAULT_POLLING_INTERVAL }); expect(executePollSpy).not.toHaveBeenCalled(); }); }); it('stops specific polling session when called with token', async () => { - await withController(async ({ controller, clock }) => { + await withController(async ({ controller }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); // Start polling from consumer A const tokenA = controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(executePollSpy).toHaveBeenCalledTimes(1); executePollSpy.mockClear(); // Start polling from consumer B (reuses same polling session) const tokenB = controller.startPolling(null); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(executePollSpy).toHaveBeenCalledTimes(0); executePollSpy.mockClear(); @@ -1910,13 +1868,13 @@ describe('ConfigRegistryController', () => { controller.stopPollingByPollingToken(tokenB); // No more polls after session is stopped - await advanceTime({ clock, duration: DEFAULT_POLLING_INTERVAL }); + await jestAdvanceTime({ duration: DEFAULT_POLLING_INTERVAL }); expect(executePollSpy).not.toHaveBeenCalled(); }); }); it('works via messenger action with token', async () => { - await withController(async ({ controller, messenger, clock }) => { + await withController(async ({ controller, messenger }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); const token = messenger.call( @@ -1925,19 +1883,19 @@ describe('ConfigRegistryController', () => { ); expect(typeof token).toBe('string'); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(executePollSpy).toHaveBeenCalledTimes(1); executePollSpy.mockClear(); // Stop via messenger action (stops all polling) messenger.call('ConfigRegistryController:stopPolling'); - await advanceTime({ clock, duration: DEFAULT_POLLING_INTERVAL }); + await jestAdvanceTime({ duration: DEFAULT_POLLING_INTERVAL }); expect(executePollSpy).not.toHaveBeenCalled(); }); }); it('works via messenger action without token (backward compatible)', async () => { - await withController(async ({ controller, messenger, clock }) => { + await withController(async ({ controller, messenger }) => { const executePollSpy = jest.spyOn(controller, '_executePoll'); const token = messenger.call( @@ -1946,13 +1904,13 @@ describe('ConfigRegistryController', () => { ); expect(typeof token).toBe('string'); - await advanceTime({ clock, duration: 0 }); + await jestAdvanceTime({ duration: 0 }); expect(executePollSpy).toHaveBeenCalledTimes(1); executePollSpy.mockClear(); // Stop without token via messenger (backward compatible) messenger.call('ConfigRegistryController:stopPolling'); - await advanceTime({ clock, duration: DEFAULT_POLLING_INTERVAL }); + await jestAdvanceTime({ duration: DEFAULT_POLLING_INTERVAL }); expect(executePollSpy).not.toHaveBeenCalled(); }); }); diff --git a/yarn.lock b/yarn.lock index 6d6ffaa933e..4f11c0ad094 100644 --- a/yarn.lock +++ b/yarn.lock @@ -30,7 +30,7 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:^7.1.0, @babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.23.2, @babel/core@npm:^7.23.9, @babel/core@npm:^7.7.2, @babel/core@npm:^7.8.0": +"@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.23.2, @babel/core@npm:^7.23.9": version: 7.29.0 resolution: "@babel/core@npm:7.29.0" dependencies: @@ -365,7 +365,7 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.23.2, @babel/traverse@npm:^7.28.6, @babel/traverse@npm:^7.29.0, @babel/traverse@npm:^7.7.2": +"@babel/traverse@npm:^7.23.2, @babel/traverse@npm:^7.28.6, @babel/traverse@npm:^7.29.0": version: 7.29.0 resolution: "@babel/traverse@npm:7.29.0" dependencies: @@ -380,7 +380,7 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.23.0, @babel/types@npm:^7.28.2, @babel/types@npm:^7.28.6, @babel/types@npm:^7.29.0, @babel/types@npm:^7.3.3": +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.23.0, @babel/types@npm:^7.28.6, @babel/types@npm:^7.29.0, @babel/types@npm:^7.3.3": version: 7.29.0 resolution: "@babel/types@npm:7.29.0" dependencies: @@ -1866,20 +1866,6 @@ __metadata: languageName: node linkType: hard -"@jest/console@npm:^27.5.1": - version: 27.5.1 - resolution: "@jest/console@npm:27.5.1" - dependencies: - "@jest/types": "npm:^27.5.1" - "@types/node": "npm:*" - chalk: "npm:^4.0.0" - jest-message-util: "npm:^27.5.1" - jest-util: "npm:^27.5.1" - slash: "npm:^3.0.0" - checksum: 10/f724ff9693b09711fded8b87145c3446091bde87f572e210667c2b8290b5364c776f3a99c7d1fd6d5642f7f9424d5acc312c12e9cc4da2ef0260d34547869fdd - languageName: node - linkType: hard - "@jest/console@npm:^29.7.0": version: 29.7.0 resolution: "@jest/console@npm:29.7.0" @@ -1894,47 +1880,6 @@ __metadata: languageName: node linkType: hard -"@jest/core@npm:^27.5.1": - version: 27.5.1 - resolution: "@jest/core@npm:27.5.1" - dependencies: - "@jest/console": "npm:^27.5.1" - "@jest/reporters": "npm:^27.5.1" - "@jest/test-result": "npm:^27.5.1" - "@jest/transform": "npm:^27.5.1" - "@jest/types": "npm:^27.5.1" - "@types/node": "npm:*" - ansi-escapes: "npm:^4.2.1" - chalk: "npm:^4.0.0" - emittery: "npm:^0.8.1" - exit: "npm:^0.1.2" - graceful-fs: "npm:^4.2.9" - jest-changed-files: "npm:^27.5.1" - jest-config: "npm:^27.5.1" - jest-haste-map: "npm:^27.5.1" - jest-message-util: "npm:^27.5.1" - jest-regex-util: "npm:^27.5.1" - jest-resolve: "npm:^27.5.1" - jest-resolve-dependencies: "npm:^27.5.1" - jest-runner: "npm:^27.5.1" - jest-runtime: "npm:^27.5.1" - jest-snapshot: "npm:^27.5.1" - jest-util: "npm:^27.5.1" - jest-validate: "npm:^27.5.1" - jest-watcher: "npm:^27.5.1" - micromatch: "npm:^4.0.4" - rimraf: "npm:^3.0.0" - slash: "npm:^3.0.0" - strip-ansi: "npm:^6.0.0" - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - checksum: 10/79eb63c3197336c39de6a3341d3f5e7dbca7e20796bd4ee3d725e4ef2832f4d07242898a8af6c9de19ebd700983385a3df16c024b4497f8beb666c8ffe96ccb4 - languageName: node - linkType: hard - "@jest/core@npm:^29.7.0": version: 29.7.0 resolution: "@jest/core@npm:29.7.0" @@ -1976,18 +1921,6 @@ __metadata: languageName: node linkType: hard -"@jest/environment@npm:^27.5.1": - version: 27.5.1 - resolution: "@jest/environment@npm:27.5.1" - dependencies: - "@jest/fake-timers": "npm:^27.5.1" - "@jest/types": "npm:^27.5.1" - "@types/node": "npm:*" - jest-mock: "npm:^27.5.1" - checksum: 10/74a2a4427f82b096c4f7223c56a27f64487ee4639b017129f31e99ebb2e9a614eb365ec77c3701d6eedc1c8d711ad2dd4b31d6dfad72cbb6d73a4f1fdc4a86cb - languageName: node - linkType: hard - "@jest/environment@npm:^29.7.0": version: 29.7.0 resolution: "@jest/environment@npm:29.7.0" @@ -2019,20 +1952,6 @@ __metadata: languageName: node linkType: hard -"@jest/fake-timers@npm:^27.5.1": - version: 27.5.1 - resolution: "@jest/fake-timers@npm:27.5.1" - dependencies: - "@jest/types": "npm:^27.5.1" - "@sinonjs/fake-timers": "npm:^8.0.1" - "@types/node": "npm:*" - jest-message-util: "npm:^27.5.1" - jest-mock: "npm:^27.5.1" - jest-util: "npm:^27.5.1" - checksum: 10/dd8b736edbc8da77af3ca14ffaa2f331168618db7b879a3a07a4667af11ae4ff840f64a61e3828e217ee94f06d5a9ba30bf19e5103bb74e193b8216ce4c0708d - languageName: node - linkType: hard - "@jest/fake-timers@npm:^29.7.0": version: 29.7.0 resolution: "@jest/fake-timers@npm:29.7.0" @@ -2047,17 +1966,6 @@ __metadata: languageName: node linkType: hard -"@jest/globals@npm:^27.5.1": - version: 27.5.1 - resolution: "@jest/globals@npm:27.5.1" - dependencies: - "@jest/environment": "npm:^27.5.1" - "@jest/types": "npm:^27.5.1" - expect: "npm:^27.5.1" - checksum: 10/f3b06e9b81686d7a5dd7bafb229cba73bdc90d3e16815deebf302d3a402ac29a1e9bafa274d908caefe7083938402619974c89420d247ab8739acd652c11b16d - languageName: node - linkType: hard - "@jest/globals@npm:^29.7.0": version: 29.7.0 resolution: "@jest/globals@npm:29.7.0" @@ -2070,44 +1978,6 @@ __metadata: languageName: node linkType: hard -"@jest/reporters@npm:^27.5.1": - version: 27.5.1 - resolution: "@jest/reporters@npm:27.5.1" - dependencies: - "@bcoe/v8-coverage": "npm:^0.2.3" - "@jest/console": "npm:^27.5.1" - "@jest/test-result": "npm:^27.5.1" - "@jest/transform": "npm:^27.5.1" - "@jest/types": "npm:^27.5.1" - "@types/node": "npm:*" - chalk: "npm:^4.0.0" - collect-v8-coverage: "npm:^1.0.0" - exit: "npm:^0.1.2" - glob: "npm:^7.1.2" - graceful-fs: "npm:^4.2.9" - istanbul-lib-coverage: "npm:^3.0.0" - istanbul-lib-instrument: "npm:^5.1.0" - istanbul-lib-report: "npm:^3.0.0" - istanbul-lib-source-maps: "npm:^4.0.0" - istanbul-reports: "npm:^3.1.3" - jest-haste-map: "npm:^27.5.1" - jest-resolve: "npm:^27.5.1" - jest-util: "npm:^27.5.1" - jest-worker: "npm:^27.5.1" - slash: "npm:^3.0.0" - source-map: "npm:^0.6.0" - string-length: "npm:^4.0.1" - terminal-link: "npm:^2.0.0" - v8-to-istanbul: "npm:^8.1.0" - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - checksum: 10/d49aea4e5b09f9a316f0ff303d11f2db057cadaf370e3e706c024e4ea7f270899cccf7488711def4a930bc23e4f4676f406d1c646f8c6656de4c43dd40652877 - languageName: node - linkType: hard - "@jest/reporters@npm:^29.7.0": version: 29.7.0 resolution: "@jest/reporters@npm:29.7.0" @@ -2154,17 +2024,6 @@ __metadata: languageName: node linkType: hard -"@jest/source-map@npm:^27.5.1": - version: 27.5.1 - resolution: "@jest/source-map@npm:27.5.1" - dependencies: - callsites: "npm:^3.0.0" - graceful-fs: "npm:^4.2.9" - source-map: "npm:^0.6.0" - checksum: 10/90b1f4212b7191d594275c9b9aae18319b944e4ed018af74a1661fd9b783983074d00369a111274697b87193aa2b084f0f022a265d070f4a66d39d06d14a0336 - languageName: node - linkType: hard - "@jest/source-map@npm:^29.6.3": version: 29.6.3 resolution: "@jest/source-map@npm:29.6.3" @@ -2176,18 +2035,6 @@ __metadata: languageName: node linkType: hard -"@jest/test-result@npm:^27.5.1": - version: 27.5.1 - resolution: "@jest/test-result@npm:27.5.1" - dependencies: - "@jest/console": "npm:^27.5.1" - "@jest/types": "npm:^27.5.1" - "@types/istanbul-lib-coverage": "npm:^2.0.0" - collect-v8-coverage: "npm:^1.0.0" - checksum: 10/43cdc31b39857d4d6487345f1bfb9c97157ddfb7ff3e3b843f3999d4a3be5b1e7c1079302459ea627976fa9da7462426dfb26cf231ef2b6eb79bc80b67361c23 - languageName: node - linkType: hard - "@jest/test-result@npm:^29.7.0": version: 29.7.0 resolution: "@jest/test-result@npm:29.7.0" @@ -2200,18 +2047,6 @@ __metadata: languageName: node linkType: hard -"@jest/test-sequencer@npm:^27.5.1": - version: 27.5.1 - resolution: "@jest/test-sequencer@npm:27.5.1" - dependencies: - "@jest/test-result": "npm:^27.5.1" - graceful-fs: "npm:^4.2.9" - jest-haste-map: "npm:^27.5.1" - jest-runtime: "npm:^27.5.1" - checksum: 10/74c9c773eb0d8de581e17a7ea1d9173b835c0c91b40665caa42fd68931a2ee7429f9ed59c97a15855d3ad46024a17e7387ad4b900d4540890a7681d4a8a42bdd - languageName: node - linkType: hard - "@jest/test-sequencer@npm:^29.7.0": version: 29.7.0 resolution: "@jest/test-sequencer@npm:29.7.0" @@ -2224,29 +2059,6 @@ __metadata: languageName: node linkType: hard -"@jest/transform@npm:^27.5.1": - version: 27.5.1 - resolution: "@jest/transform@npm:27.5.1" - dependencies: - "@babel/core": "npm:^7.1.0" - "@jest/types": "npm:^27.5.1" - babel-plugin-istanbul: "npm:^6.1.1" - chalk: "npm:^4.0.0" - convert-source-map: "npm:^1.4.0" - fast-json-stable-stringify: "npm:^2.0.0" - graceful-fs: "npm:^4.2.9" - jest-haste-map: "npm:^27.5.1" - jest-regex-util: "npm:^27.5.1" - jest-util: "npm:^27.5.1" - micromatch: "npm:^4.0.4" - pirates: "npm:^4.0.4" - slash: "npm:^3.0.0" - source-map: "npm:^0.6.1" - write-file-atomic: "npm:^3.0.0" - checksum: 10/9e0bec99971d28fc205e5e282be384a0269760b8452aa94e3d400465819b6c790c862ec5597d8c9439f2da97e68c0c4cec071340ff3e4c4414a34e5b2a19074a - languageName: node - linkType: hard - "@jest/transform@npm:^29.7.0": version: 29.7.0 resolution: "@jest/transform@npm:29.7.0" @@ -2283,19 +2095,6 @@ __metadata: languageName: node linkType: hard -"@jest/types@npm:^27.5.1": - version: 27.5.1 - resolution: "@jest/types@npm:27.5.1" - dependencies: - "@types/istanbul-lib-coverage": "npm:^2.0.0" - "@types/istanbul-reports": "npm:^3.0.0" - "@types/node": "npm:*" - "@types/yargs": "npm:^16.0.0" - chalk: "npm:^4.0.0" - checksum: 10/d3ca1655673539c54665f3e9135dc70887feb6b667b956e712c38f42e513ae007d3593b8075aecea8f2db7119f911773010f17f93be070b1725fbc6225539b6e - languageName: node - linkType: hard - "@jest/types@npm:^29.6.3": version: 29.6.3 resolution: "@jest/types@npm:29.6.3" @@ -3142,13 +2941,13 @@ __metadata: "@metamask/superstruct": "npm:^3.1.0" "@metamask/utils": "npm:^11.9.0" "@ts-bridge/cli": "npm:^0.6.4" - "@types/jest": "npm:^27.5.2" + "@types/jest": "npm:^29.5.14" deepmerge: "npm:^4.2.2" - jest: "npm:^27.5.1" + jest: "npm:^29.7.0" nock: "npm:^13.3.1" reselect: "npm:^5.1.1" sinon: "npm:^9.2.4" - ts-jest: "npm:^27.1.5" + ts-jest: "npm:^29.2.5" typedoc: "npm:^0.24.8" typedoc-plugin-missing-exports: "npm:^2.0.0" typescript: "npm:~5.3.3" @@ -5787,15 +5586,6 @@ __metadata: languageName: node linkType: hard -"@sinonjs/fake-timers@npm:^8.0.1": - version: 8.1.0 - resolution: "@sinonjs/fake-timers@npm:8.1.0" - dependencies: - "@sinonjs/commons": "npm:^1.7.0" - checksum: 10/da50ddd68411617fcf72d9fb70b621aa2a6d17faa93a2769c7af390c88b40e045f84544db022dd1ac30a6db115d2a0f96473854d4a106b0174351f22d42910ce - languageName: node - linkType: hard - "@sinonjs/samsam@npm:^5.3.1": version: 5.3.1 resolution: "@sinonjs/samsam@npm:5.3.1" @@ -5954,13 +5744,6 @@ __metadata: languageName: node linkType: hard -"@tootallnate/once@npm:1": - version: 1.1.2 - resolution: "@tootallnate/once@npm:1.1.2" - checksum: 10/e1fb1bbbc12089a0cb9433dc290f97bddd062deadb6178ce9bcb93bb7c1aecde5e60184bc7065aec42fe1663622a213493c48bbd4972d931aae48315f18e1be9 - languageName: node - linkType: hard - "@tootallnate/once@npm:2": version: 2.0.0 resolution: "@tootallnate/once@npm:2.0.0" @@ -6067,7 +5850,7 @@ __metadata: languageName: node linkType: hard -"@types/babel__core@npm:^7.0.0, @types/babel__core@npm:^7.1.14": +"@types/babel__core@npm:^7.1.14": version: 7.20.5 resolution: "@types/babel__core@npm:7.20.5" dependencies: @@ -6108,15 +5891,6 @@ __metadata: languageName: node linkType: hard -"@types/babel__traverse@npm:^7.0.4": - version: 7.28.0 - resolution: "@types/babel__traverse@npm:7.28.0" - dependencies: - "@babel/types": "npm:^7.28.2" - checksum: 10/371c5e1b40399ef17570e630b2943617b84fafde2860a56f0ebc113d8edb1d0534ade0175af89eda1ae35160903c33057ed42457e165d4aa287fedab2c82abcf - languageName: node - linkType: hard - "@types/bn.js@npm:*, @types/bn.js@npm:^5.1.0, @types/bn.js@npm:^5.1.5": version: 5.1.6 resolution: "@types/bn.js@npm:5.1.6" @@ -6185,7 +5959,7 @@ __metadata: languageName: node linkType: hard -"@types/graceful-fs@npm:^4.1.2, @types/graceful-fs@npm:^4.1.3": +"@types/graceful-fs@npm:^4.1.3": version: 4.1.9 resolution: "@types/graceful-fs@npm:4.1.9" dependencies: @@ -6238,16 +6012,6 @@ __metadata: languageName: node linkType: hard -"@types/jest@npm:^27.5.2": - version: 27.5.2 - resolution: "@types/jest@npm:27.5.2" - dependencies: - jest-matcher-utils: "npm:^27.0.0" - pretty-format: "npm:^27.0.0" - checksum: 10/8608696fbdea81bc9a600d1c5aeb290063357eaa55c0174e7db15087c4f483113b35f8b4c4ae364d2632cfed15a4dd674786254826b946c896de5612c8cb1a26 - languageName: node - linkType: hard - "@types/jsdom@npm:^20.0.0": version: 20.0.1 resolution: "@types/jsdom@npm:20.0.1" @@ -6371,13 +6135,6 @@ __metadata: languageName: node linkType: hard -"@types/prettier@npm:^2.1.5": - version: 2.7.3 - resolution: "@types/prettier@npm:2.7.3" - checksum: 10/cda84c19acc3bf327545b1ce71114a7d08efbd67b5030b9e8277b347fa57b05178045f70debe1d363ff7efdae62f237260713aafc2d7217e06fc99b048a88497 - languageName: node - linkType: hard - "@types/punycode@npm:^2.1.0": version: 2.1.4 resolution: "@types/punycode@npm:2.1.4" @@ -6464,15 +6221,6 @@ __metadata: languageName: node linkType: hard -"@types/yargs@npm:^16.0.0": - version: 16.0.11 - resolution: "@types/yargs@npm:16.0.11" - dependencies: - "@types/yargs-parser": "npm:*" - checksum: 10/b083eb4e377a9488b67d5767053a3ef531c142478d04b227529db29f5f3ccc98bc555dbe842b47edadd9901cdae03ce0b75828abfd7e70f8db614b5eabf9db9f - languageName: node - linkType: hard - "@types/yargs@npm:^17.0.32, @types/yargs@npm:^17.0.8": version: 17.0.33 resolution: "@types/yargs@npm:17.0.33" @@ -6697,7 +6445,7 @@ __metadata: languageName: node linkType: hard -"abab@npm:^2.0.3, abab@npm:^2.0.5, abab@npm:^2.0.6": +"abab@npm:^2.0.6": version: 2.0.6 resolution: "abab@npm:2.0.6" checksum: 10/ebe95d7278999e605823fc515a3b05d689bc72e7f825536e73c95ebf621636874c6de1b749b3c4bf866b96ccd4b3a2802efa313d0e45ad51a413c8c73247db20 @@ -6730,16 +6478,6 @@ __metadata: languageName: node linkType: hard -"acorn-globals@npm:^6.0.0": - version: 6.0.0 - resolution: "acorn-globals@npm:6.0.0" - dependencies: - acorn: "npm:^7.1.1" - acorn-walk: "npm:^7.1.1" - checksum: 10/72d95e5b5e585f9acd019b993ab8bbba68bb3cbc9d9b5c1ebb3c2f1fe5981f11deababfb4949f48e6262f9c57878837f5958c0cca396f81023814680ca878042 - languageName: node - linkType: hard - "acorn-globals@npm:^7.0.0": version: 7.0.1 resolution: "acorn-globals@npm:7.0.1" @@ -6759,13 +6497,6 @@ __metadata: languageName: node linkType: hard -"acorn-walk@npm:^7.1.1": - version: 7.2.0 - resolution: "acorn-walk@npm:7.2.0" - checksum: 10/4d3e186f729474aed3bc3d0df44692f2010c726582655b20a23347bef650867655521c48ada444cb4fda241ee713dcb792da363ec74c6282fa884fb7144171bb - languageName: node - linkType: hard - "acorn-walk@npm:^8.0.2": version: 8.3.4 resolution: "acorn-walk@npm:8.3.4" @@ -6775,16 +6506,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^7.1.1": - version: 7.4.1 - resolution: "acorn@npm:7.4.1" - bin: - acorn: bin/acorn - checksum: 10/8be2a40714756d713dfb62544128adce3b7102c6eb94bc312af196c2cc4af76e5b93079bd66b05e9ca31b35a9b0ce12171d16bc55f366cafdb794fdab9d753ec - languageName: node - linkType: hard - -"acorn@npm:^8.1.0, acorn@npm:^8.11.0, acorn@npm:^8.15.0, acorn@npm:^8.2.4, acorn@npm:^8.8.1": +"acorn@npm:^8.1.0, acorn@npm:^8.11.0, acorn@npm:^8.15.0, acorn@npm:^8.8.1": version: 8.15.0 resolution: "acorn@npm:8.15.0" bin: @@ -6996,20 +6718,6 @@ __metadata: languageName: node linkType: hard -"async-function@npm:^1.0.0": - version: 1.0.0 - resolution: "async-function@npm:1.0.0" - checksum: 10/1a09379937d846f0ce7614e75071c12826945d4e417db634156bf0e4673c495989302f52186dfa9767a1d9181794554717badd193ca2bbab046ef1da741d8efd - languageName: node - linkType: hard - -"async-generator-function@npm:^1.0.0": - version: 1.0.0 - resolution: "async-generator-function@npm:1.0.0" - checksum: 10/3d49e7acbeee9e84537f4cb0e0f91893df8eba976759875ae8ee9e3d3c82f6ecdebdb347c2fad9926b92596d93cdfc78ecc988bcdf407e40433e8e8e6fe5d78e - languageName: node - linkType: hard - "async-mutex@npm:^0.3.1": version: 0.3.2 resolution: "async-mutex@npm:0.3.2" @@ -7053,24 +6761,6 @@ __metadata: languageName: node linkType: hard -"babel-jest@npm:^27.5.1": - version: 27.5.1 - resolution: "babel-jest@npm:27.5.1" - dependencies: - "@jest/transform": "npm:^27.5.1" - "@jest/types": "npm:^27.5.1" - "@types/babel__core": "npm:^7.1.14" - babel-plugin-istanbul: "npm:^6.1.1" - babel-preset-jest: "npm:^27.5.1" - chalk: "npm:^4.0.0" - graceful-fs: "npm:^4.2.9" - slash: "npm:^3.0.0" - peerDependencies: - "@babel/core": ^7.8.0 - checksum: 10/d032823796072b3c269edaa623dd7fe6ecf2f72aff5b003066e7b16ad0ec4068ed04f3f569237183161d28b638936121975014bcb26ae539e669f2bdad5babe6 - languageName: node - linkType: hard - "babel-jest@npm:^29.7.0": version: 29.7.0 resolution: "babel-jest@npm:29.7.0" @@ -7101,18 +6791,6 @@ __metadata: languageName: node linkType: hard -"babel-plugin-jest-hoist@npm:^27.5.1": - version: 27.5.1 - resolution: "babel-plugin-jest-hoist@npm:27.5.1" - dependencies: - "@babel/template": "npm:^7.3.3" - "@babel/types": "npm:^7.3.3" - "@types/babel__core": "npm:^7.0.0" - "@types/babel__traverse": "npm:^7.0.6" - checksum: 10/9e334903433fd92ef9a65ea5c61f7d786238704b1327d9ca227ef40ef7142fba2bb8219bcb9b2d56eaf36ecfbcc50aa1e177db64508438569e98cfd67cce5043 - languageName: node - linkType: hard - "babel-plugin-jest-hoist@npm:^29.6.3": version: 29.6.3 resolution: "babel-plugin-jest-hoist@npm:29.6.3" @@ -7150,18 +6828,6 @@ __metadata: languageName: node linkType: hard -"babel-preset-jest@npm:^27.5.1": - version: 27.5.1 - resolution: "babel-preset-jest@npm:27.5.1" - dependencies: - babel-plugin-jest-hoist: "npm:^27.5.1" - babel-preset-current-node-syntax: "npm:^1.0.0" - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 10/251bcea11c18fd9672fec104eadb45b43f117ceeb326fa7345ced778d4c1feab29343cd7a87a1dcfae4997d6c851a8b386d7f7213792da6e23b74f4443a8976d - languageName: node - linkType: hard - "babel-preset-jest@npm:^29.6.3": version: 29.6.3 resolution: "babel-preset-jest@npm:29.6.3" @@ -7362,13 +7028,6 @@ __metadata: languageName: node linkType: hard -"browser-process-hrtime@npm:^1.0.0": - version: 1.0.0 - resolution: "browser-process-hrtime@npm:1.0.0" - checksum: 10/e30f868cdb770b1201afb714ad1575dd86366b6e861900884665fb627109b3cc757c40067d3bfee1ff2a29c835257ea30725a8018a9afd02ac1c24b408b1e45f - languageName: node - linkType: hard - "browserify-aes@npm:^1.2.0": version: 1.2.0 resolution: "browserify-aes@npm:1.2.0" @@ -7397,7 +7056,7 @@ __metadata: languageName: node linkType: hard -"bs-logger@npm:0.x, bs-logger@npm:^0.2.6": +"bs-logger@npm:^0.2.6": version: 0.2.6 resolution: "bs-logger@npm:0.2.6" dependencies: @@ -7832,13 +7491,6 @@ __metadata: languageName: node linkType: hard -"convert-source-map@npm:^1.4.0, convert-source-map@npm:^1.6.0": - version: 1.9.0 - resolution: "convert-source-map@npm:1.9.0" - checksum: 10/dc55a1f28ddd0e9485ef13565f8f756b342f9a46c4ae18b843fe3c30c675d058d6a4823eff86d472f187b176f0adf51ea7b69ea38be34be4a63cbbf91b0593c8 - languageName: node - linkType: hard - "convert-source-map@npm:^2.0.0": version: 2.0.0 resolution: "convert-source-map@npm:2.0.0" @@ -7960,13 +7612,6 @@ __metadata: languageName: node linkType: hard -"cssom@npm:^0.4.4": - version: 0.4.4 - resolution: "cssom@npm:0.4.4" - checksum: 10/6302c5f9b33a15f5430349f91553dd370f60707b1f2bb2c21954abe307b701d6095da134679fd0891a7814bc98061e1639bd0562d8f70c2dc529918111be8d2b - languageName: node - linkType: hard - "cssom@npm:^0.5.0": version: 0.5.0 resolution: "cssom@npm:0.5.0" @@ -7990,17 +7635,6 @@ __metadata: languageName: node linkType: hard -"data-urls@npm:^2.0.0": - version: 2.0.0 - resolution: "data-urls@npm:2.0.0" - dependencies: - abab: "npm:^2.0.3" - whatwg-mimetype: "npm:^2.3.0" - whatwg-url: "npm:^8.0.0" - checksum: 10/97caf828aac25e25e04ba6869db0f99c75e6859bb5b424ada28d3e7841941ebf08ddff3c1b1bb4585986bd507a5d54c2a716853ea6cb98af877400e637393e71 - languageName: node - linkType: hard - "data-urls@npm:^3.0.2": version: 3.0.2 resolution: "data-urls@npm:3.0.2" @@ -8059,20 +7693,13 @@ __metadata: languageName: node linkType: hard -"decimal.js@npm:^10.2.1, decimal.js@npm:^10.4.2": +"decimal.js@npm:^10.4.2": version: 10.6.0 resolution: "decimal.js@npm:10.6.0" checksum: 10/c0d45842d47c311d11b38ce7ccc911121953d4df3ebb1465d92b31970eb4f6738a065426a06094af59bee4b0d64e42e7c8984abd57b6767c64ea90cf90bb4a69 languageName: node linkType: hard -"dedent@npm:^0.7.0": - version: 0.7.0 - resolution: "dedent@npm:0.7.0" - checksum: 10/87de191050d9a40dd70cad01159a0bcf05ecb59750951242070b6abf9569088684880d00ba92a955b4058804f16eeaf91d604f283929b4f614d181cd7ae633d2 - languageName: node - linkType: hard - "dedent@npm:^1.0.0": version: 1.7.1 resolution: "dedent@npm:1.7.1" @@ -8244,13 +7871,6 @@ __metadata: languageName: node linkType: hard -"diff-sequences@npm:^27.5.1": - version: 27.5.1 - resolution: "diff-sequences@npm:27.5.1" - checksum: 10/34d852a13eb82735c39944a050613f952038614ce324256e1c3544948fa090f1ca7f329a4f1f57c31fe7ac982c17068d8915b633e300f040b97708c81ceb26cd - languageName: node - linkType: hard - "diff-sequences@npm:^29.6.3": version: 29.6.3 resolution: "diff-sequences@npm:29.6.3" @@ -8290,15 +7910,6 @@ __metadata: languageName: node linkType: hard -"domexception@npm:^2.0.1": - version: 2.0.1 - resolution: "domexception@npm:2.0.1" - dependencies: - webidl-conversions: "npm:^5.0.0" - checksum: 10/d638e9cb05c52999f1b2eb87c374b03311ea5b1d69c2f875bc92da73e17db60c12142b45c950228642ff7f845c536b65305483350d080df59003a653da80b691 - languageName: node - linkType: hard - "domexception@npm:^4.0.0": version: 4.0.0 resolution: "domexception@npm:4.0.0" @@ -8371,13 +7982,6 @@ __metadata: languageName: node linkType: hard -"emittery@npm:^0.8.1": - version: 0.8.1 - resolution: "emittery@npm:0.8.1" - checksum: 10/3b882c0bdc3121b4e92b85315f87da0db8e965766d6c7ff70a8f45e0c38ed49d561936650afa32759d8fb320a458bc9e12631799a0a276e9e8a960ae16c1f6f1 - languageName: node - linkType: hard - "emoji-regex@npm:^8.0.0": version: 8.0.0 resolution: "emoji-regex@npm:8.0.0" @@ -8492,18 +8096,6 @@ __metadata: languageName: node linkType: hard -"es-set-tostringtag@npm:^2.1.0": - version: 2.1.0 - resolution: "es-set-tostringtag@npm:2.1.0" - dependencies: - es-errors: "npm:^1.3.0" - get-intrinsic: "npm:^1.2.6" - has-tostringtag: "npm:^1.0.2" - hasown: "npm:^2.0.2" - checksum: 10/86814bf8afbcd8966653f731415888019d4bc4aca6b6c354132a7a75bb87566751e320369654a101d23a91c87a85c79b178bcf40332839bd347aff437c4fb65f - languageName: node - linkType: hard - "esbuild@npm:~0.25.0": version: 0.25.9 resolution: "esbuild@npm:0.25.9" @@ -9178,18 +8770,6 @@ __metadata: languageName: node linkType: hard -"expect@npm:^27.5.1": - version: 27.5.1 - resolution: "expect@npm:27.5.1" - dependencies: - "@jest/types": "npm:^27.5.1" - jest-get-type: "npm:^27.5.1" - jest-matcher-utils: "npm:^27.5.1" - jest-message-util: "npm:^27.5.1" - checksum: 10/65152be11e791361bb8f74b2516b6ba83021ac4a280b16575340a7dbb72be7fb51b021119a3f40f309a36b375cfb05d4854d5d7af3c53a293a342afc7f86bdaa - languageName: node - linkType: hard - "expect@npm:^29.0.0, expect@npm:^29.7.0": version: 29.7.0 resolution: "expect@npm:29.7.0" @@ -9541,19 +9121,6 @@ __metadata: languageName: node linkType: hard -"form-data@npm:^3.0.0": - version: 3.0.4 - resolution: "form-data@npm:3.0.4" - dependencies: - asynckit: "npm:^0.4.0" - combined-stream: "npm:^1.0.8" - es-set-tostringtag: "npm:^2.1.0" - hasown: "npm:^2.0.2" - mime-types: "npm:^2.1.35" - checksum: 10/68e4598e55cb193ef80304bff4d7513bf81ed4116d57b29c6c9a4c28c6f7ce57d46ddd60ba1a80aadf26703a722551e660bca2acaf9212d8b6e1f2e180d9e668 - languageName: node - linkType: hard - "form-data@npm:^4.0.0": version: 4.0.0 resolution: "form-data@npm:4.0.0" @@ -9652,13 +9219,6 @@ __metadata: languageName: node linkType: hard -"generator-function@npm:^2.0.0": - version: 2.0.1 - resolution: "generator-function@npm:2.0.1" - checksum: 10/eb7e7eb896c5433f3d40982b2ccacdb3dd990dd3499f14040e002b5d54572476513be8a2e6f9609f6e41ab29f2c4469307611ddbfc37ff4e46b765c326663805 - languageName: node - linkType: hard - "gensync@npm:^1.0.0-beta.2": version: 1.0.0-beta.2 resolution: "gensync@npm:1.0.0-beta.2" @@ -9691,27 +9251,6 @@ __metadata: languageName: node linkType: hard -"get-intrinsic@npm:^1.2.6": - version: 1.3.1 - resolution: "get-intrinsic@npm:1.3.1" - dependencies: - async-function: "npm:^1.0.0" - async-generator-function: "npm:^1.0.0" - call-bind-apply-helpers: "npm:^1.0.2" - es-define-property: "npm:^1.0.1" - es-errors: "npm:^1.3.0" - es-object-atoms: "npm:^1.1.1" - function-bind: "npm:^1.1.2" - generator-function: "npm:^2.0.0" - get-proto: "npm:^1.0.1" - gopd: "npm:^1.2.0" - has-symbols: "npm:^1.1.0" - hasown: "npm:^2.0.2" - math-intrinsics: "npm:^1.1.0" - checksum: 10/bb579dda84caa4a3a41611bdd483dade7f00f246f2a7992eb143c5861155290df3fdb48a8406efa3dfb0b434e2c8fafa4eebd469e409d0439247f85fc3fa2cc1 - languageName: node - linkType: hard - "get-npm-tarball-url@npm:^2.0.3": version: 2.1.0 resolution: "get-npm-tarball-url@npm:2.1.0" @@ -9807,7 +9346,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^7.1.1, glob@npm:^7.1.2, glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.7": +"glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.7": version: 7.2.3 resolution: "glob@npm:7.2.3" dependencies: @@ -9941,22 +9480,13 @@ __metadata: languageName: node linkType: hard -"has-symbols@npm:^1.0.3, has-symbols@npm:^1.1.0": +"has-symbols@npm:^1.1.0": version: 1.1.0 resolution: "has-symbols@npm:1.1.0" checksum: 10/959385c98696ebbca51e7534e0dc723ada325efa3475350951363cce216d27373e0259b63edb599f72eb94d6cde8577b4b2375f080b303947e560f85692834fa languageName: node linkType: hard -"has-tostringtag@npm:^1.0.2": - version: 1.0.2 - resolution: "has-tostringtag@npm:1.0.2" - dependencies: - has-symbols: "npm:^1.0.3" - checksum: 10/c74c5f5ceee3c8a5b8bc37719840dc3749f5b0306d818974141dda2471a1a2ca6c8e46b9d6ac222c5345df7a901c9b6f350b1e6d62763fec877e26609a401bfe - languageName: node - linkType: hard - "hash-base@npm:^3.0.0": version: 3.1.0 resolution: "hash-base@npm:3.1.0" @@ -10032,15 +9562,6 @@ __metadata: languageName: node linkType: hard -"html-encoding-sniffer@npm:^2.0.1": - version: 2.0.1 - resolution: "html-encoding-sniffer@npm:2.0.1" - dependencies: - whatwg-encoding: "npm:^1.0.5" - checksum: 10/70365109cad69ee60376715fe0a56dd9ebb081327bf155cda93b2c276976c79cbedee2b988de6b0aefd0671a5d70597a35796e6e7d91feeb2c0aba46df059630 - languageName: node - linkType: hard - "html-encoding-sniffer@npm:^3.0.0": version: 3.0.0 resolution: "html-encoding-sniffer@npm:3.0.0" @@ -10084,17 +9605,6 @@ __metadata: languageName: node linkType: hard -"http-proxy-agent@npm:^4.0.1": - version: 4.0.1 - resolution: "http-proxy-agent@npm:4.0.1" - dependencies: - "@tootallnate/once": "npm:1" - agent-base: "npm:6" - debug: "npm:4" - checksum: 10/2e17f5519f2f2740b236d1d14911ea4be170c67419dc15b05ea9a860a22c5d9c6ff4da270972117067cc2cefeba9df5f7cd5e7818fdc6ae52b6acf2a533e5fdd - languageName: node - linkType: hard - "http-proxy-agent@npm:^5.0.0": version: 5.0.0 resolution: "http-proxy-agent@npm:5.0.0" @@ -10116,7 +9626,7 @@ __metadata: languageName: node linkType: hard -"https-proxy-agent@npm:^5.0.0, https-proxy-agent@npm:^5.0.1": +"https-proxy-agent@npm:^5.0.1": version: 5.0.1 resolution: "https-proxy-agent@npm:5.0.1" dependencies: @@ -10452,13 +9962,6 @@ __metadata: languageName: node linkType: hard -"is-typedarray@npm:^1.0.0": - version: 1.0.0 - resolution: "is-typedarray@npm:1.0.0" - checksum: 10/4b433bfb0f9026f079f4eb3fbaa4ed2de17c9995c3a0b5c800bec40799b4b2a8b4e051b1ada77749deb9ded4ae52fe2096973f3a93ff83df1a5a7184a669478c - languageName: node - linkType: hard - "is-unicode-supported@npm:^0.1.0": version: 0.1.0 resolution: "is-unicode-supported@npm:0.1.0" @@ -10534,7 +10037,7 @@ __metadata: languageName: node linkType: hard -"istanbul-lib-instrument@npm:^5.0.4, istanbul-lib-instrument@npm:^5.1.0": +"istanbul-lib-instrument@npm:^5.0.4": version: 5.2.1 resolution: "istanbul-lib-instrument@npm:5.2.1" dependencies: @@ -10605,17 +10108,6 @@ __metadata: languageName: node linkType: hard -"jest-changed-files@npm:^27.5.1": - version: 27.5.1 - resolution: "jest-changed-files@npm:27.5.1" - dependencies: - "@jest/types": "npm:^27.5.1" - execa: "npm:^5.0.0" - throat: "npm:^6.0.1" - checksum: 10/fad21687f899e527bc23b3cabda1b1fa74acb8e17e81bca4d6ca10ab83ebf1d7555f38ba66dda148f97c45b816f941aa4694a09ed0d16a4d7fe3216abf1a222f - languageName: node - linkType: hard - "jest-changed-files@npm:^29.7.0": version: 29.7.0 resolution: "jest-changed-files@npm:29.7.0" @@ -10627,33 +10119,6 @@ __metadata: languageName: node linkType: hard -"jest-circus@npm:^27.5.1": - version: 27.5.1 - resolution: "jest-circus@npm:27.5.1" - dependencies: - "@jest/environment": "npm:^27.5.1" - "@jest/test-result": "npm:^27.5.1" - "@jest/types": "npm:^27.5.1" - "@types/node": "npm:*" - chalk: "npm:^4.0.0" - co: "npm:^4.6.0" - dedent: "npm:^0.7.0" - expect: "npm:^27.5.1" - is-generator-fn: "npm:^2.0.0" - jest-each: "npm:^27.5.1" - jest-matcher-utils: "npm:^27.5.1" - jest-message-util: "npm:^27.5.1" - jest-runtime: "npm:^27.5.1" - jest-snapshot: "npm:^27.5.1" - jest-util: "npm:^27.5.1" - pretty-format: "npm:^27.5.1" - slash: "npm:^3.0.0" - stack-utils: "npm:^2.0.3" - throat: "npm:^6.0.1" - checksum: 10/cf8502d2c7669a89d6d9c309842a6bae1b336335f9a108b0ba3d555dcc635c6cc119d28627a5df455215a8bb04bdcdf18b1fee3441aca39c78c8b10053cd33f7 - languageName: node - linkType: hard - "jest-circus@npm:^29.7.0": version: 29.7.0 resolution: "jest-circus@npm:29.7.0" @@ -10682,33 +10147,6 @@ __metadata: languageName: node linkType: hard -"jest-cli@npm:^27.5.1": - version: 27.5.1 - resolution: "jest-cli@npm:27.5.1" - dependencies: - "@jest/core": "npm:^27.5.1" - "@jest/test-result": "npm:^27.5.1" - "@jest/types": "npm:^27.5.1" - chalk: "npm:^4.0.0" - exit: "npm:^0.1.2" - graceful-fs: "npm:^4.2.9" - import-local: "npm:^3.0.2" - jest-config: "npm:^27.5.1" - jest-util: "npm:^27.5.1" - jest-validate: "npm:^27.5.1" - prompts: "npm:^2.0.1" - yargs: "npm:^16.2.0" - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - bin: - jest: bin/jest.js - checksum: 10/527be160786a14f541b3f75e6241da1bd9ba51894fc9f2ba6466dba7f6ffd3a03de02b40d172ad1d29edc725847f7dd4f6dbf71d304d2364b075ec81c9a53224 - languageName: node - linkType: hard - "jest-cli@npm:^29.7.0": version: 29.7.0 resolution: "jest-cli@npm:29.7.0" @@ -10735,43 +10173,6 @@ __metadata: languageName: node linkType: hard -"jest-config@npm:^27.5.1": - version: 27.5.1 - resolution: "jest-config@npm:27.5.1" - dependencies: - "@babel/core": "npm:^7.8.0" - "@jest/test-sequencer": "npm:^27.5.1" - "@jest/types": "npm:^27.5.1" - babel-jest: "npm:^27.5.1" - chalk: "npm:^4.0.0" - ci-info: "npm:^3.2.0" - deepmerge: "npm:^4.2.2" - glob: "npm:^7.1.1" - graceful-fs: "npm:^4.2.9" - jest-circus: "npm:^27.5.1" - jest-environment-jsdom: "npm:^27.5.1" - jest-environment-node: "npm:^27.5.1" - jest-get-type: "npm:^27.5.1" - jest-jasmine2: "npm:^27.5.1" - jest-regex-util: "npm:^27.5.1" - jest-resolve: "npm:^27.5.1" - jest-runner: "npm:^27.5.1" - jest-util: "npm:^27.5.1" - jest-validate: "npm:^27.5.1" - micromatch: "npm:^4.0.4" - parse-json: "npm:^5.2.0" - pretty-format: "npm:^27.5.1" - slash: "npm:^3.0.0" - strip-json-comments: "npm:^3.1.1" - peerDependencies: - ts-node: ">=9.0.0" - peerDependenciesMeta: - ts-node: - optional: true - checksum: 10/63bc2dce50289ff921debedab766daa5122129671c77a9f4137d153a27b29ef77725db15d4809553b687c83495cd7ffefc8eadfd8dfa940d7ea878de57f428c2 - languageName: node - linkType: hard - "jest-config@npm:^29.7.0": version: 29.7.0 resolution: "jest-config@npm:29.7.0" @@ -10810,18 +10211,6 @@ __metadata: languageName: node linkType: hard -"jest-diff@npm:^27.5.1": - version: 27.5.1 - resolution: "jest-diff@npm:27.5.1" - dependencies: - chalk: "npm:^4.0.0" - diff-sequences: "npm:^27.5.1" - jest-get-type: "npm:^27.5.1" - pretty-format: "npm:^27.5.1" - checksum: 10/af454f30f33af625832bdb02614e188a41e33ce79086b43f95dbcc515274dd36bf8443b8d0299e22c2416e7591da4321e6bc7f2b0aef56471d1133c6b6833221 - languageName: node - linkType: hard - "jest-diff@npm:^29.0.3, jest-diff@npm:^29.7.0": version: 29.7.0 resolution: "jest-diff@npm:29.7.0" @@ -10834,15 +10223,6 @@ __metadata: languageName: node linkType: hard -"jest-docblock@npm:^27.5.1": - version: 27.5.1 - resolution: "jest-docblock@npm:27.5.1" - dependencies: - detect-newline: "npm:^3.0.0" - checksum: 10/65c765c5418986313685b7c49dcd844cd3bc281807a35f778d6ba479246b6ea070cdd98384582a9aed1a0d3ebf94b7fb14a33df5975aaae2eb20dc00281731f4 - languageName: node - linkType: hard - "jest-docblock@npm:^29.7.0": version: 29.7.0 resolution: "jest-docblock@npm:29.7.0" @@ -10852,19 +10232,6 @@ __metadata: languageName: node linkType: hard -"jest-each@npm:^27.5.1": - version: 27.5.1 - resolution: "jest-each@npm:27.5.1" - dependencies: - "@jest/types": "npm:^27.5.1" - chalk: "npm:^4.0.0" - jest-get-type: "npm:^27.5.1" - jest-util: "npm:^27.5.1" - pretty-format: "npm:^27.5.1" - checksum: 10/d73e3c7bbcd3a073e9fa29bd1f200bb9757cbcc568460c1d0971fc21924800f2d3e421219a85e20c54ea2a0129d2da9e2dfc266b6014244c5901f3ca2de7a99e - languageName: node - linkType: hard - "jest-each@npm:^29.7.0": version: 29.7.0 resolution: "jest-each@npm:29.7.0" @@ -10878,21 +10245,6 @@ __metadata: languageName: node linkType: hard -"jest-environment-jsdom@npm:^27.5.1": - version: 27.5.1 - resolution: "jest-environment-jsdom@npm:27.5.1" - dependencies: - "@jest/environment": "npm:^27.5.1" - "@jest/fake-timers": "npm:^27.5.1" - "@jest/types": "npm:^27.5.1" - "@types/node": "npm:*" - jest-mock: "npm:^27.5.1" - jest-util: "npm:^27.5.1" - jsdom: "npm:^16.6.0" - checksum: 10/bc104aef7d7530d0740402aa84ac812138b6d1e51fe58adecce679f82b99340ddab73e5ec68fa079f33f50c9ddec9728fc9f0ddcca2ad6f0b351eed2762cc555 - languageName: node - linkType: hard - "jest-environment-jsdom@npm:^29.7.0": version: 29.7.0 resolution: "jest-environment-jsdom@npm:29.7.0" @@ -10914,20 +10266,6 @@ __metadata: languageName: node linkType: hard -"jest-environment-node@npm:^27.5.1": - version: 27.5.1 - resolution: "jest-environment-node@npm:27.5.1" - dependencies: - "@jest/environment": "npm:^27.5.1" - "@jest/fake-timers": "npm:^27.5.1" - "@jest/types": "npm:^27.5.1" - "@types/node": "npm:*" - jest-mock: "npm:^27.5.1" - jest-util: "npm:^27.5.1" - checksum: 10/0f988330c4f3eec092e3fb37ea753b0c6f702e83cd8f4d770af9c2bf964a70bc45fbd34ec6fdb6d71ce98a778d9f54afd673e63f222e4667fff289e8069dba39 - languageName: node - linkType: hard - "jest-environment-node@npm:^29.7.0": version: 29.7.0 resolution: "jest-environment-node@npm:29.7.0" @@ -10942,13 +10280,6 @@ __metadata: languageName: node linkType: hard -"jest-get-type@npm:^27.5.1": - version: 27.5.1 - resolution: "jest-get-type@npm:27.5.1" - checksum: 10/63064ab70195c21007d897c1157bf88ff94a790824a10f8c890392e7d17eda9c3900513cb291ca1c8d5722cad79169764e9a1279f7c8a9c4cd6e9109ff04bbc0 - languageName: node - linkType: hard - "jest-get-type@npm:^29.6.3": version: 29.6.3 resolution: "jest-get-type@npm:29.6.3" @@ -10956,30 +10287,6 @@ __metadata: languageName: node linkType: hard -"jest-haste-map@npm:^27.5.1": - version: 27.5.1 - resolution: "jest-haste-map@npm:27.5.1" - dependencies: - "@jest/types": "npm:^27.5.1" - "@types/graceful-fs": "npm:^4.1.2" - "@types/node": "npm:*" - anymatch: "npm:^3.0.3" - fb-watchman: "npm:^2.0.0" - fsevents: "npm:^2.3.2" - graceful-fs: "npm:^4.2.9" - jest-regex-util: "npm:^27.5.1" - jest-serializer: "npm:^27.5.1" - jest-util: "npm:^27.5.1" - jest-worker: "npm:^27.5.1" - micromatch: "npm:^4.0.4" - walker: "npm:^1.0.7" - dependenciesMeta: - fsevents: - optional: true - checksum: 10/cbf42e4a3d2b6fc8ad64d732c1bb8a230fe25ad3df7f9f93e8af2950691ef9a5241a9d48c5c88e365744a7467b8cb00ab21c01baee4ee0c2b62acc657782545f - languageName: node - linkType: hard - "jest-haste-map@npm:^29.7.0": version: 29.7.0 resolution: "jest-haste-map@npm:29.7.0" @@ -11016,41 +10323,6 @@ __metadata: languageName: node linkType: hard -"jest-jasmine2@npm:^27.5.1": - version: 27.5.1 - resolution: "jest-jasmine2@npm:27.5.1" - dependencies: - "@jest/environment": "npm:^27.5.1" - "@jest/source-map": "npm:^27.5.1" - "@jest/test-result": "npm:^27.5.1" - "@jest/types": "npm:^27.5.1" - "@types/node": "npm:*" - chalk: "npm:^4.0.0" - co: "npm:^4.6.0" - expect: "npm:^27.5.1" - is-generator-fn: "npm:^2.0.0" - jest-each: "npm:^27.5.1" - jest-matcher-utils: "npm:^27.5.1" - jest-message-util: "npm:^27.5.1" - jest-runtime: "npm:^27.5.1" - jest-snapshot: "npm:^27.5.1" - jest-util: "npm:^27.5.1" - pretty-format: "npm:^27.5.1" - throat: "npm:^6.0.1" - checksum: 10/052d3c99c36295564a6688ae7e66cfd59997ca9589ccaaa2551d344d84699816a6b8c7bebf3a5f7bcdf691a07f7065c61f4a0770b810e5d887acd21f80a06304 - languageName: node - linkType: hard - -"jest-leak-detector@npm:^27.5.1": - version: 27.5.1 - resolution: "jest-leak-detector@npm:27.5.1" - dependencies: - jest-get-type: "npm:^27.5.1" - pretty-format: "npm:^27.5.1" - checksum: 10/5c9689060960567ddaf16c570d87afa760a461885765d2c71ef4f4857bbc3af1482c34e3cce88e50beefde1bf35e33530b020480752057a7e3dbb1ca0bae359f - languageName: node - linkType: hard - "jest-leak-detector@npm:^29.7.0": version: 29.7.0 resolution: "jest-leak-detector@npm:29.7.0" @@ -11061,18 +10333,6 @@ __metadata: languageName: node linkType: hard -"jest-matcher-utils@npm:^27.0.0, jest-matcher-utils@npm:^27.5.1": - version: 27.5.1 - resolution: "jest-matcher-utils@npm:27.5.1" - dependencies: - chalk: "npm:^4.0.0" - jest-diff: "npm:^27.5.1" - jest-get-type: "npm:^27.5.1" - pretty-format: "npm:^27.5.1" - checksum: 10/037f99878a0515581d7728ed3aed03707810f4da5a1c7ffb9d68a2c6c3180851a6ec40b559af37fbe891dde3ba12552b19e47b8188a27b6c5a53376be6907f32 - languageName: node - linkType: hard - "jest-matcher-utils@npm:^29.7.0": version: 29.7.0 resolution: "jest-matcher-utils@npm:29.7.0" @@ -11085,23 +10345,6 @@ __metadata: languageName: node linkType: hard -"jest-message-util@npm:^27.5.1": - version: 27.5.1 - resolution: "jest-message-util@npm:27.5.1" - dependencies: - "@babel/code-frame": "npm:^7.12.13" - "@jest/types": "npm:^27.5.1" - "@types/stack-utils": "npm:^2.0.0" - chalk: "npm:^4.0.0" - graceful-fs: "npm:^4.2.9" - micromatch: "npm:^4.0.4" - pretty-format: "npm:^27.5.1" - slash: "npm:^3.0.0" - stack-utils: "npm:^2.0.3" - checksum: 10/8fbf39dc25a7ef328dab22efcb3b198cbc788e309bc93e39fdb42b5541dba201c76acf47df476a4ee3d3fc6a6898e77bfc02677c198a98af91db1af0a435ade6 - languageName: node - linkType: hard - "jest-message-util@npm:^29.7.0": version: 29.7.0 resolution: "jest-message-util@npm:29.7.0" @@ -11119,16 +10362,6 @@ __metadata: languageName: node linkType: hard -"jest-mock@npm:^27.5.1": - version: 27.5.1 - resolution: "jest-mock@npm:27.5.1" - dependencies: - "@jest/types": "npm:^27.5.1" - "@types/node": "npm:*" - checksum: 10/be9a8777801659227d3bb85317a3aca617542779a290a6a45c9addec8bda29f494a524cb4af96c82b825ecb02171e320dfbfde3e3d9218672f9e38c9fac118f4 - languageName: node - linkType: hard - "jest-mock@npm:^29.7.0": version: 29.7.0 resolution: "jest-mock@npm:29.7.0" @@ -11152,13 +10385,6 @@ __metadata: languageName: node linkType: hard -"jest-regex-util@npm:^27.5.1": - version: 27.5.1 - resolution: "jest-regex-util@npm:27.5.1" - checksum: 10/d45ca7a9543616a34f7f3079337439cf07566e677a096472baa2810e274b9808b76767c97b0a4029b8a5b82b9d256dee28ef9ad4138b2b9e5933f6fac106c418 - languageName: node - linkType: hard - "jest-regex-util@npm:^29.6.3": version: 29.6.3 resolution: "jest-regex-util@npm:29.6.3" @@ -11166,17 +10392,6 @@ __metadata: languageName: node linkType: hard -"jest-resolve-dependencies@npm:^27.5.1": - version: 27.5.1 - resolution: "jest-resolve-dependencies@npm:27.5.1" - dependencies: - "@jest/types": "npm:^27.5.1" - jest-regex-util: "npm:^27.5.1" - jest-snapshot: "npm:^27.5.1" - checksum: 10/c67af97afad1da88f5530317c732bbd1262d1225f6cd7f4e4740a5db48f90ab0bd8564738ac70d1a43934894f9aef62205c1b8f8ee89e5c7a737e6a121ee4c25 - languageName: node - linkType: hard - "jest-resolve-dependencies@npm:^29.7.0": version: 29.7.0 resolution: "jest-resolve-dependencies@npm:29.7.0" @@ -11187,24 +10402,6 @@ __metadata: languageName: node linkType: hard -"jest-resolve@npm:^27.5.1": - version: 27.5.1 - resolution: "jest-resolve@npm:27.5.1" - dependencies: - "@jest/types": "npm:^27.5.1" - chalk: "npm:^4.0.0" - graceful-fs: "npm:^4.2.9" - jest-haste-map: "npm:^27.5.1" - jest-pnp-resolver: "npm:^1.2.2" - jest-util: "npm:^27.5.1" - jest-validate: "npm:^27.5.1" - resolve: "npm:^1.20.0" - resolve.exports: "npm:^1.1.0" - slash: "npm:^3.0.0" - checksum: 10/93659a9d5ec365a9f2fd3fcaa8f799e3bd090318c48890951ca4325e863f4eb778bb7f7e8d1d8495eda4c157ee771d93fb31f37364ce1a36a09f77f1089e52a1 - languageName: node - linkType: hard - "jest-resolve@npm:^29.7.0": version: 29.7.0 resolution: "jest-resolve@npm:29.7.0" @@ -11222,35 +10419,6 @@ __metadata: languageName: node linkType: hard -"jest-runner@npm:^27.5.1": - version: 27.5.1 - resolution: "jest-runner@npm:27.5.1" - dependencies: - "@jest/console": "npm:^27.5.1" - "@jest/environment": "npm:^27.5.1" - "@jest/test-result": "npm:^27.5.1" - "@jest/transform": "npm:^27.5.1" - "@jest/types": "npm:^27.5.1" - "@types/node": "npm:*" - chalk: "npm:^4.0.0" - emittery: "npm:^0.8.1" - graceful-fs: "npm:^4.2.9" - jest-docblock: "npm:^27.5.1" - jest-environment-jsdom: "npm:^27.5.1" - jest-environment-node: "npm:^27.5.1" - jest-haste-map: "npm:^27.5.1" - jest-leak-detector: "npm:^27.5.1" - jest-message-util: "npm:^27.5.1" - jest-resolve: "npm:^27.5.1" - jest-runtime: "npm:^27.5.1" - jest-util: "npm:^27.5.1" - jest-worker: "npm:^27.5.1" - source-map-support: "npm:^0.5.6" - throat: "npm:^6.0.1" - checksum: 10/97bd741f442ebbcebfdb5e8389c0df645448d0b4b634e4128b3387d6fe432cf0f93feb0ecfc3842fed20a35c43c24460ed5dd89d7501ca9e2fdba65e5a4edf37 - languageName: node - linkType: hard - "jest-runner@npm:^29.7.0": version: 29.7.0 resolution: "jest-runner@npm:29.7.0" @@ -11280,36 +10448,6 @@ __metadata: languageName: node linkType: hard -"jest-runtime@npm:^27.5.1": - version: 27.5.1 - resolution: "jest-runtime@npm:27.5.1" - dependencies: - "@jest/environment": "npm:^27.5.1" - "@jest/fake-timers": "npm:^27.5.1" - "@jest/globals": "npm:^27.5.1" - "@jest/source-map": "npm:^27.5.1" - "@jest/test-result": "npm:^27.5.1" - "@jest/transform": "npm:^27.5.1" - "@jest/types": "npm:^27.5.1" - chalk: "npm:^4.0.0" - cjs-module-lexer: "npm:^1.0.0" - collect-v8-coverage: "npm:^1.0.0" - execa: "npm:^5.0.0" - glob: "npm:^7.1.3" - graceful-fs: "npm:^4.2.9" - jest-haste-map: "npm:^27.5.1" - jest-message-util: "npm:^27.5.1" - jest-mock: "npm:^27.5.1" - jest-regex-util: "npm:^27.5.1" - jest-resolve: "npm:^27.5.1" - jest-snapshot: "npm:^27.5.1" - jest-util: "npm:^27.5.1" - slash: "npm:^3.0.0" - strip-bom: "npm:^4.0.0" - checksum: 10/cc6cdce5bee4bc02935a4671394e19962f3469eeb6e823442ca99e5670fd87f60ed64b7c7156ac13d2799fc44fe9bb806454a3f17c8342bd35e564b1a40e3920 - languageName: node - linkType: hard - "jest-runtime@npm:^29.7.0": version: 29.7.0 resolution: "jest-runtime@npm:29.7.0" @@ -11340,16 +10478,6 @@ __metadata: languageName: node linkType: hard -"jest-serializer@npm:^27.5.1": - version: 27.5.1 - resolution: "jest-serializer@npm:27.5.1" - dependencies: - "@types/node": "npm:*" - graceful-fs: "npm:^4.2.9" - checksum: 10/803e03a552278610edc6753c0dd9fa5bb5cd3ca47414a7b2918106efb62b79fd5e9ae785d0a21f12a299fa599fea8acc1fa6dd41283328cee43962cf7df9bb44 - languageName: node - linkType: hard - "jest-silent-reporter@npm:^0.5.0": version: 0.5.0 resolution: "jest-silent-reporter@npm:0.5.0" @@ -11360,36 +10488,6 @@ __metadata: languageName: node linkType: hard -"jest-snapshot@npm:^27.5.1": - version: 27.5.1 - resolution: "jest-snapshot@npm:27.5.1" - dependencies: - "@babel/core": "npm:^7.7.2" - "@babel/generator": "npm:^7.7.2" - "@babel/plugin-syntax-typescript": "npm:^7.7.2" - "@babel/traverse": "npm:^7.7.2" - "@babel/types": "npm:^7.0.0" - "@jest/transform": "npm:^27.5.1" - "@jest/types": "npm:^27.5.1" - "@types/babel__traverse": "npm:^7.0.4" - "@types/prettier": "npm:^2.1.5" - babel-preset-current-node-syntax: "npm:^1.0.0" - chalk: "npm:^4.0.0" - expect: "npm:^27.5.1" - graceful-fs: "npm:^4.2.9" - jest-diff: "npm:^27.5.1" - jest-get-type: "npm:^27.5.1" - jest-haste-map: "npm:^27.5.1" - jest-matcher-utils: "npm:^27.5.1" - jest-message-util: "npm:^27.5.1" - jest-util: "npm:^27.5.1" - natural-compare: "npm:^1.4.0" - pretty-format: "npm:^27.5.1" - semver: "npm:^7.3.2" - checksum: 10/01b2c70c56980f21fc299fa68a1d1e3a9612f06d2fcdd1cf60f636c3dd427b814efc5f15aacc567e0c3b28fd32129be4a10fca34555f358534fc88e5cee4ffbb - languageName: node - linkType: hard - "jest-snapshot@npm:^29.7.0": version: 29.7.0 resolution: "jest-snapshot@npm:29.7.0" @@ -11432,20 +10530,6 @@ __metadata: languageName: node linkType: hard -"jest-util@npm:^27.0.0, jest-util@npm:^27.5.1": - version: 27.5.1 - resolution: "jest-util@npm:27.5.1" - dependencies: - "@jest/types": "npm:^27.5.1" - "@types/node": "npm:*" - chalk: "npm:^4.0.0" - ci-info: "npm:^3.2.0" - graceful-fs: "npm:^4.2.9" - picomatch: "npm:^2.2.3" - checksum: 10/ecc7da41769558e57dbde544141ffceb536ee53b663de1e002d4b86784cea500a10f9a7f02e8b804e517aa0e34d3145118734c7e8b5071f9f18a153ede5b062d - languageName: node - linkType: hard - "jest-util@npm:^29.7.0": version: 29.7.0 resolution: "jest-util@npm:29.7.0" @@ -11460,20 +10544,6 @@ __metadata: languageName: node linkType: hard -"jest-validate@npm:^27.5.1": - version: 27.5.1 - resolution: "jest-validate@npm:27.5.1" - dependencies: - "@jest/types": "npm:^27.5.1" - camelcase: "npm:^6.2.0" - chalk: "npm:^4.0.0" - jest-get-type: "npm:^27.5.1" - leven: "npm:^3.1.0" - pretty-format: "npm:^27.5.1" - checksum: 10/1fc4d46ecead311a0362bb8ea7767718b682e3d73b65c2bf55cb33722c13bb340e52d20f35d7af38918f8655a78ebbedf3d8a9eaba4ac067883cef006fcf9197 - languageName: node - linkType: hard - "jest-validate@npm:^29.7.0": version: 29.7.0 resolution: "jest-validate@npm:29.7.0" @@ -11488,21 +10558,6 @@ __metadata: languageName: node linkType: hard -"jest-watcher@npm:^27.5.1": - version: 27.5.1 - resolution: "jest-watcher@npm:27.5.1" - dependencies: - "@jest/test-result": "npm:^27.5.1" - "@jest/types": "npm:^27.5.1" - "@types/node": "npm:*" - ansi-escapes: "npm:^4.2.1" - chalk: "npm:^4.0.0" - jest-util: "npm:^27.5.1" - string-length: "npm:^4.0.1" - checksum: 10/2c2f6cb4256d5cf90c4ae2d8400d5a40399aea9152c85b8b04c3fe4cbecb65e188462de1267d134a42c69d2ddb13a6e50a8ea1aef809b1e4c8fff7a0019ca2c4 - languageName: node - linkType: hard - "jest-watcher@npm:^29.7.0": version: 29.7.0 resolution: "jest-watcher@npm:29.7.0" @@ -11528,17 +10583,6 @@ __metadata: languageName: node linkType: hard -"jest-worker@npm:^27.5.1": - version: 27.5.1 - resolution: "jest-worker@npm:27.5.1" - dependencies: - "@types/node": "npm:*" - merge-stream: "npm:^2.0.0" - supports-color: "npm:^8.0.0" - checksum: 10/06c6e2a84591d9ede704d5022fc13791e8876e83397c89d481b0063332abbb64c0f01ef4ca7de520b35c7a1058556078d6bdc3631376f4e9ffb42316c1a8488e - languageName: node - linkType: hard - "jest-worker@npm:^29.7.0": version: 29.7.0 resolution: "jest-worker@npm:29.7.0" @@ -11551,24 +10595,6 @@ __metadata: languageName: node linkType: hard -"jest@npm:^27.5.1": - version: 27.5.1 - resolution: "jest@npm:27.5.1" - dependencies: - "@jest/core": "npm:^27.5.1" - import-local: "npm:^3.0.2" - jest-cli: "npm:^27.5.1" - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - bin: - jest: bin/jest.js - checksum: 10/a1435098e1885e48d2a46c660176cd34d69bc80fa72966a1ea8781ab6d5355ee514d45cf871d2da2b5a54509979e53d39fbb9b149c94e430127f44ed0d70639c - languageName: node - linkType: hard - "jest@npm:^29.7.0": version: 29.7.0 resolution: "jest@npm:29.7.0" @@ -11660,46 +10686,6 @@ __metadata: languageName: node linkType: hard -"jsdom@npm:^16.6.0": - version: 16.7.0 - resolution: "jsdom@npm:16.7.0" - dependencies: - abab: "npm:^2.0.5" - acorn: "npm:^8.2.4" - acorn-globals: "npm:^6.0.0" - cssom: "npm:^0.4.4" - cssstyle: "npm:^2.3.0" - data-urls: "npm:^2.0.0" - decimal.js: "npm:^10.2.1" - domexception: "npm:^2.0.1" - escodegen: "npm:^2.0.0" - form-data: "npm:^3.0.0" - html-encoding-sniffer: "npm:^2.0.1" - http-proxy-agent: "npm:^4.0.1" - https-proxy-agent: "npm:^5.0.0" - is-potential-custom-element-name: "npm:^1.0.1" - nwsapi: "npm:^2.2.0" - parse5: "npm:6.0.1" - saxes: "npm:^5.0.1" - symbol-tree: "npm:^3.2.4" - tough-cookie: "npm:^4.0.0" - w3c-hr-time: "npm:^1.0.2" - w3c-xmlserializer: "npm:^2.0.0" - webidl-conversions: "npm:^6.1.0" - whatwg-encoding: "npm:^1.0.5" - whatwg-mimetype: "npm:^2.3.0" - whatwg-url: "npm:^8.5.0" - ws: "npm:^7.4.6" - xml-name-validator: "npm:^3.0.0" - peerDependencies: - canvas: ^2.5.0 - peerDependenciesMeta: - canvas: - optional: true - checksum: 10/c530c04b0e3718769a66e19b0b5c762126658bce384d6743b807a28a9d89beba4ad932e474f570323efe6ce832b3d9a8f94816fd6c4d386416d5ea0b64e07ebc - languageName: node - linkType: hard - "jsdom@npm:^20.0.0": version: 20.0.3 resolution: "jsdom@npm:20.0.3" @@ -11806,7 +10792,7 @@ __metadata: languageName: node linkType: hard -"json5@npm:2.x, json5@npm:^2.2.3": +"json5@npm:^2.2.3": version: 2.2.3 resolution: "json5@npm:2.2.3" bin: @@ -11961,7 +10947,7 @@ __metadata: languageName: node linkType: hard -"lodash.memoize@npm:4.x, lodash.memoize@npm:^4.1.2": +"lodash.memoize@npm:^4.1.2": version: 4.1.2 resolution: "lodash.memoize@npm:4.1.2" checksum: 10/192b2168f310c86f303580b53acf81ab029761b9bd9caa9506a019ffea5f3363ea98d7e39e7e11e6b9917066c9d36a09a11f6fe16f812326390d8f3a54a1a6da @@ -11982,13 +10968,6 @@ __metadata: languageName: node linkType: hard -"lodash@npm:^4.7.0": - version: 4.17.23 - resolution: "lodash@npm:4.17.23" - checksum: 10/82504c88250f58da7a5a4289f57a4f759c44946c005dd232821c7688b5fcfbf4a6268f6a6cdde4b792c91edd2f3b5398c1d2a0998274432cff76def48735e233 - languageName: node - linkType: hard - "log-symbols@npm:^4.0.0": version: 4.1.0 resolution: "log-symbols@npm:4.1.0" @@ -12070,7 +11049,7 @@ __metadata: languageName: node linkType: hard -"make-error@npm:1.x, make-error@npm:^1.3.6": +"make-error@npm:^1.3.6": version: 1.3.6 resolution: "make-error@npm:1.3.6" checksum: 10/b86e5e0e25f7f777b77fabd8e2cbf15737972869d852a22b7e73c17623928fccb826d8e46b9951501d3f20e51ad74ba8c59ed584f610526a48f8ccf88aaec402 @@ -12235,7 +11214,7 @@ __metadata: languageName: node linkType: hard -"mime-types@npm:^2.1.12, mime-types@npm:^2.1.35, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": +"mime-types@npm:^2.1.12, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": version: 2.1.35 resolution: "mime-types@npm:2.1.35" dependencies: @@ -12737,7 +11716,7 @@ __metadata: languageName: node linkType: hard -"nwsapi@npm:^2.2.0, nwsapi@npm:^2.2.2": +"nwsapi@npm:^2.2.2": version: 2.2.23 resolution: "nwsapi@npm:2.2.23" checksum: 10/aa4a570039c33d70b51436d1bb533f3e2c33c488ccbe9b09285c46a6cee5ef266fd60103461085c6954ba52460786a8138f042958328c7c1b4763898eb3dadfa @@ -12917,13 +11896,6 @@ __metadata: languageName: node linkType: hard -"parse5@npm:6.0.1": - version: 6.0.1 - resolution: "parse5@npm:6.0.1" - checksum: 10/dfb110581f62bd1425725a7c784ae022a24669bd0efc24b58c71fc731c4d868193e2ebd85b74cde2dbb965e4dcf07059b1e651adbec1b3b5267531bd132fdb75 - languageName: node - linkType: hard - "parse5@npm:^7.0.0, parse5@npm:^7.1.1": version: 7.3.0 resolution: "parse5@npm:7.3.0" @@ -13150,17 +12122,6 @@ __metadata: languageName: node linkType: hard -"pretty-format@npm:^27.0.0, pretty-format@npm:^27.5.1": - version: 27.5.1 - resolution: "pretty-format@npm:27.5.1" - dependencies: - ansi-regex: "npm:^5.0.1" - ansi-styles: "npm:^5.0.0" - react-is: "npm:^17.0.1" - checksum: 10/248990cbef9e96fb36a3e1ae6b903c551ca4ddd733f8d0912b9cc5141d3d0b3f9f8dfb4d799fb1c6723382c9c2083ffbfa4ad43ff9a0e7535d32d41fd5f01da6 - languageName: node - linkType: hard - "pretty-format@npm:^29.0.0, pretty-format@npm:^29.7.0": version: 29.7.0 resolution: "pretty-format@npm:29.7.0" @@ -13367,13 +12328,6 @@ __metadata: languageName: node linkType: hard -"react-is@npm:^17.0.1": - version: 17.0.2 - resolution: "react-is@npm:17.0.2" - checksum: 10/73b36281e58eeb27c9cc6031301b6ae19ecdc9f18ae2d518bdb39b0ac564e65c5779405d623f1df9abf378a13858b79442480244bd579968afc1faf9a2ce5e05 - languageName: node - linkType: hard - "react-is@npm:^18.0.0": version: 18.3.1 resolution: "react-is@npm:18.3.1" @@ -13560,13 +12514,6 @@ __metadata: languageName: node linkType: hard -"resolve.exports@npm:^1.1.0": - version: 1.1.1 - resolution: "resolve.exports@npm:1.1.1" - checksum: 10/de58c30aca30883f0e29910e4ad1b7b9986ec5f69434ef2e957ddbe52d3250e138ddd2688e8cd67909b4ee9bf3437424c718a5962d59edd610f035b861ef8441 - languageName: node - linkType: hard - "resolve.exports@npm:^2.0.0": version: 2.0.3 resolution: "resolve.exports@npm:2.0.3" @@ -13647,17 +12594,6 @@ __metadata: languageName: node linkType: hard -"rimraf@npm:^3.0.0": - version: 3.0.2 - resolution: "rimraf@npm:3.0.2" - dependencies: - glob: "npm:^7.1.3" - bin: - rimraf: bin.js - checksum: 10/063ffaccaaaca2cfd0ef3beafb12d6a03dd7ff1260d752d62a6077b5dfff6ae81bea571f655bb6b589d366930ec1bdd285d40d560c0dae9b12f125e54eb743d5 - languageName: node - linkType: hard - "rimraf@npm:^5.0.5": version: 5.0.10 resolution: "rimraf@npm:5.0.10" @@ -13741,15 +12677,6 @@ __metadata: languageName: node linkType: hard -"saxes@npm:^5.0.1": - version: 5.0.1 - resolution: "saxes@npm:5.0.1" - dependencies: - xmlchars: "npm:^2.2.0" - checksum: 10/148b5f98fdd45df25fa1abef35d72cdf6457ac5aef3b7d59d60f770af09d8cf6e7e3a074197071222441d68670fd3198590aba9985e37c4738af2df2f44d0686 - languageName: node - linkType: hard - "saxes@npm:^6.0.0": version: 6.0.0 resolution: "saxes@npm:6.0.0" @@ -13794,15 +12721,6 @@ __metadata: languageName: node linkType: hard -"semver@npm:7.x, semver@npm:^7.3.2": - version: 7.7.4 - resolution: "semver@npm:7.7.4" - bin: - semver: bin/semver.js - checksum: 10/26bdc6d58b29528f4142d29afb8526bc335f4fc04c4a10f2b98b217f277a031c66736bf82d3d3bb354a2f6a3ae50f18fd62b053c4ac3f294a3d10a61f5075b75 - languageName: node - linkType: hard - "semver@npm:^6.3.0, semver@npm:^6.3.1": version: 6.3.1 resolution: "semver@npm:6.3.1" @@ -13959,7 +12877,7 @@ __metadata: languageName: node linkType: hard -"signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7": +"signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7": version: 3.0.7 resolution: "signal-exit@npm:3.0.7" checksum: 10/a2f098f247adc367dffc27845853e9959b9e88b01cb301658cfe4194352d8d2bb32e18467c786a7fe15f1d44b233ea35633d076d5e737870b7139949d1ab6318 @@ -14115,16 +13033,6 @@ __metadata: languageName: node linkType: hard -"source-map-support@npm:^0.5.6": - version: 0.5.21 - resolution: "source-map-support@npm:0.5.21" - dependencies: - buffer-from: "npm:^1.0.0" - source-map: "npm:^0.6.0" - checksum: 10/8317e12d84019b31e34b86d483dd41d6f832f389f7417faf8fc5c75a66a12d9686e47f589a0554a868b8482f037e23df9d040d29387eb16fa14cb85f091ba207 - languageName: node - linkType: hard - "source-map@npm:^0.6.0, source-map@npm:^0.6.1, source-map@npm:~0.6.1": version: 0.6.1 resolution: "source-map@npm:0.6.1" @@ -14132,13 +13040,6 @@ __metadata: languageName: node linkType: hard -"source-map@npm:^0.7.3": - version: 0.7.6 - resolution: "source-map@npm:0.7.6" - checksum: 10/c8d2da7c57c14f3fd7568f764b39ad49bbf9dd7632b86df3542b31fed117d4af2fb74a4f886fc06baf7a510fee68e37998efc3080aacdac951c36211dc29a7a3 - languageName: node - linkType: hard - "spdx-correct@npm:^3.0.0": version: 3.2.0 resolution: "spdx-correct@npm:3.2.0" @@ -14473,16 +13374,6 @@ __metadata: languageName: node linkType: hard -"terminal-link@npm:^2.0.0": - version: 2.1.1 - resolution: "terminal-link@npm:2.1.1" - dependencies: - ansi-escapes: "npm:^4.2.1" - supports-hyperlinks: "npm:^2.0.0" - checksum: 10/ce3d2cd3a438c4a9453947aa664581519173ea40e77e2534d08c088ee6dda449eabdbe0a76d2a516b8b73c33262fedd10d5270ccf7576ae316e3db170ce6562f - languageName: node - linkType: hard - "test-exclude@npm:^6.0.0": version: 6.0.0 resolution: "test-exclude@npm:6.0.0" @@ -14503,13 +13394,6 @@ __metadata: languageName: node linkType: hard -"throat@npm:^6.0.1": - version: 6.0.2 - resolution: "throat@npm:6.0.2" - checksum: 10/acd99f4b7362bcf6dcc517b01517165a00f7270d0c4fe2ca06c73b6217f022f76fb20e8ca98283b25ccb85d97a5f96dbcac5577d60bb0bda1eff92fa8e79fbd7 - languageName: node - linkType: hard - "tinyglobby@npm:^0.2.15": version: 0.2.15 resolution: "tinyglobby@npm:0.2.15" @@ -14543,7 +13427,7 @@ __metadata: languageName: node linkType: hard -"tough-cookie@npm:^4.0.0, tough-cookie@npm:^4.1.2": +"tough-cookie@npm:^4.1.2": version: 4.1.4 resolution: "tough-cookie@npm:4.1.4" dependencies: @@ -14555,15 +13439,6 @@ __metadata: languageName: node linkType: hard -"tr46@npm:^2.1.0": - version: 2.1.0 - resolution: "tr46@npm:2.1.0" - dependencies: - punycode: "npm:^2.1.1" - checksum: 10/302b13f458da713b2a6ff779a0c1d27361d369fdca6c19330536d31db61789b06b246968fc879fdac818a92d02643dca1a0f4da5618df86aea4a79fb3243d3f3 - languageName: node - linkType: hard - "tr46@npm:^3.0.0": version: 3.0.0 resolution: "tr46@npm:3.0.0" @@ -14596,39 +13471,6 @@ __metadata: languageName: node linkType: hard -"ts-jest@npm:^27.1.5": - version: 27.1.5 - resolution: "ts-jest@npm:27.1.5" - dependencies: - bs-logger: "npm:0.x" - fast-json-stable-stringify: "npm:2.x" - jest-util: "npm:^27.0.0" - json5: "npm:2.x" - lodash.memoize: "npm:4.x" - make-error: "npm:1.x" - semver: "npm:7.x" - yargs-parser: "npm:20.x" - peerDependencies: - "@babel/core": ">=7.0.0-beta.0 <8" - "@types/jest": ^27.0.0 - babel-jest: ">=27.0.0 <28" - jest: ^27.0.0 - typescript: ">=3.8 <5.0" - peerDependenciesMeta: - "@babel/core": - optional: true - "@types/jest": - optional: true - babel-jest: - optional: true - esbuild: - optional: true - bin: - ts-jest: cli.js - checksum: 10/7675946cefc8c652ec35f2fd600ffb99c8e5db5ac355ceb8317707862c586ee46f7ddd589bd206fa8be2598bc4a87c5a53eb4198af78723f5661c90e32200ba3 - languageName: node - linkType: hard - "ts-jest@npm:^29.2.5": version: 29.4.6 resolution: "ts-jest@npm:29.4.6" @@ -14791,15 +13633,6 @@ __metadata: languageName: node linkType: hard -"typedarray-to-buffer@npm:^3.1.5": - version: 3.1.5 - resolution: "typedarray-to-buffer@npm:3.1.5" - dependencies: - is-typedarray: "npm:^1.0.0" - checksum: 10/7c850c3433fbdf4d04f04edfc751743b8f577828b8e1eb93b95a3bce782d156e267d83e20fb32b3b47813e69a69ab5e9b5342653332f7d21c7d1210661a7a72c - languageName: node - linkType: hard - "typedarray@npm:^0.0.6": version: 0.0.6 resolution: "typedarray@npm:0.0.6" @@ -15032,17 +13865,6 @@ __metadata: languageName: node linkType: hard -"v8-to-istanbul@npm:^8.1.0": - version: 8.1.1 - resolution: "v8-to-istanbul@npm:8.1.1" - dependencies: - "@types/istanbul-lib-coverage": "npm:^2.0.1" - convert-source-map: "npm:^1.6.0" - source-map: "npm:^0.7.3" - checksum: 10/db5469f133a7cfb7680a28ddfb31aad2cc64f282fa7cf0c8e91f91bfd542bf61597260282be28c9648f0f2114963a24b273ed92af9a5cad6cb629c708ca72f8e - languageName: node - linkType: hard - "v8-to-istanbul@npm:^9.0.1": version: 9.3.0 resolution: "v8-to-istanbul@npm:9.3.0" @@ -15099,24 +13921,6 @@ __metadata: languageName: node linkType: hard -"w3c-hr-time@npm:^1.0.2": - version: 1.0.2 - resolution: "w3c-hr-time@npm:1.0.2" - dependencies: - browser-process-hrtime: "npm:^1.0.0" - checksum: 10/03851d90c236837c24c2983f5a8806a837c6515b21d52e5f29776b07cc08695779303d481454d768308489f00dd9d3232d595acaa5b2686d199465a4d9f7b283 - languageName: node - linkType: hard - -"w3c-xmlserializer@npm:^2.0.0": - version: 2.0.0 - resolution: "w3c-xmlserializer@npm:2.0.0" - dependencies: - xml-name-validator: "npm:^3.0.0" - checksum: 10/400c18b75ce6af269168f964e7d1eb196a7422e134032906540c69d83b802f38dc64e18fc259c02966a334687483f416398d2ad7ebe9d19ab434a7a0247c71c3 - languageName: node - linkType: hard - "w3c-xmlserializer@npm:^4.0.0": version: 4.0.0 resolution: "w3c-xmlserializer@npm:4.0.0" @@ -15126,7 +13930,7 @@ __metadata: languageName: node linkType: hard -"walker@npm:^1.0.7, walker@npm:^1.0.8": +"walker@npm:^1.0.8": version: 1.0.8 resolution: "walker@npm:1.0.8" dependencies: @@ -15165,20 +13969,6 @@ __metadata: languageName: node linkType: hard -"webidl-conversions@npm:^5.0.0": - version: 5.0.0 - resolution: "webidl-conversions@npm:5.0.0" - checksum: 10/cea864dd9cf1f2133d82169a446fb94427ba089e4676f5895273ea085f165649afe587ae3f19f2f0370751a724bba2d96e9956d652b3e41ac1feaaa4376e2d70 - languageName: node - linkType: hard - -"webidl-conversions@npm:^6.1.0": - version: 6.1.0 - resolution: "webidl-conversions@npm:6.1.0" - checksum: 10/4454b73060a6d83f7ec1f1db24c480b7ecda33880306dd32a3d62d85b36df4789a383489f1248387e5451737dca17054b8cbf2e792ba89e49d76247f0f4f6380 - languageName: node - linkType: hard - "webidl-conversions@npm:^7.0.0": version: 7.0.0 resolution: "webidl-conversions@npm:7.0.0" @@ -15204,15 +13994,6 @@ __metadata: languageName: node linkType: hard -"whatwg-encoding@npm:^1.0.5": - version: 1.0.5 - resolution: "whatwg-encoding@npm:1.0.5" - dependencies: - iconv-lite: "npm:0.4.24" - checksum: 10/5be4efe111dce29ddee3448d3915477fcc3b28f991d9cf1300b4e50d6d189010d47bca2f51140a844cf9b726e8f066f4aee72a04d687bfe4f2ee2767b2f5b1e6 - languageName: node - linkType: hard - "whatwg-encoding@npm:^2.0.0": version: 2.0.0 resolution: "whatwg-encoding@npm:2.0.0" @@ -15229,13 +14010,6 @@ __metadata: languageName: node linkType: hard -"whatwg-mimetype@npm:^2.3.0": - version: 2.3.0 - resolution: "whatwg-mimetype@npm:2.3.0" - checksum: 10/3582c1d74d708716013433bbab45cb9b31ef52d276adfbe2205d948be1ec9bb1a4ac05ce6d9045f3acc4104489e1344c857b14700002385a4b997a5673ff6416 - languageName: node - linkType: hard - "whatwg-mimetype@npm:^3.0.0": version: 3.0.0 resolution: "whatwg-mimetype@npm:3.0.0" @@ -15263,17 +14037,6 @@ __metadata: languageName: node linkType: hard -"whatwg-url@npm:^8.0.0, whatwg-url@npm:^8.5.0": - version: 8.7.0 - resolution: "whatwg-url@npm:8.7.0" - dependencies: - lodash: "npm:^4.7.0" - tr46: "npm:^2.1.0" - webidl-conversions: "npm:^6.1.0" - checksum: 10/512a8b2703dffbf13a9a247bf2fb27c3048a3ceb5ece09f88b737c8260afaba4b2f6775c2f1cfc29c2ba4859f2454a9de73fac08e239b00ae2b42cd6b8bb0d35 - languageName: node - linkType: hard - "which@npm:^1.2.14": version: 1.3.1 resolution: "which@npm:1.3.1" @@ -15361,18 +14124,6 @@ __metadata: languageName: node linkType: hard -"write-file-atomic@npm:^3.0.0": - version: 3.0.3 - resolution: "write-file-atomic@npm:3.0.3" - dependencies: - imurmurhash: "npm:^0.1.4" - is-typedarray: "npm:^1.0.0" - signal-exit: "npm:^3.0.2" - typedarray-to-buffer: "npm:^3.1.5" - checksum: 10/0955ab94308b74d32bc252afe69d8b42ba4b8a28b8d79f399f3f405969f82623f981e35d13129a52aa2973450f342107c06d86047572637584e85a1c0c246bf3 - languageName: node - linkType: hard - "write-file-atomic@npm:^4.0.2": version: 4.0.2 resolution: "write-file-atomic@npm:4.0.2" @@ -15408,7 +14159,7 @@ __metadata: languageName: node linkType: hard -"ws@npm:^7.4.6, ws@npm:^7.5.10": +"ws@npm:^7.5.10": version: 7.5.10 resolution: "ws@npm:7.5.10" peerDependencies: @@ -15445,13 +14196,6 @@ __metadata: languageName: node linkType: hard -"xml-name-validator@npm:^3.0.0": - version: 3.0.0 - resolution: "xml-name-validator@npm:3.0.0" - checksum: 10/24f5d38c777ad9239dfe99c4ca3cd155415b65ac583785d1514e04b9f86d6d09eaff983ed373e7a779ceefd1fca0fd893f2fc264999e9aeaac36b6e1afc397ed - languageName: node - linkType: hard - "xml-name-validator@npm:^4.0.0": version: 4.0.0 resolution: "xml-name-validator@npm:4.0.0" @@ -15517,7 +14261,7 @@ __metadata: languageName: node linkType: hard -"yargs-parser@npm:20.x, yargs-parser@npm:^20.2.2, yargs-parser@npm:^20.2.3": +"yargs-parser@npm:^20.2.2, yargs-parser@npm:^20.2.3": version: 20.2.9 resolution: "yargs-parser@npm:20.2.9" checksum: 10/0188f430a0f496551d09df6719a9132a3469e47fe2747208b1dd0ab2bb0c512a95d0b081628bbca5400fb20dbf2fabe63d22badb346cecadffdd948b049f3fcc From a4a1bb141ff5dde27c75374df7b6551f50d934a3 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Fri, 20 Feb 2026 18:44:51 +0100 Subject: [PATCH 40/55] chore: update test --- .../src/ConfigRegistryController.test.ts | 201 +++++++----------- tests/fake-provider.ts | 30 ++- 2 files changed, 95 insertions(+), 136 deletions(-) diff --git a/packages/config-registry-controller/src/ConfigRegistryController.test.ts b/packages/config-registry-controller/src/ConfigRegistryController.test.ts index 8c6cf464541..e3e776903ee 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.test.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.test.ts @@ -881,9 +881,7 @@ describe('ConfigRegistryController', () => { }); it('works via messenger actions', async () => { - await withController(async ({ controller, messenger }) => { - const executePollSpy = jest.spyOn(controller, '_executePoll'); - + await withController(async ({ messenger, mockApiServiceHandler }) => { const token = messenger.call( 'ConfigRegistryController:startPolling', null, @@ -891,11 +889,11 @@ describe('ConfigRegistryController', () => { expect(typeof token).toBe('string'); await jestAdvanceTime({ duration: 0 }); - expect(executePollSpy).toHaveBeenCalledTimes(1); + expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); messenger.call('ConfigRegistryController:stopPolling'); await jestAdvanceTime({ duration: DEFAULT_POLLING_INTERVAL }); - expect(executePollSpy).toHaveBeenCalledTimes(1); + expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); }); }); }); @@ -955,17 +953,12 @@ describe('ConfigRegistryController', () => { }, }, }, - async ({ controller }) => { - const executePollSpy = jest.spyOn(controller, '_executePoll'); + async ({ controller, mockApiServiceHandler }) => { controller.startPolling(null); - // StaticIntervalPollingController runs first poll after 0ms (executePoll may early-return due to lastFetched) await jestAdvanceTime({ duration: 0 }); - expect(executePollSpy).toHaveBeenCalledTimes(1); - - // Next poll is scheduled at pollingInterval; advancing remainingTime+1 does not reach it await jestAdvanceTime({ duration: remainingTime + 1 }); - expect(executePollSpy).toHaveBeenCalledTimes(1); + expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); controller.stopAllPolling(); }, @@ -981,12 +974,11 @@ describe('ConfigRegistryController', () => { }, }, }, - async ({ controller }) => { - const executePollSpy = jest.spyOn(controller, '_executePoll'); + async ({ controller, mockApiServiceHandler }) => { controller.startPolling(null); await jestAdvanceTime({ duration: 0 }); - expect(executePollSpy).toHaveBeenCalledTimes(1); + expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); controller.stopAllPolling(); }, @@ -1006,13 +998,12 @@ describe('ConfigRegistryController', () => { }, }, }, - async ({ controller }) => { + async ({ controller, mockApiServiceHandler }) => { jest.spyOn(Date, 'now').mockReturnValue(now); - const executePollSpy = jest.spyOn(controller, '_executePoll'); controller.startPolling(null); await jestAdvanceTime({ duration: 1 }); - expect(executePollSpy).toHaveBeenCalledTimes(1); + expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); controller.stopAllPolling(); jest.restoreAllMocks(); @@ -1033,13 +1024,12 @@ describe('ConfigRegistryController', () => { }, }, }, - async ({ controller }) => { + async ({ controller, mockApiServiceHandler }) => { jest.spyOn(Date, 'now').mockReturnValue(now); - const executePollSpy = jest.spyOn(controller, '_executePoll'); controller.startPolling(null); await jestAdvanceTime({ duration: 1 }); - expect(executePollSpy).toHaveBeenCalledTimes(1); + expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); controller.stopAllPolling(); jest.restoreAllMocks(); @@ -1057,17 +1047,14 @@ describe('ConfigRegistryController', () => { }, }, }, - async ({ controller }) => { + async ({ controller, mockApiServiceHandler }) => { jest .spyOn(controller, 'getIntervalLength') .mockReturnValue(undefined); - const executePollSpy = jest.spyOn(controller, '_executePoll'); controller.startPolling(null); - // StaticIntervalPollingController runs first poll after 0ms - await jestAdvanceTime({ duration: 0 }); - expect(executePollSpy).toHaveBeenCalledTimes(1); + expect(mockApiServiceHandler).not.toHaveBeenCalled(); controller.stopAllPolling(); }, @@ -1086,26 +1073,14 @@ describe('ConfigRegistryController', () => { }, }, }, - async ({ controller }) => { - const executePollSpy = jest.spyOn(controller, '_executePoll'); - const clearTimeoutSpy = jest.spyOn(global, 'clearTimeout'); - - // First call runs first poll after 0ms + async ({ controller, mockApiServiceHandler }) => { controller.startPolling(null); await jestAdvanceTime({ duration: 0 }); - expect(executePollSpy).toHaveBeenCalledTimes(1); - - const clearTimeoutCallCountBefore = clearTimeoutSpy.mock.calls.length; + const callsAfterFirst = mockApiServiceHandler.mock.calls.length; - // Second call reuses same session (same input); no new _startPolling, so no extra executePoll controller.startPolling(null); await jestAdvanceTime({ duration: 0 }); - expect(executePollSpy).toHaveBeenCalledTimes(1); - - // _startPolling clears before setting; clearTimeout is used when rescheduling after executePoll - expect(clearTimeoutSpy.mock.calls.length).toBeGreaterThanOrEqual( - clearTimeoutCallCountBefore, - ); + expect(mockApiServiceHandler).toHaveBeenCalledTimes(callsAfterFirst); controller.stopAllPolling(); }, @@ -1117,7 +1092,11 @@ describe('ConfigRegistryController', () => { it('uses fallback config when feature flag is disabled', async () => { await withController( { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, - async ({ controller, mockRemoteFeatureFlagGetState }) => { + async ({ + controller, + mockRemoteFeatureFlagGetState, + mockApiServiceHandler, + }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { configRegistryApiEnabled: false, @@ -1125,12 +1104,11 @@ describe('ConfigRegistryController', () => { cacheTimestamp: Date.now(), }); - const executePollSpy = jest.spyOn(controller, '_executePoll'); controller.startPolling(null); await jestAdvanceTime({ duration: 0 }); - expect(executePollSpy).toHaveBeenCalledTimes(1); + expect(mockApiServiceHandler).not.toHaveBeenCalled(); expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG, }); @@ -1636,18 +1614,21 @@ describe('ConfigRegistryController', () => { it('defaults to fallback when feature flag is not set', async () => { await withController( { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, - async ({ controller, mockRemoteFeatureFlagGetState }) => { + async ({ + controller, + mockRemoteFeatureFlagGetState, + mockApiServiceHandler, + }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: {}, cacheTimestamp: Date.now(), }); - const executePollSpy = jest.spyOn(controller, '_executePoll'); controller.startPolling(null); await jestAdvanceTime({ duration: 0 }); - expect(executePollSpy).toHaveBeenCalledTimes(1); + expect(mockApiServiceHandler).not.toHaveBeenCalled(); expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG, }); @@ -1660,17 +1641,20 @@ describe('ConfigRegistryController', () => { it('defaults to fallback when RemoteFeatureFlagController is unavailable', async () => { await withController( { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, - async ({ controller, mockRemoteFeatureFlagGetState }) => { + async ({ + controller, + mockRemoteFeatureFlagGetState, + mockApiServiceHandler, + }) => { mockRemoteFeatureFlagGetState.mockImplementation(() => { throw new Error('RemoteFeatureFlagController not available'); }); - const executePollSpy = jest.spyOn(controller, '_executePoll'); controller.startPolling(null); await jestAdvanceTime({ duration: 0 }); - expect(executePollSpy).toHaveBeenCalledTimes(1); + expect(mockApiServiceHandler).not.toHaveBeenCalled(); expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG, }); @@ -1683,21 +1667,22 @@ describe('ConfigRegistryController', () => { describe('KeyringController event listeners', () => { it('starts polling when KeyringController:unlock event is published', async () => { - await withController(async ({ controller, rootMessenger }) => { - const executePollSpy = jest.spyOn(controller, '_executePoll'); - const startPollingSpy = jest.spyOn(controller, 'startPolling'); + await withController( + async ({ controller, rootMessenger, mockApiServiceHandler }) => { + const startPollingSpy = jest.spyOn(controller, 'startPolling'); - expect(startPollingSpy).not.toHaveBeenCalled(); + expect(startPollingSpy).not.toHaveBeenCalled(); - rootMessenger.publish('KeyringController:unlock'); + rootMessenger.publish('KeyringController:unlock'); - await jestAdvanceTime({ duration: 0 }); + await jestAdvanceTime({ duration: 0 }); - expect(startPollingSpy).toHaveBeenCalledWith(null); - expect(executePollSpy).toHaveBeenCalledTimes(1); + expect(startPollingSpy).toHaveBeenCalledWith(null); + expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); - controller.stopAllPolling(); - }); + controller.stopAllPolling(); + }, + ); }); it('stops polling when KeyringController:lock event is published', async () => { @@ -1714,13 +1699,11 @@ describe('ConfigRegistryController', () => { }); it('calls startPolling with default parameter when called without arguments', async () => { - await withController(async ({ controller }) => { - const executePollSpy = jest.spyOn(controller, '_executePoll'); - + await withController(async ({ controller, mockApiServiceHandler }) => { controller.startPolling(null); await jestAdvanceTime({ duration: 0 }); - expect(executePollSpy).toHaveBeenCalledTimes(1); + expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); controller.stopAllPolling(); }); @@ -1740,20 +1723,19 @@ describe('ConfigRegistryController', () => { }, }, }, - async ({ controller }) => { - const executePollSpy = jest.spyOn(controller, '_executePoll'); + async ({ controller, mockApiServiceHandler }) => { controller.startPolling(null); - // StaticIntervalPollingController runs first poll after 0ms await jestAdvanceTime({ duration: 0 }); - expect(executePollSpy).toHaveBeenCalledTimes(1); + const callsAfterFirstAdvance = + mockApiServiceHandler.mock.calls.length; - // Stop polling should clear the next scheduled timeout controller.stopAllPolling(); - // Advance time past when the next poll would have fired await jestAdvanceTime({ duration: pollingInterval }); - expect(executePollSpy).toHaveBeenCalledTimes(1); + expect(mockApiServiceHandler).toHaveBeenCalledTimes( + callsAfterFirstAdvance, + ); }, ); }); @@ -1777,20 +1759,19 @@ describe('ConfigRegistryController', () => { }, }, }, - async ({ controller }) => { - const executePollSpy = jest.spyOn(controller, '_executePoll'); + async ({ controller, mockApiServiceHandler }) => { const token = controller.startPolling(null); - // StaticIntervalPollingController runs first poll after 0ms await jestAdvanceTime({ duration: 0 }); - expect(executePollSpy).toHaveBeenCalledTimes(1); + const callsAfterFirstAdvance = + mockApiServiceHandler.mock.calls.length; - // Stop polling using the placeholder token controller.stopPollingByPollingToken(token); - // Advance time past when the next poll would have fired await jestAdvanceTime({ duration: pollingInterval }); - expect(executePollSpy).toHaveBeenCalledTimes(1); + expect(mockApiServiceHandler).toHaveBeenCalledTimes( + callsAfterFirstAdvance, + ); }, ); }); @@ -1808,75 +1789,59 @@ describe('ConfigRegistryController', () => { }, }, }, - async ({ controller }) => { - const executePollSpy = jest.spyOn(controller, '_executePoll'); + async ({ controller, mockApiServiceHandler }) => { const token = controller.startPolling(null); - // Advance time to when the delayed poll starts await jestAdvanceTime({ duration: remainingTime + 1 }); - expect(executePollSpy).toHaveBeenCalledTimes(1); - executePollSpy.mockClear(); + expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); + mockApiServiceHandler.mockClear(); - // Stop polling using the placeholder token (should map to actual token) controller.stopPollingByPollingToken(token); - // Advance time to verify polling stopped await jestAdvanceTime({ duration: pollingInterval }); - expect(executePollSpy).not.toHaveBeenCalled(); + expect(mockApiServiceHandler).not.toHaveBeenCalled(); }, ); }); it('stops all polling when called without token (backward compatible)', async () => { - await withController(async ({ controller }) => { - const executePollSpy = jest.spyOn(controller, '_executePoll'); - - // Start polling from multiple consumers + await withController(async ({ controller, mockApiServiceHandler }) => { controller.startPolling(null); controller.startPolling(null); await jestAdvanceTime({ duration: 0 }); - expect(executePollSpy).toHaveBeenCalledTimes(1); - executePollSpy.mockClear(); + expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); + mockApiServiceHandler.mockClear(); - // Stop without token should stop all polling controller.stopAllPolling(); await jestAdvanceTime({ duration: DEFAULT_POLLING_INTERVAL }); - expect(executePollSpy).not.toHaveBeenCalled(); + expect(mockApiServiceHandler).not.toHaveBeenCalled(); }); }); it('stops specific polling session when called with token', async () => { - await withController(async ({ controller }) => { - const executePollSpy = jest.spyOn(controller, '_executePoll'); - - // Start polling from consumer A + await withController(async ({ controller, mockApiServiceHandler }) => { const tokenA = controller.startPolling(null); await jestAdvanceTime({ duration: 0 }); - expect(executePollSpy).toHaveBeenCalledTimes(1); - executePollSpy.mockClear(); + expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); + mockApiServiceHandler.mockClear(); - // Start polling from consumer B (reuses same polling session) const tokenB = controller.startPolling(null); await jestAdvanceTime({ duration: 0 }); - expect(executePollSpy).toHaveBeenCalledTimes(0); - executePollSpy.mockClear(); + expect(mockApiServiceHandler).not.toHaveBeenCalled(); + mockApiServiceHandler.mockClear(); - // Stop both consumers so the shared session is fully stopped controller.stopPollingByPollingToken(tokenA); controller.stopPollingByPollingToken(tokenB); - // No more polls after session is stopped await jestAdvanceTime({ duration: DEFAULT_POLLING_INTERVAL }); - expect(executePollSpy).not.toHaveBeenCalled(); + expect(mockApiServiceHandler).not.toHaveBeenCalled(); }); }); it('works via messenger action with token', async () => { - await withController(async ({ controller, messenger }) => { - const executePollSpy = jest.spyOn(controller, '_executePoll'); - + await withController(async ({ messenger, mockApiServiceHandler }) => { const token = messenger.call( 'ConfigRegistryController:startPolling', null, @@ -1884,20 +1849,17 @@ describe('ConfigRegistryController', () => { expect(typeof token).toBe('string'); await jestAdvanceTime({ duration: 0 }); - expect(executePollSpy).toHaveBeenCalledTimes(1); - executePollSpy.mockClear(); + expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); + mockApiServiceHandler.mockClear(); - // Stop via messenger action (stops all polling) messenger.call('ConfigRegistryController:stopPolling'); await jestAdvanceTime({ duration: DEFAULT_POLLING_INTERVAL }); - expect(executePollSpy).not.toHaveBeenCalled(); + expect(mockApiServiceHandler).not.toHaveBeenCalled(); }); }); it('works via messenger action without token (backward compatible)', async () => { - await withController(async ({ controller, messenger }) => { - const executePollSpy = jest.spyOn(controller, '_executePoll'); - + await withController(async ({ messenger, mockApiServiceHandler }) => { const token = messenger.call( 'ConfigRegistryController:startPolling', null, @@ -1905,13 +1867,12 @@ describe('ConfigRegistryController', () => { expect(typeof token).toBe('string'); await jestAdvanceTime({ duration: 0 }); - expect(executePollSpy).toHaveBeenCalledTimes(1); - executePollSpy.mockClear(); + expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); + mockApiServiceHandler.mockClear(); - // Stop without token via messenger (backward compatible) messenger.call('ConfigRegistryController:stopPolling'); await jestAdvanceTime({ duration: DEFAULT_POLLING_INTERVAL }); - expect(executePollSpy).not.toHaveBeenCalled(); + expect(mockApiServiceHandler).not.toHaveBeenCalled(); }); }); }); diff --git a/tests/fake-provider.ts b/tests/fake-provider.ts index f46b314b03a..096bed2e40c 100644 --- a/tests/fake-provider.ts +++ b/tests/fake-provider.ts @@ -1,9 +1,9 @@ import { InternalProvider } from '@metamask/eth-json-rpc-provider'; -import { - JsonRpcEngineV2, - type JsonRpcMiddleware, - type MiddlewareContext, - type ResultConstraint, +import { JsonRpcEngineV2 } from '@metamask/json-rpc-engine/v2'; +import type { + JsonRpcMiddleware, + MiddlewareContext, + ResultConstraint, } from '@metamask/json-rpc-engine/v2'; import type { Provider } from '@metamask/network-controller'; import type { @@ -139,7 +139,7 @@ export class FakeProvider super({ engine: JsonRpcEngineV2.create({ middleware: [ - () => { + (): never => { throw new Error('FakeProvider received unstubbed method call'); }, ], @@ -156,6 +156,8 @@ export class FakeProvider return new Promise((resolve, reject) => { this.#handleSend(payload, (error, providerRes) => { if (error) { + // Error is `unknown`. + // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors reject(error); } else { resolve(providerRes.result); @@ -169,7 +171,7 @@ export class FakeProvider // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any callback: (error: unknown, providerRes?: any) => void, - ) => { + ): void => { return this.#handleSend(payload, callback); }; @@ -178,7 +180,7 @@ export class FakeProvider // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any callback: (error: unknown, providerRes?: any) => void, - ) => { + ): void => { return this.#handleSend(req, callback); }; @@ -187,7 +189,7 @@ export class FakeProvider // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any callback: (error: unknown, providerRes?: any) => void, - ) { + ): void { if (Array.isArray(req)) { throw new Error("Arrays aren't supported"); } @@ -220,9 +222,7 @@ export class FakeProvider throw new Error(message); } else { - // We are already checking that this stub exists above. - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const stub = this.#stubs[index]!; + const stub = this.#stubs[index]; if (stub.discardAfterMatching !== false) { this.#stubs.splice(index, 1); @@ -246,10 +246,8 @@ export class FakeProvider async #handleRequest( stub: FakeProviderStub, - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - callback: (error: unknown, response?: JsonRpcResponse) => void, - ) { + callback: (error: unknown, response?: JsonRpcResponse) => void, + ): Promise { if (stub.beforeCompleting) { await stub.beforeCompleting(); } From 2c63cfc77e1dde17a6cdc1ccfda5ca38298dd17b Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Fri, 20 Feb 2026 19:21:05 +0100 Subject: [PATCH 41/55] chore: simplify tests --- .../config-registry-controller/package.json | 7 +- .../src/ConfigRegistryController.test.ts | 71 ++++----- .../config-registry-api-service.test.ts | 117 +++++++-------- yarn.lock | 138 +----------------- 4 files changed, 92 insertions(+), 241 deletions(-) diff --git a/packages/config-registry-controller/package.json b/packages/config-registry-controller/package.json index f603d992359..2ceefaf136c 100644 --- a/packages/config-registry-controller/package.json +++ b/packages/config-registry-controller/package.json @@ -49,9 +49,9 @@ }, "dependencies": { "@metamask/base-controller": "^9.0.0", - "@metamask/controller-utils": "^11.18.0", + "@metamask/controller-utils": "^11.19.0", "@metamask/messenger": "^0.3.0", - "@metamask/polling-controller": "^16.0.2", + "@metamask/polling-controller": "^16.0.3", "@metamask/profile-sync-controller": "^27.1.0", "@metamask/remote-feature-flag-controller": "^4.0.0", "@metamask/superstruct": "^3.1.0", @@ -66,9 +66,8 @@ "deepmerge": "^4.2.2", "jest": "^29.7.0", "nock": "^13.3.1", - "sinon": "^9.2.4", "ts-jest": "^29.2.5", - "typedoc": "^0.24.8", + "typedoc": "^0.25.13", "typedoc-plugin-missing-exports": "^2.0.0", "typescript": "~5.3.3" }, diff --git a/packages/config-registry-controller/src/ConfigRegistryController.test.ts b/packages/config-registry-controller/src/ConfigRegistryController.test.ts index e3e776903ee..03e21b137b1 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.test.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.test.ts @@ -618,7 +618,11 @@ describe('ConfigRegistryController', () => { }, }, }, - async ({ controller, messenger, mockRemoteFeatureFlagGetState }) => { + async ({ + controller, + mockRemoteFeatureFlagGetState, + mockApiServiceHandler, + }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { configRegistryApiEnabled: true, @@ -626,18 +630,10 @@ describe('ConfigRegistryController', () => { cacheTimestamp: now, }); - const fetchConfigSpy = jest.spyOn( - messenger, - 'call', - ) as jest.SpyInstance; - controller.startPolling(null); await jestAdvanceTime({ duration: 0 }); - expect(fetchConfigSpy).not.toHaveBeenCalledWith( - 'ConfigRegistryApiService:fetchConfig', - expect.anything(), - ); + expect(mockApiServiceHandler).not.toHaveBeenCalled(); }, ); }); @@ -752,7 +748,11 @@ describe('ConfigRegistryController', () => { }, }, }, - async ({ controller, messenger, mockRemoteFeatureFlagGetState }) => { + async ({ + controller, + mockRemoteFeatureFlagGetState, + mockApiServiceHandler, + }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { configRegistryApiEnabled: true, @@ -760,17 +760,9 @@ describe('ConfigRegistryController', () => { cacheTimestamp: Date.now(), }); - const fetchConfigSpy = jest.spyOn( - messenger, - 'call', - ) as jest.SpyInstance; - controller.startPolling(null); - expect(fetchConfigSpy).not.toHaveBeenCalledWith( - 'ConfigRegistryApiService:fetchConfig', - expect.anything(), - ); + expect(mockApiServiceHandler).not.toHaveBeenCalled(); }, ); }); @@ -785,7 +777,11 @@ describe('ConfigRegistryController', () => { }, }, }, - async ({ controller, messenger, mockRemoteFeatureFlagGetState }) => { + async ({ + controller, + mockRemoteFeatureFlagGetState, + mockApiServiceHandler, + }) => { mockRemoteFeatureFlagGetState.mockReturnValue({ remoteFeatureFlags: { configRegistryApiEnabled: true, @@ -797,17 +793,9 @@ describe('ConfigRegistryController', () => { .spyOn(controller, 'getIntervalLength') .mockReturnValue(undefined); - const fetchConfigSpy = jest.spyOn( - messenger, - 'call', - ) as jest.SpyInstance; - controller.startPolling(null); - expect(fetchConfigSpy).not.toHaveBeenCalledWith( - 'ConfigRegistryApiService:fetchConfig', - expect.anything(), - ); + expect(mockApiServiceHandler).not.toHaveBeenCalled(); }, ); }); @@ -1669,15 +1657,10 @@ describe('ConfigRegistryController', () => { it('starts polling when KeyringController:unlock event is published', async () => { await withController( async ({ controller, rootMessenger, mockApiServiceHandler }) => { - const startPollingSpy = jest.spyOn(controller, 'startPolling'); - - expect(startPollingSpy).not.toHaveBeenCalled(); - rootMessenger.publish('KeyringController:unlock'); await jestAdvanceTime({ duration: 0 }); - expect(startPollingSpy).toHaveBeenCalledWith(null); expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); controller.stopAllPolling(); @@ -1686,16 +1669,18 @@ describe('ConfigRegistryController', () => { }); it('stops polling when KeyringController:lock event is published', async () => { - await withController(async ({ controller, rootMessenger }) => { - const stopPollingSpy = jest.spyOn(controller, 'stopAllPolling'); - - await jestAdvanceTime({ duration: 0 }); - expect(stopPollingSpy).not.toHaveBeenCalled(); + await withController( + async ({ controller, rootMessenger, mockApiServiceHandler }) => { + controller.startPolling(null); + await jestAdvanceTime({ duration: 0 }); + const callsAfterUnlock = mockApiServiceHandler.mock.calls.length; - rootMessenger.publish('KeyringController:lock'); + rootMessenger.publish('KeyringController:lock'); - expect(stopPollingSpy).toHaveBeenCalled(); - }); + await jestAdvanceTime({ duration: DEFAULT_POLLING_INTERVAL }); + expect(mockApiServiceHandler).toHaveBeenCalledTimes(callsAfterUnlock); + }, + ); }); it('calls startPolling with default parameter when called without arguments', async () => { diff --git a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts index 62a1140f217..2806c8c192c 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts @@ -1,11 +1,16 @@ import { SDK } from '@metamask/profile-sync-controller'; import nock from 'nock'; -import { useFakeTimers } from 'sinon'; import { ConfigRegistryApiService } from './config-registry-api-service'; import type { RegistryConfigApiResponse } from './types'; +import { jestAdvanceTime } from '../../../../tests/helpers'; import { createMockNetworkConfig } from '../test-helpers'; +const CONFIG_PATH = '/v1/config/networks'; +const UAT_ORIGIN = 'https://client-config.uat-api.cx.metamask.io'; +const DEV_ORIGIN = 'https://client-config.dev-api.cx.metamask.io'; +const PRD_ORIGIN = 'https://client-config.api.cx.metamask.io'; + const MOCK_API_RESPONSE: RegistryConfigApiResponse = { data: { version: '"24952800ba9dafbc5e2c91f57f386d28"', @@ -18,8 +23,8 @@ describe('ConfigRegistryApiService', () => { describe('fetchConfig', () => { describe('URL by env', () => { it('uses UAT URL when env is UAT', async () => { - const scope = nock('https://client-config.uat-api.cx.metamask.io') - .get('/v1/config/networks') + const scope = nock(UAT_ORIGIN) + .get(CONFIG_PATH) .reply(200, MOCK_API_RESPONSE); const service = new ConfigRegistryApiService({ env: SDK.Env.UAT }); @@ -28,8 +33,8 @@ describe('ConfigRegistryApiService', () => { }); it('uses DEV URL when env is DEV', async () => { - const scope = nock('https://client-config.dev-api.cx.metamask.io') - .get('/v1/config/networks') + const scope = nock(DEV_ORIGIN) + .get(CONFIG_PATH) .reply(200, MOCK_API_RESPONSE); const service = new ConfigRegistryApiService({ env: SDK.Env.DEV }); @@ -38,8 +43,8 @@ describe('ConfigRegistryApiService', () => { }); it('uses PRD URL when env is PRD', async () => { - const scope = nock('https://client-config.api.cx.metamask.io') - .get('/v1/config/networks') + const scope = nock(PRD_ORIGIN) + .get(CONFIG_PATH) .reply(200, MOCK_API_RESPONSE); const service = new ConfigRegistryApiService({ env: SDK.Env.PRD }); @@ -48,8 +53,8 @@ describe('ConfigRegistryApiService', () => { }); it('defaults to UAT environment', async () => { - const scope = nock('https://client-config.uat-api.cx.metamask.io') - .get('/v1/config/networks') + const scope = nock(UAT_ORIGIN) + .get(CONFIG_PATH) .reply(200, MOCK_API_RESPONSE); const service = new ConfigRegistryApiService(); @@ -61,8 +66,8 @@ describe('ConfigRegistryApiService', () => { }); it('fetches config from API successfully', async () => { - const scope = nock('https://client-config.uat-api.cx.metamask.io') - .get('/v1/config/networks') + const scope = nock(UAT_ORIGIN) + .get(CONFIG_PATH) .reply(200, MOCK_API_RESPONSE, { ETag: '"test-etag-123"', }); @@ -79,8 +84,8 @@ describe('ConfigRegistryApiService', () => { }); it('fetches config from API without ETag header', async () => { - const scope = nock('https://client-config.uat-api.cx.metamask.io') - .get('/v1/config/networks') + const scope = nock(UAT_ORIGIN) + .get(CONFIG_PATH) .reply(200, MOCK_API_RESPONSE); const service = new ConfigRegistryApiService(); @@ -93,8 +98,8 @@ describe('ConfigRegistryApiService', () => { it('handles 304 Not Modified response', async () => { const etag = '"test-etag-123"'; - const scope = nock('https://client-config.uat-api.cx.metamask.io') - .get('/v1/config/networks') + const scope = nock(UAT_ORIGIN) + .get(CONFIG_PATH) .matchHeader('If-None-Match', etag) .reply(304); @@ -108,16 +113,16 @@ describe('ConfigRegistryApiService', () => { it('returns cached data when 304 is received and service has prior successful response', async () => { const etag = '"test-etag-123"'; - const firstScope = nock('https://client-config.uat-api.cx.metamask.io') - .get('/v1/config/networks') + const firstScope = nock(UAT_ORIGIN) + .get(CONFIG_PATH) .reply(200, MOCK_API_RESPONSE, { ETag: etag }); const service = new ConfigRegistryApiService(); await service.fetchConfig(); expect(firstScope.isDone()).toBe(true); - const secondScope = nock('https://client-config.uat-api.cx.metamask.io') - .get('/v1/config/networks') + const secondScope = nock(UAT_ORIGIN) + .get(CONFIG_PATH) .matchHeader('If-None-Match', etag) .reply(304); @@ -129,9 +134,7 @@ describe('ConfigRegistryApiService', () => { }); it('handles 304 Not Modified response without ETag header', async () => { - const scope = nock('https://client-config.uat-api.cx.metamask.io') - .get('/v1/config/networks') - .reply(304); + const scope = nock(UAT_ORIGIN).get(CONFIG_PATH).reply(304); const service = new ConfigRegistryApiService(); const result = await service.fetchConfig(); @@ -143,8 +146,8 @@ describe('ConfigRegistryApiService', () => { it('includes If-None-Match header when etag is provided', async () => { const etag = '"test-etag-123"'; - const scope = nock('https://client-config.uat-api.cx.metamask.io') - .get('/v1/config/networks') + const scope = nock(UAT_ORIGIN) + .get(CONFIG_PATH) .matchHeader('If-None-Match', etag) .reply(200, MOCK_API_RESPONSE); @@ -155,8 +158,8 @@ describe('ConfigRegistryApiService', () => { }); it('does not include If-None-Match header when etag is undefined', async () => { - const scope = nock('https://client-config.uat-api.cx.metamask.io') - .get('/v1/config/networks') + const scope = nock(UAT_ORIGIN) + .get(CONFIG_PATH) .matchHeader('If-None-Match', (val) => val === undefined) .reply(200, MOCK_API_RESPONSE); @@ -167,8 +170,8 @@ describe('ConfigRegistryApiService', () => { }); it('handles fetchConfig called with undefined options', async () => { - const scope = nock('https://client-config.uat-api.cx.metamask.io') - .get('/v1/config/networks') + const scope = nock(UAT_ORIGIN) + .get(CONFIG_PATH) .reply(200, MOCK_API_RESPONSE); const service = new ConfigRegistryApiService(); @@ -179,8 +182,8 @@ describe('ConfigRegistryApiService', () => { it('throws error on invalid response structure', async () => { const invalidResponse = { invalid: 'data' }; - const scope = nock('https://client-config.uat-api.cx.metamask.io') - .get('/v1/config/networks') + const scope = nock(UAT_ORIGIN) + .get(CONFIG_PATH) .reply(200, invalidResponse); const service = new ConfigRegistryApiService(); @@ -192,9 +195,7 @@ describe('ConfigRegistryApiService', () => { }); it('throws error when data is null', async () => { - const scope = nock('https://client-config.uat-api.cx.metamask.io') - .get('/v1/config/networks') - .reply(200, 'null'); + const scope = nock(UAT_ORIGIN).get(CONFIG_PATH).reply(200, 'null'); const service = new ConfigRegistryApiService(); @@ -205,8 +206,8 @@ describe('ConfigRegistryApiService', () => { }); it('throws error when data.data is null', async () => { - const scope = nock('https://client-config.uat-api.cx.metamask.io') - .get('/v1/config/networks') + const scope = nock(UAT_ORIGIN) + .get(CONFIG_PATH) .reply(200, { data: null }); const service = new ConfigRegistryApiService(); @@ -218,8 +219,8 @@ describe('ConfigRegistryApiService', () => { }); it('throws error when data.data.networks is not an array', async () => { - const scope = nock('https://client-config.uat-api.cx.metamask.io') - .get('/v1/config/networks') + const scope = nock(UAT_ORIGIN) + .get(CONFIG_PATH) .reply(200, { data: { networks: 'not-an-array' } }); const service = new ConfigRegistryApiService(); @@ -231,8 +232,8 @@ describe('ConfigRegistryApiService', () => { }); it('throws error on HTTP error status', async () => { - const scope = nock('https://client-config.uat-api.cx.metamask.io') - .get('/v1/config/networks') + const scope = nock(UAT_ORIGIN) + .get(CONFIG_PATH) .reply(500, 'Internal Server Error'); const service = new ConfigRegistryApiService({ @@ -262,14 +263,10 @@ describe('ConfigRegistryApiService', () => { }); it('retries on failure', async () => { - nock('https://client-config.uat-api.cx.metamask.io') - .get('/v1/config/networks') - .replyWithError('Network error'); - nock('https://client-config.uat-api.cx.metamask.io') - .get('/v1/config/networks') - .replyWithError('Network error'); - const successScope = nock('https://client-config.uat-api.cx.metamask.io') - .get('/v1/config/networks') + nock(UAT_ORIGIN).get(CONFIG_PATH).replyWithError('Network error'); + nock(UAT_ORIGIN).get(CONFIG_PATH).replyWithError('Network error'); + const successScope = nock(UAT_ORIGIN) + .get(CONFIG_PATH) .reply(200, MOCK_API_RESPONSE); const service = new ConfigRegistryApiService({ @@ -284,14 +281,12 @@ describe('ConfigRegistryApiService', () => { }); describe('onBreak', () => { - let clock: sinon.SinonFakeTimers; - beforeEach(() => { - clock = useFakeTimers({ now: Date.now() }); + jest.useFakeTimers({ doNotFake: ['nextTick', 'queueMicrotask'] }); }); afterEach(() => { - clock.restore(); + jest.useRealTimers(); }); it('registers and calls onBreak handler', async () => { @@ -299,9 +294,7 @@ describe('ConfigRegistryApiService', () => { const retries = 0; for (let i = 0; i < maximumConsecutiveFailures; i++) { - nock('https://client-config.uat-api.cx.metamask.io') - .get('/v1/config/networks') - .replyWithError('Network error'); + nock(UAT_ORIGIN).get(CONFIG_PATH).replyWithError('Network error'); } const onBreakHandler = jest.fn(); @@ -319,14 +312,14 @@ describe('ConfigRegistryApiService', () => { await expect(service.fetchConfig()).rejects.toMatchObject( expect.objectContaining({ message: expect.any(String) }), ); - await clock.tickAsync(100); + await jestAdvanceTime({ duration: 100 }); } const finalPromise = service.fetchConfig(); finalPromise.catch(() => { // Expected rejection }); - await clock.tickAsync(100); + await jestAdvanceTime({ duration: 100 }); await expect(finalPromise).rejects.toMatchObject( expect.objectContaining({ message: expect.any(String) }), @@ -336,22 +329,20 @@ describe('ConfigRegistryApiService', () => { }); describe('onDegraded', () => { - let clock: sinon.SinonFakeTimers; - beforeEach(() => { - clock = useFakeTimers({ now: Date.now() }); + jest.useFakeTimers({ doNotFake: ['nextTick', 'queueMicrotask'] }); }); afterEach(() => { - clock.restore(); + jest.useRealTimers(); }); it('calls onDegraded handler when service becomes degraded', async () => { const degradedThreshold = 2000; // 2 seconds - nock('https://client-config.uat-api.cx.metamask.io') - .get('/v1/config/networks') + nock(UAT_ORIGIN) + .get(CONFIG_PATH) .reply(200, () => { - clock.tick(degradedThreshold + 100); + jest.advanceTimersByTime(degradedThreshold + 100); return MOCK_API_RESPONSE; }); diff --git a/yarn.lock b/yarn.lock index 4f11c0ad094..c22f14e1f40 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2933,9 +2933,9 @@ __metadata: "@lavamoat/allow-scripts": "npm:^3.0.4" "@metamask/auto-changelog": "npm:^3.4.4" "@metamask/base-controller": "npm:^9.0.0" - "@metamask/controller-utils": "npm:^11.18.0" + "@metamask/controller-utils": "npm:^11.19.0" "@metamask/messenger": "npm:^0.3.0" - "@metamask/polling-controller": "npm:^16.0.2" + "@metamask/polling-controller": "npm:^16.0.3" "@metamask/profile-sync-controller": "npm:^27.1.0" "@metamask/remote-feature-flag-controller": "npm:^4.0.0" "@metamask/superstruct": "npm:^3.1.0" @@ -2946,9 +2946,8 @@ __metadata: jest: "npm:^29.7.0" nock: "npm:^13.3.1" reselect: "npm:^5.1.1" - sinon: "npm:^9.2.4" ts-jest: "npm:^29.2.5" - typedoc: "npm:^0.24.8" + typedoc: "npm:^0.25.13" typedoc-plugin-missing-exports: "npm:^2.0.0" typescript: "npm:~5.3.3" languageName: unknown @@ -2980,7 +2979,7 @@ __metadata: languageName: node linkType: hard -"@metamask/controller-utils@npm:^11.18.0, @metamask/controller-utils@npm:^11.19.0, @metamask/controller-utils@workspace:packages/controller-utils": +"@metamask/controller-utils@npm:^11.19.0, @metamask/controller-utils@workspace:packages/controller-utils": version: 0.0.0-use.local resolution: "@metamask/controller-utils@workspace:packages/controller-utils" dependencies: @@ -4431,7 +4430,7 @@ __metadata: languageName: unknown linkType: soft -"@metamask/polling-controller@npm:^16.0.2, @metamask/polling-controller@npm:^16.0.3, @metamask/polling-controller@workspace:packages/polling-controller": +"@metamask/polling-controller@npm:^16.0.3, @metamask/polling-controller@workspace:packages/polling-controller": version: 0.0.0-use.local resolution: "@metamask/polling-controller@workspace:packages/polling-controller" dependencies: @@ -5550,15 +5549,6 @@ __metadata: languageName: node linkType: hard -"@sinonjs/commons@npm:^1.6.0, @sinonjs/commons@npm:^1.7.0, @sinonjs/commons@npm:^1.8.1": - version: 1.8.6 - resolution: "@sinonjs/commons@npm:1.8.6" - dependencies: - type-detect: "npm:4.0.8" - checksum: 10/51987338fd8b4d1e135822ad593dd23a3288764aa41d83c695124d512bc38b87eece859078008651ecc7f1df89a7e558a515dc6f02d21a93be4ba50b39a28914 - languageName: node - linkType: hard - "@sinonjs/commons@npm:^3.0.0": version: 3.0.1 resolution: "@sinonjs/commons@npm:3.0.1" @@ -5577,33 +5567,6 @@ __metadata: languageName: node linkType: hard -"@sinonjs/fake-timers@npm:^6.0.0, @sinonjs/fake-timers@npm:^6.0.1": - version: 6.0.1 - resolution: "@sinonjs/fake-timers@npm:6.0.1" - dependencies: - "@sinonjs/commons": "npm:^1.7.0" - checksum: 10/c7ee19f62bd0ca52553dd5fca9b3921373218c9fed0f02af2f8e5261f65ce9ff0a5e55ca612ded6daf4088a243e905d61bd6dce1c6d325794283b55c71708395 - languageName: node - linkType: hard - -"@sinonjs/samsam@npm:^5.3.1": - version: 5.3.1 - resolution: "@sinonjs/samsam@npm:5.3.1" - dependencies: - "@sinonjs/commons": "npm:^1.6.0" - lodash.get: "npm:^4.4.2" - type-detect: "npm:^4.0.8" - checksum: 10/6850b9980f042a844072a34ce3ca80b098d4550c8c7a83b2b2e7beb1e06ad19608699544b7a8b0c7db882528d8b74321dfd185d0651cff08cbe793cb73dd39d3 - languageName: node - linkType: hard - -"@sinonjs/text-encoding@npm:^0.7.1": - version: 0.7.3 - resolution: "@sinonjs/text-encoding@npm:0.7.3" - checksum: 10/f0cc89bae36e7ce159187dece7800b78831288f1913e9ae8cf8a878da5388232d2049740f6f4a43ec4b43b8ad1beb55f919f45eb9a577adb4a2a6eacb27b25fc - languageName: node - linkType: hard - "@solana/addresses@npm:^2.0.0": version: 2.0.0 resolution: "@solana/addresses@npm:2.0.0" @@ -7878,13 +7841,6 @@ __metadata: languageName: node linkType: hard -"diff@npm:^4.0.2": - version: 4.0.4 - resolution: "diff@npm:4.0.4" - checksum: 10/5019b3f5ae124ea9e95137119e1a83a59c252c75ddac873cc967832fd7a834570a58a4d58b941bdbd07832ebf98dcb232b27c561b7f5584357da6dae59bcac62 - languageName: node - linkType: hard - "diff@npm:^5.0.0": version: 5.2.0 resolution: "diff@npm:5.2.0" @@ -9992,13 +9948,6 @@ __metadata: languageName: node linkType: hard -"isarray@npm:0.0.1": - version: 0.0.1 - resolution: "isarray@npm:0.0.1" - checksum: 10/49191f1425681df4a18c2f0f93db3adb85573bcdd6a4482539d98eac9e705d8961317b01175627e860516a2fc45f8f9302db26e5a380a97a520e272e2a40a8d4 - languageName: node - linkType: hard - "isarray@npm:~1.0.0": version: 1.0.0 resolution: "isarray@npm:1.0.0" @@ -10828,13 +10777,6 @@ __metadata: languageName: node linkType: hard -"just-extend@npm:^4.0.2": - version: 4.2.1 - resolution: "just-extend@npm:4.2.1" - checksum: 10/375389c0847d56300873fa622fbc5c5e208933e372bbedb39c82f583299cdad4fe9c4773bc35fcd9c42cd85744f07474ca4163aa0f9125dd5be37bc09075eb49 - languageName: node - linkType: hard - "keccak@npm:^3.0.0": version: 3.0.4 resolution: "keccak@npm:3.0.4" @@ -10926,13 +10868,6 @@ __metadata: languageName: node linkType: hard -"lodash.get@npm:^4.4.2": - version: 4.4.2 - resolution: "lodash.get@npm:4.4.2" - checksum: 10/2a4925f6e89bc2c010a77a802d1ba357e17ed1ea03c2ddf6a146429f2856a216663e694a6aa3549a318cbbba3fd8b7decb392db457e6ac0b83dc745ed0a17380 - languageName: node - linkType: hard - "lodash.isplainobject@npm:^4.0.6": version: 4.0.6 resolution: "lodash.isplainobject@npm:4.0.6" @@ -11285,7 +11220,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^9.0.0, minimatch@npm:^9.0.3, minimatch@npm:^9.0.4, minimatch@npm:^9.0.5": +"minimatch@npm:^9.0.3, minimatch@npm:^9.0.4, minimatch@npm:^9.0.5": version: 9.0.5 resolution: "minimatch@npm:9.0.5" dependencies: @@ -11494,19 +11429,6 @@ __metadata: languageName: node linkType: hard -"nise@npm:^4.0.4": - version: 4.1.0 - resolution: "nise@npm:4.1.0" - dependencies: - "@sinonjs/commons": "npm:^1.7.0" - "@sinonjs/fake-timers": "npm:^6.0.0" - "@sinonjs/text-encoding": "npm:^0.7.1" - just-extend: "npm:^4.0.2" - path-to-regexp: "npm:^1.7.0" - checksum: 10/ff7c2e316c8ae8327573417fefcc84070d9dcfa423b123d014d21db5f7de07580f76a85143c2f91eaf5f1a979f3f9a3721e3652753e58ddaa703aa8d65539b0b - languageName: node - linkType: hard - "nock@npm:^13.3.1": version: 13.5.5 resolution: "nock@npm:13.5.5" @@ -11964,15 +11886,6 @@ __metadata: languageName: node linkType: hard -"path-to-regexp@npm:^1.7.0": - version: 1.9.0 - resolution: "path-to-regexp@npm:1.9.0" - dependencies: - isarray: "npm:0.0.1" - checksum: 10/67f0f4823f7aab356523d93a83f9f8222bdd119fa0b27a8f8b587e8e6c9825294bb4ccd16ae619def111ff3fe5d15ff8f658cdd3b0d58b9c882de6fd15bc1b76 - languageName: node - linkType: hard - "path-type@npm:^4.0.0": version: 4.0.0 resolution: "path-type@npm:4.0.0" @@ -12853,7 +12766,7 @@ __metadata: languageName: node linkType: hard -"shiki@npm:^0.14.1, shiki@npm:^0.14.7": +"shiki@npm:^0.14.7": version: 0.14.7 resolution: "shiki@npm:0.14.7" dependencies: @@ -12907,20 +12820,6 @@ __metadata: languageName: node linkType: hard -"sinon@npm:^9.2.4": - version: 9.2.4 - resolution: "sinon@npm:9.2.4" - dependencies: - "@sinonjs/commons": "npm:^1.8.1" - "@sinonjs/fake-timers": "npm:^6.0.1" - "@sinonjs/samsam": "npm:^5.3.1" - diff: "npm:^4.0.2" - nise: "npm:^4.0.4" - supports-color: "npm:^7.1.0" - checksum: 10/4597c12e2490b22aaae5fb1edca169a10e71dee73c13d2d12d6d9fa7f3bdbdb53ec5ad52c631c301fb3eab79471a30b05be65155c30ca415169470ea4789eae6 - languageName: node - linkType: hard - "sisteransi@npm:^1.0.5": version: 1.0.5 resolution: "sisteransi@npm:1.0.5" @@ -13581,13 +13480,6 @@ __metadata: languageName: node linkType: hard -"type-detect@npm:^4.0.8": - version: 4.1.0 - resolution: "type-detect@npm:4.1.0" - checksum: 10/e363bf0352427a79301f26a7795a27718624c49c576965076624eb5495d87515030b207217845f7018093adcbe169b2d119bb9b7f1a31a92bfbb1ab9639ca8dd - languageName: node - linkType: hard - "type-fest@npm:^0.18.0": version: 0.18.1 resolution: "type-fest@npm:0.18.1" @@ -13649,22 +13541,6 @@ __metadata: languageName: node linkType: hard -"typedoc@npm:^0.24.8": - version: 0.24.8 - resolution: "typedoc@npm:0.24.8" - dependencies: - lunr: "npm:^2.3.9" - marked: "npm:^4.3.0" - minimatch: "npm:^9.0.0" - shiki: "npm:^0.14.1" - peerDependencies: - typescript: 4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x - bin: - typedoc: bin/typedoc - checksum: 10/4f2f92ddde3f70a1a9666507f6bdf6620023599bd2c2a3ed3f8f909f9c28d92594c30ee6ee68f5a248ff70e09623acf1323bad633cb713b9f2e36bbd4fccf683 - languageName: node - linkType: hard - "typedoc@npm:^0.25.13": version: 0.25.13 resolution: "typedoc@npm:0.25.13" From 8ed3a1f7cc1b8bffbbe40bbbe0484ea1be89e201 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Fri, 20 Feb 2026 19:37:58 +0100 Subject: [PATCH 42/55] fix: fix cursor bot comment --- .../src/ConfigRegistryController.test.ts | 12 ++++++++---- .../src/ConfigRegistryController.ts | 6 +++++- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/packages/config-registry-controller/src/ConfigRegistryController.test.ts b/packages/config-registry-controller/src/ConfigRegistryController.test.ts index 03e21b137b1..cf3e9965133 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.test.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.test.ts @@ -768,10 +768,12 @@ describe('ConfigRegistryController', () => { }); it('uses DEFAULT_POLLING_INTERVAL when getIntervalLength returns undefined', async () => { + const pollingInterval = 10000; const recentTimestamp = Date.now() - 1000; await withController( { options: { + pollingInterval, state: { lastFetched: recentTimestamp, }, @@ -794,6 +796,7 @@ describe('ConfigRegistryController', () => { .mockReturnValue(undefined); controller.startPolling(null); + await jestAdvanceTime({ duration: pollingInterval }); expect(mockApiServiceHandler).not.toHaveBeenCalled(); }, @@ -931,7 +934,6 @@ describe('ConfigRegistryController', () => { it('delays first poll when lastFetched is recent', async () => { const pollingInterval = 10000; const recentTimestamp = Date.now() - 2000; - const remainingTime = pollingInterval - 2000; await withController( { options: { @@ -945,7 +947,7 @@ describe('ConfigRegistryController', () => { controller.startPolling(null); await jestAdvanceTime({ duration: 0 }); - await jestAdvanceTime({ duration: remainingTime + 1 }); + await jestAdvanceTime({ duration: pollingInterval }); expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); controller.stopAllPolling(); @@ -1026,10 +1028,12 @@ describe('ConfigRegistryController', () => { }); it('uses DEFAULT_POLLING_INTERVAL when getIntervalLength returns undefined', async () => { + const pollingInterval = 10000; const recentTimestamp = Date.now() - 1000; await withController( { options: { + pollingInterval, state: { lastFetched: recentTimestamp, }, @@ -1041,6 +1045,7 @@ describe('ConfigRegistryController', () => { .mockReturnValue(undefined); controller.startPolling(null); + await jestAdvanceTime({ duration: pollingInterval }); expect(mockApiServiceHandler).not.toHaveBeenCalled(); @@ -1764,7 +1769,6 @@ describe('ConfigRegistryController', () => { it('stops delayed poll using placeholder token after timeout fires', async () => { const pollingInterval = 10000; const recentTimestamp = Date.now() - 2000; - const remainingTime = pollingInterval - 2000; await withController( { options: { @@ -1777,7 +1781,7 @@ describe('ConfigRegistryController', () => { async ({ controller, mockApiServiceHandler }) => { const token = controller.startPolling(null); - await jestAdvanceTime({ duration: remainingTime + 1 }); + await jestAdvanceTime({ duration: pollingInterval }); expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); mockApiServiceHandler.mockClear(); diff --git a/packages/config-registry-controller/src/ConfigRegistryController.ts b/packages/config-registry-controller/src/ConfigRegistryController.ts index 8f9da2809d8..3b3e8f6f408 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.ts @@ -248,7 +248,11 @@ export class ConfigRegistryController extends StaticIntervalPollingController Date: Fri, 20 Feb 2026 19:39:00 +0100 Subject: [PATCH 43/55] chore: add comment to when future flag is off --- .../config-registry-controller/src/ConfigRegistryController.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/config-registry-controller/src/ConfigRegistryController.ts b/packages/config-registry-controller/src/ConfigRegistryController.ts index 3b3e8f6f408..986c753b1d1 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.ts @@ -244,6 +244,7 @@ export class ConfigRegistryController extends StaticIntervalPollingController { const isApiEnabled = this.#isConfigRegistryApiEnabled(this.messenger); + // Skip fetch when API is disabled; client uses static config. if (!isApiEnabled) { return; } From de595cc8b986e183ae77e8aeeee4b874cb799e83 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Mon, 23 Feb 2026 10:45:07 +0100 Subject: [PATCH 44/55] feat: adopt CAIP-2 config API response --- .../src/ConfigRegistryController.test.ts | 378 +++++------------- .../src/ConfigRegistryController.ts | 13 +- .../config-registry-api-service.test.ts | 12 +- .../filters.test.ts | 52 +-- .../config-registry-api-service/filters.ts | 9 +- .../src/config-registry-api-service/types.ts | 77 +++- .../src/selectors.test.ts | 52 +-- .../src/test-helpers.ts | 76 +++- 8 files changed, 285 insertions(+), 384 deletions(-) diff --git a/packages/config-registry-controller/src/ConfigRegistryController.test.ts b/packages/config-registry-controller/src/ConfigRegistryController.test.ts index cf3e9965133..01c231a03c9 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.test.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.test.ts @@ -63,7 +63,7 @@ function getConfigRegistryControllerMessenger(): { const MOCK_FALLBACK_CONFIG: Record = { 'fallback-key': createMockNetworkConfig({ - chainId: '0x2', + chainId: 'eip155:2', name: 'Fallback Network', }), }; @@ -84,7 +84,7 @@ function buildMockApiServiceHandler(overrides?: { data: { version: '1', timestamp: Date.now(), - networks: [], + chains: [], }, }, modified: true, @@ -171,7 +171,7 @@ describe('ConfigRegistryController', () => { it('sets initial state when provided', async () => { const initialNetworks: Record = { 'test-key': createMockNetworkConfig({ - chainId: '0x1', + chainId: 'eip155:1', name: 'Test Network', }), }; @@ -285,7 +285,7 @@ describe('ConfigRegistryController', () => { it('keeps existing configs when fetch fails and configs already exist', async () => { const existingNetworks: Record = { 'existing-key': createMockNetworkConfig({ - chainId: '0x3', + chainId: 'eip155:3', name: 'Existing Network', }), }; @@ -511,7 +511,7 @@ describe('ConfigRegistryController', () => { ); }); - it('handles validation error when result.data.data is missing', async () => { + it('handles validation error when result.data is missing', async () => { await withController( async ({ controller, @@ -527,7 +527,7 @@ describe('ConfigRegistryController', () => { }); const validationError = new Error( - 'Validation error: data.data is missing', + 'Validation error: data is missing', ); mockApiServiceHandler.mockRejectedValue(validationError); @@ -536,14 +536,14 @@ describe('ConfigRegistryController', () => { expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ - message: 'Validation error: data.data is missing', + message: 'Validation error: data is missing', }), ); }, ); }); - it('handles validation error when result.data.data.networks is not an array', async () => { + it('handles validation error when result.data.chains is not an array', async () => { await withController( async ({ controller, @@ -559,7 +559,7 @@ describe('ConfigRegistryController', () => { }); const validationError = new Error( - 'Validation error: data.data.networks is not an array', + 'Validation error: data.chains is not an array', ); mockApiServiceHandler.mockRejectedValue(validationError); @@ -568,14 +568,14 @@ describe('ConfigRegistryController', () => { expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ - message: 'Validation error: data.data.networks is not an array', + message: 'Validation error: data.chains is not an array', }), ); }, ); }); - it('handles validation error when result.data.data.version is not a string', async () => { + it('handles validation error when result.data.version is not a string', async () => { await withController( async ({ controller, @@ -591,7 +591,7 @@ describe('ConfigRegistryController', () => { }); const validationError = new Error( - 'Validation error: data.data.version is not a string', + 'Validation error: data.version is not a string', ); mockApiServiceHandler.mockRejectedValue(validationError); @@ -600,7 +600,7 @@ describe('ConfigRegistryController', () => { expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ - message: 'Validation error: data.data.version is not a string', + message: 'Validation error: data.version is not a string', }), ); }, @@ -662,13 +662,14 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockResolvedValue({ data: { data: { - networks: [ + version: '1.0.0', + timestamp: Date.now(), + chains: [ createMockNetworkConfig({ - chainId: '0x1', + chainId: 'eip155:1', name: 'Ethereum Mainnet', }), ], - version: '1.0.0', }, }, etag: '"test-etag"', @@ -712,13 +713,14 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockResolvedValue({ data: { data: { - networks: [ + version: '1.0.0', + timestamp: Date.now(), + chains: [ createMockNetworkConfig({ - chainId: '0x1', + chainId: 'eip155:1', name: 'Ethereum Mainnet', }), ], - version: '1.0.0', }, }, etag: '"test-etag"', @@ -1125,30 +1127,11 @@ describe('ConfigRegistryController', () => { cacheTimestamp: Date.now(), }); - const mockNetworks = [ - { - chainId: '0x1', + const mockChains = [ + createMockNetworkConfig({ + chainId: 'eip155:1', name: 'Ethereum Mainnet', - nativeCurrency: 'ETH', - rpcEndpoints: [ - { - url: 'https://mainnet.infura.io/v3/{infuraProjectId}', - type: 'infura', - networkClientId: 'mainnet', - failoverUrls: [], - }, - ], - blockExplorerUrls: ['https://etherscan.io'], - defaultRpcEndpointIndex: 0, - defaultBlockExplorerUrlIndex: 0, - isTestnet: false, - isFeatured: true, - isActive: true, - isDefault: false, - isDeprecated: false, - priority: 0, - isDeletable: false, - }, + }), ]; const fetchConfigSpy = jest.fn().mockResolvedValue({ @@ -1156,7 +1139,7 @@ describe('ConfigRegistryController', () => { data: { version: '1.0.0', timestamp: Date.now(), - networks: mockNetworks, + chains: mockChains, }, }, modified: true, @@ -1169,7 +1152,7 @@ describe('ConfigRegistryController', () => { await jestAdvanceTime({ duration: 0 }); expect(fetchConfigSpy).toHaveBeenCalled(); - expect(controller.state.configs.networks['0x1']).toBeDefined(); + expect(controller.state.configs.networks['eip155:1']).toBeDefined(); expect(controller.state.version).toBe('1.0.0'); }, ); @@ -1189,99 +1172,27 @@ describe('ConfigRegistryController', () => { cacheTimestamp: Date.now(), }); - const mockNetworks = [ - { - chainId: '0x1', + const mockChains = [ + createMockNetworkConfig({ + chainId: 'eip155:1', name: 'Ethereum Mainnet', - nativeCurrency: 'ETH', - rpcEndpoints: [ - { - url: 'https://mainnet.infura.io/v3/{infuraProjectId}', - type: 'infura', - networkClientId: 'mainnet', - failoverUrls: [], - }, - ], - blockExplorerUrls: ['https://etherscan.io'], - defaultRpcEndpointIndex: 0, - defaultBlockExplorerUrlIndex: 0, - isTestnet: false, - isFeatured: true, - isActive: true, - isDefault: false, - isDeprecated: false, - priority: 0, - isDeletable: false, - }, - { - chainId: '0x5', + config: { isTestnet: false, isFeatured: true, isActive: true }, + }), + createMockNetworkConfig({ + chainId: 'eip155:5', name: 'Goerli', - nativeCurrency: 'ETH', - rpcEndpoints: [ - { - url: 'https://goerli.infura.io/v3/{infuraProjectId}', - type: 'infura', - networkClientId: 'goerli', - failoverUrls: [], - }, - ], - blockExplorerUrls: ['https://goerli.etherscan.io'], - defaultRpcEndpointIndex: 0, - defaultBlockExplorerUrlIndex: 0, - isTestnet: true, - isFeatured: true, - isActive: true, - isDefault: false, - isDeprecated: false, - priority: 0, - isDeletable: false, - }, - { - chainId: '0xa', + config: { isTestnet: true, isFeatured: true, isActive: true }, + }), + createMockNetworkConfig({ + chainId: 'eip155:10', name: 'Optimism', - nativeCurrency: 'ETH', - rpcEndpoints: [ - { - url: 'https://optimism.infura.io/v3/{infuraProjectId}', - type: 'infura', - networkClientId: 'optimism', - failoverUrls: [], - }, - ], - blockExplorerUrls: ['https://optimistic.etherscan.io'], - defaultRpcEndpointIndex: 0, - defaultBlockExplorerUrlIndex: 0, - isTestnet: false, - isFeatured: false, - isActive: true, - isDefault: false, - isDeprecated: false, - priority: 0, - isDeletable: false, - }, - { - chainId: '0x89', + config: { isTestnet: false, isFeatured: false, isActive: true }, + }), + createMockNetworkConfig({ + chainId: 'eip155:137', name: 'Polygon', - nativeCurrency: 'MATIC', - rpcEndpoints: [ - { - url: 'https://polygon.infura.io/v3/{infuraProjectId}', - type: 'infura', - networkClientId: 'polygon', - failoverUrls: [], - }, - ], - blockExplorerUrls: ['https://polygonscan.com'], - defaultRpcEndpointIndex: 0, - defaultBlockExplorerUrlIndex: 0, - isTestnet: false, - isFeatured: true, - isActive: false, - isDefault: false, - isDeprecated: false, - priority: 0, - isDeletable: false, - }, + config: { isTestnet: false, isFeatured: true, isActive: false }, + }), ]; const fetchConfigSpy = jest.fn().mockResolvedValue({ @@ -1289,7 +1200,7 @@ describe('ConfigRegistryController', () => { data: { version: '1.0.0', timestamp: Date.now(), - networks: mockNetworks, + chains: mockChains, }, }, modified: true, @@ -1303,18 +1214,18 @@ describe('ConfigRegistryController', () => { // All networks stored in state const allNetworks = selectNetworks(controller.state); - expect(allNetworks['0x1']).toBeDefined(); - expect(allNetworks['0x5']).toBeDefined(); - expect(allNetworks['0xa']).toBeDefined(); - expect(allNetworks['0x89']).toBeDefined(); + expect(allNetworks['eip155:1']).toBeDefined(); + expect(allNetworks['eip155:5']).toBeDefined(); + expect(allNetworks['eip155:10']).toBeDefined(); + expect(allNetworks['eip155:137']).toBeDefined(); expect(Object.keys(allNetworks)).toHaveLength(4); // selectFeaturedNetworks returns only featured, active, non-testnet const featuredNetworks = selectFeaturedNetworks(controller.state); - expect(featuredNetworks['0x1']).toBeDefined(); - expect(featuredNetworks['0x5']).toBeUndefined(); - expect(featuredNetworks['0xa']).toBeUndefined(); - expect(featuredNetworks['0x89']).toBeUndefined(); + expect(featuredNetworks['eip155:1']).toBeDefined(); + expect(featuredNetworks['eip155:5']).toBeUndefined(); + expect(featuredNetworks['eip155:10']).toBeUndefined(); + expect(featuredNetworks['eip155:137']).toBeUndefined(); expect(Object.keys(featuredNetworks)).toHaveLength(1); }, ); @@ -1334,77 +1245,38 @@ describe('ConfigRegistryController', () => { cacheTimestamp: Date.now(), }); - // Mock API response with duplicate chainIds - const mockNetworks = [ - { - chainId: '0x1', + // Mock API response with duplicate chainIds (last occurrence wins) + const mockChains = [ + createMockNetworkConfig({ + chainId: 'eip155:1', name: 'Ethereum Mainnet (Low Priority)', - nativeCurrency: 'ETH', - rpcEndpoints: [ - { + config: { priority: 10 }, + rpcProviders: { + default: { url: 'https://mainnet.infura.io/v3/{infuraProjectId}', type: 'infura', networkClientId: 'mainnet', - failoverUrls: [], }, - ], - blockExplorerUrls: ['https://etherscan.io'], - defaultRpcEndpointIndex: 0, - defaultBlockExplorerUrlIndex: 0, - isTestnet: false, - isFeatured: true, - isActive: true, - isDefault: false, - isDeprecated: false, - priority: 10, // Lower priority (higher number) - isDeletable: false, - }, - { - chainId: '0x1', + fallbacks: [], + }, + }), + createMockNetworkConfig({ + chainId: 'eip155:1', name: 'Ethereum Mainnet (High Priority)', - nativeCurrency: 'ETH', - rpcEndpoints: [ - { + config: { priority: 0 }, + rpcProviders: { + default: { url: 'https://mainnet.alchemy.io/v2/{alchemyApiKey}', type: 'alchemy', networkClientId: 'mainnet-alchemy', - failoverUrls: [], }, - ], - blockExplorerUrls: ['https://etherscan.io'], - defaultRpcEndpointIndex: 0, - defaultBlockExplorerUrlIndex: 0, - isTestnet: false, - isFeatured: true, - isActive: true, - isDefault: false, - isDeprecated: false, - priority: 0, // Higher priority (lower number) - isDeletable: false, - }, - { - chainId: '0x89', + fallbacks: [], + }, + }), + createMockNetworkConfig({ + chainId: 'eip155:137', name: 'Polygon', - nativeCurrency: 'MATIC', - rpcEndpoints: [ - { - url: 'https://polygon.infura.io/v3/{infuraProjectId}', - type: 'infura', - networkClientId: 'polygon', - failoverUrls: [], - }, - ], - blockExplorerUrls: ['https://polygonscan.com'], - defaultRpcEndpointIndex: 0, - defaultBlockExplorerUrlIndex: 0, - isTestnet: false, - isFeatured: true, - isActive: true, - isDefault: false, - isDeprecated: false, - priority: 0, - isDeletable: false, - }, + }), ]; mockApiServiceHandler.mockResolvedValue({ @@ -1412,7 +1284,7 @@ describe('ConfigRegistryController', () => { data: { version: '1.0.0', timestamp: Date.now(), - networks: mockNetworks, + chains: mockChains, }, }, modified: true, @@ -1423,15 +1295,16 @@ describe('ConfigRegistryController', () => { await jestAdvanceTime({ duration: 0 }); // Last occurrence overwrites (no grouping/priority) - expect(controller.state.configs.networks['0x1']).toBeDefined(); - expect(controller.state.configs.networks['0x1']?.name).toBe( + expect(controller.state.configs.networks['eip155:1']).toBeDefined(); + expect(controller.state.configs.networks['eip155:1']?.name).toBe( 'Ethereum Mainnet (High Priority)', ); expect( - controller.state.configs.networks['0x1']?.rpcEndpoints[0].type, + controller.state.configs.networks['eip155:1']?.rpcProviders.default + .type, ).toBe('alchemy'); - expect(controller.state.configs.networks['0x89']).toBeDefined(); + expect(controller.state.configs.networks['eip155:137']).toBeDefined(); }, ); }); @@ -1451,53 +1324,25 @@ describe('ConfigRegistryController', () => { }); // Mock API response with duplicate chainIds having same priority - const mockNetworks = [ - { - chainId: '0x1', + const mockChains = [ + createMockNetworkConfig({ + chainId: 'eip155:1', name: 'Ethereum Mainnet (First)', - nativeCurrency: 'ETH', - rpcEndpoints: [ - { - url: 'https://mainnet.infura.io/v3/{infuraProjectId}', - type: 'infura', - networkClientId: 'mainnet', - failoverUrls: [], - }, - ], - blockExplorerUrls: ['https://etherscan.io'], - defaultRpcEndpointIndex: 0, - defaultBlockExplorerUrlIndex: 0, - isTestnet: false, - isFeatured: true, - isActive: true, - isDefault: false, - isDeprecated: false, - priority: 5, // Same priority - isDeletable: false, - }, - { - chainId: '0x1', + config: { priority: 5 }, + }), + createMockNetworkConfig({ + chainId: 'eip155:1', name: 'Ethereum Mainnet (Second)', - nativeCurrency: 'ETH', - rpcEndpoints: [ - { + config: { priority: 5 }, + rpcProviders: { + default: { url: 'https://mainnet.alchemy.io/v2/{alchemyApiKey}', type: 'alchemy', networkClientId: 'mainnet-alchemy', - failoverUrls: [], }, - ], - blockExplorerUrls: ['https://etherscan.io'], - defaultRpcEndpointIndex: 0, - defaultBlockExplorerUrlIndex: 0, - isTestnet: false, - isFeatured: true, - isActive: true, - isDefault: false, - isDeprecated: false, - priority: 5, // Same priority - isDeletable: false, - }, + fallbacks: [], + }, + }), ]; mockApiServiceHandler.mockResolvedValue({ @@ -1505,7 +1350,7 @@ describe('ConfigRegistryController', () => { data: { version: '1.0.0', timestamp: Date.now(), - networks: mockNetworks, + chains: mockChains, }, }, modified: true, @@ -1516,8 +1361,8 @@ describe('ConfigRegistryController', () => { await jestAdvanceTime({ duration: 0 }); // Last occurrence overwrites - expect(controller.state.configs.networks['0x1']).toBeDefined(); - expect(controller.state.configs.networks['0x1']?.name).toBe( + expect(controller.state.configs.networks['eip155:1']).toBeDefined(); + expect(controller.state.configs.networks['eip155:1']?.name).toBe( 'Ethereum Mainnet (Second)', ); }, @@ -1533,30 +1378,11 @@ describe('ConfigRegistryController', () => { }, }, async ({ controller, messenger, mockApiServiceHandler }) => { - const mockNetworks = [ - { - chainId: '0x1', + const mockChains = [ + createMockNetworkConfig({ + chainId: 'eip155:1', name: 'Ethereum Mainnet', - nativeCurrency: 'ETH', - rpcEndpoints: [ - { - url: 'https://mainnet.infura.io/v3/{infuraProjectId}', - type: 'infura', - networkClientId: 'mainnet', - failoverUrls: [], - }, - ], - blockExplorerUrls: ['https://etherscan.io'], - defaultRpcEndpointIndex: 0, - defaultBlockExplorerUrlIndex: 0, - isTestnet: false, - isFeatured: true, - isActive: true, - isDefault: false, - isDeprecated: false, - priority: 0, - isDeletable: false, - }, + }), ]; mockApiServiceHandler.mockResolvedValue({ @@ -1564,7 +1390,7 @@ describe('ConfigRegistryController', () => { data: { version: '1.0.0', timestamp: Date.now(), - networks: mockNetworks, + chains: mockChains, }, }, modified: true, @@ -1576,7 +1402,7 @@ describe('ConfigRegistryController', () => { expect(customIsEnabled).toHaveBeenCalledWith(messenger); expect(mockApiServiceHandler).toHaveBeenCalled(); - expect(controller.state.configs.networks['0x1']).toBeDefined(); + expect(controller.state.configs.networks['eip155:1']).toBeDefined(); expect(controller.state.version).toBe('1.0.0'); }, ); diff --git a/packages/config-registry-controller/src/ConfigRegistryController.ts b/packages/config-registry-controller/src/ConfigRegistryController.ts index 986c753b1d1..f5e3bed2e81 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.ts @@ -275,18 +275,21 @@ export class ConfigRegistryController extends StaticIntervalPollingController = {}; - apiNetworks.forEach((registryConfig) => { - const { chainId } = registryConfig; - newConfigs[chainId] = registryConfig; + // duplicate chainIds from API response are not expected + apiChains.forEach((chainConfig) => { + const { chainId } = chainConfig; + newConfigs[chainId] = chainConfig; }); this.update((state) => { state.configs.networks = newConfigs; state.version = result.data.data.version; state.lastFetched = Date.now(); - state.etag = result.etag ?? null; + if (result.etag !== undefined) { + state.etag = result.etag; + } }); } catch (error) { const errorInstance = diff --git a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts index 2806c8c192c..fe6fb21cafe 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts @@ -15,7 +15,7 @@ const MOCK_API_RESPONSE: RegistryConfigApiResponse = { data: { version: '"24952800ba9dafbc5e2c91f57f386d28"', timestamp: 1761829548000, - networks: [createMockNetworkConfig()], + chains: [createMockNetworkConfig()], }, }; @@ -194,7 +194,7 @@ describe('ConfigRegistryApiService', () => { expect(scope.isDone()).toBe(true); }); - it('throws error when data is null', async () => { + it('throws error when response body is null', async () => { const scope = nock(UAT_ORIGIN).get(CONFIG_PATH).reply(200, 'null'); const service = new ConfigRegistryApiService(); @@ -205,7 +205,7 @@ describe('ConfigRegistryApiService', () => { expect(scope.isDone()).toBe(true); }); - it('throws error when data.data is null', async () => { + it('throws error when data is null', async () => { const scope = nock(UAT_ORIGIN) .get(CONFIG_PATH) .reply(200, { data: null }); @@ -218,10 +218,12 @@ describe('ConfigRegistryApiService', () => { expect(scope.isDone()).toBe(true); }); - it('throws error when data.data.networks is not an array', async () => { + it('throws error when data.chains is not an array', async () => { const scope = nock(UAT_ORIGIN) .get(CONFIG_PATH) - .reply(200, { data: { networks: 'not-an-array' } }); + .reply(200, { + data: { version: '1', timestamp: 0, chains: 'not-an-array' }, + }); const service = new ConfigRegistryApiService(); diff --git a/packages/config-registry-controller/src/config-registry-api-service/filters.test.ts b/packages/config-registry-controller/src/config-registry-api-service/filters.test.ts index a2979ade302..831fd551b5d 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/filters.test.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/filters.test.ts @@ -6,27 +6,33 @@ describe('filters', () => { describe('filterNetworks', () => { const networks: RegistryNetworkConfig[] = [ createMockNetworkConfig({ - isFeatured: true, - isTestnet: false, - isActive: true, - isDeprecated: false, - isDefault: true, + config: { + isFeatured: true, + isTestnet: false, + isActive: true, + isDeprecated: false, + isDefault: true, + }, }), createMockNetworkConfig({ - chainId: '0x5', - isFeatured: false, - isTestnet: true, - isActive: true, - isDeprecated: false, - isDefault: false, + chainId: 'eip155:5', + config: { + isFeatured: false, + isTestnet: true, + isActive: true, + isDeprecated: false, + isDefault: false, + }, }), createMockNetworkConfig({ - chainId: '0x2a', - isFeatured: true, - isTestnet: false, - isActive: false, - isDeprecated: true, - isDefault: false, + chainId: 'eip155:42', + config: { + isFeatured: true, + isTestnet: false, + isActive: false, + isDeprecated: true, + isDefault: false, + }, }), ]; @@ -40,35 +46,35 @@ describe('filters', () => { const result = filterNetworks(networks, { isFeatured: true }); expect(result).toHaveLength(2); - expect(result.every((network) => network.isFeatured)).toBe(true); + expect(result.every((network) => network.config.isFeatured)).toBe(true); }); it('filters by isTestnet', () => { const result = filterNetworks(networks, { isTestnet: true }); expect(result).toHaveLength(1); - expect(result[0].chainId).toBe('0x5'); + expect(result[0].chainId).toBe('eip155:5'); }); it('filters by isActive', () => { const result = filterNetworks(networks, { isActive: true }); expect(result).toHaveLength(2); - expect(result.every((network) => network.isActive)).toBe(true); + expect(result.every((network) => network.config.isActive)).toBe(true); }); it('filters by isDeprecated', () => { const result = filterNetworks(networks, { isDeprecated: true }); expect(result).toHaveLength(1); - expect(result[0].chainId).toBe('0x2a'); + expect(result[0].chainId).toBe('eip155:42'); }); it('filters by isDefault', () => { const result = filterNetworks(networks, { isDefault: true }); expect(result).toHaveLength(1); - expect(result[0].chainId).toBe('0x1'); + expect(result[0].chainId).toBe('eip155:1'); }); it('filters by multiple criteria (requiring all filters to match)', () => { @@ -79,7 +85,7 @@ describe('filters', () => { }); expect(result).toHaveLength(1); - expect(result[0].chainId).toBe('0x1'); + expect(result[0].chainId).toBe('eip155:1'); }); it('returns empty array for empty input', () => { diff --git a/packages/config-registry-controller/src/config-registry-api-service/filters.ts b/packages/config-registry-controller/src/config-registry-api-service/filters.ts index f8eabf4bc08..668ce8bae8c 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/filters.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/filters.ts @@ -17,20 +17,21 @@ const FILTER_KEYS: (keyof NetworkFilterOptions)[] = [ ]; /** - * @param networks - Array of network configurations to filter. - * @param options - Filter options. - * @returns Filtered array of network configurations. + * @param networks - Array of chain configurations to filter. + * @param options - Filter options (matched against config.*). + * @returns Filtered array of chain configurations. */ export function filterNetworks( networks: RegistryNetworkConfig[], options: NetworkFilterOptions = {}, ): RegistryNetworkConfig[] { return networks.filter((network) => { + const { config } = network; for (const key of FILTER_KEYS) { const optionValue = options[key]; if ( optionValue !== undefined && - network[key as keyof RegistryNetworkConfig] !== optionValue + config[key as keyof typeof config] !== optionValue ) { return false; } diff --git a/packages/config-registry-controller/src/config-registry-api-service/types.ts b/packages/config-registry-controller/src/config-registry-api-service/types.ts index 4e6789d3d5f..a5858225f3c 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/types.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/types.ts @@ -9,43 +9,80 @@ import { type, } from '@metamask/superstruct'; -const RpcEndpointSchema = type({ +const NativeAssetSchema = type({ + assetId: string(), + imageUrl: string(), + name: string(), + symbol: string(), + decimals: number(), + coingeckoCoinId: string(), +}); + +const GovernanceAssetSchema = type({ + assetId: string(), + imageUrl: string(), + name: string(), + symbol: string(), + decimals: number(), + coingeckoCoinId: string(), +}); + +const AssetsSchema = type({ + listUrl: string(), + native: NativeAssetSchema, + governance: optional(GovernanceAssetSchema), +}); + +const RpcProviderSchema = type({ url: string(), type: string(), networkClientId: string(), - failoverUrls: array(string()), }); -/** - * Schema for a single network in the API response. - * Matches the flat shape returned by the config registry API - * (all fields at top level, not nested under "network"). - */ -export const RegistryNetworkConfigSchema = type({ - chainId: string(), - name: string(), - nativeCurrency: string(), - rpcEndpoints: array(RpcEndpointSchema), - blockExplorerUrls: array(string()), - defaultRpcEndpointIndex: number(), - defaultBlockExplorerUrlIndex: number(), - lastUpdatedAt: optional(number()), - networkImageUrl: optional(string()), - nativeTokenImageUrl: optional(string()), +const RpcProvidersSchema = type({ + default: RpcProviderSchema, + fallbacks: array(string()), +}); + +const BlockExplorerUrlsSchema = type({ + default: string(), + fallbacks: array(string()), +}); + +const ChainConfigSchema = type({ isActive: boolean(), isTestnet: boolean(), isDefault: boolean(), isFeatured: boolean(), isDeprecated: boolean(), - priority: number(), isDeletable: boolean(), + priority: number(), +}); + +/** + * Schema for a single chain in the CAIP-2 config registry API response. + * chainId is in CAIP-2 format (e.g. "eip155:1", "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"). + */ +export const RegistryNetworkConfigSchema = type({ + chainId: string(), + name: string(), + imageUrl: string(), + coingeckoPlatformId: string(), + geckoTerminalPlatformId: optional(string()), + assets: AssetsSchema, + rpcProviders: RpcProvidersSchema, + blockExplorerUrls: BlockExplorerUrlsSchema, + config: ChainConfigSchema, }); +/** + * Top-level API response shape. Uses `data.chains` (CAIP-2) and `data.version`. + */ export const RegistryConfigApiResponseSchema = type({ data: type({ version: string(), timestamp: number(), - networks: array(RegistryNetworkConfigSchema), + chains: array(RegistryNetworkConfigSchema), }), }); diff --git a/packages/config-registry-controller/src/selectors.test.ts b/packages/config-registry-controller/src/selectors.test.ts index 1530b3bb5af..3a6e1ba31c2 100644 --- a/packages/config-registry-controller/src/selectors.test.ts +++ b/packages/config-registry-controller/src/selectors.test.ts @@ -5,9 +5,9 @@ describe('selectors', () => { describe('selectNetworks', () => { it('returns all networks from state', () => { const networks = { - '0x1': createMockNetworkConfig({ chainId: '0x1' }), - '0x89': createMockNetworkConfig({ - chainId: '0x89', + 'eip155:1': createMockNetworkConfig({ chainId: 'eip155:1' }), + 'eip155:137': createMockNetworkConfig({ + chainId: 'eip155:137', name: 'Polygon', }), }; @@ -26,32 +26,24 @@ describe('selectors', () => { describe('selectFeaturedNetworks', () => { it('returns only featured, active, non-testnet networks', () => { const networks = { - '0x1': createMockNetworkConfig({ - chainId: '0x1', - isFeatured: true, - isActive: true, - isTestnet: false, + 'eip155:1': createMockNetworkConfig({ + chainId: 'eip155:1', + config: { isFeatured: true, isActive: true, isTestnet: false }, }), - '0x5': createMockNetworkConfig({ - chainId: '0x5', + 'eip155:5': createMockNetworkConfig({ + chainId: 'eip155:5', name: 'Goerli', - isFeatured: true, - isActive: true, - isTestnet: true, + config: { isFeatured: true, isActive: true, isTestnet: true }, }), - '0xa': createMockNetworkConfig({ - chainId: '0xa', + 'eip155:10': createMockNetworkConfig({ + chainId: 'eip155:10', name: 'Optimism', - isFeatured: false, - isActive: true, - isTestnet: false, + config: { isFeatured: false, isActive: true, isTestnet: false }, }), - '0x89': createMockNetworkConfig({ - chainId: '0x89', + 'eip155:137': createMockNetworkConfig({ + chainId: 'eip155:137', name: 'Polygon', - isFeatured: true, - isActive: false, - isTestnet: false, + config: { isFeatured: true, isActive: false, isTestnet: false }, }), }; const state = { @@ -63,17 +55,17 @@ describe('selectors', () => { const featured = selectFeaturedNetworks(state); expect(Object.keys(featured)).toHaveLength(1); - expect(featured['0x1']).toBeDefined(); - expect(featured['0x5']).toBeUndefined(); - expect(featured['0xa']).toBeUndefined(); - expect(featured['0x89']).toBeUndefined(); + expect(featured['eip155:1']).toBeDefined(); + expect(featured['eip155:5']).toBeUndefined(); + expect(featured['eip155:10']).toBeUndefined(); + expect(featured['eip155:137']).toBeUndefined(); }); it('returns empty object when no networks match', () => { const networks = { - '0x5': createMockNetworkConfig({ - chainId: '0x5', - isTestnet: true, + 'eip155:5': createMockNetworkConfig({ + chainId: 'eip155:5', + config: { isTestnet: true }, }), }; const state = { diff --git a/packages/config-registry-controller/src/test-helpers.ts b/packages/config-registry-controller/src/test-helpers.ts index a51f63caa68..4b5f335c02b 100644 --- a/packages/config-registry-controller/src/test-helpers.ts +++ b/packages/config-registry-controller/src/test-helpers.ts @@ -1,36 +1,70 @@ import type { RegistryNetworkConfig } from './config-registry-api-service'; /** - * Creates a mock RegistryNetworkConfig for testing. + * Creates a mock RegistryNetworkConfig (CAIP-2 chain) for testing. * - * @param overrides - Optional properties to override in the default RegistryNetworkConfig. + * @param overrides - Optional properties to override in the default config. * @returns A mock RegistryNetworkConfig object. */ +const DEFAULT_CHAIN_CONFIG = { + isActive: true, + isTestnet: false, + isDefault: true, + isFeatured: true, + isDeprecated: false, + isDeletable: false, + priority: 0, +} as const; + +/** Overrides for createMockNetworkConfig; config can be partial. */ +export type MockNetworkConfigOverrides = Partial< + Omit +> & { + config?: Partial; +}; + export function createMockNetworkConfig( - overrides: Partial = {}, + overrides: MockNetworkConfigOverrides = {}, ): RegistryNetworkConfig { - return { - chainId: '0x1', + const base: RegistryNetworkConfig = { + chainId: 'eip155:1', name: 'Ethereum Mainnet', - nativeCurrency: 'ETH', - rpcEndpoints: [ - { + imageUrl: + 'https://token.api.cx.metamask.io/assets/networkLogos/ethereum.svg', + coingeckoPlatformId: 'ethereum', + geckoTerminalPlatformId: 'eth', + assets: { + listUrl: 'https://tokens.api.cx.metamask.io/v3/chains/eip155:1/assets', + native: { + assetId: 'eip155:1/slip44:60', + imageUrl: + 'https://static.cx.metamask.io/api/v2/tokenIcons/assets/eip155/1/slip44/60.png', + name: 'Ether', + symbol: 'ETH', + decimals: 18, + coingeckoCoinId: 'ethereum', + }, + }, + rpcProviders: { + default: { url: 'https://mainnet.infura.io/v3/{infuraProjectId}', type: 'infura', networkClientId: 'mainnet', - failoverUrls: [], }, - ], - blockExplorerUrls: ['https://etherscan.io'], - defaultRpcEndpointIndex: 0, - defaultBlockExplorerUrlIndex: 0, - isActive: true, - isTestnet: false, - isDefault: true, - isFeatured: true, - isDeprecated: false, - priority: 0, - isDeletable: false, - ...overrides, + fallbacks: [], + }, + blockExplorerUrls: { + default: 'https://etherscan.io', + fallbacks: [], + }, + config: { ...DEFAULT_CHAIN_CONFIG }, + }; + const { config: configOverride, ...rest } = overrides; + return { + ...base, + ...rest, + config: configOverride + ? { ...DEFAULT_CHAIN_CONFIG, ...configOverride } + : base.config, }; } From 32ed9958c049270151ebd45606e0eb3871830edd Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Mon, 23 Feb 2026 11:18:23 +0100 Subject: [PATCH 45/55] fix: small fix --- .../src/config-registry-api-service/types.ts | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/packages/config-registry-controller/src/config-registry-api-service/types.ts b/packages/config-registry-controller/src/config-registry-api-service/types.ts index a5858225f3c..dcf027847c3 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/types.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/types.ts @@ -9,16 +9,7 @@ import { type, } from '@metamask/superstruct'; -const NativeAssetSchema = type({ - assetId: string(), - imageUrl: string(), - name: string(), - symbol: string(), - decimals: number(), - coingeckoCoinId: string(), -}); - -const GovernanceAssetSchema = type({ +const AssetSchema = type({ assetId: string(), imageUrl: string(), name: string(), @@ -29,8 +20,8 @@ const GovernanceAssetSchema = type({ const AssetsSchema = type({ listUrl: string(), - native: NativeAssetSchema, - governance: optional(GovernanceAssetSchema), + native: AssetSchema, + governance: optional(AssetSchema), }); const RpcProviderSchema = type({ From e63c863051978a8d87b1b5359b2e0f30b0eeb995 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Fri, 27 Feb 2026 16:12:26 +0100 Subject: [PATCH 46/55] fix: fix comments --- README.md | 11 + package.json | 3 +- .../config-registry-controller/package.json | 1 + .../src/ConfigRegistryController.test.ts | 401 +++++++----------- .../src/ConfigRegistryController.ts | 60 ++- ...egistry-api-service-method-action-types.ts | 18 + .../config-registry-api-service.test.ts | 85 ++-- .../config-registry-api-service.ts | 80 +++- .../filters.test.ts | 2 +- .../config-registry-api-service/filters.ts | 4 +- .../src/config-registry-api-service/index.ts | 13 - .../config-registry-controller/src/index.ts | 19 +- .../src/selectors.test.ts | 2 +- .../src/selectors.ts | 4 +- .../src/utils/feature-flags.ts | 4 +- .../{src/test-helpers.ts => tests/helpers.ts} | 2 +- .../tsconfig.build.json | 2 +- .../config-registry-controller/tsconfig.json | 2 +- yarn.lock | 1 + 19 files changed, 376 insertions(+), 338 deletions(-) create mode 100644 packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service-method-action-types.ts delete mode 100644 packages/config-registry-controller/src/config-registry-api-service/index.ts rename packages/config-registry-controller/{src/test-helpers.ts => tests/helpers.ts} (95%) diff --git a/README.md b/README.md index c26fcd5e057..1468e6a4be9 100644 --- a/README.md +++ b/README.md @@ -218,6 +218,7 @@ linkStyle default opacity:0.5 assets_controllers --> approval_controller; assets_controllers --> base_controller; assets_controllers --> controller_utils; + assets_controllers --> core_backend; assets_controllers --> keyring_controller; assets_controllers --> messenger; assets_controllers --> multichain_account_service; @@ -241,6 +242,7 @@ linkStyle default opacity:0.5 bridge_controller --> multichain_network_controller; bridge_controller --> network_controller; bridge_controller --> polling_controller; + bridge_controller --> profile_sync_controller; bridge_controller --> remote_feature_flag_controller; bridge_controller --> transaction_controller; bridge_controller --> eth_json_rpc_provider; @@ -251,6 +253,7 @@ linkStyle default opacity:0.5 bridge_status_controller --> gas_fee_controller; bridge_status_controller --> network_controller; bridge_status_controller --> polling_controller; + bridge_status_controller --> profile_sync_controller; bridge_status_controller --> transaction_controller; chain_agnostic_permission --> controller_utils; chain_agnostic_permission --> permission_controller; @@ -267,6 +270,13 @@ linkStyle default opacity:0.5 composable_controller --> base_controller; composable_controller --> messenger; composable_controller --> json_rpc_engine; + config_registry_controller --> base_controller; + config_registry_controller --> controller_utils; + config_registry_controller --> keyring_controller; + config_registry_controller --> messenger; + config_registry_controller --> polling_controller; + config_registry_controller --> profile_sync_controller; + config_registry_controller --> remote_feature_flag_controller; connectivity_controller --> base_controller; connectivity_controller --> messenger; core_backend --> accounts_controller; @@ -444,6 +454,7 @@ linkStyle default opacity:0.5 transaction_controller --> approval_controller; transaction_controller --> base_controller; transaction_controller --> controller_utils; + transaction_controller --> core_backend; transaction_controller --> gas_fee_controller; transaction_controller --> messenger; transaction_controller --> network_controller; diff --git a/package.json b/package.json index 53ed66cb556..d17cef064bb 100644 --- a/package.json +++ b/package.json @@ -109,8 +109,7 @@ "@keystonehq/bc-ur-registry-eth>hdkey>secp256k1": true, "babel-runtime>core-js": false, "simple-git-hooks": false, - "tsx>esbuild": false, - "eslint-plugin-import-x>unrs-resolver": false + "tsx>esbuild": false } } } diff --git a/packages/config-registry-controller/package.json b/packages/config-registry-controller/package.json index 2ceefaf136c..d29d01c71d2 100644 --- a/packages/config-registry-controller/package.json +++ b/packages/config-registry-controller/package.json @@ -50,6 +50,7 @@ "dependencies": { "@metamask/base-controller": "^9.0.0", "@metamask/controller-utils": "^11.19.0", + "@metamask/keyring-controller": "^25.1.0", "@metamask/messenger": "^0.3.0", "@metamask/polling-controller": "^16.0.3", "@metamask/profile-sync-controller": "^27.1.0", diff --git a/packages/config-registry-controller/src/ConfigRegistryController.test.ts b/packages/config-registry-controller/src/ConfigRegistryController.test.ts index 01c231a03c9..5b40e5d19a1 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.test.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.test.ts @@ -5,22 +5,21 @@ import type { } from '@metamask/messenger'; import { Messenger, MOCK_ANY_NAMESPACE } from '@metamask/messenger'; -import type { RegistryNetworkConfig } from './config-registry-api-service'; -import type { FetchConfigResult } from './config-registry-api-service'; -import type { ConfigRegistryMessenger } from './ConfigRegistryController'; +import type { RegistryNetworkConfig } from './config-registry-api-service/types'; +import type { FetchConfigResult } from './config-registry-api-service/types'; +import type { ConfigRegistryControllerMessenger } from './ConfigRegistryController'; import { ConfigRegistryController, DEFAULT_POLLING_INTERVAL, } from './ConfigRegistryController'; import { selectFeaturedNetworks, selectNetworks } from './selectors'; -import { createMockNetworkConfig } from './test-helpers'; -import { jestAdvanceTime } from '../../../tests/helpers'; +import { createMockNetworkConfig } from '../tests/helpers'; const namespace = 'ConfigRegistryController' as const; -type AllActions = MessengerActions; +type AllActions = MessengerActions; -type AllEvents = MessengerEvents; +type AllEvents = MessengerEvents; type RootMessenger = Messenger; @@ -30,7 +29,7 @@ type RootMessenger = Messenger; * @returns A controller messenger and root messenger. */ function getConfigRegistryControllerMessenger(): { - messenger: ConfigRegistryMessenger; + messenger: ConfigRegistryControllerMessenger; rootMessenger: RootMessenger; } { const rootMessenger: RootMessenger = new Messenger({ @@ -38,7 +37,7 @@ function getConfigRegistryControllerMessenger(): { captureException: jest.fn(), }); - const configRegistryControllerMessenger: ConfigRegistryMessenger = + const configRegistryControllerMessenger: ConfigRegistryControllerMessenger = new Messenger< typeof namespace, AllActions, @@ -55,7 +54,11 @@ function getConfigRegistryControllerMessenger(): { 'RemoteFeatureFlagController:getState', 'ConfigRegistryApiService:fetchConfig', ], - events: ['KeyringController:unlock', 'KeyringController:lock'], + events: [ + 'KeyringController:unlock', + 'KeyringController:lock', + 'RemoteFeatureFlagController:stateChange', + ], }); return { messenger: configRegistryControllerMessenger, rootMessenger }; @@ -97,7 +100,7 @@ function buildMockApiServiceHandler(overrides?: { type WithControllerCallback = (args: { controller: ConfigRegistryController; rootMessenger: RootMessenger; - messenger: ConfigRegistryMessenger; + messenger: ConfigRegistryControllerMessenger; mockApiServiceHandler: jest.Mock; mockRemoteFeatureFlagGetState: jest.Mock; }) => Promise | ReturnValue; @@ -216,10 +219,10 @@ describe('ConfigRegistryController', () => { }); describe('polling', () => { - it('starts polling', async () => { + it('hits the config registry API when polling is started', async () => { await withController(async ({ controller, mockApiServiceHandler }) => { controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); controller.stopAllPolling(); }); @@ -231,22 +234,22 @@ describe('ConfigRegistryController', () => { { options: { pollingInterval } }, async ({ controller, mockApiServiceHandler }) => { controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); mockApiServiceHandler.mockClear(); - await jestAdvanceTime({ duration: pollingInterval }); + await jest.advanceTimersByTimeAsync(pollingInterval); expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); controller.stopAllPolling(); }, ); }); - it('stops polling', async () => { + it('does not hit the config registry API periodically when polling is stopped', async () => { await withController(async ({ controller, mockApiServiceHandler }) => { controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); mockApiServiceHandler.mockClear(); controller.stopAllPolling(); - await jestAdvanceTime({ duration: DEFAULT_POLLING_INTERVAL }); + await jest.advanceTimersByTimeAsync(DEFAULT_POLLING_INTERVAL); expect(mockApiServiceHandler).not.toHaveBeenCalled(); }); }); @@ -270,7 +273,7 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockRejectedValue(new Error('Network error')); controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ message: 'Network error' }), @@ -314,7 +317,7 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockRejectedValue(new Error('Network error')); controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ message: 'Network error' }), @@ -345,7 +348,7 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockRejectedValue(new Error('Network error')); controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ message: 'Network error' }), @@ -379,7 +382,7 @@ describe('ConfigRegistryController', () => { const beforeTimestamp = Date.now(); controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); const afterTimestamp = Date.now(); expect(controller.state.etag).toBe('"test-etag"'); @@ -421,7 +424,7 @@ describe('ConfigRegistryController', () => { const beforeTimestamp = Date.now(); controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); const afterTimestamp = Date.now(); expect(controller.state.etag).toBe('"existing-etag"'); @@ -464,7 +467,7 @@ describe('ConfigRegistryController', () => { const beforeTimestamp = Date.now(); controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); const afterTimestamp = Date.now(); expect(controller.state.etag).toBeNull(); @@ -500,7 +503,7 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockRejectedValue(validationError); controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ @@ -532,7 +535,7 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockRejectedValue(validationError); controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ @@ -564,7 +567,7 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockRejectedValue(validationError); controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ @@ -596,7 +599,7 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockRejectedValue(validationError); controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ @@ -607,37 +610,6 @@ describe('ConfigRegistryController', () => { ); }); - it('skips fetch when lastFetched is in the future', async () => { - const now = Date.now(); - const futureTimestamp = now + 10000; - await withController( - { - options: { - state: { - lastFetched: futureTimestamp, - }, - }, - }, - async ({ - controller, - mockRemoteFeatureFlagGetState, - mockApiServiceHandler, - }) => { - mockRemoteFeatureFlagGetState.mockReturnValue({ - remoteFeatureFlags: { - configRegistryApiEnabled: true, - }, - cacheTimestamp: now, - }); - - controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); - - expect(mockApiServiceHandler).not.toHaveBeenCalled(); - }, - ); - }); - it('proceeds with fetch when lastFetched is null', async () => { await withController( { @@ -677,7 +649,7 @@ describe('ConfigRegistryController', () => { }); controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); expect(mockApiServiceHandler).toHaveBeenCalled(); expect(controller.state.lastFetched).not.toBeNull(); @@ -728,7 +700,7 @@ describe('ConfigRegistryController', () => { }); controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); expect(mockApiServiceHandler).toHaveBeenCalled(); expect(controller.state.lastFetched).not.toBe(oldTimestamp); @@ -738,73 +710,6 @@ describe('ConfigRegistryController', () => { ); }); - it('uses custom polling interval when checking lastFetched', async () => { - const customInterval = 5000; - const recentTimestamp = Date.now() - 3000; - await withController( - { - options: { - pollingInterval: customInterval, - state: { - lastFetched: recentTimestamp, - }, - }, - }, - async ({ - controller, - mockRemoteFeatureFlagGetState, - mockApiServiceHandler, - }) => { - mockRemoteFeatureFlagGetState.mockReturnValue({ - remoteFeatureFlags: { - configRegistryApiEnabled: true, - }, - cacheTimestamp: Date.now(), - }); - - controller.startPolling(null); - - expect(mockApiServiceHandler).not.toHaveBeenCalled(); - }, - ); - }); - - it('uses DEFAULT_POLLING_INTERVAL when getIntervalLength returns undefined', async () => { - const pollingInterval = 10000; - const recentTimestamp = Date.now() - 1000; - await withController( - { - options: { - pollingInterval, - state: { - lastFetched: recentTimestamp, - }, - }, - }, - async ({ - controller, - mockRemoteFeatureFlagGetState, - mockApiServiceHandler, - }) => { - mockRemoteFeatureFlagGetState.mockReturnValue({ - remoteFeatureFlags: { - configRegistryApiEnabled: true, - }, - cacheTimestamp: Date.now(), - }); - - jest - .spyOn(controller, 'getIntervalLength') - .mockReturnValue(undefined); - - controller.startPolling(null); - await jestAdvanceTime({ duration: pollingInterval }); - - expect(mockApiServiceHandler).not.toHaveBeenCalled(); - }, - ); - }); - it('handles non-Error exceptions', async () => { await withController( { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, @@ -824,7 +729,7 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockRejectedValue('String error'); controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ message: 'String error' }), @@ -861,7 +766,7 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockRejectedValue(new Error('Network error')); controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); expect(rootMessenger.captureException).toHaveBeenCalledWith( expect.objectContaining({ message: 'Network error' }), @@ -881,11 +786,11 @@ describe('ConfigRegistryController', () => { ); expect(typeof token).toBe('string'); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); messenger.call('ConfigRegistryController:stopPolling'); - await jestAdvanceTime({ duration: DEFAULT_POLLING_INTERVAL }); + await jest.advanceTimersByTimeAsync(DEFAULT_POLLING_INTERVAL); expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); }); }); @@ -918,8 +823,6 @@ describe('ConfigRegistryController', () => { const token = controller.startPolling(null); expect(typeof token).toBe('string'); expect(token.length).toBeGreaterThan(0); - - controller.stopAllPolling(); }); }); @@ -928,35 +831,9 @@ describe('ConfigRegistryController', () => { const token = controller.startPolling(null); expect(typeof token).toBe('string'); expect(token.length).toBeGreaterThan(0); - - controller.stopAllPolling(); }); }); - it('delays first poll when lastFetched is recent', async () => { - const pollingInterval = 10000; - const recentTimestamp = Date.now() - 2000; - await withController( - { - options: { - pollingInterval, - state: { - lastFetched: recentTimestamp, - }, - }, - }, - async ({ controller, mockApiServiceHandler }) => { - controller.startPolling(null); - - await jestAdvanceTime({ duration: 0 }); - await jestAdvanceTime({ duration: pollingInterval }); - expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); - - controller.stopAllPolling(); - }, - ); - }); - it('proceeds immediately when lastFetched is null', async () => { await withController( { @@ -969,7 +846,7 @@ describe('ConfigRegistryController', () => { async ({ controller, mockApiServiceHandler }) => { controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); controller.stopAllPolling(); @@ -994,7 +871,7 @@ describe('ConfigRegistryController', () => { jest.spyOn(Date, 'now').mockReturnValue(now); controller.startPolling(null); - await jestAdvanceTime({ duration: 1 }); + await jest.advanceTimersByTimeAsync(1); expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); controller.stopAllPolling(); @@ -1020,7 +897,7 @@ describe('ConfigRegistryController', () => { jest.spyOn(Date, 'now').mockReturnValue(now); controller.startPolling(null); - await jestAdvanceTime({ duration: 1 }); + await jest.advanceTimersByTimeAsync(1); expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); controller.stopAllPolling(); @@ -1029,33 +906,6 @@ describe('ConfigRegistryController', () => { ); }); - it('uses DEFAULT_POLLING_INTERVAL when getIntervalLength returns undefined', async () => { - const pollingInterval = 10000; - const recentTimestamp = Date.now() - 1000; - await withController( - { - options: { - pollingInterval, - state: { - lastFetched: recentTimestamp, - }, - }, - }, - async ({ controller, mockApiServiceHandler }) => { - jest - .spyOn(controller, 'getIntervalLength') - .mockReturnValue(undefined); - - controller.startPolling(null); - await jestAdvanceTime({ duration: pollingInterval }); - - expect(mockApiServiceHandler).not.toHaveBeenCalled(); - - controller.stopAllPolling(); - }, - ); - }); - it('clears existing timeout when startPolling is called multiple times', async () => { const pollingInterval = 10000; const recentTimestamp = Date.now() - 2000; @@ -1070,11 +920,11 @@ describe('ConfigRegistryController', () => { }, async ({ controller, mockApiServiceHandler }) => { controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); const callsAfterFirst = mockApiServiceHandler.mock.calls.length; controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); expect(mockApiServiceHandler).toHaveBeenCalledTimes(callsAfterFirst); controller.stopAllPolling(); @@ -1101,7 +951,7 @@ describe('ConfigRegistryController', () => { controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); expect(mockApiServiceHandler).not.toHaveBeenCalled(); expect(controller.state.configs).toStrictEqual({ @@ -1149,7 +999,7 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockImplementation(fetchConfigSpy); controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); expect(fetchConfigSpy).toHaveBeenCalled(); expect(controller.state.configs.networks['eip155:1']).toBeDefined(); @@ -1210,7 +1060,7 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockImplementation(fetchConfigSpy); controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); // All networks stored in state const allNetworks = selectNetworks(controller.state); @@ -1292,7 +1142,7 @@ describe('ConfigRegistryController', () => { }); controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); // Last occurrence overwrites (no grouping/priority) expect(controller.state.configs.networks['eip155:1']).toBeDefined(); @@ -1358,7 +1208,7 @@ describe('ConfigRegistryController', () => { }); controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); // Last occurrence overwrites expect(controller.state.configs.networks['eip155:1']).toBeDefined(); @@ -1369,15 +1219,14 @@ describe('ConfigRegistryController', () => { ); }); - it('uses custom isConfigRegistryApiEnabled function when provided', async () => { - const customIsEnabled = jest.fn().mockReturnValue(true); + it('fetches when feature flag is enabled (default mock)', async () => { await withController( - { - options: { - isConfigRegistryApiEnabled: customIsEnabled, - }, - }, - async ({ controller, messenger, mockApiServiceHandler }) => { + {}, + async ({ + controller, + mockRemoteFeatureFlagGetState, + mockApiServiceHandler, + }) => { const mockChains = [ createMockNetworkConfig({ chainId: 'eip155:1', @@ -1385,6 +1234,11 @@ describe('ConfigRegistryController', () => { }), ]; + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { configRegistryApiEnabled: true }, + cacheTimestamp: Date.now(), + }); + mockApiServiceHandler.mockResolvedValue({ data: { data: { @@ -1398,9 +1252,9 @@ describe('ConfigRegistryController', () => { }); controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); - expect(customIsEnabled).toHaveBeenCalledWith(messenger); + expect(mockRemoteFeatureFlagGetState).toHaveBeenCalled(); expect(mockApiServiceHandler).toHaveBeenCalled(); expect(controller.state.configs.networks['eip155:1']).toBeDefined(); expect(controller.state.version).toBe('1.0.0'); @@ -1408,20 +1262,23 @@ describe('ConfigRegistryController', () => { ); }); - it('uses custom isConfigRegistryApiEnabled function returning false', async () => { - const customIsEnabled = jest.fn().mockReturnValue(false); + it('skips fetch when feature flag is disabled', async () => { await withController( - { - options: { - fallbackConfig: MOCK_FALLBACK_CONFIG, - isConfigRegistryApiEnabled: customIsEnabled, - }, - }, - async ({ controller, messenger, mockApiServiceHandler }) => { + { options: { fallbackConfig: MOCK_FALLBACK_CONFIG } }, + async ({ + controller, + mockRemoteFeatureFlagGetState, + mockApiServiceHandler, + }) => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { configRegistryApiEnabled: false }, + cacheTimestamp: Date.now(), + }); + controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); - expect(customIsEnabled).toHaveBeenCalledWith(messenger); + expect(mockRemoteFeatureFlagGetState).toHaveBeenCalled(); expect(mockApiServiceHandler).not.toHaveBeenCalled(); expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG, @@ -1445,7 +1302,7 @@ describe('ConfigRegistryController', () => { controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); expect(mockApiServiceHandler).not.toHaveBeenCalled(); expect(controller.state.configs).toStrictEqual({ @@ -1471,7 +1328,7 @@ describe('ConfigRegistryController', () => { controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); expect(mockApiServiceHandler).not.toHaveBeenCalled(); expect(controller.state.configs).toStrictEqual({ @@ -1490,7 +1347,7 @@ describe('ConfigRegistryController', () => { async ({ controller, rootMessenger, mockApiServiceHandler }) => { rootMessenger.publish('KeyringController:unlock'); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); @@ -1503,12 +1360,12 @@ describe('ConfigRegistryController', () => { await withController( async ({ controller, rootMessenger, mockApiServiceHandler }) => { controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); const callsAfterUnlock = mockApiServiceHandler.mock.calls.length; rootMessenger.publish('KeyringController:lock'); - await jestAdvanceTime({ duration: DEFAULT_POLLING_INTERVAL }); + await jest.advanceTimersByTimeAsync(DEFAULT_POLLING_INTERVAL); expect(mockApiServiceHandler).toHaveBeenCalledTimes(callsAfterUnlock); }, ); @@ -1518,7 +1375,7 @@ describe('ConfigRegistryController', () => { await withController(async ({ controller, mockApiServiceHandler }) => { controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); controller.stopAllPolling(); @@ -1526,6 +1383,70 @@ describe('ConfigRegistryController', () => { }); }); + describe('RemoteFeatureFlagController:stateChange', () => { + it('starts polling when flag becomes enabled', async () => { + await withController( + async ({ + controller, + rootMessenger, + mockRemoteFeatureFlagGetState, + mockApiServiceHandler, + }) => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { configRegistryApiEnabled: true }, + cacheTimestamp: Date.now(), + }); + + rootMessenger.publish( + 'RemoteFeatureFlagController:stateChange', + { + remoteFeatureFlags: { configRegistryApiEnabled: true }, + cacheTimestamp: Date.now(), + }, + [], + ); + + await jest.advanceTimersByTimeAsync(0); + expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); + + controller.stopAllPolling(); + }, + ); + }); + + it('stops polling when flag becomes disabled', async () => { + await withController( + async ({ + controller, + rootMessenger, + mockRemoteFeatureFlagGetState, + mockApiServiceHandler, + }) => { + controller.startPolling(null); + await jest.advanceTimersByTimeAsync(0); + const callsAfterStart = mockApiServiceHandler.mock.calls.length; + + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { configRegistryApiEnabled: false }, + cacheTimestamp: Date.now(), + }); + + rootMessenger.publish( + 'RemoteFeatureFlagController:stateChange', + { + remoteFeatureFlags: { configRegistryApiEnabled: false }, + cacheTimestamp: Date.now(), + }, + [], + ); + + await jest.advanceTimersByTimeAsync(DEFAULT_POLLING_INTERVAL); + expect(mockApiServiceHandler).toHaveBeenCalledTimes(callsAfterStart); + }, + ); + }); + }); + describe('stopPolling', () => { it('clears pending delayed poll timeout when stopping', async () => { const pollingInterval = 10000; @@ -1542,13 +1463,13 @@ describe('ConfigRegistryController', () => { async ({ controller, mockApiServiceHandler }) => { controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); const callsAfterFirstAdvance = mockApiServiceHandler.mock.calls.length; controller.stopAllPolling(); - await jestAdvanceTime({ duration: pollingInterval }); + await jest.advanceTimersByTimeAsync(pollingInterval); expect(mockApiServiceHandler).toHaveBeenCalledTimes( callsAfterFirstAdvance, ); @@ -1578,13 +1499,13 @@ describe('ConfigRegistryController', () => { async ({ controller, mockApiServiceHandler }) => { const token = controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); const callsAfterFirstAdvance = mockApiServiceHandler.mock.calls.length; controller.stopPollingByPollingToken(token); - await jestAdvanceTime({ duration: pollingInterval }); + await jest.advanceTimersByTimeAsync(pollingInterval); expect(mockApiServiceHandler).toHaveBeenCalledTimes( callsAfterFirstAdvance, ); @@ -1607,13 +1528,13 @@ describe('ConfigRegistryController', () => { async ({ controller, mockApiServiceHandler }) => { const token = controller.startPolling(null); - await jestAdvanceTime({ duration: pollingInterval }); - expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); + await jest.advanceTimersByTimeAsync(pollingInterval); + expect(mockApiServiceHandler).toHaveBeenCalledTimes(2); mockApiServiceHandler.mockClear(); controller.stopPollingByPollingToken(token); - await jestAdvanceTime({ duration: pollingInterval }); + await jest.advanceTimersByTimeAsync(pollingInterval); expect(mockApiServiceHandler).not.toHaveBeenCalled(); }, ); @@ -1624,13 +1545,13 @@ describe('ConfigRegistryController', () => { controller.startPolling(null); controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); mockApiServiceHandler.mockClear(); controller.stopAllPolling(); - await jestAdvanceTime({ duration: DEFAULT_POLLING_INTERVAL }); + await jest.advanceTimersByTimeAsync(DEFAULT_POLLING_INTERVAL); expect(mockApiServiceHandler).not.toHaveBeenCalled(); }); }); @@ -1638,19 +1559,19 @@ describe('ConfigRegistryController', () => { it('stops specific polling session when called with token', async () => { await withController(async ({ controller, mockApiServiceHandler }) => { const tokenA = controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); mockApiServiceHandler.mockClear(); const tokenB = controller.startPolling(null); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); expect(mockApiServiceHandler).not.toHaveBeenCalled(); mockApiServiceHandler.mockClear(); controller.stopPollingByPollingToken(tokenA); controller.stopPollingByPollingToken(tokenB); - await jestAdvanceTime({ duration: DEFAULT_POLLING_INTERVAL }); + await jest.advanceTimersByTimeAsync(DEFAULT_POLLING_INTERVAL); expect(mockApiServiceHandler).not.toHaveBeenCalled(); }); }); @@ -1663,12 +1584,12 @@ describe('ConfigRegistryController', () => { ); expect(typeof token).toBe('string'); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); mockApiServiceHandler.mockClear(); messenger.call('ConfigRegistryController:stopPolling'); - await jestAdvanceTime({ duration: DEFAULT_POLLING_INTERVAL }); + await jest.advanceTimersByTimeAsync(DEFAULT_POLLING_INTERVAL); expect(mockApiServiceHandler).not.toHaveBeenCalled(); }); }); @@ -1681,12 +1602,12 @@ describe('ConfigRegistryController', () => { ); expect(typeof token).toBe('string'); - await jestAdvanceTime({ duration: 0 }); + await jest.advanceTimersByTimeAsync(0); expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); mockApiServiceHandler.mockClear(); messenger.call('ConfigRegistryController:stopPolling'); - await jestAdvanceTime({ duration: DEFAULT_POLLING_INTERVAL }); + await jest.advanceTimersByTimeAsync(DEFAULT_POLLING_INTERVAL); expect(mockApiServiceHandler).not.toHaveBeenCalled(); }); }); diff --git a/packages/config-registry-controller/src/ConfigRegistryController.ts b/packages/config-registry-controller/src/ConfigRegistryController.ts index f5e3bed2e81..612d50ea57f 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.ts @@ -10,14 +10,12 @@ import type { import type { Messenger } from '@metamask/messenger'; import { StaticIntervalPollingController } from '@metamask/polling-controller'; import { RemoteFeatureFlagControllerGetStateAction } from '@metamask/remote-feature-flag-controller'; +import type { RemoteFeatureFlagControllerStateChangeEvent } from '@metamask/remote-feature-flag-controller'; import { Duration, inMilliseconds } from '@metamask/utils'; -import type { - FetchConfigOptions, - FetchConfigResult, - RegistryNetworkConfig, -} from './config-registry-api-service'; -import { isConfigRegistryApiEnabled as defaultIsConfigRegistryApiEnabled } from './utils/feature-flags'; +import type { ConfigRegistryApiServiceFetchConfigAction } from './config-registry-api-service/config-registry-api-service-method-action-types'; +import type { RegistryNetworkConfig } from './config-registry-api-service/types'; +import { isConfigRegistryApiEnabled } from './utils/feature-flags'; const controllerName = 'ConfigRegistryController'; @@ -141,10 +139,7 @@ export type ConfigRegistryControllerActions = */ type AllowedActions = | RemoteFeatureFlagControllerGetStateAction - | { - type: 'ConfigRegistryApiService:fetchConfig'; - handler: (options?: FetchConfigOptions) => Promise; - }; + | ConfigRegistryApiServiceFetchConfigAction; /** * Events that {@link ConfigRegistryControllerMessenger} exposes to other consumers. @@ -156,7 +151,10 @@ export type ConfigRegistryControllerEvents = * Events from other messengers that {@link ConfigRegistryControllerMessenger} * subscribes to. */ -type AllowedEvents = KeyringControllerUnlockEvent | KeyringControllerLockEvent; +type AllowedEvents = + | KeyringControllerUnlockEvent + | KeyringControllerLockEvent + | RemoteFeatureFlagControllerStateChangeEvent; /** * The messenger restricted to actions and events accessed by @@ -168,42 +166,33 @@ export type ConfigRegistryControllerMessenger = Messenger< ConfigRegistryControllerEvents | AllowedEvents >; -/** @deprecated Use {@link ConfigRegistryControllerMessenger} instead. */ -export type ConfigRegistryMessenger = ConfigRegistryControllerMessenger; - export type ConfigRegistryControllerOptions = { - messenger: ConfigRegistryMessenger; + messenger: ConfigRegistryControllerMessenger; state?: Partial; pollingInterval?: number; fallbackConfig?: Record; - isConfigRegistryApiEnabled?: (messenger: ConfigRegistryMessenger) => boolean; }; export class ConfigRegistryController extends StaticIntervalPollingController()< typeof controllerName, ConfigRegistryControllerState, - ConfigRegistryMessenger + ConfigRegistryControllerMessenger > { - readonly #isConfigRegistryApiEnabled: ( - messenger: ConfigRegistryMessenger, - ) => boolean; - /** * @param options - The controller options. * @param options.messenger - The controller messenger. Must have - * `ConfigRegistryApiService:fetchConfig` action handler registered. + * `ConfigRegistryApiService:fetchConfig` action handler registered + * (e.g. by instantiating {@link ConfigRegistryApiService} with the same + * messenger). * @param options.state - Initial state. * @param options.pollingInterval - Polling interval in milliseconds. * @param options.fallbackConfig - Fallback configuration. - * @param options.isConfigRegistryApiEnabled - Function to check if the config - * registry API is enabled. Defaults to checking the remote feature flag. */ constructor({ messenger, state = {}, pollingInterval = DEFAULT_POLLING_INTERVAL, fallbackConfig = DEFAULT_FALLBACK_CONFIG, - isConfigRegistryApiEnabled = defaultIsConfigRegistryApiEnabled, }: ConfigRegistryControllerOptions) { super({ name: controllerName, @@ -220,7 +209,6 @@ export class ConfigRegistryController extends StaticIntervalPollingController this.stopAllPolling(), ); + + this.messenger.subscribe('RemoteFeatureFlagController:stateChange', () => { + if (isConfigRegistryApiEnabled(this.messenger)) { + this.startPolling(null); + } else { + this.stopAllPolling(); + } + }); } async _executePoll(_input: null): Promise { - const isApiEnabled = this.#isConfigRegistryApiEnabled(this.messenger); + const isApiEnabled = isConfigRegistryApiEnabled(this.messenger); // Skip fetch when API is disabled; client uses static config. if (!isApiEnabled) { return; } - const interval = this.getIntervalLength() ?? DEFAULT_POLLING_INTERVAL; - if ( - this.state.lastFetched !== null && - Date.now() - this.state.lastFetched < interval - ) { - return; - } - try { - const result: FetchConfigResult = await this.messenger.call( + const result = await this.messenger.call( 'ConfigRegistryApiService:fetchConfig', { etag: this.state.etag ?? undefined, diff --git a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service-method-action-types.ts b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service-method-action-types.ts new file mode 100644 index 00000000000..1ef2ae24d17 --- /dev/null +++ b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service-method-action-types.ts @@ -0,0 +1,18 @@ +import type { ConfigRegistryApiService } from './config-registry-api-service'; + +/** + * Fetches the latest config from the config registry API. + * + * @param args - The arguments to the function. + * @param args.options - Optional fetch options (e.g. etag for cache validation). + */ +export type ConfigRegistryApiServiceFetchConfigAction = { + type: 'ConfigRegistryApiService:fetchConfig'; + handler: ConfigRegistryApiService['fetchConfig']; +}; + +/** + * Union of all ConfigRegistryApiService action types. + */ +export type ConfigRegistryApiServiceMethodActions = + ConfigRegistryApiServiceFetchConfigAction; diff --git a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts index fe6fb21cafe..a8894ecc41f 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.test.ts @@ -2,9 +2,27 @@ import { SDK } from '@metamask/profile-sync-controller'; import nock from 'nock'; import { ConfigRegistryApiService } from './config-registry-api-service'; +import type { + ConfigRegistryApiServiceMessenger, + ConfigRegistryApiServiceOptions, +} from './config-registry-api-service'; import type { RegistryConfigApiResponse } from './types'; -import { jestAdvanceTime } from '../../../../tests/helpers'; -import { createMockNetworkConfig } from '../test-helpers'; +import { createMockNetworkConfig } from '../../tests/helpers'; + +function createMockServiceMessenger(): ConfigRegistryApiServiceMessenger { + return { + registerMethodActionHandlers: jest.fn(), + } as unknown as ConfigRegistryApiServiceMessenger; +} + +function createService( + overrides: Partial> = {}, +): ConfigRegistryApiService { + return new ConfigRegistryApiService({ + ...overrides, + messenger: createMockServiceMessenger(), + }); +} const CONFIG_PATH = '/v1/config/networks'; const UAT_ORIGIN = 'https://client-config.uat-api.cx.metamask.io'; @@ -27,7 +45,7 @@ describe('ConfigRegistryApiService', () => { .get(CONFIG_PATH) .reply(200, MOCK_API_RESPONSE); - const service = new ConfigRegistryApiService({ env: SDK.Env.UAT }); + const service = createService({ env: SDK.Env.UAT }); await service.fetchConfig(); expect(scope.isDone()).toBe(true); }); @@ -37,7 +55,7 @@ describe('ConfigRegistryApiService', () => { .get(CONFIG_PATH) .reply(200, MOCK_API_RESPONSE); - const service = new ConfigRegistryApiService({ env: SDK.Env.DEV }); + const service = createService({ env: SDK.Env.DEV }); await service.fetchConfig(); expect(scope.isDone()).toBe(true); }); @@ -47,7 +65,7 @@ describe('ConfigRegistryApiService', () => { .get(CONFIG_PATH) .reply(200, MOCK_API_RESPONSE); - const service = new ConfigRegistryApiService({ env: SDK.Env.PRD }); + const service = createService({ env: SDK.Env.PRD }); await service.fetchConfig(); expect(scope.isDone()).toBe(true); }); @@ -57,7 +75,7 @@ describe('ConfigRegistryApiService', () => { .get(CONFIG_PATH) .reply(200, MOCK_API_RESPONSE); - const service = new ConfigRegistryApiService(); + const service = createService(); await service.fetchConfig(); @@ -72,7 +90,7 @@ describe('ConfigRegistryApiService', () => { ETag: '"test-etag-123"', }); - const service = new ConfigRegistryApiService(); + const service = createService(); const result = await service.fetchConfig(); expect(result).toMatchObject({ @@ -88,7 +106,7 @@ describe('ConfigRegistryApiService', () => { .get(CONFIG_PATH) .reply(200, MOCK_API_RESPONSE); - const service = new ConfigRegistryApiService(); + const service = createService(); const result = await service.fetchConfig(); expect(result).toMatchObject({ modified: true, data: MOCK_API_RESPONSE }); @@ -103,7 +121,7 @@ describe('ConfigRegistryApiService', () => { .matchHeader('If-None-Match', etag) .reply(304); - const service = new ConfigRegistryApiService(); + const service = createService(); const result = await service.fetchConfig({ etag }); expect(result.modified).toBe(false); @@ -117,7 +135,7 @@ describe('ConfigRegistryApiService', () => { .get(CONFIG_PATH) .reply(200, MOCK_API_RESPONSE, { ETag: etag }); - const service = new ConfigRegistryApiService(); + const service = createService(); await service.fetchConfig(); expect(firstScope.isDone()).toBe(true); @@ -136,7 +154,7 @@ describe('ConfigRegistryApiService', () => { it('handles 304 Not Modified response without ETag header', async () => { const scope = nock(UAT_ORIGIN).get(CONFIG_PATH).reply(304); - const service = new ConfigRegistryApiService(); + const service = createService(); const result = await service.fetchConfig(); expect(result.modified).toBe(false); @@ -151,7 +169,7 @@ describe('ConfigRegistryApiService', () => { .matchHeader('If-None-Match', etag) .reply(200, MOCK_API_RESPONSE); - const service = new ConfigRegistryApiService(); + const service = createService(); await service.fetchConfig({ etag }); expect(scope.isDone()).toBe(true); @@ -163,7 +181,7 @@ describe('ConfigRegistryApiService', () => { .matchHeader('If-None-Match', (val) => val === undefined) .reply(200, MOCK_API_RESPONSE); - const service = new ConfigRegistryApiService(); + const service = createService(); await service.fetchConfig({ etag: undefined }); expect(scope.isDone()).toBe(true); @@ -174,7 +192,7 @@ describe('ConfigRegistryApiService', () => { .get(CONFIG_PATH) .reply(200, MOCK_API_RESPONSE); - const service = new ConfigRegistryApiService(); + const service = createService(); await service.fetchConfig(undefined); expect(scope.isDone()).toBe(true); @@ -186,7 +204,7 @@ describe('ConfigRegistryApiService', () => { .get(CONFIG_PATH) .reply(200, invalidResponse); - const service = new ConfigRegistryApiService(); + const service = createService(); await expect(service.fetchConfig()).rejects.toMatchObject( expect.objectContaining({ message: expect.any(String) }), @@ -197,7 +215,7 @@ describe('ConfigRegistryApiService', () => { it('throws error when response body is null', async () => { const scope = nock(UAT_ORIGIN).get(CONFIG_PATH).reply(200, 'null'); - const service = new ConfigRegistryApiService(); + const service = createService(); await expect(service.fetchConfig()).rejects.toMatchObject( expect.objectContaining({ message: expect.any(String) }), @@ -210,7 +228,7 @@ describe('ConfigRegistryApiService', () => { .get(CONFIG_PATH) .reply(200, { data: null }); - const service = new ConfigRegistryApiService(); + const service = createService(); await expect(service.fetchConfig()).rejects.toMatchObject( expect.objectContaining({ message: expect.any(String) }), @@ -225,7 +243,7 @@ describe('ConfigRegistryApiService', () => { data: { version: '1', timestamp: 0, chains: 'not-an-array' }, }); - const service = new ConfigRegistryApiService(); + const service = createService(); await expect(service.fetchConfig()).rejects.toMatchObject( expect.objectContaining({ message: expect.any(String) }), @@ -238,7 +256,7 @@ describe('ConfigRegistryApiService', () => { .get(CONFIG_PATH) .reply(500, 'Internal Server Error'); - const service = new ConfigRegistryApiService({ + const service = createService({ policyOptions: { maxRetries: 0 }, }); @@ -255,7 +273,7 @@ describe('ConfigRegistryApiService', () => { .fn() .mockRejectedValue(new Error('Network connection failed')); - const service = new ConfigRegistryApiService({ + const service = createService({ fetch: customFetch, }); @@ -271,7 +289,7 @@ describe('ConfigRegistryApiService', () => { .get(CONFIG_PATH) .reply(200, MOCK_API_RESPONSE); - const service = new ConfigRegistryApiService({ + const service = createService({ policyOptions: { maxRetries: 2 }, }); @@ -282,6 +300,16 @@ describe('ConfigRegistryApiService', () => { }); }); + describe('onRetry', () => { + it('registers and returns a disposable', () => { + const service = createService(); + const listener = jest.fn(); + const disposable = service.onRetry(listener); + expect(disposable).toHaveProperty('dispose'); + expect(typeof disposable.dispose).toBe('function'); + }); + }); + describe('onBreak', () => { beforeEach(() => { jest.useFakeTimers({ doNotFake: ['nextTick', 'queueMicrotask'] }); @@ -300,7 +328,7 @@ describe('ConfigRegistryApiService', () => { } const onBreakHandler = jest.fn(); - const service = new ConfigRegistryApiService({ + const service = createService({ policyOptions: { maxRetries: retries, maxConsecutiveFailures: maximumConsecutiveFailures, @@ -309,20 +337,17 @@ describe('ConfigRegistryApiService', () => { }); service.onBreak(onBreakHandler); + service.onRetry(() => { + jest.advanceTimersToNextTimer(); + }); for (let i = 0; i < maximumConsecutiveFailures; i++) { await expect(service.fetchConfig()).rejects.toMatchObject( expect.objectContaining({ message: expect.any(String) }), ); - await jestAdvanceTime({ duration: 100 }); } const finalPromise = service.fetchConfig(); - finalPromise.catch(() => { - // Expected rejection - }); - await jestAdvanceTime({ duration: 100 }); - await expect(finalPromise).rejects.toMatchObject( expect.objectContaining({ message: expect.any(String) }), ); @@ -348,7 +373,7 @@ describe('ConfigRegistryApiService', () => { return MOCK_API_RESPONSE; }); - const service = new ConfigRegistryApiService({ + const service = createService({ policyOptions: { degradedThreshold, maxRetries: 0 }, }); const onDegradedHandler = jest.fn(); @@ -370,7 +395,7 @@ describe('ConfigRegistryApiService', () => { }), ); - const service = new ConfigRegistryApiService({ + const service = createService({ fetch: customFetch, }); diff --git a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts index fcf5d7003d8..6757788d897 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts @@ -3,8 +3,11 @@ import type { CreateServicePolicyOptions, ServicePolicy, } from '@metamask/controller-utils'; +import type { Messenger } from '@metamask/messenger'; import { SDK } from '@metamask/profile-sync-controller'; +import type { IDisposable } from 'cockatiel'; +import type { ConfigRegistryApiServiceMethodActions } from './config-registry-api-service-method-action-types'; import type { FetchConfigOptions, FetchConfigResult, @@ -14,6 +17,49 @@ import { validateRegistryConfigApiResponse } from './types'; const ENDPOINT_PATH = '/config/networks'; +/** + * The name of the {@link ConfigRegistryApiService}, used to namespace the + * service's actions and events. + */ +export const serviceName = 'ConfigRegistryApiService'; + +// === MESSENGER === + +const MESSENGER_EXPOSED_METHODS = ['fetchConfig'] as const; + +/** + * Actions that {@link ConfigRegistryApiService} exposes to other consumers. + */ +export type ConfigRegistryApiServiceActions = + ConfigRegistryApiServiceMethodActions; + +/** + * Actions from other messengers that {@link ConfigRegistryApiServiceMessenger} calls. + */ +type AllowedActions = never; + +/** + * Events that {@link ConfigRegistryApiService} exposes to other consumers. + */ +export type ConfigRegistryApiServiceEvents = never; + +/** + * Events from other messengers that {@link ConfigRegistryApiService} subscribes to. + */ +type AllowedEvents = never; + +/** + * The messenger which is restricted to actions and events accessed by + * {@link ConfigRegistryApiService}. + */ +export type ConfigRegistryApiServiceMessenger = Messenger< + typeof serviceName, + ConfigRegistryApiServiceActions | AllowedActions, + ConfigRegistryApiServiceEvents | AllowedEvents +>; + +// === SERVICE DEFINITION === + /** * Returns the base URL for the config registry API for the given environment. * @@ -26,6 +72,11 @@ function getConfigRegistryUrl(env: SDK.Env): string { } export type ConfigRegistryApiServiceOptions = { + /** + * The messenger suited for this service. Required so the service can be used + * independently and register its actions. + */ + messenger: ConfigRegistryApiServiceMessenger; env?: SDK.Env; fetch?: typeof fetch; /** @@ -36,6 +87,10 @@ export type ConfigRegistryApiServiceOptions = { }; export class ConfigRegistryApiService { + readonly name: typeof serviceName; + + readonly #messenger: ConfigRegistryApiServiceMessenger; + readonly #policy: ServicePolicy; readonly #url: string; @@ -49,19 +104,42 @@ export class ConfigRegistryApiService { * Construct a Config Registry API Service. * * @param options - The options for constructing the service. + * @param options.messenger - The messenger suited for this service. * @param options.env - The environment to determine the correct API endpoints. Defaults to UAT. * @param options.fetch - Custom fetch function for testing or custom implementations. Defaults to the global fetch. * @param options.policyOptions - Options to pass to `createServicePolicy`, which wraps each request. See {@link CreateServicePolicyOptions}. */ constructor({ + messenger, env = SDK.Env.UAT, fetch: customFetch = globalThis.fetch, policyOptions = {}, - }: ConfigRegistryApiServiceOptions = {}) { + }: ConfigRegistryApiServiceOptions) { + this.name = serviceName; + this.#messenger = messenger; this.#url = getConfigRegistryUrl(env); this.#fetch = customFetch; this.#policy = createServicePolicy(policyOptions); + + this.#messenger.registerMethodActionHandlers( + this, + MESSENGER_EXPOSED_METHODS, + ); + } + + /** + * Registers a handler that will be called after a request returns a non-500 + * response, causing a retry. Primarily useful in tests where timers are being + * mocked. + * + * @param listener - The handler to be called. + * @returns An object that can be used to unregister the handler. See + * {@link CockatielEvent}. + * @see {@link createServicePolicy} + */ + onRetry(listener: Parameters[0]): IDisposable { + return this.#policy.onRetry(listener); } /** diff --git a/packages/config-registry-controller/src/config-registry-api-service/filters.test.ts b/packages/config-registry-controller/src/config-registry-api-service/filters.test.ts index 831fd551b5d..ef4963496b1 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/filters.test.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/filters.test.ts @@ -1,6 +1,6 @@ import { filterNetworks } from './filters'; import type { RegistryNetworkConfig } from './types'; -import { createMockNetworkConfig } from '../test-helpers'; +import { createMockNetworkConfig } from '../../tests/helpers'; describe('filters', () => { describe('filterNetworks', () => { diff --git a/packages/config-registry-controller/src/config-registry-api-service/filters.ts b/packages/config-registry-controller/src/config-registry-api-service/filters.ts index 668ce8bae8c..0827d6ad65d 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/filters.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/filters.ts @@ -8,13 +8,13 @@ export type NetworkFilterOptions = { isDefault?: boolean; }; -const FILTER_KEYS: (keyof NetworkFilterOptions)[] = [ +const FILTER_KEYS = [ 'isFeatured', 'isTestnet', 'isActive', 'isDeprecated', 'isDefault', -]; +] as const satisfies (keyof NetworkFilterOptions)[]; /** * @param networks - Array of chain configurations to filter. diff --git a/packages/config-registry-controller/src/config-registry-api-service/index.ts b/packages/config-registry-controller/src/config-registry-api-service/index.ts deleted file mode 100644 index a740666621a..00000000000 --- a/packages/config-registry-controller/src/config-registry-api-service/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -export type { - FetchConfigOptions, - FetchConfigResult, - RegistryNetworkConfig, - RegistryConfigApiResponse, -} from './types'; - -export { ConfigRegistryApiService } from './config-registry-api-service'; - -export type { ConfigRegistryApiServiceOptions } from './config-registry-api-service'; - -export type { NetworkFilterOptions } from './filters'; -export { filterNetworks } from './filters'; diff --git a/packages/config-registry-controller/src/index.ts b/packages/config-registry-controller/src/index.ts index 081861fbdaf..fb78860cb7b 100644 --- a/packages/config-registry-controller/src/index.ts +++ b/packages/config-registry-controller/src/index.ts @@ -8,7 +8,6 @@ export type { ConfigRegistryControllerEvents, ConfigRegistryControllerStateChangeEvent, ConfigRegistryControllerMessenger, - ConfigRegistryMessenger, } from './ConfigRegistryController'; export { ConfigRegistryController, @@ -20,11 +19,21 @@ export type { FetchConfigResult, RegistryNetworkConfig, RegistryConfigApiResponse, +} from './config-registry-api-service/types'; +export type { ConfigRegistryApiServiceOptions, - NetworkFilterOptions, -} from './config-registry-api-service'; + ConfigRegistryApiServiceActions, + ConfigRegistryApiServiceEvents, + ConfigRegistryApiServiceMessenger, +} from './config-registry-api-service/config-registry-api-service'; +export type { + ConfigRegistryApiServiceFetchConfigAction, + ConfigRegistryApiServiceMethodActions, +} from './config-registry-api-service/config-registry-api-service-method-action-types'; +export type { NetworkFilterOptions } from './config-registry-api-service/filters'; export { ConfigRegistryApiService, - filterNetworks, -} from './config-registry-api-service'; + serviceName as configRegistryApiServiceName, +} from './config-registry-api-service/config-registry-api-service'; +export { filterNetworks } from './config-registry-api-service/filters'; export { isConfigRegistryApiEnabled } from './utils/feature-flags'; diff --git a/packages/config-registry-controller/src/selectors.test.ts b/packages/config-registry-controller/src/selectors.test.ts index 3a6e1ba31c2..e1fe6e7ddad 100644 --- a/packages/config-registry-controller/src/selectors.test.ts +++ b/packages/config-registry-controller/src/selectors.test.ts @@ -1,5 +1,5 @@ import { selectFeaturedNetworks, selectNetworks } from './selectors'; -import { createMockNetworkConfig } from './test-helpers'; +import { createMockNetworkConfig } from '../tests/helpers'; describe('selectors', () => { describe('selectNetworks', () => { diff --git a/packages/config-registry-controller/src/selectors.ts b/packages/config-registry-controller/src/selectors.ts index 67bc9ea3fff..7d44c486a59 100644 --- a/packages/config-registry-controller/src/selectors.ts +++ b/packages/config-registry-controller/src/selectors.ts @@ -1,7 +1,7 @@ import { createSelector } from 'reselect'; -import { filterNetworks } from './config-registry-api-service'; -import type { RegistryNetworkConfig } from './config-registry-api-service'; +import { filterNetworks } from './config-registry-api-service/filters'; +import type { RegistryNetworkConfig } from './config-registry-api-service/types'; import type { ConfigRegistryControllerState } from './ConfigRegistryController'; /** diff --git a/packages/config-registry-controller/src/utils/feature-flags.ts b/packages/config-registry-controller/src/utils/feature-flags.ts index c20f90e2eeb..0957c654fb8 100644 --- a/packages/config-registry-controller/src/utils/feature-flags.ts +++ b/packages/config-registry-controller/src/utils/feature-flags.ts @@ -1,4 +1,4 @@ -import type { ConfigRegistryMessenger } from '../ConfigRegistryController'; +import type { ConfigRegistryControllerMessenger } from '../ConfigRegistryController'; const FEATURE_FLAG_KEY = 'configRegistryApiEnabled'; const DEFAULT_FEATURE_FLAG_VALUE = false; @@ -10,7 +10,7 @@ const DEFAULT_FEATURE_FLAG_VALUE = false; * @returns True if the feature flag is enabled, false otherwise. */ export function isConfigRegistryApiEnabled( - messenger: ConfigRegistryMessenger, + messenger: ConfigRegistryControllerMessenger, ): boolean { try { const state = messenger.call('RemoteFeatureFlagController:getState'); diff --git a/packages/config-registry-controller/src/test-helpers.ts b/packages/config-registry-controller/tests/helpers.ts similarity index 95% rename from packages/config-registry-controller/src/test-helpers.ts rename to packages/config-registry-controller/tests/helpers.ts index 4b5f335c02b..a096f0e9143 100644 --- a/packages/config-registry-controller/src/test-helpers.ts +++ b/packages/config-registry-controller/tests/helpers.ts @@ -1,4 +1,4 @@ -import type { RegistryNetworkConfig } from './config-registry-api-service'; +import type { RegistryNetworkConfig } from '../src/config-registry-api-service/types'; /** * Creates a mock RegistryNetworkConfig (CAIP-2 chain) for testing. diff --git a/packages/config-registry-controller/tsconfig.build.json b/packages/config-registry-controller/tsconfig.build.json index 70dd82381c2..08b48b2b526 100644 --- a/packages/config-registry-controller/tsconfig.build.json +++ b/packages/config-registry-controller/tsconfig.build.json @@ -5,7 +5,7 @@ "outDir": "./dist", "rootDir": "./src" }, - "exclude": ["**/*.test.ts", "./src/test-helpers.ts"], + "exclude": ["**/*.test.ts"], "references": [ { "path": "../base-controller/tsconfig.build.json" }, { "path": "../controller-utils/tsconfig.build.json" }, diff --git a/packages/config-registry-controller/tsconfig.json b/packages/config-registry-controller/tsconfig.json index f6522b88f9c..05f86e783c9 100644 --- a/packages/config-registry-controller/tsconfig.json +++ b/packages/config-registry-controller/tsconfig.json @@ -12,5 +12,5 @@ { "path": "../profile-sync-controller" }, { "path": "../remote-feature-flag-controller" } ], - "include": ["../../types", "./src"] + "include": ["../../types", "./src", "./tests"] } diff --git a/yarn.lock b/yarn.lock index c22f14e1f40..5c4e26fa85b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2934,6 +2934,7 @@ __metadata: "@metamask/auto-changelog": "npm:^3.4.4" "@metamask/base-controller": "npm:^9.0.0" "@metamask/controller-utils": "npm:^11.19.0" + "@metamask/keyring-controller": "npm:^25.1.0" "@metamask/messenger": "npm:^0.3.0" "@metamask/polling-controller": "npm:^16.0.3" "@metamask/profile-sync-controller": "npm:^27.1.0" From f4e648756e3e0e55ca8af2cfd2c6f2f599a54451 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Fri, 27 Feb 2026 16:28:11 +0100 Subject: [PATCH 47/55] chore: update lockfile for config-registry-controller dependencies --- yarn.lock | 4282 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 2442 insertions(+), 1840 deletions(-) diff --git a/yarn.lock b/yarn.lock index 5c4e26fa85b..bdd36b6dfd4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,7 +12,7 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.28.6, @babel/code-frame@npm:^7.29.0": +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.27.1, @babel/code-frame@npm:^7.28.6, @babel/code-frame@npm:^7.29.0": version: 7.29.0 resolution: "@babel/code-frame@npm:7.29.0" dependencies: @@ -109,7 +109,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.24.7, @babel/helper-plugin-utils@npm:^7.24.8, @babel/helper-plugin-utils@npm:^7.28.6, @babel/helper-plugin-utils@npm:^7.8.0": +"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.28.6, @babel/helper-plugin-utils@npm:^7.8.0": version: 7.28.6 resolution: "@babel/helper-plugin-utils@npm:7.28.6" checksum: 10/21c853bbc13dbdddf03309c9a0477270124ad48989e1ad6524b83e83a77524b333f92edd2caae645c5a7ecf264ec6d04a9ebe15aeb54c7f33c037b71ec521e4a @@ -147,7 +147,7 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.0, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.24.7, @babel/parser@npm:^7.28.6, @babel/parser@npm:^7.29.0": +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.0, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.28.6, @babel/parser@npm:^7.29.0": version: 7.29.0 resolution: "@babel/parser@npm:7.29.0" dependencies: @@ -203,13 +203,13 @@ __metadata: linkType: hard "@babel/plugin-syntax-import-attributes@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-syntax-import-attributes@npm:7.24.7" + version: 7.28.6 + resolution: "@babel/plugin-syntax-import-attributes@npm:7.28.6" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.28.6" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10/22fc50bd85a491bb8d22065f330a41f60d66f2f2d7a1deb73e80c8a4b5d7a42a092a03f8da18800650eca0fc14585167cc4e5c9fab351f0d390d1592347162ae + checksum: 10/6c8c6a5988dbb9799d6027360d1a5ba64faabf551f2ef11ba4eade0c62253b5c85d44ddc8eb643c74b9acb2bcaa664a950bd5de9a5d4aef291c4f2a48223bb4b languageName: node linkType: hard @@ -335,22 +335,20 @@ __metadata: linkType: hard "@babel/plugin-syntax-typescript@npm:^7.7.2": - version: 7.25.4 - resolution: "@babel/plugin-syntax-typescript@npm:7.25.4" + version: 7.28.6 + resolution: "@babel/plugin-syntax-typescript@npm:7.28.6" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.8" + "@babel/helper-plugin-utils": "npm:^7.28.6" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10/0771b45a35fd536cd3b3a48e5eda0f53e2d4f4a0ca07377cc247efa39eaf6002ed1c478106aad2650e54aefaebcb4f34f3284c4ae9252695dbd944bf66addfb0 + checksum: 10/5c55f9c63bd36cf3d7e8db892294c8f85000f9c1526c3a1cc310d47d1e174f5c6f6605e5cc902c4636d885faba7a9f3d5e5edc6b35e4f3b1fd4c2d58d0304fa5 languageName: node linkType: hard "@babel/runtime@npm:^7.23.9": - version: 7.25.4 - resolution: "@babel/runtime@npm:7.25.4" - dependencies: - regenerator-runtime: "npm:^0.14.0" - checksum: 10/70d2a420c24a3289ea6c4addaf3a1c4186bc3d001c92445faa3cd7601d7d2fbdb32c63b3a26b9771e20ff2f511fa76b726bf256f823cdb95bc37b8eadbd02f70 + version: 7.28.6 + resolution: "@babel/runtime@npm:7.28.6" + checksum: 10/fbcd439cb74d4a681958eb064c509829e3f46d8a4bfaaf441baa81bb6733d1e680bccc676c813883d7741bcaada1d0d04b15aa320ef280b5734e2192b50decf9 languageName: node linkType: hard @@ -380,7 +378,7 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.23.0, @babel/types@npm:^7.28.6, @babel/types@npm:^7.29.0, @babel/types@npm:^7.3.3": +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.23.0, @babel/types@npm:^7.28.2, @babel/types@npm:^7.28.6, @babel/types@npm:^7.29.0, @babel/types@npm:^7.3.3": version: 7.29.0 resolution: "@babel/types@npm:7.29.0" dependencies: @@ -398,29 +396,57 @@ __metadata: linkType: hard "@contentful/content-source-maps@npm:^0.11.0": - version: 0.11.1 - resolution: "@contentful/content-source-maps@npm:0.11.1" + version: 0.11.44 + resolution: "@contentful/content-source-maps@npm:0.11.44" dependencies: "@vercel/stega": "npm:^0.1.2" json-pointer: "npm:^0.6.2" - checksum: 10/598e88349210aed21c9ee871250353ae15cb4130180ade9cf283261e192a80c72f8674c5533c490ad1358850e45578ed6ed4ac997b32c23b029ae4d096fa5646 + checksum: 10/30c5334c9921853e3a2ec71b4e572fd0f361fd2d6da3378c6345c9f8a2693ffda1f88bcc84243dba1a514562ef9a766315b9c8626f757dec8b000c6ace5a3d23 languageName: node linkType: hard "@contentful/rich-text-html-renderer@npm:^16.5.2": - version: 16.6.9 - resolution: "@contentful/rich-text-html-renderer@npm:16.6.9" + version: 16.6.10 + resolution: "@contentful/rich-text-html-renderer@npm:16.6.10" dependencies: - "@contentful/rich-text-types": "npm:^16.8.4" + "@contentful/rich-text-types": "npm:^16.8.5" escape-html: "npm:^1.0.3" - checksum: 10/10bdcee4c01b89e5ab54ccab592bad7d3658fdd32ee58e2d5d18628a59ca47c7393c8dec41e96172b4c171f7fb4d2d1d6b9da9d6eeebbe5ed83fc3de8c4c0c89 + checksum: 10/fdf5121524355c96cd8a4628b2cc50a61b9b9d37da167dd983cc8fa24fa822427809d00064ebca9b85b8f40d92719f0b86f0e4ea4eaa8d078656ed56c51df6bb + languageName: node + linkType: hard + +"@contentful/rich-text-types@npm:^16.0.2, @contentful/rich-text-types@npm:^16.8.5": + version: 16.8.5 + resolution: "@contentful/rich-text-types@npm:16.8.5" + checksum: 10/7c1ec7088cc39bbd8f5edc14867ed3d59d06a55f2c92e6c62913aa2312056e920528e6ca6d59780b32c6fe2ab89c429b9f0bce9a52f456be7260f458527ccc3b + languageName: node + linkType: hard + +"@emnapi/core@npm:^1.4.3": + version: 1.8.1 + resolution: "@emnapi/core@npm:1.8.1" + dependencies: + "@emnapi/wasi-threads": "npm:1.1.0" + tslib: "npm:^2.4.0" + checksum: 10/904ea60c91fc7d8aeb4a8f2c433b8cfb47c50618f2b6f37429fc5093c857c6381c60628a5cfbc3a7b0d75b0a288f21d4ed2d4533e82f92c043801ef255fd6a5c languageName: node linkType: hard -"@contentful/rich-text-types@npm:^16.0.2, @contentful/rich-text-types@npm:^16.8.4": - version: 16.8.4 - resolution: "@contentful/rich-text-types@npm:16.8.4" - checksum: 10/22e0a165545f32cc51d1e6231a9e7b617af98c452ecfb28ace9ba8a53b89bb2d940019ffae00ef2bc77c998630a66bfc88d01031e732afb11172f877064aa5b2 +"@emnapi/runtime@npm:^1.4.3": + version: 1.8.1 + resolution: "@emnapi/runtime@npm:1.8.1" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10/26725e202d4baefdc4a6ba770f703dfc80825a27c27a08c22bac1e1ce6f8f75c47b4fe9424d9b63239463c33ef20b650f08d710da18dfa1164a95e5acb865dba + languageName: node + linkType: hard + +"@emnapi/wasi-threads@npm:1.1.0": + version: 1.1.0 + resolution: "@emnapi/wasi-threads@npm:1.1.0" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10/0d557e75262d2f4c95cb2a456ba0785ef61f919ce488c1d76e5e3acfd26e00c753ef928cd80068363e0c166ba8cc0141305daf0f81aad5afcd421f38f11e0f4e languageName: node linkType: hard @@ -445,200 +471,202 @@ __metadata: languageName: node linkType: hard -"@es-joy/jsdoccomment@npm:~0.49.0": - version: 0.49.0 - resolution: "@es-joy/jsdoccomment@npm:0.49.0" +"@es-joy/jsdoccomment@npm:~0.50.2": + version: 0.50.2 + resolution: "@es-joy/jsdoccomment@npm:0.50.2" dependencies: + "@types/estree": "npm:^1.0.6" + "@typescript-eslint/types": "npm:^8.11.0" comment-parser: "npm:1.4.1" esquery: "npm:^1.6.0" jsdoc-type-pratt-parser: "npm:~4.1.0" - checksum: 10/d767cef9b09f22d1892b8bd544eee32aa7b55c585edf6b51452e6f377f205b06f46bd319174022f75794d39625b4b0f8ce75c8a4ea0b7fd0f773063506e0ef4d + checksum: 10/a309f01bd1691c6991e5efb78057ec9122ef33208fec2464d7b9e5838964b948fa46c9c944a09218a752b49267f05ac15b557018c8a1897fd8df47b944b4537f languageName: node linkType: hard -"@esbuild/aix-ppc64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/aix-ppc64@npm:0.25.9" +"@esbuild/aix-ppc64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/aix-ppc64@npm:0.27.3" conditions: os=aix & cpu=ppc64 languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/android-arm64@npm:0.25.9" +"@esbuild/android-arm64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/android-arm64@npm:0.27.3" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@esbuild/android-arm@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/android-arm@npm:0.25.9" +"@esbuild/android-arm@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/android-arm@npm:0.27.3" conditions: os=android & cpu=arm languageName: node linkType: hard -"@esbuild/android-x64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/android-x64@npm:0.25.9" +"@esbuild/android-x64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/android-x64@npm:0.27.3" conditions: os=android & cpu=x64 languageName: node linkType: hard -"@esbuild/darwin-arm64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/darwin-arm64@npm:0.25.9" +"@esbuild/darwin-arm64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/darwin-arm64@npm:0.27.3" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@esbuild/darwin-x64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/darwin-x64@npm:0.25.9" +"@esbuild/darwin-x64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/darwin-x64@npm:0.27.3" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@esbuild/freebsd-arm64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/freebsd-arm64@npm:0.25.9" +"@esbuild/freebsd-arm64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/freebsd-arm64@npm:0.27.3" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/freebsd-x64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/freebsd-x64@npm:0.25.9" +"@esbuild/freebsd-x64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/freebsd-x64@npm:0.27.3" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@esbuild/linux-arm64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/linux-arm64@npm:0.25.9" +"@esbuild/linux-arm64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/linux-arm64@npm:0.27.3" conditions: os=linux & cpu=arm64 languageName: node linkType: hard -"@esbuild/linux-arm@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/linux-arm@npm:0.25.9" +"@esbuild/linux-arm@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/linux-arm@npm:0.27.3" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@esbuild/linux-ia32@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/linux-ia32@npm:0.25.9" +"@esbuild/linux-ia32@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/linux-ia32@npm:0.27.3" conditions: os=linux & cpu=ia32 languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/linux-loong64@npm:0.25.9" +"@esbuild/linux-loong64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/linux-loong64@npm:0.27.3" conditions: os=linux & cpu=loong64 languageName: node linkType: hard -"@esbuild/linux-mips64el@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/linux-mips64el@npm:0.25.9" +"@esbuild/linux-mips64el@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/linux-mips64el@npm:0.27.3" conditions: os=linux & cpu=mips64el languageName: node linkType: hard -"@esbuild/linux-ppc64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/linux-ppc64@npm:0.25.9" +"@esbuild/linux-ppc64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/linux-ppc64@npm:0.27.3" conditions: os=linux & cpu=ppc64 languageName: node linkType: hard -"@esbuild/linux-riscv64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/linux-riscv64@npm:0.25.9" +"@esbuild/linux-riscv64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/linux-riscv64@npm:0.27.3" conditions: os=linux & cpu=riscv64 languageName: node linkType: hard -"@esbuild/linux-s390x@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/linux-s390x@npm:0.25.9" +"@esbuild/linux-s390x@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/linux-s390x@npm:0.27.3" conditions: os=linux & cpu=s390x languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/linux-x64@npm:0.25.9" +"@esbuild/linux-x64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/linux-x64@npm:0.27.3" conditions: os=linux & cpu=x64 languageName: node linkType: hard -"@esbuild/netbsd-arm64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/netbsd-arm64@npm:0.25.9" +"@esbuild/netbsd-arm64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/netbsd-arm64@npm:0.27.3" conditions: os=netbsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/netbsd-x64@npm:0.25.9" +"@esbuild/netbsd-x64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/netbsd-x64@npm:0.27.3" conditions: os=netbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/openbsd-arm64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/openbsd-arm64@npm:0.25.9" +"@esbuild/openbsd-arm64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/openbsd-arm64@npm:0.27.3" conditions: os=openbsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/openbsd-x64@npm:0.25.9" +"@esbuild/openbsd-x64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/openbsd-x64@npm:0.27.3" conditions: os=openbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/openharmony-arm64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/openharmony-arm64@npm:0.25.9" +"@esbuild/openharmony-arm64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/openharmony-arm64@npm:0.27.3" conditions: os=openharmony & cpu=arm64 languageName: node linkType: hard -"@esbuild/sunos-x64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/sunos-x64@npm:0.25.9" +"@esbuild/sunos-x64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/sunos-x64@npm:0.27.3" conditions: os=sunos & cpu=x64 languageName: node linkType: hard -"@esbuild/win32-arm64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/win32-arm64@npm:0.25.9" +"@esbuild/win32-arm64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/win32-arm64@npm:0.27.3" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@esbuild/win32-ia32@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/win32-ia32@npm:0.25.9" +"@esbuild/win32-ia32@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/win32-ia32@npm:0.27.3" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.25.9": - version: 0.25.9 - resolution: "@esbuild/win32-x64@npm:0.25.9" +"@esbuild/win32-x64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/win32-x64@npm:0.27.3" conditions: os=win32 & cpu=x64 languageName: node linkType: hard -"@eslint-community/eslint-utils@npm:^4.1.2, @eslint-community/eslint-utils@npm:^4.4.0, @eslint-community/eslint-utils@npm:^4.4.1, @eslint-community/eslint-utils@npm:^4.8.0, @eslint-community/eslint-utils@npm:^4.9.1": +"@eslint-community/eslint-utils@npm:^4.1.2, @eslint-community/eslint-utils@npm:^4.4.0, @eslint-community/eslint-utils@npm:^4.5.0, @eslint-community/eslint-utils@npm:^4.8.0, @eslint-community/eslint-utils@npm:^4.9.1": version: 4.9.1 resolution: "@eslint-community/eslint-utils@npm:4.9.1" dependencies: @@ -686,26 +714,26 @@ __metadata: linkType: hard "@eslint/eslintrc@npm:^3.3.1": - version: 3.3.1 - resolution: "@eslint/eslintrc@npm:3.3.1" + version: 3.3.4 + resolution: "@eslint/eslintrc@npm:3.3.4" dependencies: - ajv: "npm:^6.12.4" + ajv: "npm:^6.14.0" debug: "npm:^4.3.2" espree: "npm:^10.0.1" globals: "npm:^14.0.0" ignore: "npm:^5.2.0" import-fresh: "npm:^3.2.1" - js-yaml: "npm:^4.1.0" - minimatch: "npm:^3.1.2" + js-yaml: "npm:^4.1.1" + minimatch: "npm:^3.1.3" strip-json-comments: "npm:^3.1.1" - checksum: 10/cc240addbab3c5fceaa65b2c8d5d4fd77ddbbf472c2f74f0270b9d33263dc9116840b6099c46b64c9680301146250439b044ed79278a1bcc557da412a4e3c1bb + checksum: 10/537e6bddb55d37a6b128910d54eaa2c1851992781f82dbf36294583de50386ca92bd669eadc99db9181ab4d735f7e6fa286cba10dab1327b1ea88599a2c5e6a7 languageName: node linkType: hard -"@eslint/js@npm:9.39.1, @eslint/js@npm:^9.11.0": - version: 9.39.1 - resolution: "@eslint/js@npm:9.39.1" - checksum: 10/b10b9b953212c0f3ffca475159bbe519e9e98847200c7432d1637d444fddcd7b712d2b7710a7dc20510f9cfbe8db330039b2aad09cb55d9545b116d940dbeed2 +"@eslint/js@npm:9.39.3, @eslint/js@npm:^9.11.0": + version: 9.39.3 + resolution: "@eslint/js@npm:9.39.3" + checksum: 10/91a1a1822cfeb2eb8a89aae86be5dfabad0b66b0915946516690a8485ddd80b91f43eee346789313fea1acbb7390a4958119ca7dc9a684a5c4014f12fcb3aaf3 languageName: node linkType: hard @@ -808,24 +836,24 @@ __metadata: languageName: node linkType: hard -"@ethersproject/abi@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/abi@npm:5.7.0" +"@ethersproject/abi@npm:^5.7.0, @ethersproject/abi@npm:^5.8.0": + version: 5.8.0 + resolution: "@ethersproject/abi@npm:5.8.0" dependencies: - "@ethersproject/address": "npm:^5.7.0" - "@ethersproject/bignumber": "npm:^5.7.0" - "@ethersproject/bytes": "npm:^5.7.0" - "@ethersproject/constants": "npm:^5.7.0" - "@ethersproject/hash": "npm:^5.7.0" - "@ethersproject/keccak256": "npm:^5.7.0" - "@ethersproject/logger": "npm:^5.7.0" - "@ethersproject/properties": "npm:^5.7.0" - "@ethersproject/strings": "npm:^5.7.0" - checksum: 10/6ed002cbc61a7e21bc0182702345659c1984f6f8e6bad166e43aee76ea8f74766dd0f6236574a868e1b4600af27972bf25b973fae7877ae8da3afa90d3965cac + "@ethersproject/address": "npm:^5.8.0" + "@ethersproject/bignumber": "npm:^5.8.0" + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/constants": "npm:^5.8.0" + "@ethersproject/hash": "npm:^5.8.0" + "@ethersproject/keccak256": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + "@ethersproject/properties": "npm:^5.8.0" + "@ethersproject/strings": "npm:^5.8.0" + checksum: 10/a63ebc2c8ea795ceca5289abaf817bb402c83c330cffd0ae2d355be70c54050a21ddd408abd4fd0dce4c3fd5c5f091707be2095011c233022a52f2110e7012d6 languageName: node linkType: hard -"@ethersproject/abstract-provider@npm:^5.7.0, @ethersproject/abstract-provider@npm:^5.8.0": +"@ethersproject/abstract-provider@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/abstract-provider@npm:5.8.0" dependencies: @@ -840,7 +868,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/abstract-signer@npm:^5.7.0, @ethersproject/abstract-signer@npm:^5.8.0": +"@ethersproject/abstract-signer@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/abstract-signer@npm:5.8.0" dependencies: @@ -866,7 +894,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/base64@npm:^5.7.0, @ethersproject/base64@npm:^5.8.0": +"@ethersproject/base64@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/base64@npm:5.8.0" dependencies: @@ -875,7 +903,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/basex@npm:^5.7.0, @ethersproject/basex@npm:^5.8.0": +"@ethersproject/basex@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/basex@npm:5.8.0" dependencies: @@ -896,7 +924,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/bytes@npm:^5.7.0, @ethersproject/bytes@npm:^5.8.0": +"@ethersproject/bytes@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/bytes@npm:5.8.0" dependencies: @@ -915,24 +943,24 @@ __metadata: linkType: hard "@ethersproject/contracts@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/contracts@npm:5.7.0" + version: 5.8.0 + resolution: "@ethersproject/contracts@npm:5.8.0" dependencies: - "@ethersproject/abi": "npm:^5.7.0" - "@ethersproject/abstract-provider": "npm:^5.7.0" - "@ethersproject/abstract-signer": "npm:^5.7.0" - "@ethersproject/address": "npm:^5.7.0" - "@ethersproject/bignumber": "npm:^5.7.0" - "@ethersproject/bytes": "npm:^5.7.0" - "@ethersproject/constants": "npm:^5.7.0" - "@ethersproject/logger": "npm:^5.7.0" - "@ethersproject/properties": "npm:^5.7.0" - "@ethersproject/transactions": "npm:^5.7.0" - checksum: 10/5df66179af242faabea287a83fd2f8f303a4244dc87a6ff802e1e3b643f091451295c8e3d088c7739970b7915a16a581c192d4e007d848f1fdf3cc9e49010053 + "@ethersproject/abi": "npm:^5.8.0" + "@ethersproject/abstract-provider": "npm:^5.8.0" + "@ethersproject/abstract-signer": "npm:^5.8.0" + "@ethersproject/address": "npm:^5.8.0" + "@ethersproject/bignumber": "npm:^5.8.0" + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/constants": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + "@ethersproject/properties": "npm:^5.8.0" + "@ethersproject/transactions": "npm:^5.8.0" + checksum: 10/839f8211f5e560f15468ae843ba316ffeacab5cebcece1eec76bc5714472ebfe3453484f283d3e46b9d3faaffef1e17cc3583cf24e01638a1fd52f69012cf8d4 languageName: node linkType: hard -"@ethersproject/hash@npm:^5.7.0, @ethersproject/hash@npm:^5.8.0": +"@ethersproject/hash@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/hash@npm:5.8.0" dependencies: @@ -990,7 +1018,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/keccak256@npm:^5.7.0, @ethersproject/keccak256@npm:^5.8.0": +"@ethersproject/keccak256@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/keccak256@npm:5.8.0" dependencies: @@ -1000,14 +1028,14 @@ __metadata: languageName: node linkType: hard -"@ethersproject/logger@npm:^5.7.0, @ethersproject/logger@npm:^5.8.0": +"@ethersproject/logger@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/logger@npm:5.8.0" checksum: 10/dab862d6cc3a4312f4c49d62b4a603f4b60707da8b8ff0fee6bdfee3cbed48b34ec8f23fedfef04dd3d24f2fa2d7ad2be753c775aa00fe24dcd400631d65004a languageName: node linkType: hard -"@ethersproject/networks@npm:^5.7.0, @ethersproject/networks@npm:^5.8.0": +"@ethersproject/networks@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/networks@npm:5.8.0" dependencies: @@ -1026,7 +1054,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/properties@npm:^5.7.0, @ethersproject/properties@npm:^5.8.0": +"@ethersproject/properties@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/properties@npm:5.8.0" dependencies: @@ -1036,34 +1064,34 @@ __metadata: linkType: hard "@ethersproject/providers@npm:^5.7.0, @ethersproject/providers@npm:^5.7.2": - version: 5.7.2 - resolution: "@ethersproject/providers@npm:5.7.2" + version: 5.8.0 + resolution: "@ethersproject/providers@npm:5.8.0" dependencies: - "@ethersproject/abstract-provider": "npm:^5.7.0" - "@ethersproject/abstract-signer": "npm:^5.7.0" - "@ethersproject/address": "npm:^5.7.0" - "@ethersproject/base64": "npm:^5.7.0" - "@ethersproject/basex": "npm:^5.7.0" - "@ethersproject/bignumber": "npm:^5.7.0" - "@ethersproject/bytes": "npm:^5.7.0" - "@ethersproject/constants": "npm:^5.7.0" - "@ethersproject/hash": "npm:^5.7.0" - "@ethersproject/logger": "npm:^5.7.0" - "@ethersproject/networks": "npm:^5.7.0" - "@ethersproject/properties": "npm:^5.7.0" - "@ethersproject/random": "npm:^5.7.0" - "@ethersproject/rlp": "npm:^5.7.0" - "@ethersproject/sha2": "npm:^5.7.0" - "@ethersproject/strings": "npm:^5.7.0" - "@ethersproject/transactions": "npm:^5.7.0" - "@ethersproject/web": "npm:^5.7.0" + "@ethersproject/abstract-provider": "npm:^5.8.0" + "@ethersproject/abstract-signer": "npm:^5.8.0" + "@ethersproject/address": "npm:^5.8.0" + "@ethersproject/base64": "npm:^5.8.0" + "@ethersproject/basex": "npm:^5.8.0" + "@ethersproject/bignumber": "npm:^5.8.0" + "@ethersproject/bytes": "npm:^5.8.0" + "@ethersproject/constants": "npm:^5.8.0" + "@ethersproject/hash": "npm:^5.8.0" + "@ethersproject/logger": "npm:^5.8.0" + "@ethersproject/networks": "npm:^5.8.0" + "@ethersproject/properties": "npm:^5.8.0" + "@ethersproject/random": "npm:^5.8.0" + "@ethersproject/rlp": "npm:^5.8.0" + "@ethersproject/sha2": "npm:^5.8.0" + "@ethersproject/strings": "npm:^5.8.0" + "@ethersproject/transactions": "npm:^5.8.0" + "@ethersproject/web": "npm:^5.8.0" bech32: "npm:1.1.4" - ws: "npm:7.4.6" - checksum: 10/8534a1896e61b9f0b66427a639df64a5fe76d0c08ec59b9f0cc64fdd1d0cc28d9fc3312838ae8d7817c8f5e2e76b7f228b689bc33d1cbb8e1b9517d4c4f678d8 + ws: "npm:8.18.0" + checksum: 10/7d40fc0abb78fc9e69b71cb560beb2a93cf1da2cf978a061031a34c0ed76c2f5936ed8c0bdb9aa1307fe5308d0159e429b83b779dbd550639a886a88d6d17817 languageName: node linkType: hard -"@ethersproject/random@npm:^5.7.0, @ethersproject/random@npm:^5.8.0": +"@ethersproject/random@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/random@npm:5.8.0" dependencies: @@ -1073,7 +1101,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/rlp@npm:^5.7.0, @ethersproject/rlp@npm:^5.8.0": +"@ethersproject/rlp@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/rlp@npm:5.8.0" dependencies: @@ -1083,7 +1111,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/sha2@npm:^5.7.0, @ethersproject/sha2@npm:^5.8.0": +"@ethersproject/sha2@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/sha2@npm:5.8.0" dependencies: @@ -1108,7 +1136,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/strings@npm:^5.7.0, @ethersproject/strings@npm:^5.8.0": +"@ethersproject/strings@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/strings@npm:5.8.0" dependencies: @@ -1119,7 +1147,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/transactions@npm:^5.7.0, @ethersproject/transactions@npm:^5.8.0": +"@ethersproject/transactions@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/transactions@npm:5.8.0" dependencies: @@ -1159,7 +1187,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/web@npm:^5.7.0, @ethersproject/web@npm:^5.8.0": +"@ethersproject/web@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/web@npm:5.8.0" dependencies: @@ -1185,18 +1213,34 @@ __metadata: languageName: node linkType: hard -"@firebase/analytics-compat@npm:0.2.17": - version: 0.2.17 - resolution: "@firebase/analytics-compat@npm:0.2.17" +"@firebase/ai@npm:1.4.1": + version: 1.4.1 + resolution: "@firebase/ai@npm:1.4.1" + dependencies: + "@firebase/app-check-interop-types": "npm:0.3.3" + "@firebase/component": "npm:0.6.18" + "@firebase/logger": "npm:0.4.4" + "@firebase/util": "npm:1.12.1" + tslib: "npm:^2.1.0" + peerDependencies: + "@firebase/app": 0.x + "@firebase/app-types": 0.x + checksum: 10/64b152365f3de9d12dc6691eebe673193a3a1034e9a2217c736a3b5d52e671f9cb61b35e85ecaf9a36c9667ce4c45fccaa4fc750b01fafcaeef757dc761ea971 + languageName: node + linkType: hard + +"@firebase/analytics-compat@npm:0.2.23": + version: 0.2.23 + resolution: "@firebase/analytics-compat@npm:0.2.23" dependencies: - "@firebase/analytics": "npm:0.10.11" + "@firebase/analytics": "npm:0.10.17" "@firebase/analytics-types": "npm:0.8.3" - "@firebase/component": "npm:0.6.12" - "@firebase/util": "npm:1.10.3" + "@firebase/component": "npm:0.6.18" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app-compat": 0.x - checksum: 10/3b048b41e0405a3975050f5d55afa923263ba3768d7b1b635d70892504cac03bd0bcf353b44819959dc6de7c04f1df818e34cec705c8ce18cf5c0866abe277b9 + checksum: 10/17414002039df8cfb5f1ed320b60b9d369ef2e9833cb4a4c485afff3ebad520e33aebda628556e940f5a2ad4741d56f58d3eaf754d1811dbd5fec9ed48a27fec languageName: node linkType: hard @@ -1207,34 +1251,34 @@ __metadata: languageName: node linkType: hard -"@firebase/analytics@npm:0.10.11": - version: 0.10.11 - resolution: "@firebase/analytics@npm:0.10.11" +"@firebase/analytics@npm:0.10.17": + version: 0.10.17 + resolution: "@firebase/analytics@npm:0.10.17" dependencies: - "@firebase/component": "npm:0.6.12" - "@firebase/installations": "npm:0.6.12" + "@firebase/component": "npm:0.6.18" + "@firebase/installations": "npm:0.6.18" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app": 0.x - checksum: 10/804083f61ffc57dabeb7a1b49e16f86969d1b2a37fafc23633c90324768ab849e52324b6a10928d789e038ec2f5d93248717f18d5f0d2a4b916850b86051c214 + checksum: 10/689c9e8ce0f86c606c1c8ffc1c44cee84c9eb0c767fdf8ef8ccc138515a81071011d958aa06f35a8fc6cdff8050d3e91cb559aebc42fa944ab79ffab2b8dc1d4 languageName: node linkType: hard -"@firebase/app-check-compat@npm:0.3.18": - version: 0.3.18 - resolution: "@firebase/app-check-compat@npm:0.3.18" +"@firebase/app-check-compat@npm:0.3.26": + version: 0.3.26 + resolution: "@firebase/app-check-compat@npm:0.3.26" dependencies: - "@firebase/app-check": "npm:0.8.11" + "@firebase/app-check": "npm:0.10.1" "@firebase/app-check-types": "npm:0.5.3" - "@firebase/component": "npm:0.6.12" + "@firebase/component": "npm:0.6.18" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app-compat": 0.x - checksum: 10/24b103fc309fa66d9830614c69bdf62810ecf0b77ad4fc9f318e05361a686cc3a684d84bddbd6afddc6a641739ead93ab1e8c28a75ed915750602b371aeb9b32 + checksum: 10/679cefa70e2c9b448e4c494a7e87f032b804777b0a4dde403ebdb9a1b3b2087e6d3248f3265a0083b32b24fbfd960b12ba171dd762f783a64fd47e0088583fa8 languageName: node linkType: hard @@ -1252,30 +1296,30 @@ __metadata: languageName: node linkType: hard -"@firebase/app-check@npm:0.8.11": - version: 0.8.11 - resolution: "@firebase/app-check@npm:0.8.11" +"@firebase/app-check@npm:0.10.1": + version: 0.10.1 + resolution: "@firebase/app-check@npm:0.10.1" dependencies: - "@firebase/component": "npm:0.6.12" + "@firebase/component": "npm:0.6.18" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app": 0.x - checksum: 10/e3f6a3940037c17a2faaf97a700d33b2c7821e07460e0a854d9f542acdcb589514bb4699df3adba1fb1d17ee75261006939b8ef60ec44bbe6c8c827b0797aa77 + checksum: 10/b10d72aa267799344a8f11539b427db27edfdcd9fd9810b94b54c980c509fe91af5cf2ca491c8aa28d312d72e27f162377bd0acd4ada28152c152a9b304209ba languageName: node linkType: hard -"@firebase/app-compat@npm:0.2.48": - version: 0.2.48 - resolution: "@firebase/app-compat@npm:0.2.48" +"@firebase/app-compat@npm:0.4.2": + version: 0.4.2 + resolution: "@firebase/app-compat@npm:0.4.2" dependencies: - "@firebase/app": "npm:0.10.18" - "@firebase/component": "npm:0.6.12" + "@firebase/app": "npm:0.13.2" + "@firebase/component": "npm:0.6.18" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" - checksum: 10/b74598b960ebb0a773b04e04d45dd59dbc8e09d1ae46c8ee7fd950632c95d357e8edab353df7032b798f2613884c96f3201eb5fbcdbfba67cb23757d66e63586 + checksum: 10/07547051fbd4164547f208907493db37c41d418e03436d1058dfcbaa4850125f937247edc5a0c29c661cbbc532357c9cde936ccb113ba5ca71c7544be88b3c00 languageName: node linkType: hard @@ -1286,31 +1330,31 @@ __metadata: languageName: node linkType: hard -"@firebase/app@npm:0.10.18": - version: 0.10.18 - resolution: "@firebase/app@npm:0.10.18" +"@firebase/app@npm:0.13.2": + version: 0.13.2 + resolution: "@firebase/app@npm:0.13.2" dependencies: - "@firebase/component": "npm:0.6.12" + "@firebase/component": "npm:0.6.18" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" idb: "npm:7.1.1" tslib: "npm:^2.1.0" - checksum: 10/ac215e594d66e933207263c4c11ff585ba3843a0e73ab6f02c85f504f7b5e166f407a9bef299f5a91893840c7f5c8978895c0f6103b361fb188c1cfdb8c35030 + checksum: 10/74ab96561490da7d0bd46be5bb04d43edb65aaf96e6c9b17a7bda15d43a299b8204908e14e1fc29d690cff5a59345cc9e4a598ec99b46a22c1416f304875bc5e languageName: node linkType: hard -"@firebase/auth-compat@npm:0.5.17": - version: 0.5.17 - resolution: "@firebase/auth-compat@npm:0.5.17" +"@firebase/auth-compat@npm:0.5.28": + version: 0.5.28 + resolution: "@firebase/auth-compat@npm:0.5.28" dependencies: - "@firebase/auth": "npm:1.8.2" - "@firebase/auth-types": "npm:0.12.3" - "@firebase/component": "npm:0.6.12" - "@firebase/util": "npm:1.10.3" + "@firebase/auth": "npm:1.10.8" + "@firebase/auth-types": "npm:0.13.0" + "@firebase/component": "npm:0.6.18" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app-compat": 0.x - checksum: 10/4c6d0fa6f76c398872627f49c427c810269c0284bdca1acddf82b154c9cda7131e8acecd961c2e0947f0340428b67349b7f9471bb1bd75bd82839ce89879ccad + checksum: 10/df87c841e8ce44510927df1f5d6387787cc9ca7119a72436e1960f08fb8a96f11caf0dd71f947062bac78c104fb9afa7c04e5ef5dfa343a08c4609fb4b9deabd languageName: node linkType: hard @@ -1321,23 +1365,23 @@ __metadata: languageName: node linkType: hard -"@firebase/auth-types@npm:0.12.3": - version: 0.12.3 - resolution: "@firebase/auth-types@npm:0.12.3" +"@firebase/auth-types@npm:0.13.0": + version: 0.13.0 + resolution: "@firebase/auth-types@npm:0.13.0" peerDependencies: "@firebase/app-types": 0.x "@firebase/util": 1.x - checksum: 10/5eda88380e9b33a6c91b0f8dd6a581895c2770aa5b46b1928a006a74d35c6a310bfe737141ff013764a4e02815efa530f1576d674f09f905fbe3b14050dc7fce + checksum: 10/57d8e4b80e58d3a9e453b4676a29e3b0e548ca9f4c2b465137007bb5753e3bde2f6537f0be9779df17859ebc4e6b1b59c88215cdd59a32106391cf117072372d languageName: node linkType: hard -"@firebase/auth@npm:1.8.2": - version: 1.8.2 - resolution: "@firebase/auth@npm:1.8.2" +"@firebase/auth@npm:1.10.8": + version: 1.10.8 + resolution: "@firebase/auth@npm:1.10.8" dependencies: - "@firebase/component": "npm:0.6.12" + "@firebase/component": "npm:0.6.18" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app": 0.x @@ -1345,86 +1389,86 @@ __metadata: peerDependenciesMeta: "@react-native-async-storage/async-storage": optional: true - checksum: 10/8cfe5e6d78ea555f52bffad6e4b21824a30040fd52ffeb3d60edf0c122f0cbb66fc012e708f49473f045fa3064a4ac760e8bc6b24d5ccdf4ae7087b07da61247 + checksum: 10/c319d9c39a746317556c879e174bc8e0c4b6d3c72b8226ca3d6c6fc146387f0ad05cbe0b1d84c675a5b7cf6769fe5e696fbb140249c10f6b77586414642c0b39 languageName: node linkType: hard -"@firebase/component@npm:0.6.12": - version: 0.6.12 - resolution: "@firebase/component@npm:0.6.12" +"@firebase/component@npm:0.6.18": + version: 0.6.18 + resolution: "@firebase/component@npm:0.6.18" dependencies: - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" - checksum: 10/4dfd201d3709ef5eed477e13d399611a78a186ca8911846e24361f9848c3b4eecc14c295a8f78ec40c88816329fde0ba6cc30dce9a444fa43a619b7ea744f0dc + checksum: 10/cc50bd7fba3219c1dc8049cb3eee513ff76c13c9750588db3acc5d0bce98cdc7e546c227c7d7a21a96a1eb9366d20243d5770c4582fc967d2856235bf47a2023 languageName: node linkType: hard -"@firebase/data-connect@npm:0.2.0": - version: 0.2.0 - resolution: "@firebase/data-connect@npm:0.2.0" +"@firebase/data-connect@npm:0.3.10": + version: 0.3.10 + resolution: "@firebase/data-connect@npm:0.3.10" dependencies: "@firebase/auth-interop-types": "npm:0.2.4" - "@firebase/component": "npm:0.6.12" + "@firebase/component": "npm:0.6.18" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app": 0.x - checksum: 10/7ba5886bc69b0a42757539a3de417d550ca3359f495a3d8a3974e799a21fbcc2ea15393c00e183dcd01a845d42cad15a914345b4bed63bd401089861e92b1b35 + checksum: 10/22ca29b05ef868355b5744ba895bd4df7225f21c22a2f60147096d9f4fb7c68985cd7949d7674bf481a7a135b0a52355bc997eacdd1c29b99e3f236b4e4ea676 languageName: node linkType: hard -"@firebase/database-compat@npm:2.0.2": - version: 2.0.2 - resolution: "@firebase/database-compat@npm:2.0.2" +"@firebase/database-compat@npm:2.0.11": + version: 2.0.11 + resolution: "@firebase/database-compat@npm:2.0.11" dependencies: - "@firebase/component": "npm:0.6.12" - "@firebase/database": "npm:1.0.11" - "@firebase/database-types": "npm:1.0.8" + "@firebase/component": "npm:0.6.18" + "@firebase/database": "npm:1.0.20" + "@firebase/database-types": "npm:1.0.15" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" - checksum: 10/5a341662c32f08f248ce9e8cecb940169f618c42a5a85de72247f13ffa32d5ca0a5619d0330f6ff8c7e1ea6952733534531e03e53e2746732bcfc6e851c031b3 + checksum: 10/fc85067ffbb3bf789353465e8f79b05d34a563cde909fc3057bcbdee002e07e26b99eba049f41c79385c71217db1d1207591415545a7b42e54318dc869bff7f2 languageName: node linkType: hard -"@firebase/database-types@npm:1.0.8": - version: 1.0.8 - resolution: "@firebase/database-types@npm:1.0.8" +"@firebase/database-types@npm:1.0.15": + version: 1.0.15 + resolution: "@firebase/database-types@npm:1.0.15" dependencies: "@firebase/app-types": "npm:0.9.3" - "@firebase/util": "npm:1.10.3" - checksum: 10/1b5483de082ff8d7551b21f087ba2f237bcd38ca9e3f48b1377b96213718e0a206437fe31a4e055c1b90d05a1f38f89fe1c92d50d907ca06c8727c73fc521c40 + "@firebase/util": "npm:1.12.1" + checksum: 10/b9e2ef2d4c51fa518e7ace10e990d8b0f449dc669537b6fe57dc2beca64c658703e7b06272ad5b0935f094f65abe870ef34793ee205aa6559f5404b886c835e6 languageName: node linkType: hard -"@firebase/database@npm:1.0.11": - version: 1.0.11 - resolution: "@firebase/database@npm:1.0.11" +"@firebase/database@npm:1.0.20": + version: 1.0.20 + resolution: "@firebase/database@npm:1.0.20" dependencies: "@firebase/app-check-interop-types": "npm:0.3.3" "@firebase/auth-interop-types": "npm:0.2.4" - "@firebase/component": "npm:0.6.12" + "@firebase/component": "npm:0.6.18" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" faye-websocket: "npm:0.11.4" tslib: "npm:^2.1.0" - checksum: 10/8df5c54a6e88ecd2f71fe5bf156d23132c92f698210e23f27144dd871ea518e2268dc0eac91152091c8b75dbdf66d18c0ca623e80d1d3a69af5a3ed956a26e59 + checksum: 10/337189b26ef27bfb31244ef230f4b3c26797dfd3c80004f5fac256ec276783c90ee3b78a4b3efc5d7feb1afcfe817f739c212ea3a94126849a26a0b4a4134dd7 languageName: node linkType: hard -"@firebase/firestore-compat@npm:0.3.41": - version: 0.3.41 - resolution: "@firebase/firestore-compat@npm:0.3.41" +"@firebase/firestore-compat@npm:0.3.53": + version: 0.3.53 + resolution: "@firebase/firestore-compat@npm:0.3.53" dependencies: - "@firebase/component": "npm:0.6.12" - "@firebase/firestore": "npm:4.7.6" + "@firebase/component": "npm:0.6.18" + "@firebase/firestore": "npm:4.8.0" "@firebase/firestore-types": "npm:3.0.3" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app-compat": 0.x - checksum: 10/a719fc6bd1150b5b1653053e73709b2b2edddb6c2a9274a896f9b38a6a09e92d650dbb5df55aceaf23c413445a8beb18073b8726247df9aadbe13d175154fff1 + checksum: 10/4ec87a5b060bd7111b0eaadd34f6f73a5ab5d8464fabc7e6cbc4df86d228ae4cbdb72fd214e328f9b6e6cd8614b54a88a1cbd41a6d468f4861429b6399e7a5f3 languageName: node linkType: hard @@ -1438,35 +1482,35 @@ __metadata: languageName: node linkType: hard -"@firebase/firestore@npm:4.7.6": - version: 4.7.6 - resolution: "@firebase/firestore@npm:4.7.6" +"@firebase/firestore@npm:4.8.0": + version: 4.8.0 + resolution: "@firebase/firestore@npm:4.8.0" dependencies: - "@firebase/component": "npm:0.6.12" + "@firebase/component": "npm:0.6.18" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" "@firebase/webchannel-wrapper": "npm:1.0.3" "@grpc/grpc-js": "npm:~1.9.0" "@grpc/proto-loader": "npm:^0.7.8" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app": 0.x - checksum: 10/76e879675b34212af74e3d294458e254c3f547d4168a377074671317b3bcfc07acdff1e853bd1f139b8e4a767e91749f00ee00aa52d968c67f190fe490256151 + checksum: 10/201f5c4773bcf1e87aacf248b9ea902402665c27670503f1f17e2ef4602b4eca371288c9f504e88a6ac23f97df0af1aab5e107ddb86b95b7a62adcfe0974dbf7 languageName: node linkType: hard -"@firebase/functions-compat@npm:0.3.18": - version: 0.3.18 - resolution: "@firebase/functions-compat@npm:0.3.18" +"@firebase/functions-compat@npm:0.3.26": + version: 0.3.26 + resolution: "@firebase/functions-compat@npm:0.3.26" dependencies: - "@firebase/component": "npm:0.6.12" - "@firebase/functions": "npm:0.12.1" + "@firebase/component": "npm:0.6.18" + "@firebase/functions": "npm:0.12.9" "@firebase/functions-types": "npm:0.6.3" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app-compat": 0.x - checksum: 10/224132bbd592c73c717fb8b065a8e718d43c1f72d05135313fd19f7efd566164217d13e65bf6f142973bc35b29ff792c414610a9ddcd708601ddf718d739d3c9 + checksum: 10/42a0c5914bbb9dfdb1630acc6e7fd0c05cee0b5965df6325fb0bc34c591e8d12c45151b0edef3f56180bc3f0131ed2d33552d6a2428ac6929f717e5f485149e4 languageName: node linkType: hard @@ -1477,34 +1521,34 @@ __metadata: languageName: node linkType: hard -"@firebase/functions@npm:0.12.1": - version: 0.12.1 - resolution: "@firebase/functions@npm:0.12.1" +"@firebase/functions@npm:0.12.9": + version: 0.12.9 + resolution: "@firebase/functions@npm:0.12.9" dependencies: "@firebase/app-check-interop-types": "npm:0.3.3" "@firebase/auth-interop-types": "npm:0.2.4" - "@firebase/component": "npm:0.6.12" + "@firebase/component": "npm:0.6.18" "@firebase/messaging-interop-types": "npm:0.2.3" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app": 0.x - checksum: 10/db32ed6297a1f187062c772f3134f19849e3f1e55345838ebf2256555f1d65648c018ead208909bafd9620deba1191385f4223835cdad5c1c4e9567cb9244721 + checksum: 10/5646363243e07451c568d7b471a1c895a6b273d9cae168f70fa512a86916d85f9e2a73f9b378adef423a5e6b3af41cc2b5a8545458503f9956b1a5ebc93fd918 languageName: node linkType: hard -"@firebase/installations-compat@npm:0.2.12": - version: 0.2.12 - resolution: "@firebase/installations-compat@npm:0.2.12" +"@firebase/installations-compat@npm:0.2.18": + version: 0.2.18 + resolution: "@firebase/installations-compat@npm:0.2.18" dependencies: - "@firebase/component": "npm:0.6.12" - "@firebase/installations": "npm:0.6.12" + "@firebase/component": "npm:0.6.18" + "@firebase/installations": "npm:0.6.18" "@firebase/installations-types": "npm:0.5.3" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app-compat": 0.x - checksum: 10/ffd5e08e65e7067c06a4eb5601a09b017fce006b38108c10c412df8144e79bd08b4347998740425f312288b5a0839818e634486875857df5518c05a737c46ad8 + checksum: 10/5f5adc8384dcc6e1cee0c1f2e162134a38d3aac7a4152e5ee512da06174d79957c27bc49798dc79b28b668a233fb0b8eafb8d8dcd90c077357383329e7acf8a0 languageName: node linkType: hard @@ -1517,17 +1561,17 @@ __metadata: languageName: node linkType: hard -"@firebase/installations@npm:0.6.12": - version: 0.6.12 - resolution: "@firebase/installations@npm:0.6.12" +"@firebase/installations@npm:0.6.18": + version: 0.6.18 + resolution: "@firebase/installations@npm:0.6.18" dependencies: - "@firebase/component": "npm:0.6.12" - "@firebase/util": "npm:1.10.3" + "@firebase/component": "npm:0.6.18" + "@firebase/util": "npm:1.12.1" idb: "npm:7.1.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app": 0.x - checksum: 10/093295de087b4c9287d06243eb19814e25674047aafa4f5db9a222d8e64283d0362f37edf8cfbe882a80eac1d2d9fc52b821fbb01151ac925f023765251dd1de + checksum: 10/70d9036c6aa9c5ed79d1e66221ab38badbdcc2ff745d0bba4bede2d857c50e5678da6bea8862f8c31a74cb924778f6d0916286c4e5a9cb851decea3884ad6f56 languageName: node linkType: hard @@ -1540,17 +1584,17 @@ __metadata: languageName: node linkType: hard -"@firebase/messaging-compat@npm:0.2.16": - version: 0.2.16 - resolution: "@firebase/messaging-compat@npm:0.2.16" +"@firebase/messaging-compat@npm:0.2.22": + version: 0.2.22 + resolution: "@firebase/messaging-compat@npm:0.2.22" dependencies: - "@firebase/component": "npm:0.6.12" - "@firebase/messaging": "npm:0.12.16" - "@firebase/util": "npm:1.10.3" + "@firebase/component": "npm:0.6.18" + "@firebase/messaging": "npm:0.12.22" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app-compat": 0.x - checksum: 10/1887599e3f7d7db5a70f923118eda769130aa134c6a6ba0a9f599c541d78b2e00b9548fc51c12f430c60a6e902221fe951a4beeddd674f1c042ffa32d1593dc9 + checksum: 10/67f266689f6889fa169188e276d483f546565ee895481ba890a549bc27977a1ef08066a320c3099b77cc695086c9f5f2d90a4b7d9a2e0e4293de01397b38c956 languageName: node linkType: hard @@ -1561,35 +1605,35 @@ __metadata: languageName: node linkType: hard -"@firebase/messaging@npm:0.12.16": - version: 0.12.16 - resolution: "@firebase/messaging@npm:0.12.16" +"@firebase/messaging@npm:0.12.22": + version: 0.12.22 + resolution: "@firebase/messaging@npm:0.12.22" dependencies: - "@firebase/component": "npm:0.6.12" - "@firebase/installations": "npm:0.6.12" + "@firebase/component": "npm:0.6.18" + "@firebase/installations": "npm:0.6.18" "@firebase/messaging-interop-types": "npm:0.2.3" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" idb: "npm:7.1.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app": 0.x - checksum: 10/e237f35c4b179a521a6a37255fa719784ec73f30b76d179c059f21bf1e7ee6f907299c137a7b55496134dc5c3578d365c62b2e44988323edd3d96e5468f016d6 + checksum: 10/0639961d0cd695a44cb8f80a44a7e3d030a3746e6586db4a8d730623ac5d2a238d0a721fbd77cdaf3873f775881aee234e0e312c9bdcf70b65eb57be3ad5d58a languageName: node linkType: hard -"@firebase/performance-compat@npm:0.2.12": - version: 0.2.12 - resolution: "@firebase/performance-compat@npm:0.2.12" +"@firebase/performance-compat@npm:0.2.20": + version: 0.2.20 + resolution: "@firebase/performance-compat@npm:0.2.20" dependencies: - "@firebase/component": "npm:0.6.12" + "@firebase/component": "npm:0.6.18" "@firebase/logger": "npm:0.4.4" - "@firebase/performance": "npm:0.6.12" + "@firebase/performance": "npm:0.7.7" "@firebase/performance-types": "npm:0.2.3" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app-compat": 0.x - checksum: 10/c171273df3994da6687a8e02dd7f046cd749d80d18e1bc241e1e8fd55f4d05578bcdd3924153fbf7175da2a0b88dc8fb6e7de98afe72dd1a36e54f96e807dea1 + checksum: 10/5589470cfc1952a53fa81885b9d061eacab431f1875d858ff25632f2287d789d0d6641bd1c08f54c93681e58d37104acf895c07583898c6e9ec7184a03460ff3 languageName: node linkType: hard @@ -1600,34 +1644,35 @@ __metadata: languageName: node linkType: hard -"@firebase/performance@npm:0.6.12": - version: 0.6.12 - resolution: "@firebase/performance@npm:0.6.12" +"@firebase/performance@npm:0.7.7": + version: 0.7.7 + resolution: "@firebase/performance@npm:0.7.7" dependencies: - "@firebase/component": "npm:0.6.12" - "@firebase/installations": "npm:0.6.12" + "@firebase/component": "npm:0.6.18" + "@firebase/installations": "npm:0.6.18" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" + web-vitals: "npm:^4.2.4" peerDependencies: "@firebase/app": 0.x - checksum: 10/68f802e2a1f0add51e2346049957487561d1f59f9ea57f8447d7ba771210aee875aaa144d7db56bb376bac3509d800e917e6c3560e3dbf19bdc60c6e1bc67766 + checksum: 10/c4ad40b795966cecec89de66f4da76b750215cd4c859fda84db00c3a11b0633749873ac71d2c2dee307239cfdf9e5d1f1e83ef54061f9f03995df4cddc724319 languageName: node linkType: hard -"@firebase/remote-config-compat@npm:0.2.12": - version: 0.2.12 - resolution: "@firebase/remote-config-compat@npm:0.2.12" +"@firebase/remote-config-compat@npm:0.2.18": + version: 0.2.18 + resolution: "@firebase/remote-config-compat@npm:0.2.18" dependencies: - "@firebase/component": "npm:0.6.12" + "@firebase/component": "npm:0.6.18" "@firebase/logger": "npm:0.4.4" - "@firebase/remote-config": "npm:0.5.0" + "@firebase/remote-config": "npm:0.6.5" "@firebase/remote-config-types": "npm:0.4.0" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app-compat": 0.x - checksum: 10/931c4739c2b11b2719076630f09f5aa18f9edf8e89cf35c9b9a3a8cc5afc497c86e68cca165e1416afcb0b8040ed04363c676d31118fdcf4bf3823ef9172785c + checksum: 10/ba4311b295a35bfa27628698cf06b46d8debaa2e0a0dae147baa28f72340809e94132eaa793df3fd3973b00b6713cc89ccaf4bd33f6c5bcd1f68064f35a563f2 languageName: node linkType: hard @@ -1638,33 +1683,33 @@ __metadata: languageName: node linkType: hard -"@firebase/remote-config@npm:0.5.0": - version: 0.5.0 - resolution: "@firebase/remote-config@npm:0.5.0" +"@firebase/remote-config@npm:0.6.5": + version: 0.6.5 + resolution: "@firebase/remote-config@npm:0.6.5" dependencies: - "@firebase/component": "npm:0.6.12" - "@firebase/installations": "npm:0.6.12" + "@firebase/component": "npm:0.6.18" + "@firebase/installations": "npm:0.6.18" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app": 0.x - checksum: 10/58a6fad255d3975700e65d4d19ec3360703f920bcbd3bd2ff21f239367af7405bfec5fddf3f800fb405dd4e4456f73cdf0c5cbf624a9512d77293f7cf14b64d8 + checksum: 10/50e14afd65f9f4abb2dc3a268b3b82e522a9591123a1154b42a157228b71c661d7a7b77c81a3de59eec38c6ee278d5479516114f8d0e46162959e7af52bd6e2e languageName: node linkType: hard -"@firebase/storage-compat@npm:0.3.15": - version: 0.3.15 - resolution: "@firebase/storage-compat@npm:0.3.15" +"@firebase/storage-compat@npm:0.3.24": + version: 0.3.24 + resolution: "@firebase/storage-compat@npm:0.3.24" dependencies: - "@firebase/component": "npm:0.6.12" - "@firebase/storage": "npm:0.13.5" + "@firebase/component": "npm:0.6.18" + "@firebase/storage": "npm:0.13.14" "@firebase/storage-types": "npm:0.8.3" - "@firebase/util": "npm:1.10.3" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app-compat": 0.x - checksum: 10/a4a4c64c44ea914a9509061ec373f33278f7096a547e7a9ed55c9100562bd688ca4f14f15eb3a798d5075b0e18dc15801bb95b23eddb2da600d855ee6c69e745 + checksum: 10/5445c8165d3732e31b77ca616497f930ed17c70d45202709907a38e82605d96df083fd5682b0c1fb6b34e71cebae9f8aa084abe81fd80e362ef80410fefcd508 languageName: node linkType: hard @@ -1678,41 +1723,25 @@ __metadata: languageName: node linkType: hard -"@firebase/storage@npm:0.13.5": - version: 0.13.5 - resolution: "@firebase/storage@npm:0.13.5" +"@firebase/storage@npm:0.13.14": + version: 0.13.14 + resolution: "@firebase/storage@npm:0.13.14" dependencies: - "@firebase/component": "npm:0.6.12" - "@firebase/util": "npm:1.10.3" + "@firebase/component": "npm:0.6.18" + "@firebase/util": "npm:1.12.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app": 0.x - checksum: 10/89acbd41d3ed9bffe7a37e293b0dc572622c196665db2821d76690ee205397f3f331666c24b5c63c14caaadb3e519b3489400a6c5387e78d4fe0c97fe75128a9 - languageName: node - linkType: hard - -"@firebase/util@npm:1.10.3": - version: 1.10.3 - resolution: "@firebase/util@npm:1.10.3" - dependencies: - tslib: "npm:^2.1.0" - checksum: 10/8e5e1664a09798348abfa0cd138157943f8ee9c6e3804e6cb1dcff004b351a03f14f4b2711338133bb89f7f824546664af2c2aa98e229becbc9294cdddeecc99 + checksum: 10/e107960285ea7b0405e152e0da236c508d0b2b43f87a17accfd3fda5ea8b2d5fdad6a78a18b5e11b55817468afa3531b608bbb15ab83c54d3535aecd5a1e4ebd languageName: node linkType: hard -"@firebase/vertexai@npm:1.0.3": - version: 1.0.3 - resolution: "@firebase/vertexai@npm:1.0.3" +"@firebase/util@npm:1.12.1": + version: 1.12.1 + resolution: "@firebase/util@npm:1.12.1" dependencies: - "@firebase/app-check-interop-types": "npm:0.3.3" - "@firebase/component": "npm:0.6.12" - "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.10.3" tslib: "npm:^2.1.0" - peerDependencies: - "@firebase/app": 0.x - "@firebase/app-types": 0.x - checksum: 10/67b0ac231a547ac99bef3a549199fbaa67271fe93c1dc2af48bfebcf8ac1a7ea45bec6c633b8ac3ad28b089a6601e2b352c68c53065242dccac07a20a887d6cd + checksum: 10/31c608b4a614534366bec66dd699384467bf08b60b97801c33793025851f530cd1837ff00434aef49bfc1f35a1b38262ed0ac73d4393a3c4eab77dccb30a215f languageName: node linkType: hard @@ -1734,8 +1763,8 @@ __metadata: linkType: hard "@grpc/proto-loader@npm:^0.7.8": - version: 0.7.13 - resolution: "@grpc/proto-loader@npm:0.7.13" + version: 0.7.15 + resolution: "@grpc/proto-loader@npm:0.7.15" dependencies: lodash.camelcase: "npm:^4.3.0" long: "npm:^5.0.0" @@ -1743,7 +1772,7 @@ __metadata: yargs: "npm:^17.7.2" bin: proto-loader-gen-types: build/bin/proto-loader-gen-types.js - checksum: 10/7e2d842c2061cbaf6450c71da0077263be3bab165454d5c8a3e1ae4d3c6d2915f02fd27da63ff01f05e127b1221acd40705273f5d29303901e60514e852992f4 + checksum: 10/2e2b33ace8bc34211522751a9e654faf9ac997577a9e9291b1619b4c05d7878a74d2101c3bc43b2b2b92bca7509001678fb191d4eb100684cc2910d66f36c373 languageName: node linkType: hard @@ -1755,12 +1784,12 @@ __metadata: linkType: hard "@humanfs/node@npm:^0.16.6": - version: 0.16.6 - resolution: "@humanfs/node@npm:0.16.6" + version: 0.16.7 + resolution: "@humanfs/node@npm:0.16.7" dependencies: "@humanfs/core": "npm:^0.19.1" - "@humanwhocodes/retry": "npm:^0.3.0" - checksum: 10/6d43c6727463772d05610aa05c83dab2bfbe78291022ee7a92cb50999910b8c720c76cc312822e2dea2b497aa1b3fef5fe9f68803fc45c9d4ed105874a65e339 + "@humanwhocodes/retry": "npm:^0.4.0" + checksum: 10/b3633d3dce898592cac515ba5e6693c78e6be92863541d3eaf2c009b10f52b2fa62ff6e6e06f240f2447ddbe7b5f1890bc34e9308470675c876eee207553a08d languageName: node linkType: hard @@ -1771,14 +1800,7 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/retry@npm:^0.3.0": - version: 0.3.1 - resolution: "@humanwhocodes/retry@npm:0.3.1" - checksum: 10/eb457f699529de7f07649679ec9e0353055eebe443c2efe71c6dd950258892475a038e13c6a8c5e13ed1fb538cdd0a8794faa96b24b6ffc4c87fb1fc9f70ad7f - languageName: node - linkType: hard - -"@humanwhocodes/retry@npm:^0.4.2": +"@humanwhocodes/retry@npm:^0.4.0, @humanwhocodes/retry@npm:^0.4.2": version: 0.4.3 resolution: "@humanwhocodes/retry@npm:0.4.3" checksum: 10/0b32cfd362bea7a30fbf80bb38dcaf77fee9c2cae477ee80b460871d03590110ac9c77d654f04ec5beaf71b6f6a89851bdf6c1e34ccdf2f686bd86fcd97d9e61 @@ -1921,6 +1943,13 @@ __metadata: languageName: node linkType: hard +"@jest/diff-sequences@npm:30.0.1": + version: 30.0.1 + resolution: "@jest/diff-sequences@npm:30.0.1" + checksum: 10/0ddb7c7ba92d6057a2ee51a9cfc2155b77cca707fe959167466ea02dcb0687018cc3c22b9622f25f3a417d6ad370e2d4dcfedf9f1410dc9c02954a7484423cc7 + languageName: node + linkType: hard + "@jest/environment@npm:^29.7.0": version: 29.7.0 resolution: "@jest/environment@npm:29.7.0" @@ -1933,6 +1962,15 @@ __metadata: languageName: node linkType: hard +"@jest/expect-utils@npm:30.2.0": + version: 30.2.0 + resolution: "@jest/expect-utils@npm:30.2.0" + dependencies: + "@jest/get-type": "npm:30.1.0" + checksum: 10/f2442f1bceb3411240d0f16fd0074377211b4373d3b8b2dc28929e861b6527a6deb403a362c25afa511d933cda4dfbdc98d4a08eeb51ee4968f7cb0299562349 + languageName: node + linkType: hard + "@jest/expect-utils@npm:^29.7.0": version: 29.7.0 resolution: "@jest/expect-utils@npm:29.7.0" @@ -1966,6 +2004,13 @@ __metadata: languageName: node linkType: hard +"@jest/get-type@npm:30.1.0": + version: 30.1.0 + resolution: "@jest/get-type@npm:30.1.0" + checksum: 10/e2a95fbb49ce2d15547db8af5602626caf9b05f62a5e583b4a2de9bd93a2bfe7175f9bbb2b8a5c3909ce261d467b6991d7265bb1d547cb60e7e97f571f361a70 + languageName: node + linkType: hard + "@jest/globals@npm:^29.7.0": version: 29.7.0 resolution: "@jest/globals@npm:29.7.0" @@ -1978,6 +2023,16 @@ __metadata: languageName: node linkType: hard +"@jest/pattern@npm:30.0.1": + version: 30.0.1 + resolution: "@jest/pattern@npm:30.0.1" + dependencies: + "@types/node": "npm:*" + jest-regex-util: "npm:30.0.1" + checksum: 10/afd03b4d3eadc9c9970cf924955dee47984a7e767901fe6fa463b17b246f0ddeec07b3e82c09715c54bde3c8abb92074160c0d79967bd23778724f184e7f5b7b + languageName: node + linkType: hard + "@jest/reporters@npm:^29.7.0": version: 29.7.0 resolution: "@jest/reporters@npm:29.7.0" @@ -2015,6 +2070,15 @@ __metadata: languageName: node linkType: hard +"@jest/schemas@npm:30.0.5": + version: 30.0.5 + resolution: "@jest/schemas@npm:30.0.5" + dependencies: + "@sinclair/typebox": "npm:^0.34.0" + checksum: 10/40df4db55d4aeed09d1c7e19caf23788309cea34490a1c5d584c913494195e698b9967e996afc27226cac6d76e7512fe73ae6b9584480695c60dd18a5459cdba + languageName: node + linkType: hard + "@jest/schemas@npm:^29.6.3": version: 29.6.3 resolution: "@jest/schemas@npm:29.6.3" @@ -2082,6 +2146,21 @@ __metadata: languageName: node linkType: hard +"@jest/types@npm:30.2.0": + version: 30.2.0 + resolution: "@jest/types@npm:30.2.0" + dependencies: + "@jest/pattern": "npm:30.0.1" + "@jest/schemas": "npm:30.0.5" + "@types/istanbul-lib-coverage": "npm:^2.0.6" + "@types/istanbul-reports": "npm:^3.0.4" + "@types/node": "npm:*" + "@types/yargs": "npm:^17.0.33" + chalk: "npm:^4.1.2" + checksum: 10/f50fcaea56f873a51d19254ab16762f2ea8ca88e3e08da2e496af5da2b67c322915a4fcd0153803cc05063ffe87ebef2ab4330e0a1b06ab984a26c916cbfc26b + languageName: node + linkType: hard + "@jest/types@npm:^26.6.2": version: 26.6.2 resolution: "@jest/types@npm:26.6.2" @@ -2136,10 +2215,10 @@ __metadata: languageName: node linkType: hard -"@jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.5.0": - version: 1.5.0 - resolution: "@jridgewell/sourcemap-codec@npm:1.5.0" - checksum: 10/4ed6123217569a1484419ac53f6ea0d9f3b57e5b57ab30d7c267bdb27792a27eb0e4b08e84a2680aa55cc2f2b411ffd6ec3db01c44fdc6dc43aca4b55f8374fd +"@jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.5.0, @jridgewell/sourcemap-codec@npm:^1.5.5": + version: 1.5.5 + resolution: "@jridgewell/sourcemap-codec@npm:1.5.5" + checksum: 10/5d9d207b462c11e322d71911e55e21a4e2772f71ffe8d6f1221b8eb5ae6774458c1d242f897fb0814e8714ca9a6b498abfa74dfe4f434493342902b1a48b33a5 languageName: node linkType: hard @@ -2179,9 +2258,9 @@ __metadata: linkType: hard "@json-schema-tools/meta-schema@npm:^1.7.5": - version: 1.7.5 - resolution: "@json-schema-tools/meta-schema@npm:1.7.5" - checksum: 10/707dc3a285c26c37d00f418e9d0ef8a2ad1c23d4936ad5aab0ce94c9ae36a7a6125c4ca5048513af64b7e6e527b5472a1701d1f709c379acdd7ad12f6409d2cd + version: 1.8.0 + resolution: "@json-schema-tools/meta-schema@npm:1.8.0" + checksum: 10/c6c9c3e6504299126c65bcf4bb7e6d28bfe5ab46d3c4fdc9b856204581edb0f088b15e790759e6357e91468d8a5213192fbe9b027a4811b988c19bbbb8d8f617 languageName: node linkType: hard @@ -2196,44 +2275,43 @@ __metadata: linkType: hard "@json-schema-tools/traverse@npm:^1.10.4": - version: 1.10.4 - resolution: "@json-schema-tools/traverse@npm:1.10.4" - checksum: 10/0027bc90df01c5eeee0833e722b7320b53be8b5ce3f4e0e4a6e45713a38e6f88f21aba31e3dd973093ef75cd21a40c07fe8f112da8f49a7919b1c0e44c904d20 + version: 1.11.0 + resolution: "@json-schema-tools/traverse@npm:1.11.0" + checksum: 10/1dd81baf29fd6de164f30376d2b9ca9e68778255a872dd78f81cf6f610127e9f4eba2507244c35189078839ed4aa453a876c169681eb9028954c0148355c2fcb languageName: node linkType: hard -"@lavamoat/aa@npm:^4.3.0": - version: 4.3.0 - resolution: "@lavamoat/aa@npm:4.3.0" +"@lavamoat/aa@npm:^4.3.6": + version: 4.3.6 + resolution: "@lavamoat/aa@npm:4.3.6" dependencies: - resolve: "npm:1.22.8" + resolve: "npm:1.22.10" bin: lavamoat-ls: src/cli.js - checksum: 10/c6c24ea88194ad06a83cc2a9e0b6918ee41ab40abcc5c889e1a33f214e48eb160dd0c4cea7b0e299f86d472810ef80e7caf0b2600499222b108690516d9f8123 + checksum: 10/6c6636962527054e5c25f801721c49c6b03c6173e86a7c048a8061f18f9c2c4628413cdfa1c928c8e028ac7128891d54f545fa61751c93e4689891393f0be3ec languageName: node linkType: hard "@lavamoat/allow-scripts@npm:^3.0.4": - version: 3.2.0 - resolution: "@lavamoat/allow-scripts@npm:3.2.0" + version: 3.4.3 + resolution: "@lavamoat/allow-scripts@npm:3.4.3" dependencies: - "@lavamoat/aa": "npm:^4.3.0" - "@npmcli/run-script": "npm:8.1.0" + "@lavamoat/aa": "npm:^4.3.6" + "@npmcli/run-script": "npm:10.0.3" bin-links: "npm:4.0.4" npm-normalize-package-bin: "npm:3.0.1" + type-fest: "npm:4.41.0" yargs: "npm:17.7.2" - peerDependencies: - "@lavamoat/preinstall-always-fail": "*" bin: allow-scripts: src/cli.js - checksum: 10/21afb11ce25c0b2c9763bfb8f1127bb89f304ed83f64e00955c4d3007216a0ee553b777359e9ded874c61b3d7fa8d19ff8a35881cd3816985adab4d6b58bcb07 + checksum: 10/75a6156efa5f76d97ddfd21cdeaf68f256fc5b1adc9be2bfa0691abd38c0c4769a511eda20d5a4700b05629423a26e02b3cbb84c3407c26d5287a19cf4630967 languageName: node linkType: hard "@lavamoat/preinstall-always-fail@npm:^2.1.0": - version: 2.1.0 - resolution: "@lavamoat/preinstall-always-fail@npm:2.1.0" - checksum: 10/385c3fac828b9edff2d8b5825bd29ea475206046984cdb3217518ad655f145ff37046414041534960d92cbe0759f0dc675f7c7dcf39a95003ae715a834fbd750 + version: 2.1.1 + resolution: "@lavamoat/preinstall-always-fail@npm:2.1.1" + checksum: 10/679cfd6b981326bf6f7cce63af4062b1e1e2ffaefd4db316e918ec41ac089c835aafd7f2bb5193cd25538e084d3df1375cd2ac5a52c3e7777aedeb2ee507dd29 languageName: node linkType: hard @@ -2677,8 +2755,8 @@ __metadata: linkType: hard "@metamask/auto-changelog@npm:^4.0.0": - version: 4.0.0 - resolution: "@metamask/auto-changelog@npm:4.0.0" + version: 4.1.0 + resolution: "@metamask/auto-changelog@npm:4.1.0" dependencies: diff: "npm:^5.0.0" execa: "npm:^5.1.1" @@ -2688,7 +2766,7 @@ __metadata: prettier: ">=3.0.0" bin: auto-changelog: dist/cli.js - checksum: 10/4968d316411e5f4820092391f79078839f49e0e26ecd0c48266b5a1e0e32614b75dad5f36b76e632a7a22a2f2eeeb762a693ae390b0373bff29081ff2a7eefda + checksum: 10/fe31a9eb364939c83bc5098482b761ca93593081680c4cba17b221150b4d32636cb25fd708e3692c198feddc95d8bcf524e19fa93567fb5aa30b03ea93249250 languageName: node linkType: hard @@ -3381,17 +3459,20 @@ __metadata: linkType: soft "@metamask/eth-hd-keyring@npm:^13.0.0": - version: 13.0.0 - resolution: "@metamask/eth-hd-keyring@npm:13.0.0" + version: 13.1.0 + resolution: "@metamask/eth-hd-keyring@npm:13.1.0" dependencies: + "@ethereumjs/tx": "npm:^5.4.0" "@ethereumjs/util": "npm:^9.1.0" "@metamask/eth-sig-util": "npm:^8.2.0" "@metamask/key-tree": "npm:^10.0.2" + "@metamask/keyring-api": "npm:^21.3.0" "@metamask/keyring-utils": "npm:^3.1.0" "@metamask/scure-bip39": "npm:^2.1.1" + "@metamask/superstruct": "npm:^3.1.0" "@metamask/utils": "npm:^11.1.0" ethereum-cryptography: "npm:^2.1.2" - checksum: 10/fe955a4e0331090df8110dbd8f46ea6286c2ad20e6677ecf535361ea9d0008194b2043eddd692cd7ceac2e033a54e4e340caa7d302bd5211826cb252b526f6bc + checksum: 10/7d67c29c6387ffe871995e67e4802b9a6f6eb2f14b556e43690509b342ef66b72765477b27e4b669fe8a00606e219e00991f94da3a74fcedcf339ab765215ae6 languageName: node linkType: hard @@ -3842,7 +3923,7 @@ __metadata: languageName: node linkType: hard -"@metamask/keyring-api@npm:^21.4.0, @metamask/keyring-api@npm:^21.5.0": +"@metamask/keyring-api@npm:^21.3.0, @metamask/keyring-api@npm:^21.4.0, @metamask/keyring-api@npm:^21.5.0": version: 21.5.0 resolution: "@metamask/keyring-api@npm:21.5.0" dependencies: @@ -4267,14 +4348,12 @@ __metadata: linkType: soft "@metamask/nonce-tracker@npm:^6.0.0": - version: 6.0.0 - resolution: "@metamask/nonce-tracker@npm:6.0.0" + version: 6.1.0 + resolution: "@metamask/nonce-tracker@npm:6.1.0" dependencies: "@ethersproject/providers": "npm:^5.7.2" - async-mutex: "npm:^0.3.1" - peerDependencies: - "@metamask/eth-block-tracker": ">=9" - checksum: 10/e62edd38eeaba6d917bc3aed38017294f2bfdb59120a9fb4f093fe96a46d8d9214453a802fe782faaf4a007f4cd5f393607c70a2ff8479ecd7ef18827cad067a + async-mutex: "npm:^0.5.0" + checksum: 10/a20cf7084348ef7bdcd9e57e873ca34bf8e04ee43a2ab08634a3ad47fddb632d0e170c1dff03b4ca5bac34a24c35c542fcec509f3c23ce483834082f41b50e4a languageName: node linkType: hard @@ -4652,9 +4731,9 @@ __metadata: linkType: hard "@metamask/safe-event-emitter@npm:^3.0.0, @metamask/safe-event-emitter@npm:^3.1.1": - version: 3.1.1 - resolution: "@metamask/safe-event-emitter@npm:3.1.1" - checksum: 10/e24db4d7c20764bfc5b025065f92518c805f0ffb1da4820078b8cff7dcae964c0f354cf053fcb7ac659de015d5ffdf21aae5e8d44e191ee8faa9066855f22653 + version: 3.1.2 + resolution: "@metamask/safe-event-emitter@npm:3.1.2" + checksum: 10/8ef7579f9317eb5c94ecf3e6abb8d13b119af274b678805eac76abe4c0667bfdf539f385e552bb973e96333b71b77aa7c787cb3fce9cd5fb4b00f1dbbabf880d languageName: node linkType: hard @@ -4809,7 +4888,7 @@ __metadata: languageName: unknown linkType: soft -"@metamask/slip44@npm:^4.3.0": +"@metamask/slip44@npm:^4.3.0, @metamask/slip44@npm:^4.4.0": version: 4.4.0 resolution: "@metamask/slip44@npm:4.4.0" checksum: 10/296ac7c578bd35792c7e3942a9a0b7d9d7af76cf98358b97403c1ed483faa3c2fe6c71b1c3f8c7719fbfcf9fc73e5fa8707c89ac277ee9ce6c8bc4c694b2059d @@ -4872,19 +4951,19 @@ __metadata: linkType: hard "@metamask/snaps-rpc-methods@npm:^14.1.1": - version: 14.2.0 - resolution: "@metamask/snaps-rpc-methods@npm:14.2.0" + version: 14.3.0 + resolution: "@metamask/snaps-rpc-methods@npm:14.3.0" dependencies: "@metamask/key-tree": "npm:^10.1.1" "@metamask/permission-controller": "npm:^12.2.0" "@metamask/rpc-errors": "npm:^7.0.3" "@metamask/snaps-sdk": "npm:^10.4.0" - "@metamask/snaps-utils": "npm:^12.0.0" + "@metamask/snaps-utils": "npm:^12.1.0" "@metamask/superstruct": "npm:^3.2.1" "@metamask/utils": "npm:^11.9.0" "@noble/hashes": "npm:^1.7.1" async-mutex: "npm:^0.5.0" - checksum: 10/36264d40ebcca8b7d40d766cfc5dffd4e2afa61ff3bc11ee52af3669043e4428c9845565e78315fb7cb0981efd5d26681244fb292d94c42b059f6a76fc527a26 + checksum: 10/feddc0820e9a18a5ebed5ebdd4ee771e68990427634b7a5719bbaf1955fb2deba8531d353b7db664b394b2b3a9e05baf734af6048b8ea009d2379fbce09f9889 languageName: node linkType: hard @@ -4933,9 +5012,9 @@ __metadata: languageName: node linkType: hard -"@metamask/snaps-utils@npm:^12.0.0": - version: 12.0.1 - resolution: "@metamask/snaps-utils@npm:12.0.1" +"@metamask/snaps-utils@npm:^12.1.0": + version: 12.1.0 + resolution: "@metamask/snaps-utils@npm:12.1.0" dependencies: "@babel/core": "npm:^7.23.2" "@babel/types": "npm:^7.23.0" @@ -4943,7 +5022,7 @@ __metadata: "@metamask/messenger": "npm:^0.3.0" "@metamask/permission-controller": "npm:^12.2.0" "@metamask/rpc-errors": "npm:^7.0.3" - "@metamask/slip44": "npm:^4.3.0" + "@metamask/slip44": "npm:^4.4.0" "@metamask/snaps-registry": "npm:^4.0.0" "@metamask/snaps-sdk": "npm:^10.4.0" "@metamask/superstruct": "npm:^3.2.1" @@ -4953,21 +5032,21 @@ __metadata: cron-parser: "npm:^4.5.0" fast-deep-equal: "npm:^3.1.3" fast-json-stable-stringify: "npm:^2.1.0" - fast-xml-parser: "npm:^4.4.1" + fast-xml-parser: "npm:^5.3.4" luxon: "npm:^3.5.0" marked: "npm:^12.0.1" rfdc: "npm:^1.3.0" semver: "npm:^7.5.4" ses: "npm:^1.14.0" validate-npm-package-name: "npm:^5.0.0" - checksum: 10/e4f4ee17b674025c3686ed3e0269643db46c737dab418ce1172a43aa227d66a58f857d2956e8956ea225be1bd23d1c1e101eb22e7bd09ae8a34ddafafd5b8a80 + checksum: 10/f81a66a0f0d7710f18cfcebceacf2ec7ca9c468a4839b8cc15652cc046a15455c55a3fff846061ff7d1ecd4368c182566db4f73b3c8b4ed4b2a09adc57e2e711 languageName: node linkType: hard "@metamask/stake-sdk@npm:^3.2.1": - version: 3.2.1 - resolution: "@metamask/stake-sdk@npm:3.2.1" - checksum: 10/7404ac54e2bd426158b0ae92a2f4c420ef551d18d8a14293c5760b1da1c48cab88df9a7dcce7133f91bbe7899f6c2016642f0e41e170353b6b9ae4c6423d2ad5 + version: 3.4.0 + resolution: "@metamask/stake-sdk@npm:3.4.0" + checksum: 10/32241bf7a904b0b12568467482b28f550eae1a4d97ffb7487a1cd1614d43f3b584d78dc96df72ece024a0402d3591c19d79f370a3955ea4b11369f000c309a08 languageName: node linkType: hard @@ -5174,8 +5253,8 @@ __metadata: linkType: soft "@metamask/utils@npm:^11.0.1, @metamask/utils@npm:^11.1.0, @metamask/utils@npm:^11.4.0, @metamask/utils@npm:^11.4.2, @metamask/utils@npm:^11.8.1, @metamask/utils@npm:^11.9.0": - version: 11.9.0 - resolution: "@metamask/utils@npm:11.9.0" + version: 11.10.0 + resolution: "@metamask/utils@npm:11.10.0" dependencies: "@ethereumjs/tx": "npm:^4.2.0" "@metamask/superstruct": "npm:^3.1.0" @@ -5188,7 +5267,7 @@ __metadata: pony-cause: "npm:^2.1.10" semver: "npm:^7.5.4" uuid: "npm:^9.0.1" - checksum: 10/f8f5e99ba6c6de0395ed4e0acc82ee9c0dca26991ea6a8f10b3896e72745790966a8eded8c42be905d9f01fa99c1fd29a7f68541e2ef9854fc14984a0b514ad3 + checksum: 10/691a268af66593b60e9807a069127993cea3cdc941f99d5d7ca4664868754f08945821f1787b2f3e99e4497df63ceb0af37a2419ad494da29a1fddffe94f5797 languageName: node linkType: hard @@ -5209,6 +5288,17 @@ __metadata: languageName: node linkType: hard +"@napi-rs/wasm-runtime@npm:^0.2.11": + version: 0.2.12 + resolution: "@napi-rs/wasm-runtime@npm:0.2.12" + dependencies: + "@emnapi/core": "npm:^1.4.3" + "@emnapi/runtime": "npm:^1.4.3" + "@tybys/wasm-util": "npm:^0.10.0" + checksum: 10/5fd518182427980c28bc724adf06c5f32f9a8915763ef560b5f7d73607d30cd15ac86d0cbd2eb80d4cfab23fc80d0876d89ca36a9daadcb864bc00917c94187c + languageName: node + linkType: hard + "@noble/ciphers@npm:^1.2.1, @noble/ciphers@npm:^1.3.0": version: 1.3.0 resolution: "@noble/ciphers@npm:1.3.0" @@ -5305,87 +5395,86 @@ __metadata: languageName: node linkType: hard -"@npmcli/agent@npm:^2.0.0": - version: 2.2.2 - resolution: "@npmcli/agent@npm:2.2.2" +"@npmcli/agent@npm:^4.0.0": + version: 4.0.0 + resolution: "@npmcli/agent@npm:4.0.0" dependencies: agent-base: "npm:^7.1.0" http-proxy-agent: "npm:^7.0.0" https-proxy-agent: "npm:^7.0.1" - lru-cache: "npm:^10.0.1" + lru-cache: "npm:^11.2.1" socks-proxy-agent: "npm:^8.0.3" - checksum: 10/96fc0036b101bae5032dc2a4cd832efb815ce9b33f9ee2f29909ee49d96a0026b3565f73c507a69eb8603f5cb32e0ae45a70cab1e2655990a4e06ae99f7f572a + checksum: 10/1a81573becc60515031accc696e6405e9b894e65c12b98ef4aeee03b5617c41948633159dbf6caf5dde5b47367eeb749bdc7b7dfb21960930a9060a935c6f636 languageName: node linkType: hard -"@npmcli/fs@npm:^3.1.0": - version: 3.1.1 - resolution: "@npmcli/fs@npm:3.1.1" +"@npmcli/fs@npm:^5.0.0": + version: 5.0.0 + resolution: "@npmcli/fs@npm:5.0.0" dependencies: semver: "npm:^7.3.5" - checksum: 10/1e0e04087049b24b38bc0b30d87a9388ee3ca1d3fdfc347c2f77d84fcfe6a51f250bc57ba2c1f614d7e4285c6c62bf8c769bc19aa0949ea39e5b043ee023b0bd + checksum: 10/4935c7719d17830d0f9fa46c50be17b2a3c945cec61760f6d0909bce47677c42e1810ca673305890f9e84f008ec4d8e841182f371e42100a8159d15f22249208 languageName: node linkType: hard -"@npmcli/git@npm:^5.0.0": - version: 5.0.8 - resolution: "@npmcli/git@npm:5.0.8" - dependencies: - "@npmcli/promise-spawn": "npm:^7.0.0" - ini: "npm:^4.1.3" - lru-cache: "npm:^10.0.1" - npm-pick-manifest: "npm:^9.0.0" - proc-log: "npm:^4.0.0" - promise-inflight: "npm:^1.0.1" +"@npmcli/git@npm:^7.0.0": + version: 7.0.1 + resolution: "@npmcli/git@npm:7.0.1" + dependencies: + "@npmcli/promise-spawn": "npm:^9.0.0" + ini: "npm:^6.0.0" + lru-cache: "npm:^11.2.1" + npm-pick-manifest: "npm:^11.0.1" + proc-log: "npm:^6.0.0" promise-retry: "npm:^2.0.1" semver: "npm:^7.3.5" - which: "npm:^4.0.0" - checksum: 10/e6f94175fb9dde13d84849b29b32ffb4c4df968822cc85df2aebfca13bf8ca76f33b1d281911f5bcddc95bccba2f9e795669c736a38de4d9c76efb5047ffb4fb + which: "npm:^6.0.0" + checksum: 10/dc2c7558fa034be6123b6a049091fd4fcdf79bf497ab8ff3213ac99e0c7a4f968e3cf747322af5d1d70e41ed21b8189f8e12d7b3f1a6143793d056dd8c8b50c5 languageName: node linkType: hard -"@npmcli/node-gyp@npm:^3.0.0": - version: 3.0.0 - resolution: "@npmcli/node-gyp@npm:3.0.0" - checksum: 10/dd9fed3e80df8fbb20443f28651a8ed7235f2c15286ecc010e2d3cd392c85912e59ef29218c0b02f098defb4cbc8cdf045aab1d32d5cef6ace289913196ed5df +"@npmcli/node-gyp@npm:^5.0.0": + version: 5.0.0 + resolution: "@npmcli/node-gyp@npm:5.0.0" + checksum: 10/31488b0a0a6293efc4ab1bd87ba483d1000f8720c5f068d4c28cf49e39a045cd122960ba2a166a376fc9767f457f6124d99ec673ebcb19015cd29835bb038e46 languageName: node linkType: hard -"@npmcli/package-json@npm:^5.0.0": - version: 5.2.0 - resolution: "@npmcli/package-json@npm:5.2.0" - dependencies: - "@npmcli/git": "npm:^5.0.0" - glob: "npm:^10.2.2" - hosted-git-info: "npm:^7.0.0" - json-parse-even-better-errors: "npm:^3.0.0" - normalize-package-data: "npm:^6.0.0" - proc-log: "npm:^4.0.0" +"@npmcli/package-json@npm:^7.0.0": + version: 7.0.5 + resolution: "@npmcli/package-json@npm:7.0.5" + dependencies: + "@npmcli/git": "npm:^7.0.0" + glob: "npm:^13.0.0" + hosted-git-info: "npm:^9.0.0" + json-parse-even-better-errors: "npm:^5.0.0" + proc-log: "npm:^6.0.0" semver: "npm:^7.5.3" - checksum: 10/c3d2218877bfc005bca3b7a11f53825bf16a68811b8e8ed0c9b219cceb8e8e646d70efab8c5d6decbd8007f286076468b3f456dab4d41d648aff73a5f3a6fce2 + spdx-expression-parse: "npm:^4.0.0" + checksum: 10/d07a5bb98f59675afa51c0a8ba1f32d7a459da36c14e2ad2b2dd6e312c99684fd3a76f5cc497376af588fc98a2be7d05651e5a58c8a282f12dcfed44c44338fa languageName: node linkType: hard -"@npmcli/promise-spawn@npm:^7.0.0": - version: 7.0.2 - resolution: "@npmcli/promise-spawn@npm:7.0.2" +"@npmcli/promise-spawn@npm:^9.0.0": + version: 9.0.1 + resolution: "@npmcli/promise-spawn@npm:9.0.1" dependencies: - which: "npm:^4.0.0" - checksum: 10/94cbbbeeb20342026c3b68fc8eb09e1600b7645d4e509f2588ef5ea7cff977eb01e628cc8e014595d04a6af4b4bc5c467c950a8135920f39f7c7b57fba43f4e9 + which: "npm:^6.0.0" + checksum: 10/93f539f12813dacf0084c5f444982d44c67f2016f417f2e937afb81c3fd228cf330abeabdffc95ca3e8315a4a9b9e732be7e7870c926d7dfc6c458549fcd11ea languageName: node linkType: hard -"@npmcli/run-script@npm:8.1.0": - version: 8.1.0 - resolution: "@npmcli/run-script@npm:8.1.0" +"@npmcli/run-script@npm:10.0.3": + version: 10.0.3 + resolution: "@npmcli/run-script@npm:10.0.3" dependencies: - "@npmcli/node-gyp": "npm:^3.0.0" - "@npmcli/package-json": "npm:^5.0.0" - "@npmcli/promise-spawn": "npm:^7.0.0" - node-gyp: "npm:^10.0.0" - proc-log: "npm:^4.0.0" - which: "npm:^4.0.0" - checksum: 10/256bd580f82b98db93e54065bf9bcc94946be4f2d668a062cf756cb8ea091f58ef7154b3d2450d79738081a150f25cc48f6075351911e672f24ffd34350f02f2 + "@npmcli/node-gyp": "npm:^5.0.0" + "@npmcli/package-json": "npm:^7.0.0" + "@npmcli/promise-spawn": "npm:^9.0.0" + node-gyp: "npm:^12.1.0" + proc-log: "npm:^6.0.0" + which: "npm:^6.0.0" + checksum: 10/3b2b6b02a40c7470a900e8d77d23e2239608c08e919d6ddee7849fc7093be0999d9eb2c9dec871988e80165a64f9d8c55430f0a699690e555ebd3e81bf1dbd35 languageName: node linkType: hard @@ -5397,20 +5486,28 @@ __metadata: linkType: hard "@open-rpc/schema-utils-js@npm:^2.0.5": - version: 2.0.5 - resolution: "@open-rpc/schema-utils-js@npm:2.0.5" + version: 2.1.2 + resolution: "@open-rpc/schema-utils-js@npm:2.1.2" dependencies: "@json-schema-tools/dereferencer": "npm:^1.6.3" "@json-schema-tools/meta-schema": "npm:^1.7.5" "@json-schema-tools/reference-resolver": "npm:^1.2.6" "@open-rpc/meta-schema": "npm:^1.14.9" + "@open-rpc/specification-extension-spec": "npm:^1.0.2" ajv: "npm:^6.10.0" detect-node: "npm:^2.0.4" fast-safe-stringify: "npm:^2.0.7" fs-extra: "npm:^10.1.0" is-url: "npm:^1.2.4" isomorphic-fetch: "npm:^3.0.0" - checksum: 10/9e10215606e9a00a47b082c9cfd70d05bf0d38de6cf1c147246c545c6997375d94cd3caafe919b71178df58b5facadfd0dcc8b6857bf5e79c40e5e33683dd3d5 + checksum: 10/0f38a403c696ee74319503cfba9656cdb2ff6dbd84dfba3c6ce5c3d010dfd72bc396bfb6dacf39de01d523ee7e3b0d5637657a48e5f2c7e74ae33b9354b2c4c1 + languageName: node + linkType: hard + +"@open-rpc/specification-extension-spec@npm:^1.0.2": + version: 1.0.2 + resolution: "@open-rpc/specification-extension-spec@npm:1.0.2" + checksum: 10/04111d8ce84deb45358c504b425f8d3e5c0b8991c739708b6b2662de665002da541fc7b39065d2394a9509866f580c3a5aaedc56b42c0d679fe6054eda034b9b languageName: node linkType: hard @@ -5421,10 +5518,10 @@ __metadata: languageName: node linkType: hard -"@pkgr/core@npm:^0.1.0": - version: 0.1.1 - resolution: "@pkgr/core@npm:0.1.1" - checksum: 10/6f25fd2e3008f259c77207ac9915b02f1628420403b2630c92a07ff963129238c9262afc9e84344c7a23b5cc1f3965e2cd17e3798219f5fd78a63d144d3cceba +"@pkgr/core@npm:^0.2.9": + version: 0.2.9 + resolution: "@pkgr/core@npm:0.2.9" + checksum: 10/bb2fb86977d63f836f8f5b09015d74e6af6488f7a411dcd2bfdca79d76b5a681a9112f41c45bdf88a9069f049718efc6f3900d7f1de66a2ec966068308ae517f languageName: node linkType: hard @@ -5509,9 +5606,9 @@ __metadata: linkType: hard "@scure/base@npm:~1.1.3, @scure/base@npm:~1.1.6": - version: 1.1.7 - resolution: "@scure/base@npm:1.1.7" - checksum: 10/fc50ffaab36cb46ff9fa4dc5052a06089ab6a6707f63d596bb34aaaec76173c9a564ac312a0b981b5e7a5349d60097b8878673c75d6cbfc4da7012b63a82099b + version: 1.1.9 + resolution: "@scure/base@npm:1.1.9" + checksum: 10/f0ab7f687bbcdee2a01377fe3cd808bf63977999672751295b6a92625d5322f4754a96d40f6bd579bc367aad48ecf8a4e6d0390e70296e6ded1076f52adb16bb languageName: node linkType: hard @@ -5537,16 +5634,23 @@ __metadata: linkType: hard "@sentry/core@npm:^9.10.0, @sentry/core@npm:^9.22.0": - version: 9.23.0 - resolution: "@sentry/core@npm:9.23.0" - checksum: 10/4ee771098d4ce4f4d2f7bd62cacb41ee2993780f4cab0eea600e73de3a3803cb953ac47ac015c23bcd7a9919e2220fd6cdc5a9a22a3663440296336d8df959b7 + version: 9.47.1 + resolution: "@sentry/core@npm:9.47.1" + checksum: 10/62cc2a0f45d89e3b78f083fe365007e59aed54e20b55ae5b45931cfa8e4d79d457c0c57450c6c7f92cec71fa682cd9cb3b64414fa86273f08cf3d8d06bd99c24 languageName: node linkType: hard "@sinclair/typebox@npm:^0.27.8": - version: 0.27.8 - resolution: "@sinclair/typebox@npm:0.27.8" - checksum: 10/297f95ff77c82c54de8c9907f186076e715ff2621c5222ba50b8d40a170661c0c5242c763cba2a4791f0f91cb1d8ffa53ea1d7294570cf8cd4694c0e383e484d + version: 0.27.10 + resolution: "@sinclair/typebox@npm:0.27.10" + checksum: 10/1498c5ef1375787e6272528615d5c262afb60873191d2441316359817b1c411917063c8be102ef15b0b5c62243a9daa7aefc8426f20eb406b67038b3eaa0695a + languageName: node + linkType: hard + +"@sinclair/typebox@npm:^0.34.0": + version: 0.34.48 + resolution: "@sinclair/typebox@npm:0.34.48" + checksum: 10/186eebb338255db7cfd77c2f94be0ad91816c7b5ee994c3adb95e0474ae98b769574c2b6b1f26a81613d7148ed20b11e02528f4263d8d95e3ca8dcf8faaf5306 languageName: node linkType: hard @@ -5569,78 +5673,88 @@ __metadata: linkType: hard "@solana/addresses@npm:^2.0.0": - version: 2.0.0 - resolution: "@solana/addresses@npm:2.0.0" + version: 2.3.0 + resolution: "@solana/addresses@npm:2.3.0" dependencies: - "@solana/assertions": "npm:2.0.0" - "@solana/codecs-core": "npm:2.0.0" - "@solana/codecs-strings": "npm:2.0.0" - "@solana/errors": "npm:2.0.0" + "@solana/assertions": "npm:2.3.0" + "@solana/codecs-core": "npm:2.3.0" + "@solana/codecs-strings": "npm:2.3.0" + "@solana/errors": "npm:2.3.0" + "@solana/nominal-types": "npm:2.3.0" peerDependencies: - typescript: ">=5" - checksum: 10/f99d09c72046c73858aa8b7bc323e634a60b1023a4d280036bc94489e431075c7f29d2889e8787e33a04cfdecbe77cd8ca26c31ded73f735dc98e49c3151cc17 + typescript: ">=5.3.3" + checksum: 10/11ee6774f938dd2fe5174375b02c4e52063173ce80a895dd35beb84635dcf3e2ba2e3fe7c74a614b2322da10906abceab758c91a13415a9cda53faf91a8ea722 languageName: node linkType: hard -"@solana/assertions@npm:2.0.0": - version: 2.0.0 - resolution: "@solana/assertions@npm:2.0.0" +"@solana/assertions@npm:2.3.0": + version: 2.3.0 + resolution: "@solana/assertions@npm:2.3.0" dependencies: - "@solana/errors": "npm:2.0.0" + "@solana/errors": "npm:2.3.0" peerDependencies: - typescript: ">=5" - checksum: 10/c1af37ae1bd79b1657395d9315ac261dabc9908a64af6ed80e3b7e5140909cd8c8c757f0c41fff084e26fbb4d32f091c89c092a8c1ed5e6f4565dfe7426c0979 + typescript: ">=5.3.3" + checksum: 10/3b430f01d5991569059fea3e6679a4548a624ff5da6db0c2eb2eba757a9ff774c9d90941a0a2335148599aaef8e8fc004a9c5996eb3627b25dca108b05591d02 languageName: node linkType: hard -"@solana/codecs-core@npm:2.0.0": - version: 2.0.0 - resolution: "@solana/codecs-core@npm:2.0.0" +"@solana/codecs-core@npm:2.3.0": + version: 2.3.0 + resolution: "@solana/codecs-core@npm:2.3.0" dependencies: - "@solana/errors": "npm:2.0.0" + "@solana/errors": "npm:2.3.0" peerDependencies: - typescript: ">=5" - checksum: 10/e58a72e67bee3e5da60201eecda345c604b49138d5298e39b8e7d4d57a4dee47be3b0ecc8fc3429a2a60a42c952eaf860d43d3df1eb2b1d857e35368eca9c820 + typescript: ">=5.3.3" + checksum: 10/d9bba1eaa3ee38fef04e1cbfa43defeea16729a1cf1628a71cb72340558a3f2296279899680e1dda4b1756ab2b280b5f1502330c21c35e167e554f3d0c9d193d languageName: node linkType: hard -"@solana/codecs-numbers@npm:2.0.0": - version: 2.0.0 - resolution: "@solana/codecs-numbers@npm:2.0.0" +"@solana/codecs-numbers@npm:2.3.0": + version: 2.3.0 + resolution: "@solana/codecs-numbers@npm:2.3.0" dependencies: - "@solana/codecs-core": "npm:2.0.0" - "@solana/errors": "npm:2.0.0" + "@solana/codecs-core": "npm:2.3.0" + "@solana/errors": "npm:2.3.0" peerDependencies: - typescript: ">=5" - checksum: 10/500144d549ea0292c2f672300610df9054339a31cb6a4e61b29623308ef3b14f15eb587ee6139cf3334d2e0f29db1da053522da244b12184bb8fbdb097b7102b + typescript: ">=5.3.3" + checksum: 10/e661338b5eb04268a104ff2189b5d001bd2f99e1a3726deaa7157d5acbc3b24740bc25ca03b2028c52ad21fd71d5d5aa64957411c895a9dc1c132aa3bc97b336 languageName: node linkType: hard -"@solana/codecs-strings@npm:2.0.0": - version: 2.0.0 - resolution: "@solana/codecs-strings@npm:2.0.0" +"@solana/codecs-strings@npm:2.3.0": + version: 2.3.0 + resolution: "@solana/codecs-strings@npm:2.3.0" dependencies: - "@solana/codecs-core": "npm:2.0.0" - "@solana/codecs-numbers": "npm:2.0.0" - "@solana/errors": "npm:2.0.0" + "@solana/codecs-core": "npm:2.3.0" + "@solana/codecs-numbers": "npm:2.3.0" + "@solana/errors": "npm:2.3.0" peerDependencies: fastestsmallesttextencoderdecoder: ^1.0.22 - typescript: ">=5" - checksum: 10/4380136e2603c2cee12a28438817beb34b0fe45da222b8c38342c5b3680f02086ec7868cde0bb7b4e5dd459af5988613af1d97230c6a193db3be1c45122aba39 + typescript: ">=5.3.3" + checksum: 10/a553a891ce149a87f37ff338587980e81f9752e13039cb0d02f0fc6f21ce27af8548ad10f4c9e63f9ef74786ea0e498c91a2f5e3e996a930f581f2977bb1c215 languageName: node linkType: hard -"@solana/errors@npm:2.0.0": - version: 2.0.0 - resolution: "@solana/errors@npm:2.0.0" +"@solana/errors@npm:2.3.0": + version: 2.3.0 + resolution: "@solana/errors@npm:2.3.0" dependencies: - chalk: "npm:^5.3.0" - commander: "npm:^12.1.0" + chalk: "npm:^5.4.1" + commander: "npm:^14.0.0" peerDependencies: - typescript: ">=5" + typescript: ">=5.3.3" bin: errors: bin/cli.mjs - checksum: 10/4191f96cad47c64266ec501ae1911a6245fd02b2f68a2c53c3dabbc63eb7c5462f170a765b584348b195da2387e7ca02096d792c67352c2c30a4f3a3cc7e4270 + checksum: 10/0e8a329790b7d38b4bfe1fa6ec2ac60be20562a610d992031395fe9886da28b578a9d0aebb318f5357ae0d4cbc8f3d323c12b9520da2cf6adc9038f96afc3fe1 + languageName: node + linkType: hard + +"@solana/nominal-types@npm:2.3.0": + version: 2.3.0 + resolution: "@solana/nominal-types@npm:2.3.0" + peerDependencies: + typescript: ">=5.3.3" + checksum: 10/0594893661f4ff2f8587689cd4b61ee15c38c455fe5cbaa7ae7e416f3a483fac97cc3f5a5b3d0a7526bfb89d7da91bc2c72e7b1790bbe59b986579ef2f76689b languageName: node linkType: hard @@ -5814,6 +5928,15 @@ __metadata: languageName: node linkType: hard +"@tybys/wasm-util@npm:^0.10.0": + version: 0.10.1 + resolution: "@tybys/wasm-util@npm:0.10.1" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10/7fe0d239397aebb002ac4855d30c197c06a05ea8df8511350a3a5b1abeefe26167c60eda8a5508337571161e4c4b53d7c1342296123f9607af8705369de9fa7f + languageName: node + linkType: hard + "@types/babel__core@npm:^7.1.14": version: 7.20.5 resolution: "@types/babel__core@npm:7.20.5" @@ -5828,11 +5951,11 @@ __metadata: linkType: hard "@types/babel__generator@npm:*": - version: 7.6.8 - resolution: "@types/babel__generator@npm:7.6.8" + version: 7.27.0 + resolution: "@types/babel__generator@npm:7.27.0" dependencies: "@babel/types": "npm:^7.0.0" - checksum: 10/b53c215e9074c69d212402990b0ca8fa57595d09e10d94bda3130aa22b55d796e50449199867879e4ea0ee968f3a2099e009cfb21a726a53324483abbf25cd30 + checksum: 10/f572e67a9a39397664350a4437d8a7fbd34acc83ff4887a8cf08349e39f8aeb5ad2f70fb78a0a0a23a280affe3a5f4c25f50966abdce292bcf31237af1c27b1a languageName: node linkType: hard @@ -5847,20 +5970,20 @@ __metadata: linkType: hard "@types/babel__traverse@npm:*, @types/babel__traverse@npm:^7.0.6": - version: 7.20.6 - resolution: "@types/babel__traverse@npm:7.20.6" + version: 7.28.0 + resolution: "@types/babel__traverse@npm:7.28.0" dependencies: - "@babel/types": "npm:^7.20.7" - checksum: 10/63d13a3789aa1e783b87a8b03d9fb2c2c90078de7782422feff1631b8c2a25db626e63a63ac5a1465d47359201c73069dacb4b52149d17c568187625da3064ae + "@babel/types": "npm:^7.28.2" + checksum: 10/371c5e1b40399ef17570e630b2943617b84fafde2860a56f0ebc113d8edb1d0534ade0175af89eda1ae35160903c33057ed42457e165d4aa287fedab2c82abcf languageName: node linkType: hard "@types/bn.js@npm:*, @types/bn.js@npm:^5.1.0, @types/bn.js@npm:^5.1.5": - version: 5.1.6 - resolution: "@types/bn.js@npm:5.1.6" + version: 5.2.0 + resolution: "@types/bn.js@npm:5.2.0" dependencies: "@types/node": "npm:*" - checksum: 10/db565b5a2af59b09459d74441153bf23a0e80f1fb2d070330786054e7ce1a7285dc40afcd8f289426c61a83166bdd70814f70e2d439744686aac5d3ea75daf13 + checksum: 10/06c93841f74e4a5e5b81b74427d56303b223c9af36389b4cd3c562bda93f43c425c7e241aee1b0b881dde57238dc2e07f21d30d412b206a7dae4435af4c054e8 languageName: node linkType: hard @@ -5880,13 +6003,6 @@ __metadata: languageName: node linkType: hard -"@types/doctrine@npm:^0.0.9": - version: 0.0.9 - resolution: "@types/doctrine@npm:0.0.9" - checksum: 10/64ef06e6eea2f4f9684d259fedbcb8bf21c954630b96ea2e04875ca42763552b0ba3b01b3dd27ec0f9ea6f8b3b0dba4965d31d5a925cd4c6225fd13a93ae9354 - languageName: node - linkType: hard - "@types/elliptic@npm:^6": version: 6.4.18 resolution: "@types/elliptic@npm:6.4.18" @@ -5917,9 +6033,9 @@ __metadata: linkType: hard "@types/estree@npm:*, @types/estree@npm:^1.0.6": - version: 1.0.6 - resolution: "@types/estree@npm:1.0.6" - checksum: 10/9d35d475095199c23e05b431bcdd1f6fec7380612aed068b14b2a08aa70494de8a9026765a5a91b1073f636fb0368f6d8973f518a31391d519e20c59388ed88d + version: 1.0.8 + resolution: "@types/estree@npm:1.0.8" + checksum: 10/25a4c16a6752538ffde2826c2cc0c6491d90e69cd6187bef4a006dd2c3c45469f049e643d7e516c515f21484dc3d48fd5c870be158a5beb72f5baf3dc43e4099 languageName: node linkType: hard @@ -5932,7 +6048,7 @@ __metadata: languageName: node linkType: hard -"@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.0, @types/istanbul-lib-coverage@npm:^2.0.1": +"@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.0, @types/istanbul-lib-coverage@npm:^2.0.1, @types/istanbul-lib-coverage@npm:^2.0.6": version: 2.0.6 resolution: "@types/istanbul-lib-coverage@npm:2.0.6" checksum: 10/3feac423fd3e5449485afac999dcfcb3d44a37c830af898b689fadc65d26526460bedb889db278e0d4d815a670331796494d073a10ee6e3a6526301fe7415778 @@ -5948,7 +6064,7 @@ __metadata: languageName: node linkType: hard -"@types/istanbul-reports@npm:^3.0.0": +"@types/istanbul-reports@npm:^3.0.0, @types/istanbul-reports@npm:^3.0.4": version: 3.0.4 resolution: "@types/istanbul-reports@npm:3.0.4" dependencies: @@ -5966,7 +6082,17 @@ __metadata: languageName: node linkType: hard -"@types/jest@npm:*, @types/jest@npm:^29.5.14": +"@types/jest@npm:*": + version: 30.0.0 + resolution: "@types/jest@npm:30.0.0" + dependencies: + expect: "npm:^30.0.0" + pretty-format: "npm:^30.0.0" + checksum: 10/cdeaa924c68b5233d9ff92861a89e7042df2b0f197633729bcf3a31e65bd4e9426e751c5665b5ac2de0b222b33f100a5502da22aefce3d2c62931c715e88f209 + languageName: node + linkType: hard + +"@types/jest@npm:^29.5.14": version: 29.5.14 resolution: "@types/jest@npm:29.5.14" dependencies: @@ -6009,9 +6135,9 @@ __metadata: linkType: hard "@types/lodash@npm:^4.14.191, @types/lodash@npm:^4.17.20": - version: 4.17.20 - resolution: "@types/lodash@npm:4.17.20" - checksum: 10/8cd8ad3bd78d2e06a93ae8d6c9907981d5673655fec7cb274a4d9a59549aab5bb5b3017361280773b8990ddfccf363e14d1b37c97af8a9fe363de677f9a61524 + version: 4.17.24 + resolution: "@types/lodash@npm:4.17.24" + checksum: 10/0f2082565f60f9787eefc046edc38458054512be5a8b3584ef0bad5fd9e85d0ab55ec5a1fbfae1ed6ba015cf1f9e837d5fb4da1f99fc60b8f74b2a46146fb00f languageName: node linkType: hard @@ -6030,42 +6156,44 @@ __metadata: linkType: hard "@types/ms@npm:*": - version: 0.7.34 - resolution: "@types/ms@npm:0.7.34" - checksum: 10/f38d36e7b6edecd9badc9cf50474159e9da5fa6965a75186cceaf883278611b9df6669dc3a3cc122b7938d317b68a9e3d573d316fcb35d1be47ec9e468c6bd8a + version: 2.1.0 + resolution: "@types/ms@npm:2.1.0" + checksum: 10/532d2ebb91937ccc4a89389715e5b47d4c66e708d15942fe6cc25add6dc37b2be058230a327dd50f43f89b8b6d5d52b74685a9e8f70516edfc9bdd6be910eff4 languageName: node linkType: hard "@types/node-fetch@npm:^2.6.12": - version: 2.6.12 - resolution: "@types/node-fetch@npm:2.6.12" + version: 2.6.13 + resolution: "@types/node-fetch@npm:2.6.13" dependencies: "@types/node": "npm:*" - form-data: "npm:^4.0.0" - checksum: 10/8107c479da83a3114fcbfa882eba95ee5175cccb5e4dd53f737a96f2559ae6262f662176b8457c1656de09ec393cc7b20a266c077e4bfb21e929976e1cf4d0f9 + form-data: "npm:^4.0.4" + checksum: 10/944d52214791ebba482ca1393a4f0d62b0dbac5f7343ff42c128b75d5356d8bcefd4df77771b55c1acd19d118e16e9bd5d2792819c51bc13402d1c87c0975435 languageName: node linkType: hard "@types/node@npm:*, @types/node@npm:>=12.12.47, @types/node@npm:>=13.7.0": - version: 22.5.0 - resolution: "@types/node@npm:22.5.0" + version: 25.3.0 + resolution: "@types/node@npm:25.3.0" dependencies: - undici-types: "npm:~6.19.2" - checksum: 10/89af3bd217b1559b645a9ed16d4ae3add75749814cbd8eefddd1b96003d1973afb1c8a2b23d69f3a8cc6c532e3aa185eaf5cc29a6e7c42c311a2aad4c99430ae + undici-types: "npm:~7.18.0" + checksum: 10/061b00c8de070a606a052afaa4c45dca5f8d6a8e7e39c0c3e196bb650ee37e986bbb161991ea39076a05aada102f36b13c974528448a09efd8d36bdfee75de4b languageName: node linkType: hard -"@types/node@npm:18.15.13": - version: 18.15.13 - resolution: "@types/node@npm:18.15.13" - checksum: 10/b9bbe923573797ef7c5fd2641a6793489e25d9369c32aeadcaa5c7c175c85b42eb12d6fe173f6781ab6f42eaa1ebd9576a419eeaa2a1ec810094adb8adaa9a54 +"@types/node@npm:22.7.5": + version: 22.7.5 + resolution: "@types/node@npm:22.7.5" + dependencies: + undici-types: "npm:~6.19.2" + checksum: 10/e8ba102f8c1aa7623787d625389be68d64e54fcbb76d41f6c2c64e8cf4c9f4a2370e7ef5e5f1732f3c57529d3d26afdcb2edc0101c5e413a79081449825c57ac languageName: node linkType: hard "@types/node@npm:^16.18.54": - version: 16.18.106 - resolution: "@types/node@npm:16.18.106" - checksum: 10/1970719a048bfc56554f8e132e8e5292c197d6e023d334190b0d3817a05a12bfb6537eaa24778ddb695d2073195f0545e5a4b6bcaf81b656994bbca39f349c3b + version: 16.18.126 + resolution: "@types/node@npm:16.18.126" + checksum: 10/33e0fa9209a4a96459a8fdf6b078ca9590eb67a8d51899180cfac8afecb9aa133c755d1c38a8b947b9f384f2faa184cabf4e567f5f6dded285be1b31588ec199 languageName: node linkType: hard @@ -6117,22 +6245,22 @@ __metadata: linkType: hard "@types/secp256k1@npm:^4.0.1": - version: 4.0.6 - resolution: "@types/secp256k1@npm:4.0.6" + version: 4.0.7 + resolution: "@types/secp256k1@npm:4.0.7" dependencies: "@types/node": "npm:*" - checksum: 10/211f823be990b55612e604d620acf0dc3bc942d3836bdd8da604269effabc86d98161e5947487b4e4e128f9180fc1682daae2f89ea7a4d9648fdfe52fba365fc + checksum: 10/bcf7adbd953d2cb829ae98a3cd2f8eeb1e2316f4f6de720ee3863da90bd98899c08fa8c42748e8701cad16ede0898df69a6e7f22660d1fb3cb276d5c771069db languageName: node linkType: hard "@types/semver@npm:^7, @types/semver@npm:^7.3.6": - version: 7.5.8 - resolution: "@types/semver@npm:7.5.8" - checksum: 10/3496808818ddb36deabfe4974fd343a78101fa242c4690044ccdc3b95dcf8785b494f5d628f2f47f38a702f8db9c53c67f47d7818f2be1b79f2efb09692e1178 + version: 7.7.1 + resolution: "@types/semver@npm:7.7.1" + checksum: 10/8f09e7e6ca3ded67d78ba7a8f7535c8d9cf8ced83c52e7f3ac3c281fe8c689c3fe475d199d94390dc04fc681d51f2358b430bb7b2e21c62de24f2bee2c719068 languageName: node linkType: hard -"@types/stack-utils@npm:^2.0.0": +"@types/stack-utils@npm:^2.0.0, @types/stack-utils@npm:^2.0.3": version: 2.0.3 resolution: "@types/stack-utils@npm:2.0.3" checksum: 10/72576cc1522090fe497337c2b99d9838e320659ac57fa5560fcbdcbafcf5d0216c6b3a0a8a4ee4fdb3b1f5e3420aa4f6223ab57b82fef3578bec3206425c6cf5 @@ -6177,219 +6305,354 @@ __metadata: linkType: hard "@types/yargs@npm:^15.0.0": - version: 15.0.19 - resolution: "@types/yargs@npm:15.0.19" + version: 15.0.20 + resolution: "@types/yargs@npm:15.0.20" dependencies: "@types/yargs-parser": "npm:*" - checksum: 10/c3abcd3472c32c02702f365dc1702a0728562deb8a8c61f3ce2161958d756cc033f7d78567565b4eba62f5869e9b5eac93d4c1dcb2c97af17aafda8f9f892b4b + checksum: 10/f348069c4a0cf5b365e72507f67c6569b12a4af44346c08288319d522272dbe1e3f3acde3ff9ab72bd9f894676624d10fff21096d44bad33e390d092cd409aeb languageName: node linkType: hard -"@types/yargs@npm:^17.0.32, @types/yargs@npm:^17.0.8": - version: 17.0.33 - resolution: "@types/yargs@npm:17.0.33" +"@types/yargs@npm:^17.0.32, @types/yargs@npm:^17.0.33, @types/yargs@npm:^17.0.8": + version: 17.0.35 + resolution: "@types/yargs@npm:17.0.35" dependencies: "@types/yargs-parser": "npm:*" - checksum: 10/16f6681bf4d99fb671bf56029141ed01db2862e3db9df7fc92d8bea494359ac96a1b4b1c35a836d1e95e665fb18ad753ab2015fc0db663454e8fd4e5d5e2ef91 + checksum: 10/47bcd4476a4194ea11617ea71cba8a1eddf5505fc39c44336c1a08d452a0de4486aedbc13f47a017c8efbcb5a8aa358d976880663732ebcbc6dbcbbecadb0581 languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:8.54.0, @typescript-eslint/eslint-plugin@npm:^8.48.0": - version: 8.54.0 - resolution: "@typescript-eslint/eslint-plugin@npm:8.54.0" +"@typescript-eslint/eslint-plugin@npm:8.56.1, @typescript-eslint/eslint-plugin@npm:^8.48.0": + version: 8.56.1 + resolution: "@typescript-eslint/eslint-plugin@npm:8.56.1" dependencies: "@eslint-community/regexpp": "npm:^4.12.2" - "@typescript-eslint/scope-manager": "npm:8.54.0" - "@typescript-eslint/type-utils": "npm:8.54.0" - "@typescript-eslint/utils": "npm:8.54.0" - "@typescript-eslint/visitor-keys": "npm:8.54.0" + "@typescript-eslint/scope-manager": "npm:8.56.1" + "@typescript-eslint/type-utils": "npm:8.56.1" + "@typescript-eslint/utils": "npm:8.56.1" + "@typescript-eslint/visitor-keys": "npm:8.56.1" ignore: "npm:^7.0.5" natural-compare: "npm:^1.4.0" ts-api-utils: "npm:^2.4.0" peerDependencies: - "@typescript-eslint/parser": ^8.54.0 - eslint: ^8.57.0 || ^9.0.0 + "@typescript-eslint/parser": ^8.56.1 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10/8f1c74ac77d7a84ae3f201bb09cb67271662befed036266af1eaa0653d09b545353441640516c1c86e0a94939887d32f0473c61a642488b14d46533742bfbd1b + checksum: 10/669d19cff91fcad5fe34dba97cc8c0c2df3160ae14646759fb23dfd6ffbb861d00d8d081e74d1060d544bfba0ea4d05588c5b73ae104907af26cc18189c0d139 languageName: node linkType: hard -"@typescript-eslint/parser@npm:8.54.0, @typescript-eslint/parser@npm:^8.48.0": - version: 8.54.0 - resolution: "@typescript-eslint/parser@npm:8.54.0" +"@typescript-eslint/parser@npm:8.56.1, @typescript-eslint/parser@npm:^8.48.0": + version: 8.56.1 + resolution: "@typescript-eslint/parser@npm:8.56.1" dependencies: - "@typescript-eslint/scope-manager": "npm:8.54.0" - "@typescript-eslint/types": "npm:8.54.0" - "@typescript-eslint/typescript-estree": "npm:8.54.0" - "@typescript-eslint/visitor-keys": "npm:8.54.0" + "@typescript-eslint/scope-manager": "npm:8.56.1" + "@typescript-eslint/types": "npm:8.56.1" + "@typescript-eslint/typescript-estree": "npm:8.56.1" + "@typescript-eslint/visitor-keys": "npm:8.56.1" debug: "npm:^4.4.3" peerDependencies: - eslint: ^8.57.0 || ^9.0.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10/d2e09462c9966ef3deeba71d9e41d1d4876c61eea65888c93a3db6fba48b89a2165459c6519741d40e969da05ed98d3f4c87a7f56c5521ab5699743cc315f6cb + checksum: 10/280b041a69153caf9e721b307781830483dd39d881b02d993156635bd8600e30e6a816aaead8bdd662ae5149b8870aef7b3823d3b98ec974d924c23a786fb6d9 languageName: node linkType: hard -"@typescript-eslint/project-service@npm:8.54.0": - version: 8.54.0 - resolution: "@typescript-eslint/project-service@npm:8.54.0" +"@typescript-eslint/project-service@npm:8.56.1": + version: 8.56.1 + resolution: "@typescript-eslint/project-service@npm:8.56.1" dependencies: - "@typescript-eslint/tsconfig-utils": "npm:^8.54.0" - "@typescript-eslint/types": "npm:^8.54.0" + "@typescript-eslint/tsconfig-utils": "npm:^8.56.1" + "@typescript-eslint/types": "npm:^8.56.1" debug: "npm:^4.4.3" peerDependencies: typescript: ">=4.8.4 <6.0.0" - checksum: 10/93f0483f6bbcf7cf776a53a130f7606f597fba67cf111e1897873bf1531efaa96e4851cfd461da0f0cc93afbdb51e47bcce11cf7dd4fb68b7030c7f9f240b92f + checksum: 10/5e7fdc95aebcefc72fec77806bb0821a9a59e5e88f86d72b15ad011eb6110da05419b803875f021716a219fc7fb8517331a6736364344c8613a90209539a6d32 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:8.54.0, @typescript-eslint/scope-manager@npm:^8.1.0": - version: 8.54.0 - resolution: "@typescript-eslint/scope-manager@npm:8.54.0" +"@typescript-eslint/scope-manager@npm:8.56.1": + version: 8.56.1 + resolution: "@typescript-eslint/scope-manager@npm:8.56.1" dependencies: - "@typescript-eslint/types": "npm:8.54.0" - "@typescript-eslint/visitor-keys": "npm:8.54.0" - checksum: 10/3474f3197e8647754393dee62b3145c9de71eaa66c8a68f61c8283aa332141803885db9c96caa6a51f78128ad9ef92f774a90361655e57bd951d5b57eb76f914 + "@typescript-eslint/types": "npm:8.56.1" + "@typescript-eslint/visitor-keys": "npm:8.56.1" + checksum: 10/f358cf8bd32952eed005d4f34c1e95805baefe35abee96d866222b0eff8027cc02f831cee04b308707d74db2b415437a134191207b4213ee8acbc6d67a435616 languageName: node linkType: hard -"@typescript-eslint/tsconfig-utils@npm:8.54.0, @typescript-eslint/tsconfig-utils@npm:^8.54.0": - version: 8.54.0 - resolution: "@typescript-eslint/tsconfig-utils@npm:8.54.0" +"@typescript-eslint/tsconfig-utils@npm:8.56.1, @typescript-eslint/tsconfig-utils@npm:^8.56.1": + version: 8.56.1 + resolution: "@typescript-eslint/tsconfig-utils@npm:8.56.1" peerDependencies: typescript: ">=4.8.4 <6.0.0" - checksum: 10/e9d6b29538716f007919bfcee94f09b7f8e7d2b684ad43d1a3c8d43afb9f0539c7707f84a34f42054e31c8c056b0ccf06575d89e860b4d34632ffefaefafe1fc + checksum: 10/d509f1ae4b14969173e498db6d15c833b6407db456c7fca9e25396798a35014229a73754691f353c4a99f5f0bbb4535b4144f42f84e596645a16d88a2022135f languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:8.54.0": - version: 8.54.0 - resolution: "@typescript-eslint/type-utils@npm:8.54.0" +"@typescript-eslint/type-utils@npm:8.56.1": + version: 8.56.1 + resolution: "@typescript-eslint/type-utils@npm:8.56.1" dependencies: - "@typescript-eslint/types": "npm:8.54.0" - "@typescript-eslint/typescript-estree": "npm:8.54.0" - "@typescript-eslint/utils": "npm:8.54.0" + "@typescript-eslint/types": "npm:8.56.1" + "@typescript-eslint/typescript-estree": "npm:8.56.1" + "@typescript-eslint/utils": "npm:8.56.1" debug: "npm:^4.4.3" ts-api-utils: "npm:^2.4.0" peerDependencies: - eslint: ^8.57.0 || ^9.0.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10/60e92fb32274abd70165ce6f4187e4cffa55416374c63731d7de8fdcfb7a558b4dd48909ff1ad38ac39d2ea1248ec54d6ce38dbc065fd34529a217fc2450d5b1 + checksum: 10/2b07c674c26d797d05c05779ac5c89761b6b96680ecaf01440957727d12c6d06a2e48f0b139e45752eb4b53bf13c03940628656c519d362082b716d6a0ece6d9 languageName: node linkType: hard -"@typescript-eslint/types@npm:8.54.0, @typescript-eslint/types@npm:^8.54.0": - version: 8.54.0 - resolution: "@typescript-eslint/types@npm:8.54.0" - checksum: 10/c25cc0bdf90fb150cf6ce498897f43fe3adf9e872562159118f34bd91a9bfab5f720cb1a41f3cdf253b2e840145d7d372089b7cef5156624ef31e98d34f91b31 +"@typescript-eslint/types@npm:8.56.1, @typescript-eslint/types@npm:^8.11.0, @typescript-eslint/types@npm:^8.35.0, @typescript-eslint/types@npm:^8.56.1": + version: 8.56.1 + resolution: "@typescript-eslint/types@npm:8.56.1" + checksum: 10/4bcffab5b0fd48adb731fcade86a776ca4a66e229defa5a282b58ba9c95af16ffc459a7d188e27c988a35be1f6fb5b812f9cf0952692eac38d5b3e87daafb20a languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:8.54.0": - version: 8.54.0 - resolution: "@typescript-eslint/typescript-estree@npm:8.54.0" +"@typescript-eslint/typescript-estree@npm:8.56.1": + version: 8.56.1 + resolution: "@typescript-eslint/typescript-estree@npm:8.56.1" dependencies: - "@typescript-eslint/project-service": "npm:8.54.0" - "@typescript-eslint/tsconfig-utils": "npm:8.54.0" - "@typescript-eslint/types": "npm:8.54.0" - "@typescript-eslint/visitor-keys": "npm:8.54.0" + "@typescript-eslint/project-service": "npm:8.56.1" + "@typescript-eslint/tsconfig-utils": "npm:8.56.1" + "@typescript-eslint/types": "npm:8.56.1" + "@typescript-eslint/visitor-keys": "npm:8.56.1" debug: "npm:^4.4.3" - minimatch: "npm:^9.0.5" + minimatch: "npm:^10.2.2" semver: "npm:^7.7.3" tinyglobby: "npm:^0.2.15" ts-api-utils: "npm:^2.4.0" peerDependencies: typescript: ">=4.8.4 <6.0.0" - checksum: 10/3a545037c6f9319251d3ba44cf7a3216b1372422469e27f7ed3415244ebf42553da1ab4644da42d3f0ae2706a8cad12529ffebcb2e75406f74e3b30b812d010d + checksum: 10/af39dae0a8fada72295a11f0efb49f311241134b0a3d819100eeda6a2f92368844645873ba785de5513ad541cd9c2ba17b9bfed2679daac4682fa2a3b627f087 languageName: node linkType: hard -"@typescript-eslint/utils@npm:8.54.0, @typescript-eslint/utils@npm:^6.0.0 || ^7.0.0 || ^8.0.0, @typescript-eslint/utils@npm:^8.1.0": - version: 8.54.0 - resolution: "@typescript-eslint/utils@npm:8.54.0" +"@typescript-eslint/utils@npm:8.56.1, @typescript-eslint/utils@npm:^6.0.0 || ^7.0.0 || ^8.0.0": + version: 8.56.1 + resolution: "@typescript-eslint/utils@npm:8.56.1" dependencies: "@eslint-community/eslint-utils": "npm:^4.9.1" - "@typescript-eslint/scope-manager": "npm:8.54.0" - "@typescript-eslint/types": "npm:8.54.0" - "@typescript-eslint/typescript-estree": "npm:8.54.0" + "@typescript-eslint/scope-manager": "npm:8.56.1" + "@typescript-eslint/types": "npm:8.56.1" + "@typescript-eslint/typescript-estree": "npm:8.56.1" peerDependencies: - eslint: ^8.57.0 || ^9.0.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10/9f88a2a7ab3e11aa0ff7f99c0e66a0cf2cba10b640def4c64a4f4ef427fecfb22f28dbe5697535915eb01f6507515ac43e45e0ff384bf82856e3420194d9ffdd + checksum: 10/528cbd187d8288a8cfce24a043f993b93711087f53d2b6f95cdd615a1a4087af1dab083a747761af97474a621c7b14f11c84ee50c250f31566ebc64cf73867fe languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:8.54.0": - version: 8.54.0 - resolution: "@typescript-eslint/visitor-keys@npm:8.54.0" +"@typescript-eslint/visitor-keys@npm:8.56.1": + version: 8.56.1 + resolution: "@typescript-eslint/visitor-keys@npm:8.56.1" dependencies: - "@typescript-eslint/types": "npm:8.54.0" - eslint-visitor-keys: "npm:^4.2.1" - checksum: 10/cca5380ee30250302ee1459e5a0a38de8c16213026dbbff3d167fa7d71d012f31d60ac4483ad45ebd13f2ac963d1ca52dd5f22759a68d4ee57626e421769187a + "@typescript-eslint/types": "npm:8.56.1" + eslint-visitor-keys: "npm:^5.0.0" + checksum: 10/efed6a9867e7be203eec543e5a65da5aaec96aae55fba6fe74a305bf600e57c707764835e82bb8eb541f49a9b70442ff1e1a0ecf3543c78c91b84dda43b95c53 languageName: node linkType: hard -"@vercel/stega@npm:^0.1.2": - version: 0.1.2 - resolution: "@vercel/stega@npm:0.1.2" - checksum: 10/67ade78b77f579e39bbdd010cc31c39e75b1c1a1ef5a8accdd78df57d156ecd163c767a1feb61b95df190f8ab10642d038776bc5f2fab48bf705d49ee9cced01 +"@unrs/resolver-binding-android-arm-eabi@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-android-arm-eabi@npm:1.11.1" + conditions: os=android & cpu=arm languageName: node linkType: hard -"@vue/compiler-core@npm:3.4.38": - version: 3.4.38 - resolution: "@vue/compiler-core@npm:3.4.38" - dependencies: - "@babel/parser": "npm:^7.24.7" - "@vue/shared": "npm:3.4.38" - entities: "npm:^4.5.0" - estree-walker: "npm:^2.0.2" - source-map-js: "npm:^1.2.0" - checksum: 10/16449e9083c290e6c13e1cc0cb0a0a457817a52533d10902388c872fb1337ba0fa29fb7b8394df5a10f5ed3bad264d6c386f9eaf47c07982a543f277dbee9b8a +"@unrs/resolver-binding-android-arm64@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-android-arm64@npm:1.11.1" + conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@vue/compiler-dom@npm:3.4.38": - version: 3.4.38 - resolution: "@vue/compiler-dom@npm:3.4.38" - dependencies: - "@vue/compiler-core": "npm:3.4.38" - "@vue/shared": "npm:3.4.38" - checksum: 10/4012fab212dc0628ef72f5ae13aa2dd551efb8be7f2aa8abe2a1db15058ddda29912a1e3aa1fc6712e2d8efe84724f16a907ad2cda987631bfc79330afc8d451 +"@unrs/resolver-binding-darwin-arm64@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-darwin-arm64@npm:1.11.1" + conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@vue/compiler-sfc@npm:^3.3.4": - version: 3.4.38 - resolution: "@vue/compiler-sfc@npm:3.4.38" - dependencies: - "@babel/parser": "npm:^7.24.7" - "@vue/compiler-core": "npm:3.4.38" - "@vue/compiler-dom": "npm:3.4.38" - "@vue/compiler-ssr": "npm:3.4.38" - "@vue/shared": "npm:3.4.38" +"@unrs/resolver-binding-darwin-x64@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-darwin-x64@npm:1.11.1" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-freebsd-x64@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-freebsd-x64@npm:1.11.1" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm-gnueabihf@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-arm-gnueabihf@npm:1.11.1" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm-musleabihf@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-arm-musleabihf@npm:1.11.1" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm64-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-arm64-gnu@npm:1.11.1" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm64-musl@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-arm64-musl@npm:1.11.1" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-ppc64-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-ppc64-gnu@npm:1.11.1" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-riscv64-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-riscv64-gnu@npm:1.11.1" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-riscv64-musl@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-riscv64-musl@npm:1.11.1" + conditions: os=linux & cpu=riscv64 & libc=musl + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-s390x-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-s390x-gnu@npm:1.11.1" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-x64-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-x64-gnu@npm:1.11.1" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-x64-musl@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-x64-musl@npm:1.11.1" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@unrs/resolver-binding-wasm32-wasi@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-wasm32-wasi@npm:1.11.1" + dependencies: + "@napi-rs/wasm-runtime": "npm:^0.2.11" + conditions: cpu=wasm32 + languageName: node + linkType: hard + +"@unrs/resolver-binding-win32-arm64-msvc@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-win32-arm64-msvc@npm:1.11.1" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-win32-ia32-msvc@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-win32-ia32-msvc@npm:1.11.1" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@unrs/resolver-binding-win32-x64-msvc@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-win32-x64-msvc@npm:1.11.1" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@vercel/stega@npm:^0.1.2": + version: 0.1.2 + resolution: "@vercel/stega@npm:0.1.2" + checksum: 10/67ade78b77f579e39bbdd010cc31c39e75b1c1a1ef5a8accdd78df57d156ecd163c767a1feb61b95df190f8ab10642d038776bc5f2fab48bf705d49ee9cced01 + languageName: node + linkType: hard + +"@vue/compiler-core@npm:3.5.29": + version: 3.5.29 + resolution: "@vue/compiler-core@npm:3.5.29" + dependencies: + "@babel/parser": "npm:^7.29.0" + "@vue/shared": "npm:3.5.29" + entities: "npm:^7.0.1" estree-walker: "npm:^2.0.2" - magic-string: "npm:^0.30.10" - postcss: "npm:^8.4.40" - source-map-js: "npm:^1.2.0" - checksum: 10/3eec1ddc03e06a162087dbbff9679f941ff34c43e553006aa2717c6a396445f488b62b89afa9cf65688468a05d8517bf1ee64936ad78d7ba6647a850a089e0e0 + source-map-js: "npm:^1.2.1" + checksum: 10/55c9dc371049f9b46f62210e72cea084212e2177dde42697da5008c2a64bfa88a886f42bcbb14fc5447fe9611082c6b30b3d2f148c512d14bce3ba8e2960212e languageName: node linkType: hard -"@vue/compiler-ssr@npm:3.4.38": - version: 3.4.38 - resolution: "@vue/compiler-ssr@npm:3.4.38" +"@vue/compiler-dom@npm:3.5.29": + version: 3.5.29 + resolution: "@vue/compiler-dom@npm:3.5.29" dependencies: - "@vue/compiler-dom": "npm:3.4.38" - "@vue/shared": "npm:3.4.38" - checksum: 10/3ee052c8f10bf18db5d6788df21105698c139fac1de6c82532878cca86be4d052510a216184b3ea73331d84befcefd3f9ada11470c862f03696fed96ce1005cb + "@vue/compiler-core": "npm:3.5.29" + "@vue/shared": "npm:3.5.29" + checksum: 10/50156e63a3c249e82f6e57f2e8fc1705b659d81845d0f59552a92e86c1907ef5c53c17670c03d76fd9bc850d06ad29ff8ca1ebc92bfdf0c77efa1a8e449be98b languageName: node linkType: hard -"@vue/shared@npm:3.4.38": - version: 3.4.38 - resolution: "@vue/shared@npm:3.4.38" - checksum: 10/46bfc1f3932fd154ff84dcd267cae4db730c98db433c848d40c9c0dc23dcabdb5efe96a3a378c9ed3b7e8281ca17e2753f0ce98ae43b54b315550dfaccb56868 +"@vue/compiler-sfc@npm:^3.3.4": + version: 3.5.29 + resolution: "@vue/compiler-sfc@npm:3.5.29" + dependencies: + "@babel/parser": "npm:^7.29.0" + "@vue/compiler-core": "npm:3.5.29" + "@vue/compiler-dom": "npm:3.5.29" + "@vue/compiler-ssr": "npm:3.5.29" + "@vue/shared": "npm:3.5.29" + estree-walker: "npm:^2.0.2" + magic-string: "npm:^0.30.21" + postcss: "npm:^8.5.6" + source-map-js: "npm:^1.2.1" + checksum: 10/0052b6ce36e70e923a5151d64c0a0d63ebb2e00c3ad5198bad983783d3e536ca6b0b4245c6d0b3c311bf97c10b16359453cfc597267a45f0efb18edcf7e35987 + languageName: node + linkType: hard + +"@vue/compiler-ssr@npm:3.5.29": + version: 3.5.29 + resolution: "@vue/compiler-ssr@npm:3.5.29" + dependencies: + "@vue/compiler-dom": "npm:3.5.29" + "@vue/shared": "npm:3.5.29" + checksum: 10/0240a488fc42fb4221a03e2e4eb258256c9b7043e26841fe5e6e4097ff944c8e9f78ef21792517af6434927f8f51d2c1f007a09b940aacbc5930c999d336d14e + languageName: node + linkType: hard + +"@vue/shared@npm:3.5.29": + version: 3.5.29 + resolution: "@vue/shared@npm:3.5.29" + checksum: 10/cad8e9925f672d9e3eaa08a6b502777e6a264cfae1faf648e0b759d0c1cb8d91980fb9a6338c8dc09dee6bf5235fec4c9ac3cc5d3312b159292da271b8864546 languageName: node linkType: hard @@ -6401,11 +6664,11 @@ __metadata: linkType: hard "@yarnpkg/types@npm:^4.0.0": - version: 4.0.0 - resolution: "@yarnpkg/types@npm:4.0.0" + version: 4.0.1 + resolution: "@yarnpkg/types@npm:4.0.1" dependencies: tslib: "npm:^2.4.0" - checksum: 10/f9670e120761a4d17461df2f01aa4b92213fbdd063501a36145d11ea01bd87ba01d44615cba3d6bc8f9bfc39a03a9a6452bf0436c7fb0c9c5311352b975349e6 + checksum: 10/f391763cd955356e9aad551b29e8de7bbf68a6c8992af7cdc950ccf53f8aff6695ad81aa4c8a8e7c582786a840a4f30617732e2cb49f4109b971a9242c31c9fc languageName: node linkType: hard @@ -6416,10 +6679,10 @@ __metadata: languageName: node linkType: hard -"abbrev@npm:^2.0.0": - version: 2.0.0 - resolution: "abbrev@npm:2.0.0" - checksum: 10/ca0a54e35bea4ece0ecb68a47b312e1a9a6f772408d5bcb9051230aaa94b0460671c5b5c9cb3240eb5b7bc94c52476550eb221f65a0bbd0145bdc9f3113a6707 +"abbrev@npm:^4.0.0": + version: 4.0.0 + resolution: "abbrev@npm:4.0.0" + checksum: 10/e2f0c6a6708ad738b3e8f50233f4800de31ad41a6cdc50e0cbe51b76fed69fd0213516d92c15ce1a9985fca71a14606a9be22bf00f8475a58987b9bfb671c582 languageName: node linkType: hard @@ -6462,20 +6725,20 @@ __metadata: linkType: hard "acorn-walk@npm:^8.0.2": - version: 8.3.4 - resolution: "acorn-walk@npm:8.3.4" + version: 8.3.5 + resolution: "acorn-walk@npm:8.3.5" dependencies: acorn: "npm:^8.11.0" - checksum: 10/871386764e1451c637bb8ab9f76f4995d408057e9909be6fb5ad68537ae3375d85e6a6f170b98989f44ab3ff6c74ad120bc2779a3d577606e7a0cd2b4efcaf77 + checksum: 10/f52a158a1c1f00c82702c7eb9b8ae8aad79748a7689241dcc2d797dce680f1dcb15c78f312f687eeacdfb3a4cac4b87d04af470f0201bd56c6661fca6f94b195 languageName: node linkType: hard "acorn@npm:^8.1.0, acorn@npm:^8.11.0, acorn@npm:^8.15.0, acorn@npm:^8.8.1": - version: 8.15.0 - resolution: "acorn@npm:8.15.0" + version: 8.16.0 + resolution: "acorn@npm:8.16.0" bin: acorn: bin/acorn - checksum: 10/77f2de5051a631cf1729c090e5759148459cdb76b5f5c70f890503d629cf5052357b0ce783c0f976dd8a93c5150f59f6d18df1def3f502396a20f81282482fa4 + checksum: 10/690c673bb4d61b38ef82795fab58526471ad7f7e67c0e40c4ff1e10ecd80ce5312554ef633c9995bfc4e6d170cef165711f9ca9e49040b62c0c66fbf2dd3df2b languageName: node linkType: hard @@ -6509,34 +6772,22 @@ __metadata: languageName: node linkType: hard -"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0, agent-base@npm:^7.1.1": - version: 7.1.1 - resolution: "agent-base@npm:7.1.1" - dependencies: - debug: "npm:^4.3.4" - checksum: 10/c478fec8f79953f118704d007a38f2a185458853f5c45579b9669372bd0e12602e88dc2ad0233077831504f7cd6fcc8251c383375bba5eaaf563b102938bda26 - languageName: node - linkType: hard - -"aggregate-error@npm:^3.0.0": - version: 3.1.0 - resolution: "aggregate-error@npm:3.1.0" - dependencies: - clean-stack: "npm:^2.0.0" - indent-string: "npm:^4.0.0" - checksum: 10/1101a33f21baa27a2fa8e04b698271e64616b886795fd43c31068c07533c7b3facfcaf4e9e0cab3624bd88f729a592f1c901a1a229c9e490eafce411a8644b79 +"agent-base@npm:^7.1.0, agent-base@npm:^7.1.2": + version: 7.1.4 + resolution: "agent-base@npm:7.1.4" + checksum: 10/79bef167247789f955aaba113bae74bf64aa1e1acca4b1d6bb444bdf91d82c3e07e9451ef6a6e2e35e8f71a6f97ce33e3d855a5328eb9fad1bc3cc4cfd031ed8 languageName: node linkType: hard -"ajv@npm:^6.10.0, ajv@npm:^6.12.4": - version: 6.12.6 - resolution: "ajv@npm:6.12.6" +"ajv@npm:^6.10.0, ajv@npm:^6.12.4, ajv@npm:^6.14.0": + version: 6.14.0 + resolution: "ajv@npm:6.14.0" dependencies: fast-deep-equal: "npm:^3.1.1" fast-json-stable-stringify: "npm:^2.0.0" json-schema-traverse: "npm:^0.4.1" uri-js: "npm:^4.2.2" - checksum: 10/48d6ad21138d12eb4d16d878d630079a2bda25a04e745c07846a4ad768319533031e28872a9b3c5790fa1ec41aabdf2abed30a56e5a03ebc2cf92184b8ee306c + checksum: 10/c71f14dd2b6f2535d043f74019c8169f7aeb1106bafbb741af96f34fdbf932255c919ddd46344043d03b62ea0ccb319f83667ec5eedf612393f29054fe5ce4a5 languageName: node linkType: hard @@ -6564,16 +6815,16 @@ __metadata: linkType: hard "ansi-regex@npm:^6.0.1": - version: 6.0.1 - resolution: "ansi-regex@npm:6.0.1" - checksum: 10/1ff8b7667cded1de4fa2c9ae283e979fc87036864317da86a2e546725f96406746411d0d85e87a2d12fa5abd715d90006de7fa4fa0477c92321ad3b4c7d4e169 + version: 6.2.2 + resolution: "ansi-regex@npm:6.2.2" + checksum: 10/9b17ce2c6daecc75bcd5966b9ad672c23b184dc3ed9bf3c98a0702f0d2f736c15c10d461913568f2cf527a5e64291c7473358885dd493305c84a1cfed66ba94f languageName: node linkType: hard "ansi-sequence-parser@npm:^1.1.0": - version: 1.1.1 - resolution: "ansi-sequence-parser@npm:1.1.1" - checksum: 10/9ce30f257badc2ef62cac8028a7e26c368d22bf26650427192e8ffd102da42e377e3affe90fae58062eecc963b0b055f510dde3b677c7e0c433c67069b5a8ee5 + version: 1.1.3 + resolution: "ansi-sequence-parser@npm:1.1.3" + checksum: 10/0f298aad5c9429dc71fc85668b4b502a5c0670c6dc1253b6e9ed5fc7d457a05ede5b10fd0d69a33a1435e41c0a841360bec9131053bdce04a2367c475acb97d6 languageName: node linkType: hard @@ -6586,7 +6837,7 @@ __metadata: languageName: node linkType: hard -"ansi-styles@npm:^5.0.0": +"ansi-styles@npm:^5.0.0, ansi-styles@npm:^5.2.0": version: 5.2.0 resolution: "ansi-styles@npm:5.2.0" checksum: 10/d7f4e97ce0623aea6bc0d90dcd28881ee04cba06c570b97fd3391bd7a268eedfd9d5e2dd4fdcbdd82b8105df5faf6f24aaedc08eaf3da898e702db5948f63469 @@ -6594,9 +6845,9 @@ __metadata: linkType: hard "ansi-styles@npm:^6.1.0": - version: 6.2.1 - resolution: "ansi-styles@npm:6.2.1" - checksum: 10/70fdf883b704d17a5dfc9cde206e698c16bcd74e7f196ab821511651aee4f9f76c9514bdfa6ca3a27b5e49138b89cb222a28caf3afe4567570139577f991df32 + version: 6.2.3 + resolution: "ansi-styles@npm:6.2.3" + checksum: 10/c49dad7639f3e48859bd51824c93b9eb0db628afc243c51c3dd2410c4a15ede1a83881c6c7341aa2b159c4f90c11befb38f2ba848c07c66c9f9de4bcd7cb9f30 languageName: node linkType: hard @@ -6682,12 +6933,17 @@ __metadata: languageName: node linkType: hard -"async-mutex@npm:^0.3.1": - version: 0.3.2 - resolution: "async-mutex@npm:0.3.2" - dependencies: - tslib: "npm:^2.3.1" - checksum: 10/cf0b02f7f916d202a727e15a64d51110c3258a719588ca263875024172aa9368efa5dbec6dc4f4fd10e35744e238e1075306a93ce86549de642d5f7d0c06bc23 +"async-function@npm:^1.0.0": + version: 1.0.0 + resolution: "async-function@npm:1.0.0" + checksum: 10/1a09379937d846f0ce7614e75071c12826945d4e417db634156bf0e4673c495989302f52186dfa9767a1d9181794554717badd193ca2bbab046ef1da741d8efd + languageName: node + linkType: hard + +"async-generator-function@npm:^1.0.0": + version: 1.0.0 + resolution: "async-generator-function@npm:1.0.0" + checksum: 10/3d49e7acbeee9e84537f4cb0e0f91893df8eba976759875ae8ee9e3d3c82f6ecdebdb347c2fad9926b92596d93cdfc78ecc988bcdf407e40433e8e8e6fe5d78e languageName: node linkType: hard @@ -6707,21 +6963,35 @@ __metadata: languageName: node linkType: hard +"available-typed-arrays@npm:^1.0.7": + version: 1.0.7 + resolution: "available-typed-arrays@npm:1.0.7" + dependencies: + possible-typed-array-names: "npm:^1.0.0" + checksum: 10/6c9da3a66caddd83c875010a1ca8ef11eac02ba15fb592dc9418b2b5e7b77b645fa7729380a92d9835c2f05f2ca1b6251f39b993e0feb3f1517c74fa1af02cab + languageName: node + linkType: hard + "axios@npm:^1.7.4": - version: 1.7.5 - resolution: "axios@npm:1.7.5" + version: 1.13.5 + resolution: "axios@npm:1.13.5" dependencies: - follow-redirects: "npm:^1.15.6" - form-data: "npm:^4.0.0" + follow-redirects: "npm:^1.15.11" + form-data: "npm:^4.0.5" proxy-from-env: "npm:^1.1.0" - checksum: 10/6cbcfe943a84089f420a900a3a3aeb54ee94dcc9c2b81b150434896357be5d1079eff0b1bbb628597371e79f896b1bc5776df04184756ba99656ff31df9a75bf + checksum: 10/db726d09902565ef9a0632893530028310e2ec2b95b727114eca1b101450b00014133dfc3871cffc87983fb922bca7e4874d7e2826d1550a377a157cdf3f05b6 languageName: node linkType: hard "b4a@npm:^1.6.4": - version: 1.6.6 - resolution: "b4a@npm:1.6.6" - checksum: 10/6154a36bd78b53ecd2843a829352532a1bf9fc8081dab339ba06ca3c9ffcf25d340c3b18fe4ba0fc17a546a54c1ed814cea92cd6b895f6bd2837ca4ee0fc9f52 + version: 1.8.0 + resolution: "b4a@npm:1.8.0" + peerDependencies: + react-native-b4a: "*" + peerDependenciesMeta: + react-native-b4a: + optional: true + checksum: 10/ce85601eef7f68f81320c2bcadd96a0c1be654bcb8c10622f73ef8b99762a323b1f3a3603dfaee557bd706a7326e372b8e5544b8746f5096ef4d3612ee4da061 languageName: node linkType: hard @@ -6768,8 +7038,8 @@ __metadata: linkType: hard "babel-preset-current-node-syntax@npm:^1.0.0": - version: 1.1.0 - resolution: "babel-preset-current-node-syntax@npm:1.1.0" + version: 1.2.0 + resolution: "babel-preset-current-node-syntax@npm:1.2.0" dependencies: "@babel/plugin-syntax-async-generators": "npm:^7.8.4" "@babel/plugin-syntax-bigint": "npm:^7.8.3" @@ -6787,8 +7057,8 @@ __metadata: "@babel/plugin-syntax-private-property-in-object": "npm:^7.14.5" "@babel/plugin-syntax-top-level-await": "npm:^7.14.5" peerDependencies: - "@babel/core": ^7.0.0 - checksum: 10/46331111ae72b7121172fd9e6a4a7830f651ad44bf26dbbf77b3c8a60a18009411a3eacb5e72274004290c110371230272109957d5224d155436b4794ead2f1b + "@babel/core": ^7.0.0 || ^8.0.0-0 + checksum: 10/3608fa671cfa46364ea6ec704b8fcdd7514b7b70e6ec09b1199e13ae73ed346c51d5ce2cb6d4d5b295f6a3f2cad1fdeec2308aa9e037002dd7c929194cc838ea languageName: node linkType: hard @@ -6821,19 +7091,31 @@ __metadata: languageName: node linkType: hard -"bare-events@npm:^2.2.0": - version: 2.4.2 - resolution: "bare-events@npm:2.4.2" - checksum: 10/c1006ad13b7e62a412466d4eac8466b4ceb46ce84a5e2fc164cd4b10edaaa5016adc684147134b67a6a3865aaf5aa007191647bdb5dbf859b1d5735d2a9ddf3b +"balanced-match@npm:^4.0.2": + version: 4.0.4 + resolution: "balanced-match@npm:4.0.4" + checksum: 10/fb07bb66a0959c2843fc055838047e2a95ccebb837c519614afb067ebfdf2fa967ca8d712c35ced07f2cd26fc6f07964230b094891315ad74f11eba3d53178a0 + languageName: node + linkType: hard + +"bare-events@npm:^2.7.0": + version: 2.8.2 + resolution: "bare-events@npm:2.8.2" + peerDependencies: + bare-abort-controller: "*" + peerDependenciesMeta: + bare-abort-controller: + optional: true + checksum: 10/f31848ea2f5627c3a50aadfc17e518a602629f7a6671da1352975cc6c8a520441fcc9d93c0a21f8f95de65b1a5133fcd5f766d312f3d5a326dde4fe7d2fc575f languageName: node linkType: hard "base-x@npm:^3.0.2": - version: 3.0.10 - resolution: "base-x@npm:3.0.10" + version: 3.0.11 + resolution: "base-x@npm:3.0.11" dependencies: safe-buffer: "npm:^5.0.1" - checksum: 10/52307739559e81d9980889de2359cb4f816cc0eb9a463028fa3ab239ab913d9044a1b47b4520f98e68453df32a457b8ba58b8d0ee7e757fc3fb971f3fa7a1482 + checksum: 10/c2e3c443fd07cb9b9d3e179a9e9c581daa31881005841fe8d6a834e534505890fedf03465ccf14512da60e3f7be00fe66167806b159ba076d2c03952ae7460c4 languageName: node linkType: hard @@ -6851,6 +7133,15 @@ __metadata: languageName: node linkType: hard +"baseline-browser-mapping@npm:^2.9.0": + version: 2.10.0 + resolution: "baseline-browser-mapping@npm:2.10.0" + bin: + baseline-browser-mapping: dist/cli.cjs + checksum: 10/8145e076e4299f04c7a412e6ea63803e330153cd89c47b5303f9b56b58078f4c3d5a5b5332c1069da889e76facacca4d43f8940375f7e73ce0a4d96214332953 + languageName: node + linkType: hard + "bech32@npm:1.1.4": version: 1.1.4 resolution: "bech32@npm:1.1.4" @@ -6866,9 +7157,9 @@ __metadata: linkType: hard "bignumber.js@npm:^9.1.2": - version: 9.1.2 - resolution: "bignumber.js@npm:9.1.2" - checksum: 10/d89b8800a987225d2c00dcbf8a69dc08e92aa0880157c851c287b307d31ceb2fc2acb0c62c3e3a3d42b6c5fcae9b004035f13eb4386e56d529d7edac18d5c9d8 + version: 9.3.1 + resolution: "bignumber.js@npm:9.3.1" + checksum: 10/1be0372bf0d6d29d0a49b9e6a9cefbd54dad9918232ad21fcd4ec39030260773abf0c76af960c6b3b98d3115a3a71e61c6a111812d1395040a039cfa178e0245 languageName: node linkType: hard @@ -6924,55 +7215,64 @@ __metadata: linkType: hard "bn.js@npm:^4.11.9": - version: 4.12.0 - resolution: "bn.js@npm:4.12.0" - checksum: 10/10f8db196d3da5adfc3207d35d0a42aa29033eb33685f20ba2c36cadfe2de63dad05df0a20ab5aae01b418d1c4b3d4d205273085262fa020d17e93ff32b67527 + version: 4.12.3 + resolution: "bn.js@npm:4.12.3" + checksum: 10/57ed5a055f946f3e009f1589c45a5242db07f3dddfc72e4506f0dd9d8b145f0dbee4edabc2499288f3fc338eb712fb96a1c623a2ed2bcd49781df1a64db64dd1 languageName: node linkType: hard "bn.js@npm:^5.1.2, bn.js@npm:^5.2.0, bn.js@npm:^5.2.1, bn.js@npm:^5.2.2": - version: 5.2.2 - resolution: "bn.js@npm:5.2.2" - checksum: 10/51ebb2df83b33e5d8581165206e260d5e9c873752954616e5bf3758952b84d7399a9c6d00852815a0aeefb1150a7f34451b62d4287342d457fa432eee869e83e + version: 5.2.3 + resolution: "bn.js@npm:5.2.3" + checksum: 10/dfb3927e0d531e6ec4f191597ce6f7f7665310c356fef5f968ada676b8058027f959af42eaa37b5f5c63617e819d3741813025ab15dd71a90f2e74698df0b58e languageName: node linkType: hard -"body-parser@npm:1.20.3": - version: 1.20.3 - resolution: "body-parser@npm:1.20.3" +"body-parser@npm:~1.20.3": + version: 1.20.4 + resolution: "body-parser@npm:1.20.4" dependencies: - bytes: "npm:3.1.2" + bytes: "npm:~3.1.2" content-type: "npm:~1.0.5" debug: "npm:2.6.9" depd: "npm:2.0.0" - destroy: "npm:1.2.0" - http-errors: "npm:2.0.0" - iconv-lite: "npm:0.4.24" - on-finished: "npm:2.4.1" - qs: "npm:6.13.0" - raw-body: "npm:2.5.2" + destroy: "npm:~1.2.0" + http-errors: "npm:~2.0.1" + iconv-lite: "npm:~0.4.24" + on-finished: "npm:~2.4.1" + qs: "npm:~6.14.0" + raw-body: "npm:~2.5.3" type-is: "npm:~1.6.18" - unpipe: "npm:1.0.0" - checksum: 10/8723e3d7a672eb50854327453bed85ac48d045f4958e81e7d470c56bf111f835b97e5b73ae9f6393d0011cc9e252771f46fd281bbabc57d33d3986edf1e6aeca + unpipe: "npm:~1.0.0" + checksum: 10/ff67e28d3f426707be8697a75fdf8d564dc50c341b41f054264d8ab6e2924e519c7ce8acc9d0de05328fdc41e1d9f3f200aec9c1cfb1867d6b676a410d97c689 languageName: node linkType: hard "brace-expansion@npm:^1.1.7": - version: 1.1.11 - resolution: "brace-expansion@npm:1.1.11" + version: 1.1.12 + resolution: "brace-expansion@npm:1.1.12" dependencies: balanced-match: "npm:^1.0.0" concat-map: "npm:0.0.1" - checksum: 10/faf34a7bb0c3fcf4b59c7808bc5d2a96a40988addf2e7e09dfbb67a2251800e0d14cd2bfc1aa79174f2f5095c54ff27f46fb1289fe2d77dac755b5eb3434cc07 + checksum: 10/12cb6d6310629e3048cadb003e1aca4d8c9bb5c67c3c321bafdd7e7a50155de081f78ea3e0ed92ecc75a9015e784f301efc8132383132f4f7904ad1ac529c562 languageName: node linkType: hard "brace-expansion@npm:^2.0.1": - version: 2.0.1 - resolution: "brace-expansion@npm:2.0.1" + version: 2.0.2 + resolution: "brace-expansion@npm:2.0.2" dependencies: balanced-match: "npm:^1.0.0" - checksum: 10/a61e7cd2e8a8505e9f0036b3b6108ba5e926b4b55089eeb5550cd04a471fe216c96d4fe7e4c7f995c728c554ae20ddfc4244cad10aef255e72b62930afd233d1 + checksum: 10/01dff195e3646bc4b0d27b63d9bab84d2ebc06121ff5013ad6e5356daa5a9d6b60fa26cf73c74797f2dc3fbec112af13578d51f75228c1112b26c790a87b0488 + languageName: node + linkType: hard + +"brace-expansion@npm:^5.0.2": + version: 5.0.3 + resolution: "brace-expansion@npm:5.0.3" + dependencies: + balanced-match: "npm:^4.0.2" + checksum: 10/8ba7deae4ca333d52418d2cde3287ac23f44f7330d92c3ecd96a8941597bea8aab02227bd990944d6711dd549bcc6e550fe70be5d94aa02e2fdc88942f480c9b languageName: node linkType: hard @@ -7007,16 +7307,17 @@ __metadata: linkType: hard "browserslist@npm:^4.24.0": - version: 4.24.4 - resolution: "browserslist@npm:4.24.4" - dependencies: - caniuse-lite: "npm:^1.0.30001688" - electron-to-chromium: "npm:^1.5.73" - node-releases: "npm:^2.0.19" - update-browserslist-db: "npm:^1.1.1" + version: 4.28.1 + resolution: "browserslist@npm:4.28.1" + dependencies: + baseline-browser-mapping: "npm:^2.9.0" + caniuse-lite: "npm:^1.0.30001759" + electron-to-chromium: "npm:^1.5.263" + node-releases: "npm:^2.0.27" + update-browserslist-db: "npm:^1.2.0" bin: browserslist: cli.js - checksum: 10/11fda105e803d891311a21a1f962d83599319165faf471c2d70e045dff82a12128f5b50b1fcba665a2352ad66147aaa248a9d2355a80aadc3f53375eb3de2e48 + checksum: 10/64f2a97de4bce8473c0e5ae0af8d76d1ead07a5b05fc6bc87b848678bb9c3a91ae787b27aa98cdd33fc00779607e6c156000bed58fefb9cf8e4c5a183b994cdb languageName: node linkType: hard @@ -7091,30 +7392,29 @@ __metadata: languageName: node linkType: hard -"bytes@npm:3.1.2": +"bytes@npm:~3.1.2": version: 3.1.2 resolution: "bytes@npm:3.1.2" checksum: 10/a10abf2ba70c784471d6b4f58778c0beeb2b5d405148e66affa91f23a9f13d07603d0a0354667310ae1d6dc141474ffd44e2a074be0f6e2254edb8fc21445388 languageName: node linkType: hard -"cacache@npm:^18.0.0": - version: 18.0.4 - resolution: "cacache@npm:18.0.4" +"cacache@npm:^20.0.1": + version: 20.0.3 + resolution: "cacache@npm:20.0.3" dependencies: - "@npmcli/fs": "npm:^3.1.0" + "@npmcli/fs": "npm:^5.0.0" fs-minipass: "npm:^3.0.0" - glob: "npm:^10.2.2" - lru-cache: "npm:^10.0.1" + glob: "npm:^13.0.0" + lru-cache: "npm:^11.1.0" minipass: "npm:^7.0.3" minipass-collect: "npm:^2.0.1" minipass-flush: "npm:^1.0.5" minipass-pipeline: "npm:^1.2.4" - p-map: "npm:^4.0.0" - ssri: "npm:^10.0.0" - tar: "npm:^6.1.11" - unique-filename: "npm:^3.0.0" - checksum: 10/ca2f7b2d3003f84d362da9580b5561058ccaecd46cba661cbcff0375c90734b610520d46b472a339fd032d91597ad6ed12dde8af81571197f3c9772b5d35b104 + p-map: "npm:^7.0.2" + ssri: "npm:^13.0.0" + unique-filename: "npm:^5.0.0" + checksum: 10/388a0169970df9d051da30437f93f81b7e91efb570ad0ff2b8fde33279fbe726c1bc8e8e2b9c05053ffb4f563854c73db395e8712e3b62347a1bc4f7fb8899ff languageName: node linkType: hard @@ -7128,7 +7428,7 @@ __metadata: languageName: node linkType: hard -"call-bind@npm:^1.0.7": +"call-bind@npm:^1.0.8": version: 1.0.8 resolution: "call-bind@npm:1.0.8" dependencies: @@ -7140,6 +7440,16 @@ __metadata: languageName: node linkType: hard +"call-bound@npm:^1.0.2, call-bound@npm:^1.0.3, call-bound@npm:^1.0.4": + version: 1.0.4 + resolution: "call-bound@npm:1.0.4" + dependencies: + call-bind-apply-helpers: "npm:^1.0.2" + get-intrinsic: "npm:^1.3.0" + checksum: 10/ef2b96e126ec0e58a7ff694db43f4d0d44f80e641370c21549ed911fecbdbc2df3ebc9bddad918d6bbdefeafb60bb3337902006d5176d72bcd2da74820991af7 + languageName: node + linkType: hard + "callsite@npm:^1.0.0": version: 1.0.0 resolution: "callsite@npm:1.0.0" @@ -7179,10 +7489,10 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.30001688": - version: 1.0.30001690 - resolution: "caniuse-lite@npm:1.0.30001690" - checksum: 10/9fb4659eb09a298601b9593739072c481e2f5cc524bd0530e5e0f002e66246da5e866669854dfc0d53195ee36b201dab02f7933a7cdf60ccba7adb2d4a304caf +"caniuse-lite@npm:^1.0.30001759": + version: 1.0.30001774 + resolution: "caniuse-lite@npm:1.0.30001774" + checksum: 10/63c87aeac08548847ecd12746144029761707d9eae57750f673543a2b2a6126bca98584dd551818e8dc2a480d11489bebe0027af26de4ee46466e7b216109862 languageName: node linkType: hard @@ -7196,10 +7506,10 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^5.3.0": - version: 5.3.0 - resolution: "chalk@npm:5.3.0" - checksum: 10/6373caaab21bd64c405bfc4bd9672b145647fc9482657b5ea1d549b3b2765054e9d3d928870cdf764fb4aad67555f5061538ff247b8310f110c5c888d92397ea +"chalk@npm:^5.3.0, chalk@npm:^5.4.1": + version: 5.6.2 + resolution: "chalk@npm:5.6.2" + checksum: 10/1b2f48f6fba1370670d5610f9cd54c391d6ede28f4b7062dd38244ea5768777af72e5be6b74fb6c6d54cb84c4a2dff3f3afa9b7cb5948f7f022cfd3d087989e0 languageName: node linkType: hard @@ -7210,13 +7520,6 @@ __metadata: languageName: node linkType: hard -"chownr@npm:^2.0.0": - version: 2.0.0 - resolution: "chownr@npm:2.0.0" - checksum: 10/c57cf9dd0791e2f18a5ee9c1a299ae6e801ff58fee96dc8bfd0dcb4738a6ce58dd252a3605b1c93c6418fe4f9d5093b28ffbf4d66648cb2a9c67eaef9679be2f - languageName: node - linkType: hard - "chownr@npm:^3.0.0": version: 3.0.0 resolution: "chownr@npm:3.0.0" @@ -7238,27 +7541,28 @@ __metadata: languageName: node linkType: hard -"cipher-base@npm:^1.0.0, cipher-base@npm:^1.0.1, cipher-base@npm:^1.0.3": - version: 1.0.4 - resolution: "cipher-base@npm:1.0.4" - dependencies: - inherits: "npm:^2.0.1" - safe-buffer: "npm:^5.0.1" - checksum: 10/3d5d6652ca499c3f7c5d7fdc2932a357ec1e5aa84f2ad766d850efd42e89753c97b795c3a104a8e7ae35b4e293f5363926913de3bf8181af37067d9d541ca0db +"ci-info@npm:^4.2.0": + version: 4.4.0 + resolution: "ci-info@npm:4.4.0" + checksum: 10/dfded0c630267d89660c8abb988ac8395a382bdfefedcc03e3e2858523312c5207db777c239c34774e3fcff11f015477c19d2ac8a58ea58aa476614a2e64f434 languageName: node linkType: hard -"cjs-module-lexer@npm:^1.0.0, cjs-module-lexer@npm:^1.3.1": - version: 1.4.0 - resolution: "cjs-module-lexer@npm:1.4.0" - checksum: 10/b041096749792526120d8b8756929f8ef5dd4596502a0e1013f857e3027acd6091915fea77037921d70ee1a99988a100d994d3d3c2e323b04dd4c5ffd516cf13 +"cipher-base@npm:^1.0.0, cipher-base@npm:^1.0.1, cipher-base@npm:^1.0.3": + version: 1.0.7 + resolution: "cipher-base@npm:1.0.7" + dependencies: + inherits: "npm:^2.0.4" + safe-buffer: "npm:^5.2.1" + to-buffer: "npm:^1.2.2" + checksum: 10/9501d2241b7968aaae74fc3db1d6a69a804e0b14117a8fd5d811edf351fcd39a1807bfd98e090a799cfe98b183fbf2e01ebb57f1239080850db07b68dcd9ba02 languageName: node linkType: hard -"clean-stack@npm:^2.0.0": - version: 2.2.0 - resolution: "clean-stack@npm:2.2.0" - checksum: 10/2ac8cd2b2f5ec986a3c743935ec85b07bc174d5421a5efc8017e1f146a1cf5f781ae962618f416352103b32c9cd7e203276e8c28241bbe946160cab16149fb68 +"cjs-module-lexer@npm:^1.0.0, cjs-module-lexer@npm:^1.3.1": + version: 1.4.3 + resolution: "cjs-module-lexer@npm:1.4.3" + checksum: 10/d2b92f919a2dedbfd61d016964fce8da0035f827182ed6839c97cac56e8a8077cfa6a59388adfe2bc588a19cef9bbe830d683a76a6e93c51f65852062cfe2591 languageName: node linkType: hard @@ -7320,9 +7624,9 @@ __metadata: linkType: hard "collect-v8-coverage@npm:^1.0.0": - version: 1.0.2 - resolution: "collect-v8-coverage@npm:1.0.2" - checksum: 10/30ea7d5c9ee51f2fdba4901d4186c5b7114a088ef98fd53eda3979da77eed96758a2cae81cc6d97e239aaea6065868cf908b24980663f7b7e96aa291b3e12fa4 + version: 1.0.3 + resolution: "collect-v8-coverage@npm:1.0.3" + checksum: 10/656443261fb7b79cf79e89cba4b55622b07c1d4976c630829d7c5c585c73cda1c2ff101f316bfb19bb9e2c58d724c7db1f70a21e213dcd14099227c5e6019860 languageName: node linkType: hard @@ -7351,10 +7655,10 @@ __metadata: languageName: node linkType: hard -"commander@npm:^12.1.0": - version: 12.1.0 - resolution: "commander@npm:12.1.0" - checksum: 10/cdaeb672d979816853a4eed7f1310a9319e8b976172485c2a6b437ed0db0a389a44cfb222bfbde772781efa9f215bdd1b936f80d6b249485b465c6cb906e1f93 +"commander@npm:^14.0.0": + version: 14.0.3 + resolution: "commander@npm:14.0.3" + checksum: 10/dfa9ebe2a433d277de5cb0252d23b10a543d245d892db858d23b516336a835c50fd4f52bee4cd13c705cc8acb6f03dc632c73dd806f7d06d3353eb09953dd17a languageName: node linkType: hard @@ -7383,6 +7687,13 @@ __metadata: languageName: node linkType: hard +"comment-parser@npm:^1.4.1": + version: 1.4.5 + resolution: "comment-parser@npm:1.4.5" + checksum: 10/4b5cacc7ab1ec48e3f51b788bd7cda567f5c83040e029e5c92eacf0785735a9b44ac49fdaf73d9bd4af9464aa4cc8cc7184902090b55b0023605a845f2666ba4 + languageName: node + linkType: hard + "concat-map@npm:0.0.1": version: 0.0.1 resolution: "concat-map@npm:0.0.1" @@ -7402,7 +7713,7 @@ __metadata: languageName: node linkType: hard -"content-disposition@npm:0.5.4": +"content-disposition@npm:~0.5.4": version: 0.5.4 resolution: "content-disposition@npm:0.5.4" dependencies: @@ -7419,30 +7730,30 @@ __metadata: linkType: hard "contentful-resolve-response@npm:^1.9.0": - version: 1.9.0 - resolution: "contentful-resolve-response@npm:1.9.0" + version: 1.9.6 + resolution: "contentful-resolve-response@npm:1.9.6" dependencies: - fast-copy: "npm:^2.1.7" - checksum: 10/0c5daa59a3a6b020f9b5316812e3f14e62833b4aead008527c5bfde6549365e8e8e9f373af8836f06ca7b2023d861fdd2c241d3e74d3797133d18983be8bb3b3 + fast-copy: "npm:^3.0.2" + checksum: 10/ce77702a19c090eafc5e3e3b371ecf2531d6d149d450a36098d76e0888a7046c95ebabbe110643ad5824dbf6eedb13693fe4dd81f914c467dea6c6a50058d541 languageName: node linkType: hard "contentful-sdk-core@npm:^8.3.1": - version: 8.3.1 - resolution: "contentful-sdk-core@npm:8.3.1" + version: 8.3.2 + resolution: "contentful-sdk-core@npm:8.3.2" dependencies: fast-copy: "npm:^2.1.7" lodash.isplainobject: "npm:^4.0.6" lodash.isstring: "npm:^4.0.1" p-throttle: "npm:^4.1.1" qs: "npm:^6.11.2" - checksum: 10/645d3a5d296d0e2a5ce87cceb04cf1ddf572183b5946cb1b3b717436bc7be96864216225fb845e61850d580436021c6284e7c95da0600a16c89c0af81a5f0d2c + checksum: 10/4af0aba2bb7e3db3ebf260fea74843de89f150f5af883134c370eb695fd8b2587cf94d4524d03020286f565eb3bff7b12d42f2a38718b62eb75cb28556e40f42 languageName: node linkType: hard "contentful@npm:^10.15.0": - version: 10.15.0 - resolution: "contentful@npm:10.15.0" + version: 10.15.1 + resolution: "contentful@npm:10.15.1" dependencies: "@contentful/content-source-maps": "npm:^0.11.0" "@contentful/rich-text-types": "npm:^16.0.2" @@ -7451,7 +7762,7 @@ __metadata: contentful-sdk-core: "npm:^8.3.1" json-stringify-safe: "npm:^5.0.1" type-fest: "npm:^4.0.0" - checksum: 10/b57c51faa99074a2f60c930c4827d1f8fe9867a359e53738532bbe859f5d72e750645fa4e195e65ad015811f344d95a0b3cebe6debef7d4e92ce9510bd55939e + checksum: 10/eb913a79e38d87bc7fb3a79952e4d7c5a1de5cccfbe0a012e8131c9c1e5a0a525cfcb7eaea971b02fb9e57b9e49c71ce96dd7096c3f65483992017ef70de80e5 languageName: node linkType: hard @@ -7462,17 +7773,17 @@ __metadata: languageName: node linkType: hard -"cookie-signature@npm:1.0.6": - version: 1.0.6 - resolution: "cookie-signature@npm:1.0.6" - checksum: 10/f4e1b0a98a27a0e6e66fd7ea4e4e9d8e038f624058371bf4499cfcd8f3980be9a121486995202ba3fca74fbed93a407d6d54d43a43f96fd28d0bd7a06761591a +"cookie-signature@npm:~1.0.6": + version: 1.0.7 + resolution: "cookie-signature@npm:1.0.7" + checksum: 10/1a62808cd30d15fb43b70e19829b64d04b0802d8ef00275b57d152de4ae6a3208ca05c197b6668d104c4d9de389e53ccc2d3bc6bcaaffd9602461417d8c40710 languageName: node linkType: hard -"cookie@npm:0.7.1": - version: 0.7.1 - resolution: "cookie@npm:0.7.1" - checksum: 10/aec6a6aa0781761bf55d60447d6be08861d381136a0fe94aa084fddd4f0300faa2b064df490c6798adfa1ebaef9e0af9b08a189c823e0811b8b313b3d9a03380 +"cookie@npm:~0.7.1": + version: 0.7.2 + resolution: "cookie@npm:0.7.2" + checksum: 10/24b286c556420d4ba4e9bc09120c9d3db7d28ace2bd0f8ccee82422ce42322f73c8312441271e5eefafbead725980e5996cc02766dbb89a90ac7f5636ede608f languageName: node linkType: hard @@ -7525,7 +7836,7 @@ __metadata: languageName: node linkType: hard -"create-hmac@npm:^1.1.4, create-hmac@npm:^1.1.7": +"create-hmac@npm:^1.1.7": version: 1.1.7 resolution: "create-hmac@npm:1.1.7" dependencies: @@ -7565,7 +7876,7 @@ __metadata: languageName: node linkType: hard -"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.3, cross-spawn@npm:^7.0.6": +"cross-spawn@npm:^7.0.3, cross-spawn@npm:^7.0.6": version: 7.0.6 resolution: "cross-spawn@npm:7.0.6" dependencies: @@ -7619,7 +7930,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.3.6, debug@npm:^4.3.7, debug@npm:^4.4.3": +"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.4.0, debug@npm:^4.4.1, debug@npm:^4.4.3": version: 4.4.3 resolution: "debug@npm:4.4.3" dependencies: @@ -7631,15 +7942,6 @@ __metadata: languageName: node linkType: hard -"debug@npm:^3.2.7": - version: 3.2.7 - resolution: "debug@npm:3.2.7" - dependencies: - ms: "npm:^2.1.1" - checksum: 10/d86fd7be2b85462297ea16f1934dc219335e802f629ca9a69b63ed8ed041dda492389bb2ee039217c02e5b54792b1c51aa96ae954cf28634d363a2360c7a1639 - languageName: node - linkType: hard - "decamelize-keys@npm:^1.1.0": version: 1.1.1 resolution: "decamelize-keys@npm:1.1.1" @@ -7698,19 +8000,19 @@ __metadata: linkType: hard "default-browser-id@npm:^5.0.0": - version: 5.0.0 - resolution: "default-browser-id@npm:5.0.0" - checksum: 10/185bfaecec2c75fa423544af722a3469b20704c8d1942794a86e4364fe7d9e8e9f63241a5b769d61c8151993bc65833a5b959026fa1ccea343b3db0a33aa6deb + version: 5.0.1 + resolution: "default-browser-id@npm:5.0.1" + checksum: 10/52c637637bcd76bfe974462a2f1dd75cb04784c2852935575760f82e1fd338e5e80d3c45a9b01fdbb1e450553a830bb163b004d2eca223c5573989f82232a072 languageName: node linkType: hard "default-browser@npm:^5.2.1": - version: 5.2.1 - resolution: "default-browser@npm:5.2.1" + version: 5.5.0 + resolution: "default-browser@npm:5.5.0" dependencies: bundle-name: "npm:^4.1.0" default-browser-id: "npm:^5.0.0" - checksum: 10/afab7eff7b7f5f7a94d9114d1ec67273d3fbc539edf8c0f80019879d53aa71e867303c6f6d7cffeb10a6f3cfb59d4f963dba3f9c96830b4540cc7339a1bf9840 + checksum: 10/c5c5d84a4abd82850e98f06798a55dee87fc1064538bea00cc14c0fb2dccccbff5e9e07eeea80385fa653202d5d92509838b4239d610ddfa1c76a04a1f65e767 languageName: node linkType: hard @@ -7772,7 +8074,7 @@ __metadata: languageName: node linkType: hard -"depd@npm:2.0.0": +"depd@npm:2.0.0, depd@npm:~2.0.0": version: 2.0.0 resolution: "depd@npm:2.0.0" checksum: 10/c0c8ff36079ce5ada64f46cc9d6fd47ebcf38241105b6e0c98f412e8ad91f084bcf906ff644cc3a4bd876ca27a62accb8b0fff72ea6ed1a414b89d8506f4a5ca @@ -7786,7 +8088,7 @@ __metadata: languageName: node linkType: hard -"destroy@npm:1.2.0": +"destroy@npm:1.2.0, destroy@npm:~1.2.0": version: 1.2.0 resolution: "destroy@npm:1.2.0" checksum: 10/0acb300b7478a08b92d810ab229d5afe0d2f4399272045ab22affa0d99dbaf12637659411530a6fcd597a9bdac718fc94373a61a95b4651bbc7b83684a565e38 @@ -7807,10 +8109,10 @@ __metadata: languageName: node linkType: hard -"detect-indent@npm:^7.0.1": - version: 7.0.1 - resolution: "detect-indent@npm:7.0.1" - checksum: 10/cbf3f0b1c3c881934ca94428e1179b26ab2a587e0d719031d37a67fb506d49d067de54ff057cb1e772e75975fed5155c01cd4518306fee60988b1486e3fc7768 +"detect-indent@npm:^7.0.2": + version: 7.0.2 + resolution: "detect-indent@npm:7.0.2" + checksum: 10/ef215d1b55a14f677ce03e840973b25362b6f8cd3f566bc82831fa1abb2be6a95423729bc573dc2334b1371ad7be18d9ec67e1a9611b71a04cb6d63f0d8e54cc languageName: node linkType: hard @@ -7821,7 +8123,7 @@ __metadata: languageName: node linkType: hard -"detect-newline@npm:^4.0.0": +"detect-newline@npm:^4.0.1": version: 4.0.1 resolution: "detect-newline@npm:4.0.1" checksum: 10/0409ecdfb93419591ccff24fccfe2ddddad29b66637d1ed898872125b25af05014fdeedc9306339577060f69f59fe6e9830cdd80948597f136dfbffefa60599c @@ -7843,9 +8145,9 @@ __metadata: linkType: hard "diff@npm:^5.0.0": - version: 5.2.0 - resolution: "diff@npm:5.2.0" - checksum: 10/01b7b440f83a997350a988e9d2f558366c0f90f15be19f4aa7f1bb3109a4e153dfc3b9fbf78e14ea725717017407eeaa2271e3896374a0181e8f52445740846d + version: 5.2.2 + resolution: "diff@npm:5.2.2" + checksum: 10/8a885b38113d96138d87f6cb474ee959b7e9ab33c0c4cb1b07dcf019ec544945a2309d53d721532af020de4b3a58fb89f1026f64f42f9421aa9c3ae48a36998b languageName: node linkType: hard @@ -7858,15 +8160,6 @@ __metadata: languageName: node linkType: hard -"doctrine@npm:^3.0.0": - version: 3.0.0 - resolution: "doctrine@npm:3.0.0" - dependencies: - esutils: "npm:^2.0.2" - checksum: 10/b4b28f1df5c563f7d876e7461254a4597b8cabe915abe94d7c5d1633fed263fcf9a85e8d3836591fc2d040108e822b0d32758e5ec1fe31c590dc7e08086e3e48 - languageName: node - linkType: hard - "domexception@npm:^4.0.0": version: 4.0.0 resolution: "domexception@npm:4.0.0" @@ -7910,10 +8203,10 @@ __metadata: languageName: node linkType: hard -"electron-to-chromium@npm:^1.5.73": - version: 1.5.79 - resolution: "electron-to-chromium@npm:1.5.79" - checksum: 10/c5b25ba04b4f4b46c4024b96e00e43adcd6c321b48c74c8d2660f69704901da5a6592009cbf96c36c89e3f6b53d7742e2b89514477fddbccf4e5c4caebed9d49 +"electron-to-chromium@npm:^1.5.263": + version: 1.5.302 + resolution: "electron-to-chromium@npm:1.5.302" + checksum: 10/0d31470d04a0d1ea046dd363370081b67e6fe822949b10cfece0a64fd2f8180afb5ccaf14f4294251e444a0af627eb0dc0156242b714c0f10561adf2a21aa5f7 languageName: node linkType: hard @@ -7953,13 +8246,6 @@ __metadata: languageName: node linkType: hard -"encodeurl@npm:~1.0.2": - version: 1.0.2 - resolution: "encodeurl@npm:1.0.2" - checksum: 10/e50e3d508cdd9c4565ba72d2012e65038e5d71bdc9198cb125beb6237b5b1ade6c0d343998da9e170fb2eae52c1bed37d4d6d98a46ea423a0cddbed5ac3f780c - languageName: node - linkType: hard - "encodeurl@npm:~2.0.0": version: 2.0.0 resolution: "encodeurl@npm:2.0.0" @@ -7967,29 +8253,13 @@ __metadata: languageName: node linkType: hard -"encoding@npm:^0.1.13": - version: 0.1.13 - resolution: "encoding@npm:0.1.13" - dependencies: - iconv-lite: "npm:^0.6.2" - checksum: 10/bb98632f8ffa823996e508ce6a58ffcf5856330fde839ae42c9e1f436cc3b5cc651d4aeae72222916545428e54fd0f6aa8862fd8d25bdbcc4589f1e3f3715e7f - languageName: node - linkType: hard - -"enhanced-resolve@npm:^5.15.0, enhanced-resolve@npm:^5.17.1": - version: 5.18.0 - resolution: "enhanced-resolve@npm:5.18.0" +"enhanced-resolve@npm:^5.17.1": + version: 5.19.0 + resolution: "enhanced-resolve@npm:5.19.0" dependencies: graceful-fs: "npm:^4.2.4" - tapable: "npm:^2.2.0" - checksum: 10/e88463ef97b68d40d0da0cd0c572e23f43dba0be622d6d44eae5cafed05f0c5dac43e463a83a86c4f70186d029357f82b56d9e1e47e8fc91dce3d6602f8bd6ce - languageName: node - linkType: hard - -"entities@npm:^4.5.0": - version: 4.5.0 - resolution: "entities@npm:4.5.0" - checksum: 10/ede2a35c9bce1aeccd055a1b445d41c75a14a2bb1cd22e242f20cf04d236cdcd7f9c859eb83f76885327bfae0c25bf03303665ee1ce3d47c5927b98b0e3e3d48 + tapable: "npm:^2.3.0" + checksum: 10/b537d52173bf1ba903c623f96a43ea3b51466ee2b606b2fcca30d73d453fd79c8683dccbb83523de27cd02763c906f11486e2591a4335e6afe49fa5ad6e67b83 languageName: node linkType: hard @@ -8000,6 +8270,13 @@ __metadata: languageName: node linkType: hard +"entities@npm:^7.0.1": + version: 7.0.1 + resolution: "entities@npm:7.0.1" + checksum: 10/3c0c58d869c45148463e96d21dee2d1b801bd3fe4cf47aa470cd26dfe81d59e9e0a9be92ae083fa02fa441283c883a471486e94538dcfb8544428aa80a55271b + languageName: node + linkType: hard + "env-paths@npm:^2.2.0": version: 2.2.1 resolution: "env-paths@npm:2.2.1" @@ -8015,11 +8292,11 @@ __metadata: linkType: hard "error-ex@npm:^1.3.1": - version: 1.3.2 - resolution: "error-ex@npm:1.3.2" + version: 1.3.4 + resolution: "error-ex@npm:1.3.4" dependencies: is-arrayish: "npm:^0.2.1" - checksum: 10/d547740aa29c34e753fb6fed2c5de81802438529c12b3673bd37b6bb1fe49b9b7abdc3c11e6062fe625d8a296b3cf769a80f878865e25e685f787763eede3ffb + checksum: 10/ae3939fd4a55b1404e877df2080c6b59acc516d5b7f08a181040f78f38b4e2399633bfed2d9a21b91c803713fff7295ac70bebd8f3657ef352a95c2cd9aa2e4b languageName: node linkType: hard @@ -8037,13 +8314,6 @@ __metadata: languageName: node linkType: hard -"es-module-lexer@npm:^1.5.3": - version: 1.6.0 - resolution: "es-module-lexer@npm:1.6.0" - checksum: 10/807ee7020cc46a9c970c78cad1f2f3fc139877e5ebad7f66dbfbb124d451189ba1c48c1c632bd5f8ce1b8af2caef3fca340ba044a410fa890d17b080a59024bb - languageName: node - linkType: hard - "es-object-atoms@npm:^1.0.0, es-object-atoms@npm:^1.1.1": version: 1.1.1 resolution: "es-object-atoms@npm:1.1.1" @@ -8053,36 +8323,48 @@ __metadata: languageName: node linkType: hard -"esbuild@npm:~0.25.0": - version: 0.25.9 - resolution: "esbuild@npm:0.25.9" - dependencies: - "@esbuild/aix-ppc64": "npm:0.25.9" - "@esbuild/android-arm": "npm:0.25.9" - "@esbuild/android-arm64": "npm:0.25.9" - "@esbuild/android-x64": "npm:0.25.9" - "@esbuild/darwin-arm64": "npm:0.25.9" - "@esbuild/darwin-x64": "npm:0.25.9" - "@esbuild/freebsd-arm64": "npm:0.25.9" - "@esbuild/freebsd-x64": "npm:0.25.9" - "@esbuild/linux-arm": "npm:0.25.9" - "@esbuild/linux-arm64": "npm:0.25.9" - "@esbuild/linux-ia32": "npm:0.25.9" - "@esbuild/linux-loong64": "npm:0.25.9" - "@esbuild/linux-mips64el": "npm:0.25.9" - "@esbuild/linux-ppc64": "npm:0.25.9" - "@esbuild/linux-riscv64": "npm:0.25.9" - "@esbuild/linux-s390x": "npm:0.25.9" - "@esbuild/linux-x64": "npm:0.25.9" - "@esbuild/netbsd-arm64": "npm:0.25.9" - "@esbuild/netbsd-x64": "npm:0.25.9" - "@esbuild/openbsd-arm64": "npm:0.25.9" - "@esbuild/openbsd-x64": "npm:0.25.9" - "@esbuild/openharmony-arm64": "npm:0.25.9" - "@esbuild/sunos-x64": "npm:0.25.9" - "@esbuild/win32-arm64": "npm:0.25.9" - "@esbuild/win32-ia32": "npm:0.25.9" - "@esbuild/win32-x64": "npm:0.25.9" +"es-set-tostringtag@npm:^2.1.0": + version: 2.1.0 + resolution: "es-set-tostringtag@npm:2.1.0" + dependencies: + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.6" + has-tostringtag: "npm:^1.0.2" + hasown: "npm:^2.0.2" + checksum: 10/86814bf8afbcd8966653f731415888019d4bc4aca6b6c354132a7a75bb87566751e320369654a101d23a91c87a85c79b178bcf40332839bd347aff437c4fb65f + languageName: node + linkType: hard + +"esbuild@npm:~0.27.0": + version: 0.27.3 + resolution: "esbuild@npm:0.27.3" + dependencies: + "@esbuild/aix-ppc64": "npm:0.27.3" + "@esbuild/android-arm": "npm:0.27.3" + "@esbuild/android-arm64": "npm:0.27.3" + "@esbuild/android-x64": "npm:0.27.3" + "@esbuild/darwin-arm64": "npm:0.27.3" + "@esbuild/darwin-x64": "npm:0.27.3" + "@esbuild/freebsd-arm64": "npm:0.27.3" + "@esbuild/freebsd-x64": "npm:0.27.3" + "@esbuild/linux-arm": "npm:0.27.3" + "@esbuild/linux-arm64": "npm:0.27.3" + "@esbuild/linux-ia32": "npm:0.27.3" + "@esbuild/linux-loong64": "npm:0.27.3" + "@esbuild/linux-mips64el": "npm:0.27.3" + "@esbuild/linux-ppc64": "npm:0.27.3" + "@esbuild/linux-riscv64": "npm:0.27.3" + "@esbuild/linux-s390x": "npm:0.27.3" + "@esbuild/linux-x64": "npm:0.27.3" + "@esbuild/netbsd-arm64": "npm:0.27.3" + "@esbuild/netbsd-x64": "npm:0.27.3" + "@esbuild/openbsd-arm64": "npm:0.27.3" + "@esbuild/openbsd-x64": "npm:0.27.3" + "@esbuild/openharmony-arm64": "npm:0.27.3" + "@esbuild/sunos-x64": "npm:0.27.3" + "@esbuild/win32-arm64": "npm:0.27.3" + "@esbuild/win32-ia32": "npm:0.27.3" + "@esbuild/win32-x64": "npm:0.27.3" dependenciesMeta: "@esbuild/aix-ppc64": optional: true @@ -8138,7 +8420,7 @@ __metadata: optional: true bin: esbuild: bin/esbuild - checksum: 10/fc174ae7f646ad413adb641c7e46f16be575e462ed209866b55d5954d382e5da839e3f3f89a8e42e2b71d48895cc636ba43523011249fe5ff9c63d8d39d3a364 + checksum: 10/aa74b8d8a3ed8e2eea4d8421737b322f4d21215244e8fa2156c6402d49b5bda01343c220196f1e3f830a7ce92b54ef653c6c723a8cc2e912bb4d17b7398b51ae languageName: node linkType: hard @@ -8200,13 +8482,13 @@ __metadata: linkType: hard "eslint-config-prettier@npm:^9.1.0": - version: 9.1.0 - resolution: "eslint-config-prettier@npm:9.1.0" + version: 9.1.2 + resolution: "eslint-config-prettier@npm:9.1.2" peerDependencies: eslint: ">=7.0.0" bin: eslint-config-prettier: bin/cli.js - checksum: 10/411e3b3b1c7aa04e3e0f20d561271b3b909014956c4dba51c878bf1a23dbb8c800a3be235c46c4732c70827276e540b6eed4636d9b09b444fd0a8e07f0fcd830 + checksum: 10/e4bba2d76df9dc6e2adca2866e544bfd1ff32232fc483743c04cedd93918a90a327b56d4a7e3f9d3fa32d90bd50b034d09df987860260064b18c026b8bbd15aa languageName: node linkType: hard @@ -8226,29 +8508,32 @@ __metadata: languageName: node linkType: hard -"eslint-import-resolver-node@npm:^0.3.9": - version: 0.3.9 - resolution: "eslint-import-resolver-node@npm:0.3.9" +"eslint-import-context@npm:^0.1.9": + version: 0.1.9 + resolution: "eslint-import-context@npm:0.1.9" dependencies: - debug: "npm:^3.2.7" - is-core-module: "npm:^2.13.0" - resolve: "npm:^1.22.4" - checksum: 10/d52e08e1d96cf630957272e4f2644dcfb531e49dcfd1edd2e07e43369eb2ec7a7d4423d417beee613201206ff2efa4eb9a582b5825ee28802fc7c71fcd53ca83 + get-tsconfig: "npm:^4.10.1" + stable-hash-x: "npm:^0.2.0" + peerDependencies: + unrs-resolver: ^1.0.0 + peerDependenciesMeta: + unrs-resolver: + optional: true + checksum: 10/f0778126bb3aae57c8c68946c71c4418927e9d39f72099b799d9c47a3b5712d6c9166b63ee8be58a020961dcc9216df09c856b825336af375ccbbdeedfc82a99 languageName: node linkType: hard "eslint-import-resolver-typescript@npm:^3.6.3": - version: 3.7.0 - resolution: "eslint-import-resolver-typescript@npm:3.7.0" + version: 3.10.1 + resolution: "eslint-import-resolver-typescript@npm:3.10.1" dependencies: "@nolyfill/is-core-module": "npm:1.0.39" - debug: "npm:^4.3.7" - enhanced-resolve: "npm:^5.15.0" - fast-glob: "npm:^3.3.2" - get-tsconfig: "npm:^4.7.5" - is-bun-module: "npm:^1.0.2" - is-glob: "npm:^4.0.3" - stable-hash: "npm:^0.0.4" + debug: "npm:^4.4.0" + get-tsconfig: "npm:^4.10.0" + is-bun-module: "npm:^2.0.0" + stable-hash: "npm:^0.0.5" + tinyglobby: "npm:^0.2.13" + unrs-resolver: "npm:^1.6.2" peerDependencies: eslint: "*" eslint-plugin-import: "*" @@ -8258,7 +8543,7 @@ __metadata: optional: true eslint-plugin-import-x: optional: true - checksum: 10/8158730c11e562c56ed9bf7236dc75bce35b6992dc32c39ac2f4177ab77fca97b95999850204a6458054243607b54aee88c028a61fed4184f24f425fa1afff01 + checksum: 10/b8d6a9b2045c70f043f722f78c9e65bc0283126f0ad92c8f07473f7647d77f7b1562f765a472f17e06b81897b407091c0ec9f2e4592b158c9fd92d0b0c33de89 languageName: node linkType: hard @@ -8276,31 +8561,34 @@ __metadata: linkType: hard "eslint-plugin-import-x@npm:^4.3.0": - version: 4.6.1 - resolution: "eslint-plugin-import-x@npm:4.6.1" + version: 4.16.1 + resolution: "eslint-plugin-import-x@npm:4.16.1" dependencies: - "@types/doctrine": "npm:^0.0.9" - "@typescript-eslint/scope-manager": "npm:^8.1.0" - "@typescript-eslint/utils": "npm:^8.1.0" - debug: "npm:^4.3.4" - doctrine: "npm:^3.0.0" - enhanced-resolve: "npm:^5.17.1" - eslint-import-resolver-node: "npm:^0.3.9" - get-tsconfig: "npm:^4.7.3" + "@typescript-eslint/types": "npm:^8.35.0" + comment-parser: "npm:^1.4.1" + debug: "npm:^4.4.1" + eslint-import-context: "npm:^0.1.9" is-glob: "npm:^4.0.3" - minimatch: "npm:^9.0.3" - semver: "npm:^7.6.3" - stable-hash: "npm:^0.0.4" - tslib: "npm:^2.6.3" + minimatch: "npm:^9.0.3 || ^10.0.1" + semver: "npm:^7.7.2" + stable-hash-x: "npm:^0.2.0" + unrs-resolver: "npm:^1.9.2" peerDependencies: + "@typescript-eslint/utils": ^8.0.0 eslint: ^8.57.0 || ^9.0.0 - checksum: 10/514d8147f7bdff4accbeb06c294b68670287ecdaada9b2fbd3a2ba89d35860095cadd5a4175894fc8e75ba3b2be83dc172eba5cc71b823fd0dd846b7d49877ff + eslint-import-resolver-node: "*" + peerDependenciesMeta: + "@typescript-eslint/utils": + optional: true + eslint-import-resolver-node: + optional: true + checksum: 10/d1390d49499b613c1334e48fe8b104221584a1473fbec8974584002561aacef5347c4450c559df6fe24c3abe3b0d167eefdc5510e794e96a4ea4f9cb1d501515 languageName: node linkType: hard "eslint-plugin-jest@npm:^28.8.3": - version: 28.10.0 - resolution: "eslint-plugin-jest@npm:28.10.0" + version: 28.14.0 + resolution: "eslint-plugin-jest@npm:28.14.0" dependencies: "@typescript-eslint/utils": "npm:^6.0.0 || ^7.0.0 || ^8.0.0" peerDependencies: @@ -8312,66 +8600,66 @@ __metadata: optional: true jest: optional: true - checksum: 10/cb19f2171e93873d9207425c4fa52ec49018579d73ece23a1ffea90f3ffd284b0e48f74ff4f50b15ff31882b06b03fec0e48c9c6ca830acdeff8931802ef0a9e + checksum: 10/6032497bd97d6dd010450d5fdf535b8613a2789f4f83764ae04361c48d06d92f3d9b2e4350914b8fd857b6e611ba2b5282a1133ab8ec51b3e7053f9d336058e6 languageName: node linkType: hard "eslint-plugin-jsdoc@npm:^50.2.4": - version: 50.6.1 - resolution: "eslint-plugin-jsdoc@npm:50.6.1" + version: 50.8.0 + resolution: "eslint-plugin-jsdoc@npm:50.8.0" dependencies: - "@es-joy/jsdoccomment": "npm:~0.49.0" + "@es-joy/jsdoccomment": "npm:~0.50.2" are-docs-informative: "npm:^0.0.2" comment-parser: "npm:1.4.1" - debug: "npm:^4.3.6" + debug: "npm:^4.4.1" escape-string-regexp: "npm:^4.0.0" - espree: "npm:^10.1.0" + espree: "npm:^10.3.0" esquery: "npm:^1.6.0" - parse-imports: "npm:^2.1.1" - semver: "npm:^7.6.3" + parse-imports-exports: "npm:^0.2.4" + semver: "npm:^7.7.2" spdx-expression-parse: "npm:^4.0.0" - synckit: "npm:^0.9.1" peerDependencies: eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 - checksum: 10/53fceff38a5317bb7c42c15a622100515aec89aea0d2bbf07e7d2d07eacdaa10ce625232a1bc7c1497f7bbe044675123d30cd3e123fa52fe5c7a9c336a59709c + checksum: 10/8857bb6583e04af0a1949e602e2b5b2abc5a951583bdc5a3baa0cc24f7c16db367cbc44e008c45b06dc2029685f0eb1ff6a0bb91e90fd82710ce30952d878d5d languageName: node linkType: hard "eslint-plugin-n@npm:^17.10.3": - version: 17.15.1 - resolution: "eslint-plugin-n@npm:17.15.1" + version: 17.24.0 + resolution: "eslint-plugin-n@npm:17.24.0" dependencies: - "@eslint-community/eslint-utils": "npm:^4.4.1" + "@eslint-community/eslint-utils": "npm:^4.5.0" enhanced-resolve: "npm:^5.17.1" eslint-plugin-es-x: "npm:^7.8.0" get-tsconfig: "npm:^4.8.1" globals: "npm:^15.11.0" + globrex: "npm:^0.1.2" ignore: "npm:^5.3.2" - minimatch: "npm:^9.0.5" semver: "npm:^7.6.3" + ts-declaration-location: "npm:^1.0.6" peerDependencies: eslint: ">=8.23.0" - checksum: 10/43fc161949fa0346ac7063a30580cd0db27e216b8e6a48d73d0bf4f10b88e9b65f263399843b3fe2087f766f264d16f0cbe8f2f898591516842201dc115a2d21 + checksum: 10/bbff1172f7297288d209f167febb3a31747838d5ed8050aa7d1aa2540a49b4f9932828831529f0306f2909e41ae3ae8848c145238a6990eae5a9d128a59b056c languageName: node linkType: hard "eslint-plugin-prettier@npm:^5.2.1": - version: 5.2.1 - resolution: "eslint-plugin-prettier@npm:5.2.1" + version: 5.5.5 + resolution: "eslint-plugin-prettier@npm:5.5.5" dependencies: - prettier-linter-helpers: "npm:^1.0.0" - synckit: "npm:^0.9.1" + prettier-linter-helpers: "npm:^1.0.1" + synckit: "npm:^0.11.12" peerDependencies: "@types/eslint": ">=8.0.0" eslint: ">=8.0.0" - eslint-config-prettier: "*" + eslint-config-prettier: ">= 7.0.0 <10.0.0 || >=10.1.0" prettier: ">=3.0.0" peerDependenciesMeta: "@types/eslint": optional: true eslint-config-prettier: optional: true - checksum: 10/10ddf68215237e327af09a47adab4c63f3885fda4fb28c4c42d1fc5f47d8a0cc45df6484799360ff1417a0aa3c77c3aaac49d7e9dfd145557b17e2d7ecc2a27c + checksum: 10/36c22c2fa2fd7c61ed292af1280e1d8f94dfe1671eacc5a503a249ca4b27fd226dbf6a1820457d611915926946f42729488d2dc7a5c320601e6cf1fad0d28f66 languageName: node linkType: hard @@ -8417,9 +8705,16 @@ __metadata: languageName: node linkType: hard +"eslint-visitor-keys@npm:^5.0.0": + version: 5.0.1 + resolution: "eslint-visitor-keys@npm:5.0.1" + checksum: 10/f9cc1a57b75e0ef949545cac33d01e8367e302de4c1483266ed4d8646ee5c306376660196bbb38b004e767b7043d1e661cb4336b49eff634a1bbe75c1db709ec + languageName: node + linkType: hard + "eslint@npm:^9.39.1": - version: 9.39.1 - resolution: "eslint@npm:9.39.1" + version: 9.39.3 + resolution: "eslint@npm:9.39.3" dependencies: "@eslint-community/eslint-utils": "npm:^4.8.0" "@eslint-community/regexpp": "npm:^4.12.1" @@ -8427,7 +8722,7 @@ __metadata: "@eslint/config-helpers": "npm:^0.4.2" "@eslint/core": "npm:^0.17.0" "@eslint/eslintrc": "npm:^3.3.1" - "@eslint/js": "npm:9.39.1" + "@eslint/js": "npm:9.39.3" "@eslint/plugin-kit": "npm:^0.4.1" "@humanfs/node": "npm:^0.16.6" "@humanwhocodes/module-importer": "npm:^1.0.1" @@ -8462,11 +8757,11 @@ __metadata: optional: true bin: eslint: bin/eslint.js - checksum: 10/c85fefe4a81a1a476e62087366907af830b62a6565ac153f6d50a100a42a946aeb049c3af8f06c0e091105ba0fe97ac109f379f32755a67f66ecb7d4d1e4dca3 + checksum: 10/1c95c92983ddf435e7f7d54edd06d703a15773a7d189583d3388e5b5ac714f0a2450b91c0b3bb9b9ccec9bd20994fd8e48d231ed6dabca0be56ef314b32820ff languageName: node linkType: hard -"espree@npm:^10.0.1, espree@npm:^10.1.0, espree@npm:^10.4.0": +"espree@npm:^10.0.1, espree@npm:^10.3.0, espree@npm:^10.4.0": version: 10.4.0 resolution: "espree@npm:10.4.0" dependencies: @@ -8488,11 +8783,11 @@ __metadata: linkType: hard "esquery@npm:^1.5.0, esquery@npm:^1.6.0": - version: 1.6.0 - resolution: "esquery@npm:1.6.0" + version: 1.7.0 + resolution: "esquery@npm:1.7.0" dependencies: estraverse: "npm:^5.1.0" - checksum: 10/c587fb8ec9ed83f2b1bc97cf2f6854cc30bf784a79d62ba08c6e358bf22280d69aee12827521cf38e69ae9761d23fb7fde593ce315610f85655c139d99b05e5a + checksum: 10/4afaf3089367e1f5885caa116ef386dffd8bfd64da21fd3d0e56e938d2667cfb2e5400ab4a825aa70e799bb3741e5b5d63c0b94d86e2d4cf3095c9e64b2f5a15 languageName: node linkType: hard @@ -8620,17 +8915,17 @@ __metadata: linkType: hard "ethers@npm:^6.12.0": - version: 6.13.2 - resolution: "ethers@npm:6.13.2" + version: 6.16.0 + resolution: "ethers@npm:6.16.0" dependencies: "@adraffy/ens-normalize": "npm:1.10.1" "@noble/curves": "npm:1.2.0" "@noble/hashes": "npm:1.3.2" - "@types/node": "npm:18.15.13" + "@types/node": "npm:22.7.5" aes-js: "npm:4.0.0-beta.5" - tslib: "npm:2.4.0" + tslib: "npm:2.7.0" ws: "npm:8.17.1" - checksum: 10/e611c2e2c5340982dfd1f004895f55abda11748a7edec9e6315226dec42d58aa61b827dd389ec904db5f9a244c475ae795e528da579251fdf62e914bde12809e + checksum: 10/7e980f0a77963fbe14321a3b9746c3ca3cad44932e28bb3506406a66c4b4d9dc1e60ed68d9d784224e9f2582a53d6a0a2e55a7c9559659681f4ad1f70e00e325 languageName: node linkType: hard @@ -8659,6 +8954,15 @@ __metadata: languageName: node linkType: hard +"events-universal@npm:^1.0.0": + version: 1.0.1 + resolution: "events-universal@npm:1.0.1" + dependencies: + bare-events: "npm:^2.7.0" + checksum: 10/71b2e6079b4dc030c613ef73d99f1acb369dd3ddb6034f49fd98b3e2c6632cde9f61c15fb1351004339d7c79672252a4694ecc46a6124dc794b558be50a83867 + languageName: node + linkType: hard + "events@npm:^3.3.0": version: 3.3.0 resolution: "events@npm:3.3.0" @@ -8740,49 +9044,63 @@ __metadata: languageName: node linkType: hard +"expect@npm:^30.0.0": + version: 30.2.0 + resolution: "expect@npm:30.2.0" + dependencies: + "@jest/expect-utils": "npm:30.2.0" + "@jest/get-type": "npm:30.1.0" + jest-matcher-utils: "npm:30.2.0" + jest-message-util: "npm:30.2.0" + jest-mock: "npm:30.2.0" + jest-util: "npm:30.2.0" + checksum: 10/cf98ab45ab2e9f2fb9943a3ae0097f72d63a94be179a19fd2818d8fdc3b7681d31cc8ef540606eb8dd967d9c44d73fef263a614e9de260c22943ffb122ad66fd + languageName: node + linkType: hard + "exponential-backoff@npm:^3.1.1": - version: 3.1.1 - resolution: "exponential-backoff@npm:3.1.1" - checksum: 10/2d9bbb6473de7051f96790d5f9a678f32e60ed0aa70741dc7fdc96fec8d631124ec3374ac144387604f05afff9500f31a1d45bd9eee4cdc2e4f9ad2d9b9d5dbd + version: 3.1.3 + resolution: "exponential-backoff@npm:3.1.3" + checksum: 10/ca25962b4bbab943b7c4ed0b5228e263833a5063c65e1cdeac4be9afad350aae5466e8e619b5051f4f8d37b2144a2d6e8fcc771b6cc82934f7dade2f964f652c languageName: node linkType: hard "express@npm:^4.21.2": - version: 4.21.2 - resolution: "express@npm:4.21.2" + version: 4.22.1 + resolution: "express@npm:4.22.1" dependencies: accepts: "npm:~1.3.8" array-flatten: "npm:1.1.1" - body-parser: "npm:1.20.3" - content-disposition: "npm:0.5.4" + body-parser: "npm:~1.20.3" + content-disposition: "npm:~0.5.4" content-type: "npm:~1.0.4" - cookie: "npm:0.7.1" - cookie-signature: "npm:1.0.6" + cookie: "npm:~0.7.1" + cookie-signature: "npm:~1.0.6" debug: "npm:2.6.9" depd: "npm:2.0.0" encodeurl: "npm:~2.0.0" escape-html: "npm:~1.0.3" etag: "npm:~1.8.1" - finalhandler: "npm:1.3.1" - fresh: "npm:0.5.2" - http-errors: "npm:2.0.0" + finalhandler: "npm:~1.3.1" + fresh: "npm:~0.5.2" + http-errors: "npm:~2.0.0" merge-descriptors: "npm:1.0.3" methods: "npm:~1.1.2" - on-finished: "npm:2.4.1" + on-finished: "npm:~2.4.1" parseurl: "npm:~1.3.3" - path-to-regexp: "npm:0.1.12" + path-to-regexp: "npm:~0.1.12" proxy-addr: "npm:~2.0.7" - qs: "npm:6.13.0" + qs: "npm:~6.14.0" range-parser: "npm:~1.2.1" safe-buffer: "npm:5.2.1" - send: "npm:0.19.0" - serve-static: "npm:1.16.2" + send: "npm:~0.19.0" + serve-static: "npm:~1.16.2" setprototypeof: "npm:1.2.0" - statuses: "npm:2.0.1" + statuses: "npm:~2.0.1" type-is: "npm:~1.6.18" utils-merge: "npm:1.0.1" vary: "npm:~1.1.2" - checksum: 10/34571c442fc8c9f2c4b442d2faa10ea1175cf8559237fc6a278f5ce6254a8ffdbeb9a15d99f77c1a9f2926ab183e3b7ba560e3261f1ad4149799e3412ab66bd1 + checksum: 10/f33c1bd0c7d36e2a1f18de9cdc176469d32f68e20258d2941b8d296ab9a4fd9011872c246391bf87714f009fac5114c832ec5ac65cbee39421f1258801eb8470 languageName: node linkType: hard @@ -8814,6 +9132,13 @@ __metadata: languageName: node linkType: hard +"fast-copy@npm:^3.0.2": + version: 3.0.2 + resolution: "fast-copy@npm:3.0.2" + checksum: 10/97e1022e2aaa27acf4a986d679310bfd66bfb87fe8da9dd33b698e3e50189484001cf1eeb9670e19b59d9d299828ed86c8da354c954f125995ab2a6331c5f290 + languageName: node + linkType: hard + "fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3": version: 3.1.3 resolution: "fast-deep-equal@npm:3.1.3" @@ -8835,7 +9160,7 @@ __metadata: languageName: node linkType: hard -"fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.0, fast-glob@npm:^3.3.2": +"fast-glob@npm:^3.2.9": version: 3.3.3 resolution: "fast-glob@npm:3.3.3" dependencies: @@ -8877,13 +9202,24 @@ __metadata: linkType: hard "fast-xml-parser@npm:^4.4.1": - version: 4.4.1 - resolution: "fast-xml-parser@npm:4.4.1" + version: 4.5.3 + resolution: "fast-xml-parser@npm:4.5.3" + dependencies: + strnum: "npm:^1.1.1" + bin: + fxparser: src/cli/cli.js + checksum: 10/ca22bf9d65c10b8447c1034c13403e90ecee210e2b3852690df3d8a42b8a46ec655fae7356096abd98a15b89ddaf11878587b1773e0c3be4cbc2ac4af4c7bf95 + languageName: node + linkType: hard + +"fast-xml-parser@npm:^5.3.4": + version: 5.3.7 + resolution: "fast-xml-parser@npm:5.3.7" dependencies: - strnum: "npm:^1.0.5" + strnum: "npm:^2.1.2" bin: fxparser: src/cli/cli.js - checksum: 10/0c05ab8703630d8c857fafadbd78d0020d3a8e54310c3842179cd4a0d9d97e96d209ce885e91241f4aa9dd8dfc2fd924a682741a423d65153cad34da2032ec44 + checksum: 10/c3dfba84b8c8920a1a6f2596c387c8fbb3b76fcad9a26769a793f1e26d7718c50363478f3be2a71e952b2bf765be51d8f8e3434b37cc7af029c6a09662ea6ba4 languageName: node linkType: hard @@ -8895,11 +9231,11 @@ __metadata: linkType: hard "fastq@npm:^1.6.0": - version: 1.17.1 - resolution: "fastq@npm:1.17.1" + version: 1.20.1 + resolution: "fastq@npm:1.20.1" dependencies: reusify: "npm:^1.0.4" - checksum: 10/a443180068b527dd7b3a63dc7f2a47ceca2f3e97b9c00a1efe5538757e6cc4056a3526df94308075d7727561baf09ebaa5b67da8dcbddb913a021c5ae69d1f69 + checksum: 10/ab2fe3a7a108112e7752cfe7fc11683c21e595913a6a593ad0b4415f31dddbfc283775ab66f2c8ccea6ab7cfc116157cbddcfae9798d9de98d08fe0a2c3e97b2 languageName: node linkType: hard @@ -8951,18 +9287,18 @@ __metadata: languageName: node linkType: hard -"finalhandler@npm:1.3.1": - version: 1.3.1 - resolution: "finalhandler@npm:1.3.1" +"finalhandler@npm:~1.3.1": + version: 1.3.2 + resolution: "finalhandler@npm:1.3.2" dependencies: debug: "npm:2.6.9" encodeurl: "npm:~2.0.0" escape-html: "npm:~1.0.3" - on-finished: "npm:2.4.1" + on-finished: "npm:~2.4.1" parseurl: "npm:~1.3.3" - statuses: "npm:2.0.1" + statuses: "npm:~2.0.2" unpipe: "npm:~1.0.0" - checksum: 10/4babe72969b7373b5842bc9f75c3a641a4d0f8eb53af6b89fa714d4460ce03fb92b28de751d12ba415e96e7e02870c436d67412120555e2b382640535697305b + checksum: 10/6cb4f9f80eaeb5a0fac4fdbd27a65d39271f040a0034df16556d896bfd855fd42f09da886781b3102117ea8fceba97b903c1f8b08df1fb5740576d5e0f481eed languageName: node linkType: hard @@ -8999,38 +9335,38 @@ __metadata: linkType: hard "firebase@npm:^11.2.0": - version: 11.2.0 - resolution: "firebase@npm:11.2.0" - dependencies: - "@firebase/analytics": "npm:0.10.11" - "@firebase/analytics-compat": "npm:0.2.17" - "@firebase/app": "npm:0.10.18" - "@firebase/app-check": "npm:0.8.11" - "@firebase/app-check-compat": "npm:0.3.18" - "@firebase/app-compat": "npm:0.2.48" + version: 11.10.0 + resolution: "firebase@npm:11.10.0" + dependencies: + "@firebase/ai": "npm:1.4.1" + "@firebase/analytics": "npm:0.10.17" + "@firebase/analytics-compat": "npm:0.2.23" + "@firebase/app": "npm:0.13.2" + "@firebase/app-check": "npm:0.10.1" + "@firebase/app-check-compat": "npm:0.3.26" + "@firebase/app-compat": "npm:0.4.2" "@firebase/app-types": "npm:0.9.3" - "@firebase/auth": "npm:1.8.2" - "@firebase/auth-compat": "npm:0.5.17" - "@firebase/data-connect": "npm:0.2.0" - "@firebase/database": "npm:1.0.11" - "@firebase/database-compat": "npm:2.0.2" - "@firebase/firestore": "npm:4.7.6" - "@firebase/firestore-compat": "npm:0.3.41" - "@firebase/functions": "npm:0.12.1" - "@firebase/functions-compat": "npm:0.3.18" - "@firebase/installations": "npm:0.6.12" - "@firebase/installations-compat": "npm:0.2.12" - "@firebase/messaging": "npm:0.12.16" - "@firebase/messaging-compat": "npm:0.2.16" - "@firebase/performance": "npm:0.6.12" - "@firebase/performance-compat": "npm:0.2.12" - "@firebase/remote-config": "npm:0.5.0" - "@firebase/remote-config-compat": "npm:0.2.12" - "@firebase/storage": "npm:0.13.5" - "@firebase/storage-compat": "npm:0.3.15" - "@firebase/util": "npm:1.10.3" - "@firebase/vertexai": "npm:1.0.3" - checksum: 10/9a3a8f6be4b34e76428cf6ae11bff8141772b7b3ec8a8fe0ef69188fdf2a602bd6e542a663133f90845d5a358daadeadf760841cf3ea8ec726475ee84a694ea4 + "@firebase/auth": "npm:1.10.8" + "@firebase/auth-compat": "npm:0.5.28" + "@firebase/data-connect": "npm:0.3.10" + "@firebase/database": "npm:1.0.20" + "@firebase/database-compat": "npm:2.0.11" + "@firebase/firestore": "npm:4.8.0" + "@firebase/firestore-compat": "npm:0.3.53" + "@firebase/functions": "npm:0.12.9" + "@firebase/functions-compat": "npm:0.3.26" + "@firebase/installations": "npm:0.6.18" + "@firebase/installations-compat": "npm:0.2.18" + "@firebase/messaging": "npm:0.12.22" + "@firebase/messaging-compat": "npm:0.2.22" + "@firebase/performance": "npm:0.7.7" + "@firebase/performance-compat": "npm:0.2.20" + "@firebase/remote-config": "npm:0.6.5" + "@firebase/remote-config-compat": "npm:0.2.18" + "@firebase/storage": "npm:0.13.14" + "@firebase/storage-compat": "npm:0.3.24" + "@firebase/util": "npm:1.12.1" + checksum: 10/ec78a2e079ff3d18ce7579a56a646d2979e619e504d74066d33bfea4941a87eb8b0ebea67e99fa1a3d76fd2b858c92958304b05b5a3bab60b662fa70821b12b1 languageName: node linkType: hard @@ -9045,19 +9381,28 @@ __metadata: linkType: hard "flatted@npm:^3.2.9": - version: 3.3.1 - resolution: "flatted@npm:3.3.1" - checksum: 10/7b8376061d5be6e0d3658bbab8bde587647f68797cf6bfeae9dea0e5137d9f27547ab92aaff3512dd9d1299086a6d61be98e9d48a56d17531b634f77faadbc49 + version: 3.3.3 + resolution: "flatted@npm:3.3.3" + checksum: 10/8c96c02fbeadcf4e8ffd0fa24983241e27698b0781295622591fc13585e2f226609d95e422bcf2ef044146ffacb6b68b1f20871454eddf75ab3caa6ee5f4a1fe languageName: node linkType: hard -"follow-redirects@npm:^1.15.6": - version: 1.15.6 - resolution: "follow-redirects@npm:1.15.6" +"follow-redirects@npm:^1.15.11": + version: 1.15.11 + resolution: "follow-redirects@npm:1.15.11" peerDependenciesMeta: debug: optional: true - checksum: 10/70c7612c4cab18e546e36b991bbf8009a1a41cf85354afe04b113d1117569abf760269409cb3eb842d9f7b03d62826687086b081c566ea7b1e6613cf29030bf7 + checksum: 10/07372fd74b98c78cf4d417d68d41fdaa0be4dcacafffb9e67b1e3cf090bc4771515e65020651528faab238f10f9b9c0d9707d6c1574a6c0387c5de1042cde9ba + languageName: node + linkType: hard + +"for-each@npm:^0.3.5": + version: 0.3.5 + resolution: "for-each@npm:0.3.5" + dependencies: + is-callable: "npm:^1.2.7" + checksum: 10/330cc2439f85c94f4609de3ee1d32c5693ae15cdd7fe3d112c4fd9efd4ce7143f2c64ef6c2c9e0cfdb0058437f33ef05b5bdae5b98fcc903fb2143fbaf0fea0f languageName: node linkType: hard @@ -9069,23 +9414,25 @@ __metadata: linkType: hard "foreground-child@npm:^3.1.0": - version: 3.3.0 - resolution: "foreground-child@npm:3.3.0" + version: 3.3.1 + resolution: "foreground-child@npm:3.3.1" dependencies: - cross-spawn: "npm:^7.0.0" + cross-spawn: "npm:^7.0.6" signal-exit: "npm:^4.0.1" - checksum: 10/e3a60480f3a09b12273ce2c5fcb9514d98dd0e528f58656a1b04680225f918d60a2f81f6a368f2f3b937fcee9cfc0cbf16f1ad9a0bc6a3a6e103a84c9a90087e + checksum: 10/427b33f997a98073c0424e5c07169264a62cda806d8d2ded159b5b903fdfc8f0a1457e06b5fc35506497acb3f1e353f025edee796300209ac6231e80edece835 languageName: node linkType: hard -"form-data@npm:^4.0.0": - version: 4.0.0 - resolution: "form-data@npm:4.0.0" +"form-data@npm:^4.0.0, form-data@npm:^4.0.4, form-data@npm:^4.0.5": + version: 4.0.5 + resolution: "form-data@npm:4.0.5" dependencies: asynckit: "npm:^0.4.0" combined-stream: "npm:^1.0.8" + es-set-tostringtag: "npm:^2.1.0" + hasown: "npm:^2.0.2" mime-types: "npm:^2.1.12" - checksum: 10/7264aa760a8cf09482816d8300f1b6e2423de1b02bba612a136857413fdc96d7178298ced106817655facc6b89036c6e12ae31c9eb5bdc16aabf502ae8a5d805 + checksum: 10/52ecd6e927c8c4e215e68a7ad5e0f7c1031397439672fd9741654b4a94722c4182e74cc815b225dcb5be3f4180f36428f67c6dd39eaa98af0dcfdd26c00c19cd languageName: node linkType: hard @@ -9096,7 +9443,7 @@ __metadata: languageName: node linkType: hard -"fresh@npm:0.5.2": +"fresh@npm:~0.5.2": version: 0.5.2 resolution: "fresh@npm:0.5.2" checksum: 10/64c88e489b5d08e2f29664eb3c79c705ff9a8eb15d3e597198ef76546d4ade295897a44abb0abd2700e7ef784b2e3cbf1161e4fbf16f59129193fd1030d16da1 @@ -9115,22 +9462,13 @@ __metadata: linkType: hard "fs-extra@npm:^11.2.0": - version: 11.3.0 - resolution: "fs-extra@npm:11.3.0" + version: 11.3.3 + resolution: "fs-extra@npm:11.3.3" dependencies: graceful-fs: "npm:^4.2.0" jsonfile: "npm:^6.0.1" universalify: "npm:^2.0.0" - checksum: 10/c9fe7b23dded1efe7bbae528d685c3206477e20cc60e9aaceb3f024f9b9ff2ee1f62413c161cb88546cc564009ab516dec99e9781ba782d869bb37e4fe04a97f - languageName: node - linkType: hard - -"fs-minipass@npm:^2.0.0": - version: 2.1.0 - resolution: "fs-minipass@npm:2.1.0" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10/03191781e94bc9a54bd376d3146f90fe8e082627c502185dbf7b9b3032f66b0b142c1115f3b2cc5936575fc1b44845ce903dd4c21bec2a8d69f3bd56f9cee9ec + checksum: 10/daeaefafbebe8fa6efd2fb96fc926f2c952be5877811f00a6794f0d64e0128e3d0d93368cd328f8f063b45deacf385c40e3d931aa46014245431cd2f4f89c67a languageName: node linkType: hard @@ -9176,6 +9514,13 @@ __metadata: languageName: node linkType: hard +"generator-function@npm:^2.0.0": + version: 2.0.1 + resolution: "generator-function@npm:2.0.1" + checksum: 10/eb7e7eb896c5433f3d40982b2ccacdb3dd990dd3499f14040e002b5d54572476513be8a2e6f9609f6e41ab29f2c4469307611ddbfc37ff4e46b765c326663805 + languageName: node + linkType: hard + "gensync@npm:^1.0.0-beta.2": version: 1.0.0-beta.2 resolution: "gensync@npm:1.0.0-beta.2" @@ -9190,21 +9535,24 @@ __metadata: languageName: node linkType: hard -"get-intrinsic@npm:^1.2.4": - version: 1.3.0 - resolution: "get-intrinsic@npm:1.3.0" +"get-intrinsic@npm:^1.2.4, get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.2.6, get-intrinsic@npm:^1.3.0": + version: 1.3.1 + resolution: "get-intrinsic@npm:1.3.1" dependencies: + async-function: "npm:^1.0.0" + async-generator-function: "npm:^1.0.0" call-bind-apply-helpers: "npm:^1.0.2" es-define-property: "npm:^1.0.1" es-errors: "npm:^1.3.0" es-object-atoms: "npm:^1.1.1" function-bind: "npm:^1.1.2" + generator-function: "npm:^2.0.0" get-proto: "npm:^1.0.1" gopd: "npm:^1.2.0" has-symbols: "npm:^1.1.0" hasown: "npm:^2.0.2" math-intrinsics: "npm:^1.1.0" - checksum: 10/6e9dd920ff054147b6f44cb98104330e87caafae051b6d37b13384a45ba15e71af33c3baeac7cb630a0aaa23142718dcf25b45cfdd86c184c5dcb4e56d953a10 + checksum: 10/bb579dda84caa4a3a41611bdd483dade7f00f246f2a7992eb143c5861155290df3fdb48a8406efa3dfb0b434e2c8fafa4eebd469e409d0439247f85fc3fa2cc1 languageName: node linkType: hard @@ -9232,13 +9580,6 @@ __metadata: languageName: node linkType: hard -"get-stdin@npm:^9.0.0": - version: 9.0.0 - resolution: "get-stdin@npm:9.0.0" - checksum: 10/5972bc34d05932b45512c8e2d67b040f1c1ca8afb95c56cbc480985f2d761b7e37fe90dc8abd22527f062cc5639a6930ff346e9952ae4c11a2d4275869459594 - languageName: node - linkType: hard - "get-stream@npm:^6.0.0": version: 6.0.1 resolution: "get-stream@npm:6.0.1" @@ -9253,19 +9594,19 @@ __metadata: languageName: node linkType: hard -"get-tsconfig@npm:^4.7.3, get-tsconfig@npm:^4.7.5, get-tsconfig@npm:^4.8.1": - version: 4.8.1 - resolution: "get-tsconfig@npm:4.8.1" +"get-tsconfig@npm:^4.10.0, get-tsconfig@npm:^4.10.1, get-tsconfig@npm:^4.7.5, get-tsconfig@npm:^4.8.1": + version: 4.13.6 + resolution: "get-tsconfig@npm:4.13.6" dependencies: resolve-pkg-maps: "npm:^1.0.0" - checksum: 10/3fb5a8ad57b9633eaea085d81661e9e5c9f78b35d8f8689eaf8b8b45a2a3ebf3b3422266d4d7df765e308cc1e6231648d114803ab3d018332e29916f2c1de036 + checksum: 10/5cd1c1f273e9f1cd9f1ebeaaea281a3b7b71562fc9614ee0cf0575463b0435de68831354434a5a1a564e1049062d597d0dae8ef33f489a6d12afccee032f6784 languageName: node linkType: hard -"git-hooks-list@npm:^3.0.0": - version: 3.1.0 - resolution: "git-hooks-list@npm:3.1.0" - checksum: 10/05cbdb29e1e14f3b6fde78c876a34383e4476b1be32e8486ad03293f01add884c1a8df8c2dce2ca5d99119c94951b2ff9fa9cbd51d834ae6477b6813cefb998f +"git-hooks-list@npm:^4.1.1": + version: 4.2.1 + resolution: "git-hooks-list@npm:4.2.1" + checksum: 10/39449520045539c03b1d45d3a010424849152d6f723b638c6f19cb8c8b0993bb30ed5ef09653f4d1c1356f5fb51a396059096d8bdfcb6ca7ccb54f6e26efc338 languageName: node linkType: hard @@ -9287,9 +9628,9 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7": - version: 10.4.5 - resolution: "glob@npm:10.4.5" +"glob@npm:^10.3.7": + version: 10.5.0 + resolution: "glob@npm:10.5.0" dependencies: foreground-child: "npm:^3.1.0" jackspeak: "npm:^3.1.2" @@ -9299,7 +9640,18 @@ __metadata: path-scurry: "npm:^1.11.1" bin: glob: dist/esm/bin.mjs - checksum: 10/698dfe11828b7efd0514cd11e573eaed26b2dff611f0400907281ce3eab0c1e56143ef9b35adc7c77ecc71fba74717b510c7c223d34ca8a98ec81777b293d4ac + checksum: 10/ab3bccfefcc0afaedbd1f480cd0c4a2c0e322eb3f0aa7ceaa31b3f00b825069f17cf0f1fc8b6f256795074b903f37c0ade37ddda6a176aa57f1c2bbfe7240653 + languageName: node + linkType: hard + +"glob@npm:^13.0.0": + version: 13.0.6 + resolution: "glob@npm:13.0.6" + dependencies: + minimatch: "npm:^10.2.2" + minipass: "npm:^7.1.3" + path-scurry: "npm:^2.0.2" + checksum: 10/201ad69e5f0aa74e1d8c00a481581f8b8c804b6a4fbfabeeb8541f5d756932800331daeba99b58fb9e4cd67e12ba5a7eba5b82fb476691588418060b84353214 languageName: node linkType: hard @@ -9349,9 +9701,9 @@ __metadata: linkType: hard "globals@npm:^15.11.0, globals@npm:^15.9.0": - version: 15.14.0 - resolution: "globals@npm:15.14.0" - checksum: 10/e35ffbdbc024d6381efca906f67211a7bbf935db2af8c14a65155785479e28b3e475950e5933bb6b296eed54b6dcd924e25b26dbc8579b1bde9d5d25916e1c5f + version: 15.15.0 + resolution: "globals@npm:15.15.0" + checksum: 10/7f561c87b2fd381b27fc2db7df8a4ea7a9bb378667b8a7193e61fd2ca3a876479174e2a303a74345fbea6e1242e16db48915c1fd3bf35adcf4060a795b425e18 languageName: node linkType: hard @@ -9369,16 +9721,10 @@ __metadata: languageName: node linkType: hard -"globby@npm:^13.1.2": - version: 13.2.2 - resolution: "globby@npm:13.2.2" - dependencies: - dir-glob: "npm:^3.0.1" - fast-glob: "npm:^3.3.0" - ignore: "npm:^5.2.4" - merge2: "npm:^1.4.1" - slash: "npm:^4.0.0" - checksum: 10/4494a9d2162a7e4d327988b26be66d8eab87d7f59a83219e74b065e2c3ced23698f68fb10482bf9337133819281803fb886d6ae06afbb2affa743623eb0b1949 +"globrex@npm:^0.1.2": + version: 0.1.2 + resolution: "globrex@npm:0.1.2" + checksum: 10/81ce62ee6f800d823d6b7da7687f841676d60ee8f51f934ddd862e4057316d26665c4edc0358d4340a923ac00a514f8b67c787e28fe693aae16350f4e60d55e9 languageName: node linkType: hard @@ -9389,7 +9735,7 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.2, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": +"graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.11, graceful-fs@npm:^4.2.2, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" checksum: 10/bf152d0ed1dc159239db1ba1f74fdbc40cb02f626770dcd5815c427ce0688c2635a06ed69af364396da4636d0408fcf7d4afdf7881724c3307e46aff30ca49e2 @@ -9437,21 +9783,31 @@ __metadata: languageName: node linkType: hard -"has-symbols@npm:^1.1.0": +"has-symbols@npm:^1.0.3, has-symbols@npm:^1.1.0": version: 1.1.0 resolution: "has-symbols@npm:1.1.0" checksum: 10/959385c98696ebbca51e7534e0dc723ada325efa3475350951363cce216d27373e0259b63edb599f72eb94d6cde8577b4b2375f080b303947e560f85692834fa languageName: node linkType: hard -"hash-base@npm:^3.0.0": - version: 3.1.0 - resolution: "hash-base@npm:3.1.0" +"has-tostringtag@npm:^1.0.2": + version: 1.0.2 + resolution: "has-tostringtag@npm:1.0.2" + dependencies: + has-symbols: "npm:^1.0.3" + checksum: 10/c74c5f5ceee3c8a5b8bc37719840dc3749f5b0306d818974141dda2471a1a2ca6c8e46b9d6ac222c5345df7a901c9b6f350b1e6d62763fec877e26609a401bfe + languageName: node + linkType: hard + +"hash-base@npm:^3.0.0, hash-base@npm:^3.1.2": + version: 3.1.2 + resolution: "hash-base@npm:3.1.2" dependencies: inherits: "npm:^2.0.4" - readable-stream: "npm:^3.6.0" - safe-buffer: "npm:^5.2.0" - checksum: 10/26b7e97ac3de13cb23fc3145e7e3450b0530274a9562144fc2bf5c1e2983afd0e09ed7cc3b20974ba66039fad316db463da80eb452e7373e780cbee9a0d2f2dc + readable-stream: "npm:^2.3.8" + safe-buffer: "npm:^5.2.1" + to-buffer: "npm:^1.2.1" + checksum: 10/f2100420521ec77736ebd9279f2c0b3ab2820136a2fa408ea36f3201d3f6984cda166806e6a0287f92adf179430bedfbdd74348ac351e24a3eff9f01a8c406b0 languageName: node linkType: hard @@ -9510,12 +9866,12 @@ __metadata: languageName: node linkType: hard -"hosted-git-info@npm:^7.0.0": - version: 7.0.2 - resolution: "hosted-git-info@npm:7.0.2" +"hosted-git-info@npm:^9.0.0": + version: 9.0.2 + resolution: "hosted-git-info@npm:9.0.2" dependencies: - lru-cache: "npm:^10.0.1" - checksum: 10/8f085df8a4a637d995f357f48b1e3f6fc1f9f92e82b33fb406415b5741834ed431a510a09141071001e8deea2eee43ce72786463e2aa5e5a70db8648c0eedeab + lru-cache: "npm:^11.1.0" + checksum: 10/0619c284ca7fc35322735e03fece90ed3ded67a2cf68e855e688d1bffd47078515d98ab8dff4bd08fb78d68d1a72ab8892180e15c7f23f24c922a6dfa601dbad languageName: node linkType: hard @@ -9536,29 +9892,29 @@ __metadata: linkType: hard "http-cache-semantics@npm:^4.1.1": - version: 4.1.1 - resolution: "http-cache-semantics@npm:4.1.1" - checksum: 10/362d5ed66b12ceb9c0a328fb31200b590ab1b02f4a254a697dc796850cc4385603e75f53ec59f768b2dad3bfa1464bd229f7de278d2899a0e3beffc634b6683f + version: 4.2.0 + resolution: "http-cache-semantics@npm:4.2.0" + checksum: 10/4efd2dfcfeea9d5e88c84af450b9980be8a43c2c8179508b1c57c7b4421c855f3e8efe92fa53e0b3f4a43c85824ada930eabbc306d1b3beab750b6dcc5187693 languageName: node linkType: hard -"http-errors@npm:2.0.0": - version: 2.0.0 - resolution: "http-errors@npm:2.0.0" +"http-errors@npm:~2.0.0, http-errors@npm:~2.0.1": + version: 2.0.1 + resolution: "http-errors@npm:2.0.1" dependencies: - depd: "npm:2.0.0" - inherits: "npm:2.0.4" - setprototypeof: "npm:1.2.0" - statuses: "npm:2.0.1" - toidentifier: "npm:1.0.1" - checksum: 10/0e7f76ee8ff8a33e58a3281a469815b893c41357378f408be8f6d4aa7d1efafb0da064625518e7078381b6a92325949b119dc38fcb30bdbc4e3a35f78c44c439 + depd: "npm:~2.0.0" + inherits: "npm:~2.0.4" + setprototypeof: "npm:~1.2.0" + statuses: "npm:~2.0.2" + toidentifier: "npm:~1.0.1" + checksum: 10/9fe31bc0edf36566c87048aed1d3d0cbe03552564adc3541626a0613f542d753fbcb13bdfcec0a3a530dbe1714bb566c89d46244616b66bddd26ac413b06a207 languageName: node linkType: hard "http-parser-js@npm:>=0.5.1": - version: 0.5.8 - resolution: "http-parser-js@npm:0.5.8" - checksum: 10/2a78a567ee6366dae0129d819b799dce1f95ec9732c5ab164a78ee69804ffb984abfa0660274e94e890fc54af93546eb9f12b6d10edbaed017e2d41c29b7cf29 + version: 0.5.10 + resolution: "http-parser-js@npm:0.5.10" + checksum: 10/33c53b458cfdf7e43f1517f9bcb6bed1c614b1c7c5d65581a84304110eb9eb02a48f998c7504b8bee432ef4a8ec9318e7009406b506b28b5610fed516242b20a languageName: node linkType: hard @@ -9594,12 +9950,12 @@ __metadata: linkType: hard "https-proxy-agent@npm:^7.0.1": - version: 7.0.5 - resolution: "https-proxy-agent@npm:7.0.5" + version: 7.0.6 + resolution: "https-proxy-agent@npm:7.0.6" dependencies: - agent-base: "npm:^7.0.2" + agent-base: "npm:^7.1.2" debug: "npm:4" - checksum: 10/6679d46159ab3f9a5509ee80c3a3fc83fba3a920a5e18d32176c3327852c3c00ad640c0c4210a8fd70ea3c4a6d3a1b375bf01942516e7df80e2646bdc77658ab + checksum: 10/784b628cbd55b25542a9d85033bdfd03d4eda630fb8b3c9477959367f3be95dc476ed2ecbb9836c359c7c698027fc7b45723a302324433590f45d6c1706e8c13 languageName: node linkType: hard @@ -9617,21 +9973,30 @@ __metadata: languageName: node linkType: hard -"iconv-lite@npm:0.4.24": - version: 0.4.24 - resolution: "iconv-lite@npm:0.4.24" +"iconv-lite@npm:0.6.3": + version: 0.6.3 + resolution: "iconv-lite@npm:0.6.3" dependencies: - safer-buffer: "npm:>= 2.1.2 < 3" - checksum: 10/6d3a2dac6e5d1fb126d25645c25c3a1209f70cceecc68b8ef51ae0da3cdc078c151fade7524a30b12a3094926336831fca09c666ef55b37e2c69638b5d6bd2e3 + safer-buffer: "npm:>= 2.1.2 < 3.0.0" + checksum: 10/24e3292dd3dadaa81d065c6f8c41b274a47098150d444b96e5f53b4638a9a71482921ea6a91a1f59bb71d9796de25e04afd05919fa64c360347ba65d3766f10f languageName: node linkType: hard -"iconv-lite@npm:0.6.3, iconv-lite@npm:^0.6.2": - version: 0.6.3 - resolution: "iconv-lite@npm:0.6.3" +"iconv-lite@npm:^0.7.2": + version: 0.7.2 + resolution: "iconv-lite@npm:0.7.2" dependencies: safer-buffer: "npm:>= 2.1.2 < 3.0.0" - checksum: 10/24e3292dd3dadaa81d065c6f8c41b274a47098150d444b96e5f53b4638a9a71482921ea6a91a1f59bb71d9796de25e04afd05919fa64c360347ba65d3766f10f + checksum: 10/24c937b532f868e938386b62410b303b7c767ce3d08dc2829cbe59464d5a26ef86ae5ad1af6b34eec43ddfea39e7d101638644b0178d67262fa87015d59f983a + languageName: node + linkType: hard + +"iconv-lite@npm:~0.4.24": + version: 0.4.24 + resolution: "iconv-lite@npm:0.4.24" + dependencies: + safer-buffer: "npm:>= 2.1.2 < 3" + checksum: 10/6d3a2dac6e5d1fb126d25645c25c3a1209f70cceecc68b8ef51ae0da3cdc078c151fade7524a30b12a3094926336831fca09c666ef55b37e2c69638b5d6bd2e3 languageName: node linkType: hard @@ -9680,12 +10045,12 @@ __metadata: linkType: hard "import-fresh@npm:^3.2.1": - version: 3.3.0 - resolution: "import-fresh@npm:3.3.0" + version: 3.3.1 + resolution: "import-fresh@npm:3.3.1" dependencies: parent-module: "npm:^1.0.0" resolve-from: "npm:^4.0.0" - checksum: 10/2cacfad06e652b1edc50be650f7ec3be08c5e5a6f6d12d035c440a42a8cc028e60a5b99ca08a77ab4d6b1346da7d971915828f33cdab730d3d42f08242d09baa + checksum: 10/a06b19461b4879cc654d46f8a6244eb55eb053437afd4cbb6613cad6be203811849ed3e4ea038783092879487299fda24af932b86bdfff67c9055ba3612b8c87 languageName: node linkType: hard @@ -9725,7 +10090,7 @@ __metadata: languageName: node linkType: hard -"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3": +"inherits@npm:2, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3, inherits@npm:~2.0.4": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 10/cd45e923bee15186c07fa4c89db0aace24824c482fb887b528304694b2aa6ff8a898da8657046a5dcf3e46cd6db6c61629551f9215f208d7c3f157cf9b290521 @@ -9739,20 +10104,17 @@ __metadata: languageName: node linkType: hard -"ini@npm:^4.1.3": - version: 4.1.3 - resolution: "ini@npm:4.1.3" - checksum: 10/f536b414d1442e5b233429e2b56efcdb354109b2d65ddd489e5939d8f0f5ad23c88aa2b19c92987249d0dd63ba8192e9aeb1a02b0459549c5a9ff31acd729a5d +"ini@npm:^6.0.0": + version: 6.0.0 + resolution: "ini@npm:6.0.0" + checksum: 10/e87d8cde86d091ddb104580d42dfdc8306593627269990ca0f5176ccc60c936268bad56856398fef924cdf0af33b1a9c21e84f85914820037e003ee45443cc85 languageName: node linkType: hard -"ip-address@npm:^9.0.5": - version: 9.0.5 - resolution: "ip-address@npm:9.0.5" - dependencies: - jsbn: "npm:1.1.0" - sprintf-js: "npm:^1.1.3" - checksum: 10/1ed81e06721af012306329b31f532b5e24e00cb537be18ddc905a84f19fe8f83a09a1699862bf3a1ec4b9dea93c55a3fa5faf8b5ea380431469df540f38b092c +"ip-address@npm:^10.0.1": + version: 10.1.0 + resolution: "ip-address@npm:10.1.0" + checksum: 10/a6979629d1ad9c1fb424bc25182203fad739b40225aebc55ec6243bbff5035faf7b9ed6efab3a097de6e713acbbfde944baacfa73e11852bb43989c45a68d79e languageName: node linkType: hard @@ -9777,12 +10139,19 @@ __metadata: languageName: node linkType: hard -"is-bun-module@npm:^1.0.2": - version: 1.3.0 - resolution: "is-bun-module@npm:1.3.0" +"is-bun-module@npm:^2.0.0": + version: 2.0.0 + resolution: "is-bun-module@npm:2.0.0" dependencies: - semver: "npm:^7.6.3" - checksum: 10/b23d9ec7b4d4bfd89e4e72b5cd52e1bc153facad59fdd7394c656f8859a78740ef35996a2066240a32f39cc9a9da4b4eb69e68df3c71755a61ebbaf56d3daef0 + semver: "npm:^7.7.1" + checksum: 10/cded5a1a58368b847872d08617975d620ad94426d76a932f3e08d55b4574d199e0a62a4fb024fa2dc444200b71719eb0bffc5d3d1e1cc82e29b293bb8d66a990 + languageName: node + linkType: hard + +"is-callable@npm:^1.2.7": + version: 1.2.7 + resolution: "is-callable@npm:1.2.7" + checksum: 10/48a9297fb92c99e9df48706241a189da362bff3003354aea4048bd5f7b2eb0d823cd16d0a383cece3d76166ba16d85d9659165ac6fcce1ac12e6c649d66dbdb9 languageName: node linkType: hard @@ -9797,7 +10166,7 @@ __metadata: languageName: node linkType: hard -"is-core-module@npm:^2.12.0, is-core-module@npm:^2.13.0, is-core-module@npm:^2.16.0, is-core-module@npm:^2.5.0": +"is-core-module@npm:^2.12.0, is-core-module@npm:^2.16.0, is-core-module@npm:^2.16.1, is-core-module@npm:^2.5.0": version: 2.16.1 resolution: "is-core-module@npm:2.16.1" dependencies: @@ -9870,13 +10239,6 @@ __metadata: languageName: node linkType: hard -"is-lambda@npm:^1.0.1": - version: 1.0.1 - resolution: "is-lambda@npm:1.0.1" - checksum: 10/93a32f01940220532e5948538699ad610d5924ac86093fcee83022252b363eb0cc99ba53ab084a04e4fb62bf7b5731f55496257a4c38adf87af9c4d352c71c35 - languageName: node - linkType: hard - "is-number@npm:^7.0.0": version: 7.0.0 resolution: "is-number@npm:7.0.0" @@ -9919,6 +10281,15 @@ __metadata: languageName: node linkType: hard +"is-typed-array@npm:^1.1.14": + version: 1.1.15 + resolution: "is-typed-array@npm:1.1.15" + dependencies: + which-typed-array: "npm:^1.1.16" + checksum: 10/e8cf60b9ea85667097a6ad68c209c9722cfe8c8edf04d6218366469e51944c5cc25bae45ffb845c23f811d262e4314d3b0168748eb16711aa34d12724cdf0735 + languageName: node + linkType: hard + "is-unicode-supported@npm:^0.1.0": version: 0.1.0 resolution: "is-unicode-supported@npm:0.1.0" @@ -9941,11 +10312,18 @@ __metadata: linkType: hard "is-wsl@npm:^3.1.0": - version: 3.1.0 - resolution: "is-wsl@npm:3.1.0" + version: 3.1.1 + resolution: "is-wsl@npm:3.1.1" dependencies: is-inside-container: "npm:^1.0.0" - checksum: 10/f9734c81f2f9cf9877c5db8356bfe1ff61680f1f4c1011e91278a9c0564b395ae796addb4bf33956871041476ec82c3e5260ed57b22ac91794d4ae70a1d2f0a9 + checksum: 10/513d95b89af0e60b43d7b17ecb7eb78edea0a439136a3da37b1b56e215379cc46a9221474ad5b2de044824ca72d7869dee6e015273dc3f71f2bb87c715f9f1dc + languageName: node + linkType: hard + +"isarray@npm:^2.0.5": + version: 2.0.5 + resolution: "isarray@npm:2.0.5" + checksum: 10/1d8bc7911e13bb9f105b1b3e0b396c787a9e63046af0b8fe0ab1414488ab06b2b099b87a2d8a9e31d21c9a6fad773c7fc8b257c4880f2d957274479d28ca3414 languageName: node linkType: hard @@ -9963,10 +10341,10 @@ __metadata: languageName: node linkType: hard -"isexe@npm:^3.1.1": - version: 3.1.1 - resolution: "isexe@npm:3.1.1" - checksum: 10/7fe1931ee4e88eb5aa524cd3ceb8c882537bc3a81b02e438b240e47012eef49c86904d0f0e593ea7c3a9996d18d0f1f3be8d3eaa92333977b0c3a9d353d5563e +"isexe@npm:^4.0.0": + version: 4.0.0 + resolution: "isexe@npm:4.0.0" + checksum: 10/2ead327ef596042ef9c9ec5f236b316acfaedb87f4bb61b3c3d574fb2e9c8a04b67305e04733bde52c24d9622fdebd3270aadb632adfbf9cadef88fe30f479e5 languageName: node linkType: hard @@ -10036,12 +10414,12 @@ __metadata: linkType: hard "istanbul-reports@npm:^3.1.3": - version: 3.1.7 - resolution: "istanbul-reports@npm:3.1.7" + version: 3.2.0 + resolution: "istanbul-reports@npm:3.2.0" dependencies: html-escaper: "npm:^2.0.0" istanbul-lib-report: "npm:^3.0.0" - checksum: 10/f1faaa4684efaf57d64087776018d7426312a59aa6eeb4e0e3a777347d23cd286ad18f427e98f0e3dee666103d7404c9d7abc5f240406a912fa16bd6695437fa + checksum: 10/6773a1d5c7d47eeec75b317144fe2a3b1da84a44b6282bebdc856e09667865e58c9b025b75b3d87f5bc62939126cbba4c871ee84254537d934ba5da5d4c4ec4e languageName: node linkType: hard @@ -10161,6 +10539,18 @@ __metadata: languageName: node linkType: hard +"jest-diff@npm:30.2.0": + version: 30.2.0 + resolution: "jest-diff@npm:30.2.0" + dependencies: + "@jest/diff-sequences": "npm:30.0.1" + "@jest/get-type": "npm:30.1.0" + chalk: "npm:^4.1.2" + pretty-format: "npm:30.2.0" + checksum: 10/1fb9e4fb7dff81814b4f69eaa7db28e184d62306a3a8ea2447d02ca53d2cfa771e83ede513f67ec5239dffacfaac32ff2b49866d211e4c7516f51c1fc06ede42 + languageName: node + linkType: hard + "jest-diff@npm:^29.0.3, jest-diff@npm:^29.7.0": version: 29.7.0 resolution: "jest-diff@npm:29.7.0" @@ -10283,6 +10673,18 @@ __metadata: languageName: node linkType: hard +"jest-matcher-utils@npm:30.2.0": + version: 30.2.0 + resolution: "jest-matcher-utils@npm:30.2.0" + dependencies: + "@jest/get-type": "npm:30.1.0" + chalk: "npm:^4.1.2" + jest-diff: "npm:30.2.0" + pretty-format: "npm:30.2.0" + checksum: 10/f3f1ecf68ca63c9d1d80a175637a8fc655edfd1ee83220f6e3f6bd464ecbe2f93148fdd440a5a5e5a2b0b2cc8ee84ddc3dcef58a6dbc66821c792f48d260c6d4 + languageName: node + linkType: hard + "jest-matcher-utils@npm:^29.7.0": version: 29.7.0 resolution: "jest-matcher-utils@npm:29.7.0" @@ -10295,6 +10697,23 @@ __metadata: languageName: node linkType: hard +"jest-message-util@npm:30.2.0": + version: 30.2.0 + resolution: "jest-message-util@npm:30.2.0" + dependencies: + "@babel/code-frame": "npm:^7.27.1" + "@jest/types": "npm:30.2.0" + "@types/stack-utils": "npm:^2.0.3" + chalk: "npm:^4.1.2" + graceful-fs: "npm:^4.2.11" + micromatch: "npm:^4.0.8" + pretty-format: "npm:30.2.0" + slash: "npm:^3.0.0" + stack-utils: "npm:^2.0.6" + checksum: 10/e29ec76e8c8e4da5f5b25198be247535626ccf3a940e93fdd51fc6a6bcf70feaa2921baae3806182a090431d90b08c939eb13fb64249b171d2e9ae3a452a8fd2 + languageName: node + linkType: hard + "jest-message-util@npm:^29.7.0": version: 29.7.0 resolution: "jest-message-util@npm:29.7.0" @@ -10312,6 +10731,17 @@ __metadata: languageName: node linkType: hard +"jest-mock@npm:30.2.0": + version: 30.2.0 + resolution: "jest-mock@npm:30.2.0" + dependencies: + "@jest/types": "npm:30.2.0" + "@types/node": "npm:*" + jest-util: "npm:30.2.0" + checksum: 10/cde9b56805f90bf811a9231873ee88a0fb83bf4bf50972ae76960725da65220fcb119688f2e90e1ef33fbfd662194858d7f43809d881f1c41bb55d94e62adeab + languageName: node + linkType: hard + "jest-mock@npm:^29.7.0": version: 29.7.0 resolution: "jest-mock@npm:29.7.0" @@ -10335,6 +10765,13 @@ __metadata: languageName: node linkType: hard +"jest-regex-util@npm:30.0.1": + version: 30.0.1 + resolution: "jest-regex-util@npm:30.0.1" + checksum: 10/fa8dac80c3e94db20d5e1e51d1bdf101cf5ede8f4e0b8f395ba8b8ea81e71804ffd747452a6bb6413032865de98ac656ef8ae43eddd18d980b6442a2764ed562 + languageName: node + linkType: hard + "jest-regex-util@npm:^29.6.3": version: 29.6.3 resolution: "jest-regex-util@npm:29.6.3" @@ -10466,6 +10903,20 @@ __metadata: languageName: node linkType: hard +"jest-util@npm:30.2.0": + version: 30.2.0 + resolution: "jest-util@npm:30.2.0" + dependencies: + "@jest/types": "npm:30.2.0" + "@types/node": "npm:*" + chalk: "npm:^4.1.2" + ci-info: "npm:^4.2.0" + graceful-fs: "npm:^4.2.11" + picomatch: "npm:^4.0.2" + checksum: 10/cf2f2fb83417ea69f9992121561c95cf4e9aad7946819b771b8b52addf78811101b33b51d0a39fa0c305f2751dab262feed7699de052659ff03d51827c8862f5 + languageName: node + linkType: hard + "jest-util@npm:^26.0.0": version: 26.6.2 resolution: "jest-util@npm:26.6.2" @@ -10525,11 +10976,11 @@ __metadata: linkType: hard "jest-when@npm:^3.4.2": - version: 3.6.0 - resolution: "jest-when@npm:3.6.0" + version: 3.7.0 + resolution: "jest-when@npm:3.7.0" peerDependencies: jest: ">= 25" - checksum: 10/0cb92738ccfa5711a685107f4437f18aefbe3cda120c912a9d49b612eeef03a910481ab40fe753fd42c4e617ffbb3d84c6bd66a76d963dac7f1ad9e9e5059359 + checksum: 10/b5b88d077ed467aab220c71c885dbc5f448604f06e68f761ce9f479c99bb74e0dbf553d1cc980751d88401b034a578e1c44eec5e4095743b7586f02bb7c6313d languageName: node linkType: hard @@ -10600,32 +11051,25 @@ __metadata: linkType: hard "js-yaml@npm:^3.13.1, js-yaml@npm:^3.14.1": - version: 3.14.1 - resolution: "js-yaml@npm:3.14.1" + version: 3.14.2 + resolution: "js-yaml@npm:3.14.2" dependencies: argparse: "npm:^1.0.7" esprima: "npm:^4.0.0" bin: js-yaml: bin/js-yaml.js - checksum: 10/9e22d80b4d0105b9899135365f746d47466ed53ef4223c529b3c0f7a39907743fdbd3c4379f94f1106f02755b5e90b2faaf84801a891135544e1ea475d1a1379 + checksum: 10/172e0b6007b0bf0fc8d2469c94424f7dd765c64a047d2b790831fecef2204a4054eabf4d911eb73ab8c9a3256ab8ba1ee8d655b789bf24bf059c772acc2075a1 languageName: node linkType: hard -"js-yaml@npm:^4.1.0": - version: 4.1.0 - resolution: "js-yaml@npm:4.1.0" +"js-yaml@npm:^4.1.1": + version: 4.1.1 + resolution: "js-yaml@npm:4.1.1" dependencies: argparse: "npm:^2.0.1" bin: js-yaml: bin/js-yaml.js - checksum: 10/c138a34a3fd0d08ebaf71273ad4465569a483b8a639e0b118ff65698d257c2791d3199e3f303631f2cb98213fa7b5f5d6a4621fd0fff819421b990d30d967140 - languageName: node - linkType: hard - -"jsbn@npm:1.1.0": - version: 1.1.0 - resolution: "jsbn@npm:1.1.0" - checksum: 10/bebe7ae829bbd586ce8cbe83501dd8cb8c282c8902a8aeeed0a073a89dc37e8103b1244f3c6acd60278bcbfe12d93a3f83c9ac396868a3b3bbc3c5e5e3b648ef + checksum: 10/a52d0519f0f4ef5b4adc1cde466cb54c50d56e2b4a983b9d5c9c0f2f99462047007a6274d7e95617a21d3c91fde3ee6115536ed70991cd645ba8521058b78f77 languageName: node linkType: hard @@ -10698,10 +11142,10 @@ __metadata: languageName: node linkType: hard -"json-parse-even-better-errors@npm:^3.0.0": - version: 3.0.2 - resolution: "json-parse-even-better-errors@npm:3.0.2" - checksum: 10/6f04ea6c9ccb783630a59297959247e921cc90b917b8351197ca7fd058fccc7079268fd9362be21ba876fc26aa5039369dd0a2280aae49aae425784794a94927 +"json-parse-even-better-errors@npm:^5.0.0": + version: 5.0.0 + resolution: "json-parse-even-better-errors@npm:5.0.0" + checksum: 10/b5aeaa65e072bc3bda2cb1da50bf1822814b4aa7c568e7c2bed25af89d730f113dcb74393da574c0a32e889eeba4a826db600b8a6ecef917c59c8c6b38f2efaa languageName: node linkType: hard @@ -10759,22 +11203,22 @@ __metadata: linkType: hard "jsonfile@npm:^6.0.1": - version: 6.1.0 - resolution: "jsonfile@npm:6.1.0" + version: 6.2.0 + resolution: "jsonfile@npm:6.2.0" dependencies: graceful-fs: "npm:^4.1.6" universalify: "npm:^2.0.0" dependenciesMeta: graceful-fs: optional: true - checksum: 10/03014769e7dc77d4cf05fa0b534907270b60890085dd5e4d60a382ff09328580651da0b8b4cdf44d91e4c8ae64d91791d965f05707beff000ed494a38b6fec85 + checksum: 10/513aac94a6eff070767cafc8eb4424b35d523eec0fcd8019fe5b975f4de5b10a54640c8d5961491ddd8e6f562588cf62435c5ddaf83aaf0986cd2ee789e0d7b9 languageName: node linkType: hard "jsonschema@npm:^1.4.1": - version: 1.4.1 - resolution: "jsonschema@npm:1.4.1" - checksum: 10/d7a188da7a3100a2caa362b80e98666d46607b7a7153aac405b8e758132961911c6df02d444d4700691330874e21a62639f550e856b21ddd28423690751ca9c6 + version: 1.5.0 + resolution: "jsonschema@npm:1.5.0" + checksum: 10/46bf49b388ba922073bcb3c8d5e90af9d29fc8303dc866fd440182c88d6b4fd2807679fd39cdefb4113156d104ea47da9c0ff4bbcb0032c9fa29461cb1a92182 languageName: node linkType: hard @@ -10898,9 +11342,9 @@ __metadata: linkType: hard "lodash@npm:^4.17.21": - version: 4.17.21 - resolution: "lodash@npm:4.17.21" - checksum: 10/c08619c038846ea6ac754abd6dd29d2568aa705feb69339e836dfa8d8b09abbb2f859371e86863eda41848221f9af43714491467b5b0299122431e202bb0c532 + version: 4.17.23 + resolution: "lodash@npm:4.17.23" + checksum: 10/82504c88250f58da7a5a4289f57a4f759c44946c005dd232821c7688b5fcfbf4a6268f6a6cdde4b792c91edd2f3b5398c1d2a0998274432cff76def48735e233 languageName: node linkType: hard @@ -10922,19 +11366,26 @@ __metadata: linkType: hard "long@npm:^5.0.0": - version: 5.2.3 - resolution: "long@npm:5.2.3" - checksum: 10/9167ec6947a825b827c30da169a7384eec6c0c9ec2f0b9c74da2e93d81159bbe39fb09c3f13dae9721d4b807ccfa09797a7dd1012f5d478e3e33ca3c78b608e6 + version: 5.3.2 + resolution: "long@npm:5.3.2" + checksum: 10/b6b55ddae56fcce2864d37119d6b02fe28f6dd6d9e44fd22705f86a9254b9321bd69e9ffe35263b4846d54aba197c64882adcb8c543f2383c1e41284b321ea64 languageName: node linkType: hard -"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": +"lru-cache@npm:^10.2.0": version: 10.4.3 resolution: "lru-cache@npm:10.4.3" checksum: 10/e6e90267360476720fa8e83cc168aa2bf0311f3f2eea20a6ba78b90a885ae72071d9db132f40fda4129c803e7dcec3a6b6a6fbb44ca90b081630b810b5d6a41a languageName: node linkType: hard +"lru-cache@npm:^11.0.0, lru-cache@npm:^11.1.0, lru-cache@npm:^11.2.1": + version: 11.2.6 + resolution: "lru-cache@npm:11.2.6" + checksum: 10/91222bbd59f793a0a0ad57789388f06b34ac9bb1613433c1d1810457d09db5cd3ec8943227ce2e1f5d6a0a15d6f1a9f129cb2c49ae9b6b10e82d4965fddecbef + languageName: node + linkType: hard + "lru-cache@npm:^5.1.1": version: 5.1.1 resolution: "lru-cache@npm:5.1.1" @@ -10961,18 +11412,18 @@ __metadata: linkType: hard "luxon@npm:^3.2.1, luxon@npm:^3.5.0": - version: 3.5.0 - resolution: "luxon@npm:3.5.0" - checksum: 10/48f86e6c1c96815139f8559456a3354a276ba79bcef0ae0d4f2172f7652f3ba2be2237b0e103b8ea0b79b47715354ac9fac04eb1db3485dcc72d5110491dd47f + version: 3.7.2 + resolution: "luxon@npm:3.7.2" + checksum: 10/b24cd205ed306ce7415991687897dcc4027921ae413c9116590bc33a95f93b86ce52cf74ba72b4f5c5ab1c10090517f54ac8edfb127c049e0bf55b90dc2260be languageName: node linkType: hard -"magic-string@npm:^0.30.10": - version: 0.30.11 - resolution: "magic-string@npm:0.30.11" +"magic-string@npm:^0.30.21": + version: 0.30.21 + resolution: "magic-string@npm:0.30.21" dependencies: - "@jridgewell/sourcemap-codec": "npm:^1.5.0" - checksum: 10/b784d2240252f5b1e755d487354ada4c672cbca16f045144f7185a75b059210e5fcca7be7be03ef1bac2ca754c4428b21d36ae64a9057ba429916f06b8c54eb2 + "@jridgewell/sourcemap-codec": "npm:^1.5.5" + checksum: 10/57d5691f41ed40d962d8bd300148114f53db67fadbff336207db10a99f2bdf4a1be9cac3a68ee85dba575912ee1d4402e4396408196ec2d3afd043b076156221 languageName: node linkType: hard @@ -10992,23 +11443,22 @@ __metadata: languageName: node linkType: hard -"make-fetch-happen@npm:^13.0.0": - version: 13.0.1 - resolution: "make-fetch-happen@npm:13.0.1" +"make-fetch-happen@npm:^15.0.0": + version: 15.0.3 + resolution: "make-fetch-happen@npm:15.0.3" dependencies: - "@npmcli/agent": "npm:^2.0.0" - cacache: "npm:^18.0.0" + "@npmcli/agent": "npm:^4.0.0" + cacache: "npm:^20.0.1" http-cache-semantics: "npm:^4.1.1" - is-lambda: "npm:^1.0.1" minipass: "npm:^7.0.2" - minipass-fetch: "npm:^3.0.0" + minipass-fetch: "npm:^5.0.0" minipass-flush: "npm:^1.0.5" minipass-pipeline: "npm:^1.2.4" - negotiator: "npm:^0.6.3" - proc-log: "npm:^4.2.0" + negotiator: "npm:^1.0.0" + proc-log: "npm:^6.0.0" promise-retry: "npm:^2.0.1" - ssri: "npm:^10.0.0" - checksum: 10/11bae5ad6ac59b654dbd854f30782f9de052186c429dfce308eda42374528185a100ee40ac9ffdc36a2b6c821ecaba43913e4730a12f06f15e895ea9cb23fa59 + ssri: "npm:^13.0.0" + checksum: 10/78da4fc1df83cb596e2bae25aa0653b8a9c6cbdd6674a104894e03be3acfcd08c70b78f06ef6407fbd6b173f6a60672480d78641e693d05eb71c09c13ee35278 languageName: node linkType: hard @@ -11203,30 +11653,39 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^3.0.4, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": - version: 3.1.2 - resolution: "minimatch@npm:3.1.2" +"minimatch@npm:^10.2.2, minimatch@npm:^9.0.3 || ^10.0.1": + version: 10.2.2 + resolution: "minimatch@npm:10.2.2" + dependencies: + brace-expansion: "npm:^5.0.2" + checksum: 10/e135be7b502ac97c02bcee42ccc1c55dc26dbac036c0f4acde69e42fe339d7fb53fae711e57b3546cb533426382ea492c73a073c7f78832e0453d120d48dd015 + languageName: node + linkType: hard + +"minimatch@npm:^3.0.4, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2, minimatch@npm:^3.1.3": + version: 3.1.3 + resolution: "minimatch@npm:3.1.3" dependencies: brace-expansion: "npm:^1.1.7" - checksum: 10/e0b25b04cd4ec6732830344e5739b13f8690f8a012d73445a4a19fbc623f5dd481ef7a5827fde25954cd6026fede7574cc54dc4643c99d6c6b653d6203f94634 + checksum: 10/d430c40785fdb42c9fc1a36b9c9e3b08146044bd0f2fd043b05afb436aa4eaf6cdcb7756939ab8fc01664cd75d6335fd5043b2fe2aa084756927ffc77c1e3597 languageName: node linkType: hard "minimatch@npm:^7.4.6": - version: 7.4.6 - resolution: "minimatch@npm:7.4.6" + version: 7.4.7 + resolution: "minimatch@npm:7.4.7" dependencies: brace-expansion: "npm:^2.0.1" - checksum: 10/0046ba1161ac6414bde1b07c440792ebcdb2ed93e6714c85c73974332b709b7e692801550bc9da22028a8613407b3f13861e17dd0dd44f4babdeacd44950430b + checksum: 10/509558c83a264ef8ba5cccab39a8937d8a1fdb2da336031de2444cda4dc3fb4e0d8ec78c0d51309635b910aaaa88d84a59f1a7dcfbefb6f6f5b7ce3204de17d4 languageName: node linkType: hard -"minimatch@npm:^9.0.3, minimatch@npm:^9.0.4, minimatch@npm:^9.0.5": - version: 9.0.5 - resolution: "minimatch@npm:9.0.5" +"minimatch@npm:^9.0.3, minimatch@npm:^9.0.4": + version: 9.0.6 + resolution: "minimatch@npm:9.0.6" dependencies: - brace-expansion: "npm:^2.0.1" - checksum: 10/dd6a8927b063aca6d910b119e1f2df6d2ce7d36eab91de83167dd136bb85e1ebff97b0d3de1cb08bd1f7e018ca170b4962479fefab5b2a69e2ae12cb2edc8348 + brace-expansion: "npm:^5.0.2" + checksum: 10/c7a46134aaf349f386de9a3f6c5b48c53bc3a4e2ef4b8b6365184504e28cc31cc261a388e181648cbc756b40e213dbce115c8087a47eff8f54ee28d62bc17b08 languageName: node linkType: hard @@ -11257,18 +11716,18 @@ __metadata: languageName: node linkType: hard -"minipass-fetch@npm:^3.0.0": - version: 3.0.5 - resolution: "minipass-fetch@npm:3.0.5" +"minipass-fetch@npm:^5.0.0": + version: 5.0.2 + resolution: "minipass-fetch@npm:5.0.2" dependencies: - encoding: "npm:^0.1.13" + iconv-lite: "npm:^0.7.2" minipass: "npm:^7.0.3" - minipass-sized: "npm:^1.0.3" - minizlib: "npm:^2.1.2" + minipass-sized: "npm:^2.0.0" + minizlib: "npm:^3.0.1" dependenciesMeta: - encoding: + iconv-lite: optional: true - checksum: 10/c669948bec1373313aaa8f104b962a3ced9f45c49b26366a4b0ae27ccdfa9c5740d72c8a84d3f8623d7a61c5fc7afdfda44789008c078f61a62441142efc4a97 + checksum: 10/4f3f65ea5b20a3a287765ebf21cc73e62031f754944272df2a3039296cc75a8fc2dc50b8a3c4f39ce3ac6e5cc583e8dc664d12c6ab98e0883d263e49f344bc86 languageName: node linkType: hard @@ -11290,12 +11749,12 @@ __metadata: languageName: node linkType: hard -"minipass-sized@npm:^1.0.3": - version: 1.0.3 - resolution: "minipass-sized@npm:1.0.3" +"minipass-sized@npm:^2.0.0": + version: 2.0.0 + resolution: "minipass-sized@npm:2.0.0" dependencies: - minipass: "npm:^3.0.0" - checksum: 10/40982d8d836a52b0f37049a0a7e5d0f089637298e6d9b45df9c115d4f0520682a78258905e5c8b180fb41b593b0a82cc1361d2c74b45f7ada66334f84d1ecfdd + minipass: "npm:^7.1.2" + checksum: 10/3b89adf64ca705662f77481e278eff5ec0a57aeffb5feba7cc8843722b1e7770efc880f2a17d1d4877b2d7bf227873cd46afb4da44c0fd18088b601ea50f96bb languageName: node linkType: hard @@ -11308,54 +11767,19 @@ __metadata: languageName: node linkType: hard -"minipass@npm:^5.0.0": - version: 5.0.0 - resolution: "minipass@npm:5.0.0" - checksum: 10/61682162d29f45d3152b78b08bab7fb32ca10899bc5991ffe98afc18c9e9543bd1e3be94f8b8373ba6262497db63607079dc242ea62e43e7b2270837b7347c93 - languageName: node - linkType: hard - -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4, minipass@npm:^7.1.2": - version: 7.1.2 - resolution: "minipass@npm:7.1.2" - checksum: 10/c25f0ee8196d8e6036661104bacd743785b2599a21de5c516b32b3fa2b83113ac89a2358465bc04956baab37ffb956ae43be679b2262bf7be15fce467ccd7950 +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4, minipass@npm:^7.1.2, minipass@npm:^7.1.3": + version: 7.1.3 + resolution: "minipass@npm:7.1.3" + checksum: 10/175e4d5e20980c3cd316ae82d2c031c42f6c746467d8b1905b51060a0ba4461441a0c25bb67c025fd9617f9a3873e152c7b543c6b5ac83a1846be8ade80dffd6 languageName: node linkType: hard -"minizlib@npm:^2.1.1, minizlib@npm:^2.1.2": - version: 2.1.2 - resolution: "minizlib@npm:2.1.2" - dependencies: - minipass: "npm:^3.0.0" - yallist: "npm:^4.0.0" - checksum: 10/ae0f45436fb51344dcb87938446a32fbebb540d0e191d63b35e1c773d47512e17307bf54aa88326cc6d176594d00e4423563a091f7266c2f9a6872cdc1e234d1 - languageName: node - linkType: hard - -"minizlib@npm:^3.0.1": - version: 3.0.2 - resolution: "minizlib@npm:3.0.2" +"minizlib@npm:^3.0.1, minizlib@npm:^3.1.0": + version: 3.1.0 + resolution: "minizlib@npm:3.1.0" dependencies: minipass: "npm:^7.1.2" - checksum: 10/c075bed1594f68dcc8c35122333520112daefd4d070e5d0a228bd4cf5580e9eed3981b96c0ae1d62488e204e80fd27b2b9d0068ca9a5ef3993e9565faf63ca41 - languageName: node - linkType: hard - -"mkdirp@npm:^1.0.3": - version: 1.0.4 - resolution: "mkdirp@npm:1.0.4" - bin: - mkdirp: bin/cmd.js - checksum: 10/d71b8dcd4b5af2fe13ecf3bd24070263489404fe216488c5ba7e38ece1f54daf219e72a833a3a2dc404331e870e9f44963a33399589490956bff003a3404d3b2 - languageName: node - linkType: hard - -"mkdirp@npm:^3.0.1": - version: 3.0.1 - resolution: "mkdirp@npm:3.0.1" - bin: - mkdirp: dist/cjs/src/bin.js - checksum: 10/16fd79c28645759505914561e249b9a1f5fe3362279ad95487a4501e4467abeb714fd35b95307326b8fd03f3c7719065ef11a6f97b7285d7888306d1bd2232ba + checksum: 10/f47365cc2cb7f078cbe7e046eb52655e2e7e97f8c0a9a674f4da60d94fb0624edfcec9b5db32e8ba5a99a5f036f595680ae6fe02a262beaa73026e505cc52f99 languageName: node linkType: hard @@ -11366,7 +11790,7 @@ __metadata: languageName: node linkType: hard -"ms@npm:2.1.3, ms@npm:^2.1.1, ms@npm:^2.1.3": +"ms@npm:2.1.3, ms@npm:^2.1.3": version: 2.1.3 resolution: "ms@npm:2.1.3" checksum: 10/aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d @@ -11400,7 +11824,7 @@ __metadata: languageName: node linkType: hard -"nanoid@npm:^3.3.10, nanoid@npm:^3.3.7, nanoid@npm:^3.3.8": +"nanoid@npm:^3.3.10, nanoid@npm:^3.3.11, nanoid@npm:^3.3.8": version: 3.3.11 resolution: "nanoid@npm:3.3.11" bin: @@ -11409,6 +11833,15 @@ __metadata: languageName: node linkType: hard +"napi-postinstall@npm:^0.3.0": + version: 0.3.4 + resolution: "napi-postinstall@npm:0.3.4" + bin: + napi-postinstall: lib/cli.js + checksum: 10/5541381508f9e1051ff3518701c7130ebac779abb3a1ffe9391fcc3cab4cc0569b0ba0952357db3f6b12909c3bb508359a7a60261ffd795feebbdab967175832 + languageName: node + linkType: hard + "natural-compare@npm:^1.4.0": version: 1.4.0 resolution: "natural-compare@npm:1.4.0" @@ -11416,13 +11849,20 @@ __metadata: languageName: node linkType: hard -"negotiator@npm:0.6.3, negotiator@npm:^0.6.3": +"negotiator@npm:0.6.3": version: 0.6.3 resolution: "negotiator@npm:0.6.3" checksum: 10/2723fb822a17ad55c93a588a4bc44d53b22855bf4be5499916ca0cab1e7165409d0b288ba2577d7b029f10ce18cf2ed8e703e5af31c984e1e2304277ef979837 languageName: node linkType: hard +"negotiator@npm:^1.0.0": + version: 1.0.0 + resolution: "negotiator@npm:1.0.0" + checksum: 10/b5734e87295324fabf868e36fb97c84b7d7f3156ec5f4ee5bf6e488079c11054f818290fc33804cef7b1ee21f55eeb14caea83e7dafae6492a409b3e573153e5 + languageName: node + linkType: hard + "neo-async@npm:^2.6.2": version: 2.6.2 resolution: "neo-async@npm:2.6.2" @@ -11431,13 +11871,13 @@ __metadata: linkType: hard "nock@npm:^13.3.1": - version: 13.5.5 - resolution: "nock@npm:13.5.5" + version: 13.5.6 + resolution: "nock@npm:13.5.6" dependencies: debug: "npm:^4.1.0" json-stringify-safe: "npm:^5.0.1" propagate: "npm:^2.0.0" - checksum: 10/c19d7bf9654db056357a22b00127bb5606c1bbdff188a5b6c469825e580e31cd0cb0701bce8dd8b4876dbbd36a145fdb681fd69fd59308d6db4923ce8ab2439e + checksum: 10/a57c265b75e5f7767e2f8baf058773cdbf357c31c5fea2761386ec03a008a657f9df921899fe2a9502773b47145b708863b32345aef529b3c45cba4019120f88 languageName: node linkType: hard @@ -11474,33 +11914,33 @@ __metadata: linkType: hard "node-gyp-build@npm:^4.2.0": - version: 4.8.1 - resolution: "node-gyp-build@npm:4.8.1" + version: 4.8.4 + resolution: "node-gyp-build@npm:4.8.4" bin: node-gyp-build: bin.js node-gyp-build-optional: optional.js node-gyp-build-test: build-test.js - checksum: 10/b9297770f96a92e5f2b854f3fd5e4bd418df81d7785a81ab60cec5cf2e5e72dc2c3319808978adc572cfa3885e6b12338cb5f4034bed2cab35f0d76a4b75ccdf + checksum: 10/6a7d62289d1afc419fc8fc9bd00aa4e554369e50ca0acbc215cb91446148b75ff7e2a3b53c2c5b2c09a39d416d69f3d3237937860373104b5fe429bf30ad9ac5 languageName: node linkType: hard -"node-gyp@npm:^10.0.0, node-gyp@npm:latest": - version: 10.2.0 - resolution: "node-gyp@npm:10.2.0" +"node-gyp@npm:^12.1.0, node-gyp@npm:latest": + version: 12.2.0 + resolution: "node-gyp@npm:12.2.0" dependencies: env-paths: "npm:^2.2.0" exponential-backoff: "npm:^3.1.1" - glob: "npm:^10.3.10" graceful-fs: "npm:^4.2.6" - make-fetch-happen: "npm:^13.0.0" - nopt: "npm:^7.0.0" - proc-log: "npm:^4.1.0" + make-fetch-happen: "npm:^15.0.0" + nopt: "npm:^9.0.0" + proc-log: "npm:^6.0.0" semver: "npm:^7.3.5" - tar: "npm:^6.2.1" - which: "npm:^4.0.0" + tar: "npm:^7.5.4" + tinyglobby: "npm:^0.2.12" + which: "npm:^6.0.0" bin: node-gyp: bin/node-gyp.js - checksum: 10/41773093b1275751dec942b985982fd4e7a69b88cae719b868babcef3880ee6168aaec8dcaa8cd0b9fa7c84873e36cc549c6cac6a124ee65ba4ce1f1cc108cfe + checksum: 10/4ebab5b77585a637315e969c2274b5520562473fe75de850639a580c2599652fb9f33959ec782ea45a2e149d8f04b548030f472eeeb3dbdf19a7f2ccbc30b908 languageName: node linkType: hard @@ -11511,21 +11951,21 @@ __metadata: languageName: node linkType: hard -"node-releases@npm:^2.0.19": - version: 2.0.19 - resolution: "node-releases@npm:2.0.19" - checksum: 10/c2b33b4f0c40445aee56141f13ca692fa6805db88510e5bbb3baadb2da13e1293b738e638e15e4a8eb668bb9e97debb08e7a35409b477b5cc18f171d35a83045 +"node-releases@npm:^2.0.27": + version: 2.0.27 + resolution: "node-releases@npm:2.0.27" + checksum: 10/f6c78ddb392ae500719644afcbe68a9ea533242c02312eb6a34e8478506eb7482a3fb709c70235b01c32fe65625b68dfa9665113f816d87f163bc3819b62b106 languageName: node linkType: hard -"nopt@npm:^7.0.0": - version: 7.2.1 - resolution: "nopt@npm:7.2.1" +"nopt@npm:^9.0.0": + version: 9.0.0 + resolution: "nopt@npm:9.0.0" dependencies: - abbrev: "npm:^2.0.0" + abbrev: "npm:^4.0.0" bin: nopt: bin/nopt.js - checksum: 10/95a1f6dec8a81cd18cdc2fed93e6f0b4e02cf6bdb4501c848752c6e34f9883d9942f036a5e3b21a699047d8a448562d891e67492df68ec9c373e6198133337ae + checksum: 10/56a1ccd2ad711fb5115918e2c96828703cddbe12ba2c3bd00591758f6fa30e6f47dd905c59dbfcf9b773f3a293b45996609fb6789ae29d6bfcc3cf3a6f7d9fda languageName: node linkType: hard @@ -11553,17 +11993,6 @@ __metadata: languageName: node linkType: hard -"normalize-package-data@npm:^6.0.0": - version: 6.0.2 - resolution: "normalize-package-data@npm:6.0.2" - dependencies: - hosted-git-info: "npm:^7.0.0" - semver: "npm:^7.3.5" - validate-npm-package-license: "npm:^3.0.4" - checksum: 10/7c4216a2426aa76c0197f8372f06b23a0484d62b3518fb5c0f6ebccb16376bdfab29ceba96f95c75f60506473198f1337fe337b945c8df0541fe32b8049ab4c9 - languageName: node - linkType: hard - "normalize-path@npm:^3.0.0": version: 3.0.0 resolution: "normalize-path@npm:3.0.0" @@ -11571,12 +12000,12 @@ __metadata: languageName: node linkType: hard -"npm-install-checks@npm:^6.0.0": - version: 6.3.0 - resolution: "npm-install-checks@npm:6.3.0" +"npm-install-checks@npm:^8.0.0": + version: 8.0.0 + resolution: "npm-install-checks@npm:8.0.0" dependencies: semver: "npm:^7.1.1" - checksum: 10/6c20dadb878a0d2f1f777405217b6b63af1299d0b43e556af9363ee6eefaa98a17dfb7b612a473a473e96faf7e789c58b221e0d8ffdc1d34903c4f71618df3b4 + checksum: 10/eb4df6c3270ce6efcebcbc1a02997b3b4bcfa906ac2129ccef80eeffcf062d2e6dcbed02327109296725c1eb138ad93973303e025d2e0115f718fa4c09ed013f languageName: node linkType: hard @@ -11587,27 +12016,34 @@ __metadata: languageName: node linkType: hard -"npm-package-arg@npm:^11.0.0": - version: 11.0.3 - resolution: "npm-package-arg@npm:11.0.3" +"npm-normalize-package-bin@npm:^5.0.0": + version: 5.0.0 + resolution: "npm-normalize-package-bin@npm:5.0.0" + checksum: 10/969bc042d7bb029b5da7eb733e7642b238e3cb071ad57b56a3f128069bc1a3cbc2a4f4af30ee75b11660c368d60b89811ecd1430cf2ea1a7ff36f30052a4aeda + languageName: node + linkType: hard + +"npm-package-arg@npm:^13.0.0": + version: 13.0.2 + resolution: "npm-package-arg@npm:13.0.2" dependencies: - hosted-git-info: "npm:^7.0.0" - proc-log: "npm:^4.0.0" + hosted-git-info: "npm:^9.0.0" + proc-log: "npm:^6.0.0" semver: "npm:^7.3.5" - validate-npm-package-name: "npm:^5.0.0" - checksum: 10/bacc863907edf98940286edc2fd80327901c1e8b34426d538cdc708ed66bc6567f06d742d838eaf35db6804347bb4ba56ca9cef032c4b52743b33e7a22a2678e + validate-npm-package-name: "npm:^7.0.0" + checksum: 10/810868f4b8c666fc1979f33c5b45606f541be97e82958af486e8d3f5ff2c91f96cea56f22c4665a92dc9a23698cf831cba2e09691387d473f910f9e6590638b3 languageName: node linkType: hard -"npm-pick-manifest@npm:^9.0.0": - version: 9.1.0 - resolution: "npm-pick-manifest@npm:9.1.0" +"npm-pick-manifest@npm:^11.0.1": + version: 11.0.3 + resolution: "npm-pick-manifest@npm:11.0.3" dependencies: - npm-install-checks: "npm:^6.0.0" - npm-normalize-package-bin: "npm:^3.0.0" - npm-package-arg: "npm:^11.0.0" + npm-install-checks: "npm:^8.0.0" + npm-normalize-package-bin: "npm:^5.0.0" + npm-package-arg: "npm:^13.0.0" semver: "npm:^7.3.5" - checksum: 10/e759e4fe4076da9169cf522964a80bbc096d50cd24c8c44b50b44706c4479bd9d9d018fbdb76c6ea0c6037e012e07c6c917a1ecaa7ae1a1169cddfae1c0f24b6 + checksum: 10/189872190af34f7eccf3c586ad2e21e8c093f90a8f716db80887e8defa2bfb3ea917f61f339908ce0487a4cb1df40fe592aee3e8fe76a180a5b15a887850921a languageName: node linkType: hard @@ -11646,14 +12082,14 @@ __metadata: languageName: node linkType: hard -"object-inspect@npm:^1.13.1": - version: 1.13.2 - resolution: "object-inspect@npm:1.13.2" - checksum: 10/7ef65583b6397570a17c56f0c1841e0920e83900f2c94638927abb7b81ac08a19c7aae135bd9dcca96208cac0c7332b4650fb927f027b0cf92d71df2990d0561 +"object-inspect@npm:^1.13.3": + version: 1.13.4 + resolution: "object-inspect@npm:1.13.4" + checksum: 10/aa13b1190ad3e366f6c83ad8a16ed37a19ed57d267385aa4bfdccda833d7b90465c057ff6c55d035a6b2e52c1a2295582b294217a0a3a1ae7abdd6877ef781fb languageName: node linkType: hard -"on-finished@npm:2.4.1": +"on-finished@npm:~2.4.1": version: 2.4.1 resolution: "on-finished@npm:2.4.1" dependencies: @@ -11690,14 +12126,14 @@ __metadata: linkType: hard "open@npm:^10.1.0": - version: 10.1.0 - resolution: "open@npm:10.1.0" + version: 10.2.0 + resolution: "open@npm:10.2.0" dependencies: default-browser: "npm:^5.2.1" define-lazy-prop: "npm:^3.0.0" is-inside-container: "npm:^1.0.0" - is-wsl: "npm:^3.1.0" - checksum: 10/a9c4105243a1b3c5312bf2aeb678f78d31f00618b5100088ee01eed2769963ea1f2dd464ac8d93cef51bba2d911e1a9c0c34a753ec7b91d6b22795903ea6647a + wsl-utils: "npm:^0.1.0" + checksum: 10/e6ad9474734eac3549dcc7d85e952394856ccaee48107c453bd6a725b82e3b8ed5f427658935df27efa76b411aeef62888edea8a9e347e8e7c82632ec966b30e languageName: node linkType: hard @@ -11751,12 +12187,10 @@ __metadata: languageName: node linkType: hard -"p-map@npm:^4.0.0": - version: 4.0.0 - resolution: "p-map@npm:4.0.0" - dependencies: - aggregate-error: "npm:^3.0.0" - checksum: 10/7ba4a2b1e24c05e1fc14bbaea0fc6d85cf005ae7e9c9425d4575550f37e2e584b1af97bcde78eacd7559208f20995988d52881334db16cf77bc1bcf68e48ed7c +"p-map@npm:^7.0.2": + version: 7.0.4 + resolution: "p-map@npm:7.0.4" + checksum: 10/ef48c3b2e488f31c693c9fcc0df0ef76518cf6426a495cf9486ebbb0fd7f31aef7f90e96f72e0070c0ff6e3177c9318f644b512e2c29e3feee8d7153fcb6782e languageName: node linkType: hard @@ -11775,9 +12209,9 @@ __metadata: linkType: hard "package-json-from-dist@npm:^1.0.0": - version: 1.0.0 - resolution: "package-json-from-dist@npm:1.0.0" - checksum: 10/ac706ec856a5a03f5261e4e48fa974f24feb044d51f84f8332e2af0af04fbdbdd5bbbfb9cbbe354190409bc8307c83a9e38c6672c3c8855f709afb0006a009ea + version: 1.0.1 + resolution: "package-json-from-dist@npm:1.0.1" + checksum: 10/58ee9538f2f762988433da00e26acc788036914d57c71c246bf0be1b60cdbd77dd60b6a3e1a30465f0b248aeb80079e0b34cb6050b1dfa18c06953bb1cbc7602 languageName: node linkType: hard @@ -11790,13 +12224,12 @@ __metadata: languageName: node linkType: hard -"parse-imports@npm:^2.1.1": - version: 2.2.1 - resolution: "parse-imports@npm:2.2.1" +"parse-imports-exports@npm:^0.2.4": + version: 0.2.4 + resolution: "parse-imports-exports@npm:0.2.4" dependencies: - es-module-lexer: "npm:^1.5.3" - slashes: "npm:^3.0.12" - checksum: 10/db1d98077587d23bfa1f136abae158ea08e1e588d0260dfc0769092be86b842c798ae47466742b1d9bc106d3430cebbd9730fc34872a2c0e72b9ff720986e82e + parse-statements: "npm:1.0.11" + checksum: 10/144d459771d1aeaa80eebffe43a2074c34e5b79a86d326c907efea90b62ff41af9555600b8e117e6cab717654d8e20b440e9ab09cdbbc9092f352cb0a9e1f3a3 languageName: node linkType: hard @@ -11819,6 +12252,13 @@ __metadata: languageName: node linkType: hard +"parse-statements@npm:1.0.11": + version: 1.0.11 + resolution: "parse-statements@npm:1.0.11" + checksum: 10/287c2739f4cbffa08e28a95ea2d3ff4a8a51ddb367df6212ae2cd80580a1189e09c6edcb8277fc05d0fdbcb93c86ad16b591f317e2fe12ac4189de738863e514 + languageName: node + linkType: hard + "parse5@npm:^7.0.0, parse5@npm:^7.1.1": version: 7.3.0 resolution: "parse5@npm:7.3.0" @@ -11880,7 +12320,17 @@ __metadata: languageName: node linkType: hard -"path-to-regexp@npm:0.1.12": +"path-scurry@npm:^2.0.2": + version: 2.0.2 + resolution: "path-scurry@npm:2.0.2" + dependencies: + lru-cache: "npm:^11.0.0" + minipass: "npm:^7.1.2" + checksum: 10/2b4257422bcb870a4c2d205b3acdbb213a72f5e2250f61c80f79c9d014d010f82bdf8584441612c8e1fa4eb098678f5704a66fa8377d72646bad4be38e57a2c3 + languageName: node + linkType: hard + +"path-to-regexp@npm:~0.1.12": version: 0.1.12 resolution: "path-to-regexp@npm:0.1.12" checksum: 10/2e30f6a0144679c1f95c98e166b96e6acd1e72be9417830fefc8de7ac1992147eb9a4c7acaa59119fb1b3c34eec393b2129ef27e24b2054a3906fc4fb0d1398e @@ -11895,19 +12345,20 @@ __metadata: linkType: hard "pbkdf2@npm:^3.0.17": - version: 3.1.2 - resolution: "pbkdf2@npm:3.1.2" + version: 3.1.5 + resolution: "pbkdf2@npm:3.1.5" dependencies: - create-hash: "npm:^1.1.2" - create-hmac: "npm:^1.1.4" - ripemd160: "npm:^2.0.1" - safe-buffer: "npm:^5.0.1" - sha.js: "npm:^2.4.8" - checksum: 10/40bdf30df1c9bb1ae41ec50c11e480cf0d36484b7c7933bf55e4451d1d0e3f09589df70935c56e7fccc5702779a0d7b842d012be8c08a187b44eb24d55bb9460 + create-hash: "npm:^1.2.0" + create-hmac: "npm:^1.1.7" + ripemd160: "npm:^2.0.3" + safe-buffer: "npm:^5.2.1" + sha.js: "npm:^2.4.12" + to-buffer: "npm:^1.2.1" + checksum: 10/ce1c9a2ebbc843c86090ec6cac6d07429dece7c1fdb87437ce6cf869d0429cc39cab61bc34215585f4a00d8009862df45e197fbd54f3508ccba8ff312a88261b languageName: node linkType: hard -"picocolors@npm:^1.0.1, picocolors@npm:^1.1.1": +"picocolors@npm:^1.1.1": version: 1.1.1 resolution: "picocolors@npm:1.1.1" checksum: 10/e1cf46bf84886c79055fdfa9dcb3e4711ad259949e3565154b004b260cd356c5d54b31a1437ce9782624bf766272fe6b0154f5f0c744fb7af5d454d2b60db045 @@ -11921,7 +12372,7 @@ __metadata: languageName: node linkType: hard -"picomatch@npm:^4.0.3": +"picomatch@npm:^4.0.2, picomatch@npm:^4.0.3": version: 4.0.3 resolution: "picomatch@npm:4.0.3" checksum: 10/57b99055f40b16798f2802916d9c17e9744e620a0db136554af01d19598b96e45e2f00014c91d1b8b13874b80caa8c295b3d589a3f72373ec4aaf54baa5962d5 @@ -11936,9 +12387,9 @@ __metadata: linkType: hard "pirates@npm:^4.0.4": - version: 4.0.6 - resolution: "pirates@npm:4.0.6" - checksum: 10/d02dda76f4fec1cbdf395c36c11cf26f76a644f9f9a1bfa84d3167d0d3154d5289aacc72677aa20d599bb4a6937a471de1b65c995e2aea2d8687cbcd7e43ea5f + version: 4.0.7 + resolution: "pirates@npm:4.0.7" + checksum: 10/2427f371366081ae42feb58214f04805d6b41d6b84d74480ebcc9e0ddbd7105a139f7c653daeaf83ad8a1a77214cf07f64178e76de048128fec501eab3305a96 languageName: node linkType: hard @@ -11976,14 +12427,21 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^8.4.40": - version: 8.4.41 - resolution: "postcss@npm:8.4.41" +"possible-typed-array-names@npm:^1.0.0": + version: 1.1.0 + resolution: "possible-typed-array-names@npm:1.1.0" + checksum: 10/2f44137b8d3dd35f4a7ba7469eec1cd9cfbb46ec164b93a5bc1f4c3d68599c9910ee3b91da1d28b4560e9cc8414c3cd56fedc07259c67e52cc774476270d3302 + languageName: node + linkType: hard + +"postcss@npm:^8.5.6": + version: 8.5.6 + resolution: "postcss@npm:8.5.6" dependencies: - nanoid: "npm:^3.3.7" - picocolors: "npm:^1.0.1" - source-map-js: "npm:^1.2.0" - checksum: 10/6e6176c2407eff60493ca60a706c6b7def20a722c3adda94ea1ece38345eb99964191336fd62b62652279cec6938e79e0b1e1d477142c8d3516e7a725a74ee37 + nanoid: "npm:^3.3.11" + picocolors: "npm:^1.1.1" + source-map-js: "npm:^1.2.1" + checksum: 10/9e4fbe97574091e9736d0e82a591e29aa100a0bf60276a926308f8c57249698935f35c5d2f4e80de778d0cbb8dcffab4f383d85fd50c5649aca421c3df729b86 languageName: node linkType: hard @@ -12003,36 +12461,46 @@ __metadata: languageName: node linkType: hard -"prettier-linter-helpers@npm:^1.0.0": - version: 1.0.0 - resolution: "prettier-linter-helpers@npm:1.0.0" +"prettier-linter-helpers@npm:^1.0.1": + version: 1.0.1 + resolution: "prettier-linter-helpers@npm:1.0.1" dependencies: fast-diff: "npm:^1.1.2" - checksum: 10/00ce8011cf6430158d27f9c92cfea0a7699405633f7f1d4a45f07e21bf78e99895911cbcdc3853db3a824201a7c745bd49bfea8abd5fb9883e765a90f74f8392 + checksum: 10/2dc35f5036a35f4c4f5e645887edda1436acb63687a7f12b2383e0a6f3c1f76b8a0a4709fe4d82e19157210feb5984b159bb714d43290022911ab53d606474ec languageName: node linkType: hard "prettier-plugin-packagejson@npm:^2.4.5": - version: 2.5.2 - resolution: "prettier-plugin-packagejson@npm:2.5.2" + version: 2.5.22 + resolution: "prettier-plugin-packagejson@npm:2.5.22" dependencies: - sort-package-json: "npm:2.10.1" - synckit: "npm:0.9.1" + sort-package-json: "npm:3.6.0" peerDependencies: prettier: ">= 1.16.0" peerDependenciesMeta: prettier: optional: true - checksum: 10/f280d69327a468cd104c72a81134258d3573e56d697a88a5c4498c8d02cecda9a27d9eb3f1d29cc726491782eb3f279c9d41ecf8364a197e20b239c5ccfd0269 + checksum: 10/874ba785d6c3c32abca23470cebfd7b80de7b546c0b3752a83cf5aea7a8030885f0c3a91ef40c52373c1be144b46983d1e5bc6d492096d79604441eae6ed1be0 languageName: node linkType: hard "prettier@npm:^3.3.3": - version: 3.4.2 - resolution: "prettier@npm:3.4.2" + version: 3.8.1 + resolution: "prettier@npm:3.8.1" bin: prettier: bin/prettier.cjs - checksum: 10/a3e806fb0b635818964d472d35d27e21a4e17150c679047f5501e1f23bd4aa806adf660f0c0d35214a210d5d440da6896c2e86156da55f221a57938278dc326e + checksum: 10/3da1cf8c1ef9bea828aa618553696c312e951f810bee368f6887109b203f18ee869fe88f66e65f9cf60b7cb1f2eae859892c860a300c062ff8ec69c381fc8dbd + languageName: node + linkType: hard + +"pretty-format@npm:30.2.0, pretty-format@npm:^30.0.0": + version: 30.2.0 + resolution: "pretty-format@npm:30.2.0" + dependencies: + "@jest/schemas": "npm:30.0.5" + ansi-styles: "npm:^5.2.0" + react-is: "npm:^18.3.1" + checksum: 10/725890d648e3400575eebc99a334a4cd1498e0d36746313913706bbeea20ada27e17c184a3cd45c50f705c16111afa829f3450233fc0fda5eed293c69757e926 languageName: node linkType: hard @@ -12047,10 +12515,10 @@ __metadata: languageName: node linkType: hard -"proc-log@npm:^4.0.0, proc-log@npm:^4.1.0, proc-log@npm:^4.2.0": - version: 4.2.0 - resolution: "proc-log@npm:4.2.0" - checksum: 10/4e1394491b717f6c1ade15c570ecd4c2b681698474d3ae2d303c1e4b6ab9455bd5a81566211e82890d5a5ae9859718cc6954d5150bb18b09b72ecb297beae90a +"proc-log@npm:^6.0.0": + version: 6.1.0 + resolution: "proc-log@npm:6.1.0" + checksum: 10/9033f30f168ed5a0991b773d0c50ff88384c4738e9a0a67d341de36bf7293771eed648ab6a0562f62276da12fde91f3bbfc75ffff6e71ad49aafd74fc646be66 languageName: node linkType: hard @@ -12068,13 +12536,6 @@ __metadata: languageName: node linkType: hard -"promise-inflight@npm:^1.0.1": - version: 1.0.1 - resolution: "promise-inflight@npm:1.0.1" - checksum: 10/1560d413ea20c5a74f3631d39ba8cbd1972b9228072a755d01e1f5ca5110382d9af76a1582d889445adc6e75bb5ac4886b56dc4b6eae51b30145d7bb1ac7505b - languageName: node - linkType: hard - "promise-retry@npm:^2.0.1": version: 2.0.1 resolution: "promise-retry@npm:2.0.1" @@ -12113,8 +12574,8 @@ __metadata: linkType: hard "protobufjs@npm:^7.2.5": - version: 7.4.0 - resolution: "protobufjs@npm:7.4.0" + version: 7.5.4 + resolution: "protobufjs@npm:7.5.4" dependencies: "@protobufjs/aspromise": "npm:^1.1.2" "@protobufjs/base64": "npm:^1.1.2" @@ -12128,7 +12589,7 @@ __metadata: "@protobufjs/utf8": "npm:^1.1.0" "@types/node": "npm:>=13.7.0" long: "npm:^5.0.0" - checksum: 10/408423506610f70858d7593632f4a6aa4f05796c90fd632be9b9252457c795acc71aa6d3b54bb7f48a890141728fee4ca3906723ccea6c202ad71f21b3879b8b + checksum: 10/88d677bb6f11a2ecec63fdd053dfe6d31120844d04e865efa9c8fbe0674cd077d6624ecfdf014018a20dcb114ae2a59c1b21966dd8073e920650c71370966439 languageName: node linkType: hard @@ -12150,9 +12611,11 @@ __metadata: linkType: hard "psl@npm:^1.1.33": - version: 1.9.0 - resolution: "psl@npm:1.9.0" - checksum: 10/d07879d4bfd0ac74796306a8e5a36a93cfb9c4f4e8ee8e63fbb909066c192fe1008cd8f12abd8ba2f62ca28247949a20c8fb32e1d18831d9e71285a1569720f9 + version: 1.15.0 + resolution: "psl@npm:1.15.0" + dependencies: + punycode: "npm:^2.3.1" + checksum: 10/5e7467eb5196eb7900d156783d12907d445c0122f76c73203ce96b148a6ccf8c5450cc805887ffada38ff92d634afcf33720c24053cb01d5b6598d1c913c5caf languageName: node linkType: hard @@ -12163,7 +12626,7 @@ __metadata: languageName: node linkType: hard -"punycode@npm:^2.1.0, punycode@npm:^2.1.1": +"punycode@npm:^2.1.0, punycode@npm:^2.1.1, punycode@npm:^2.3.1": version: 2.3.1 resolution: "punycode@npm:2.3.1" checksum: 10/febdc4362bead22f9e2608ff0171713230b57aff9dddc1c273aa2a651fbd366f94b7d6a71d78342a7c0819906750351ca7f2edd26ea41b626d87d6a13d1bd059 @@ -12177,12 +12640,21 @@ __metadata: languageName: node linkType: hard -"qs@npm:6.13.0, qs@npm:^6.11.2": - version: 6.13.0 - resolution: "qs@npm:6.13.0" +"qs@npm:^6.11.2": + version: 6.15.0 + resolution: "qs@npm:6.15.0" + dependencies: + side-channel: "npm:^1.1.0" + checksum: 10/a3458f2f389285c3512e0ebc55522ee370ac7cb720ba9f0eff3e30fb2bb07631caf556c08e2a3d4481a371ac14faa9ceb7442a0610c5a7e55b23a5bdee7b701c + languageName: node + linkType: hard + +"qs@npm:~6.14.0": + version: 6.14.2 + resolution: "qs@npm:6.14.2" dependencies: - side-channel: "npm:^1.0.6" - checksum: 10/f548b376e685553d12e461409f0d6e5c59ec7c7d76f308e2a888fd9db3e0c5e89902bedd0754db3a9038eda5f27da2331a6f019c8517dc5e0a16b3c9a6e9cef8 + side-channel: "npm:^1.1.0" + checksum: 10/682933a85bb4b7bd0d66e13c0a40d9e612b5e4bcc2cb9238f711a9368cd22d91654097a74fff93551e58146db282c56ac094957dfdc60ce64ea72c3c9d7779ac languageName: node linkType: hard @@ -12200,13 +12672,6 @@ __metadata: languageName: node linkType: hard -"queue-tick@npm:^1.0.1": - version: 1.0.1 - resolution: "queue-tick@npm:1.0.1" - checksum: 10/f447926c513b64a857906f017a3b350f7d11277e3c8d2a21a42b7998fa1a613d7a829091e12d142bb668905c8f68d8103416c7197856efb0c72fa835b8e254b5 - languageName: node - linkType: hard - "quick-lru@npm:^4.0.1": version: 4.0.1 resolution: "quick-lru@npm:4.0.1" @@ -12230,19 +12695,19 @@ __metadata: languageName: node linkType: hard -"raw-body@npm:2.5.2": - version: 2.5.2 - resolution: "raw-body@npm:2.5.2" +"raw-body@npm:~2.5.3": + version: 2.5.3 + resolution: "raw-body@npm:2.5.3" dependencies: - bytes: "npm:3.1.2" - http-errors: "npm:2.0.0" - iconv-lite: "npm:0.4.24" - unpipe: "npm:1.0.0" - checksum: 10/863b5171e140546a4d99f349b720abac4410338e23df5e409cfcc3752538c9caf947ce382c89129ba976f71894bd38b5806c774edac35ebf168d02aa1ac11a95 + bytes: "npm:~3.1.2" + http-errors: "npm:~2.0.1" + iconv-lite: "npm:~0.4.24" + unpipe: "npm:~1.0.0" + checksum: 10/f35759fe5a6548e7c529121ead1de4dd163f899749a5896c42e278479df2d9d7f98b5bb17312737c03617765e5a1433e586f717616e5cfbebc13b4738b820601 languageName: node linkType: hard -"react-is@npm:^18.0.0": +"react-is@npm:^18.0.0, react-is@npm:^18.3.1": version: 18.3.1 resolution: "react-is@npm:18.3.1" checksum: 10/d5f60c87d285af24b1e1e7eaeb123ec256c3c8bdea7061ab3932e3e14685708221bf234ec50b21e10dd07f008f1b966a2730a0ce4ff67905b3872ff2042aec22 @@ -12290,7 +12755,7 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^2.0.2": +"readable-stream@npm:^2.0.2, readable-stream@npm:^2.3.8": version: 2.3.8 resolution: "readable-stream@npm:2.3.8" dependencies: @@ -12305,25 +12770,25 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^3.6.2 || ^4.4.2": - version: 4.5.2 - resolution: "readable-stream@npm:4.5.2" +"readable-stream@npm:^3.6.2 || ^4.4.2, readable-stream@npm:^4.7.0": + version: 4.7.0 + resolution: "readable-stream@npm:4.7.0" dependencies: abort-controller: "npm:^3.0.0" buffer: "npm:^6.0.3" events: "npm:^3.3.0" process: "npm:^0.11.10" string_decoder: "npm:^1.3.0" - checksum: 10/01b128a559c5fd76a898495f858cf0a8839f135e6a69e3409f986e88460134791657eb46a2ff16826f331682a3c4d0c5a75cef5e52ef259711021ba52b1c2e82 + checksum: 10/bdf096c8ff59452ce5d08f13da9597f9fcfe400b4facfaa88e74ec057e5ad1fdfa140ffe28e5ed806cf4d2055f0b812806e962bca91dce31bc4cef08e53be3a4 languageName: node linkType: hard "readable-web-to-node-stream@npm:^3.0.2": - version: 3.0.2 - resolution: "readable-web-to-node-stream@npm:3.0.2" + version: 3.0.4 + resolution: "readable-web-to-node-stream@npm:3.0.4" dependencies: - readable-stream: "npm:^3.6.0" - checksum: 10/d3a5bf9d707c01183d546a64864aa63df4d9cb835dfd2bf89ac8305e17389feef2170c4c14415a10d38f9b9bfddf829a57aaef7c53c8b40f11d499844bf8f1a4 + readable-stream: "npm:^4.7.0" + checksum: 10/d8fb3de7579d70ea1e9efdfb2f02e2965ae62a1e1d9e9b0bdce493cb3b98090bd4a34526a9ab6c793bb833b89ffd31a5ab06117a3ae2a3df21363651b2131da9 languageName: node linkType: hard @@ -12353,13 +12818,6 @@ __metadata: languageName: node linkType: hard -"regenerator-runtime@npm:^0.14.0": - version: 0.14.1 - resolution: "regenerator-runtime@npm:0.14.1" - checksum: 10/5db3161abb311eef8c45bcf6565f4f378f785900ed3945acf740a9888c792f75b98ecb77f0775f3bf95502ff423529d23e94f41d80c8256e8fa05ed4b07cf471 - languageName: node - linkType: hard - "require-directory@npm:^2.1.1": version: 2.1.1 resolution: "require-directory@npm:2.1.1" @@ -12435,20 +12893,7 @@ __metadata: languageName: node linkType: hard -"resolve@npm:1.22.8": - version: 1.22.8 - resolution: "resolve@npm:1.22.8" - dependencies: - is-core-module: "npm:^2.13.0" - path-parse: "npm:^1.0.7" - supports-preserve-symlinks-flag: "npm:^1.0.0" - bin: - resolve: bin/resolve - checksum: 10/c473506ee01eb45cbcfefb68652ae5759e092e6b0fb64547feadf9736a6394f258fbc6f88e00c5ca36d5477fbb65388b272432a3600fa223062e54333c156753 - languageName: node - linkType: hard - -"resolve@npm:^1.10.0, resolve@npm:^1.20.0, resolve@npm:^1.22.3, resolve@npm:^1.22.4": +"resolve@npm:1.22.10": version: 1.22.10 resolution: "resolve@npm:1.22.10" dependencies: @@ -12461,20 +12906,20 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@npm%3A1.22.8#optional!builtin": - version: 1.22.8 - resolution: "resolve@patch:resolve@npm%3A1.22.8#optional!builtin::version=1.22.8&hash=c3c19d" +"resolve@npm:^1.10.0, resolve@npm:^1.20.0, resolve@npm:^1.22.3": + version: 1.22.11 + resolution: "resolve@npm:1.22.11" dependencies: - is-core-module: "npm:^2.13.0" + is-core-module: "npm:^2.16.1" path-parse: "npm:^1.0.7" supports-preserve-symlinks-flag: "npm:^1.0.0" bin: resolve: bin/resolve - checksum: 10/f345cd37f56a2c0275e3fe062517c650bb673815d885e7507566df589375d165bbbf4bdb6aa95600a9bc55f4744b81f452b5a63f95b9f10a72787dba3c90890a + checksum: 10/e1b2e738884a08de03f97ee71494335eba8c2b0feb1de9ae065e82c48997f349f77a2b10e8817e147cf610bfabc4b1cb7891ee8eaf5bf80d4ad514a34c4fab0a languageName: node linkType: hard -"resolve@patch:resolve@npm%3A^1.10.0#optional!builtin, resolve@patch:resolve@npm%3A^1.20.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.3#optional!builtin, resolve@patch:resolve@npm%3A^1.22.4#optional!builtin": +"resolve@patch:resolve@npm%3A1.22.10#optional!builtin": version: 1.22.10 resolution: "resolve@patch:resolve@npm%3A1.22.10#optional!builtin::version=1.22.10&hash=c3c19d" dependencies: @@ -12487,6 +12932,19 @@ __metadata: languageName: node linkType: hard +"resolve@patch:resolve@npm%3A^1.10.0#optional!builtin, resolve@patch:resolve@npm%3A^1.20.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.3#optional!builtin": + version: 1.22.11 + resolution: "resolve@patch:resolve@npm%3A1.22.11#optional!builtin::version=1.22.11&hash=c3c19d" + dependencies: + is-core-module: "npm:^2.16.1" + path-parse: "npm:^1.0.7" + supports-preserve-symlinks-flag: "npm:^1.0.0" + bin: + resolve: bin/resolve + checksum: 10/fd342cad25e52cd6f4f3d1716e189717f2522bfd6641109fe7aa372f32b5714a296ed7c238ddbe7ebb0c1ddfe0b7f71c9984171024c97cf1b2073e3e40ff71a8 + languageName: node + linkType: hard + "retry@npm:^0.12.0": version: 0.12.0 resolution: "retry@npm:0.12.0" @@ -12495,9 +12953,9 @@ __metadata: linkType: hard "reusify@npm:^1.0.4": - version: 1.0.4 - resolution: "reusify@npm:1.0.4" - checksum: 10/14222c9e1d3f9ae01480c50d96057228a8524706db79cdeb5a2ce5bb7070dd9f409a6f84a02cbef8cdc80d39aef86f2dd03d155188a1300c599b05437dcd2ffb + version: 1.1.0 + resolution: "reusify@npm:1.1.0" + checksum: 10/af47851b547e8a8dc89af144fceee17b80d5beaf5e6f57ed086432d79943434ff67ca526e92275be6f54b6189f6920a24eace75c2657eed32d02c400312b21ec languageName: node linkType: hard @@ -12519,13 +12977,13 @@ __metadata: languageName: node linkType: hard -"ripemd160@npm:^2.0.0, ripemd160@npm:^2.0.1": - version: 2.0.2 - resolution: "ripemd160@npm:2.0.2" +"ripemd160@npm:^2.0.0, ripemd160@npm:^2.0.1, ripemd160@npm:^2.0.3": + version: 2.0.3 + resolution: "ripemd160@npm:2.0.3" dependencies: - hash-base: "npm:^3.0.0" - inherits: "npm:^2.0.1" - checksum: 10/006accc40578ee2beae382757c4ce2908a826b27e2b079efdcd2959ee544ddf210b7b5d7d5e80467807604244e7388427330f5c6d4cd61e6edaddc5773ccc393 + hash-base: "npm:^3.1.2" + inherits: "npm:^2.0.4" + checksum: 10/d15d42ea0460426675e5320f86d3468ab408af95b1761cf35f8d32c0c97b4d3bb72b7226e990e643b96e1637a8ad26b343a6c7666e1a297bcab4f305a1d9d3e3 languageName: node linkType: hard @@ -12541,9 +12999,9 @@ __metadata: linkType: hard "run-applescript@npm:^7.0.0": - version: 7.0.0 - resolution: "run-applescript@npm:7.0.0" - checksum: 10/b02462454d8b182ad4117e5d4626e9e6782eb2072925c9fac582170b0627ae3c1ea92ee9b2df7daf84b5e9ffe14eb1cf5fb70bc44b15c8a0bfcdb47987e2410c + version: 7.1.0 + resolution: "run-applescript@npm:7.1.0" + checksum: 10/8659fb5f2717b2b37a68cbfe5f678254cf24b5a82a6df3372b180c80c7c137dcd757a4166c3887e459f59a090ca414e8ea7ca97cf3ee5123db54b3b4006d7b7a languageName: node linkType: hard @@ -12563,7 +13021,7 @@ __metadata: languageName: node linkType: hard -"safe-buffer@npm:5.2.1, safe-buffer@npm:>=5.1.0, safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.1.1, safe-buffer@npm:^5.1.2, safe-buffer@npm:^5.2.0, safe-buffer@npm:~5.2.0": +"safe-buffer@npm:5.2.1, safe-buffer@npm:>=5.1.0, safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.1.1, safe-buffer@npm:^5.1.2, safe-buffer@npm:^5.2.1, safe-buffer@npm:~5.2.0": version: 5.2.1 resolution: "safe-buffer@npm:5.2.1" checksum: 10/32872cd0ff68a3ddade7a7617b8f4c2ae8764d8b7d884c651b74457967a9e0e886267d3ecc781220629c44a865167b61c375d2da6c720c840ecd73f45d5d9451 @@ -12644,45 +13102,45 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.1.1, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0, semver@npm:^7.6.3, semver@npm:^7.7.3": - version: 7.7.3 - resolution: "semver@npm:7.7.3" +"semver@npm:^7.1.1, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.3, semver@npm:^7.7.1, semver@npm:^7.7.2, semver@npm:^7.7.3": + version: 7.7.4 + resolution: "semver@npm:7.7.4" bin: semver: bin/semver.js - checksum: 10/8dbc3168e057a38fc322af909c7f5617483c50caddba135439ff09a754b20bdd6482a5123ff543dad4affa488ecf46ec5fb56d61312ad20bb140199b88dfaea9 + checksum: 10/26bdc6d58b29528f4142d29afb8526bc335f4fc04c4a10f2b98b217f277a031c66736bf82d3d3bb354a2f6a3ae50f18fd62b053c4ac3f294a3d10a61f5075b75 languageName: node linkType: hard -"send@npm:0.19.0": - version: 0.19.0 - resolution: "send@npm:0.19.0" +"send@npm:~0.19.0, send@npm:~0.19.1": + version: 0.19.2 + resolution: "send@npm:0.19.2" dependencies: debug: "npm:2.6.9" depd: "npm:2.0.0" destroy: "npm:1.2.0" - encodeurl: "npm:~1.0.2" + encodeurl: "npm:~2.0.0" escape-html: "npm:~1.0.3" etag: "npm:~1.8.1" - fresh: "npm:0.5.2" - http-errors: "npm:2.0.0" + fresh: "npm:~0.5.2" + http-errors: "npm:~2.0.1" mime: "npm:1.6.0" ms: "npm:2.1.3" - on-finished: "npm:2.4.1" + on-finished: "npm:~2.4.1" range-parser: "npm:~1.2.1" - statuses: "npm:2.0.1" - checksum: 10/1f6064dea0ae4cbe4878437aedc9270c33f2a6650a77b56a16b62d057527f2766d96ee282997dd53ec0339082f2aad935bc7d989b46b48c82fc610800dc3a1d0 + statuses: "npm:~2.0.2" + checksum: 10/e932a592f62c58560b608a402d52333a8ae98a5ada076feb5db1d03adaa77c3ca32a7befa1c4fd6dedc186e88f342725b0cb4b3d86835eaf834688b259bef18d languageName: node linkType: hard -"serve-static@npm:1.16.2": - version: 1.16.2 - resolution: "serve-static@npm:1.16.2" +"serve-static@npm:~1.16.2": + version: 1.16.3 + resolution: "serve-static@npm:1.16.3" dependencies: encodeurl: "npm:~2.0.0" escape-html: "npm:~1.0.3" parseurl: "npm:~1.3.3" - send: "npm:0.19.0" - checksum: 10/7fa9d9c68090f6289976b34fc13c50ac8cd7f16ae6bce08d16459300f7fc61fbc2d7ebfa02884c073ec9d6ab9e7e704c89561882bbe338e99fcacb2912fde737 + send: "npm:~0.19.1" + checksum: 10/149d6718dd9e53166784d0a65535e21a7c01249d9c51f57224b786a7306354c6807e7811a9f6c143b45c863b1524721fca2f52b5c81a8b5194e3dde034a03b9c languageName: node linkType: hard @@ -12725,22 +13183,23 @@ __metadata: languageName: node linkType: hard -"setprototypeof@npm:1.2.0": +"setprototypeof@npm:1.2.0, setprototypeof@npm:~1.2.0": version: 1.2.0 resolution: "setprototypeof@npm:1.2.0" checksum: 10/fde1630422502fbbc19e6844346778f99d449986b2f9cdcceb8326730d2f3d9964dbcb03c02aaadaefffecd0f2c063315ebea8b3ad895914bf1afc1747fc172e languageName: node linkType: hard -"sha.js@npm:^2.4.0, sha.js@npm:^2.4.8": - version: 2.4.11 - resolution: "sha.js@npm:2.4.11" +"sha.js@npm:^2.4.0, sha.js@npm:^2.4.12, sha.js@npm:^2.4.8": + version: 2.4.12 + resolution: "sha.js@npm:2.4.12" dependencies: - inherits: "npm:^2.0.1" - safe-buffer: "npm:^5.0.1" + inherits: "npm:^2.0.4" + safe-buffer: "npm:^5.2.1" + to-buffer: "npm:^1.2.0" bin: - sha.js: ./bin.js - checksum: 10/d833bfa3e0a67579a6ce6e1bc95571f05246e0a441dd8c76e3057972f2a3e098465687a4369b07e83a0375a88703577f71b5b2e966809e67ebc340dbedb478c7 + sha.js: bin.js + checksum: 10/39c0993592c2ab34eb2daae2199a2a1d502713765aecb611fd97c0c4ab7cd53e902d628e1962aaf384bafd28f55951fef46dcc78799069ce41d74b03aa13b5a7 languageName: node linkType: hard @@ -12779,15 +13238,51 @@ __metadata: languageName: node linkType: hard -"side-channel@npm:^1.0.6": - version: 1.0.6 - resolution: "side-channel@npm:1.0.6" +"side-channel-list@npm:^1.0.0": + version: 1.0.0 + resolution: "side-channel-list@npm:1.0.0" dependencies: - call-bind: "npm:^1.0.7" es-errors: "npm:^1.3.0" - get-intrinsic: "npm:^1.2.4" - object-inspect: "npm:^1.13.1" - checksum: 10/eb10944f38cebad8ad643dd02657592fa41273ce15b8bfa928d3291aff2d30c20ff777cfe908f76ccc4551ace2d1245822fdc576657cce40e9066c638ca8fa4d + object-inspect: "npm:^1.13.3" + checksum: 10/603b928997abd21c5a5f02ae6b9cc36b72e3176ad6827fab0417ead74580cc4fb4d5c7d0a8a2ff4ead34d0f9e35701ed7a41853dac8a6d1a664fcce1a044f86f + languageName: node + linkType: hard + +"side-channel-map@npm:^1.0.1": + version: 1.0.1 + resolution: "side-channel-map@npm:1.0.1" + dependencies: + call-bound: "npm:^1.0.2" + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.5" + object-inspect: "npm:^1.13.3" + checksum: 10/5771861f77feefe44f6195ed077a9e4f389acc188f895f570d56445e251b861754b547ea9ef73ecee4e01fdada6568bfe9020d2ec2dfc5571e9fa1bbc4a10615 + languageName: node + linkType: hard + +"side-channel-weakmap@npm:^1.0.2": + version: 1.0.2 + resolution: "side-channel-weakmap@npm:1.0.2" + dependencies: + call-bound: "npm:^1.0.2" + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.5" + object-inspect: "npm:^1.13.3" + side-channel-map: "npm:^1.0.1" + checksum: 10/a815c89bc78c5723c714ea1a77c938377ea710af20d4fb886d362b0d1f8ac73a17816a5f6640f354017d7e292a43da9c5e876c22145bac00b76cfb3468001736 + languageName: node + linkType: hard + +"side-channel@npm:^1.1.0": + version: 1.1.0 + resolution: "side-channel@npm:1.1.0" + dependencies: + es-errors: "npm:^1.3.0" + object-inspect: "npm:^1.13.3" + side-channel-list: "npm:^1.0.0" + side-channel-map: "npm:^1.0.1" + side-channel-weakmap: "npm:^1.0.2" + checksum: 10/7d53b9db292c6262f326b6ff3bc1611db84ece36c2c7dc0e937954c13c73185b0406c56589e2bb8d071d6fee468e14c39fb5d203ee39be66b7b8174f179afaba languageName: node linkType: hard @@ -12806,11 +13301,11 @@ __metadata: linkType: hard "simple-git-hooks@npm:^2.8.0": - version: 2.11.1 - resolution: "simple-git-hooks@npm:2.11.1" + version: 2.13.1 + resolution: "simple-git-hooks@npm:2.13.1" bin: simple-git-hooks: cli.js - checksum: 10/b19b1edaca3af95442a35e3963fa54955ddd58f481dde25da4f7a48353ae5e35bc875ae381e214fe2889be494e6fe01cc1c5f24aebb9558cee496deda3d026a4 + checksum: 10/a315ab71dcc5da1552970051c8b05ab745496e95667501e6961165f9946b58119ed8c3aa0e97748ca04c61b891936e3464c5feb4c5fb2d70a79e8f431809453d languageName: node linkType: hard @@ -12849,20 +13344,6 @@ __metadata: languageName: node linkType: hard -"slash@npm:^4.0.0": - version: 4.0.0 - resolution: "slash@npm:4.0.0" - checksum: 10/da8e4af73712253acd21b7853b7e0dbba776b786e82b010a5bfc8b5051a1db38ed8aba8e1e8f400dd2c9f373be91eb1c42b66e91abb407ff42b10feece5e1d2d - languageName: node - linkType: hard - -"slashes@npm:^3.0.12": - version: 3.0.12 - resolution: "slashes@npm:3.0.12" - checksum: 10/c221d73765013db64f3eaf49dacc6b99a5d5477e63720c1bb71d1af647965dda23ab100ca1eb622e080f11ffe68e1e0a233b7b908073260bed4ec819ff1d3e42 - languageName: node - linkType: hard - "smart-buffer@npm:^4.2.0": version: 4.2.0 resolution: "smart-buffer@npm:4.2.0" @@ -12871,55 +13352,54 @@ __metadata: linkType: hard "socks-proxy-agent@npm:^8.0.3": - version: 8.0.4 - resolution: "socks-proxy-agent@npm:8.0.4" + version: 8.0.5 + resolution: "socks-proxy-agent@npm:8.0.5" dependencies: - agent-base: "npm:^7.1.1" + agent-base: "npm:^7.1.2" debug: "npm:^4.3.4" socks: "npm:^2.8.3" - checksum: 10/c8e7c2b398338b49a0a0f4d2bae5c0602aeeca6b478b99415927b6c5db349ca258448f2c87c6958ebf83eea17d42cbc5d1af0bfecb276cac10b9658b0f07f7d7 + checksum: 10/ee99e1dacab0985b52cbe5a75640be6e604135e9489ebdc3048635d186012fbaecc20fbbe04b177dee434c319ba20f09b3e7dfefb7d932466c0d707744eac05c languageName: node linkType: hard "socks@npm:^2.8.3": - version: 2.8.3 - resolution: "socks@npm:2.8.3" + version: 2.8.7 + resolution: "socks@npm:2.8.7" dependencies: - ip-address: "npm:^9.0.5" + ip-address: "npm:^10.0.1" smart-buffer: "npm:^4.2.0" - checksum: 10/ffcb622c22481dfcd7589aae71fbfd71ca34334064d181df64bf8b7feaeee19706aba4cffd1de35cc7bbaeeaa0af96be2d7f40fcbc7bc0ab69533a7ae9ffc4fb + checksum: 10/d19366c95908c19db154f329bbe94c2317d315dc933a7c2b5101e73f32a555c84fb199b62174e1490082a593a4933d8d5a9b297bde7d1419c14a11a965f51356 languageName: node linkType: hard -"sort-object-keys@npm:^1.1.3": - version: 1.1.3 - resolution: "sort-object-keys@npm:1.1.3" - checksum: 10/abea944d6722a1710a1aa6e4f9509da085d93d5fc0db23947cb411eedc7731f80022ce8fa68ed83a53dd2ac7441fcf72a3f38c09b3d9bbc4ff80546aa2e151ad +"sort-object-keys@npm:^2.0.1": + version: 2.1.0 + resolution: "sort-object-keys@npm:2.1.0" + checksum: 10/a0a18a6f4ab601adb889204a83e2664a4810042dd9680e588cabb47fffd40473939ce3fda5a28fdb58bac0762a7b45ad442815465b978d4b243bab840df3d7cd languageName: node linkType: hard -"sort-package-json@npm:2.10.1": - version: 2.10.1 - resolution: "sort-package-json@npm:2.10.1" +"sort-package-json@npm:3.6.0": + version: 3.6.0 + resolution: "sort-package-json@npm:3.6.0" dependencies: - detect-indent: "npm:^7.0.1" - detect-newline: "npm:^4.0.0" - get-stdin: "npm:^9.0.0" - git-hooks-list: "npm:^3.0.0" - globby: "npm:^13.1.2" + detect-indent: "npm:^7.0.2" + detect-newline: "npm:^4.0.1" + git-hooks-list: "npm:^4.1.1" is-plain-obj: "npm:^4.1.0" - semver: "npm:^7.6.0" - sort-object-keys: "npm:^1.1.3" + semver: "npm:^7.7.3" + sort-object-keys: "npm:^2.0.1" + tinyglobby: "npm:^0.2.15" bin: sort-package-json: cli.js - checksum: 10/3a08cb9227c244d51bfb0eaaa5a9ea82fd3c96ea299c040365700b3f445d46a98411df4237f4e3c96ba67be4dcd53931747eab3b799f0335d278b36d64f1061d + checksum: 10/1489edd177dc325c1e5fbfa55e9583dfea8caa950363b43f797d99986f00b722644275f4dfd5491265519365d6394a5fec9fe5d360ed83b74317fdc9fc071ba1 languageName: node linkType: hard -"source-map-js@npm:^1.2.0": - version: 1.2.0 - resolution: "source-map-js@npm:1.2.0" - checksum: 10/74f331cfd2d121c50790c8dd6d3c9de6be21926de80583b23b37029b0f37aefc3e019fa91f9a10a5e120c08135297e1ecf312d561459c45908cb1e0e365f49e5 +"source-map-js@npm:^1.2.1": + version: 1.2.1 + resolution: "source-map-js@npm:1.2.1" + checksum: 10/ff9d8c8bf096d534a5b7707e0382ef827b4dd360a577d3f34d2b9f48e12c9d230b5747974ee7c607f0df65113732711bb701fe9ece3c7edbd43cb2294d707df3 languageName: node linkType: hard @@ -12978,16 +13458,9 @@ __metadata: linkType: hard "spdx-license-ids@npm:^3.0.0": - version: 3.0.20 - resolution: "spdx-license-ids@npm:3.0.20" - checksum: 10/30e566ea74b04232c64819d1f5313c00d92e9c73d054541650331fc794499b3bcc4991bcd90fa3c2fc4d040006f58f63104706255266e87a9d452e6574afc60c - languageName: node - linkType: hard - -"sprintf-js@npm:^1.1.3": - version: 1.1.3 - resolution: "sprintf-js@npm:1.1.3" - checksum: 10/e7587128c423f7e43cc625fe2f87e6affdf5ca51c1cc468e910d8aaca46bb44a7fbcfa552f787b1d3987f7043aeb4527d1b99559e6621e01b42b3f45e5a24cbb + version: 3.0.23 + resolution: "spdx-license-ids@npm:3.0.23" + checksum: 10/fead6be44478e4dd73a0721ae569f4a04f358846d8d82e8d92efae64aca928592e380cf17e8b84c25c948f3a7d8a0b4fc781a1830f3911ca87d52733265176b5 languageName: node linkType: hard @@ -12998,23 +13471,30 @@ __metadata: languageName: node linkType: hard -"ssri@npm:^10.0.0": - version: 10.0.6 - resolution: "ssri@npm:10.0.6" +"ssri@npm:^13.0.0": + version: 13.0.1 + resolution: "ssri@npm:13.0.1" dependencies: minipass: "npm:^7.0.3" - checksum: 10/f92c1b3cc9bfd0a925417412d07d999935917bc87049f43ebec41074661d64cf720315661844106a77da9f8204b6d55ae29f9514e673083cae39464343af2a8b + checksum: 10/ae560d0378d074006a71b06af71bfbe84a3fe1ac6e16c1f07575f69e670d40170507fe52b21bcc23399429bc6a15f4bc3ea8d9bc88e9dfd7e87de564e6da6a72 + languageName: node + linkType: hard + +"stable-hash-x@npm:^0.2.0": + version: 0.2.0 + resolution: "stable-hash-x@npm:0.2.0" + checksum: 10/136f05d0e4d441876012b423541476ff5b695c93b56d1959560be858b9e324ea6de6c16ecbd735a040ee8396427dd867bed0bf90b2cdb1fc422566747b91a0e5 languageName: node linkType: hard -"stable-hash@npm:^0.0.4": - version: 0.0.4 - resolution: "stable-hash@npm:0.0.4" - checksum: 10/21c039d21c1cb739cf8342561753a5e007cb95ea682ccd452e76310bbb9c6987a89de8eda023e320b019f3e4691aabda75079cdbb7dadf7ab9013e931f2f23cd +"stable-hash@npm:^0.0.5": + version: 0.0.5 + resolution: "stable-hash@npm:0.0.5" + checksum: 10/9222ea2c558e37c4a576cb4e406966b9e6aa05b93f5c4f09ef4aaabe3577439b9b8fbff407b16840b63e2ae83de74290c7b1c2da7360d571e480e46a4aec0a56 languageName: node linkType: hard -"stack-utils@npm:^2.0.3": +"stack-utils@npm:^2.0.3, stack-utils@npm:^2.0.6": version: 2.0.6 resolution: "stack-utils@npm:2.0.6" dependencies: @@ -13023,25 +13503,21 @@ __metadata: languageName: node linkType: hard -"statuses@npm:2.0.1": - version: 2.0.1 - resolution: "statuses@npm:2.0.1" - checksum: 10/18c7623fdb8f646fb213ca4051be4df7efb3484d4ab662937ca6fbef7ced9b9e12842709872eb3020cc3504b93bde88935c9f6417489627a7786f24f8031cbcb +"statuses@npm:~2.0.1, statuses@npm:~2.0.2": + version: 2.0.2 + resolution: "statuses@npm:2.0.2" + checksum: 10/6927feb50c2a75b2a4caab2c565491f7a93ad3d8dbad7b1398d52359e9243a20e2ebe35e33726dee945125ef7a515e9097d8a1b910ba2bbd818265a2f6c39879 languageName: node linkType: hard "streamx@npm:^2.15.0": - version: 2.19.0 - resolution: "streamx@npm:2.19.0" + version: 2.23.0 + resolution: "streamx@npm:2.23.0" dependencies: - bare-events: "npm:^2.2.0" + events-universal: "npm:^1.0.0" fast-fifo: "npm:^1.3.2" - queue-tick: "npm:^1.0.1" text-decoder: "npm:^1.1.0" - dependenciesMeta: - bare-events: - optional: true - checksum: 10/3e57a12402200cce347bd0658b5e7ef14a41636341256d2a9f43100e5c4f5d82166a4df77aef92082686150805a1b14f74370f3c96b4ed3d6d9889da1e3b3c21 + checksum: 10/4969d7032b16497172afa2f8ac889d137764963ae564daf1611a03225dd62d9316d51de8098b5866d21722babde71353067184e7a3e9795d6dc17c902904a780 languageName: node linkType: hard @@ -13105,11 +13581,11 @@ __metadata: linkType: hard "strip-ansi@npm:^7.0.1": - version: 7.1.0 - resolution: "strip-ansi@npm:7.1.0" + version: 7.1.2 + resolution: "strip-ansi@npm:7.1.2" dependencies: ansi-regex: "npm:^6.0.1" - checksum: 10/475f53e9c44375d6e72807284024ac5d668ee1d06010740dec0b9744f2ddf47de8d7151f80e5f6190fc8f384e802fdf9504b76a7e9020c9faee7103623338be2 + checksum: 10/db0e3f9654e519c8a33c50fc9304d07df5649388e7da06d3aabf66d29e5ad65d5e6315d8519d409c15b32fa82c1df7e11ed6f8cd50b0e4404463f0c9d77c8d0b languageName: node linkType: hard @@ -13159,10 +13635,17 @@ __metadata: languageName: node linkType: hard -"strnum@npm:^1.0.5": - version: 1.0.5 - resolution: "strnum@npm:1.0.5" - checksum: 10/d3117975db8372d4d7b2c07601ed2f65bf21cc48d741f37a8617b76370d228f2ec26336e53791ebc3638264d23ca54e6c241f57f8c69bd4941c63c79440525ca +"strnum@npm:^1.1.1": + version: 1.1.2 + resolution: "strnum@npm:1.1.2" + checksum: 10/ccd6297a1fdaf0fc8ea0ea904acdae76878d49a4b0d98a70155df4bc081fd88eac5ec99fb150f3d1d1af065c1898d38420705259ba6c39aa850c671bcd54e35d + languageName: node + linkType: hard + +"strnum@npm:^2.1.2": + version: 2.1.2 + resolution: "strnum@npm:2.1.2" + checksum: 10/7d894dff385e3a5c5b29c012cf0a7ea7962a92c6a299383c3d6db945ad2b6f3e770511356a9774dbd54444c56af1dc7c435dad6466c47293c48173274dd6c631 languageName: node linkType: hard @@ -13208,30 +13691,19 @@ __metadata: languageName: node linkType: hard -"synckit@npm:0.9.1": - version: 0.9.1 - resolution: "synckit@npm:0.9.1" - dependencies: - "@pkgr/core": "npm:^0.1.0" - tslib: "npm:^2.6.2" - checksum: 10/bff3903976baf8b699b5483228116d70223781a93b17c70e685c277ee960cdfd1a09cb5a741e6a9ec35e2428f14f4664baec41ccc99a598f267608b2a54f529b - languageName: node - linkType: hard - -"synckit@npm:^0.9.1": - version: 0.9.2 - resolution: "synckit@npm:0.9.2" +"synckit@npm:^0.11.12": + version: 0.11.12 + resolution: "synckit@npm:0.11.12" dependencies: - "@pkgr/core": "npm:^0.1.0" - tslib: "npm:^2.6.2" - checksum: 10/d45c4288be9c0232343650643892a7edafb79152c0c08d7ae5d33ca2c296b67a0e15f8cb5c9153969612c4ea5cd5686297542384aab977db23cfa6653fe02027 + "@pkgr/core": "npm:^0.2.9" + checksum: 10/2f51978bfed81aaf0b093f596709a72c49b17909020f42b43c5549f9c0fe18b1fe29f82e41ef771172d729b32e9ce82900a85d2b87fa14d59f886d4df8d7a329 languageName: node linkType: hard -"tapable@npm:^2.2.0": - version: 2.2.1 - resolution: "tapable@npm:2.2.1" - checksum: 10/1769336dd21481ae6347611ca5fca47add0962fd8e80466515032125eca0084a4f0ede11e65341b9c0018ef4e1cf1ad820adbb0fba7cc99865c6005734000b0a +"tapable@npm:^2.3.0": + version: 2.3.0 + resolution: "tapable@npm:2.3.0" + checksum: 10/496a841039960533bb6e44816a01fffc2a1eb428bb2051ecab9e87adf07f19e1f937566cbbbb09dceff31163c0ffd81baafcad84db900b601f0155dd0b37e9f2 languageName: node linkType: hard @@ -13246,31 +13718,16 @@ __metadata: languageName: node linkType: hard -"tar@npm:^6.1.11, tar@npm:^6.2.1": - version: 6.2.1 - resolution: "tar@npm:6.2.1" - dependencies: - chownr: "npm:^2.0.0" - fs-minipass: "npm:^2.0.0" - minipass: "npm:^5.0.0" - minizlib: "npm:^2.1.1" - mkdirp: "npm:^1.0.3" - yallist: "npm:^4.0.0" - checksum: 10/bfbfbb2861888077fc1130b84029cdc2721efb93d1d1fb80f22a7ac3a98ec6f8972f29e564103bbebf5e97be67ebc356d37fa48dbc4960600a1eb7230fbd1ea0 - languageName: node - linkType: hard - -"tar@npm:^7.4.3": - version: 7.4.3 - resolution: "tar@npm:7.4.3" +"tar@npm:^7.4.3, tar@npm:^7.5.4": + version: 7.5.9 + resolution: "tar@npm:7.5.9" dependencies: "@isaacs/fs-minipass": "npm:^4.0.0" chownr: "npm:^3.0.0" minipass: "npm:^7.1.2" - minizlib: "npm:^3.0.1" - mkdirp: "npm:^3.0.1" + minizlib: "npm:^3.1.0" yallist: "npm:^5.0.0" - checksum: 10/12a2a4fc6dee23e07cc47f1aeb3a14a1afd3f16397e1350036a8f4cdfee8dcac7ef5978337a4e7b2ac2c27a9a6d46388fc2088ea7c80cb6878c814b1425f8ecf + checksum: 10/1213cdde9c22d6acf8809ba5d2a025212ce3517bc99c4a4c6981b7dc0489bf3b164db9c826c9517680889194c9ba57448c8ff0da35eca9a60bb7689bf0b3897d languageName: node linkType: hard @@ -13286,15 +13743,15 @@ __metadata: linkType: hard "text-decoder@npm:^1.1.0": - version: 1.1.1 - resolution: "text-decoder@npm:1.1.1" + version: 1.2.7 + resolution: "text-decoder@npm:1.2.7" dependencies: b4a: "npm:^1.6.4" - checksum: 10/c6981b93850daeafc8bd1dbd8f984d4fb2d14632f450de0892692b5bbee2d2f4cbef8a807142527370649fd357f58491ede4915d43669eca624cb52b8dd247b6 + checksum: 10/151f89339a497353ad579b32536be94bf90a0785fd2aa2dc0a5ec8a4b71ed59998f4adb872201bdc536805425aa8c5cf8f4a936c449be614c1d3c4527688b3d0 languageName: node linkType: hard -"tinyglobby@npm:^0.2.15": +"tinyglobby@npm:^0.2.12, tinyglobby@npm:^0.2.13, tinyglobby@npm:^0.2.15": version: 0.2.15 resolution: "tinyglobby@npm:0.2.15" dependencies: @@ -13311,6 +13768,17 @@ __metadata: languageName: node linkType: hard +"to-buffer@npm:^1.2.0, to-buffer@npm:^1.2.1, to-buffer@npm:^1.2.2": + version: 1.2.2 + resolution: "to-buffer@npm:1.2.2" + dependencies: + isarray: "npm:^2.0.5" + safe-buffer: "npm:^5.2.1" + typed-array-buffer: "npm:^1.0.3" + checksum: 10/69d806c20524ff1e4c44d49276bc96ff282dcae484780a3974e275dabeb75651ea430b074a2a4023701e63b3e1d87811cd82c0972f35280fe5461710e4872aba + languageName: node + linkType: hard + "to-regex-range@npm:^5.0.1": version: 5.0.1 resolution: "to-regex-range@npm:5.0.1" @@ -13320,7 +13788,7 @@ __metadata: languageName: node linkType: hard -"toidentifier@npm:1.0.1": +"toidentifier@npm:~1.0.1": version: 1.0.1 resolution: "toidentifier@npm:1.0.1" checksum: 10/952c29e2a85d7123239b5cfdd889a0dde47ab0497f0913d70588f19c53f7e0b5327c95f4651e413c74b785147f9637b17410ac8c846d5d4a20a5a33eb6dc3a45 @@ -13371,6 +13839,17 @@ __metadata: languageName: node linkType: hard +"ts-declaration-location@npm:^1.0.6": + version: 1.0.7 + resolution: "ts-declaration-location@npm:1.0.7" + dependencies: + picomatch: "npm:^4.0.2" + peerDependencies: + typescript: ">=4.0.0" + checksum: 10/a7932fc75d41f10c16089f8f5a5c1ea49d6afca30f09c91c1df14d0a8510f72bcb9f8a395c04f060b66b855b6bd7ea4df81b335fb9d21bef402969a672a4afa7 + languageName: node + linkType: hard + "ts-jest@npm:^29.2.5": version: 29.4.6 resolution: "ts-jest@npm:29.4.6" @@ -13428,14 +13907,14 @@ __metadata: languageName: node linkType: hard -"tslib@npm:2.4.0": - version: 2.4.0 - resolution: "tslib@npm:2.4.0" - checksum: 10/d8379e68b36caf082c1905ec25d17df8261e1d68ddc1abfd6c91158a064f6e4402039ae7c02cf4c81d12e3a2a2c7cd8ea2f57b233eb80136a2e3e7279daf2911 +"tslib@npm:2.7.0": + version: 2.7.0 + resolution: "tslib@npm:2.7.0" + checksum: 10/9a5b47ddac65874fa011c20ff76db69f97cf90c78cff5934799ab8894a5342db2d17b4e7613a087046bc1d133d21547ddff87ac558abeec31ffa929c88b7fce6 languageName: node linkType: hard -"tslib@npm:^2.1.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0, tslib@npm:^2.6.2, tslib@npm:^2.6.3": +"tslib@npm:^2.1.0, tslib@npm:^2.4.0": version: 2.8.1 resolution: "tslib@npm:2.8.1" checksum: 10/3e2e043d5c2316461cb54e5c7fe02c30ef6dccb3384717ca22ae5c6b5bc95232a6241df19c622d9c73b809bea33b187f6dbc73030963e29950c2141bc32a79f7 @@ -13443,10 +13922,10 @@ __metadata: linkType: hard "tsx@npm:^4.20.5": - version: 4.20.5 - resolution: "tsx@npm:4.20.5" + version: 4.21.0 + resolution: "tsx@npm:4.21.0" dependencies: - esbuild: "npm:~0.25.0" + esbuild: "npm:~0.27.0" fsevents: "npm:~2.3.3" get-tsconfig: "npm:^4.7.5" dependenciesMeta: @@ -13454,7 +13933,7 @@ __metadata: optional: true bin: tsx: dist/cli.mjs - checksum: 10/161420678027c43d07b60b7b6b512cc67ff86ae3cca0641a19b0d3e742c5e262bca57034c4bff6d9346f9269e9ada24b6030e1d2bc890df5e1a9754865d3c08a + checksum: 10/7afedeff855ba98c47dc28b33d7e8e253c4dc1f791938db402d79c174bdf806b897c1a5f91e5b1259c112520c816f826b4c5d98f0bad7e95b02dec66fedb64d2 languageName: node linkType: hard @@ -13481,6 +13960,13 @@ __metadata: languageName: node linkType: hard +"type-fest@npm:4.41.0, type-fest@npm:^4.0.0, type-fest@npm:^4.41.0": + version: 4.41.0 + resolution: "type-fest@npm:4.41.0" + checksum: 10/617ace794ac0893c2986912d28b3065ad1afb484cad59297835a0807dc63286c39e8675d65f7de08fafa339afcb8fe06a36e9a188b9857756ae1e92ee8bda212 + languageName: node + linkType: hard + "type-fest@npm:^0.18.0": version: 0.18.1 resolution: "type-fest@npm:0.18.1" @@ -13509,13 +13995,6 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^4.0.0, type-fest@npm:^4.41.0": - version: 4.41.0 - resolution: "type-fest@npm:4.41.0" - checksum: 10/617ace794ac0893c2986912d28b3065ad1afb484cad59297835a0807dc63286c39e8675d65f7de08fafa339afcb8fe06a36e9a188b9857756ae1e92ee8bda212 - languageName: node - linkType: hard - "type-is@npm:~1.6.18": version: 1.6.18 resolution: "type-is@npm:1.6.18" @@ -13526,6 +14005,17 @@ __metadata: languageName: node linkType: hard +"typed-array-buffer@npm:^1.0.3": + version: 1.0.3 + resolution: "typed-array-buffer@npm:1.0.3" + dependencies: + call-bound: "npm:^1.0.3" + es-errors: "npm:^1.3.0" + is-typed-array: "npm:^1.1.14" + checksum: 10/3fb91f0735fb413b2bbaaca9fabe7b8fc14a3fa5a5a7546bab8a57e755be0e3788d893195ad9c2b842620592de0e68d4c077d4c2c41f04ec25b8b5bb82fa9a80 + languageName: node + linkType: hard + "typedarray@npm:^0.0.6": version: 0.0.6 resolution: "typedarray@npm:0.0.6" @@ -13559,17 +14049,17 @@ __metadata: linkType: hard "typescript-eslint@npm:^8.48.0": - version: 8.54.0 - resolution: "typescript-eslint@npm:8.54.0" + version: 8.56.1 + resolution: "typescript-eslint@npm:8.56.1" dependencies: - "@typescript-eslint/eslint-plugin": "npm:8.54.0" - "@typescript-eslint/parser": "npm:8.54.0" - "@typescript-eslint/typescript-estree": "npm:8.54.0" - "@typescript-eslint/utils": "npm:8.54.0" + "@typescript-eslint/eslint-plugin": "npm:8.56.1" + "@typescript-eslint/parser": "npm:8.56.1" + "@typescript-eslint/typescript-estree": "npm:8.56.1" + "@typescript-eslint/utils": "npm:8.56.1" peerDependencies: - eslint: ^8.57.0 || ^9.0.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10/21b1a27fd44716df8d2c7bac4ebd0caef196a04375fff7919dc817066017b6b8700f1e242bd065a26ac7ce0505b7a588626099e04a28142504ed4f0aae8bffb1 + checksum: 10/e18cd347ddce0f0e5b28121346f27736a418adf68e73d613690ea3a1d0adfe03bc393f77a8872c2cef77ca74bcc0974212d1775c360de33a9987a94cda11a05b languageName: node linkType: hard @@ -13603,11 +14093,11 @@ __metadata: linkType: hard "ulid@npm:^2.3.0": - version: 2.3.0 - resolution: "ulid@npm:2.3.0" + version: 2.4.0 + resolution: "ulid@npm:2.4.0" bin: - ulid: ./bin/cli.js - checksum: 10/11d7dd35072b863effb1249f66fb03070142a625610f00e5afd99af7e909b5de9cc7ebca6ede621a6bb1b7479b2489d6f064db6742b55c14bff6496ac60f290f + ulid: bin/cli.js + checksum: 10/409ad0a703ea9f25d2a35cf790b767030a2c7b5ca0df6acb73669628156ab63bb97925a3fd7aaaf0b2384d39bd3ed2f7cd2c2de9f1171df6bc79b8c097865d92 languageName: node linkType: hard @@ -13618,21 +14108,28 @@ __metadata: languageName: node linkType: hard -"unique-filename@npm:^3.0.0": - version: 3.0.0 - resolution: "unique-filename@npm:3.0.0" +"undici-types@npm:~7.18.0": + version: 7.18.2 + resolution: "undici-types@npm:7.18.2" + checksum: 10/e61a5918f624d68420c3ca9d301e9f15b61cba6e97be39fe2ce266dd6151e4afe424d679372638826cb506be33952774e0424141200111a9857e464216c009af + languageName: node + linkType: hard + +"unique-filename@npm:^5.0.0": + version: 5.0.0 + resolution: "unique-filename@npm:5.0.0" dependencies: - unique-slug: "npm:^4.0.0" - checksum: 10/8e2f59b356cb2e54aab14ff98a51ac6c45781d15ceaab6d4f1c2228b780193dc70fae4463ce9e1df4479cb9d3304d7c2043a3fb905bdeca71cc7e8ce27e063df + unique-slug: "npm:^6.0.0" + checksum: 10/a5f67085caef74bdd2a6869a200ed5d68d171f5cc38435a836b5fd12cce4e4eb55e6a190298035c325053a5687ed7a3c96f0a91e82215fd14729769d9ac57d9b languageName: node linkType: hard -"unique-slug@npm:^4.0.0": - version: 4.0.0 - resolution: "unique-slug@npm:4.0.0" +"unique-slug@npm:^6.0.0": + version: 6.0.0 + resolution: "unique-slug@npm:6.0.0" dependencies: imurmurhash: "npm:^0.1.4" - checksum: 10/40912a8963fc02fb8b600cf50197df4a275c602c60de4cac4f75879d3c48558cfac48de08a25cc10df8112161f7180b3bbb4d662aadb711568602f9eddee54f0 + checksum: 10/b78ed9d5b01ff465f80975f17387750ed3639909ac487fa82c4ae4326759f6de87c2131c0c39eca4c68cf06c537a8d104fba1dfc8a30308f99bc505345e1eba3 languageName: node linkType: hard @@ -13650,13 +14147,80 @@ __metadata: languageName: node linkType: hard -"unpipe@npm:1.0.0, unpipe@npm:~1.0.0": +"unpipe@npm:~1.0.0": version: 1.0.0 resolution: "unpipe@npm:1.0.0" checksum: 10/4fa18d8d8d977c55cb09715385c203197105e10a6d220087ec819f50cb68870f02942244f1017565484237f1f8c5d3cd413631b1ae104d3096f24fdfde1b4aa2 languageName: node linkType: hard +"unrs-resolver@npm:^1.6.2, unrs-resolver@npm:^1.9.2": + version: 1.11.1 + resolution: "unrs-resolver@npm:1.11.1" + dependencies: + "@unrs/resolver-binding-android-arm-eabi": "npm:1.11.1" + "@unrs/resolver-binding-android-arm64": "npm:1.11.1" + "@unrs/resolver-binding-darwin-arm64": "npm:1.11.1" + "@unrs/resolver-binding-darwin-x64": "npm:1.11.1" + "@unrs/resolver-binding-freebsd-x64": "npm:1.11.1" + "@unrs/resolver-binding-linux-arm-gnueabihf": "npm:1.11.1" + "@unrs/resolver-binding-linux-arm-musleabihf": "npm:1.11.1" + "@unrs/resolver-binding-linux-arm64-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-arm64-musl": "npm:1.11.1" + "@unrs/resolver-binding-linux-ppc64-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-riscv64-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-riscv64-musl": "npm:1.11.1" + "@unrs/resolver-binding-linux-s390x-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-x64-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-x64-musl": "npm:1.11.1" + "@unrs/resolver-binding-wasm32-wasi": "npm:1.11.1" + "@unrs/resolver-binding-win32-arm64-msvc": "npm:1.11.1" + "@unrs/resolver-binding-win32-ia32-msvc": "npm:1.11.1" + "@unrs/resolver-binding-win32-x64-msvc": "npm:1.11.1" + napi-postinstall: "npm:^0.3.0" + dependenciesMeta: + "@unrs/resolver-binding-android-arm-eabi": + optional: true + "@unrs/resolver-binding-android-arm64": + optional: true + "@unrs/resolver-binding-darwin-arm64": + optional: true + "@unrs/resolver-binding-darwin-x64": + optional: true + "@unrs/resolver-binding-freebsd-x64": + optional: true + "@unrs/resolver-binding-linux-arm-gnueabihf": + optional: true + "@unrs/resolver-binding-linux-arm-musleabihf": + optional: true + "@unrs/resolver-binding-linux-arm64-gnu": + optional: true + "@unrs/resolver-binding-linux-arm64-musl": + optional: true + "@unrs/resolver-binding-linux-ppc64-gnu": + optional: true + "@unrs/resolver-binding-linux-riscv64-gnu": + optional: true + "@unrs/resolver-binding-linux-riscv64-musl": + optional: true + "@unrs/resolver-binding-linux-s390x-gnu": + optional: true + "@unrs/resolver-binding-linux-x64-gnu": + optional: true + "@unrs/resolver-binding-linux-x64-musl": + optional: true + "@unrs/resolver-binding-wasm32-wasi": + optional: true + "@unrs/resolver-binding-win32-arm64-msvc": + optional: true + "@unrs/resolver-binding-win32-ia32-msvc": + optional: true + "@unrs/resolver-binding-win32-x64-msvc": + optional: true + checksum: 10/4de653508cbaae47883a896bd5cdfef0e5e87b428d62620d16fd35cd534beaebf08ebf0cf2f8b4922aa947b2fe745180facf6cc3f39ba364f7ce0f974cb06a70 + languageName: node + linkType: hard + "unzipper@npm:^0.12.3": version: 0.12.3 resolution: "unzipper@npm:0.12.3" @@ -13670,9 +14234,9 @@ __metadata: languageName: node linkType: hard -"update-browserslist-db@npm:^1.1.1": - version: 1.1.2 - resolution: "update-browserslist-db@npm:1.1.2" +"update-browserslist-db@npm:^1.2.0": + version: 1.2.3 + resolution: "update-browserslist-db@npm:1.2.3" dependencies: escalade: "npm:^3.2.0" picocolors: "npm:^1.1.1" @@ -13680,7 +14244,7 @@ __metadata: browserslist: ">= 4.21.0" bin: update-browserslist-db: cli.js - checksum: 10/e7bf8221dfb21eba4a770cd803df94625bb04f65a706aa94c567de9600fe4eb6133fda016ec471dad43b9e7959c1bffb6580b5e20a87808d2e8a13e3892699a9 + checksum: 10/059f774300efb4b084a49293143c511f3ae946d40397b5c30914e900cd5691a12b8e61b41dd54ed73d3b56c8204165a0333107dd784ccf8f8c81790bcc423175 languageName: node linkType: hard @@ -13760,7 +14324,7 @@ __metadata: languageName: node linkType: hard -"validate-npm-package-license@npm:^3.0.1, validate-npm-package-license@npm:^3.0.4": +"validate-npm-package-license@npm:^3.0.1": version: 3.0.4 resolution: "validate-npm-package-license@npm:3.0.4" dependencies: @@ -13777,6 +14341,13 @@ __metadata: languageName: node linkType: hard +"validate-npm-package-name@npm:^7.0.0": + version: 7.0.2 + resolution: "validate-npm-package-name@npm:7.0.2" + checksum: 10/2a9bdc6fd5e4284c8e02279446bfd3c38c0c01222555fd3b00b4765d9d47b217d4a200910be71b80b958f6baf40d2d32e812a8632633a2ce376a9b3b74811072 + languageName: node + linkType: hard + "vary@npm:~1.1.2": version: 1.1.2 resolution: "vary@npm:1.1.2" @@ -13816,6 +14387,13 @@ __metadata: languageName: node linkType: hard +"web-vitals@npm:^4.2.4": + version: 4.2.4 + resolution: "web-vitals@npm:4.2.4" + checksum: 10/68cd1c2625a04b26e7eab67110623396afc6c9ef8c3a76f4e780aefe5b7d4ca1691737a0b99119e1d1ca9a463c4d468c0f0090b1875b6d784589d3a4a8503313 + languageName: node + linkType: hard + "webextension-polyfill-ts@npm:^0.26.0": version: 0.26.0 resolution: "webextension-polyfill-ts@npm:0.26.0" @@ -13914,6 +14492,21 @@ __metadata: languageName: node linkType: hard +"which-typed-array@npm:^1.1.16": + version: 1.1.20 + resolution: "which-typed-array@npm:1.1.20" + dependencies: + available-typed-arrays: "npm:^1.0.7" + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.4" + for-each: "npm:^0.3.5" + get-proto: "npm:^1.0.1" + gopd: "npm:^1.2.0" + has-tostringtag: "npm:^1.0.2" + checksum: 10/e56da3fc995d330ff012f682476f7883c16b12d36c6717c87c7ca23eb5a5ef957fa89115dacb389b11a9b4e99d5dbe2d12689b4d5d08c050b5aed0eae385b840 + languageName: node + linkType: hard + "which@npm:^1.2.14": version: 1.3.1 resolution: "which@npm:1.3.1" @@ -13947,14 +14540,14 @@ __metadata: languageName: node linkType: hard -"which@npm:^4.0.0": - version: 4.0.0 - resolution: "which@npm:4.0.0" +"which@npm:^6.0.0": + version: 6.0.1 + resolution: "which@npm:6.0.1" dependencies: - isexe: "npm:^3.1.1" + isexe: "npm:^4.0.0" bin: node-which: bin/which.js - checksum: 10/f17e84c042592c21e23c8195108cff18c64050b9efb8459589116999ea9da6dd1509e6a1bac3aeebefd137be00fabbb61b5c2bc0aa0f8526f32b58ee2f545651 + checksum: 10/dbea77c7d3058bf6c78bf9659d2dce4d2b57d39a15b826b2af6ac2e5a219b99dc8a831b79fdbc453c0598adb4f3f84cf9c2491fd52beb9f5d2dececcad117f68 languageName: node linkType: hard @@ -14036,18 +14629,18 @@ __metadata: languageName: node linkType: hard -"ws@npm:^7.5.10": - version: 7.5.10 - resolution: "ws@npm:7.5.10" +"ws@npm:8.18.0": + version: 8.18.0 + resolution: "ws@npm:8.18.0" peerDependencies: bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 + utf-8-validate: ">=5.0.2" peerDependenciesMeta: bufferutil: optional: true utf-8-validate: optional: true - checksum: 10/9c796b84ba80ffc2c2adcdfc9c8e9a219ba99caa435c9a8d45f9ac593bba325563b3f83edc5eb067cc6d21b9a6bf2c930adf76dd40af5f58a5ca6859e81858f0 + checksum: 10/70dfe53f23ff4368d46e4c0b1d4ca734db2c4149c6f68bc62cb16fc21f753c47b35fcc6e582f3bdfba0eaeb1c488cddab3c2255755a5c3eecb251431e42b3ff6 languageName: node linkType: hard @@ -14066,6 +14659,15 @@ __metadata: languageName: node linkType: hard +"wsl-utils@npm:^0.1.0": + version: 0.1.0 + resolution: "wsl-utils@npm:0.1.0" + dependencies: + is-wsl: "npm:^3.1.0" + checksum: 10/de4c92187e04c3c27b4478f410a02e81c351dc85efa3447bf1666f34fc80baacd890a6698ec91995631714086992036013286aea3d77e6974020d40a08e00aec + languageName: node + linkType: hard + "xhr2@npm:0.2.1": version: 0.2.1 resolution: "xhr2@npm:0.2.1" @@ -14130,11 +14732,11 @@ __metadata: linkType: hard "yaml@npm:^2.2.2, yaml@npm:^2.3.4": - version: 2.8.0 - resolution: "yaml@npm:2.8.0" + version: 2.8.2 + resolution: "yaml@npm:2.8.2" bin: yaml: bin.mjs - checksum: 10/7d4bd9c10d0e467601f496193f2ac254140f8e36f96f5ff7f852b9ce37974168eb7354f4c36dc8837dde527a2043d004b6aff48818ec24a69ab2dd3c6b6c381c + checksum: 10/4eab0074da6bc5a5bffd25b9b359cf7061b771b95d1b3b571852098380db3b1b8f96e0f1f354b56cc7216aa97cea25163377ccbc33a2e9ce00316fe8d02f4539 languageName: node linkType: hard From e8831ffd0c0888c7f9050246e43bbe56609b3e12 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Fri, 27 Feb 2026 16:36:10 +0100 Subject: [PATCH 48/55] chore: update lockfile for config-registry-controller dependencies --- yarn.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index fa24d46e50b..ba0c9cafa6f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4719,7 +4719,7 @@ __metadata: languageName: unknown linkType: soft -"@metamask/remote-feature-flag-controller@npm:^4.1.0, @metamask/remote-feature-flag-controller@workspace:packages/remote-feature-flag-controller": +"@metamask/remote-feature-flag-controller@npm:^4.0.0, @metamask/remote-feature-flag-controller@npm:^4.1.0, @metamask/remote-feature-flag-controller@workspace:packages/remote-feature-flag-controller": version: 0.0.0-use.local resolution: "@metamask/remote-feature-flag-controller@workspace:packages/remote-feature-flag-controller" dependencies: From 04c0da8770eac23b9b6764f4bb296fc7e5a55434 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Fri, 27 Feb 2026 16:49:28 +0100 Subject: [PATCH 49/55] chore: add lavamoat allowScripts entry for eslint-plugin-import-x>unrs-resolver --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 36a961d6c81..fc15aba21a6 100644 --- a/package.json +++ b/package.json @@ -108,7 +108,8 @@ "@keystonehq/bc-ur-registry-eth>hdkey>secp256k1": true, "babel-runtime>core-js": false, "simple-git-hooks": false, - "tsx>esbuild": false + "tsx>esbuild": false, + "eslint-plugin-import-x>unrs-resolver": false } } } From 5f192b8140c28a4a0550d9ef518c318092c7cf84 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Fri, 27 Feb 2026 17:20:36 +0100 Subject: [PATCH 50/55] fix: clear etag when modified response has no ETag header --- .../src/ConfigRegistryController.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/config-registry-controller/src/ConfigRegistryController.ts b/packages/config-registry-controller/src/ConfigRegistryController.ts index 612d50ea57f..44fafc33996 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.ts @@ -275,9 +275,7 @@ export class ConfigRegistryController extends StaticIntervalPollingController Date: Fri, 27 Feb 2026 17:44:55 +0100 Subject: [PATCH 51/55] fix: failing build and lint --- .../config-registry-controller/package.json | 2 +- yarn.lock | 4286 +++++++---------- 2 files changed, 1843 insertions(+), 2445 deletions(-) diff --git a/packages/config-registry-controller/package.json b/packages/config-registry-controller/package.json index d29d01c71d2..ca7e500e761 100644 --- a/packages/config-registry-controller/package.json +++ b/packages/config-registry-controller/package.json @@ -54,7 +54,7 @@ "@metamask/messenger": "^0.3.0", "@metamask/polling-controller": "^16.0.3", "@metamask/profile-sync-controller": "^27.1.0", - "@metamask/remote-feature-flag-controller": "^4.0.0", + "@metamask/remote-feature-flag-controller": "^4.1.0", "@metamask/superstruct": "^3.1.0", "@metamask/utils": "^11.9.0", "reselect": "^5.1.1" diff --git a/yarn.lock b/yarn.lock index ba0c9cafa6f..1dd72951c10 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,7 +12,7 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.27.1, @babel/code-frame@npm:^7.28.6, @babel/code-frame@npm:^7.29.0": +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.28.6, @babel/code-frame@npm:^7.29.0": version: 7.29.0 resolution: "@babel/code-frame@npm:7.29.0" dependencies: @@ -109,7 +109,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.28.6, @babel/helper-plugin-utils@npm:^7.8.0": +"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.24.7, @babel/helper-plugin-utils@npm:^7.24.8, @babel/helper-plugin-utils@npm:^7.28.6, @babel/helper-plugin-utils@npm:^7.8.0": version: 7.28.6 resolution: "@babel/helper-plugin-utils@npm:7.28.6" checksum: 10/21c853bbc13dbdddf03309c9a0477270124ad48989e1ad6524b83e83a77524b333f92edd2caae645c5a7ecf264ec6d04a9ebe15aeb54c7f33c037b71ec521e4a @@ -147,7 +147,7 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.0, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.28.6, @babel/parser@npm:^7.29.0": +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.0, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.24.7, @babel/parser@npm:^7.28.6, @babel/parser@npm:^7.29.0": version: 7.29.0 resolution: "@babel/parser@npm:7.29.0" dependencies: @@ -203,13 +203,13 @@ __metadata: linkType: hard "@babel/plugin-syntax-import-attributes@npm:^7.24.7": - version: 7.28.6 - resolution: "@babel/plugin-syntax-import-attributes@npm:7.28.6" + version: 7.24.7 + resolution: "@babel/plugin-syntax-import-attributes@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.28.6" + "@babel/helper-plugin-utils": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10/6c8c6a5988dbb9799d6027360d1a5ba64faabf551f2ef11ba4eade0c62253b5c85d44ddc8eb643c74b9acb2bcaa664a950bd5de9a5d4aef291c4f2a48223bb4b + checksum: 10/22fc50bd85a491bb8d22065f330a41f60d66f2f2d7a1deb73e80c8a4b5d7a42a092a03f8da18800650eca0fc14585167cc4e5c9fab351f0d390d1592347162ae languageName: node linkType: hard @@ -335,20 +335,22 @@ __metadata: linkType: hard "@babel/plugin-syntax-typescript@npm:^7.7.2": - version: 7.28.6 - resolution: "@babel/plugin-syntax-typescript@npm:7.28.6" + version: 7.25.4 + resolution: "@babel/plugin-syntax-typescript@npm:7.25.4" dependencies: - "@babel/helper-plugin-utils": "npm:^7.28.6" + "@babel/helper-plugin-utils": "npm:^7.24.8" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10/5c55f9c63bd36cf3d7e8db892294c8f85000f9c1526c3a1cc310d47d1e174f5c6f6605e5cc902c4636d885faba7a9f3d5e5edc6b35e4f3b1fd4c2d58d0304fa5 + checksum: 10/0771b45a35fd536cd3b3a48e5eda0f53e2d4f4a0ca07377cc247efa39eaf6002ed1c478106aad2650e54aefaebcb4f34f3284c4ae9252695dbd944bf66addfb0 languageName: node linkType: hard "@babel/runtime@npm:^7.23.9": - version: 7.28.6 - resolution: "@babel/runtime@npm:7.28.6" - checksum: 10/fbcd439cb74d4a681958eb064c509829e3f46d8a4bfaaf441baa81bb6733d1e680bccc676c813883d7741bcaada1d0d04b15aa320ef280b5734e2192b50decf9 + version: 7.25.4 + resolution: "@babel/runtime@npm:7.25.4" + dependencies: + regenerator-runtime: "npm:^0.14.0" + checksum: 10/70d2a420c24a3289ea6c4addaf3a1c4186bc3d001c92445faa3cd7601d7d2fbdb32c63b3a26b9771e20ff2f511fa76b726bf256f823cdb95bc37b8eadbd02f70 languageName: node linkType: hard @@ -378,7 +380,7 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.23.0, @babel/types@npm:^7.28.2, @babel/types@npm:^7.28.6, @babel/types@npm:^7.29.0, @babel/types@npm:^7.3.3": +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.23.0, @babel/types@npm:^7.28.6, @babel/types@npm:^7.29.0, @babel/types@npm:^7.3.3": version: 7.29.0 resolution: "@babel/types@npm:7.29.0" dependencies: @@ -396,57 +398,29 @@ __metadata: linkType: hard "@contentful/content-source-maps@npm:^0.11.0": - version: 0.11.44 - resolution: "@contentful/content-source-maps@npm:0.11.44" + version: 0.11.1 + resolution: "@contentful/content-source-maps@npm:0.11.1" dependencies: "@vercel/stega": "npm:^0.1.2" json-pointer: "npm:^0.6.2" - checksum: 10/30c5334c9921853e3a2ec71b4e572fd0f361fd2d6da3378c6345c9f8a2693ffda1f88bcc84243dba1a514562ef9a766315b9c8626f757dec8b000c6ace5a3d23 + checksum: 10/598e88349210aed21c9ee871250353ae15cb4130180ade9cf283261e192a80c72f8674c5533c490ad1358850e45578ed6ed4ac997b32c23b029ae4d096fa5646 languageName: node linkType: hard "@contentful/rich-text-html-renderer@npm:^16.5.2": - version: 16.6.10 - resolution: "@contentful/rich-text-html-renderer@npm:16.6.10" + version: 16.6.9 + resolution: "@contentful/rich-text-html-renderer@npm:16.6.9" dependencies: - "@contentful/rich-text-types": "npm:^16.8.5" + "@contentful/rich-text-types": "npm:^16.8.4" escape-html: "npm:^1.0.3" - checksum: 10/fdf5121524355c96cd8a4628b2cc50a61b9b9d37da167dd983cc8fa24fa822427809d00064ebca9b85b8f40d92719f0b86f0e4ea4eaa8d078656ed56c51df6bb - languageName: node - linkType: hard - -"@contentful/rich-text-types@npm:^16.0.2, @contentful/rich-text-types@npm:^16.8.5": - version: 16.8.5 - resolution: "@contentful/rich-text-types@npm:16.8.5" - checksum: 10/7c1ec7088cc39bbd8f5edc14867ed3d59d06a55f2c92e6c62913aa2312056e920528e6ca6d59780b32c6fe2ab89c429b9f0bce9a52f456be7260f458527ccc3b - languageName: node - linkType: hard - -"@emnapi/core@npm:^1.4.3": - version: 1.8.1 - resolution: "@emnapi/core@npm:1.8.1" - dependencies: - "@emnapi/wasi-threads": "npm:1.1.0" - tslib: "npm:^2.4.0" - checksum: 10/904ea60c91fc7d8aeb4a8f2c433b8cfb47c50618f2b6f37429fc5093c857c6381c60628a5cfbc3a7b0d75b0a288f21d4ed2d4533e82f92c043801ef255fd6a5c + checksum: 10/10bdcee4c01b89e5ab54ccab592bad7d3658fdd32ee58e2d5d18628a59ca47c7393c8dec41e96172b4c171f7fb4d2d1d6b9da9d6eeebbe5ed83fc3de8c4c0c89 languageName: node linkType: hard -"@emnapi/runtime@npm:^1.4.3": - version: 1.8.1 - resolution: "@emnapi/runtime@npm:1.8.1" - dependencies: - tslib: "npm:^2.4.0" - checksum: 10/26725e202d4baefdc4a6ba770f703dfc80825a27c27a08c22bac1e1ce6f8f75c47b4fe9424d9b63239463c33ef20b650f08d710da18dfa1164a95e5acb865dba - languageName: node - linkType: hard - -"@emnapi/wasi-threads@npm:1.1.0": - version: 1.1.0 - resolution: "@emnapi/wasi-threads@npm:1.1.0" - dependencies: - tslib: "npm:^2.4.0" - checksum: 10/0d557e75262d2f4c95cb2a456ba0785ef61f919ce488c1d76e5e3acfd26e00c753ef928cd80068363e0c166ba8cc0141305daf0f81aad5afcd421f38f11e0f4e +"@contentful/rich-text-types@npm:^16.0.2, @contentful/rich-text-types@npm:^16.8.4": + version: 16.8.4 + resolution: "@contentful/rich-text-types@npm:16.8.4" + checksum: 10/22e0a165545f32cc51d1e6231a9e7b617af98c452ecfb28ace9ba8a53b89bb2d940019ffae00ef2bc77c998630a66bfc88d01031e732afb11172f877064aa5b2 languageName: node linkType: hard @@ -471,202 +445,200 @@ __metadata: languageName: node linkType: hard -"@es-joy/jsdoccomment@npm:~0.50.2": - version: 0.50.2 - resolution: "@es-joy/jsdoccomment@npm:0.50.2" +"@es-joy/jsdoccomment@npm:~0.49.0": + version: 0.49.0 + resolution: "@es-joy/jsdoccomment@npm:0.49.0" dependencies: - "@types/estree": "npm:^1.0.6" - "@typescript-eslint/types": "npm:^8.11.0" comment-parser: "npm:1.4.1" esquery: "npm:^1.6.0" jsdoc-type-pratt-parser: "npm:~4.1.0" - checksum: 10/a309f01bd1691c6991e5efb78057ec9122ef33208fec2464d7b9e5838964b948fa46c9c944a09218a752b49267f05ac15b557018c8a1897fd8df47b944b4537f + checksum: 10/d767cef9b09f22d1892b8bd544eee32aa7b55c585edf6b51452e6f377f205b06f46bd319174022f75794d39625b4b0f8ce75c8a4ea0b7fd0f773063506e0ef4d languageName: node linkType: hard -"@esbuild/aix-ppc64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/aix-ppc64@npm:0.27.3" +"@esbuild/aix-ppc64@npm:0.25.9": + version: 0.25.9 + resolution: "@esbuild/aix-ppc64@npm:0.25.9" conditions: os=aix & cpu=ppc64 languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/android-arm64@npm:0.27.3" +"@esbuild/android-arm64@npm:0.25.9": + version: 0.25.9 + resolution: "@esbuild/android-arm64@npm:0.25.9" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@esbuild/android-arm@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/android-arm@npm:0.27.3" +"@esbuild/android-arm@npm:0.25.9": + version: 0.25.9 + resolution: "@esbuild/android-arm@npm:0.25.9" conditions: os=android & cpu=arm languageName: node linkType: hard -"@esbuild/android-x64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/android-x64@npm:0.27.3" +"@esbuild/android-x64@npm:0.25.9": + version: 0.25.9 + resolution: "@esbuild/android-x64@npm:0.25.9" conditions: os=android & cpu=x64 languageName: node linkType: hard -"@esbuild/darwin-arm64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/darwin-arm64@npm:0.27.3" +"@esbuild/darwin-arm64@npm:0.25.9": + version: 0.25.9 + resolution: "@esbuild/darwin-arm64@npm:0.25.9" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@esbuild/darwin-x64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/darwin-x64@npm:0.27.3" +"@esbuild/darwin-x64@npm:0.25.9": + version: 0.25.9 + resolution: "@esbuild/darwin-x64@npm:0.25.9" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@esbuild/freebsd-arm64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/freebsd-arm64@npm:0.27.3" +"@esbuild/freebsd-arm64@npm:0.25.9": + version: 0.25.9 + resolution: "@esbuild/freebsd-arm64@npm:0.25.9" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/freebsd-x64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/freebsd-x64@npm:0.27.3" +"@esbuild/freebsd-x64@npm:0.25.9": + version: 0.25.9 + resolution: "@esbuild/freebsd-x64@npm:0.25.9" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@esbuild/linux-arm64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/linux-arm64@npm:0.27.3" +"@esbuild/linux-arm64@npm:0.25.9": + version: 0.25.9 + resolution: "@esbuild/linux-arm64@npm:0.25.9" conditions: os=linux & cpu=arm64 languageName: node linkType: hard -"@esbuild/linux-arm@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/linux-arm@npm:0.27.3" +"@esbuild/linux-arm@npm:0.25.9": + version: 0.25.9 + resolution: "@esbuild/linux-arm@npm:0.25.9" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@esbuild/linux-ia32@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/linux-ia32@npm:0.27.3" +"@esbuild/linux-ia32@npm:0.25.9": + version: 0.25.9 + resolution: "@esbuild/linux-ia32@npm:0.25.9" conditions: os=linux & cpu=ia32 languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/linux-loong64@npm:0.27.3" +"@esbuild/linux-loong64@npm:0.25.9": + version: 0.25.9 + resolution: "@esbuild/linux-loong64@npm:0.25.9" conditions: os=linux & cpu=loong64 languageName: node linkType: hard -"@esbuild/linux-mips64el@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/linux-mips64el@npm:0.27.3" +"@esbuild/linux-mips64el@npm:0.25.9": + version: 0.25.9 + resolution: "@esbuild/linux-mips64el@npm:0.25.9" conditions: os=linux & cpu=mips64el languageName: node linkType: hard -"@esbuild/linux-ppc64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/linux-ppc64@npm:0.27.3" +"@esbuild/linux-ppc64@npm:0.25.9": + version: 0.25.9 + resolution: "@esbuild/linux-ppc64@npm:0.25.9" conditions: os=linux & cpu=ppc64 languageName: node linkType: hard -"@esbuild/linux-riscv64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/linux-riscv64@npm:0.27.3" +"@esbuild/linux-riscv64@npm:0.25.9": + version: 0.25.9 + resolution: "@esbuild/linux-riscv64@npm:0.25.9" conditions: os=linux & cpu=riscv64 languageName: node linkType: hard -"@esbuild/linux-s390x@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/linux-s390x@npm:0.27.3" +"@esbuild/linux-s390x@npm:0.25.9": + version: 0.25.9 + resolution: "@esbuild/linux-s390x@npm:0.25.9" conditions: os=linux & cpu=s390x languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/linux-x64@npm:0.27.3" +"@esbuild/linux-x64@npm:0.25.9": + version: 0.25.9 + resolution: "@esbuild/linux-x64@npm:0.25.9" conditions: os=linux & cpu=x64 languageName: node linkType: hard -"@esbuild/netbsd-arm64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/netbsd-arm64@npm:0.27.3" +"@esbuild/netbsd-arm64@npm:0.25.9": + version: 0.25.9 + resolution: "@esbuild/netbsd-arm64@npm:0.25.9" conditions: os=netbsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/netbsd-x64@npm:0.27.3" +"@esbuild/netbsd-x64@npm:0.25.9": + version: 0.25.9 + resolution: "@esbuild/netbsd-x64@npm:0.25.9" conditions: os=netbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/openbsd-arm64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/openbsd-arm64@npm:0.27.3" +"@esbuild/openbsd-arm64@npm:0.25.9": + version: 0.25.9 + resolution: "@esbuild/openbsd-arm64@npm:0.25.9" conditions: os=openbsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/openbsd-x64@npm:0.27.3" +"@esbuild/openbsd-x64@npm:0.25.9": + version: 0.25.9 + resolution: "@esbuild/openbsd-x64@npm:0.25.9" conditions: os=openbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/openharmony-arm64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/openharmony-arm64@npm:0.27.3" +"@esbuild/openharmony-arm64@npm:0.25.9": + version: 0.25.9 + resolution: "@esbuild/openharmony-arm64@npm:0.25.9" conditions: os=openharmony & cpu=arm64 languageName: node linkType: hard -"@esbuild/sunos-x64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/sunos-x64@npm:0.27.3" +"@esbuild/sunos-x64@npm:0.25.9": + version: 0.25.9 + resolution: "@esbuild/sunos-x64@npm:0.25.9" conditions: os=sunos & cpu=x64 languageName: node linkType: hard -"@esbuild/win32-arm64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/win32-arm64@npm:0.27.3" +"@esbuild/win32-arm64@npm:0.25.9": + version: 0.25.9 + resolution: "@esbuild/win32-arm64@npm:0.25.9" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@esbuild/win32-ia32@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/win32-ia32@npm:0.27.3" +"@esbuild/win32-ia32@npm:0.25.9": + version: 0.25.9 + resolution: "@esbuild/win32-ia32@npm:0.25.9" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.27.3": - version: 0.27.3 - resolution: "@esbuild/win32-x64@npm:0.27.3" +"@esbuild/win32-x64@npm:0.25.9": + version: 0.25.9 + resolution: "@esbuild/win32-x64@npm:0.25.9" conditions: os=win32 & cpu=x64 languageName: node linkType: hard -"@eslint-community/eslint-utils@npm:^4.1.2, @eslint-community/eslint-utils@npm:^4.4.0, @eslint-community/eslint-utils@npm:^4.5.0, @eslint-community/eslint-utils@npm:^4.8.0, @eslint-community/eslint-utils@npm:^4.9.1": +"@eslint-community/eslint-utils@npm:^4.1.2, @eslint-community/eslint-utils@npm:^4.4.0, @eslint-community/eslint-utils@npm:^4.4.1, @eslint-community/eslint-utils@npm:^4.8.0, @eslint-community/eslint-utils@npm:^4.9.1": version: 4.9.1 resolution: "@eslint-community/eslint-utils@npm:4.9.1" dependencies: @@ -714,26 +686,26 @@ __metadata: linkType: hard "@eslint/eslintrc@npm:^3.3.1": - version: 3.3.4 - resolution: "@eslint/eslintrc@npm:3.3.4" + version: 3.3.1 + resolution: "@eslint/eslintrc@npm:3.3.1" dependencies: - ajv: "npm:^6.14.0" + ajv: "npm:^6.12.4" debug: "npm:^4.3.2" espree: "npm:^10.0.1" globals: "npm:^14.0.0" ignore: "npm:^5.2.0" import-fresh: "npm:^3.2.1" - js-yaml: "npm:^4.1.1" - minimatch: "npm:^3.1.3" + js-yaml: "npm:^4.1.0" + minimatch: "npm:^3.1.2" strip-json-comments: "npm:^3.1.1" - checksum: 10/537e6bddb55d37a6b128910d54eaa2c1851992781f82dbf36294583de50386ca92bd669eadc99db9181ab4d735f7e6fa286cba10dab1327b1ea88599a2c5e6a7 + checksum: 10/cc240addbab3c5fceaa65b2c8d5d4fd77ddbbf472c2f74f0270b9d33263dc9116840b6099c46b64c9680301146250439b044ed79278a1bcc557da412a4e3c1bb languageName: node linkType: hard -"@eslint/js@npm:9.39.3, @eslint/js@npm:^9.11.0": - version: 9.39.3 - resolution: "@eslint/js@npm:9.39.3" - checksum: 10/91a1a1822cfeb2eb8a89aae86be5dfabad0b66b0915946516690a8485ddd80b91f43eee346789313fea1acbb7390a4958119ca7dc9a684a5c4014f12fcb3aaf3 +"@eslint/js@npm:9.39.1, @eslint/js@npm:^9.11.0": + version: 9.39.1 + resolution: "@eslint/js@npm:9.39.1" + checksum: 10/b10b9b953212c0f3ffca475159bbe519e9e98847200c7432d1637d444fddcd7b712d2b7710a7dc20510f9cfbe8db330039b2aad09cb55d9545b116d940dbeed2 languageName: node linkType: hard @@ -836,24 +808,24 @@ __metadata: languageName: node linkType: hard -"@ethersproject/abi@npm:^5.7.0, @ethersproject/abi@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/abi@npm:5.8.0" +"@ethersproject/abi@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/abi@npm:5.7.0" dependencies: - "@ethersproject/address": "npm:^5.8.0" - "@ethersproject/bignumber": "npm:^5.8.0" - "@ethersproject/bytes": "npm:^5.8.0" - "@ethersproject/constants": "npm:^5.8.0" - "@ethersproject/hash": "npm:^5.8.0" - "@ethersproject/keccak256": "npm:^5.8.0" - "@ethersproject/logger": "npm:^5.8.0" - "@ethersproject/properties": "npm:^5.8.0" - "@ethersproject/strings": "npm:^5.8.0" - checksum: 10/a63ebc2c8ea795ceca5289abaf817bb402c83c330cffd0ae2d355be70c54050a21ddd408abd4fd0dce4c3fd5c5f091707be2095011c233022a52f2110e7012d6 + "@ethersproject/address": "npm:^5.7.0" + "@ethersproject/bignumber": "npm:^5.7.0" + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/constants": "npm:^5.7.0" + "@ethersproject/hash": "npm:^5.7.0" + "@ethersproject/keccak256": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + "@ethersproject/properties": "npm:^5.7.0" + "@ethersproject/strings": "npm:^5.7.0" + checksum: 10/6ed002cbc61a7e21bc0182702345659c1984f6f8e6bad166e43aee76ea8f74766dd0f6236574a868e1b4600af27972bf25b973fae7877ae8da3afa90d3965cac languageName: node linkType: hard -"@ethersproject/abstract-provider@npm:^5.8.0": +"@ethersproject/abstract-provider@npm:^5.7.0, @ethersproject/abstract-provider@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/abstract-provider@npm:5.8.0" dependencies: @@ -868,7 +840,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/abstract-signer@npm:^5.8.0": +"@ethersproject/abstract-signer@npm:^5.7.0, @ethersproject/abstract-signer@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/abstract-signer@npm:5.8.0" dependencies: @@ -894,7 +866,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/base64@npm:^5.8.0": +"@ethersproject/base64@npm:^5.7.0, @ethersproject/base64@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/base64@npm:5.8.0" dependencies: @@ -903,7 +875,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/basex@npm:^5.8.0": +"@ethersproject/basex@npm:^5.7.0, @ethersproject/basex@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/basex@npm:5.8.0" dependencies: @@ -924,7 +896,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/bytes@npm:^5.8.0": +"@ethersproject/bytes@npm:^5.7.0, @ethersproject/bytes@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/bytes@npm:5.8.0" dependencies: @@ -943,24 +915,24 @@ __metadata: linkType: hard "@ethersproject/contracts@npm:^5.7.0": - version: 5.8.0 - resolution: "@ethersproject/contracts@npm:5.8.0" + version: 5.7.0 + resolution: "@ethersproject/contracts@npm:5.7.0" dependencies: - "@ethersproject/abi": "npm:^5.8.0" - "@ethersproject/abstract-provider": "npm:^5.8.0" - "@ethersproject/abstract-signer": "npm:^5.8.0" - "@ethersproject/address": "npm:^5.8.0" - "@ethersproject/bignumber": "npm:^5.8.0" - "@ethersproject/bytes": "npm:^5.8.0" - "@ethersproject/constants": "npm:^5.8.0" - "@ethersproject/logger": "npm:^5.8.0" - "@ethersproject/properties": "npm:^5.8.0" - "@ethersproject/transactions": "npm:^5.8.0" - checksum: 10/839f8211f5e560f15468ae843ba316ffeacab5cebcece1eec76bc5714472ebfe3453484f283d3e46b9d3faaffef1e17cc3583cf24e01638a1fd52f69012cf8d4 + "@ethersproject/abi": "npm:^5.7.0" + "@ethersproject/abstract-provider": "npm:^5.7.0" + "@ethersproject/abstract-signer": "npm:^5.7.0" + "@ethersproject/address": "npm:^5.7.0" + "@ethersproject/bignumber": "npm:^5.7.0" + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/constants": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + "@ethersproject/properties": "npm:^5.7.0" + "@ethersproject/transactions": "npm:^5.7.0" + checksum: 10/5df66179af242faabea287a83fd2f8f303a4244dc87a6ff802e1e3b643f091451295c8e3d088c7739970b7915a16a581c192d4e007d848f1fdf3cc9e49010053 languageName: node linkType: hard -"@ethersproject/hash@npm:^5.8.0": +"@ethersproject/hash@npm:^5.7.0, @ethersproject/hash@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/hash@npm:5.8.0" dependencies: @@ -1018,7 +990,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/keccak256@npm:^5.8.0": +"@ethersproject/keccak256@npm:^5.7.0, @ethersproject/keccak256@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/keccak256@npm:5.8.0" dependencies: @@ -1028,14 +1000,14 @@ __metadata: languageName: node linkType: hard -"@ethersproject/logger@npm:^5.8.0": +"@ethersproject/logger@npm:^5.7.0, @ethersproject/logger@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/logger@npm:5.8.0" checksum: 10/dab862d6cc3a4312f4c49d62b4a603f4b60707da8b8ff0fee6bdfee3cbed48b34ec8f23fedfef04dd3d24f2fa2d7ad2be753c775aa00fe24dcd400631d65004a languageName: node linkType: hard -"@ethersproject/networks@npm:^5.8.0": +"@ethersproject/networks@npm:^5.7.0, @ethersproject/networks@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/networks@npm:5.8.0" dependencies: @@ -1054,7 +1026,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/properties@npm:^5.8.0": +"@ethersproject/properties@npm:^5.7.0, @ethersproject/properties@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/properties@npm:5.8.0" dependencies: @@ -1064,34 +1036,34 @@ __metadata: linkType: hard "@ethersproject/providers@npm:^5.7.0, @ethersproject/providers@npm:^5.7.2": - version: 5.8.0 - resolution: "@ethersproject/providers@npm:5.8.0" + version: 5.7.2 + resolution: "@ethersproject/providers@npm:5.7.2" dependencies: - "@ethersproject/abstract-provider": "npm:^5.8.0" - "@ethersproject/abstract-signer": "npm:^5.8.0" - "@ethersproject/address": "npm:^5.8.0" - "@ethersproject/base64": "npm:^5.8.0" - "@ethersproject/basex": "npm:^5.8.0" - "@ethersproject/bignumber": "npm:^5.8.0" - "@ethersproject/bytes": "npm:^5.8.0" - "@ethersproject/constants": "npm:^5.8.0" - "@ethersproject/hash": "npm:^5.8.0" - "@ethersproject/logger": "npm:^5.8.0" - "@ethersproject/networks": "npm:^5.8.0" - "@ethersproject/properties": "npm:^5.8.0" - "@ethersproject/random": "npm:^5.8.0" - "@ethersproject/rlp": "npm:^5.8.0" - "@ethersproject/sha2": "npm:^5.8.0" - "@ethersproject/strings": "npm:^5.8.0" - "@ethersproject/transactions": "npm:^5.8.0" - "@ethersproject/web": "npm:^5.8.0" + "@ethersproject/abstract-provider": "npm:^5.7.0" + "@ethersproject/abstract-signer": "npm:^5.7.0" + "@ethersproject/address": "npm:^5.7.0" + "@ethersproject/base64": "npm:^5.7.0" + "@ethersproject/basex": "npm:^5.7.0" + "@ethersproject/bignumber": "npm:^5.7.0" + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/constants": "npm:^5.7.0" + "@ethersproject/hash": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + "@ethersproject/networks": "npm:^5.7.0" + "@ethersproject/properties": "npm:^5.7.0" + "@ethersproject/random": "npm:^5.7.0" + "@ethersproject/rlp": "npm:^5.7.0" + "@ethersproject/sha2": "npm:^5.7.0" + "@ethersproject/strings": "npm:^5.7.0" + "@ethersproject/transactions": "npm:^5.7.0" + "@ethersproject/web": "npm:^5.7.0" bech32: "npm:1.1.4" - ws: "npm:8.18.0" - checksum: 10/7d40fc0abb78fc9e69b71cb560beb2a93cf1da2cf978a061031a34c0ed76c2f5936ed8c0bdb9aa1307fe5308d0159e429b83b779dbd550639a886a88d6d17817 + ws: "npm:7.4.6" + checksum: 10/8534a1896e61b9f0b66427a639df64a5fe76d0c08ec59b9f0cc64fdd1d0cc28d9fc3312838ae8d7817c8f5e2e76b7f228b689bc33d1cbb8e1b9517d4c4f678d8 languageName: node linkType: hard -"@ethersproject/random@npm:^5.8.0": +"@ethersproject/random@npm:^5.7.0, @ethersproject/random@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/random@npm:5.8.0" dependencies: @@ -1101,7 +1073,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/rlp@npm:^5.8.0": +"@ethersproject/rlp@npm:^5.7.0, @ethersproject/rlp@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/rlp@npm:5.8.0" dependencies: @@ -1111,7 +1083,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/sha2@npm:^5.8.0": +"@ethersproject/sha2@npm:^5.7.0, @ethersproject/sha2@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/sha2@npm:5.8.0" dependencies: @@ -1136,7 +1108,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/strings@npm:^5.8.0": +"@ethersproject/strings@npm:^5.7.0, @ethersproject/strings@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/strings@npm:5.8.0" dependencies: @@ -1147,7 +1119,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/transactions@npm:^5.8.0": +"@ethersproject/transactions@npm:^5.7.0, @ethersproject/transactions@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/transactions@npm:5.8.0" dependencies: @@ -1187,7 +1159,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/web@npm:^5.8.0": +"@ethersproject/web@npm:^5.7.0, @ethersproject/web@npm:^5.8.0": version: 5.8.0 resolution: "@ethersproject/web@npm:5.8.0" dependencies: @@ -1213,34 +1185,18 @@ __metadata: languageName: node linkType: hard -"@firebase/ai@npm:1.4.1": - version: 1.4.1 - resolution: "@firebase/ai@npm:1.4.1" - dependencies: - "@firebase/app-check-interop-types": "npm:0.3.3" - "@firebase/component": "npm:0.6.18" - "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.12.1" - tslib: "npm:^2.1.0" - peerDependencies: - "@firebase/app": 0.x - "@firebase/app-types": 0.x - checksum: 10/64b152365f3de9d12dc6691eebe673193a3a1034e9a2217c736a3b5d52e671f9cb61b35e85ecaf9a36c9667ce4c45fccaa4fc750b01fafcaeef757dc761ea971 - languageName: node - linkType: hard - -"@firebase/analytics-compat@npm:0.2.23": - version: 0.2.23 - resolution: "@firebase/analytics-compat@npm:0.2.23" +"@firebase/analytics-compat@npm:0.2.17": + version: 0.2.17 + resolution: "@firebase/analytics-compat@npm:0.2.17" dependencies: - "@firebase/analytics": "npm:0.10.17" + "@firebase/analytics": "npm:0.10.11" "@firebase/analytics-types": "npm:0.8.3" - "@firebase/component": "npm:0.6.18" - "@firebase/util": "npm:1.12.1" + "@firebase/component": "npm:0.6.12" + "@firebase/util": "npm:1.10.3" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app-compat": 0.x - checksum: 10/17414002039df8cfb5f1ed320b60b9d369ef2e9833cb4a4c485afff3ebad520e33aebda628556e940f5a2ad4741d56f58d3eaf754d1811dbd5fec9ed48a27fec + checksum: 10/3b048b41e0405a3975050f5d55afa923263ba3768d7b1b635d70892504cac03bd0bcf353b44819959dc6de7c04f1df818e34cec705c8ce18cf5c0866abe277b9 languageName: node linkType: hard @@ -1251,34 +1207,34 @@ __metadata: languageName: node linkType: hard -"@firebase/analytics@npm:0.10.17": - version: 0.10.17 - resolution: "@firebase/analytics@npm:0.10.17" +"@firebase/analytics@npm:0.10.11": + version: 0.10.11 + resolution: "@firebase/analytics@npm:0.10.11" dependencies: - "@firebase/component": "npm:0.6.18" - "@firebase/installations": "npm:0.6.18" + "@firebase/component": "npm:0.6.12" + "@firebase/installations": "npm:0.6.12" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.12.1" + "@firebase/util": "npm:1.10.3" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app": 0.x - checksum: 10/689c9e8ce0f86c606c1c8ffc1c44cee84c9eb0c767fdf8ef8ccc138515a81071011d958aa06f35a8fc6cdff8050d3e91cb559aebc42fa944ab79ffab2b8dc1d4 + checksum: 10/804083f61ffc57dabeb7a1b49e16f86969d1b2a37fafc23633c90324768ab849e52324b6a10928d789e038ec2f5d93248717f18d5f0d2a4b916850b86051c214 languageName: node linkType: hard -"@firebase/app-check-compat@npm:0.3.26": - version: 0.3.26 - resolution: "@firebase/app-check-compat@npm:0.3.26" +"@firebase/app-check-compat@npm:0.3.18": + version: 0.3.18 + resolution: "@firebase/app-check-compat@npm:0.3.18" dependencies: - "@firebase/app-check": "npm:0.10.1" + "@firebase/app-check": "npm:0.8.11" "@firebase/app-check-types": "npm:0.5.3" - "@firebase/component": "npm:0.6.18" + "@firebase/component": "npm:0.6.12" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.12.1" + "@firebase/util": "npm:1.10.3" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app-compat": 0.x - checksum: 10/679cefa70e2c9b448e4c494a7e87f032b804777b0a4dde403ebdb9a1b3b2087e6d3248f3265a0083b32b24fbfd960b12ba171dd762f783a64fd47e0088583fa8 + checksum: 10/24b103fc309fa66d9830614c69bdf62810ecf0b77ad4fc9f318e05361a686cc3a684d84bddbd6afddc6a641739ead93ab1e8c28a75ed915750602b371aeb9b32 languageName: node linkType: hard @@ -1296,30 +1252,30 @@ __metadata: languageName: node linkType: hard -"@firebase/app-check@npm:0.10.1": - version: 0.10.1 - resolution: "@firebase/app-check@npm:0.10.1" +"@firebase/app-check@npm:0.8.11": + version: 0.8.11 + resolution: "@firebase/app-check@npm:0.8.11" dependencies: - "@firebase/component": "npm:0.6.18" + "@firebase/component": "npm:0.6.12" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.12.1" + "@firebase/util": "npm:1.10.3" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app": 0.x - checksum: 10/b10d72aa267799344a8f11539b427db27edfdcd9fd9810b94b54c980c509fe91af5cf2ca491c8aa28d312d72e27f162377bd0acd4ada28152c152a9b304209ba + checksum: 10/e3f6a3940037c17a2faaf97a700d33b2c7821e07460e0a854d9f542acdcb589514bb4699df3adba1fb1d17ee75261006939b8ef60ec44bbe6c8c827b0797aa77 languageName: node linkType: hard -"@firebase/app-compat@npm:0.4.2": - version: 0.4.2 - resolution: "@firebase/app-compat@npm:0.4.2" +"@firebase/app-compat@npm:0.2.48": + version: 0.2.48 + resolution: "@firebase/app-compat@npm:0.2.48" dependencies: - "@firebase/app": "npm:0.13.2" - "@firebase/component": "npm:0.6.18" + "@firebase/app": "npm:0.10.18" + "@firebase/component": "npm:0.6.12" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.12.1" + "@firebase/util": "npm:1.10.3" tslib: "npm:^2.1.0" - checksum: 10/07547051fbd4164547f208907493db37c41d418e03436d1058dfcbaa4850125f937247edc5a0c29c661cbbc532357c9cde936ccb113ba5ca71c7544be88b3c00 + checksum: 10/b74598b960ebb0a773b04e04d45dd59dbc8e09d1ae46c8ee7fd950632c95d357e8edab353df7032b798f2613884c96f3201eb5fbcdbfba67cb23757d66e63586 languageName: node linkType: hard @@ -1330,31 +1286,31 @@ __metadata: languageName: node linkType: hard -"@firebase/app@npm:0.13.2": - version: 0.13.2 - resolution: "@firebase/app@npm:0.13.2" +"@firebase/app@npm:0.10.18": + version: 0.10.18 + resolution: "@firebase/app@npm:0.10.18" dependencies: - "@firebase/component": "npm:0.6.18" + "@firebase/component": "npm:0.6.12" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.12.1" + "@firebase/util": "npm:1.10.3" idb: "npm:7.1.1" tslib: "npm:^2.1.0" - checksum: 10/74ab96561490da7d0bd46be5bb04d43edb65aaf96e6c9b17a7bda15d43a299b8204908e14e1fc29d690cff5a59345cc9e4a598ec99b46a22c1416f304875bc5e + checksum: 10/ac215e594d66e933207263c4c11ff585ba3843a0e73ab6f02c85f504f7b5e166f407a9bef299f5a91893840c7f5c8978895c0f6103b361fb188c1cfdb8c35030 languageName: node linkType: hard -"@firebase/auth-compat@npm:0.5.28": - version: 0.5.28 - resolution: "@firebase/auth-compat@npm:0.5.28" +"@firebase/auth-compat@npm:0.5.17": + version: 0.5.17 + resolution: "@firebase/auth-compat@npm:0.5.17" dependencies: - "@firebase/auth": "npm:1.10.8" - "@firebase/auth-types": "npm:0.13.0" - "@firebase/component": "npm:0.6.18" - "@firebase/util": "npm:1.12.1" + "@firebase/auth": "npm:1.8.2" + "@firebase/auth-types": "npm:0.12.3" + "@firebase/component": "npm:0.6.12" + "@firebase/util": "npm:1.10.3" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app-compat": 0.x - checksum: 10/df87c841e8ce44510927df1f5d6387787cc9ca7119a72436e1960f08fb8a96f11caf0dd71f947062bac78c104fb9afa7c04e5ef5dfa343a08c4609fb4b9deabd + checksum: 10/4c6d0fa6f76c398872627f49c427c810269c0284bdca1acddf82b154c9cda7131e8acecd961c2e0947f0340428b67349b7f9471bb1bd75bd82839ce89879ccad languageName: node linkType: hard @@ -1365,23 +1321,23 @@ __metadata: languageName: node linkType: hard -"@firebase/auth-types@npm:0.13.0": - version: 0.13.0 - resolution: "@firebase/auth-types@npm:0.13.0" +"@firebase/auth-types@npm:0.12.3": + version: 0.12.3 + resolution: "@firebase/auth-types@npm:0.12.3" peerDependencies: "@firebase/app-types": 0.x "@firebase/util": 1.x - checksum: 10/57d8e4b80e58d3a9e453b4676a29e3b0e548ca9f4c2b465137007bb5753e3bde2f6537f0be9779df17859ebc4e6b1b59c88215cdd59a32106391cf117072372d + checksum: 10/5eda88380e9b33a6c91b0f8dd6a581895c2770aa5b46b1928a006a74d35c6a310bfe737141ff013764a4e02815efa530f1576d674f09f905fbe3b14050dc7fce languageName: node linkType: hard -"@firebase/auth@npm:1.10.8": - version: 1.10.8 - resolution: "@firebase/auth@npm:1.10.8" +"@firebase/auth@npm:1.8.2": + version: 1.8.2 + resolution: "@firebase/auth@npm:1.8.2" dependencies: - "@firebase/component": "npm:0.6.18" + "@firebase/component": "npm:0.6.12" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.12.1" + "@firebase/util": "npm:1.10.3" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app": 0.x @@ -1389,86 +1345,86 @@ __metadata: peerDependenciesMeta: "@react-native-async-storage/async-storage": optional: true - checksum: 10/c319d9c39a746317556c879e174bc8e0c4b6d3c72b8226ca3d6c6fc146387f0ad05cbe0b1d84c675a5b7cf6769fe5e696fbb140249c10f6b77586414642c0b39 + checksum: 10/8cfe5e6d78ea555f52bffad6e4b21824a30040fd52ffeb3d60edf0c122f0cbb66fc012e708f49473f045fa3064a4ac760e8bc6b24d5ccdf4ae7087b07da61247 languageName: node linkType: hard -"@firebase/component@npm:0.6.18": - version: 0.6.18 - resolution: "@firebase/component@npm:0.6.18" +"@firebase/component@npm:0.6.12": + version: 0.6.12 + resolution: "@firebase/component@npm:0.6.12" dependencies: - "@firebase/util": "npm:1.12.1" + "@firebase/util": "npm:1.10.3" tslib: "npm:^2.1.0" - checksum: 10/cc50bd7fba3219c1dc8049cb3eee513ff76c13c9750588db3acc5d0bce98cdc7e546c227c7d7a21a96a1eb9366d20243d5770c4582fc967d2856235bf47a2023 + checksum: 10/4dfd201d3709ef5eed477e13d399611a78a186ca8911846e24361f9848c3b4eecc14c295a8f78ec40c88816329fde0ba6cc30dce9a444fa43a619b7ea744f0dc languageName: node linkType: hard -"@firebase/data-connect@npm:0.3.10": - version: 0.3.10 - resolution: "@firebase/data-connect@npm:0.3.10" +"@firebase/data-connect@npm:0.2.0": + version: 0.2.0 + resolution: "@firebase/data-connect@npm:0.2.0" dependencies: "@firebase/auth-interop-types": "npm:0.2.4" - "@firebase/component": "npm:0.6.18" + "@firebase/component": "npm:0.6.12" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.12.1" + "@firebase/util": "npm:1.10.3" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app": 0.x - checksum: 10/22ca29b05ef868355b5744ba895bd4df7225f21c22a2f60147096d9f4fb7c68985cd7949d7674bf481a7a135b0a52355bc997eacdd1c29b99e3f236b4e4ea676 + checksum: 10/7ba5886bc69b0a42757539a3de417d550ca3359f495a3d8a3974e799a21fbcc2ea15393c00e183dcd01a845d42cad15a914345b4bed63bd401089861e92b1b35 languageName: node linkType: hard -"@firebase/database-compat@npm:2.0.11": - version: 2.0.11 - resolution: "@firebase/database-compat@npm:2.0.11" +"@firebase/database-compat@npm:2.0.2": + version: 2.0.2 + resolution: "@firebase/database-compat@npm:2.0.2" dependencies: - "@firebase/component": "npm:0.6.18" - "@firebase/database": "npm:1.0.20" - "@firebase/database-types": "npm:1.0.15" + "@firebase/component": "npm:0.6.12" + "@firebase/database": "npm:1.0.11" + "@firebase/database-types": "npm:1.0.8" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.12.1" + "@firebase/util": "npm:1.10.3" tslib: "npm:^2.1.0" - checksum: 10/fc85067ffbb3bf789353465e8f79b05d34a563cde909fc3057bcbdee002e07e26b99eba049f41c79385c71217db1d1207591415545a7b42e54318dc869bff7f2 + checksum: 10/5a341662c32f08f248ce9e8cecb940169f618c42a5a85de72247f13ffa32d5ca0a5619d0330f6ff8c7e1ea6952733534531e03e53e2746732bcfc6e851c031b3 languageName: node linkType: hard -"@firebase/database-types@npm:1.0.15": - version: 1.0.15 - resolution: "@firebase/database-types@npm:1.0.15" +"@firebase/database-types@npm:1.0.8": + version: 1.0.8 + resolution: "@firebase/database-types@npm:1.0.8" dependencies: "@firebase/app-types": "npm:0.9.3" - "@firebase/util": "npm:1.12.1" - checksum: 10/b9e2ef2d4c51fa518e7ace10e990d8b0f449dc669537b6fe57dc2beca64c658703e7b06272ad5b0935f094f65abe870ef34793ee205aa6559f5404b886c835e6 + "@firebase/util": "npm:1.10.3" + checksum: 10/1b5483de082ff8d7551b21f087ba2f237bcd38ca9e3f48b1377b96213718e0a206437fe31a4e055c1b90d05a1f38f89fe1c92d50d907ca06c8727c73fc521c40 languageName: node linkType: hard -"@firebase/database@npm:1.0.20": - version: 1.0.20 - resolution: "@firebase/database@npm:1.0.20" +"@firebase/database@npm:1.0.11": + version: 1.0.11 + resolution: "@firebase/database@npm:1.0.11" dependencies: "@firebase/app-check-interop-types": "npm:0.3.3" "@firebase/auth-interop-types": "npm:0.2.4" - "@firebase/component": "npm:0.6.18" + "@firebase/component": "npm:0.6.12" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.12.1" + "@firebase/util": "npm:1.10.3" faye-websocket: "npm:0.11.4" tslib: "npm:^2.1.0" - checksum: 10/337189b26ef27bfb31244ef230f4b3c26797dfd3c80004f5fac256ec276783c90ee3b78a4b3efc5d7feb1afcfe817f739c212ea3a94126849a26a0b4a4134dd7 + checksum: 10/8df5c54a6e88ecd2f71fe5bf156d23132c92f698210e23f27144dd871ea518e2268dc0eac91152091c8b75dbdf66d18c0ca623e80d1d3a69af5a3ed956a26e59 languageName: node linkType: hard -"@firebase/firestore-compat@npm:0.3.53": - version: 0.3.53 - resolution: "@firebase/firestore-compat@npm:0.3.53" +"@firebase/firestore-compat@npm:0.3.41": + version: 0.3.41 + resolution: "@firebase/firestore-compat@npm:0.3.41" dependencies: - "@firebase/component": "npm:0.6.18" - "@firebase/firestore": "npm:4.8.0" + "@firebase/component": "npm:0.6.12" + "@firebase/firestore": "npm:4.7.6" "@firebase/firestore-types": "npm:3.0.3" - "@firebase/util": "npm:1.12.1" + "@firebase/util": "npm:1.10.3" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app-compat": 0.x - checksum: 10/4ec87a5b060bd7111b0eaadd34f6f73a5ab5d8464fabc7e6cbc4df86d228ae4cbdb72fd214e328f9b6e6cd8614b54a88a1cbd41a6d468f4861429b6399e7a5f3 + checksum: 10/a719fc6bd1150b5b1653053e73709b2b2edddb6c2a9274a896f9b38a6a09e92d650dbb5df55aceaf23c413445a8beb18073b8726247df9aadbe13d175154fff1 languageName: node linkType: hard @@ -1482,35 +1438,35 @@ __metadata: languageName: node linkType: hard -"@firebase/firestore@npm:4.8.0": - version: 4.8.0 - resolution: "@firebase/firestore@npm:4.8.0" +"@firebase/firestore@npm:4.7.6": + version: 4.7.6 + resolution: "@firebase/firestore@npm:4.7.6" dependencies: - "@firebase/component": "npm:0.6.18" + "@firebase/component": "npm:0.6.12" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.12.1" + "@firebase/util": "npm:1.10.3" "@firebase/webchannel-wrapper": "npm:1.0.3" "@grpc/grpc-js": "npm:~1.9.0" "@grpc/proto-loader": "npm:^0.7.8" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app": 0.x - checksum: 10/201f5c4773bcf1e87aacf248b9ea902402665c27670503f1f17e2ef4602b4eca371288c9f504e88a6ac23f97df0af1aab5e107ddb86b95b7a62adcfe0974dbf7 + checksum: 10/76e879675b34212af74e3d294458e254c3f547d4168a377074671317b3bcfc07acdff1e853bd1f139b8e4a767e91749f00ee00aa52d968c67f190fe490256151 languageName: node linkType: hard -"@firebase/functions-compat@npm:0.3.26": - version: 0.3.26 - resolution: "@firebase/functions-compat@npm:0.3.26" +"@firebase/functions-compat@npm:0.3.18": + version: 0.3.18 + resolution: "@firebase/functions-compat@npm:0.3.18" dependencies: - "@firebase/component": "npm:0.6.18" - "@firebase/functions": "npm:0.12.9" + "@firebase/component": "npm:0.6.12" + "@firebase/functions": "npm:0.12.1" "@firebase/functions-types": "npm:0.6.3" - "@firebase/util": "npm:1.12.1" + "@firebase/util": "npm:1.10.3" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app-compat": 0.x - checksum: 10/42a0c5914bbb9dfdb1630acc6e7fd0c05cee0b5965df6325fb0bc34c591e8d12c45151b0edef3f56180bc3f0131ed2d33552d6a2428ac6929f717e5f485149e4 + checksum: 10/224132bbd592c73c717fb8b065a8e718d43c1f72d05135313fd19f7efd566164217d13e65bf6f142973bc35b29ff792c414610a9ddcd708601ddf718d739d3c9 languageName: node linkType: hard @@ -1521,34 +1477,34 @@ __metadata: languageName: node linkType: hard -"@firebase/functions@npm:0.12.9": - version: 0.12.9 - resolution: "@firebase/functions@npm:0.12.9" +"@firebase/functions@npm:0.12.1": + version: 0.12.1 + resolution: "@firebase/functions@npm:0.12.1" dependencies: "@firebase/app-check-interop-types": "npm:0.3.3" "@firebase/auth-interop-types": "npm:0.2.4" - "@firebase/component": "npm:0.6.18" + "@firebase/component": "npm:0.6.12" "@firebase/messaging-interop-types": "npm:0.2.3" - "@firebase/util": "npm:1.12.1" + "@firebase/util": "npm:1.10.3" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app": 0.x - checksum: 10/5646363243e07451c568d7b471a1c895a6b273d9cae168f70fa512a86916d85f9e2a73f9b378adef423a5e6b3af41cc2b5a8545458503f9956b1a5ebc93fd918 + checksum: 10/db32ed6297a1f187062c772f3134f19849e3f1e55345838ebf2256555f1d65648c018ead208909bafd9620deba1191385f4223835cdad5c1c4e9567cb9244721 languageName: node linkType: hard -"@firebase/installations-compat@npm:0.2.18": - version: 0.2.18 - resolution: "@firebase/installations-compat@npm:0.2.18" +"@firebase/installations-compat@npm:0.2.12": + version: 0.2.12 + resolution: "@firebase/installations-compat@npm:0.2.12" dependencies: - "@firebase/component": "npm:0.6.18" - "@firebase/installations": "npm:0.6.18" + "@firebase/component": "npm:0.6.12" + "@firebase/installations": "npm:0.6.12" "@firebase/installations-types": "npm:0.5.3" - "@firebase/util": "npm:1.12.1" + "@firebase/util": "npm:1.10.3" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app-compat": 0.x - checksum: 10/5f5adc8384dcc6e1cee0c1f2e162134a38d3aac7a4152e5ee512da06174d79957c27bc49798dc79b28b668a233fb0b8eafb8d8dcd90c077357383329e7acf8a0 + checksum: 10/ffd5e08e65e7067c06a4eb5601a09b017fce006b38108c10c412df8144e79bd08b4347998740425f312288b5a0839818e634486875857df5518c05a737c46ad8 languageName: node linkType: hard @@ -1561,17 +1517,17 @@ __metadata: languageName: node linkType: hard -"@firebase/installations@npm:0.6.18": - version: 0.6.18 - resolution: "@firebase/installations@npm:0.6.18" +"@firebase/installations@npm:0.6.12": + version: 0.6.12 + resolution: "@firebase/installations@npm:0.6.12" dependencies: - "@firebase/component": "npm:0.6.18" - "@firebase/util": "npm:1.12.1" + "@firebase/component": "npm:0.6.12" + "@firebase/util": "npm:1.10.3" idb: "npm:7.1.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app": 0.x - checksum: 10/70d9036c6aa9c5ed79d1e66221ab38badbdcc2ff745d0bba4bede2d857c50e5678da6bea8862f8c31a74cb924778f6d0916286c4e5a9cb851decea3884ad6f56 + checksum: 10/093295de087b4c9287d06243eb19814e25674047aafa4f5db9a222d8e64283d0362f37edf8cfbe882a80eac1d2d9fc52b821fbb01151ac925f023765251dd1de languageName: node linkType: hard @@ -1584,17 +1540,17 @@ __metadata: languageName: node linkType: hard -"@firebase/messaging-compat@npm:0.2.22": - version: 0.2.22 - resolution: "@firebase/messaging-compat@npm:0.2.22" +"@firebase/messaging-compat@npm:0.2.16": + version: 0.2.16 + resolution: "@firebase/messaging-compat@npm:0.2.16" dependencies: - "@firebase/component": "npm:0.6.18" - "@firebase/messaging": "npm:0.12.22" - "@firebase/util": "npm:1.12.1" + "@firebase/component": "npm:0.6.12" + "@firebase/messaging": "npm:0.12.16" + "@firebase/util": "npm:1.10.3" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app-compat": 0.x - checksum: 10/67f266689f6889fa169188e276d483f546565ee895481ba890a549bc27977a1ef08066a320c3099b77cc695086c9f5f2d90a4b7d9a2e0e4293de01397b38c956 + checksum: 10/1887599e3f7d7db5a70f923118eda769130aa134c6a6ba0a9f599c541d78b2e00b9548fc51c12f430c60a6e902221fe951a4beeddd674f1c042ffa32d1593dc9 languageName: node linkType: hard @@ -1605,35 +1561,35 @@ __metadata: languageName: node linkType: hard -"@firebase/messaging@npm:0.12.22": - version: 0.12.22 - resolution: "@firebase/messaging@npm:0.12.22" +"@firebase/messaging@npm:0.12.16": + version: 0.12.16 + resolution: "@firebase/messaging@npm:0.12.16" dependencies: - "@firebase/component": "npm:0.6.18" - "@firebase/installations": "npm:0.6.18" + "@firebase/component": "npm:0.6.12" + "@firebase/installations": "npm:0.6.12" "@firebase/messaging-interop-types": "npm:0.2.3" - "@firebase/util": "npm:1.12.1" + "@firebase/util": "npm:1.10.3" idb: "npm:7.1.1" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app": 0.x - checksum: 10/0639961d0cd695a44cb8f80a44a7e3d030a3746e6586db4a8d730623ac5d2a238d0a721fbd77cdaf3873f775881aee234e0e312c9bdcf70b65eb57be3ad5d58a + checksum: 10/e237f35c4b179a521a6a37255fa719784ec73f30b76d179c059f21bf1e7ee6f907299c137a7b55496134dc5c3578d365c62b2e44988323edd3d96e5468f016d6 languageName: node linkType: hard -"@firebase/performance-compat@npm:0.2.20": - version: 0.2.20 - resolution: "@firebase/performance-compat@npm:0.2.20" +"@firebase/performance-compat@npm:0.2.12": + version: 0.2.12 + resolution: "@firebase/performance-compat@npm:0.2.12" dependencies: - "@firebase/component": "npm:0.6.18" + "@firebase/component": "npm:0.6.12" "@firebase/logger": "npm:0.4.4" - "@firebase/performance": "npm:0.7.7" + "@firebase/performance": "npm:0.6.12" "@firebase/performance-types": "npm:0.2.3" - "@firebase/util": "npm:1.12.1" + "@firebase/util": "npm:1.10.3" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app-compat": 0.x - checksum: 10/5589470cfc1952a53fa81885b9d061eacab431f1875d858ff25632f2287d789d0d6641bd1c08f54c93681e58d37104acf895c07583898c6e9ec7184a03460ff3 + checksum: 10/c171273df3994da6687a8e02dd7f046cd749d80d18e1bc241e1e8fd55f4d05578bcdd3924153fbf7175da2a0b88dc8fb6e7de98afe72dd1a36e54f96e807dea1 languageName: node linkType: hard @@ -1644,35 +1600,34 @@ __metadata: languageName: node linkType: hard -"@firebase/performance@npm:0.7.7": - version: 0.7.7 - resolution: "@firebase/performance@npm:0.7.7" +"@firebase/performance@npm:0.6.12": + version: 0.6.12 + resolution: "@firebase/performance@npm:0.6.12" dependencies: - "@firebase/component": "npm:0.6.18" - "@firebase/installations": "npm:0.6.18" + "@firebase/component": "npm:0.6.12" + "@firebase/installations": "npm:0.6.12" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.12.1" + "@firebase/util": "npm:1.10.3" tslib: "npm:^2.1.0" - web-vitals: "npm:^4.2.4" peerDependencies: "@firebase/app": 0.x - checksum: 10/c4ad40b795966cecec89de66f4da76b750215cd4c859fda84db00c3a11b0633749873ac71d2c2dee307239cfdf9e5d1f1e83ef54061f9f03995df4cddc724319 + checksum: 10/68f802e2a1f0add51e2346049957487561d1f59f9ea57f8447d7ba771210aee875aaa144d7db56bb376bac3509d800e917e6c3560e3dbf19bdc60c6e1bc67766 languageName: node linkType: hard -"@firebase/remote-config-compat@npm:0.2.18": - version: 0.2.18 - resolution: "@firebase/remote-config-compat@npm:0.2.18" +"@firebase/remote-config-compat@npm:0.2.12": + version: 0.2.12 + resolution: "@firebase/remote-config-compat@npm:0.2.12" dependencies: - "@firebase/component": "npm:0.6.18" + "@firebase/component": "npm:0.6.12" "@firebase/logger": "npm:0.4.4" - "@firebase/remote-config": "npm:0.6.5" + "@firebase/remote-config": "npm:0.5.0" "@firebase/remote-config-types": "npm:0.4.0" - "@firebase/util": "npm:1.12.1" + "@firebase/util": "npm:1.10.3" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app-compat": 0.x - checksum: 10/ba4311b295a35bfa27628698cf06b46d8debaa2e0a0dae147baa28f72340809e94132eaa793df3fd3973b00b6713cc89ccaf4bd33f6c5bcd1f68064f35a563f2 + checksum: 10/931c4739c2b11b2719076630f09f5aa18f9edf8e89cf35c9b9a3a8cc5afc497c86e68cca165e1416afcb0b8040ed04363c676d31118fdcf4bf3823ef9172785c languageName: node linkType: hard @@ -1683,33 +1638,33 @@ __metadata: languageName: node linkType: hard -"@firebase/remote-config@npm:0.6.5": - version: 0.6.5 - resolution: "@firebase/remote-config@npm:0.6.5" +"@firebase/remote-config@npm:0.5.0": + version: 0.5.0 + resolution: "@firebase/remote-config@npm:0.5.0" dependencies: - "@firebase/component": "npm:0.6.18" - "@firebase/installations": "npm:0.6.18" + "@firebase/component": "npm:0.6.12" + "@firebase/installations": "npm:0.6.12" "@firebase/logger": "npm:0.4.4" - "@firebase/util": "npm:1.12.1" + "@firebase/util": "npm:1.10.3" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app": 0.x - checksum: 10/50e14afd65f9f4abb2dc3a268b3b82e522a9591123a1154b42a157228b71c661d7a7b77c81a3de59eec38c6ee278d5479516114f8d0e46162959e7af52bd6e2e + checksum: 10/58a6fad255d3975700e65d4d19ec3360703f920bcbd3bd2ff21f239367af7405bfec5fddf3f800fb405dd4e4456f73cdf0c5cbf624a9512d77293f7cf14b64d8 languageName: node linkType: hard -"@firebase/storage-compat@npm:0.3.24": - version: 0.3.24 - resolution: "@firebase/storage-compat@npm:0.3.24" +"@firebase/storage-compat@npm:0.3.15": + version: 0.3.15 + resolution: "@firebase/storage-compat@npm:0.3.15" dependencies: - "@firebase/component": "npm:0.6.18" - "@firebase/storage": "npm:0.13.14" + "@firebase/component": "npm:0.6.12" + "@firebase/storage": "npm:0.13.5" "@firebase/storage-types": "npm:0.8.3" - "@firebase/util": "npm:1.12.1" + "@firebase/util": "npm:1.10.3" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app-compat": 0.x - checksum: 10/5445c8165d3732e31b77ca616497f930ed17c70d45202709907a38e82605d96df083fd5682b0c1fb6b34e71cebae9f8aa084abe81fd80e362ef80410fefcd508 + checksum: 10/a4a4c64c44ea914a9509061ec373f33278f7096a547e7a9ed55c9100562bd688ca4f14f15eb3a798d5075b0e18dc15801bb95b23eddb2da600d855ee6c69e745 languageName: node linkType: hard @@ -1723,25 +1678,41 @@ __metadata: languageName: node linkType: hard -"@firebase/storage@npm:0.13.14": - version: 0.13.14 - resolution: "@firebase/storage@npm:0.13.14" +"@firebase/storage@npm:0.13.5": + version: 0.13.5 + resolution: "@firebase/storage@npm:0.13.5" dependencies: - "@firebase/component": "npm:0.6.18" - "@firebase/util": "npm:1.12.1" + "@firebase/component": "npm:0.6.12" + "@firebase/util": "npm:1.10.3" tslib: "npm:^2.1.0" peerDependencies: "@firebase/app": 0.x - checksum: 10/e107960285ea7b0405e152e0da236c508d0b2b43f87a17accfd3fda5ea8b2d5fdad6a78a18b5e11b55817468afa3531b608bbb15ab83c54d3535aecd5a1e4ebd + checksum: 10/89acbd41d3ed9bffe7a37e293b0dc572622c196665db2821d76690ee205397f3f331666c24b5c63c14caaadb3e519b3489400a6c5387e78d4fe0c97fe75128a9 + languageName: node + linkType: hard + +"@firebase/util@npm:1.10.3": + version: 1.10.3 + resolution: "@firebase/util@npm:1.10.3" + dependencies: + tslib: "npm:^2.1.0" + checksum: 10/8e5e1664a09798348abfa0cd138157943f8ee9c6e3804e6cb1dcff004b351a03f14f4b2711338133bb89f7f824546664af2c2aa98e229becbc9294cdddeecc99 languageName: node linkType: hard -"@firebase/util@npm:1.12.1": - version: 1.12.1 - resolution: "@firebase/util@npm:1.12.1" +"@firebase/vertexai@npm:1.0.3": + version: 1.0.3 + resolution: "@firebase/vertexai@npm:1.0.3" dependencies: + "@firebase/app-check-interop-types": "npm:0.3.3" + "@firebase/component": "npm:0.6.12" + "@firebase/logger": "npm:0.4.4" + "@firebase/util": "npm:1.10.3" tslib: "npm:^2.1.0" - checksum: 10/31c608b4a614534366bec66dd699384467bf08b60b97801c33793025851f530cd1837ff00434aef49bfc1f35a1b38262ed0ac73d4393a3c4eab77dccb30a215f + peerDependencies: + "@firebase/app": 0.x + "@firebase/app-types": 0.x + checksum: 10/67b0ac231a547ac99bef3a549199fbaa67271fe93c1dc2af48bfebcf8ac1a7ea45bec6c633b8ac3ad28b089a6601e2b352c68c53065242dccac07a20a887d6cd languageName: node linkType: hard @@ -1763,8 +1734,8 @@ __metadata: linkType: hard "@grpc/proto-loader@npm:^0.7.8": - version: 0.7.15 - resolution: "@grpc/proto-loader@npm:0.7.15" + version: 0.7.13 + resolution: "@grpc/proto-loader@npm:0.7.13" dependencies: lodash.camelcase: "npm:^4.3.0" long: "npm:^5.0.0" @@ -1772,7 +1743,7 @@ __metadata: yargs: "npm:^17.7.2" bin: proto-loader-gen-types: build/bin/proto-loader-gen-types.js - checksum: 10/2e2b33ace8bc34211522751a9e654faf9ac997577a9e9291b1619b4c05d7878a74d2101c3bc43b2b2b92bca7509001678fb191d4eb100684cc2910d66f36c373 + checksum: 10/7e2d842c2061cbaf6450c71da0077263be3bab165454d5c8a3e1ae4d3c6d2915f02fd27da63ff01f05e127b1221acd40705273f5d29303901e60514e852992f4 languageName: node linkType: hard @@ -1784,12 +1755,12 @@ __metadata: linkType: hard "@humanfs/node@npm:^0.16.6": - version: 0.16.7 - resolution: "@humanfs/node@npm:0.16.7" + version: 0.16.6 + resolution: "@humanfs/node@npm:0.16.6" dependencies: "@humanfs/core": "npm:^0.19.1" - "@humanwhocodes/retry": "npm:^0.4.0" - checksum: 10/b3633d3dce898592cac515ba5e6693c78e6be92863541d3eaf2c009b10f52b2fa62ff6e6e06f240f2447ddbe7b5f1890bc34e9308470675c876eee207553a08d + "@humanwhocodes/retry": "npm:^0.3.0" + checksum: 10/6d43c6727463772d05610aa05c83dab2bfbe78291022ee7a92cb50999910b8c720c76cc312822e2dea2b497aa1b3fef5fe9f68803fc45c9d4ed105874a65e339 languageName: node linkType: hard @@ -1800,7 +1771,14 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/retry@npm:^0.4.0, @humanwhocodes/retry@npm:^0.4.2": +"@humanwhocodes/retry@npm:^0.3.0": + version: 0.3.1 + resolution: "@humanwhocodes/retry@npm:0.3.1" + checksum: 10/eb457f699529de7f07649679ec9e0353055eebe443c2efe71c6dd950258892475a038e13c6a8c5e13ed1fb538cdd0a8794faa96b24b6ffc4c87fb1fc9f70ad7f + languageName: node + linkType: hard + +"@humanwhocodes/retry@npm:^0.4.2": version: 0.4.3 resolution: "@humanwhocodes/retry@npm:0.4.3" checksum: 10/0b32cfd362bea7a30fbf80bb38dcaf77fee9c2cae477ee80b460871d03590110ac9c77d654f04ec5beaf71b6f6a89851bdf6c1e34ccdf2f686bd86fcd97d9e61 @@ -1943,13 +1921,6 @@ __metadata: languageName: node linkType: hard -"@jest/diff-sequences@npm:30.0.1": - version: 30.0.1 - resolution: "@jest/diff-sequences@npm:30.0.1" - checksum: 10/0ddb7c7ba92d6057a2ee51a9cfc2155b77cca707fe959167466ea02dcb0687018cc3c22b9622f25f3a417d6ad370e2d4dcfedf9f1410dc9c02954a7484423cc7 - languageName: node - linkType: hard - "@jest/environment@npm:^29.7.0": version: 29.7.0 resolution: "@jest/environment@npm:29.7.0" @@ -1962,15 +1933,6 @@ __metadata: languageName: node linkType: hard -"@jest/expect-utils@npm:30.2.0": - version: 30.2.0 - resolution: "@jest/expect-utils@npm:30.2.0" - dependencies: - "@jest/get-type": "npm:30.1.0" - checksum: 10/f2442f1bceb3411240d0f16fd0074377211b4373d3b8b2dc28929e861b6527a6deb403a362c25afa511d933cda4dfbdc98d4a08eeb51ee4968f7cb0299562349 - languageName: node - linkType: hard - "@jest/expect-utils@npm:^29.7.0": version: 29.7.0 resolution: "@jest/expect-utils@npm:29.7.0" @@ -2004,13 +1966,6 @@ __metadata: languageName: node linkType: hard -"@jest/get-type@npm:30.1.0": - version: 30.1.0 - resolution: "@jest/get-type@npm:30.1.0" - checksum: 10/e2a95fbb49ce2d15547db8af5602626caf9b05f62a5e583b4a2de9bd93a2bfe7175f9bbb2b8a5c3909ce261d467b6991d7265bb1d547cb60e7e97f571f361a70 - languageName: node - linkType: hard - "@jest/globals@npm:^29.7.0": version: 29.7.0 resolution: "@jest/globals@npm:29.7.0" @@ -2023,16 +1978,6 @@ __metadata: languageName: node linkType: hard -"@jest/pattern@npm:30.0.1": - version: 30.0.1 - resolution: "@jest/pattern@npm:30.0.1" - dependencies: - "@types/node": "npm:*" - jest-regex-util: "npm:30.0.1" - checksum: 10/afd03b4d3eadc9c9970cf924955dee47984a7e767901fe6fa463b17b246f0ddeec07b3e82c09715c54bde3c8abb92074160c0d79967bd23778724f184e7f5b7b - languageName: node - linkType: hard - "@jest/reporters@npm:^29.7.0": version: 29.7.0 resolution: "@jest/reporters@npm:29.7.0" @@ -2070,15 +2015,6 @@ __metadata: languageName: node linkType: hard -"@jest/schemas@npm:30.0.5": - version: 30.0.5 - resolution: "@jest/schemas@npm:30.0.5" - dependencies: - "@sinclair/typebox": "npm:^0.34.0" - checksum: 10/40df4db55d4aeed09d1c7e19caf23788309cea34490a1c5d584c913494195e698b9967e996afc27226cac6d76e7512fe73ae6b9584480695c60dd18a5459cdba - languageName: node - linkType: hard - "@jest/schemas@npm:^29.6.3": version: 29.6.3 resolution: "@jest/schemas@npm:29.6.3" @@ -2146,21 +2082,6 @@ __metadata: languageName: node linkType: hard -"@jest/types@npm:30.2.0": - version: 30.2.0 - resolution: "@jest/types@npm:30.2.0" - dependencies: - "@jest/pattern": "npm:30.0.1" - "@jest/schemas": "npm:30.0.5" - "@types/istanbul-lib-coverage": "npm:^2.0.6" - "@types/istanbul-reports": "npm:^3.0.4" - "@types/node": "npm:*" - "@types/yargs": "npm:^17.0.33" - chalk: "npm:^4.1.2" - checksum: 10/f50fcaea56f873a51d19254ab16762f2ea8ca88e3e08da2e496af5da2b67c322915a4fcd0153803cc05063ffe87ebef2ab4330e0a1b06ab984a26c916cbfc26b - languageName: node - linkType: hard - "@jest/types@npm:^26.6.2": version: 26.6.2 resolution: "@jest/types@npm:26.6.2" @@ -2215,10 +2136,10 @@ __metadata: languageName: node linkType: hard -"@jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.5.0, @jridgewell/sourcemap-codec@npm:^1.5.5": - version: 1.5.5 - resolution: "@jridgewell/sourcemap-codec@npm:1.5.5" - checksum: 10/5d9d207b462c11e322d71911e55e21a4e2772f71ffe8d6f1221b8eb5ae6774458c1d242f897fb0814e8714ca9a6b498abfa74dfe4f434493342902b1a48b33a5 +"@jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.5.0": + version: 1.5.0 + resolution: "@jridgewell/sourcemap-codec@npm:1.5.0" + checksum: 10/4ed6123217569a1484419ac53f6ea0d9f3b57e5b57ab30d7c267bdb27792a27eb0e4b08e84a2680aa55cc2f2b411ffd6ec3db01c44fdc6dc43aca4b55f8374fd languageName: node linkType: hard @@ -2258,9 +2179,9 @@ __metadata: linkType: hard "@json-schema-tools/meta-schema@npm:^1.7.5": - version: 1.8.0 - resolution: "@json-schema-tools/meta-schema@npm:1.8.0" - checksum: 10/c6c9c3e6504299126c65bcf4bb7e6d28bfe5ab46d3c4fdc9b856204581edb0f088b15e790759e6357e91468d8a5213192fbe9b027a4811b988c19bbbb8d8f617 + version: 1.7.5 + resolution: "@json-schema-tools/meta-schema@npm:1.7.5" + checksum: 10/707dc3a285c26c37d00f418e9d0ef8a2ad1c23d4936ad5aab0ce94c9ae36a7a6125c4ca5048513af64b7e6e527b5472a1701d1f709c379acdd7ad12f6409d2cd languageName: node linkType: hard @@ -2275,43 +2196,44 @@ __metadata: linkType: hard "@json-schema-tools/traverse@npm:^1.10.4": - version: 1.11.0 - resolution: "@json-schema-tools/traverse@npm:1.11.0" - checksum: 10/1dd81baf29fd6de164f30376d2b9ca9e68778255a872dd78f81cf6f610127e9f4eba2507244c35189078839ed4aa453a876c169681eb9028954c0148355c2fcb + version: 1.10.4 + resolution: "@json-schema-tools/traverse@npm:1.10.4" + checksum: 10/0027bc90df01c5eeee0833e722b7320b53be8b5ce3f4e0e4a6e45713a38e6f88f21aba31e3dd973093ef75cd21a40c07fe8f112da8f49a7919b1c0e44c904d20 languageName: node linkType: hard -"@lavamoat/aa@npm:^4.3.6": - version: 4.3.6 - resolution: "@lavamoat/aa@npm:4.3.6" +"@lavamoat/aa@npm:^4.3.0": + version: 4.3.0 + resolution: "@lavamoat/aa@npm:4.3.0" dependencies: - resolve: "npm:1.22.10" + resolve: "npm:1.22.8" bin: lavamoat-ls: src/cli.js - checksum: 10/6c6636962527054e5c25f801721c49c6b03c6173e86a7c048a8061f18f9c2c4628413cdfa1c928c8e028ac7128891d54f545fa61751c93e4689891393f0be3ec + checksum: 10/c6c24ea88194ad06a83cc2a9e0b6918ee41ab40abcc5c889e1a33f214e48eb160dd0c4cea7b0e299f86d472810ef80e7caf0b2600499222b108690516d9f8123 languageName: node linkType: hard "@lavamoat/allow-scripts@npm:^3.0.4": - version: 3.4.3 - resolution: "@lavamoat/allow-scripts@npm:3.4.3" + version: 3.2.0 + resolution: "@lavamoat/allow-scripts@npm:3.2.0" dependencies: - "@lavamoat/aa": "npm:^4.3.6" - "@npmcli/run-script": "npm:10.0.3" + "@lavamoat/aa": "npm:^4.3.0" + "@npmcli/run-script": "npm:8.1.0" bin-links: "npm:4.0.4" npm-normalize-package-bin: "npm:3.0.1" - type-fest: "npm:4.41.0" yargs: "npm:17.7.2" + peerDependencies: + "@lavamoat/preinstall-always-fail": "*" bin: allow-scripts: src/cli.js - checksum: 10/75a6156efa5f76d97ddfd21cdeaf68f256fc5b1adc9be2bfa0691abd38c0c4769a511eda20d5a4700b05629423a26e02b3cbb84c3407c26d5287a19cf4630967 + checksum: 10/21afb11ce25c0b2c9763bfb8f1127bb89f304ed83f64e00955c4d3007216a0ee553b777359e9ded874c61b3d7fa8d19ff8a35881cd3816985adab4d6b58bcb07 languageName: node linkType: hard "@lavamoat/preinstall-always-fail@npm:^2.1.0": - version: 2.1.1 - resolution: "@lavamoat/preinstall-always-fail@npm:2.1.1" - checksum: 10/679cfd6b981326bf6f7cce63af4062b1e1e2ffaefd4db316e918ec41ac089c835aafd7f2bb5193cd25538e084d3df1375cd2ac5a52c3e7777aedeb2ee507dd29 + version: 2.1.0 + resolution: "@lavamoat/preinstall-always-fail@npm:2.1.0" + checksum: 10/385c3fac828b9edff2d8b5825bd29ea475206046984cdb3217518ad655f145ff37046414041534960d92cbe0759f0dc675f7c7dcf39a95003ae715a834fbd750 languageName: node linkType: hard @@ -2759,8 +2681,8 @@ __metadata: linkType: hard "@metamask/auto-changelog@npm:^4.0.0": - version: 4.1.0 - resolution: "@metamask/auto-changelog@npm:4.1.0" + version: 4.0.0 + resolution: "@metamask/auto-changelog@npm:4.0.0" dependencies: diff: "npm:^5.0.0" execa: "npm:^5.1.1" @@ -2770,7 +2692,7 @@ __metadata: prettier: ">=3.0.0" bin: auto-changelog: dist/cli.js - checksum: 10/fe31a9eb364939c83bc5098482b761ca93593081680c4cba17b221150b4d32636cb25fd708e3692c198feddc95d8bcf524e19fa93567fb5aa30b03ea93249250 + checksum: 10/4968d316411e5f4820092391f79078839f49e0e26ecd0c48266b5a1e0e32614b75dad5f36b76e632a7a22a2f2eeeb762a693ae390b0373bff29081ff2a7eefda languageName: node linkType: hard @@ -3479,20 +3401,17 @@ __metadata: linkType: soft "@metamask/eth-hd-keyring@npm:^13.0.0": - version: 13.1.0 - resolution: "@metamask/eth-hd-keyring@npm:13.1.0" + version: 13.0.0 + resolution: "@metamask/eth-hd-keyring@npm:13.0.0" dependencies: - "@ethereumjs/tx": "npm:^5.4.0" "@ethereumjs/util": "npm:^9.1.0" "@metamask/eth-sig-util": "npm:^8.2.0" "@metamask/key-tree": "npm:^10.0.2" - "@metamask/keyring-api": "npm:^21.3.0" "@metamask/keyring-utils": "npm:^3.1.0" "@metamask/scure-bip39": "npm:^2.1.1" - "@metamask/superstruct": "npm:^3.1.0" "@metamask/utils": "npm:^11.1.0" ethereum-cryptography: "npm:^2.1.2" - checksum: 10/7d67c29c6387ffe871995e67e4802b9a6f6eb2f14b556e43690509b342ef66b72765477b27e4b669fe8a00606e219e00991f94da3a74fcedcf339ab765215ae6 + checksum: 10/fe955a4e0331090df8110dbd8f46ea6286c2ad20e6677ecf535361ea9d0008194b2043eddd692cd7ceac2e033a54e4e340caa7d302bd5211826cb252b526f6bc languageName: node linkType: hard @@ -3943,7 +3862,7 @@ __metadata: languageName: node linkType: hard -"@metamask/keyring-api@npm:^21.3.0, @metamask/keyring-api@npm:^21.4.0, @metamask/keyring-api@npm:^21.5.0": +"@metamask/keyring-api@npm:^21.4.0, @metamask/keyring-api@npm:^21.5.0": version: 21.5.0 resolution: "@metamask/keyring-api@npm:21.5.0" dependencies: @@ -4369,12 +4288,14 @@ __metadata: linkType: soft "@metamask/nonce-tracker@npm:^6.0.0": - version: 6.1.0 - resolution: "@metamask/nonce-tracker@npm:6.1.0" + version: 6.0.0 + resolution: "@metamask/nonce-tracker@npm:6.0.0" dependencies: "@ethersproject/providers": "npm:^5.7.2" - async-mutex: "npm:^0.5.0" - checksum: 10/a20cf7084348ef7bdcd9e57e873ca34bf8e04ee43a2ab08634a3ad47fddb632d0e170c1dff03b4ca5bac34a24c35c542fcec509f3c23ce483834082f41b50e4a + async-mutex: "npm:^0.3.1" + peerDependencies: + "@metamask/eth-block-tracker": ">=9" + checksum: 10/e62edd38eeaba6d917bc3aed38017294f2bfdb59120a9fb4f093fe96a46d8d9214453a802fe782faaf4a007f4cd5f393607c70a2ff8479ecd7ef18827cad067a languageName: node linkType: hard @@ -4753,9 +4674,9 @@ __metadata: linkType: hard "@metamask/safe-event-emitter@npm:^3.0.0, @metamask/safe-event-emitter@npm:^3.1.1": - version: 3.1.2 - resolution: "@metamask/safe-event-emitter@npm:3.1.2" - checksum: 10/8ef7579f9317eb5c94ecf3e6abb8d13b119af274b678805eac76abe4c0667bfdf539f385e552bb973e96333b71b77aa7c787cb3fce9cd5fb4b00f1dbbabf880d + version: 3.1.1 + resolution: "@metamask/safe-event-emitter@npm:3.1.1" + checksum: 10/e24db4d7c20764bfc5b025065f92518c805f0ffb1da4820078b8cff7dcae964c0f354cf053fcb7ac659de015d5ffdf21aae5e8d44e191ee8faa9066855f22653 languageName: node linkType: hard @@ -4910,7 +4831,7 @@ __metadata: languageName: unknown linkType: soft -"@metamask/slip44@npm:^4.3.0, @metamask/slip44@npm:^4.4.0": +"@metamask/slip44@npm:^4.3.0": version: 4.4.0 resolution: "@metamask/slip44@npm:4.4.0" checksum: 10/296ac7c578bd35792c7e3942a9a0b7d9d7af76cf98358b97403c1ed483faa3c2fe6c71b1c3f8c7719fbfcf9fc73e5fa8707c89ac277ee9ce6c8bc4c694b2059d @@ -4973,19 +4894,19 @@ __metadata: linkType: hard "@metamask/snaps-rpc-methods@npm:^14.1.1": - version: 14.3.0 - resolution: "@metamask/snaps-rpc-methods@npm:14.3.0" + version: 14.2.0 + resolution: "@metamask/snaps-rpc-methods@npm:14.2.0" dependencies: "@metamask/key-tree": "npm:^10.1.1" "@metamask/permission-controller": "npm:^12.2.0" "@metamask/rpc-errors": "npm:^7.0.3" "@metamask/snaps-sdk": "npm:^10.4.0" - "@metamask/snaps-utils": "npm:^12.1.0" + "@metamask/snaps-utils": "npm:^12.0.0" "@metamask/superstruct": "npm:^3.2.1" "@metamask/utils": "npm:^11.9.0" "@noble/hashes": "npm:^1.7.1" async-mutex: "npm:^0.5.0" - checksum: 10/feddc0820e9a18a5ebed5ebdd4ee771e68990427634b7a5719bbaf1955fb2deba8531d353b7db664b394b2b3a9e05baf734af6048b8ea009d2379fbce09f9889 + checksum: 10/36264d40ebcca8b7d40d766cfc5dffd4e2afa61ff3bc11ee52af3669043e4428c9845565e78315fb7cb0981efd5d26681244fb292d94c42b059f6a76fc527a26 languageName: node linkType: hard @@ -5034,9 +4955,9 @@ __metadata: languageName: node linkType: hard -"@metamask/snaps-utils@npm:^12.1.0": - version: 12.1.0 - resolution: "@metamask/snaps-utils@npm:12.1.0" +"@metamask/snaps-utils@npm:^12.0.0": + version: 12.0.1 + resolution: "@metamask/snaps-utils@npm:12.0.1" dependencies: "@babel/core": "npm:^7.23.2" "@babel/types": "npm:^7.23.0" @@ -5044,7 +4965,7 @@ __metadata: "@metamask/messenger": "npm:^0.3.0" "@metamask/permission-controller": "npm:^12.2.0" "@metamask/rpc-errors": "npm:^7.0.3" - "@metamask/slip44": "npm:^4.4.0" + "@metamask/slip44": "npm:^4.3.0" "@metamask/snaps-registry": "npm:^4.0.0" "@metamask/snaps-sdk": "npm:^10.4.0" "@metamask/superstruct": "npm:^3.2.1" @@ -5054,21 +4975,21 @@ __metadata: cron-parser: "npm:^4.5.0" fast-deep-equal: "npm:^3.1.3" fast-json-stable-stringify: "npm:^2.1.0" - fast-xml-parser: "npm:^5.3.4" + fast-xml-parser: "npm:^4.4.1" luxon: "npm:^3.5.0" marked: "npm:^12.0.1" rfdc: "npm:^1.3.0" semver: "npm:^7.5.4" ses: "npm:^1.14.0" validate-npm-package-name: "npm:^5.0.0" - checksum: 10/f81a66a0f0d7710f18cfcebceacf2ec7ca9c468a4839b8cc15652cc046a15455c55a3fff846061ff7d1ecd4368c182566db4f73b3c8b4ed4b2a09adc57e2e711 + checksum: 10/e4f4ee17b674025c3686ed3e0269643db46c737dab418ce1172a43aa227d66a58f857d2956e8956ea225be1bd23d1c1e101eb22e7bd09ae8a34ddafafd5b8a80 languageName: node linkType: hard "@metamask/stake-sdk@npm:^3.2.1": - version: 3.4.0 - resolution: "@metamask/stake-sdk@npm:3.4.0" - checksum: 10/32241bf7a904b0b12568467482b28f550eae1a4d97ffb7487a1cd1614d43f3b584d78dc96df72ece024a0402d3591c19d79f370a3955ea4b11369f000c309a08 + version: 3.2.1 + resolution: "@metamask/stake-sdk@npm:3.2.1" + checksum: 10/7404ac54e2bd426158b0ae92a2f4c420ef551d18d8a14293c5760b1da1c48cab88df9a7dcce7133f91bbe7899f6c2016642f0e41e170353b6b9ae4c6423d2ad5 languageName: node linkType: hard @@ -5275,8 +5196,8 @@ __metadata: linkType: soft "@metamask/utils@npm:^11.0.1, @metamask/utils@npm:^11.1.0, @metamask/utils@npm:^11.4.0, @metamask/utils@npm:^11.4.2, @metamask/utils@npm:^11.8.1, @metamask/utils@npm:^11.9.0": - version: 11.10.0 - resolution: "@metamask/utils@npm:11.10.0" + version: 11.9.0 + resolution: "@metamask/utils@npm:11.9.0" dependencies: "@ethereumjs/tx": "npm:^4.2.0" "@metamask/superstruct": "npm:^3.1.0" @@ -5289,7 +5210,7 @@ __metadata: pony-cause: "npm:^2.1.10" semver: "npm:^7.5.4" uuid: "npm:^9.0.1" - checksum: 10/691a268af66593b60e9807a069127993cea3cdc941f99d5d7ca4664868754f08945821f1787b2f3e99e4497df63ceb0af37a2419ad494da29a1fddffe94f5797 + checksum: 10/f8f5e99ba6c6de0395ed4e0acc82ee9c0dca26991ea6a8f10b3896e72745790966a8eded8c42be905d9f01fa99c1fd29a7f68541e2ef9854fc14984a0b514ad3 languageName: node linkType: hard @@ -5310,17 +5231,6 @@ __metadata: languageName: node linkType: hard -"@napi-rs/wasm-runtime@npm:^0.2.11": - version: 0.2.12 - resolution: "@napi-rs/wasm-runtime@npm:0.2.12" - dependencies: - "@emnapi/core": "npm:^1.4.3" - "@emnapi/runtime": "npm:^1.4.3" - "@tybys/wasm-util": "npm:^0.10.0" - checksum: 10/5fd518182427980c28bc724adf06c5f32f9a8915763ef560b5f7d73607d30cd15ac86d0cbd2eb80d4cfab23fc80d0876d89ca36a9daadcb864bc00917c94187c - languageName: node - linkType: hard - "@noble/ciphers@npm:^1.2.1, @noble/ciphers@npm:^1.3.0": version: 1.3.0 resolution: "@noble/ciphers@npm:1.3.0" @@ -5417,86 +5327,87 @@ __metadata: languageName: node linkType: hard -"@npmcli/agent@npm:^4.0.0": - version: 4.0.0 - resolution: "@npmcli/agent@npm:4.0.0" +"@npmcli/agent@npm:^2.0.0": + version: 2.2.2 + resolution: "@npmcli/agent@npm:2.2.2" dependencies: agent-base: "npm:^7.1.0" http-proxy-agent: "npm:^7.0.0" https-proxy-agent: "npm:^7.0.1" - lru-cache: "npm:^11.2.1" + lru-cache: "npm:^10.0.1" socks-proxy-agent: "npm:^8.0.3" - checksum: 10/1a81573becc60515031accc696e6405e9b894e65c12b98ef4aeee03b5617c41948633159dbf6caf5dde5b47367eeb749bdc7b7dfb21960930a9060a935c6f636 + checksum: 10/96fc0036b101bae5032dc2a4cd832efb815ce9b33f9ee2f29909ee49d96a0026b3565f73c507a69eb8603f5cb32e0ae45a70cab1e2655990a4e06ae99f7f572a languageName: node linkType: hard -"@npmcli/fs@npm:^5.0.0": - version: 5.0.0 - resolution: "@npmcli/fs@npm:5.0.0" +"@npmcli/fs@npm:^3.1.0": + version: 3.1.1 + resolution: "@npmcli/fs@npm:3.1.1" dependencies: semver: "npm:^7.3.5" - checksum: 10/4935c7719d17830d0f9fa46c50be17b2a3c945cec61760f6d0909bce47677c42e1810ca673305890f9e84f008ec4d8e841182f371e42100a8159d15f22249208 + checksum: 10/1e0e04087049b24b38bc0b30d87a9388ee3ca1d3fdfc347c2f77d84fcfe6a51f250bc57ba2c1f614d7e4285c6c62bf8c769bc19aa0949ea39e5b043ee023b0bd languageName: node linkType: hard -"@npmcli/git@npm:^7.0.0": - version: 7.0.1 - resolution: "@npmcli/git@npm:7.0.1" - dependencies: - "@npmcli/promise-spawn": "npm:^9.0.0" - ini: "npm:^6.0.0" - lru-cache: "npm:^11.2.1" - npm-pick-manifest: "npm:^11.0.1" - proc-log: "npm:^6.0.0" +"@npmcli/git@npm:^5.0.0": + version: 5.0.8 + resolution: "@npmcli/git@npm:5.0.8" + dependencies: + "@npmcli/promise-spawn": "npm:^7.0.0" + ini: "npm:^4.1.3" + lru-cache: "npm:^10.0.1" + npm-pick-manifest: "npm:^9.0.0" + proc-log: "npm:^4.0.0" + promise-inflight: "npm:^1.0.1" promise-retry: "npm:^2.0.1" semver: "npm:^7.3.5" - which: "npm:^6.0.0" - checksum: 10/dc2c7558fa034be6123b6a049091fd4fcdf79bf497ab8ff3213ac99e0c7a4f968e3cf747322af5d1d70e41ed21b8189f8e12d7b3f1a6143793d056dd8c8b50c5 + which: "npm:^4.0.0" + checksum: 10/e6f94175fb9dde13d84849b29b32ffb4c4df968822cc85df2aebfca13bf8ca76f33b1d281911f5bcddc95bccba2f9e795669c736a38de4d9c76efb5047ffb4fb languageName: node linkType: hard -"@npmcli/node-gyp@npm:^5.0.0": - version: 5.0.0 - resolution: "@npmcli/node-gyp@npm:5.0.0" - checksum: 10/31488b0a0a6293efc4ab1bd87ba483d1000f8720c5f068d4c28cf49e39a045cd122960ba2a166a376fc9767f457f6124d99ec673ebcb19015cd29835bb038e46 +"@npmcli/node-gyp@npm:^3.0.0": + version: 3.0.0 + resolution: "@npmcli/node-gyp@npm:3.0.0" + checksum: 10/dd9fed3e80df8fbb20443f28651a8ed7235f2c15286ecc010e2d3cd392c85912e59ef29218c0b02f098defb4cbc8cdf045aab1d32d5cef6ace289913196ed5df languageName: node linkType: hard -"@npmcli/package-json@npm:^7.0.0": - version: 7.0.5 - resolution: "@npmcli/package-json@npm:7.0.5" - dependencies: - "@npmcli/git": "npm:^7.0.0" - glob: "npm:^13.0.0" - hosted-git-info: "npm:^9.0.0" - json-parse-even-better-errors: "npm:^5.0.0" - proc-log: "npm:^6.0.0" +"@npmcli/package-json@npm:^5.0.0": + version: 5.2.0 + resolution: "@npmcli/package-json@npm:5.2.0" + dependencies: + "@npmcli/git": "npm:^5.0.0" + glob: "npm:^10.2.2" + hosted-git-info: "npm:^7.0.0" + json-parse-even-better-errors: "npm:^3.0.0" + normalize-package-data: "npm:^6.0.0" + proc-log: "npm:^4.0.0" semver: "npm:^7.5.3" - spdx-expression-parse: "npm:^4.0.0" - checksum: 10/d07a5bb98f59675afa51c0a8ba1f32d7a459da36c14e2ad2b2dd6e312c99684fd3a76f5cc497376af588fc98a2be7d05651e5a58c8a282f12dcfed44c44338fa + checksum: 10/c3d2218877bfc005bca3b7a11f53825bf16a68811b8e8ed0c9b219cceb8e8e646d70efab8c5d6decbd8007f286076468b3f456dab4d41d648aff73a5f3a6fce2 languageName: node linkType: hard -"@npmcli/promise-spawn@npm:^9.0.0": - version: 9.0.1 - resolution: "@npmcli/promise-spawn@npm:9.0.1" +"@npmcli/promise-spawn@npm:^7.0.0": + version: 7.0.2 + resolution: "@npmcli/promise-spawn@npm:7.0.2" dependencies: - which: "npm:^6.0.0" - checksum: 10/93f539f12813dacf0084c5f444982d44c67f2016f417f2e937afb81c3fd228cf330abeabdffc95ca3e8315a4a9b9e732be7e7870c926d7dfc6c458549fcd11ea + which: "npm:^4.0.0" + checksum: 10/94cbbbeeb20342026c3b68fc8eb09e1600b7645d4e509f2588ef5ea7cff977eb01e628cc8e014595d04a6af4b4bc5c467c950a8135920f39f7c7b57fba43f4e9 languageName: node linkType: hard -"@npmcli/run-script@npm:10.0.3": - version: 10.0.3 - resolution: "@npmcli/run-script@npm:10.0.3" +"@npmcli/run-script@npm:8.1.0": + version: 8.1.0 + resolution: "@npmcli/run-script@npm:8.1.0" dependencies: - "@npmcli/node-gyp": "npm:^5.0.0" - "@npmcli/package-json": "npm:^7.0.0" - "@npmcli/promise-spawn": "npm:^9.0.0" - node-gyp: "npm:^12.1.0" - proc-log: "npm:^6.0.0" - which: "npm:^6.0.0" - checksum: 10/3b2b6b02a40c7470a900e8d77d23e2239608c08e919d6ddee7849fc7093be0999d9eb2c9dec871988e80165a64f9d8c55430f0a699690e555ebd3e81bf1dbd35 + "@npmcli/node-gyp": "npm:^3.0.0" + "@npmcli/package-json": "npm:^5.0.0" + "@npmcli/promise-spawn": "npm:^7.0.0" + node-gyp: "npm:^10.0.0" + proc-log: "npm:^4.0.0" + which: "npm:^4.0.0" + checksum: 10/256bd580f82b98db93e54065bf9bcc94946be4f2d668a062cf756cb8ea091f58ef7154b3d2450d79738081a150f25cc48f6075351911e672f24ffd34350f02f2 languageName: node linkType: hard @@ -5508,28 +5419,20 @@ __metadata: linkType: hard "@open-rpc/schema-utils-js@npm:^2.0.5": - version: 2.1.2 - resolution: "@open-rpc/schema-utils-js@npm:2.1.2" + version: 2.0.5 + resolution: "@open-rpc/schema-utils-js@npm:2.0.5" dependencies: "@json-schema-tools/dereferencer": "npm:^1.6.3" "@json-schema-tools/meta-schema": "npm:^1.7.5" "@json-schema-tools/reference-resolver": "npm:^1.2.6" "@open-rpc/meta-schema": "npm:^1.14.9" - "@open-rpc/specification-extension-spec": "npm:^1.0.2" ajv: "npm:^6.10.0" detect-node: "npm:^2.0.4" fast-safe-stringify: "npm:^2.0.7" fs-extra: "npm:^10.1.0" is-url: "npm:^1.2.4" isomorphic-fetch: "npm:^3.0.0" - checksum: 10/0f38a403c696ee74319503cfba9656cdb2ff6dbd84dfba3c6ce5c3d010dfd72bc396bfb6dacf39de01d523ee7e3b0d5637657a48e5f2c7e74ae33b9354b2c4c1 - languageName: node - linkType: hard - -"@open-rpc/specification-extension-spec@npm:^1.0.2": - version: 1.0.2 - resolution: "@open-rpc/specification-extension-spec@npm:1.0.2" - checksum: 10/04111d8ce84deb45358c504b425f8d3e5c0b8991c739708b6b2662de665002da541fc7b39065d2394a9509866f580c3a5aaedc56b42c0d679fe6054eda034b9b + checksum: 10/9e10215606e9a00a47b082c9cfd70d05bf0d38de6cf1c147246c545c6997375d94cd3caafe919b71178df58b5facadfd0dcc8b6857bf5e79c40e5e33683dd3d5 languageName: node linkType: hard @@ -5540,10 +5443,10 @@ __metadata: languageName: node linkType: hard -"@pkgr/core@npm:^0.2.9": - version: 0.2.9 - resolution: "@pkgr/core@npm:0.2.9" - checksum: 10/bb2fb86977d63f836f8f5b09015d74e6af6488f7a411dcd2bfdca79d76b5a681a9112f41c45bdf88a9069f049718efc6f3900d7f1de66a2ec966068308ae517f +"@pkgr/core@npm:^0.1.0": + version: 0.1.1 + resolution: "@pkgr/core@npm:0.1.1" + checksum: 10/6f25fd2e3008f259c77207ac9915b02f1628420403b2630c92a07ff963129238c9262afc9e84344c7a23b5cc1f3965e2cd17e3798219f5fd78a63d144d3cceba languageName: node linkType: hard @@ -5628,9 +5531,9 @@ __metadata: linkType: hard "@scure/base@npm:~1.1.3, @scure/base@npm:~1.1.6": - version: 1.1.9 - resolution: "@scure/base@npm:1.1.9" - checksum: 10/f0ab7f687bbcdee2a01377fe3cd808bf63977999672751295b6a92625d5322f4754a96d40f6bd579bc367aad48ecf8a4e6d0390e70296e6ded1076f52adb16bb + version: 1.1.7 + resolution: "@scure/base@npm:1.1.7" + checksum: 10/fc50ffaab36cb46ff9fa4dc5052a06089ab6a6707f63d596bb34aaaec76173c9a564ac312a0b981b5e7a5349d60097b8878673c75d6cbfc4da7012b63a82099b languageName: node linkType: hard @@ -5656,23 +5559,16 @@ __metadata: linkType: hard "@sentry/core@npm:^9.10.0, @sentry/core@npm:^9.22.0": - version: 9.47.1 - resolution: "@sentry/core@npm:9.47.1" - checksum: 10/62cc2a0f45d89e3b78f083fe365007e59aed54e20b55ae5b45931cfa8e4d79d457c0c57450c6c7f92cec71fa682cd9cb3b64414fa86273f08cf3d8d06bd99c24 + version: 9.23.0 + resolution: "@sentry/core@npm:9.23.0" + checksum: 10/4ee771098d4ce4f4d2f7bd62cacb41ee2993780f4cab0eea600e73de3a3803cb953ac47ac015c23bcd7a9919e2220fd6cdc5a9a22a3663440296336d8df959b7 languageName: node linkType: hard "@sinclair/typebox@npm:^0.27.8": - version: 0.27.10 - resolution: "@sinclair/typebox@npm:0.27.10" - checksum: 10/1498c5ef1375787e6272528615d5c262afb60873191d2441316359817b1c411917063c8be102ef15b0b5c62243a9daa7aefc8426f20eb406b67038b3eaa0695a - languageName: node - linkType: hard - -"@sinclair/typebox@npm:^0.34.0": - version: 0.34.48 - resolution: "@sinclair/typebox@npm:0.34.48" - checksum: 10/186eebb338255db7cfd77c2f94be0ad91816c7b5ee994c3adb95e0474ae98b769574c2b6b1f26a81613d7148ed20b11e02528f4263d8d95e3ca8dcf8faaf5306 + version: 0.27.8 + resolution: "@sinclair/typebox@npm:0.27.8" + checksum: 10/297f95ff77c82c54de8c9907f186076e715ff2621c5222ba50b8d40a170661c0c5242c763cba2a4791f0f91cb1d8ffa53ea1d7294570cf8cd4694c0e383e484d languageName: node linkType: hard @@ -5695,88 +5591,78 @@ __metadata: linkType: hard "@solana/addresses@npm:^2.0.0": - version: 2.3.0 - resolution: "@solana/addresses@npm:2.3.0" + version: 2.0.0 + resolution: "@solana/addresses@npm:2.0.0" dependencies: - "@solana/assertions": "npm:2.3.0" - "@solana/codecs-core": "npm:2.3.0" - "@solana/codecs-strings": "npm:2.3.0" - "@solana/errors": "npm:2.3.0" - "@solana/nominal-types": "npm:2.3.0" + "@solana/assertions": "npm:2.0.0" + "@solana/codecs-core": "npm:2.0.0" + "@solana/codecs-strings": "npm:2.0.0" + "@solana/errors": "npm:2.0.0" peerDependencies: - typescript: ">=5.3.3" - checksum: 10/11ee6774f938dd2fe5174375b02c4e52063173ce80a895dd35beb84635dcf3e2ba2e3fe7c74a614b2322da10906abceab758c91a13415a9cda53faf91a8ea722 + typescript: ">=5" + checksum: 10/f99d09c72046c73858aa8b7bc323e634a60b1023a4d280036bc94489e431075c7f29d2889e8787e33a04cfdecbe77cd8ca26c31ded73f735dc98e49c3151cc17 languageName: node linkType: hard -"@solana/assertions@npm:2.3.0": - version: 2.3.0 - resolution: "@solana/assertions@npm:2.3.0" +"@solana/assertions@npm:2.0.0": + version: 2.0.0 + resolution: "@solana/assertions@npm:2.0.0" dependencies: - "@solana/errors": "npm:2.3.0" + "@solana/errors": "npm:2.0.0" peerDependencies: - typescript: ">=5.3.3" - checksum: 10/3b430f01d5991569059fea3e6679a4548a624ff5da6db0c2eb2eba757a9ff774c9d90941a0a2335148599aaef8e8fc004a9c5996eb3627b25dca108b05591d02 + typescript: ">=5" + checksum: 10/c1af37ae1bd79b1657395d9315ac261dabc9908a64af6ed80e3b7e5140909cd8c8c757f0c41fff084e26fbb4d32f091c89c092a8c1ed5e6f4565dfe7426c0979 languageName: node linkType: hard -"@solana/codecs-core@npm:2.3.0": - version: 2.3.0 - resolution: "@solana/codecs-core@npm:2.3.0" +"@solana/codecs-core@npm:2.0.0": + version: 2.0.0 + resolution: "@solana/codecs-core@npm:2.0.0" dependencies: - "@solana/errors": "npm:2.3.0" + "@solana/errors": "npm:2.0.0" peerDependencies: - typescript: ">=5.3.3" - checksum: 10/d9bba1eaa3ee38fef04e1cbfa43defeea16729a1cf1628a71cb72340558a3f2296279899680e1dda4b1756ab2b280b5f1502330c21c35e167e554f3d0c9d193d + typescript: ">=5" + checksum: 10/e58a72e67bee3e5da60201eecda345c604b49138d5298e39b8e7d4d57a4dee47be3b0ecc8fc3429a2a60a42c952eaf860d43d3df1eb2b1d857e35368eca9c820 languageName: node linkType: hard -"@solana/codecs-numbers@npm:2.3.0": - version: 2.3.0 - resolution: "@solana/codecs-numbers@npm:2.3.0" +"@solana/codecs-numbers@npm:2.0.0": + version: 2.0.0 + resolution: "@solana/codecs-numbers@npm:2.0.0" dependencies: - "@solana/codecs-core": "npm:2.3.0" - "@solana/errors": "npm:2.3.0" + "@solana/codecs-core": "npm:2.0.0" + "@solana/errors": "npm:2.0.0" peerDependencies: - typescript: ">=5.3.3" - checksum: 10/e661338b5eb04268a104ff2189b5d001bd2f99e1a3726deaa7157d5acbc3b24740bc25ca03b2028c52ad21fd71d5d5aa64957411c895a9dc1c132aa3bc97b336 + typescript: ">=5" + checksum: 10/500144d549ea0292c2f672300610df9054339a31cb6a4e61b29623308ef3b14f15eb587ee6139cf3334d2e0f29db1da053522da244b12184bb8fbdb097b7102b languageName: node linkType: hard -"@solana/codecs-strings@npm:2.3.0": - version: 2.3.0 - resolution: "@solana/codecs-strings@npm:2.3.0" +"@solana/codecs-strings@npm:2.0.0": + version: 2.0.0 + resolution: "@solana/codecs-strings@npm:2.0.0" dependencies: - "@solana/codecs-core": "npm:2.3.0" - "@solana/codecs-numbers": "npm:2.3.0" - "@solana/errors": "npm:2.3.0" + "@solana/codecs-core": "npm:2.0.0" + "@solana/codecs-numbers": "npm:2.0.0" + "@solana/errors": "npm:2.0.0" peerDependencies: fastestsmallesttextencoderdecoder: ^1.0.22 - typescript: ">=5.3.3" - checksum: 10/a553a891ce149a87f37ff338587980e81f9752e13039cb0d02f0fc6f21ce27af8548ad10f4c9e63f9ef74786ea0e498c91a2f5e3e996a930f581f2977bb1c215 + typescript: ">=5" + checksum: 10/4380136e2603c2cee12a28438817beb34b0fe45da222b8c38342c5b3680f02086ec7868cde0bb7b4e5dd459af5988613af1d97230c6a193db3be1c45122aba39 languageName: node linkType: hard -"@solana/errors@npm:2.3.0": - version: 2.3.0 - resolution: "@solana/errors@npm:2.3.0" +"@solana/errors@npm:2.0.0": + version: 2.0.0 + resolution: "@solana/errors@npm:2.0.0" dependencies: - chalk: "npm:^5.4.1" - commander: "npm:^14.0.0" + chalk: "npm:^5.3.0" + commander: "npm:^12.1.0" peerDependencies: - typescript: ">=5.3.3" + typescript: ">=5" bin: errors: bin/cli.mjs - checksum: 10/0e8a329790b7d38b4bfe1fa6ec2ac60be20562a610d992031395fe9886da28b578a9d0aebb318f5357ae0d4cbc8f3d323c12b9520da2cf6adc9038f96afc3fe1 - languageName: node - linkType: hard - -"@solana/nominal-types@npm:2.3.0": - version: 2.3.0 - resolution: "@solana/nominal-types@npm:2.3.0" - peerDependencies: - typescript: ">=5.3.3" - checksum: 10/0594893661f4ff2f8587689cd4b61ee15c38c455fe5cbaa7ae7e416f3a483fac97cc3f5a5b3d0a7526bfb89d7da91bc2c72e7b1790bbe59b986579ef2f76689b + checksum: 10/4191f96cad47c64266ec501ae1911a6245fd02b2f68a2c53c3dabbc63eb7c5462f170a765b584348b195da2387e7ca02096d792c67352c2c30a4f3a3cc7e4270 languageName: node linkType: hard @@ -5950,15 +5836,6 @@ __metadata: languageName: node linkType: hard -"@tybys/wasm-util@npm:^0.10.0": - version: 0.10.1 - resolution: "@tybys/wasm-util@npm:0.10.1" - dependencies: - tslib: "npm:^2.4.0" - checksum: 10/7fe0d239397aebb002ac4855d30c197c06a05ea8df8511350a3a5b1abeefe26167c60eda8a5508337571161e4c4b53d7c1342296123f9607af8705369de9fa7f - languageName: node - linkType: hard - "@types/babel__core@npm:^7.1.14": version: 7.20.5 resolution: "@types/babel__core@npm:7.20.5" @@ -5973,11 +5850,11 @@ __metadata: linkType: hard "@types/babel__generator@npm:*": - version: 7.27.0 - resolution: "@types/babel__generator@npm:7.27.0" + version: 7.6.8 + resolution: "@types/babel__generator@npm:7.6.8" dependencies: "@babel/types": "npm:^7.0.0" - checksum: 10/f572e67a9a39397664350a4437d8a7fbd34acc83ff4887a8cf08349e39f8aeb5ad2f70fb78a0a0a23a280affe3a5f4c25f50966abdce292bcf31237af1c27b1a + checksum: 10/b53c215e9074c69d212402990b0ca8fa57595d09e10d94bda3130aa22b55d796e50449199867879e4ea0ee968f3a2099e009cfb21a726a53324483abbf25cd30 languageName: node linkType: hard @@ -5992,20 +5869,20 @@ __metadata: linkType: hard "@types/babel__traverse@npm:*, @types/babel__traverse@npm:^7.0.6": - version: 7.28.0 - resolution: "@types/babel__traverse@npm:7.28.0" + version: 7.20.6 + resolution: "@types/babel__traverse@npm:7.20.6" dependencies: - "@babel/types": "npm:^7.28.2" - checksum: 10/371c5e1b40399ef17570e630b2943617b84fafde2860a56f0ebc113d8edb1d0534ade0175af89eda1ae35160903c33057ed42457e165d4aa287fedab2c82abcf + "@babel/types": "npm:^7.20.7" + checksum: 10/63d13a3789aa1e783b87a8b03d9fb2c2c90078de7782422feff1631b8c2a25db626e63a63ac5a1465d47359201c73069dacb4b52149d17c568187625da3064ae languageName: node linkType: hard "@types/bn.js@npm:*, @types/bn.js@npm:^5.1.0, @types/bn.js@npm:^5.1.5": - version: 5.2.0 - resolution: "@types/bn.js@npm:5.2.0" + version: 5.1.6 + resolution: "@types/bn.js@npm:5.1.6" dependencies: "@types/node": "npm:*" - checksum: 10/06c93841f74e4a5e5b81b74427d56303b223c9af36389b4cd3c562bda93f43c425c7e241aee1b0b881dde57238dc2e07f21d30d412b206a7dae4435af4c054e8 + checksum: 10/db565b5a2af59b09459d74441153bf23a0e80f1fb2d070330786054e7ce1a7285dc40afcd8f289426c61a83166bdd70814f70e2d439744686aac5d3ea75daf13 languageName: node linkType: hard @@ -6025,6 +5902,13 @@ __metadata: languageName: node linkType: hard +"@types/doctrine@npm:^0.0.9": + version: 0.0.9 + resolution: "@types/doctrine@npm:0.0.9" + checksum: 10/64ef06e6eea2f4f9684d259fedbcb8bf21c954630b96ea2e04875ca42763552b0ba3b01b3dd27ec0f9ea6f8b3b0dba4965d31d5a925cd4c6225fd13a93ae9354 + languageName: node + linkType: hard + "@types/elliptic@npm:^6": version: 6.4.18 resolution: "@types/elliptic@npm:6.4.18" @@ -6055,9 +5939,9 @@ __metadata: linkType: hard "@types/estree@npm:*, @types/estree@npm:^1.0.6": - version: 1.0.8 - resolution: "@types/estree@npm:1.0.8" - checksum: 10/25a4c16a6752538ffde2826c2cc0c6491d90e69cd6187bef4a006dd2c3c45469f049e643d7e516c515f21484dc3d48fd5c870be158a5beb72f5baf3dc43e4099 + version: 1.0.6 + resolution: "@types/estree@npm:1.0.6" + checksum: 10/9d35d475095199c23e05b431bcdd1f6fec7380612aed068b14b2a08aa70494de8a9026765a5a91b1073f636fb0368f6d8973f518a31391d519e20c59388ed88d languageName: node linkType: hard @@ -6070,7 +5954,7 @@ __metadata: languageName: node linkType: hard -"@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.0, @types/istanbul-lib-coverage@npm:^2.0.1, @types/istanbul-lib-coverage@npm:^2.0.6": +"@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.0, @types/istanbul-lib-coverage@npm:^2.0.1": version: 2.0.6 resolution: "@types/istanbul-lib-coverage@npm:2.0.6" checksum: 10/3feac423fd3e5449485afac999dcfcb3d44a37c830af898b689fadc65d26526460bedb889db278e0d4d815a670331796494d073a10ee6e3a6526301fe7415778 @@ -6086,7 +5970,7 @@ __metadata: languageName: node linkType: hard -"@types/istanbul-reports@npm:^3.0.0, @types/istanbul-reports@npm:^3.0.4": +"@types/istanbul-reports@npm:^3.0.0": version: 3.0.4 resolution: "@types/istanbul-reports@npm:3.0.4" dependencies: @@ -6104,17 +5988,7 @@ __metadata: languageName: node linkType: hard -"@types/jest@npm:*": - version: 30.0.0 - resolution: "@types/jest@npm:30.0.0" - dependencies: - expect: "npm:^30.0.0" - pretty-format: "npm:^30.0.0" - checksum: 10/cdeaa924c68b5233d9ff92861a89e7042df2b0f197633729bcf3a31e65bd4e9426e751c5665b5ac2de0b222b33f100a5502da22aefce3d2c62931c715e88f209 - languageName: node - linkType: hard - -"@types/jest@npm:^29.5.14": +"@types/jest@npm:*, @types/jest@npm:^29.5.14": version: 29.5.14 resolution: "@types/jest@npm:29.5.14" dependencies: @@ -6157,9 +6031,9 @@ __metadata: linkType: hard "@types/lodash@npm:^4.14.191, @types/lodash@npm:^4.17.20": - version: 4.17.24 - resolution: "@types/lodash@npm:4.17.24" - checksum: 10/0f2082565f60f9787eefc046edc38458054512be5a8b3584ef0bad5fd9e85d0ab55ec5a1fbfae1ed6ba015cf1f9e837d5fb4da1f99fc60b8f74b2a46146fb00f + version: 4.17.20 + resolution: "@types/lodash@npm:4.17.20" + checksum: 10/8cd8ad3bd78d2e06a93ae8d6c9907981d5673655fec7cb274a4d9a59549aab5bb5b3017361280773b8990ddfccf363e14d1b37c97af8a9fe363de677f9a61524 languageName: node linkType: hard @@ -6178,44 +6052,42 @@ __metadata: linkType: hard "@types/ms@npm:*": - version: 2.1.0 - resolution: "@types/ms@npm:2.1.0" - checksum: 10/532d2ebb91937ccc4a89389715e5b47d4c66e708d15942fe6cc25add6dc37b2be058230a327dd50f43f89b8b6d5d52b74685a9e8f70516edfc9bdd6be910eff4 + version: 0.7.34 + resolution: "@types/ms@npm:0.7.34" + checksum: 10/f38d36e7b6edecd9badc9cf50474159e9da5fa6965a75186cceaf883278611b9df6669dc3a3cc122b7938d317b68a9e3d573d316fcb35d1be47ec9e468c6bd8a languageName: node linkType: hard "@types/node-fetch@npm:^2.6.12": - version: 2.6.13 - resolution: "@types/node-fetch@npm:2.6.13" + version: 2.6.12 + resolution: "@types/node-fetch@npm:2.6.12" dependencies: "@types/node": "npm:*" - form-data: "npm:^4.0.4" - checksum: 10/944d52214791ebba482ca1393a4f0d62b0dbac5f7343ff42c128b75d5356d8bcefd4df77771b55c1acd19d118e16e9bd5d2792819c51bc13402d1c87c0975435 + form-data: "npm:^4.0.0" + checksum: 10/8107c479da83a3114fcbfa882eba95ee5175cccb5e4dd53f737a96f2559ae6262f662176b8457c1656de09ec393cc7b20a266c077e4bfb21e929976e1cf4d0f9 languageName: node linkType: hard "@types/node@npm:*, @types/node@npm:>=12.12.47, @types/node@npm:>=13.7.0": - version: 25.3.0 - resolution: "@types/node@npm:25.3.0" + version: 22.5.0 + resolution: "@types/node@npm:22.5.0" dependencies: - undici-types: "npm:~7.18.0" - checksum: 10/061b00c8de070a606a052afaa4c45dca5f8d6a8e7e39c0c3e196bb650ee37e986bbb161991ea39076a05aada102f36b13c974528448a09efd8d36bdfee75de4b + undici-types: "npm:~6.19.2" + checksum: 10/89af3bd217b1559b645a9ed16d4ae3add75749814cbd8eefddd1b96003d1973afb1c8a2b23d69f3a8cc6c532e3aa185eaf5cc29a6e7c42c311a2aad4c99430ae languageName: node linkType: hard -"@types/node@npm:22.7.5": - version: 22.7.5 - resolution: "@types/node@npm:22.7.5" - dependencies: - undici-types: "npm:~6.19.2" - checksum: 10/e8ba102f8c1aa7623787d625389be68d64e54fcbb76d41f6c2c64e8cf4c9f4a2370e7ef5e5f1732f3c57529d3d26afdcb2edc0101c5e413a79081449825c57ac +"@types/node@npm:18.15.13": + version: 18.15.13 + resolution: "@types/node@npm:18.15.13" + checksum: 10/b9bbe923573797ef7c5fd2641a6793489e25d9369c32aeadcaa5c7c175c85b42eb12d6fe173f6781ab6f42eaa1ebd9576a419eeaa2a1ec810094adb8adaa9a54 languageName: node linkType: hard "@types/node@npm:^16.18.54": - version: 16.18.126 - resolution: "@types/node@npm:16.18.126" - checksum: 10/33e0fa9209a4a96459a8fdf6b078ca9590eb67a8d51899180cfac8afecb9aa133c755d1c38a8b947b9f384f2faa184cabf4e567f5f6dded285be1b31588ec199 + version: 16.18.106 + resolution: "@types/node@npm:16.18.106" + checksum: 10/1970719a048bfc56554f8e132e8e5292c197d6e023d334190b0d3817a05a12bfb6537eaa24778ddb695d2073195f0545e5a4b6bcaf81b656994bbca39f349c3b languageName: node linkType: hard @@ -6267,22 +6139,22 @@ __metadata: linkType: hard "@types/secp256k1@npm:^4.0.1": - version: 4.0.7 - resolution: "@types/secp256k1@npm:4.0.7" + version: 4.0.6 + resolution: "@types/secp256k1@npm:4.0.6" dependencies: "@types/node": "npm:*" - checksum: 10/bcf7adbd953d2cb829ae98a3cd2f8eeb1e2316f4f6de720ee3863da90bd98899c08fa8c42748e8701cad16ede0898df69a6e7f22660d1fb3cb276d5c771069db + checksum: 10/211f823be990b55612e604d620acf0dc3bc942d3836bdd8da604269effabc86d98161e5947487b4e4e128f9180fc1682daae2f89ea7a4d9648fdfe52fba365fc languageName: node linkType: hard "@types/semver@npm:^7, @types/semver@npm:^7.3.6": - version: 7.7.1 - resolution: "@types/semver@npm:7.7.1" - checksum: 10/8f09e7e6ca3ded67d78ba7a8f7535c8d9cf8ced83c52e7f3ac3c281fe8c689c3fe475d199d94390dc04fc681d51f2358b430bb7b2e21c62de24f2bee2c719068 + version: 7.5.8 + resolution: "@types/semver@npm:7.5.8" + checksum: 10/3496808818ddb36deabfe4974fd343a78101fa242c4690044ccdc3b95dcf8785b494f5d628f2f47f38a702f8db9c53c67f47d7818f2be1b79f2efb09692e1178 languageName: node linkType: hard -"@types/stack-utils@npm:^2.0.0, @types/stack-utils@npm:^2.0.3": +"@types/stack-utils@npm:^2.0.0": version: 2.0.3 resolution: "@types/stack-utils@npm:2.0.3" checksum: 10/72576cc1522090fe497337c2b99d9838e320659ac57fa5560fcbdcbafcf5d0216c6b3a0a8a4ee4fdb3b1f5e3420aa4f6223ab57b82fef3578bec3206425c6cf5 @@ -6327,354 +6199,219 @@ __metadata: linkType: hard "@types/yargs@npm:^15.0.0": - version: 15.0.20 - resolution: "@types/yargs@npm:15.0.20" + version: 15.0.19 + resolution: "@types/yargs@npm:15.0.19" dependencies: "@types/yargs-parser": "npm:*" - checksum: 10/f348069c4a0cf5b365e72507f67c6569b12a4af44346c08288319d522272dbe1e3f3acde3ff9ab72bd9f894676624d10fff21096d44bad33e390d092cd409aeb + checksum: 10/c3abcd3472c32c02702f365dc1702a0728562deb8a8c61f3ce2161958d756cc033f7d78567565b4eba62f5869e9b5eac93d4c1dcb2c97af17aafda8f9f892b4b languageName: node linkType: hard -"@types/yargs@npm:^17.0.32, @types/yargs@npm:^17.0.33, @types/yargs@npm:^17.0.8": - version: 17.0.35 - resolution: "@types/yargs@npm:17.0.35" +"@types/yargs@npm:^17.0.32, @types/yargs@npm:^17.0.8": + version: 17.0.33 + resolution: "@types/yargs@npm:17.0.33" dependencies: "@types/yargs-parser": "npm:*" - checksum: 10/47bcd4476a4194ea11617ea71cba8a1eddf5505fc39c44336c1a08d452a0de4486aedbc13f47a017c8efbcb5a8aa358d976880663732ebcbc6dbcbbecadb0581 + checksum: 10/16f6681bf4d99fb671bf56029141ed01db2862e3db9df7fc92d8bea494359ac96a1b4b1c35a836d1e95e665fb18ad753ab2015fc0db663454e8fd4e5d5e2ef91 languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:8.56.1, @typescript-eslint/eslint-plugin@npm:^8.48.0": - version: 8.56.1 - resolution: "@typescript-eslint/eslint-plugin@npm:8.56.1" +"@typescript-eslint/eslint-plugin@npm:8.54.0, @typescript-eslint/eslint-plugin@npm:^8.48.0": + version: 8.54.0 + resolution: "@typescript-eslint/eslint-plugin@npm:8.54.0" dependencies: "@eslint-community/regexpp": "npm:^4.12.2" - "@typescript-eslint/scope-manager": "npm:8.56.1" - "@typescript-eslint/type-utils": "npm:8.56.1" - "@typescript-eslint/utils": "npm:8.56.1" - "@typescript-eslint/visitor-keys": "npm:8.56.1" + "@typescript-eslint/scope-manager": "npm:8.54.0" + "@typescript-eslint/type-utils": "npm:8.54.0" + "@typescript-eslint/utils": "npm:8.54.0" + "@typescript-eslint/visitor-keys": "npm:8.54.0" ignore: "npm:^7.0.5" natural-compare: "npm:^1.4.0" ts-api-utils: "npm:^2.4.0" peerDependencies: - "@typescript-eslint/parser": ^8.56.1 - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + "@typescript-eslint/parser": ^8.54.0 + eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10/669d19cff91fcad5fe34dba97cc8c0c2df3160ae14646759fb23dfd6ffbb861d00d8d081e74d1060d544bfba0ea4d05588c5b73ae104907af26cc18189c0d139 + checksum: 10/8f1c74ac77d7a84ae3f201bb09cb67271662befed036266af1eaa0653d09b545353441640516c1c86e0a94939887d32f0473c61a642488b14d46533742bfbd1b languageName: node linkType: hard -"@typescript-eslint/parser@npm:8.56.1, @typescript-eslint/parser@npm:^8.48.0": - version: 8.56.1 - resolution: "@typescript-eslint/parser@npm:8.56.1" +"@typescript-eslint/parser@npm:8.54.0, @typescript-eslint/parser@npm:^8.48.0": + version: 8.54.0 + resolution: "@typescript-eslint/parser@npm:8.54.0" dependencies: - "@typescript-eslint/scope-manager": "npm:8.56.1" - "@typescript-eslint/types": "npm:8.56.1" - "@typescript-eslint/typescript-estree": "npm:8.56.1" - "@typescript-eslint/visitor-keys": "npm:8.56.1" + "@typescript-eslint/scope-manager": "npm:8.54.0" + "@typescript-eslint/types": "npm:8.54.0" + "@typescript-eslint/typescript-estree": "npm:8.54.0" + "@typescript-eslint/visitor-keys": "npm:8.54.0" debug: "npm:^4.4.3" peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10/280b041a69153caf9e721b307781830483dd39d881b02d993156635bd8600e30e6a816aaead8bdd662ae5149b8870aef7b3823d3b98ec974d924c23a786fb6d9 + checksum: 10/d2e09462c9966ef3deeba71d9e41d1d4876c61eea65888c93a3db6fba48b89a2165459c6519741d40e969da05ed98d3f4c87a7f56c5521ab5699743cc315f6cb languageName: node linkType: hard -"@typescript-eslint/project-service@npm:8.56.1": - version: 8.56.1 - resolution: "@typescript-eslint/project-service@npm:8.56.1" +"@typescript-eslint/project-service@npm:8.54.0": + version: 8.54.0 + resolution: "@typescript-eslint/project-service@npm:8.54.0" dependencies: - "@typescript-eslint/tsconfig-utils": "npm:^8.56.1" - "@typescript-eslint/types": "npm:^8.56.1" + "@typescript-eslint/tsconfig-utils": "npm:^8.54.0" + "@typescript-eslint/types": "npm:^8.54.0" debug: "npm:^4.4.3" peerDependencies: typescript: ">=4.8.4 <6.0.0" - checksum: 10/5e7fdc95aebcefc72fec77806bb0821a9a59e5e88f86d72b15ad011eb6110da05419b803875f021716a219fc7fb8517331a6736364344c8613a90209539a6d32 + checksum: 10/93f0483f6bbcf7cf776a53a130f7606f597fba67cf111e1897873bf1531efaa96e4851cfd461da0f0cc93afbdb51e47bcce11cf7dd4fb68b7030c7f9f240b92f languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:8.56.1": - version: 8.56.1 - resolution: "@typescript-eslint/scope-manager@npm:8.56.1" +"@typescript-eslint/scope-manager@npm:8.54.0, @typescript-eslint/scope-manager@npm:^8.1.0": + version: 8.54.0 + resolution: "@typescript-eslint/scope-manager@npm:8.54.0" dependencies: - "@typescript-eslint/types": "npm:8.56.1" - "@typescript-eslint/visitor-keys": "npm:8.56.1" - checksum: 10/f358cf8bd32952eed005d4f34c1e95805baefe35abee96d866222b0eff8027cc02f831cee04b308707d74db2b415437a134191207b4213ee8acbc6d67a435616 + "@typescript-eslint/types": "npm:8.54.0" + "@typescript-eslint/visitor-keys": "npm:8.54.0" + checksum: 10/3474f3197e8647754393dee62b3145c9de71eaa66c8a68f61c8283aa332141803885db9c96caa6a51f78128ad9ef92f774a90361655e57bd951d5b57eb76f914 languageName: node linkType: hard -"@typescript-eslint/tsconfig-utils@npm:8.56.1, @typescript-eslint/tsconfig-utils@npm:^8.56.1": - version: 8.56.1 - resolution: "@typescript-eslint/tsconfig-utils@npm:8.56.1" +"@typescript-eslint/tsconfig-utils@npm:8.54.0, @typescript-eslint/tsconfig-utils@npm:^8.54.0": + version: 8.54.0 + resolution: "@typescript-eslint/tsconfig-utils@npm:8.54.0" peerDependencies: typescript: ">=4.8.4 <6.0.0" - checksum: 10/d509f1ae4b14969173e498db6d15c833b6407db456c7fca9e25396798a35014229a73754691f353c4a99f5f0bbb4535b4144f42f84e596645a16d88a2022135f + checksum: 10/e9d6b29538716f007919bfcee94f09b7f8e7d2b684ad43d1a3c8d43afb9f0539c7707f84a34f42054e31c8c056b0ccf06575d89e860b4d34632ffefaefafe1fc languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:8.56.1": - version: 8.56.1 - resolution: "@typescript-eslint/type-utils@npm:8.56.1" +"@typescript-eslint/type-utils@npm:8.54.0": + version: 8.54.0 + resolution: "@typescript-eslint/type-utils@npm:8.54.0" dependencies: - "@typescript-eslint/types": "npm:8.56.1" - "@typescript-eslint/typescript-estree": "npm:8.56.1" - "@typescript-eslint/utils": "npm:8.56.1" + "@typescript-eslint/types": "npm:8.54.0" + "@typescript-eslint/typescript-estree": "npm:8.54.0" + "@typescript-eslint/utils": "npm:8.54.0" debug: "npm:^4.4.3" ts-api-utils: "npm:^2.4.0" peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10/2b07c674c26d797d05c05779ac5c89761b6b96680ecaf01440957727d12c6d06a2e48f0b139e45752eb4b53bf13c03940628656c519d362082b716d6a0ece6d9 + checksum: 10/60e92fb32274abd70165ce6f4187e4cffa55416374c63731d7de8fdcfb7a558b4dd48909ff1ad38ac39d2ea1248ec54d6ce38dbc065fd34529a217fc2450d5b1 languageName: node linkType: hard -"@typescript-eslint/types@npm:8.56.1, @typescript-eslint/types@npm:^8.11.0, @typescript-eslint/types@npm:^8.35.0, @typescript-eslint/types@npm:^8.56.1": - version: 8.56.1 - resolution: "@typescript-eslint/types@npm:8.56.1" - checksum: 10/4bcffab5b0fd48adb731fcade86a776ca4a66e229defa5a282b58ba9c95af16ffc459a7d188e27c988a35be1f6fb5b812f9cf0952692eac38d5b3e87daafb20a +"@typescript-eslint/types@npm:8.54.0, @typescript-eslint/types@npm:^8.54.0": + version: 8.54.0 + resolution: "@typescript-eslint/types@npm:8.54.0" + checksum: 10/c25cc0bdf90fb150cf6ce498897f43fe3adf9e872562159118f34bd91a9bfab5f720cb1a41f3cdf253b2e840145d7d372089b7cef5156624ef31e98d34f91b31 languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:8.56.1": - version: 8.56.1 - resolution: "@typescript-eslint/typescript-estree@npm:8.56.1" +"@typescript-eslint/typescript-estree@npm:8.54.0": + version: 8.54.0 + resolution: "@typescript-eslint/typescript-estree@npm:8.54.0" dependencies: - "@typescript-eslint/project-service": "npm:8.56.1" - "@typescript-eslint/tsconfig-utils": "npm:8.56.1" - "@typescript-eslint/types": "npm:8.56.1" - "@typescript-eslint/visitor-keys": "npm:8.56.1" + "@typescript-eslint/project-service": "npm:8.54.0" + "@typescript-eslint/tsconfig-utils": "npm:8.54.0" + "@typescript-eslint/types": "npm:8.54.0" + "@typescript-eslint/visitor-keys": "npm:8.54.0" debug: "npm:^4.4.3" - minimatch: "npm:^10.2.2" + minimatch: "npm:^9.0.5" semver: "npm:^7.7.3" tinyglobby: "npm:^0.2.15" ts-api-utils: "npm:^2.4.0" peerDependencies: typescript: ">=4.8.4 <6.0.0" - checksum: 10/af39dae0a8fada72295a11f0efb49f311241134b0a3d819100eeda6a2f92368844645873ba785de5513ad541cd9c2ba17b9bfed2679daac4682fa2a3b627f087 + checksum: 10/3a545037c6f9319251d3ba44cf7a3216b1372422469e27f7ed3415244ebf42553da1ab4644da42d3f0ae2706a8cad12529ffebcb2e75406f74e3b30b812d010d languageName: node linkType: hard -"@typescript-eslint/utils@npm:8.56.1, @typescript-eslint/utils@npm:^6.0.0 || ^7.0.0 || ^8.0.0": - version: 8.56.1 - resolution: "@typescript-eslint/utils@npm:8.56.1" +"@typescript-eslint/utils@npm:8.54.0, @typescript-eslint/utils@npm:^6.0.0 || ^7.0.0 || ^8.0.0, @typescript-eslint/utils@npm:^8.1.0": + version: 8.54.0 + resolution: "@typescript-eslint/utils@npm:8.54.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.9.1" - "@typescript-eslint/scope-manager": "npm:8.56.1" - "@typescript-eslint/types": "npm:8.56.1" - "@typescript-eslint/typescript-estree": "npm:8.56.1" + "@typescript-eslint/scope-manager": "npm:8.54.0" + "@typescript-eslint/types": "npm:8.54.0" + "@typescript-eslint/typescript-estree": "npm:8.54.0" peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10/528cbd187d8288a8cfce24a043f993b93711087f53d2b6f95cdd615a1a4087af1dab083a747761af97474a621c7b14f11c84ee50c250f31566ebc64cf73867fe + checksum: 10/9f88a2a7ab3e11aa0ff7f99c0e66a0cf2cba10b640def4c64a4f4ef427fecfb22f28dbe5697535915eb01f6507515ac43e45e0ff384bf82856e3420194d9ffdd languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:8.56.1": - version: 8.56.1 - resolution: "@typescript-eslint/visitor-keys@npm:8.56.1" +"@typescript-eslint/visitor-keys@npm:8.54.0": + version: 8.54.0 + resolution: "@typescript-eslint/visitor-keys@npm:8.54.0" dependencies: - "@typescript-eslint/types": "npm:8.56.1" - eslint-visitor-keys: "npm:^5.0.0" - checksum: 10/efed6a9867e7be203eec543e5a65da5aaec96aae55fba6fe74a305bf600e57c707764835e82bb8eb541f49a9b70442ff1e1a0ecf3543c78c91b84dda43b95c53 + "@typescript-eslint/types": "npm:8.54.0" + eslint-visitor-keys: "npm:^4.2.1" + checksum: 10/cca5380ee30250302ee1459e5a0a38de8c16213026dbbff3d167fa7d71d012f31d60ac4483ad45ebd13f2ac963d1ca52dd5f22759a68d4ee57626e421769187a languageName: node linkType: hard -"@unrs/resolver-binding-android-arm-eabi@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-android-arm-eabi@npm:1.11.1" - conditions: os=android & cpu=arm +"@vercel/stega@npm:^0.1.2": + version: 0.1.2 + resolution: "@vercel/stega@npm:0.1.2" + checksum: 10/67ade78b77f579e39bbdd010cc31c39e75b1c1a1ef5a8accdd78df57d156ecd163c767a1feb61b95df190f8ab10642d038776bc5f2fab48bf705d49ee9cced01 languageName: node linkType: hard -"@unrs/resolver-binding-android-arm64@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-android-arm64@npm:1.11.1" - conditions: os=android & cpu=arm64 +"@vue/compiler-core@npm:3.4.38": + version: 3.4.38 + resolution: "@vue/compiler-core@npm:3.4.38" + dependencies: + "@babel/parser": "npm:^7.24.7" + "@vue/shared": "npm:3.4.38" + entities: "npm:^4.5.0" + estree-walker: "npm:^2.0.2" + source-map-js: "npm:^1.2.0" + checksum: 10/16449e9083c290e6c13e1cc0cb0a0a457817a52533d10902388c872fb1337ba0fa29fb7b8394df5a10f5ed3bad264d6c386f9eaf47c07982a543f277dbee9b8a languageName: node linkType: hard -"@unrs/resolver-binding-darwin-arm64@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-darwin-arm64@npm:1.11.1" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"@unrs/resolver-binding-darwin-x64@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-darwin-x64@npm:1.11.1" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"@unrs/resolver-binding-freebsd-x64@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-freebsd-x64@npm:1.11.1" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - -"@unrs/resolver-binding-linux-arm-gnueabihf@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-linux-arm-gnueabihf@npm:1.11.1" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"@unrs/resolver-binding-linux-arm-musleabihf@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-linux-arm-musleabihf@npm:1.11.1" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"@unrs/resolver-binding-linux-arm64-gnu@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-linux-arm64-gnu@npm:1.11.1" - conditions: os=linux & cpu=arm64 & libc=glibc - languageName: node - linkType: hard - -"@unrs/resolver-binding-linux-arm64-musl@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-linux-arm64-musl@npm:1.11.1" - conditions: os=linux & cpu=arm64 & libc=musl - languageName: node - linkType: hard - -"@unrs/resolver-binding-linux-ppc64-gnu@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-linux-ppc64-gnu@npm:1.11.1" - conditions: os=linux & cpu=ppc64 & libc=glibc - languageName: node - linkType: hard - -"@unrs/resolver-binding-linux-riscv64-gnu@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-linux-riscv64-gnu@npm:1.11.1" - conditions: os=linux & cpu=riscv64 & libc=glibc - languageName: node - linkType: hard - -"@unrs/resolver-binding-linux-riscv64-musl@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-linux-riscv64-musl@npm:1.11.1" - conditions: os=linux & cpu=riscv64 & libc=musl - languageName: node - linkType: hard - -"@unrs/resolver-binding-linux-s390x-gnu@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-linux-s390x-gnu@npm:1.11.1" - conditions: os=linux & cpu=s390x & libc=glibc - languageName: node - linkType: hard - -"@unrs/resolver-binding-linux-x64-gnu@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-linux-x64-gnu@npm:1.11.1" - conditions: os=linux & cpu=x64 & libc=glibc - languageName: node - linkType: hard - -"@unrs/resolver-binding-linux-x64-musl@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-linux-x64-musl@npm:1.11.1" - conditions: os=linux & cpu=x64 & libc=musl - languageName: node - linkType: hard - -"@unrs/resolver-binding-wasm32-wasi@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-wasm32-wasi@npm:1.11.1" - dependencies: - "@napi-rs/wasm-runtime": "npm:^0.2.11" - conditions: cpu=wasm32 - languageName: node - linkType: hard - -"@unrs/resolver-binding-win32-arm64-msvc@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-win32-arm64-msvc@npm:1.11.1" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"@unrs/resolver-binding-win32-ia32-msvc@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-win32-ia32-msvc@npm:1.11.1" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - -"@unrs/resolver-binding-win32-x64-msvc@npm:1.11.1": - version: 1.11.1 - resolution: "@unrs/resolver-binding-win32-x64-msvc@npm:1.11.1" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"@vercel/stega@npm:^0.1.2": - version: 0.1.2 - resolution: "@vercel/stega@npm:0.1.2" - checksum: 10/67ade78b77f579e39bbdd010cc31c39e75b1c1a1ef5a8accdd78df57d156ecd163c767a1feb61b95df190f8ab10642d038776bc5f2fab48bf705d49ee9cced01 - languageName: node - linkType: hard - -"@vue/compiler-core@npm:3.5.29": - version: 3.5.29 - resolution: "@vue/compiler-core@npm:3.5.29" - dependencies: - "@babel/parser": "npm:^7.29.0" - "@vue/shared": "npm:3.5.29" - entities: "npm:^7.0.1" - estree-walker: "npm:^2.0.2" - source-map-js: "npm:^1.2.1" - checksum: 10/55c9dc371049f9b46f62210e72cea084212e2177dde42697da5008c2a64bfa88a886f42bcbb14fc5447fe9611082c6b30b3d2f148c512d14bce3ba8e2960212e - languageName: node - linkType: hard - -"@vue/compiler-dom@npm:3.5.29": - version: 3.5.29 - resolution: "@vue/compiler-dom@npm:3.5.29" - dependencies: - "@vue/compiler-core": "npm:3.5.29" - "@vue/shared": "npm:3.5.29" - checksum: 10/50156e63a3c249e82f6e57f2e8fc1705b659d81845d0f59552a92e86c1907ef5c53c17670c03d76fd9bc850d06ad29ff8ca1ebc92bfdf0c77efa1a8e449be98b +"@vue/compiler-dom@npm:3.4.38": + version: 3.4.38 + resolution: "@vue/compiler-dom@npm:3.4.38" + dependencies: + "@vue/compiler-core": "npm:3.4.38" + "@vue/shared": "npm:3.4.38" + checksum: 10/4012fab212dc0628ef72f5ae13aa2dd551efb8be7f2aa8abe2a1db15058ddda29912a1e3aa1fc6712e2d8efe84724f16a907ad2cda987631bfc79330afc8d451 languageName: node linkType: hard "@vue/compiler-sfc@npm:^3.3.4": - version: 3.5.29 - resolution: "@vue/compiler-sfc@npm:3.5.29" - dependencies: - "@babel/parser": "npm:^7.29.0" - "@vue/compiler-core": "npm:3.5.29" - "@vue/compiler-dom": "npm:3.5.29" - "@vue/compiler-ssr": "npm:3.5.29" - "@vue/shared": "npm:3.5.29" + version: 3.4.38 + resolution: "@vue/compiler-sfc@npm:3.4.38" + dependencies: + "@babel/parser": "npm:^7.24.7" + "@vue/compiler-core": "npm:3.4.38" + "@vue/compiler-dom": "npm:3.4.38" + "@vue/compiler-ssr": "npm:3.4.38" + "@vue/shared": "npm:3.4.38" estree-walker: "npm:^2.0.2" - magic-string: "npm:^0.30.21" - postcss: "npm:^8.5.6" - source-map-js: "npm:^1.2.1" - checksum: 10/0052b6ce36e70e923a5151d64c0a0d63ebb2e00c3ad5198bad983783d3e536ca6b0b4245c6d0b3c311bf97c10b16359453cfc597267a45f0efb18edcf7e35987 + magic-string: "npm:^0.30.10" + postcss: "npm:^8.4.40" + source-map-js: "npm:^1.2.0" + checksum: 10/3eec1ddc03e06a162087dbbff9679f941ff34c43e553006aa2717c6a396445f488b62b89afa9cf65688468a05d8517bf1ee64936ad78d7ba6647a850a089e0e0 languageName: node linkType: hard -"@vue/compiler-ssr@npm:3.5.29": - version: 3.5.29 - resolution: "@vue/compiler-ssr@npm:3.5.29" +"@vue/compiler-ssr@npm:3.4.38": + version: 3.4.38 + resolution: "@vue/compiler-ssr@npm:3.4.38" dependencies: - "@vue/compiler-dom": "npm:3.5.29" - "@vue/shared": "npm:3.5.29" - checksum: 10/0240a488fc42fb4221a03e2e4eb258256c9b7043e26841fe5e6e4097ff944c8e9f78ef21792517af6434927f8f51d2c1f007a09b940aacbc5930c999d336d14e + "@vue/compiler-dom": "npm:3.4.38" + "@vue/shared": "npm:3.4.38" + checksum: 10/3ee052c8f10bf18db5d6788df21105698c139fac1de6c82532878cca86be4d052510a216184b3ea73331d84befcefd3f9ada11470c862f03696fed96ce1005cb languageName: node linkType: hard -"@vue/shared@npm:3.5.29": - version: 3.5.29 - resolution: "@vue/shared@npm:3.5.29" - checksum: 10/cad8e9925f672d9e3eaa08a6b502777e6a264cfae1faf648e0b759d0c1cb8d91980fb9a6338c8dc09dee6bf5235fec4c9ac3cc5d3312b159292da271b8864546 +"@vue/shared@npm:3.4.38": + version: 3.4.38 + resolution: "@vue/shared@npm:3.4.38" + checksum: 10/46bfc1f3932fd154ff84dcd267cae4db730c98db433c848d40c9c0dc23dcabdb5efe96a3a378c9ed3b7e8281ca17e2753f0ce98ae43b54b315550dfaccb56868 languageName: node linkType: hard @@ -6686,11 +6423,11 @@ __metadata: linkType: hard "@yarnpkg/types@npm:^4.0.0": - version: 4.0.1 - resolution: "@yarnpkg/types@npm:4.0.1" + version: 4.0.0 + resolution: "@yarnpkg/types@npm:4.0.0" dependencies: tslib: "npm:^2.4.0" - checksum: 10/f391763cd955356e9aad551b29e8de7bbf68a6c8992af7cdc950ccf53f8aff6695ad81aa4c8a8e7c582786a840a4f30617732e2cb49f4109b971a9242c31c9fc + checksum: 10/f9670e120761a4d17461df2f01aa4b92213fbdd063501a36145d11ea01bd87ba01d44615cba3d6bc8f9bfc39a03a9a6452bf0436c7fb0c9c5311352b975349e6 languageName: node linkType: hard @@ -6701,10 +6438,10 @@ __metadata: languageName: node linkType: hard -"abbrev@npm:^4.0.0": - version: 4.0.0 - resolution: "abbrev@npm:4.0.0" - checksum: 10/e2f0c6a6708ad738b3e8f50233f4800de31ad41a6cdc50e0cbe51b76fed69fd0213516d92c15ce1a9985fca71a14606a9be22bf00f8475a58987b9bfb671c582 +"abbrev@npm:^2.0.0": + version: 2.0.0 + resolution: "abbrev@npm:2.0.0" + checksum: 10/ca0a54e35bea4ece0ecb68a47b312e1a9a6f772408d5bcb9051230aaa94b0460671c5b5c9cb3240eb5b7bc94c52476550eb221f65a0bbd0145bdc9f3113a6707 languageName: node linkType: hard @@ -6747,20 +6484,20 @@ __metadata: linkType: hard "acorn-walk@npm:^8.0.2": - version: 8.3.5 - resolution: "acorn-walk@npm:8.3.5" + version: 8.3.4 + resolution: "acorn-walk@npm:8.3.4" dependencies: acorn: "npm:^8.11.0" - checksum: 10/f52a158a1c1f00c82702c7eb9b8ae8aad79748a7689241dcc2d797dce680f1dcb15c78f312f687eeacdfb3a4cac4b87d04af470f0201bd56c6661fca6f94b195 + checksum: 10/871386764e1451c637bb8ab9f76f4995d408057e9909be6fb5ad68537ae3375d85e6a6f170b98989f44ab3ff6c74ad120bc2779a3d577606e7a0cd2b4efcaf77 languageName: node linkType: hard "acorn@npm:^8.1.0, acorn@npm:^8.11.0, acorn@npm:^8.15.0, acorn@npm:^8.8.1": - version: 8.16.0 - resolution: "acorn@npm:8.16.0" + version: 8.15.0 + resolution: "acorn@npm:8.15.0" bin: acorn: bin/acorn - checksum: 10/690c673bb4d61b38ef82795fab58526471ad7f7e67c0e40c4ff1e10ecd80ce5312554ef633c9995bfc4e6d170cef165711f9ca9e49040b62c0c66fbf2dd3df2b + checksum: 10/77f2de5051a631cf1729c090e5759148459cdb76b5f5c70f890503d629cf5052357b0ce783c0f976dd8a93c5150f59f6d18df1def3f502396a20f81282482fa4 languageName: node linkType: hard @@ -6794,22 +6531,34 @@ __metadata: languageName: node linkType: hard -"agent-base@npm:^7.1.0, agent-base@npm:^7.1.2": - version: 7.1.4 - resolution: "agent-base@npm:7.1.4" - checksum: 10/79bef167247789f955aaba113bae74bf64aa1e1acca4b1d6bb444bdf91d82c3e07e9451ef6a6e2e35e8f71a6f97ce33e3d855a5328eb9fad1bc3cc4cfd031ed8 +"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0, agent-base@npm:^7.1.1": + version: 7.1.1 + resolution: "agent-base@npm:7.1.1" + dependencies: + debug: "npm:^4.3.4" + checksum: 10/c478fec8f79953f118704d007a38f2a185458853f5c45579b9669372bd0e12602e88dc2ad0233077831504f7cd6fcc8251c383375bba5eaaf563b102938bda26 + languageName: node + linkType: hard + +"aggregate-error@npm:^3.0.0": + version: 3.1.0 + resolution: "aggregate-error@npm:3.1.0" + dependencies: + clean-stack: "npm:^2.0.0" + indent-string: "npm:^4.0.0" + checksum: 10/1101a33f21baa27a2fa8e04b698271e64616b886795fd43c31068c07533c7b3facfcaf4e9e0cab3624bd88f729a592f1c901a1a229c9e490eafce411a8644b79 languageName: node linkType: hard -"ajv@npm:^6.10.0, ajv@npm:^6.12.4, ajv@npm:^6.14.0": - version: 6.14.0 - resolution: "ajv@npm:6.14.0" +"ajv@npm:^6.10.0, ajv@npm:^6.12.4": + version: 6.12.6 + resolution: "ajv@npm:6.12.6" dependencies: fast-deep-equal: "npm:^3.1.1" fast-json-stable-stringify: "npm:^2.0.0" json-schema-traverse: "npm:^0.4.1" uri-js: "npm:^4.2.2" - checksum: 10/c71f14dd2b6f2535d043f74019c8169f7aeb1106bafbb741af96f34fdbf932255c919ddd46344043d03b62ea0ccb319f83667ec5eedf612393f29054fe5ce4a5 + checksum: 10/48d6ad21138d12eb4d16d878d630079a2bda25a04e745c07846a4ad768319533031e28872a9b3c5790fa1ec41aabdf2abed30a56e5a03ebc2cf92184b8ee306c languageName: node linkType: hard @@ -6837,16 +6586,16 @@ __metadata: linkType: hard "ansi-regex@npm:^6.0.1": - version: 6.2.2 - resolution: "ansi-regex@npm:6.2.2" - checksum: 10/9b17ce2c6daecc75bcd5966b9ad672c23b184dc3ed9bf3c98a0702f0d2f736c15c10d461913568f2cf527a5e64291c7473358885dd493305c84a1cfed66ba94f + version: 6.0.1 + resolution: "ansi-regex@npm:6.0.1" + checksum: 10/1ff8b7667cded1de4fa2c9ae283e979fc87036864317da86a2e546725f96406746411d0d85e87a2d12fa5abd715d90006de7fa4fa0477c92321ad3b4c7d4e169 languageName: node linkType: hard "ansi-sequence-parser@npm:^1.1.0": - version: 1.1.3 - resolution: "ansi-sequence-parser@npm:1.1.3" - checksum: 10/0f298aad5c9429dc71fc85668b4b502a5c0670c6dc1253b6e9ed5fc7d457a05ede5b10fd0d69a33a1435e41c0a841360bec9131053bdce04a2367c475acb97d6 + version: 1.1.1 + resolution: "ansi-sequence-parser@npm:1.1.1" + checksum: 10/9ce30f257badc2ef62cac8028a7e26c368d22bf26650427192e8ffd102da42e377e3affe90fae58062eecc963b0b055f510dde3b677c7e0c433c67069b5a8ee5 languageName: node linkType: hard @@ -6859,7 +6608,7 @@ __metadata: languageName: node linkType: hard -"ansi-styles@npm:^5.0.0, ansi-styles@npm:^5.2.0": +"ansi-styles@npm:^5.0.0": version: 5.2.0 resolution: "ansi-styles@npm:5.2.0" checksum: 10/d7f4e97ce0623aea6bc0d90dcd28881ee04cba06c570b97fd3391bd7a268eedfd9d5e2dd4fdcbdd82b8105df5faf6f24aaedc08eaf3da898e702db5948f63469 @@ -6867,9 +6616,9 @@ __metadata: linkType: hard "ansi-styles@npm:^6.1.0": - version: 6.2.3 - resolution: "ansi-styles@npm:6.2.3" - checksum: 10/c49dad7639f3e48859bd51824c93b9eb0db628afc243c51c3dd2410c4a15ede1a83881c6c7341aa2b159c4f90c11befb38f2ba848c07c66c9f9de4bcd7cb9f30 + version: 6.2.1 + resolution: "ansi-styles@npm:6.2.1" + checksum: 10/70fdf883b704d17a5dfc9cde206e698c16bcd74e7f196ab821511651aee4f9f76c9514bdfa6ca3a27b5e49138b89cb222a28caf3afe4567570139577f991df32 languageName: node linkType: hard @@ -6955,17 +6704,12 @@ __metadata: languageName: node linkType: hard -"async-function@npm:^1.0.0": - version: 1.0.0 - resolution: "async-function@npm:1.0.0" - checksum: 10/1a09379937d846f0ce7614e75071c12826945d4e417db634156bf0e4673c495989302f52186dfa9767a1d9181794554717badd193ca2bbab046ef1da741d8efd - languageName: node - linkType: hard - -"async-generator-function@npm:^1.0.0": - version: 1.0.0 - resolution: "async-generator-function@npm:1.0.0" - checksum: 10/3d49e7acbeee9e84537f4cb0e0f91893df8eba976759875ae8ee9e3d3c82f6ecdebdb347c2fad9926b92596d93cdfc78ecc988bcdf407e40433e8e8e6fe5d78e +"async-mutex@npm:^0.3.1": + version: 0.3.2 + resolution: "async-mutex@npm:0.3.2" + dependencies: + tslib: "npm:^2.3.1" + checksum: 10/cf0b02f7f916d202a727e15a64d51110c3258a719588ca263875024172aa9368efa5dbec6dc4f4fd10e35744e238e1075306a93ce86549de642d5f7d0c06bc23 languageName: node linkType: hard @@ -6985,35 +6729,21 @@ __metadata: languageName: node linkType: hard -"available-typed-arrays@npm:^1.0.7": - version: 1.0.7 - resolution: "available-typed-arrays@npm:1.0.7" - dependencies: - possible-typed-array-names: "npm:^1.0.0" - checksum: 10/6c9da3a66caddd83c875010a1ca8ef11eac02ba15fb592dc9418b2b5e7b77b645fa7729380a92d9835c2f05f2ca1b6251f39b993e0feb3f1517c74fa1af02cab - languageName: node - linkType: hard - "axios@npm:^1.7.4": - version: 1.13.5 - resolution: "axios@npm:1.13.5" + version: 1.7.5 + resolution: "axios@npm:1.7.5" dependencies: - follow-redirects: "npm:^1.15.11" - form-data: "npm:^4.0.5" + follow-redirects: "npm:^1.15.6" + form-data: "npm:^4.0.0" proxy-from-env: "npm:^1.1.0" - checksum: 10/db726d09902565ef9a0632893530028310e2ec2b95b727114eca1b101450b00014133dfc3871cffc87983fb922bca7e4874d7e2826d1550a377a157cdf3f05b6 + checksum: 10/6cbcfe943a84089f420a900a3a3aeb54ee94dcc9c2b81b150434896357be5d1079eff0b1bbb628597371e79f896b1bc5776df04184756ba99656ff31df9a75bf languageName: node linkType: hard "b4a@npm:^1.6.4": - version: 1.8.0 - resolution: "b4a@npm:1.8.0" - peerDependencies: - react-native-b4a: "*" - peerDependenciesMeta: - react-native-b4a: - optional: true - checksum: 10/ce85601eef7f68f81320c2bcadd96a0c1be654bcb8c10622f73ef8b99762a323b1f3a3603dfaee557bd706a7326e372b8e5544b8746f5096ef4d3612ee4da061 + version: 1.6.6 + resolution: "b4a@npm:1.6.6" + checksum: 10/6154a36bd78b53ecd2843a829352532a1bf9fc8081dab339ba06ca3c9ffcf25d340c3b18fe4ba0fc17a546a54c1ed814cea92cd6b895f6bd2837ca4ee0fc9f52 languageName: node linkType: hard @@ -7060,8 +6790,8 @@ __metadata: linkType: hard "babel-preset-current-node-syntax@npm:^1.0.0": - version: 1.2.0 - resolution: "babel-preset-current-node-syntax@npm:1.2.0" + version: 1.1.0 + resolution: "babel-preset-current-node-syntax@npm:1.1.0" dependencies: "@babel/plugin-syntax-async-generators": "npm:^7.8.4" "@babel/plugin-syntax-bigint": "npm:^7.8.3" @@ -7079,8 +6809,8 @@ __metadata: "@babel/plugin-syntax-private-property-in-object": "npm:^7.14.5" "@babel/plugin-syntax-top-level-await": "npm:^7.14.5" peerDependencies: - "@babel/core": ^7.0.0 || ^8.0.0-0 - checksum: 10/3608fa671cfa46364ea6ec704b8fcdd7514b7b70e6ec09b1199e13ae73ed346c51d5ce2cb6d4d5b295f6a3f2cad1fdeec2308aa9e037002dd7c929194cc838ea + "@babel/core": ^7.0.0 + checksum: 10/46331111ae72b7121172fd9e6a4a7830f651ad44bf26dbbf77b3c8a60a18009411a3eacb5e72274004290c110371230272109957d5224d155436b4794ead2f1b languageName: node linkType: hard @@ -7113,31 +6843,19 @@ __metadata: languageName: node linkType: hard -"balanced-match@npm:^4.0.2": - version: 4.0.4 - resolution: "balanced-match@npm:4.0.4" - checksum: 10/fb07bb66a0959c2843fc055838047e2a95ccebb837c519614afb067ebfdf2fa967ca8d712c35ced07f2cd26fc6f07964230b094891315ad74f11eba3d53178a0 - languageName: node - linkType: hard - -"bare-events@npm:^2.7.0": - version: 2.8.2 - resolution: "bare-events@npm:2.8.2" - peerDependencies: - bare-abort-controller: "*" - peerDependenciesMeta: - bare-abort-controller: - optional: true - checksum: 10/f31848ea2f5627c3a50aadfc17e518a602629f7a6671da1352975cc6c8a520441fcc9d93c0a21f8f95de65b1a5133fcd5f766d312f3d5a326dde4fe7d2fc575f +"bare-events@npm:^2.2.0": + version: 2.4.2 + resolution: "bare-events@npm:2.4.2" + checksum: 10/c1006ad13b7e62a412466d4eac8466b4ceb46ce84a5e2fc164cd4b10edaaa5016adc684147134b67a6a3865aaf5aa007191647bdb5dbf859b1d5735d2a9ddf3b languageName: node linkType: hard "base-x@npm:^3.0.2": - version: 3.0.11 - resolution: "base-x@npm:3.0.11" + version: 3.0.10 + resolution: "base-x@npm:3.0.10" dependencies: safe-buffer: "npm:^5.0.1" - checksum: 10/c2e3c443fd07cb9b9d3e179a9e9c581daa31881005841fe8d6a834e534505890fedf03465ccf14512da60e3f7be00fe66167806b159ba076d2c03952ae7460c4 + checksum: 10/52307739559e81d9980889de2359cb4f816cc0eb9a463028fa3ab239ab913d9044a1b47b4520f98e68453df32a457b8ba58b8d0ee7e757fc3fb971f3fa7a1482 languageName: node linkType: hard @@ -7155,15 +6873,6 @@ __metadata: languageName: node linkType: hard -"baseline-browser-mapping@npm:^2.9.0": - version: 2.10.0 - resolution: "baseline-browser-mapping@npm:2.10.0" - bin: - baseline-browser-mapping: dist/cli.cjs - checksum: 10/8145e076e4299f04c7a412e6ea63803e330153cd89c47b5303f9b56b58078f4c3d5a5b5332c1069da889e76facacca4d43f8940375f7e73ce0a4d96214332953 - languageName: node - linkType: hard - "bech32@npm:1.1.4": version: 1.1.4 resolution: "bech32@npm:1.1.4" @@ -7179,9 +6888,9 @@ __metadata: linkType: hard "bignumber.js@npm:^9.1.2": - version: 9.3.1 - resolution: "bignumber.js@npm:9.3.1" - checksum: 10/1be0372bf0d6d29d0a49b9e6a9cefbd54dad9918232ad21fcd4ec39030260773abf0c76af960c6b3b98d3115a3a71e61c6a111812d1395040a039cfa178e0245 + version: 9.1.2 + resolution: "bignumber.js@npm:9.1.2" + checksum: 10/d89b8800a987225d2c00dcbf8a69dc08e92aa0880157c851c287b307d31ceb2fc2acb0c62c3e3a3d42b6c5fcae9b004035f13eb4386e56d529d7edac18d5c9d8 languageName: node linkType: hard @@ -7237,64 +6946,55 @@ __metadata: linkType: hard "bn.js@npm:^4.11.9": - version: 4.12.3 - resolution: "bn.js@npm:4.12.3" - checksum: 10/57ed5a055f946f3e009f1589c45a5242db07f3dddfc72e4506f0dd9d8b145f0dbee4edabc2499288f3fc338eb712fb96a1c623a2ed2bcd49781df1a64db64dd1 + version: 4.12.0 + resolution: "bn.js@npm:4.12.0" + checksum: 10/10f8db196d3da5adfc3207d35d0a42aa29033eb33685f20ba2c36cadfe2de63dad05df0a20ab5aae01b418d1c4b3d4d205273085262fa020d17e93ff32b67527 languageName: node linkType: hard "bn.js@npm:^5.1.2, bn.js@npm:^5.2.0, bn.js@npm:^5.2.1, bn.js@npm:^5.2.2": - version: 5.2.3 - resolution: "bn.js@npm:5.2.3" - checksum: 10/dfb3927e0d531e6ec4f191597ce6f7f7665310c356fef5f968ada676b8058027f959af42eaa37b5f5c63617e819d3741813025ab15dd71a90f2e74698df0b58e + version: 5.2.2 + resolution: "bn.js@npm:5.2.2" + checksum: 10/51ebb2df83b33e5d8581165206e260d5e9c873752954616e5bf3758952b84d7399a9c6d00852815a0aeefb1150a7f34451b62d4287342d457fa432eee869e83e languageName: node linkType: hard -"body-parser@npm:~1.20.3": - version: 1.20.4 - resolution: "body-parser@npm:1.20.4" +"body-parser@npm:1.20.3": + version: 1.20.3 + resolution: "body-parser@npm:1.20.3" dependencies: - bytes: "npm:~3.1.2" + bytes: "npm:3.1.2" content-type: "npm:~1.0.5" debug: "npm:2.6.9" depd: "npm:2.0.0" - destroy: "npm:~1.2.0" - http-errors: "npm:~2.0.1" - iconv-lite: "npm:~0.4.24" - on-finished: "npm:~2.4.1" - qs: "npm:~6.14.0" - raw-body: "npm:~2.5.3" + destroy: "npm:1.2.0" + http-errors: "npm:2.0.0" + iconv-lite: "npm:0.4.24" + on-finished: "npm:2.4.1" + qs: "npm:6.13.0" + raw-body: "npm:2.5.2" type-is: "npm:~1.6.18" - unpipe: "npm:~1.0.0" - checksum: 10/ff67e28d3f426707be8697a75fdf8d564dc50c341b41f054264d8ab6e2924e519c7ce8acc9d0de05328fdc41e1d9f3f200aec9c1cfb1867d6b676a410d97c689 + unpipe: "npm:1.0.0" + checksum: 10/8723e3d7a672eb50854327453bed85ac48d045f4958e81e7d470c56bf111f835b97e5b73ae9f6393d0011cc9e252771f46fd281bbabc57d33d3986edf1e6aeca languageName: node linkType: hard "brace-expansion@npm:^1.1.7": - version: 1.1.12 - resolution: "brace-expansion@npm:1.1.12" + version: 1.1.11 + resolution: "brace-expansion@npm:1.1.11" dependencies: balanced-match: "npm:^1.0.0" concat-map: "npm:0.0.1" - checksum: 10/12cb6d6310629e3048cadb003e1aca4d8c9bb5c67c3c321bafdd7e7a50155de081f78ea3e0ed92ecc75a9015e784f301efc8132383132f4f7904ad1ac529c562 + checksum: 10/faf34a7bb0c3fcf4b59c7808bc5d2a96a40988addf2e7e09dfbb67a2251800e0d14cd2bfc1aa79174f2f5095c54ff27f46fb1289fe2d77dac755b5eb3434cc07 languageName: node linkType: hard "brace-expansion@npm:^2.0.1": - version: 2.0.2 - resolution: "brace-expansion@npm:2.0.2" + version: 2.0.1 + resolution: "brace-expansion@npm:2.0.1" dependencies: balanced-match: "npm:^1.0.0" - checksum: 10/01dff195e3646bc4b0d27b63d9bab84d2ebc06121ff5013ad6e5356daa5a9d6b60fa26cf73c74797f2dc3fbec112af13578d51f75228c1112b26c790a87b0488 - languageName: node - linkType: hard - -"brace-expansion@npm:^5.0.2": - version: 5.0.3 - resolution: "brace-expansion@npm:5.0.3" - dependencies: - balanced-match: "npm:^4.0.2" - checksum: 10/8ba7deae4ca333d52418d2cde3287ac23f44f7330d92c3ecd96a8941597bea8aab02227bd990944d6711dd549bcc6e550fe70be5d94aa02e2fdc88942f480c9b + checksum: 10/a61e7cd2e8a8505e9f0036b3b6108ba5e926b4b55089eeb5550cd04a471fe216c96d4fe7e4c7f995c728c554ae20ddfc4244cad10aef255e72b62930afd233d1 languageName: node linkType: hard @@ -7329,17 +7029,16 @@ __metadata: linkType: hard "browserslist@npm:^4.24.0": - version: 4.28.1 - resolution: "browserslist@npm:4.28.1" - dependencies: - baseline-browser-mapping: "npm:^2.9.0" - caniuse-lite: "npm:^1.0.30001759" - electron-to-chromium: "npm:^1.5.263" - node-releases: "npm:^2.0.27" - update-browserslist-db: "npm:^1.2.0" + version: 4.24.4 + resolution: "browserslist@npm:4.24.4" + dependencies: + caniuse-lite: "npm:^1.0.30001688" + electron-to-chromium: "npm:^1.5.73" + node-releases: "npm:^2.0.19" + update-browserslist-db: "npm:^1.1.1" bin: browserslist: cli.js - checksum: 10/64f2a97de4bce8473c0e5ae0af8d76d1ead07a5b05fc6bc87b848678bb9c3a91ae787b27aa98cdd33fc00779607e6c156000bed58fefb9cf8e4c5a183b994cdb + checksum: 10/11fda105e803d891311a21a1f962d83599319165faf471c2d70e045dff82a12128f5b50b1fcba665a2352ad66147aaa248a9d2355a80aadc3f53375eb3de2e48 languageName: node linkType: hard @@ -7414,29 +7113,30 @@ __metadata: languageName: node linkType: hard -"bytes@npm:~3.1.2": +"bytes@npm:3.1.2": version: 3.1.2 resolution: "bytes@npm:3.1.2" checksum: 10/a10abf2ba70c784471d6b4f58778c0beeb2b5d405148e66affa91f23a9f13d07603d0a0354667310ae1d6dc141474ffd44e2a074be0f6e2254edb8fc21445388 languageName: node linkType: hard -"cacache@npm:^20.0.1": - version: 20.0.3 - resolution: "cacache@npm:20.0.3" +"cacache@npm:^18.0.0": + version: 18.0.4 + resolution: "cacache@npm:18.0.4" dependencies: - "@npmcli/fs": "npm:^5.0.0" + "@npmcli/fs": "npm:^3.1.0" fs-minipass: "npm:^3.0.0" - glob: "npm:^13.0.0" - lru-cache: "npm:^11.1.0" + glob: "npm:^10.2.2" + lru-cache: "npm:^10.0.1" minipass: "npm:^7.0.3" minipass-collect: "npm:^2.0.1" minipass-flush: "npm:^1.0.5" minipass-pipeline: "npm:^1.2.4" - p-map: "npm:^7.0.2" - ssri: "npm:^13.0.0" - unique-filename: "npm:^5.0.0" - checksum: 10/388a0169970df9d051da30437f93f81b7e91efb570ad0ff2b8fde33279fbe726c1bc8e8e2b9c05053ffb4f563854c73db395e8712e3b62347a1bc4f7fb8899ff + p-map: "npm:^4.0.0" + ssri: "npm:^10.0.0" + tar: "npm:^6.1.11" + unique-filename: "npm:^3.0.0" + checksum: 10/ca2f7b2d3003f84d362da9580b5561058ccaecd46cba661cbcff0375c90734b610520d46b472a339fd032d91597ad6ed12dde8af81571197f3c9772b5d35b104 languageName: node linkType: hard @@ -7450,7 +7150,7 @@ __metadata: languageName: node linkType: hard -"call-bind@npm:^1.0.8": +"call-bind@npm:^1.0.7": version: 1.0.8 resolution: "call-bind@npm:1.0.8" dependencies: @@ -7462,16 +7162,6 @@ __metadata: languageName: node linkType: hard -"call-bound@npm:^1.0.2, call-bound@npm:^1.0.3, call-bound@npm:^1.0.4": - version: 1.0.4 - resolution: "call-bound@npm:1.0.4" - dependencies: - call-bind-apply-helpers: "npm:^1.0.2" - get-intrinsic: "npm:^1.3.0" - checksum: 10/ef2b96e126ec0e58a7ff694db43f4d0d44f80e641370c21549ed911fecbdbc2df3ebc9bddad918d6bbdefeafb60bb3337902006d5176d72bcd2da74820991af7 - languageName: node - linkType: hard - "callsite@npm:^1.0.0": version: 1.0.0 resolution: "callsite@npm:1.0.0" @@ -7511,10 +7201,10 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.30001759": - version: 1.0.30001774 - resolution: "caniuse-lite@npm:1.0.30001774" - checksum: 10/63c87aeac08548847ecd12746144029761707d9eae57750f673543a2b2a6126bca98584dd551818e8dc2a480d11489bebe0027af26de4ee46466e7b216109862 +"caniuse-lite@npm:^1.0.30001688": + version: 1.0.30001690 + resolution: "caniuse-lite@npm:1.0.30001690" + checksum: 10/9fb4659eb09a298601b9593739072c481e2f5cc524bd0530e5e0f002e66246da5e866669854dfc0d53195ee36b201dab02f7933a7cdf60ccba7adb2d4a304caf languageName: node linkType: hard @@ -7528,10 +7218,10 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^5.3.0, chalk@npm:^5.4.1": - version: 5.6.2 - resolution: "chalk@npm:5.6.2" - checksum: 10/1b2f48f6fba1370670d5610f9cd54c391d6ede28f4b7062dd38244ea5768777af72e5be6b74fb6c6d54cb84c4a2dff3f3afa9b7cb5948f7f022cfd3d087989e0 +"chalk@npm:^5.3.0": + version: 5.3.0 + resolution: "chalk@npm:5.3.0" + checksum: 10/6373caaab21bd64c405bfc4bd9672b145647fc9482657b5ea1d549b3b2765054e9d3d928870cdf764fb4aad67555f5061538ff247b8310f110c5c888d92397ea languageName: node linkType: hard @@ -7542,6 +7232,13 @@ __metadata: languageName: node linkType: hard +"chownr@npm:^2.0.0": + version: 2.0.0 + resolution: "chownr@npm:2.0.0" + checksum: 10/c57cf9dd0791e2f18a5ee9c1a299ae6e801ff58fee96dc8bfd0dcb4738a6ce58dd252a3605b1c93c6418fe4f9d5093b28ffbf4d66648cb2a9c67eaef9679be2f + languageName: node + linkType: hard + "chownr@npm:^3.0.0": version: 3.0.0 resolution: "chownr@npm:3.0.0" @@ -7563,28 +7260,27 @@ __metadata: languageName: node linkType: hard -"ci-info@npm:^4.2.0": - version: 4.4.0 - resolution: "ci-info@npm:4.4.0" - checksum: 10/dfded0c630267d89660c8abb988ac8395a382bdfefedcc03e3e2858523312c5207db777c239c34774e3fcff11f015477c19d2ac8a58ea58aa476614a2e64f434 - languageName: node - linkType: hard - "cipher-base@npm:^1.0.0, cipher-base@npm:^1.0.1, cipher-base@npm:^1.0.3": - version: 1.0.7 - resolution: "cipher-base@npm:1.0.7" + version: 1.0.4 + resolution: "cipher-base@npm:1.0.4" dependencies: - inherits: "npm:^2.0.4" - safe-buffer: "npm:^5.2.1" - to-buffer: "npm:^1.2.2" - checksum: 10/9501d2241b7968aaae74fc3db1d6a69a804e0b14117a8fd5d811edf351fcd39a1807bfd98e090a799cfe98b183fbf2e01ebb57f1239080850db07b68dcd9ba02 + inherits: "npm:^2.0.1" + safe-buffer: "npm:^5.0.1" + checksum: 10/3d5d6652ca499c3f7c5d7fdc2932a357ec1e5aa84f2ad766d850efd42e89753c97b795c3a104a8e7ae35b4e293f5363926913de3bf8181af37067d9d541ca0db languageName: node linkType: hard "cjs-module-lexer@npm:^1.0.0, cjs-module-lexer@npm:^1.3.1": - version: 1.4.3 - resolution: "cjs-module-lexer@npm:1.4.3" - checksum: 10/d2b92f919a2dedbfd61d016964fce8da0035f827182ed6839c97cac56e8a8077cfa6a59388adfe2bc588a19cef9bbe830d683a76a6e93c51f65852062cfe2591 + version: 1.4.0 + resolution: "cjs-module-lexer@npm:1.4.0" + checksum: 10/b041096749792526120d8b8756929f8ef5dd4596502a0e1013f857e3027acd6091915fea77037921d70ee1a99988a100d994d3d3c2e323b04dd4c5ffd516cf13 + languageName: node + linkType: hard + +"clean-stack@npm:^2.0.0": + version: 2.2.0 + resolution: "clean-stack@npm:2.2.0" + checksum: 10/2ac8cd2b2f5ec986a3c743935ec85b07bc174d5421a5efc8017e1f146a1cf5f781ae962618f416352103b32c9cd7e203276e8c28241bbe946160cab16149fb68 languageName: node linkType: hard @@ -7646,9 +7342,9 @@ __metadata: linkType: hard "collect-v8-coverage@npm:^1.0.0": - version: 1.0.3 - resolution: "collect-v8-coverage@npm:1.0.3" - checksum: 10/656443261fb7b79cf79e89cba4b55622b07c1d4976c630829d7c5c585c73cda1c2ff101f316bfb19bb9e2c58d724c7db1f70a21e213dcd14099227c5e6019860 + version: 1.0.2 + resolution: "collect-v8-coverage@npm:1.0.2" + checksum: 10/30ea7d5c9ee51f2fdba4901d4186c5b7114a088ef98fd53eda3979da77eed96758a2cae81cc6d97e239aaea6065868cf908b24980663f7b7e96aa291b3e12fa4 languageName: node linkType: hard @@ -7677,10 +7373,10 @@ __metadata: languageName: node linkType: hard -"commander@npm:^14.0.0": - version: 14.0.3 - resolution: "commander@npm:14.0.3" - checksum: 10/dfa9ebe2a433d277de5cb0252d23b10a543d245d892db858d23b516336a835c50fd4f52bee4cd13c705cc8acb6f03dc632c73dd806f7d06d3353eb09953dd17a +"commander@npm:^12.1.0": + version: 12.1.0 + resolution: "commander@npm:12.1.0" + checksum: 10/cdaeb672d979816853a4eed7f1310a9319e8b976172485c2a6b437ed0db0a389a44cfb222bfbde772781efa9f215bdd1b936f80d6b249485b465c6cb906e1f93 languageName: node linkType: hard @@ -7709,13 +7405,6 @@ __metadata: languageName: node linkType: hard -"comment-parser@npm:^1.4.1": - version: 1.4.5 - resolution: "comment-parser@npm:1.4.5" - checksum: 10/4b5cacc7ab1ec48e3f51b788bd7cda567f5c83040e029e5c92eacf0785735a9b44ac49fdaf73d9bd4af9464aa4cc8cc7184902090b55b0023605a845f2666ba4 - languageName: node - linkType: hard - "concat-map@npm:0.0.1": version: 0.0.1 resolution: "concat-map@npm:0.0.1" @@ -7735,7 +7424,7 @@ __metadata: languageName: node linkType: hard -"content-disposition@npm:~0.5.4": +"content-disposition@npm:0.5.4": version: 0.5.4 resolution: "content-disposition@npm:0.5.4" dependencies: @@ -7752,30 +7441,30 @@ __metadata: linkType: hard "contentful-resolve-response@npm:^1.9.0": - version: 1.9.6 - resolution: "contentful-resolve-response@npm:1.9.6" + version: 1.9.0 + resolution: "contentful-resolve-response@npm:1.9.0" dependencies: - fast-copy: "npm:^3.0.2" - checksum: 10/ce77702a19c090eafc5e3e3b371ecf2531d6d149d450a36098d76e0888a7046c95ebabbe110643ad5824dbf6eedb13693fe4dd81f914c467dea6c6a50058d541 + fast-copy: "npm:^2.1.7" + checksum: 10/0c5daa59a3a6b020f9b5316812e3f14e62833b4aead008527c5bfde6549365e8e8e9f373af8836f06ca7b2023d861fdd2c241d3e74d3797133d18983be8bb3b3 languageName: node linkType: hard "contentful-sdk-core@npm:^8.3.1": - version: 8.3.2 - resolution: "contentful-sdk-core@npm:8.3.2" + version: 8.3.1 + resolution: "contentful-sdk-core@npm:8.3.1" dependencies: fast-copy: "npm:^2.1.7" lodash.isplainobject: "npm:^4.0.6" lodash.isstring: "npm:^4.0.1" p-throttle: "npm:^4.1.1" qs: "npm:^6.11.2" - checksum: 10/4af0aba2bb7e3db3ebf260fea74843de89f150f5af883134c370eb695fd8b2587cf94d4524d03020286f565eb3bff7b12d42f2a38718b62eb75cb28556e40f42 + checksum: 10/645d3a5d296d0e2a5ce87cceb04cf1ddf572183b5946cb1b3b717436bc7be96864216225fb845e61850d580436021c6284e7c95da0600a16c89c0af81a5f0d2c languageName: node linkType: hard "contentful@npm:^10.15.0": - version: 10.15.1 - resolution: "contentful@npm:10.15.1" + version: 10.15.0 + resolution: "contentful@npm:10.15.0" dependencies: "@contentful/content-source-maps": "npm:^0.11.0" "@contentful/rich-text-types": "npm:^16.0.2" @@ -7784,7 +7473,7 @@ __metadata: contentful-sdk-core: "npm:^8.3.1" json-stringify-safe: "npm:^5.0.1" type-fest: "npm:^4.0.0" - checksum: 10/eb913a79e38d87bc7fb3a79952e4d7c5a1de5cccfbe0a012e8131c9c1e5a0a525cfcb7eaea971b02fb9e57b9e49c71ce96dd7096c3f65483992017ef70de80e5 + checksum: 10/b57c51faa99074a2f60c930c4827d1f8fe9867a359e53738532bbe859f5d72e750645fa4e195e65ad015811f344d95a0b3cebe6debef7d4e92ce9510bd55939e languageName: node linkType: hard @@ -7795,17 +7484,17 @@ __metadata: languageName: node linkType: hard -"cookie-signature@npm:~1.0.6": - version: 1.0.7 - resolution: "cookie-signature@npm:1.0.7" - checksum: 10/1a62808cd30d15fb43b70e19829b64d04b0802d8ef00275b57d152de4ae6a3208ca05c197b6668d104c4d9de389e53ccc2d3bc6bcaaffd9602461417d8c40710 +"cookie-signature@npm:1.0.6": + version: 1.0.6 + resolution: "cookie-signature@npm:1.0.6" + checksum: 10/f4e1b0a98a27a0e6e66fd7ea4e4e9d8e038f624058371bf4499cfcd8f3980be9a121486995202ba3fca74fbed93a407d6d54d43a43f96fd28d0bd7a06761591a languageName: node linkType: hard -"cookie@npm:~0.7.1": - version: 0.7.2 - resolution: "cookie@npm:0.7.2" - checksum: 10/24b286c556420d4ba4e9bc09120c9d3db7d28ace2bd0f8ccee82422ce42322f73c8312441271e5eefafbead725980e5996cc02766dbb89a90ac7f5636ede608f +"cookie@npm:0.7.1": + version: 0.7.1 + resolution: "cookie@npm:0.7.1" + checksum: 10/aec6a6aa0781761bf55d60447d6be08861d381136a0fe94aa084fddd4f0300faa2b064df490c6798adfa1ebaef9e0af9b08a189c823e0811b8b313b3d9a03380 languageName: node linkType: hard @@ -7858,7 +7547,7 @@ __metadata: languageName: node linkType: hard -"create-hmac@npm:^1.1.7": +"create-hmac@npm:^1.1.4, create-hmac@npm:^1.1.7": version: 1.1.7 resolution: "create-hmac@npm:1.1.7" dependencies: @@ -7898,7 +7587,7 @@ __metadata: languageName: node linkType: hard -"cross-spawn@npm:^7.0.3, cross-spawn@npm:^7.0.6": +"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.3, cross-spawn@npm:^7.0.6": version: 7.0.6 resolution: "cross-spawn@npm:7.0.6" dependencies: @@ -7952,7 +7641,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.4.0, debug@npm:^4.4.1, debug@npm:^4.4.3": +"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.3.6, debug@npm:^4.3.7, debug@npm:^4.4.3": version: 4.4.3 resolution: "debug@npm:4.4.3" dependencies: @@ -7964,6 +7653,15 @@ __metadata: languageName: node linkType: hard +"debug@npm:^3.2.7": + version: 3.2.7 + resolution: "debug@npm:3.2.7" + dependencies: + ms: "npm:^2.1.1" + checksum: 10/d86fd7be2b85462297ea16f1934dc219335e802f629ca9a69b63ed8ed041dda492389bb2ee039217c02e5b54792b1c51aa96ae954cf28634d363a2360c7a1639 + languageName: node + linkType: hard + "decamelize-keys@npm:^1.1.0": version: 1.1.1 resolution: "decamelize-keys@npm:1.1.1" @@ -8022,19 +7720,19 @@ __metadata: linkType: hard "default-browser-id@npm:^5.0.0": - version: 5.0.1 - resolution: "default-browser-id@npm:5.0.1" - checksum: 10/52c637637bcd76bfe974462a2f1dd75cb04784c2852935575760f82e1fd338e5e80d3c45a9b01fdbb1e450553a830bb163b004d2eca223c5573989f82232a072 + version: 5.0.0 + resolution: "default-browser-id@npm:5.0.0" + checksum: 10/185bfaecec2c75fa423544af722a3469b20704c8d1942794a86e4364fe7d9e8e9f63241a5b769d61c8151993bc65833a5b959026fa1ccea343b3db0a33aa6deb languageName: node linkType: hard "default-browser@npm:^5.2.1": - version: 5.5.0 - resolution: "default-browser@npm:5.5.0" + version: 5.2.1 + resolution: "default-browser@npm:5.2.1" dependencies: bundle-name: "npm:^4.1.0" default-browser-id: "npm:^5.0.0" - checksum: 10/c5c5d84a4abd82850e98f06798a55dee87fc1064538bea00cc14c0fb2dccccbff5e9e07eeea80385fa653202d5d92509838b4239d610ddfa1c76a04a1f65e767 + checksum: 10/afab7eff7b7f5f7a94d9114d1ec67273d3fbc539edf8c0f80019879d53aa71e867303c6f6d7cffeb10a6f3cfb59d4f963dba3f9c96830b4540cc7339a1bf9840 languageName: node linkType: hard @@ -8096,7 +7794,7 @@ __metadata: languageName: node linkType: hard -"depd@npm:2.0.0, depd@npm:~2.0.0": +"depd@npm:2.0.0": version: 2.0.0 resolution: "depd@npm:2.0.0" checksum: 10/c0c8ff36079ce5ada64f46cc9d6fd47ebcf38241105b6e0c98f412e8ad91f084bcf906ff644cc3a4bd876ca27a62accb8b0fff72ea6ed1a414b89d8506f4a5ca @@ -8110,7 +7808,7 @@ __metadata: languageName: node linkType: hard -"destroy@npm:1.2.0, destroy@npm:~1.2.0": +"destroy@npm:1.2.0": version: 1.2.0 resolution: "destroy@npm:1.2.0" checksum: 10/0acb300b7478a08b92d810ab229d5afe0d2f4399272045ab22affa0d99dbaf12637659411530a6fcd597a9bdac718fc94373a61a95b4651bbc7b83684a565e38 @@ -8131,10 +7829,10 @@ __metadata: languageName: node linkType: hard -"detect-indent@npm:^7.0.2": - version: 7.0.2 - resolution: "detect-indent@npm:7.0.2" - checksum: 10/ef215d1b55a14f677ce03e840973b25362b6f8cd3f566bc82831fa1abb2be6a95423729bc573dc2334b1371ad7be18d9ec67e1a9611b71a04cb6d63f0d8e54cc +"detect-indent@npm:^7.0.1": + version: 7.0.1 + resolution: "detect-indent@npm:7.0.1" + checksum: 10/cbf3f0b1c3c881934ca94428e1179b26ab2a587e0d719031d37a67fb506d49d067de54ff057cb1e772e75975fed5155c01cd4518306fee60988b1486e3fc7768 languageName: node linkType: hard @@ -8145,7 +7843,7 @@ __metadata: languageName: node linkType: hard -"detect-newline@npm:^4.0.1": +"detect-newline@npm:^4.0.0": version: 4.0.1 resolution: "detect-newline@npm:4.0.1" checksum: 10/0409ecdfb93419591ccff24fccfe2ddddad29b66637d1ed898872125b25af05014fdeedc9306339577060f69f59fe6e9830cdd80948597f136dfbffefa60599c @@ -8167,9 +7865,9 @@ __metadata: linkType: hard "diff@npm:^5.0.0": - version: 5.2.2 - resolution: "diff@npm:5.2.2" - checksum: 10/8a885b38113d96138d87f6cb474ee959b7e9ab33c0c4cb1b07dcf019ec544945a2309d53d721532af020de4b3a58fb89f1026f64f42f9421aa9c3ae48a36998b + version: 5.2.0 + resolution: "diff@npm:5.2.0" + checksum: 10/01b7b440f83a997350a988e9d2f558366c0f90f15be19f4aa7f1bb3109a4e153dfc3b9fbf78e14ea725717017407eeaa2271e3896374a0181e8f52445740846d languageName: node linkType: hard @@ -8182,6 +7880,15 @@ __metadata: languageName: node linkType: hard +"doctrine@npm:^3.0.0": + version: 3.0.0 + resolution: "doctrine@npm:3.0.0" + dependencies: + esutils: "npm:^2.0.2" + checksum: 10/b4b28f1df5c563f7d876e7461254a4597b8cabe915abe94d7c5d1633fed263fcf9a85e8d3836591fc2d040108e822b0d32758e5ec1fe31c590dc7e08086e3e48 + languageName: node + linkType: hard + "domexception@npm:^4.0.0": version: 4.0.0 resolution: "domexception@npm:4.0.0" @@ -8225,10 +7932,10 @@ __metadata: languageName: node linkType: hard -"electron-to-chromium@npm:^1.5.263": - version: 1.5.302 - resolution: "electron-to-chromium@npm:1.5.302" - checksum: 10/0d31470d04a0d1ea046dd363370081b67e6fe822949b10cfece0a64fd2f8180afb5ccaf14f4294251e444a0af627eb0dc0156242b714c0f10561adf2a21aa5f7 +"electron-to-chromium@npm:^1.5.73": + version: 1.5.79 + resolution: "electron-to-chromium@npm:1.5.79" + checksum: 10/c5b25ba04b4f4b46c4024b96e00e43adcd6c321b48c74c8d2660f69704901da5a6592009cbf96c36c89e3f6b53d7742e2b89514477fddbccf4e5c4caebed9d49 languageName: node linkType: hard @@ -8268,6 +7975,13 @@ __metadata: languageName: node linkType: hard +"encodeurl@npm:~1.0.2": + version: 1.0.2 + resolution: "encodeurl@npm:1.0.2" + checksum: 10/e50e3d508cdd9c4565ba72d2012e65038e5d71bdc9198cb125beb6237b5b1ade6c0d343998da9e170fb2eae52c1bed37d4d6d98a46ea423a0cddbed5ac3f780c + languageName: node + linkType: hard + "encodeurl@npm:~2.0.0": version: 2.0.0 resolution: "encodeurl@npm:2.0.0" @@ -8275,13 +7989,29 @@ __metadata: languageName: node linkType: hard -"enhanced-resolve@npm:^5.17.1": - version: 5.19.0 - resolution: "enhanced-resolve@npm:5.19.0" +"encoding@npm:^0.1.13": + version: 0.1.13 + resolution: "encoding@npm:0.1.13" + dependencies: + iconv-lite: "npm:^0.6.2" + checksum: 10/bb98632f8ffa823996e508ce6a58ffcf5856330fde839ae42c9e1f436cc3b5cc651d4aeae72222916545428e54fd0f6aa8862fd8d25bdbcc4589f1e3f3715e7f + languageName: node + linkType: hard + +"enhanced-resolve@npm:^5.15.0, enhanced-resolve@npm:^5.17.1": + version: 5.18.0 + resolution: "enhanced-resolve@npm:5.18.0" dependencies: graceful-fs: "npm:^4.2.4" - tapable: "npm:^2.3.0" - checksum: 10/b537d52173bf1ba903c623f96a43ea3b51466ee2b606b2fcca30d73d453fd79c8683dccbb83523de27cd02763c906f11486e2591a4335e6afe49fa5ad6e67b83 + tapable: "npm:^2.2.0" + checksum: 10/e88463ef97b68d40d0da0cd0c572e23f43dba0be622d6d44eae5cafed05f0c5dac43e463a83a86c4f70186d029357f82b56d9e1e47e8fc91dce3d6602f8bd6ce + languageName: node + linkType: hard + +"entities@npm:^4.5.0": + version: 4.5.0 + resolution: "entities@npm:4.5.0" + checksum: 10/ede2a35c9bce1aeccd055a1b445d41c75a14a2bb1cd22e242f20cf04d236cdcd7f9c859eb83f76885327bfae0c25bf03303665ee1ce3d47c5927b98b0e3e3d48 languageName: node linkType: hard @@ -8292,13 +8022,6 @@ __metadata: languageName: node linkType: hard -"entities@npm:^7.0.1": - version: 7.0.1 - resolution: "entities@npm:7.0.1" - checksum: 10/3c0c58d869c45148463e96d21dee2d1b801bd3fe4cf47aa470cd26dfe81d59e9e0a9be92ae083fa02fa441283c883a471486e94538dcfb8544428aa80a55271b - languageName: node - linkType: hard - "env-paths@npm:^2.2.0": version: 2.2.1 resolution: "env-paths@npm:2.2.1" @@ -8314,11 +8037,11 @@ __metadata: linkType: hard "error-ex@npm:^1.3.1": - version: 1.3.4 - resolution: "error-ex@npm:1.3.4" + version: 1.3.2 + resolution: "error-ex@npm:1.3.2" dependencies: is-arrayish: "npm:^0.2.1" - checksum: 10/ae3939fd4a55b1404e877df2080c6b59acc516d5b7f08a181040f78f38b4e2399633bfed2d9a21b91c803713fff7295ac70bebd8f3657ef352a95c2cd9aa2e4b + checksum: 10/d547740aa29c34e753fb6fed2c5de81802438529c12b3673bd37b6bb1fe49b9b7abdc3c11e6062fe625d8a296b3cf769a80f878865e25e685f787763eede3ffb languageName: node linkType: hard @@ -8336,6 +8059,13 @@ __metadata: languageName: node linkType: hard +"es-module-lexer@npm:^1.5.3": + version: 1.6.0 + resolution: "es-module-lexer@npm:1.6.0" + checksum: 10/807ee7020cc46a9c970c78cad1f2f3fc139877e5ebad7f66dbfbb124d451189ba1c48c1c632bd5f8ce1b8af2caef3fca340ba044a410fa890d17b080a59024bb + languageName: node + linkType: hard + "es-object-atoms@npm:^1.0.0, es-object-atoms@npm:^1.1.1": version: 1.1.1 resolution: "es-object-atoms@npm:1.1.1" @@ -8345,48 +8075,36 @@ __metadata: languageName: node linkType: hard -"es-set-tostringtag@npm:^2.1.0": - version: 2.1.0 - resolution: "es-set-tostringtag@npm:2.1.0" - dependencies: - es-errors: "npm:^1.3.0" - get-intrinsic: "npm:^1.2.6" - has-tostringtag: "npm:^1.0.2" - hasown: "npm:^2.0.2" - checksum: 10/86814bf8afbcd8966653f731415888019d4bc4aca6b6c354132a7a75bb87566751e320369654a101d23a91c87a85c79b178bcf40332839bd347aff437c4fb65f - languageName: node - linkType: hard - -"esbuild@npm:~0.27.0": - version: 0.27.3 - resolution: "esbuild@npm:0.27.3" - dependencies: - "@esbuild/aix-ppc64": "npm:0.27.3" - "@esbuild/android-arm": "npm:0.27.3" - "@esbuild/android-arm64": "npm:0.27.3" - "@esbuild/android-x64": "npm:0.27.3" - "@esbuild/darwin-arm64": "npm:0.27.3" - "@esbuild/darwin-x64": "npm:0.27.3" - "@esbuild/freebsd-arm64": "npm:0.27.3" - "@esbuild/freebsd-x64": "npm:0.27.3" - "@esbuild/linux-arm": "npm:0.27.3" - "@esbuild/linux-arm64": "npm:0.27.3" - "@esbuild/linux-ia32": "npm:0.27.3" - "@esbuild/linux-loong64": "npm:0.27.3" - "@esbuild/linux-mips64el": "npm:0.27.3" - "@esbuild/linux-ppc64": "npm:0.27.3" - "@esbuild/linux-riscv64": "npm:0.27.3" - "@esbuild/linux-s390x": "npm:0.27.3" - "@esbuild/linux-x64": "npm:0.27.3" - "@esbuild/netbsd-arm64": "npm:0.27.3" - "@esbuild/netbsd-x64": "npm:0.27.3" - "@esbuild/openbsd-arm64": "npm:0.27.3" - "@esbuild/openbsd-x64": "npm:0.27.3" - "@esbuild/openharmony-arm64": "npm:0.27.3" - "@esbuild/sunos-x64": "npm:0.27.3" - "@esbuild/win32-arm64": "npm:0.27.3" - "@esbuild/win32-ia32": "npm:0.27.3" - "@esbuild/win32-x64": "npm:0.27.3" +"esbuild@npm:~0.25.0": + version: 0.25.9 + resolution: "esbuild@npm:0.25.9" + dependencies: + "@esbuild/aix-ppc64": "npm:0.25.9" + "@esbuild/android-arm": "npm:0.25.9" + "@esbuild/android-arm64": "npm:0.25.9" + "@esbuild/android-x64": "npm:0.25.9" + "@esbuild/darwin-arm64": "npm:0.25.9" + "@esbuild/darwin-x64": "npm:0.25.9" + "@esbuild/freebsd-arm64": "npm:0.25.9" + "@esbuild/freebsd-x64": "npm:0.25.9" + "@esbuild/linux-arm": "npm:0.25.9" + "@esbuild/linux-arm64": "npm:0.25.9" + "@esbuild/linux-ia32": "npm:0.25.9" + "@esbuild/linux-loong64": "npm:0.25.9" + "@esbuild/linux-mips64el": "npm:0.25.9" + "@esbuild/linux-ppc64": "npm:0.25.9" + "@esbuild/linux-riscv64": "npm:0.25.9" + "@esbuild/linux-s390x": "npm:0.25.9" + "@esbuild/linux-x64": "npm:0.25.9" + "@esbuild/netbsd-arm64": "npm:0.25.9" + "@esbuild/netbsd-x64": "npm:0.25.9" + "@esbuild/openbsd-arm64": "npm:0.25.9" + "@esbuild/openbsd-x64": "npm:0.25.9" + "@esbuild/openharmony-arm64": "npm:0.25.9" + "@esbuild/sunos-x64": "npm:0.25.9" + "@esbuild/win32-arm64": "npm:0.25.9" + "@esbuild/win32-ia32": "npm:0.25.9" + "@esbuild/win32-x64": "npm:0.25.9" dependenciesMeta: "@esbuild/aix-ppc64": optional: true @@ -8442,7 +8160,7 @@ __metadata: optional: true bin: esbuild: bin/esbuild - checksum: 10/aa74b8d8a3ed8e2eea4d8421737b322f4d21215244e8fa2156c6402d49b5bda01343c220196f1e3f830a7ce92b54ef653c6c723a8cc2e912bb4d17b7398b51ae + checksum: 10/fc174ae7f646ad413adb641c7e46f16be575e462ed209866b55d5954d382e5da839e3f3f89a8e42e2b71d48895cc636ba43523011249fe5ff9c63d8d39d3a364 languageName: node linkType: hard @@ -8504,13 +8222,13 @@ __metadata: linkType: hard "eslint-config-prettier@npm:^9.1.0": - version: 9.1.2 - resolution: "eslint-config-prettier@npm:9.1.2" + version: 9.1.0 + resolution: "eslint-config-prettier@npm:9.1.0" peerDependencies: eslint: ">=7.0.0" bin: eslint-config-prettier: bin/cli.js - checksum: 10/e4bba2d76df9dc6e2adca2866e544bfd1ff32232fc483743c04cedd93918a90a327b56d4a7e3f9d3fa32d90bd50b034d09df987860260064b18c026b8bbd15aa + checksum: 10/411e3b3b1c7aa04e3e0f20d561271b3b909014956c4dba51c878bf1a23dbb8c800a3be235c46c4732c70827276e540b6eed4636d9b09b444fd0a8e07f0fcd830 languageName: node linkType: hard @@ -8530,32 +8248,29 @@ __metadata: languageName: node linkType: hard -"eslint-import-context@npm:^0.1.9": - version: 0.1.9 - resolution: "eslint-import-context@npm:0.1.9" +"eslint-import-resolver-node@npm:^0.3.9": + version: 0.3.9 + resolution: "eslint-import-resolver-node@npm:0.3.9" dependencies: - get-tsconfig: "npm:^4.10.1" - stable-hash-x: "npm:^0.2.0" - peerDependencies: - unrs-resolver: ^1.0.0 - peerDependenciesMeta: - unrs-resolver: - optional: true - checksum: 10/f0778126bb3aae57c8c68946c71c4418927e9d39f72099b799d9c47a3b5712d6c9166b63ee8be58a020961dcc9216df09c856b825336af375ccbbdeedfc82a99 + debug: "npm:^3.2.7" + is-core-module: "npm:^2.13.0" + resolve: "npm:^1.22.4" + checksum: 10/d52e08e1d96cf630957272e4f2644dcfb531e49dcfd1edd2e07e43369eb2ec7a7d4423d417beee613201206ff2efa4eb9a582b5825ee28802fc7c71fcd53ca83 languageName: node linkType: hard "eslint-import-resolver-typescript@npm:^3.6.3": - version: 3.10.1 - resolution: "eslint-import-resolver-typescript@npm:3.10.1" + version: 3.7.0 + resolution: "eslint-import-resolver-typescript@npm:3.7.0" dependencies: "@nolyfill/is-core-module": "npm:1.0.39" - debug: "npm:^4.4.0" - get-tsconfig: "npm:^4.10.0" - is-bun-module: "npm:^2.0.0" - stable-hash: "npm:^0.0.5" - tinyglobby: "npm:^0.2.13" - unrs-resolver: "npm:^1.6.2" + debug: "npm:^4.3.7" + enhanced-resolve: "npm:^5.15.0" + fast-glob: "npm:^3.3.2" + get-tsconfig: "npm:^4.7.5" + is-bun-module: "npm:^1.0.2" + is-glob: "npm:^4.0.3" + stable-hash: "npm:^0.0.4" peerDependencies: eslint: "*" eslint-plugin-import: "*" @@ -8565,7 +8280,7 @@ __metadata: optional: true eslint-plugin-import-x: optional: true - checksum: 10/b8d6a9b2045c70f043f722f78c9e65bc0283126f0ad92c8f07473f7647d77f7b1562f765a472f17e06b81897b407091c0ec9f2e4592b158c9fd92d0b0c33de89 + checksum: 10/8158730c11e562c56ed9bf7236dc75bce35b6992dc32c39ac2f4177ab77fca97b95999850204a6458054243607b54aee88c028a61fed4184f24f425fa1afff01 languageName: node linkType: hard @@ -8583,34 +8298,31 @@ __metadata: linkType: hard "eslint-plugin-import-x@npm:^4.3.0": - version: 4.16.1 - resolution: "eslint-plugin-import-x@npm:4.16.1" + version: 4.6.1 + resolution: "eslint-plugin-import-x@npm:4.6.1" dependencies: - "@typescript-eslint/types": "npm:^8.35.0" - comment-parser: "npm:^1.4.1" - debug: "npm:^4.4.1" - eslint-import-context: "npm:^0.1.9" + "@types/doctrine": "npm:^0.0.9" + "@typescript-eslint/scope-manager": "npm:^8.1.0" + "@typescript-eslint/utils": "npm:^8.1.0" + debug: "npm:^4.3.4" + doctrine: "npm:^3.0.0" + enhanced-resolve: "npm:^5.17.1" + eslint-import-resolver-node: "npm:^0.3.9" + get-tsconfig: "npm:^4.7.3" is-glob: "npm:^4.0.3" - minimatch: "npm:^9.0.3 || ^10.0.1" - semver: "npm:^7.7.2" - stable-hash-x: "npm:^0.2.0" - unrs-resolver: "npm:^1.9.2" + minimatch: "npm:^9.0.3" + semver: "npm:^7.6.3" + stable-hash: "npm:^0.0.4" + tslib: "npm:^2.6.3" peerDependencies: - "@typescript-eslint/utils": ^8.0.0 eslint: ^8.57.0 || ^9.0.0 - eslint-import-resolver-node: "*" - peerDependenciesMeta: - "@typescript-eslint/utils": - optional: true - eslint-import-resolver-node: - optional: true - checksum: 10/d1390d49499b613c1334e48fe8b104221584a1473fbec8974584002561aacef5347c4450c559df6fe24c3abe3b0d167eefdc5510e794e96a4ea4f9cb1d501515 + checksum: 10/514d8147f7bdff4accbeb06c294b68670287ecdaada9b2fbd3a2ba89d35860095cadd5a4175894fc8e75ba3b2be83dc172eba5cc71b823fd0dd846b7d49877ff languageName: node linkType: hard "eslint-plugin-jest@npm:^28.8.3": - version: 28.14.0 - resolution: "eslint-plugin-jest@npm:28.14.0" + version: 28.10.0 + resolution: "eslint-plugin-jest@npm:28.10.0" dependencies: "@typescript-eslint/utils": "npm:^6.0.0 || ^7.0.0 || ^8.0.0" peerDependencies: @@ -8622,66 +8334,66 @@ __metadata: optional: true jest: optional: true - checksum: 10/6032497bd97d6dd010450d5fdf535b8613a2789f4f83764ae04361c48d06d92f3d9b2e4350914b8fd857b6e611ba2b5282a1133ab8ec51b3e7053f9d336058e6 + checksum: 10/cb19f2171e93873d9207425c4fa52ec49018579d73ece23a1ffea90f3ffd284b0e48f74ff4f50b15ff31882b06b03fec0e48c9c6ca830acdeff8931802ef0a9e languageName: node linkType: hard "eslint-plugin-jsdoc@npm:^50.2.4": - version: 50.8.0 - resolution: "eslint-plugin-jsdoc@npm:50.8.0" + version: 50.6.1 + resolution: "eslint-plugin-jsdoc@npm:50.6.1" dependencies: - "@es-joy/jsdoccomment": "npm:~0.50.2" + "@es-joy/jsdoccomment": "npm:~0.49.0" are-docs-informative: "npm:^0.0.2" comment-parser: "npm:1.4.1" - debug: "npm:^4.4.1" + debug: "npm:^4.3.6" escape-string-regexp: "npm:^4.0.0" - espree: "npm:^10.3.0" + espree: "npm:^10.1.0" esquery: "npm:^1.6.0" - parse-imports-exports: "npm:^0.2.4" - semver: "npm:^7.7.2" + parse-imports: "npm:^2.1.1" + semver: "npm:^7.6.3" spdx-expression-parse: "npm:^4.0.0" + synckit: "npm:^0.9.1" peerDependencies: eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 - checksum: 10/8857bb6583e04af0a1949e602e2b5b2abc5a951583bdc5a3baa0cc24f7c16db367cbc44e008c45b06dc2029685f0eb1ff6a0bb91e90fd82710ce30952d878d5d + checksum: 10/53fceff38a5317bb7c42c15a622100515aec89aea0d2bbf07e7d2d07eacdaa10ce625232a1bc7c1497f7bbe044675123d30cd3e123fa52fe5c7a9c336a59709c languageName: node linkType: hard "eslint-plugin-n@npm:^17.10.3": - version: 17.24.0 - resolution: "eslint-plugin-n@npm:17.24.0" + version: 17.15.1 + resolution: "eslint-plugin-n@npm:17.15.1" dependencies: - "@eslint-community/eslint-utils": "npm:^4.5.0" + "@eslint-community/eslint-utils": "npm:^4.4.1" enhanced-resolve: "npm:^5.17.1" eslint-plugin-es-x: "npm:^7.8.0" get-tsconfig: "npm:^4.8.1" globals: "npm:^15.11.0" - globrex: "npm:^0.1.2" ignore: "npm:^5.3.2" + minimatch: "npm:^9.0.5" semver: "npm:^7.6.3" - ts-declaration-location: "npm:^1.0.6" peerDependencies: eslint: ">=8.23.0" - checksum: 10/bbff1172f7297288d209f167febb3a31747838d5ed8050aa7d1aa2540a49b4f9932828831529f0306f2909e41ae3ae8848c145238a6990eae5a9d128a59b056c + checksum: 10/43fc161949fa0346ac7063a30580cd0db27e216b8e6a48d73d0bf4f10b88e9b65f263399843b3fe2087f766f264d16f0cbe8f2f898591516842201dc115a2d21 languageName: node linkType: hard "eslint-plugin-prettier@npm:^5.2.1": - version: 5.5.5 - resolution: "eslint-plugin-prettier@npm:5.5.5" + version: 5.2.1 + resolution: "eslint-plugin-prettier@npm:5.2.1" dependencies: - prettier-linter-helpers: "npm:^1.0.1" - synckit: "npm:^0.11.12" + prettier-linter-helpers: "npm:^1.0.0" + synckit: "npm:^0.9.1" peerDependencies: "@types/eslint": ">=8.0.0" eslint: ">=8.0.0" - eslint-config-prettier: ">= 7.0.0 <10.0.0 || >=10.1.0" + eslint-config-prettier: "*" prettier: ">=3.0.0" peerDependenciesMeta: "@types/eslint": optional: true eslint-config-prettier: optional: true - checksum: 10/36c22c2fa2fd7c61ed292af1280e1d8f94dfe1671eacc5a503a249ca4b27fd226dbf6a1820457d611915926946f42729488d2dc7a5c320601e6cf1fad0d28f66 + checksum: 10/10ddf68215237e327af09a47adab4c63f3885fda4fb28c4c42d1fc5f47d8a0cc45df6484799360ff1417a0aa3c77c3aaac49d7e9dfd145557b17e2d7ecc2a27c languageName: node linkType: hard @@ -8727,16 +8439,9 @@ __metadata: languageName: node linkType: hard -"eslint-visitor-keys@npm:^5.0.0": - version: 5.0.1 - resolution: "eslint-visitor-keys@npm:5.0.1" - checksum: 10/f9cc1a57b75e0ef949545cac33d01e8367e302de4c1483266ed4d8646ee5c306376660196bbb38b004e767b7043d1e661cb4336b49eff634a1bbe75c1db709ec - languageName: node - linkType: hard - "eslint@npm:^9.39.1": - version: 9.39.3 - resolution: "eslint@npm:9.39.3" + version: 9.39.1 + resolution: "eslint@npm:9.39.1" dependencies: "@eslint-community/eslint-utils": "npm:^4.8.0" "@eslint-community/regexpp": "npm:^4.12.1" @@ -8744,7 +8449,7 @@ __metadata: "@eslint/config-helpers": "npm:^0.4.2" "@eslint/core": "npm:^0.17.0" "@eslint/eslintrc": "npm:^3.3.1" - "@eslint/js": "npm:9.39.3" + "@eslint/js": "npm:9.39.1" "@eslint/plugin-kit": "npm:^0.4.1" "@humanfs/node": "npm:^0.16.6" "@humanwhocodes/module-importer": "npm:^1.0.1" @@ -8779,11 +8484,11 @@ __metadata: optional: true bin: eslint: bin/eslint.js - checksum: 10/1c95c92983ddf435e7f7d54edd06d703a15773a7d189583d3388e5b5ac714f0a2450b91c0b3bb9b9ccec9bd20994fd8e48d231ed6dabca0be56ef314b32820ff + checksum: 10/c85fefe4a81a1a476e62087366907af830b62a6565ac153f6d50a100a42a946aeb049c3af8f06c0e091105ba0fe97ac109f379f32755a67f66ecb7d4d1e4dca3 languageName: node linkType: hard -"espree@npm:^10.0.1, espree@npm:^10.3.0, espree@npm:^10.4.0": +"espree@npm:^10.0.1, espree@npm:^10.1.0, espree@npm:^10.4.0": version: 10.4.0 resolution: "espree@npm:10.4.0" dependencies: @@ -8805,11 +8510,11 @@ __metadata: linkType: hard "esquery@npm:^1.5.0, esquery@npm:^1.6.0": - version: 1.7.0 - resolution: "esquery@npm:1.7.0" + version: 1.6.0 + resolution: "esquery@npm:1.6.0" dependencies: estraverse: "npm:^5.1.0" - checksum: 10/4afaf3089367e1f5885caa116ef386dffd8bfd64da21fd3d0e56e938d2667cfb2e5400ab4a825aa70e799bb3741e5b5d63c0b94d86e2d4cf3095c9e64b2f5a15 + checksum: 10/c587fb8ec9ed83f2b1bc97cf2f6854cc30bf784a79d62ba08c6e358bf22280d69aee12827521cf38e69ae9761d23fb7fde593ce315610f85655c139d99b05e5a languageName: node linkType: hard @@ -8937,17 +8642,17 @@ __metadata: linkType: hard "ethers@npm:^6.12.0": - version: 6.16.0 - resolution: "ethers@npm:6.16.0" + version: 6.13.2 + resolution: "ethers@npm:6.13.2" dependencies: "@adraffy/ens-normalize": "npm:1.10.1" "@noble/curves": "npm:1.2.0" "@noble/hashes": "npm:1.3.2" - "@types/node": "npm:22.7.5" + "@types/node": "npm:18.15.13" aes-js: "npm:4.0.0-beta.5" - tslib: "npm:2.7.0" + tslib: "npm:2.4.0" ws: "npm:8.17.1" - checksum: 10/7e980f0a77963fbe14321a3b9746c3ca3cad44932e28bb3506406a66c4b4d9dc1e60ed68d9d784224e9f2582a53d6a0a2e55a7c9559659681f4ad1f70e00e325 + checksum: 10/e611c2e2c5340982dfd1f004895f55abda11748a7edec9e6315226dec42d58aa61b827dd389ec904db5f9a244c475ae795e528da579251fdf62e914bde12809e languageName: node linkType: hard @@ -8976,15 +8681,6 @@ __metadata: languageName: node linkType: hard -"events-universal@npm:^1.0.0": - version: 1.0.1 - resolution: "events-universal@npm:1.0.1" - dependencies: - bare-events: "npm:^2.7.0" - checksum: 10/71b2e6079b4dc030c613ef73d99f1acb369dd3ddb6034f49fd98b3e2c6632cde9f61c15fb1351004339d7c79672252a4694ecc46a6124dc794b558be50a83867 - languageName: node - linkType: hard - "events@npm:^3.3.0": version: 3.3.0 resolution: "events@npm:3.3.0" @@ -9066,63 +8762,49 @@ __metadata: languageName: node linkType: hard -"expect@npm:^30.0.0": - version: 30.2.0 - resolution: "expect@npm:30.2.0" - dependencies: - "@jest/expect-utils": "npm:30.2.0" - "@jest/get-type": "npm:30.1.0" - jest-matcher-utils: "npm:30.2.0" - jest-message-util: "npm:30.2.0" - jest-mock: "npm:30.2.0" - jest-util: "npm:30.2.0" - checksum: 10/cf98ab45ab2e9f2fb9943a3ae0097f72d63a94be179a19fd2818d8fdc3b7681d31cc8ef540606eb8dd967d9c44d73fef263a614e9de260c22943ffb122ad66fd - languageName: node - linkType: hard - "exponential-backoff@npm:^3.1.1": - version: 3.1.3 - resolution: "exponential-backoff@npm:3.1.3" - checksum: 10/ca25962b4bbab943b7c4ed0b5228e263833a5063c65e1cdeac4be9afad350aae5466e8e619b5051f4f8d37b2144a2d6e8fcc771b6cc82934f7dade2f964f652c + version: 3.1.1 + resolution: "exponential-backoff@npm:3.1.1" + checksum: 10/2d9bbb6473de7051f96790d5f9a678f32e60ed0aa70741dc7fdc96fec8d631124ec3374ac144387604f05afff9500f31a1d45bd9eee4cdc2e4f9ad2d9b9d5dbd languageName: node linkType: hard "express@npm:^4.21.2": - version: 4.22.1 - resolution: "express@npm:4.22.1" + version: 4.21.2 + resolution: "express@npm:4.21.2" dependencies: accepts: "npm:~1.3.8" array-flatten: "npm:1.1.1" - body-parser: "npm:~1.20.3" - content-disposition: "npm:~0.5.4" + body-parser: "npm:1.20.3" + content-disposition: "npm:0.5.4" content-type: "npm:~1.0.4" - cookie: "npm:~0.7.1" - cookie-signature: "npm:~1.0.6" + cookie: "npm:0.7.1" + cookie-signature: "npm:1.0.6" debug: "npm:2.6.9" depd: "npm:2.0.0" encodeurl: "npm:~2.0.0" escape-html: "npm:~1.0.3" etag: "npm:~1.8.1" - finalhandler: "npm:~1.3.1" - fresh: "npm:~0.5.2" - http-errors: "npm:~2.0.0" + finalhandler: "npm:1.3.1" + fresh: "npm:0.5.2" + http-errors: "npm:2.0.0" merge-descriptors: "npm:1.0.3" methods: "npm:~1.1.2" - on-finished: "npm:~2.4.1" + on-finished: "npm:2.4.1" parseurl: "npm:~1.3.3" - path-to-regexp: "npm:~0.1.12" + path-to-regexp: "npm:0.1.12" proxy-addr: "npm:~2.0.7" - qs: "npm:~6.14.0" + qs: "npm:6.13.0" range-parser: "npm:~1.2.1" safe-buffer: "npm:5.2.1" - send: "npm:~0.19.0" - serve-static: "npm:~1.16.2" + send: "npm:0.19.0" + serve-static: "npm:1.16.2" setprototypeof: "npm:1.2.0" - statuses: "npm:~2.0.1" + statuses: "npm:2.0.1" type-is: "npm:~1.6.18" utils-merge: "npm:1.0.1" vary: "npm:~1.1.2" - checksum: 10/f33c1bd0c7d36e2a1f18de9cdc176469d32f68e20258d2941b8d296ab9a4fd9011872c246391bf87714f009fac5114c832ec5ac65cbee39421f1258801eb8470 + checksum: 10/34571c442fc8c9f2c4b442d2faa10ea1175cf8559237fc6a278f5ce6254a8ffdbeb9a15d99f77c1a9f2926ab183e3b7ba560e3261f1ad4149799e3412ab66bd1 languageName: node linkType: hard @@ -9154,13 +8836,6 @@ __metadata: languageName: node linkType: hard -"fast-copy@npm:^3.0.2": - version: 3.0.2 - resolution: "fast-copy@npm:3.0.2" - checksum: 10/97e1022e2aaa27acf4a986d679310bfd66bfb87fe8da9dd33b698e3e50189484001cf1eeb9670e19b59d9d299828ed86c8da354c954f125995ab2a6331c5f290 - languageName: node - linkType: hard - "fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3": version: 3.1.3 resolution: "fast-deep-equal@npm:3.1.3" @@ -9182,7 +8857,7 @@ __metadata: languageName: node linkType: hard -"fast-glob@npm:^3.2.9": +"fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.0, fast-glob@npm:^3.3.2": version: 3.3.3 resolution: "fast-glob@npm:3.3.3" dependencies: @@ -9224,24 +8899,13 @@ __metadata: linkType: hard "fast-xml-parser@npm:^4.4.1": - version: 4.5.3 - resolution: "fast-xml-parser@npm:4.5.3" - dependencies: - strnum: "npm:^1.1.1" - bin: - fxparser: src/cli/cli.js - checksum: 10/ca22bf9d65c10b8447c1034c13403e90ecee210e2b3852690df3d8a42b8a46ec655fae7356096abd98a15b89ddaf11878587b1773e0c3be4cbc2ac4af4c7bf95 - languageName: node - linkType: hard - -"fast-xml-parser@npm:^5.3.4": - version: 5.3.7 - resolution: "fast-xml-parser@npm:5.3.7" + version: 4.4.1 + resolution: "fast-xml-parser@npm:4.4.1" dependencies: - strnum: "npm:^2.1.2" + strnum: "npm:^1.0.5" bin: fxparser: src/cli/cli.js - checksum: 10/c3dfba84b8c8920a1a6f2596c387c8fbb3b76fcad9a26769a793f1e26d7718c50363478f3be2a71e952b2bf765be51d8f8e3434b37cc7af029c6a09662ea6ba4 + checksum: 10/0c05ab8703630d8c857fafadbd78d0020d3a8e54310c3842179cd4a0d9d97e96d209ce885e91241f4aa9dd8dfc2fd924a682741a423d65153cad34da2032ec44 languageName: node linkType: hard @@ -9253,11 +8917,11 @@ __metadata: linkType: hard "fastq@npm:^1.6.0": - version: 1.20.1 - resolution: "fastq@npm:1.20.1" + version: 1.17.1 + resolution: "fastq@npm:1.17.1" dependencies: reusify: "npm:^1.0.4" - checksum: 10/ab2fe3a7a108112e7752cfe7fc11683c21e595913a6a593ad0b4415f31dddbfc283775ab66f2c8ccea6ab7cfc116157cbddcfae9798d9de98d08fe0a2c3e97b2 + checksum: 10/a443180068b527dd7b3a63dc7f2a47ceca2f3e97b9c00a1efe5538757e6cc4056a3526df94308075d7727561baf09ebaa5b67da8dcbddb913a021c5ae69d1f69 languageName: node linkType: hard @@ -9309,18 +8973,18 @@ __metadata: languageName: node linkType: hard -"finalhandler@npm:~1.3.1": - version: 1.3.2 - resolution: "finalhandler@npm:1.3.2" +"finalhandler@npm:1.3.1": + version: 1.3.1 + resolution: "finalhandler@npm:1.3.1" dependencies: debug: "npm:2.6.9" encodeurl: "npm:~2.0.0" escape-html: "npm:~1.0.3" - on-finished: "npm:~2.4.1" + on-finished: "npm:2.4.1" parseurl: "npm:~1.3.3" - statuses: "npm:~2.0.2" + statuses: "npm:2.0.1" unpipe: "npm:~1.0.0" - checksum: 10/6cb4f9f80eaeb5a0fac4fdbd27a65d39271f040a0034df16556d896bfd855fd42f09da886781b3102117ea8fceba97b903c1f8b08df1fb5740576d5e0f481eed + checksum: 10/4babe72969b7373b5842bc9f75c3a641a4d0f8eb53af6b89fa714d4460ce03fb92b28de751d12ba415e96e7e02870c436d67412120555e2b382640535697305b languageName: node linkType: hard @@ -9357,38 +9021,38 @@ __metadata: linkType: hard "firebase@npm:^11.2.0": - version: 11.10.0 - resolution: "firebase@npm:11.10.0" - dependencies: - "@firebase/ai": "npm:1.4.1" - "@firebase/analytics": "npm:0.10.17" - "@firebase/analytics-compat": "npm:0.2.23" - "@firebase/app": "npm:0.13.2" - "@firebase/app-check": "npm:0.10.1" - "@firebase/app-check-compat": "npm:0.3.26" - "@firebase/app-compat": "npm:0.4.2" + version: 11.2.0 + resolution: "firebase@npm:11.2.0" + dependencies: + "@firebase/analytics": "npm:0.10.11" + "@firebase/analytics-compat": "npm:0.2.17" + "@firebase/app": "npm:0.10.18" + "@firebase/app-check": "npm:0.8.11" + "@firebase/app-check-compat": "npm:0.3.18" + "@firebase/app-compat": "npm:0.2.48" "@firebase/app-types": "npm:0.9.3" - "@firebase/auth": "npm:1.10.8" - "@firebase/auth-compat": "npm:0.5.28" - "@firebase/data-connect": "npm:0.3.10" - "@firebase/database": "npm:1.0.20" - "@firebase/database-compat": "npm:2.0.11" - "@firebase/firestore": "npm:4.8.0" - "@firebase/firestore-compat": "npm:0.3.53" - "@firebase/functions": "npm:0.12.9" - "@firebase/functions-compat": "npm:0.3.26" - "@firebase/installations": "npm:0.6.18" - "@firebase/installations-compat": "npm:0.2.18" - "@firebase/messaging": "npm:0.12.22" - "@firebase/messaging-compat": "npm:0.2.22" - "@firebase/performance": "npm:0.7.7" - "@firebase/performance-compat": "npm:0.2.20" - "@firebase/remote-config": "npm:0.6.5" - "@firebase/remote-config-compat": "npm:0.2.18" - "@firebase/storage": "npm:0.13.14" - "@firebase/storage-compat": "npm:0.3.24" - "@firebase/util": "npm:1.12.1" - checksum: 10/ec78a2e079ff3d18ce7579a56a646d2979e619e504d74066d33bfea4941a87eb8b0ebea67e99fa1a3d76fd2b858c92958304b05b5a3bab60b662fa70821b12b1 + "@firebase/auth": "npm:1.8.2" + "@firebase/auth-compat": "npm:0.5.17" + "@firebase/data-connect": "npm:0.2.0" + "@firebase/database": "npm:1.0.11" + "@firebase/database-compat": "npm:2.0.2" + "@firebase/firestore": "npm:4.7.6" + "@firebase/firestore-compat": "npm:0.3.41" + "@firebase/functions": "npm:0.12.1" + "@firebase/functions-compat": "npm:0.3.18" + "@firebase/installations": "npm:0.6.12" + "@firebase/installations-compat": "npm:0.2.12" + "@firebase/messaging": "npm:0.12.16" + "@firebase/messaging-compat": "npm:0.2.16" + "@firebase/performance": "npm:0.6.12" + "@firebase/performance-compat": "npm:0.2.12" + "@firebase/remote-config": "npm:0.5.0" + "@firebase/remote-config-compat": "npm:0.2.12" + "@firebase/storage": "npm:0.13.5" + "@firebase/storage-compat": "npm:0.3.15" + "@firebase/util": "npm:1.10.3" + "@firebase/vertexai": "npm:1.0.3" + checksum: 10/9a3a8f6be4b34e76428cf6ae11bff8141772b7b3ec8a8fe0ef69188fdf2a602bd6e542a663133f90845d5a358daadeadf760841cf3ea8ec726475ee84a694ea4 languageName: node linkType: hard @@ -9403,28 +9067,19 @@ __metadata: linkType: hard "flatted@npm:^3.2.9": - version: 3.3.3 - resolution: "flatted@npm:3.3.3" - checksum: 10/8c96c02fbeadcf4e8ffd0fa24983241e27698b0781295622591fc13585e2f226609d95e422bcf2ef044146ffacb6b68b1f20871454eddf75ab3caa6ee5f4a1fe + version: 3.3.1 + resolution: "flatted@npm:3.3.1" + checksum: 10/7b8376061d5be6e0d3658bbab8bde587647f68797cf6bfeae9dea0e5137d9f27547ab92aaff3512dd9d1299086a6d61be98e9d48a56d17531b634f77faadbc49 languageName: node linkType: hard -"follow-redirects@npm:^1.15.11": - version: 1.15.11 - resolution: "follow-redirects@npm:1.15.11" +"follow-redirects@npm:^1.15.6": + version: 1.15.6 + resolution: "follow-redirects@npm:1.15.6" peerDependenciesMeta: debug: optional: true - checksum: 10/07372fd74b98c78cf4d417d68d41fdaa0be4dcacafffb9e67b1e3cf090bc4771515e65020651528faab238f10f9b9c0d9707d6c1574a6c0387c5de1042cde9ba - languageName: node - linkType: hard - -"for-each@npm:^0.3.5": - version: 0.3.5 - resolution: "for-each@npm:0.3.5" - dependencies: - is-callable: "npm:^1.2.7" - checksum: 10/330cc2439f85c94f4609de3ee1d32c5693ae15cdd7fe3d112c4fd9efd4ce7143f2c64ef6c2c9e0cfdb0058437f33ef05b5bdae5b98fcc903fb2143fbaf0fea0f + checksum: 10/70c7612c4cab18e546e36b991bbf8009a1a41cf85354afe04b113d1117569abf760269409cb3eb842d9f7b03d62826687086b081c566ea7b1e6613cf29030bf7 languageName: node linkType: hard @@ -9436,25 +9091,23 @@ __metadata: linkType: hard "foreground-child@npm:^3.1.0": - version: 3.3.1 - resolution: "foreground-child@npm:3.3.1" + version: 3.3.0 + resolution: "foreground-child@npm:3.3.0" dependencies: - cross-spawn: "npm:^7.0.6" + cross-spawn: "npm:^7.0.0" signal-exit: "npm:^4.0.1" - checksum: 10/427b33f997a98073c0424e5c07169264a62cda806d8d2ded159b5b903fdfc8f0a1457e06b5fc35506497acb3f1e353f025edee796300209ac6231e80edece835 + checksum: 10/e3a60480f3a09b12273ce2c5fcb9514d98dd0e528f58656a1b04680225f918d60a2f81f6a368f2f3b937fcee9cfc0cbf16f1ad9a0bc6a3a6e103a84c9a90087e languageName: node linkType: hard -"form-data@npm:^4.0.0, form-data@npm:^4.0.4, form-data@npm:^4.0.5": - version: 4.0.5 - resolution: "form-data@npm:4.0.5" +"form-data@npm:^4.0.0": + version: 4.0.0 + resolution: "form-data@npm:4.0.0" dependencies: asynckit: "npm:^0.4.0" combined-stream: "npm:^1.0.8" - es-set-tostringtag: "npm:^2.1.0" - hasown: "npm:^2.0.2" mime-types: "npm:^2.1.12" - checksum: 10/52ecd6e927c8c4e215e68a7ad5e0f7c1031397439672fd9741654b4a94722c4182e74cc815b225dcb5be3f4180f36428f67c6dd39eaa98af0dcfdd26c00c19cd + checksum: 10/7264aa760a8cf09482816d8300f1b6e2423de1b02bba612a136857413fdc96d7178298ced106817655facc6b89036c6e12ae31c9eb5bdc16aabf502ae8a5d805 languageName: node linkType: hard @@ -9465,7 +9118,7 @@ __metadata: languageName: node linkType: hard -"fresh@npm:~0.5.2": +"fresh@npm:0.5.2": version: 0.5.2 resolution: "fresh@npm:0.5.2" checksum: 10/64c88e489b5d08e2f29664eb3c79c705ff9a8eb15d3e597198ef76546d4ade295897a44abb0abd2700e7ef784b2e3cbf1161e4fbf16f59129193fd1030d16da1 @@ -9484,13 +9137,22 @@ __metadata: linkType: hard "fs-extra@npm:^11.2.0": - version: 11.3.3 - resolution: "fs-extra@npm:11.3.3" + version: 11.3.0 + resolution: "fs-extra@npm:11.3.0" dependencies: graceful-fs: "npm:^4.2.0" jsonfile: "npm:^6.0.1" universalify: "npm:^2.0.0" - checksum: 10/daeaefafbebe8fa6efd2fb96fc926f2c952be5877811f00a6794f0d64e0128e3d0d93368cd328f8f063b45deacf385c40e3d931aa46014245431cd2f4f89c67a + checksum: 10/c9fe7b23dded1efe7bbae528d685c3206477e20cc60e9aaceb3f024f9b9ff2ee1f62413c161cb88546cc564009ab516dec99e9781ba782d869bb37e4fe04a97f + languageName: node + linkType: hard + +"fs-minipass@npm:^2.0.0": + version: 2.1.0 + resolution: "fs-minipass@npm:2.1.0" + dependencies: + minipass: "npm:^3.0.0" + checksum: 10/03191781e94bc9a54bd376d3146f90fe8e082627c502185dbf7b9b3032f66b0b142c1115f3b2cc5936575fc1b44845ce903dd4c21bec2a8d69f3bd56f9cee9ec languageName: node linkType: hard @@ -9536,13 +9198,6 @@ __metadata: languageName: node linkType: hard -"generator-function@npm:^2.0.0": - version: 2.0.1 - resolution: "generator-function@npm:2.0.1" - checksum: 10/eb7e7eb896c5433f3d40982b2ccacdb3dd990dd3499f14040e002b5d54572476513be8a2e6f9609f6e41ab29f2c4469307611ddbfc37ff4e46b765c326663805 - languageName: node - linkType: hard - "gensync@npm:^1.0.0-beta.2": version: 1.0.0-beta.2 resolution: "gensync@npm:1.0.0-beta.2" @@ -9557,24 +9212,21 @@ __metadata: languageName: node linkType: hard -"get-intrinsic@npm:^1.2.4, get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.2.6, get-intrinsic@npm:^1.3.0": - version: 1.3.1 - resolution: "get-intrinsic@npm:1.3.1" +"get-intrinsic@npm:^1.2.4": + version: 1.3.0 + resolution: "get-intrinsic@npm:1.3.0" dependencies: - async-function: "npm:^1.0.0" - async-generator-function: "npm:^1.0.0" call-bind-apply-helpers: "npm:^1.0.2" es-define-property: "npm:^1.0.1" es-errors: "npm:^1.3.0" es-object-atoms: "npm:^1.1.1" function-bind: "npm:^1.1.2" - generator-function: "npm:^2.0.0" get-proto: "npm:^1.0.1" gopd: "npm:^1.2.0" has-symbols: "npm:^1.1.0" hasown: "npm:^2.0.2" math-intrinsics: "npm:^1.1.0" - checksum: 10/bb579dda84caa4a3a41611bdd483dade7f00f246f2a7992eb143c5861155290df3fdb48a8406efa3dfb0b434e2c8fafa4eebd469e409d0439247f85fc3fa2cc1 + checksum: 10/6e9dd920ff054147b6f44cb98104330e87caafae051b6d37b13384a45ba15e71af33c3baeac7cb630a0aaa23142718dcf25b45cfdd86c184c5dcb4e56d953a10 languageName: node linkType: hard @@ -9602,6 +9254,13 @@ __metadata: languageName: node linkType: hard +"get-stdin@npm:^9.0.0": + version: 9.0.0 + resolution: "get-stdin@npm:9.0.0" + checksum: 10/5972bc34d05932b45512c8e2d67b040f1c1ca8afb95c56cbc480985f2d761b7e37fe90dc8abd22527f062cc5639a6930ff346e9952ae4c11a2d4275869459594 + languageName: node + linkType: hard + "get-stream@npm:^6.0.0": version: 6.0.1 resolution: "get-stream@npm:6.0.1" @@ -9616,19 +9275,19 @@ __metadata: languageName: node linkType: hard -"get-tsconfig@npm:^4.10.0, get-tsconfig@npm:^4.10.1, get-tsconfig@npm:^4.7.5, get-tsconfig@npm:^4.8.1": - version: 4.13.6 - resolution: "get-tsconfig@npm:4.13.6" +"get-tsconfig@npm:^4.7.3, get-tsconfig@npm:^4.7.5, get-tsconfig@npm:^4.8.1": + version: 4.8.1 + resolution: "get-tsconfig@npm:4.8.1" dependencies: resolve-pkg-maps: "npm:^1.0.0" - checksum: 10/5cd1c1f273e9f1cd9f1ebeaaea281a3b7b71562fc9614ee0cf0575463b0435de68831354434a5a1a564e1049062d597d0dae8ef33f489a6d12afccee032f6784 + checksum: 10/3fb5a8ad57b9633eaea085d81661e9e5c9f78b35d8f8689eaf8b8b45a2a3ebf3b3422266d4d7df765e308cc1e6231648d114803ab3d018332e29916f2c1de036 languageName: node linkType: hard -"git-hooks-list@npm:^4.1.1": - version: 4.2.1 - resolution: "git-hooks-list@npm:4.2.1" - checksum: 10/39449520045539c03b1d45d3a010424849152d6f723b638c6f19cb8c8b0993bb30ed5ef09653f4d1c1356f5fb51a396059096d8bdfcb6ca7ccb54f6e26efc338 +"git-hooks-list@npm:^3.0.0": + version: 3.1.0 + resolution: "git-hooks-list@npm:3.1.0" + checksum: 10/05cbdb29e1e14f3b6fde78c876a34383e4476b1be32e8486ad03293f01add884c1a8df8c2dce2ca5d99119c94951b2ff9fa9cbd51d834ae6477b6813cefb998f languageName: node linkType: hard @@ -9650,9 +9309,9 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.3.7": - version: 10.5.0 - resolution: "glob@npm:10.5.0" +"glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7": + version: 10.4.5 + resolution: "glob@npm:10.4.5" dependencies: foreground-child: "npm:^3.1.0" jackspeak: "npm:^3.1.2" @@ -9662,18 +9321,7 @@ __metadata: path-scurry: "npm:^1.11.1" bin: glob: dist/esm/bin.mjs - checksum: 10/ab3bccfefcc0afaedbd1f480cd0c4a2c0e322eb3f0aa7ceaa31b3f00b825069f17cf0f1fc8b6f256795074b903f37c0ade37ddda6a176aa57f1c2bbfe7240653 - languageName: node - linkType: hard - -"glob@npm:^13.0.0": - version: 13.0.6 - resolution: "glob@npm:13.0.6" - dependencies: - minimatch: "npm:^10.2.2" - minipass: "npm:^7.1.3" - path-scurry: "npm:^2.0.2" - checksum: 10/201ad69e5f0aa74e1d8c00a481581f8b8c804b6a4fbfabeeb8541f5d756932800331daeba99b58fb9e4cd67e12ba5a7eba5b82fb476691588418060b84353214 + checksum: 10/698dfe11828b7efd0514cd11e573eaed26b2dff611f0400907281ce3eab0c1e56143ef9b35adc7c77ecc71fba74717b510c7c223d34ca8a98ec81777b293d4ac languageName: node linkType: hard @@ -9723,9 +9371,9 @@ __metadata: linkType: hard "globals@npm:^15.11.0, globals@npm:^15.9.0": - version: 15.15.0 - resolution: "globals@npm:15.15.0" - checksum: 10/7f561c87b2fd381b27fc2db7df8a4ea7a9bb378667b8a7193e61fd2ca3a876479174e2a303a74345fbea6e1242e16db48915c1fd3bf35adcf4060a795b425e18 + version: 15.14.0 + resolution: "globals@npm:15.14.0" + checksum: 10/e35ffbdbc024d6381efca906f67211a7bbf935db2af8c14a65155785479e28b3e475950e5933bb6b296eed54b6dcd924e25b26dbc8579b1bde9d5d25916e1c5f languageName: node linkType: hard @@ -9743,10 +9391,16 @@ __metadata: languageName: node linkType: hard -"globrex@npm:^0.1.2": - version: 0.1.2 - resolution: "globrex@npm:0.1.2" - checksum: 10/81ce62ee6f800d823d6b7da7687f841676d60ee8f51f934ddd862e4057316d26665c4edc0358d4340a923ac00a514f8b67c787e28fe693aae16350f4e60d55e9 +"globby@npm:^13.1.2": + version: 13.2.2 + resolution: "globby@npm:13.2.2" + dependencies: + dir-glob: "npm:^3.0.1" + fast-glob: "npm:^3.3.0" + ignore: "npm:^5.2.4" + merge2: "npm:^1.4.1" + slash: "npm:^4.0.0" + checksum: 10/4494a9d2162a7e4d327988b26be66d8eab87d7f59a83219e74b065e2c3ced23698f68fb10482bf9337133819281803fb886d6ae06afbb2affa743623eb0b1949 languageName: node linkType: hard @@ -9757,7 +9411,7 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.11, graceful-fs@npm:^4.2.2, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": +"graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.2, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" checksum: 10/bf152d0ed1dc159239db1ba1f74fdbc40cb02f626770dcd5815c427ce0688c2635a06ed69af364396da4636d0408fcf7d4afdf7881724c3307e46aff30ca49e2 @@ -9805,31 +9459,21 @@ __metadata: languageName: node linkType: hard -"has-symbols@npm:^1.0.3, has-symbols@npm:^1.1.0": +"has-symbols@npm:^1.1.0": version: 1.1.0 resolution: "has-symbols@npm:1.1.0" checksum: 10/959385c98696ebbca51e7534e0dc723ada325efa3475350951363cce216d27373e0259b63edb599f72eb94d6cde8577b4b2375f080b303947e560f85692834fa languageName: node linkType: hard -"has-tostringtag@npm:^1.0.2": - version: 1.0.2 - resolution: "has-tostringtag@npm:1.0.2" - dependencies: - has-symbols: "npm:^1.0.3" - checksum: 10/c74c5f5ceee3c8a5b8bc37719840dc3749f5b0306d818974141dda2471a1a2ca6c8e46b9d6ac222c5345df7a901c9b6f350b1e6d62763fec877e26609a401bfe - languageName: node - linkType: hard - -"hash-base@npm:^3.0.0, hash-base@npm:^3.1.2": - version: 3.1.2 - resolution: "hash-base@npm:3.1.2" +"hash-base@npm:^3.0.0": + version: 3.1.0 + resolution: "hash-base@npm:3.1.0" dependencies: inherits: "npm:^2.0.4" - readable-stream: "npm:^2.3.8" - safe-buffer: "npm:^5.2.1" - to-buffer: "npm:^1.2.1" - checksum: 10/f2100420521ec77736ebd9279f2c0b3ab2820136a2fa408ea36f3201d3f6984cda166806e6a0287f92adf179430bedfbdd74348ac351e24a3eff9f01a8c406b0 + readable-stream: "npm:^3.6.0" + safe-buffer: "npm:^5.2.0" + checksum: 10/26b7e97ac3de13cb23fc3145e7e3450b0530274a9562144fc2bf5c1e2983afd0e09ed7cc3b20974ba66039fad316db463da80eb452e7373e780cbee9a0d2f2dc languageName: node linkType: hard @@ -9888,12 +9532,12 @@ __metadata: languageName: node linkType: hard -"hosted-git-info@npm:^9.0.0": - version: 9.0.2 - resolution: "hosted-git-info@npm:9.0.2" +"hosted-git-info@npm:^7.0.0": + version: 7.0.2 + resolution: "hosted-git-info@npm:7.0.2" dependencies: - lru-cache: "npm:^11.1.0" - checksum: 10/0619c284ca7fc35322735e03fece90ed3ded67a2cf68e855e688d1bffd47078515d98ab8dff4bd08fb78d68d1a72ab8892180e15c7f23f24c922a6dfa601dbad + lru-cache: "npm:^10.0.1" + checksum: 10/8f085df8a4a637d995f357f48b1e3f6fc1f9f92e82b33fb406415b5741834ed431a510a09141071001e8deea2eee43ce72786463e2aa5e5a70db8648c0eedeab languageName: node linkType: hard @@ -9914,29 +9558,29 @@ __metadata: linkType: hard "http-cache-semantics@npm:^4.1.1": - version: 4.2.0 - resolution: "http-cache-semantics@npm:4.2.0" - checksum: 10/4efd2dfcfeea9d5e88c84af450b9980be8a43c2c8179508b1c57c7b4421c855f3e8efe92fa53e0b3f4a43c85824ada930eabbc306d1b3beab750b6dcc5187693 + version: 4.1.1 + resolution: "http-cache-semantics@npm:4.1.1" + checksum: 10/362d5ed66b12ceb9c0a328fb31200b590ab1b02f4a254a697dc796850cc4385603e75f53ec59f768b2dad3bfa1464bd229f7de278d2899a0e3beffc634b6683f languageName: node linkType: hard -"http-errors@npm:~2.0.0, http-errors@npm:~2.0.1": - version: 2.0.1 - resolution: "http-errors@npm:2.0.1" +"http-errors@npm:2.0.0": + version: 2.0.0 + resolution: "http-errors@npm:2.0.0" dependencies: - depd: "npm:~2.0.0" - inherits: "npm:~2.0.4" - setprototypeof: "npm:~1.2.0" - statuses: "npm:~2.0.2" - toidentifier: "npm:~1.0.1" - checksum: 10/9fe31bc0edf36566c87048aed1d3d0cbe03552564adc3541626a0613f542d753fbcb13bdfcec0a3a530dbe1714bb566c89d46244616b66bddd26ac413b06a207 + depd: "npm:2.0.0" + inherits: "npm:2.0.4" + setprototypeof: "npm:1.2.0" + statuses: "npm:2.0.1" + toidentifier: "npm:1.0.1" + checksum: 10/0e7f76ee8ff8a33e58a3281a469815b893c41357378f408be8f6d4aa7d1efafb0da064625518e7078381b6a92325949b119dc38fcb30bdbc4e3a35f78c44c439 languageName: node linkType: hard "http-parser-js@npm:>=0.5.1": - version: 0.5.10 - resolution: "http-parser-js@npm:0.5.10" - checksum: 10/33c53b458cfdf7e43f1517f9bcb6bed1c614b1c7c5d65581a84304110eb9eb02a48f998c7504b8bee432ef4a8ec9318e7009406b506b28b5610fed516242b20a + version: 0.5.8 + resolution: "http-parser-js@npm:0.5.8" + checksum: 10/2a78a567ee6366dae0129d819b799dce1f95ec9732c5ab164a78ee69804ffb984abfa0660274e94e890fc54af93546eb9f12b6d10edbaed017e2d41c29b7cf29 languageName: node linkType: hard @@ -9972,12 +9616,12 @@ __metadata: linkType: hard "https-proxy-agent@npm:^7.0.1": - version: 7.0.6 - resolution: "https-proxy-agent@npm:7.0.6" + version: 7.0.5 + resolution: "https-proxy-agent@npm:7.0.5" dependencies: - agent-base: "npm:^7.1.2" + agent-base: "npm:^7.0.2" debug: "npm:4" - checksum: 10/784b628cbd55b25542a9d85033bdfd03d4eda630fb8b3c9477959367f3be95dc476ed2ecbb9836c359c7c698027fc7b45723a302324433590f45d6c1706e8c13 + checksum: 10/6679d46159ab3f9a5509ee80c3a3fc83fba3a920a5e18d32176c3327852c3c00ad640c0c4210a8fd70ea3c4a6d3a1b375bf01942516e7df80e2646bdc77658ab languageName: node linkType: hard @@ -9995,30 +9639,21 @@ __metadata: languageName: node linkType: hard -"iconv-lite@npm:0.6.3": - version: 0.6.3 - resolution: "iconv-lite@npm:0.6.3" +"iconv-lite@npm:0.4.24": + version: 0.4.24 + resolution: "iconv-lite@npm:0.4.24" dependencies: - safer-buffer: "npm:>= 2.1.2 < 3.0.0" - checksum: 10/24e3292dd3dadaa81d065c6f8c41b274a47098150d444b96e5f53b4638a9a71482921ea6a91a1f59bb71d9796de25e04afd05919fa64c360347ba65d3766f10f + safer-buffer: "npm:>= 2.1.2 < 3" + checksum: 10/6d3a2dac6e5d1fb126d25645c25c3a1209f70cceecc68b8ef51ae0da3cdc078c151fade7524a30b12a3094926336831fca09c666ef55b37e2c69638b5d6bd2e3 languageName: node linkType: hard -"iconv-lite@npm:^0.7.2": - version: 0.7.2 - resolution: "iconv-lite@npm:0.7.2" +"iconv-lite@npm:0.6.3, iconv-lite@npm:^0.6.2": + version: 0.6.3 + resolution: "iconv-lite@npm:0.6.3" dependencies: safer-buffer: "npm:>= 2.1.2 < 3.0.0" - checksum: 10/24c937b532f868e938386b62410b303b7c767ce3d08dc2829cbe59464d5a26ef86ae5ad1af6b34eec43ddfea39e7d101638644b0178d67262fa87015d59f983a - languageName: node - linkType: hard - -"iconv-lite@npm:~0.4.24": - version: 0.4.24 - resolution: "iconv-lite@npm:0.4.24" - dependencies: - safer-buffer: "npm:>= 2.1.2 < 3" - checksum: 10/6d3a2dac6e5d1fb126d25645c25c3a1209f70cceecc68b8ef51ae0da3cdc078c151fade7524a30b12a3094926336831fca09c666ef55b37e2c69638b5d6bd2e3 + checksum: 10/24e3292dd3dadaa81d065c6f8c41b274a47098150d444b96e5f53b4638a9a71482921ea6a91a1f59bb71d9796de25e04afd05919fa64c360347ba65d3766f10f languageName: node linkType: hard @@ -10067,12 +9702,12 @@ __metadata: linkType: hard "import-fresh@npm:^3.2.1": - version: 3.3.1 - resolution: "import-fresh@npm:3.3.1" + version: 3.3.0 + resolution: "import-fresh@npm:3.3.0" dependencies: parent-module: "npm:^1.0.0" resolve-from: "npm:^4.0.0" - checksum: 10/a06b19461b4879cc654d46f8a6244eb55eb053437afd4cbb6613cad6be203811849ed3e4ea038783092879487299fda24af932b86bdfff67c9055ba3612b8c87 + checksum: 10/2cacfad06e652b1edc50be650f7ec3be08c5e5a6f6d12d035c440a42a8cc028e60a5b99ca08a77ab4d6b1346da7d971915828f33cdab730d3d42f08242d09baa languageName: node linkType: hard @@ -10112,7 +9747,7 @@ __metadata: languageName: node linkType: hard -"inherits@npm:2, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3, inherits@npm:~2.0.4": +"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 10/cd45e923bee15186c07fa4c89db0aace24824c482fb887b528304694b2aa6ff8a898da8657046a5dcf3e46cd6db6c61629551f9215f208d7c3f157cf9b290521 @@ -10126,17 +9761,20 @@ __metadata: languageName: node linkType: hard -"ini@npm:^6.0.0": - version: 6.0.0 - resolution: "ini@npm:6.0.0" - checksum: 10/e87d8cde86d091ddb104580d42dfdc8306593627269990ca0f5176ccc60c936268bad56856398fef924cdf0af33b1a9c21e84f85914820037e003ee45443cc85 +"ini@npm:^4.1.3": + version: 4.1.3 + resolution: "ini@npm:4.1.3" + checksum: 10/f536b414d1442e5b233429e2b56efcdb354109b2d65ddd489e5939d8f0f5ad23c88aa2b19c92987249d0dd63ba8192e9aeb1a02b0459549c5a9ff31acd729a5d languageName: node linkType: hard -"ip-address@npm:^10.0.1": - version: 10.1.0 - resolution: "ip-address@npm:10.1.0" - checksum: 10/a6979629d1ad9c1fb424bc25182203fad739b40225aebc55ec6243bbff5035faf7b9ed6efab3a097de6e713acbbfde944baacfa73e11852bb43989c45a68d79e +"ip-address@npm:^9.0.5": + version: 9.0.5 + resolution: "ip-address@npm:9.0.5" + dependencies: + jsbn: "npm:1.1.0" + sprintf-js: "npm:^1.1.3" + checksum: 10/1ed81e06721af012306329b31f532b5e24e00cb537be18ddc905a84f19fe8f83a09a1699862bf3a1ec4b9dea93c55a3fa5faf8b5ea380431469df540f38b092c languageName: node linkType: hard @@ -10161,19 +9799,12 @@ __metadata: languageName: node linkType: hard -"is-bun-module@npm:^2.0.0": - version: 2.0.0 - resolution: "is-bun-module@npm:2.0.0" +"is-bun-module@npm:^1.0.2": + version: 1.3.0 + resolution: "is-bun-module@npm:1.3.0" dependencies: - semver: "npm:^7.7.1" - checksum: 10/cded5a1a58368b847872d08617975d620ad94426d76a932f3e08d55b4574d199e0a62a4fb024fa2dc444200b71719eb0bffc5d3d1e1cc82e29b293bb8d66a990 - languageName: node - linkType: hard - -"is-callable@npm:^1.2.7": - version: 1.2.7 - resolution: "is-callable@npm:1.2.7" - checksum: 10/48a9297fb92c99e9df48706241a189da362bff3003354aea4048bd5f7b2eb0d823cd16d0a383cece3d76166ba16d85d9659165ac6fcce1ac12e6c649d66dbdb9 + semver: "npm:^7.6.3" + checksum: 10/b23d9ec7b4d4bfd89e4e72b5cd52e1bc153facad59fdd7394c656f8859a78740ef35996a2066240a32f39cc9a9da4b4eb69e68df3c71755a61ebbaf56d3daef0 languageName: node linkType: hard @@ -10188,7 +9819,7 @@ __metadata: languageName: node linkType: hard -"is-core-module@npm:^2.12.0, is-core-module@npm:^2.16.0, is-core-module@npm:^2.16.1, is-core-module@npm:^2.5.0": +"is-core-module@npm:^2.12.0, is-core-module@npm:^2.13.0, is-core-module@npm:^2.16.0, is-core-module@npm:^2.5.0": version: 2.16.1 resolution: "is-core-module@npm:2.16.1" dependencies: @@ -10261,6 +9892,13 @@ __metadata: languageName: node linkType: hard +"is-lambda@npm:^1.0.1": + version: 1.0.1 + resolution: "is-lambda@npm:1.0.1" + checksum: 10/93a32f01940220532e5948538699ad610d5924ac86093fcee83022252b363eb0cc99ba53ab084a04e4fb62bf7b5731f55496257a4c38adf87af9c4d352c71c35 + languageName: node + linkType: hard + "is-number@npm:^7.0.0": version: 7.0.0 resolution: "is-number@npm:7.0.0" @@ -10303,15 +9941,6 @@ __metadata: languageName: node linkType: hard -"is-typed-array@npm:^1.1.14": - version: 1.1.15 - resolution: "is-typed-array@npm:1.1.15" - dependencies: - which-typed-array: "npm:^1.1.16" - checksum: 10/e8cf60b9ea85667097a6ad68c209c9722cfe8c8edf04d6218366469e51944c5cc25bae45ffb845c23f811d262e4314d3b0168748eb16711aa34d12724cdf0735 - languageName: node - linkType: hard - "is-unicode-supported@npm:^0.1.0": version: 0.1.0 resolution: "is-unicode-supported@npm:0.1.0" @@ -10334,18 +9963,11 @@ __metadata: linkType: hard "is-wsl@npm:^3.1.0": - version: 3.1.1 - resolution: "is-wsl@npm:3.1.1" + version: 3.1.0 + resolution: "is-wsl@npm:3.1.0" dependencies: is-inside-container: "npm:^1.0.0" - checksum: 10/513d95b89af0e60b43d7b17ecb7eb78edea0a439136a3da37b1b56e215379cc46a9221474ad5b2de044824ca72d7869dee6e015273dc3f71f2bb87c715f9f1dc - languageName: node - linkType: hard - -"isarray@npm:^2.0.5": - version: 2.0.5 - resolution: "isarray@npm:2.0.5" - checksum: 10/1d8bc7911e13bb9f105b1b3e0b396c787a9e63046af0b8fe0ab1414488ab06b2b099b87a2d8a9e31d21c9a6fad773c7fc8b257c4880f2d957274479d28ca3414 + checksum: 10/f9734c81f2f9cf9877c5db8356bfe1ff61680f1f4c1011e91278a9c0564b395ae796addb4bf33956871041476ec82c3e5260ed57b22ac91794d4ae70a1d2f0a9 languageName: node linkType: hard @@ -10363,10 +9985,10 @@ __metadata: languageName: node linkType: hard -"isexe@npm:^4.0.0": - version: 4.0.0 - resolution: "isexe@npm:4.0.0" - checksum: 10/2ead327ef596042ef9c9ec5f236b316acfaedb87f4bb61b3c3d574fb2e9c8a04b67305e04733bde52c24d9622fdebd3270aadb632adfbf9cadef88fe30f479e5 +"isexe@npm:^3.1.1": + version: 3.1.1 + resolution: "isexe@npm:3.1.1" + checksum: 10/7fe1931ee4e88eb5aa524cd3ceb8c882537bc3a81b02e438b240e47012eef49c86904d0f0e593ea7c3a9996d18d0f1f3be8d3eaa92333977b0c3a9d353d5563e languageName: node linkType: hard @@ -10436,12 +10058,12 @@ __metadata: linkType: hard "istanbul-reports@npm:^3.1.3": - version: 3.2.0 - resolution: "istanbul-reports@npm:3.2.0" + version: 3.1.7 + resolution: "istanbul-reports@npm:3.1.7" dependencies: html-escaper: "npm:^2.0.0" istanbul-lib-report: "npm:^3.0.0" - checksum: 10/6773a1d5c7d47eeec75b317144fe2a3b1da84a44b6282bebdc856e09667865e58c9b025b75b3d87f5bc62939126cbba4c871ee84254537d934ba5da5d4c4ec4e + checksum: 10/f1faaa4684efaf57d64087776018d7426312a59aa6eeb4e0e3a777347d23cd286ad18f427e98f0e3dee666103d7404c9d7abc5f240406a912fa16bd6695437fa languageName: node linkType: hard @@ -10561,18 +10183,6 @@ __metadata: languageName: node linkType: hard -"jest-diff@npm:30.2.0": - version: 30.2.0 - resolution: "jest-diff@npm:30.2.0" - dependencies: - "@jest/diff-sequences": "npm:30.0.1" - "@jest/get-type": "npm:30.1.0" - chalk: "npm:^4.1.2" - pretty-format: "npm:30.2.0" - checksum: 10/1fb9e4fb7dff81814b4f69eaa7db28e184d62306a3a8ea2447d02ca53d2cfa771e83ede513f67ec5239dffacfaac32ff2b49866d211e4c7516f51c1fc06ede42 - languageName: node - linkType: hard - "jest-diff@npm:^29.0.3, jest-diff@npm:^29.7.0": version: 29.7.0 resolution: "jest-diff@npm:29.7.0" @@ -10695,18 +10305,6 @@ __metadata: languageName: node linkType: hard -"jest-matcher-utils@npm:30.2.0": - version: 30.2.0 - resolution: "jest-matcher-utils@npm:30.2.0" - dependencies: - "@jest/get-type": "npm:30.1.0" - chalk: "npm:^4.1.2" - jest-diff: "npm:30.2.0" - pretty-format: "npm:30.2.0" - checksum: 10/f3f1ecf68ca63c9d1d80a175637a8fc655edfd1ee83220f6e3f6bd464ecbe2f93148fdd440a5a5e5a2b0b2cc8ee84ddc3dcef58a6dbc66821c792f48d260c6d4 - languageName: node - linkType: hard - "jest-matcher-utils@npm:^29.7.0": version: 29.7.0 resolution: "jest-matcher-utils@npm:29.7.0" @@ -10719,23 +10317,6 @@ __metadata: languageName: node linkType: hard -"jest-message-util@npm:30.2.0": - version: 30.2.0 - resolution: "jest-message-util@npm:30.2.0" - dependencies: - "@babel/code-frame": "npm:^7.27.1" - "@jest/types": "npm:30.2.0" - "@types/stack-utils": "npm:^2.0.3" - chalk: "npm:^4.1.2" - graceful-fs: "npm:^4.2.11" - micromatch: "npm:^4.0.8" - pretty-format: "npm:30.2.0" - slash: "npm:^3.0.0" - stack-utils: "npm:^2.0.6" - checksum: 10/e29ec76e8c8e4da5f5b25198be247535626ccf3a940e93fdd51fc6a6bcf70feaa2921baae3806182a090431d90b08c939eb13fb64249b171d2e9ae3a452a8fd2 - languageName: node - linkType: hard - "jest-message-util@npm:^29.7.0": version: 29.7.0 resolution: "jest-message-util@npm:29.7.0" @@ -10753,17 +10334,6 @@ __metadata: languageName: node linkType: hard -"jest-mock@npm:30.2.0": - version: 30.2.0 - resolution: "jest-mock@npm:30.2.0" - dependencies: - "@jest/types": "npm:30.2.0" - "@types/node": "npm:*" - jest-util: "npm:30.2.0" - checksum: 10/cde9b56805f90bf811a9231873ee88a0fb83bf4bf50972ae76960725da65220fcb119688f2e90e1ef33fbfd662194858d7f43809d881f1c41bb55d94e62adeab - languageName: node - linkType: hard - "jest-mock@npm:^29.7.0": version: 29.7.0 resolution: "jest-mock@npm:29.7.0" @@ -10787,13 +10357,6 @@ __metadata: languageName: node linkType: hard -"jest-regex-util@npm:30.0.1": - version: 30.0.1 - resolution: "jest-regex-util@npm:30.0.1" - checksum: 10/fa8dac80c3e94db20d5e1e51d1bdf101cf5ede8f4e0b8f395ba8b8ea81e71804ffd747452a6bb6413032865de98ac656ef8ae43eddd18d980b6442a2764ed562 - languageName: node - linkType: hard - "jest-regex-util@npm:^29.6.3": version: 29.6.3 resolution: "jest-regex-util@npm:29.6.3" @@ -10925,20 +10488,6 @@ __metadata: languageName: node linkType: hard -"jest-util@npm:30.2.0": - version: 30.2.0 - resolution: "jest-util@npm:30.2.0" - dependencies: - "@jest/types": "npm:30.2.0" - "@types/node": "npm:*" - chalk: "npm:^4.1.2" - ci-info: "npm:^4.2.0" - graceful-fs: "npm:^4.2.11" - picomatch: "npm:^4.0.2" - checksum: 10/cf2f2fb83417ea69f9992121561c95cf4e9aad7946819b771b8b52addf78811101b33b51d0a39fa0c305f2751dab262feed7699de052659ff03d51827c8862f5 - languageName: node - linkType: hard - "jest-util@npm:^26.0.0": version: 26.6.2 resolution: "jest-util@npm:26.6.2" @@ -10998,11 +10547,11 @@ __metadata: linkType: hard "jest-when@npm:^3.4.2": - version: 3.7.0 - resolution: "jest-when@npm:3.7.0" + version: 3.6.0 + resolution: "jest-when@npm:3.6.0" peerDependencies: jest: ">= 25" - checksum: 10/b5b88d077ed467aab220c71c885dbc5f448604f06e68f761ce9f479c99bb74e0dbf553d1cc980751d88401b034a578e1c44eec5e4095743b7586f02bb7c6313d + checksum: 10/0cb92738ccfa5711a685107f4437f18aefbe3cda120c912a9d49b612eeef03a910481ab40fe753fd42c4e617ffbb3d84c6bd66a76d963dac7f1ad9e9e5059359 languageName: node linkType: hard @@ -11073,25 +10622,32 @@ __metadata: linkType: hard "js-yaml@npm:^3.13.1, js-yaml@npm:^3.14.1": - version: 3.14.2 - resolution: "js-yaml@npm:3.14.2" + version: 3.14.1 + resolution: "js-yaml@npm:3.14.1" dependencies: argparse: "npm:^1.0.7" esprima: "npm:^4.0.0" bin: js-yaml: bin/js-yaml.js - checksum: 10/172e0b6007b0bf0fc8d2469c94424f7dd765c64a047d2b790831fecef2204a4054eabf4d911eb73ab8c9a3256ab8ba1ee8d655b789bf24bf059c772acc2075a1 + checksum: 10/9e22d80b4d0105b9899135365f746d47466ed53ef4223c529b3c0f7a39907743fdbd3c4379f94f1106f02755b5e90b2faaf84801a891135544e1ea475d1a1379 languageName: node linkType: hard -"js-yaml@npm:^4.1.1": - version: 4.1.1 - resolution: "js-yaml@npm:4.1.1" +"js-yaml@npm:^4.1.0": + version: 4.1.0 + resolution: "js-yaml@npm:4.1.0" dependencies: argparse: "npm:^2.0.1" bin: js-yaml: bin/js-yaml.js - checksum: 10/a52d0519f0f4ef5b4adc1cde466cb54c50d56e2b4a983b9d5c9c0f2f99462047007a6274d7e95617a21d3c91fde3ee6115536ed70991cd645ba8521058b78f77 + checksum: 10/c138a34a3fd0d08ebaf71273ad4465569a483b8a639e0b118ff65698d257c2791d3199e3f303631f2cb98213fa7b5f5d6a4621fd0fff819421b990d30d967140 + languageName: node + linkType: hard + +"jsbn@npm:1.1.0": + version: 1.1.0 + resolution: "jsbn@npm:1.1.0" + checksum: 10/bebe7ae829bbd586ce8cbe83501dd8cb8c282c8902a8aeeed0a073a89dc37e8103b1244f3c6acd60278bcbfe12d93a3f83c9ac396868a3b3bbc3c5e5e3b648ef languageName: node linkType: hard @@ -11164,10 +10720,10 @@ __metadata: languageName: node linkType: hard -"json-parse-even-better-errors@npm:^5.0.0": - version: 5.0.0 - resolution: "json-parse-even-better-errors@npm:5.0.0" - checksum: 10/b5aeaa65e072bc3bda2cb1da50bf1822814b4aa7c568e7c2bed25af89d730f113dcb74393da574c0a32e889eeba4a826db600b8a6ecef917c59c8c6b38f2efaa +"json-parse-even-better-errors@npm:^3.0.0": + version: 3.0.2 + resolution: "json-parse-even-better-errors@npm:3.0.2" + checksum: 10/6f04ea6c9ccb783630a59297959247e921cc90b917b8351197ca7fd058fccc7079268fd9362be21ba876fc26aa5039369dd0a2280aae49aae425784794a94927 languageName: node linkType: hard @@ -11225,22 +10781,22 @@ __metadata: linkType: hard "jsonfile@npm:^6.0.1": - version: 6.2.0 - resolution: "jsonfile@npm:6.2.0" + version: 6.1.0 + resolution: "jsonfile@npm:6.1.0" dependencies: graceful-fs: "npm:^4.1.6" universalify: "npm:^2.0.0" dependenciesMeta: graceful-fs: optional: true - checksum: 10/513aac94a6eff070767cafc8eb4424b35d523eec0fcd8019fe5b975f4de5b10a54640c8d5961491ddd8e6f562588cf62435c5ddaf83aaf0986cd2ee789e0d7b9 + checksum: 10/03014769e7dc77d4cf05fa0b534907270b60890085dd5e4d60a382ff09328580651da0b8b4cdf44d91e4c8ae64d91791d965f05707beff000ed494a38b6fec85 languageName: node linkType: hard "jsonschema@npm:^1.4.1": - version: 1.5.0 - resolution: "jsonschema@npm:1.5.0" - checksum: 10/46bf49b388ba922073bcb3c8d5e90af9d29fc8303dc866fd440182c88d6b4fd2807679fd39cdefb4113156d104ea47da9c0ff4bbcb0032c9fa29461cb1a92182 + version: 1.4.1 + resolution: "jsonschema@npm:1.4.1" + checksum: 10/d7a188da7a3100a2caa362b80e98666d46607b7a7153aac405b8e758132961911c6df02d444d4700691330874e21a62639f550e856b21ddd28423690751ca9c6 languageName: node linkType: hard @@ -11364,9 +10920,9 @@ __metadata: linkType: hard "lodash@npm:^4.17.21": - version: 4.17.23 - resolution: "lodash@npm:4.17.23" - checksum: 10/82504c88250f58da7a5a4289f57a4f759c44946c005dd232821c7688b5fcfbf4a6268f6a6cdde4b792c91edd2f3b5398c1d2a0998274432cff76def48735e233 + version: 4.17.21 + resolution: "lodash@npm:4.17.21" + checksum: 10/c08619c038846ea6ac754abd6dd29d2568aa705feb69339e836dfa8d8b09abbb2f859371e86863eda41848221f9af43714491467b5b0299122431e202bb0c532 languageName: node linkType: hard @@ -11388,26 +10944,19 @@ __metadata: linkType: hard "long@npm:^5.0.0": - version: 5.3.2 - resolution: "long@npm:5.3.2" - checksum: 10/b6b55ddae56fcce2864d37119d6b02fe28f6dd6d9e44fd22705f86a9254b9321bd69e9ffe35263b4846d54aba197c64882adcb8c543f2383c1e41284b321ea64 + version: 5.2.3 + resolution: "long@npm:5.2.3" + checksum: 10/9167ec6947a825b827c30da169a7384eec6c0c9ec2f0b9c74da2e93d81159bbe39fb09c3f13dae9721d4b807ccfa09797a7dd1012f5d478e3e33ca3c78b608e6 languageName: node linkType: hard -"lru-cache@npm:^10.2.0": +"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": version: 10.4.3 resolution: "lru-cache@npm:10.4.3" checksum: 10/e6e90267360476720fa8e83cc168aa2bf0311f3f2eea20a6ba78b90a885ae72071d9db132f40fda4129c803e7dcec3a6b6a6fbb44ca90b081630b810b5d6a41a languageName: node linkType: hard -"lru-cache@npm:^11.0.0, lru-cache@npm:^11.1.0, lru-cache@npm:^11.2.1": - version: 11.2.6 - resolution: "lru-cache@npm:11.2.6" - checksum: 10/91222bbd59f793a0a0ad57789388f06b34ac9bb1613433c1d1810457d09db5cd3ec8943227ce2e1f5d6a0a15d6f1a9f129cb2c49ae9b6b10e82d4965fddecbef - languageName: node - linkType: hard - "lru-cache@npm:^5.1.1": version: 5.1.1 resolution: "lru-cache@npm:5.1.1" @@ -11434,18 +10983,18 @@ __metadata: linkType: hard "luxon@npm:^3.2.1, luxon@npm:^3.5.0": - version: 3.7.2 - resolution: "luxon@npm:3.7.2" - checksum: 10/b24cd205ed306ce7415991687897dcc4027921ae413c9116590bc33a95f93b86ce52cf74ba72b4f5c5ab1c10090517f54ac8edfb127c049e0bf55b90dc2260be + version: 3.5.0 + resolution: "luxon@npm:3.5.0" + checksum: 10/48f86e6c1c96815139f8559456a3354a276ba79bcef0ae0d4f2172f7652f3ba2be2237b0e103b8ea0b79b47715354ac9fac04eb1db3485dcc72d5110491dd47f languageName: node linkType: hard -"magic-string@npm:^0.30.21": - version: 0.30.21 - resolution: "magic-string@npm:0.30.21" +"magic-string@npm:^0.30.10": + version: 0.30.11 + resolution: "magic-string@npm:0.30.11" dependencies: - "@jridgewell/sourcemap-codec": "npm:^1.5.5" - checksum: 10/57d5691f41ed40d962d8bd300148114f53db67fadbff336207db10a99f2bdf4a1be9cac3a68ee85dba575912ee1d4402e4396408196ec2d3afd043b076156221 + "@jridgewell/sourcemap-codec": "npm:^1.5.0" + checksum: 10/b784d2240252f5b1e755d487354ada4c672cbca16f045144f7185a75b059210e5fcca7be7be03ef1bac2ca754c4428b21d36ae64a9057ba429916f06b8c54eb2 languageName: node linkType: hard @@ -11465,22 +11014,23 @@ __metadata: languageName: node linkType: hard -"make-fetch-happen@npm:^15.0.0": - version: 15.0.3 - resolution: "make-fetch-happen@npm:15.0.3" +"make-fetch-happen@npm:^13.0.0": + version: 13.0.1 + resolution: "make-fetch-happen@npm:13.0.1" dependencies: - "@npmcli/agent": "npm:^4.0.0" - cacache: "npm:^20.0.1" + "@npmcli/agent": "npm:^2.0.0" + cacache: "npm:^18.0.0" http-cache-semantics: "npm:^4.1.1" + is-lambda: "npm:^1.0.1" minipass: "npm:^7.0.2" - minipass-fetch: "npm:^5.0.0" + minipass-fetch: "npm:^3.0.0" minipass-flush: "npm:^1.0.5" minipass-pipeline: "npm:^1.2.4" - negotiator: "npm:^1.0.0" - proc-log: "npm:^6.0.0" + negotiator: "npm:^0.6.3" + proc-log: "npm:^4.2.0" promise-retry: "npm:^2.0.1" - ssri: "npm:^13.0.0" - checksum: 10/78da4fc1df83cb596e2bae25aa0653b8a9c6cbdd6674a104894e03be3acfcd08c70b78f06ef6407fbd6b173f6a60672480d78641e693d05eb71c09c13ee35278 + ssri: "npm:^10.0.0" + checksum: 10/11bae5ad6ac59b654dbd854f30782f9de052186c429dfce308eda42374528185a100ee40ac9ffdc36a2b6c821ecaba43913e4730a12f06f15e895ea9cb23fa59 languageName: node linkType: hard @@ -11675,39 +11225,30 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^10.2.2, minimatch@npm:^9.0.3 || ^10.0.1": - version: 10.2.2 - resolution: "minimatch@npm:10.2.2" - dependencies: - brace-expansion: "npm:^5.0.2" - checksum: 10/e135be7b502ac97c02bcee42ccc1c55dc26dbac036c0f4acde69e42fe339d7fb53fae711e57b3546cb533426382ea492c73a073c7f78832e0453d120d48dd015 - languageName: node - linkType: hard - -"minimatch@npm:^3.0.4, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2, minimatch@npm:^3.1.3": - version: 3.1.3 - resolution: "minimatch@npm:3.1.3" +"minimatch@npm:^3.0.4, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": + version: 3.1.2 + resolution: "minimatch@npm:3.1.2" dependencies: brace-expansion: "npm:^1.1.7" - checksum: 10/d430c40785fdb42c9fc1a36b9c9e3b08146044bd0f2fd043b05afb436aa4eaf6cdcb7756939ab8fc01664cd75d6335fd5043b2fe2aa084756927ffc77c1e3597 + checksum: 10/e0b25b04cd4ec6732830344e5739b13f8690f8a012d73445a4a19fbc623f5dd481ef7a5827fde25954cd6026fede7574cc54dc4643c99d6c6b653d6203f94634 languageName: node linkType: hard "minimatch@npm:^7.4.6": - version: 7.4.7 - resolution: "minimatch@npm:7.4.7" + version: 7.4.6 + resolution: "minimatch@npm:7.4.6" dependencies: brace-expansion: "npm:^2.0.1" - checksum: 10/509558c83a264ef8ba5cccab39a8937d8a1fdb2da336031de2444cda4dc3fb4e0d8ec78c0d51309635b910aaaa88d84a59f1a7dcfbefb6f6f5b7ce3204de17d4 + checksum: 10/0046ba1161ac6414bde1b07c440792ebcdb2ed93e6714c85c73974332b709b7e692801550bc9da22028a8613407b3f13861e17dd0dd44f4babdeacd44950430b languageName: node linkType: hard -"minimatch@npm:^9.0.3, minimatch@npm:^9.0.4": - version: 9.0.6 - resolution: "minimatch@npm:9.0.6" +"minimatch@npm:^9.0.3, minimatch@npm:^9.0.4, minimatch@npm:^9.0.5": + version: 9.0.5 + resolution: "minimatch@npm:9.0.5" dependencies: - brace-expansion: "npm:^5.0.2" - checksum: 10/c7a46134aaf349f386de9a3f6c5b48c53bc3a4e2ef4b8b6365184504e28cc31cc261a388e181648cbc756b40e213dbce115c8087a47eff8f54ee28d62bc17b08 + brace-expansion: "npm:^2.0.1" + checksum: 10/dd6a8927b063aca6d910b119e1f2df6d2ce7d36eab91de83167dd136bb85e1ebff97b0d3de1cb08bd1f7e018ca170b4962479fefab5b2a69e2ae12cb2edc8348 languageName: node linkType: hard @@ -11738,18 +11279,18 @@ __metadata: languageName: node linkType: hard -"minipass-fetch@npm:^5.0.0": - version: 5.0.2 - resolution: "minipass-fetch@npm:5.0.2" +"minipass-fetch@npm:^3.0.0": + version: 3.0.5 + resolution: "minipass-fetch@npm:3.0.5" dependencies: - iconv-lite: "npm:^0.7.2" + encoding: "npm:^0.1.13" minipass: "npm:^7.0.3" - minipass-sized: "npm:^2.0.0" - minizlib: "npm:^3.0.1" + minipass-sized: "npm:^1.0.3" + minizlib: "npm:^2.1.2" dependenciesMeta: - iconv-lite: + encoding: optional: true - checksum: 10/4f3f65ea5b20a3a287765ebf21cc73e62031f754944272df2a3039296cc75a8fc2dc50b8a3c4f39ce3ac6e5cc583e8dc664d12c6ab98e0883d263e49f344bc86 + checksum: 10/c669948bec1373313aaa8f104b962a3ced9f45c49b26366a4b0ae27ccdfa9c5740d72c8a84d3f8623d7a61c5fc7afdfda44789008c078f61a62441142efc4a97 languageName: node linkType: hard @@ -11771,12 +11312,12 @@ __metadata: languageName: node linkType: hard -"minipass-sized@npm:^2.0.0": - version: 2.0.0 - resolution: "minipass-sized@npm:2.0.0" +"minipass-sized@npm:^1.0.3": + version: 1.0.3 + resolution: "minipass-sized@npm:1.0.3" dependencies: - minipass: "npm:^7.1.2" - checksum: 10/3b89adf64ca705662f77481e278eff5ec0a57aeffb5feba7cc8843722b1e7770efc880f2a17d1d4877b2d7bf227873cd46afb4da44c0fd18088b601ea50f96bb + minipass: "npm:^3.0.0" + checksum: 10/40982d8d836a52b0f37049a0a7e5d0f089637298e6d9b45df9c115d4f0520682a78258905e5c8b180fb41b593b0a82cc1361d2c74b45f7ada66334f84d1ecfdd languageName: node linkType: hard @@ -11789,19 +11330,54 @@ __metadata: languageName: node linkType: hard -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4, minipass@npm:^7.1.2, minipass@npm:^7.1.3": - version: 7.1.3 - resolution: "minipass@npm:7.1.3" - checksum: 10/175e4d5e20980c3cd316ae82d2c031c42f6c746467d8b1905b51060a0ba4461441a0c25bb67c025fd9617f9a3873e152c7b543c6b5ac83a1846be8ade80dffd6 +"minipass@npm:^5.0.0": + version: 5.0.0 + resolution: "minipass@npm:5.0.0" + checksum: 10/61682162d29f45d3152b78b08bab7fb32ca10899bc5991ffe98afc18c9e9543bd1e3be94f8b8373ba6262497db63607079dc242ea62e43e7b2270837b7347c93 languageName: node linkType: hard -"minizlib@npm:^3.0.1, minizlib@npm:^3.1.0": - version: 3.1.0 - resolution: "minizlib@npm:3.1.0" +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4, minipass@npm:^7.1.2": + version: 7.1.2 + resolution: "minipass@npm:7.1.2" + checksum: 10/c25f0ee8196d8e6036661104bacd743785b2599a21de5c516b32b3fa2b83113ac89a2358465bc04956baab37ffb956ae43be679b2262bf7be15fce467ccd7950 + languageName: node + linkType: hard + +"minizlib@npm:^2.1.1, minizlib@npm:^2.1.2": + version: 2.1.2 + resolution: "minizlib@npm:2.1.2" + dependencies: + minipass: "npm:^3.0.0" + yallist: "npm:^4.0.0" + checksum: 10/ae0f45436fb51344dcb87938446a32fbebb540d0e191d63b35e1c773d47512e17307bf54aa88326cc6d176594d00e4423563a091f7266c2f9a6872cdc1e234d1 + languageName: node + linkType: hard + +"minizlib@npm:^3.0.1": + version: 3.0.2 + resolution: "minizlib@npm:3.0.2" dependencies: minipass: "npm:^7.1.2" - checksum: 10/f47365cc2cb7f078cbe7e046eb52655e2e7e97f8c0a9a674f4da60d94fb0624edfcec9b5db32e8ba5a99a5f036f595680ae6fe02a262beaa73026e505cc52f99 + checksum: 10/c075bed1594f68dcc8c35122333520112daefd4d070e5d0a228bd4cf5580e9eed3981b96c0ae1d62488e204e80fd27b2b9d0068ca9a5ef3993e9565faf63ca41 + languageName: node + linkType: hard + +"mkdirp@npm:^1.0.3": + version: 1.0.4 + resolution: "mkdirp@npm:1.0.4" + bin: + mkdirp: bin/cmd.js + checksum: 10/d71b8dcd4b5af2fe13ecf3bd24070263489404fe216488c5ba7e38ece1f54daf219e72a833a3a2dc404331e870e9f44963a33399589490956bff003a3404d3b2 + languageName: node + linkType: hard + +"mkdirp@npm:^3.0.1": + version: 3.0.1 + resolution: "mkdirp@npm:3.0.1" + bin: + mkdirp: dist/cjs/src/bin.js + checksum: 10/16fd79c28645759505914561e249b9a1f5fe3362279ad95487a4501e4467abeb714fd35b95307326b8fd03f3c7719065ef11a6f97b7285d7888306d1bd2232ba languageName: node linkType: hard @@ -11812,7 +11388,7 @@ __metadata: languageName: node linkType: hard -"ms@npm:2.1.3, ms@npm:^2.1.3": +"ms@npm:2.1.3, ms@npm:^2.1.1, ms@npm:^2.1.3": version: 2.1.3 resolution: "ms@npm:2.1.3" checksum: 10/aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d @@ -11846,7 +11422,7 @@ __metadata: languageName: node linkType: hard -"nanoid@npm:^3.3.10, nanoid@npm:^3.3.11, nanoid@npm:^3.3.8": +"nanoid@npm:^3.3.10, nanoid@npm:^3.3.7, nanoid@npm:^3.3.8": version: 3.3.11 resolution: "nanoid@npm:3.3.11" bin: @@ -11855,15 +11431,6 @@ __metadata: languageName: node linkType: hard -"napi-postinstall@npm:^0.3.0": - version: 0.3.4 - resolution: "napi-postinstall@npm:0.3.4" - bin: - napi-postinstall: lib/cli.js - checksum: 10/5541381508f9e1051ff3518701c7130ebac779abb3a1ffe9391fcc3cab4cc0569b0ba0952357db3f6b12909c3bb508359a7a60261ffd795feebbdab967175832 - languageName: node - linkType: hard - "natural-compare@npm:^1.4.0": version: 1.4.0 resolution: "natural-compare@npm:1.4.0" @@ -11871,20 +11438,13 @@ __metadata: languageName: node linkType: hard -"negotiator@npm:0.6.3": +"negotiator@npm:0.6.3, negotiator@npm:^0.6.3": version: 0.6.3 resolution: "negotiator@npm:0.6.3" checksum: 10/2723fb822a17ad55c93a588a4bc44d53b22855bf4be5499916ca0cab1e7165409d0b288ba2577d7b029f10ce18cf2ed8e703e5af31c984e1e2304277ef979837 languageName: node linkType: hard -"negotiator@npm:^1.0.0": - version: 1.0.0 - resolution: "negotiator@npm:1.0.0" - checksum: 10/b5734e87295324fabf868e36fb97c84b7d7f3156ec5f4ee5bf6e488079c11054f818290fc33804cef7b1ee21f55eeb14caea83e7dafae6492a409b3e573153e5 - languageName: node - linkType: hard - "neo-async@npm:^2.6.2": version: 2.6.2 resolution: "neo-async@npm:2.6.2" @@ -11893,13 +11453,13 @@ __metadata: linkType: hard "nock@npm:^13.3.1": - version: 13.5.6 - resolution: "nock@npm:13.5.6" + version: 13.5.5 + resolution: "nock@npm:13.5.5" dependencies: debug: "npm:^4.1.0" json-stringify-safe: "npm:^5.0.1" propagate: "npm:^2.0.0" - checksum: 10/a57c265b75e5f7767e2f8baf058773cdbf357c31c5fea2761386ec03a008a657f9df921899fe2a9502773b47145b708863b32345aef529b3c45cba4019120f88 + checksum: 10/c19d7bf9654db056357a22b00127bb5606c1bbdff188a5b6c469825e580e31cd0cb0701bce8dd8b4876dbbd36a145fdb681fd69fd59308d6db4923ce8ab2439e languageName: node linkType: hard @@ -11936,33 +11496,33 @@ __metadata: linkType: hard "node-gyp-build@npm:^4.2.0": - version: 4.8.4 - resolution: "node-gyp-build@npm:4.8.4" + version: 4.8.1 + resolution: "node-gyp-build@npm:4.8.1" bin: node-gyp-build: bin.js node-gyp-build-optional: optional.js node-gyp-build-test: build-test.js - checksum: 10/6a7d62289d1afc419fc8fc9bd00aa4e554369e50ca0acbc215cb91446148b75ff7e2a3b53c2c5b2c09a39d416d69f3d3237937860373104b5fe429bf30ad9ac5 + checksum: 10/b9297770f96a92e5f2b854f3fd5e4bd418df81d7785a81ab60cec5cf2e5e72dc2c3319808978adc572cfa3885e6b12338cb5f4034bed2cab35f0d76a4b75ccdf languageName: node linkType: hard -"node-gyp@npm:^12.1.0, node-gyp@npm:latest": - version: 12.2.0 - resolution: "node-gyp@npm:12.2.0" +"node-gyp@npm:^10.0.0, node-gyp@npm:latest": + version: 10.2.0 + resolution: "node-gyp@npm:10.2.0" dependencies: env-paths: "npm:^2.2.0" exponential-backoff: "npm:^3.1.1" + glob: "npm:^10.3.10" graceful-fs: "npm:^4.2.6" - make-fetch-happen: "npm:^15.0.0" - nopt: "npm:^9.0.0" - proc-log: "npm:^6.0.0" + make-fetch-happen: "npm:^13.0.0" + nopt: "npm:^7.0.0" + proc-log: "npm:^4.1.0" semver: "npm:^7.3.5" - tar: "npm:^7.5.4" - tinyglobby: "npm:^0.2.12" - which: "npm:^6.0.0" + tar: "npm:^6.2.1" + which: "npm:^4.0.0" bin: node-gyp: bin/node-gyp.js - checksum: 10/4ebab5b77585a637315e969c2274b5520562473fe75de850639a580c2599652fb9f33959ec782ea45a2e149d8f04b548030f472eeeb3dbdf19a7f2ccbc30b908 + checksum: 10/41773093b1275751dec942b985982fd4e7a69b88cae719b868babcef3880ee6168aaec8dcaa8cd0b9fa7c84873e36cc549c6cac6a124ee65ba4ce1f1cc108cfe languageName: node linkType: hard @@ -11973,21 +11533,21 @@ __metadata: languageName: node linkType: hard -"node-releases@npm:^2.0.27": - version: 2.0.27 - resolution: "node-releases@npm:2.0.27" - checksum: 10/f6c78ddb392ae500719644afcbe68a9ea533242c02312eb6a34e8478506eb7482a3fb709c70235b01c32fe65625b68dfa9665113f816d87f163bc3819b62b106 +"node-releases@npm:^2.0.19": + version: 2.0.19 + resolution: "node-releases@npm:2.0.19" + checksum: 10/c2b33b4f0c40445aee56141f13ca692fa6805db88510e5bbb3baadb2da13e1293b738e638e15e4a8eb668bb9e97debb08e7a35409b477b5cc18f171d35a83045 languageName: node linkType: hard -"nopt@npm:^9.0.0": - version: 9.0.0 - resolution: "nopt@npm:9.0.0" +"nopt@npm:^7.0.0": + version: 7.2.1 + resolution: "nopt@npm:7.2.1" dependencies: - abbrev: "npm:^4.0.0" + abbrev: "npm:^2.0.0" bin: nopt: bin/nopt.js - checksum: 10/56a1ccd2ad711fb5115918e2c96828703cddbe12ba2c3bd00591758f6fa30e6f47dd905c59dbfcf9b773f3a293b45996609fb6789ae29d6bfcc3cf3a6f7d9fda + checksum: 10/95a1f6dec8a81cd18cdc2fed93e6f0b4e02cf6bdb4501c848752c6e34f9883d9942f036a5e3b21a699047d8a448562d891e67492df68ec9c373e6198133337ae languageName: node linkType: hard @@ -12015,6 +11575,17 @@ __metadata: languageName: node linkType: hard +"normalize-package-data@npm:^6.0.0": + version: 6.0.2 + resolution: "normalize-package-data@npm:6.0.2" + dependencies: + hosted-git-info: "npm:^7.0.0" + semver: "npm:^7.3.5" + validate-npm-package-license: "npm:^3.0.4" + checksum: 10/7c4216a2426aa76c0197f8372f06b23a0484d62b3518fb5c0f6ebccb16376bdfab29ceba96f95c75f60506473198f1337fe337b945c8df0541fe32b8049ab4c9 + languageName: node + linkType: hard + "normalize-path@npm:^3.0.0": version: 3.0.0 resolution: "normalize-path@npm:3.0.0" @@ -12022,50 +11593,43 @@ __metadata: languageName: node linkType: hard -"npm-install-checks@npm:^8.0.0": - version: 8.0.0 - resolution: "npm-install-checks@npm:8.0.0" +"npm-install-checks@npm:^6.0.0": + version: 6.3.0 + resolution: "npm-install-checks@npm:6.3.0" dependencies: semver: "npm:^7.1.1" - checksum: 10/eb4df6c3270ce6efcebcbc1a02997b3b4bcfa906ac2129ccef80eeffcf062d2e6dcbed02327109296725c1eb138ad93973303e025d2e0115f718fa4c09ed013f + checksum: 10/6c20dadb878a0d2f1f777405217b6b63af1299d0b43e556af9363ee6eefaa98a17dfb7b612a473a473e96faf7e789c58b221e0d8ffdc1d34903c4f71618df3b4 languageName: node linkType: hard "npm-normalize-package-bin@npm:3.0.1, npm-normalize-package-bin@npm:^3.0.0": - version: 3.0.1 - resolution: "npm-normalize-package-bin@npm:3.0.1" - checksum: 10/de416d720ab22137a36292ff8a333af499ea0933ef2320a8c6f56a73b0f0448227fec4db5c890d702e26d21d04f271415eab6580b5546456861cc0c19498a4bf - languageName: node - linkType: hard - -"npm-normalize-package-bin@npm:^5.0.0": - version: 5.0.0 - resolution: "npm-normalize-package-bin@npm:5.0.0" - checksum: 10/969bc042d7bb029b5da7eb733e7642b238e3cb071ad57b56a3f128069bc1a3cbc2a4f4af30ee75b11660c368d60b89811ecd1430cf2ea1a7ff36f30052a4aeda + version: 3.0.1 + resolution: "npm-normalize-package-bin@npm:3.0.1" + checksum: 10/de416d720ab22137a36292ff8a333af499ea0933ef2320a8c6f56a73b0f0448227fec4db5c890d702e26d21d04f271415eab6580b5546456861cc0c19498a4bf languageName: node linkType: hard -"npm-package-arg@npm:^13.0.0": - version: 13.0.2 - resolution: "npm-package-arg@npm:13.0.2" +"npm-package-arg@npm:^11.0.0": + version: 11.0.3 + resolution: "npm-package-arg@npm:11.0.3" dependencies: - hosted-git-info: "npm:^9.0.0" - proc-log: "npm:^6.0.0" + hosted-git-info: "npm:^7.0.0" + proc-log: "npm:^4.0.0" semver: "npm:^7.3.5" - validate-npm-package-name: "npm:^7.0.0" - checksum: 10/810868f4b8c666fc1979f33c5b45606f541be97e82958af486e8d3f5ff2c91f96cea56f22c4665a92dc9a23698cf831cba2e09691387d473f910f9e6590638b3 + validate-npm-package-name: "npm:^5.0.0" + checksum: 10/bacc863907edf98940286edc2fd80327901c1e8b34426d538cdc708ed66bc6567f06d742d838eaf35db6804347bb4ba56ca9cef032c4b52743b33e7a22a2678e languageName: node linkType: hard -"npm-pick-manifest@npm:^11.0.1": - version: 11.0.3 - resolution: "npm-pick-manifest@npm:11.0.3" +"npm-pick-manifest@npm:^9.0.0": + version: 9.1.0 + resolution: "npm-pick-manifest@npm:9.1.0" dependencies: - npm-install-checks: "npm:^8.0.0" - npm-normalize-package-bin: "npm:^5.0.0" - npm-package-arg: "npm:^13.0.0" + npm-install-checks: "npm:^6.0.0" + npm-normalize-package-bin: "npm:^3.0.0" + npm-package-arg: "npm:^11.0.0" semver: "npm:^7.3.5" - checksum: 10/189872190af34f7eccf3c586ad2e21e8c093f90a8f716db80887e8defa2bfb3ea917f61f339908ce0487a4cb1df40fe592aee3e8fe76a180a5b15a887850921a + checksum: 10/e759e4fe4076da9169cf522964a80bbc096d50cd24c8c44b50b44706c4479bd9d9d018fbdb76c6ea0c6037e012e07c6c917a1ecaa7ae1a1169cddfae1c0f24b6 languageName: node linkType: hard @@ -12104,14 +11668,14 @@ __metadata: languageName: node linkType: hard -"object-inspect@npm:^1.13.3": - version: 1.13.4 - resolution: "object-inspect@npm:1.13.4" - checksum: 10/aa13b1190ad3e366f6c83ad8a16ed37a19ed57d267385aa4bfdccda833d7b90465c057ff6c55d035a6b2e52c1a2295582b294217a0a3a1ae7abdd6877ef781fb +"object-inspect@npm:^1.13.1": + version: 1.13.2 + resolution: "object-inspect@npm:1.13.2" + checksum: 10/7ef65583b6397570a17c56f0c1841e0920e83900f2c94638927abb7b81ac08a19c7aae135bd9dcca96208cac0c7332b4650fb927f027b0cf92d71df2990d0561 languageName: node linkType: hard -"on-finished@npm:~2.4.1": +"on-finished@npm:2.4.1": version: 2.4.1 resolution: "on-finished@npm:2.4.1" dependencies: @@ -12148,14 +11712,14 @@ __metadata: linkType: hard "open@npm:^10.1.0": - version: 10.2.0 - resolution: "open@npm:10.2.0" + version: 10.1.0 + resolution: "open@npm:10.1.0" dependencies: default-browser: "npm:^5.2.1" define-lazy-prop: "npm:^3.0.0" is-inside-container: "npm:^1.0.0" - wsl-utils: "npm:^0.1.0" - checksum: 10/e6ad9474734eac3549dcc7d85e952394856ccaee48107c453bd6a725b82e3b8ed5f427658935df27efa76b411aeef62888edea8a9e347e8e7c82632ec966b30e + is-wsl: "npm:^3.1.0" + checksum: 10/a9c4105243a1b3c5312bf2aeb678f78d31f00618b5100088ee01eed2769963ea1f2dd464ac8d93cef51bba2d911e1a9c0c34a753ec7b91d6b22795903ea6647a languageName: node linkType: hard @@ -12209,10 +11773,12 @@ __metadata: languageName: node linkType: hard -"p-map@npm:^7.0.2": - version: 7.0.4 - resolution: "p-map@npm:7.0.4" - checksum: 10/ef48c3b2e488f31c693c9fcc0df0ef76518cf6426a495cf9486ebbb0fd7f31aef7f90e96f72e0070c0ff6e3177c9318f644b512e2c29e3feee8d7153fcb6782e +"p-map@npm:^4.0.0": + version: 4.0.0 + resolution: "p-map@npm:4.0.0" + dependencies: + aggregate-error: "npm:^3.0.0" + checksum: 10/7ba4a2b1e24c05e1fc14bbaea0fc6d85cf005ae7e9c9425d4575550f37e2e584b1af97bcde78eacd7559208f20995988d52881334db16cf77bc1bcf68e48ed7c languageName: node linkType: hard @@ -12231,9 +11797,9 @@ __metadata: linkType: hard "package-json-from-dist@npm:^1.0.0": - version: 1.0.1 - resolution: "package-json-from-dist@npm:1.0.1" - checksum: 10/58ee9538f2f762988433da00e26acc788036914d57c71c246bf0be1b60cdbd77dd60b6a3e1a30465f0b248aeb80079e0b34cb6050b1dfa18c06953bb1cbc7602 + version: 1.0.0 + resolution: "package-json-from-dist@npm:1.0.0" + checksum: 10/ac706ec856a5a03f5261e4e48fa974f24feb044d51f84f8332e2af0af04fbdbdd5bbbfb9cbbe354190409bc8307c83a9e38c6672c3c8855f709afb0006a009ea languageName: node linkType: hard @@ -12246,12 +11812,13 @@ __metadata: languageName: node linkType: hard -"parse-imports-exports@npm:^0.2.4": - version: 0.2.4 - resolution: "parse-imports-exports@npm:0.2.4" +"parse-imports@npm:^2.1.1": + version: 2.2.1 + resolution: "parse-imports@npm:2.2.1" dependencies: - parse-statements: "npm:1.0.11" - checksum: 10/144d459771d1aeaa80eebffe43a2074c34e5b79a86d326c907efea90b62ff41af9555600b8e117e6cab717654d8e20b440e9ab09cdbbc9092f352cb0a9e1f3a3 + es-module-lexer: "npm:^1.5.3" + slashes: "npm:^3.0.12" + checksum: 10/db1d98077587d23bfa1f136abae158ea08e1e588d0260dfc0769092be86b842c798ae47466742b1d9bc106d3430cebbd9730fc34872a2c0e72b9ff720986e82e languageName: node linkType: hard @@ -12274,13 +11841,6 @@ __metadata: languageName: node linkType: hard -"parse-statements@npm:1.0.11": - version: 1.0.11 - resolution: "parse-statements@npm:1.0.11" - checksum: 10/287c2739f4cbffa08e28a95ea2d3ff4a8a51ddb367df6212ae2cd80580a1189e09c6edcb8277fc05d0fdbcb93c86ad16b591f317e2fe12ac4189de738863e514 - languageName: node - linkType: hard - "parse5@npm:^7.0.0, parse5@npm:^7.1.1": version: 7.3.0 resolution: "parse5@npm:7.3.0" @@ -12342,17 +11902,7 @@ __metadata: languageName: node linkType: hard -"path-scurry@npm:^2.0.2": - version: 2.0.2 - resolution: "path-scurry@npm:2.0.2" - dependencies: - lru-cache: "npm:^11.0.0" - minipass: "npm:^7.1.2" - checksum: 10/2b4257422bcb870a4c2d205b3acdbb213a72f5e2250f61c80f79c9d014d010f82bdf8584441612c8e1fa4eb098678f5704a66fa8377d72646bad4be38e57a2c3 - languageName: node - linkType: hard - -"path-to-regexp@npm:~0.1.12": +"path-to-regexp@npm:0.1.12": version: 0.1.12 resolution: "path-to-regexp@npm:0.1.12" checksum: 10/2e30f6a0144679c1f95c98e166b96e6acd1e72be9417830fefc8de7ac1992147eb9a4c7acaa59119fb1b3c34eec393b2129ef27e24b2054a3906fc4fb0d1398e @@ -12367,20 +11917,19 @@ __metadata: linkType: hard "pbkdf2@npm:^3.0.17": - version: 3.1.5 - resolution: "pbkdf2@npm:3.1.5" + version: 3.1.2 + resolution: "pbkdf2@npm:3.1.2" dependencies: - create-hash: "npm:^1.2.0" - create-hmac: "npm:^1.1.7" - ripemd160: "npm:^2.0.3" - safe-buffer: "npm:^5.2.1" - sha.js: "npm:^2.4.12" - to-buffer: "npm:^1.2.1" - checksum: 10/ce1c9a2ebbc843c86090ec6cac6d07429dece7c1fdb87437ce6cf869d0429cc39cab61bc34215585f4a00d8009862df45e197fbd54f3508ccba8ff312a88261b + create-hash: "npm:^1.1.2" + create-hmac: "npm:^1.1.4" + ripemd160: "npm:^2.0.1" + safe-buffer: "npm:^5.0.1" + sha.js: "npm:^2.4.8" + checksum: 10/40bdf30df1c9bb1ae41ec50c11e480cf0d36484b7c7933bf55e4451d1d0e3f09589df70935c56e7fccc5702779a0d7b842d012be8c08a187b44eb24d55bb9460 languageName: node linkType: hard -"picocolors@npm:^1.1.1": +"picocolors@npm:^1.0.1, picocolors@npm:^1.1.1": version: 1.1.1 resolution: "picocolors@npm:1.1.1" checksum: 10/e1cf46bf84886c79055fdfa9dcb3e4711ad259949e3565154b004b260cd356c5d54b31a1437ce9782624bf766272fe6b0154f5f0c744fb7af5d454d2b60db045 @@ -12394,7 +11943,7 @@ __metadata: languageName: node linkType: hard -"picomatch@npm:^4.0.2, picomatch@npm:^4.0.3": +"picomatch@npm:^4.0.3": version: 4.0.3 resolution: "picomatch@npm:4.0.3" checksum: 10/57b99055f40b16798f2802916d9c17e9744e620a0db136554af01d19598b96e45e2f00014c91d1b8b13874b80caa8c295b3d589a3f72373ec4aaf54baa5962d5 @@ -12409,9 +11958,9 @@ __metadata: linkType: hard "pirates@npm:^4.0.4": - version: 4.0.7 - resolution: "pirates@npm:4.0.7" - checksum: 10/2427f371366081ae42feb58214f04805d6b41d6b84d74480ebcc9e0ddbd7105a139f7c653daeaf83ad8a1a77214cf07f64178e76de048128fec501eab3305a96 + version: 4.0.6 + resolution: "pirates@npm:4.0.6" + checksum: 10/d02dda76f4fec1cbdf395c36c11cf26f76a644f9f9a1bfa84d3167d0d3154d5289aacc72677aa20d599bb4a6937a471de1b65c995e2aea2d8687cbcd7e43ea5f languageName: node linkType: hard @@ -12449,21 +11998,14 @@ __metadata: languageName: node linkType: hard -"possible-typed-array-names@npm:^1.0.0": - version: 1.1.0 - resolution: "possible-typed-array-names@npm:1.1.0" - checksum: 10/2f44137b8d3dd35f4a7ba7469eec1cd9cfbb46ec164b93a5bc1f4c3d68599c9910ee3b91da1d28b4560e9cc8414c3cd56fedc07259c67e52cc774476270d3302 - languageName: node - linkType: hard - -"postcss@npm:^8.5.6": - version: 8.5.6 - resolution: "postcss@npm:8.5.6" +"postcss@npm:^8.4.40": + version: 8.4.41 + resolution: "postcss@npm:8.4.41" dependencies: - nanoid: "npm:^3.3.11" - picocolors: "npm:^1.1.1" - source-map-js: "npm:^1.2.1" - checksum: 10/9e4fbe97574091e9736d0e82a591e29aa100a0bf60276a926308f8c57249698935f35c5d2f4e80de778d0cbb8dcffab4f383d85fd50c5649aca421c3df729b86 + nanoid: "npm:^3.3.7" + picocolors: "npm:^1.0.1" + source-map-js: "npm:^1.2.0" + checksum: 10/6e6176c2407eff60493ca60a706c6b7def20a722c3adda94ea1ece38345eb99964191336fd62b62652279cec6938e79e0b1e1d477142c8d3516e7a725a74ee37 languageName: node linkType: hard @@ -12483,46 +12025,36 @@ __metadata: languageName: node linkType: hard -"prettier-linter-helpers@npm:^1.0.1": - version: 1.0.1 - resolution: "prettier-linter-helpers@npm:1.0.1" +"prettier-linter-helpers@npm:^1.0.0": + version: 1.0.0 + resolution: "prettier-linter-helpers@npm:1.0.0" dependencies: fast-diff: "npm:^1.1.2" - checksum: 10/2dc35f5036a35f4c4f5e645887edda1436acb63687a7f12b2383e0a6f3c1f76b8a0a4709fe4d82e19157210feb5984b159bb714d43290022911ab53d606474ec + checksum: 10/00ce8011cf6430158d27f9c92cfea0a7699405633f7f1d4a45f07e21bf78e99895911cbcdc3853db3a824201a7c745bd49bfea8abd5fb9883e765a90f74f8392 languageName: node linkType: hard "prettier-plugin-packagejson@npm:^2.4.5": - version: 2.5.22 - resolution: "prettier-plugin-packagejson@npm:2.5.22" + version: 2.5.2 + resolution: "prettier-plugin-packagejson@npm:2.5.2" dependencies: - sort-package-json: "npm:3.6.0" + sort-package-json: "npm:2.10.1" + synckit: "npm:0.9.1" peerDependencies: prettier: ">= 1.16.0" peerDependenciesMeta: prettier: optional: true - checksum: 10/874ba785d6c3c32abca23470cebfd7b80de7b546c0b3752a83cf5aea7a8030885f0c3a91ef40c52373c1be144b46983d1e5bc6d492096d79604441eae6ed1be0 + checksum: 10/f280d69327a468cd104c72a81134258d3573e56d697a88a5c4498c8d02cecda9a27d9eb3f1d29cc726491782eb3f279c9d41ecf8364a197e20b239c5ccfd0269 languageName: node linkType: hard "prettier@npm:^3.3.3": - version: 3.8.1 - resolution: "prettier@npm:3.8.1" + version: 3.4.2 + resolution: "prettier@npm:3.4.2" bin: prettier: bin/prettier.cjs - checksum: 10/3da1cf8c1ef9bea828aa618553696c312e951f810bee368f6887109b203f18ee869fe88f66e65f9cf60b7cb1f2eae859892c860a300c062ff8ec69c381fc8dbd - languageName: node - linkType: hard - -"pretty-format@npm:30.2.0, pretty-format@npm:^30.0.0": - version: 30.2.0 - resolution: "pretty-format@npm:30.2.0" - dependencies: - "@jest/schemas": "npm:30.0.5" - ansi-styles: "npm:^5.2.0" - react-is: "npm:^18.3.1" - checksum: 10/725890d648e3400575eebc99a334a4cd1498e0d36746313913706bbeea20ada27e17c184a3cd45c50f705c16111afa829f3450233fc0fda5eed293c69757e926 + checksum: 10/a3e806fb0b635818964d472d35d27e21a4e17150c679047f5501e1f23bd4aa806adf660f0c0d35214a210d5d440da6896c2e86156da55f221a57938278dc326e languageName: node linkType: hard @@ -12537,10 +12069,10 @@ __metadata: languageName: node linkType: hard -"proc-log@npm:^6.0.0": - version: 6.1.0 - resolution: "proc-log@npm:6.1.0" - checksum: 10/9033f30f168ed5a0991b773d0c50ff88384c4738e9a0a67d341de36bf7293771eed648ab6a0562f62276da12fde91f3bbfc75ffff6e71ad49aafd74fc646be66 +"proc-log@npm:^4.0.0, proc-log@npm:^4.1.0, proc-log@npm:^4.2.0": + version: 4.2.0 + resolution: "proc-log@npm:4.2.0" + checksum: 10/4e1394491b717f6c1ade15c570ecd4c2b681698474d3ae2d303c1e4b6ab9455bd5a81566211e82890d5a5ae9859718cc6954d5150bb18b09b72ecb297beae90a languageName: node linkType: hard @@ -12558,6 +12090,13 @@ __metadata: languageName: node linkType: hard +"promise-inflight@npm:^1.0.1": + version: 1.0.1 + resolution: "promise-inflight@npm:1.0.1" + checksum: 10/1560d413ea20c5a74f3631d39ba8cbd1972b9228072a755d01e1f5ca5110382d9af76a1582d889445adc6e75bb5ac4886b56dc4b6eae51b30145d7bb1ac7505b + languageName: node + linkType: hard + "promise-retry@npm:^2.0.1": version: 2.0.1 resolution: "promise-retry@npm:2.0.1" @@ -12596,8 +12135,8 @@ __metadata: linkType: hard "protobufjs@npm:^7.2.5": - version: 7.5.4 - resolution: "protobufjs@npm:7.5.4" + version: 7.4.0 + resolution: "protobufjs@npm:7.4.0" dependencies: "@protobufjs/aspromise": "npm:^1.1.2" "@protobufjs/base64": "npm:^1.1.2" @@ -12611,7 +12150,7 @@ __metadata: "@protobufjs/utf8": "npm:^1.1.0" "@types/node": "npm:>=13.7.0" long: "npm:^5.0.0" - checksum: 10/88d677bb6f11a2ecec63fdd053dfe6d31120844d04e865efa9c8fbe0674cd077d6624ecfdf014018a20dcb114ae2a59c1b21966dd8073e920650c71370966439 + checksum: 10/408423506610f70858d7593632f4a6aa4f05796c90fd632be9b9252457c795acc71aa6d3b54bb7f48a890141728fee4ca3906723ccea6c202ad71f21b3879b8b languageName: node linkType: hard @@ -12633,11 +12172,9 @@ __metadata: linkType: hard "psl@npm:^1.1.33": - version: 1.15.0 - resolution: "psl@npm:1.15.0" - dependencies: - punycode: "npm:^2.3.1" - checksum: 10/5e7467eb5196eb7900d156783d12907d445c0122f76c73203ce96b148a6ccf8c5450cc805887ffada38ff92d634afcf33720c24053cb01d5b6598d1c913c5caf + version: 1.9.0 + resolution: "psl@npm:1.9.0" + checksum: 10/d07879d4bfd0ac74796306a8e5a36a93cfb9c4f4e8ee8e63fbb909066c192fe1008cd8f12abd8ba2f62ca28247949a20c8fb32e1d18831d9e71285a1569720f9 languageName: node linkType: hard @@ -12648,7 +12185,7 @@ __metadata: languageName: node linkType: hard -"punycode@npm:^2.1.0, punycode@npm:^2.1.1, punycode@npm:^2.3.1": +"punycode@npm:^2.1.0, punycode@npm:^2.1.1": version: 2.3.1 resolution: "punycode@npm:2.3.1" checksum: 10/febdc4362bead22f9e2608ff0171713230b57aff9dddc1c273aa2a651fbd366f94b7d6a71d78342a7c0819906750351ca7f2edd26ea41b626d87d6a13d1bd059 @@ -12662,21 +12199,12 @@ __metadata: languageName: node linkType: hard -"qs@npm:^6.11.2": - version: 6.15.0 - resolution: "qs@npm:6.15.0" - dependencies: - side-channel: "npm:^1.1.0" - checksum: 10/a3458f2f389285c3512e0ebc55522ee370ac7cb720ba9f0eff3e30fb2bb07631caf556c08e2a3d4481a371ac14faa9ceb7442a0610c5a7e55b23a5bdee7b701c - languageName: node - linkType: hard - -"qs@npm:~6.14.0": - version: 6.14.2 - resolution: "qs@npm:6.14.2" +"qs@npm:6.13.0, qs@npm:^6.11.2": + version: 6.13.0 + resolution: "qs@npm:6.13.0" dependencies: - side-channel: "npm:^1.1.0" - checksum: 10/682933a85bb4b7bd0d66e13c0a40d9e612b5e4bcc2cb9238f711a9368cd22d91654097a74fff93551e58146db282c56ac094957dfdc60ce64ea72c3c9d7779ac + side-channel: "npm:^1.0.6" + checksum: 10/f548b376e685553d12e461409f0d6e5c59ec7c7d76f308e2a888fd9db3e0c5e89902bedd0754db3a9038eda5f27da2331a6f019c8517dc5e0a16b3c9a6e9cef8 languageName: node linkType: hard @@ -12694,6 +12222,13 @@ __metadata: languageName: node linkType: hard +"queue-tick@npm:^1.0.1": + version: 1.0.1 + resolution: "queue-tick@npm:1.0.1" + checksum: 10/f447926c513b64a857906f017a3b350f7d11277e3c8d2a21a42b7998fa1a613d7a829091e12d142bb668905c8f68d8103416c7197856efb0c72fa835b8e254b5 + languageName: node + linkType: hard + "quick-lru@npm:^4.0.1": version: 4.0.1 resolution: "quick-lru@npm:4.0.1" @@ -12717,19 +12252,19 @@ __metadata: languageName: node linkType: hard -"raw-body@npm:~2.5.3": - version: 2.5.3 - resolution: "raw-body@npm:2.5.3" +"raw-body@npm:2.5.2": + version: 2.5.2 + resolution: "raw-body@npm:2.5.2" dependencies: - bytes: "npm:~3.1.2" - http-errors: "npm:~2.0.1" - iconv-lite: "npm:~0.4.24" - unpipe: "npm:~1.0.0" - checksum: 10/f35759fe5a6548e7c529121ead1de4dd163f899749a5896c42e278479df2d9d7f98b5bb17312737c03617765e5a1433e586f717616e5cfbebc13b4738b820601 + bytes: "npm:3.1.2" + http-errors: "npm:2.0.0" + iconv-lite: "npm:0.4.24" + unpipe: "npm:1.0.0" + checksum: 10/863b5171e140546a4d99f349b720abac4410338e23df5e409cfcc3752538c9caf947ce382c89129ba976f71894bd38b5806c774edac35ebf168d02aa1ac11a95 languageName: node linkType: hard -"react-is@npm:^18.0.0, react-is@npm:^18.3.1": +"react-is@npm:^18.0.0": version: 18.3.1 resolution: "react-is@npm:18.3.1" checksum: 10/d5f60c87d285af24b1e1e7eaeb123ec256c3c8bdea7061ab3932e3e14685708221bf234ec50b21e10dd07f008f1b966a2730a0ce4ff67905b3872ff2042aec22 @@ -12777,7 +12312,7 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^2.0.2, readable-stream@npm:^2.3.8": +"readable-stream@npm:^2.0.2": version: 2.3.8 resolution: "readable-stream@npm:2.3.8" dependencies: @@ -12792,25 +12327,25 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^3.6.2 || ^4.4.2, readable-stream@npm:^4.7.0": - version: 4.7.0 - resolution: "readable-stream@npm:4.7.0" +"readable-stream@npm:^3.6.2 || ^4.4.2": + version: 4.5.2 + resolution: "readable-stream@npm:4.5.2" dependencies: abort-controller: "npm:^3.0.0" buffer: "npm:^6.0.3" events: "npm:^3.3.0" process: "npm:^0.11.10" string_decoder: "npm:^1.3.0" - checksum: 10/bdf096c8ff59452ce5d08f13da9597f9fcfe400b4facfaa88e74ec057e5ad1fdfa140ffe28e5ed806cf4d2055f0b812806e962bca91dce31bc4cef08e53be3a4 + checksum: 10/01b128a559c5fd76a898495f858cf0a8839f135e6a69e3409f986e88460134791657eb46a2ff16826f331682a3c4d0c5a75cef5e52ef259711021ba52b1c2e82 languageName: node linkType: hard "readable-web-to-node-stream@npm:^3.0.2": - version: 3.0.4 - resolution: "readable-web-to-node-stream@npm:3.0.4" + version: 3.0.2 + resolution: "readable-web-to-node-stream@npm:3.0.2" dependencies: - readable-stream: "npm:^4.7.0" - checksum: 10/d8fb3de7579d70ea1e9efdfb2f02e2965ae62a1e1d9e9b0bdce493cb3b98090bd4a34526a9ab6c793bb833b89ffd31a5ab06117a3ae2a3df21363651b2131da9 + readable-stream: "npm:^3.6.0" + checksum: 10/d3a5bf9d707c01183d546a64864aa63df4d9cb835dfd2bf89ac8305e17389feef2170c4c14415a10d38f9b9bfddf829a57aaef7c53c8b40f11d499844bf8f1a4 languageName: node linkType: hard @@ -12840,6 +12375,13 @@ __metadata: languageName: node linkType: hard +"regenerator-runtime@npm:^0.14.0": + version: 0.14.1 + resolution: "regenerator-runtime@npm:0.14.1" + checksum: 10/5db3161abb311eef8c45bcf6565f4f378f785900ed3945acf740a9888c792f75b98ecb77f0775f3bf95502ff423529d23e94f41d80c8256e8fa05ed4b07cf471 + languageName: node + linkType: hard + "require-directory@npm:^2.1.1": version: 2.1.1 resolution: "require-directory@npm:2.1.1" @@ -12915,55 +12457,55 @@ __metadata: languageName: node linkType: hard -"resolve@npm:1.22.10": - version: 1.22.10 - resolution: "resolve@npm:1.22.10" +"resolve@npm:1.22.8": + version: 1.22.8 + resolution: "resolve@npm:1.22.8" dependencies: - is-core-module: "npm:^2.16.0" + is-core-module: "npm:^2.13.0" path-parse: "npm:^1.0.7" supports-preserve-symlinks-flag: "npm:^1.0.0" bin: resolve: bin/resolve - checksum: 10/0a398b44da5c05e6e421d70108822c327675febb880eebe905587628de401854c61d5df02866ff34fc4cb1173a51c9f0e84a94702738df3611a62e2acdc68181 + checksum: 10/c473506ee01eb45cbcfefb68652ae5759e092e6b0fb64547feadf9736a6394f258fbc6f88e00c5ca36d5477fbb65388b272432a3600fa223062e54333c156753 languageName: node linkType: hard -"resolve@npm:^1.10.0, resolve@npm:^1.20.0, resolve@npm:^1.22.3": - version: 1.22.11 - resolution: "resolve@npm:1.22.11" +"resolve@npm:^1.10.0, resolve@npm:^1.20.0, resolve@npm:^1.22.3, resolve@npm:^1.22.4": + version: 1.22.10 + resolution: "resolve@npm:1.22.10" dependencies: - is-core-module: "npm:^2.16.1" + is-core-module: "npm:^2.16.0" path-parse: "npm:^1.0.7" supports-preserve-symlinks-flag: "npm:^1.0.0" bin: resolve: bin/resolve - checksum: 10/e1b2e738884a08de03f97ee71494335eba8c2b0feb1de9ae065e82c48997f349f77a2b10e8817e147cf610bfabc4b1cb7891ee8eaf5bf80d4ad514a34c4fab0a + checksum: 10/0a398b44da5c05e6e421d70108822c327675febb880eebe905587628de401854c61d5df02866ff34fc4cb1173a51c9f0e84a94702738df3611a62e2acdc68181 languageName: node linkType: hard -"resolve@patch:resolve@npm%3A1.22.10#optional!builtin": - version: 1.22.10 - resolution: "resolve@patch:resolve@npm%3A1.22.10#optional!builtin::version=1.22.10&hash=c3c19d" +"resolve@patch:resolve@npm%3A1.22.8#optional!builtin": + version: 1.22.8 + resolution: "resolve@patch:resolve@npm%3A1.22.8#optional!builtin::version=1.22.8&hash=c3c19d" dependencies: - is-core-module: "npm:^2.16.0" + is-core-module: "npm:^2.13.0" path-parse: "npm:^1.0.7" supports-preserve-symlinks-flag: "npm:^1.0.0" bin: resolve: bin/resolve - checksum: 10/d4d878bfe3702d215ea23e75e0e9caf99468e3db76f5ca100d27ebdc527366fee3877e54bce7d47cc72ca8952fc2782a070d238bfa79a550eeb0082384c3b81a + checksum: 10/f345cd37f56a2c0275e3fe062517c650bb673815d885e7507566df589375d165bbbf4bdb6aa95600a9bc55f4744b81f452b5a63f95b9f10a72787dba3c90890a languageName: node linkType: hard -"resolve@patch:resolve@npm%3A^1.10.0#optional!builtin, resolve@patch:resolve@npm%3A^1.20.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.3#optional!builtin": - version: 1.22.11 - resolution: "resolve@patch:resolve@npm%3A1.22.11#optional!builtin::version=1.22.11&hash=c3c19d" +"resolve@patch:resolve@npm%3A^1.10.0#optional!builtin, resolve@patch:resolve@npm%3A^1.20.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.3#optional!builtin, resolve@patch:resolve@npm%3A^1.22.4#optional!builtin": + version: 1.22.10 + resolution: "resolve@patch:resolve@npm%3A1.22.10#optional!builtin::version=1.22.10&hash=c3c19d" dependencies: - is-core-module: "npm:^2.16.1" + is-core-module: "npm:^2.16.0" path-parse: "npm:^1.0.7" supports-preserve-symlinks-flag: "npm:^1.0.0" bin: resolve: bin/resolve - checksum: 10/fd342cad25e52cd6f4f3d1716e189717f2522bfd6641109fe7aa372f32b5714a296ed7c238ddbe7ebb0c1ddfe0b7f71c9984171024c97cf1b2073e3e40ff71a8 + checksum: 10/d4d878bfe3702d215ea23e75e0e9caf99468e3db76f5ca100d27ebdc527366fee3877e54bce7d47cc72ca8952fc2782a070d238bfa79a550eeb0082384c3b81a languageName: node linkType: hard @@ -12975,9 +12517,9 @@ __metadata: linkType: hard "reusify@npm:^1.0.4": - version: 1.1.0 - resolution: "reusify@npm:1.1.0" - checksum: 10/af47851b547e8a8dc89af144fceee17b80d5beaf5e6f57ed086432d79943434ff67ca526e92275be6f54b6189f6920a24eace75c2657eed32d02c400312b21ec + version: 1.0.4 + resolution: "reusify@npm:1.0.4" + checksum: 10/14222c9e1d3f9ae01480c50d96057228a8524706db79cdeb5a2ce5bb7070dd9f409a6f84a02cbef8cdc80d39aef86f2dd03d155188a1300c599b05437dcd2ffb languageName: node linkType: hard @@ -12999,13 +12541,13 @@ __metadata: languageName: node linkType: hard -"ripemd160@npm:^2.0.0, ripemd160@npm:^2.0.1, ripemd160@npm:^2.0.3": - version: 2.0.3 - resolution: "ripemd160@npm:2.0.3" +"ripemd160@npm:^2.0.0, ripemd160@npm:^2.0.1": + version: 2.0.2 + resolution: "ripemd160@npm:2.0.2" dependencies: - hash-base: "npm:^3.1.2" - inherits: "npm:^2.0.4" - checksum: 10/d15d42ea0460426675e5320f86d3468ab408af95b1761cf35f8d32c0c97b4d3bb72b7226e990e643b96e1637a8ad26b343a6c7666e1a297bcab4f305a1d9d3e3 + hash-base: "npm:^3.0.0" + inherits: "npm:^2.0.1" + checksum: 10/006accc40578ee2beae382757c4ce2908a826b27e2b079efdcd2959ee544ddf210b7b5d7d5e80467807604244e7388427330f5c6d4cd61e6edaddc5773ccc393 languageName: node linkType: hard @@ -13021,9 +12563,9 @@ __metadata: linkType: hard "run-applescript@npm:^7.0.0": - version: 7.1.0 - resolution: "run-applescript@npm:7.1.0" - checksum: 10/8659fb5f2717b2b37a68cbfe5f678254cf24b5a82a6df3372b180c80c7c137dcd757a4166c3887e459f59a090ca414e8ea7ca97cf3ee5123db54b3b4006d7b7a + version: 7.0.0 + resolution: "run-applescript@npm:7.0.0" + checksum: 10/b02462454d8b182ad4117e5d4626e9e6782eb2072925c9fac582170b0627ae3c1ea92ee9b2df7daf84b5e9ffe14eb1cf5fb70bc44b15c8a0bfcdb47987e2410c languageName: node linkType: hard @@ -13043,7 +12585,7 @@ __metadata: languageName: node linkType: hard -"safe-buffer@npm:5.2.1, safe-buffer@npm:>=5.1.0, safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.1.1, safe-buffer@npm:^5.1.2, safe-buffer@npm:^5.2.1, safe-buffer@npm:~5.2.0": +"safe-buffer@npm:5.2.1, safe-buffer@npm:>=5.1.0, safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.1.1, safe-buffer@npm:^5.1.2, safe-buffer@npm:^5.2.0, safe-buffer@npm:~5.2.0": version: 5.2.1 resolution: "safe-buffer@npm:5.2.1" checksum: 10/32872cd0ff68a3ddade7a7617b8f4c2ae8764d8b7d884c651b74457967a9e0e886267d3ecc781220629c44a865167b61c375d2da6c720c840ecd73f45d5d9451 @@ -13124,45 +12666,45 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.1.1, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.3, semver@npm:^7.7.1, semver@npm:^7.7.2, semver@npm:^7.7.3": - version: 7.7.4 - resolution: "semver@npm:7.7.4" +"semver@npm:^7.1.1, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0, semver@npm:^7.6.3, semver@npm:^7.7.3": + version: 7.7.3 + resolution: "semver@npm:7.7.3" bin: semver: bin/semver.js - checksum: 10/26bdc6d58b29528f4142d29afb8526bc335f4fc04c4a10f2b98b217f277a031c66736bf82d3d3bb354a2f6a3ae50f18fd62b053c4ac3f294a3d10a61f5075b75 + checksum: 10/8dbc3168e057a38fc322af909c7f5617483c50caddba135439ff09a754b20bdd6482a5123ff543dad4affa488ecf46ec5fb56d61312ad20bb140199b88dfaea9 languageName: node linkType: hard -"send@npm:~0.19.0, send@npm:~0.19.1": - version: 0.19.2 - resolution: "send@npm:0.19.2" +"send@npm:0.19.0": + version: 0.19.0 + resolution: "send@npm:0.19.0" dependencies: debug: "npm:2.6.9" depd: "npm:2.0.0" destroy: "npm:1.2.0" - encodeurl: "npm:~2.0.0" + encodeurl: "npm:~1.0.2" escape-html: "npm:~1.0.3" etag: "npm:~1.8.1" - fresh: "npm:~0.5.2" - http-errors: "npm:~2.0.1" + fresh: "npm:0.5.2" + http-errors: "npm:2.0.0" mime: "npm:1.6.0" ms: "npm:2.1.3" - on-finished: "npm:~2.4.1" + on-finished: "npm:2.4.1" range-parser: "npm:~1.2.1" - statuses: "npm:~2.0.2" - checksum: 10/e932a592f62c58560b608a402d52333a8ae98a5ada076feb5db1d03adaa77c3ca32a7befa1c4fd6dedc186e88f342725b0cb4b3d86835eaf834688b259bef18d + statuses: "npm:2.0.1" + checksum: 10/1f6064dea0ae4cbe4878437aedc9270c33f2a6650a77b56a16b62d057527f2766d96ee282997dd53ec0339082f2aad935bc7d989b46b48c82fc610800dc3a1d0 languageName: node linkType: hard -"serve-static@npm:~1.16.2": - version: 1.16.3 - resolution: "serve-static@npm:1.16.3" +"serve-static@npm:1.16.2": + version: 1.16.2 + resolution: "serve-static@npm:1.16.2" dependencies: encodeurl: "npm:~2.0.0" escape-html: "npm:~1.0.3" parseurl: "npm:~1.3.3" - send: "npm:~0.19.1" - checksum: 10/149d6718dd9e53166784d0a65535e21a7c01249d9c51f57224b786a7306354c6807e7811a9f6c143b45c863b1524721fca2f52b5c81a8b5194e3dde034a03b9c + send: "npm:0.19.0" + checksum: 10/7fa9d9c68090f6289976b34fc13c50ac8cd7f16ae6bce08d16459300f7fc61fbc2d7ebfa02884c073ec9d6ab9e7e704c89561882bbe338e99fcacb2912fde737 languageName: node linkType: hard @@ -13205,23 +12747,22 @@ __metadata: languageName: node linkType: hard -"setprototypeof@npm:1.2.0, setprototypeof@npm:~1.2.0": +"setprototypeof@npm:1.2.0": version: 1.2.0 resolution: "setprototypeof@npm:1.2.0" checksum: 10/fde1630422502fbbc19e6844346778f99d449986b2f9cdcceb8326730d2f3d9964dbcb03c02aaadaefffecd0f2c063315ebea8b3ad895914bf1afc1747fc172e languageName: node linkType: hard -"sha.js@npm:^2.4.0, sha.js@npm:^2.4.12, sha.js@npm:^2.4.8": - version: 2.4.12 - resolution: "sha.js@npm:2.4.12" +"sha.js@npm:^2.4.0, sha.js@npm:^2.4.8": + version: 2.4.11 + resolution: "sha.js@npm:2.4.11" dependencies: - inherits: "npm:^2.0.4" - safe-buffer: "npm:^5.2.1" - to-buffer: "npm:^1.2.0" + inherits: "npm:^2.0.1" + safe-buffer: "npm:^5.0.1" bin: - sha.js: bin.js - checksum: 10/39c0993592c2ab34eb2daae2199a2a1d502713765aecb611fd97c0c4ab7cd53e902d628e1962aaf384bafd28f55951fef46dcc78799069ce41d74b03aa13b5a7 + sha.js: ./bin.js + checksum: 10/d833bfa3e0a67579a6ce6e1bc95571f05246e0a441dd8c76e3057972f2a3e098465687a4369b07e83a0375a88703577f71b5b2e966809e67ebc340dbedb478c7 languageName: node linkType: hard @@ -13260,51 +12801,15 @@ __metadata: languageName: node linkType: hard -"side-channel-list@npm:^1.0.0": - version: 1.0.0 - resolution: "side-channel-list@npm:1.0.0" - dependencies: - es-errors: "npm:^1.3.0" - object-inspect: "npm:^1.13.3" - checksum: 10/603b928997abd21c5a5f02ae6b9cc36b72e3176ad6827fab0417ead74580cc4fb4d5c7d0a8a2ff4ead34d0f9e35701ed7a41853dac8a6d1a664fcce1a044f86f - languageName: node - linkType: hard - -"side-channel-map@npm:^1.0.1": - version: 1.0.1 - resolution: "side-channel-map@npm:1.0.1" - dependencies: - call-bound: "npm:^1.0.2" - es-errors: "npm:^1.3.0" - get-intrinsic: "npm:^1.2.5" - object-inspect: "npm:^1.13.3" - checksum: 10/5771861f77feefe44f6195ed077a9e4f389acc188f895f570d56445e251b861754b547ea9ef73ecee4e01fdada6568bfe9020d2ec2dfc5571e9fa1bbc4a10615 - languageName: node - linkType: hard - -"side-channel-weakmap@npm:^1.0.2": - version: 1.0.2 - resolution: "side-channel-weakmap@npm:1.0.2" - dependencies: - call-bound: "npm:^1.0.2" - es-errors: "npm:^1.3.0" - get-intrinsic: "npm:^1.2.5" - object-inspect: "npm:^1.13.3" - side-channel-map: "npm:^1.0.1" - checksum: 10/a815c89bc78c5723c714ea1a77c938377ea710af20d4fb886d362b0d1f8ac73a17816a5f6640f354017d7e292a43da9c5e876c22145bac00b76cfb3468001736 - languageName: node - linkType: hard - -"side-channel@npm:^1.1.0": - version: 1.1.0 - resolution: "side-channel@npm:1.1.0" +"side-channel@npm:^1.0.6": + version: 1.0.6 + resolution: "side-channel@npm:1.0.6" dependencies: + call-bind: "npm:^1.0.7" es-errors: "npm:^1.3.0" - object-inspect: "npm:^1.13.3" - side-channel-list: "npm:^1.0.0" - side-channel-map: "npm:^1.0.1" - side-channel-weakmap: "npm:^1.0.2" - checksum: 10/7d53b9db292c6262f326b6ff3bc1611db84ece36c2c7dc0e937954c13c73185b0406c56589e2bb8d071d6fee468e14c39fb5d203ee39be66b7b8174f179afaba + get-intrinsic: "npm:^1.2.4" + object-inspect: "npm:^1.13.1" + checksum: 10/eb10944f38cebad8ad643dd02657592fa41273ce15b8bfa928d3291aff2d30c20ff777cfe908f76ccc4551ace2d1245822fdc576657cce40e9066c638ca8fa4d languageName: node linkType: hard @@ -13323,11 +12828,11 @@ __metadata: linkType: hard "simple-git-hooks@npm:^2.8.0": - version: 2.13.1 - resolution: "simple-git-hooks@npm:2.13.1" + version: 2.11.1 + resolution: "simple-git-hooks@npm:2.11.1" bin: simple-git-hooks: cli.js - checksum: 10/a315ab71dcc5da1552970051c8b05ab745496e95667501e6961165f9946b58119ed8c3aa0e97748ca04c61b891936e3464c5feb4c5fb2d70a79e8f431809453d + checksum: 10/b19b1edaca3af95442a35e3963fa54955ddd58f481dde25da4f7a48353ae5e35bc875ae381e214fe2889be494e6fe01cc1c5f24aebb9558cee496deda3d026a4 languageName: node linkType: hard @@ -13366,6 +12871,20 @@ __metadata: languageName: node linkType: hard +"slash@npm:^4.0.0": + version: 4.0.0 + resolution: "slash@npm:4.0.0" + checksum: 10/da8e4af73712253acd21b7853b7e0dbba776b786e82b010a5bfc8b5051a1db38ed8aba8e1e8f400dd2c9f373be91eb1c42b66e91abb407ff42b10feece5e1d2d + languageName: node + linkType: hard + +"slashes@npm:^3.0.12": + version: 3.0.12 + resolution: "slashes@npm:3.0.12" + checksum: 10/c221d73765013db64f3eaf49dacc6b99a5d5477e63720c1bb71d1af647965dda23ab100ca1eb622e080f11ffe68e1e0a233b7b908073260bed4ec819ff1d3e42 + languageName: node + linkType: hard + "smart-buffer@npm:^4.2.0": version: 4.2.0 resolution: "smart-buffer@npm:4.2.0" @@ -13374,54 +12893,55 @@ __metadata: linkType: hard "socks-proxy-agent@npm:^8.0.3": - version: 8.0.5 - resolution: "socks-proxy-agent@npm:8.0.5" + version: 8.0.4 + resolution: "socks-proxy-agent@npm:8.0.4" dependencies: - agent-base: "npm:^7.1.2" + agent-base: "npm:^7.1.1" debug: "npm:^4.3.4" socks: "npm:^2.8.3" - checksum: 10/ee99e1dacab0985b52cbe5a75640be6e604135e9489ebdc3048635d186012fbaecc20fbbe04b177dee434c319ba20f09b3e7dfefb7d932466c0d707744eac05c + checksum: 10/c8e7c2b398338b49a0a0f4d2bae5c0602aeeca6b478b99415927b6c5db349ca258448f2c87c6958ebf83eea17d42cbc5d1af0bfecb276cac10b9658b0f07f7d7 languageName: node linkType: hard "socks@npm:^2.8.3": - version: 2.8.7 - resolution: "socks@npm:2.8.7" + version: 2.8.3 + resolution: "socks@npm:2.8.3" dependencies: - ip-address: "npm:^10.0.1" + ip-address: "npm:^9.0.5" smart-buffer: "npm:^4.2.0" - checksum: 10/d19366c95908c19db154f329bbe94c2317d315dc933a7c2b5101e73f32a555c84fb199b62174e1490082a593a4933d8d5a9b297bde7d1419c14a11a965f51356 + checksum: 10/ffcb622c22481dfcd7589aae71fbfd71ca34334064d181df64bf8b7feaeee19706aba4cffd1de35cc7bbaeeaa0af96be2d7f40fcbc7bc0ab69533a7ae9ffc4fb languageName: node linkType: hard -"sort-object-keys@npm:^2.0.1": - version: 2.1.0 - resolution: "sort-object-keys@npm:2.1.0" - checksum: 10/a0a18a6f4ab601adb889204a83e2664a4810042dd9680e588cabb47fffd40473939ce3fda5a28fdb58bac0762a7b45ad442815465b978d4b243bab840df3d7cd +"sort-object-keys@npm:^1.1.3": + version: 1.1.3 + resolution: "sort-object-keys@npm:1.1.3" + checksum: 10/abea944d6722a1710a1aa6e4f9509da085d93d5fc0db23947cb411eedc7731f80022ce8fa68ed83a53dd2ac7441fcf72a3f38c09b3d9bbc4ff80546aa2e151ad languageName: node linkType: hard -"sort-package-json@npm:3.6.0": - version: 3.6.0 - resolution: "sort-package-json@npm:3.6.0" +"sort-package-json@npm:2.10.1": + version: 2.10.1 + resolution: "sort-package-json@npm:2.10.1" dependencies: - detect-indent: "npm:^7.0.2" - detect-newline: "npm:^4.0.1" - git-hooks-list: "npm:^4.1.1" + detect-indent: "npm:^7.0.1" + detect-newline: "npm:^4.0.0" + get-stdin: "npm:^9.0.0" + git-hooks-list: "npm:^3.0.0" + globby: "npm:^13.1.2" is-plain-obj: "npm:^4.1.0" - semver: "npm:^7.7.3" - sort-object-keys: "npm:^2.0.1" - tinyglobby: "npm:^0.2.15" + semver: "npm:^7.6.0" + sort-object-keys: "npm:^1.1.3" bin: sort-package-json: cli.js - checksum: 10/1489edd177dc325c1e5fbfa55e9583dfea8caa950363b43f797d99986f00b722644275f4dfd5491265519365d6394a5fec9fe5d360ed83b74317fdc9fc071ba1 + checksum: 10/3a08cb9227c244d51bfb0eaaa5a9ea82fd3c96ea299c040365700b3f445d46a98411df4237f4e3c96ba67be4dcd53931747eab3b799f0335d278b36d64f1061d languageName: node linkType: hard -"source-map-js@npm:^1.2.1": - version: 1.2.1 - resolution: "source-map-js@npm:1.2.1" - checksum: 10/ff9d8c8bf096d534a5b7707e0382ef827b4dd360a577d3f34d2b9f48e12c9d230b5747974ee7c607f0df65113732711bb701fe9ece3c7edbd43cb2294d707df3 +"source-map-js@npm:^1.2.0": + version: 1.2.0 + resolution: "source-map-js@npm:1.2.0" + checksum: 10/74f331cfd2d121c50790c8dd6d3c9de6be21926de80583b23b37029b0f37aefc3e019fa91f9a10a5e120c08135297e1ecf312d561459c45908cb1e0e365f49e5 languageName: node linkType: hard @@ -13480,9 +13000,16 @@ __metadata: linkType: hard "spdx-license-ids@npm:^3.0.0": - version: 3.0.23 - resolution: "spdx-license-ids@npm:3.0.23" - checksum: 10/fead6be44478e4dd73a0721ae569f4a04f358846d8d82e8d92efae64aca928592e380cf17e8b84c25c948f3a7d8a0b4fc781a1830f3911ca87d52733265176b5 + version: 3.0.20 + resolution: "spdx-license-ids@npm:3.0.20" + checksum: 10/30e566ea74b04232c64819d1f5313c00d92e9c73d054541650331fc794499b3bcc4991bcd90fa3c2fc4d040006f58f63104706255266e87a9d452e6574afc60c + languageName: node + linkType: hard + +"sprintf-js@npm:^1.1.3": + version: 1.1.3 + resolution: "sprintf-js@npm:1.1.3" + checksum: 10/e7587128c423f7e43cc625fe2f87e6affdf5ca51c1cc468e910d8aaca46bb44a7fbcfa552f787b1d3987f7043aeb4527d1b99559e6621e01b42b3f45e5a24cbb languageName: node linkType: hard @@ -13493,30 +13020,23 @@ __metadata: languageName: node linkType: hard -"ssri@npm:^13.0.0": - version: 13.0.1 - resolution: "ssri@npm:13.0.1" +"ssri@npm:^10.0.0": + version: 10.0.6 + resolution: "ssri@npm:10.0.6" dependencies: minipass: "npm:^7.0.3" - checksum: 10/ae560d0378d074006a71b06af71bfbe84a3fe1ac6e16c1f07575f69e670d40170507fe52b21bcc23399429bc6a15f4bc3ea8d9bc88e9dfd7e87de564e6da6a72 - languageName: node - linkType: hard - -"stable-hash-x@npm:^0.2.0": - version: 0.2.0 - resolution: "stable-hash-x@npm:0.2.0" - checksum: 10/136f05d0e4d441876012b423541476ff5b695c93b56d1959560be858b9e324ea6de6c16ecbd735a040ee8396427dd867bed0bf90b2cdb1fc422566747b91a0e5 + checksum: 10/f92c1b3cc9bfd0a925417412d07d999935917bc87049f43ebec41074661d64cf720315661844106a77da9f8204b6d55ae29f9514e673083cae39464343af2a8b languageName: node linkType: hard -"stable-hash@npm:^0.0.5": - version: 0.0.5 - resolution: "stable-hash@npm:0.0.5" - checksum: 10/9222ea2c558e37c4a576cb4e406966b9e6aa05b93f5c4f09ef4aaabe3577439b9b8fbff407b16840b63e2ae83de74290c7b1c2da7360d571e480e46a4aec0a56 +"stable-hash@npm:^0.0.4": + version: 0.0.4 + resolution: "stable-hash@npm:0.0.4" + checksum: 10/21c039d21c1cb739cf8342561753a5e007cb95ea682ccd452e76310bbb9c6987a89de8eda023e320b019f3e4691aabda75079cdbb7dadf7ab9013e931f2f23cd languageName: node linkType: hard -"stack-utils@npm:^2.0.3, stack-utils@npm:^2.0.6": +"stack-utils@npm:^2.0.3": version: 2.0.6 resolution: "stack-utils@npm:2.0.6" dependencies: @@ -13525,21 +13045,25 @@ __metadata: languageName: node linkType: hard -"statuses@npm:~2.0.1, statuses@npm:~2.0.2": - version: 2.0.2 - resolution: "statuses@npm:2.0.2" - checksum: 10/6927feb50c2a75b2a4caab2c565491f7a93ad3d8dbad7b1398d52359e9243a20e2ebe35e33726dee945125ef7a515e9097d8a1b910ba2bbd818265a2f6c39879 +"statuses@npm:2.0.1": + version: 2.0.1 + resolution: "statuses@npm:2.0.1" + checksum: 10/18c7623fdb8f646fb213ca4051be4df7efb3484d4ab662937ca6fbef7ced9b9e12842709872eb3020cc3504b93bde88935c9f6417489627a7786f24f8031cbcb languageName: node linkType: hard "streamx@npm:^2.15.0": - version: 2.23.0 - resolution: "streamx@npm:2.23.0" + version: 2.19.0 + resolution: "streamx@npm:2.19.0" dependencies: - events-universal: "npm:^1.0.0" + bare-events: "npm:^2.2.0" fast-fifo: "npm:^1.3.2" + queue-tick: "npm:^1.0.1" text-decoder: "npm:^1.1.0" - checksum: 10/4969d7032b16497172afa2f8ac889d137764963ae564daf1611a03225dd62d9316d51de8098b5866d21722babde71353067184e7a3e9795d6dc17c902904a780 + dependenciesMeta: + bare-events: + optional: true + checksum: 10/3e57a12402200cce347bd0658b5e7ef14a41636341256d2a9f43100e5c4f5d82166a4df77aef92082686150805a1b14f74370f3c96b4ed3d6d9889da1e3b3c21 languageName: node linkType: hard @@ -13603,11 +13127,11 @@ __metadata: linkType: hard "strip-ansi@npm:^7.0.1": - version: 7.1.2 - resolution: "strip-ansi@npm:7.1.2" + version: 7.1.0 + resolution: "strip-ansi@npm:7.1.0" dependencies: ansi-regex: "npm:^6.0.1" - checksum: 10/db0e3f9654e519c8a33c50fc9304d07df5649388e7da06d3aabf66d29e5ad65d5e6315d8519d409c15b32fa82c1df7e11ed6f8cd50b0e4404463f0c9d77c8d0b + checksum: 10/475f53e9c44375d6e72807284024ac5d668ee1d06010740dec0b9744f2ddf47de8d7151f80e5f6190fc8f384e802fdf9504b76a7e9020c9faee7103623338be2 languageName: node linkType: hard @@ -13657,17 +13181,10 @@ __metadata: languageName: node linkType: hard -"strnum@npm:^1.1.1": - version: 1.1.2 - resolution: "strnum@npm:1.1.2" - checksum: 10/ccd6297a1fdaf0fc8ea0ea904acdae76878d49a4b0d98a70155df4bc081fd88eac5ec99fb150f3d1d1af065c1898d38420705259ba6c39aa850c671bcd54e35d - languageName: node - linkType: hard - -"strnum@npm:^2.1.2": - version: 2.1.2 - resolution: "strnum@npm:2.1.2" - checksum: 10/7d894dff385e3a5c5b29c012cf0a7ea7962a92c6a299383c3d6db945ad2b6f3e770511356a9774dbd54444c56af1dc7c435dad6466c47293c48173274dd6c631 +"strnum@npm:^1.0.5": + version: 1.0.5 + resolution: "strnum@npm:1.0.5" + checksum: 10/d3117975db8372d4d7b2c07601ed2f65bf21cc48d741f37a8617b76370d228f2ec26336e53791ebc3638264d23ca54e6c241f57f8c69bd4941c63c79440525ca languageName: node linkType: hard @@ -13713,19 +13230,30 @@ __metadata: languageName: node linkType: hard -"synckit@npm:^0.11.12": - version: 0.11.12 - resolution: "synckit@npm:0.11.12" +"synckit@npm:0.9.1": + version: 0.9.1 + resolution: "synckit@npm:0.9.1" dependencies: - "@pkgr/core": "npm:^0.2.9" - checksum: 10/2f51978bfed81aaf0b093f596709a72c49b17909020f42b43c5549f9c0fe18b1fe29f82e41ef771172d729b32e9ce82900a85d2b87fa14d59f886d4df8d7a329 + "@pkgr/core": "npm:^0.1.0" + tslib: "npm:^2.6.2" + checksum: 10/bff3903976baf8b699b5483228116d70223781a93b17c70e685c277ee960cdfd1a09cb5a741e6a9ec35e2428f14f4664baec41ccc99a598f267608b2a54f529b languageName: node linkType: hard -"tapable@npm:^2.3.0": - version: 2.3.0 - resolution: "tapable@npm:2.3.0" - checksum: 10/496a841039960533bb6e44816a01fffc2a1eb428bb2051ecab9e87adf07f19e1f937566cbbbb09dceff31163c0ffd81baafcad84db900b601f0155dd0b37e9f2 +"synckit@npm:^0.9.1": + version: 0.9.2 + resolution: "synckit@npm:0.9.2" + dependencies: + "@pkgr/core": "npm:^0.1.0" + tslib: "npm:^2.6.2" + checksum: 10/d45c4288be9c0232343650643892a7edafb79152c0c08d7ae5d33ca2c296b67a0e15f8cb5c9153969612c4ea5cd5686297542384aab977db23cfa6653fe02027 + languageName: node + linkType: hard + +"tapable@npm:^2.2.0": + version: 2.2.1 + resolution: "tapable@npm:2.2.1" + checksum: 10/1769336dd21481ae6347611ca5fca47add0962fd8e80466515032125eca0084a4f0ede11e65341b9c0018ef4e1cf1ad820adbb0fba7cc99865c6005734000b0a languageName: node linkType: hard @@ -13740,16 +13268,31 @@ __metadata: languageName: node linkType: hard -"tar@npm:^7.4.3, tar@npm:^7.5.4": - version: 7.5.9 - resolution: "tar@npm:7.5.9" +"tar@npm:^6.1.11, tar@npm:^6.2.1": + version: 6.2.1 + resolution: "tar@npm:6.2.1" + dependencies: + chownr: "npm:^2.0.0" + fs-minipass: "npm:^2.0.0" + minipass: "npm:^5.0.0" + minizlib: "npm:^2.1.1" + mkdirp: "npm:^1.0.3" + yallist: "npm:^4.0.0" + checksum: 10/bfbfbb2861888077fc1130b84029cdc2721efb93d1d1fb80f22a7ac3a98ec6f8972f29e564103bbebf5e97be67ebc356d37fa48dbc4960600a1eb7230fbd1ea0 + languageName: node + linkType: hard + +"tar@npm:^7.4.3": + version: 7.4.3 + resolution: "tar@npm:7.4.3" dependencies: "@isaacs/fs-minipass": "npm:^4.0.0" chownr: "npm:^3.0.0" minipass: "npm:^7.1.2" - minizlib: "npm:^3.1.0" + minizlib: "npm:^3.0.1" + mkdirp: "npm:^3.0.1" yallist: "npm:^5.0.0" - checksum: 10/1213cdde9c22d6acf8809ba5d2a025212ce3517bc99c4a4c6981b7dc0489bf3b164db9c826c9517680889194c9ba57448c8ff0da35eca9a60bb7689bf0b3897d + checksum: 10/12a2a4fc6dee23e07cc47f1aeb3a14a1afd3f16397e1350036a8f4cdfee8dcac7ef5978337a4e7b2ac2c27a9a6d46388fc2088ea7c80cb6878c814b1425f8ecf languageName: node linkType: hard @@ -13765,15 +13308,15 @@ __metadata: linkType: hard "text-decoder@npm:^1.1.0": - version: 1.2.7 - resolution: "text-decoder@npm:1.2.7" + version: 1.1.1 + resolution: "text-decoder@npm:1.1.1" dependencies: b4a: "npm:^1.6.4" - checksum: 10/151f89339a497353ad579b32536be94bf90a0785fd2aa2dc0a5ec8a4b71ed59998f4adb872201bdc536805425aa8c5cf8f4a936c449be614c1d3c4527688b3d0 + checksum: 10/c6981b93850daeafc8bd1dbd8f984d4fb2d14632f450de0892692b5bbee2d2f4cbef8a807142527370649fd357f58491ede4915d43669eca624cb52b8dd247b6 languageName: node linkType: hard -"tinyglobby@npm:^0.2.12, tinyglobby@npm:^0.2.13, tinyglobby@npm:^0.2.15": +"tinyglobby@npm:^0.2.15": version: 0.2.15 resolution: "tinyglobby@npm:0.2.15" dependencies: @@ -13790,17 +13333,6 @@ __metadata: languageName: node linkType: hard -"to-buffer@npm:^1.2.0, to-buffer@npm:^1.2.1, to-buffer@npm:^1.2.2": - version: 1.2.2 - resolution: "to-buffer@npm:1.2.2" - dependencies: - isarray: "npm:^2.0.5" - safe-buffer: "npm:^5.2.1" - typed-array-buffer: "npm:^1.0.3" - checksum: 10/69d806c20524ff1e4c44d49276bc96ff282dcae484780a3974e275dabeb75651ea430b074a2a4023701e63b3e1d87811cd82c0972f35280fe5461710e4872aba - languageName: node - linkType: hard - "to-regex-range@npm:^5.0.1": version: 5.0.1 resolution: "to-regex-range@npm:5.0.1" @@ -13810,7 +13342,7 @@ __metadata: languageName: node linkType: hard -"toidentifier@npm:~1.0.1": +"toidentifier@npm:1.0.1": version: 1.0.1 resolution: "toidentifier@npm:1.0.1" checksum: 10/952c29e2a85d7123239b5cfdd889a0dde47ab0497f0913d70588f19c53f7e0b5327c95f4651e413c74b785147f9637b17410ac8c846d5d4a20a5a33eb6dc3a45 @@ -13861,17 +13393,6 @@ __metadata: languageName: node linkType: hard -"ts-declaration-location@npm:^1.0.6": - version: 1.0.7 - resolution: "ts-declaration-location@npm:1.0.7" - dependencies: - picomatch: "npm:^4.0.2" - peerDependencies: - typescript: ">=4.0.0" - checksum: 10/a7932fc75d41f10c16089f8f5a5c1ea49d6afca30f09c91c1df14d0a8510f72bcb9f8a395c04f060b66b855b6bd7ea4df81b335fb9d21bef402969a672a4afa7 - languageName: node - linkType: hard - "ts-jest@npm:^29.2.5": version: 29.4.6 resolution: "ts-jest@npm:29.4.6" @@ -13929,14 +13450,14 @@ __metadata: languageName: node linkType: hard -"tslib@npm:2.7.0": - version: 2.7.0 - resolution: "tslib@npm:2.7.0" - checksum: 10/9a5b47ddac65874fa011c20ff76db69f97cf90c78cff5934799ab8894a5342db2d17b4e7613a087046bc1d133d21547ddff87ac558abeec31ffa929c88b7fce6 +"tslib@npm:2.4.0": + version: 2.4.0 + resolution: "tslib@npm:2.4.0" + checksum: 10/d8379e68b36caf082c1905ec25d17df8261e1d68ddc1abfd6c91158a064f6e4402039ae7c02cf4c81d12e3a2a2c7cd8ea2f57b233eb80136a2e3e7279daf2911 languageName: node linkType: hard -"tslib@npm:^2.1.0, tslib@npm:^2.4.0": +"tslib@npm:^2.1.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0, tslib@npm:^2.6.2, tslib@npm:^2.6.3": version: 2.8.1 resolution: "tslib@npm:2.8.1" checksum: 10/3e2e043d5c2316461cb54e5c7fe02c30ef6dccb3384717ca22ae5c6b5bc95232a6241df19c622d9c73b809bea33b187f6dbc73030963e29950c2141bc32a79f7 @@ -13944,10 +13465,10 @@ __metadata: linkType: hard "tsx@npm:^4.20.5": - version: 4.21.0 - resolution: "tsx@npm:4.21.0" + version: 4.20.5 + resolution: "tsx@npm:4.20.5" dependencies: - esbuild: "npm:~0.27.0" + esbuild: "npm:~0.25.0" fsevents: "npm:~2.3.3" get-tsconfig: "npm:^4.7.5" dependenciesMeta: @@ -13955,7 +13476,7 @@ __metadata: optional: true bin: tsx: dist/cli.mjs - checksum: 10/7afedeff855ba98c47dc28b33d7e8e253c4dc1f791938db402d79c174bdf806b897c1a5f91e5b1259c112520c816f826b4c5d98f0bad7e95b02dec66fedb64d2 + checksum: 10/161420678027c43d07b60b7b6b512cc67ff86ae3cca0641a19b0d3e742c5e262bca57034c4bff6d9346f9269e9ada24b6030e1d2bc890df5e1a9754865d3c08a languageName: node linkType: hard @@ -13982,13 +13503,6 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:4.41.0, type-fest@npm:^4.0.0, type-fest@npm:^4.41.0": - version: 4.41.0 - resolution: "type-fest@npm:4.41.0" - checksum: 10/617ace794ac0893c2986912d28b3065ad1afb484cad59297835a0807dc63286c39e8675d65f7de08fafa339afcb8fe06a36e9a188b9857756ae1e92ee8bda212 - languageName: node - linkType: hard - "type-fest@npm:^0.18.0": version: 0.18.1 resolution: "type-fest@npm:0.18.1" @@ -14017,6 +13531,13 @@ __metadata: languageName: node linkType: hard +"type-fest@npm:^4.0.0, type-fest@npm:^4.41.0": + version: 4.41.0 + resolution: "type-fest@npm:4.41.0" + checksum: 10/617ace794ac0893c2986912d28b3065ad1afb484cad59297835a0807dc63286c39e8675d65f7de08fafa339afcb8fe06a36e9a188b9857756ae1e92ee8bda212 + languageName: node + linkType: hard + "type-is@npm:~1.6.18": version: 1.6.18 resolution: "type-is@npm:1.6.18" @@ -14027,17 +13548,6 @@ __metadata: languageName: node linkType: hard -"typed-array-buffer@npm:^1.0.3": - version: 1.0.3 - resolution: "typed-array-buffer@npm:1.0.3" - dependencies: - call-bound: "npm:^1.0.3" - es-errors: "npm:^1.3.0" - is-typed-array: "npm:^1.1.14" - checksum: 10/3fb91f0735fb413b2bbaaca9fabe7b8fc14a3fa5a5a7546bab8a57e755be0e3788d893195ad9c2b842620592de0e68d4c077d4c2c41f04ec25b8b5bb82fa9a80 - languageName: node - linkType: hard - "typedarray@npm:^0.0.6": version: 0.0.6 resolution: "typedarray@npm:0.0.6" @@ -14071,17 +13581,17 @@ __metadata: linkType: hard "typescript-eslint@npm:^8.48.0": - version: 8.56.1 - resolution: "typescript-eslint@npm:8.56.1" + version: 8.54.0 + resolution: "typescript-eslint@npm:8.54.0" dependencies: - "@typescript-eslint/eslint-plugin": "npm:8.56.1" - "@typescript-eslint/parser": "npm:8.56.1" - "@typescript-eslint/typescript-estree": "npm:8.56.1" - "@typescript-eslint/utils": "npm:8.56.1" + "@typescript-eslint/eslint-plugin": "npm:8.54.0" + "@typescript-eslint/parser": "npm:8.54.0" + "@typescript-eslint/typescript-estree": "npm:8.54.0" + "@typescript-eslint/utils": "npm:8.54.0" peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10/e18cd347ddce0f0e5b28121346f27736a418adf68e73d613690ea3a1d0adfe03bc393f77a8872c2cef77ca74bcc0974212d1775c360de33a9987a94cda11a05b + checksum: 10/21b1a27fd44716df8d2c7bac4ebd0caef196a04375fff7919dc817066017b6b8700f1e242bd065a26ac7ce0505b7a588626099e04a28142504ed4f0aae8bffb1 languageName: node linkType: hard @@ -14115,11 +13625,11 @@ __metadata: linkType: hard "ulid@npm:^2.3.0": - version: 2.4.0 - resolution: "ulid@npm:2.4.0" + version: 2.3.0 + resolution: "ulid@npm:2.3.0" bin: - ulid: bin/cli.js - checksum: 10/409ad0a703ea9f25d2a35cf790b767030a2c7b5ca0df6acb73669628156ab63bb97925a3fd7aaaf0b2384d39bd3ed2f7cd2c2de9f1171df6bc79b8c097865d92 + ulid: ./bin/cli.js + checksum: 10/11d7dd35072b863effb1249f66fb03070142a625610f00e5afd99af7e909b5de9cc7ebca6ede621a6bb1b7479b2489d6f064db6742b55c14bff6496ac60f290f languageName: node linkType: hard @@ -14130,28 +13640,21 @@ __metadata: languageName: node linkType: hard -"undici-types@npm:~7.18.0": - version: 7.18.2 - resolution: "undici-types@npm:7.18.2" - checksum: 10/e61a5918f624d68420c3ca9d301e9f15b61cba6e97be39fe2ce266dd6151e4afe424d679372638826cb506be33952774e0424141200111a9857e464216c009af - languageName: node - linkType: hard - -"unique-filename@npm:^5.0.0": - version: 5.0.0 - resolution: "unique-filename@npm:5.0.0" +"unique-filename@npm:^3.0.0": + version: 3.0.0 + resolution: "unique-filename@npm:3.0.0" dependencies: - unique-slug: "npm:^6.0.0" - checksum: 10/a5f67085caef74bdd2a6869a200ed5d68d171f5cc38435a836b5fd12cce4e4eb55e6a190298035c325053a5687ed7a3c96f0a91e82215fd14729769d9ac57d9b + unique-slug: "npm:^4.0.0" + checksum: 10/8e2f59b356cb2e54aab14ff98a51ac6c45781d15ceaab6d4f1c2228b780193dc70fae4463ce9e1df4479cb9d3304d7c2043a3fb905bdeca71cc7e8ce27e063df languageName: node linkType: hard -"unique-slug@npm:^6.0.0": - version: 6.0.0 - resolution: "unique-slug@npm:6.0.0" +"unique-slug@npm:^4.0.0": + version: 4.0.0 + resolution: "unique-slug@npm:4.0.0" dependencies: imurmurhash: "npm:^0.1.4" - checksum: 10/b78ed9d5b01ff465f80975f17387750ed3639909ac487fa82c4ae4326759f6de87c2131c0c39eca4c68cf06c537a8d104fba1dfc8a30308f99bc505345e1eba3 + checksum: 10/40912a8963fc02fb8b600cf50197df4a275c602c60de4cac4f75879d3c48558cfac48de08a25cc10df8112161f7180b3bbb4d662aadb711568602f9eddee54f0 languageName: node linkType: hard @@ -14169,80 +13672,13 @@ __metadata: languageName: node linkType: hard -"unpipe@npm:~1.0.0": +"unpipe@npm:1.0.0, unpipe@npm:~1.0.0": version: 1.0.0 resolution: "unpipe@npm:1.0.0" checksum: 10/4fa18d8d8d977c55cb09715385c203197105e10a6d220087ec819f50cb68870f02942244f1017565484237f1f8c5d3cd413631b1ae104d3096f24fdfde1b4aa2 languageName: node linkType: hard -"unrs-resolver@npm:^1.6.2, unrs-resolver@npm:^1.9.2": - version: 1.11.1 - resolution: "unrs-resolver@npm:1.11.1" - dependencies: - "@unrs/resolver-binding-android-arm-eabi": "npm:1.11.1" - "@unrs/resolver-binding-android-arm64": "npm:1.11.1" - "@unrs/resolver-binding-darwin-arm64": "npm:1.11.1" - "@unrs/resolver-binding-darwin-x64": "npm:1.11.1" - "@unrs/resolver-binding-freebsd-x64": "npm:1.11.1" - "@unrs/resolver-binding-linux-arm-gnueabihf": "npm:1.11.1" - "@unrs/resolver-binding-linux-arm-musleabihf": "npm:1.11.1" - "@unrs/resolver-binding-linux-arm64-gnu": "npm:1.11.1" - "@unrs/resolver-binding-linux-arm64-musl": "npm:1.11.1" - "@unrs/resolver-binding-linux-ppc64-gnu": "npm:1.11.1" - "@unrs/resolver-binding-linux-riscv64-gnu": "npm:1.11.1" - "@unrs/resolver-binding-linux-riscv64-musl": "npm:1.11.1" - "@unrs/resolver-binding-linux-s390x-gnu": "npm:1.11.1" - "@unrs/resolver-binding-linux-x64-gnu": "npm:1.11.1" - "@unrs/resolver-binding-linux-x64-musl": "npm:1.11.1" - "@unrs/resolver-binding-wasm32-wasi": "npm:1.11.1" - "@unrs/resolver-binding-win32-arm64-msvc": "npm:1.11.1" - "@unrs/resolver-binding-win32-ia32-msvc": "npm:1.11.1" - "@unrs/resolver-binding-win32-x64-msvc": "npm:1.11.1" - napi-postinstall: "npm:^0.3.0" - dependenciesMeta: - "@unrs/resolver-binding-android-arm-eabi": - optional: true - "@unrs/resolver-binding-android-arm64": - optional: true - "@unrs/resolver-binding-darwin-arm64": - optional: true - "@unrs/resolver-binding-darwin-x64": - optional: true - "@unrs/resolver-binding-freebsd-x64": - optional: true - "@unrs/resolver-binding-linux-arm-gnueabihf": - optional: true - "@unrs/resolver-binding-linux-arm-musleabihf": - optional: true - "@unrs/resolver-binding-linux-arm64-gnu": - optional: true - "@unrs/resolver-binding-linux-arm64-musl": - optional: true - "@unrs/resolver-binding-linux-ppc64-gnu": - optional: true - "@unrs/resolver-binding-linux-riscv64-gnu": - optional: true - "@unrs/resolver-binding-linux-riscv64-musl": - optional: true - "@unrs/resolver-binding-linux-s390x-gnu": - optional: true - "@unrs/resolver-binding-linux-x64-gnu": - optional: true - "@unrs/resolver-binding-linux-x64-musl": - optional: true - "@unrs/resolver-binding-wasm32-wasi": - optional: true - "@unrs/resolver-binding-win32-arm64-msvc": - optional: true - "@unrs/resolver-binding-win32-ia32-msvc": - optional: true - "@unrs/resolver-binding-win32-x64-msvc": - optional: true - checksum: 10/4de653508cbaae47883a896bd5cdfef0e5e87b428d62620d16fd35cd534beaebf08ebf0cf2f8b4922aa947b2fe745180facf6cc3f39ba364f7ce0f974cb06a70 - languageName: node - linkType: hard - "unzipper@npm:^0.12.3": version: 0.12.3 resolution: "unzipper@npm:0.12.3" @@ -14256,9 +13692,9 @@ __metadata: languageName: node linkType: hard -"update-browserslist-db@npm:^1.2.0": - version: 1.2.3 - resolution: "update-browserslist-db@npm:1.2.3" +"update-browserslist-db@npm:^1.1.1": + version: 1.1.2 + resolution: "update-browserslist-db@npm:1.1.2" dependencies: escalade: "npm:^3.2.0" picocolors: "npm:^1.1.1" @@ -14266,7 +13702,7 @@ __metadata: browserslist: ">= 4.21.0" bin: update-browserslist-db: cli.js - checksum: 10/059f774300efb4b084a49293143c511f3ae946d40397b5c30914e900cd5691a12b8e61b41dd54ed73d3b56c8204165a0333107dd784ccf8f8c81790bcc423175 + checksum: 10/e7bf8221dfb21eba4a770cd803df94625bb04f65a706aa94c567de9600fe4eb6133fda016ec471dad43b9e7959c1bffb6580b5e20a87808d2e8a13e3892699a9 languageName: node linkType: hard @@ -14346,7 +13782,7 @@ __metadata: languageName: node linkType: hard -"validate-npm-package-license@npm:^3.0.1": +"validate-npm-package-license@npm:^3.0.1, validate-npm-package-license@npm:^3.0.4": version: 3.0.4 resolution: "validate-npm-package-license@npm:3.0.4" dependencies: @@ -14363,13 +13799,6 @@ __metadata: languageName: node linkType: hard -"validate-npm-package-name@npm:^7.0.0": - version: 7.0.2 - resolution: "validate-npm-package-name@npm:7.0.2" - checksum: 10/2a9bdc6fd5e4284c8e02279446bfd3c38c0c01222555fd3b00b4765d9d47b217d4a200910be71b80b958f6baf40d2d32e812a8632633a2ce376a9b3b74811072 - languageName: node - linkType: hard - "vary@npm:~1.1.2": version: 1.1.2 resolution: "vary@npm:1.1.2" @@ -14409,13 +13838,6 @@ __metadata: languageName: node linkType: hard -"web-vitals@npm:^4.2.4": - version: 4.2.4 - resolution: "web-vitals@npm:4.2.4" - checksum: 10/68cd1c2625a04b26e7eab67110623396afc6c9ef8c3a76f4e780aefe5b7d4ca1691737a0b99119e1d1ca9a463c4d468c0f0090b1875b6d784589d3a4a8503313 - languageName: node - linkType: hard - "webextension-polyfill-ts@npm:^0.26.0": version: 0.26.0 resolution: "webextension-polyfill-ts@npm:0.26.0" @@ -14514,21 +13936,6 @@ __metadata: languageName: node linkType: hard -"which-typed-array@npm:^1.1.16": - version: 1.1.20 - resolution: "which-typed-array@npm:1.1.20" - dependencies: - available-typed-arrays: "npm:^1.0.7" - call-bind: "npm:^1.0.8" - call-bound: "npm:^1.0.4" - for-each: "npm:^0.3.5" - get-proto: "npm:^1.0.1" - gopd: "npm:^1.2.0" - has-tostringtag: "npm:^1.0.2" - checksum: 10/e56da3fc995d330ff012f682476f7883c16b12d36c6717c87c7ca23eb5a5ef957fa89115dacb389b11a9b4e99d5dbe2d12689b4d5d08c050b5aed0eae385b840 - languageName: node - linkType: hard - "which@npm:^1.2.14": version: 1.3.1 resolution: "which@npm:1.3.1" @@ -14562,14 +13969,14 @@ __metadata: languageName: node linkType: hard -"which@npm:^6.0.0": - version: 6.0.1 - resolution: "which@npm:6.0.1" +"which@npm:^4.0.0": + version: 4.0.0 + resolution: "which@npm:4.0.0" dependencies: - isexe: "npm:^4.0.0" + isexe: "npm:^3.1.1" bin: node-which: bin/which.js - checksum: 10/dbea77c7d3058bf6c78bf9659d2dce4d2b57d39a15b826b2af6ac2e5a219b99dc8a831b79fdbc453c0598adb4f3f84cf9c2491fd52beb9f5d2dececcad117f68 + checksum: 10/f17e84c042592c21e23c8195108cff18c64050b9efb8459589116999ea9da6dd1509e6a1bac3aeebefd137be00fabbb61b5c2bc0aa0f8526f32b58ee2f545651 languageName: node linkType: hard @@ -14651,18 +14058,18 @@ __metadata: languageName: node linkType: hard -"ws@npm:8.18.0": - version: 8.18.0 - resolution: "ws@npm:8.18.0" +"ws@npm:^7.5.10": + version: 7.5.10 + resolution: "ws@npm:7.5.10" peerDependencies: bufferutil: ^4.0.1 - utf-8-validate: ">=5.0.2" + utf-8-validate: ^5.0.2 peerDependenciesMeta: bufferutil: optional: true utf-8-validate: optional: true - checksum: 10/70dfe53f23ff4368d46e4c0b1d4ca734db2c4149c6f68bc62cb16fc21f753c47b35fcc6e582f3bdfba0eaeb1c488cddab3c2255755a5c3eecb251431e42b3ff6 + checksum: 10/9c796b84ba80ffc2c2adcdfc9c8e9a219ba99caa435c9a8d45f9ac593bba325563b3f83edc5eb067cc6d21b9a6bf2c930adf76dd40af5f58a5ca6859e81858f0 languageName: node linkType: hard @@ -14681,15 +14088,6 @@ __metadata: languageName: node linkType: hard -"wsl-utils@npm:^0.1.0": - version: 0.1.0 - resolution: "wsl-utils@npm:0.1.0" - dependencies: - is-wsl: "npm:^3.1.0" - checksum: 10/de4c92187e04c3c27b4478f410a02e81c351dc85efa3447bf1666f34fc80baacd890a6698ec91995631714086992036013286aea3d77e6974020d40a08e00aec - languageName: node - linkType: hard - "xhr2@npm:0.2.1": version: 0.2.1 resolution: "xhr2@npm:0.2.1" @@ -14754,11 +14152,11 @@ __metadata: linkType: hard "yaml@npm:^2.2.2, yaml@npm:^2.3.4": - version: 2.8.2 - resolution: "yaml@npm:2.8.2" + version: 2.8.0 + resolution: "yaml@npm:2.8.0" bin: yaml: bin.mjs - checksum: 10/4eab0074da6bc5a5bffd25b9b359cf7061b771b95d1b3b571852098380db3b1b8f96e0f1f354b56cc7216aa97cea25163377ccbc33a2e9ce00316fe8d02f4539 + checksum: 10/7d4bd9c10d0e467601f496193f2ac254140f8e36f96f5ff7f852b9ce37974168eb7354f4c36dc8837dde527a2043d004b6aff48818ec24a69ab2dd3c6b6c381c languageName: node linkType: hard From 8abf646ecfe239a6c2215881055942abe7278185 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Fri, 27 Feb 2026 18:02:24 +0100 Subject: [PATCH 52/55] chore: update lockfile for remote-feature-flag-controller ^4.1.0 --- yarn.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn.lock b/yarn.lock index 1dd72951c10..86a55159976 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2958,7 +2958,7 @@ __metadata: "@metamask/messenger": "npm:^0.3.0" "@metamask/polling-controller": "npm:^16.0.3" "@metamask/profile-sync-controller": "npm:^27.1.0" - "@metamask/remote-feature-flag-controller": "npm:^4.0.0" + "@metamask/remote-feature-flag-controller": "npm:^4.1.0" "@metamask/superstruct": "npm:^3.1.0" "@metamask/utils": "npm:^11.9.0" "@ts-bridge/cli": "npm:^0.6.4" @@ -4640,7 +4640,7 @@ __metadata: languageName: unknown linkType: soft -"@metamask/remote-feature-flag-controller@npm:^4.0.0, @metamask/remote-feature-flag-controller@npm:^4.1.0, @metamask/remote-feature-flag-controller@workspace:packages/remote-feature-flag-controller": +"@metamask/remote-feature-flag-controller@npm:^4.1.0, @metamask/remote-feature-flag-controller@workspace:packages/remote-feature-flag-controller": version: 0.0.0-use.local resolution: "@metamask/remote-feature-flag-controller@workspace:packages/remote-feature-flag-controller" dependencies: From 6a590eff90237123287619d1d8412cbb1a5eabd5 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Fri, 27 Feb 2026 22:03:38 +0100 Subject: [PATCH 53/55] fix: fix comments --- packages/config-registry-controller/LICENSE | 2 +- .../src/ConfigRegistryController.test.ts | 173 +++++++++--------- .../src/ConfigRegistryController.ts | 39 +++- .../config-registry-api-service.ts | 5 +- .../config-registry-controller/src/index.ts | 5 +- .../src/utils/feature-flags.test.ts | 41 +++++ .../src/utils/feature-flags.ts | 27 ++- 7 files changed, 175 insertions(+), 117 deletions(-) create mode 100644 packages/config-registry-controller/src/utils/feature-flags.test.ts diff --git a/packages/config-registry-controller/LICENSE b/packages/config-registry-controller/LICENSE index 7d002dced3a..c8a0ff6be3a 100644 --- a/packages/config-registry-controller/LICENSE +++ b/packages/config-registry-controller/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2025 MetaMask +Copyright (c) 2026 MetaMask Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/packages/config-registry-controller/src/ConfigRegistryController.test.ts b/packages/config-registry-controller/src/ConfigRegistryController.test.ts index 5b40e5d19a1..3f1de1f2a51 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.test.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.test.ts @@ -224,7 +224,6 @@ describe('ConfigRegistryController', () => { controller.startPolling(null); await jest.advanceTimersByTimeAsync(0); expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); - controller.stopAllPolling(); }); }); @@ -238,7 +237,6 @@ describe('ConfigRegistryController', () => { mockApiServiceHandler.mockClear(); await jest.advanceTimersByTimeAsync(pollingInterval); expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); - controller.stopAllPolling(); }, ); }); @@ -848,8 +846,6 @@ describe('ConfigRegistryController', () => { await jest.advanceTimersByTimeAsync(0); expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); - - controller.stopAllPolling(); }, ); }); @@ -873,9 +869,6 @@ describe('ConfigRegistryController', () => { await jest.advanceTimersByTimeAsync(1); expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); - - controller.stopAllPolling(); - jest.restoreAllMocks(); }, ); }); @@ -899,9 +892,6 @@ describe('ConfigRegistryController', () => { await jest.advanceTimersByTimeAsync(1); expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); - - controller.stopAllPolling(); - jest.restoreAllMocks(); }, ); }); @@ -926,8 +916,6 @@ describe('ConfigRegistryController', () => { controller.startPolling(null); await jest.advanceTimersByTimeAsync(0); expect(mockApiServiceHandler).toHaveBeenCalledTimes(callsAfterFirst); - - controller.stopAllPolling(); }, ); }); @@ -957,8 +945,6 @@ describe('ConfigRegistryController', () => { expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG, }); - - controller.stopAllPolling(); }, ); }); @@ -1308,8 +1294,6 @@ describe('ConfigRegistryController', () => { expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG, }); - - controller.stopAllPolling(); }, ); }); @@ -1334,8 +1318,6 @@ describe('ConfigRegistryController', () => { expect(controller.state.configs).toStrictEqual({ networks: MOCK_FALLBACK_CONFIG, }); - - controller.stopAllPolling(); }, ); }); @@ -1343,17 +1325,13 @@ describe('ConfigRegistryController', () => { describe('KeyringController event listeners', () => { it('starts polling when KeyringController:unlock event is published', async () => { - await withController( - async ({ controller, rootMessenger, mockApiServiceHandler }) => { - rootMessenger.publish('KeyringController:unlock'); + await withController(async ({ rootMessenger, mockApiServiceHandler }) => { + rootMessenger.publish('KeyringController:unlock'); - await jest.advanceTimersByTimeAsync(0); - - expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); + await jest.advanceTimersByTimeAsync(0); - controller.stopAllPolling(); - }, - ); + expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); + }); }); it('stops polling when KeyringController:lock event is published', async () => { @@ -1377,17 +1355,14 @@ describe('ConfigRegistryController', () => { await jest.advanceTimersByTimeAsync(0); expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); - - controller.stopAllPolling(); }); }); }); describe('RemoteFeatureFlagController:stateChange', () => { - it('starts polling when flag becomes enabled', async () => { + it('starts polling when flag becomes enabled and keyring is unlocked', async () => { await withController( async ({ - controller, rootMessenger, mockRemoteFeatureFlagGetState, mockApiServiceHandler, @@ -1397,6 +1372,7 @@ describe('ConfigRegistryController', () => { cacheTimestamp: Date.now(), }); + rootMessenger.publish('KeyringController:unlock'); rootMessenger.publish( 'RemoteFeatureFlagController:stateChange', { @@ -1408,8 +1384,33 @@ describe('ConfigRegistryController', () => { await jest.advanceTimersByTimeAsync(0); expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); + }, + ); + }); - controller.stopAllPolling(); + it('does not start polling when keyring is locked and flag becomes enabled', async () => { + await withController( + async ({ + rootMessenger, + mockRemoteFeatureFlagGetState, + mockApiServiceHandler, + }) => { + mockRemoteFeatureFlagGetState.mockReturnValue({ + remoteFeatureFlags: { configRegistryApiEnabled: true }, + cacheTimestamp: Date.now(), + }); + + rootMessenger.publish( + 'RemoteFeatureFlagController:stateChange', + { + remoteFeatureFlags: { configRegistryApiEnabled: true }, + cacheTimestamp: Date.now(), + }, + [], + ); + + await jest.advanceTimersByTimeAsync(DEFAULT_POLLING_INTERVAL); + expect(mockApiServiceHandler).not.toHaveBeenCalled(); }, ); }); @@ -1447,7 +1448,7 @@ describe('ConfigRegistryController', () => { }); }); - describe('stopPolling', () => { + describe('stopAllPolling', () => { it('clears pending delayed poll timeout when stopping', async () => { const pollingInterval = 10000; const recentTimestamp = Date.now() - 2000; @@ -1484,6 +1485,60 @@ describe('ConfigRegistryController', () => { }); }); + it('stops all polling when called without token (backward compatible)', async () => { + await withController(async ({ controller, mockApiServiceHandler }) => { + controller.startPolling(null); + controller.startPolling(null); + + await jest.advanceTimersByTimeAsync(0); + expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); + mockApiServiceHandler.mockClear(); + + controller.stopAllPolling(); + + await jest.advanceTimersByTimeAsync(DEFAULT_POLLING_INTERVAL); + expect(mockApiServiceHandler).not.toHaveBeenCalled(); + }); + }); + + it('works via messenger action with token', async () => { + await withController(async ({ messenger, mockApiServiceHandler }) => { + const token = messenger.call( + 'ConfigRegistryController:startPolling', + null, + ); + expect(typeof token).toBe('string'); + + await jest.advanceTimersByTimeAsync(0); + expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); + mockApiServiceHandler.mockClear(); + + messenger.call('ConfigRegistryController:stopPolling'); + await jest.advanceTimersByTimeAsync(DEFAULT_POLLING_INTERVAL); + expect(mockApiServiceHandler).not.toHaveBeenCalled(); + }); + }); + + it('works via messenger action without token (backward compatible)', async () => { + await withController(async ({ messenger, mockApiServiceHandler }) => { + const token = messenger.call( + 'ConfigRegistryController:startPolling', + null, + ); + expect(typeof token).toBe('string'); + + await jest.advanceTimersByTimeAsync(0); + expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); + mockApiServiceHandler.mockClear(); + + messenger.call('ConfigRegistryController:stopPolling'); + await jest.advanceTimersByTimeAsync(DEFAULT_POLLING_INTERVAL); + expect(mockApiServiceHandler).not.toHaveBeenCalled(); + }); + }); + }); + + describe('stopPollingByPollingToken', () => { it('stops delayed poll using placeholder token', async () => { const pollingInterval = 10000; const recentTimestamp = Date.now() - 2000; @@ -1540,22 +1595,6 @@ describe('ConfigRegistryController', () => { ); }); - it('stops all polling when called without token (backward compatible)', async () => { - await withController(async ({ controller, mockApiServiceHandler }) => { - controller.startPolling(null); - controller.startPolling(null); - - await jest.advanceTimersByTimeAsync(0); - expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); - mockApiServiceHandler.mockClear(); - - controller.stopAllPolling(); - - await jest.advanceTimersByTimeAsync(DEFAULT_POLLING_INTERVAL); - expect(mockApiServiceHandler).not.toHaveBeenCalled(); - }); - }); - it('stops specific polling session when called with token', async () => { await withController(async ({ controller, mockApiServiceHandler }) => { const tokenA = controller.startPolling(null); @@ -1575,41 +1614,5 @@ describe('ConfigRegistryController', () => { expect(mockApiServiceHandler).not.toHaveBeenCalled(); }); }); - - it('works via messenger action with token', async () => { - await withController(async ({ messenger, mockApiServiceHandler }) => { - const token = messenger.call( - 'ConfigRegistryController:startPolling', - null, - ); - expect(typeof token).toBe('string'); - - await jest.advanceTimersByTimeAsync(0); - expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); - mockApiServiceHandler.mockClear(); - - messenger.call('ConfigRegistryController:stopPolling'); - await jest.advanceTimersByTimeAsync(DEFAULT_POLLING_INTERVAL); - expect(mockApiServiceHandler).not.toHaveBeenCalled(); - }); - }); - - it('works via messenger action without token (backward compatible)', async () => { - await withController(async ({ messenger, mockApiServiceHandler }) => { - const token = messenger.call( - 'ConfigRegistryController:startPolling', - null, - ); - expect(typeof token).toBe('string'); - - await jest.advanceTimersByTimeAsync(0); - expect(mockApiServiceHandler).toHaveBeenCalledTimes(1); - mockApiServiceHandler.mockClear(); - - messenger.call('ConfigRegistryController:stopPolling'); - await jest.advanceTimersByTimeAsync(DEFAULT_POLLING_INTERVAL); - expect(mockApiServiceHandler).not.toHaveBeenCalled(); - }); - }); }); }); diff --git a/packages/config-registry-controller/src/ConfigRegistryController.ts b/packages/config-registry-controller/src/ConfigRegistryController.ts index 44fafc33996..151e4c65926 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.ts @@ -178,6 +178,8 @@ export class ConfigRegistryController extends StaticIntervalPollingController { + #keyringLocked = true; + /** * @param options - The controller options. * @param options.messenger - The controller messenger. Must have @@ -220,17 +222,29 @@ export class ConfigRegistryController extends StaticIntervalPollingController - this.startPolling(null), - ); + this.messenger.subscribe('KeyringController:unlock', () => { + this.#keyringLocked = false; + this.startPolling(null); + }); - this.messenger.subscribe('KeyringController:lock', () => - this.stopAllPolling(), - ); + this.messenger.subscribe('KeyringController:lock', () => { + this.#keyringLocked = true; + this.stopAllPolling(); + }); this.messenger.subscribe('RemoteFeatureFlagController:stateChange', () => { - if (isConfigRegistryApiEnabled(this.messenger)) { - this.startPolling(null); + let enabled = false; + try { + enabled = isConfigRegistryApiEnabled( + this.messenger.call('RemoteFeatureFlagController:getState'), + ); + } catch { + // RemoteFeatureFlagController unavailable; treat as disabled. + } + if (enabled) { + if (!this.#keyringLocked) { + this.startPolling(null); + } } else { this.stopAllPolling(); } @@ -238,7 +252,14 @@ export class ConfigRegistryController extends StaticIntervalPollingController { - const isApiEnabled = isConfigRegistryApiEnabled(this.messenger); + let isApiEnabled = false; + try { + isApiEnabled = isConfigRegistryApiEnabled( + this.messenger.call('RemoteFeatureFlagController:getState'), + ); + } catch { + // RemoteFeatureFlagController unavailable; skip fetch. + } // Skip fetch when API is disabled; client uses static config. if (!isApiEnabled) { diff --git a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts index 6757788d897..b023e2bdb42 100644 --- a/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts +++ b/packages/config-registry-controller/src/config-registry-api-service/config-registry-api-service.ts @@ -1,4 +1,4 @@ -import { createServicePolicy } from '@metamask/controller-utils'; +import { createServicePolicy, HttpError } from '@metamask/controller-utils'; import type { CreateServicePolicyOptions, ServicePolicy, @@ -203,7 +203,8 @@ export class ConfigRegistryApiService { } if (!res.ok) { - throw new Error( + throw new HttpError( + res.status, `Failed to fetch config: ${res.status} ${res.statusText}`, ); } diff --git a/packages/config-registry-controller/src/index.ts b/packages/config-registry-controller/src/index.ts index fb78860cb7b..71bef8bf446 100644 --- a/packages/config-registry-controller/src/index.ts +++ b/packages/config-registry-controller/src/index.ts @@ -31,9 +31,6 @@ export type { ConfigRegistryApiServiceMethodActions, } from './config-registry-api-service/config-registry-api-service-method-action-types'; export type { NetworkFilterOptions } from './config-registry-api-service/filters'; -export { - ConfigRegistryApiService, - serviceName as configRegistryApiServiceName, -} from './config-registry-api-service/config-registry-api-service'; +export { ConfigRegistryApiService } from './config-registry-api-service/config-registry-api-service'; export { filterNetworks } from './config-registry-api-service/filters'; export { isConfigRegistryApiEnabled } from './utils/feature-flags'; diff --git a/packages/config-registry-controller/src/utils/feature-flags.test.ts b/packages/config-registry-controller/src/utils/feature-flags.test.ts new file mode 100644 index 00000000000..a81376fca22 --- /dev/null +++ b/packages/config-registry-controller/src/utils/feature-flags.test.ts @@ -0,0 +1,41 @@ +import { isConfigRegistryApiEnabled } from './feature-flags'; + +describe('isConfigRegistryApiEnabled', () => { + it('returns true when configRegistryApiEnabled is true', () => { + expect( + isConfigRegistryApiEnabled({ + remoteFeatureFlags: { configRegistryApiEnabled: true }, + cacheTimestamp: 0, + }), + ).toBe(true); + }); + + it('returns false when configRegistryApiEnabled is false', () => { + expect( + isConfigRegistryApiEnabled({ + remoteFeatureFlags: { configRegistryApiEnabled: false }, + cacheTimestamp: 0, + }), + ).toBe(false); + }); + + it('returns false when configRegistryApiEnabled is missing', () => { + expect( + isConfigRegistryApiEnabled({ + remoteFeatureFlags: {}, + cacheTimestamp: 0, + }), + ).toBe(false); + }); + + it('returns false when flag value is not a boolean', () => { + expect( + isConfigRegistryApiEnabled({ + remoteFeatureFlags: { + configRegistryApiEnabled: 'true' as unknown as boolean, + }, + cacheTimestamp: 0, + }), + ).toBe(false); + }); +}); diff --git a/packages/config-registry-controller/src/utils/feature-flags.ts b/packages/config-registry-controller/src/utils/feature-flags.ts index 0957c654fb8..a7d6fe0f17b 100644 --- a/packages/config-registry-controller/src/utils/feature-flags.ts +++ b/packages/config-registry-controller/src/utils/feature-flags.ts @@ -1,29 +1,24 @@ -import type { ConfigRegistryControllerMessenger } from '../ConfigRegistryController'; +import type { RemoteFeatureFlagControllerState } from '@metamask/remote-feature-flag-controller'; const FEATURE_FLAG_KEY = 'configRegistryApiEnabled'; const DEFAULT_FEATURE_FLAG_VALUE = false; /** - * Checks if the config registry API feature flag is enabled. + * Selector: returns whether the config registry API feature flag is enabled + * from the given RemoteFeatureFlagController state. * - * @param messenger - The controller messenger. + * @param state - The RemoteFeatureFlagController state. * @returns True if the feature flag is enabled, false otherwise. */ export function isConfigRegistryApiEnabled( - messenger: ConfigRegistryControllerMessenger, + state: RemoteFeatureFlagControllerState, ): boolean { - try { - const state = messenger.call('RemoteFeatureFlagController:getState'); - const featureFlags = state.remoteFeatureFlags; + const { remoteFeatureFlags } = state; + const flagValue = remoteFeatureFlags?.[FEATURE_FLAG_KEY]; - const flagValue = featureFlags[FEATURE_FLAG_KEY]; - - if (typeof flagValue === 'boolean') { - return flagValue; - } - - return DEFAULT_FEATURE_FLAG_VALUE; - } catch { - return DEFAULT_FEATURE_FLAG_VALUE; + if (typeof flagValue === 'boolean') { + return flagValue; } + + return DEFAULT_FEATURE_FLAG_VALUE; } From 5c05642a0491c8e3056c85f298e137a7874c84a3 Mon Sep 17 00:00:00 2001 From: Amine Harty Date: Fri, 27 Feb 2026 22:39:39 +0100 Subject: [PATCH 54/55] fix: restart polling when feature flag enabled after unlock --- .../config-registry-controller/src/ConfigRegistryController.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/config-registry-controller/src/ConfigRegistryController.ts b/packages/config-registry-controller/src/ConfigRegistryController.ts index 151e4c65926..66fc9ab8cdb 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.ts @@ -243,6 +243,7 @@ export class ConfigRegistryController extends StaticIntervalPollingController Date: Fri, 27 Feb 2026 23:04:40 +0100 Subject: [PATCH 55/55] fix: fix cursor bot comment --- .../src/ConfigRegistryController.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/config-registry-controller/src/ConfigRegistryController.ts b/packages/config-registry-controller/src/ConfigRegistryController.ts index 66fc9ab8cdb..f6638470e01 100644 --- a/packages/config-registry-controller/src/ConfigRegistryController.ts +++ b/packages/config-registry-controller/src/ConfigRegistryController.ts @@ -224,7 +224,17 @@ export class ConfigRegistryController extends StaticIntervalPollingController { this.#keyringLocked = false; - this.startPolling(null); + try { + if ( + isConfigRegistryApiEnabled( + this.messenger.call('RemoteFeatureFlagController:getState'), + ) + ) { + this.startPolling(null); + } + } catch { + // RemoteFeatureFlagController unavailable; do not start polling. + } }); this.messenger.subscribe('KeyringController:lock', () => {