@metamask/polling-controller 0.1.0 → 1.0.0

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,9 +6,31 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [1.0.0]
10
+ ### Added
11
+ - Add `PollingControllerOnly` to extend from an empty class. This will allow classes that previously are just classes that don't extend from BaseV1 or V2 to extend from this new `PollingControllerOnly`. ([#1873](https://github.com/MetaMask/core/pull/1873))
12
+
13
+ ### Changed
14
+ - **BREAKING:** `_executePoll()` is called immediately on start if no polling interval is already active for the networkClientId + options combination ([#1874](https://github.com/MetaMask/core/pull/1874))
15
+ - Bump dependency and peer dependency on `@metamask/network-controller` to ^15.1.0
16
+
17
+ ## [0.2.0]
18
+ ### Added
19
+ - Add way to start and stop different polling sessions for the same network client ID by providing extra scoping data ([#1776](https://github.com/MetaMask/core/pull/1776))
20
+ - Add optional second argument to `stopPollingByPollingToken` (formerly `stopPollingByNetworkClientId`)
21
+ - Add optional second argument to `onPollingCompleteByNetworkClientId`
22
+
23
+ ### Changed
24
+ - **BREAKING:** Bump dependency and peer dependency on `@metamask/network-controller` to ^15.0.0
25
+ - **BREAKING:** Polling controllers are expected to override `_executePoll` instead of `executePoll` ([#1810](https://github.com/MetaMask/core/pull/1810))
26
+ - **BREAKING:** Rename `stopPollingByNetworkClientId` to `stopPollingByPollingToken` ([#1810](https://github.com/MetaMask/core/pull/1810))
27
+ - Add dependency on `fast-json-stable-stringify` ^2.1.0
28
+
9
29
  ## [0.1.0]
10
30
  ### Added
11
31
  - Initial release
12
32
 
13
- [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/polling-controller@0.1.0...HEAD
33
+ [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/polling-controller@1.0.0...HEAD
34
+ [1.0.0]: https://github.com/MetaMask/core/compare/@metamask/polling-controller@0.2.0...@metamask/polling-controller@1.0.0
35
+ [0.2.0]: https://github.com/MetaMask/core/compare/@metamask/polling-controller@0.1.0...@metamask/polling-controller@0.2.0
14
36
  [0.1.0]: https://github.com/MetaMask/core/releases/tag/@metamask/polling-controller@0.1.0
@@ -5,11 +5,69 @@
5
5
  /// <reference types="node" />
6
6
  import { BaseController, BaseControllerV2 } from '@metamask/base-controller';
7
7
  import type { NetworkClientId } from '@metamask/network-controller';
8
+ import type { Json } from '@metamask/utils';
9
+ /**
10
+ * Returns a unique key for a networkClientId and options. This is used to group networkClientId polls with the same options
11
+ * @param networkClientId - The networkClientId to get a key for
12
+ * @param options - The options used to group the polling events
13
+ * @returns The unique key
14
+ */
15
+ export declare const getKey: (networkClientId: NetworkClientId, options: Json) => PollingTokenSetId;
16
+ declare type PollingTokenSetId = `${NetworkClientId}:${string}`;
17
+ declare class Empty {
18
+ }
19
+ export declare const PollingControllerOnly: (abstract new (...args: any[]) => {
20
+ readonly "__#88103@#pollingTokenSets": Map<PollingTokenSetId, Set<string>>;
21
+ readonly "__#88103@#intervalIds": Record<PollingTokenSetId, NodeJS.Timeout>;
22
+ "__#88103@#callbacks": Map<string, Set<(networkClientId: NetworkClientId) => void>>;
23
+ "__#88103@#intervalLength": number;
24
+ getIntervalLength(): number;
25
+ /**
26
+ * Sets the length of the polling interval
27
+ *
28
+ * @param length - The length of the polling interval in milliseconds
29
+ */
30
+ setIntervalLength(length: number): void;
31
+ /**
32
+ * Starts polling for a networkClientId
33
+ *
34
+ * @param networkClientId - The networkClientId to start polling for
35
+ * @param options - The options used to group the polling events
36
+ * @returns void
37
+ */
38
+ startPollingByNetworkClientId(networkClientId: NetworkClientId, options?: Json): string;
39
+ /**
40
+ * Stops polling for all networkClientIds
41
+ */
42
+ stopAllPolling(): void;
43
+ /**
44
+ * Stops polling for a networkClientId
45
+ *
46
+ * @param pollingToken - The polling token to stop polling for
47
+ */
48
+ stopPollingByPollingToken(pollingToken: string): void;
49
+ /**
50
+ * Executes the poll for a networkClientId
51
+ *
52
+ * @param networkClientId - The networkClientId to execute the poll for
53
+ * @param options - The options passed to startPollingByNetworkClientId
54
+ */
55
+ _executePoll(networkClientId: NetworkClientId, options: Json): Promise<void>;
56
+ "__#88103@#poll"(networkClientId: NetworkClientId, options: Json): void;
57
+ /**
58
+ * Adds a callback to execute when polling is complete
59
+ *
60
+ * @param networkClientId - The networkClientId to listen for polling complete events
61
+ * @param callback - The callback to execute when polling is complete
62
+ * @param options - The options used to group the polling events
63
+ */
64
+ onPollingCompleteByNetworkClientId(networkClientId: NetworkClientId, callback: (networkClientId: NetworkClientId) => void, options?: Json): void;
65
+ }) & typeof Empty;
8
66
  export declare const PollingController: (abstract new (...args: any[]) => {
9
- readonly "__#112124@#networkClientIdTokensMap": Map<NetworkClientId, Set<string>>;
10
- readonly "__#112124@#intervalIds": Record<NetworkClientId, NodeJS.Timeout>;
11
- "__#112124@#callbacks": Map<string, Set<(networkClientId: NetworkClientId) => void>>;
12
- "__#112124@#intervalLength": number;
67
+ readonly "__#88103@#pollingTokenSets": Map<PollingTokenSetId, Set<string>>;
68
+ readonly "__#88103@#intervalIds": Record<PollingTokenSetId, NodeJS.Timeout>;
69
+ "__#88103@#callbacks": Map<string, Set<(networkClientId: NetworkClientId) => void>>;
70
+ "__#88103@#intervalLength": number;
13
71
  getIntervalLength(): number;
14
72
  /**
15
73
  * Sets the length of the polling interval
@@ -21,9 +79,10 @@ export declare const PollingController: (abstract new (...args: any[]) => {
21
79
  * Starts polling for a networkClientId
22
80
  *
23
81
  * @param networkClientId - The networkClientId to start polling for
82
+ * @param options - The options used to group the polling events
24
83
  * @returns void
25
84
  */
26
- startPollingByNetworkClientId(networkClientId: NetworkClientId): string;
85
+ startPollingByNetworkClientId(networkClientId: NetworkClientId, options?: Json): string;
27
86
  /**
28
87
  * Stops polling for all networkClientIds
29
88
  */
@@ -33,27 +92,29 @@ export declare const PollingController: (abstract new (...args: any[]) => {
33
92
  *
34
93
  * @param pollingToken - The polling token to stop polling for
35
94
  */
36
- stopPollingByNetworkClientId(pollingToken: string): void;
95
+ stopPollingByPollingToken(pollingToken: string): void;
37
96
  /**
38
97
  * Executes the poll for a networkClientId
39
98
  *
40
99
  * @param networkClientId - The networkClientId to execute the poll for
100
+ * @param options - The options passed to startPollingByNetworkClientId
41
101
  */
42
- executePoll(networkClientId: NetworkClientId): Promise<void>;
43
- "__#112124@#poll"(networkClientId: NetworkClientId): void;
102
+ _executePoll(networkClientId: NetworkClientId, options: Json): Promise<void>;
103
+ "__#88103@#poll"(networkClientId: NetworkClientId, options: Json): void;
44
104
  /**
45
105
  * Adds a callback to execute when polling is complete
46
106
  *
47
107
  * @param networkClientId - The networkClientId to listen for polling complete events
48
108
  * @param callback - The callback to execute when polling is complete
109
+ * @param options - The options used to group the polling events
49
110
  */
50
- onPollingCompleteByNetworkClientId(networkClientId: NetworkClientId, callback: (networkClientId: NetworkClientId) => void): void;
111
+ onPollingCompleteByNetworkClientId(networkClientId: NetworkClientId, callback: (networkClientId: NetworkClientId) => void, options?: Json): void;
51
112
  }) & typeof BaseControllerV2;
52
113
  export declare const PollingControllerV1: (abstract new (...args: any[]) => {
53
- readonly "__#112124@#networkClientIdTokensMap": Map<NetworkClientId, Set<string>>;
54
- readonly "__#112124@#intervalIds": Record<NetworkClientId, NodeJS.Timeout>;
55
- "__#112124@#callbacks": Map<string, Set<(networkClientId: NetworkClientId) => void>>;
56
- "__#112124@#intervalLength": number;
114
+ readonly "__#88103@#pollingTokenSets": Map<PollingTokenSetId, Set<string>>;
115
+ readonly "__#88103@#intervalIds": Record<PollingTokenSetId, NodeJS.Timeout>;
116
+ "__#88103@#callbacks": Map<string, Set<(networkClientId: NetworkClientId) => void>>;
117
+ "__#88103@#intervalLength": number;
57
118
  getIntervalLength(): number;
58
119
  /**
59
120
  * Sets the length of the polling interval
@@ -65,9 +126,10 @@ export declare const PollingControllerV1: (abstract new (...args: any[]) => {
65
126
  * Starts polling for a networkClientId
66
127
  *
67
128
  * @param networkClientId - The networkClientId to start polling for
129
+ * @param options - The options used to group the polling events
68
130
  * @returns void
69
131
  */
70
- startPollingByNetworkClientId(networkClientId: NetworkClientId): string;
132
+ startPollingByNetworkClientId(networkClientId: NetworkClientId, options?: Json): string;
71
133
  /**
72
134
  * Stops polling for all networkClientIds
73
135
  */
@@ -77,20 +139,23 @@ export declare const PollingControllerV1: (abstract new (...args: any[]) => {
77
139
  *
78
140
  * @param pollingToken - The polling token to stop polling for
79
141
  */
80
- stopPollingByNetworkClientId(pollingToken: string): void;
142
+ stopPollingByPollingToken(pollingToken: string): void;
81
143
  /**
82
144
  * Executes the poll for a networkClientId
83
145
  *
84
146
  * @param networkClientId - The networkClientId to execute the poll for
147
+ * @param options - The options passed to startPollingByNetworkClientId
85
148
  */
86
- executePoll(networkClientId: NetworkClientId): Promise<void>;
87
- "__#112124@#poll"(networkClientId: NetworkClientId): void;
149
+ _executePoll(networkClientId: NetworkClientId, options: Json): Promise<void>;
150
+ "__#88103@#poll"(networkClientId: NetworkClientId, options: Json): void;
88
151
  /**
89
152
  * Adds a callback to execute when polling is complete
90
153
  *
91
154
  * @param networkClientId - The networkClientId to listen for polling complete events
92
155
  * @param callback - The callback to execute when polling is complete
156
+ * @param options - The options used to group the polling events
93
157
  */
94
- onPollingCompleteByNetworkClientId(networkClientId: NetworkClientId, callback: (networkClientId: NetworkClientId) => void): void;
158
+ onPollingCompleteByNetworkClientId(networkClientId: NetworkClientId, callback: (networkClientId: NetworkClientId) => void, options?: Json): void;
95
159
  }) & typeof BaseController;
160
+ export {};
96
161
  //# sourceMappingURL=PollingController.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PollingController.d.ts","sourceRoot":"","sources":["../src/PollingController.ts"],"names":[],"mappings":";;;;;AAAA,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AA4JpE,eAAO,MAAM,iBAAiB,0BAvJG,GAAG,EAAE;oDAgBE,IAAI,eAAe,EAAE,IAAI,MAAM,CAAC,CAAC;uCAG9C,OAAO,eAAe,EAAE,OAAO,OAAO,CAAC;8DAItC,eAAe,KAAK,IAAI;;;IAShD;;;;OAIG;8BACuB,MAAM;IAIhC;;;;;OAKG;mDAC4C,eAAe;IAc9D;;OAEG;;IASH;;;;OAIG;+CACwC,MAAM;IA2BjD;;;;OAIG;iCACmC,eAAe,GAAG,QAAQ,IAAI,CAAC;uCAE9C,eAAe;IAkBtC;;;;;OAKG;wDAEgB,eAAe,8BACJ,eAAe,KAAK,IAAI;4BAce,CAAC;AAC1E,eAAO,MAAM,mBAAmB,0BAxJC,GAAG,EAAE;oDAgBE,IAAI,eAAe,EAAE,IAAI,MAAM,CAAC,CAAC;uCAG9C,OAAO,eAAe,EAAE,OAAO,OAAO,CAAC;8DAItC,eAAe,KAAK,IAAI;;;IAShD;;;;OAIG;8BACuB,MAAM;IAIhC;;;;;OAKG;mDAC4C,eAAe;IAc9D;;OAEG;;IASH;;;;OAIG;+CACwC,MAAM;IA2BjD;;;;OAIG;iCACmC,eAAe,GAAG,QAAQ,IAAI,CAAC;uCAE9C,eAAe;IAkBtC;;;;;OAKG;wDAEgB,eAAe,8BACJ,eAAe,KAAK,IAAI;0BAee,CAAC"}
1
+ {"version":3,"file":"PollingController.d.ts","sourceRoot":"","sources":["../src/PollingController.ts"],"names":[],"mappings":";;;;;AAAA,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAQ5C;;;;;GAKG;AACH,eAAO,MAAM,MAAM,oBACA,eAAe,WACvB,IAAI,KACZ,iBAA+D,CAAC;AAEnE,aAAK,iBAAiB,GAAG,GAAG,eAAe,IAAI,MAAM,EAAE,CAAC;AAwKxD,cAAM,KAAK;CAAG;AAEd,eAAO,MAAM,qBAAqB,0BAvLD,GAAG,EAAE;2CA4BN,IAAI,iBAAiB,EAAE,IAAI,MAAM,CAAC,CAAC;sCAExC,OAAO,iBAAiB,EAAE,OAAO,OAAO,CAAC;6DAIxC,eAAe,KAAK,IAAI;;;IAShD;;;;OAIG;8BACuB,MAAM;IAIhC;;;;;;OAMG;mDAEgB,eAAe,YACvB,IAAI;IAkBf;;OAEG;;IASH;;;;OAIG;4CACqC,MAAM;IAyB9C;;;;;OAKG;kCAEgB,eAAe,WACvB,IAAI,GACZ,QAAQ,IAAI,CAAC;sCAEO,eAAe,WAAW,IAAI;IAuBrD;;;;;;OAMG;wDAEgB,eAAe,8BACJ,eAAe,KAAK,IAAI,YAC3C,IAAI;iBAmB+C,CAAC;AACnE,eAAO,MAAM,iBAAiB,0BAxLG,GAAG,EAAE;2CA4BN,IAAI,iBAAiB,EAAE,IAAI,MAAM,CAAC,CAAC;sCAExC,OAAO,iBAAiB,EAAE,OAAO,OAAO,CAAC;6DAIxC,eAAe,KAAK,IAAI;;;IAShD;;;;OAIG;8BACuB,MAAM;IAIhC;;;;;;OAMG;mDAEgB,eAAe,YACvB,IAAI;IAkBf;;OAEG;;IASH;;;;OAIG;4CACqC,MAAM;IAyB9C;;;;;OAKG;kCAEgB,eAAe,WACvB,IAAI,GACZ,QAAQ,IAAI,CAAC;sCAEO,eAAe,WAAW,IAAI;IAuBrD;;;;;;OAMG;wDAEgB,eAAe,8BACJ,eAAe,KAAK,IAAI,YAC3C,IAAI;4BAoBsD,CAAC;AAC1E,eAAO,MAAM,mBAAmB,0BAzLC,GAAG,EAAE;2CA4BN,IAAI,iBAAiB,EAAE,IAAI,MAAM,CAAC,CAAC;sCAExC,OAAO,iBAAiB,EAAE,OAAO,OAAO,CAAC;6DAIxC,eAAe,KAAK,IAAI;;;IAShD;;;;OAIG;8BACuB,MAAM;IAIhC;;;;;;OAMG;mDAEgB,eAAe,YACvB,IAAI;IAkBf;;OAEG;;IASH;;;;OAIG;4CACqC,MAAM;IAyB9C;;;;;OAKG;kCAEgB,eAAe,WACvB,IAAI,GACZ,QAAQ,IAAI,CAAC;sCAEO,eAAe,WAAW,IAAI;IAuBrD;;;;;;OAMG;wDAEgB,eAAe,8BACJ,eAAe,KAAK,IAAI,YAC3C,IAAI;0BAqBsD,CAAC"}
@@ -19,10 +19,22 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
19
19
  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");
20
20
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
21
21
  };
22
+ var __importDefault = (this && this.__importDefault) || function (mod) {
23
+ return (mod && mod.__esModule) ? mod : { "default": mod };
24
+ };
22
25
  Object.defineProperty(exports, "__esModule", { value: true });
23
- exports.PollingControllerV1 = exports.PollingController = void 0;
26
+ exports.PollingControllerV1 = exports.PollingController = exports.PollingControllerOnly = exports.getKey = void 0;
24
27
  const base_controller_1 = require("@metamask/base-controller");
28
+ const fast_json_stable_stringify_1 = __importDefault(require("fast-json-stable-stringify"));
25
29
  const uuid_1 = require("uuid");
30
+ /**
31
+ * Returns a unique key for a networkClientId and options. This is used to group networkClientId polls with the same options
32
+ * @param networkClientId - The networkClientId to get a key for
33
+ * @param options - The options used to group the polling events
34
+ * @returns The unique key
35
+ */
36
+ const getKey = (networkClientId, options) => `${networkClientId}:${(0, fast_json_stable_stringify_1.default)(options)}`;
37
+ exports.getKey = getKey;
26
38
  /**
27
39
  * PollingControllerMixin
28
40
  *
@@ -30,7 +42,7 @@ const uuid_1 = require("uuid");
30
42
  * @returns The composed class.
31
43
  */
32
44
  function PollingControllerMixin(Base) {
33
- var _PollingControllerBase_instances, _PollingControllerBase_networkClientIdTokensMap, _PollingControllerBase_intervalIds, _PollingControllerBase_callbacks, _PollingControllerBase_intervalLength, _PollingControllerBase_poll;
45
+ var _PollingControllerBase_instances, _PollingControllerBase_pollingTokenSets, _PollingControllerBase_intervalIds, _PollingControllerBase_callbacks, _PollingControllerBase_intervalLength, _PollingControllerBase_poll;
34
46
  /**
35
47
  * PollingController is an abstract class that implements the polling
36
48
  * functionality for a controller. It is meant to be extended by a controller
@@ -41,7 +53,7 @@ function PollingControllerMixin(Base) {
41
53
  constructor() {
42
54
  super(...arguments);
43
55
  _PollingControllerBase_instances.add(this);
44
- _PollingControllerBase_networkClientIdTokensMap.set(this, new Map());
56
+ _PollingControllerBase_pollingTokenSets.set(this, new Map());
45
57
  _PollingControllerBase_intervalIds.set(this, {});
46
58
  _PollingControllerBase_callbacks.set(this, new Map());
47
59
  _PollingControllerBase_intervalLength.set(this, 1000);
@@ -61,29 +73,31 @@ function PollingControllerMixin(Base) {
61
73
  * Starts polling for a networkClientId
62
74
  *
63
75
  * @param networkClientId - The networkClientId to start polling for
76
+ * @param options - The options used to group the polling events
64
77
  * @returns void
65
78
  */
66
- startPollingByNetworkClientId(networkClientId) {
67
- const innerPollToken = (0, uuid_1.v4)();
68
- if (__classPrivateFieldGet(this, _PollingControllerBase_networkClientIdTokensMap, "f").has(networkClientId)) {
69
- const set = __classPrivateFieldGet(this, _PollingControllerBase_networkClientIdTokensMap, "f").get(networkClientId);
70
- set === null || set === void 0 ? void 0 : set.add(innerPollToken);
79
+ startPollingByNetworkClientId(networkClientId, options = {}) {
80
+ const pollToken = (0, uuid_1.v4)();
81
+ const key = (0, exports.getKey)(networkClientId, options);
82
+ const pollingTokenSet = __classPrivateFieldGet(this, _PollingControllerBase_pollingTokenSets, "f").get(key);
83
+ if (pollingTokenSet) {
84
+ pollingTokenSet.add(pollToken);
71
85
  }
72
86
  else {
73
87
  const set = new Set();
74
- set.add(innerPollToken);
75
- __classPrivateFieldGet(this, _PollingControllerBase_networkClientIdTokensMap, "f").set(networkClientId, set);
88
+ set.add(pollToken);
89
+ __classPrivateFieldGet(this, _PollingControllerBase_pollingTokenSets, "f").set(key, set);
76
90
  }
77
- __classPrivateFieldGet(this, _PollingControllerBase_instances, "m", _PollingControllerBase_poll).call(this, networkClientId);
78
- return innerPollToken;
91
+ __classPrivateFieldGet(this, _PollingControllerBase_instances, "m", _PollingControllerBase_poll).call(this, networkClientId, options);
92
+ return pollToken;
79
93
  }
80
94
  /**
81
95
  * Stops polling for all networkClientIds
82
96
  */
83
97
  stopAllPolling() {
84
- __classPrivateFieldGet(this, _PollingControllerBase_networkClientIdTokensMap, "f").forEach((tokens, _networkClientId) => {
85
- tokens.forEach((token) => {
86
- this.stopPollingByNetworkClientId(token);
98
+ __classPrivateFieldGet(this, _PollingControllerBase_pollingTokenSets, "f").forEach((tokenSet, _networkClientId) => {
99
+ tokenSet.forEach((token) => {
100
+ this.stopPollingByPollingToken(token);
87
101
  });
88
102
  });
89
103
  }
@@ -92,25 +106,24 @@ function PollingControllerMixin(Base) {
92
106
  *
93
107
  * @param pollingToken - The polling token to stop polling for
94
108
  */
95
- stopPollingByNetworkClientId(pollingToken) {
109
+ stopPollingByPollingToken(pollingToken) {
96
110
  if (!pollingToken) {
97
111
  throw new Error('pollingToken required');
98
112
  }
99
113
  let found = false;
100
- __classPrivateFieldGet(this, _PollingControllerBase_networkClientIdTokensMap, "f").forEach((tokens, networkClientId) => {
101
- var _a, _b, _c, _d;
102
- if (tokens.has(pollingToken)) {
114
+ __classPrivateFieldGet(this, _PollingControllerBase_pollingTokenSets, "f").forEach((tokenSet, key) => {
115
+ var _a, _b;
116
+ if (tokenSet.has(pollingToken)) {
103
117
  found = true;
104
- (_a = __classPrivateFieldGet(this, _PollingControllerBase_networkClientIdTokensMap, "f")
105
- .get(networkClientId)) === null || _a === void 0 ? void 0 : _a.delete(pollingToken);
106
- if (((_b = __classPrivateFieldGet(this, _PollingControllerBase_networkClientIdTokensMap, "f").get(networkClientId)) === null || _b === void 0 ? void 0 : _b.size) === 0) {
107
- clearTimeout(__classPrivateFieldGet(this, _PollingControllerBase_intervalIds, "f")[networkClientId]);
108
- delete __classPrivateFieldGet(this, _PollingControllerBase_intervalIds, "f")[networkClientId];
109
- __classPrivateFieldGet(this, _PollingControllerBase_networkClientIdTokensMap, "f").delete(networkClientId);
110
- (_c = __classPrivateFieldGet(this, _PollingControllerBase_callbacks, "f").get(networkClientId)) === null || _c === void 0 ? void 0 : _c.forEach((callback) => {
111
- callback(networkClientId);
118
+ tokenSet.delete(pollingToken);
119
+ if (tokenSet.size === 0) {
120
+ clearTimeout(__classPrivateFieldGet(this, _PollingControllerBase_intervalIds, "f")[key]);
121
+ delete __classPrivateFieldGet(this, _PollingControllerBase_intervalIds, "f")[key];
122
+ __classPrivateFieldGet(this, _PollingControllerBase_pollingTokenSets, "f").delete(key);
123
+ (_a = __classPrivateFieldGet(this, _PollingControllerBase_callbacks, "f").get(key)) === null || _a === void 0 ? void 0 : _a.forEach((callback) => {
124
+ callback(key);
112
125
  });
113
- (_d = __classPrivateFieldGet(this, _PollingControllerBase_callbacks, "f").get(networkClientId)) === null || _d === void 0 ? void 0 : _d.clear();
126
+ (_b = __classPrivateFieldGet(this, _PollingControllerBase_callbacks, "f").get(key)) === null || _b === void 0 ? void 0 : _b.clear();
114
127
  }
115
128
  }
116
129
  });
@@ -123,39 +136,46 @@ function PollingControllerMixin(Base) {
123
136
  *
124
137
  * @param networkClientId - The networkClientId to listen for polling complete events
125
138
  * @param callback - The callback to execute when polling is complete
139
+ * @param options - The options used to group the polling events
126
140
  */
127
- onPollingCompleteByNetworkClientId(networkClientId, callback) {
128
- var _a;
129
- if (__classPrivateFieldGet(this, _PollingControllerBase_callbacks, "f").has(networkClientId)) {
130
- (_a = __classPrivateFieldGet(this, _PollingControllerBase_callbacks, "f").get(networkClientId)) === null || _a === void 0 ? void 0 : _a.add(callback);
131
- }
132
- else {
141
+ onPollingCompleteByNetworkClientId(networkClientId, callback, options = {}) {
142
+ const key = (0, exports.getKey)(networkClientId, options);
143
+ const callbacks = __classPrivateFieldGet(this, _PollingControllerBase_callbacks, "f").get(key);
144
+ if (callbacks === undefined) {
133
145
  const set = new Set();
134
146
  set.add(callback);
135
- __classPrivateFieldGet(this, _PollingControllerBase_callbacks, "f").set(networkClientId, set);
147
+ __classPrivateFieldGet(this, _PollingControllerBase_callbacks, "f").set(key, set);
148
+ }
149
+ else {
150
+ callbacks.add(callback);
136
151
  }
137
152
  }
138
153
  }
139
- _PollingControllerBase_networkClientIdTokensMap = new WeakMap(), _PollingControllerBase_intervalIds = new WeakMap(), _PollingControllerBase_callbacks = new WeakMap(), _PollingControllerBase_intervalLength = new WeakMap(), _PollingControllerBase_instances = new WeakSet(), _PollingControllerBase_poll = function _PollingControllerBase_poll(networkClientId) {
140
- if (__classPrivateFieldGet(this, _PollingControllerBase_intervalIds, "f")[networkClientId]) {
141
- clearTimeout(__classPrivateFieldGet(this, _PollingControllerBase_intervalIds, "f")[networkClientId]);
142
- delete __classPrivateFieldGet(this, _PollingControllerBase_intervalIds, "f")[networkClientId];
154
+ _PollingControllerBase_pollingTokenSets = new WeakMap(), _PollingControllerBase_intervalIds = new WeakMap(), _PollingControllerBase_callbacks = new WeakMap(), _PollingControllerBase_intervalLength = new WeakMap(), _PollingControllerBase_instances = new WeakSet(), _PollingControllerBase_poll = function _PollingControllerBase_poll(networkClientId, options) {
155
+ const key = (0, exports.getKey)(networkClientId, options);
156
+ const interval = __classPrivateFieldGet(this, _PollingControllerBase_intervalIds, "f")[key];
157
+ if (interval) {
158
+ clearTimeout(interval);
159
+ delete __classPrivateFieldGet(this, _PollingControllerBase_intervalIds, "f")[key];
143
160
  }
144
161
  // setTimeout is not `await`ing this async function, which is expected
145
162
  // We're just using async here for improved stack traces
146
163
  // eslint-disable-next-line @typescript-eslint/no-misused-promises
147
- __classPrivateFieldGet(this, _PollingControllerBase_intervalIds, "f")[networkClientId] = setTimeout(() => __awaiter(this, void 0, void 0, function* () {
164
+ __classPrivateFieldGet(this, _PollingControllerBase_intervalIds, "f")[key] = setTimeout(() => __awaiter(this, void 0, void 0, function* () {
148
165
  try {
149
- yield this.executePoll(networkClientId);
166
+ yield this._executePoll(networkClientId, options);
150
167
  }
151
168
  catch (error) {
152
169
  console.error(error);
153
170
  }
154
- __classPrivateFieldGet(this, _PollingControllerBase_instances, "m", _PollingControllerBase_poll).call(this, networkClientId);
155
- }), __classPrivateFieldGet(this, _PollingControllerBase_intervalLength, "f"));
171
+ __classPrivateFieldGet(this, _PollingControllerBase_instances, "m", _PollingControllerBase_poll).call(this, networkClientId, options);
172
+ }), interval ? __classPrivateFieldGet(this, _PollingControllerBase_intervalLength, "f") : 0);
156
173
  };
157
174
  return PollingControllerBase;
158
175
  }
176
+ class Empty {
177
+ }
178
+ exports.PollingControllerOnly = PollingControllerMixin(Empty);
159
179
  exports.PollingController = PollingControllerMixin(base_controller_1.BaseControllerV2);
160
180
  exports.PollingControllerV1 = PollingControllerMixin(base_controller_1.BaseController);
161
181
  //# sourceMappingURL=PollingController.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PollingController.js","sourceRoot":"","sources":["../src/PollingController.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseController, BaseControllerV2 } from '@metamask/base-controller';\nimport type { NetworkClientId } from '@metamask/network-controller';\nimport { v4 as random } from 'uuid';\n\n// Mixin classes require a constructor with an `...any[]` parameter\n// See TS2545\ntype Constructor = new (...args: any[]) => object;\n\n/**\n * PollingControllerMixin\n *\n * @param Base - The base class to mix onto.\n * @returns The composed class.\n */\nfunction PollingControllerMixin<TBase extends Constructor>(Base: TBase) {\n /**\n * PollingController is an abstract class that implements the polling\n * functionality for a controller. It is meant to be extended by a controller\n * that needs to poll for data by networkClientId.\n *\n */\n abstract class PollingControllerBase extends Base {\n readonly #networkClientIdTokensMap: Map<NetworkClientId, Set<string>> =\n new Map();\n\n readonly #intervalIds: Record<NetworkClientId, NodeJS.Timeout> = {};\n\n #callbacks: Map<\n NetworkClientId,\n Set<(networkClientId: NetworkClientId) => void>\n > = new Map();\n\n #intervalLength = 1000;\n\n getIntervalLength() {\n return this.#intervalLength;\n }\n\n /**\n * Sets the length of the polling interval\n *\n * @param length - The length of the polling interval in milliseconds\n */\n setIntervalLength(length: number) {\n this.#intervalLength = length;\n }\n\n /**\n * Starts polling for a networkClientId\n *\n * @param networkClientId - The networkClientId to start polling for\n * @returns void\n */\n startPollingByNetworkClientId(networkClientId: NetworkClientId) {\n const innerPollToken = random();\n if (this.#networkClientIdTokensMap.has(networkClientId)) {\n const set = this.#networkClientIdTokensMap.get(networkClientId);\n set?.add(innerPollToken);\n } else {\n const set = new Set<string>();\n set.add(innerPollToken);\n this.#networkClientIdTokensMap.set(networkClientId, set);\n }\n this.#poll(networkClientId);\n return innerPollToken;\n }\n\n /**\n * Stops polling for all networkClientIds\n */\n stopAllPolling() {\n this.#networkClientIdTokensMap.forEach((tokens, _networkClientId) => {\n tokens.forEach((token) => {\n this.stopPollingByNetworkClientId(token);\n });\n });\n }\n\n /**\n * Stops polling for a networkClientId\n *\n * @param pollingToken - The polling token to stop polling for\n */\n stopPollingByNetworkClientId(pollingToken: string) {\n if (!pollingToken) {\n throw new Error('pollingToken required');\n }\n let found = false;\n this.#networkClientIdTokensMap.forEach((tokens, networkClientId) => {\n if (tokens.has(pollingToken)) {\n found = true;\n this.#networkClientIdTokensMap\n .get(networkClientId)\n ?.delete(pollingToken);\n if (this.#networkClientIdTokensMap.get(networkClientId)?.size === 0) {\n clearTimeout(this.#intervalIds[networkClientId]);\n delete this.#intervalIds[networkClientId];\n this.#networkClientIdTokensMap.delete(networkClientId);\n this.#callbacks.get(networkClientId)?.forEach((callback) => {\n callback(networkClientId);\n });\n this.#callbacks.get(networkClientId)?.clear();\n }\n }\n });\n if (!found) {\n throw new Error('pollingToken not found');\n }\n }\n\n /**\n * Executes the poll for a networkClientId\n *\n * @param networkClientId - The networkClientId to execute the poll for\n */\n abstract executePoll(networkClientId: NetworkClientId): Promise<void>;\n\n #poll(networkClientId: NetworkClientId) {\n if (this.#intervalIds[networkClientId]) {\n clearTimeout(this.#intervalIds[networkClientId]);\n delete this.#intervalIds[networkClientId];\n }\n // setTimeout is not `await`ing this async function, which is expected\n // We're just using async here for improved stack traces\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n this.#intervalIds[networkClientId] = setTimeout(async () => {\n try {\n await this.executePoll(networkClientId);\n } catch (error) {\n console.error(error);\n }\n this.#poll(networkClientId);\n }, this.#intervalLength);\n }\n\n /**\n * Adds a callback to execute when polling is complete\n *\n * @param networkClientId - The networkClientId to listen for polling complete events\n * @param callback - The callback to execute when polling is complete\n */\n onPollingCompleteByNetworkClientId(\n networkClientId: NetworkClientId,\n callback: (networkClientId: NetworkClientId) => void,\n ) {\n if (this.#callbacks.has(networkClientId)) {\n this.#callbacks.get(networkClientId)?.add(callback);\n } else {\n const set = new Set<typeof callback>();\n set.add(callback);\n this.#callbacks.set(networkClientId, set);\n }\n }\n }\n return PollingControllerBase;\n}\n\nexport const PollingController = PollingControllerMixin(BaseControllerV2);\nexport const PollingControllerV1 = PollingControllerMixin(BaseController);\n"]}
1
+ {"version":3,"file":"PollingController.js","sourceRoot":"","sources":["../src/PollingController.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseController, BaseControllerV2 } from '@metamask/base-controller';\nimport type { NetworkClientId } from '@metamask/network-controller';\nimport type { Json } from '@metamask/utils';\nimport stringify from 'fast-json-stable-stringify';\nimport { v4 as random } from 'uuid';\n\n// Mixin classes require a constructor with an `...any[]` parameter\n// See TS2545\ntype Constructor = new (...args: any[]) => object;\n\n/**\n * Returns a unique key for a networkClientId and options. This is used to group networkClientId polls with the same options\n * @param networkClientId - The networkClientId to get a key for\n * @param options - The options used to group the polling events\n * @returns The unique key\n */\nexport const getKey = (\n networkClientId: NetworkClientId,\n options: Json,\n): PollingTokenSetId => `${networkClientId}:${stringify(options)}`;\n\ntype PollingTokenSetId = `${NetworkClientId}:${string}`;\n/**\n * PollingControllerMixin\n *\n * @param Base - The base class to mix onto.\n * @returns The composed class.\n */\nfunction PollingControllerMixin<TBase extends Constructor>(Base: TBase) {\n /**\n * PollingController is an abstract class that implements the polling\n * functionality for a controller. It is meant to be extended by a controller\n * that needs to poll for data by networkClientId.\n *\n */\n abstract class PollingControllerBase extends Base {\n readonly #pollingTokenSets: Map<PollingTokenSetId, Set<string>> = new Map();\n\n readonly #intervalIds: Record<PollingTokenSetId, NodeJS.Timeout> = {};\n\n #callbacks: Map<\n NetworkClientId,\n Set<(networkClientId: NetworkClientId) => void>\n > = new Map();\n\n #intervalLength = 1000;\n\n getIntervalLength() {\n return this.#intervalLength;\n }\n\n /**\n * Sets the length of the polling interval\n *\n * @param length - The length of the polling interval in milliseconds\n */\n setIntervalLength(length: number) {\n this.#intervalLength = length;\n }\n\n /**\n * Starts polling for a networkClientId\n *\n * @param networkClientId - The networkClientId to start polling for\n * @param options - The options used to group the polling events\n * @returns void\n */\n startPollingByNetworkClientId(\n networkClientId: NetworkClientId,\n options: Json = {},\n ) {\n const pollToken = random();\n\n const key = getKey(networkClientId, options);\n\n const pollingTokenSet = this.#pollingTokenSets.get(key);\n if (pollingTokenSet) {\n pollingTokenSet.add(pollToken);\n } else {\n const set = new Set<string>();\n set.add(pollToken);\n this.#pollingTokenSets.set(key, set);\n }\n this.#poll(networkClientId, options);\n return pollToken;\n }\n\n /**\n * Stops polling for all networkClientIds\n */\n stopAllPolling() {\n this.#pollingTokenSets.forEach((tokenSet, _networkClientId) => {\n tokenSet.forEach((token) => {\n this.stopPollingByPollingToken(token);\n });\n });\n }\n\n /**\n * Stops polling for a networkClientId\n *\n * @param pollingToken - The polling token to stop polling for\n */\n stopPollingByPollingToken(pollingToken: string) {\n if (!pollingToken) {\n throw new Error('pollingToken required');\n }\n let found = false;\n this.#pollingTokenSets.forEach((tokenSet, key) => {\n if (tokenSet.has(pollingToken)) {\n found = true;\n tokenSet.delete(pollingToken);\n if (tokenSet.size === 0) {\n clearTimeout(this.#intervalIds[key]);\n delete this.#intervalIds[key];\n this.#pollingTokenSets.delete(key);\n this.#callbacks.get(key)?.forEach((callback) => {\n callback(key);\n });\n this.#callbacks.get(key)?.clear();\n }\n }\n });\n if (!found) {\n throw new Error('pollingToken not found');\n }\n }\n\n /**\n * Executes the poll for a networkClientId\n *\n * @param networkClientId - The networkClientId to execute the poll for\n * @param options - The options passed to startPollingByNetworkClientId\n */\n abstract _executePoll(\n networkClientId: NetworkClientId,\n options: Json,\n ): Promise<void>;\n\n #poll(networkClientId: NetworkClientId, options: Json) {\n const key = getKey(networkClientId, options);\n const interval = this.#intervalIds[key];\n if (interval) {\n clearTimeout(interval);\n delete this.#intervalIds[key];\n }\n // setTimeout is not `await`ing this async function, which is expected\n // We're just using async here for improved stack traces\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n this.#intervalIds[key] = setTimeout(\n async () => {\n try {\n await this._executePoll(networkClientId, options);\n } catch (error) {\n console.error(error);\n }\n this.#poll(networkClientId, options);\n },\n interval ? this.#intervalLength : 0,\n );\n }\n\n /**\n * Adds a callback to execute when polling is complete\n *\n * @param networkClientId - The networkClientId to listen for polling complete events\n * @param callback - The callback to execute when polling is complete\n * @param options - The options used to group the polling events\n */\n onPollingCompleteByNetworkClientId(\n networkClientId: NetworkClientId,\n callback: (networkClientId: NetworkClientId) => void,\n options: Json = {},\n ) {\n const key = getKey(networkClientId, options);\n const callbacks = this.#callbacks.get(key);\n\n if (callbacks === undefined) {\n const set = new Set<typeof callback>();\n set.add(callback);\n this.#callbacks.set(key, set);\n } else {\n callbacks.add(callback);\n }\n }\n }\n return PollingControllerBase;\n}\n\nclass Empty {}\n\nexport const PollingControllerOnly = PollingControllerMixin(Empty);\nexport const PollingController = PollingControllerMixin(BaseControllerV2);\nexport const PollingControllerV1 = PollingControllerMixin(BaseController);\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask/polling-controller",
3
- "version": "0.1.0",
3
+ "version": "1.0.0",
4
4
  "description": "Polling Controller is the base for controllers that polling by networkClientId",
5
5
  "keywords": [
6
6
  "MetaMask",
@@ -31,13 +31,14 @@
31
31
  "dependencies": {
32
32
  "@metamask/base-controller": "^3.2.3",
33
33
  "@metamask/controller-utils": "^5.0.2",
34
- "@metamask/network-controller": "^14.0.0",
34
+ "@metamask/network-controller": "^15.1.0",
35
35
  "@metamask/utils": "^8.1.0",
36
36
  "@types/uuid": "^8.3.0",
37
+ "fast-json-stable-stringify": "^2.1.0",
37
38
  "uuid": "^8.3.2"
38
39
  },
39
40
  "devDependencies": {
40
- "@metamask/auto-changelog": "^3.1.0",
41
+ "@metamask/auto-changelog": "^3.4.2",
41
42
  "@types/jest": "^27.4.1",
42
43
  "deepmerge": "^4.2.2",
43
44
  "jest": "^27.5.1",
@@ -47,7 +48,7 @@
47
48
  "typescript": "~4.8.4"
48
49
  },
49
50
  "peerDependencies": {
50
- "@metamask/network-controller": "^14.0.0"
51
+ "@metamask/network-controller": "^15.1.0"
51
52
  },
52
53
  "engines": {
53
54
  "node": ">=16.0.0"