diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index dd322799ccc..f97fef01a56 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -68,6 +68,7 @@ /packages/base-controller @MetaMask/core-platform /packages/build-utils @MetaMask/core-platform /packages/composable-controller @MetaMask/core-platform +/packages/connectivity-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/README.md b/README.md index 92d9c369396..48d06d72c30 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,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/connectivity-controller`](packages/connectivity-controller) - [`@metamask/controller-utils`](packages/controller-utils) - [`@metamask/core-backend`](packages/core-backend) - [`@metamask/delegation-controller`](packages/delegation-controller) @@ -111,6 +112,7 @@ linkStyle default opacity:0.5 chain_agnostic_permission(["@metamask/chain-agnostic-permission"]); claims_controller(["@metamask/claims-controller"]); composable_controller(["@metamask/composable-controller"]); + connectivity_controller(["@metamask/connectivity-controller"]); controller_utils(["@metamask/controller-utils"]); core_backend(["@metamask/core-backend"]); delegation_controller(["@metamask/delegation-controller"]); @@ -231,6 +233,8 @@ linkStyle default opacity:0.5 composable_controller --> base_controller; composable_controller --> messenger; composable_controller --> json_rpc_engine; + connectivity_controller --> base_controller; + connectivity_controller --> messenger; core_backend --> accounts_controller; core_backend --> controller_utils; core_backend --> keyring_controller; diff --git a/packages/connectivity-controller/CHANGELOG.md b/packages/connectivity-controller/CHANGELOG.md new file mode 100644 index 00000000000..a7b62e188a8 --- /dev/null +++ b/packages/connectivity-controller/CHANGELOG.md @@ -0,0 +1,14 @@ +# 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] + +### Added + +- Initial release ([#7623](https://github.com/MetaMask/core/pull/7623)) + +[Unreleased]: https://github.com/MetaMask/core/ diff --git a/packages/connectivity-controller/LICENSE b/packages/connectivity-controller/LICENSE new file mode 100644 index 00000000000..c8a0ff6be3a --- /dev/null +++ b/packages/connectivity-controller/LICENSE @@ -0,0 +1,20 @@ +MIT License + +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 +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/connectivity-controller/README.md b/packages/connectivity-controller/README.md new file mode 100644 index 00000000000..fb6eabf17b6 --- /dev/null +++ b/packages/connectivity-controller/README.md @@ -0,0 +1,15 @@ +# `@metamask/connectivity-controller` + +ConnectivityController stores the device's internet connectivity status. + +## Installation + +`yarn add @metamask/connectivity-controller` + +or + +`npm install @metamask/connectivity-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/connectivity-controller/jest.config.js b/packages/connectivity-controller/jest.config.js new file mode 100644 index 00000000000..ca084133399 --- /dev/null +++ b/packages/connectivity-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/connectivity-controller/package.json b/packages/connectivity-controller/package.json new file mode 100644 index 00000000000..404f78b55e8 --- /dev/null +++ b/packages/connectivity-controller/package.json @@ -0,0 +1,72 @@ +{ + "name": "@metamask/connectivity-controller", + "version": "0.0.0", + "description": "ConnectivityController stores the device's internet connectivity status", + "keywords": [ + "MetaMask", + "Ethereum" + ], + "homepage": "https://github.com/MetaMask/core/tree/main/packages/connectivity-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/connectivity-controller", + "changelog:validate": "../../scripts/validate-changelog.sh @metamask/connectivity-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": { + "@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/connectivity-controller/src/ConnectivityController.test.ts b/packages/connectivity-controller/src/ConnectivityController.test.ts new file mode 100644 index 00000000000..c7826c5118a --- /dev/null +++ b/packages/connectivity-controller/src/ConnectivityController.test.ts @@ -0,0 +1,256 @@ +import { deriveStateFromMetadata } from '@metamask/base-controller'; +import { Messenger, MOCK_ANY_NAMESPACE } from '@metamask/messenger'; +import type { + MockAnyNamespace, + MessengerActions, + MessengerEvents, +} from '@metamask/messenger'; + +import type { ConnectivityControllerMessenger } from './ConnectivityController'; +import { ConnectivityController } from './ConnectivityController'; +import { CONNECTIVITY_STATUSES } from './types'; +import type { ConnectivityAdapter, ConnectivityStatus } from './types'; + +describe('ConnectivityController', () => { + describe('constructor', () => { + it('uses service initial state when online', async () => { + const mockAdapter: ConnectivityAdapter = { + getStatus: jest.fn().mockReturnValue(CONNECTIVITY_STATUSES.Online), + onConnectivityChange: jest.fn(), + destroy: jest.fn(), + }; + + await withController( + { options: { connectivityAdapter: mockAdapter } }, + ({ controller }) => { + expect(controller.state.connectivityStatus).toBe( + CONNECTIVITY_STATUSES.Online, + ); + expect(mockAdapter.getStatus).toHaveBeenCalled(); + }, + ); + }); + + it('uses service initial state when offline', async () => { + const mockAdapter: ConnectivityAdapter = { + getStatus: jest.fn().mockReturnValue(CONNECTIVITY_STATUSES.Offline), + onConnectivityChange: jest.fn(), + destroy: jest.fn(), + }; + + await withController( + { options: { connectivityAdapter: mockAdapter } }, + ({ controller }) => { + expect(controller.state.connectivityStatus).toBe( + CONNECTIVITY_STATUSES.Offline, + ); + }, + ); + }); + }); + + describe('metadata', () => { + it('includes expected state in debug snapshots', async () => { + await withController(({ controller }) => { + expect( + deriveStateFromMetadata( + controller.state, + controller.metadata, + 'includeInDebugSnapshot', + ), + ).toMatchInlineSnapshot(` + Object { + "connectivityStatus": "online", + } + `); + }); + }); + + it('includes expected state in state logs', async () => { + await withController(({ controller }) => { + expect( + deriveStateFromMetadata( + controller.state, + controller.metadata, + 'includeInStateLogs', + ), + ).toMatchInlineSnapshot(` + Object { + "connectivityStatus": "online", + } + `); + }); + }); + + it('persists expected state', async () => { + await withController(({ controller }) => { + expect( + deriveStateFromMetadata( + controller.state, + controller.metadata, + 'persist', + ), + ).toMatchInlineSnapshot(`Object {}`); + }); + }); + + it('exposes expected state to UI', async () => { + await withController(({ controller }) => { + expect( + deriveStateFromMetadata( + controller.state, + controller.metadata, + 'usedInUi', + ), + ).toMatchInlineSnapshot(` + Object { + "connectivityStatus": "online", + } + `); + }); + }); + }); + + describe('when connectivity changes via the adapter', () => { + it('updates state when service reports offline', async () => { + let onConnectivityChangeCallback: ( + connectivityStatus: ConnectivityStatus, + ) => void; + const mockAdapter: ConnectivityAdapter = { + getStatus: jest.fn().mockReturnValue(CONNECTIVITY_STATUSES.Online), + onConnectivityChange( + callback: (connectivityStatus: ConnectivityStatus) => void, + ) { + onConnectivityChangeCallback = callback; + }, + destroy: jest.fn(), + }; + await withController( + { options: { connectivityAdapter: mockAdapter } }, + ({ controller }) => { + expect(controller.state.connectivityStatus).toBe( + CONNECTIVITY_STATUSES.Online, + ); + // Simulate service reporting offline + onConnectivityChangeCallback(CONNECTIVITY_STATUSES.Offline); + expect(controller.state.connectivityStatus).toBe( + CONNECTIVITY_STATUSES.Offline, + ); + }, + ); + }); + + it('updates state when service reports online', async () => { + let onConnectivityChangeCallback: ( + connectivityStatus: ConnectivityStatus, + ) => void; + const mockAdapter: ConnectivityAdapter = { + getStatus: jest.fn().mockReturnValue(CONNECTIVITY_STATUSES.Offline), + onConnectivityChange( + callback: (connectivityStatus: ConnectivityStatus) => void, + ) { + onConnectivityChangeCallback = callback; + }, + destroy: jest.fn(), + }; + await withController( + { options: { connectivityAdapter: mockAdapter } }, + ({ controller }) => { + expect(controller.state.connectivityStatus).toBe( + CONNECTIVITY_STATUSES.Offline, + ); + // Simulate service reporting online + onConnectivityChangeCallback(CONNECTIVITY_STATUSES.Online); + expect(controller.state.connectivityStatus).toBe( + CONNECTIVITY_STATUSES.Online, + ); + }, + ); + }); + }); +}); + +/** + * The type of the messenger populated with all external actions and events + * required by the controller under test. + */ +type RootMessenger = Messenger< + MockAnyNamespace, + MessengerActions, + MessengerEvents +>; + +/** + * The callback that `withController` calls. + */ +type WithControllerCallback = (payload: { + controller: ConnectivityController; + rootMessenger: RootMessenger; + controllerMessenger: ConnectivityControllerMessenger; +}) => Promise | ReturnValue; + +/** + * The options that `withController` takes. + */ +type WithControllerOptions = { + options: Partial[0]>; +}; + +/** + * Constructs the messenger populated with all external actions and events + * required by the controller under test. + * + * @returns The root messenger. + */ +function getRootMessenger(): RootMessenger { + return new Messenger({ namespace: MOCK_ANY_NAMESPACE }); +} + +/** + * Constructs the messenger for the controller under test. + * + * @param rootMessenger - The root messenger, with all external actions and + * events required by the controller's messenger. + * @returns The controller-specific messenger. + */ +function getMessenger( + rootMessenger: RootMessenger, +): ConnectivityControllerMessenger { + return new Messenger({ + namespace: 'ConnectivityController', + parent: rootMessenger, + }); +} + +/** + * Wrap tests for the controller under test by ensuring that the controller is + * created ahead of time and then safely destroyed afterward as needed. + * + * @param args - Either a function, or an options bag + a function. The options + * bag contains arguments for the controller constructor. All constructor + * arguments are optional and will be filled in with defaults in as needed + * (including `messenger` and `connectivityAdapter`). The function is called + * with the instantiated controller, root messenger, and controller messenger. + * @returns The same return value as the given function. + */ +async function withController( + ...args: + | [WithControllerCallback] + | [WithControllerOptions, WithControllerCallback] +): Promise { + const [{ options = {} }, testFunction] = + args.length === 2 ? args : [{}, args[0]]; + const rootMessenger = getRootMessenger(); + const controllerMessenger = getMessenger(rootMessenger); + const defaultAdapter: ConnectivityAdapter = { + getStatus: jest.fn().mockReturnValue(CONNECTIVITY_STATUSES.Online), + onConnectivityChange: jest.fn(), + destroy: jest.fn(), + }; + const controller = new ConnectivityController({ + messenger: controllerMessenger, + connectivityAdapter: defaultAdapter, + ...options, + }); + return await testFunction({ controller, rootMessenger, controllerMessenger }); +} diff --git a/packages/connectivity-controller/src/ConnectivityController.ts b/packages/connectivity-controller/src/ConnectivityController.ts new file mode 100644 index 00000000000..63bd8e304aa --- /dev/null +++ b/packages/connectivity-controller/src/ConnectivityController.ts @@ -0,0 +1,168 @@ +import type { + ControllerGetStateAction, + ControllerStateChangeEvent, + StateMetadata, +} from '@metamask/base-controller'; +import { BaseController } from '@metamask/base-controller'; +import type { Messenger } from '@metamask/messenger'; + +import { CONNECTIVITY_STATUSES } from './types'; +import type { ConnectivityAdapter, ConnectivityStatus } from './types'; + +/** + * The name of the {@link ConnectivityController}, used to namespace the + * controller's actions and events and to namespace the controller's state data + * when composed with other controllers. + */ +export const controllerName = 'ConnectivityController'; + +/** + * State for the {@link ConnectivityController}. + */ +export type ConnectivityControllerState = { + /** + * The current device connectivity status. + * Named with 'connectivity' prefix to avoid conflicts when state is flattened in Redux. + */ + connectivityStatus: ConnectivityStatus; +}; + +/** + * The metadata for each property in {@link ConnectivityControllerState}. + */ +const connectivityControllerMetadata = { + connectivityStatus: { + persist: false, + includeInDebugSnapshot: true, + includeInStateLogs: true, + usedInUi: true, + }, +} satisfies StateMetadata; + +/** + * Constructs the default {@link ConnectivityController} state. This allows + * consumers to provide a partial state object when initializing the controller + * and also helps in constructing complete state objects for this controller in + * tests. + * + * @returns The default {@link ConnectivityController} state. + */ +export function getDefaultConnectivityControllerState(): ConnectivityControllerState { + return { + connectivityStatus: CONNECTIVITY_STATUSES.Online, + }; +} + +/** + * Retrieves the state of the {@link ConnectivityController}. + */ +export type ConnectivityControllerGetStateAction = ControllerGetStateAction< + typeof controllerName, + ConnectivityControllerState +>; + +/** + * Actions that {@link ConnectivityControllerMessenger} exposes to other consumers. + */ +export type ConnectivityControllerActions = + ConnectivityControllerGetStateAction; + +/** + * Actions from other messengers that {@link ConnectivityControllerMessenger} calls. + */ +type AllowedActions = never; + +/** + * Published when the state of {@link ConnectivityController} changes. + */ +export type ConnectivityControllerStateChangeEvent = ControllerStateChangeEvent< + typeof controllerName, + ConnectivityControllerState +>; + +/** + * Events that {@link ConnectivityControllerMessenger} exposes to other consumers. + */ +export type ConnectivityControllerEvents = + ConnectivityControllerStateChangeEvent; + +/** + * Events from other messengers that {@link ConnectivityControllerMessenger} subscribes + * to. + */ +type AllowedEvents = never; + +/** + * The messenger restricted to actions and events accessed by + * {@link ConnectivityController}. + */ +export type ConnectivityControllerMessenger = Messenger< + typeof controllerName, + ConnectivityControllerActions | AllowedActions, + ConnectivityControllerEvents | AllowedEvents +>; + +/** + * Options for constructing the {@link ConnectivityController}. + */ +export type ConnectivityControllerOptions = { + /** + * The messenger for inter-controller communication. + */ + messenger: ConnectivityControllerMessenger; + + /** + * Connectivity adapter for platform-specific detection. + */ + connectivityAdapter: ConnectivityAdapter; +}; + +/** + * ConnectivityController stores the device's internet connectivity status. + * + * This controller is platform-agnostic and designed to be used across different + * MetaMask clients (extension, mobile). It requires a `ConnectivityAdapter` to + * be injected, which provides platform-specific connectivity detection. + * + * The controller subscribes to the adapter's `onConnectivityChange` callback + * and updates its state accordingly. All connectivity updates flow through + * the adapter, ensuring a single source of truth. + * + * This controller provides a centralized state for connectivity status, + * enabling the UI and other controllers to adapt when the user goes offline. + */ +export class ConnectivityController extends BaseController< + typeof controllerName, + ConnectivityControllerState, + ConnectivityControllerMessenger +> { + /** + * Constructs a new {@link ConnectivityController}. + * + * @param args - The arguments to this controller. + * @param args.messenger - The messenger suited for this controller. + * @param args.connectivityAdapter - The connectivity adapter to use. + */ + constructor({ + messenger, + connectivityAdapter, + }: ConnectivityControllerOptions) { + const initialStatus = connectivityAdapter.getStatus(); + + super({ + messenger, + metadata: connectivityControllerMetadata, + name: controllerName, + state: { + ...getDefaultConnectivityControllerState(), + connectivityStatus: initialStatus, + }, + }); + + connectivityAdapter.onConnectivityChange((status) => { + this.update((draftState) => { + draftState.connectivityStatus = status; + }); + }); + } +} diff --git a/packages/connectivity-controller/src/index.ts b/packages/connectivity-controller/src/index.ts new file mode 100644 index 00000000000..d3306e84e19 --- /dev/null +++ b/packages/connectivity-controller/src/index.ts @@ -0,0 +1,14 @@ +export type { + ConnectivityControllerState, + ConnectivityControllerGetStateAction, + ConnectivityControllerActions, + ConnectivityControllerStateChangeEvent, + ConnectivityControllerEvents, + ConnectivityControllerMessenger, +} from './ConnectivityController'; +export type { ConnectivityAdapter, ConnectivityStatus } from './types'; +export { CONNECTIVITY_STATUSES } from './types'; +export { + ConnectivityController, + getDefaultConnectivityControllerState, +} from './ConnectivityController'; diff --git a/packages/connectivity-controller/src/types.ts b/packages/connectivity-controller/src/types.ts new file mode 100644 index 00000000000..13b336064fd --- /dev/null +++ b/packages/connectivity-controller/src/types.ts @@ -0,0 +1,37 @@ +/** + * Connectivity status constants. + * Used to represent whether the device has internet connectivity. + */ +export const CONNECTIVITY_STATUSES = { + Online: 'online', + Offline: 'offline', +} as const; + +export type ConnectivityStatus = + (typeof CONNECTIVITY_STATUSES)[keyof typeof CONNECTIVITY_STATUSES]; + +/** + * Adapter interface for platform-specific connectivity detection. + * Each platform (extension, mobile) implements this interface using + * platform-specific APIs to detect internet connectivity. + */ +export type ConnectivityAdapter = { + /** + * Returns the current connectivity status. + * + * @returns 'online' if the device is online, 'offline' otherwise. + */ + getStatus(): ConnectivityStatus; + + /** + * Registers a callback to be called when connectivity status changes. + * + * @param callback - Function called with 'online' when online, 'offline' when offline. + */ + onConnectivityChange(callback: (status: ConnectivityStatus) => void): void; + + /** + * Cleans up any resources (event listeners, subscriptions). + */ + destroy(): void; +}; diff --git a/packages/connectivity-controller/tsconfig.build.json b/packages/connectivity-controller/tsconfig.build.json new file mode 100644 index 00000000000..931c4d6594b --- /dev/null +++ b/packages/connectivity-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/connectivity-controller/tsconfig.json b/packages/connectivity-controller/tsconfig.json new file mode 100644 index 00000000000..68c3ddfc2cd --- /dev/null +++ b/packages/connectivity-controller/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.packages.json", + "compilerOptions": { + "baseUrl": "./" + }, + "references": [{ "path": "../base-controller" }, { "path": "../messenger" }], + "include": ["../../types", "./src"] +} diff --git a/packages/connectivity-controller/typedoc.json b/packages/connectivity-controller/typedoc.json new file mode 100644 index 00000000000..c9da015dbf8 --- /dev/null +++ b/packages/connectivity-controller/typedoc.json @@ -0,0 +1,7 @@ +{ + "entryPoints": ["./src/index.ts"], + "excludePrivate": true, + "hideGenerator": true, + "out": "docs", + "tsconfig": "./tsconfig.build.json" +} diff --git a/teams.json b/teams.json index 0d749eecf5d..dc7dc9d2f93 100644 --- a/teams.json +++ b/teams.json @@ -37,6 +37,7 @@ "metamask/base-controller": "team-core-platform", "metamask/build-utils": "team-core-platform", "metamask/composable-controller": "team-core-platform", + "metamask/connectivity-controller": "team-core-platform", "metamask/controller-utils": "team-core-platform", "metamask/error-reporting-service": "team-core-platform", "metamask/messenger": "team-core-platform", diff --git a/tsconfig.build.json b/tsconfig.build.json index b9952494357..9737d20b28b 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -55,6 +55,9 @@ { "path": "./packages/composable-controller/tsconfig.build.json" }, + { + "path": "./packages/connectivity-controller/tsconfig.build.json" + }, { "path": "./packages/controller-utils/tsconfig.build.json" }, diff --git a/tsconfig.json b/tsconfig.json index c712ed48c73..1429ad75efb 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -56,6 +56,9 @@ { "path": "./packages/composable-controller" }, + { + "path": "./packages/connectivity-controller" + }, { "path": "./packages/controller-utils" }, diff --git a/yarn.lock b/yarn.lock index e679695eb24..88b4ce0614c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2964,6 +2964,24 @@ __metadata: languageName: unknown linkType: soft +"@metamask/connectivity-controller@workspace:packages/connectivity-controller": + version: 0.0.0-use.local + resolution: "@metamask/connectivity-controller@workspace:packages/connectivity-controller" + dependencies: + "@metamask/auto-changelog": "npm:^3.4.4" + "@metamask/base-controller": "npm:^9.0.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"