@fluidframework/core-utils 2.0.0-dev-rc.1.0.0.224419

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.
Files changed (111) hide show
  1. package/.eslintrc.js +36 -0
  2. package/.mocharc.js +13 -0
  3. package/CHANGELOG.md +81 -0
  4. package/LICENSE +21 -0
  5. package/README.md +75 -0
  6. package/api-extractor-lint.json +4 -0
  7. package/api-extractor.json +4 -0
  8. package/api-report/core-utils.api.md +147 -0
  9. package/dist/assert.d.ts +17 -0
  10. package/dist/assert.d.ts.map +1 -0
  11. package/dist/assert.js +25 -0
  12. package/dist/assert.js.map +1 -0
  13. package/dist/compare.d.ts +16 -0
  14. package/dist/compare.d.ts.map +1 -0
  15. package/dist/compare.js +28 -0
  16. package/dist/compare.js.map +1 -0
  17. package/dist/core-utils-alpha.d.ts +191 -0
  18. package/dist/core-utils-beta.d.ts +41 -0
  19. package/dist/core-utils-public.d.ts +41 -0
  20. package/dist/core-utils-untrimmed.d.ts +414 -0
  21. package/dist/delay.d.ts +11 -0
  22. package/dist/delay.d.ts.map +1 -0
  23. package/dist/delay.js +15 -0
  24. package/dist/delay.js.map +1 -0
  25. package/dist/heap.d.ts +86 -0
  26. package/dist/heap.d.ts.map +1 -0
  27. package/dist/heap.js +144 -0
  28. package/dist/heap.js.map +1 -0
  29. package/dist/index.d.ts +14 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +30 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/lazy.d.ts +44 -0
  34. package/dist/lazy.d.ts.map +1 -0
  35. package/dist/lazy.js +84 -0
  36. package/dist/lazy.js.map +1 -0
  37. package/dist/promiseCache.d.ts +89 -0
  38. package/dist/promiseCache.d.ts.map +1 -0
  39. package/dist/promiseCache.js +148 -0
  40. package/dist/promiseCache.js.map +1 -0
  41. package/dist/promises.d.ts +38 -0
  42. package/dist/promises.d.ts.map +1 -0
  43. package/dist/promises.js +60 -0
  44. package/dist/promises.js.map +1 -0
  45. package/dist/timer.d.ts +115 -0
  46. package/dist/timer.d.ts.map +1 -0
  47. package/dist/timer.js +189 -0
  48. package/dist/timer.js.map +1 -0
  49. package/dist/tsdoc-metadata.json +11 -0
  50. package/dist/unreachable.d.ts +22 -0
  51. package/dist/unreachable.d.ts.map +1 -0
  52. package/dist/unreachable.js +28 -0
  53. package/dist/unreachable.js.map +1 -0
  54. package/lib/assert.d.ts +17 -0
  55. package/lib/assert.d.ts.map +1 -0
  56. package/lib/assert.js +25 -0
  57. package/lib/assert.js.map +1 -0
  58. package/lib/compare.d.ts +16 -0
  59. package/lib/compare.d.ts.map +1 -0
  60. package/lib/compare.js +28 -0
  61. package/lib/compare.js.map +1 -0
  62. package/lib/core-utils-alpha.d.ts +191 -0
  63. package/lib/core-utils-beta.d.ts +41 -0
  64. package/lib/core-utils-public.d.ts +41 -0
  65. package/lib/core-utils-untrimmed.d.ts +414 -0
  66. package/lib/delay.d.ts +11 -0
  67. package/lib/delay.d.ts.map +1 -0
  68. package/lib/delay.js +15 -0
  69. package/lib/delay.js.map +1 -0
  70. package/lib/heap.d.ts +86 -0
  71. package/lib/heap.d.ts.map +1 -0
  72. package/lib/heap.js +144 -0
  73. package/lib/heap.js.map +1 -0
  74. package/lib/index.d.ts +14 -0
  75. package/lib/index.d.ts.map +1 -0
  76. package/lib/index.js +30 -0
  77. package/lib/index.js.map +1 -0
  78. package/lib/lazy.d.ts +44 -0
  79. package/lib/lazy.d.ts.map +1 -0
  80. package/lib/lazy.js +84 -0
  81. package/lib/lazy.js.map +1 -0
  82. package/lib/promiseCache.d.ts +89 -0
  83. package/lib/promiseCache.d.ts.map +1 -0
  84. package/lib/promiseCache.js +148 -0
  85. package/lib/promiseCache.js.map +1 -0
  86. package/lib/promises.d.ts +38 -0
  87. package/lib/promises.d.ts.map +1 -0
  88. package/lib/promises.js +60 -0
  89. package/lib/promises.js.map +1 -0
  90. package/lib/timer.d.ts +115 -0
  91. package/lib/timer.d.ts.map +1 -0
  92. package/lib/timer.js +189 -0
  93. package/lib/timer.js.map +1 -0
  94. package/lib/unreachable.d.ts +22 -0
  95. package/lib/unreachable.d.ts.map +1 -0
  96. package/lib/unreachable.js +28 -0
  97. package/lib/unreachable.js.map +1 -0
  98. package/package.json +111 -0
  99. package/prettier.config.cjs +8 -0
  100. package/src/assert.ts +23 -0
  101. package/src/compare.ts +33 -0
  102. package/src/delay.ts +12 -0
  103. package/src/heap.ts +182 -0
  104. package/src/index.ts +21 -0
  105. package/src/lazy.ts +88 -0
  106. package/src/promiseCache.ts +205 -0
  107. package/src/promises.ts +63 -0
  108. package/src/timer.ts +289 -0
  109. package/src/unreachable.ts +24 -0
  110. package/tsconfig.esnext.json +6 -0
  111. package/tsconfig.json +12 -0
