@metamask-previews/base-controller 9.1.0-preview-8bfa290fb → 10.0.0-preview-97d6b86c0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,10 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [10.0.0]
11
+
10
12
  ### Changed
11
13
 
14
+ - **BREAKING:** Drop CommonJS support ([#9536](https://github.com/MetaMask/core/pull/9536))
15
+ - This package is now ESM-only, but can still be used in CommonJS projects via `require(esm)` in modern Node.js versions (22+), or dynamic imports in older Node.js versions.
16
+ - **BREAKING:** Bump minimum Node.js version to 22 ([#9976](https://github.com/MetaMask/core/pull/9976))
17
+ - **BREAKING:** Bump TypeScript target to ES2022 ([#10019](https://github.com/MetaMask/core/pull/10019))
18
+ - This package now ships ES2022 code, requiring a compatible modern environment or bundler configuration to consume.
12
19
  - Bump `@metamask/utils` from `^11.9.0` to `^11.12.0` ([#9074](https://github.com/MetaMask/core/pull/9074), [#10076](https://github.com/MetaMask/core/pull/10076))
13
- - Bump `@metamask/messenger` from `^1.1.1` to `^2.0.0` ([#8632](https://github.com/MetaMask/core/pull/8632), [#9392](https://github.com/MetaMask/core/pull/9392))
20
+ - Bump `@metamask/messenger` from `^1.1.1` to `^3.0.0` ([#8632](https://github.com/MetaMask/core/pull/8632), [#9392](https://github.com/MetaMask/core/pull/9392), [#10160](https://github.com/MetaMask/core/pull/10160))
14
21
 
15
22
  ## [9.1.0]
16
23
 
@@ -151,14 +158,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
151
158
  - Remove `RestrictedControllerMessenger` export which was an alias for `RestrictedMessenger`. Consumers should import `RestrictedMessenger` directly
152
159
  - Remove `RestrictedControllerMessengerConstraint` type export which was an alias for `RestrictedMessengerConstraint`. Consumers should use `RestrictedMessengerConstraint` type directly
153
160
  - Simplify `RestrictedMessenger` constructor by removing deprecated `controllerMessenger` parameter. The messenger instance should now be passed using only the `messenger` parameter instead of supporting both options
154
- - Widen input parameter for type guard `isBaseController` from `ControllerInstance` to `unknown` ([#5018](https://github.com/MetaMask/core/pull/5018/))
161
+ - Widen input parameter for type guard `isBaseController` from `ControllerInstance` to `unknown` ([#5018](https://github.com/MetaMask/core/pull/5018))
155
162
  - Bump `@metamask/json-rpc-engine` from `^10.0.2` to `^10.0.3` ([#5272](https://github.com/MetaMask/core/pull/5272))
156
163
  - Bump `@metamask/utils` from `^11.0.1` to `^11.1.0` ([#5223](https://github.com/MetaMask/core/pull/5223))
157
164
 
158
165
  ### Removed
159
166
 
160
- - **BREAKING:** Remove class `BaseControllerV1` and type guard `isBaseControllerV1` ([#5018](https://github.com/MetaMask/core/pull/5018/))
161
- - **BREAKING:** Remove types `BaseConfig`, `BaseControllerV1Instance`, `BaseState`, `ConfigConstraintV1`, `Listener`, `StateConstraintV1`, `LegacyControllerStateConstraint`, `ControllerInstance` ([#5018](https://github.com/MetaMask/core/pull/5018/))
167
+ - **BREAKING:** Remove class `BaseControllerV1` and type guard `isBaseControllerV1` ([#5018](https://github.com/MetaMask/core/pull/5018))
168
+ - **BREAKING:** Remove types `BaseConfig`, `BaseControllerV1Instance`, `BaseState`, `ConfigConstraintV1`, `Listener`, `StateConstraintV1`, `LegacyControllerStateConstraint`, `ControllerInstance` ([#5018](https://github.com/MetaMask/core/pull/5018))
162
169
 
163
170
  ## [7.1.1]
164
171
 
@@ -195,7 +202,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
195
202
  ["Are the Types Wrong?"](https://arethetypeswrong.github.io/) tool as
196
203
  ["masquerading as CJS"](https://github.com/arethetypeswrong/arethetypeswrong.github.io/blob/main/docs/problems/FalseCJS.md).
197
204
  All of the ATTW checks now pass.
198
- - Remove chunk files ([#4648](https://github.com/MetaMask/core/pull/4648)).
205
+ - Remove chunk files. ([#4648](https://github.com/MetaMask/core/pull/4648))
199
206
  - Previously, the build tool we used to generate JavaScript files extracted
200
207
  common code to "chunk" files. While this was intended to make this package
201
208
  more tree-shakeable, it also made debugging more difficult for our
@@ -437,7 +444,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
437
444
 
438
445
  All changes listed after this point were applied to this package following the monorepo conversion.
439
446
 
440
- [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/base-controller@9.1.0...HEAD
447
+ [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/base-controller@10.0.0...HEAD
448
+ [10.0.0]: https://github.com/MetaMask/core/compare/@metamask/base-controller@9.1.0...@metamask/base-controller@10.0.0
441
449
  [9.1.0]: https://github.com/MetaMask/core/compare/@metamask/base-controller@9.0.1...@metamask/base-controller@9.1.0
442
450
  [9.0.1]: https://github.com/MetaMask/core/compare/@metamask/base-controller@9.0.0...@metamask/base-controller@9.0.1
443
451
  [9.0.0]: https://github.com/MetaMask/core/compare/@metamask/base-controller@8.4.2...@metamask/base-controller@9.0.0
@@ -1,6 +1,6 @@
1
- import type { ActionConstraint, EventConstraint, Messenger, MessengerActions, MessengerEvents } from "@metamask/messenger";
2
- import type { Json, PublicInterface } from "@metamask/utils";
3
- import type { Draft, Patch } from "immer";
1
+ import type { ActionConstraint, EventConstraint, Messenger, MessengerActions, MessengerEvents } from '@metamask/messenger';
2
+ import type { Json, PublicInterface } from '@metamask/utils';
3
+ import type { Draft, Patch } from 'immer';
4
4
  /**
5
5
  * A type that constrains the state of all controllers.
6
6
  *
@@ -211,4 +211,4 @@ export declare class BaseController<ControllerName extends string, ControllerSta
211
211
  * @returns The metadata-derived controller state.
212
212
  */
213
213
  export declare function deriveStateFromMetadata<ControllerState extends StateConstraint>(state: ControllerState, metadata: StateMetadata<ControllerState>, metadataProperty: keyof StatePropertyMetadata<Json>, captureException?: (error: Error) => void): Record<keyof ControllerState, Json>;
214
- //# sourceMappingURL=BaseController.d.mts.map
214
+ //# sourceMappingURL=BaseController.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseController.d.ts","sourceRoot":"","sources":["../src/BaseController.ts"],"names":[],"mappings":"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"}
@@ -1,21 +1,31 @@
1
- var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
2
- if (kind === "m") throw new TypeError("Private method is not writable");
3
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
5
- return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6
- };
7
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
- };
12
- var _BaseController_internalState, _BaseController_messenger;
13
- import { enablePatches, produceWithPatches, applyPatches, freeze } from "immer";
1
+ import { enablePatches, produceWithPatches, applyPatches, freeze } from 'immer';
14
2
  enablePatches();
15
3
  /**
16
4
  * Controller class that provides state management, subscriptions, and state metadata
17
5
  */
18
6
  export class BaseController {
7
+ /**
8
+ * The controller state.
9
+ */
10
+ #internalState;
11
+ /**
12
+ * The controller messenger. This is used to interact with other parts of the application.
13
+ */
14
+ messenger;
15
+ /**
16
+ * The controller messenger.
17
+ *
18
+ * This is the same as the `messenger` property, but has a type that only lets us use
19
+ * actions and events that are part of the `BaseController` class.
20
+ */
21
+ #messenger;
22
+ /**
23
+ * The name of the controller.
24
+ *
25
+ * This is used by the ComposableController to construct a composed application state.
26
+ */
27
+ name;
28
+ metadata;
19
29
  /**
20
30
  * Creates a BaseController instance.
21
31
  *
@@ -27,20 +37,9 @@ export class BaseController {
27
37
  * @param options.state - Initial controller state.
28
38
  */
29
39
  constructor({ messenger, metadata, name, state, }) {
30
- /**
31
- * The controller state.
32
- */
33
- _BaseController_internalState.set(this, void 0);
34
- /**
35
- * The controller messenger.
36
- *
37
- * This is the same as the `messenger` property, but has a type that only lets us use
38
- * actions and events that are part of the `BaseController` class.
39
- */
40
- _BaseController_messenger.set(this, void 0);
41
40
  // The parameter type validates that the expected actions/events are present
42
41
  // We don't have a way to validate the type property because the type is invariant
43
- __classPrivateFieldSet(this, _BaseController_messenger, messenger, "f");
42
+ this.#messenger = messenger;
44
43
  this.messenger = messenger;
45
44
  this.name = name;
46
45
  // Here we use `freeze` from Immer to enforce that the state is deeply
@@ -48,14 +47,14 @@ export class BaseController {
48
47
  // That is, unlike `Object.freeze`, this does not narrow the type
49
48
  // recursively to `Readonly`. The equivalent in Immer is `Immutable`, but
50
49
  // `Immutable` does not handle recursive types such as our `Json` type.
51
- __classPrivateFieldSet(this, _BaseController_internalState, freeze(state, true), "f");
50
+ this.#internalState = freeze(state, true);
52
51
  this.metadata = metadata;
53
- __classPrivateFieldGet(this, _BaseController_messenger, "f").registerActionHandler(`${name}:getState`, () => this.state);
54
- __classPrivateFieldGet(this, _BaseController_messenger, "f").registerInitialEventPayload({
52
+ this.#messenger.registerActionHandler(`${name}:getState`, () => this.state);
53
+ this.#messenger.registerInitialEventPayload({
55
54
  eventType: `${name}:stateChange`,
56
55
  getPayload: () => [this.state, []],
57
56
  });
58
- __classPrivateFieldGet(this, _BaseController_messenger, "f").registerInitialEventPayload({
57
+ this.#messenger.registerInitialEventPayload({
59
58
  eventType: `${name}:stateChanged`,
60
59
  getPayload: () => [this.state, []],
61
60
  });
@@ -66,7 +65,7 @@ export class BaseController {
66
65
  * @returns The current state.
67
66
  */
68
67
  get state() {
69
- return __classPrivateFieldGet(this, _BaseController_internalState, "f");
68
+ return this.#internalState;
70
69
  }
71
70
  set state(_) {
72
71
  throw new Error(`Controller state cannot be directly mutated; use 'update' method instead.`);
@@ -85,12 +84,12 @@ export class BaseController {
85
84
  update(callback) {
86
85
  // We run into ts2589, "infinite type depth", if we don't cast
87
86
  // produceWithPatches here.
88
- const [nextState, patches, inversePatches] = produceWithPatches(__classPrivateFieldGet(this, _BaseController_internalState, "f"), callback);
87
+ const [nextState, patches, inversePatches] = produceWithPatches(this.#internalState, callback);
89
88
  // Protect against unnecessary state updates when there is no state diff.
90
89
  if (patches.length > 0) {
91
- __classPrivateFieldSet(this, _BaseController_internalState, nextState, "f");
92
- __classPrivateFieldGet(this, _BaseController_messenger, "f").publish(`${this.name}:stateChange`, nextState, patches);
93
- __classPrivateFieldGet(this, _BaseController_messenger, "f").publish(`${this.name}:stateChanged`, nextState, patches);
90
+ this.#internalState = nextState;
91
+ this.#messenger.publish(`${this.name}:stateChange`, nextState, patches);
92
+ this.#messenger.publish(`${this.name}:stateChanged`, nextState, patches);
94
93
  }
95
94
  return { nextState, patches, inversePatches };
96
95
  }
@@ -102,10 +101,10 @@ export class BaseController {
102
101
  * or undo changes.
103
102
  */
104
103
  applyPatches(patches) {
105
- const nextState = applyPatches(__classPrivateFieldGet(this, _BaseController_internalState, "f"), patches);
106
- __classPrivateFieldSet(this, _BaseController_internalState, nextState, "f");
107
- __classPrivateFieldGet(this, _BaseController_messenger, "f").publish(`${this.name}:stateChange`, nextState, patches);
108
- __classPrivateFieldGet(this, _BaseController_messenger, "f").publish(`${this.name}:stateChanged`, nextState, patches);
104
+ const nextState = applyPatches(this.#internalState, patches);
105
+ this.#internalState = nextState;
106
+ this.#messenger.publish(`${this.name}:stateChange`, nextState, patches);
107
+ this.#messenger.publish(`${this.name}:stateChanged`, nextState, patches);
109
108
  }
110
109
  /**
111
110
  * Prepares the controller for garbage collection. This should be extended
@@ -121,7 +120,6 @@ export class BaseController {
121
120
  this.messenger.clearEventSubscriptions(`${this.name}:stateChanged`);
122
121
  }
123
122
  }
124
- _BaseController_internalState = new WeakMap(), _BaseController_messenger = new WeakMap();
125
123
  /**
126
124
  * Use the metadata to derive state according to the given metadata property.
127
125
  *
@@ -167,4 +165,4 @@ export function deriveStateFromMetadata(state, metadata, metadataProperty, captu
167
165
  }
168
166
  }, {});
169
167
  }
170
- //# sourceMappingURL=BaseController.mjs.map
168
+ //# sourceMappingURL=BaseController.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseController.js","sourceRoot":"","sources":["../src/BaseController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ActionConstraint,\n EventConstraint,\n Messenger,\n MessengerActions,\n MessengerEvents,\n} from '@metamask/messenger';\nimport type { Json, PublicInterface } from '@metamask/utils';\nimport { enablePatches, produceWithPatches, applyPatches, freeze } from 'immer';\nimport type { Draft, Patch } from 'immer';\n\nenablePatches();\n\n/**\n * A type that constrains the state of all controllers.\n *\n * In other words, the narrowest supertype encompassing all controller state.\n */\nexport type StateConstraint = Record<string, Json>;\n\n/**\n * A state change listener.\n *\n * This function will get called for each state change, and is given a copy of\n * the new state along with a set of patches describing the changes since the\n * last update.\n *\n * @param state - The new controller state.\n * @param patches - A list of patches describing any changes (see here for more\n * information: https://immerjs.github.io/immer/docs/patches)\n */\nexport type StateChangeListener<Type> = (state: Type, patches: Patch[]) => void;\n\n/**\n * An function to derive state.\n *\n * This function will accept one piece of the controller state (one property),\n * and will return some derivation of that state.\n *\n * @param value - A piece of controller state.\n * @returns Something derived from controller state.\n */\nexport type StateDeriver<Type extends Json> = (value: Type) => Json;\n\n/**\n * State metadata.\n *\n * This metadata describes which parts of state should be persisted, and how to\n * get an anonymized representation of the state.\n */\nexport type StateMetadata<Type extends StateConstraint> = {\n [Key in keyof Type]-?: StatePropertyMetadata<Type[Key]>;\n};\n\n/**\n * Metadata for a single state property\n */\nexport type StatePropertyMetadata<ControllerState extends Json> = {\n /**\n * Indicates whether this property should be included in debug snapshots attached to Sentry\n * errors.\n *\n * Set this to false if the state may contain personally identifiable information, or if it's\n * too large to include in a debug snapshot.\n */\n includeInDebugSnapshot: boolean | StateDeriver<ControllerState>;\n /**\n * Indicates whether this property should be included in state logs.\n *\n * Set this to false if the data should be kept hidden from support agents (e.g. if it contains\n * secret keys, or personally-identifiable information that is not useful for debugging).\n *\n * We do allow state logs to contain some personally identifiable information to assist with\n * diagnosing errors (e.g. transaction hashes, addresses), but we still attempt to limit the\n * data we expose to what is most useful for helping users.\n */\n includeInStateLogs: boolean | StateDeriver<ControllerState>;\n /**\n * Indicates whether this property should be persisted.\n *\n * If true, the property will be persisted and saved between sessions.\n * If false, the property will not be saved between sessions, and it will always be missing from the `state` constructor parameter.\n */\n persist: boolean | StateDeriver<ControllerState>;\n /**\n * Indicates whether this property is used by the UI.\n *\n * If true, the property will be accessible from the UI.\n * If false, it will be inaccessible from the UI.\n *\n * Making a property accessible to the UI has a performance overhead, so it's better to set this\n * to `false` if it's not used in the UI, especially for properties that can be large in size.\n *\n * Note that we disallow the use of a state derivation function here to preserve type information\n * for the UI (the state deriver type always returns `Json`).\n */\n usedInUi: boolean;\n};\n\n/**\n * A universal supertype of `StateDeriver` types.\n * This type can be assigned to any `StateDeriver` type.\n */\nexport type StateDeriverConstraint = (value: never) => Json;\n\n/**\n * A universal supertype of `StatePropertyMetadata` types.\n * This type can be assigned to any `StatePropertyMetadata` type.\n */\nexport type StatePropertyMetadataConstraint = {\n includeInDebugSnapshot: boolean | StateDeriverConstraint;\n includeInStateLogs: boolean | StateDeriverConstraint;\n persist: boolean | StateDeriverConstraint;\n usedInUi: boolean;\n};\n\n/**\n * A universal supertype of `StateMetadata` types.\n * This type can be assigned to any `StateMetadata` type.\n */\nexport type StateMetadataConstraint = Record<\n string,\n StatePropertyMetadataConstraint\n>;\n\n/**\n * The widest subtype of all controller instances that inherit from `BaseController` (formerly `BaseControllerV2`).\n * Any `BaseController` subclass instance can be assigned to this type.\n */\nexport type BaseControllerInstance = Omit<\n PublicInterface<\n BaseController<\n string,\n StateConstraint,\n // Use `any` to allow any parent to be set.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n Messenger<string, ActionConstraint, EventConstraint, any>\n >\n >,\n 'metadata'\n> & {\n metadata: StateMetadataConstraint;\n};\n\nexport type ControllerGetStateAction<\n ControllerName extends string,\n ControllerState extends StateConstraint,\n> = {\n type: `${ControllerName}:getState`;\n handler: () => ControllerState;\n};\n\n/**\n * @deprecated This event type is deprecated. Please use\n * `ControllerStateChangedEvent` instead.\n */\nexport type ControllerStateChangeEvent<\n ControllerName extends string,\n ControllerState extends StateConstraint,\n> = {\n type: `${ControllerName}:stateChange`;\n payload: [ControllerState, Patch[]];\n};\n\nexport type ControllerStateChangedEvent<\n ControllerName extends string,\n ControllerState extends StateConstraint,\n> = {\n type: `${ControllerName}:stateChanged`;\n payload: [ControllerState, Patch[]];\n};\n\nexport type ControllerActions<\n ControllerName extends string,\n ControllerState extends StateConstraint,\n> = ControllerGetStateAction<ControllerName, ControllerState>;\n\nexport type ControllerEvents<\n ControllerName extends string,\n ControllerState extends StateConstraint,\n> =\n | ControllerStateChangeEvent<ControllerName, ControllerState>\n | ControllerStateChangedEvent<ControllerName, ControllerState>;\n\n/**\n * Controller class that provides state management, subscriptions, and state metadata\n */\nexport class BaseController<\n ControllerName extends string,\n ControllerState extends StateConstraint,\n ControllerMessenger extends Messenger<\n ControllerName,\n ActionConstraint,\n EventConstraint,\n // Use `any` to allow any parent to be set. `any` is harmless in a type constraint anyway,\n // it's the one totally safe place to use it.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n any\n >,\n> {\n /**\n * The controller state.\n */\n #internalState: ControllerState;\n\n /**\n * The controller messenger. This is used to interact with other parts of the application.\n */\n protected messenger: ControllerMessenger;\n\n /**\n * The controller messenger.\n *\n * This is the same as the `messenger` property, but has a type that only lets us use\n * actions and events that are part of the `BaseController` class.\n */\n readonly #messenger: Messenger<\n ControllerName,\n ControllerActions<ControllerName, ControllerState>,\n ControllerEvents<ControllerName, ControllerState>\n >;\n\n /**\n * The name of the controller.\n *\n * This is used by the ComposableController to construct a composed application state.\n */\n public readonly name: ControllerName;\n\n public readonly metadata: StateMetadata<ControllerState>;\n\n /**\n * Creates a BaseController instance.\n *\n * @param options - Controller options.\n * @param options.messenger - The controller messenger.\n * @param options.metadata - ControllerState metadata, describing how to \"anonymize\" the state, and which\n * parts should be persisted.\n * @param options.name - The name of the controller, used as a namespace for events and actions.\n * @param options.state - Initial controller state.\n */\n constructor({\n messenger,\n metadata,\n name,\n state,\n }: {\n messenger: ControllerActions<\n ControllerName,\n ControllerState\n >['type'] extends MessengerActions<ControllerMessenger>['type']\n ? ControllerStateChangeEvent<\n ControllerName,\n ControllerState\n >['type'] extends MessengerEvents<ControllerMessenger>['type']\n ? ControllerMessenger\n : ControllerStateChangedEvent<\n ControllerName,\n ControllerState\n >['type'] extends MessengerEvents<ControllerMessenger>['type']\n ? ControllerMessenger\n : never\n : never;\n metadata: StateMetadata<ControllerState>;\n name: ControllerName;\n state: ControllerState;\n }) {\n // The parameter type validates that the expected actions/events are present\n // We don't have a way to validate the type property because the type is invariant\n this.#messenger = messenger as unknown as Messenger<\n ControllerName,\n ControllerActions<ControllerName, ControllerState>,\n ControllerEvents<ControllerName, ControllerState>\n >;\n this.messenger = messenger;\n this.name = name;\n // Here we use `freeze` from Immer to enforce that the state is deeply\n // immutable. Note that this is a runtime check, not a compile-time check.\n // That is, unlike `Object.freeze`, this does not narrow the type\n // recursively to `Readonly`. The equivalent in Immer is `Immutable`, but\n // `Immutable` does not handle recursive types such as our `Json` type.\n this.#internalState = freeze(state, true);\n this.metadata = metadata;\n\n this.#messenger.registerActionHandler(`${name}:getState`, () => this.state);\n\n this.#messenger.registerInitialEventPayload({\n eventType: `${name}:stateChange`,\n getPayload: () => [this.state, []],\n });\n this.#messenger.registerInitialEventPayload({\n eventType: `${name}:stateChanged`,\n getPayload: () => [this.state, []],\n });\n }\n\n /**\n * Retrieves current controller state.\n *\n * @returns The current state.\n */\n get state(): ControllerState {\n return this.#internalState;\n }\n\n set state(_) {\n throw new Error(\n `Controller state cannot be directly mutated; use 'update' method instead.`,\n );\n }\n\n /**\n * Updates controller state. Accepts a callback that is passed a draft copy\n * of the controller state. If a value is returned, it is set as the new\n * state. Otherwise, any changes made within that callback to the draft are\n * applied to the controller state.\n *\n * @param callback - Callback for updating state, passed a draft state\n * object. Return a new state object or mutate the draft to update state.\n * @returns An object that has the next state, patches applied in the update and inverse patches to\n * rollback the update.\n */\n protected update(\n callback: (state: Draft<ControllerState>) => void | ControllerState,\n ): {\n nextState: ControllerState;\n patches: Patch[];\n inversePatches: Patch[];\n } {\n // We run into ts2589, \"infinite type depth\", if we don't cast\n // produceWithPatches here.\n const [nextState, patches, inversePatches] = (\n produceWithPatches as unknown as (\n state: ControllerState,\n callbackFn: typeof callback,\n ) => [ControllerState, Patch[], Patch[]]\n )(this.#internalState, callback);\n\n // Protect against unnecessary state updates when there is no state diff.\n if (patches.length > 0) {\n this.#internalState = nextState;\n this.#messenger.publish(\n `${this.name}:stateChange` as const,\n nextState,\n patches,\n );\n this.#messenger.publish(\n `${this.name}:stateChanged` as const,\n nextState,\n patches,\n );\n }\n\n return { nextState, patches, inversePatches };\n }\n\n /**\n * Applies immer patches to the current state. The patches come from the\n * update function itself and can either be normal or inverse patches.\n *\n * @param patches - An array of immer patches that are to be applied to make\n * or undo changes.\n */\n protected applyPatches(patches: Patch[]): void {\n const nextState = applyPatches(this.#internalState, patches);\n this.#internalState = nextState;\n this.#messenger.publish(\n `${this.name}:stateChange` as const,\n nextState,\n patches,\n );\n this.#messenger.publish(\n `${this.name}:stateChanged` as const,\n nextState,\n patches,\n );\n }\n\n /**\n * Prepares the controller for garbage collection. This should be extended\n * by any subclasses to clean up any additional connections or events.\n *\n * The only cleanup performed here is to remove listeners. While technically\n * this is not required to ensure this instance is garbage collected, it at\n * least ensures this instance won't be responsible for preventing the\n * listeners from being garbage collected.\n */\n protected destroy(): void {\n this.messenger.clearEventSubscriptions(`${this.name}:stateChange`);\n this.messenger.clearEventSubscriptions(`${this.name}:stateChanged`);\n }\n}\n\n/**\n * Use the metadata to derive state according to the given metadata property.\n *\n * @param state - The full controller state.\n * @param metadata - The controller metadata.\n * @param metadataProperty - The metadata property to use to derive state.\n * @param captureException - Reports an error to an error monitoring service.\n * @returns The metadata-derived controller state.\n */\nexport function deriveStateFromMetadata<\n ControllerState extends StateConstraint,\n>(\n state: ControllerState,\n metadata: StateMetadata<ControllerState>,\n metadataProperty: keyof StatePropertyMetadata<Json>,\n captureException?: (error: Error) => void,\n): Record<keyof ControllerState, Json> {\n return (Object.keys(state) as (keyof ControllerState)[]).reduce<\n Record<keyof ControllerState, Json>\n >((derivedState, key) => {\n try {\n const stateMetadata = metadata[key];\n if (!stateMetadata) {\n throw new Error(`No metadata found for '${String(key)}'`);\n }\n const propertyMetadata = stateMetadata[metadataProperty];\n const stateProperty = state[key];\n if (typeof propertyMetadata === 'function') {\n derivedState[key] = propertyMetadata(stateProperty);\n } else if (propertyMetadata) {\n derivedState[key] = stateProperty;\n }\n return derivedState;\n } catch (error) {\n // Capture error without interrupting state-related operations\n // See [ADR core#0016](https://github.com/MetaMask/decisions/blob/main/decisions/core/0016-core-classes-error-reporting.md)\n if (captureException) {\n try {\n captureException(\n error instanceof Error ? error : new Error(String(error)),\n );\n } catch (captureExceptionError) {\n console.error(\n new Error(`Error thrown when calling 'captureException'`),\n captureExceptionError,\n );\n console.error(error);\n }\n } else {\n console.error(error);\n }\n return derivedState;\n }\n }, {} as never);\n}\n"]}
@@ -1,3 +1,3 @@
1
- export type { BaseControllerInstance, StateChangeListener, StateConstraint, StateDeriver, StateDeriverConstraint, StateMetadata, StateMetadataConstraint, StatePropertyMetadata, StatePropertyMetadataConstraint, ControllerGetStateAction, ControllerStateChangeEvent, ControllerStateChangedEvent, } from "./BaseController.cjs";
2
- export { BaseController, deriveStateFromMetadata } from "./BaseController.cjs";
3
- //# sourceMappingURL=index.d.cts.map
1
+ export type { BaseControllerInstance, StateChangeListener, StateConstraint, StateDeriver, StateDeriverConstraint, StateMetadata, StateMetadataConstraint, StatePropertyMetadata, StatePropertyMetadataConstraint, ControllerGetStateAction, ControllerStateChangeEvent, ControllerStateChangedEvent, } from './BaseController.js';
2
+ export { BaseController, deriveStateFromMetadata } from './BaseController.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,sBAAsB,EACtB,mBAAmB,EACnB,eAAe,EACf,YAAY,EACZ,sBAAsB,EACtB,aAAa,EACb,uBAAuB,EACvB,qBAAqB,EACrB,+BAA+B,EAC/B,wBAAwB,EACxB,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { BaseController, deriveStateFromMetadata } from './BaseController.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC","sourcesContent":["export type {\n BaseControllerInstance,\n StateChangeListener,\n StateConstraint,\n StateDeriver,\n StateDeriverConstraint,\n StateMetadata,\n StateMetadataConstraint,\n StatePropertyMetadata,\n StatePropertyMetadataConstraint,\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n ControllerStateChangedEvent,\n} from './BaseController.js';\nexport { BaseController, deriveStateFromMetadata } from './BaseController.js';\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask-previews/base-controller",
3
- "version": "9.1.0-preview-8bfa290fb",
3
+ "version": "10.0.0-preview-97d6b86c0",
4
4
  "description": "Provides scaffolding for controllers as well a communication system for all controllers",
5
5
  "keywords": [
6
6
  "Ethereum",
@@ -18,18 +18,11 @@
18
18
  "files": [
19
19
  "dist/"
20
20
  ],
21
- "main": "./dist/index.cjs",
22
- "types": "./dist/index.d.cts",
21
+ "type": "module",
23
22
  "exports": {
24
23
  ".": {
25
- "import": {
26
- "types": "./dist/index.d.mts",
27
- "default": "./dist/index.mjs"
28
- },
29
- "require": {
30
- "types": "./dist/index.d.cts",
31
- "default": "./dist/index.cjs"
32
- }
24
+ "types": "./dist/index.d.ts",
25
+ "default": "./dist/index.js"
33
26
  },
34
27
  "./package.json": "./package.json"
35
28
  },
@@ -38,9 +31,11 @@
38
31
  "registry": "https://registry.npmjs.org/"
39
32
  },
40
33
  "scripts": {
41
- "build": "ts-bridge --project tsconfig.build.json --verbose --clean --no-references",
42
- "build:all": "ts-bridge --project tsconfig.build.json --verbose --clean",
34
+ "build": "tsc --project tsconfig.build.json",
35
+ "build:all": "tsc --build tsconfig.build.json --verbose",
36
+ "build:clean": "yarn build:only-clean && yarn build",
43
37
  "build:docs": "typedoc",
38
+ "build:only-clean": "rimraf './dist' './tsconfig.build.tsbuildinfo'",
44
39
  "changelog:update": "../../scripts/update-changelog.sh @metamask/base-controller",
45
40
  "changelog:validate": "../../scripts/validate-changelog.sh @metamask/base-controller",
46
41
  "lint:tsconfigs": "tsx ../../scripts/lint-tsconfigs/lint-tsconfigs.mts",
@@ -52,23 +47,24 @@
52
47
  "test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch"
53
48
  },
54
49
  "dependencies": {
55
- "@metamask/messenger": "^2.0.0",
50
+ "@metamask/messenger": "^3.0.0",
56
51
  "@metamask/utils": "^11.12.0",
57
52
  "immer": "^9.0.6"
58
53
  },
59
54
  "devDependencies": {
60
55
  "@metamask/auto-changelog": "^6.1.0",
61
- "@ts-bridge/cli": "^0.6.4",
62
56
  "@types/jest": "^30.0.0",
57
+ "@typescript/native": "npm:typescript@^7.0.2",
63
58
  "deepmerge": "^4.2.2",
64
59
  "jest": "^30.4.2",
60
+ "rimraf": "^5.0.5",
65
61
  "ts-jest": "^29.4.11",
66
62
  "tsx": "^4.20.5",
67
63
  "typedoc": "^0.25.13",
68
64
  "typedoc-plugin-missing-exports": "^2.0.0",
69
- "typescript": "~5.3.3"
65
+ "typescript": "npm:@typescript/typescript6@^6.0.2"
70
66
  },
71
67
  "engines": {
72
- "node": "^18.18 || >=20"
68
+ "node": "^22.14.0 || ^24"
73
69
  }
74
70
  }
@@ -1,175 +0,0 @@
1
- "use strict";
2
- var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
3
- if (kind === "m") throw new TypeError("Private method is not writable");
4
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
5
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
6
- return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
7
- };
8
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
9
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
10
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
- };
13
- var _BaseController_internalState, _BaseController_messenger;
14
- Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.deriveStateFromMetadata = exports.BaseController = void 0;
16
- const immer_1 = require("immer");
17
- (0, immer_1.enablePatches)();
18
- /**
19
- * Controller class that provides state management, subscriptions, and state metadata
20
- */
21
- class BaseController {
22
- /**
23
- * Creates a BaseController instance.
24
- *
25
- * @param options - Controller options.
26
- * @param options.messenger - The controller messenger.
27
- * @param options.metadata - ControllerState metadata, describing how to "anonymize" the state, and which
28
- * parts should be persisted.
29
- * @param options.name - The name of the controller, used as a namespace for events and actions.
30
- * @param options.state - Initial controller state.
31
- */
32
- constructor({ messenger, metadata, name, state, }) {
33
- /**
34
- * The controller state.
35
- */
36
- _BaseController_internalState.set(this, void 0);
37
- /**
38
- * The controller messenger.
39
- *
40
- * This is the same as the `messenger` property, but has a type that only lets us use
41
- * actions and events that are part of the `BaseController` class.
42
- */
43
- _BaseController_messenger.set(this, void 0);
44
- // The parameter type validates that the expected actions/events are present
45
- // We don't have a way to validate the type property because the type is invariant
46
- __classPrivateFieldSet(this, _BaseController_messenger, messenger, "f");
47
- this.messenger = messenger;
48
- this.name = name;
49
- // Here we use `freeze` from Immer to enforce that the state is deeply
50
- // immutable. Note that this is a runtime check, not a compile-time check.
51
- // That is, unlike `Object.freeze`, this does not narrow the type
52
- // recursively to `Readonly`. The equivalent in Immer is `Immutable`, but
53
- // `Immutable` does not handle recursive types such as our `Json` type.
54
- __classPrivateFieldSet(this, _BaseController_internalState, (0, immer_1.freeze)(state, true), "f");
55
- this.metadata = metadata;
56
- __classPrivateFieldGet(this, _BaseController_messenger, "f").registerActionHandler(`${name}:getState`, () => this.state);
57
- __classPrivateFieldGet(this, _BaseController_messenger, "f").registerInitialEventPayload({
58
- eventType: `${name}:stateChange`,
59
- getPayload: () => [this.state, []],
60
- });
61
- __classPrivateFieldGet(this, _BaseController_messenger, "f").registerInitialEventPayload({
62
- eventType: `${name}:stateChanged`,
63
- getPayload: () => [this.state, []],
64
- });
65
- }
66
- /**
67
- * Retrieves current controller state.
68
- *
69
- * @returns The current state.
70
- */
71
- get state() {
72
- return __classPrivateFieldGet(this, _BaseController_internalState, "f");
73
- }
74
- set state(_) {
75
- throw new Error(`Controller state cannot be directly mutated; use 'update' method instead.`);
76
- }
77
- /**
78
- * Updates controller state. Accepts a callback that is passed a draft copy
79
- * of the controller state. If a value is returned, it is set as the new
80
- * state. Otherwise, any changes made within that callback to the draft are
81
- * applied to the controller state.
82
- *
83
- * @param callback - Callback for updating state, passed a draft state
84
- * object. Return a new state object or mutate the draft to update state.
85
- * @returns An object that has the next state, patches applied in the update and inverse patches to
86
- * rollback the update.
87
- */
88
- update(callback) {
89
- // We run into ts2589, "infinite type depth", if we don't cast
90
- // produceWithPatches here.
91
- const [nextState, patches, inversePatches] = immer_1.produceWithPatches(__classPrivateFieldGet(this, _BaseController_internalState, "f"), callback);
92
- // Protect against unnecessary state updates when there is no state diff.
93
- if (patches.length > 0) {
94
- __classPrivateFieldSet(this, _BaseController_internalState, nextState, "f");
95
- __classPrivateFieldGet(this, _BaseController_messenger, "f").publish(`${this.name}:stateChange`, nextState, patches);
96
- __classPrivateFieldGet(this, _BaseController_messenger, "f").publish(`${this.name}:stateChanged`, nextState, patches);
97
- }
98
- return { nextState, patches, inversePatches };
99
- }
100
- /**
101
- * Applies immer patches to the current state. The patches come from the
102
- * update function itself and can either be normal or inverse patches.
103
- *
104
- * @param patches - An array of immer patches that are to be applied to make
105
- * or undo changes.
106
- */
107
- applyPatches(patches) {
108
- const nextState = (0, immer_1.applyPatches)(__classPrivateFieldGet(this, _BaseController_internalState, "f"), patches);
109
- __classPrivateFieldSet(this, _BaseController_internalState, nextState, "f");
110
- __classPrivateFieldGet(this, _BaseController_messenger, "f").publish(`${this.name}:stateChange`, nextState, patches);
111
- __classPrivateFieldGet(this, _BaseController_messenger, "f").publish(`${this.name}:stateChanged`, nextState, patches);
112
- }
113
- /**
114
- * Prepares the controller for garbage collection. This should be extended
115
- * by any subclasses to clean up any additional connections or events.
116
- *
117
- * The only cleanup performed here is to remove listeners. While technically
118
- * this is not required to ensure this instance is garbage collected, it at
119
- * least ensures this instance won't be responsible for preventing the
120
- * listeners from being garbage collected.
121
- */
122
- destroy() {
123
- this.messenger.clearEventSubscriptions(`${this.name}:stateChange`);
124
- this.messenger.clearEventSubscriptions(`${this.name}:stateChanged`);
125
- }
126
- }
127
- exports.BaseController = BaseController;
128
- _BaseController_internalState = new WeakMap(), _BaseController_messenger = new WeakMap();
129
- /**
130
- * Use the metadata to derive state according to the given metadata property.
131
- *
132
- * @param state - The full controller state.
133
- * @param metadata - The controller metadata.
134
- * @param metadataProperty - The metadata property to use to derive state.
135
- * @param captureException - Reports an error to an error monitoring service.
136
- * @returns The metadata-derived controller state.
137
- */
138
- function deriveStateFromMetadata(state, metadata, metadataProperty, captureException) {
139
- return Object.keys(state).reduce((derivedState, key) => {
140
- try {
141
- const stateMetadata = metadata[key];
142
- if (!stateMetadata) {
143
- throw new Error(`No metadata found for '${String(key)}'`);
144
- }
145
- const propertyMetadata = stateMetadata[metadataProperty];
146
- const stateProperty = state[key];
147
- if (typeof propertyMetadata === 'function') {
148
- derivedState[key] = propertyMetadata(stateProperty);
149
- }
150
- else if (propertyMetadata) {
151
- derivedState[key] = stateProperty;
152
- }
153
- return derivedState;
154
- }
155
- catch (error) {
156
- // Capture error without interrupting state-related operations
157
- // See [ADR core#0016](https://github.com/MetaMask/decisions/blob/main/decisions/core/0016-core-classes-error-reporting.md)
158
- if (captureException) {
159
- try {
160
- captureException(error instanceof Error ? error : new Error(String(error)));
161
- }
162
- catch (captureExceptionError) {
163
- console.error(new Error(`Error thrown when calling 'captureException'`), captureExceptionError);
164
- console.error(error);
165
- }
166
- }
167
- else {
168
- console.error(error);
169
- }
170
- return derivedState;
171
- }
172
- }, {});
173
- }
174
- exports.deriveStateFromMetadata = deriveStateFromMetadata;
175
- //# sourceMappingURL=BaseController.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"BaseController.cjs","sourceRoot":"","sources":["../src/BaseController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ActionConstraint,\n EventConstraint,\n Messenger,\n MessengerActions,\n MessengerEvents,\n} from '@metamask/messenger';\nimport type { Json, PublicInterface } from '@metamask/utils';\nimport { enablePatches, produceWithPatches, applyPatches, freeze } from 'immer';\nimport type { Draft, Patch } from 'immer';\n\nenablePatches();\n\n/**\n * A type that constrains the state of all controllers.\n *\n * In other words, the narrowest supertype encompassing all controller state.\n */\nexport type StateConstraint = Record<string, Json>;\n\n/**\n * A state change listener.\n *\n * This function will get called for each state change, and is given a copy of\n * the new state along with a set of patches describing the changes since the\n * last update.\n *\n * @param state - The new controller state.\n * @param patches - A list of patches describing any changes (see here for more\n * information: https://immerjs.github.io/immer/docs/patches)\n */\nexport type StateChangeListener<Type> = (state: Type, patches: Patch[]) => void;\n\n/**\n * An function to derive state.\n *\n * This function will accept one piece of the controller state (one property),\n * and will return some derivation of that state.\n *\n * @param value - A piece of controller state.\n * @returns Something derived from controller state.\n */\nexport type StateDeriver<Type extends Json> = (value: Type) => Json;\n\n/**\n * State metadata.\n *\n * This metadata describes which parts of state should be persisted, and how to\n * get an anonymized representation of the state.\n */\nexport type StateMetadata<Type extends StateConstraint> = {\n [Key in keyof Type]-?: StatePropertyMetadata<Type[Key]>;\n};\n\n/**\n * Metadata for a single state property\n */\nexport type StatePropertyMetadata<ControllerState extends Json> = {\n /**\n * Indicates whether this property should be included in debug snapshots attached to Sentry\n * errors.\n *\n * Set this to false if the state may contain personally identifiable information, or if it's\n * too large to include in a debug snapshot.\n */\n includeInDebugSnapshot: boolean | StateDeriver<ControllerState>;\n /**\n * Indicates whether this property should be included in state logs.\n *\n * Set this to false if the data should be kept hidden from support agents (e.g. if it contains\n * secret keys, or personally-identifiable information that is not useful for debugging).\n *\n * We do allow state logs to contain some personally identifiable information to assist with\n * diagnosing errors (e.g. transaction hashes, addresses), but we still attempt to limit the\n * data we expose to what is most useful for helping users.\n */\n includeInStateLogs: boolean | StateDeriver<ControllerState>;\n /**\n * Indicates whether this property should be persisted.\n *\n * If true, the property will be persisted and saved between sessions.\n * If false, the property will not be saved between sessions, and it will always be missing from the `state` constructor parameter.\n */\n persist: boolean | StateDeriver<ControllerState>;\n /**\n * Indicates whether this property is used by the UI.\n *\n * If true, the property will be accessible from the UI.\n * If false, it will be inaccessible from the UI.\n *\n * Making a property accessible to the UI has a performance overhead, so it's better to set this\n * to `false` if it's not used in the UI, especially for properties that can be large in size.\n *\n * Note that we disallow the use of a state derivation function here to preserve type information\n * for the UI (the state deriver type always returns `Json`).\n */\n usedInUi: boolean;\n};\n\n/**\n * A universal supertype of `StateDeriver` types.\n * This type can be assigned to any `StateDeriver` type.\n */\nexport type StateDeriverConstraint = (value: never) => Json;\n\n/**\n * A universal supertype of `StatePropertyMetadata` types.\n * This type can be assigned to any `StatePropertyMetadata` type.\n */\nexport type StatePropertyMetadataConstraint = {\n includeInDebugSnapshot: boolean | StateDeriverConstraint;\n includeInStateLogs: boolean | StateDeriverConstraint;\n persist: boolean | StateDeriverConstraint;\n usedInUi: boolean;\n};\n\n/**\n * A universal supertype of `StateMetadata` types.\n * This type can be assigned to any `StateMetadata` type.\n */\nexport type StateMetadataConstraint = Record<\n string,\n StatePropertyMetadataConstraint\n>;\n\n/**\n * The widest subtype of all controller instances that inherit from `BaseController` (formerly `BaseControllerV2`).\n * Any `BaseController` subclass instance can be assigned to this type.\n */\nexport type BaseControllerInstance = Omit<\n PublicInterface<\n BaseController<\n string,\n StateConstraint,\n // Use `any` to allow any parent to be set.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n Messenger<string, ActionConstraint, EventConstraint, any>\n >\n >,\n 'metadata'\n> & {\n metadata: StateMetadataConstraint;\n};\n\nexport type ControllerGetStateAction<\n ControllerName extends string,\n ControllerState extends StateConstraint,\n> = {\n type: `${ControllerName}:getState`;\n handler: () => ControllerState;\n};\n\n/**\n * @deprecated This event type is deprecated. Please use\n * `ControllerStateChangedEvent` instead.\n */\nexport type ControllerStateChangeEvent<\n ControllerName extends string,\n ControllerState extends StateConstraint,\n> = {\n type: `${ControllerName}:stateChange`;\n payload: [ControllerState, Patch[]];\n};\n\nexport type ControllerStateChangedEvent<\n ControllerName extends string,\n ControllerState extends StateConstraint,\n> = {\n type: `${ControllerName}:stateChanged`;\n payload: [ControllerState, Patch[]];\n};\n\nexport type ControllerActions<\n ControllerName extends string,\n ControllerState extends StateConstraint,\n> = ControllerGetStateAction<ControllerName, ControllerState>;\n\nexport type ControllerEvents<\n ControllerName extends string,\n ControllerState extends StateConstraint,\n> =\n | ControllerStateChangeEvent<ControllerName, ControllerState>\n | ControllerStateChangedEvent<ControllerName, ControllerState>;\n\n/**\n * Controller class that provides state management, subscriptions, and state metadata\n */\nexport class BaseController<\n ControllerName extends string,\n ControllerState extends StateConstraint,\n ControllerMessenger extends Messenger<\n ControllerName,\n ActionConstraint,\n EventConstraint,\n // Use `any` to allow any parent to be set. `any` is harmless in a type constraint anyway,\n // it's the one totally safe place to use it.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n any\n >,\n> {\n /**\n * The controller state.\n */\n #internalState: ControllerState;\n\n /**\n * The controller messenger. This is used to interact with other parts of the application.\n */\n protected messenger: ControllerMessenger;\n\n /**\n * The controller messenger.\n *\n * This is the same as the `messenger` property, but has a type that only lets us use\n * actions and events that are part of the `BaseController` class.\n */\n readonly #messenger: Messenger<\n ControllerName,\n ControllerActions<ControllerName, ControllerState>,\n ControllerEvents<ControllerName, ControllerState>\n >;\n\n /**\n * The name of the controller.\n *\n * This is used by the ComposableController to construct a composed application state.\n */\n public readonly name: ControllerName;\n\n public readonly metadata: StateMetadata<ControllerState>;\n\n /**\n * Creates a BaseController instance.\n *\n * @param options - Controller options.\n * @param options.messenger - The controller messenger.\n * @param options.metadata - ControllerState metadata, describing how to \"anonymize\" the state, and which\n * parts should be persisted.\n * @param options.name - The name of the controller, used as a namespace for events and actions.\n * @param options.state - Initial controller state.\n */\n constructor({\n messenger,\n metadata,\n name,\n state,\n }: {\n messenger: ControllerActions<\n ControllerName,\n ControllerState\n >['type'] extends MessengerActions<ControllerMessenger>['type']\n ? ControllerStateChangeEvent<\n ControllerName,\n ControllerState\n >['type'] extends MessengerEvents<ControllerMessenger>['type']\n ? ControllerMessenger\n : ControllerStateChangedEvent<\n ControllerName,\n ControllerState\n >['type'] extends MessengerEvents<ControllerMessenger>['type']\n ? ControllerMessenger\n : never\n : never;\n metadata: StateMetadata<ControllerState>;\n name: ControllerName;\n state: ControllerState;\n }) {\n // The parameter type validates that the expected actions/events are present\n // We don't have a way to validate the type property because the type is invariant\n this.#messenger = messenger as unknown as Messenger<\n ControllerName,\n ControllerActions<ControllerName, ControllerState>,\n ControllerEvents<ControllerName, ControllerState>\n >;\n this.messenger = messenger;\n this.name = name;\n // Here we use `freeze` from Immer to enforce that the state is deeply\n // immutable. Note that this is a runtime check, not a compile-time check.\n // That is, unlike `Object.freeze`, this does not narrow the type\n // recursively to `Readonly`. The equivalent in Immer is `Immutable`, but\n // `Immutable` does not handle recursive types such as our `Json` type.\n this.#internalState = freeze(state, true);\n this.metadata = metadata;\n\n this.#messenger.registerActionHandler(`${name}:getState`, () => this.state);\n\n this.#messenger.registerInitialEventPayload({\n eventType: `${name}:stateChange`,\n getPayload: () => [this.state, []],\n });\n this.#messenger.registerInitialEventPayload({\n eventType: `${name}:stateChanged`,\n getPayload: () => [this.state, []],\n });\n }\n\n /**\n * Retrieves current controller state.\n *\n * @returns The current state.\n */\n get state(): ControllerState {\n return this.#internalState;\n }\n\n set state(_) {\n throw new Error(\n `Controller state cannot be directly mutated; use 'update' method instead.`,\n );\n }\n\n /**\n * Updates controller state. Accepts a callback that is passed a draft copy\n * of the controller state. If a value is returned, it is set as the new\n * state. Otherwise, any changes made within that callback to the draft are\n * applied to the controller state.\n *\n * @param callback - Callback for updating state, passed a draft state\n * object. Return a new state object or mutate the draft to update state.\n * @returns An object that has the next state, patches applied in the update and inverse patches to\n * rollback the update.\n */\n protected update(\n callback: (state: Draft<ControllerState>) => void | ControllerState,\n ): {\n nextState: ControllerState;\n patches: Patch[];\n inversePatches: Patch[];\n } {\n // We run into ts2589, \"infinite type depth\", if we don't cast\n // produceWithPatches here.\n const [nextState, patches, inversePatches] = (\n produceWithPatches as unknown as (\n state: ControllerState,\n callbackFn: typeof callback,\n ) => [ControllerState, Patch[], Patch[]]\n )(this.#internalState, callback);\n\n // Protect against unnecessary state updates when there is no state diff.\n if (patches.length > 0) {\n this.#internalState = nextState;\n this.#messenger.publish(\n `${this.name}:stateChange` as const,\n nextState,\n patches,\n );\n this.#messenger.publish(\n `${this.name}:stateChanged` as const,\n nextState,\n patches,\n );\n }\n\n return { nextState, patches, inversePatches };\n }\n\n /**\n * Applies immer patches to the current state. The patches come from the\n * update function itself and can either be normal or inverse patches.\n *\n * @param patches - An array of immer patches that are to be applied to make\n * or undo changes.\n */\n protected applyPatches(patches: Patch[]): void {\n const nextState = applyPatches(this.#internalState, patches);\n this.#internalState = nextState;\n this.#messenger.publish(\n `${this.name}:stateChange` as const,\n nextState,\n patches,\n );\n this.#messenger.publish(\n `${this.name}:stateChanged` as const,\n nextState,\n patches,\n );\n }\n\n /**\n * Prepares the controller for garbage collection. This should be extended\n * by any subclasses to clean up any additional connections or events.\n *\n * The only cleanup performed here is to remove listeners. While technically\n * this is not required to ensure this instance is garbage collected, it at\n * least ensures this instance won't be responsible for preventing the\n * listeners from being garbage collected.\n */\n protected destroy(): void {\n this.messenger.clearEventSubscriptions(`${this.name}:stateChange`);\n this.messenger.clearEventSubscriptions(`${this.name}:stateChanged`);\n }\n}\n\n/**\n * Use the metadata to derive state according to the given metadata property.\n *\n * @param state - The full controller state.\n * @param metadata - The controller metadata.\n * @param metadataProperty - The metadata property to use to derive state.\n * @param captureException - Reports an error to an error monitoring service.\n * @returns The metadata-derived controller state.\n */\nexport function deriveStateFromMetadata<\n ControllerState extends StateConstraint,\n>(\n state: ControllerState,\n metadata: StateMetadata<ControllerState>,\n metadataProperty: keyof StatePropertyMetadata<Json>,\n captureException?: (error: Error) => void,\n): Record<keyof ControllerState, Json> {\n return (Object.keys(state) as (keyof ControllerState)[]).reduce<\n Record<keyof ControllerState, Json>\n >((derivedState, key) => {\n try {\n const stateMetadata = metadata[key];\n if (!stateMetadata) {\n throw new Error(`No metadata found for '${String(key)}'`);\n }\n const propertyMetadata = stateMetadata[metadataProperty];\n const stateProperty = state[key];\n if (typeof propertyMetadata === 'function') {\n derivedState[key] = propertyMetadata(stateProperty);\n } else if (propertyMetadata) {\n derivedState[key] = stateProperty;\n }\n return derivedState;\n } catch (error) {\n // Capture error without interrupting state-related operations\n // See [ADR core#0016](https://github.com/MetaMask/decisions/blob/main/decisions/core/0016-core-classes-error-reporting.md)\n if (captureException) {\n try {\n captureException(\n error instanceof Error ? error : new Error(String(error)),\n );\n } catch (captureExceptionError) {\n console.error(\n new Error(`Error thrown when calling 'captureException'`),\n captureExceptionError,\n );\n console.error(error);\n }\n } else {\n console.error(error);\n }\n return derivedState;\n }\n }, {} as never);\n}\n"]}
@@ -1,214 +0,0 @@
1
- import type { ActionConstraint, EventConstraint, Messenger, MessengerActions, MessengerEvents } from "@metamask/messenger";
2
- import type { Json, PublicInterface } from "@metamask/utils";
3
- import type { Draft, Patch } from "immer";
4
- /**
5
- * A type that constrains the state of all controllers.
6
- *
7
- * In other words, the narrowest supertype encompassing all controller state.
8
- */
9
- export type StateConstraint = Record<string, Json>;
10
- /**
11
- * A state change listener.
12
- *
13
- * This function will get called for each state change, and is given a copy of
14
- * the new state along with a set of patches describing the changes since the
15
- * last update.
16
- *
17
- * @param state - The new controller state.
18
- * @param patches - A list of patches describing any changes (see here for more
19
- * information: https://immerjs.github.io/immer/docs/patches)
20
- */
21
- export type StateChangeListener<Type> = (state: Type, patches: Patch[]) => void;
22
- /**
23
- * An function to derive state.
24
- *
25
- * This function will accept one piece of the controller state (one property),
26
- * and will return some derivation of that state.
27
- *
28
- * @param value - A piece of controller state.
29
- * @returns Something derived from controller state.
30
- */
31
- export type StateDeriver<Type extends Json> = (value: Type) => Json;
32
- /**
33
- * State metadata.
34
- *
35
- * This metadata describes which parts of state should be persisted, and how to
36
- * get an anonymized representation of the state.
37
- */
38
- export type StateMetadata<Type extends StateConstraint> = {
39
- [Key in keyof Type]-?: StatePropertyMetadata<Type[Key]>;
40
- };
41
- /**
42
- * Metadata for a single state property
43
- */
44
- export type StatePropertyMetadata<ControllerState extends Json> = {
45
- /**
46
- * Indicates whether this property should be included in debug snapshots attached to Sentry
47
- * errors.
48
- *
49
- * Set this to false if the state may contain personally identifiable information, or if it's
50
- * too large to include in a debug snapshot.
51
- */
52
- includeInDebugSnapshot: boolean | StateDeriver<ControllerState>;
53
- /**
54
- * Indicates whether this property should be included in state logs.
55
- *
56
- * Set this to false if the data should be kept hidden from support agents (e.g. if it contains
57
- * secret keys, or personally-identifiable information that is not useful for debugging).
58
- *
59
- * We do allow state logs to contain some personally identifiable information to assist with
60
- * diagnosing errors (e.g. transaction hashes, addresses), but we still attempt to limit the
61
- * data we expose to what is most useful for helping users.
62
- */
63
- includeInStateLogs: boolean | StateDeriver<ControllerState>;
64
- /**
65
- * Indicates whether this property should be persisted.
66
- *
67
- * If true, the property will be persisted and saved between sessions.
68
- * If false, the property will not be saved between sessions, and it will always be missing from the `state` constructor parameter.
69
- */
70
- persist: boolean | StateDeriver<ControllerState>;
71
- /**
72
- * Indicates whether this property is used by the UI.
73
- *
74
- * If true, the property will be accessible from the UI.
75
- * If false, it will be inaccessible from the UI.
76
- *
77
- * Making a property accessible to the UI has a performance overhead, so it's better to set this
78
- * to `false` if it's not used in the UI, especially for properties that can be large in size.
79
- *
80
- * Note that we disallow the use of a state derivation function here to preserve type information
81
- * for the UI (the state deriver type always returns `Json`).
82
- */
83
- usedInUi: boolean;
84
- };
85
- /**
86
- * A universal supertype of `StateDeriver` types.
87
- * This type can be assigned to any `StateDeriver` type.
88
- */
89
- export type StateDeriverConstraint = (value: never) => Json;
90
- /**
91
- * A universal supertype of `StatePropertyMetadata` types.
92
- * This type can be assigned to any `StatePropertyMetadata` type.
93
- */
94
- export type StatePropertyMetadataConstraint = {
95
- includeInDebugSnapshot: boolean | StateDeriverConstraint;
96
- includeInStateLogs: boolean | StateDeriverConstraint;
97
- persist: boolean | StateDeriverConstraint;
98
- usedInUi: boolean;
99
- };
100
- /**
101
- * A universal supertype of `StateMetadata` types.
102
- * This type can be assigned to any `StateMetadata` type.
103
- */
104
- export type StateMetadataConstraint = Record<string, StatePropertyMetadataConstraint>;
105
- /**
106
- * The widest subtype of all controller instances that inherit from `BaseController` (formerly `BaseControllerV2`).
107
- * Any `BaseController` subclass instance can be assigned to this type.
108
- */
109
- export type BaseControllerInstance = Omit<PublicInterface<BaseController<string, StateConstraint, Messenger<string, ActionConstraint, EventConstraint, any>>>, 'metadata'> & {
110
- metadata: StateMetadataConstraint;
111
- };
112
- export type ControllerGetStateAction<ControllerName extends string, ControllerState extends StateConstraint> = {
113
- type: `${ControllerName}:getState`;
114
- handler: () => ControllerState;
115
- };
116
- /**
117
- * @deprecated This event type is deprecated. Please use
118
- * `ControllerStateChangedEvent` instead.
119
- */
120
- export type ControllerStateChangeEvent<ControllerName extends string, ControllerState extends StateConstraint> = {
121
- type: `${ControllerName}:stateChange`;
122
- payload: [ControllerState, Patch[]];
123
- };
124
- export type ControllerStateChangedEvent<ControllerName extends string, ControllerState extends StateConstraint> = {
125
- type: `${ControllerName}:stateChanged`;
126
- payload: [ControllerState, Patch[]];
127
- };
128
- export type ControllerActions<ControllerName extends string, ControllerState extends StateConstraint> = ControllerGetStateAction<ControllerName, ControllerState>;
129
- export type ControllerEvents<ControllerName extends string, ControllerState extends StateConstraint> = ControllerStateChangeEvent<ControllerName, ControllerState> | ControllerStateChangedEvent<ControllerName, ControllerState>;
130
- /**
131
- * Controller class that provides state management, subscriptions, and state metadata
132
- */
133
- export declare class BaseController<ControllerName extends string, ControllerState extends StateConstraint, ControllerMessenger extends Messenger<ControllerName, ActionConstraint, EventConstraint, any>> {
134
- #private;
135
- /**
136
- * The controller messenger. This is used to interact with other parts of the application.
137
- */
138
- protected messenger: ControllerMessenger;
139
- /**
140
- * The name of the controller.
141
- *
142
- * This is used by the ComposableController to construct a composed application state.
143
- */
144
- readonly name: ControllerName;
145
- readonly metadata: StateMetadata<ControllerState>;
146
- /**
147
- * Creates a BaseController instance.
148
- *
149
- * @param options - Controller options.
150
- * @param options.messenger - The controller messenger.
151
- * @param options.metadata - ControllerState metadata, describing how to "anonymize" the state, and which
152
- * parts should be persisted.
153
- * @param options.name - The name of the controller, used as a namespace for events and actions.
154
- * @param options.state - Initial controller state.
155
- */
156
- constructor({ messenger, metadata, name, state, }: {
157
- messenger: ControllerActions<ControllerName, ControllerState>['type'] extends MessengerActions<ControllerMessenger>['type'] ? ControllerStateChangeEvent<ControllerName, ControllerState>['type'] extends MessengerEvents<ControllerMessenger>['type'] ? ControllerMessenger : ControllerStateChangedEvent<ControllerName, ControllerState>['type'] extends MessengerEvents<ControllerMessenger>['type'] ? ControllerMessenger : never : never;
158
- metadata: StateMetadata<ControllerState>;
159
- name: ControllerName;
160
- state: ControllerState;
161
- });
162
- /**
163
- * Retrieves current controller state.
164
- *
165
- * @returns The current state.
166
- */
167
- get state(): ControllerState;
168
- set state(_: ControllerState);
169
- /**
170
- * Updates controller state. Accepts a callback that is passed a draft copy
171
- * of the controller state. If a value is returned, it is set as the new
172
- * state. Otherwise, any changes made within that callback to the draft are
173
- * applied to the controller state.
174
- *
175
- * @param callback - Callback for updating state, passed a draft state
176
- * object. Return a new state object or mutate the draft to update state.
177
- * @returns An object that has the next state, patches applied in the update and inverse patches to
178
- * rollback the update.
179
- */
180
- protected update(callback: (state: Draft<ControllerState>) => void | ControllerState): {
181
- nextState: ControllerState;
182
- patches: Patch[];
183
- inversePatches: Patch[];
184
- };
185
- /**
186
- * Applies immer patches to the current state. The patches come from the
187
- * update function itself and can either be normal or inverse patches.
188
- *
189
- * @param patches - An array of immer patches that are to be applied to make
190
- * or undo changes.
191
- */
192
- protected applyPatches(patches: Patch[]): void;
193
- /**
194
- * Prepares the controller for garbage collection. This should be extended
195
- * by any subclasses to clean up any additional connections or events.
196
- *
197
- * The only cleanup performed here is to remove listeners. While technically
198
- * this is not required to ensure this instance is garbage collected, it at
199
- * least ensures this instance won't be responsible for preventing the
200
- * listeners from being garbage collected.
201
- */
202
- protected destroy(): void;
203
- }
204
- /**
205
- * Use the metadata to derive state according to the given metadata property.
206
- *
207
- * @param state - The full controller state.
208
- * @param metadata - The controller metadata.
209
- * @param metadataProperty - The metadata property to use to derive state.
210
- * @param captureException - Reports an error to an error monitoring service.
211
- * @returns The metadata-derived controller state.
212
- */
213
- export declare function deriveStateFromMetadata<ControllerState extends StateConstraint>(state: ControllerState, metadata: StateMetadata<ControllerState>, metadataProperty: keyof StatePropertyMetadata<Json>, captureException?: (error: Error) => void): Record<keyof ControllerState, Json>;
214
- //# sourceMappingURL=BaseController.d.cts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"BaseController.d.cts","sourceRoot":"","sources":["../src/BaseController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,SAAS,EACT,gBAAgB,EAChB,eAAe,EAChB,4BAA4B;AAC7B,OAAO,KAAK,EAAE,IAAI,EAAE,eAAe,EAAE,wBAAwB;AAE7D,OAAO,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc;AAI1C;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AAEnD;;;;;;;;;;GAUG;AACH,MAAM,MAAM,mBAAmB,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC;AAEhF;;;;;;;;GAQG;AACH,MAAM,MAAM,YAAY,CAAC,IAAI,SAAS,IAAI,IAAI,CAAC,KAAK,EAAE,IAAI,KAAK,IAAI,CAAC;AAEpE;;;;;GAKG;AACH,MAAM,MAAM,aAAa,CAAC,IAAI,SAAS,eAAe,IAAI;KACvD,GAAG,IAAI,MAAM,IAAI,CAAC,CAAC,GAAG,qBAAqB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;CACxD,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,qBAAqB,CAAC,eAAe,SAAS,IAAI,IAAI;IAChE;;;;;;OAMG;IACH,sBAAsB,EAAE,OAAO,GAAG,YAAY,CAAC,eAAe,CAAC,CAAC;IAChE;;;;;;;;;OASG;IACH,kBAAkB,EAAE,OAAO,GAAG,YAAY,CAAC,eAAe,CAAC,CAAC;IAC5D;;;;;OAKG;IACH,OAAO,EAAE,OAAO,GAAG,YAAY,CAAC,eAAe,CAAC,CAAC;IACjD;;;;;;;;;;;OAWG;IACH,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;AAE5D;;;GAGG;AACH,MAAM,MAAM,+BAA+B,GAAG;IAC5C,sBAAsB,EAAE,OAAO,GAAG,sBAAsB,CAAC;IACzD,kBAAkB,EAAE,OAAO,GAAG,sBAAsB,CAAC;IACrD,OAAO,EAAE,OAAO,GAAG,sBAAsB,CAAC;IAC1C,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,uBAAuB,GAAG,MAAM,CAC1C,MAAM,EACN,+BAA+B,CAChC,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,sBAAsB,GAAG,IAAI,CACvC,eAAe,CACb,cAAc,CACZ,MAAM,EACN,eAAe,EAGf,SAAS,CAAC,MAAM,EAAE,gBAAgB,EAAE,eAAe,EAAE,GAAG,CAAC,CAC1D,CACF,EACD,UAAU,CACX,GAAG;IACF,QAAQ,EAAE,uBAAuB,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,wBAAwB,CAClC,cAAc,SAAS,MAAM,EAC7B,eAAe,SAAS,eAAe,IACrC;IACF,IAAI,EAAE,GAAG,cAAc,WAAW,CAAC;IACnC,OAAO,EAAE,MAAM,eAAe,CAAC;CAChC,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,0BAA0B,CACpC,cAAc,SAAS,MAAM,EAC7B,eAAe,SAAS,eAAe,IACrC;IACF,IAAI,EAAE,GAAG,cAAc,cAAc,CAAC;IACtC,OAAO,EAAE,CAAC,eAAe,EAAE,KAAK,EAAE,CAAC,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,2BAA2B,CACrC,cAAc,SAAS,MAAM,EAC7B,eAAe,SAAS,eAAe,IACrC;IACF,IAAI,EAAE,GAAG,cAAc,eAAe,CAAC;IACvC,OAAO,EAAE,CAAC,eAAe,EAAE,KAAK,EAAE,CAAC,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,iBAAiB,CAC3B,cAAc,SAAS,MAAM,EAC7B,eAAe,SAAS,eAAe,IACrC,wBAAwB,CAAC,cAAc,EAAE,eAAe,CAAC,CAAC;AAE9D,MAAM,MAAM,gBAAgB,CAC1B,cAAc,SAAS,MAAM,EAC7B,eAAe,SAAS,eAAe,IAErC,0BAA0B,CAAC,cAAc,EAAE,eAAe,CAAC,GAC3D,2BAA2B,CAAC,cAAc,EAAE,eAAe,CAAC,CAAC;AAEjE;;GAEG;AACH,qBAAa,cAAc,CACzB,cAAc,SAAS,MAAM,EAC7B,eAAe,SAAS,eAAe,EACvC,mBAAmB,SAAS,SAAS,CACnC,cAAc,EACd,gBAAgB,EAChB,eAAe,EAIf,GAAG,CACJ;;IAOD;;OAEG;IACH,SAAS,CAAC,SAAS,EAAE,mBAAmB,CAAC;IAczC;;;;OAIG;IACH,SAAgB,IAAI,EAAE,cAAc,CAAC;IAErC,SAAgB,QAAQ,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;IAEzD;;;;;;;;;OASG;gBACS,EACV,SAAS,EACT,QAAQ,EACR,IAAI,EACJ,KAAK,GACN,EAAE;QACD,SAAS,EAAE,iBAAiB,CAC1B,cAAc,EACd,eAAe,CAChB,CAAC,MAAM,CAAC,SAAS,gBAAgB,CAAC,mBAAmB,CAAC,CAAC,MAAM,CAAC,GAC3D,0BAA0B,CACxB,cAAc,EACd,eAAe,CAChB,CAAC,MAAM,CAAC,SAAS,eAAe,CAAC,mBAAmB,CAAC,CAAC,MAAM,CAAC,GAC5D,mBAAmB,GACnB,2BAA2B,CACvB,cAAc,EACd,eAAe,CAChB,CAAC,MAAM,CAAC,SAAS,eAAe,CAAC,mBAAmB,CAAC,CAAC,MAAM,CAAC,GAC9D,mBAAmB,GACnB,KAAK,GACT,KAAK,CAAC;QACV,QAAQ,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;QACzC,IAAI,EAAE,cAAc,CAAC;QACrB,KAAK,EAAE,eAAe,CAAC;KACxB;IA8BD;;;;OAIG;IACH,IAAI,KAAK,IAAI,eAAe,CAE3B;IAED,IAAI,KAAK,CAAC,CAAC,EAJE,eAIF,EAIV;IAED;;;;;;;;;;OAUG;IACH,SAAS,CAAC,MAAM,CACd,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,eAAe,CAAC,KAAK,IAAI,GAAG,eAAe,GAClE;QACD,SAAS,EAAE,eAAe,CAAC;QAC3B,OAAO,EAAE,KAAK,EAAE,CAAC;QACjB,cAAc,EAAE,KAAK,EAAE,CAAC;KACzB;IA4BD;;;;;;OAMG;IACH,SAAS,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,EAAE,GAAG,IAAI;IAe9C;;;;;;;;OAQG;IACH,SAAS,CAAC,OAAO,IAAI,IAAI;CAI1B;AAED;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CACrC,eAAe,SAAS,eAAe,EAEvC,KAAK,EAAE,eAAe,EACtB,QAAQ,EAAE,aAAa,CAAC,eAAe,CAAC,EACxC,gBAAgB,EAAE,MAAM,qBAAqB,CAAC,IAAI,CAAC,EACnD,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GACxC,MAAM,CAAC,MAAM,eAAe,EAAE,IAAI,CAAC,CAsCrC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"BaseController.d.mts","sourceRoot":"","sources":["../src/BaseController.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"BaseController.mjs","sourceRoot":"","sources":["../src/BaseController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ActionConstraint,\n EventConstraint,\n Messenger,\n MessengerActions,\n MessengerEvents,\n} from '@metamask/messenger';\nimport type { Json, PublicInterface } from '@metamask/utils';\nimport { enablePatches, produceWithPatches, applyPatches, freeze } from 'immer';\nimport type { Draft, Patch } from 'immer';\n\nenablePatches();\n\n/**\n * A type that constrains the state of all controllers.\n *\n * In other words, the narrowest supertype encompassing all controller state.\n */\nexport type StateConstraint = Record<string, Json>;\n\n/**\n * A state change listener.\n *\n * This function will get called for each state change, and is given a copy of\n * the new state along with a set of patches describing the changes since the\n * last update.\n *\n * @param state - The new controller state.\n * @param patches - A list of patches describing any changes (see here for more\n * information: https://immerjs.github.io/immer/docs/patches)\n */\nexport type StateChangeListener<Type> = (state: Type, patches: Patch[]) => void;\n\n/**\n * An function to derive state.\n *\n * This function will accept one piece of the controller state (one property),\n * and will return some derivation of that state.\n *\n * @param value - A piece of controller state.\n * @returns Something derived from controller state.\n */\nexport type StateDeriver<Type extends Json> = (value: Type) => Json;\n\n/**\n * State metadata.\n *\n * This metadata describes which parts of state should be persisted, and how to\n * get an anonymized representation of the state.\n */\nexport type StateMetadata<Type extends StateConstraint> = {\n [Key in keyof Type]-?: StatePropertyMetadata<Type[Key]>;\n};\n\n/**\n * Metadata for a single state property\n */\nexport type StatePropertyMetadata<ControllerState extends Json> = {\n /**\n * Indicates whether this property should be included in debug snapshots attached to Sentry\n * errors.\n *\n * Set this to false if the state may contain personally identifiable information, or if it's\n * too large to include in a debug snapshot.\n */\n includeInDebugSnapshot: boolean | StateDeriver<ControllerState>;\n /**\n * Indicates whether this property should be included in state logs.\n *\n * Set this to false if the data should be kept hidden from support agents (e.g. if it contains\n * secret keys, or personally-identifiable information that is not useful for debugging).\n *\n * We do allow state logs to contain some personally identifiable information to assist with\n * diagnosing errors (e.g. transaction hashes, addresses), but we still attempt to limit the\n * data we expose to what is most useful for helping users.\n */\n includeInStateLogs: boolean | StateDeriver<ControllerState>;\n /**\n * Indicates whether this property should be persisted.\n *\n * If true, the property will be persisted and saved between sessions.\n * If false, the property will not be saved between sessions, and it will always be missing from the `state` constructor parameter.\n */\n persist: boolean | StateDeriver<ControllerState>;\n /**\n * Indicates whether this property is used by the UI.\n *\n * If true, the property will be accessible from the UI.\n * If false, it will be inaccessible from the UI.\n *\n * Making a property accessible to the UI has a performance overhead, so it's better to set this\n * to `false` if it's not used in the UI, especially for properties that can be large in size.\n *\n * Note that we disallow the use of a state derivation function here to preserve type information\n * for the UI (the state deriver type always returns `Json`).\n */\n usedInUi: boolean;\n};\n\n/**\n * A universal supertype of `StateDeriver` types.\n * This type can be assigned to any `StateDeriver` type.\n */\nexport type StateDeriverConstraint = (value: never) => Json;\n\n/**\n * A universal supertype of `StatePropertyMetadata` types.\n * This type can be assigned to any `StatePropertyMetadata` type.\n */\nexport type StatePropertyMetadataConstraint = {\n includeInDebugSnapshot: boolean | StateDeriverConstraint;\n includeInStateLogs: boolean | StateDeriverConstraint;\n persist: boolean | StateDeriverConstraint;\n usedInUi: boolean;\n};\n\n/**\n * A universal supertype of `StateMetadata` types.\n * This type can be assigned to any `StateMetadata` type.\n */\nexport type StateMetadataConstraint = Record<\n string,\n StatePropertyMetadataConstraint\n>;\n\n/**\n * The widest subtype of all controller instances that inherit from `BaseController` (formerly `BaseControllerV2`).\n * Any `BaseController` subclass instance can be assigned to this type.\n */\nexport type BaseControllerInstance = Omit<\n PublicInterface<\n BaseController<\n string,\n StateConstraint,\n // Use `any` to allow any parent to be set.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n Messenger<string, ActionConstraint, EventConstraint, any>\n >\n >,\n 'metadata'\n> & {\n metadata: StateMetadataConstraint;\n};\n\nexport type ControllerGetStateAction<\n ControllerName extends string,\n ControllerState extends StateConstraint,\n> = {\n type: `${ControllerName}:getState`;\n handler: () => ControllerState;\n};\n\n/**\n * @deprecated This event type is deprecated. Please use\n * `ControllerStateChangedEvent` instead.\n */\nexport type ControllerStateChangeEvent<\n ControllerName extends string,\n ControllerState extends StateConstraint,\n> = {\n type: `${ControllerName}:stateChange`;\n payload: [ControllerState, Patch[]];\n};\n\nexport type ControllerStateChangedEvent<\n ControllerName extends string,\n ControllerState extends StateConstraint,\n> = {\n type: `${ControllerName}:stateChanged`;\n payload: [ControllerState, Patch[]];\n};\n\nexport type ControllerActions<\n ControllerName extends string,\n ControllerState extends StateConstraint,\n> = ControllerGetStateAction<ControllerName, ControllerState>;\n\nexport type ControllerEvents<\n ControllerName extends string,\n ControllerState extends StateConstraint,\n> =\n | ControllerStateChangeEvent<ControllerName, ControllerState>\n | ControllerStateChangedEvent<ControllerName, ControllerState>;\n\n/**\n * Controller class that provides state management, subscriptions, and state metadata\n */\nexport class BaseController<\n ControllerName extends string,\n ControllerState extends StateConstraint,\n ControllerMessenger extends Messenger<\n ControllerName,\n ActionConstraint,\n EventConstraint,\n // Use `any` to allow any parent to be set. `any` is harmless in a type constraint anyway,\n // it's the one totally safe place to use it.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n any\n >,\n> {\n /**\n * The controller state.\n */\n #internalState: ControllerState;\n\n /**\n * The controller messenger. This is used to interact with other parts of the application.\n */\n protected messenger: ControllerMessenger;\n\n /**\n * The controller messenger.\n *\n * This is the same as the `messenger` property, but has a type that only lets us use\n * actions and events that are part of the `BaseController` class.\n */\n readonly #messenger: Messenger<\n ControllerName,\n ControllerActions<ControllerName, ControllerState>,\n ControllerEvents<ControllerName, ControllerState>\n >;\n\n /**\n * The name of the controller.\n *\n * This is used by the ComposableController to construct a composed application state.\n */\n public readonly name: ControllerName;\n\n public readonly metadata: StateMetadata<ControllerState>;\n\n /**\n * Creates a BaseController instance.\n *\n * @param options - Controller options.\n * @param options.messenger - The controller messenger.\n * @param options.metadata - ControllerState metadata, describing how to \"anonymize\" the state, and which\n * parts should be persisted.\n * @param options.name - The name of the controller, used as a namespace for events and actions.\n * @param options.state - Initial controller state.\n */\n constructor({\n messenger,\n metadata,\n name,\n state,\n }: {\n messenger: ControllerActions<\n ControllerName,\n ControllerState\n >['type'] extends MessengerActions<ControllerMessenger>['type']\n ? ControllerStateChangeEvent<\n ControllerName,\n ControllerState\n >['type'] extends MessengerEvents<ControllerMessenger>['type']\n ? ControllerMessenger\n : ControllerStateChangedEvent<\n ControllerName,\n ControllerState\n >['type'] extends MessengerEvents<ControllerMessenger>['type']\n ? ControllerMessenger\n : never\n : never;\n metadata: StateMetadata<ControllerState>;\n name: ControllerName;\n state: ControllerState;\n }) {\n // The parameter type validates that the expected actions/events are present\n // We don't have a way to validate the type property because the type is invariant\n this.#messenger = messenger as unknown as Messenger<\n ControllerName,\n ControllerActions<ControllerName, ControllerState>,\n ControllerEvents<ControllerName, ControllerState>\n >;\n this.messenger = messenger;\n this.name = name;\n // Here we use `freeze` from Immer to enforce that the state is deeply\n // immutable. Note that this is a runtime check, not a compile-time check.\n // That is, unlike `Object.freeze`, this does not narrow the type\n // recursively to `Readonly`. The equivalent in Immer is `Immutable`, but\n // `Immutable` does not handle recursive types such as our `Json` type.\n this.#internalState = freeze(state, true);\n this.metadata = metadata;\n\n this.#messenger.registerActionHandler(`${name}:getState`, () => this.state);\n\n this.#messenger.registerInitialEventPayload({\n eventType: `${name}:stateChange`,\n getPayload: () => [this.state, []],\n });\n this.#messenger.registerInitialEventPayload({\n eventType: `${name}:stateChanged`,\n getPayload: () => [this.state, []],\n });\n }\n\n /**\n * Retrieves current controller state.\n *\n * @returns The current state.\n */\n get state(): ControllerState {\n return this.#internalState;\n }\n\n set state(_) {\n throw new Error(\n `Controller state cannot be directly mutated; use 'update' method instead.`,\n );\n }\n\n /**\n * Updates controller state. Accepts a callback that is passed a draft copy\n * of the controller state. If a value is returned, it is set as the new\n * state. Otherwise, any changes made within that callback to the draft are\n * applied to the controller state.\n *\n * @param callback - Callback for updating state, passed a draft state\n * object. Return a new state object or mutate the draft to update state.\n * @returns An object that has the next state, patches applied in the update and inverse patches to\n * rollback the update.\n */\n protected update(\n callback: (state: Draft<ControllerState>) => void | ControllerState,\n ): {\n nextState: ControllerState;\n patches: Patch[];\n inversePatches: Patch[];\n } {\n // We run into ts2589, \"infinite type depth\", if we don't cast\n // produceWithPatches here.\n const [nextState, patches, inversePatches] = (\n produceWithPatches as unknown as (\n state: ControllerState,\n callbackFn: typeof callback,\n ) => [ControllerState, Patch[], Patch[]]\n )(this.#internalState, callback);\n\n // Protect against unnecessary state updates when there is no state diff.\n if (patches.length > 0) {\n this.#internalState = nextState;\n this.#messenger.publish(\n `${this.name}:stateChange` as const,\n nextState,\n patches,\n );\n this.#messenger.publish(\n `${this.name}:stateChanged` as const,\n nextState,\n patches,\n );\n }\n\n return { nextState, patches, inversePatches };\n }\n\n /**\n * Applies immer patches to the current state. The patches come from the\n * update function itself and can either be normal or inverse patches.\n *\n * @param patches - An array of immer patches that are to be applied to make\n * or undo changes.\n */\n protected applyPatches(patches: Patch[]): void {\n const nextState = applyPatches(this.#internalState, patches);\n this.#internalState = nextState;\n this.#messenger.publish(\n `${this.name}:stateChange` as const,\n nextState,\n patches,\n );\n this.#messenger.publish(\n `${this.name}:stateChanged` as const,\n nextState,\n patches,\n );\n }\n\n /**\n * Prepares the controller for garbage collection. This should be extended\n * by any subclasses to clean up any additional connections or events.\n *\n * The only cleanup performed here is to remove listeners. While technically\n * this is not required to ensure this instance is garbage collected, it at\n * least ensures this instance won't be responsible for preventing the\n * listeners from being garbage collected.\n */\n protected destroy(): void {\n this.messenger.clearEventSubscriptions(`${this.name}:stateChange`);\n this.messenger.clearEventSubscriptions(`${this.name}:stateChanged`);\n }\n}\n\n/**\n * Use the metadata to derive state according to the given metadata property.\n *\n * @param state - The full controller state.\n * @param metadata - The controller metadata.\n * @param metadataProperty - The metadata property to use to derive state.\n * @param captureException - Reports an error to an error monitoring service.\n * @returns The metadata-derived controller state.\n */\nexport function deriveStateFromMetadata<\n ControllerState extends StateConstraint,\n>(\n state: ControllerState,\n metadata: StateMetadata<ControllerState>,\n metadataProperty: keyof StatePropertyMetadata<Json>,\n captureException?: (error: Error) => void,\n): Record<keyof ControllerState, Json> {\n return (Object.keys(state) as (keyof ControllerState)[]).reduce<\n Record<keyof ControllerState, Json>\n >((derivedState, key) => {\n try {\n const stateMetadata = metadata[key];\n if (!stateMetadata) {\n throw new Error(`No metadata found for '${String(key)}'`);\n }\n const propertyMetadata = stateMetadata[metadataProperty];\n const stateProperty = state[key];\n if (typeof propertyMetadata === 'function') {\n derivedState[key] = propertyMetadata(stateProperty);\n } else if (propertyMetadata) {\n derivedState[key] = stateProperty;\n }\n return derivedState;\n } catch (error) {\n // Capture error without interrupting state-related operations\n // See [ADR core#0016](https://github.com/MetaMask/decisions/blob/main/decisions/core/0016-core-classes-error-reporting.md)\n if (captureException) {\n try {\n captureException(\n error instanceof Error ? error : new Error(String(error)),\n );\n } catch (captureExceptionError) {\n console.error(\n new Error(`Error thrown when calling 'captureException'`),\n captureExceptionError,\n );\n console.error(error);\n }\n } else {\n console.error(error);\n }\n return derivedState;\n }\n }, {} as never);\n}\n"]}
package/dist/index.cjs DELETED
@@ -1,7 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.deriveStateFromMetadata = exports.BaseController = void 0;
4
- var BaseController_js_1 = require("./BaseController.cjs");
5
- Object.defineProperty(exports, "BaseController", { enumerable: true, get: function () { return BaseController_js_1.BaseController; } });
6
- Object.defineProperty(exports, "deriveStateFromMetadata", { enumerable: true, get: function () { return BaseController_js_1.deriveStateFromMetadata; } });
7
- //# sourceMappingURL=index.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.cjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAcA,0DAA8E;AAArE,mHAAA,cAAc,OAAA;AAAE,4HAAA,uBAAuB,OAAA","sourcesContent":["export type {\n BaseControllerInstance,\n StateChangeListener,\n StateConstraint,\n StateDeriver,\n StateDeriverConstraint,\n StateMetadata,\n StateMetadataConstraint,\n StatePropertyMetadata,\n StatePropertyMetadataConstraint,\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n ControllerStateChangedEvent,\n} from './BaseController.js';\nexport { BaseController, deriveStateFromMetadata } from './BaseController.js';\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,sBAAsB,EACtB,mBAAmB,EACnB,eAAe,EACf,YAAY,EACZ,sBAAsB,EACtB,aAAa,EACb,uBAAuB,EACvB,qBAAqB,EACrB,+BAA+B,EAC/B,wBAAwB,EACxB,0BAA0B,EAC1B,2BAA2B,GAC5B,6BAA4B;AAC7B,OAAO,EAAE,cAAc,EAAE,uBAAuB,EAAE,6BAA4B"}
package/dist/index.d.mts DELETED
@@ -1,3 +0,0 @@
1
- export type { BaseControllerInstance, StateChangeListener, StateConstraint, StateDeriver, StateDeriverConstraint, StateMetadata, StateMetadataConstraint, StatePropertyMetadata, StatePropertyMetadataConstraint, ControllerGetStateAction, ControllerStateChangeEvent, ControllerStateChangedEvent, } from "./BaseController.mjs";
2
- export { BaseController, deriveStateFromMetadata } from "./BaseController.mjs";
3
- //# sourceMappingURL=index.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,sBAAsB,EACtB,mBAAmB,EACnB,eAAe,EACf,YAAY,EACZ,sBAAsB,EACtB,aAAa,EACb,uBAAuB,EACvB,qBAAqB,EACrB,+BAA+B,EAC/B,wBAAwB,EACxB,0BAA0B,EAC1B,2BAA2B,GAC5B,6BAA4B;AAC7B,OAAO,EAAE,cAAc,EAAE,uBAAuB,EAAE,6BAA4B"}
package/dist/index.mjs DELETED
@@ -1,2 +0,0 @@
1
- export { BaseController, deriveStateFromMetadata } from "./BaseController.mjs";
2
- //# sourceMappingURL=index.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,cAAc,EAAE,uBAAuB,EAAE,6BAA4B","sourcesContent":["export type {\n BaseControllerInstance,\n StateChangeListener,\n StateConstraint,\n StateDeriver,\n StateDeriverConstraint,\n StateMetadata,\n StateMetadataConstraint,\n StatePropertyMetadata,\n StatePropertyMetadataConstraint,\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n ControllerStateChangedEvent,\n} from './BaseController.js';\nexport { BaseController, deriveStateFromMetadata } from './BaseController.js';\n"]}