@asaidimu/utils-sync 2.3.0 → 2.3.2

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/index.d.mts DELETED
@@ -1,809 +0,0 @@
1
- interface DebouncerOptions {
2
- /**
3
- * Quiet period in milliseconds. The last-enqueued function runs after
4
- * no new calls have arrived for this duration.
5
- * @default 300
6
- */
7
- delay?: number;
8
- /**
9
- * If true, also fires immediately on the leading edge (first call in a
10
- * quiet period), then debounces subsequent calls normally.
11
- *
12
- * Leading-edge semantics: the leading call fires immediately and clears
13
- * _pendingFn. Any calls arriving *while* the leading execution is in flight
14
- * register as a new trailing call and will be resolved by the trailing timer
15
- * when the quiet period expires. Calls arriving during the leading execution
16
- * are never lost.
17
- *
18
- * @default false
19
- */
20
- leading?: boolean;
21
- }
22
- /**
23
- * Result when the debounced function successfully executed.
24
- */
25
- type DebouncerOk<T> = {
26
- status: "ok";
27
- value: T;
28
- };
29
- /**
30
- * Result when the debounced function threw an error.
31
- */
32
- type DebouncerError = {
33
- status: "error";
34
- error: unknown;
35
- };
36
- /**
37
- * Result when the debounced call was cancelled before execution.
38
- */
39
- type DebouncerCancelled = {
40
- status: "cancelled";
41
- };
42
- /**
43
- * Discriminated union of all possible Debouncer outcomes.
44
- *
45
- * - `DebouncerOk<T>`: function ran and returned a value.
46
- * - `DebouncerError`: function ran and threw an error.
47
- * - `DebouncerCancelled`: call was cancelled before it ran.
48
- */
49
- type DebouncerResult<T> = DebouncerOk<T> | DebouncerError | DebouncerCancelled;
50
- /**
51
- * Collapses rapid successive calls into a single execution.
52
- *
53
- * Each call to `do()` returns a promise that resolves with the result of the
54
- * debounced execution — i.e. all callers within the same quiet window share
55
- * the same result. The function that actually runs is always the *last* one
56
- * enqueued before the delay expires.
57
- *
58
- * @example
59
- * const debounced = new Debouncer({ delay: 200 });
60
- * // Called rapidly three times — only the last fn runs.
61
- * const [a, b, c] = await Promise.all([
62
- * debounced.do(() => fetch("/api/search?q=h")),
63
- * debounced.do(() => fetch("/api/search?q=he")),
64
- * debounced.do(() => fetch("/api/search?q=hel")),
65
- * ]);
66
- * // a.status === "ok" and a.value is the result of the third fetch.
67
- * // b and c share the same result as a.
68
- */
69
- declare class Debouncer<T = void> {
70
- private _delay;
71
- private _leading;
72
- private _timer;
73
- private _pendingFn;
74
- private _pendingResolvers;
75
- private _leadingFired;
76
- constructor(options?: DebouncerOptions);
77
- /**
78
- * Enqueues a function and returns a promise that resolves with its result.
79
- *
80
- * All callers within the same quiet window share the same result — the
81
- * function that actually runs is the *last* one enqueued before the delay
82
- * expires. Use this when you need the return value of the debounced call.
83
- *
84
- * For fire-and-forget use (void fns, event handlers), prefer `fire()` to
85
- * avoid unhandled-promise-rejection warnings and make intent explicit.
86
- *
87
- * @param fn - The function to debounce.
88
- * @returns A promise resolving with a DebouncerResult discriminated union.
89
- */
90
- do(fn: () => Promise<T> | T): Promise<DebouncerResult<T>>;
91
- /**
92
- * Enqueues a function without returning a promise (fire-and-forget).
93
- *
94
- * Identical debounce semantics to `do()` — the last-enqueued function runs
95
- * after the quiet period. Use this for void callbacks, DOM event handlers,
96
- * or any caller that doesn't care about the result. No dangling promise,
97
- * no unhandled-rejection risk.
98
- *
99
- * @param fn - The function to debounce.
100
- */
101
- fire(fn: () => Promise<T> | T): void;
102
- /**
103
- * Shared enqueue logic for both `do()` and `fire()`.
104
- *
105
- */
106
- private _enqueue;
107
- /**
108
- * Immediately cancels any pending debounced execution.
109
- * All waiting callers resolve with `{ status: "cancelled" }`.
110
- */
111
- cancel(): void;
112
- /**
113
- * Immediately executes the pending function (if any), bypassing the remaining delay.
114
- * All waiting callers receive the result.
115
- */
116
- flush(): Promise<DebouncerResult<T> | null>;
117
- /** Returns true if a debounced call is currently pending. */
118
- pending(): boolean;
119
- /**
120
- * Executes the latest pending function and resolves all waiting callers.
121
- */
122
- private _fire;
123
- }
124
-
125
- /**
126
- * Severity levels for structured issues and errors.
127
- */
128
- type Severity = "error" | "warning" | "info";
129
- /**
130
- * Represents a detailed validation or operational problem.
131
- * Designed to be machine-readable while remaining human-friendly.
132
- */
133
- interface Issue {
134
- /** Machine-readable identifier (e.g., `"REQUIRED_FIELD_MISSING"`). */
135
- readonly code: string;
136
- /** Human-readable description of the problem. */
137
- readonly message: string;
138
- /** Field path in a document or state (e.g., `"users.0.email"`). */
139
- readonly path?: string;
140
- /** Optional array index when the issue relates to a specific element. */
141
- readonly index?: number;
142
- /** Seriousness of the issue. Defaults to `"error"`. */
143
- readonly severity?: Severity;
144
- /** Optional detailed explanation, can be multi-line. */
145
- readonly description?: string;
146
- /** Nested issues that caused this one. */
147
- readonly cause?: readonly Issue[];
148
- }
149
- /**
150
- * Standardized error code format: `CATEGORY-XXX[-SUFFIX]`
151
- *
152
- * @example
153
- * ```typescript
154
- * // VAL-001 (Validation: required field missing)
155
- * // DB-001-NF (Database: not found)
156
- * // AUTH-001-DENIED (Auth: permission denied)
157
- * ```
158
- */
159
- interface ErrorCodeMetadata {
160
- /** The formal unique error code identifier (e.g., `"VAL-001"`). */
161
- readonly code: string;
162
- /** Human-readable uppercase name for the error type (e.g., `"VALIDATION_FAILED"`). */
163
- readonly name: string;
164
- /** Detailed description of when and why this error occurs. */
165
- readonly description: string;
166
- /** Suggested immediate action for engineers or systems to handle or resolve the error. */
167
- readonly action?: string;
168
- /** HTTP status code mapping for upstream REST APIs (e.g., `404`, `500`). */
169
- readonly httpStatus?: number;
170
- /** Operational category this error belongs to. */
171
- readonly category: ErrorCategory;
172
- /** Recommended logging level threshold (`"debug" | "info" | "warn" | "error"`). */
173
- readonly logLevel?: "debug" | "info" | "warn" | "error";
174
- }
175
- /**
176
- * Categories classifying the origin and nature of an error.
177
- */
178
- type ErrorCategory = "validation" | "database" | "auth" | "business" | "system" | "network" | "concurrency" | "custom";
179
- /**
180
- * Configuration options container used when constructing a new `SystemError`.
181
- */
182
- interface SystemErrorParams {
183
- /** The unique registered error code identifier (e.g., `ErrorCodes.INTERNAL_ERROR.code`). */
184
- code: string;
185
- /** Explicit error message overrides. If omitted, defaults to the error code's description. */
186
- message?: string;
187
- /** Operational severity tier. Defaults to `"error"`. */
188
- severity?: Severity;
189
- /** State path or key where the operational failure occurred (e.g., `"users.0.email"`). */
190
- path?: string;
191
- /** The function block, track component, or routing process executing during failure. */
192
- operation?: string;
193
- /** Flat array of precise granular input issues or schema violations. */
194
- issues?: readonly Issue[];
195
- /** The underlying trigger cause. Accepts native `Error` instances, custom errors, or concurrent `Error[]` arrays. */
196
- cause?: unknown | unknown[];
197
- /** Ad-hoc modifications overriding base properties mapped from the code registry. */
198
- metadata?: Partial<Omit<ErrorCodeMetadata, "code" | "category">>;
199
- }
200
- /**
201
- * Primary domain operational error wrapper.
202
- * Unfolds historical deep error hierarchies into flat, parallel-aware trace timelines.
203
- */
204
- declare class SystemError extends Error {
205
- /** The associated error identifier code (e.g., `"SYS-001"`). */
206
- readonly code: string;
207
- /** Static documentation mapping and registration rules bound to this code type. */
208
- readonly codeMetadata: ErrorCodeMetadata;
209
- /** Severity tier grading the operational consequence of this failure. */
210
- readonly severity: Severity;
211
- /** Target state or document path where processing failed. */
212
- readonly path?: string;
213
- /** Active system segment, workflow node, or function context executing during failure. */
214
- readonly operation?: string;
215
- /** Detailed sub-layer list representing structural data validation failures. */
216
- readonly issues: readonly Issue[];
217
- /** Raw backing trigger, array of concurrent branches, or source error instance. */
218
- readonly cause?: unknown | unknown[];
219
- /** Exact moment this error was instantiated (ISO string). */
220
- readonly timestamp: string;
221
- /**
222
- * Instantiate a structurally traceable `SystemError`.
223
- * @param params - Configuration parameters outlining the error's state context.
224
- */
225
- constructor(params: SystemErrorParams);
226
- /**
227
- * Generates a separate immutable clone assigning a target file, state, or field path.
228
- */
229
- withPath(path: string): SystemError;
230
- /**
231
- * Generates a separate immutable clone assigning a specific execution block or track tracking context.
232
- */
233
- withOperation(operation: string): SystemError;
234
- /**
235
- * Appends an operational validation structural issue to a fresh clone of this error.
236
- */
237
- withIssue(issue: Issue): SystemError;
238
- /**
239
- * Appends multiple validation issues onto a fresh clone of this error instance.
240
- */
241
- withIssues(issues: readonly Issue[]): SystemError;
242
- /**
243
- * Maps a backing raw trigger or concurrent array tracking set to a fresh clone of this error instance.
244
- */
245
- withCause(cause: unknown | unknown[]): SystemError;
246
- /**
247
- * Retrieves the recommended HTTP Status code mapped to this error's code metadata registry.
248
- */
249
- getHttpStatus(): number | undefined;
250
- /**
251
- * Unrolls execution hierarchies chronologically, isolating parallel pipelines into clear trace frames.
252
- * Always returns an array of trace nodes.
253
- */
254
- private extractChronologicalTrace;
255
- /**
256
- * Transforms the error payload into a flattened transmission format.
257
- * Strips recursive depth in favor of an array-mapped chronological failure `trace`.
258
- */
259
- toJSON(): Record<string, unknown>;
260
- /**
261
- * Generates a flat payload matching `toJSON` format requirements for centralized platform ingestion engines.
262
- */
263
- toLogEntry(): Record<string, unknown>;
264
- /**
265
- * Terminal terminal dump representation formatting details cleanly into plain strings.
266
- */
267
- toString(): string;
268
- }
269
-
270
- /** Represents all errors within the sync system */
271
- declare class SyncError extends SystemError {
272
- constructor(message: string, cause?: unknown);
273
- }
274
- declare class TimeoutError extends SyncError {
275
- constructor(message?: string);
276
- }
277
- declare class OnceExecutionConflict extends SyncError {
278
- constructor(cause?: unknown);
279
- }
280
- declare class SerializerExecutionDone extends SyncError {
281
- constructor(cause?: unknown);
282
- }
283
-
284
- /**
285
- * A one-shot gate that starts closed and opens exactly once.
286
- *
287
- * All current and future `wait()` callers resolve immediately once `open()` is
288
- * called. Unlike Once, Latch carries no return value and has no retry logic —
289
- * it is a pure signalling primitive.
290
- *
291
- * Typical use: coordinate startup, signal that an initialisation phase is done,
292
- * or gate downstream work on a single event.
293
- *
294
- * @example
295
- * const ready = new Latch();
296
- * // Consumer
297
- * await ready.wait();
298
- * // Producer (elsewhere)
299
- * ready.open();
300
- */
301
- declare class Latch {
302
- private _open;
303
- private _resolve;
304
- private _promise;
305
- constructor();
306
- /**
307
- * Opens the latch. All current and future waiters resolve immediately.
308
- * Calling open() more than once is a no-op.
309
- */
310
- open(): void;
311
- /**
312
- * Returns a promise that resolves when the latch is opened.
313
- * If already open, resolves on the next microtask checkpoint.
314
- *
315
- * @param timeout - Optional maximum wait time in milliseconds.
316
- * @throws {TimeoutError} If the latch does not open within the timeout.
317
- */
318
- wait(timeout?: number): Promise<void>;
319
- /**
320
- * Synchronously checks whether the latch has been opened.
321
- */
322
- isOpen(): boolean;
323
- }
324
-
325
- interface MutexOptions {
326
- /**
327
- * Maximum number of pending requests allowed in the queue.
328
- * If exceeded, tryLock/lock will fail.
329
- * @default Infinity
330
- */
331
- capacity?: number;
332
- /**
333
- * Controls how lock handoff is scheduled when a waiter is unblocked.
334
- *
335
- * - `"macrotask"` (default): Uses setTimeout(fn, 0) to yield to the event
336
- * loop between handoffs. Prevents microtask starvation under heavy
337
- * contention — I/O, rendering, and other macrotasks can run between
338
- * lock acquisitions. Use for Serializer and other coarse-grained
339
- * serializers.
340
- *
341
- * - `"microtask"`: Uses queueMicrotask(fn) for handoff. Near-zero latency
342
- * between acquisitions — no macrotask delay. Safe when you need
343
- * back-to-back operations to complete as fast as possible and starvation
344
- * is not a concern (e.g. Once, Semaphore where builds are infrequent
345
- * and latency matters more than fairness).
346
- */
347
- yieldMode?: "macrotask" | "microtask";
348
- }
349
- /**
350
- * A mutual exclusion lock.
351
- * Allows only one execution context to access a resource at a time.
352
- *
353
- * Yield mode is configurable per instance:
354
- * - "macrotask" (default): yields between handoffs, preventing microtask starvation.
355
- * - "microtask": zero-delay handoff for latency-sensitive paths.
356
- */
357
- declare class Mutex {
358
- private _locked;
359
- private _capacity;
360
- private _yieldMode;
361
- private waiters;
362
- constructor(options?: MutexOptions);
363
- /**
364
- * Acquires the lock. If already held, waits until released or timeout reached.
365
- *
366
- * @param timeout - Optional maximum wait time in milliseconds.
367
- * @throws {TimeoutError} If the lock cannot be acquired within the timeout.
368
- * @throws {Error} If the wait queue is full (backpressure).
369
- */
370
- lock(timeout?: number): Promise<void>;
371
- /**
372
- * Attempts to acquire the lock without waiting.
373
- * @returns `true` if the lock was acquired, `false` otherwise.
374
- */
375
- tryLock(): boolean;
376
- /**
377
- * Releases the lock, scheduling the next waiter according to yieldMode.
378
- *
379
- * When a waiter exists, `_locked` intentionally remains `true` — ownership
380
- * transfers directly to the next waiter without ever clearing the flag.
381
- * Only when the queue is empty is `_locked` set to false.
382
- *
383
- * @throws {Error} If the mutex is not currently locked.
384
- */
385
- unlock(): void;
386
- /** Returns true if the mutex is currently locked. */
387
- locked(): boolean;
388
- /** Returns the number of operations waiting for the lock. */
389
- pending(): number;
390
- }
391
-
392
- type OnceResult<T> = {
393
- value: T | null;
394
- error?: unknown;
395
- };
396
- /**
397
- * Ensures a specific task is executed exactly once, regardless of concurrent callers.
398
- * Handles race conditions, caching, and optional retries on failure.
399
- *
400
- * Uses microtask yield mode for its internal mutex — builds are latency-sensitive
401
- * and starvation is not a concern (only one build runs at a time by design).
402
- *
403
- * @template T - The type of value returned by the execution.
404
- */
405
- declare class Once<T = void> {
406
- private mutex;
407
- private promise;
408
- private _value;
409
- private _error;
410
- private _done;
411
- private retry;
412
- private throws;
413
- constructor({ retry, throws }?: {
414
- retry?: boolean;
415
- throws?: boolean;
416
- });
417
- /**
418
- * Manually sets a value, marking the operation as done.
419
- * Throws if the operation is already done or currently running.
420
- *
421
- * @param value - The value to resolve to.
422
- */
423
- resolve(value: T): void;
424
- /**
425
- * Execute the function if it hasn't been executed yet.
426
- * Subsequent calls return the result of the first execution.
427
- *
428
- * @param fn - The function to execute.
429
- * @param timeout - Max wait time in ms (includes lock wait + execution time).
430
- */
431
- do(fn: () => Promise<T> | T, timeout?: number): Promise<OnceResult<T>>;
432
- /**
433
- * Executes the function synchronously if it hasn't been executed yet.
434
- * If an async operation is pending or the lock is contended, it will fail immediately.
435
- * The failure is returned as an error state, OR thrown if `throws: true` is configured.
436
- *
437
- * @param fn - The synchronous function to execute.
438
- * @returns The result of the execution.
439
- */
440
- doSync(fn: () => T): OnceResult<T>;
441
- /**
442
- * Returns true if the operation is currently executing.
443
- *
444
- * Uses ready() as the canonical check: running is its logical complement
445
- * when a promise is in flight. This correctly handles the brief window where
446
- * _done=true but the promise hasn't been cleared yet in finally.
447
- */
448
- running(): boolean;
449
- /**
450
- * Returns the current state without waiting.
451
- */
452
- peek(): OnceResult<T>;
453
- /**
454
- * Returns the stored value if successful, otherwise throws the stored error.
455
- * Throws if the operation is not yet complete.
456
- */
457
- get(): T | null;
458
- /**
459
- * Resets the instance, allowing the action to run again on the next call.
460
- *
461
- * @throws {Error} If called while an operation is currently executing,
462
- * as this would leave the in-flight promise in an inconsistent state.
463
- */
464
- reset(): void;
465
- /**
466
- * Returns true if the operation has finished (success or final failure).
467
- */
468
- done(): boolean;
469
- /**
470
- * Returns the in-flight execution promise if one is currently running, null otherwise.
471
- *
472
- * Use this to join an in-progress operation without triggering a new one.
473
- */
474
- current(): Promise<OnceResult<T>> | null;
475
- /**
476
- * Awaits a promise with an optional timeout.
477
- *
478
- * We clear the timer on the winning branch, consistent with the
479
- * Mutex/Semaphore/Latch timeout pattern throughout this module.
480
- */
481
- private _awaitWithTimeout;
482
- }
483
-
484
- interface RWMutexOptions {
485
- /**
486
- * Controls how lock handoff is scheduled when a waiter is unblocked.
487
- *
488
- * - `"microtask"` (default): Uses queueMicrotask(fn). Near-zero latency
489
- * between handoffs. Appropriate for RWMutex because readers are woken in
490
- * bulk and writers are rarely contended enough to cause starvation.
491
- *
492
- * - `"macrotask"`: Uses setTimeout(fn, 0) to yield to the event loop between
493
- * handoffs. Use if you observe microtask starvation under extreme write
494
- * contention on this specific lock.
495
- */
496
- yieldMode?: "macrotask" | "microtask";
497
- }
498
- /**
499
- * A read-write mutex with writer preference.
500
- *
501
- * - Multiple readers can hold the lock concurrently.
502
- * - Writers get exclusive access — no readers or other writers.
503
- * - Writer preference: once a writer is waiting, new readers queue behind it.
504
- * This prevents writer starvation under read-heavy loads.
505
- *
506
- * Readers should call `rlock()` / `runlock()`.
507
- * Writers should call `lock()` / `unlock()`.
508
- * Prefer the `read()` and `write()` convenience wrappers to avoid lock leaks.
509
- */
510
- declare class RWMutex {
511
- private _readers;
512
- private _writeLocked;
513
- private _pendingWriters;
514
- private _yieldMode;
515
- private readerWaiters;
516
- private writerWaiters;
517
- constructor(options?: RWMutexOptions);
518
- /**
519
- * Acquires a read lock. Blocks if a writer holds or is waiting for the lock.
520
- *
521
- * @param timeout - Optional maximum wait time in milliseconds.
522
- * @throws {TimeoutError} If the read lock cannot be acquired within the timeout.
523
- */
524
- rlock(timeout?: number): Promise<void>;
525
- /**
526
- * Releases a read lock.
527
- * @throws {Error} If no read lock is currently held.
528
- */
529
- runlock(): void;
530
- /**
531
- * Acquires the write lock. Blocks until all current readers and any prior
532
- * writers have finished.
533
- *
534
- * @param timeout - Optional maximum wait time in milliseconds.
535
- * @throws {TimeoutError} If the write lock cannot be acquired within the timeout.
536
- */
537
- lock(timeout?: number): Promise<void>;
538
- /**
539
- * Releases the write lock.
540
- * Wakes the next pending writer if one exists; otherwise wakes all pending readers.
541
- *
542
- * @throws {Error} If no write lock is currently held.
543
- */
544
- unlock(): void;
545
- /**
546
- * Runs a function under a read lock, releasing it when done.
547
- * Prefer this over manual rlock/runlock to avoid lock leaks.
548
- */
549
- read<T>(fn: () => Promise<T> | T, timeout?: number): Promise<T>;
550
- /**
551
- * Runs a function under the write lock, releasing it when done.
552
- * Prefer this over manual lock/unlock to avoid lock leaks.
553
- */
554
- write<T>(fn: () => Promise<T> | T, timeout?: number): Promise<T>;
555
- /** Returns true if the write lock is currently held. */
556
- writeLocked(): boolean;
557
- /** Returns the number of active read lock holders. */
558
- readers(): number;
559
- /** Returns the number of writers currently waiting for the lock. */
560
- pendingWriters(): number;
561
- /** Returns the number of readers currently waiting for the lock. */
562
- pendingReaders(): number;
563
- /**
564
- * Wakes the next writer if the lock is free and a writer is waiting.
565
- * Returns true if a writer was woken, false otherwise.
566
- */
567
- private _tryWakeWriter;
568
- /**
569
- * Wakes all pending readers (called when a writer releases and no writers are queued).
570
- */
571
- private _wakeAllReaders;
572
- /**
573
- * Schedules a waiter callback according to the configured yieldMode.
574
- */
575
- private _schedule;
576
- }
577
-
578
- interface SemaphoreOptions extends MutexOptions {
579
- /**
580
- * Number of concurrent holders allowed.
581
- * Inherits `capacity` and `yieldMode` from MutexOptions.
582
- * @default 1 (equivalent to a Mutex)
583
- */
584
- slots?: number;
585
- }
586
- /**
587
- * A counting semaphore — generalises Mutex to allow up to N concurrent holders.
588
- *
589
- * Useful for rate-limiting concurrency: e.g. "at most 3 in-flight HTTP requests".
590
- * With slots=1 it behaves identically to Mutex.
591
- *
592
- * Accepts the same `capacity` and `yieldMode` options as Mutex, plus `slots`.
593
- */
594
- declare class Semaphore {
595
- private _slots;
596
- private _available;
597
- private _capacity;
598
- private _yieldMode;
599
- private waiters;
600
- constructor(options?: SemaphoreOptions);
601
- /**
602
- * Acquires one slot. If all slots are taken, waits until one is released.
603
- *
604
- * @param timeout - Optional maximum wait time in milliseconds.
605
- * @throws {TimeoutError} If a slot cannot be acquired within the timeout.
606
- * @throws {Error} If the wait queue is full.
607
- */
608
- acquire(timeout?: number): Promise<void>;
609
- /**
610
- * Attempts to acquire a slot without waiting.
611
- * @returns `true` if a slot was acquired, `false` otherwise.
612
- */
613
- tryAcquire(): boolean;
614
- /**
615
- * Releases one slot. If waiters are queued, the next one is scheduled
616
- * according to yieldMode.
617
- *
618
- * @throws {Error} If no slot is currently held (release without acquire).
619
- */
620
- release(): void;
621
- /**
622
- * Runs a function with one acquired slot, releasing it when done.
623
- * Convenience wrapper — prefer this over manual acquire/release.
624
- */
625
- run<T>(fn: () => Promise<T> | T, timeout?: number): Promise<T>;
626
- /** Number of slots currently free. */
627
- available(): number;
628
- /** Number of callers waiting for a slot. */
629
- pending(): number;
630
- /** Total slot count (as configured). */
631
- slots(): number;
632
- }
633
-
634
- type SerializerResult<T> = {
635
- value: T | null;
636
- error?: unknown;
637
- };
638
- interface SerializerOptions {
639
- /**
640
- * Max items in queue. If full, .do() returns an error immediately.
641
- * @default 1000
642
- */
643
- capacity?: number;
644
- /**
645
- * Yield mode for the internal mutex. Defaults to "macrotask" for
646
- * coarse-grained serializers. Use "microtask" for fine-grained
647
- * latency-sensitive serializers.
648
- */
649
- yieldMode?: "macrotask" | "microtask";
650
- }
651
- /**
652
- * Ensures tasks are executed sequentially (FIFO).
653
- * Maintains the result of the last successful execution.
654
- * Includes backpressure protection via configurable queue capacity.
655
- */
656
- declare class Serializer<T = void> {
657
- private mutex;
658
- private _done;
659
- private _lastValue;
660
- private _lastError;
661
- private _hasRun;
662
- constructor(options?: SerializerOptions);
663
- /**
664
- * Enqueue a function to be executed after all previous tasks complete.
665
- *
666
- * @param fn - The function to execute.
667
- * @param timeout - Max time to wait to acquire the lock.
668
- * @returns Object containing the value or error.
669
- */
670
- do(fn: () => Promise<T> | T, timeout?: number): Promise<SerializerResult<T | null>>;
671
- /**
672
- * Returns the result of the last execution.
673
- *
674
- * Returns `{ value: null, error: undefined }` both when the serializer has
675
- * never run and when it ran and returned null — use `hasRun()` to distinguish
676
- * these two cases.
677
- */
678
- peek(): SerializerResult<T | null>;
679
- /**
680
- * Returns true if at least one task has been executed (successfully or not).
681
- */
682
- hasRun(): boolean;
683
- /**
684
- * Permanently closes the serializer.
685
- * Subsequent calls to `do()` will fail immediately with SerializerExecutionDone.
686
- */
687
- close(): void;
688
- /** Returns the number of tasks currently waiting. */
689
- pending(): number;
690
- /** Returns true if a task is currently executing. */
691
- running(): boolean;
692
- }
693
-
694
- interface SharedResourceOptions {
695
- /**
696
- * How long to wait after the last subscriber leaves before cleaning up.
697
- * - "microtask": (Default) Waits until the end of the current synchronous execution tick.
698
- * Perfect for React StrictMode or concurrent rendering.
699
- * - number: Waits for the specified milliseconds. Useful for debouncing rapid reconnects.
700
- * - "sync": Cleans up immediately (bypasses the grace period entirely).
701
- */
702
- gracePeriod?: "microtask" | "sync" | number;
703
- }
704
- /**
705
- * Manages the lifecycle of a reference-counted shared resource.
706
- * Ensures the resource is created exactly once on the first acquisition,
707
- * and cleaned up only when the last subscriber releases it (after an optional grace period).
708
- */
709
- declare class SharedResource<T> {
710
- private readonly factory;
711
- private readonly onCleanup;
712
- private readonly options;
713
- private _count;
714
- private readonly init;
715
- private pendingMicrotask;
716
- private cleanupTimer?;
717
- constructor(factory: () => Promise<T> | T, onCleanup: (value: T | null) => void | Promise<void>, options?: SharedResourceOptions);
718
- /**
719
- * The current number of active subscribers.
720
- */
721
- get subscribers(): number;
722
- /**
723
- * Increments the reference count and ensures the resource is initialized.
724
- * If a cleanup was scheduled but hasn't executed yet, it is cancelled.
725
- *
726
- * @returns The initialized resource.
727
- */
728
- acquire(): Promise<T>;
729
- /**
730
- * Decrements the reference count.
731
- * If the count reaches zero, the cleanup process is scheduled according to the grace period.
732
- */
733
- release(): void;
734
- /**
735
- * Returns the current value synchronously if it has been successfully initialized.
736
- * Returns null if initialization is pending, failed, or hasn't started.
737
- */
738
- peek(): T | null;
739
- /**
740
- * Forcibly tears down the resource, ignoring the reference count and grace period.
741
- * Useful for emergency teardowns (e.g., container disposal).
742
- */
743
- forceCleanup(): void;
744
- /**
745
- * Cancels any scheduled cleanup tasks.
746
- * This is the core mechanism that prevents React StrictMode from destroying the resource.
747
- */
748
- private cancelPendingCleanup;
749
- /**
750
- * Determines how to schedule the cleanup based on the configured options.
751
- */
752
- private scheduleCleanup;
753
- /**
754
- * Performs the actual teardown of the resource and resets the initialization state.
755
- */
756
- private executeCleanup;
757
- }
758
-
759
- interface ResourceRegistryOptions<T, K, O> {
760
- /**
761
- * Async factory: receives the key and per-call options.
762
- * Only invoked when a resource does not already exist.
763
- */
764
- onCreate?: (key: K, options: O) => Promise<T>;
765
- /**
766
- * Sync factory: receives the key and per-call options.
767
- * Only invoked when a resource does not already exist.
768
- */
769
- onCreateSync?: (key: K, options: O) => T;
770
- /**
771
- * Optional disposer for explicit cleanup (release/clear).
772
- */
773
- onDispose?: (resource: T) => void | Promise<void>;
774
- /**
775
- * Optional callback fired when the resource is GC'd.
776
- */
777
- onEvict?: (key: K) => void;
778
- }
779
- declare class ResourceRegistry<R extends object, K extends string | number = string, O = void> {
780
- private readonly entries;
781
- private readonly resourceToOnce;
782
- private readonly finalizer;
783
- private readonly onCreate?;
784
- private readonly onCreateSync?;
785
- private readonly onDispose?;
786
- private readonly onEvict?;
787
- constructor(options: ResourceRegistryOptions<R, K, O>);
788
- /**
789
- * Get or create a resource.
790
- *
791
- * IMPORTANT: The `options` are ONLY used if the resource does NOT exist yet.
792
- * If the resource already exists (or is being created by another concurrent call),
793
- * the `options` are ignored and the existing instance is returned.
794
- *
795
- * This matches the original `registry.ts` behavior.
796
- */
797
- get(key: K, options: O, timeout?: number): Promise<R>;
798
- /**
799
- * Synchronous version of `get`.
800
- * Options are only used on the first creation.
801
- */
802
- getSync(key: K, options: O): R;
803
- release(key: K): Promise<boolean>;
804
- clear(): Promise<void>;
805
- has(key: K): boolean;
806
- get size(): number;
807
- }
808
-
809
- export { Debouncer, type DebouncerCancelled, type DebouncerError, type DebouncerOk, type DebouncerOptions, type DebouncerResult, Latch, Mutex, type MutexOptions, Once, OnceExecutionConflict, type OnceResult, RWMutex, type RWMutexOptions, ResourceRegistry, type ResourceRegistryOptions, Semaphore, type SemaphoreOptions, Serializer, SerializerExecutionDone, type SerializerOptions, type SerializerResult, SharedResource, type SharedResourceOptions, SyncError, TimeoutError };