@actuallab/core 13.0.25 → 13.0.167

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/dist/index.d.ts CHANGED
@@ -108,10 +108,11 @@ declare class Result<T> implements IResult<T> {
108
108
  readonly hasError: boolean;
109
109
  private readonly _value;
110
110
  private readonly _error;
111
- constructor(value: T | undefined, error?: unknown);
111
+ constructor(value: T | undefined, error?: unknown, hasError?: boolean);
112
112
  get value(): T;
113
113
  get error(): unknown;
114
114
  get valueOrUndefined(): T | undefined;
115
+ equals(other: Result<T>, valueComparer?: (a: T, b: T) => boolean): boolean;
115
116
  static ok<T>(value: T): Result<T>;
116
117
  static error<T>(error: unknown): Result<T>;
117
118
  }
@@ -129,12 +130,16 @@ declare class AsyncContextKey<T> {
129
130
  /** General-purpose typed context container — named for forward-compatibility with TC39 AsyncContext proposal. */
130
131
  declare const abortSignalKey: AsyncContextKey<AbortSignal | undefined>;
131
132
  declare class AsyncContext {
132
- static current: AsyncContext | undefined;
133
133
  /** Immutable empty singleton — avoids allocating new AsyncContext(). */
134
134
  static readonly empty: AsyncContext;
135
+ private static _current;
135
136
  private static _defaults;
136
137
  private _values;
137
138
  constructor(values?: Map<symbol, unknown>);
139
+ static get current(): AsyncContext | undefined;
140
+ static set current(value: AsyncContext | undefined);
141
+ /** True when AsyncContext.current flows across awaits (Node AsyncLocalStorage is active). */
142
+ static get isAsyncLocalStorageActive(): boolean;
138
143
  get<T>(key: AsyncContextKey<T>): T;
139
144
  with<T>(key: AsyncContextKey<T>, value: T): AsyncContext;
140
145
  activate(): Disposable;
@@ -147,6 +152,7 @@ declare class AsyncContext {
147
152
  static fromArgs(args: unknown[]): AsyncContext | undefined;
148
153
  static setDefault<T>(key: AsyncContextKey<T>, value: T): void;
149
154
  static getOrCreate(): AsyncContext;
155
+ static _setAsyncLocalStorageActive(active: boolean): void;
150
156
  }
151
157
 
152
158
  /** Promise-based mutual exclusion lock for serializing async operations. */
@@ -154,22 +160,32 @@ declare class AsyncLock {
154
160
  private _queue;
155
161
  private _locked;
156
162
  get isLocked(): boolean;
157
- acquire(): Promise<void>;
163
+ acquire(signal?: AbortSignal): Promise<void>;
158
164
  release(): void;
159
- run<T>(fn: () => T | Promise<T>): Promise<T>;
165
+ run<T>(fn: () => T | Promise<T>, signal?: AbortSignal): Promise<T>;
160
166
  }
161
167
 
162
- /** Typed pub/sub event handler set — similar to .NET's EventHandler<T> multicast delegate. */
168
+ /**
169
+ * Typed pub/sub event handler set — similar to .NET's EventHandler<T> multicast delegate.
170
+ * Deviation: Set-backed, so adding the same handler twice fires it once (a C# delegate fires it twice).
171
+ */
163
172
  declare class EventHandlerSet<T> {
164
173
  private _handlers;
165
174
  get count(): number;
166
175
  add(handler: (arg: T) => void): void;
167
176
  remove(handler: (arg: T) => void): void;
168
177
  trigger(arg: T): void;
178
+ triggerSafe(arg: T, onError: (error: unknown) => void): void;
169
179
  clear(): void;
170
180
  whenNext(): Promise<T>;
171
181
  }
172
182
 
183
+ declare class AsyncSignal {
184
+ private source;
185
+ wait(): Promise<void>;
186
+ notify(): void;
187
+ }
188
+
173
189
  /** Externally-resolvable promise — similar to .NET's TaskCompletionSource<T>. */
174
190
  declare class PromiseSource<T> implements Promise<T> {
175
191
  readonly promise: Promise<T>;
@@ -264,13 +280,43 @@ declare class TimeoutError extends Error {
264
280
  */
265
281
  declare function withTimeout<T>(promise: PromiseLike<T>, ms: number, message?: string): Promise<T>;
266
282
 
267
- /** Resolves after `ms` milliseconds. */
268
- declare function delayAsync(ms: number): Promise<void>;
283
+ /** Resolves after `ms` milliseconds, or rejects with `signal.reason` if
284
+ * `signal` aborts first (including when it is already aborted). */
285
+ declare function delayAsync(ms: number, signal?: AbortSignal): Promise<void>;
269
286
  /** Resolves with `value` after `ms` milliseconds. */
270
287
  declare function delayAsyncWith<T>(ms: number, value: T): Promise<T>;
271
288
 
272
289
  declare function abortPromise(signal: AbortSignal): Promise<never>;
273
290
 
291
+ /**
292
+ * True when `error` is a cancellation/abort signal rather than a real failure.
293
+ *
294
+ * Recognizes the wave-1 cancellation convention: `delayAsync`, `AsyncLock`, and
295
+ * `abortPromise` all reject with `signal.reason`, which — per the Web spec —
296
+ * defaults to a `DOMException` named `'AbortError'` (and is whatever value was
297
+ * passed to `abort(reason)` otherwise). A plain `Error` named `'AbortError'`
298
+ * (e.g. from a fetch abort) is matched too.
299
+ */
300
+ declare function isCancellation(error: unknown): boolean;
301
+ /**
302
+ * Builds a cancellation-shaped error recognized by {@link isCancellation}.
303
+ * Named `'AbortError'` so it rides the same never-cache path as an aborted
304
+ * `fetch`: the compute kernel invalidates such computeds instead of caching
305
+ * the error (K6), and RPC callers treat it as a retryable cancellation.
306
+ */
307
+ declare function cancellationError(message?: string): Error;
308
+
309
+ type AbortOutcome = 'resolve' | 'reject';
310
+ /**
311
+ * Builds a Promise that settles when the first completion source fires, then runs
312
+ * every registered cleanup exactly once — on completion or when `abortSignal`
313
+ * aborts. `wire` installs the sources (timers, event handlers), calling
314
+ * `complete()` to resolve and `addCleanup(fn)` to register teardown; every
315
+ * cleanup, plus the abort listener, is removed on every exit path. `onAbort`
316
+ * selects whether an abort resolves or rejects (with `signal.reason`).
317
+ */
318
+ declare function awaitWithCleanup(abortSignal: AbortSignal | undefined, onAbort: AbortOutcome, wire: (complete: () => void, addCleanup: (cleanup: () => void) => void) => void): Promise<void>;
319
+
274
320
  /** A function wrapped by {@link throttle} or {@link debounce}. Calling it
275
321
  * triggers the underlying function according to the scheduling rule;
276
322
  * `reset()` discards any pending scheduled call. */
@@ -393,8 +439,11 @@ type RetryDelaySchedule = (tryIndex: number) => number;
393
439
  * `fn` is passed the 0-based attempt index and the last error (or
394
440
  * `undefined` for the first attempt) — useful for adapting behavior per
395
441
  * try (e.g. switching endpoints, escalating timeouts).
442
+ *
443
+ * Aborting `signal` during an inter-attempt delay rejects with
444
+ * `signal.reason` instead of waiting the delay out.
396
445
  */
397
- declare function retry<TResult>(tryCount: number, fn: (tryIndex: number, lastError: unknown) => PromiseLike<TResult> | TResult, retryDelays?: RetryDelaySchedule): Promise<TResult>;
446
+ declare function retry<TResult>(tryCount: number, fn: (tryIndex: number, lastError: unknown) => PromiseLike<TResult> | TResult, retryDelays?: RetryDelaySchedule, signal?: AbortSignal): Promise<TResult>;
398
447
  /**
399
448
  * Run `fn` and swallow any throw, returning `onError(e)` if provided or
400
449
  * `undefined` otherwise. The returned promise always settles successfully
@@ -406,4 +455,7 @@ declare function retry<TResult>(tryCount: number, fn: (tryIndex: number, lastErr
406
455
  */
407
456
  declare function catchErrors<TResult>(fn: () => PromiseLike<TResult> | TResult, onError?: (e: unknown) => TResult): Promise<TResult | undefined>;
408
457
 
409
- export { AsyncContext, AsyncContextKey, type AsyncDisposable, AsyncLock, type Disposable, DisposableBag, EventHandlerSet, type IResult, Log, LogLevel, LogLevelController, type LogRef, type LogScopeFns, PromiseSource, PromiseSourceWithTimeout, type ResettableFunc, ResolvedPromise, Result, type RetryDelay, RetryDelayLimitExceeded, RetryDelayNone, type RetryDelaySchedule, RetryDelaySeq, RetryDelayer, RingBuffer, type ThrottleMode, TimedOut, TimeoutError, abortPromise, abortSignalKey, catchErrors, createLogProvider, debounce, delayAsync, delayAsyncWith, errorResult, initLogging, initWorkerLogging, resolvedVoidPromise, result, resultFrom, resultFromAsync, retry, serialize, throttle, withTimeout };
458
+ declare function ownMetadata<T extends object>(metadata: object, key: symbol): T;
459
+ declare function resolveArgCount(fn: (...args: never[]) => unknown, explicit: number | undefined, methodName: string): number;
460
+
461
+ export { type AbortOutcome, AsyncContext, AsyncContextKey, type AsyncDisposable, AsyncLock, AsyncSignal, type Disposable, DisposableBag, EventHandlerSet, type IResult, Log, LogLevel, LogLevelController, type LogRef, type LogScopeFns, PromiseSource, PromiseSourceWithTimeout, type ResettableFunc, ResolvedPromise, Result, type RetryDelay, RetryDelayLimitExceeded, RetryDelayNone, type RetryDelaySchedule, RetryDelaySeq, RetryDelayer, RingBuffer, type ThrottleMode, TimedOut, TimeoutError, abortPromise, abortSignalKey, awaitWithCleanup, cancellationError, catchErrors, createLogProvider, debounce, delayAsync, delayAsyncWith, errorResult, initLogging, initWorkerLogging, isCancellation, ownMetadata, resolveArgCount, resolvedVoidPromise, result, resultFrom, resultFromAsync, retry, serialize, throttle, withTimeout };
package/dist/index.js CHANGED
@@ -439,9 +439,9 @@ var Result = class _Result {
439
439
  hasError;
440
440
  _value;
441
441
  _error;
442
- constructor(value, error) {
443
- this.hasValue = error === void 0;
444
- this.hasError = !this.hasValue;
442
+ constructor(value, error, hasError = error !== void 0) {
443
+ this.hasError = hasError;
444
+ this.hasValue = !hasError;
445
445
  this._value = value;
446
446
  this._error = error;
447
447
  }
@@ -455,11 +455,17 @@ var Result = class _Result {
455
455
  get valueOrUndefined() {
456
456
  return this.hasValue ? this._value : void 0;
457
457
  }
458
+ // Values compared with valueComparer (Object.is by default); errors by reference — mirrors C# Result<T>.Equals.
459
+ equals(other, valueComparer = Object.is) {
460
+ if (this.hasError !== other.hasError || this._error !== other._error)
461
+ return false;
462
+ return valueComparer(this._value, other._value);
463
+ }
458
464
  static ok(value) {
459
- return new _Result(value);
465
+ return new _Result(value, void 0, false);
460
466
  }
461
467
  static error(error) {
462
- return new _Result(void 0, error);
468
+ return new _Result(void 0, error ?? new Error("Unspecified error"), true);
463
469
  }
464
470
  };
465
471
  function result(value, error) {
@@ -496,15 +502,35 @@ var abortSignalKey = new AsyncContextKey(
496
502
  "AbortSignal",
497
503
  void 0
498
504
  );
505
+ var _alsImpl = detectAsyncLocalStorage();
506
+ var _als = _alsImpl;
507
+ function detectAsyncLocalStorage() {
508
+ const proc = globalThis.process;
509
+ const asyncHooks = proc?.getBuiltinModule?.("node:async_hooks");
510
+ return asyncHooks === void 0 ? void 0 : new asyncHooks.AsyncLocalStorage();
511
+ }
499
512
  var AsyncContext = class _AsyncContext {
500
- static current = void 0;
501
513
  /** Immutable empty singleton — avoids allocating new AsyncContext(). */
502
514
  static empty = new _AsyncContext();
515
+ static _current = void 0;
503
516
  static _defaults = /* @__PURE__ */ new Map();
504
517
  _values;
505
518
  constructor(values) {
506
519
  this._values = values ?? /* @__PURE__ */ new Map();
507
520
  }
521
+ static get current() {
522
+ return _als?.getStore() ?? _AsyncContext._current;
523
+ }
524
+ static set current(value) {
525
+ if (_als !== void 0)
526
+ _als.enterWith(value);
527
+ else
528
+ _AsyncContext._current = value;
529
+ }
530
+ /** True when AsyncContext.current flows across awaits (Node AsyncLocalStorage is active). */
531
+ static get isAsyncLocalStorageActive() {
532
+ return _als !== void 0;
533
+ }
508
534
  get(key) {
509
535
  if (this._values.has(key.id)) return this._values.get(key.id);
510
536
  if (_AsyncContext._defaults.has(key.id))
@@ -518,20 +544,27 @@ var AsyncContext = class _AsyncContext {
518
544
  }
519
545
  activate() {
520
546
  const prev = _AsyncContext.current;
521
- _AsyncContext.current = this;
547
+ const als = _als;
548
+ if (als !== void 0) {
549
+ als.enterWith(this);
550
+ return { dispose: () => als.enterWith(prev) };
551
+ }
552
+ _AsyncContext._current = this;
522
553
  return {
523
554
  dispose: () => {
524
- _AsyncContext.current = prev;
555
+ _AsyncContext._current = prev;
525
556
  }
526
557
  };
527
558
  }
528
559
  run(fn) {
529
- const prev = _AsyncContext.current;
530
- _AsyncContext.current = this;
560
+ if (_als !== void 0)
561
+ return _als.run(this, fn);
562
+ const prev = _AsyncContext._current;
563
+ _AsyncContext._current = this;
531
564
  try {
532
565
  return fn();
533
566
  } finally {
534
- _AsyncContext.current = prev;
567
+ _AsyncContext._current = prev;
535
568
  }
536
569
  }
537
570
  /** Strip THIS exact instance from args if it's the last element (reference equality). */
@@ -553,6 +586,12 @@ var AsyncContext = class _AsyncContext {
553
586
  static getOrCreate() {
554
587
  return _AsyncContext.current ?? _AsyncContext.empty;
555
588
  }
589
+ // Toggles AsyncLocalStorage backing — for tests that exercise the browser fallback path.
590
+ // Clears the fallback static field so no stale context bleeds across the toggle.
591
+ static _setAsyncLocalStorageActive(active) {
592
+ _als = active ? _alsImpl : void 0;
593
+ _AsyncContext._current = void 0;
594
+ }
556
595
  };
557
596
 
558
597
  // src/async-lock.ts
@@ -562,13 +601,26 @@ var AsyncLock = class {
562
601
  get isLocked() {
563
602
  return this._locked;
564
603
  }
565
- async acquire() {
604
+ async acquire(signal) {
605
+ if (signal?.aborted)
606
+ throw signal.reason;
566
607
  if (!this._locked) {
567
608
  this._locked = true;
568
609
  return;
569
610
  }
570
- return new Promise((resolve) => {
571
- this._queue.push(resolve);
611
+ return new Promise((resolve, reject) => {
612
+ const onAbort = () => {
613
+ const i = this._queue.indexOf(waiter);
614
+ if (i >= 0)
615
+ this._queue.splice(i, 1);
616
+ reject(signal.reason);
617
+ };
618
+ const waiter = () => {
619
+ signal?.removeEventListener("abort", onAbort);
620
+ resolve();
621
+ };
622
+ this._queue.push(waiter);
623
+ signal?.addEventListener("abort", onAbort, { once: true });
572
624
  });
573
625
  }
574
626
  release() {
@@ -580,8 +632,8 @@ var AsyncLock = class {
580
632
  this._locked = false;
581
633
  }
582
634
  }
583
- async run(fn) {
584
- await this.acquire();
635
+ async run(fn, signal) {
636
+ await this.acquire(signal);
585
637
  try {
586
638
  return await fn();
587
639
  } finally {
@@ -602,6 +654,8 @@ var PromiseSource = class {
602
654
  this._resolve = resolve;
603
655
  this._reject = reject;
604
656
  });
657
+ this.promise.catch(() => {
658
+ });
605
659
  }
606
660
  get isCompleted() {
607
661
  return this._isCompleted;
@@ -643,7 +697,18 @@ var EventHandlerSet = class {
643
697
  this._handlers.delete(handler);
644
698
  }
645
699
  trigger(arg) {
646
- for (const handler of this._handlers) handler(arg);
700
+ for (const handler of [...this._handlers])
701
+ handler(arg);
702
+ }
703
+ // Fires every handler once, isolating each so one that throws can't stop the rest.
704
+ triggerSafe(arg, onError) {
705
+ for (const handler of [...this._handlers]) {
706
+ try {
707
+ handler(arg);
708
+ } catch (error) {
709
+ onError(error);
710
+ }
711
+ }
647
712
  }
648
713
  clear() {
649
714
  this._handlers.clear();
@@ -659,6 +724,19 @@ var EventHandlerSet = class {
659
724
  }
660
725
  };
661
726
 
727
+ // src/async-signal.ts
728
+ var AsyncSignal = class {
729
+ source = new PromiseSource();
730
+ wait() {
731
+ return this.source.promise;
732
+ }
733
+ notify() {
734
+ const source = this.source;
735
+ this.source = new PromiseSource();
736
+ source.resolve();
737
+ }
738
+ };
739
+
662
740
  // src/withTimeout.ts
663
741
  var TimeoutError = class extends Error {
664
742
  name = "TimeoutError";
@@ -733,9 +811,19 @@ var TimedOut = class _TimedOut {
733
811
  };
734
812
 
735
813
  // src/delay.ts
736
- function delayAsync(ms) {
737
- return new Promise((resolve) => {
738
- setTimeout(resolve, ms);
814
+ function delayAsync(ms, signal) {
815
+ if (signal?.aborted)
816
+ return Promise.reject(signal.reason);
817
+ return new Promise((resolve, reject) => {
818
+ const onAbort = () => {
819
+ clearTimeout(timer);
820
+ reject(signal.reason);
821
+ };
822
+ const timer = setTimeout(() => {
823
+ signal?.removeEventListener("abort", onAbort);
824
+ resolve();
825
+ }, ms);
826
+ signal?.addEventListener("abort", onAbort, { once: true });
739
827
  });
740
828
  }
741
829
  function delayAsyncWith(ms, value) {
@@ -747,10 +835,13 @@ function delayAsyncWith(ms, value) {
747
835
  // src/abort-promise.ts
748
836
  var abortPromiseCache = /* @__PURE__ */ new WeakMap();
749
837
  function abortPromise(signal) {
750
- if (signal.aborted) return Promise.reject(signal.reason);
751
838
  let cached = abortPromiseCache.get(signal);
752
839
  if (!cached) {
753
840
  cached = new Promise((_, reject) => {
841
+ if (signal.aborted) {
842
+ reject(signal.reason);
843
+ return;
844
+ }
754
845
  signal.addEventListener("abort", () => reject(signal.reason), { once: true });
755
846
  });
756
847
  cached.catch(() => {
@@ -760,6 +851,59 @@ function abortPromise(signal) {
760
851
  return cached;
761
852
  }
762
853
 
854
+ // src/cancellation.ts
855
+ function isCancellation(error) {
856
+ return error != null && typeof error === "object" && error.name === "AbortError";
857
+ }
858
+ function cancellationError(message = "The operation was cancelled.") {
859
+ const error = new Error(message);
860
+ error.name = "AbortError";
861
+ return error;
862
+ }
863
+
864
+ // src/await-with-cleanup.ts
865
+ function awaitWithCleanup(abortSignal, onAbort, wire) {
866
+ if (abortSignal?.aborted)
867
+ return onAbort === "reject" ? Promise.reject(abortSignal.reason ?? new Error("Operation cancelled.")) : resolvedVoidPromise;
868
+ const ps = new PromiseSource();
869
+ const cleanups = [];
870
+ let settled = false;
871
+ const runCleanups = () => {
872
+ for (const cleanup of cleanups)
873
+ cleanup();
874
+ cleanups.length = 0;
875
+ };
876
+ const complete = () => {
877
+ if (settled)
878
+ return;
879
+ settled = true;
880
+ runCleanups();
881
+ ps.resolve(void 0);
882
+ };
883
+ const addCleanup = (cleanup) => {
884
+ if (settled)
885
+ cleanup();
886
+ else
887
+ cleanups.push(cleanup);
888
+ };
889
+ if (abortSignal !== void 0) {
890
+ const onAbortFired = () => {
891
+ if (settled)
892
+ return;
893
+ settled = true;
894
+ runCleanups();
895
+ if (onAbort === "reject")
896
+ ps.reject(abortSignal.reason ?? new Error("Operation cancelled."));
897
+ else
898
+ ps.resolve(void 0);
899
+ };
900
+ abortSignal.addEventListener("abort", onAbortFired, { once: true });
901
+ cleanups.push(() => abortSignal.removeEventListener("abort", onAbortFired));
902
+ }
903
+ wire(complete, addCleanup);
904
+ return ps;
905
+ }
906
+
763
907
  // src/internal-logging.ts
764
908
  var scopeDefaults = {
765
909
  retry: 3 /* Warn */,
@@ -1041,29 +1185,10 @@ var RetryDelayer = class {
1041
1185
  const actualDelayMs = Math.max(1, delayMs);
1042
1186
  const endsAt = Date.now() + actualDelayMs;
1043
1187
  const cancelSignal = this._cancelController.signal;
1044
- const promise = new Promise((resolve, reject) => {
1045
- const timer = setTimeout(() => {
1046
- cleanup();
1047
- resolve();
1048
- }, actualDelayMs);
1049
- const onCancel = () => {
1050
- clearTimeout(timer);
1051
- cleanup();
1052
- resolve();
1053
- };
1054
- const onAbort = () => {
1055
- clearTimeout(timer);
1056
- cleanup();
1057
- reject(new Error("Retry delay aborted."));
1058
- };
1059
- const cleanup = () => {
1060
- cancelSignal.removeEventListener("abort", onCancel);
1061
- cancellationSignal?.removeEventListener("abort", onAbort);
1062
- };
1063
- cancelSignal.addEventListener("abort", onCancel, { once: true });
1064
- cancellationSignal?.addEventListener("abort", onAbort, {
1065
- once: true
1066
- });
1188
+ const combinedSignal = cancellationSignal ? AbortSignal.any([cancellationSignal, cancelSignal]) : cancelSignal;
1189
+ const promise = delayAsync(actualDelayMs, combinedSignal).catch((e) => {
1190
+ if (!cancelSignal.aborted)
1191
+ throw e;
1067
1192
  });
1068
1193
  return { promise, endsAt, isLimitExceeded: false };
1069
1194
  }
@@ -1078,7 +1203,7 @@ var RetryDelayer = class {
1078
1203
  // src/retry.ts
1079
1204
  var { warnLog } = getLogs("retry");
1080
1205
  var defaultRetryDelays = () => 50;
1081
- async function retry(tryCount, fn, retryDelays = defaultRetryDelays) {
1206
+ async function retry(tryCount, fn, retryDelays = defaultRetryDelays, signal) {
1082
1207
  if (tryCount <= 0)
1083
1208
  throw new Error("retry: tryCount must be positive.");
1084
1209
  let lastError;
@@ -1092,7 +1217,7 @@ async function retry(tryCount, fn, retryDelays = defaultRetryDelays) {
1092
1217
  ++tryIndex;
1093
1218
  if (tryIndex >= tryCount) throw lastError;
1094
1219
  warnLog?.log(`retry(${tryIndex}/${tryCount}): error:`, lastError);
1095
- await delayAsync(retryDelays(tryIndex));
1220
+ await delayAsync(retryDelays(tryIndex), signal);
1096
1221
  }
1097
1222
  }
1098
1223
  async function catchErrors(fn, onError) {
@@ -1102,10 +1227,51 @@ async function catchErrors(fn, onError) {
1102
1227
  return onError ? onError(e) : void 0;
1103
1228
  }
1104
1229
  }
1230
+
1231
+ // src/decorators.ts
1232
+ function ownMetadata(metadata, key) {
1233
+ const bag = metadata;
1234
+ if (!Object.hasOwn(metadata, key))
1235
+ bag[key] = { ...bag[key] };
1236
+ return bag[key];
1237
+ }
1238
+ function resolveArgCount(fn, explicit, methodName) {
1239
+ if (explicit !== void 0)
1240
+ return explicit;
1241
+ if (hasAmbiguousArity(fn))
1242
+ throw new Error(
1243
+ `Cannot infer the argument count of "${methodName}": its parameter list uses default and/or rest parameters, for which Function.length is unreliable. Pass an explicit argCount to the decorator.`
1244
+ );
1245
+ return fn.length;
1246
+ }
1247
+ function hasAmbiguousArity(fn) {
1248
+ const params = parameterListText(fn);
1249
+ return params !== void 0 && (params.includes("=") || params.includes("..."));
1250
+ }
1251
+ function parameterListText(fn) {
1252
+ const src = fn.toString();
1253
+ const open = src.indexOf("(");
1254
+ const arrow = src.indexOf("=>");
1255
+ if (open < 0 || arrow >= 0 && arrow < open)
1256
+ return void 0;
1257
+ let depth = 0;
1258
+ for (let i = open; i < src.length; i++) {
1259
+ const ch = src[i];
1260
+ if (ch === "(")
1261
+ depth++;
1262
+ else if (ch === ")") {
1263
+ depth--;
1264
+ if (depth === 0)
1265
+ return src.slice(open + 1, i);
1266
+ }
1267
+ }
1268
+ return void 0;
1269
+ }
1105
1270
  export {
1106
1271
  AsyncContext,
1107
1272
  AsyncContextKey,
1108
1273
  AsyncLock,
1274
+ AsyncSignal,
1109
1275
  DisposableBag,
1110
1276
  EventHandlerSet,
1111
1277
  Log,
@@ -1124,6 +1290,8 @@ export {
1124
1290
  TimeoutError,
1125
1291
  abortPromise,
1126
1292
  abortSignalKey,
1293
+ awaitWithCleanup,
1294
+ cancellationError,
1127
1295
  catchErrors,
1128
1296
  createLogProvider,
1129
1297
  debounce,
@@ -1132,6 +1300,9 @@ export {
1132
1300
  errorResult,
1133
1301
  initLogging,
1134
1302
  initWorkerLogging,
1303
+ isCancellation,
1304
+ ownMetadata,
1305
+ resolveArgCount,
1135
1306
  resolvedVoidPromise,
1136
1307
  result,
1137
1308
  resultFrom,