@metamask-previews/composable-controller 4.0.0-preview.3fbb6b41 → 5.0.0-preview.1ef189c

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [5.0.0]
10
+ ### Added
11
+ - Add types `ComposableControllerState`, `ComposableControllerStateChangeEvent`, `ComposableControllerEvents`, `ComposableControllerMessenger` ([#3590](https://github.com/MetaMask/core/pull/3590))
12
+
13
+ ### Changed
14
+ - **BREAKING:** `ComposableController` is upgraded to extend `BaseControllerV2` ([#3590](https://github.com/MetaMask/core/pull/3590))
15
+ - The constructor now expects an options object with required properties `controllers` and `messenger` as its only argument.
16
+ - `ComposableController` no longer has a `subscribe` method. Instead, listeners for `ComposableController` events must be registered to the controller messenger that generated the restricted messenger assigned to the instance's `messagingSystem` class field.
17
+ - Any getters for `ComposableController` state that access the internal class field directly should be refactored to instead use listeners that are subscribed to `ComposableControllerStateChangeEvent`.
18
+ - Bump `@metamask/base-controller` to `^4.0.1` ([#3695](https://github.com/MetaMask/core/pull/3695))
19
+
9
20
  ## [4.0.0]
10
21
  ### Changed
11
22
  - **BREAKING:** Bump `@metamask/base-controller` to ^4.0.0 ([#2063](https://github.com/MetaMask/core/pull/2063))
@@ -50,7 +61,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
50
61
 
51
62
  All changes listed after this point were applied to this package following the monorepo conversion.
52
63
 
53
- [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/composable-controller@4.0.0...HEAD
64
+ [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/composable-controller@5.0.0...HEAD
65
+ [5.0.0]: https://github.com/MetaMask/core/compare/@metamask/composable-controller@4.0.0...@metamask/composable-controller@5.0.0
54
66
  [4.0.0]: https://github.com/MetaMask/core/compare/@metamask/composable-controller@3.0.3...@metamask/composable-controller@4.0.0
55
67
  [3.0.3]: https://github.com/MetaMask/core/compare/@metamask/composable-controller@3.0.2...@metamask/composable-controller@3.0.3
56
68
  [3.0.2]: https://github.com/MetaMask/core/compare/@metamask/composable-controller@3.0.1...@metamask/composable-controller@3.0.2
@@ -1,36 +1,36 @@
1
- import type { RestrictedControllerMessenger } from '@metamask/base-controller';
2
- import { BaseControllerV1 } from '@metamask/base-controller';
1
+ import { BaseController, BaseControllerV1 } from '@metamask/base-controller';
2
+ import type { ControllerStateChangeEvent, RestrictedControllerMessenger } from '@metamask/base-controller';
3
+ export declare const controllerName = "ComposableController";
4
+ declare type ControllerInstance = BaseControllerV1<any, any> | {
5
+ name: string;
6
+ state: Record<string, unknown>;
7
+ };
3
8
  /**
4
9
  * List of child controller instances
5
- *
6
- * This type encompasses controllers based up either BaseControllerV1 or
7
- * BaseController. The BaseController type can't be included directly
8
- * because the generic parameters it expects require knowing the exact state
9
- * shape, so instead we look for an object with the BaseController properties
10
- * that we use in the ComposableController (name and state).
11
10
  */
12
- export declare type ControllerList = (BaseControllerV1<any, any> | {
13
- name: string;
14
- state: Record<string, unknown>;
15
- })[];
16
- export declare type ComposableControllerRestrictedMessenger = RestrictedControllerMessenger<'ComposableController', never, any, never, any>;
11
+ export declare type ControllerList = ControllerInstance[];
12
+ export declare type ComposableControllerState = {
13
+ [name: string]: ControllerInstance['state'];
14
+ };
15
+ export declare type ComposableControllerStateChangeEvent = ControllerStateChangeEvent<typeof controllerName, ComposableControllerState>;
16
+ export declare type ComposableControllerEvents = ComposableControllerStateChangeEvent;
17
+ export declare type ComposableControllerMessenger = RestrictedControllerMessenger<typeof controllerName, never, ControllerStateChangeEvent<string, Record<string, unknown>>, string, string>;
17
18
  /**
18
19
  * Controller that can be used to compose multiple controllers together.
19
20
  */
20
- export declare class ComposableController extends BaseControllerV1<never, any> {
21
- private readonly controllers;
22
- private readonly messagingSystem?;
23
- /**
24
- * Name of this controller used during composition
25
- */
26
- name: string;
21
+ export declare class ComposableController extends BaseController<typeof controllerName, ComposableControllerState, ComposableControllerMessenger> {
22
+ #private;
27
23
  /**
28
24
  * Creates a ComposableController instance.
29
25
  *
30
- * @param controllers - Map of names to controller instances.
31
- * @param messenger - The controller messaging system, used for communicating with BaseController controllers.
26
+ * @param options - Initial options used to configure this controller
27
+ * @param options.controllers - List of child controller instances to compose.
28
+ * @param options.messenger - A restricted controller messenger.
32
29
  */
33
- constructor(controllers: ControllerList, messenger?: ComposableControllerRestrictedMessenger);
30
+ constructor({ controllers, messenger, }: {
31
+ controllers: ControllerList;
32
+ messenger: ComposableControllerMessenger;
33
+ });
34
34
  /**
35
35
  * Flat state representation, one that isn't keyed
36
36
  * of controller name. Instead, all child controller state is merged
@@ -1 +1 @@
1
- {"version":3,"file":"ComposableController.d.ts","sourceRoot":"","sources":["../src/ComposableController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,2BAA2B,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAE7D;;;;;;;;GAQG;AACH,oBAAY,cAAc,GAAG,CACzB,gBAAgB,CAAC,GAAG,EAAE,GAAG,CAAC,GAC1B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CACnD,EAAE,CAAC;AAEJ,oBAAY,uCAAuC,GACjD,6BAA6B,CAAC,sBAAsB,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;AAEhF;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,gBAAgB,CAAC,KAAK,EAAE,GAAG,CAAC;IACpE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAsB;IAElD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,CAA0C;IAE3E;;OAEG;IACM,IAAI,SAA0B;IAEvC;;;;;OAKG;gBAED,WAAW,EAAE,cAAc,EAC3B,SAAS,CAAC,EAAE,uCAAuC;IAiCrD;;;;;;OAMG;IACH,IAAI,SAAS,OAMZ;CACF;AAED,eAAe,oBAAoB,CAAC"}
1
+ {"version":3,"file":"ComposableController.d.ts","sourceRoot":"","sources":["../src/ComposableController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,KAAK,EACV,0BAA0B,EAC1B,6BAA6B,EAC9B,MAAM,2BAA2B,CAAC;AAEnC,eAAO,MAAM,cAAc,yBAAyB,CAAC;AASrD,aAAK,kBAAkB,GAGrB,gBAAgB,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC;AAEhF;;GAEG;AACH,oBAAY,cAAc,GAAG,kBAAkB,EAAE,CAAC;AAelD,oBAAY,yBAAyB,GAAG;IACtC,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;CAC7C,CAAC;AAEF,oBAAY,oCAAoC,GAAG,0BAA0B,CAC3E,OAAO,cAAc,EACrB,yBAAyB,CAC1B,CAAC;AAEF,oBAAY,0BAA0B,GAAG,oCAAoC,CAAC;AAE9E,oBAAY,6BAA6B,GAAG,6BAA6B,CACvE,OAAO,cAAc,EACrB,KAAK,EACL,0BAA0B,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAC3D,MAAM,EACN,MAAM,CACP,CAAC;AAEF;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,cAAc,CACtD,OAAO,cAAc,EACrB,yBAAyB,EACzB,6BAA6B,CAC9B;;IAGC;;;;;;OAMG;gBAES,EACV,WAAW,EACX,SAAS,GACV,EAAE;QACD,WAAW,EAAE,cAAc,CAAC;QAC5B,SAAS,EAAE,6BAA6B,CAAC;KAC1C;IAoBD;;;;;;OAMG;IACH,IAAI,SAAS,OAMZ;CA4BF;AAED,eAAe,oBAAoB,CAAC"}
@@ -1,46 +1,55 @@
1
1
  "use strict";
2
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
3
+ if (kind === "m") throw new TypeError("Private method is not writable");
4
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
5
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
6
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
7
+ };
8
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
9
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
10
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
+ };
13
+ var _ComposableController_instances, _ComposableController_controllers, _ComposableController_updateChildController;
2
14
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ComposableController = void 0;
15
+ exports.ComposableController = exports.controllerName = void 0;
4
16
  const base_controller_1 = require("@metamask/base-controller");
17
+ exports.controllerName = 'ComposableController';
18
+ /**
19
+ * Determines if the given controller is an instance of BaseControllerV1
20
+ * @param controller - Controller instance to check
21
+ * @returns True if the controller is an instance of BaseControllerV1
22
+ */
23
+ function isBaseControllerV1(controller) {
24
+ return controller instanceof base_controller_1.BaseControllerV1;
25
+ }
5
26
  /**
6
27
  * Controller that can be used to compose multiple controllers together.
7
28
  */
8
- class ComposableController extends base_controller_1.BaseControllerV1 {
29
+ class ComposableController extends base_controller_1.BaseController {
9
30
  /**
10
31
  * Creates a ComposableController instance.
11
32
  *
12
- * @param controllers - Map of names to controller instances.
13
- * @param messenger - The controller messaging system, used for communicating with BaseController controllers.
33
+ * @param options - Initial options used to configure this controller
34
+ * @param options.controllers - List of child controller instances to compose.
35
+ * @param options.messenger - A restricted controller messenger.
14
36
  */
15
- constructor(controllers, messenger) {
16
- super(undefined, controllers.reduce((state, controller) => {
17
- state[controller.name] = controller.state;
18
- return state;
19
- }, {}));
20
- this.controllers = [];
21
- /**
22
- * Name of this controller used during composition
23
- */
24
- this.name = 'ComposableController';
25
- this.initialize();
26
- this.controllers = controllers;
27
- this.messagingSystem = messenger;
28
- this.controllers.forEach((controller) => {
29
- const { name } = controller;
30
- if (controller.subscribe !== undefined) {
31
- controller.subscribe((state) => {
32
- this.update({ [name]: state });
33
- });
34
- }
35
- else if (this.messagingSystem) {
36
- this.messagingSystem.subscribe(`${name}:stateChange`, (state) => {
37
- this.update({ [name]: state });
38
- });
39
- }
40
- else {
41
- throw new Error(`Messaging system required if any BaseController controllers are used`);
42
- }
37
+ constructor({ controllers, messenger, }) {
38
+ if (messenger === undefined) {
39
+ throw new Error(`Messaging system is required`);
40
+ }
41
+ super({
42
+ name: exports.controllerName,
43
+ metadata: {},
44
+ state: controllers.reduce((state, controller) => {
45
+ return Object.assign(Object.assign({}, state), { [controller.name]: controller.state });
46
+ }, {}),
47
+ messenger,
43
48
  });
49
+ _ComposableController_instances.add(this);
50
+ _ComposableController_controllers.set(this, []);
51
+ __classPrivateFieldSet(this, _ComposableController_controllers, controllers, "f");
52
+ __classPrivateFieldGet(this, _ComposableController_controllers, "f").forEach((controller) => __classPrivateFieldGet(this, _ComposableController_instances, "m", _ComposableController_updateChildController).call(this, controller));
44
53
  }
45
54
  /**
46
55
  * Flat state representation, one that isn't keyed
@@ -51,12 +60,25 @@ class ComposableController extends base_controller_1.BaseControllerV1 {
51
60
  */
52
61
  get flatState() {
53
62
  let flatState = {};
54
- for (const controller of this.controllers) {
63
+ for (const controller of __classPrivateFieldGet(this, _ComposableController_controllers, "f")) {
55
64
  flatState = Object.assign(Object.assign({}, flatState), controller.state);
56
65
  }
57
66
  return flatState;
58
67
  }
59
68
  }
60
69
  exports.ComposableController = ComposableController;
70
+ _ComposableController_controllers = new WeakMap(), _ComposableController_instances = new WeakSet(), _ComposableController_updateChildController = function _ComposableController_updateChildController(controller) {
71
+ const { name } = controller;
72
+ if (isBaseControllerV1(controller)) {
73
+ controller.subscribe((childState) => {
74
+ this.update((state) => (Object.assign(Object.assign({}, state), { [name]: childState })));
75
+ });
76
+ }
77
+ else {
78
+ this.messagingSystem.subscribe(`${String(name)}:stateChange`, (childState) => {
79
+ this.update((state) => (Object.assign(Object.assign({}, state), { [name]: childState })));
80
+ });
81
+ }
82
+ };
61
83
  exports.default = ComposableController;
62
84
  //# sourceMappingURL=ComposableController.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ComposableController.js","sourceRoot":"","sources":["../src/ComposableController.ts"],"names":[],"mappings":";;;AACA,+DAA6D;AAmB7D;;GAEG;AACH,MAAa,oBAAqB,SAAQ,kCAA4B;IAUpE;;;;;OAKG;IACH,YACE,WAA2B,EAC3B,SAAmD;QAEnD,KAAK,CACH,SAAS,EACT,WAAW,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE;YACvC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC;YAC1C,OAAO,KAAK,CAAC;QACf,CAAC,EAAE,EAAS,CAAC,CACd,CAAC;QAzBa,gBAAW,GAAmB,EAAE,CAAC;QAIlD;;WAEG;QACM,SAAI,GAAG,sBAAsB,CAAC;QAmBrC,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,eAAe,GAAG,SAAS,CAAC;QACjC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,EAAE;YACtC,MAAM,EAAE,IAAI,EAAE,GAAG,UAAU,CAAC;YAC5B,IAAK,UAAyC,CAAC,SAAS,KAAK,SAAS,EAAE;gBACrE,UAAyC,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE;oBAC7D,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;gBACjC,CAAC,CAAC,CAAC;aACJ;iBAAM,IAAI,IAAI,CAAC,eAAe,EAAE;gBAC9B,IAAI,CAAC,eAAe,CAAC,SAAiB,CACrC,GAAG,IAAI,cAAc,EACrB,CAAC,KAAU,EAAE,EAAE;oBACb,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;gBACjC,CAAC,CACF,CAAC;aACH;iBAAM;gBACL,MAAM,IAAI,KAAK,CACb,sEAAsE,CACvE,CAAC;aACH;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACH,IAAI,SAAS;QACX,IAAI,SAAS,GAAG,EAAE,CAAC;QACnB,KAAK,MAAM,UAAU,IAAI,IAAI,CAAC,WAAW,EAAE;YACzC,SAAS,mCAAQ,SAAS,GAAK,UAAU,CAAC,KAAK,CAAE,CAAC;SACnD;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;CACF;AAjED,oDAiEC;AAED,kBAAe,oBAAoB,CAAC","sourcesContent":["import type { RestrictedControllerMessenger } from '@metamask/base-controller';\nimport { BaseControllerV1 } from '@metamask/base-controller';\n\n/**\n * List of child controller instances\n *\n * This type encompasses controllers based up either BaseControllerV1 or\n * BaseController. The BaseController type can't be included directly\n * because the generic parameters it expects require knowing the exact state\n * shape, so instead we look for an object with the BaseController properties\n * that we use in the ComposableController (name and state).\n */\nexport type ControllerList = (\n | BaseControllerV1<any, any>\n | { name: string; state: Record<string, unknown> }\n)[];\n\nexport type ComposableControllerRestrictedMessenger =\n RestrictedControllerMessenger<'ComposableController', never, any, never, any>;\n\n/**\n * Controller that can be used to compose multiple controllers together.\n */\nexport class ComposableController extends BaseControllerV1<never, any> {\n private readonly controllers: ControllerList = [];\n\n private readonly messagingSystem?: ComposableControllerRestrictedMessenger;\n\n /**\n * Name of this controller used during composition\n */\n override name = 'ComposableController';\n\n /**\n * Creates a ComposableController instance.\n *\n * @param controllers - Map of names to controller instances.\n * @param messenger - The controller messaging system, used for communicating with BaseController controllers.\n */\n constructor(\n controllers: ControllerList,\n messenger?: ComposableControllerRestrictedMessenger,\n ) {\n super(\n undefined,\n controllers.reduce((state, controller) => {\n state[controller.name] = controller.state;\n return state;\n }, {} as any),\n );\n this.initialize();\n this.controllers = controllers;\n this.messagingSystem = messenger;\n this.controllers.forEach((controller) => {\n const { name } = controller;\n if ((controller as BaseControllerV1<any, any>).subscribe !== undefined) {\n (controller as BaseControllerV1<any, any>).subscribe((state) => {\n this.update({ [name]: state });\n });\n } else if (this.messagingSystem) {\n (this.messagingSystem.subscribe as any)(\n `${name}:stateChange`,\n (state: any) => {\n this.update({ [name]: state });\n },\n );\n } else {\n throw new Error(\n `Messaging system required if any BaseController controllers are used`,\n );\n }\n });\n }\n\n /**\n * Flat state representation, one that isn't keyed\n * of controller name. Instead, all child controller state is merged\n * together into a single, flat object.\n *\n * @returns Merged state representation of all child controllers.\n */\n get flatState() {\n let flatState = {};\n for (const controller of this.controllers) {\n flatState = { ...flatState, ...controller.state };\n }\n return flatState;\n }\n}\n\nexport default ComposableController;\n"]}
1
+ {"version":3,"file":"ComposableController.js","sourceRoot":"","sources":["../src/ComposableController.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,+DAA6E;AAMhE,QAAA,cAAc,GAAG,sBAAsB,CAAC;AAmBrD;;;;GAIG;AACH,SAAS,kBAAkB,CACzB,UAA8B;IAI9B,OAAO,UAAU,YAAY,kCAAgB,CAAC;AAChD,CAAC;AAqBD;;GAEG;AACH,MAAa,oBAAqB,SAAQ,gCAIzC;IAGC;;;;;;OAMG;IAEH,YAAY,EACV,WAAW,EACX,SAAS,GAIV;QACC,IAAI,SAAS,KAAK,SAAS,EAAE;YAC3B,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;SACjD;QAED,KAAK,CAAC;YACJ,IAAI,EAAE,sBAAc;YACpB,QAAQ,EAAE,EAAE;YACZ,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE;gBAC9C,uCAAY,KAAK,KAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC,KAAK,IAAG;YAC3D,CAAC,EAAE,EAA+B,CAAC;YACnC,SAAS;SACV,CAAC,CAAC;;QA5BL,4CAAwC,EAAE,EAAC;QA8BzC,uBAAA,IAAI,qCAAgB,WAAW,MAAA,CAAC;QAChC,uBAAA,IAAI,yCAAa,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,EAAE,CACvC,uBAAA,IAAI,oFAAuB,MAA3B,IAAI,EAAwB,UAAU,CAAC,CACxC,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACH,IAAI,SAAS;QACX,IAAI,SAAS,GAAG,EAAE,CAAC;QACnB,KAAK,MAAM,UAAU,IAAI,uBAAA,IAAI,yCAAa,EAAE;YAC1C,SAAS,mCAAQ,SAAS,GAAK,UAAU,CAAC,KAAK,CAAE,CAAC;SACnD;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;CA4BF;AAlFD,oDAkFC;uMArBwB,UAA8B;IACnD,MAAM,EAAE,IAAI,EAAE,GAAG,UAAU,CAAC;IAC5B,IAAI,kBAAkB,CAAC,UAAU,CAAC,EAAE;QAClC,UAAU,CAAC,SAAS,CAAC,CAAC,UAAU,EAAE,EAAE;YAClC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,iCAClB,KAAK,KACR,CAAC,IAAI,CAAC,EAAE,UAAU,IAClB,CAAC,CAAC;QACN,CAAC,CAAC,CAAC;KACJ;SAAM;QACL,IAAI,CAAC,eAAe,CAAC,SAAS,CAC5B,GAAG,MAAM,CAAC,IAAI,CAAC,cAAc,EAC7B,CAAC,UAAmC,EAAE,EAAE;YACtC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,iCAClB,KAAK,KACR,CAAC,IAAI,CAAC,EAAE,UAAU,IAClB,CAAC,CAAC;QACN,CAAC,CACF,CAAC;KACH;AACH,CAAC;AAGH,kBAAe,oBAAoB,CAAC","sourcesContent":["import { BaseController, BaseControllerV1 } from '@metamask/base-controller';\nimport type {\n ControllerStateChangeEvent,\n RestrictedControllerMessenger,\n} from '@metamask/base-controller';\n\nexport const controllerName = 'ComposableController';\n\n/*\n * This type encompasses controllers based on either BaseControllerV1 or\n * BaseController. The BaseController type can't be included directly\n * because the generic parameters it expects require knowing the exact state\n * shape, so instead we look for an object with the BaseController properties\n * that we use in the ComposableController (name and state).\n */\ntype ControllerInstance =\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n BaseControllerV1<any, any> | { name: string; state: Record<string, unknown> };\n\n/**\n * List of child controller instances\n */\nexport type ControllerList = ControllerInstance[];\n\n/**\n * Determines if the given controller is an instance of BaseControllerV1\n * @param controller - Controller instance to check\n * @returns True if the controller is an instance of BaseControllerV1\n */\nfunction isBaseControllerV1(\n controller: ControllerInstance,\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n): controller is BaseControllerV1<any, any> {\n return controller instanceof BaseControllerV1;\n}\n\nexport type ComposableControllerState = {\n [name: string]: ControllerInstance['state'];\n};\n\nexport type ComposableControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n ComposableControllerState\n>;\n\nexport type ComposableControllerEvents = ComposableControllerStateChangeEvent;\n\nexport type ComposableControllerMessenger = RestrictedControllerMessenger<\n typeof controllerName,\n never,\n ControllerStateChangeEvent<string, Record<string, unknown>>,\n string,\n string\n>;\n\n/**\n * Controller that can be used to compose multiple controllers together.\n */\nexport class ComposableController extends BaseController<\n typeof controllerName,\n ComposableControllerState,\n ComposableControllerMessenger\n> {\n readonly #controllers: ControllerList = [];\n\n /**\n * Creates a ComposableController instance.\n *\n * @param options - Initial options used to configure this controller\n * @param options.controllers - List of child controller instances to compose.\n * @param options.messenger - A restricted controller messenger.\n */\n\n constructor({\n controllers,\n messenger,\n }: {\n controllers: ControllerList;\n messenger: ComposableControllerMessenger;\n }) {\n if (messenger === undefined) {\n throw new Error(`Messaging system is required`);\n }\n\n super({\n name: controllerName,\n metadata: {},\n state: controllers.reduce((state, controller) => {\n return { ...state, [controller.name]: controller.state };\n }, {} as ComposableControllerState),\n messenger,\n });\n\n this.#controllers = controllers;\n this.#controllers.forEach((controller) =>\n this.#updateChildController(controller),\n );\n }\n\n /**\n * Flat state representation, one that isn't keyed\n * of controller name. Instead, all child controller state is merged\n * together into a single, flat object.\n *\n * @returns Merged state representation of all child controllers.\n */\n get flatState() {\n let flatState = {};\n for (const controller of this.#controllers) {\n flatState = { ...flatState, ...controller.state };\n }\n return flatState;\n }\n\n /**\n * Adds a child controller instance to composable controller state,\n * or updates the state of a child controller.\n * @param controller - Controller instance to update\n */\n #updateChildController(controller: ControllerInstance): void {\n const { name } = controller;\n if (isBaseControllerV1(controller)) {\n controller.subscribe((childState) => {\n this.update((state) => ({\n ...state,\n [name]: childState,\n }));\n });\n } else {\n this.messagingSystem.subscribe(\n `${String(name)}:stateChange`,\n (childState: Record<string, unknown>) => {\n this.update((state) => ({\n ...state,\n [name]: childState,\n }));\n },\n );\n }\n }\n}\n\nexport default ComposableController;\n"]}
package/dist/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
- export * from './ComposableController';
1
+ export type { ControllerList, ComposableControllerState, ComposableControllerStateChangeEvent, ComposableControllerEvents, ComposableControllerMessenger, } from './ComposableController';
2
+ export { ComposableController } from './ComposableController';
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,cAAc,EACd,yBAAyB,EACzB,oCAAoC,EACpC,0BAA0B,EAC1B,6BAA6B,GAC9B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC"}
package/dist/index.js CHANGED
@@ -1,18 +1,6 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
2
  Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./ComposableController"), exports);
3
+ exports.ComposableController = void 0;
4
+ var ComposableController_1 = require("./ComposableController");
5
+ Object.defineProperty(exports, "ComposableController", { enumerable: true, get: function () { return ComposableController_1.ComposableController; } });
18
6
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yDAAuC","sourcesContent":["export * from './ComposableController';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAOA,+DAA8D;AAArD,4HAAA,oBAAoB,OAAA","sourcesContent":["export type {\n ControllerList,\n ComposableControllerState,\n ComposableControllerStateChangeEvent,\n ComposableControllerEvents,\n ComposableControllerMessenger,\n} from './ComposableController';\nexport { ComposableController } from './ComposableController';\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask-previews/composable-controller",
3
- "version": "4.0.0-preview.3fbb6b41",
3
+ "version": "5.0.0-preview.1ef189c",
4
4
  "description": "Consolidates the state from multiple controllers into one",
5
5
  "keywords": [
6
6
  "MetaMask",
@@ -22,6 +22,7 @@
22
22
  ],
23
23
  "scripts": {
24
24
  "build:docs": "typedoc",
25
+ "changelog:update": "../../scripts/update-changelog.sh @metamask/composable-controller",
25
26
  "changelog:validate": "../../scripts/validate-changelog.sh @metamask/composable-controller",
26
27
  "publish:preview": "yarn npm publish --tag preview",
27
28
  "test": "jest --reporters=jest-silent-reporter",
@@ -30,10 +31,10 @@
30
31
  "test:watch": "jest --watch"
31
32
  },
32
33
  "dependencies": {
33
- "@metamask/base-controller": "^4.0.0"
34
+ "@metamask/base-controller": "^4.1.0"
34
35
  },
35
36
  "devDependencies": {
36
- "@metamask/auto-changelog": "^3.4.3",
37
+ "@metamask/auto-changelog": "^3.4.4",
37
38
  "@types/jest": "^27.4.1",
38
39
  "deepmerge": "^4.2.2",
39
40
  "immer": "^9.0.6",