@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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/polyfills.ts","../src/disposable.ts","../src/logging-init.ts","../src/logging.ts","../src/result.ts","../src/async-context.ts","../src/async-lock.ts","../src/promise-source.ts","../src/events.ts","../src/withTimeout.ts","../src/promise-source-with-timeout.ts","../src/resolved-promise.ts","../src/timed-out.ts","../src/delay.ts","../src/abort-promise.ts","../src/internal-logging.ts","../src/throttle.ts","../src/serialize.ts","../src/ring-buffer.ts","../src/retry-delay-seq.ts","../src/retry-delayer.ts","../src/retry.ts"],"sourcesContent":["import './polyfills.js';\n\n// Disposable\nexport type { Disposable, AsyncDisposable } from './disposable.js';\nexport { DisposableBag } from './disposable.js';\n\n// Logging\nexport type { LogRef, LogScopeFns } from './logging.js';\nexport { Log, LogLevel, createLogProvider } from './logging.js';\nexport { initLogging, initWorkerLogging, LogLevelController } from './logging-init.js';\n\n// Result & IResult\nexport type { IResult } from './result.js';\nexport {\n Result,\n result,\n errorResult,\n resultFrom,\n resultFromAsync,\n} from './result.js';\n\n// Async-related\nexport {\n AsyncContext,\n AsyncContextKey,\n abortSignalKey,\n} from './async-context.js';\nexport { AsyncLock } from './async-lock.js';\n\n// Event handling, primises\nexport { EventHandlerSet } from './events.js';\nexport { PromiseSource, resolvedVoidPromise } from './promise-source.js';\nexport { PromiseSourceWithTimeout } from './promise-source-with-timeout.js';\nexport { ResolvedPromise } from './resolved-promise.js';\nexport { TimedOut } from './timed-out.js';\nexport { TimeoutError, withTimeout } from './withTimeout.js';\nexport { delayAsync, delayAsyncWith } from './delay.js';\nexport { abortPromise } from './abort-promise.js';\n\n// Higher-order async operators\nexport type { ResettableFunc, ThrottleMode } from './throttle.js';\nexport { throttle, debounce } from './throttle.js';\nexport { serialize } from './serialize.js';\n\n// Collections\nexport { RingBuffer } from './ring-buffer.js';\n\n// Resilience\nexport { RetryDelaySeq } from './retry-delay-seq.js';\nexport type { RetryDelay } from './retry-delayer.js';\nexport {\n RetryDelayer,\n RetryDelayNone,\n RetryDelayLimitExceeded,\n} from './retry-delayer.js';\nexport type { RetryDelaySchedule } from './retry.js';\nexport { retry, catchErrors } from './retry.js';\n","// TC39 decorator metadata polyfill — required for Symbol.metadata support\r\n// in runtimes that don't yet implement it natively.\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access\r\n(Symbol as any).metadata ??= Symbol('Symbol.metadata');\r\n","/** Synchronous dispose pattern, similar to .NET's IDisposable. */\r\nexport interface Disposable {\r\n dispose(): void;\r\n}\r\n\r\n/** Asynchronous dispose pattern, similar to .NET's IAsyncDisposable. */\r\nexport interface AsyncDisposable {\r\n disposeAsync(): Promise<void>;\r\n}\r\n\r\n/** Aggregates multiple disposables and disposes them together. */\r\nexport class DisposableBag implements Disposable, AsyncDisposable {\r\n private _items: (Disposable | AsyncDisposable)[] = [];\r\n private _disposed = false;\r\n\r\n get isDisposed(): boolean {\r\n return this._disposed;\r\n }\r\n\r\n add(item: Disposable | AsyncDisposable): void {\r\n if (this._disposed)\r\n throw new Error('DisposableBag is already disposed.');\r\n this._items.push(item);\r\n }\r\n\r\n dispose(): void {\r\n if (this._disposed) return;\r\n this._disposed = true;\r\n const items = this._items;\r\n this._items = [];\r\n // Dispose in reverse order (LIFO)\r\n for (let i = items.length - 1; i >= 0; i--) {\r\n const item = items[i];\r\n if ('dispose' in item) item.dispose();\r\n }\r\n }\r\n\r\n async disposeAsync(): Promise<void> {\r\n if (this._disposed) return;\r\n this._disposed = true;\r\n const items = this._items;\r\n this._items = [];\r\n for (let i = items.length - 1; i >= 0; i--) {\r\n const item = items[i];\r\n if ('disposeAsync' in item) await item.disposeAsync();\r\n else if ('dispose' in item) item.dispose();\r\n }\r\n }\r\n}\r\n","// Initialization helpers for the logging system.\n//\n// The Log class uses a single Map<string, LogLevel> to determine the minimum\n// level for each scope. This module is responsible for:\n// - Persisting the map across page reloads via localStorage on the main\n// thread, and via IndexedDB for workers.\n// - Exposing a globally accessible LogLevelController so developers can tweak\n// levels at runtime from the browser dev console (globalThis.logLevels).\n//\n// initLogging() is idempotent and called automatically on the first Log.get().\n//\n// Runtime override examples (paste into browser dev console):\n// logLevels.override('rpc.RpcPeer', 1) // exact: one scope to Debug\n// logLevels.override('rpc.*', 1) // prefix: all rpc.* scopes\n// logLevels.override('*Video*', 1) // contains: every scope with 'Video'\n// logLevels.override('*Decoder', 1) // suffix: every scope ending in 'Decoder'\n// logLevels.reset() // reset to package defaults\n// logLevels.clear() // clear all overrides\n\nimport { Log, LogLevel } from './logging.js';\n\nconst GlobalThisKey = 'logLevels';\nconst StorageKey = 'logLevels';\nconst DateStorageKey = `${StorageKey}.date`;\nconst MaxStorageAge = 86_400_000 * 3; // 3 days\nconst IndexedDbName = 'actuallab-logging';\nconst IndexedDbStore = 'settings';\nconst IndexedDbKey = 'logLevels';\n\nconst localStorage: Storage | null = tryGetLocalStorage();\n\n// Workers, worklets, and service workers run in separate JS realms with\n// their own globalThis. Within one realm, esbuild can also produce multiple\n// chunks that each carry their own copy of @actuallab/core (so multiple\n// distinct `Log` classes exist). We want the install + restore + console\n// message to happen exactly once per realm — gate via globalThis.logLevels.\nconst isMainThread = typeof window !== 'undefined';\n\nexport function initLogging(): void {\n // Warn is the global baseline — packages set per-scope defaults\n // (typically Info or Warn) via createLogProvider.\n Log.defaultMinLevel = LogLevel.Warn;\n const minLevels = Log.minLevels;\n const g = globalThis as Record<string, unknown>;\n const existing = g[GlobalThisKey] as LogLevelController | undefined;\n\n if (existing !== undefined) {\n // Another chunk in this realm already initialized. Mirror its\n // overrides into our local Log.minLevels so this Log class observes\n // the same effective levels. (Each chunk has its own Log class with\n // its own static minLevels Map — they only converge through this\n // one-shot copy at init time.)\n for (const [k, v] of existing.getMinLevels())\n minLevels.set(k, v);\n return;\n }\n\n g[GlobalThisKey] = new LogLevelController(minLevels);\n const wasRestored = restore(minLevels);\n if (wasRestored) {\n if (isMainThread)\n console.log('Logging: logLevels are restored');\n }\n else {\n if (isMainThread)\n console.log('Logging: logLevels are reset');\n reset(minLevels);\n }\n}\n\n/** Worker bootstrap path: await this before dynamically importing any module\n * that may call getLogs() at top level. */\nexport async function initWorkerLogging(): Promise<void> {\n Log.defaultMinLevel = LogLevel.Warn;\n const minLevels = Log.minLevels;\n const g = globalThis as Record<string, unknown>;\n const existing = g[GlobalThisKey] as LogLevelController | undefined;\n\n if (existing !== undefined) {\n for (const [k, v] of existing.getMinLevels())\n minLevels.set(k, v);\n return;\n }\n\n g[GlobalThisKey] = new LogLevelController(minLevels);\n const wasRestored = await restoreFromIndexedDb(minLevels);\n if (!wasRestored)\n reset(minLevels, false);\n}\n\nexport class LogLevelController {\n constructor(private minLevels: Map<string, LogLevel>)\n { }\n\n /** Internal: used by initLogging() in secondary bundles to share the\n * primary bundle's minLevels map. */\n public getMinLevels(): Map<string, LogLevel> {\n return this.minLevels;\n }\n\n /** List the current set of overrides. */\n public list(): Record<string, LogLevel> {\n return Object.fromEntries(this.minLevels);\n }\n\n /** Print every known scope's effective level to the console as a table.\n * Shows: scope, effective level, the source ('override' / 'default-key' /\n * 'package-default' / 'baseline'), and the package default for reference.\n * Use this from the dev console to discover what to pass to override(). */\n public dump(): void {\n const baseline = Log.defaultMinLevel;\n const globalOverride = this.minLevels.get('default');\n const allScopes = new Set<string>([\n ...Log.knownScopes,\n ...Log.scopeDefaults.keys(),\n ...this.minLevels.keys(),\n ]);\n // Drop the special 'default' bucket — surfaced separately below.\n allScopes.delete('default');\n const rows: Record<string, {\n level: string;\n source: string;\n packageDefault: string;\n }> = {};\n const sorted = [...allScopes].sort();\n for (const scope of sorted) {\n const override = this.minLevels.get(scope);\n const pkgDefault = Log.scopeDefaults.get(scope);\n let level: LogLevel;\n let source: string;\n if (override !== undefined) {\n level = override;\n source = 'override';\n }\n else if (globalOverride !== undefined) {\n level = globalOverride;\n source = \"minLevels.get('default')\";\n }\n else if (pkgDefault !== undefined) {\n level = pkgDefault;\n source = 'package-default';\n }\n else {\n level = baseline;\n source = 'baseline';\n }\n rows[scope] = {\n level: LogLevel[level],\n source,\n packageDefault: pkgDefault === undefined ? '-' : LogLevel[pkgDefault],\n };\n }\n console.table(rows);\n console.log(\n `Baseline: ${LogLevel[baseline]}` +\n (globalOverride === undefined ? '' : `, default override: ${LogLevel[globalOverride]}`),\n );\n }\n\n /** Override the level for every scope matching a glob-like pattern.\n * `*` matches any sequence of characters; everything else is literal.\n * Examples:\n * override('rpc.RpcPeer', 1) // exact — one scope to Debug\n * override('rpc.*', 1) // prefix — every scope starting with 'rpc.'\n * override('*rpc*', 1) // contains — every scope with 'rpc' in it\n * override('*Peer', 1) // suffix — every scope ending with 'Peer'\n * Matches scopes that are user-overridden, package-registered (defaults),\n * or have ever been requested via Log.get(). If the pattern has no `*`\n * and nothing known matches, the literal scope is set anyway — so an\n * exact-name override placed before its scope is loaded still applies.\n * Persisted to localStorage + IndexedDB. */\n public override(pattern: string, newLevel: LogLevel): void {\n const matched = new Set<string>();\n if (pattern.includes('*')) {\n const re = patternToRegExp(pattern);\n for (const [scope] of this.minLevels)\n if (re.test(scope)) matched.add(scope);\n for (const [scope] of Log.scopeDefaults)\n if (re.test(scope)) matched.add(scope);\n for (const scope of Log.knownScopes)\n if (re.test(scope)) matched.add(scope);\n }\n else {\n matched.add(pattern);\n }\n for (const scope of matched)\n this.minLevels.set(scope, newLevel);\n persist(this.minLevels);\n }\n\n /** Reset all overrides; package defaults take effect again. Persisted. */\n public reset(): void {\n reset(this.minLevels);\n }\n\n /** Clear all overrides (no global default unless `defaultLevel` is given). */\n public clear(defaultLevel?: LogLevel): void {\n this.minLevels.clear();\n if (defaultLevel !== undefined)\n this.minLevels.set('default', defaultLevel);\n persist(this.minLevels);\n }\n}\n\nfunction patternToRegExp(pattern: string): RegExp {\n // Escape regex metacharacters except `*`, then turn each `*` into `.*`.\n const escaped = pattern.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&').replace(/\\*/g, '.*');\n return new RegExp(`^${escaped}$`);\n}\n\ninterface PersistedLogLevels {\n date: number;\n entries: [string, LogLevel][];\n}\n\nfunction restore(minLevels: Map<string, LogLevel>): boolean {\n const snapshot = readFromStorage(localStorage);\n if (!snapshot)\n return false;\n\n return applySnapshot(minLevels, snapshot);\n}\n\nasync function restoreFromIndexedDb(minLevels: Map<string, LogLevel>): Promise<boolean> {\n const snapshot = await readFromIndexedDb();\n if (!snapshot)\n return false;\n\n return applySnapshot(minLevels, snapshot);\n}\n\nfunction readFromStorage(storage: Storage | null): PersistedLogLevels | null {\n if (!storage)\n return null;\n\n try {\n const dateJson = storage.getItem(DateStorageKey);\n const entriesJson = storage.getItem(StorageKey);\n if (!dateJson || !entriesJson)\n return null;\n\n return {\n date: JSON.parse(dateJson) as number,\n entries: JSON.parse(entriesJson) as [string, LogLevel][],\n };\n } catch {\n return null;\n }\n}\n\nfunction applySnapshot(minLevels: Map<string, LogLevel>, snapshot: PersistedLogLevels): boolean {\n if (typeof snapshot.date !== 'number')\n return false;\n if (Date.now() - snapshot.date > MaxStorageAge)\n return false;\n if (!Array.isArray(snapshot.entries))\n return false;\n\n minLevels.clear();\n for (const entry of snapshot.entries) {\n // Runtime guard for JSON-parsed input — types claim it's a tuple, but\n // localStorage may carry corrupted data. eslint flags the length check\n // as always-false against the static type; that's the point.\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!Array.isArray(entry) || entry.length !== 2)\n return false;\n const [key, value] = entry;\n if (typeof key !== 'string' || typeof value !== 'number')\n return false;\n minLevels.set(key, value);\n }\n\n return true;\n}\n\nfunction persist(minLevels: Map<string, LogLevel>): boolean {\n const snapshot = createSnapshot(minLevels);\n let wasPersisted = false;\n\n if (localStorage) {\n try {\n localStorage.setItem(DateStorageKey, JSON.stringify(snapshot.date));\n localStorage.setItem(StorageKey, JSON.stringify(snapshot.entries));\n wasPersisted = true;\n } catch {\n // Storage may be unavailable in private / sandboxed contexts.\n }\n }\n\n void writeToIndexedDb(snapshot);\n return wasPersisted;\n}\n\nfunction createSnapshot(minLevels: Map<string, LogLevel>): PersistedLogLevels {\n return {\n date: Date.now(),\n entries: Array.from(minLevels.entries()),\n };\n}\n\nfunction tryGetLocalStorage(): Storage | null {\n if (typeof globalThis === 'undefined' || !('localStorage' in globalThis))\n return null;\n\n try {\n return (globalThis as unknown as { localStorage: Storage }).localStorage;\n } catch {\n return null;\n }\n}\n\nasync function openLoggingDb(): Promise<IDBDatabase | null> {\n if (typeof indexedDB === 'undefined')\n return null;\n\n return new Promise(resolve => {\n const request = indexedDB.open(IndexedDbName, 1);\n request.onupgradeneeded = () => {\n const db = request.result;\n if (!db.objectStoreNames.contains(IndexedDbStore))\n db.createObjectStore(IndexedDbStore);\n };\n request.onerror = () => resolve(null);\n request.onblocked = () => resolve(null);\n request.onsuccess = () => resolve(request.result);\n });\n}\n\nasync function readFromIndexedDb(): Promise<PersistedLogLevels | null> {\n const db = await openLoggingDb();\n if (!db)\n return null;\n\n return new Promise(resolve => {\n const tx = db.transaction(IndexedDbStore, 'readonly');\n const request = tx.objectStore(IndexedDbStore).get(IndexedDbKey);\n request.onerror = () => resolve(null);\n request.onsuccess = () => resolve(request.result as PersistedLogLevels | null);\n tx.oncomplete = () => db.close();\n tx.onerror = () => db.close();\n tx.onabort = () => db.close();\n });\n}\n\nasync function writeToIndexedDb(snapshot: PersistedLogLevels): Promise<void> {\n const db = await openLoggingDb();\n if (!db)\n return;\n\n await new Promise<void>(resolve => {\n const tx = db.transaction(IndexedDbStore, 'readwrite');\n tx.objectStore(IndexedDbStore).put(snapshot, IndexedDbKey);\n tx.oncomplete = () => {\n db.close();\n resolve();\n };\n tx.onerror = () => {\n db.close();\n resolve();\n };\n tx.onabort = () => {\n db.close();\n resolve();\n };\n });\n}\n\nfunction reset(minLevels: Map<string, LogLevel>, mustPersist = true): void {\n minLevels.clear();\n // Add per-scope defaults here for development.\n // Use prefix conventions: 'rpc.', 'fusion.', 'app.', etc.\n\n // minLevels.set('rpc.RpcPeer', LogLevel.Debug);\n // minLevels.set('fusion.Computed', LogLevel.Debug);\n\n if (mustPersist)\n persist(minLevels);\n}\n","// Lightweight logging primitives shared by all ActualLab TypeScript packages.\n//\n// Design:\n// - Log.get(scope) returns a bag of optional loggers ({ debugLog, infoLog,\n// warnLog, errorLog }). Each is null when its level is below the scope's\n// minimum level, so the typical call site looks like:\n//\n// debugLog?.log('something happened', value);\n//\n// The optional chaining short-circuits before evaluating the arguments —\n// so the cost of disabled logs is just one nullish check.\n//\n// - Scopes are plain strings. Each package defines its own typed scope union\n// and uses createLogProvider<TScope>(prefix) to get a typed helper that keeps\n// scope names short at call sites while ensuring globally unique keys\n// ('rpc.RpcPeer', 'fusion.Computed', etc.).\n//\n// - Minimum levels live in Log.minLevels (a Map<string, LogLevel>). An\n// entry 'default' acts as a fallback before Log.defaultMinLevel.\n//\n// - initLogging() is invoked lazily on the first Log.get() call. It restores\n// persisted levels and installs globalThis.logLevels so devs can tweak\n// levels at runtime.\n\nimport { initLogging } from './logging-init.js';\n\nexport enum LogLevel {\n Debug = 1,\n Info,\n Warn,\n Error,\n None = 1000,\n}\n\nexport interface LogRef {\n target: unknown;\n id: number;\n}\n\ninterface LogRefSetItem {\n ref: LogRef;\n touchedAt: number;\n}\n\ninterface LogRefData {\n __logRefId?: number;\n}\n\nclass LogRefSet {\n private items: LogRefSetItem[] = [];\n private idSeed = 0;\n\n constructor(private capacity: number)\n { }\n\n public ref(data: object): LogRef {\n const itemIndex = this.items.findIndex(el => el.ref.target === data);\n if (itemIndex >= 0) {\n const existing = this.items[itemIndex];\n existing.touchedAt = Date.now();\n return existing.ref;\n }\n const id = (data as LogRefData).__logRefId ?? this.idSeed++;\n const newRef: LogRef = { target: data, id };\n (data as LogRefData).__logRefId = id;\n if (this.items.length >= this.capacity)\n this.removeOldest();\n this.items.push({ ref: newRef, touchedAt: Date.now() });\n return newRef;\n }\n\n private removeOldest(): void {\n let indexToEvict = 0;\n let itemToEvict = this.items[0];\n for (let i = 1; i < this.items.length; i++) {\n const item = this.items[i];\n if (item.touchedAt < itemToEvict.touchedAt) {\n itemToEvict = item;\n indexToEvict = i;\n }\n }\n this.items.splice(indexToEvict, 1);\n // Replace the live target with its string form so we don't keep the\n // object alive purely for log identity reasons.\n const ref = itemToEvict.ref;\n ref.target = ref.target?.toString();\n }\n}\n\nexport class Log {\n private static isInitialized = false;\n private static logRefs = new LogRefSet(10);\n /** User-set overrides (persisted by logging-init). Empty by default. */\n public static readonly minLevels = new Map<string, LogLevel>();\n /** Per-scope defaults registered by packages via createLogProvider(). */\n public static readonly scopeDefaults = new Map<string, LogLevel>();\n /** Every scope ever requested via Log.get(). Used by logLevels.dump()\n * so devs can discover what's available to override at runtime. */\n public static readonly knownScopes = new Set<string>();\n /** Global baseline for any scope without a default or override. */\n public static defaultMinLevel = LogLevel.Warn;\n public static loggerFactory: (scope: string, level: LogLevel) => Log = (scope, level) => new Log(scope, level);\n\n public log: (...data: unknown[]) => void;\n public trace: (...data: unknown[]) => void;\n\n constructor(\n public readonly scope: string,\n public readonly level: LogLevel,\n ) {\n const prefix = `[${scope}]`;\n switch (level) {\n case LogLevel.Debug:\n this.log = (...data: unknown[]) => console.debug(prefix, ...data);\n break;\n case LogLevel.Info:\n this.log = (...data: unknown[]) => console.log(prefix, ...data);\n break;\n case LogLevel.Warn:\n this.log = (...data: unknown[]) => console.warn(prefix, ...data);\n break;\n case LogLevel.Error:\n this.log = (...data: unknown[]) => console.error(prefix, ...data);\n break;\n case LogLevel.None:\n throw new Error('LogLevel.None cannot be used here');\n }\n this.trace = (...data: unknown[]) => console.trace(prefix, ...data);\n }\n\n public static get(scope: string): LogScopeFns {\n if (!this.isInitialized) {\n this.isInitialized = true;\n initLogging();\n }\n this.knownScopes.add(scope);\n\n const minLevels = this.minLevels;\n // Resolution order:\n // 1. User override for this scope (persisted by logging-init)\n // 2. User-set global override (minLevels.get('default'))\n // 3. Package default for this scope (registered via createLogProvider)\n // 4. Framework baseline (Log.defaultMinLevel, Warn)\n const minLevel = minLevels.get(scope)\n ?? minLevels.get('default')\n ?? this.scopeDefaults.get(scope)\n ?? this.defaultMinLevel;\n\n const getLogger = (level: LogLevel): Log | null =>\n level >= minLevel ? this.loggerFactory(scope, level) : null;\n\n return {\n logScope: scope,\n debugLog: getLogger(LogLevel.Debug),\n infoLog: getLogger(LogLevel.Info),\n warnLog: getLogger(LogLevel.Warn),\n errorLog: getLogger(LogLevel.Error),\n };\n }\n\n public static ref(data: object | null | undefined): object | null | undefined {\n if (!data)\n return data;\n return this.logRefs.ref(data);\n }\n\n public assert(predicate?: boolean, ...data: unknown[]): void {\n if (!predicate)\n this.log(...data);\n }\n}\n\nexport interface LogScopeFns {\n logScope: string;\n debugLog: Log | null;\n infoLog: Log | null;\n warnLog: Log | null;\n errorLog: Log | null;\n}\n\n// Per-package factory: creates a typed getLogs(scope) that prepends the package\n// prefix to the scope name before delegating to Log.get. Keeps call sites\n// concise while ensuring globally unique scope keys.\n//\n// `defaults` is required (not Partial) so that every scope in TScope has an\n// explicit default level — TypeScript will refuse to compile if a scope is\n// missing. Defaults register into Log.scopeDefaults and act as the fallback\n// when no user override is set.\n//\n// All declared scopes are also pre-registered in Log.knownScopes so that\n// logLevels.dump() (in dev console) can list them even before they're first\n// touched at runtime.\nexport function createLogProvider<TScope extends string>(\n prefix: string,\n defaults: Record<TScope, LogLevel>,\n): (scope: TScope) => LogScopeFns {\n for (const [scope, level] of Object.entries(defaults) as [TScope, LogLevel][]) {\n const fullName = prefix + scope;\n Log.scopeDefaults.set(fullName, level);\n Log.knownScopes.add(fullName);\n }\n return scope => Log.get(prefix + scope);\n}\n","/** Common interface for types that carry a value-or-error outcome. */\r\nexport interface IResult<T> {\r\n readonly hasValue: boolean;\r\n readonly hasError: boolean;\r\n readonly value: T;\r\n readonly error: unknown;\r\n readonly valueOrUndefined: T | undefined;\r\n}\r\n\r\n/** Immutable value-or-error container — similar to .NET's Result<T>. */\r\nexport class Result<T> implements IResult<T> {\r\n readonly hasValue: boolean;\r\n readonly hasError: boolean;\r\n private readonly _value: T | undefined;\r\n private readonly _error: unknown;\r\n\r\n public constructor(value: T | undefined, error?: unknown) {\r\n this.hasValue = error === undefined;\r\n this.hasError = !this.hasValue;\r\n this._value = value;\r\n this._error = error;\r\n }\r\n\r\n get value(): T {\r\n if (this.hasError) throw this._error;\r\n return this._value as T;\r\n }\r\n\r\n get error(): unknown {\r\n return this._error;\r\n }\r\n\r\n get valueOrUndefined(): T | undefined {\r\n return this.hasValue ? this._value : undefined;\r\n }\r\n\r\n static ok<T>(value: T): Result<T> {\r\n return new Result<T>(value);\r\n }\r\n\r\n static error<T>(error: unknown): Result<T> {\r\n return new Result<T>(undefined, error);\r\n }\r\n}\r\n\r\nexport function result<T>(value: T, error?: unknown): Result<T> {\r\n return new Result<T>(value, error);\r\n}\r\n\r\nexport function errorResult<T>(error: unknown): Result<T> {\r\n return Result.error(error);\r\n}\r\n\r\nexport function resultFrom<T>(fn: () => T): Result<T> {\r\n try {\r\n return result(fn());\r\n } catch (e) {\r\n return errorResult(e);\r\n }\r\n}\r\n\r\nexport async function resultFromAsync<T>(\r\n fn: () => Promise<T>\r\n): Promise<Result<T>> {\r\n try {\r\n return result(await fn());\r\n } catch (e) {\r\n return errorResult(e);\r\n }\r\n}\r\n","import type { Disposable } from './disposable.js';\r\n\r\n/** Typed key for values stored in AsyncContext — each subsystem defines its own keys. */\r\nexport class AsyncContextKey<T> {\r\n readonly id: symbol;\r\n readonly defaultValue: T;\r\n\r\n constructor(name: string, defaultValue: T) {\r\n this.id = Symbol(name);\r\n this.defaultValue = defaultValue;\r\n }\r\n}\r\n\r\n/** General-purpose typed context container — named for forward-compatibility with TC39 AsyncContext proposal. */\r\nexport const abortSignalKey = new AsyncContextKey<AbortSignal | undefined>(\r\n 'AbortSignal',\r\n undefined\r\n);\r\n\r\nexport class AsyncContext {\r\n static current: AsyncContext | undefined = undefined;\r\n\r\n /** Immutable empty singleton — avoids allocating new AsyncContext(). */\r\n static readonly empty: AsyncContext = new AsyncContext();\r\n\r\n private static _defaults = new Map<symbol, unknown>();\r\n\r\n private _values: Map<symbol, unknown>;\r\n\r\n constructor(values?: Map<symbol, unknown>) {\r\n this._values = values ?? new Map<symbol, unknown>();\r\n }\r\n\r\n get<T>(key: AsyncContextKey<T>): T {\r\n if (this._values.has(key.id)) return this._values.get(key.id) as T;\r\n if (AsyncContext._defaults.has(key.id))\r\n return AsyncContext._defaults.get(key.id) as T;\r\n return key.defaultValue;\r\n }\r\n\r\n with<T>(key: AsyncContextKey<T>, value: T): AsyncContext {\r\n const copy = new Map(this._values);\r\n copy.set(key.id, value);\r\n return new AsyncContext(copy);\r\n }\r\n\r\n activate(): Disposable {\r\n const prev = AsyncContext.current;\r\n AsyncContext.current = this;\r\n return {\r\n dispose: () => {\r\n AsyncContext.current = prev;\r\n },\r\n };\r\n }\r\n\r\n run<R>(fn: () => R): R {\r\n const prev = AsyncContext.current;\r\n AsyncContext.current = this;\r\n try {\r\n return fn();\r\n } finally {\r\n AsyncContext.current = prev;\r\n }\r\n }\r\n\r\n /** Strip THIS exact instance from args if it's the last element (reference equality). */\r\n stripFromArgs(args: unknown[]): unknown[] {\r\n return args[args.length - 1] === this ? args.slice(0, -1) : args;\r\n }\r\n\r\n /** Resolve: return ctx if provided, otherwise AsyncContext.current. */\r\n static from(ctx: AsyncContext | undefined): AsyncContext | undefined {\r\n return ctx ?? AsyncContext.current;\r\n }\r\n\r\n /** Extract AsyncContext from last arg if instanceof AsyncContext, else fall back to .current. */\r\n static fromArgs(args: unknown[]): AsyncContext | undefined {\r\n const last = args[args.length - 1];\r\n return last instanceof AsyncContext ? last : AsyncContext.current;\r\n }\r\n\r\n static setDefault<T>(key: AsyncContextKey<T>, value: T): void {\r\n AsyncContext._defaults.set(key.id, value);\r\n }\r\n\r\n static getOrCreate(): AsyncContext {\r\n return AsyncContext.current ?? AsyncContext.empty;\r\n }\r\n}\r\n","/** Promise-based mutual exclusion lock for serializing async operations. */\r\nexport class AsyncLock {\r\n private _queue: (() => void)[] = [];\r\n private _locked = false;\r\n\r\n get isLocked(): boolean {\r\n return this._locked;\r\n }\r\n\r\n async acquire(): Promise<void> {\r\n if (!this._locked) {\r\n this._locked = true;\r\n return;\r\n }\r\n return new Promise<void>(resolve => {\r\n this._queue.push(resolve);\r\n });\r\n }\r\n\r\n release(): void {\r\n if (!this._locked) throw new Error('AsyncLock is not locked.');\r\n\r\n const next = this._queue.shift();\r\n if (next !== undefined) {\r\n // Transfer lock to the next waiter\r\n next();\r\n } else {\r\n this._locked = false;\r\n }\r\n }\r\n\r\n async run<T>(fn: () => T | Promise<T>): Promise<T> {\r\n await this.acquire();\r\n try {\r\n return await fn();\r\n } finally {\r\n this.release();\r\n }\r\n }\r\n}\r\n","/** Externally-resolvable promise — similar to .NET's TaskCompletionSource<T>. */\r\nexport class PromiseSource<T> implements Promise<T> {\r\n readonly promise: Promise<T>;\r\n readonly [Symbol.toStringTag] = 'Promise';\r\n private _resolve!: (value: T | PromiseLike<T>) => void;\r\n private _reject!: (reason?: unknown) => void;\r\n private _isCompleted = false;\r\n\r\n constructor() {\r\n this.promise = new Promise<T>((resolve, reject) => {\r\n this._resolve = resolve;\r\n this._reject = reject;\r\n });\r\n }\r\n\r\n get isCompleted(): boolean {\r\n return this._isCompleted;\r\n }\r\n\r\n resolve(value: T): boolean {\r\n if (this._isCompleted) return false;\r\n this._isCompleted = true;\r\n this._resolve(value);\r\n return true;\r\n }\r\n\r\n reject(reason?: unknown): boolean {\r\n if (this._isCompleted) return false;\r\n this._isCompleted = true;\r\n this._reject(reason);\r\n return true;\r\n }\r\n\r\n then<TResult1 = T, TResult2 = never>(\r\n onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null,\r\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,\r\n ): Promise<TResult1 | TResult2> {\r\n return this.promise.then(onfulfilled, onrejected);\r\n }\r\n\r\n catch<TResult = never>(\r\n onrejected?: ((reason: unknown) => TResult | PromiseLike<TResult>) | null,\r\n ): Promise<T | TResult> {\r\n return this.promise.catch(onrejected);\r\n }\r\n\r\n finally(onfinally?: (() => void) | null): Promise<T> {\r\n return this.promise.finally(onfinally);\r\n }\r\n}\r\n\r\nexport const resolvedVoidPromise: Promise<void> = Promise.resolve();\r\n","import { PromiseSource } from './promise-source.js';\r\n\r\n/** Typed pub/sub event handler set — similar to .NET's EventHandler<T> multicast delegate. */\r\nexport class EventHandlerSet<T> {\r\n private _handlers = new Set<(arg: T) => void>();\r\n\r\n get count(): number {\r\n return this._handlers.size;\r\n }\r\n\r\n add(handler: (arg: T) => void): void {\r\n this._handlers.add(handler);\r\n }\r\n\r\n remove(handler: (arg: T) => void): void {\r\n this._handlers.delete(handler);\r\n }\r\n\r\n trigger(arg: T): void {\r\n for (const handler of this._handlers) handler(arg);\r\n }\r\n\r\n clear(): void {\r\n this._handlers.clear();\r\n }\r\n\r\n whenNext(): Promise<T> {\r\n const ps = new PromiseSource<T>();\r\n const handler = (arg: T) => {\r\n this._handlers.delete(handler);\r\n ps.resolve(arg);\r\n };\r\n this._handlers.add(handler);\r\n return ps;\r\n }\r\n}\r\n","/** Error type rejected by {@link withTimeout} when its budget elapses. */\nexport class TimeoutError extends Error {\n override readonly name = 'TimeoutError';\n\n constructor(message = 'Operation timed out') {\n super(message);\n }\n}\n\n/**\n * Race `promise` against a `ms`-millisecond timer. Resolves with the inner\n * promise's value if it settles first; otherwise rejects with a\n * {@link TimeoutError} carrying `message`. The timer is always cleared in\n * a `finally`, so it cannot keep the event loop alive after the race ends.\n *\n * The inner promise's rejection (and the timeout's) are routed through\n * `Promise.race`, so callers should `await` the result inside a `try/catch`\n * exactly as they would for a single awaited promise. There's no\n * \"unhandled rejection\" hazard from the timeout branch — the race always\n * observes whichever promise wins, and the loser is allowed to settle\n * silently into the void.\n */\nexport async function withTimeout<T>(\n promise: PromiseLike<T>,\n ms: number,\n message?: string\n): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeoutPromise = new Promise<never>((_, reject) => {\n timer = setTimeout(\n () => reject(new TimeoutError(message ?? `Operation timed out after ${ms}ms`)),\n ms\n );\n });\n // Routed via `Promise.race` below; suppress the standalone unhandled-\n // rejection warning that fires when `promise` wins instead.\n timeoutPromise.catch(() => { /* noop */ });\n try {\n return await Promise.race([promise, timeoutPromise]);\n } finally {\n if (timer !== undefined) clearTimeout(timer);\n }\n}\n","import { PromiseSource } from './promise-source.js';\nimport { TimeoutError } from './withTimeout.js';\n\n/**\n * A {@link PromiseSource} with a built-in timer that can reject (or run a\n * caller-supplied callback) after a configurable delay. The timer is\n * automatically cleared when the promise settles by other means, so callers\n * don't have to remember to `clearTimeout()` on every success path.\n *\n * Typical use:\n * ```ts\n * const ps = new PromiseSourceWithTimeout<string>();\n * ps.setTimeout(5_000); // rejects after 5s if still pending\n * ps.setTimeout(5_000, () => ps.resolve('fallback')); // or run a custom callback\n * ```\n *\n * Replaces the `PromiseSourceWithTimeout` previously kept in\n * `ActualChat/src/nodejs/src/promises.ts`. Note: the Voxt original supported a\n * \"precise\" (requestAnimationFrame-based) variant; we drop it here because no\n * caller in ActualChat uses it outside `promises.ts` itself.\n */\nexport class PromiseSourceWithTimeout<T> extends PromiseSource<T> {\n private _timer: ReturnType<typeof setTimeout> | undefined;\n\n hasTimeout(): boolean {\n return this._timer !== undefined;\n }\n\n /**\n * Install (or replace) a timeout. Pass `null` to remove without setting a\n * new one. `callback` is invoked when the timer fires — if omitted, the\n * promise is rejected with a generic \"timed out\" error.\n */\n setTimeout(ms: number | null, callback?: () => unknown): void {\n this.clearTimeout();\n if (ms === null || this.isCompleted) return;\n\n this._timer = setTimeout(() => {\n this._timer = undefined;\n if (callback) callback();\n else this.reject(new TimeoutError(`The promise has timed out after ${ms}ms.`));\n }, ms);\n }\n\n clearTimeout(): void {\n if (this._timer === undefined) return;\n clearTimeout(this._timer);\n this._timer = undefined;\n }\n\n override resolve(value: T): boolean {\n const didSettle = super.resolve(value);\n if (didSettle) this.clearTimeout();\n return didSettle;\n }\n\n override reject(reason?: unknown): boolean {\n const didSettle = super.reject(reason);\n if (didSettle) this.clearTimeout();\n return didSettle;\n }\n}\n","/**\n * Pre-resolved promises for the three values most often returned as a\n * \"no-op\" successful path: `void`, `true`, `false`. Returning these\n * avoids allocating a fresh promise per call site.\n *\n * Idiomatic use:\n * ```ts\n * if (alreadyInitialized) return ResolvedPromise.Void;\n * ```\n */\nexport const ResolvedPromise = {\n Void: Promise.resolve(),\n True: Promise.resolve(true),\n False: Promise.resolve(false),\n} as const;\n","/**\n * Sentinel returned/thrown by code that distinguishes \"the operation took\n * too long\" from a generic rejection. Identity-comparable via the\n * `instance` singleton — callers can branch on `result === TimedOut.instance`.\n */\nexport class TimedOut {\n static readonly instance: TimedOut = new TimedOut();\n}\n","/** Resolves after `ms` milliseconds. */\nexport function delayAsync(ms: number): Promise<void> {\n return new Promise<void>(resolve => {\n setTimeout(resolve, ms);\n });\n}\n\n/** Resolves with `value` after `ms` milliseconds. */\nexport function delayAsyncWith<T>(ms: number, value: T): Promise<T> {\n return new Promise<T>(resolve => {\n setTimeout(() => resolve(value), ms);\n });\n}\n","/**\n * Adapt an `AbortSignal` to a Promise that **rejects** with the signal's\n * `reason` once the signal fires (or immediately, if it's already\n * aborted). Mirrors `signal.throwIfAborted()` semantics in Promise form:\n * the rejected value is exactly what `throwIfAborted()` would have\n * thrown — by default a `DOMException` with `name === 'AbortError'`,\n * or whatever was passed to `abortController.abort(reason)`.\n *\n * Operators racing upstream pulls / timers against cancellation plug\n * this into `Promise.race(...)` so abort propagates as a thrown error —\n * `try/finally` blocks unwind naturally; no sentinel values to thread.\n *\n * Promises are cached per signal: every call for the same signal returns\n * the SAME promise and registers AT MOST ONE listener. Operators that\n * race per-iteration (e.g. encode loops calling this once per chunk)\n * won't accumulate listeners or hit Node's `MaxListenersExceeded` warning.\n * The cache is a `WeakMap` so signals remain GC-eligible normally.\n *\n * Callers that prefer a sentinel can attach `.catch()` to convert the\n * rejection back into a value: `abortPromise(s).catch(() => 'stopped')`.\n */\nconst abortPromiseCache = new WeakMap<AbortSignal, Promise<never>>();\n\nexport function abortPromise(signal: AbortSignal): Promise<never> {\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors -- mirroring `signal.throwIfAborted()`: the rejection value IS the signal's reason, which by Web spec is a `DOMException` by default but can be any value the caller passed to `abort(reason)`.\n if (signal.aborted) return Promise.reject(signal.reason);\n let cached = abortPromiseCache.get(signal);\n if (!cached) {\n cached = new Promise<never>((_, reject) => {\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors -- see comment above; signal.reason is the canonical thrown value.\n signal.addEventListener('abort', () => reject(signal.reason), { once: true });\n });\n // Mark the cached rejection as observed so unhandled-rejection\n // warnings don't fire when a caller never `await`s it (e.g. an\n // operator that completed before abort and let the race promise\n // GC). The actual await-time rejection still surfaces normally.\n cached.catch(() => { /* swallow for cache-only consumers */ });\n abortPromiseCache.set(signal, cached);\n }\n return cached;\n}\n","import { LogLevel, createLogProvider } from './logging.js';\n\n/** Log scopes used inside `@actuallab/core` itself. Each is registered at\n * `core.<scope>`. Keep the list tight — most utilities should propagate\n * errors rather than log them. */\nexport type CoreLogScope =\n | 'retry'\n | 'throttle';\n\nconst scopeDefaults: Record<CoreLogScope, LogLevel> = {\n retry: LogLevel.Warn,\n throttle: LogLevel.Warn,\n};\n\nexport const getLogs = createLogProvider<CoreLogScope>('core.', scopeDefaults);\n","import { getLogs } from './internal-logging.js';\n\nconst { errorLog } = getLogs('throttle');\n\n/** A function wrapped by {@link throttle} or {@link debounce}. Calling it\n * triggers the underlying function according to the scheduling rule;\n * `reset()` discards any pending scheduled call. */\nexport interface ResettableFunc<TArgs extends unknown[]> {\n (...args: TArgs): void;\n reset(): void;\n}\n\nclass Call<TArgs extends unknown[]> {\n constructor(\n readonly func: (...args: TArgs) => unknown,\n readonly self: unknown,\n readonly parameters: TArgs\n ) { }\n\n invoke(): unknown {\n return this.func.apply(this.self, this.parameters);\n }\n\n invokeSilently(): unknown {\n try {\n return this.invoke();\n } catch (error) {\n errorLog?.log('Call.invokeSilently: unhandled error:', error);\n }\n }\n}\n\n/** Throttle modes:\n * - `default` — fire the head call immediately, then drop further calls\n * until the interval elapses; the *last* one is fired at interval end.\n * - `skip` — fire the head call immediately, drop ALL calls during the\n * interval (no tail call).\n * - `delayHead` — delay even the head call by one interval; subsequent\n * calls overwrite the pending one. */\nexport type ThrottleMode = 'default' | 'skip' | 'delayHead';\n\n/**\n * Throttle calls to `func` so that it fires at most once every `intervalMs`.\n * The returned function has a `.reset()` that discards any pending tail call\n * and re-arms the head-call behavior on the next invocation.\n */\nexport function throttle<TArgs extends unknown[]>(\n func: (...args: TArgs) => unknown,\n intervalMs: number,\n mode: ThrottleMode = 'default'\n): ResettableFunc<TArgs> {\n let lastCall: Call<TArgs> | null = null;\n let nextFireTime = 0;\n let timeoutHandle: ReturnType<typeof setTimeout> | null = null;\n\n const reset = (): void => {\n if (timeoutHandle !== null) clearTimeout(timeoutHandle);\n timeoutHandle = null;\n lastCall = null;\n nextFireTime = 0;\n };\n\n const fire = (): void => {\n if (timeoutHandle !== null) clearTimeout(timeoutHandle);\n\n if (lastCall !== null) {\n const call = lastCall;\n lastCall = null;\n nextFireTime = Date.now() + intervalMs;\n timeoutHandle = setTimeout(fire, intervalMs);\n call.invokeSilently(); // Must be last\n } else {\n timeoutHandle = null;\n nextFireTime = 0;\n }\n };\n\n const wrapped: ResettableFunc<TArgs> = function (this: unknown, ...args: TArgs): void {\n const call = new Call<TArgs>(func, this, args);\n const fireDelay = nextFireTime - Date.now();\n if (timeoutHandle !== null && fireDelay <= 0) {\n // Delayed \"fire\" is ready but not yet executed — flush it now.\n fire();\n }\n\n if (timeoutHandle === null) {\n // lastCall is null here\n nextFireTime = Date.now() + intervalMs;\n timeoutHandle = setTimeout(fire, intervalMs);\n if (mode === 'delayHead') {\n lastCall = call;\n } else {\n call.invokeSilently();\n }\n } else if (mode !== 'skip') {\n lastCall = call;\n }\n };\n wrapped.reset = reset;\n return wrapped;\n}\n\n/**\n * Debounce calls to `func`: the function fires only after `intervalMs` have\n * elapsed since the LAST call. Each new call resets the timer. `.reset()`\n * discards any pending fire without invoking `func`.\n */\nexport function debounce<TArgs extends unknown[]>(\n func: (...args: TArgs) => unknown,\n intervalMs: number\n): ResettableFunc<TArgs> {\n let lastCall: Call<TArgs> | null = null;\n let nextFireTime = 0;\n let timeoutHandle: ReturnType<typeof setTimeout> | null = null;\n\n const reset = (): void => {\n // Don't clearTimeout here: the live timer will see `lastCall === null`\n // and exit quietly. Avoids a churn of cleared-then-set timers when\n // callers `reset()` then immediately call again.\n timeoutHandle = null;\n lastCall = null;\n nextFireTime = 0;\n };\n\n const fire = (): void => {\n if (timeoutHandle !== null) clearTimeout(timeoutHandle);\n timeoutHandle = null;\n\n const fireDelay = nextFireTime - Date.now();\n if (fireDelay <= 0) {\n nextFireTime = 0;\n if (lastCall !== null) {\n const call = lastCall;\n lastCall = null;\n call.invokeSilently(); // Must be last\n }\n } else {\n // Another call landed; reschedule for the new deadline.\n timeoutHandle = setTimeout(fire, fireDelay);\n }\n };\n\n const wrapped: ResettableFunc<TArgs> = function (this: unknown, ...args: TArgs): void {\n lastCall = new Call<TArgs>(func, this, args);\n nextFireTime = Date.now() + intervalMs;\n timeoutHandle ??= setTimeout(fire, intervalMs);\n };\n wrapped.reset = reset;\n return wrapped;\n}\n","/**\n * Wrap an async function so concurrent invocations are serialized into a\n * single chain — each call awaits the previous one before running, and the\n * caller receives the result of *its* own invocation.\n *\n * Useful for stateful async operations (DB writes, file I/O, network I/O\n * that must not overlap) where the underlying contract is \"one at a time.\"\n *\n * If `limit` is set and the queue is already that deep, the call short-\n * circuits and returns the same promise the most recent queued call returned\n * — i.e. it coalesces excess pressure onto the trailing in-flight call.\n * Pass `null` (the default) for unbounded queueing.\n */\nexport function serialize<TArgs extends unknown[], TResult>(\n func: (...args: TArgs) => PromiseLike<TResult> | TResult,\n limit: number | null = null\n): (...args: TArgs) => Promise<TResult> {\n let lastCall: Promise<TResult> = Promise.resolve(null as TResult);\n let queueSize = 0;\n\n return function (this: unknown, ...args: TArgs): Promise<TResult> {\n if (limit !== null && queueSize >= limit) return lastCall;\n\n queueSize++;\n const prevCall = lastCall;\n // Capture `this` via the bound caller chain so we don't have to alias\n // `this` to a local (which the linter flags). `Reflect.apply` preserves\n // the function's typed return value (unlike `Function.prototype.apply`,\n // which is declared as returning `any`).\n const invoke = (): PromiseLike<TResult> | TResult => Reflect.apply(func, this, args);\n return lastCall = (async () => {\n try {\n // Wait for the previous call to settle — but don't inherit its\n // rejection. The previous caller already owns that error; if we\n // re-threw here, a single failure would poison the queue\n // forever (every subsequent call awaits the previous one).\n await prevCall.catch(() => { /* see comment above */ });\n return await invoke();\n } finally {\n queueSize--;\n }\n })();\n };\n}\n","/**\n * A fixed-capacity circular buffer supporting efficient push/pull at both\n * head and tail.\n *\n * Direct port of .NET `ActualLab.Collections.RingBuffer<T>` at\n * src/ActualLab.Core/Collections/RingBuffer.cs (simplified — TS uses plain\n * modulo instead of the power-of-two-minus-one bit-mask trick, since the\n * performance difference is negligible in JavaScript).\n */\nexport class RingBuffer<T> {\n private _buffer: (T | undefined)[];\n private _start = 0;\n private _end = 0;\n private _count = 0;\n\n readonly capacity: number;\n\n get count(): number { return this._count; }\n get isEmpty(): boolean { return this._count === 0; }\n get isFull(): boolean { return this._count === this.capacity; }\n get remainingCapacity(): number { return this.capacity - this._count; }\n get hasRemainingCapacity(): boolean { return this._count < this.capacity; }\n\n constructor(capacity: number) {\n if (capacity < 1)\n throw new RangeError(`RingBuffer capacity must be >= 1 (was ${capacity}).`);\n this.capacity = capacity;\n this._buffer = new Array<T | undefined>(capacity);\n }\n\n /** Read the item at `index` (0-indexed, from head). */\n get(index: number): T {\n if (index < 0 || index >= this._count)\n throw new RangeError(`Index ${index} out of range [0, ${this._count}).`);\n return this._buffer[(this._start + index) % this.capacity] as T;\n }\n\n /** Add an item at the tail. Throws if the buffer is full. */\n pushTail(item: T): void {\n if (this._count >= this.capacity)\n throw new Error('RingBuffer is full.');\n this._buffer[this._end] = item;\n this._end = (this._end + 1) % this.capacity;\n this._count++;\n }\n\n /** Add an item at the tail, evicting the head item if the buffer is full. */\n pushTailAndMoveHeadIfFull(item: T): void {\n if (this._count >= this.capacity) {\n this._buffer[this._start] = undefined;\n this._start = (this._start + 1) % this.capacity;\n this._count--;\n }\n this.pushTail(item);\n }\n\n /** Remove the head item. Throws if the buffer is empty. */\n pullHead(): T {\n if (this._count === 0)\n throw new Error('RingBuffer is empty.');\n const head = this._buffer[this._start] as T;\n this._buffer[this._start] = undefined;\n this._start = (this._start + 1) % this.capacity;\n this._count--;\n return head;\n }\n\n /**\n * Advance the head by `skipCount` slots, releasing references to skipped\n * items so they can be garbage-collected.\n */\n moveHead(skipCount: number): void {\n if (skipCount === 0) return;\n if (skipCount < 0 || skipCount > this._count)\n throw new RangeError(`skipCount ${skipCount} out of range [0, ${this._count}].`);\n for (let k = 0; k < skipCount; k++) {\n this._buffer[(this._start + k) % this.capacity] = undefined;\n }\n this._start = (this._start + skipCount) % this.capacity;\n this._count -= skipCount;\n }\n\n /** Remove all items. */\n clear(): void {\n for (let i = 0; i < this.capacity; i++) this._buffer[i] = undefined;\n this._start = 0;\n this._end = 0;\n this._count = 0;\n }\n\n /** Copy the buffer's contents to a new array, head-first. */\n toArray(): T[] {\n const out = new Array<T>(this._count);\n for (let i = 0; i < this._count; i++) {\n out[i] = this._buffer[(this._start + i) % this.capacity] as T;\n }\n return out;\n }\n}\n","// .NET counterpart: ActualLab.Time.RetryDelaySeq\r\n\r\nconst DefaultSpread = 0.1;\r\nconst DefaultMultiplier = 1.41421356237; // Math.sqrt(2)\r\n\r\nfunction applySpread(origin: number, spread: number): number {\r\n if (spread <= 0) return origin;\r\n const delta = origin * spread;\r\n return origin + (Math.random() * 2 - 1) * delta;\r\n}\r\n\r\nexport class RetryDelaySeq {\r\n readonly min: number;\r\n readonly max: number;\r\n readonly spread: number;\r\n readonly multiplier: number;\r\n\r\n constructor(\r\n min: number,\r\n max: number,\r\n spread: number = DefaultSpread,\r\n multiplier: number = DefaultMultiplier\r\n ) {\r\n this.min = min;\r\n this.max = max;\r\n this.spread = spread;\r\n this.multiplier = multiplier;\r\n }\r\n\r\n static fixed(\r\n delayMs: number,\r\n spread: number = DefaultSpread\r\n ): RetryDelaySeq {\r\n return new RetryDelaySeq(delayMs, delayMs, spread, 1);\r\n }\r\n\r\n static exp(\r\n minMs: number,\r\n maxMs: number,\r\n spread: number = DefaultSpread,\r\n multiplier: number = DefaultMultiplier\r\n ): RetryDelaySeq {\r\n return new RetryDelaySeq(minMs, maxMs, spread, multiplier);\r\n }\r\n\r\n getDelay(failureCount: number): number {\r\n if (this.min < 0)\r\n throw new Error('RetryDelaySeq.min must be non-negative.');\r\n if (failureCount <= 0) return 0;\r\n\r\n if (this.multiplier <= 1) {\r\n // Fixed — no exponential component\r\n return Math.max(\r\n 0,\r\n this.spread <= 0 ? this.min : applySpread(this.min, this.spread)\r\n );\r\n }\r\n\r\n const multiplier = Math.pow(this.multiplier, failureCount - 1);\r\n const raw = Math.min(this.max, this.min * multiplier);\r\n return Math.max(0, applySpread(raw, this.spread));\r\n }\r\n}\r\n","// .NET counterparts: ActualLab.Net.RetryDelayer, ActualLab.Net.RetryDelay\r\n\r\nimport { EventHandlerSet } from './events.js';\r\nimport { RetryDelaySeq } from './retry-delay-seq.js';\r\n\r\nexport interface RetryDelay {\r\n readonly promise: Promise<void>;\r\n readonly endsAt: number; // Date.now()-based timestamp, 0 = no delay\r\n readonly isLimitExceeded: boolean;\r\n}\r\n\r\nexport const RetryDelayNone: RetryDelay = {\r\n promise: Promise.resolve(),\r\n endsAt: 0,\r\n isLimitExceeded: false,\r\n};\r\n\r\nexport const RetryDelayLimitExceeded: RetryDelay = {\r\n promise: Promise.resolve(),\r\n endsAt: 0,\r\n isLimitExceeded: true,\r\n};\r\n\r\nexport class RetryDelayer {\r\n private _cancelController = new AbortController();\r\n\r\n delays: RetryDelaySeq = RetryDelaySeq.fixed(1000);\r\n limit: number | undefined = undefined;\r\n\r\n readonly cancelDelaysChanged = new EventHandlerSet<void>();\r\n\r\n getDelay(tryIndex: number, cancellationSignal?: AbortSignal): RetryDelay {\r\n if (this.limit !== undefined && tryIndex >= this.limit)\r\n return RetryDelayLimitExceeded;\r\n\r\n const delayMs = this.delays.getDelay(tryIndex);\r\n if (tryIndex === 0 || delayMs <= 0) return RetryDelayNone;\r\n\r\n const actualDelayMs = Math.max(1, delayMs);\r\n const endsAt = Date.now() + actualDelayMs;\r\n\r\n const cancelSignal = this._cancelController.signal;\r\n const promise = new Promise<void>((resolve, reject) => {\r\n const timer = setTimeout(() => {\r\n cleanup();\r\n resolve();\r\n }, actualDelayMs);\r\n\r\n const onCancel = () => {\r\n clearTimeout(timer);\r\n cleanup();\r\n resolve(); // cancelDelays resolves, does NOT reject\r\n };\r\n\r\n const onAbort = () => {\r\n clearTimeout(timer);\r\n cleanup();\r\n reject(new Error('Retry delay aborted.'));\r\n };\r\n\r\n const cleanup = () => {\r\n cancelSignal.removeEventListener('abort', onCancel);\r\n cancellationSignal?.removeEventListener('abort', onAbort);\r\n };\r\n\r\n cancelSignal.addEventListener('abort', onCancel, { once: true });\r\n cancellationSignal?.addEventListener('abort', onAbort, {\r\n once: true,\r\n });\r\n });\r\n\r\n return { promise, endsAt, isLimitExceeded: false };\r\n }\r\n\r\n cancelDelays(): void {\r\n const old = this._cancelController;\r\n this._cancelController = new AbortController();\r\n old.abort();\r\n this.cancelDelaysChanged.trigger();\r\n }\r\n}\r\n","import { delayAsync } from './delay.js';\nimport { getLogs } from './internal-logging.js';\n\nconst { warnLog } = getLogs('retry');\n\n/** A sequence of retry delays — given a 1-based try index (1 = first\n * retry, i.e. AFTER the initial failure), returns the delay in ms before\n * the next attempt. For more elaborate delay schemes, see\n * {@link RetryDelaySeq.getDelay}. */\nexport type RetryDelaySchedule = (tryIndex: number) => number;\n\nconst defaultRetryDelays: RetryDelaySchedule = () => 50;\n\n/**\n * Run `fn` up to `tryCount` times, awaiting a delay between attempts.\n * The last error is rethrown if every attempt fails.\n *\n * `fn` is passed the 0-based attempt index and the last error (or\n * `undefined` for the first attempt) — useful for adapting behavior per\n * try (e.g. switching endpoints, escalating timeouts).\n */\nexport async function retry<TResult>(\n tryCount: number,\n fn: (tryIndex: number, lastError: unknown) => PromiseLike<TResult> | TResult,\n retryDelays: RetryDelaySchedule = defaultRetryDelays,\n): Promise<TResult> {\n if (tryCount <= 0)\n throw new Error('retry: tryCount must be positive.');\n\n let lastError: unknown;\n for (let tryIndex = 0; ; ) {\n if (tryIndex >= tryCount) throw lastError;\n try {\n return await fn(tryIndex, lastError);\n } catch (e) {\n lastError = e;\n }\n ++tryIndex;\n if (tryIndex >= tryCount) throw lastError;\n warnLog?.log(`retry(${tryIndex}/${tryCount}): error:`, lastError);\n await delayAsync(retryDelays(tryIndex));\n }\n}\n\n/**\n * Run `fn` and swallow any throw, returning `onError(e)` if provided or\n * `undefined` otherwise. The returned promise always settles successfully\n * — the caller never has to `try/catch` it.\n *\n * Useful where a logical \"best-effort\" return is wanted but the runtime\n * defaults — unhandled rejection warnings, exception escape past finally\n * blocks — are not.\n */\nexport async function catchErrors<TResult>(\n fn: () => PromiseLike<TResult> | TResult,\n onError?: (e: unknown) => TResult,\n): Promise<TResult | undefined> {\n try {\n return await fn();\n } catch (e) {\n return onError ? onError(e) : undefined;\n }\n}\n"],"mappings":"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","names":["LogLevel","reset"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/polyfills.ts","../src/disposable.ts","../src/logging-init.ts","../src/logging.ts","../src/result.ts","../src/async-context.ts","../src/async-lock.ts","../src/promise-source.ts","../src/events.ts","../src/async-signal.ts","../src/withTimeout.ts","../src/promise-source-with-timeout.ts","../src/resolved-promise.ts","../src/timed-out.ts","../src/delay.ts","../src/abort-promise.ts","../src/cancellation.ts","../src/await-with-cleanup.ts","../src/internal-logging.ts","../src/throttle.ts","../src/serialize.ts","../src/ring-buffer.ts","../src/retry-delay-seq.ts","../src/retry-delayer.ts","../src/retry.ts","../src/decorators.ts"],"sourcesContent":["import './polyfills.js';\r\n\r\n// Disposable\r\nexport type { Disposable, AsyncDisposable } from './disposable.js';\r\nexport { DisposableBag } from './disposable.js';\r\n\r\n// Logging\r\nexport type { LogRef, LogScopeFns } from './logging.js';\r\nexport { Log, LogLevel, createLogProvider } from './logging.js';\r\nexport { initLogging, initWorkerLogging, LogLevelController } from './logging-init.js';\r\n\r\n// Result & IResult\r\nexport type { IResult } from './result.js';\r\nexport {\r\n Result,\r\n result,\r\n errorResult,\r\n resultFrom,\r\n resultFromAsync,\r\n} from './result.js';\r\n\r\n// Async-related\r\nexport {\r\n AsyncContext,\r\n AsyncContextKey,\r\n abortSignalKey,\r\n} from './async-context.js';\r\nexport { AsyncLock } from './async-lock.js';\r\n\r\n// Event handling, primises\r\nexport { EventHandlerSet } from './events.js';\r\nexport { AsyncSignal } from './async-signal.js';\r\nexport { PromiseSource, resolvedVoidPromise } from './promise-source.js';\r\nexport { PromiseSourceWithTimeout } from './promise-source-with-timeout.js';\r\nexport { ResolvedPromise } from './resolved-promise.js';\r\nexport { TimedOut } from './timed-out.js';\r\nexport { TimeoutError, withTimeout } from './withTimeout.js';\r\nexport { delayAsync, delayAsyncWith } from './delay.js';\r\nexport { abortPromise } from './abort-promise.js';\r\nexport { isCancellation, cancellationError } from './cancellation.js';\r\nexport type { AbortOutcome } from './await-with-cleanup.js';\r\nexport { awaitWithCleanup } from './await-with-cleanup.js';\r\n\r\n// Higher-order async operators\r\nexport type { ResettableFunc, ThrottleMode } from './throttle.js';\r\nexport { throttle, debounce } from './throttle.js';\r\nexport { serialize } from './serialize.js';\r\n\r\n// Collections\r\nexport { RingBuffer } from './ring-buffer.js';\r\n\r\n// Resilience\r\nexport { RetryDelaySeq } from './retry-delay-seq.js';\r\nexport type { RetryDelay } from './retry-delayer.js';\r\nexport {\r\n RetryDelayer,\r\n RetryDelayNone,\r\n RetryDelayLimitExceeded,\r\n} from './retry-delayer.js';\r\nexport type { RetryDelaySchedule } from './retry.js';\r\nexport { retry, catchErrors } from './retry.js';\r\n\r\n// Decorator helpers\r\nexport { ownMetadata, resolveArgCount } from './decorators.js';\r\n","// TC39 decorator metadata polyfill — required for Symbol.metadata support\r\n// in runtimes that don't yet implement it natively.\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access\r\n(Symbol as any).metadata ??= Symbol('Symbol.metadata');\r\n","/** Synchronous dispose pattern, similar to .NET's IDisposable. */\r\nexport interface Disposable {\r\n dispose(): void;\r\n}\r\n\r\n/** Asynchronous dispose pattern, similar to .NET's IAsyncDisposable. */\r\nexport interface AsyncDisposable {\r\n disposeAsync(): Promise<void>;\r\n}\r\n\r\n/** Aggregates multiple disposables and disposes them together. */\r\nexport class DisposableBag implements Disposable, AsyncDisposable {\r\n private _items: (Disposable | AsyncDisposable)[] = [];\r\n private _disposed = false;\r\n\r\n get isDisposed(): boolean {\r\n return this._disposed;\r\n }\r\n\r\n add(item: Disposable | AsyncDisposable): void {\r\n if (this._disposed)\r\n throw new Error('DisposableBag is already disposed.');\r\n this._items.push(item);\r\n }\r\n\r\n dispose(): void {\r\n if (this._disposed) return;\r\n this._disposed = true;\r\n const items = this._items;\r\n this._items = [];\r\n // Dispose in reverse order (LIFO)\r\n for (let i = items.length - 1; i >= 0; i--) {\r\n const item = items[i];\r\n if ('dispose' in item) item.dispose();\r\n }\r\n }\r\n\r\n async disposeAsync(): Promise<void> {\r\n if (this._disposed) return;\r\n this._disposed = true;\r\n const items = this._items;\r\n this._items = [];\r\n for (let i = items.length - 1; i >= 0; i--) {\r\n const item = items[i];\r\n if ('disposeAsync' in item) await item.disposeAsync();\r\n else if ('dispose' in item) item.dispose();\r\n }\r\n }\r\n}\r\n","// Initialization helpers for the logging system.\n//\n// The Log class uses a single Map<string, LogLevel> to determine the minimum\n// level for each scope. This module is responsible for:\n// - Persisting the map across page reloads via localStorage on the main\n// thread, and via IndexedDB for workers.\n// - Exposing a globally accessible LogLevelController so developers can tweak\n// levels at runtime from the browser dev console (globalThis.logLevels).\n//\n// initLogging() is idempotent and called automatically on the first Log.get().\n//\n// Runtime override examples (paste into browser dev console):\n// logLevels.override('rpc.RpcPeer', 1) // exact: one scope to Debug\n// logLevels.override('rpc.*', 1) // prefix: all rpc.* scopes\n// logLevels.override('*Video*', 1) // contains: every scope with 'Video'\n// logLevels.override('*Decoder', 1) // suffix: every scope ending in 'Decoder'\n// logLevels.reset() // reset to package defaults\n// logLevels.clear() // clear all overrides\n\nimport { Log, LogLevel } from './logging.js';\n\nconst GlobalThisKey = 'logLevels';\nconst StorageKey = 'logLevels';\nconst DateStorageKey = `${StorageKey}.date`;\nconst MaxStorageAge = 86_400_000 * 3; // 3 days\nconst IndexedDbName = 'actuallab-logging';\nconst IndexedDbStore = 'settings';\nconst IndexedDbKey = 'logLevels';\n\nconst localStorage: Storage | null = tryGetLocalStorage();\n\n// Workers, worklets, and service workers run in separate JS realms with\n// their own globalThis. Within one realm, esbuild can also produce multiple\n// chunks that each carry their own copy of @actuallab/core (so multiple\n// distinct `Log` classes exist). We want the install + restore + console\n// message to happen exactly once per realm — gate via globalThis.logLevels.\nconst isMainThread = typeof window !== 'undefined';\n\nexport function initLogging(): void {\n // Warn is the global baseline — packages set per-scope defaults\n // (typically Info or Warn) via createLogProvider.\n Log.defaultMinLevel = LogLevel.Warn;\n const minLevels = Log.minLevels;\n const g = globalThis as Record<string, unknown>;\n const existing = g[GlobalThisKey] as LogLevelController | undefined;\n\n if (existing !== undefined) {\n // Another chunk in this realm already initialized. Mirror its\n // overrides into our local Log.minLevels so this Log class observes\n // the same effective levels. (Each chunk has its own Log class with\n // its own static minLevels Map — they only converge through this\n // one-shot copy at init time.)\n for (const [k, v] of existing.getMinLevels())\n minLevels.set(k, v);\n return;\n }\n\n g[GlobalThisKey] = new LogLevelController(minLevels);\n const wasRestored = restore(minLevels);\n if (wasRestored) {\n if (isMainThread)\n console.log('Logging: logLevels are restored');\n }\n else {\n if (isMainThread)\n console.log('Logging: logLevels are reset');\n reset(minLevels);\n }\n}\n\n/** Worker bootstrap path: await this before dynamically importing any module\n * that may call getLogs() at top level. */\nexport async function initWorkerLogging(): Promise<void> {\n Log.defaultMinLevel = LogLevel.Warn;\n const minLevels = Log.minLevels;\n const g = globalThis as Record<string, unknown>;\n const existing = g[GlobalThisKey] as LogLevelController | undefined;\n\n if (existing !== undefined) {\n for (const [k, v] of existing.getMinLevels())\n minLevels.set(k, v);\n return;\n }\n\n g[GlobalThisKey] = new LogLevelController(minLevels);\n const wasRestored = await restoreFromIndexedDb(minLevels);\n if (!wasRestored)\n reset(minLevels, false);\n}\n\nexport class LogLevelController {\n constructor(private minLevels: Map<string, LogLevel>)\n { }\n\n /** Internal: used by initLogging() in secondary bundles to share the\n * primary bundle's minLevels map. */\n public getMinLevels(): Map<string, LogLevel> {\n return this.minLevels;\n }\n\n /** List the current set of overrides. */\n public list(): Record<string, LogLevel> {\n return Object.fromEntries(this.minLevels);\n }\n\n /** Print every known scope's effective level to the console as a table.\n * Shows: scope, effective level, the source ('override' / 'default-key' /\n * 'package-default' / 'baseline'), and the package default for reference.\n * Use this from the dev console to discover what to pass to override(). */\n public dump(): void {\n const baseline = Log.defaultMinLevel;\n const globalOverride = this.minLevels.get('default');\n const allScopes = new Set<string>([\n ...Log.knownScopes,\n ...Log.scopeDefaults.keys(),\n ...this.minLevels.keys(),\n ]);\n // Drop the special 'default' bucket — surfaced separately below.\n allScopes.delete('default');\n const rows: Record<string, {\n level: string;\n source: string;\n packageDefault: string;\n }> = {};\n const sorted = [...allScopes].sort();\n for (const scope of sorted) {\n const override = this.minLevels.get(scope);\n const pkgDefault = Log.scopeDefaults.get(scope);\n let level: LogLevel;\n let source: string;\n if (override !== undefined) {\n level = override;\n source = 'override';\n }\n else if (globalOverride !== undefined) {\n level = globalOverride;\n source = \"minLevels.get('default')\";\n }\n else if (pkgDefault !== undefined) {\n level = pkgDefault;\n source = 'package-default';\n }\n else {\n level = baseline;\n source = 'baseline';\n }\n rows[scope] = {\n level: LogLevel[level],\n source,\n packageDefault: pkgDefault === undefined ? '-' : LogLevel[pkgDefault],\n };\n }\n console.table(rows);\n console.log(\n `Baseline: ${LogLevel[baseline]}` +\n (globalOverride === undefined ? '' : `, default override: ${LogLevel[globalOverride]}`),\n );\n }\n\n /** Override the level for every scope matching a glob-like pattern.\n * `*` matches any sequence of characters; everything else is literal.\n * Examples:\n * override('rpc.RpcPeer', 1) // exact — one scope to Debug\n * override('rpc.*', 1) // prefix — every scope starting with 'rpc.'\n * override('*rpc*', 1) // contains — every scope with 'rpc' in it\n * override('*Peer', 1) // suffix — every scope ending with 'Peer'\n * Matches scopes that are user-overridden, package-registered (defaults),\n * or have ever been requested via Log.get(). If the pattern has no `*`\n * and nothing known matches, the literal scope is set anyway — so an\n * exact-name override placed before its scope is loaded still applies.\n * Persisted to localStorage + IndexedDB. */\n public override(pattern: string, newLevel: LogLevel): void {\n const matched = new Set<string>();\n if (pattern.includes('*')) {\n const re = patternToRegExp(pattern);\n for (const [scope] of this.minLevels)\n if (re.test(scope)) matched.add(scope);\n for (const [scope] of Log.scopeDefaults)\n if (re.test(scope)) matched.add(scope);\n for (const scope of Log.knownScopes)\n if (re.test(scope)) matched.add(scope);\n }\n else {\n matched.add(pattern);\n }\n for (const scope of matched)\n this.minLevels.set(scope, newLevel);\n persist(this.minLevels);\n }\n\n /** Reset all overrides; package defaults take effect again. Persisted. */\n public reset(): void {\n reset(this.minLevels);\n }\n\n /** Clear all overrides (no global default unless `defaultLevel` is given). */\n public clear(defaultLevel?: LogLevel): void {\n this.minLevels.clear();\n if (defaultLevel !== undefined)\n this.minLevels.set('default', defaultLevel);\n persist(this.minLevels);\n }\n}\n\nfunction patternToRegExp(pattern: string): RegExp {\n // Escape regex metacharacters except `*`, then turn each `*` into `.*`.\n const escaped = pattern.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&').replace(/\\*/g, '.*');\n return new RegExp(`^${escaped}$`);\n}\n\ninterface PersistedLogLevels {\n date: number;\n entries: [string, LogLevel][];\n}\n\nfunction restore(minLevels: Map<string, LogLevel>): boolean {\n const snapshot = readFromStorage(localStorage);\n if (!snapshot)\n return false;\n\n return applySnapshot(minLevels, snapshot);\n}\n\nasync function restoreFromIndexedDb(minLevels: Map<string, LogLevel>): Promise<boolean> {\n const snapshot = await readFromIndexedDb();\n if (!snapshot)\n return false;\n\n return applySnapshot(minLevels, snapshot);\n}\n\nfunction readFromStorage(storage: Storage | null): PersistedLogLevels | null {\n if (!storage)\n return null;\n\n try {\n const dateJson = storage.getItem(DateStorageKey);\n const entriesJson = storage.getItem(StorageKey);\n if (!dateJson || !entriesJson)\n return null;\n\n return {\n date: JSON.parse(dateJson) as number,\n entries: JSON.parse(entriesJson) as [string, LogLevel][],\n };\n } catch {\n return null;\n }\n}\n\nfunction applySnapshot(minLevels: Map<string, LogLevel>, snapshot: PersistedLogLevels): boolean {\n if (typeof snapshot.date !== 'number')\n return false;\n if (Date.now() - snapshot.date > MaxStorageAge)\n return false;\n if (!Array.isArray(snapshot.entries))\n return false;\n\n minLevels.clear();\n for (const entry of snapshot.entries) {\n // Runtime guard for JSON-parsed input — types claim it's a tuple, but\n // localStorage may carry corrupted data. eslint flags the length check\n // as always-false against the static type; that's the point.\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!Array.isArray(entry) || entry.length !== 2)\n return false;\n const [key, value] = entry;\n if (typeof key !== 'string' || typeof value !== 'number')\n return false;\n minLevels.set(key, value);\n }\n\n return true;\n}\n\nfunction persist(minLevels: Map<string, LogLevel>): boolean {\n const snapshot = createSnapshot(minLevels);\n let wasPersisted = false;\n\n if (localStorage) {\n try {\n localStorage.setItem(DateStorageKey, JSON.stringify(snapshot.date));\n localStorage.setItem(StorageKey, JSON.stringify(snapshot.entries));\n wasPersisted = true;\n } catch {\n // Storage may be unavailable in private / sandboxed contexts.\n }\n }\n\n void writeToIndexedDb(snapshot);\n return wasPersisted;\n}\n\nfunction createSnapshot(minLevels: Map<string, LogLevel>): PersistedLogLevels {\n return {\n date: Date.now(),\n entries: Array.from(minLevels.entries()),\n };\n}\n\nfunction tryGetLocalStorage(): Storage | null {\n if (typeof globalThis === 'undefined' || !('localStorage' in globalThis))\n return null;\n\n try {\n return (globalThis as unknown as { localStorage: Storage }).localStorage;\n } catch {\n return null;\n }\n}\n\nasync function openLoggingDb(): Promise<IDBDatabase | null> {\n if (typeof indexedDB === 'undefined')\n return null;\n\n return new Promise(resolve => {\n const request = indexedDB.open(IndexedDbName, 1);\n request.onupgradeneeded = () => {\n const db = request.result;\n if (!db.objectStoreNames.contains(IndexedDbStore))\n db.createObjectStore(IndexedDbStore);\n };\n request.onerror = () => resolve(null);\n request.onblocked = () => resolve(null);\n request.onsuccess = () => resolve(request.result);\n });\n}\n\nasync function readFromIndexedDb(): Promise<PersistedLogLevels | null> {\n const db = await openLoggingDb();\n if (!db)\n return null;\n\n return new Promise(resolve => {\n const tx = db.transaction(IndexedDbStore, 'readonly');\n const request = tx.objectStore(IndexedDbStore).get(IndexedDbKey);\n request.onerror = () => resolve(null);\n request.onsuccess = () => resolve(request.result as PersistedLogLevels | null);\n tx.oncomplete = () => db.close();\n tx.onerror = () => db.close();\n tx.onabort = () => db.close();\n });\n}\n\nasync function writeToIndexedDb(snapshot: PersistedLogLevels): Promise<void> {\n const db = await openLoggingDb();\n if (!db)\n return;\n\n await new Promise<void>(resolve => {\n const tx = db.transaction(IndexedDbStore, 'readwrite');\n tx.objectStore(IndexedDbStore).put(snapshot, IndexedDbKey);\n tx.oncomplete = () => {\n db.close();\n resolve();\n };\n tx.onerror = () => {\n db.close();\n resolve();\n };\n tx.onabort = () => {\n db.close();\n resolve();\n };\n });\n}\n\nfunction reset(minLevels: Map<string, LogLevel>, mustPersist = true): void {\n minLevels.clear();\n // Add per-scope defaults here for development.\n // Use prefix conventions: 'rpc.', 'fusion.', 'app.', etc.\n\n // minLevels.set('rpc.RpcPeer', LogLevel.Debug);\n // minLevels.set('fusion.Computed', LogLevel.Debug);\n\n if (mustPersist)\n persist(minLevels);\n}\n","// Lightweight logging primitives shared by all ActualLab TypeScript packages.\n//\n// Design:\n// - Log.get(scope) returns a bag of optional loggers ({ debugLog, infoLog,\n// warnLog, errorLog }). Each is null when its level is below the scope's\n// minimum level, so the typical call site looks like:\n//\n// debugLog?.log('something happened', value);\n//\n// The optional chaining short-circuits before evaluating the arguments —\n// so the cost of disabled logs is just one nullish check.\n//\n// - Scopes are plain strings. Each package defines its own typed scope union\n// and uses createLogProvider<TScope>(prefix) to get a typed helper that keeps\n// scope names short at call sites while ensuring globally unique keys\n// ('rpc.RpcPeer', 'fusion.Computed', etc.).\n//\n// - Minimum levels live in Log.minLevels (a Map<string, LogLevel>). An\n// entry 'default' acts as a fallback before Log.defaultMinLevel.\n//\n// - initLogging() is invoked lazily on the first Log.get() call. It restores\n// persisted levels and installs globalThis.logLevels so devs can tweak\n// levels at runtime.\n\nimport { initLogging } from './logging-init.js';\n\nexport enum LogLevel {\n Debug = 1,\n Info,\n Warn,\n Error,\n None = 1000,\n}\n\nexport interface LogRef {\n target: unknown;\n id: number;\n}\n\ninterface LogRefSetItem {\n ref: LogRef;\n touchedAt: number;\n}\n\ninterface LogRefData {\n __logRefId?: number;\n}\n\nclass LogRefSet {\n private items: LogRefSetItem[] = [];\n private idSeed = 0;\n\n constructor(private capacity: number)\n { }\n\n public ref(data: object): LogRef {\n const itemIndex = this.items.findIndex(el => el.ref.target === data);\n if (itemIndex >= 0) {\n const existing = this.items[itemIndex];\n existing.touchedAt = Date.now();\n return existing.ref;\n }\n const id = (data as LogRefData).__logRefId ?? this.idSeed++;\n const newRef: LogRef = { target: data, id };\n (data as LogRefData).__logRefId = id;\n if (this.items.length >= this.capacity)\n this.removeOldest();\n this.items.push({ ref: newRef, touchedAt: Date.now() });\n return newRef;\n }\n\n private removeOldest(): void {\n let indexToEvict = 0;\n let itemToEvict = this.items[0];\n for (let i = 1; i < this.items.length; i++) {\n const item = this.items[i];\n if (item.touchedAt < itemToEvict.touchedAt) {\n itemToEvict = item;\n indexToEvict = i;\n }\n }\n this.items.splice(indexToEvict, 1);\n // Replace the live target with its string form so we don't keep the\n // object alive purely for log identity reasons.\n const ref = itemToEvict.ref;\n ref.target = ref.target?.toString();\n }\n}\n\nexport class Log {\n private static isInitialized = false;\n private static logRefs = new LogRefSet(10);\n /** User-set overrides (persisted by logging-init). Empty by default. */\n public static readonly minLevels = new Map<string, LogLevel>();\n /** Per-scope defaults registered by packages via createLogProvider(). */\n public static readonly scopeDefaults = new Map<string, LogLevel>();\n /** Every scope ever requested via Log.get(). Used by logLevels.dump()\n * so devs can discover what's available to override at runtime. */\n public static readonly knownScopes = new Set<string>();\n /** Global baseline for any scope without a default or override. */\n public static defaultMinLevel = LogLevel.Warn;\n public static loggerFactory: (scope: string, level: LogLevel) => Log = (scope, level) => new Log(scope, level);\n\n public log: (...data: unknown[]) => void;\n public trace: (...data: unknown[]) => void;\n\n constructor(\n public readonly scope: string,\n public readonly level: LogLevel,\n ) {\n const prefix = `[${scope}]`;\n switch (level) {\n case LogLevel.Debug:\n this.log = (...data: unknown[]) => console.debug(prefix, ...data);\n break;\n case LogLevel.Info:\n this.log = (...data: unknown[]) => console.log(prefix, ...data);\n break;\n case LogLevel.Warn:\n this.log = (...data: unknown[]) => console.warn(prefix, ...data);\n break;\n case LogLevel.Error:\n this.log = (...data: unknown[]) => console.error(prefix, ...data);\n break;\n case LogLevel.None:\n throw new Error('LogLevel.None cannot be used here');\n }\n this.trace = (...data: unknown[]) => console.trace(prefix, ...data);\n }\n\n public static get(scope: string): LogScopeFns {\n if (!this.isInitialized) {\n this.isInitialized = true;\n initLogging();\n }\n this.knownScopes.add(scope);\n\n const minLevels = this.minLevels;\n // Resolution order:\n // 1. User override for this scope (persisted by logging-init)\n // 2. User-set global override (minLevels.get('default'))\n // 3. Package default for this scope (registered via createLogProvider)\n // 4. Framework baseline (Log.defaultMinLevel, Warn)\n const minLevel = minLevels.get(scope)\n ?? minLevels.get('default')\n ?? this.scopeDefaults.get(scope)\n ?? this.defaultMinLevel;\n\n const getLogger = (level: LogLevel): Log | null =>\n level >= minLevel ? this.loggerFactory(scope, level) : null;\n\n return {\n logScope: scope,\n debugLog: getLogger(LogLevel.Debug),\n infoLog: getLogger(LogLevel.Info),\n warnLog: getLogger(LogLevel.Warn),\n errorLog: getLogger(LogLevel.Error),\n };\n }\n\n public static ref(data: object | null | undefined): object | null | undefined {\n if (!data)\n return data;\n return this.logRefs.ref(data);\n }\n\n public assert(predicate?: boolean, ...data: unknown[]): void {\n if (!predicate)\n this.log(...data);\n }\n}\n\nexport interface LogScopeFns {\n logScope: string;\n debugLog: Log | null;\n infoLog: Log | null;\n warnLog: Log | null;\n errorLog: Log | null;\n}\n\n// Per-package factory: creates a typed getLogs(scope) that prepends the package\n// prefix to the scope name before delegating to Log.get. Keeps call sites\n// concise while ensuring globally unique scope keys.\n//\n// `defaults` is required (not Partial) so that every scope in TScope has an\n// explicit default level — TypeScript will refuse to compile if a scope is\n// missing. Defaults register into Log.scopeDefaults and act as the fallback\n// when no user override is set.\n//\n// All declared scopes are also pre-registered in Log.knownScopes so that\n// logLevels.dump() (in dev console) can list them even before they're first\n// touched at runtime.\nexport function createLogProvider<TScope extends string>(\n prefix: string,\n defaults: Record<TScope, LogLevel>,\n): (scope: TScope) => LogScopeFns {\n for (const [scope, level] of Object.entries(defaults) as [TScope, LogLevel][]) {\n const fullName = prefix + scope;\n Log.scopeDefaults.set(fullName, level);\n Log.knownScopes.add(fullName);\n }\n return scope => Log.get(prefix + scope);\n}\n","/** Common interface for types that carry a value-or-error outcome. */\r\nexport interface IResult<T> {\r\n readonly hasValue: boolean;\r\n readonly hasError: boolean;\r\n readonly value: T;\r\n readonly error: unknown;\r\n readonly valueOrUndefined: T | undefined;\r\n}\r\n\r\n/** Immutable value-or-error container — similar to .NET's Result<T>. */\r\nexport class Result<T> implements IResult<T> {\r\n readonly hasValue: boolean;\r\n readonly hasError: boolean;\r\n private readonly _value: T | undefined;\r\n private readonly _error: unknown;\r\n\r\n public constructor(value: T | undefined, error?: unknown, hasError = error !== undefined) {\r\n this.hasError = hasError;\r\n this.hasValue = !hasError;\r\n this._value = value;\r\n this._error = error;\r\n }\r\n\r\n get value(): T {\r\n if (this.hasError) throw this._error;\r\n return this._value as T;\r\n }\r\n\r\n get error(): unknown {\r\n return this._error;\r\n }\r\n\r\n get valueOrUndefined(): T | undefined {\r\n return this.hasValue ? this._value : undefined;\r\n }\r\n\r\n // Values compared with valueComparer (Object.is by default); errors by reference — mirrors C# Result<T>.Equals.\r\n equals(other: Result<T>, valueComparer: (a: T, b: T) => boolean = Object.is): boolean {\r\n if (this.hasError !== other.hasError || this._error !== other._error)\r\n return false;\r\n\r\n return valueComparer(this._value as T, other._value as T);\r\n }\r\n\r\n static ok<T>(value: T): Result<T> {\r\n return new Result<T>(value, undefined, false);\r\n }\r\n\r\n static error<T>(error: unknown): Result<T> {\r\n return new Result<T>(undefined, error ?? new Error('Unspecified error'), true);\r\n }\r\n}\r\n\r\nexport function result<T>(value: T, error?: unknown): Result<T> {\r\n return new Result<T>(value, error);\r\n}\r\n\r\nexport function errorResult<T>(error: unknown): Result<T> {\r\n return Result.error(error);\r\n}\r\n\r\nexport function resultFrom<T>(fn: () => T): Result<T> {\r\n try {\r\n return result(fn());\r\n } catch (e) {\r\n return errorResult(e);\r\n }\r\n}\r\n\r\nexport async function resultFromAsync<T>(\r\n fn: () => Promise<T>\r\n): Promise<Result<T>> {\r\n try {\r\n return result(await fn());\r\n } catch (e) {\r\n return errorResult(e);\r\n }\r\n}\r\n","import type { Disposable } from './disposable.js';\r\n\r\n/** Typed key for values stored in AsyncContext — each subsystem defines its own keys. */\r\nexport class AsyncContextKey<T> {\r\n readonly id: symbol;\r\n readonly defaultValue: T;\r\n\r\n constructor(name: string, defaultValue: T) {\r\n this.id = Symbol(name);\r\n this.defaultValue = defaultValue;\r\n }\r\n}\r\n\r\n/** General-purpose typed context container — named for forward-compatibility with TC39 AsyncContext proposal. */\r\nexport const abortSignalKey = new AsyncContextKey<AbortSignal | undefined>(\r\n 'AbortSignal',\r\n undefined\r\n);\r\n\r\ninterface AsyncLocalStorageLike {\r\n getStore(): AsyncContext | undefined;\r\n run<R>(store: AsyncContext, fn: () => R): R;\r\n enterWith(store: AsyncContext | undefined): void;\r\n}\r\n\r\n// Node's AsyncLocalStorage, if available. When active it backs AsyncContext.current, so the\r\n// current context flows across awaits exactly like C#'s AsyncLocal ComputeContext — dependencies\r\n// used after the first await are still captured. In browsers (no node:async_hooks) it stays\r\n// undefined and AsyncContext falls back to the synchronous-prefix-only static field; there,\r\n// dependencies used after the first await are captured only through the ctx argument threaded\r\n// into a compute body (see ComputeFunction.invoke's trailing AsyncContext argument).\r\nconst _alsImpl: AsyncLocalStorageLike | undefined = detectAsyncLocalStorage();\r\nlet _als: AsyncLocalStorageLike | undefined = _alsImpl;\r\n\r\nfunction detectAsyncLocalStorage(): AsyncLocalStorageLike | undefined {\r\n // process.getBuiltinModule (Node >= 20.16) is the only synchronous, bundler-safe way to\r\n // load node:async_hooks here: a static import breaks browsers, and a top-level-await\r\n // dynamic import breaks the CJS build output.\r\n const proc = (\r\n globalThis as {\r\n process?: { getBuiltinModule?: (id: string) => unknown };\r\n }\r\n ).process;\r\n const asyncHooks = proc?.getBuiltinModule?.('node:async_hooks') as\r\n | { AsyncLocalStorage: new () => AsyncLocalStorageLike }\r\n | undefined;\r\n return asyncHooks === undefined\r\n ? undefined\r\n : new asyncHooks.AsyncLocalStorage();\r\n}\r\n\r\nexport class AsyncContext {\r\n /** Immutable empty singleton — avoids allocating new AsyncContext(). */\r\n static readonly empty: AsyncContext = new AsyncContext();\r\n\r\n private static _current: AsyncContext | undefined = undefined;\r\n private static _defaults = new Map<symbol, unknown>();\r\n\r\n private _values: Map<symbol, unknown>;\r\n\r\n constructor(values?: Map<symbol, unknown>) {\r\n this._values = values ?? new Map<symbol, unknown>();\r\n }\r\n\r\n static get current(): AsyncContext | undefined {\r\n return _als?.getStore() ?? AsyncContext._current;\r\n }\r\n\r\n static set current(value: AsyncContext | undefined) {\r\n if (_als !== undefined)\r\n _als.enterWith(value);\r\n else\r\n AsyncContext._current = value;\r\n }\r\n\r\n /** True when AsyncContext.current flows across awaits (Node AsyncLocalStorage is active). */\r\n static get isAsyncLocalStorageActive(): boolean {\r\n return _als !== undefined;\r\n }\r\n\r\n get<T>(key: AsyncContextKey<T>): T {\r\n if (this._values.has(key.id)) return this._values.get(key.id) as T;\r\n if (AsyncContext._defaults.has(key.id))\r\n return AsyncContext._defaults.get(key.id) as T;\r\n return key.defaultValue;\r\n }\r\n\r\n with<T>(key: AsyncContextKey<T>, value: T): AsyncContext {\r\n const copy = new Map(this._values);\r\n copy.set(key.id, value);\r\n return new AsyncContext(copy);\r\n }\r\n\r\n activate(): Disposable {\r\n const prev = AsyncContext.current;\r\n const als = _als;\r\n if (als !== undefined) {\r\n // enterWith persists for the rest of this async branch, so a leaked (undisposed)\r\n // activate() can only affect its own branch — the compute pipeline always uses run(),\r\n // which is properly scoped, so dependency capture is never attributed to a leaked ctx.\r\n als.enterWith(this);\r\n return { dispose: () => als.enterWith(prev) };\r\n }\r\n AsyncContext._current = this;\r\n return {\r\n dispose: () => {\r\n AsyncContext._current = prev;\r\n },\r\n };\r\n }\r\n\r\n run<R>(fn: () => R): R {\r\n if (_als !== undefined)\r\n return _als.run(this, fn);\r\n const prev = AsyncContext._current;\r\n AsyncContext._current = this;\r\n try {\r\n return fn();\r\n } finally {\r\n AsyncContext._current = prev;\r\n }\r\n }\r\n\r\n /** Strip THIS exact instance from args if it's the last element (reference equality). */\r\n stripFromArgs(args: unknown[]): unknown[] {\r\n return args[args.length - 1] === this ? args.slice(0, -1) : args;\r\n }\r\n\r\n /** Resolve: return ctx if provided, otherwise AsyncContext.current. */\r\n static from(ctx: AsyncContext | undefined): AsyncContext | undefined {\r\n return ctx ?? AsyncContext.current;\r\n }\r\n\r\n /** Extract AsyncContext from last arg if instanceof AsyncContext, else fall back to .current. */\r\n static fromArgs(args: unknown[]): AsyncContext | undefined {\r\n const last = args[args.length - 1];\r\n return last instanceof AsyncContext ? last : AsyncContext.current;\r\n }\r\n\r\n static setDefault<T>(key: AsyncContextKey<T>, value: T): void {\r\n AsyncContext._defaults.set(key.id, value);\r\n }\r\n\r\n static getOrCreate(): AsyncContext {\r\n return AsyncContext.current ?? AsyncContext.empty;\r\n }\r\n\r\n // Toggles AsyncLocalStorage backing — for tests that exercise the browser fallback path.\r\n // Clears the fallback static field so no stale context bleeds across the toggle.\r\n static _setAsyncLocalStorageActive(active: boolean): void {\r\n _als = active ? _alsImpl : undefined;\r\n AsyncContext._current = undefined;\r\n }\r\n}\r\n","/** Promise-based mutual exclusion lock for serializing async operations. */\r\nexport class AsyncLock {\r\n private _queue: (() => void)[] = [];\r\n private _locked = false;\r\n\r\n get isLocked(): boolean {\r\n return this._locked;\r\n }\r\n\r\n async acquire(signal?: AbortSignal): Promise<void> {\r\n if (signal?.aborted)\r\n throw signal.reason;\r\n\r\n if (!this._locked) {\r\n this._locked = true;\r\n return;\r\n }\r\n return new Promise<void>((resolve, reject) => {\r\n const onAbort = () => {\r\n const i = this._queue.indexOf(waiter);\r\n if (i >= 0)\r\n this._queue.splice(i, 1);\r\n\r\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors -- the rejection value IS signal.reason.\r\n reject(signal!.reason);\r\n };\r\n const waiter = () => {\r\n signal?.removeEventListener('abort', onAbort);\r\n resolve();\r\n };\r\n this._queue.push(waiter);\r\n signal?.addEventListener('abort', onAbort, { once: true });\r\n });\r\n }\r\n\r\n release(): void {\r\n if (!this._locked) throw new Error('AsyncLock is not locked.');\r\n\r\n const next = this._queue.shift();\r\n if (next !== undefined) {\r\n // Transfer lock to the next waiter\r\n next();\r\n } else {\r\n this._locked = false;\r\n }\r\n }\r\n\r\n async run<T>(fn: () => T | Promise<T>, signal?: AbortSignal): Promise<T> {\r\n await this.acquire(signal);\r\n try {\r\n return await fn();\r\n } finally {\r\n this.release();\r\n }\r\n }\r\n}\r\n","/** Externally-resolvable promise — similar to .NET's TaskCompletionSource<T>. */\r\nexport class PromiseSource<T> implements Promise<T> {\r\n readonly promise: Promise<T>;\r\n readonly [Symbol.toStringTag] = 'Promise';\r\n private _resolve!: (value: T | PromiseLike<T>) => void;\r\n private _reject!: (reason?: unknown) => void;\r\n private _isCompleted = false;\r\n\r\n constructor() {\r\n this.promise = new Promise<T>((resolve, reject) => {\r\n this._resolve = resolve;\r\n this._reject = reject;\r\n });\r\n // Keep an unobserved rejection benign, like .NET's faulted Task: RPC code\r\n // rejects tracked calls nobody may be awaiting (peer disconnect/error).\r\n this.promise.catch(() => { /* swallow for unobserved consumers */ });\r\n }\r\n\r\n get isCompleted(): boolean {\r\n return this._isCompleted;\r\n }\r\n\r\n resolve(value: T): boolean {\r\n if (this._isCompleted) return false;\r\n this._isCompleted = true;\r\n this._resolve(value);\r\n return true;\r\n }\r\n\r\n reject(reason?: unknown): boolean {\r\n if (this._isCompleted) return false;\r\n this._isCompleted = true;\r\n this._reject(reason);\r\n return true;\r\n }\r\n\r\n then<TResult1 = T, TResult2 = never>(\r\n onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null,\r\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,\r\n ): Promise<TResult1 | TResult2> {\r\n return this.promise.then(onfulfilled, onrejected);\r\n }\r\n\r\n catch<TResult = never>(\r\n onrejected?: ((reason: unknown) => TResult | PromiseLike<TResult>) | null,\r\n ): Promise<T | TResult> {\r\n return this.promise.catch(onrejected);\r\n }\r\n\r\n finally(onfinally?: (() => void) | null): Promise<T> {\r\n return this.promise.finally(onfinally);\r\n }\r\n}\r\n\r\nexport const resolvedVoidPromise: Promise<void> = Promise.resolve();\r\n","import { PromiseSource } from './promise-source.js';\r\n\r\n/**\r\n * Typed pub/sub event handler set — similar to .NET's EventHandler<T> multicast delegate.\r\n * Deviation: Set-backed, so adding the same handler twice fires it once (a C# delegate fires it twice).\r\n */\r\nexport class EventHandlerSet<T> {\r\n private _handlers = new Set<(arg: T) => void>();\r\n\r\n get count(): number {\r\n return this._handlers.size;\r\n }\r\n\r\n add(handler: (arg: T) => void): void {\r\n this._handlers.add(handler);\r\n }\r\n\r\n remove(handler: (arg: T) => void): void {\r\n this._handlers.delete(handler);\r\n }\r\n\r\n trigger(arg: T): void {\r\n // Snapshot so handlers added during dispatch aren't invoked by it (multicast-delegate parity).\r\n for (const handler of [...this._handlers])\r\n handler(arg);\r\n }\r\n\r\n // Fires every handler once, isolating each so one that throws can't stop the rest.\r\n triggerSafe(arg: T, onError: (error: unknown) => void): void {\r\n for (const handler of [...this._handlers]) {\r\n try {\r\n handler(arg);\r\n } catch (error) {\r\n onError(error);\r\n }\r\n }\r\n }\r\n\r\n clear(): void {\r\n this._handlers.clear();\r\n }\r\n\r\n whenNext(): Promise<T> {\r\n const ps = new PromiseSource<T>();\r\n const handler = (arg: T) => {\r\n this._handlers.delete(handler);\r\n ps.resolve(arg);\r\n };\r\n this._handlers.add(handler);\r\n return ps;\r\n }\r\n}\r\n","import { PromiseSource } from './promise-source.js';\n\n// Auto-reset, edge-triggered async wakeup. One notify() releases every waiter\n// parked at that moment, then arms a fresh promise for subsequent waits — a\n// notify with no waiter is NOT latched (pure edge trigger).\n//\n// Lost-wakeup-safe usage: take the wait promise BEFORE checking the condition,\n// so a notify() that lands between the check and the await still wins:\n//\n// const w = signal.wait();\n// if (conditionAlreadyMet)\n// consume(); // notify before wait() already set the condition\n// else\n// await Promise.race([w, abortWait]); // notify after wait() resolves w\nexport class AsyncSignal {\n private source = new PromiseSource<void>();\n\n wait(): Promise<void> {\n return this.source.promise;\n }\n\n notify(): void {\n const source = this.source;\n this.source = new PromiseSource<void>();\n source.resolve();\n }\n}\n","/** Error type rejected by {@link withTimeout} when its budget elapses. */\nexport class TimeoutError extends Error {\n override readonly name = 'TimeoutError';\n\n constructor(message = 'Operation timed out') {\n super(message);\n }\n}\n\n/**\n * Race `promise` against a `ms`-millisecond timer. Resolves with the inner\n * promise's value if it settles first; otherwise rejects with a\n * {@link TimeoutError} carrying `message`. The timer is always cleared in\n * a `finally`, so it cannot keep the event loop alive after the race ends.\n *\n * The inner promise's rejection (and the timeout's) are routed through\n * `Promise.race`, so callers should `await` the result inside a `try/catch`\n * exactly as they would for a single awaited promise. There's no\n * \"unhandled rejection\" hazard from the timeout branch — the race always\n * observes whichever promise wins, and the loser is allowed to settle\n * silently into the void.\n */\nexport async function withTimeout<T>(\n promise: PromiseLike<T>,\n ms: number,\n message?: string\n): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeoutPromise = new Promise<never>((_, reject) => {\n timer = setTimeout(\n () => reject(new TimeoutError(message ?? `Operation timed out after ${ms}ms`)),\n ms\n );\n });\n // Routed via `Promise.race` below; suppress the standalone unhandled-\n // rejection warning that fires when `promise` wins instead.\n timeoutPromise.catch(() => { /* noop */ });\n try {\n return await Promise.race([promise, timeoutPromise]);\n } finally {\n if (timer !== undefined) clearTimeout(timer);\n }\n}\n","import { PromiseSource } from './promise-source.js';\nimport { TimeoutError } from './withTimeout.js';\n\n/**\n * A {@link PromiseSource} with a built-in timer that can reject (or run a\n * caller-supplied callback) after a configurable delay. The timer is\n * automatically cleared when the promise settles by other means, so callers\n * don't have to remember to `clearTimeout()` on every success path.\n *\n * Typical use:\n * ```ts\n * const ps = new PromiseSourceWithTimeout<string>();\n * ps.setTimeout(5_000); // rejects after 5s if still pending\n * ps.setTimeout(5_000, () => ps.resolve('fallback')); // or run a custom callback\n * ```\n *\n * Replaces the `PromiseSourceWithTimeout` previously kept in\n * `ActualChat/src/nodejs/src/promises.ts`. Note: the Voxt original supported a\n * \"precise\" (requestAnimationFrame-based) variant; we drop it here because no\n * caller in ActualChat uses it outside `promises.ts` itself.\n */\nexport class PromiseSourceWithTimeout<T> extends PromiseSource<T> {\n private _timer: ReturnType<typeof setTimeout> | undefined;\n\n hasTimeout(): boolean {\n return this._timer !== undefined;\n }\n\n /**\n * Install (or replace) a timeout. Pass `null` to remove without setting a\n * new one. `callback` is invoked when the timer fires — if omitted, the\n * promise is rejected with a generic \"timed out\" error.\n */\n setTimeout(ms: number | null, callback?: () => unknown): void {\n this.clearTimeout();\n if (ms === null || this.isCompleted) return;\n\n this._timer = setTimeout(() => {\n this._timer = undefined;\n if (callback) callback();\n else this.reject(new TimeoutError(`The promise has timed out after ${ms}ms.`));\n }, ms);\n }\n\n clearTimeout(): void {\n if (this._timer === undefined) return;\n clearTimeout(this._timer);\n this._timer = undefined;\n }\n\n override resolve(value: T): boolean {\n const didSettle = super.resolve(value);\n if (didSettle) this.clearTimeout();\n return didSettle;\n }\n\n override reject(reason?: unknown): boolean {\n const didSettle = super.reject(reason);\n if (didSettle) this.clearTimeout();\n return didSettle;\n }\n}\n","/**\n * Pre-resolved promises for the three values most often returned as a\n * \"no-op\" successful path: `void`, `true`, `false`. Returning these\n * avoids allocating a fresh promise per call site.\n *\n * Idiomatic use:\n * ```ts\n * if (alreadyInitialized) return ResolvedPromise.Void;\n * ```\n */\nexport const ResolvedPromise = {\n Void: Promise.resolve(),\n True: Promise.resolve(true),\n False: Promise.resolve(false),\n} as const;\n","/**\n * Sentinel returned/thrown by code that distinguishes \"the operation took\n * too long\" from a generic rejection. Identity-comparable via the\n * `instance` singleton — callers can branch on `result === TimedOut.instance`.\n */\nexport class TimedOut {\n static readonly instance: TimedOut = new TimedOut();\n}\n","/** Resolves after `ms` milliseconds, or rejects with `signal.reason` if\r\n * `signal` aborts first (including when it is already aborted). */\r\nexport function delayAsync(ms: number, signal?: AbortSignal): Promise<void> {\r\n if (signal?.aborted)\r\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors -- mirrors signal.throwIfAborted(): the rejection value IS signal.reason.\r\n return Promise.reject(signal.reason);\r\n\r\n return new Promise<void>((resolve, reject) => {\r\n const onAbort = () => {\r\n clearTimeout(timer);\r\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors -- see delayAsync's already-aborted branch.\r\n reject(signal!.reason);\r\n };\r\n const timer = setTimeout(() => {\r\n signal?.removeEventListener('abort', onAbort);\r\n resolve();\r\n }, ms);\r\n signal?.addEventListener('abort', onAbort, { once: true });\r\n });\r\n}\r\n\r\n/** Resolves with `value` after `ms` milliseconds. */\r\nexport function delayAsyncWith<T>(ms: number, value: T): Promise<T> {\r\n return new Promise<T>(resolve => {\r\n setTimeout(() => resolve(value), ms);\r\n });\r\n}\r\n","/**\r\n * Adapt an `AbortSignal` to a Promise that **rejects** with the signal's\r\n * `reason` once the signal fires (or immediately, if it's already\r\n * aborted). Mirrors `signal.throwIfAborted()` semantics in Promise form:\r\n * the rejected value is exactly what `throwIfAborted()` would have\r\n * thrown — by default a `DOMException` with `name === 'AbortError'`,\r\n * or whatever was passed to `abortController.abort(reason)`.\r\n *\r\n * Operators racing upstream pulls / timers against cancellation plug\r\n * this into `Promise.race(...)` so abort propagates as a thrown error —\r\n * `try/finally` blocks unwind naturally; no sentinel values to thread.\r\n *\r\n * Promises are cached per signal: every call for the same signal returns\r\n * the SAME promise and registers AT MOST ONE listener. Operators that\r\n * race per-iteration (e.g. encode loops calling this once per chunk)\r\n * won't accumulate listeners or hit Node's `MaxListenersExceeded` warning.\r\n * The cache is a `WeakMap` so signals remain GC-eligible normally.\r\n *\r\n * Callers that prefer a sentinel can attach `.catch()` to convert the\r\n * rejection back into a value: `abortPromise(s).catch(() => 'stopped')`.\r\n */\r\nconst abortPromiseCache = new WeakMap<AbortSignal, Promise<never>>();\r\n\r\nexport function abortPromise(signal: AbortSignal): Promise<never> {\r\n let cached = abortPromiseCache.get(signal);\r\n if (!cached) {\r\n cached = new Promise<never>((_, reject) => {\r\n if (signal.aborted) {\r\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors -- mirroring `signal.throwIfAborted()`: the rejection value IS the signal's reason, which by Web spec is a `DOMException` by default but can be any value the caller passed to `abort(reason)`.\r\n reject(signal.reason);\r\n return;\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors -- see comment above; signal.reason is the canonical thrown value.\r\n signal.addEventListener('abort', () => reject(signal.reason), { once: true });\r\n });\r\n // Mark the cached rejection as observed so unhandled-rejection\r\n // warnings don't fire when a caller never `await`s it (e.g. an\r\n // operator that completed before abort and let the race promise\r\n // GC). The actual await-time rejection still surfaces normally.\r\n cached.catch(() => { /* swallow for cache-only consumers */ });\r\n abortPromiseCache.set(signal, cached);\r\n }\r\n return cached;\r\n}\r\n","/**\r\n * True when `error` is a cancellation/abort signal rather than a real failure.\r\n *\r\n * Recognizes the wave-1 cancellation convention: `delayAsync`, `AsyncLock`, and\r\n * `abortPromise` all reject with `signal.reason`, which — per the Web spec —\r\n * defaults to a `DOMException` named `'AbortError'` (and is whatever value was\r\n * passed to `abort(reason)` otherwise). A plain `Error` named `'AbortError'`\r\n * (e.g. from a fetch abort) is matched too.\r\n */\r\nexport function isCancellation(error: unknown): boolean {\r\n return (\r\n error != null &&\r\n typeof error === 'object' &&\r\n (error as { name?: unknown }).name === 'AbortError'\r\n );\r\n}\r\n\r\n/**\r\n * Builds a cancellation-shaped error recognized by {@link isCancellation}.\r\n * Named `'AbortError'` so it rides the same never-cache path as an aborted\r\n * `fetch`: the compute kernel invalidates such computeds instead of caching\r\n * the error (K6), and RPC callers treat it as a retryable cancellation.\r\n */\r\nexport function cancellationError(message = 'The operation was cancelled.'): Error {\r\n const error = new Error(message);\r\n error.name = 'AbortError';\r\n return error;\r\n}\r\n","import { PromiseSource, resolvedVoidPromise } from './promise-source.js';\r\n\r\nexport type AbortOutcome = 'resolve' | 'reject';\r\n\r\n/**\r\n * Builds a Promise that settles when the first completion source fires, then runs\r\n * every registered cleanup exactly once — on completion or when `abortSignal`\r\n * aborts. `wire` installs the sources (timers, event handlers), calling\r\n * `complete()` to resolve and `addCleanup(fn)` to register teardown; every\r\n * cleanup, plus the abort listener, is removed on every exit path. `onAbort`\r\n * selects whether an abort resolves or rejects (with `signal.reason`).\r\n */\r\nexport function awaitWithCleanup(\r\n abortSignal: AbortSignal | undefined,\r\n onAbort: AbortOutcome,\r\n wire: (complete: () => void, addCleanup: (cleanup: () => void) => void) => void,\r\n): Promise<void> {\r\n if (abortSignal?.aborted)\r\n return onAbort === 'reject'\r\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors -- mirrors signal.throwIfAborted(): the rejection value IS signal.reason.\r\n ? Promise.reject(abortSignal.reason ?? new Error('Operation cancelled.'))\r\n : resolvedVoidPromise;\r\n\r\n const ps = new PromiseSource<void>();\r\n const cleanups: (() => void)[] = [];\r\n let settled = false;\r\n const runCleanups = () => {\r\n for (const cleanup of cleanups)\r\n cleanup();\r\n\r\n cleanups.length = 0;\r\n };\r\n const complete = () => {\r\n if (settled)\r\n return;\r\n\r\n settled = true;\r\n runCleanups();\r\n ps.resolve(undefined);\r\n };\r\n const addCleanup = (cleanup: () => void) => {\r\n if (settled)\r\n cleanup();\r\n else\r\n cleanups.push(cleanup);\r\n };\r\n\r\n if (abortSignal !== undefined) {\r\n const onAbortFired = () => {\r\n if (settled)\r\n return;\r\n\r\n settled = true;\r\n runCleanups();\r\n if (onAbort === 'reject')\r\n ps.reject(abortSignal.reason ?? new Error('Operation cancelled.'));\r\n else\r\n ps.resolve(undefined);\r\n };\r\n abortSignal.addEventListener('abort', onAbortFired, { once: true });\r\n cleanups.push(() => abortSignal.removeEventListener('abort', onAbortFired));\r\n }\r\n\r\n wire(complete, addCleanup);\r\n return ps;\r\n}\r\n","import { LogLevel, createLogProvider } from './logging.js';\n\n/** Log scopes used inside `@actuallab/core` itself. Each is registered at\n * `core.<scope>`. Keep the list tight — most utilities should propagate\n * errors rather than log them. */\nexport type CoreLogScope =\n | 'retry'\n | 'throttle';\n\nconst scopeDefaults: Record<CoreLogScope, LogLevel> = {\n retry: LogLevel.Warn,\n throttle: LogLevel.Warn,\n};\n\nexport const getLogs = createLogProvider<CoreLogScope>('core.', scopeDefaults);\n","import { getLogs } from './internal-logging.js';\n\nconst { errorLog } = getLogs('throttle');\n\n/** A function wrapped by {@link throttle} or {@link debounce}. Calling it\n * triggers the underlying function according to the scheduling rule;\n * `reset()` discards any pending scheduled call. */\nexport interface ResettableFunc<TArgs extends unknown[]> {\n (...args: TArgs): void;\n reset(): void;\n}\n\nclass Call<TArgs extends unknown[]> {\n constructor(\n readonly func: (...args: TArgs) => unknown,\n readonly self: unknown,\n readonly parameters: TArgs\n ) { }\n\n invoke(): unknown {\n return this.func.apply(this.self, this.parameters);\n }\n\n invokeSilently(): unknown {\n try {\n return this.invoke();\n } catch (error) {\n errorLog?.log('Call.invokeSilently: unhandled error:', error);\n }\n }\n}\n\n/** Throttle modes:\n * - `default` — fire the head call immediately, then drop further calls\n * until the interval elapses; the *last* one is fired at interval end.\n * - `skip` — fire the head call immediately, drop ALL calls during the\n * interval (no tail call).\n * - `delayHead` — delay even the head call by one interval; subsequent\n * calls overwrite the pending one. */\nexport type ThrottleMode = 'default' | 'skip' | 'delayHead';\n\n/**\n * Throttle calls to `func` so that it fires at most once every `intervalMs`.\n * The returned function has a `.reset()` that discards any pending tail call\n * and re-arms the head-call behavior on the next invocation.\n */\nexport function throttle<TArgs extends unknown[]>(\n func: (...args: TArgs) => unknown,\n intervalMs: number,\n mode: ThrottleMode = 'default'\n): ResettableFunc<TArgs> {\n let lastCall: Call<TArgs> | null = null;\n let nextFireTime = 0;\n let timeoutHandle: ReturnType<typeof setTimeout> | null = null;\n\n const reset = (): void => {\n if (timeoutHandle !== null) clearTimeout(timeoutHandle);\n timeoutHandle = null;\n lastCall = null;\n nextFireTime = 0;\n };\n\n const fire = (): void => {\n if (timeoutHandle !== null) clearTimeout(timeoutHandle);\n\n if (lastCall !== null) {\n const call = lastCall;\n lastCall = null;\n nextFireTime = Date.now() + intervalMs;\n timeoutHandle = setTimeout(fire, intervalMs);\n call.invokeSilently(); // Must be last\n } else {\n timeoutHandle = null;\n nextFireTime = 0;\n }\n };\n\n const wrapped: ResettableFunc<TArgs> = function (this: unknown, ...args: TArgs): void {\n const call = new Call<TArgs>(func, this, args);\n const fireDelay = nextFireTime - Date.now();\n if (timeoutHandle !== null && fireDelay <= 0) {\n // Delayed \"fire\" is ready but not yet executed — flush it now.\n fire();\n }\n\n if (timeoutHandle === null) {\n // lastCall is null here\n nextFireTime = Date.now() + intervalMs;\n timeoutHandle = setTimeout(fire, intervalMs);\n if (mode === 'delayHead') {\n lastCall = call;\n } else {\n call.invokeSilently();\n }\n } else if (mode !== 'skip') {\n lastCall = call;\n }\n };\n wrapped.reset = reset;\n return wrapped;\n}\n\n/**\n * Debounce calls to `func`: the function fires only after `intervalMs` have\n * elapsed since the LAST call. Each new call resets the timer. `.reset()`\n * discards any pending fire without invoking `func`.\n */\nexport function debounce<TArgs extends unknown[]>(\n func: (...args: TArgs) => unknown,\n intervalMs: number\n): ResettableFunc<TArgs> {\n let lastCall: Call<TArgs> | null = null;\n let nextFireTime = 0;\n let timeoutHandle: ReturnType<typeof setTimeout> | null = null;\n\n const reset = (): void => {\n // Don't clearTimeout here: the live timer will see `lastCall === null`\n // and exit quietly. Avoids a churn of cleared-then-set timers when\n // callers `reset()` then immediately call again.\n timeoutHandle = null;\n lastCall = null;\n nextFireTime = 0;\n };\n\n const fire = (): void => {\n if (timeoutHandle !== null) clearTimeout(timeoutHandle);\n timeoutHandle = null;\n\n const fireDelay = nextFireTime - Date.now();\n if (fireDelay <= 0) {\n nextFireTime = 0;\n if (lastCall !== null) {\n const call = lastCall;\n lastCall = null;\n call.invokeSilently(); // Must be last\n }\n } else {\n // Another call landed; reschedule for the new deadline.\n timeoutHandle = setTimeout(fire, fireDelay);\n }\n };\n\n const wrapped: ResettableFunc<TArgs> = function (this: unknown, ...args: TArgs): void {\n lastCall = new Call<TArgs>(func, this, args);\n nextFireTime = Date.now() + intervalMs;\n timeoutHandle ??= setTimeout(fire, intervalMs);\n };\n wrapped.reset = reset;\n return wrapped;\n}\n","/**\n * Wrap an async function so concurrent invocations are serialized into a\n * single chain — each call awaits the previous one before running, and the\n * caller receives the result of *its* own invocation.\n *\n * Useful for stateful async operations (DB writes, file I/O, network I/O\n * that must not overlap) where the underlying contract is \"one at a time.\"\n *\n * If `limit` is set and the queue is already that deep, the call short-\n * circuits and returns the same promise the most recent queued call returned\n * — i.e. it coalesces excess pressure onto the trailing in-flight call.\n * Pass `null` (the default) for unbounded queueing.\n */\nexport function serialize<TArgs extends unknown[], TResult>(\n func: (...args: TArgs) => PromiseLike<TResult> | TResult,\n limit: number | null = null\n): (...args: TArgs) => Promise<TResult> {\n let lastCall: Promise<TResult> = Promise.resolve(null as TResult);\n let queueSize = 0;\n\n return function (this: unknown, ...args: TArgs): Promise<TResult> {\n if (limit !== null && queueSize >= limit) return lastCall;\n\n queueSize++;\n const prevCall = lastCall;\n // Capture `this` via the bound caller chain so we don't have to alias\n // `this` to a local (which the linter flags). `Reflect.apply` preserves\n // the function's typed return value (unlike `Function.prototype.apply`,\n // which is declared as returning `any`).\n const invoke = (): PromiseLike<TResult> | TResult => Reflect.apply(func, this, args);\n return lastCall = (async () => {\n try {\n // Wait for the previous call to settle — but don't inherit its\n // rejection. The previous caller already owns that error; if we\n // re-threw here, a single failure would poison the queue\n // forever (every subsequent call awaits the previous one).\n await prevCall.catch(() => { /* see comment above */ });\n return await invoke();\n } finally {\n queueSize--;\n }\n })();\n };\n}\n","/**\n * A fixed-capacity circular buffer supporting efficient push/pull at both\n * head and tail.\n *\n * Direct port of .NET `ActualLab.Collections.RingBuffer<T>` at\n * src/ActualLab.Core/Collections/RingBuffer.cs (simplified — TS uses plain\n * modulo instead of the power-of-two-minus-one bit-mask trick, since the\n * performance difference is negligible in JavaScript).\n */\nexport class RingBuffer<T> {\n private _buffer: (T | undefined)[];\n private _start = 0;\n private _end = 0;\n private _count = 0;\n\n readonly capacity: number;\n\n get count(): number { return this._count; }\n get isEmpty(): boolean { return this._count === 0; }\n get isFull(): boolean { return this._count === this.capacity; }\n get remainingCapacity(): number { return this.capacity - this._count; }\n get hasRemainingCapacity(): boolean { return this._count < this.capacity; }\n\n constructor(capacity: number) {\n if (capacity < 1)\n throw new RangeError(`RingBuffer capacity must be >= 1 (was ${capacity}).`);\n this.capacity = capacity;\n this._buffer = new Array<T | undefined>(capacity);\n }\n\n /** Read the item at `index` (0-indexed, from head). */\n get(index: number): T {\n if (index < 0 || index >= this._count)\n throw new RangeError(`Index ${index} out of range [0, ${this._count}).`);\n return this._buffer[(this._start + index) % this.capacity] as T;\n }\n\n /** Add an item at the tail. Throws if the buffer is full. */\n pushTail(item: T): void {\n if (this._count >= this.capacity)\n throw new Error('RingBuffer is full.');\n this._buffer[this._end] = item;\n this._end = (this._end + 1) % this.capacity;\n this._count++;\n }\n\n /** Add an item at the tail, evicting the head item if the buffer is full. */\n pushTailAndMoveHeadIfFull(item: T): void {\n if (this._count >= this.capacity) {\n this._buffer[this._start] = undefined;\n this._start = (this._start + 1) % this.capacity;\n this._count--;\n }\n this.pushTail(item);\n }\n\n /** Remove the head item. Throws if the buffer is empty. */\n pullHead(): T {\n if (this._count === 0)\n throw new Error('RingBuffer is empty.');\n const head = this._buffer[this._start] as T;\n this._buffer[this._start] = undefined;\n this._start = (this._start + 1) % this.capacity;\n this._count--;\n return head;\n }\n\n /**\n * Advance the head by `skipCount` slots, releasing references to skipped\n * items so they can be garbage-collected.\n */\n moveHead(skipCount: number): void {\n if (skipCount === 0) return;\n if (skipCount < 0 || skipCount > this._count)\n throw new RangeError(`skipCount ${skipCount} out of range [0, ${this._count}].`);\n for (let k = 0; k < skipCount; k++) {\n this._buffer[(this._start + k) % this.capacity] = undefined;\n }\n this._start = (this._start + skipCount) % this.capacity;\n this._count -= skipCount;\n }\n\n /** Remove all items. */\n clear(): void {\n for (let i = 0; i < this.capacity; i++) this._buffer[i] = undefined;\n this._start = 0;\n this._end = 0;\n this._count = 0;\n }\n\n /** Copy the buffer's contents to a new array, head-first. */\n toArray(): T[] {\n const out = new Array<T>(this._count);\n for (let i = 0; i < this._count; i++) {\n out[i] = this._buffer[(this._start + i) % this.capacity] as T;\n }\n return out;\n }\n}\n","// .NET counterpart: ActualLab.Time.RetryDelaySeq\r\n\r\nconst DefaultSpread = 0.1;\r\nconst DefaultMultiplier = 1.41421356237; // Math.sqrt(2)\r\n\r\nfunction applySpread(origin: number, spread: number): number {\r\n if (spread <= 0) return origin;\r\n const delta = origin * spread;\r\n return origin + (Math.random() * 2 - 1) * delta;\r\n}\r\n\r\nexport class RetryDelaySeq {\r\n readonly min: number;\r\n readonly max: number;\r\n readonly spread: number;\r\n readonly multiplier: number;\r\n\r\n constructor(\r\n min: number,\r\n max: number,\r\n spread: number = DefaultSpread,\r\n multiplier: number = DefaultMultiplier\r\n ) {\r\n this.min = min;\r\n this.max = max;\r\n this.spread = spread;\r\n this.multiplier = multiplier;\r\n }\r\n\r\n static fixed(\r\n delayMs: number,\r\n spread: number = DefaultSpread\r\n ): RetryDelaySeq {\r\n return new RetryDelaySeq(delayMs, delayMs, spread, 1);\r\n }\r\n\r\n static exp(\r\n minMs: number,\r\n maxMs: number,\r\n spread: number = DefaultSpread,\r\n multiplier: number = DefaultMultiplier\r\n ): RetryDelaySeq {\r\n return new RetryDelaySeq(minMs, maxMs, spread, multiplier);\r\n }\r\n\r\n getDelay(failureCount: number): number {\r\n if (this.min < 0)\r\n throw new Error('RetryDelaySeq.min must be non-negative.');\r\n if (failureCount <= 0) return 0;\r\n\r\n if (this.multiplier <= 1) {\r\n // Fixed — no exponential component\r\n return Math.max(\r\n 0,\r\n this.spread <= 0 ? this.min : applySpread(this.min, this.spread)\r\n );\r\n }\r\n\r\n const multiplier = Math.pow(this.multiplier, failureCount - 1);\r\n const raw = Math.min(this.max, this.min * multiplier);\r\n return Math.max(0, applySpread(raw, this.spread));\r\n }\r\n}\r\n","// .NET counterparts: ActualLab.Net.RetryDelayer, ActualLab.Net.RetryDelay\r\n\r\nimport { delayAsync } from './delay.js';\r\nimport { EventHandlerSet } from './events.js';\r\nimport { RetryDelaySeq } from './retry-delay-seq.js';\r\n\r\nexport interface RetryDelay {\r\n readonly promise: Promise<void>;\r\n readonly endsAt: number; // Date.now()-based timestamp, 0 = no delay\r\n readonly isLimitExceeded: boolean;\r\n}\r\n\r\nexport const RetryDelayNone: RetryDelay = {\r\n promise: Promise.resolve(),\r\n endsAt: 0,\r\n isLimitExceeded: false,\r\n};\r\n\r\nexport const RetryDelayLimitExceeded: RetryDelay = {\r\n promise: Promise.resolve(),\r\n endsAt: 0,\r\n isLimitExceeded: true,\r\n};\r\n\r\nexport class RetryDelayer {\r\n private _cancelController = new AbortController();\r\n\r\n delays: RetryDelaySeq = RetryDelaySeq.fixed(1000);\r\n limit: number | undefined = undefined;\r\n\r\n readonly cancelDelaysChanged = new EventHandlerSet<void>();\r\n\r\n getDelay(tryIndex: number, cancellationSignal?: AbortSignal): RetryDelay {\r\n if (this.limit !== undefined && tryIndex >= this.limit)\r\n return RetryDelayLimitExceeded;\r\n\r\n const delayMs = this.delays.getDelay(tryIndex);\r\n if (tryIndex === 0 || delayMs <= 0) return RetryDelayNone;\r\n\r\n const actualDelayMs = Math.max(1, delayMs);\r\n const endsAt = Date.now() + actualDelayMs;\r\n\r\n const cancelSignal = this._cancelController.signal;\r\n const combinedSignal = cancellationSignal\r\n ? AbortSignal.any([cancellationSignal, cancelSignal])\r\n : cancelSignal;\r\n const promise = delayAsync(actualDelayMs, combinedSignal).catch((e: unknown) => {\r\n // cancelDelays() completes normally (even on a tie with external\r\n // cancellation, matching the C# catch filter); external cancellation\r\n // rejects with cancellationSignal.reason (via AbortSignal.any).\r\n if (!cancelSignal.aborted)\r\n throw e;\r\n });\r\n\r\n return { promise, endsAt, isLimitExceeded: false };\r\n }\r\n\r\n cancelDelays(): void {\r\n const old = this._cancelController;\r\n this._cancelController = new AbortController();\r\n old.abort();\r\n this.cancelDelaysChanged.trigger();\r\n }\r\n}\r\n","import { delayAsync } from './delay.js';\r\nimport { getLogs } from './internal-logging.js';\r\n\r\nconst { warnLog } = getLogs('retry');\r\n\r\n/** A sequence of retry delays — given a 1-based try index (1 = first\r\n * retry, i.e. AFTER the initial failure), returns the delay in ms before\r\n * the next attempt. For more elaborate delay schemes, see\r\n * {@link RetryDelaySeq.getDelay}. */\r\nexport type RetryDelaySchedule = (tryIndex: number) => number;\r\n\r\nconst defaultRetryDelays: RetryDelaySchedule = () => 50;\r\n\r\n/**\r\n * Run `fn` up to `tryCount` times, awaiting a delay between attempts.\r\n * The last error is rethrown if every attempt fails.\r\n *\r\n * `fn` is passed the 0-based attempt index and the last error (or\r\n * `undefined` for the first attempt) — useful for adapting behavior per\r\n * try (e.g. switching endpoints, escalating timeouts).\r\n *\r\n * Aborting `signal` during an inter-attempt delay rejects with\r\n * `signal.reason` instead of waiting the delay out.\r\n */\r\nexport async function retry<TResult>(\r\n tryCount: number,\r\n fn: (tryIndex: number, lastError: unknown) => PromiseLike<TResult> | TResult,\r\n retryDelays: RetryDelaySchedule = defaultRetryDelays,\r\n signal?: AbortSignal,\r\n): Promise<TResult> {\r\n if (tryCount <= 0)\r\n throw new Error('retry: tryCount must be positive.');\r\n\r\n let lastError: unknown;\r\n for (let tryIndex = 0; ; ) {\r\n if (tryIndex >= tryCount) throw lastError;\r\n try {\r\n return await fn(tryIndex, lastError);\r\n } catch (e) {\r\n lastError = e;\r\n }\r\n ++tryIndex;\r\n if (tryIndex >= tryCount) throw lastError;\r\n warnLog?.log(`retry(${tryIndex}/${tryCount}): error:`, lastError);\r\n await delayAsync(retryDelays(tryIndex), signal);\r\n }\r\n}\r\n\r\n/**\r\n * Run `fn` and swallow any throw, returning `onError(e)` if provided or\r\n * `undefined` otherwise. The returned promise always settles successfully\r\n * — the caller never has to `try/catch` it.\r\n *\r\n * Useful where a logical \"best-effort\" return is wanted but the runtime\r\n * defaults — unhandled rejection warnings, exception escape past finally\r\n * blocks — are not.\r\n */\r\nexport async function catchErrors<TResult>(\r\n fn: () => PromiseLike<TResult> | TResult,\r\n onError?: (e: unknown) => TResult,\r\n): Promise<TResult | undefined> {\r\n try {\r\n return await fn();\r\n } catch (e) {\r\n return onError ? onError(e) : undefined;\r\n }\r\n}\r\n","// Helpers shared by the stage-3 decorators of @actuallab/rpc and @actuallab/fusion.\r\n\r\n// Returns the record stored under `key` in `metadata`, guaranteeing it is an OWN\r\n// property. Stage-3 decorator metadata of a derived class inherits from the base\r\n// class's metadata via the prototype chain, so writing through an inherited record\r\n// would silently mutate the base contract. When the record is inherited (or missing)\r\n// it is shallow-cloned into an own property first — base entries stay visible on the\r\n// derived contract while derived writes stay local to it.\r\n// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters -- callers pick the record shape\r\nexport function ownMetadata<T extends object>(metadata: object, key: symbol): T {\r\n const bag = metadata as Record<symbol, T>;\r\n if (!Object.hasOwn(metadata, key))\r\n bag[key] = { ...bag[key] };\r\n\r\n return bag[key];\r\n}\r\n\r\n// Resolves the fixed argument count of a decorated method for the RPC wire name.\r\n// Function.length silently stops at the first default parameter and ignores rest\r\n// parameters, so an inferred count would be wrong; when the parameter list is\r\n// ambiguous the caller must pass an explicit `argCount` or this throws at declaration\r\n// time (the erased count cannot be recovered reliably at runtime).\r\nexport function resolveArgCount(\r\n fn: (...args: never[]) => unknown,\r\n explicit: number | undefined,\r\n methodName: string,\r\n): number {\r\n if (explicit !== undefined)\r\n return explicit;\r\n if (hasAmbiguousArity(fn))\r\n throw new Error(\r\n `Cannot infer the argument count of \"${methodName}\": its parameter list uses ` +\r\n `default and/or rest parameters, for which Function.length is unreliable. ` +\r\n `Pass an explicit argCount to the decorator.`,\r\n );\r\n\r\n return fn.length;\r\n}\r\n\r\n// Private methods\r\n\r\nfunction hasAmbiguousArity(fn: (...args: never[]) => unknown): boolean {\r\n const params = parameterListText(fn);\r\n return params !== undefined && (params.includes('=') || params.includes('...'));\r\n}\r\n\r\nfunction parameterListText(fn: (...args: never[]) => unknown): string | undefined {\r\n const src = fn.toString();\r\n const open = src.indexOf('(');\r\n const arrow = src.indexOf('=>');\r\n // A parenless single-identifier arrow (`x => ...`) has no default/rest parameters.\r\n if (open < 0 || (arrow >= 0 && arrow < open))\r\n return undefined;\r\n\r\n let depth = 0;\r\n for (let i = open; i < src.length; i++) {\r\n const ch = src[i];\r\n if (ch === '(')\r\n depth++;\r\n else if (ch === ')') {\r\n depth--;\r\n if (depth === 0)\r\n return src.slice(open + 1, i);\r\n }\r\n }\r\n return undefined;\r\n}\r\n"],"mappings":"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","names":["LogLevel","reset"]}
package/dist/index.d.cts 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 };