@difizen/libro-common 0.0.2-alpha.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.
Files changed (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +0 -0
  3. package/es/array.d.ts +368 -0
  4. package/es/array.d.ts.map +1 -0
  5. package/es/array.js +577 -0
  6. package/es/display-wrapper.d.ts +6 -0
  7. package/es/display-wrapper.d.ts.map +1 -0
  8. package/es/display-wrapper.js +12 -0
  9. package/es/index.d.ts +11 -0
  10. package/es/index.d.ts.map +1 -0
  11. package/es/index.js +10 -0
  12. package/es/iter.d.ts +147 -0
  13. package/es/iter.d.ts.map +1 -0
  14. package/es/iter.js +162 -0
  15. package/es/json.d.ts +126 -0
  16. package/es/json.d.ts.map +1 -0
  17. package/es/json.js +274 -0
  18. package/es/path.d.ts +97 -0
  19. package/es/path.d.ts.map +1 -0
  20. package/es/path.js +60 -0
  21. package/es/polling/index.d.ts +3 -0
  22. package/es/polling/index.d.ts.map +1 -0
  23. package/es/polling/index.js +2 -0
  24. package/es/polling/poll.d.ts +193 -0
  25. package/es/polling/poll.d.ts.map +1 -0
  26. package/es/polling/poll.js +501 -0
  27. package/es/polling/protocol.d.ts +120 -0
  28. package/es/polling/protocol.d.ts.map +1 -0
  29. package/es/polling/protocol.js +13 -0
  30. package/es/posix.d.ts +2 -0
  31. package/es/posix.d.ts.map +1 -0
  32. package/es/posix.js +71 -0
  33. package/es/protocol/cell-protocol.d.ts +181 -0
  34. package/es/protocol/cell-protocol.d.ts.map +1 -0
  35. package/es/protocol/cell-protocol.js +1 -0
  36. package/es/protocol/index.d.ts +4 -0
  37. package/es/protocol/index.d.ts.map +1 -0
  38. package/es/protocol/index.js +3 -0
  39. package/es/protocol/notebook-protocol.d.ts +63 -0
  40. package/es/protocol/notebook-protocol.d.ts.map +1 -0
  41. package/es/protocol/notebook-protocol.js +41 -0
  42. package/es/protocol/output-protocol.d.ts +125 -0
  43. package/es/protocol/output-protocol.d.ts.map +1 -0
  44. package/es/protocol/output-protocol.js +1 -0
  45. package/es/sanitizer.d.ts +44 -0
  46. package/es/sanitizer.d.ts.map +1 -0
  47. package/es/sanitizer.js +659 -0
  48. package/es/url.d.ts +98 -0
  49. package/es/url.d.ts.map +1 -0
  50. package/es/url.js +134 -0
  51. package/es/utils.d.ts +57 -0
  52. package/es/utils.d.ts.map +1 -0
  53. package/es/utils.js +124 -0
  54. package/package.json +62 -0
  55. package/src/array.ts +608 -0
  56. package/src/display-wrapper.tsx +11 -0
  57. package/src/index.ts +10 -0
  58. package/src/iter.ts +199 -0
  59. package/src/json.ts +321 -0
  60. package/src/path.ts +138 -0
  61. package/src/polling/index.ts +2 -0
  62. package/src/polling/poll.ts +508 -0
  63. package/src/polling/protocol.ts +145 -0
  64. package/src/posix.ts +75 -0
  65. package/src/protocol/cell-protocol.ts +215 -0
  66. package/src/protocol/index.ts +3 -0
  67. package/src/protocol/notebook-protocol.ts +73 -0
  68. package/src/protocol/output-protocol.ts +162 -0
  69. package/src/sanitizer.ts +944 -0
  70. package/src/url.ts +157 -0
  71. package/src/utils.ts +145 -0
@@ -0,0 +1,508 @@
1
+ /* eslint-disable @typescript-eslint/no-use-before-define */
2
+ /* eslint-disable no-param-reassign */
3
+ /* eslint-disable @typescript-eslint/no-namespace */
4
+
5
+ import type { Event } from '@difizen/mana-common';
6
+ import { Emitter, Deferred } from '@difizen/mana-common';
7
+
8
+ import { deepEqual } from '../json.js';
9
+
10
+ import type { IPoll } from './protocol.js';
11
+
12
+ /**
13
+ * A class that wraps an asynchronous function to poll at a regular interval
14
+ * with exponential increases to the interval length if the poll fails.
15
+ *
16
+ * @typeparam T - The resolved type of the factory's promises.
17
+ * Defaults to `any`.
18
+ *
19
+ * @typeparam U - The rejected type of the factory's promises.
20
+ * Defaults to `any`.
21
+ *
22
+ * @typeparam V - An optional type to extend the phases supported by a poll.
23
+ * Defaults to `standby`, which already exists in the `Phase` type.
24
+ */
25
+ export class Poll<T = any, U = any, V extends string = 'standby'>
26
+ implements IPoll<T, U, V>
27
+ {
28
+ protected disposeEmitter = new Emitter<void>();
29
+ protected _factory: Poll.Factory<T, U, V>;
30
+ protected _frequency: IPoll.Frequency;
31
+ protected _standby: Poll.Standby | (() => boolean | Poll.Standby);
32
+ protected _state: IPoll.State<T, U, V>;
33
+ protected _tick = new Deferred<this>();
34
+ protected tickedEmitter = new Emitter<IPoll.State<T, U, V>>();
35
+ protected _timeout?: NodeJS.Timeout | undefined; // Support node and browser.
36
+ disposed = false;
37
+ /**
38
+ * Instantiate a new poll with exponential backoff in case of failure.
39
+ *
40
+ * @param options - The poll instantiation options.
41
+ */
42
+ constructor(options: Poll.IOptions<T, U, V>) {
43
+ const frequency = options.frequency || {};
44
+
45
+ const max = Math.max(
46
+ frequency.interval || 0,
47
+ frequency.max || 0,
48
+ Private.DEFAULT_FREQUENCY.max,
49
+ );
50
+
51
+ this._frequency = { ...Private.DEFAULT_FREQUENCY, ...frequency, ...{ max } };
52
+
53
+ this._factory = options.factory;
54
+ this._standby = options.standby || Private.DEFAULT_STANDBY;
55
+ this._state = { ...Private.DEFAULT_STATE, timestamp: new Date().getTime() };
56
+
57
+ // Normalize poll frequency `max` to be the greater of
58
+ // default `max`, `options.frequency.max`, or `options.frequency.interval`.
59
+
60
+ this.name = options.name || Private.DEFAULT_NAME;
61
+
62
+ if ('auto' in options ? options.auto : true) {
63
+ setTimeout(() => this.start());
64
+ }
65
+ }
66
+
67
+ /**
68
+ * The name of the poll.
69
+ */
70
+ readonly name: string;
71
+
72
+ /**
73
+ * A signal emitted when the poll is disposed.
74
+ */
75
+ get onDispose(): Event<void> {
76
+ return this.disposeEmitter.event;
77
+ }
78
+
79
+ /**
80
+ * The polling frequency parameters.
81
+ */
82
+ get frequency(): IPoll.Frequency {
83
+ return this._frequency;
84
+ }
85
+ set frequency(frequency: IPoll.Frequency) {
86
+ if (this.isDisposed || deepEqual(frequency, this.frequency || {})) {
87
+ return;
88
+ }
89
+
90
+ let { interval, max } = frequency;
91
+ const { backoff } = frequency;
92
+
93
+ interval = Math.round(interval);
94
+ max = Math.round(max);
95
+
96
+ if (typeof backoff === 'number' && backoff < 1) {
97
+ throw new Error('Poll backoff growth factor must be at least 1');
98
+ }
99
+
100
+ if ((interval < 0 || interval > max) && interval !== Poll.NEVER) {
101
+ throw new Error('Poll interval must be between 0 and max');
102
+ }
103
+
104
+ if (max > Poll.MAX_INTERVAL && max !== Poll.NEVER) {
105
+ throw new Error(`Max interval must be less than ${Poll.MAX_INTERVAL}`);
106
+ }
107
+
108
+ this._frequency = { backoff, interval, max };
109
+ }
110
+
111
+ /**
112
+ * Whether the poll is disposed.
113
+ */
114
+ get isDisposed(): boolean {
115
+ return this.state.phase === 'disposed';
116
+ }
117
+
118
+ /**
119
+ * Indicates when the poll switches to standby.
120
+ */
121
+ get standby(): Poll.Standby | (() => boolean | Poll.Standby) {
122
+ return this._standby;
123
+ }
124
+ set standby(standby: Poll.Standby | (() => boolean | Poll.Standby)) {
125
+ if (this.isDisposed || this.standby === standby) {
126
+ return;
127
+ }
128
+
129
+ this._standby = standby;
130
+ }
131
+
132
+ /**
133
+ * The poll state, which is the content of the current poll tick.
134
+ */
135
+ get state(): IPoll.State<T, U, V> {
136
+ return this._state;
137
+ }
138
+
139
+ /**
140
+ * A promise that resolves when the poll next ticks.
141
+ */
142
+ get tick(): Promise<this> {
143
+ return this._tick.promise;
144
+ }
145
+
146
+ /**
147
+ * A signal emitted when the poll ticks and fires off a new request.
148
+ */
149
+ get ticked(): Event<IPoll.State<T, U, V>> {
150
+ return this.tickedEmitter.event;
151
+ }
152
+
153
+ /**
154
+ * Return an async iterator that yields every tick.
155
+ */
156
+ async *[Symbol.asyncIterator](): AsyncIterableIterator<IPoll.State<T, U, V>> {
157
+ while (!this.isDisposed) {
158
+ yield this.state;
159
+ await this.tick.catch(() => undefined);
160
+ }
161
+ }
162
+
163
+ /**
164
+ * Dispose the poll.
165
+ */
166
+ dispose(): void {
167
+ if (this.isDisposed) {
168
+ return;
169
+ }
170
+
171
+ this._state = {
172
+ ...Private.DISPOSED_STATE,
173
+ timestamp: new Date().getTime(),
174
+ };
175
+ this._tick.promise.catch(() => undefined);
176
+ this._tick.reject(new Error(`Poll (${this.name}) is disposed.`));
177
+ this.disposeEmitter.fire(undefined);
178
+ this.tickedEmitter.dispose();
179
+ this.disposed = true;
180
+ this.disposeEmitter.dispose();
181
+ }
182
+
183
+ /**
184
+ * Refreshes the poll. Schedules `refreshed` tick if necessary.
185
+ *
186
+ * @returns A promise that resolves after tick is scheduled and never rejects.
187
+ *
188
+ * #### Notes
189
+ * The returned promise resolves after the tick is scheduled, but before
190
+ * the polling action is run. To wait until after the poll action executes,
191
+ * await the `poll.tick` promise: `await poll.refresh(); await poll.tick;`
192
+ */
193
+ refresh(): Promise<void> {
194
+ return this.schedule({
195
+ cancel: ({ phase }) => phase === 'refreshed',
196
+ interval: Poll.IMMEDIATE,
197
+ phase: 'refreshed',
198
+ });
199
+ }
200
+
201
+ /**
202
+ * Schedule the next poll tick.
203
+ *
204
+ * @param next - The next poll state data to schedule. Defaults to standby.
205
+ *
206
+ * @param next.cancel - Cancels state transition if function returns `true`.
207
+ *
208
+ * @returns A promise that resolves when the next poll state is active.
209
+ *
210
+ * #### Notes
211
+ * This method is not meant to be invoked by user code typically. It is public
212
+ * to allow poll instances to be composed into classes that schedule ticks.
213
+ */
214
+ async schedule(
215
+ next: Partial<
216
+ IPoll.State<T, U, V> & { cancel: (last: IPoll.State<T, U, V>) => boolean }
217
+ > = {},
218
+ ): Promise<void> {
219
+ if (this.isDisposed) {
220
+ return;
221
+ }
222
+
223
+ // Check if the phase transition should be canceled.
224
+ if (next.cancel && next.cancel(this.state)) {
225
+ return;
226
+ }
227
+
228
+ // Update poll state.
229
+ const pending = this._tick;
230
+ const scheduled = new Deferred<this>();
231
+ const state = {
232
+ interval: this.frequency.interval,
233
+ payload: null,
234
+ phase: 'standby',
235
+ timestamp: new Date().getTime(),
236
+ ...next,
237
+ } as IPoll.State<T, U, V>;
238
+ this._state = state;
239
+ this._tick = scheduled;
240
+
241
+ // Clear the schedule if possible.
242
+ clearTimeout(this._timeout);
243
+
244
+ // Emit ticked signal, resolve pending promise, and await its settlement.
245
+ this.tickedEmitter.fire(this.state);
246
+ pending.resolve(this);
247
+ await pending.promise;
248
+
249
+ if (state.interval === Poll.NEVER) {
250
+ this._timeout = undefined;
251
+ return;
252
+ }
253
+
254
+ // Schedule next execution and cache its timeout handle.
255
+ const execute = () => {
256
+ if (this.isDisposed || this.tick !== scheduled.promise) {
257
+ return;
258
+ }
259
+
260
+ this._execute();
261
+ };
262
+ this._timeout = setTimeout(execute, state.interval);
263
+ }
264
+
265
+ /**
266
+ * Starts the poll. Schedules `started` tick if necessary.
267
+ *
268
+ * @returns A promise that resolves after tick is scheduled and never rejects.
269
+ */
270
+ start(): Promise<void> {
271
+ return this.schedule({
272
+ cancel: ({ phase }) =>
273
+ phase !== 'constructed' && phase !== 'standby' && phase !== 'stopped',
274
+ interval: Poll.IMMEDIATE,
275
+ phase: 'started',
276
+ });
277
+ }
278
+
279
+ /**
280
+ * Stops the poll. Schedules `stopped` tick if necessary.
281
+ *
282
+ * @returns A promise that resolves after tick is scheduled and never rejects.
283
+ */
284
+ stop(): Promise<void> {
285
+ return this.schedule({
286
+ cancel: ({ phase }) => phase === 'stopped',
287
+ interval: Poll.NEVER,
288
+ phase: 'stopped',
289
+ });
290
+ }
291
+
292
+ /**
293
+ * Execute a new poll factory promise or stand by if necessary.
294
+ */
295
+ protected _execute(): void {
296
+ let standby = typeof this.standby === 'function' ? this.standby() : this.standby;
297
+ standby =
298
+ standby === 'never'
299
+ ? false
300
+ : standby === 'when-hidden'
301
+ ? !!(typeof document !== 'undefined' && document && document.hidden)
302
+ : standby;
303
+
304
+ // If in standby mode schedule next tick without calling the factory.
305
+ if (standby) {
306
+ void this.schedule();
307
+ return;
308
+ }
309
+
310
+ const pending = this.tick;
311
+
312
+ this._factory(this.state)
313
+ .then((resolved: T) => {
314
+ if (this.isDisposed || this.tick !== pending) {
315
+ return;
316
+ }
317
+
318
+ void this.schedule({
319
+ payload: resolved,
320
+ phase: this.state.phase === 'rejected' ? 'reconnected' : 'resolved',
321
+ });
322
+ return;
323
+ })
324
+ .catch((rejected: U) => {
325
+ if (this.isDisposed || this.tick !== pending) {
326
+ return;
327
+ }
328
+
329
+ void this.schedule({
330
+ interval: Private.sleep(this.frequency, this.state),
331
+ payload: rejected,
332
+ phase: 'rejected',
333
+ });
334
+ });
335
+ }
336
+ }
337
+
338
+ /**
339
+ * A namespace for `Poll` types, interfaces, and statics.
340
+ */
341
+ export namespace Poll {
342
+ /**
343
+ * A promise factory that returns an individual poll request.
344
+ *
345
+ * @typeparam T - The resolved type of the factory's promises.
346
+ *
347
+ * @typeparam U - The rejected type of the factory's promises.
348
+ *
349
+ * @typeparam V - The type to extend the phases supported by a poll.
350
+ */
351
+ export type Factory<T, U, V extends string> = (
352
+ state: IPoll.State<T, U, V>,
353
+ ) => Promise<T>;
354
+
355
+ /**
356
+ * Indicates when the poll switches to standby.
357
+ */
358
+ export type Standby = 'never' | 'when-hidden';
359
+
360
+ /**
361
+ * Instantiation options for polls.
362
+ *
363
+ * @typeparam T - The resolved type of the factory's promises.
364
+ *
365
+ * @typeparam U - The rejected type of the factory's promises.
366
+ *
367
+ * @typeparam V - The type to extend the phases supported by a poll.
368
+ */
369
+ export interface IOptions<T, U, V extends string> {
370
+ /**
371
+ * Whether to begin polling automatically; defaults to `true`.
372
+ */
373
+ auto?: boolean;
374
+
375
+ /**
376
+ * A factory function that is passed a poll tick and returns a poll promise.
377
+ */
378
+ factory: Factory<T, U, V>;
379
+
380
+ /**
381
+ * The polling frequency parameters.
382
+ */
383
+ frequency?: Partial<IPoll.Frequency>;
384
+
385
+ /**
386
+ * The name of the poll.
387
+ * Defaults to `'unknown'`.
388
+ */
389
+ name?: string;
390
+
391
+ /**
392
+ * Indicates when the poll switches to standby or a function that returns
393
+ * a boolean or a `Poll.Standby` value to indicate whether to stand by.
394
+ * Defaults to `'when-hidden'`.
395
+ *
396
+ * #### Notes
397
+ * If a function is passed in, for any given context, it should be
398
+ * idempotent and safe to call multiple times. It will be called before each
399
+ * tick execution, but may be called by clients as well.
400
+ */
401
+ standby?: Standby | (() => boolean | Standby);
402
+ }
403
+ /**
404
+ * An interval value (0ms) that indicates the poll should tick immediately.
405
+ */
406
+ export const IMMEDIATE = 0;
407
+
408
+ /**
409
+ * Delays are 32-bit integers in many browsers so intervals need to be capped.
410
+ *
411
+ * #### Notes
412
+ * https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout#Maximum_delay_value
413
+ */
414
+ export const MAX_INTERVAL = 2147483647;
415
+
416
+ /**
417
+ * An interval value that indicates the poll should never tick.
418
+ */
419
+ export const NEVER = Infinity;
420
+ }
421
+
422
+ /**
423
+ * A namespace for protected module data.
424
+ */
425
+ namespace Private {
426
+ /**
427
+ * The default backoff growth rate if `backoff` is `true`.
428
+ */
429
+ export const DEFAULT_BACKOFF = 3;
430
+
431
+ /**
432
+ * The default polling frequency.
433
+ */
434
+ export const DEFAULT_FREQUENCY: IPoll.Frequency = {
435
+ backoff: true,
436
+ interval: 1000,
437
+ max: 30 * 1000,
438
+ };
439
+
440
+ /**
441
+ * The default poll name.
442
+ */
443
+ export const DEFAULT_NAME = 'unknown';
444
+
445
+ /**
446
+ * The default poll standby behavior.
447
+ */
448
+ export const DEFAULT_STANDBY: Poll.Standby = 'when-hidden';
449
+
450
+ /**
451
+ * The first poll tick state's default values superseded in constructor.
452
+ */
453
+ export const DEFAULT_STATE: IPoll.State<any, any, any> = {
454
+ interval: Poll.NEVER,
455
+ payload: null,
456
+ phase: 'constructed',
457
+ timestamp: new Date(0).getTime(),
458
+ };
459
+
460
+ /**
461
+ * The disposed tick state values.
462
+ */
463
+ export const DISPOSED_STATE: IPoll.State<any, any, any> = {
464
+ interval: Poll.NEVER,
465
+ payload: null,
466
+ phase: 'disposed',
467
+ timestamp: new Date(0).getTime(),
468
+ };
469
+
470
+ /**
471
+ * Returns the number of milliseconds to sleep before the next tick.
472
+ *
473
+ * @param frequency - The poll's base frequency.
474
+ * @param last - The poll's last tick.
475
+ */
476
+ export function sleep(
477
+ frequency: IPoll.Frequency,
478
+ last: IPoll.State<any, any, any>,
479
+ ): number {
480
+ const { backoff, interval, max } = frequency;
481
+
482
+ if (interval === Poll.NEVER) {
483
+ return interval;
484
+ }
485
+
486
+ const growth = backoff === true ? DEFAULT_BACKOFF : backoff === false ? 1 : backoff;
487
+ const random = getRandomIntInclusive(interval, last.interval * growth);
488
+
489
+ return Math.min(max, random);
490
+ }
491
+ }
492
+
493
+ /**
494
+ * Get a random integer between min and max, inclusive of both.
495
+ *
496
+ * #### Notes
497
+ * From
498
+ * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random#Getting_a_random_integer_between_two_values_inclusive
499
+ *
500
+ * From the MDN page: It might be tempting to use Math.round() to accomplish
501
+ * that, but doing so would cause your random numbers to follow a non-uniform
502
+ * distribution, which may not be acceptable for your needs.
503
+ */
504
+ function getRandomIntInclusive(min: number, max: number) {
505
+ min = Math.ceil(min);
506
+ max = Math.floor(max);
507
+ return Math.floor(Math.random() * (max - min + 1)) + min;
508
+ }
@@ -0,0 +1,145 @@
1
+ import type { Event } from '@difizen/mana-common';
2
+
3
+ /**
4
+ * A readonly poll that calls an asynchronous function with each tick.
5
+ *
6
+ * @typeparam T - The resolved type of the factory's promises.
7
+ *
8
+ * @typeparam U - The rejected type of the factory's promises.
9
+ *
10
+ * @typeparam V - The type to extend the phases supported by a poll.
11
+ */
12
+ export interface IPoll<T, U, V extends string>
13
+ extends AsyncIterable<IPoll.State<T, U, V>> {
14
+ /**
15
+ * A signal emitted when the poll is disposed.
16
+ */
17
+ readonly onDispose: Event<void>;
18
+
19
+ /**
20
+ * The polling frequency data.
21
+ */
22
+ readonly frequency: IPoll.Frequency;
23
+
24
+ /**
25
+ * Whether the poll is disposed.
26
+ */
27
+ readonly disposed: boolean;
28
+
29
+ /**
30
+ * The name of the poll.
31
+ */
32
+ readonly name: string;
33
+
34
+ /**
35
+ * The poll state, which is the content of the currently-scheduled poll tick.
36
+ */
37
+ readonly state: IPoll.State<T, U, V>;
38
+
39
+ /**
40
+ * A promise that resolves when the currently-scheduled tick completes.
41
+ *
42
+ * #### Notes
43
+ * Usually this will resolve after `state.interval` milliseconds from
44
+ * `state.timestamp`. It can resolve earlier if the user starts or refreshes
45
+ * the poll, etc.
46
+ */
47
+ readonly tick: Promise<IPoll<T, U, V>>;
48
+
49
+ /**
50
+ * A signal emitted when the poll state changes, i.e., a new tick is scheduled.
51
+ */
52
+ readonly ticked: Event<IPoll.State<T, U, V>>;
53
+ }
54
+
55
+ /**
56
+ * A namespace for `IPoll` types.
57
+ */
58
+ export namespace IPoll {
59
+ /**
60
+ * The polling frequency parameters.
61
+ *
62
+ * #### Notes
63
+ * We implement the "decorrelated jitter" strategy from
64
+ * https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/.
65
+ * Essentially, if consecutive retries are needed, we choose an integer:
66
+ * `sleep = min(max, rand(interval, backoff * sleep))`
67
+ * This ensures that the poll is never less than `interval`, and nicely
68
+ * spreads out retries for consecutive tries. Over time, if (interval < max),
69
+ * the random number will be above `max` about (1 - 1/backoff) of the time
70
+ * (sleeping the `max`), and the rest of the time the sleep will be a random
71
+ * number below `max`, decorrelating our trigger time from other pollers.
72
+ */
73
+ export type Frequency = {
74
+ /**
75
+ * Whether poll frequency backs off (boolean) or the backoff growth rate
76
+ * (float > 1).
77
+ *
78
+ * #### Notes
79
+ * If `true`, the default backoff growth rate is `3`.
80
+ */
81
+ readonly backoff: boolean | number;
82
+
83
+ /**
84
+ * The basic polling interval in milliseconds (integer).
85
+ */
86
+ readonly interval: number;
87
+
88
+ /**
89
+ * The maximum milliseconds (integer) between poll requests.
90
+ */
91
+ readonly max: number;
92
+ };
93
+
94
+ /**
95
+ * The phase of the poll when the current tick was scheduled.
96
+ *
97
+ * @typeparam T - A type for any additional tick phases a poll supports.
98
+ */
99
+ export type Phase<T extends string> =
100
+ | T
101
+ | 'constructed'
102
+ | 'disposed'
103
+ | 'reconnected'
104
+ | 'refreshed'
105
+ | 'rejected'
106
+ | 'resolved'
107
+ | 'standby'
108
+ | 'started'
109
+ | 'stopped';
110
+
111
+ /**
112
+ * Definition of poll state at any given time.
113
+ *
114
+ * @typeparam T - The resolved type of the factory's promises.
115
+ *
116
+ * @typeparam U - The rejected type of the factory's promises.
117
+ *
118
+ * @typeparam V - The type to extend the phases supported by a poll.
119
+ */
120
+ export type State<T, U, V extends string> = {
121
+ /**
122
+ * The number of milliseconds until the current tick resolves.
123
+ */
124
+ readonly interval: number;
125
+
126
+ /**
127
+ * The payload of the last poll resolution or rejection.
128
+ *
129
+ * #### Notes
130
+ * The payload is `null` unless the `phase` is `'reconnected`, `'resolved'`,
131
+ * or `'rejected'`. Its type is `T` for resolutions and `U` for rejections.
132
+ */
133
+ readonly payload: T | U | null;
134
+
135
+ /**
136
+ * The current poll phase.
137
+ */
138
+ readonly phase: Phase<V>;
139
+
140
+ /**
141
+ * The timestamp for when this tick was scheduled.
142
+ */
143
+ readonly timestamp: number;
144
+ };
145
+ }