@metamask-previews/base-controller 8.3.0-preview-9873b6ef → 8.4.0-preview-463efec
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 +12 -1
- package/dist/BaseController.cjs +22 -10
- package/dist/BaseController.cjs.map +1 -1
- package/dist/BaseController.d.cts +6 -3
- package/dist/BaseController.d.cts.map +1 -1
- package/dist/BaseController.d.mts +6 -3
- package/dist/BaseController.d.mts.map +1 -1
- package/dist/BaseController.mjs +22 -10
- package/dist/BaseController.mjs.map +1 -1
- package/dist/next/BaseController.cjs +16 -6
- package/dist/next/BaseController.cjs.map +1 -1
- package/dist/next/BaseController.d.cts +2 -1
- package/dist/next/BaseController.d.cts.map +1 -1
- package/dist/next/BaseController.d.mts +2 -1
- package/dist/next/BaseController.d.mts.map +1 -1
- package/dist/next/BaseController.mjs +16 -6
- package/dist/next/BaseController.mjs.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,12 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [8.4.0]
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Add optional `captureException` parameter to `deriveStateFromMetadata`, `getPersistentState`, and `getAnonymizedState` ([#6606](https://github.com/MetaMask/core/pull/6606))
|
|
15
|
+
- This function will be used to capture any errors encountered during state derivation.
|
|
16
|
+
|
|
10
17
|
### Changed
|
|
11
18
|
|
|
12
19
|
- Bump `@metamask/utils` from `^11.4.2` to `^11.8.0` ([#6588](https://github.com/MetaMask/core/pull/6588))
|
|
13
20
|
- In experimental `next` export, rename `anonymous` metadata property to `includeInDebugSnapshot` ([#6593](https://github.com/MetaMask/core/pull/6593))
|
|
14
21
|
- In experimental `next` export, make `includeInStateLogs` and `usedInUi` metadata properties required ([#6593](https://github.com/MetaMask/core/pull/6593))
|
|
15
22
|
- In experimental `next` export, remove deprecated exports `getPersistentState` and `getAnonymizedState` ([#6611](https://github.com/MetaMask/core/pull/6611))
|
|
23
|
+
- Stop re-throwing state derivation errors in a `setTimeout` ([#6606](https://github.com/MetaMask/core/pull/6606))
|
|
24
|
+
- Instead errors are captured with `captureException`, or logged to the console.
|
|
25
|
+
- Bump `@metamask/messenger` from `^0.2.0` to `^0.3.0` ([#6632](https://github.com/MetaMask/core/pull/6632))
|
|
16
26
|
|
|
17
27
|
## [8.3.0]
|
|
18
28
|
|
|
@@ -370,7 +380,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
370
380
|
|
|
371
381
|
All changes listed after this point were applied to this package following the monorepo conversion.
|
|
372
382
|
|
|
373
|
-
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/base-controller@8.
|
|
383
|
+
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/base-controller@8.4.0...HEAD
|
|
384
|
+
[8.4.0]: https://github.com/MetaMask/core/compare/@metamask/base-controller@8.3.0...@metamask/base-controller@8.4.0
|
|
374
385
|
[8.3.0]: https://github.com/MetaMask/core/compare/@metamask/base-controller@8.2.0...@metamask/base-controller@8.3.0
|
|
375
386
|
[8.2.0]: https://github.com/MetaMask/core/compare/@metamask/base-controller@8.1.0...@metamask/base-controller@8.2.0
|
|
376
387
|
[8.1.0]: https://github.com/MetaMask/core/compare/@metamask/base-controller@8.0.1...@metamask/base-controller@8.1.0
|
package/dist/BaseController.cjs
CHANGED
|
@@ -133,10 +133,11 @@ _BaseController_internalState = new WeakMap();
|
|
|
133
133
|
* @param state - The controller state.
|
|
134
134
|
* @param metadata - The controller state metadata, which describes how to derive the
|
|
135
135
|
* anonymized state.
|
|
136
|
+
* @param captureException - Reports an error to an error monitoring service.
|
|
136
137
|
* @returns The anonymized controller state.
|
|
137
138
|
*/
|
|
138
|
-
function getAnonymizedState(state, metadata) {
|
|
139
|
-
return deriveStateFromMetadata(state, metadata, 'anonymous');
|
|
139
|
+
function getAnonymizedState(state, metadata, captureException) {
|
|
140
|
+
return deriveStateFromMetadata(state, metadata, 'anonymous', captureException);
|
|
140
141
|
}
|
|
141
142
|
exports.getAnonymizedState = getAnonymizedState;
|
|
142
143
|
/**
|
|
@@ -145,10 +146,11 @@ exports.getAnonymizedState = getAnonymizedState;
|
|
|
145
146
|
* @deprecated Use `deriveStateFromMetadata` instead.
|
|
146
147
|
* @param state - The controller state.
|
|
147
148
|
* @param metadata - The controller state metadata, which describes which pieces of state should be persisted.
|
|
149
|
+
* @param captureException - Reports an error to an error monitoring service.
|
|
148
150
|
* @returns The subset of controller state that should be persisted.
|
|
149
151
|
*/
|
|
150
|
-
function getPersistentState(state, metadata) {
|
|
151
|
-
return deriveStateFromMetadata(state, metadata, 'persist');
|
|
152
|
+
function getPersistentState(state, metadata, captureException) {
|
|
153
|
+
return deriveStateFromMetadata(state, metadata, 'persist', captureException);
|
|
152
154
|
}
|
|
153
155
|
exports.getPersistentState = getPersistentState;
|
|
154
156
|
/**
|
|
@@ -157,9 +159,10 @@ exports.getPersistentState = getPersistentState;
|
|
|
157
159
|
* @param state - The full controller state.
|
|
158
160
|
* @param metadata - The controller metadata.
|
|
159
161
|
* @param metadataProperty - The metadata property to use to derive state.
|
|
162
|
+
* @param captureException - Reports an error to an error monitoring service.
|
|
160
163
|
* @returns The metadata-derived controller state.
|
|
161
164
|
*/
|
|
162
|
-
function deriveStateFromMetadata(state, metadata, metadataProperty) {
|
|
165
|
+
function deriveStateFromMetadata(state, metadata, metadataProperty, captureException) {
|
|
163
166
|
return Object.keys(state).reduce((derivedState, key) => {
|
|
164
167
|
try {
|
|
165
168
|
const stateMetadata = metadata[key];
|
|
@@ -177,11 +180,20 @@ function deriveStateFromMetadata(state, metadata, metadataProperty) {
|
|
|
177
180
|
return derivedState;
|
|
178
181
|
}
|
|
179
182
|
catch (error) {
|
|
180
|
-
//
|
|
181
|
-
//
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
183
|
+
// Capture error without interrupting state-related operations
|
|
184
|
+
// See [ADR core#0016](https://github.com/MetaMask/decisions/blob/main/decisions/core/0016-core-classes-error-reporting.md)
|
|
185
|
+
if (captureException) {
|
|
186
|
+
try {
|
|
187
|
+
captureException(error instanceof Error ? error : new Error(String(error)));
|
|
188
|
+
}
|
|
189
|
+
catch (captureExceptionError) {
|
|
190
|
+
console.error(new Error(`Error thrown when calling 'captureException'`), captureExceptionError);
|
|
191
|
+
console.error(error);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
console.error(error);
|
|
196
|
+
}
|
|
185
197
|
return derivedState;
|
|
186
198
|
}
|
|
187
199
|
}, {});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseController.cjs","sourceRoot":"","sources":["../src/BaseController.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Json, PublicInterface } from '@metamask/utils';\nimport { enablePatches, produceWithPatches, applyPatches, freeze } from 'immer';\nimport type { Draft, Patch } from 'immer';\n\nimport type { ActionConstraint, EventConstraint } from './Messenger';\nimport type {\n RestrictedMessenger,\n RestrictedMessengerConstraint,\n} from './RestrictedMessenger';\n\nenablePatches();\n\n/**\n * Determines if the given controller is an instance of `BaseController`\n *\n * @param controller - Controller instance to check\n * @returns True if the controller is an instance of `BaseController`\n */\nexport function isBaseController(\n controller: unknown,\n): controller is BaseControllerInstance {\n return (\n typeof controller === 'object' &&\n controller !== null &&\n 'name' in controller &&\n typeof controller.name === 'string' &&\n 'state' in controller &&\n typeof controller.state === 'object' &&\n 'metadata' in controller &&\n typeof controller.metadata === 'object'\n );\n}\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 */\n// TODO: Either fix this lint violation or explain why it's necessary to ignore.\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport type Listener<T> = (state: T, 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 */\n// TODO: Either fix this lint violation or explain why it's necessary to ignore.\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport type StateDeriver<T extends Json> = (value: T) => 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 */\n// TODO: Either fix this lint violation or explain why it's necessary to ignore.\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport type StateMetadata<T extends StateConstraint> = {\n [P in keyof T]-?: StatePropertyMetadata<T[P]>;\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 anonymous: 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 anonymous: 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<string, StateConstraint, RestrictedMessengerConstraint>\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\nexport type ControllerStateChangeEvent<\n ControllerName extends string,\n ControllerState extends StateConstraint,\n> = {\n type: `${ControllerName}:stateChange`;\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> = ControllerStateChangeEvent<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 // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n messenger extends RestrictedMessenger<\n ControllerName,\n ActionConstraint | ControllerActions<ControllerName, ControllerState>,\n EventConstraint | ControllerEvents<ControllerName, ControllerState>,\n string,\n string\n >,\n> {\n #internalState: ControllerState;\n\n protected messagingSystem: messenger;\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 - Controller messaging system.\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: messenger;\n metadata: StateMetadata<ControllerState>;\n name: ControllerName;\n state: ControllerState;\n }) {\n this.messagingSystem = 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.messagingSystem.registerActionHandler(\n `${name}:getState`,\n () => this.state,\n );\n\n this.messagingSystem.registerInitialEventPayload({\n eventType: `${name}:stateChange`,\n getPayload: () => [this.state, []],\n });\n }\n\n /**\n * Retrieves current controller state.\n *\n * @returns The current state.\n */\n get state() {\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 cb: 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.messagingSystem.publish(\n `${this.name}:stateChange`,\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[]) {\n const nextState = applyPatches(this.#internalState, patches);\n this.#internalState = nextState;\n this.messagingSystem.publish(\n `${this.name}:stateChange`,\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() {\n this.messagingSystem.clearEventSubscriptions(`${this.name}:stateChange`);\n }\n}\n\n/**\n * Returns an anonymized representation of the controller state.\n *\n * By \"anonymized\" we mean that it should not contain any information that could be personally\n * identifiable.\n *\n * @deprecated Use `deriveStateFromMetadata` instead.\n * @param state - The controller state.\n * @param metadata - The controller state metadata, which describes how to derive the\n * anonymized state.\n * @returns The anonymized controller state.\n */\nexport function getAnonymizedState<ControllerState extends StateConstraint>(\n state: ControllerState,\n metadata: StateMetadata<ControllerState>,\n): Record<keyof ControllerState, Json> {\n return deriveStateFromMetadata(state, metadata, 'anonymous');\n}\n\n/**\n * Returns the subset of state that should be persisted.\n *\n * @deprecated Use `deriveStateFromMetadata` instead.\n * @param state - The controller state.\n * @param metadata - The controller state metadata, which describes which pieces of state should be persisted.\n * @returns The subset of controller state that should be persisted.\n */\nexport function getPersistentState<ControllerState extends StateConstraint>(\n state: ControllerState,\n metadata: StateMetadata<ControllerState>,\n): Record<keyof ControllerState, Json> {\n return deriveStateFromMetadata(state, metadata, 'persist');\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 * @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): 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 // Throw error after timeout so that it is captured as a console error\n // (and by Sentry) without interrupting state-related operations\n setTimeout(() => {\n throw error;\n });\n return derivedState;\n }\n }, {} as never);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"BaseController.cjs","sourceRoot":"","sources":["../src/BaseController.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Json, PublicInterface } from '@metamask/utils';\nimport { enablePatches, produceWithPatches, applyPatches, freeze } from 'immer';\nimport type { Draft, Patch } from 'immer';\n\nimport type { ActionConstraint, EventConstraint } from './Messenger';\nimport type {\n RestrictedMessenger,\n RestrictedMessengerConstraint,\n} from './RestrictedMessenger';\n\nenablePatches();\n\n/**\n * Determines if the given controller is an instance of `BaseController`\n *\n * @param controller - Controller instance to check\n * @returns True if the controller is an instance of `BaseController`\n */\nexport function isBaseController(\n controller: unknown,\n): controller is BaseControllerInstance {\n return (\n typeof controller === 'object' &&\n controller !== null &&\n 'name' in controller &&\n typeof controller.name === 'string' &&\n 'state' in controller &&\n typeof controller.state === 'object' &&\n 'metadata' in controller &&\n typeof controller.metadata === 'object'\n );\n}\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 */\n// TODO: Either fix this lint violation or explain why it's necessary to ignore.\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport type Listener<T> = (state: T, 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 */\n// TODO: Either fix this lint violation or explain why it's necessary to ignore.\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport type StateDeriver<T extends Json> = (value: T) => 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 */\n// TODO: Either fix this lint violation or explain why it's necessary to ignore.\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport type StateMetadata<T extends StateConstraint> = {\n [P in keyof T]-?: StatePropertyMetadata<T[P]>;\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 anonymous: 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 anonymous: 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<string, StateConstraint, RestrictedMessengerConstraint>\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\nexport type ControllerStateChangeEvent<\n ControllerName extends string,\n ControllerState extends StateConstraint,\n> = {\n type: `${ControllerName}:stateChange`;\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> = ControllerStateChangeEvent<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 // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n messenger extends RestrictedMessenger<\n ControllerName,\n ActionConstraint | ControllerActions<ControllerName, ControllerState>,\n EventConstraint | ControllerEvents<ControllerName, ControllerState>,\n string,\n string\n >,\n> {\n #internalState: ControllerState;\n\n protected messagingSystem: messenger;\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 - Controller messaging system.\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: messenger;\n metadata: StateMetadata<ControllerState>;\n name: ControllerName;\n state: ControllerState;\n }) {\n this.messagingSystem = 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.messagingSystem.registerActionHandler(\n `${name}:getState`,\n () => this.state,\n );\n\n this.messagingSystem.registerInitialEventPayload({\n eventType: `${name}:stateChange`,\n getPayload: () => [this.state, []],\n });\n }\n\n /**\n * Retrieves current controller state.\n *\n * @returns The current state.\n */\n get state() {\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 cb: 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.messagingSystem.publish(\n `${this.name}:stateChange`,\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[]) {\n const nextState = applyPatches(this.#internalState, patches);\n this.#internalState = nextState;\n this.messagingSystem.publish(\n `${this.name}:stateChange`,\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() {\n this.messagingSystem.clearEventSubscriptions(`${this.name}:stateChange`);\n }\n}\n\n/**\n * Returns an anonymized representation of the controller state.\n *\n * By \"anonymized\" we mean that it should not contain any information that could be personally\n * identifiable.\n *\n * @deprecated Use `deriveStateFromMetadata` instead.\n * @param state - The controller state.\n * @param metadata - The controller state metadata, which describes how to derive the\n * anonymized state.\n * @param captureException - Reports an error to an error monitoring service.\n * @returns The anonymized controller state.\n */\nexport function getAnonymizedState<ControllerState extends StateConstraint>(\n state: ControllerState,\n metadata: StateMetadata<ControllerState>,\n captureException?: (error: Error) => void,\n): Record<keyof ControllerState, Json> {\n return deriveStateFromMetadata(\n state,\n metadata,\n 'anonymous',\n captureException,\n );\n}\n\n/**\n * Returns the subset of state that should be persisted.\n *\n * @deprecated Use `deriveStateFromMetadata` instead.\n * @param state - The controller state.\n * @param metadata - The controller state metadata, which describes which pieces of state should be persisted.\n * @param captureException - Reports an error to an error monitoring service.\n * @returns The subset of controller state that should be persisted.\n */\nexport function getPersistentState<ControllerState extends StateConstraint>(\n state: ControllerState,\n metadata: StateMetadata<ControllerState>,\n captureException?: (error: Error) => void,\n): Record<keyof ControllerState, Json> {\n return deriveStateFromMetadata(state, metadata, 'persist', captureException);\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"]}
|
|
@@ -208,25 +208,28 @@ export declare class BaseController<ControllerName extends string, ControllerSta
|
|
|
208
208
|
* @param state - The controller state.
|
|
209
209
|
* @param metadata - The controller state metadata, which describes how to derive the
|
|
210
210
|
* anonymized state.
|
|
211
|
+
* @param captureException - Reports an error to an error monitoring service.
|
|
211
212
|
* @returns The anonymized controller state.
|
|
212
213
|
*/
|
|
213
|
-
export declare function getAnonymizedState<ControllerState extends StateConstraint>(state: ControllerState, metadata: StateMetadata<ControllerState
|
|
214
|
+
export declare function getAnonymizedState<ControllerState extends StateConstraint>(state: ControllerState, metadata: StateMetadata<ControllerState>, captureException?: (error: Error) => void): Record<keyof ControllerState, Json>;
|
|
214
215
|
/**
|
|
215
216
|
* Returns the subset of state that should be persisted.
|
|
216
217
|
*
|
|
217
218
|
* @deprecated Use `deriveStateFromMetadata` instead.
|
|
218
219
|
* @param state - The controller state.
|
|
219
220
|
* @param metadata - The controller state metadata, which describes which pieces of state should be persisted.
|
|
221
|
+
* @param captureException - Reports an error to an error monitoring service.
|
|
220
222
|
* @returns The subset of controller state that should be persisted.
|
|
221
223
|
*/
|
|
222
|
-
export declare function getPersistentState<ControllerState extends StateConstraint>(state: ControllerState, metadata: StateMetadata<ControllerState
|
|
224
|
+
export declare function getPersistentState<ControllerState extends StateConstraint>(state: ControllerState, metadata: StateMetadata<ControllerState>, captureException?: (error: Error) => void): Record<keyof ControllerState, Json>;
|
|
223
225
|
/**
|
|
224
226
|
* Use the metadata to derive state according to the given metadata property.
|
|
225
227
|
*
|
|
226
228
|
* @param state - The full controller state.
|
|
227
229
|
* @param metadata - The controller metadata.
|
|
228
230
|
* @param metadataProperty - The metadata property to use to derive state.
|
|
231
|
+
* @param captureException - Reports an error to an error monitoring service.
|
|
229
232
|
* @returns The metadata-derived controller state.
|
|
230
233
|
*/
|
|
231
|
-
export declare function deriveStateFromMetadata<ControllerState extends StateConstraint>(state: ControllerState, metadata: StateMetadata<ControllerState>, metadataProperty: keyof StatePropertyMetadata<Json
|
|
234
|
+
export declare function deriveStateFromMetadata<ControllerState extends StateConstraint>(state: ControllerState, metadata: StateMetadata<ControllerState>, metadataProperty: keyof StatePropertyMetadata<Json>, captureException?: (error: Error) => void): Record<keyof ControllerState, Json>;
|
|
232
235
|
//# sourceMappingURL=BaseController.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseController.d.cts","sourceRoot":"","sources":["../src/BaseController.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"BaseController.d.cts","sourceRoot":"","sources":["../src/BaseController.ts"],"names":[],"mappings":"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"}
|
|
@@ -208,25 +208,28 @@ export declare class BaseController<ControllerName extends string, ControllerSta
|
|
|
208
208
|
* @param state - The controller state.
|
|
209
209
|
* @param metadata - The controller state metadata, which describes how to derive the
|
|
210
210
|
* anonymized state.
|
|
211
|
+
* @param captureException - Reports an error to an error monitoring service.
|
|
211
212
|
* @returns The anonymized controller state.
|
|
212
213
|
*/
|
|
213
|
-
export declare function getAnonymizedState<ControllerState extends StateConstraint>(state: ControllerState, metadata: StateMetadata<ControllerState
|
|
214
|
+
export declare function getAnonymizedState<ControllerState extends StateConstraint>(state: ControllerState, metadata: StateMetadata<ControllerState>, captureException?: (error: Error) => void): Record<keyof ControllerState, Json>;
|
|
214
215
|
/**
|
|
215
216
|
* Returns the subset of state that should be persisted.
|
|
216
217
|
*
|
|
217
218
|
* @deprecated Use `deriveStateFromMetadata` instead.
|
|
218
219
|
* @param state - The controller state.
|
|
219
220
|
* @param metadata - The controller state metadata, which describes which pieces of state should be persisted.
|
|
221
|
+
* @param captureException - Reports an error to an error monitoring service.
|
|
220
222
|
* @returns The subset of controller state that should be persisted.
|
|
221
223
|
*/
|
|
222
|
-
export declare function getPersistentState<ControllerState extends StateConstraint>(state: ControllerState, metadata: StateMetadata<ControllerState
|
|
224
|
+
export declare function getPersistentState<ControllerState extends StateConstraint>(state: ControllerState, metadata: StateMetadata<ControllerState>, captureException?: (error: Error) => void): Record<keyof ControllerState, Json>;
|
|
223
225
|
/**
|
|
224
226
|
* Use the metadata to derive state according to the given metadata property.
|
|
225
227
|
*
|
|
226
228
|
* @param state - The full controller state.
|
|
227
229
|
* @param metadata - The controller metadata.
|
|
228
230
|
* @param metadataProperty - The metadata property to use to derive state.
|
|
231
|
+
* @param captureException - Reports an error to an error monitoring service.
|
|
229
232
|
* @returns The metadata-derived controller state.
|
|
230
233
|
*/
|
|
231
|
-
export declare function deriveStateFromMetadata<ControllerState extends StateConstraint>(state: ControllerState, metadata: StateMetadata<ControllerState>, metadataProperty: keyof StatePropertyMetadata<Json
|
|
234
|
+
export declare function deriveStateFromMetadata<ControllerState extends StateConstraint>(state: ControllerState, metadata: StateMetadata<ControllerState>, metadataProperty: keyof StatePropertyMetadata<Json>, captureException?: (error: Error) => void): Record<keyof ControllerState, Json>;
|
|
232
235
|
//# sourceMappingURL=BaseController.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseController.d.mts","sourceRoot":"","sources":["../src/BaseController.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"BaseController.d.mts","sourceRoot":"","sources":["../src/BaseController.ts"],"names":[],"mappings":"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"}
|
package/dist/BaseController.mjs
CHANGED
|
@@ -128,10 +128,11 @@ _BaseController_internalState = new WeakMap();
|
|
|
128
128
|
* @param state - The controller state.
|
|
129
129
|
* @param metadata - The controller state metadata, which describes how to derive the
|
|
130
130
|
* anonymized state.
|
|
131
|
+
* @param captureException - Reports an error to an error monitoring service.
|
|
131
132
|
* @returns The anonymized controller state.
|
|
132
133
|
*/
|
|
133
|
-
export function getAnonymizedState(state, metadata) {
|
|
134
|
-
return deriveStateFromMetadata(state, metadata, 'anonymous');
|
|
134
|
+
export function getAnonymizedState(state, metadata, captureException) {
|
|
135
|
+
return deriveStateFromMetadata(state, metadata, 'anonymous', captureException);
|
|
135
136
|
}
|
|
136
137
|
/**
|
|
137
138
|
* Returns the subset of state that should be persisted.
|
|
@@ -139,10 +140,11 @@ export function getAnonymizedState(state, metadata) {
|
|
|
139
140
|
* @deprecated Use `deriveStateFromMetadata` instead.
|
|
140
141
|
* @param state - The controller state.
|
|
141
142
|
* @param metadata - The controller state metadata, which describes which pieces of state should be persisted.
|
|
143
|
+
* @param captureException - Reports an error to an error monitoring service.
|
|
142
144
|
* @returns The subset of controller state that should be persisted.
|
|
143
145
|
*/
|
|
144
|
-
export function getPersistentState(state, metadata) {
|
|
145
|
-
return deriveStateFromMetadata(state, metadata, 'persist');
|
|
146
|
+
export function getPersistentState(state, metadata, captureException) {
|
|
147
|
+
return deriveStateFromMetadata(state, metadata, 'persist', captureException);
|
|
146
148
|
}
|
|
147
149
|
/**
|
|
148
150
|
* Use the metadata to derive state according to the given metadata property.
|
|
@@ -150,9 +152,10 @@ export function getPersistentState(state, metadata) {
|
|
|
150
152
|
* @param state - The full controller state.
|
|
151
153
|
* @param metadata - The controller metadata.
|
|
152
154
|
* @param metadataProperty - The metadata property to use to derive state.
|
|
155
|
+
* @param captureException - Reports an error to an error monitoring service.
|
|
153
156
|
* @returns The metadata-derived controller state.
|
|
154
157
|
*/
|
|
155
|
-
export function deriveStateFromMetadata(state, metadata, metadataProperty) {
|
|
158
|
+
export function deriveStateFromMetadata(state, metadata, metadataProperty, captureException) {
|
|
156
159
|
return Object.keys(state).reduce((derivedState, key) => {
|
|
157
160
|
try {
|
|
158
161
|
const stateMetadata = metadata[key];
|
|
@@ -170,11 +173,20 @@ export function deriveStateFromMetadata(state, metadata, metadataProperty) {
|
|
|
170
173
|
return derivedState;
|
|
171
174
|
}
|
|
172
175
|
catch (error) {
|
|
173
|
-
//
|
|
174
|
-
//
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
176
|
+
// Capture error without interrupting state-related operations
|
|
177
|
+
// See [ADR core#0016](https://github.com/MetaMask/decisions/blob/main/decisions/core/0016-core-classes-error-reporting.md)
|
|
178
|
+
if (captureException) {
|
|
179
|
+
try {
|
|
180
|
+
captureException(error instanceof Error ? error : new Error(String(error)));
|
|
181
|
+
}
|
|
182
|
+
catch (captureExceptionError) {
|
|
183
|
+
console.error(new Error(`Error thrown when calling 'captureException'`), captureExceptionError);
|
|
184
|
+
console.error(error);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
console.error(error);
|
|
189
|
+
}
|
|
178
190
|
return derivedState;
|
|
179
191
|
}
|
|
180
192
|
}, {});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseController.mjs","sourceRoot":"","sources":["../src/BaseController.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Json, PublicInterface } from '@metamask/utils';\nimport { enablePatches, produceWithPatches, applyPatches, freeze } from 'immer';\nimport type { Draft, Patch } from 'immer';\n\nimport type { ActionConstraint, EventConstraint } from './Messenger';\nimport type {\n RestrictedMessenger,\n RestrictedMessengerConstraint,\n} from './RestrictedMessenger';\n\nenablePatches();\n\n/**\n * Determines if the given controller is an instance of `BaseController`\n *\n * @param controller - Controller instance to check\n * @returns True if the controller is an instance of `BaseController`\n */\nexport function isBaseController(\n controller: unknown,\n): controller is BaseControllerInstance {\n return (\n typeof controller === 'object' &&\n controller !== null &&\n 'name' in controller &&\n typeof controller.name === 'string' &&\n 'state' in controller &&\n typeof controller.state === 'object' &&\n 'metadata' in controller &&\n typeof controller.metadata === 'object'\n );\n}\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 */\n// TODO: Either fix this lint violation or explain why it's necessary to ignore.\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport type Listener<T> = (state: T, 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 */\n// TODO: Either fix this lint violation or explain why it's necessary to ignore.\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport type StateDeriver<T extends Json> = (value: T) => 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 */\n// TODO: Either fix this lint violation or explain why it's necessary to ignore.\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport type StateMetadata<T extends StateConstraint> = {\n [P in keyof T]-?: StatePropertyMetadata<T[P]>;\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 anonymous: 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 anonymous: 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<string, StateConstraint, RestrictedMessengerConstraint>\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\nexport type ControllerStateChangeEvent<\n ControllerName extends string,\n ControllerState extends StateConstraint,\n> = {\n type: `${ControllerName}:stateChange`;\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> = ControllerStateChangeEvent<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 // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n messenger extends RestrictedMessenger<\n ControllerName,\n ActionConstraint | ControllerActions<ControllerName, ControllerState>,\n EventConstraint | ControllerEvents<ControllerName, ControllerState>,\n string,\n string\n >,\n> {\n #internalState: ControllerState;\n\n protected messagingSystem: messenger;\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 - Controller messaging system.\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: messenger;\n metadata: StateMetadata<ControllerState>;\n name: ControllerName;\n state: ControllerState;\n }) {\n this.messagingSystem = 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.messagingSystem.registerActionHandler(\n `${name}:getState`,\n () => this.state,\n );\n\n this.messagingSystem.registerInitialEventPayload({\n eventType: `${name}:stateChange`,\n getPayload: () => [this.state, []],\n });\n }\n\n /**\n * Retrieves current controller state.\n *\n * @returns The current state.\n */\n get state() {\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 cb: 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.messagingSystem.publish(\n `${this.name}:stateChange`,\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[]) {\n const nextState = applyPatches(this.#internalState, patches);\n this.#internalState = nextState;\n this.messagingSystem.publish(\n `${this.name}:stateChange`,\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() {\n this.messagingSystem.clearEventSubscriptions(`${this.name}:stateChange`);\n }\n}\n\n/**\n * Returns an anonymized representation of the controller state.\n *\n * By \"anonymized\" we mean that it should not contain any information that could be personally\n * identifiable.\n *\n * @deprecated Use `deriveStateFromMetadata` instead.\n * @param state - The controller state.\n * @param metadata - The controller state metadata, which describes how to derive the\n * anonymized state.\n * @returns The anonymized controller state.\n */\nexport function getAnonymizedState<ControllerState extends StateConstraint>(\n state: ControllerState,\n metadata: StateMetadata<ControllerState>,\n): Record<keyof ControllerState, Json> {\n return deriveStateFromMetadata(state, metadata, 'anonymous');\n}\n\n/**\n * Returns the subset of state that should be persisted.\n *\n * @deprecated Use `deriveStateFromMetadata` instead.\n * @param state - The controller state.\n * @param metadata - The controller state metadata, which describes which pieces of state should be persisted.\n * @returns The subset of controller state that should be persisted.\n */\nexport function getPersistentState<ControllerState extends StateConstraint>(\n state: ControllerState,\n metadata: StateMetadata<ControllerState>,\n): Record<keyof ControllerState, Json> {\n return deriveStateFromMetadata(state, metadata, 'persist');\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 * @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): 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 // Throw error after timeout so that it is captured as a console error\n // (and by Sentry) without interrupting state-related operations\n setTimeout(() => {\n throw error;\n });\n return derivedState;\n }\n }, {} as never);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"BaseController.mjs","sourceRoot":"","sources":["../src/BaseController.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Json, PublicInterface } from '@metamask/utils';\nimport { enablePatches, produceWithPatches, applyPatches, freeze } from 'immer';\nimport type { Draft, Patch } from 'immer';\n\nimport type { ActionConstraint, EventConstraint } from './Messenger';\nimport type {\n RestrictedMessenger,\n RestrictedMessengerConstraint,\n} from './RestrictedMessenger';\n\nenablePatches();\n\n/**\n * Determines if the given controller is an instance of `BaseController`\n *\n * @param controller - Controller instance to check\n * @returns True if the controller is an instance of `BaseController`\n */\nexport function isBaseController(\n controller: unknown,\n): controller is BaseControllerInstance {\n return (\n typeof controller === 'object' &&\n controller !== null &&\n 'name' in controller &&\n typeof controller.name === 'string' &&\n 'state' in controller &&\n typeof controller.state === 'object' &&\n 'metadata' in controller &&\n typeof controller.metadata === 'object'\n );\n}\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 */\n// TODO: Either fix this lint violation or explain why it's necessary to ignore.\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport type Listener<T> = (state: T, 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 */\n// TODO: Either fix this lint violation or explain why it's necessary to ignore.\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport type StateDeriver<T extends Json> = (value: T) => 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 */\n// TODO: Either fix this lint violation or explain why it's necessary to ignore.\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport type StateMetadata<T extends StateConstraint> = {\n [P in keyof T]-?: StatePropertyMetadata<T[P]>;\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 anonymous: 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 anonymous: 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<string, StateConstraint, RestrictedMessengerConstraint>\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\nexport type ControllerStateChangeEvent<\n ControllerName extends string,\n ControllerState extends StateConstraint,\n> = {\n type: `${ControllerName}:stateChange`;\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> = ControllerStateChangeEvent<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 // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n messenger extends RestrictedMessenger<\n ControllerName,\n ActionConstraint | ControllerActions<ControllerName, ControllerState>,\n EventConstraint | ControllerEvents<ControllerName, ControllerState>,\n string,\n string\n >,\n> {\n #internalState: ControllerState;\n\n protected messagingSystem: messenger;\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 - Controller messaging system.\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: messenger;\n metadata: StateMetadata<ControllerState>;\n name: ControllerName;\n state: ControllerState;\n }) {\n this.messagingSystem = 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.messagingSystem.registerActionHandler(\n `${name}:getState`,\n () => this.state,\n );\n\n this.messagingSystem.registerInitialEventPayload({\n eventType: `${name}:stateChange`,\n getPayload: () => [this.state, []],\n });\n }\n\n /**\n * Retrieves current controller state.\n *\n * @returns The current state.\n */\n get state() {\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 cb: 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.messagingSystem.publish(\n `${this.name}:stateChange`,\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[]) {\n const nextState = applyPatches(this.#internalState, patches);\n this.#internalState = nextState;\n this.messagingSystem.publish(\n `${this.name}:stateChange`,\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() {\n this.messagingSystem.clearEventSubscriptions(`${this.name}:stateChange`);\n }\n}\n\n/**\n * Returns an anonymized representation of the controller state.\n *\n * By \"anonymized\" we mean that it should not contain any information that could be personally\n * identifiable.\n *\n * @deprecated Use `deriveStateFromMetadata` instead.\n * @param state - The controller state.\n * @param metadata - The controller state metadata, which describes how to derive the\n * anonymized state.\n * @param captureException - Reports an error to an error monitoring service.\n * @returns The anonymized controller state.\n */\nexport function getAnonymizedState<ControllerState extends StateConstraint>(\n state: ControllerState,\n metadata: StateMetadata<ControllerState>,\n captureException?: (error: Error) => void,\n): Record<keyof ControllerState, Json> {\n return deriveStateFromMetadata(\n state,\n metadata,\n 'anonymous',\n captureException,\n );\n}\n\n/**\n * Returns the subset of state that should be persisted.\n *\n * @deprecated Use `deriveStateFromMetadata` instead.\n * @param state - The controller state.\n * @param metadata - The controller state metadata, which describes which pieces of state should be persisted.\n * @param captureException - Reports an error to an error monitoring service.\n * @returns The subset of controller state that should be persisted.\n */\nexport function getPersistentState<ControllerState extends StateConstraint>(\n state: ControllerState,\n metadata: StateMetadata<ControllerState>,\n captureException?: (error: Error) => void,\n): Record<keyof ControllerState, Json> {\n return deriveStateFromMetadata(state, metadata, 'persist', captureException);\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"]}
|
|
@@ -125,9 +125,10 @@ _BaseController_internalState = new WeakMap(), _BaseController_messenger = new W
|
|
|
125
125
|
* @param state - The full controller state.
|
|
126
126
|
* @param metadata - The controller metadata.
|
|
127
127
|
* @param metadataProperty - The metadata property to use to derive state.
|
|
128
|
+
* @param captureException - Reports an error to an error monitoring service.
|
|
128
129
|
* @returns The metadata-derived controller state.
|
|
129
130
|
*/
|
|
130
|
-
function deriveStateFromMetadata(state, metadata, metadataProperty) {
|
|
131
|
+
function deriveStateFromMetadata(state, metadata, metadataProperty, captureException) {
|
|
131
132
|
return Object.keys(state).reduce((derivedState, key) => {
|
|
132
133
|
try {
|
|
133
134
|
const stateMetadata = metadata[key];
|
|
@@ -145,11 +146,20 @@ function deriveStateFromMetadata(state, metadata, metadataProperty) {
|
|
|
145
146
|
return derivedState;
|
|
146
147
|
}
|
|
147
148
|
catch (error) {
|
|
148
|
-
//
|
|
149
|
-
//
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
149
|
+
// Capture error without interrupting state-related operations
|
|
150
|
+
// See [ADR core#0016](https://github.com/MetaMask/decisions/blob/main/decisions/core/0016-core-classes-error-reporting.md)
|
|
151
|
+
if (captureException) {
|
|
152
|
+
try {
|
|
153
|
+
captureException(error instanceof Error ? error : new Error(String(error)));
|
|
154
|
+
}
|
|
155
|
+
catch (captureExceptionError) {
|
|
156
|
+
console.error(new Error(`Error thrown when calling 'captureException'`), captureExceptionError);
|
|
157
|
+
console.error(error);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
console.error(error);
|
|
162
|
+
}
|
|
153
163
|
return derivedState;
|
|
154
164
|
}
|
|
155
165
|
}, {});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseController.cjs","sourceRoot":"","sources":["../../src/next/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<T> = (state: T, 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 */\n// TODO: Either fix this lint violation or explain why it's necessary to ignore.\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport type StateDeriver<T extends Json> = (value: T) => 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 */\n// TODO: Either fix this lint violation or explain why it's necessary to ignore.\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport type StateMetadata<T extends StateConstraint> = {\n [P in keyof T]-?: StatePropertyMetadata<T[P]>;\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 anonymous: 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\nexport type ControllerStateChangeEvent<\n ControllerName extends string,\n ControllerState extends StateConstraint,\n> = {\n type: `${ControllerName}:stateChange`;\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> = ControllerStateChangeEvent<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 `messagingSystem` 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 ? ControllerEvents<\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 }\n\n /**\n * Retrieves current controller state.\n *\n * @returns The current state.\n */\n get state() {\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 cb: 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 }\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[]) {\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 }\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() {\n this.messenger.clearEventSubscriptions(`${this.name}:stateChange`);\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 * @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): 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 // Throw error after timeout so that it is captured as a console error\n // (and by Sentry) without interrupting state-related operations\n setTimeout(() => {\n throw error;\n });\n return derivedState;\n }\n }, {} as never);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"BaseController.cjs","sourceRoot":"","sources":["../../src/next/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<T> = (state: T, 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 */\n// TODO: Either fix this lint violation or explain why it's necessary to ignore.\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport type StateDeriver<T extends Json> = (value: T) => 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 */\n// TODO: Either fix this lint violation or explain why it's necessary to ignore.\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport type StateMetadata<T extends StateConstraint> = {\n [P in keyof T]-?: StatePropertyMetadata<T[P]>;\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 anonymous: 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\nexport type ControllerStateChangeEvent<\n ControllerName extends string,\n ControllerState extends StateConstraint,\n> = {\n type: `${ControllerName}:stateChange`;\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> = ControllerStateChangeEvent<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 `messagingSystem` 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 ? ControllerEvents<\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 }\n\n /**\n * Retrieves current controller state.\n *\n * @returns The current state.\n */\n get state() {\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 cb: 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 }\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[]) {\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 }\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() {\n this.messenger.clearEventSubscriptions(`${this.name}:stateChange`);\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"]}
|
|
@@ -199,7 +199,8 @@ export declare class BaseController<ControllerName extends string, ControllerSta
|
|
|
199
199
|
* @param state - The full controller state.
|
|
200
200
|
* @param metadata - The controller metadata.
|
|
201
201
|
* @param metadataProperty - The metadata property to use to derive state.
|
|
202
|
+
* @param captureException - Reports an error to an error monitoring service.
|
|
202
203
|
* @returns The metadata-derived controller state.
|
|
203
204
|
*/
|
|
204
|
-
export declare function deriveStateFromMetadata<ControllerState extends StateConstraint>(state: ControllerState, metadata: StateMetadata<ControllerState>, metadataProperty: keyof StatePropertyMetadata<Json
|
|
205
|
+
export declare function deriveStateFromMetadata<ControllerState extends StateConstraint>(state: ControllerState, metadata: StateMetadata<ControllerState>, metadataProperty: keyof StatePropertyMetadata<Json>, captureException?: (error: Error) => void): Record<keyof ControllerState, Json>;
|
|
205
206
|
//# sourceMappingURL=BaseController.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseController.d.cts","sourceRoot":"","sources":["../../src/next/BaseController.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"BaseController.d.cts","sourceRoot":"","sources":["../../src/next/BaseController.ts"],"names":[],"mappings":"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"}
|
|
@@ -199,7 +199,8 @@ export declare class BaseController<ControllerName extends string, ControllerSta
|
|
|
199
199
|
* @param state - The full controller state.
|
|
200
200
|
* @param metadata - The controller metadata.
|
|
201
201
|
* @param metadataProperty - The metadata property to use to derive state.
|
|
202
|
+
* @param captureException - Reports an error to an error monitoring service.
|
|
202
203
|
* @returns The metadata-derived controller state.
|
|
203
204
|
*/
|
|
204
|
-
export declare function deriveStateFromMetadata<ControllerState extends StateConstraint>(state: ControllerState, metadata: StateMetadata<ControllerState>, metadataProperty: keyof StatePropertyMetadata<Json
|
|
205
|
+
export declare function deriveStateFromMetadata<ControllerState extends StateConstraint>(state: ControllerState, metadata: StateMetadata<ControllerState>, metadataProperty: keyof StatePropertyMetadata<Json>, captureException?: (error: Error) => void): Record<keyof ControllerState, Json>;
|
|
205
206
|
//# sourceMappingURL=BaseController.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseController.d.mts","sourceRoot":"","sources":["../../src/next/BaseController.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"BaseController.d.mts","sourceRoot":"","sources":["../../src/next/BaseController.ts"],"names":[],"mappings":"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"}
|
|
@@ -121,9 +121,10 @@ _BaseController_internalState = new WeakMap(), _BaseController_messenger = new W
|
|
|
121
121
|
* @param state - The full controller state.
|
|
122
122
|
* @param metadata - The controller metadata.
|
|
123
123
|
* @param metadataProperty - The metadata property to use to derive state.
|
|
124
|
+
* @param captureException - Reports an error to an error monitoring service.
|
|
124
125
|
* @returns The metadata-derived controller state.
|
|
125
126
|
*/
|
|
126
|
-
export function deriveStateFromMetadata(state, metadata, metadataProperty) {
|
|
127
|
+
export function deriveStateFromMetadata(state, metadata, metadataProperty, captureException) {
|
|
127
128
|
return Object.keys(state).reduce((derivedState, key) => {
|
|
128
129
|
try {
|
|
129
130
|
const stateMetadata = metadata[key];
|
|
@@ -141,11 +142,20 @@ export function deriveStateFromMetadata(state, metadata, metadataProperty) {
|
|
|
141
142
|
return derivedState;
|
|
142
143
|
}
|
|
143
144
|
catch (error) {
|
|
144
|
-
//
|
|
145
|
-
//
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
145
|
+
// Capture error without interrupting state-related operations
|
|
146
|
+
// See [ADR core#0016](https://github.com/MetaMask/decisions/blob/main/decisions/core/0016-core-classes-error-reporting.md)
|
|
147
|
+
if (captureException) {
|
|
148
|
+
try {
|
|
149
|
+
captureException(error instanceof Error ? error : new Error(String(error)));
|
|
150
|
+
}
|
|
151
|
+
catch (captureExceptionError) {
|
|
152
|
+
console.error(new Error(`Error thrown when calling 'captureException'`), captureExceptionError);
|
|
153
|
+
console.error(error);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
console.error(error);
|
|
158
|
+
}
|
|
149
159
|
return derivedState;
|
|
150
160
|
}
|
|
151
161
|
}, {});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseController.mjs","sourceRoot":"","sources":["../../src/next/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<T> = (state: T, 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 */\n// TODO: Either fix this lint violation or explain why it's necessary to ignore.\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport type StateDeriver<T extends Json> = (value: T) => 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 */\n// TODO: Either fix this lint violation or explain why it's necessary to ignore.\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport type StateMetadata<T extends StateConstraint> = {\n [P in keyof T]-?: StatePropertyMetadata<T[P]>;\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 anonymous: 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\nexport type ControllerStateChangeEvent<\n ControllerName extends string,\n ControllerState extends StateConstraint,\n> = {\n type: `${ControllerName}:stateChange`;\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> = ControllerStateChangeEvent<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 `messagingSystem` 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 ? ControllerEvents<\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 }\n\n /**\n * Retrieves current controller state.\n *\n * @returns The current state.\n */\n get state() {\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 cb: 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 }\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[]) {\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 }\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() {\n this.messenger.clearEventSubscriptions(`${this.name}:stateChange`);\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 * @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): 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 // Throw error after timeout so that it is captured as a console error\n // (and by Sentry) without interrupting state-related operations\n setTimeout(() => {\n throw error;\n });\n return derivedState;\n }\n }, {} as never);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"BaseController.mjs","sourceRoot":"","sources":["../../src/next/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<T> = (state: T, 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 */\n// TODO: Either fix this lint violation or explain why it's necessary to ignore.\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport type StateDeriver<T extends Json> = (value: T) => 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 */\n// TODO: Either fix this lint violation or explain why it's necessary to ignore.\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport type StateMetadata<T extends StateConstraint> = {\n [P in keyof T]-?: StatePropertyMetadata<T[P]>;\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 anonymous: 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\nexport type ControllerStateChangeEvent<\n ControllerName extends string,\n ControllerState extends StateConstraint,\n> = {\n type: `${ControllerName}:stateChange`;\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> = ControllerStateChangeEvent<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 `messagingSystem` 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 ? ControllerEvents<\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 }\n\n /**\n * Retrieves current controller state.\n *\n * @returns The current state.\n */\n get state() {\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 cb: 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 }\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[]) {\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 }\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() {\n this.messenger.clearEventSubscriptions(`${this.name}:stateChange`);\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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metamask-previews/base-controller",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.4.0-preview-463efec",
|
|
4
4
|
"description": "Provides scaffolding for controllers as well a communication system for all controllers",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"MetaMask",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch"
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"@metamask/messenger": "^0.
|
|
60
|
+
"@metamask/messenger": "^0.3.0",
|
|
61
61
|
"@metamask/utils": "^11.8.0",
|
|
62
62
|
"immer": "^9.0.6"
|
|
63
63
|
},
|