@digital-alchemy/core 26.2.17 → 26.5.28
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/CLAUDE.md +302 -0
- package/README.md +19 -3
- package/dist/helpers/async.d.mts +37 -0
- package/dist/helpers/async.mjs +50 -15
- package/dist/helpers/async.mjs.map +1 -1
- package/dist/helpers/config-environment-loader.d.mts +39 -0
- package/dist/helpers/config-environment-loader.mjs +51 -11
- package/dist/helpers/config-environment-loader.mjs.map +1 -1
- package/dist/helpers/config-file-loader.d.mts +65 -0
- package/dist/helpers/config-file-loader.mjs +80 -4
- package/dist/helpers/config-file-loader.mjs.map +1 -1
- package/dist/helpers/config.d.mts +202 -5
- package/dist/helpers/config.mjs +60 -0
- package/dist/helpers/config.mjs.map +1 -1
- package/dist/helpers/context.d.mts +12 -1
- package/dist/helpers/cron.d.mts +154 -7
- package/dist/helpers/cron.mjs +47 -4
- package/dist/helpers/cron.mjs.map +1 -1
- package/dist/helpers/errors.d.mts +45 -0
- package/dist/helpers/errors.mjs +45 -0
- package/dist/helpers/errors.mjs.map +1 -1
- package/dist/helpers/events.d.mts +23 -0
- package/dist/helpers/events.mjs +23 -0
- package/dist/helpers/events.mjs.map +1 -1
- package/dist/helpers/extend.d.mts +50 -0
- package/dist/helpers/extend.mjs +63 -0
- package/dist/helpers/extend.mjs.map +1 -1
- package/dist/helpers/index.d.mts +9 -0
- package/dist/helpers/index.mjs +9 -0
- package/dist/helpers/index.mjs.map +1 -1
- package/dist/helpers/lifecycle.d.mts +102 -16
- package/dist/helpers/lifecycle.mjs +19 -1
- package/dist/helpers/lifecycle.mjs.map +1 -1
- package/dist/helpers/logger.d.mts +182 -17
- package/dist/helpers/logger.mjs +45 -1
- package/dist/helpers/logger.mjs.map +1 -1
- package/dist/helpers/module.d.mts +110 -0
- package/dist/helpers/module.mjs +55 -6
- package/dist/helpers/module.mjs.map +1 -1
- package/dist/helpers/service-runner.d.mts +27 -1
- package/dist/helpers/service-runner.mjs +27 -1
- package/dist/helpers/service-runner.mjs.map +1 -1
- package/dist/helpers/utilities.d.mts +123 -3
- package/dist/helpers/utilities.mjs +110 -3
- package/dist/helpers/utilities.mjs.map +1 -1
- package/dist/helpers/wiring.d.mts +385 -0
- package/dist/helpers/wiring.mjs +120 -0
- package/dist/helpers/wiring.mjs.map +1 -1
- package/dist/services/als.service.d.mts +10 -0
- package/dist/services/als.service.mjs +49 -0
- package/dist/services/als.service.mjs.map +1 -1
- package/dist/services/configuration.service.d.mts +22 -0
- package/dist/services/configuration.service.mjs +140 -12
- package/dist/services/configuration.service.mjs.map +1 -1
- package/dist/services/index.d.mts +8 -0
- package/dist/services/index.mjs +8 -0
- package/dist/services/index.mjs.map +1 -1
- package/dist/services/internal.service.d.mts +98 -19
- package/dist/services/internal.service.mjs +91 -9
- package/dist/services/internal.service.mjs.map +1 -1
- package/dist/services/is.service.d.mts +64 -4
- package/dist/services/is.service.mjs +67 -4
- package/dist/services/is.service.mjs.map +1 -1
- package/dist/services/lifecycle.service.d.mts +26 -0
- package/dist/services/lifecycle.service.mjs +67 -9
- package/dist/services/lifecycle.service.mjs.map +1 -1
- package/dist/services/logger.service.d.mts +27 -0
- package/dist/services/logger.service.mjs +133 -9
- package/dist/services/logger.service.mjs.map +1 -1
- package/dist/services/scheduler.service.d.mts +19 -0
- package/dist/services/scheduler.service.mjs +87 -4
- package/dist/services/scheduler.service.mjs.map +1 -1
- package/dist/services/wiring.service.d.mts +28 -0
- package/dist/services/wiring.service.mjs +173 -19
- package/dist/services/wiring.service.mjs.map +1 -1
- package/dist/testing/index.d.mts +4 -0
- package/dist/testing/index.mjs +4 -0
- package/dist/testing/index.mjs.map +1 -1
- package/dist/testing/mock-logger.d.mts +8 -0
- package/dist/testing/mock-logger.mjs +9 -0
- package/dist/testing/mock-logger.mjs.map +1 -1
- package/dist/testing/test-module.d.mts +112 -27
- package/dist/testing/test-module.mjs +64 -2
- package/dist/testing/test-module.mjs.map +1 -1
- package/package.json +36 -34
|
@@ -1,60 +1,145 @@
|
|
|
1
1
|
import type { Dayjs } from "dayjs";
|
|
2
2
|
import type { Duration } from "dayjs/plugin/duration.js";
|
|
3
3
|
import type { TOffset } from "./cron.mts";
|
|
4
|
+
/** Even divisor — used when checking parity (`value % EVEN === 0`). */
|
|
4
5
|
export declare const EVEN = 2;
|
|
6
|
+
/** Alias for EVEN; used when the "twoness" is conceptually a pair, not parity. */
|
|
5
7
|
export declare const PAIR = 2;
|
|
8
|
+
/** Multiplier for half of a value (`total * HALF`). */
|
|
6
9
|
export declare const HALF = 0.5;
|
|
10
|
+
/** One-third fraction constant (`total * ONE_THIRD`). */
|
|
7
11
|
export declare const ONE_THIRD: number;
|
|
12
|
+
/** Two-thirds fraction constant (`total * TWO_THIRDS`). */
|
|
8
13
|
export declare const TWO_THIRDS: number;
|
|
9
14
|
/**
|
|
15
|
+
* Sensible default cap for concurrency and pagination limits.
|
|
16
|
+
*
|
|
10
17
|
* Good for a surprising number of situations
|
|
11
18
|
*/
|
|
12
19
|
export declare const DEFAULT_LIMIT = 5;
|
|
20
|
+
/** Multiply by this to negate a number (`value * INVERT_VALUE`). */
|
|
13
21
|
export declare const INVERT_VALUE = -1;
|
|
22
|
+
/** Sort comparator return for ascending order (`a > b ? UP : ...`). */
|
|
14
23
|
export declare const UP = 1;
|
|
24
|
+
/** Index of the value element in a `[label, value]` tuple. */
|
|
15
25
|
export declare const VALUE = 1;
|
|
26
|
+
/**
|
|
27
|
+
* Offset applied when converting a 1-based length to a 0-based last index
|
|
28
|
+
* (`array.length - ARRAY_OFFSET`).
|
|
29
|
+
*/
|
|
16
30
|
export declare const ARRAY_OFFSET = 1;
|
|
31
|
+
/** Step size when walking an array index one position at a time. */
|
|
17
32
|
export declare const INCREMENT = 1;
|
|
33
|
+
/** Canonical "one of something" constant; avoids the bare literal `1`. */
|
|
18
34
|
export declare const SINGLE = 1;
|
|
35
|
+
/** Sort comparator return for equal elements (`a === b ? SAME : ...`). */
|
|
19
36
|
export declare const SAME = 0;
|
|
37
|
+
/** Index of the label element in a `[label, value]` tuple. */
|
|
20
38
|
export declare const LABEL = 0;
|
|
39
|
+
/** Zero-based start index; use instead of bare `0` for array access. */
|
|
21
40
|
export declare const START = 0;
|
|
41
|
+
/** Canonical zero-count sentinel (`if (count === NONE)`). */
|
|
22
42
|
export declare const NONE = 0;
|
|
43
|
+
/** First index in any zero-based collection. */
|
|
23
44
|
export declare const FIRST = 0;
|
|
45
|
+
/** Type alias for the literal `0`; useful in discriminated union positions. */
|
|
24
46
|
export type FIRST = 0;
|
|
47
|
+
/** Zero-length sentinel; use `length === EMPTY` instead of `length === 0`. */
|
|
25
48
|
export declare const EMPTY = 0;
|
|
49
|
+
/** No-op delta — returned from comparators when a value has not changed. */
|
|
26
50
|
export declare const NO_CHANGE = 0;
|
|
51
|
+
/** Sentinel returned by `Array.prototype.indexOf` when the element is absent. */
|
|
27
52
|
export declare const NOT_FOUND = -1;
|
|
53
|
+
/** Sort comparator return for descending order (`a < b ? DOWN : ...`). */
|
|
28
54
|
export declare const DOWN = -1;
|
|
55
|
+
/** One minute expressed in milliseconds (`60_000`). */
|
|
29
56
|
export declare const MINUTE = 60000;
|
|
57
|
+
/** One hour expressed in milliseconds (`3_600_000`). */
|
|
30
58
|
export declare const HOUR = 3600000;
|
|
59
|
+
/** One day expressed in milliseconds (`86_400_000`). */
|
|
31
60
|
export declare const DAY = 86400000;
|
|
61
|
+
/** One week expressed in milliseconds (`7 * DAY`). */
|
|
32
62
|
export declare const WEEK: number;
|
|
63
|
+
/** One second expressed in milliseconds (`1_000`). */
|
|
33
64
|
export declare const SECOND = 1000;
|
|
65
|
+
/** Denominator for percent calculations (`value / PERCENT * 100`). */
|
|
34
66
|
export declare const PERCENT = 100;
|
|
67
|
+
/** One calendar year expressed in milliseconds (`365 * DAY`). */
|
|
35
68
|
export declare const YEAR: number;
|
|
69
|
+
/**
|
|
70
|
+
* Live set of every `SleepReturn` that has not yet resolved or been killed.
|
|
71
|
+
*
|
|
72
|
+
* @remarks
|
|
73
|
+
* The scheduler and teardown logic iterate this set to cancel in-flight sleeps
|
|
74
|
+
* on shutdown. Entries are added when `sleep()` is called and removed when the
|
|
75
|
+
* timer fires or `.kill()` is called.
|
|
76
|
+
*
|
|
77
|
+
* @internal
|
|
78
|
+
*/
|
|
36
79
|
export declare const ACTIVE_SLEEPS: Set<SleepReturn>;
|
|
37
80
|
/**
|
|
81
|
+
* Normalise a {@link TOffset} into a dayjs `Duration` object.
|
|
82
|
+
*
|
|
83
|
+
* @remarks
|
|
84
|
+
* Supports the full `TOffset` union:
|
|
85
|
+
* - **function** — called first to unwrap the real offset
|
|
86
|
+
* - **`[amount, unit]` tuple** — passed directly to `dayjs.duration`
|
|
87
|
+
* - **`DurationUnitsObjectType` object** — passed to `dayjs.duration`; an existing
|
|
88
|
+
* `Duration` instance is returned as-is
|
|
89
|
+
* - **string** — interpreted as a partial ISO 8601 duration after prepending `"PT"`
|
|
90
|
+
* (e.g. `"30s"` → `"PT30S"`)
|
|
91
|
+
* - **number** — treated as raw milliseconds
|
|
92
|
+
*
|
|
93
|
+
* Returns `undefined` when the offset does not match any supported form.
|
|
94
|
+
*
|
|
38
95
|
* Converts a TOffset to a Duration object (or undefined if invalid)
|
|
39
96
|
* Handles function unwrapping, arrays, objects, strings, and numbers
|
|
40
97
|
*/
|
|
41
98
|
export declare function toOffsetDuration(offset: TOffset): Duration | undefined;
|
|
42
99
|
/**
|
|
100
|
+
* Normalise a {@link TOffset} into a plain millisecond count.
|
|
101
|
+
*
|
|
102
|
+
* @remarks
|
|
103
|
+
* Unwraps function offsets then takes a fast path for raw numbers to avoid
|
|
104
|
+
* allocating a `Duration` object. All other forms are delegated to
|
|
105
|
+
* {@link toOffsetDuration} and converted via `asMilliseconds()`.
|
|
106
|
+
*
|
|
107
|
+
* Returns `NONE` (0) when the offset cannot be resolved.
|
|
108
|
+
*
|
|
43
109
|
* Converts a TOffset to milliseconds
|
|
44
110
|
*/
|
|
45
111
|
export declare function toOffsetMs(offset: TOffset): number;
|
|
112
|
+
/**
|
|
113
|
+
* A `Promise<void>` extended with a `.kill()` method for early cancellation.
|
|
114
|
+
*
|
|
115
|
+
* @remarks
|
|
116
|
+
* Returned by {@link sleep}. Awaiting resolves when the timer fires naturally.
|
|
117
|
+
* Calling `.kill("continue")` resolves the promise immediately and cancels the
|
|
118
|
+
* timer. Calling `.kill("stop")` (the default) cancels the timer and lets the
|
|
119
|
+
* promise remain forever-pending — useful when you want the awaiting code to
|
|
120
|
+
* simply stop without advancing.
|
|
121
|
+
*/
|
|
46
122
|
export type SleepReturn = Promise<void> & {
|
|
47
123
|
kill: (execute?: "stop" | "continue") => void;
|
|
48
124
|
};
|
|
49
125
|
/**
|
|
50
|
-
*
|
|
126
|
+
* Async delay that supports early cancellation via `.kill()`.
|
|
51
127
|
*
|
|
128
|
+
* @remarks
|
|
129
|
+
* Accepts any {@link TOffset}, a JS `Date`, or a `Dayjs` instance. Absolute
|
|
130
|
+
* time values (`Date` / `Dayjs`) are converted to a relative delay from now at
|
|
131
|
+
* the moment `sleep()` is called.
|
|
132
|
+
*
|
|
133
|
+
* The returned {@link SleepReturn} is tracked in {@link ACTIVE_SLEEPS} for
|
|
134
|
+
* lifecycle-aware shutdown; it is removed automatically when the timer fires or
|
|
135
|
+
* `.kill()` is called.
|
|
136
|
+
*
|
|
137
|
+
* @example Simple usage
|
|
52
138
|
* ```typescript
|
|
53
139
|
* await sleep(5000);
|
|
54
140
|
* ```
|
|
55
141
|
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
142
|
+
* @example Early stop
|
|
58
143
|
* ```typescript
|
|
59
144
|
* const start = Date.now();
|
|
60
145
|
* const timer = sleep(5000);
|
|
@@ -65,13 +150,48 @@ export type SleepReturn = Promise<void> & {
|
|
|
65
150
|
* ```
|
|
66
151
|
*/
|
|
67
152
|
export declare function sleep(target: TOffset | Date | Dayjs): SleepReturn;
|
|
153
|
+
/**
|
|
154
|
+
* Set of identifiers currently in the throttle window.
|
|
155
|
+
*
|
|
156
|
+
* @internal
|
|
157
|
+
*/
|
|
68
158
|
export declare const ACTIVE_THROTTLE: Set<string>;
|
|
159
|
+
/**
|
|
160
|
+
* Map of identifier → pending sleep for the active debounce window.
|
|
161
|
+
*
|
|
162
|
+
* @remarks
|
|
163
|
+
* Each key is a caller-supplied `identifier` string. When a new call arrives
|
|
164
|
+
* for an existing identifier, the current sleep is killed and replaced, pushing
|
|
165
|
+
* the expiry forward. Entries are removed once the delay resolves.
|
|
166
|
+
*
|
|
167
|
+
* @internal
|
|
168
|
+
*/
|
|
69
169
|
export declare const ACTIVE_DEBOUNCE: Map<string, SleepReturn>;
|
|
70
170
|
/**
|
|
171
|
+
* Debounce an async operation by identifier.
|
|
172
|
+
*
|
|
173
|
+
* @remarks
|
|
174
|
+
* Each call resets the timer for `identifier`, so the operation does not
|
|
175
|
+
* proceed until no further calls for that identifier arrive within `timeout`.
|
|
176
|
+
* Multiple concurrent callers sharing the same `identifier` all wait on the
|
|
177
|
+
* same sliding window — the last writer wins.
|
|
178
|
+
*
|
|
71
179
|
* wait for duration after call before allowing next, extends for calls inside window
|
|
72
180
|
*/
|
|
73
181
|
export declare function debounce(identifier: string, timeout: TOffset): Promise<void>;
|
|
182
|
+
/** Async no-op that resolves after one event-loop tick via `sleep(0)`. */
|
|
74
183
|
export declare const asyncNoop: () => Promise<void>;
|
|
184
|
+
/** Synchronous no-op — a named empty function for use as a default callback. */
|
|
75
185
|
export declare const noop: () => void;
|
|
186
|
+
/**
|
|
187
|
+
* Represents a return type that callers are not expected to use.
|
|
188
|
+
*
|
|
189
|
+
* @remarks
|
|
190
|
+
* Used as the return type annotation for fire-and-forget callbacks and service
|
|
191
|
+
* methods where the resolved value is intentionally discarded. Covers `void`,
|
|
192
|
+
* `Promise<void>`, and any other return to prevent TypeScript from complaining
|
|
193
|
+
* about unused return values.
|
|
194
|
+
*/
|
|
76
195
|
export type TBlackHole = unknown | void | Promise<void>;
|
|
196
|
+
/** Loose function signature that accepts any arguments and returns a {@link TBlackHole}. */
|
|
77
197
|
export type TAnyFunction = (...data: unknown[]) => TBlackHole;
|
|
@@ -3,49 +3,110 @@ import duration from "dayjs/plugin/duration.js";
|
|
|
3
3
|
import { is } from "../index.mjs";
|
|
4
4
|
dayjs.extend(duration);
|
|
5
5
|
/* eslint-disable @typescript-eslint/no-magic-numbers */
|
|
6
|
+
// --- Numeric constants ---------------------------------------------------------
|
|
7
|
+
// These are the canonical zero/one anchors used throughout the codebase.
|
|
8
|
+
// Named constants eliminate magic numbers and make intent explicit at each
|
|
9
|
+
// call site, which is why they live here rather than being inlined.
|
|
10
|
+
/** Even divisor — used when checking parity (`value % EVEN === 0`). */
|
|
6
11
|
export const EVEN = 2;
|
|
12
|
+
/** Alias for EVEN; used when the "twoness" is conceptually a pair, not parity. */
|
|
7
13
|
export const PAIR = 2;
|
|
14
|
+
/** Multiplier for half of a value (`total * HALF`). */
|
|
8
15
|
export const HALF = 0.5;
|
|
16
|
+
/** One-third fraction constant (`total * ONE_THIRD`). */
|
|
9
17
|
export const ONE_THIRD = 1 / 3;
|
|
18
|
+
/** Two-thirds fraction constant (`total * TWO_THIRDS`). */
|
|
10
19
|
export const TWO_THIRDS = 2 / 3;
|
|
11
20
|
/**
|
|
21
|
+
* Sensible default cap for concurrency and pagination limits.
|
|
22
|
+
*
|
|
12
23
|
* Good for a surprising number of situations
|
|
13
24
|
*/
|
|
14
25
|
export const DEFAULT_LIMIT = 5;
|
|
26
|
+
/** Multiply by this to negate a number (`value * INVERT_VALUE`). */
|
|
15
27
|
export const INVERT_VALUE = -1;
|
|
28
|
+
/** Sort comparator return for ascending order (`a > b ? UP : ...`). */
|
|
16
29
|
// Sort
|
|
17
30
|
export const UP = 1;
|
|
31
|
+
/** Index of the value element in a `[label, value]` tuple. */
|
|
18
32
|
// [LABEL,VALUE]
|
|
19
33
|
export const VALUE = 1;
|
|
34
|
+
/**
|
|
35
|
+
* Offset applied when converting a 1-based length to a 0-based last index
|
|
36
|
+
* (`array.length - ARRAY_OFFSET`).
|
|
37
|
+
*/
|
|
20
38
|
// Standard value
|
|
21
39
|
export const ARRAY_OFFSET = 1;
|
|
40
|
+
/** Step size when walking an array index one position at a time. */
|
|
22
41
|
// array[number +- increment]
|
|
23
42
|
export const INCREMENT = 1;
|
|
43
|
+
/** Canonical "one of something" constant; avoids the bare literal `1`. */
|
|
24
44
|
// Generic one-ness
|
|
25
45
|
export const SINGLE = 1;
|
|
46
|
+
/** Sort comparator return for equal elements (`a === b ? SAME : ...`). */
|
|
26
47
|
// Sorting
|
|
27
48
|
export const SAME = 0;
|
|
49
|
+
/** Index of the label element in a `[label, value]` tuple. */
|
|
28
50
|
// [LABEL,VALUE]
|
|
29
51
|
export const LABEL = 0;
|
|
52
|
+
/** Zero-based start index; use instead of bare `0` for array access. */
|
|
30
53
|
// Generic start of something
|
|
31
54
|
export const START = 0;
|
|
55
|
+
/** Canonical zero-count sentinel (`if (count === NONE)`). */
|
|
32
56
|
export const NONE = 0;
|
|
57
|
+
/** First index in any zero-based collection. */
|
|
33
58
|
export const FIRST = 0;
|
|
59
|
+
/** Zero-length sentinel; use `length === EMPTY` instead of `length === 0`. */
|
|
34
60
|
export const EMPTY = 0;
|
|
61
|
+
/** No-op delta — returned from comparators when a value has not changed. */
|
|
35
62
|
export const NO_CHANGE = 0;
|
|
63
|
+
/** Sentinel returned by `Array.prototype.indexOf` when the element is absent. */
|
|
36
64
|
// Testing of indexes
|
|
37
65
|
export const NOT_FOUND = -1;
|
|
66
|
+
/** Sort comparator return for descending order (`a < b ? DOWN : ...`). */
|
|
38
67
|
// Sorting
|
|
39
68
|
export const DOWN = -1;
|
|
69
|
+
/** One minute expressed in milliseconds (`60_000`). */
|
|
40
70
|
export const MINUTE = 60_000;
|
|
71
|
+
/** One hour expressed in milliseconds (`3_600_000`). */
|
|
41
72
|
export const HOUR = 3_600_000;
|
|
73
|
+
/** One day expressed in milliseconds (`86_400_000`). */
|
|
42
74
|
export const DAY = 86_400_000;
|
|
75
|
+
/** One week expressed in milliseconds (`7 * DAY`). */
|
|
43
76
|
export const WEEK = 7 * DAY;
|
|
77
|
+
/** One second expressed in milliseconds (`1_000`). */
|
|
44
78
|
export const SECOND = 1000;
|
|
79
|
+
/** Denominator for percent calculations (`value / PERCENT * 100`). */
|
|
45
80
|
export const PERCENT = 100;
|
|
81
|
+
/** One calendar year expressed in milliseconds (`365 * DAY`). */
|
|
46
82
|
export const YEAR = 365 * DAY;
|
|
83
|
+
// --- Sleep infrastructure -----------------------------------------------------
|
|
84
|
+
/**
|
|
85
|
+
* Live set of every `SleepReturn` that has not yet resolved or been killed.
|
|
86
|
+
*
|
|
87
|
+
* @remarks
|
|
88
|
+
* The scheduler and teardown logic iterate this set to cancel in-flight sleeps
|
|
89
|
+
* on shutdown. Entries are added when `sleep()` is called and removed when the
|
|
90
|
+
* timer fires or `.kill()` is called.
|
|
91
|
+
*
|
|
92
|
+
* @internal
|
|
93
|
+
*/
|
|
47
94
|
export const ACTIVE_SLEEPS = new Set();
|
|
48
95
|
/**
|
|
96
|
+
* Normalise a {@link TOffset} into a dayjs `Duration` object.
|
|
97
|
+
*
|
|
98
|
+
* @remarks
|
|
99
|
+
* Supports the full `TOffset` union:
|
|
100
|
+
* - **function** — called first to unwrap the real offset
|
|
101
|
+
* - **`[amount, unit]` tuple** — passed directly to `dayjs.duration`
|
|
102
|
+
* - **`DurationUnitsObjectType` object** — passed to `dayjs.duration`; an existing
|
|
103
|
+
* `Duration` instance is returned as-is
|
|
104
|
+
* - **string** — interpreted as a partial ISO 8601 duration after prepending `"PT"`
|
|
105
|
+
* (e.g. `"30s"` → `"PT30S"`)
|
|
106
|
+
* - **number** — treated as raw milliseconds
|
|
107
|
+
*
|
|
108
|
+
* Returns `undefined` when the offset does not match any supported form.
|
|
109
|
+
*
|
|
49
110
|
* Converts a TOffset to a Duration object (or undefined if invalid)
|
|
50
111
|
* Handles function unwrapping, arrays, objects, strings, and numbers
|
|
51
112
|
*/
|
|
@@ -76,6 +137,15 @@ export function toOffsetDuration(offset) {
|
|
|
76
137
|
return undefined;
|
|
77
138
|
}
|
|
78
139
|
/**
|
|
140
|
+
* Normalise a {@link TOffset} into a plain millisecond count.
|
|
141
|
+
*
|
|
142
|
+
* @remarks
|
|
143
|
+
* Unwraps function offsets then takes a fast path for raw numbers to avoid
|
|
144
|
+
* allocating a `Duration` object. All other forms are delegated to
|
|
145
|
+
* {@link toOffsetDuration} and converted via `asMilliseconds()`.
|
|
146
|
+
*
|
|
147
|
+
* Returns `NONE` (0) when the offset cannot be resolved.
|
|
148
|
+
*
|
|
79
149
|
* Converts a TOffset to milliseconds
|
|
80
150
|
*/
|
|
81
151
|
export function toOffsetMs(offset) {
|
|
@@ -92,14 +162,23 @@ export function toOffsetMs(offset) {
|
|
|
92
162
|
return duration?.asMilliseconds() ?? NONE;
|
|
93
163
|
}
|
|
94
164
|
/**
|
|
95
|
-
*
|
|
165
|
+
* Async delay that supports early cancellation via `.kill()`.
|
|
96
166
|
*
|
|
167
|
+
* @remarks
|
|
168
|
+
* Accepts any {@link TOffset}, a JS `Date`, or a `Dayjs` instance. Absolute
|
|
169
|
+
* time values (`Date` / `Dayjs`) are converted to a relative delay from now at
|
|
170
|
+
* the moment `sleep()` is called.
|
|
171
|
+
*
|
|
172
|
+
* The returned {@link SleepReturn} is tracked in {@link ACTIVE_SLEEPS} for
|
|
173
|
+
* lifecycle-aware shutdown; it is removed automatically when the timer fires or
|
|
174
|
+
* `.kill()` is called.
|
|
175
|
+
*
|
|
176
|
+
* @example Simple usage
|
|
97
177
|
* ```typescript
|
|
98
178
|
* await sleep(5000);
|
|
99
179
|
* ```
|
|
100
180
|
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
181
|
+
* @example Early stop
|
|
103
182
|
* ```typescript
|
|
104
183
|
* const start = Date.now();
|
|
105
184
|
* const timer = sleep(5000);
|
|
@@ -136,6 +215,7 @@ export function sleep(target) {
|
|
|
136
215
|
ACTIVE_SLEEPS.add(out);
|
|
137
216
|
out.kill = (execute = "stop") => {
|
|
138
217
|
ACTIVE_SLEEPS.delete(out);
|
|
218
|
+
// only resolve the promise when the caller wants execution to continue after the kill
|
|
139
219
|
if (execute === "continue" && done) {
|
|
140
220
|
done();
|
|
141
221
|
}
|
|
@@ -144,13 +224,38 @@ export function sleep(target) {
|
|
|
144
224
|
};
|
|
145
225
|
return out;
|
|
146
226
|
}
|
|
227
|
+
// --- Debounce infrastructure --------------------------------------------------
|
|
228
|
+
/**
|
|
229
|
+
* Set of identifiers currently in the throttle window.
|
|
230
|
+
*
|
|
231
|
+
* @internal
|
|
232
|
+
*/
|
|
147
233
|
export const ACTIVE_THROTTLE = new Set();
|
|
234
|
+
/**
|
|
235
|
+
* Map of identifier → pending sleep for the active debounce window.
|
|
236
|
+
*
|
|
237
|
+
* @remarks
|
|
238
|
+
* Each key is a caller-supplied `identifier` string. When a new call arrives
|
|
239
|
+
* for an existing identifier, the current sleep is killed and replaced, pushing
|
|
240
|
+
* the expiry forward. Entries are removed once the delay resolves.
|
|
241
|
+
*
|
|
242
|
+
* @internal
|
|
243
|
+
*/
|
|
148
244
|
export const ACTIVE_DEBOUNCE = new Map();
|
|
149
245
|
/**
|
|
246
|
+
* Debounce an async operation by identifier.
|
|
247
|
+
*
|
|
248
|
+
* @remarks
|
|
249
|
+
* Each call resets the timer for `identifier`, so the operation does not
|
|
250
|
+
* proceed until no further calls for that identifier arrive within `timeout`.
|
|
251
|
+
* Multiple concurrent callers sharing the same `identifier` all wait on the
|
|
252
|
+
* same sliding window — the last writer wins.
|
|
253
|
+
*
|
|
150
254
|
* wait for duration after call before allowing next, extends for calls inside window
|
|
151
255
|
*/
|
|
152
256
|
export async function debounce(identifier, timeout) {
|
|
153
257
|
const current = ACTIVE_DEBOUNCE.get(identifier);
|
|
258
|
+
// kill the outstanding timer so the window slides forward from this call
|
|
154
259
|
if (!is.undefined(current)) {
|
|
155
260
|
current.kill("stop");
|
|
156
261
|
}
|
|
@@ -159,6 +264,8 @@ export async function debounce(identifier, timeout) {
|
|
|
159
264
|
await delay;
|
|
160
265
|
ACTIVE_DEBOUNCE.delete(identifier);
|
|
161
266
|
}
|
|
267
|
+
/** Async no-op that resolves after one event-loop tick via `sleep(0)`. */
|
|
162
268
|
export const asyncNoop = async () => await sleep(NONE);
|
|
269
|
+
/** Synchronous no-op — a named empty function for use as a default callback. */
|
|
163
270
|
export const noop = () => { };
|
|
164
271
|
//# sourceMappingURL=utilities.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utilities.mjs","sourceRoot":"","sources":["../../src/helpers/utilities.mts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,QAAQ,MAAM,0BAA0B,CAAC;AAEhD,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAGlC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AAEvB,wDAAwD;
|
|
1
|
+
{"version":3,"file":"utilities.mjs","sourceRoot":"","sources":["../../src/helpers/utilities.mts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,QAAQ,MAAM,0BAA0B,CAAC;AAEhD,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAGlC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AAEvB,wDAAwD;AAExD,kFAAkF;AAClF,yEAAyE;AACzE,2EAA2E;AAC3E,oEAAoE;AAEpE,uEAAuE;AACvE,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC;AAEtB,kFAAkF;AAClF,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC;AAEtB,uDAAuD;AACvD,MAAM,CAAC,MAAM,IAAI,GAAG,GAAG,CAAC;AAExB,yDAAyD;AACzD,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,GAAG,CAAC,CAAC;AAE/B,2DAA2D;AAC3D,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,GAAG,CAAC,CAAC;AAEhC;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC;AAE/B,oEAAoE;AACpE,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,CAAC;AAE/B,uEAAuE;AACvE,OAAO;AACP,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAEpB,8DAA8D;AAC9D,gBAAgB;AAChB,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC;AAEvB;;;GAGG;AACH,iBAAiB;AACjB,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC;AAE9B,oEAAoE;AACpE,6BAA6B;AAC7B,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC;AAE3B,0EAA0E;AAC1E,mBAAmB;AACnB,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,CAAC;AAExB,0EAA0E;AAC1E,UAAU;AACV,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC;AAEtB,8DAA8D;AAC9D,gBAAgB;AAChB,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC;AAEvB,wEAAwE;AACxE,6BAA6B;AAC7B,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC;AAEvB,6DAA6D;AAC7D,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC;AAEtB,gDAAgD;AAChD,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC;AAKvB,8EAA8E;AAC9E,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC;AAEvB,4EAA4E;AAC5E,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC;AAE3B,iFAAiF;AACjF,qBAAqB;AACrB,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC,CAAC;AAE5B,0EAA0E;AAC1E,UAAU;AACV,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC;AAEvB,uDAAuD;AACvD,MAAM,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC;AAE7B,wDAAwD;AACxD,MAAM,CAAC,MAAM,IAAI,GAAG,SAAS,CAAC;AAE9B,wDAAwD;AACxD,MAAM,CAAC,MAAM,GAAG,GAAG,UAAU,CAAC;AAE9B,sDAAsD;AACtD,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,GAAG,GAAG,CAAC;AAE5B,sDAAsD;AACtD,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,CAAC;AAE3B,sEAAsE;AACtE,MAAM,CAAC,MAAM,OAAO,GAAG,GAAG,CAAC;AAE3B,iEAAiE;AACjE,MAAM,CAAC,MAAM,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC;AAE9B,iFAAiF;AAEjF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,GAAG,EAAe,CAAC;AAEpD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAe;IAC9C,sBAAsB;IACtB,IAAI,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACxB,MAAM,GAAG,MAAM,EAAE,CAAC;IACpB,CAAC;IACD,oBAAoB;IACpB,IAAI,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;QACrB,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,MAAM,CAAC;QAC9B,OAAO,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACtC,CAAC;IACD,uCAAuC;IACvC,IAAI,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QACtB,OAAO,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC;YAC7B,CAAC,CAAE,MAAmB;YACtB,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAiC,CAAC,CAAC;IACxD,CAAC;IACD,gCAAgC;IAChC,IAAI,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QACtB,OAAO,KAAK,CAAC,QAAQ,CAAC,KAAK,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IACrD,CAAC;IACD,cAAc;IACd,IAAI,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QACtB,OAAO,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,UAAU,CAAC,MAAe;IACxC,sBAAsB;IACtB,IAAI,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACxB,MAAM,GAAG,MAAM,EAAE,CAAC;IACpB,CAAC;IACD,gFAAgF;IAChF,IAAI,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QACtB,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,sDAAsD;IACtD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAC1C,OAAO,QAAQ,EAAE,cAAc,EAAE,IAAI,IAAI,CAAC;AAC5C,CAAC;AAgBD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,KAAK,CAAC,MAA8B;IAClD,6BAA6B;IAC7B,IAAI,IAA8B,CAAC;IAEnC,MAAM,YAAY,GAAG,GAAW,EAAE;QAChC,8BAA8B;QAC9B,IAAI,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACpB,OAAO,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvC,CAAC;QACD,+BAA+B;QAC/B,IAAI,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;YACrB,OAAO,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvC,CAAC;QACD,mCAAmC;QACnC,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;QAC9B,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,EAAE,CAAC;QACT,CAAC;QACD,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC;IAEnB,6CAA6C;IAC7C,gDAAgD;IAChD,MAAM,GAAG,GAAG,IAAI,OAAO,CAAO,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAgB,CAAC;IAC9D,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACvB,GAAG,CAAC,IAAI,GAAG,CAAC,OAAO,GAAG,MAAM,EAAE,EAAE;QAC9B,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC1B,sFAAsF;QACtF,IAAI,OAAO,KAAK,UAAU,IAAI,IAAI,EAAE,CAAC;YACnC,IAAI,EAAE,CAAC;QACT,CAAC;QACD,YAAY,CAAC,OAAO,CAAC,CAAC;QACtB,IAAI,GAAG,SAAS,CAAC;IACnB,CAAC,CAAC;IACF,OAAO,GAAG,CAAC;AACb,CAAC;AAED,iFAAiF;AAEjF;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,GAAG,EAAU,CAAC;AAEjD;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,GAAG,EAAuB,CAAC;AAE9D;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,UAAkB,EAAE,OAAgB;IACjE,MAAM,OAAO,GAAG,eAAe,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAChD,yEAAyE;IACzE,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACvB,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,eAAe,CAAC,GAAG,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IACvC,MAAM,KAAK,CAAC;IACZ,eAAe,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;AACrC,CAAC;AAED,0EAA0E;AAC1E,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;AAEvD,gFAAgF;AAChF,MAAM,CAAC,MAAM,IAAI,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC"}
|