package/src/heap.ts ADDED
@@ -0,0 +1,182 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ /**
7
+ * Interface for a comparer.
8
+ * @internal
9
+ */
10
+ export interface IComparer<T> {
11
+ /**
12
+ * The minimum value of type T.
13
+ */
14
+ min: T;
15
+
16
+ /**
17
+ * Compare the two value
18
+ *
19
+ * @returns 0 if the value is equal, negative number if a is smaller then b, positive number otherwise
20
+ */
21
+ compare(a: T, b: T): number;
22
+ }
23
+
24
+ /**
25
+ * A comparer for numbers.
26
+ * @internal
27
+ */
28
+ export const NumberComparer: IComparer<number> = {
29
+ /**
30
+ * The compare function for numbers.
31
+ * @returns The difference of the two numbers.
32
+ */
33
+ compare: (a, b): number => a - b,
34
+
35
+ /**
36
+ * The minimum value of a JavaScript number, which is `Number.MIN_VALUE`.
37
+ */
38
+ min: Number.MIN_VALUE,
39
+ };
40
+
41
+ /**
42
+ * Interface to a node in {@link Heap}.
43
+ * @internal
44
+ */
45
+ export interface IHeapNode<T> {
46
+ value: T;
47
+ position: number;
48
+ }
49
+
50
+ /**
51
+ * Ordered {@link https://en.wikipedia.org/wiki/Heap_(data_structure) | Heap} data structure implementation.
52
+ * @internal
53
+ */
54
+ export class Heap<T> {
55
+ private L: IHeapNode<T>[];
56
+
57
+ /**
58
+ * Creates an instance of `Heap` with comparer.
59
+ * @param comp - A comparer that specify how elements are ordered.
60
+ */
61
+ constructor(public comp: IComparer<T>) {
62
+ this.L = [{ value: comp.min, position: 0 }];
63
+ }
64
+
65
+ /**
66
+ * Return the smallest element in the heap as determined by the order of the comparer
67
+ *
68
+ * @returns Heap node containing the smallest element
69
+ */
70
+ public peek(): IHeapNode<T> | undefined {
71
+ return this.L[1];
72
+ }
73
+
74
+ /**
75
+ * Get and remove the smallest element in the heap as determined by the order of the comparer
76
+ *
77
+ * @returns The smallest value in the heap
78
+ */
79
+ public get(): T | undefined {
80
+ if (this.L.length === 0) {
81
+ return undefined;
82
+ }
83
+
84
+ this.swap(1, this.count());
85
+ const x = this.L.pop();
86
+ this.fixdown(1);
87
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
88
+ return x!.value;
89
+ }
90
+
91
+ /**
92
+ * Add a value to the heap
93
+ *
94
+ * @param x - value to add
95
+ * @returns The heap node that contains the value
96
+ */
97
+ public add(x: T): IHeapNode<T> {
98
+ const node = { value: x, position: this.L.length };
99
+ this.L.push(node);
100
+ this.fixup(this.count());
101
+
102
+ return node;
103
+ }
104
+
105
+ /**
106
+ * Allows for the Heap to be updated after a node's value changes.
107
+ */
108
+ public update(node: IHeapNode<T>): void {
109
+ const k = node.position;
110
+ if (this.isGreaterThanParent(k)) {
111
+ this.fixup(k);
112
+ } else {
113
+ this.fixdown(k);
114
+ }
115
+ }
116
+
117
+ /**
118
+ * Removes the given node from the heap.
119
+ *
120
+ * @param node - The node to remove from the heap.
121
+ */
122
+ public remove(node: IHeapNode<T>): void {
123
+ // Move the node we want to remove to the end of the array
124
+ const position = node.position;
125
+ this.swap(node.position, this.L.length - 1);
126
+ this.L.splice(-1);
127
+
128
+ // Update the swapped node assuming we didn't remove the end of the list
129
+ if (position !== this.L.length) {
130
+ this.update(this.L[position]);
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Get the number of elements in the Heap.
136
+ *
137
+ * @returns The number of elements in the Heap.
138
+ */
139
+ public count(): number {
140
+ return this.L.length - 1;
141
+ }
142
+
143
+ private fixup(pos: number): void {
144
+ let k = pos;
145
+ while (this.isGreaterThanParent(k)) {
146
+ // eslint-disable-next-line no-bitwise
147
+ const parent = k >> 1;
148
+ this.swap(k, parent);
149
+ k = parent;
150
+ }
151
+ }
152
+
153
+ private isGreaterThanParent(k: number): boolean {
154
+ // eslint-disable-next-line no-bitwise
155
+ return k > 1 && this.comp.compare(this.L[k >> 1].value, this.L[k].value) > 0;
156
+ }
157
+
158
+ private fixdown(pos: number): void {
159
+ let k = pos;
160
+ // eslint-disable-next-line no-bitwise
161
+ while (k << 1 <= this.count()) {
162
+ // eslint-disable-next-line no-bitwise
163
+ let j = k << 1;
164
+ if (j < this.count() && this.comp.compare(this.L[j].value, this.L[j + 1].value) > 0) {
165
+ j++;
166
+ }
167
+ if (this.comp.compare(this.L[k].value, this.L[j].value) <= 0) {
168
+ break;
169
+ }
170
+ this.swap(k, j);
171
+ k = j;
172
+ }
173
+ }
174
+
175
+ private swap(k: number, j: number): void {
176
+ const tmp = this.L[k];
177
+ this.L[k] = this.L[j];
178
+ this.L[k].position = k;
179
+ this.L[j] = tmp;
180
+ this.L[j].position = j;
181
+ }
182
+ }
package/src/index.ts ADDED
@@ -0,0 +1,21 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ export { assert } from "./assert";
7
+ export { compareArrays } from "./compare";
8
+ export { delay } from "./delay";
9
+ export { Heap, IComparer, IHeapNode, NumberComparer } from "./heap";
10
+ export { Lazy, LazyPromise } from "./lazy";
11
+ export { PromiseCache, PromiseCacheExpiry, PromiseCacheOptions } from "./promiseCache";
12
+ export { Deferred } from "./promises";
13
+ export {
14
+ IPromiseTimer,
15
+ IPromiseTimerResult,
16
+ ITimer,
17
+ PromiseTimer,
18
+ setLongTimeout,
19
+ Timer,
20
+ } from "./timer";
21
+ export { unreachableCase } from "./unreachable";
package/src/lazy.ts ADDED
@@ -0,0 +1,88 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ /**
7
+ * Helper class for lazy initialized values. Ensures the value is only generated once, and remain immutable.
8
+ * @internal
9
+ */
10
+ export class Lazy<T> {
11
+ private _value: T | undefined;
12
+ private _evaluated: boolean = false;
13
+ /**
14
+ * Instantiates an instance of Lazy<T>.
15
+ * @param valueGenerator - The function that will generate the value when value is accessed the first time.
16
+ */
17
+ public constructor(private readonly valueGenerator: () => T) {}
18
+
19
+ /**
20
+ * Return true if the value as been generated, otherwise false.
21
+ */
22
+ public get evaluated(): boolean {
23
+ return this._evaluated;
24
+ }
25
+
26
+ /**
27
+ * Get the value. If this is the first call the value will be generated.
28
+ */
29
+ public get value(): T {
30
+ if (!this._evaluated) {
31
+ this._evaluated = true;
32
+ this._value = this.valueGenerator();
33
+ }
34
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
35
+ return this._value!;
36
+ }
37
+ }
38
+
39
+ /**
40
+ * A lazy evaluated promise. The execute function is delayed until
41
+ * the promise is used, e.g. await, then, catch ...
42
+ * The execute function is only called once.
43
+ * All calls are then proxied to the promise returned by the execute method.
44
+ * @alpha
45
+ */
46
+ export class LazyPromise<T> implements Promise<T> {
47
+ public get [Symbol.toStringTag](): string {
48
+ return this.getPromise()[Symbol.toStringTag];
49
+ }
50
+
51
+ private result: Promise<T> | undefined;
52
+
53
+ public constructor(private readonly execute: () => Promise<T>) {}
54
+
55
+ // eslint-disable-next-line unicorn/no-thenable
56
+ public async then<TResult1 = T, TResult2 = never>(
57
+ // eslint-disable-next-line @rushstack/no-new-null
58
+ onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null | undefined,
59
+ // TODO: Use `unknown` instead (API breaking)
60
+ // eslint-disable-next-line @rushstack/no-new-null, @typescript-eslint/no-explicit-any
61
+ onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined,
62
+ ): Promise<TResult1 | TResult2> {
63
+ // eslint-disable-next-line prefer-rest-params
64
+ return this.getPromise().then<TResult1, TResult2>(...arguments);
65
+ }
66
+
67
+ public async catch<TResult = never>(
68
+ // TODO: Use `unknown` instead (API breaking)
69
+ // eslint-disable-next-line @rushstack/no-new-null, @typescript-eslint/no-explicit-any
70
+ onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null | undefined,
71
+ ): Promise<T | TResult> {
72
+ // eslint-disable-next-line prefer-rest-params
73
+ return this.getPromise().catch<TResult>(...arguments);
74
+ }
75
+
76
+ // eslint-disable-next-line @rushstack/no-new-null
77
+ public async finally(onfinally?: (() => void) | null | undefined): Promise<T> {
78
+ // eslint-disable-next-line prefer-rest-params
79
+ return this.getPromise().finally(...arguments);
80
+ }
81
+
82
+ private async getPromise(): Promise<T> {
83
+ if (this.result === undefined) {
84
+ this.result = this.execute();
85
+ }
86
+ return this.result;
87
+ }
88
+ }
@@ -0,0 +1,205 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ /**
7
+ * Three supported expiry policies:
8
+ * - indefinite: entries don't expire and must be explicitly removed
9
+ * - absolute: entries expire after the given duration in MS, even if accessed multiple times in the mean time
10
+ * - sliding: entries expire after the given duration in MS of inactivity (i.e. get resets the clock)
11
+ * @alpha
12
+ */
13
+ export type PromiseCacheExpiry =
14
+ | {
15
+ policy: "indefinite";
16
+ }
17
+ | {
18
+ policy: "absolute" | "sliding";
19
+ durationMs: number;
20
+ };
21
+
22
+ /**
23
+ * Options for configuring the {@link PromiseCache}
24
+ * @alpha
25
+ */
26
+ export interface PromiseCacheOptions {
27
+ /**
28
+ * Common expiration policy for all items added to this cache
29
+ */
30
+ expiry?: PromiseCacheExpiry;
31
+ /**
32
+ * If the stored Promise is rejected with a particular error, should the given key be removed?
33
+ */
34
+ // TODO: Use `unknown` instead (API breaking)
35
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
36
+ removeOnError?: (error: any) => boolean;
37
+ }
38
+
39
+ /**
40
+ * Handles garbage collection of expiring cache entries.
41
+ * Not exported.
42
+ */
43
+ class GarbageCollector<TKey> {
44
+ private readonly gcTimeouts = new Map<TKey, ReturnType<typeof setTimeout>>();
45
+
46
+ public constructor(
47
+ private readonly expiry: PromiseCacheExpiry,
48
+ private readonly cleanup: (key: TKey) => void,
49
+ ) {}
50
+
51
+ /**
52
+ * Schedule GC for the given key, as applicable
53
+ */
54
+ public schedule(key: TKey): void {
55
+ if (this.expiry.policy !== "indefinite") {
56
+ this.gcTimeouts.set(
57
+ key,
58
+ setTimeout(() => {
59
+ this.cleanup(key);
60
+ this.cancel(key);
61
+ }, this.expiry.durationMs),
62
+ );
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Cancel any pending GC for the given key
68
+ */
69
+ public cancel(key: TKey): void {
70
+ const timeout = this.gcTimeouts.get(key);
71
+ if (timeout !== undefined) {
72
+ clearTimeout(timeout);
73
+ this.gcTimeouts.delete(key);
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Update any pending GC for the given key, as applicable
79
+ */
80
+ public update(key: TKey): void {
81
+ // Cancel/reschedule new GC if the policy is sliding
82
+ if (this.expiry.policy === "sliding") {
83
+ this.cancel(key);
84
+ this.schedule(key);
85
+ }
86
+ }
87
+ }
88
+
89
+ /**
90
+ * A specialized cache for async work, allowing you to safely cache the promised result of some async work
91
+ * without fear of running it multiple times or losing track of errors.
92
+ * @alpha
93
+ */
94
+ export class PromiseCache<TKey, TResult> {
95
+ private readonly cache = new Map<TKey, Promise<TResult>>();
96
+ private readonly gc: GarbageCollector<TKey>;
97
+
98
+ private readonly removeOnError: (error: unknown) => boolean;
99
+
100
+ /**
101
+ * Create the PromiseCache with the given options, with the following defaults:
102
+ *
103
+ * expiry: indefinite, removeOnError: true for all errors
104
+ */
105
+ public constructor({
106
+ expiry = { policy: "indefinite" },
107
+ removeOnError = (): boolean => true,
108
+ }: PromiseCacheOptions = {}) {
109
+ this.removeOnError = removeOnError;
110
+ this.gc = new GarbageCollector<TKey>(expiry, (key) => this.remove(key));
111
+ }
112
+
113
+ /**
114
+ * Check if there's anything cached at the given key
115
+ */
116
+ public has(key: TKey): boolean {
117
+ return this.cache.has(key);
118
+ }
119
+
120
+ /**
121
+ * Get the Promise for the given key, or undefined if it's not found.
122
+ * Extend expiry if applicable.
123
+ */
124
+ public get(key: TKey): Promise<TResult> | undefined {
125
+ if (this.has(key)) {
126
+ this.gc.update(key);
127
+ }
128
+ return this.cache.get(key);
129
+ }
130
+
131
+ /**
132
+ * Remove the Promise for the given key, returning true if it was found and removed
133
+ */
134
+ public remove(key: TKey): boolean {
135
+ this.gc.cancel(key);
136
+ return this.cache.delete(key);
137
+ }
138
+
139
+ /**
140
+ * Try to add the result of the given asyncFn, without overwriting an existing cache entry at that key.
141
+ * Returns a Promise for the added or existing async work being done at that key.
142
+ * @param key - key name where to store the async work
143
+ * @param asyncFn - the async work to do and store, if not already in progress under the given key
144
+ */
145
+ public async addOrGet(key: TKey, asyncFn: () => Promise<TResult>): Promise<TResult> {
146
+ // NOTE: Do not await the Promise returned by asyncFn!
147
+ // Let the caller do so once we return or after a subsequent call to get
148
+ let promise = this.get(key);
149
+ if (promise === undefined) {
150
+ // Wrap in an async lambda in case asyncFn disabled @typescript-eslint/promise-function-async
151
+ const safeAsyncFn = async (): Promise<TResult> => asyncFn();
152
+
153
+ // Start the async work and put the Promise in the cache
154
+ promise = safeAsyncFn();
155
+ this.cache.set(key, promise);
156
+
157
+ // If asyncFn throws, we may remove the Promise from the cache
158
+ promise.catch((error) => {
159
+ if (this.removeOnError(error)) {
160
+ this.remove(key);
161
+ }
162
+ });
163
+
164
+ this.gc.schedule(key);
165
+ }
166
+
167
+ return promise;
168
+ }
169
+
170
+ /**
171
+ * Try to add the result of the given asyncFn, without overwriting an existing cache entry at that key.
172
+ * Returns false if the cache already contained an entry at that key, and true otherwise.
173
+ * @param key - key name where to store the async work
174
+ * @param asyncFn - the async work to do and store, if not already in progress under the given key
175
+ */
176
+ public add(key: TKey, asyncFn: () => Promise<TResult>): boolean {
177
+ const alreadyPresent = this.has(key);
178
+
179
+ // We are blindly adding the Promise to the cache here, which introduces a Promise in this scope.
180
+ // Swallow Promise rejections here, since whoever gets this out of the cache to use it will await/catch.
181
+ this.addOrGet(key, asyncFn).catch(() => {});
182
+
183
+ return !alreadyPresent;
184
+ }
185
+
186
+ /**
187
+ * Try to add the given value, without overwriting an existing cache entry at that key.
188
+ * Returns a Promise for the added or existing async work being done at that key.
189
+ * @param key - key name where to store the async work
190
+ * @param value - value to store
191
+ */
192
+ public async addValueOrGet(key: TKey, value: TResult): Promise<TResult> {
193
+ return this.addOrGet(key, async () => value);
194
+ }
195
+
196
+ /**
197
+ * Try to add the given value, without overwriting an existing cache entry at that key.
198
+ * Returns false if the cache already contained an entry at that key, and true otherwise.
199
+ * @param key - key name where to store the value
200
+ * @param value - value to store
201
+ */
202
+ public addValue(key: TKey, value: TResult): boolean {
203
+ return this.add(key, async () => value);
204
+ }
205
+ }
@@ -0,0 +1,63 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ /**
7
+ * A deferred creates a promise and the ability to resolve or reject it
8
+ * @alpha
9
+ */
10
+ export class Deferred<T> {
11
+ private readonly p: Promise<T>;
12
+ private res: ((value: T | PromiseLike<T>) => void) | undefined;
13
+ private rej: ((reason?: unknown) => void) | undefined;
14
+ private completed: boolean = false;
15
+
16
+ public constructor() {
17
+ this.p = new Promise<T>((resolve, reject) => {
18
+ this.res = resolve;
19
+ this.rej = reject;
20
+ });
21
+ }
22
+ /**
23
+ * Returns whether the underlying promise has been completed
24
+ */
25
+ public get isCompleted(): boolean {
26
+ return this.completed;
27
+ }
28
+
29
+ /**
30
+ * Retrieves the underlying promise for the deferred
31
+ *
32
+ * @returns the underlying promise
33
+ */
34
+ public get promise(): Promise<T> {
35
+ return this.p;
36
+ }
37
+
38
+ /**
39
+ * Resolves the promise
40
+ *
41
+ * @param value - the value to resolve the promise with
42
+ */
43
+ public resolve(value: T | PromiseLike<T>): void {
44
+ if (this.res !== undefined) {
45
+ this.completed = true;
46
+ this.res(value);
47
+ }
48
+ }
49
+
50
+ /**
51
+ * Rejects the promise
52
+ *
53
+ * @param value - the value to reject the promise with
54
+ */
55
+ // TODO: Use `unknown` instead (API breaking)
56
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
57
+ public reject(error: any): void {
58
+ if (this.rej !== undefined) {
59
+ this.completed = true;
60
+ this.rej(error);
61
+ }
62
+ }
63
+ }