@metamask-previews/shield-controller 0.3.2-preview-332b0b7a → 0.3.2-preview-8504447
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 +0 -6
- package/dist/ShieldController.cjs +7 -35
- package/dist/ShieldController.cjs.map +1 -1
- package/dist/ShieldController.d.cts.map +1 -1
- package/dist/ShieldController.d.mts.map +1 -1
- package/dist/ShieldController.mjs +8 -36
- package/dist/ShieldController.mjs.map +1 -1
- package/dist/backend.cjs +41 -34
- package/dist/backend.cjs.map +1 -1
- package/dist/backend.d.cts.map +1 -1
- package/dist/backend.d.mts.map +1 -1
- package/dist/backend.mjs +41 -34
- package/dist/backend.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/polling-with-timeout-abort.cjs +0 -152
- package/dist/polling-with-timeout-abort.cjs.map +0 -1
- package/dist/polling-with-timeout-abort.d.cts +0 -41
- package/dist/polling-with-timeout-abort.d.cts.map +0 -1
- package/dist/polling-with-timeout-abort.d.mts +0 -41
- package/dist/polling-with-timeout-abort.d.mts.map +0 -1
- package/dist/polling-with-timeout-abort.mjs +0 -148
- package/dist/polling-with-timeout-abort.mjs.map +0 -1
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
2
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
3
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
4
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
5
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
6
|
-
};
|
|
7
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
8
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
9
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
|
-
};
|
|
12
|
-
var _PollingWithTimeoutAndAbort_instances, _PollingWithTimeoutAndAbort_requestEntries, _PollingWithTimeoutAndAbort_timeout, _PollingWithTimeoutAndAbort_pollInterval, _PollingWithTimeoutAndAbort_insertRequestEntry, _PollingWithTimeoutAndAbort_cleanUpOnFinished, _PollingWithTimeoutAndAbort_cleanUpRequestEntryIfExists, _PollingWithTimeoutAndAbort_delayWithAbortSignal;
|
|
13
|
-
export class PollingWithTimeoutAndAbort {
|
|
14
|
-
constructor(config) {
|
|
15
|
-
_PollingWithTimeoutAndAbort_instances.add(this);
|
|
16
|
-
this.ABORT_REASON_TIMEOUT = 'Request timed out';
|
|
17
|
-
this.ABORT_REASON_CANCELLED = 'Request cancelled';
|
|
18
|
-
// Map of request ID to request entry
|
|
19
|
-
_PollingWithTimeoutAndAbort_requestEntries.set(this, new Map());
|
|
20
|
-
_PollingWithTimeoutAndAbort_timeout.set(this, void 0);
|
|
21
|
-
_PollingWithTimeoutAndAbort_pollInterval.set(this, void 0);
|
|
22
|
-
__classPrivateFieldSet(this, _PollingWithTimeoutAndAbort_timeout, config.timeout, "f");
|
|
23
|
-
__classPrivateFieldSet(this, _PollingWithTimeoutAndAbort_pollInterval, config.pollInterval, "f");
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Poll a request with a timeout and abort.
|
|
27
|
-
* This will poll the request until it succeeds or fails due to the timeout or the abort signal being triggered.
|
|
28
|
-
*
|
|
29
|
-
* @param requestId - The ID of the request to poll.
|
|
30
|
-
* @param requestFn - The function to poll the request.
|
|
31
|
-
* @param pollingOptions - The options for the polling.
|
|
32
|
-
* @param pollingOptions.timeout - The timeout for the request. Defaults to the constructor's timeout.
|
|
33
|
-
* @param pollingOptions.pollInterval - The interval for the polling. Defaults to the constructor's pollInterval.
|
|
34
|
-
* @param pollingOptions.fnName - The name of the function to poll the request. Defaults to an empty string.
|
|
35
|
-
* @returns The result of the request.
|
|
36
|
-
*/
|
|
37
|
-
async pollRequest(requestId, requestFn, pollingOptions = {}) {
|
|
38
|
-
const timeout = pollingOptions.timeout ?? __classPrivateFieldGet(this, _PollingWithTimeoutAndAbort_timeout, "f");
|
|
39
|
-
const pollInterval = pollingOptions.pollInterval ?? __classPrivateFieldGet(this, _PollingWithTimeoutAndAbort_pollInterval, "f");
|
|
40
|
-
// clean up the request entry if it exists
|
|
41
|
-
this.abortPendingRequest(requestId);
|
|
42
|
-
// insert the request entry for the next polling cycle
|
|
43
|
-
const { abortController } = __classPrivateFieldGet(this, _PollingWithTimeoutAndAbort_instances, "m", _PollingWithTimeoutAndAbort_insertRequestEntry).call(this, requestId, timeout);
|
|
44
|
-
while (!abortController.signal.aborted) {
|
|
45
|
-
try {
|
|
46
|
-
const result = await requestFn(abortController.signal);
|
|
47
|
-
// polling success, we just need to clean up the request entry and return the result
|
|
48
|
-
__classPrivateFieldGet(this, _PollingWithTimeoutAndAbort_instances, "m", _PollingWithTimeoutAndAbort_cleanUpOnFinished).call(this, requestId);
|
|
49
|
-
return result;
|
|
50
|
-
}
|
|
51
|
-
catch {
|
|
52
|
-
if (abortController.signal.aborted) {
|
|
53
|
-
// request failed due to the abort signal being triggered,
|
|
54
|
-
// then we will break out of the polling loop
|
|
55
|
-
break;
|
|
56
|
-
}
|
|
57
|
-
// otherwise, we will wait for the next polling cycle
|
|
58
|
-
// and continue the polling loop
|
|
59
|
-
await __classPrivateFieldGet(this, _PollingWithTimeoutAndAbort_instances, "m", _PollingWithTimeoutAndAbort_delayWithAbortSignal).call(this, pollInterval, abortController.signal);
|
|
60
|
-
continue;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
// At this point, the polling loop has exited and abortController is aborted
|
|
64
|
-
const abortReason = abortController.signal.reason;
|
|
65
|
-
const errorMessage = pollingOptions.fnName
|
|
66
|
-
? `${pollingOptions.fnName}: ${abortReason}`
|
|
67
|
-
: abortReason;
|
|
68
|
-
throw new Error(errorMessage);
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Abort the pending requests.
|
|
72
|
-
* This will clean up the request entry if it exists, and abort the pending request if it exists.
|
|
73
|
-
*
|
|
74
|
-
* @param requestId - The ID of the request to abort.
|
|
75
|
-
*/
|
|
76
|
-
abortPendingRequest(requestId) {
|
|
77
|
-
// firstly clean up the request entry if it exists
|
|
78
|
-
// note: this does not abort the request, it only cleans up the request entry for the next polling cycle
|
|
79
|
-
const existingEntry = __classPrivateFieldGet(this, _PollingWithTimeoutAndAbort_instances, "m", _PollingWithTimeoutAndAbort_cleanUpRequestEntryIfExists).call(this, requestId);
|
|
80
|
-
// then abort the request if it exists
|
|
81
|
-
// note: this does abort the request, but it will not trigger the abort handler (hence, {@link cleanUpRequestEntryIfExists} will not be called)
|
|
82
|
-
// coz the AbortHandler event listener is already removed from the AbortSignal
|
|
83
|
-
existingEntry?.abortController.abort(this.ABORT_REASON_CANCELLED);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
_PollingWithTimeoutAndAbort_requestEntries = new WeakMap(), _PollingWithTimeoutAndAbort_timeout = new WeakMap(), _PollingWithTimeoutAndAbort_pollInterval = new WeakMap(), _PollingWithTimeoutAndAbort_instances = new WeakSet(), _PollingWithTimeoutAndAbort_insertRequestEntry = function _PollingWithTimeoutAndAbort_insertRequestEntry(requestId, timeout) {
|
|
87
|
-
const abortController = new AbortController();
|
|
88
|
-
// Set a timeout to abort the request if it takes too long
|
|
89
|
-
const timerId = setTimeout(() => {
|
|
90
|
-
abortController.abort(this.ABORT_REASON_TIMEOUT);
|
|
91
|
-
}, timeout);
|
|
92
|
-
// Set the abort handler and listen to the `abort` event
|
|
93
|
-
const abortHandler = () => {
|
|
94
|
-
__classPrivateFieldGet(this, _PollingWithTimeoutAndAbort_instances, "m", _PollingWithTimeoutAndAbort_cleanUpOnFinished).call(this, requestId);
|
|
95
|
-
};
|
|
96
|
-
abortController.signal.addEventListener('abort', abortHandler);
|
|
97
|
-
const requestEntry = {
|
|
98
|
-
abortController,
|
|
99
|
-
abortHandler,
|
|
100
|
-
timerId,
|
|
101
|
-
};
|
|
102
|
-
// Insert the request entry
|
|
103
|
-
__classPrivateFieldGet(this, _PollingWithTimeoutAndAbort_requestEntries, "f").set(requestId, requestEntry);
|
|
104
|
-
return requestEntry;
|
|
105
|
-
}, _PollingWithTimeoutAndAbort_cleanUpOnFinished = function _PollingWithTimeoutAndAbort_cleanUpOnFinished(requestId) {
|
|
106
|
-
const requestEntry = __classPrivateFieldGet(this, _PollingWithTimeoutAndAbort_instances, "m", _PollingWithTimeoutAndAbort_cleanUpRequestEntryIfExists).call(this, requestId);
|
|
107
|
-
if (requestEntry) {
|
|
108
|
-
requestEntry.abortController.signal.removeEventListener('abort', requestEntry.abortHandler);
|
|
109
|
-
}
|
|
110
|
-
return requestEntry;
|
|
111
|
-
}, _PollingWithTimeoutAndAbort_cleanUpRequestEntryIfExists = function _PollingWithTimeoutAndAbort_cleanUpRequestEntryIfExists(requestId) {
|
|
112
|
-
const requestEntry = __classPrivateFieldGet(this, _PollingWithTimeoutAndAbort_requestEntries, "f").get(requestId);
|
|
113
|
-
if (requestEntry) {
|
|
114
|
-
clearTimeout(requestEntry.timerId); // Clear the timeout
|
|
115
|
-
__classPrivateFieldGet(this, _PollingWithTimeoutAndAbort_requestEntries, "f").delete(requestId); // Remove the request entry
|
|
116
|
-
}
|
|
117
|
-
return requestEntry;
|
|
118
|
-
}, _PollingWithTimeoutAndAbort_delayWithAbortSignal =
|
|
119
|
-
/**
|
|
120
|
-
* Delay with an abort signal.
|
|
121
|
-
* This will delay the execution of the code until the abort signal is triggered.
|
|
122
|
-
*
|
|
123
|
-
* @param ms - The number of milliseconds to delay.
|
|
124
|
-
* @param abortSignal - The abort signal to listen to.
|
|
125
|
-
* @returns A promise that resolves when the delay is complete.
|
|
126
|
-
*/
|
|
127
|
-
async function _PollingWithTimeoutAndAbort_delayWithAbortSignal(ms, abortSignal) {
|
|
128
|
-
return new Promise((resolve) => {
|
|
129
|
-
let timer = null;
|
|
130
|
-
const abortHandlerForDelay = () => {
|
|
131
|
-
// clear the timeout and resolve the promise
|
|
132
|
-
// Note: we don't reject the promise as this is only a dummy delay
|
|
133
|
-
if (timer) {
|
|
134
|
-
clearTimeout(timer);
|
|
135
|
-
}
|
|
136
|
-
resolve(undefined);
|
|
137
|
-
};
|
|
138
|
-
timer = setTimeout(() => {
|
|
139
|
-
abortSignal.removeEventListener('abort', abortHandlerForDelay);
|
|
140
|
-
resolve(undefined);
|
|
141
|
-
}, ms);
|
|
142
|
-
// set the abort handler to clear the timeout and resolve the promise
|
|
143
|
-
abortSignal.addEventListener('abort', abortHandlerForDelay, {
|
|
144
|
-
once: true, // only listen to the abort event once
|
|
145
|
-
});
|
|
146
|
-
});
|
|
147
|
-
};
|
|
148
|
-
//# sourceMappingURL=polling-with-timeout-abort.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"polling-with-timeout-abort.mjs","sourceRoot":"","sources":["../src/polling-with-timeout-abort.ts"],"names":[],"mappings":"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","sourcesContent":["export type RequestEntry = {\n abortController: AbortController; // The abort controller for the request\n abortHandler: (ev: Event) => void; // The abort handler for the request\n timerId: NodeJS.Timeout; // The timer ID for the request timeout\n};\n\nexport type RequestFn<ReturnType> = (\n signal: AbortSignal,\n) => Promise<ReturnType>;\n\nexport class PollingWithTimeoutAndAbort {\n readonly ABORT_REASON_TIMEOUT = 'Request timed out';\n\n readonly ABORT_REASON_CANCELLED = 'Request cancelled';\n\n // Map of request ID to request entry\n readonly #requestEntries: Map<string, RequestEntry> = new Map();\n\n readonly #timeout: number;\n\n readonly #pollInterval: number;\n\n constructor(config: { timeout: number; pollInterval: number }) {\n this.#timeout = config.timeout;\n this.#pollInterval = config.pollInterval;\n }\n\n /**\n * Poll a request with a timeout and abort.\n * This will poll the request until it succeeds or fails due to the timeout or the abort signal being triggered.\n *\n * @param requestId - The ID of the request to poll.\n * @param requestFn - The function to poll the request.\n * @param pollingOptions - The options for the polling.\n * @param pollingOptions.timeout - The timeout for the request. Defaults to the constructor's timeout.\n * @param pollingOptions.pollInterval - The interval for the polling. Defaults to the constructor's pollInterval.\n * @param pollingOptions.fnName - The name of the function to poll the request. Defaults to an empty string.\n * @returns The result of the request.\n */\n async pollRequest<ReturnType>(\n requestId: string,\n requestFn: RequestFn<ReturnType>,\n pollingOptions: {\n timeout?: number;\n pollInterval?: number;\n fnName?: string;\n } = {},\n ) {\n const timeout = pollingOptions.timeout ?? this.#timeout;\n const pollInterval = pollingOptions.pollInterval ?? this.#pollInterval;\n\n // clean up the request entry if it exists\n this.abortPendingRequest(requestId);\n\n // insert the request entry for the next polling cycle\n const { abortController } = this.#insertRequestEntry(requestId, timeout);\n\n while (!abortController.signal.aborted) {\n try {\n const result = await requestFn(abortController.signal);\n // polling success, we just need to clean up the request entry and return the result\n this.#cleanUpOnFinished(requestId);\n return result;\n } catch {\n if (abortController.signal.aborted) {\n // request failed due to the abort signal being triggered,\n // then we will break out of the polling loop\n break;\n }\n // otherwise, we will wait for the next polling cycle\n // and continue the polling loop\n await this.#delayWithAbortSignal(pollInterval, abortController.signal);\n continue;\n }\n }\n // At this point, the polling loop has exited and abortController is aborted\n const abortReason = abortController.signal.reason;\n const errorMessage = pollingOptions.fnName\n ? `${pollingOptions.fnName}: ${abortReason}`\n : abortReason;\n throw new Error(errorMessage);\n }\n\n /**\n * Abort the pending requests.\n * This will clean up the request entry if it exists, and abort the pending request if it exists.\n *\n * @param requestId - The ID of the request to abort.\n */\n abortPendingRequest(requestId: string) {\n // firstly clean up the request entry if it exists\n // note: this does not abort the request, it only cleans up the request entry for the next polling cycle\n const existingEntry = this.#cleanUpRequestEntryIfExists(requestId);\n // then abort the request if it exists\n // note: this does abort the request, but it will not trigger the abort handler (hence, {@link cleanUpRequestEntryIfExists} will not be called)\n // coz the AbortHandler event listener is already removed from the AbortSignal\n existingEntry?.abortController.abort(this.ABORT_REASON_CANCELLED);\n }\n\n /**\n * Insert a new request entry.\n * This will create a new abort controller, set a timeout to abort the request if it takes too long, and set the abort handler.\n *\n * @param requestId - The ID of the request to insert the entry for.\n * @param timeout - The timeout for the request.\n * @returns The request entry that was inserted.\n */\n #insertRequestEntry(requestId: string, timeout: number) {\n const abortController = new AbortController();\n\n // Set a timeout to abort the request if it takes too long\n const timerId = setTimeout(() => {\n abortController.abort(this.ABORT_REASON_TIMEOUT);\n }, timeout);\n\n // Set the abort handler and listen to the `abort` event\n const abortHandler = () => {\n this.#cleanUpOnFinished(requestId);\n };\n abortController.signal.addEventListener('abort', abortHandler);\n\n const requestEntry: RequestEntry = {\n abortController,\n abortHandler,\n timerId,\n };\n\n // Insert the request entry\n this.#requestEntries.set(requestId, requestEntry);\n\n return requestEntry;\n }\n\n /**\n * Clean up the request entry upon finished (success or failure).\n * This will remove the abort handler from the AbortSignal, clear the timeout, and remove the request entry.\n *\n * @param requestId - The ID of the request to clean up for.\n * @returns The request entry that was cleaned up, if it exists.\n */\n #cleanUpOnFinished(requestId: string): RequestEntry | undefined {\n const requestEntry = this.#cleanUpRequestEntryIfExists(requestId);\n if (requestEntry) {\n requestEntry.abortController.signal.removeEventListener(\n 'abort',\n requestEntry.abortHandler,\n );\n }\n return requestEntry;\n }\n\n /**\n * Clean up the request entry if it exists.\n * This will clear the pending timeout, remove the event listener from the AbortSignal, and remove the request entry.\n *\n * @param requestId - The ID of the request to handle the abort for.\n * @returns The request entry that was aborted, if it exists.\n */\n #cleanUpRequestEntryIfExists(requestId: string): RequestEntry | undefined {\n const requestEntry = this.#requestEntries.get(requestId);\n if (requestEntry) {\n clearTimeout(requestEntry.timerId); // Clear the timeout\n this.#requestEntries.delete(requestId); // Remove the request entry\n }\n return requestEntry;\n }\n\n /**\n * Delay with an abort signal.\n * This will delay the execution of the code until the abort signal is triggered.\n *\n * @param ms - The number of milliseconds to delay.\n * @param abortSignal - The abort signal to listen to.\n * @returns A promise that resolves when the delay is complete.\n */\n async #delayWithAbortSignal(ms: number, abortSignal: AbortSignal) {\n return new Promise((resolve) => {\n let timer: NodeJS.Timeout | null = null;\n\n const abortHandlerForDelay = () => {\n // clear the timeout and resolve the promise\n // Note: we don't reject the promise as this is only a dummy delay\n if (timer) {\n clearTimeout(timer);\n }\n resolve(undefined);\n };\n\n timer = setTimeout(() => {\n abortSignal.removeEventListener('abort', abortHandlerForDelay);\n resolve(undefined);\n }, ms);\n\n // set the abort handler to clear the timeout and resolve the promise\n abortSignal.addEventListener('abort', abortHandlerForDelay, {\n once: true, // only listen to the abort event once\n });\n });\n }\n}\n"]}
|