@bitfab/sdk 0.38.4 → 0.38.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/autoTrace.cjs +8 -1
- package/dist/autoTrace.cjs.map +1 -1
- package/dist/autoTrace.d.cts +2 -2
- package/dist/autoTrace.d.ts +2 -2
- package/dist/autoTrace.js +1 -1
- package/dist/{chunk-NKX3EY35.js → chunk-P2MYK27A.js} +154 -68
- package/dist/chunk-P2MYK27A.js.map +1 -0
- package/dist/{chunk-5GWBJGYZ.js → chunk-QTTKZMHM.js} +8 -3
- package/dist/{chunk-5GWBJGYZ.js.map → chunk-QTTKZMHM.js.map} +1 -1
- package/dist/{chunk-J47KPS77.js → chunk-ZUD7OFYB.js} +9 -2
- package/dist/{chunk-J47KPS77.js.map → chunk-ZUD7OFYB.js.map} +1 -1
- package/dist/index.cjs +167 -67
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +41 -11
- package/dist/index.d.ts +41 -11
- package/dist/index.js +5 -3
- package/dist/node.cjs +167 -67
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.cts +1 -1
- package/dist/node.d.ts +1 -1
- package/dist/node.js +5 -3
- package/dist/node.js.map +1 -1
- package/dist/{replay-O2WFIRM4.js → replay-H3AS4IF2.js} +2 -2
- package/dist/replayCli.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-NKX3EY35.js.map +0 -1
- /package/dist/{replay-O2WFIRM4.js.map → replay-H3AS4IF2.js.map} +0 -0
package/dist/autoTrace.cjs
CHANGED
|
@@ -214,11 +214,18 @@ function currentAutoTraceScope() {
|
|
|
214
214
|
}
|
|
215
215
|
function __setBitfabAutoTraceCapturePolicy(client, traceFunctionKey, functionIds) {
|
|
216
216
|
const policies = autoTraceState.capturePolicies.get(client) ?? /* @__PURE__ */ new Map();
|
|
217
|
+
if (functionIds === void 0) {
|
|
218
|
+
policies.delete(traceFunctionKey);
|
|
219
|
+
if (policies.size === 0) {
|
|
220
|
+
autoTraceState.capturePolicies.delete(client);
|
|
221
|
+
}
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
217
224
|
policies.set(traceFunctionKey, new Set(functionIds));
|
|
218
225
|
autoTraceState.capturePolicies.set(client, policies);
|
|
219
226
|
}
|
|
220
227
|
function getAutoTraceCapturePolicy(client, traceFunctionKey) {
|
|
221
|
-
return autoTraceState.capturePolicies.get(client)?.get(traceFunctionKey)
|
|
228
|
+
return autoTraceState.capturePolicies.get(client)?.get(traceFunctionKey);
|
|
222
229
|
}
|
|
223
230
|
// Annotate the CommonJS export names for ESM import in node:
|
|
224
231
|
0 && (module.exports = {
|
package/dist/autoTrace.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/autoTrace.ts","../src/asyncStorage.ts"],"sourcesContent":["import {\n type AsyncLocalStorageLike,\n createAsyncLocalStorage,\n} from \"./asyncStorage.js\"\n\nexport interface AutoTraceFunctionDefinition {\n id: string\n name: string\n file: string\n line: number\n column: number\n async?: boolean\n wrapper?: boolean\n}\n\nexport interface AutoTraceNodeConfiguration {\n functionName: string\n name?: string\n type?: \"llm\" | \"agent\" | \"function\" | \"guardrail\" | \"handoff\" | \"custom\"\n capture: boolean\n testRunId?: string\n mockOnReplay?: boolean\n // biome-ignore lint/suspicious/noExplicitAny: node finalizers receive the configured function's result, whose type is owned by the caller\n finalize?: (result: any) => unknown | Promise<unknown>\n}\n\nexport interface AutoTraceContext {\n invoke<T>(\n definition: AutoTraceFunctionDefinition,\n inputs: unknown[],\n fn: () => T,\n depth: number,\n nodeConfiguration?: AutoTraceNodeConfiguration,\n ): T\n}\n\ninterface AutoTraceScope {\n context: AutoTraceContext\n depth: number\n nodeConfiguration?: AutoTraceNodeConfiguration\n}\n\ninterface AutoTraceState {\n storage: AsyncLocalStorageLike<AutoTraceScope> | null\n browserScope: AutoTraceScope | undefined\n capturePolicies: WeakMap<object, Map<string, ReadonlySet<string>>>\n activeRoots: number\n}\n\ninterface AutoTraceGlobal {\n __bitfabAutoTraceStateV3?: AutoTraceState\n}\n\ninterface AutoTraceAsyncGenerator {\n next(value?: unknown): Promise<IteratorResult<unknown, unknown>>\n return(value?: unknown): Promise<IteratorResult<unknown, unknown>>\n throw(error?: unknown): Promise<IteratorResult<unknown, unknown>>\n [Symbol.asyncIterator](): AutoTraceAsyncGenerator\n}\n\nconst autoTraceGlobal = globalThis as unknown as AutoTraceGlobal\nconst autoTraceState: AutoTraceState =\n autoTraceGlobal.__bitfabAutoTraceStateV3 ?? {\n storage: null,\n browserScope: undefined,\n capturePolicies: new WeakMap(),\n activeRoots: 0,\n }\nautoTraceGlobal.__bitfabAutoTraceStateV3 = autoTraceState\n\nfunction initializeAutoTraceStorage(): void {\n autoTraceState.storage ??= createAsyncLocalStorage<AutoTraceScope>()\n}\n\nexport function runWithAutoTraceContext<T>(\n context: AutoTraceContext,\n fn: () => T,\n depth = 0,\n): T {\n initializeAutoTraceStorage()\n const scope = { context, depth }\n if (autoTraceState.storage) {\n return autoTraceState.storage.run(scope, fn)\n }\n\n const previous = autoTraceState.browserScope\n autoTraceState.browserScope = scope\n try {\n return fn()\n } finally {\n autoTraceState.browserScope = previous\n }\n}\n\nexport function runWithAutoTraceNodeConfiguration<T>(\n nodeConfiguration: AutoTraceNodeConfiguration,\n fn: () => T,\n): T {\n const scope = currentAutoTraceScope()\n if (!scope) {\n return fn()\n }\n\n const configuredScope = { ...scope, nodeConfiguration }\n let result: T\n if (autoTraceState.storage) {\n result = autoTraceState.storage.run(configuredScope, fn)\n } else {\n const previous = autoTraceState.browserScope\n autoTraceState.browserScope = configuredScope\n try {\n result = fn()\n } finally {\n autoTraceState.browserScope = previous\n }\n }\n\n if (isAutoTraceAsyncGenerator(result)) {\n return wrapAutoTraceNodeAsyncGenerator(nodeConfiguration, result) as T\n }\n return result\n}\n\nexport function runWithAutoTraceRootContext<T>(\n context: AutoTraceContext,\n fn: () => T,\n): T {\n autoTraceState.activeRoots += 1\n let result: T\n try {\n result = runWithAutoTraceContext(context, fn)\n } catch (error) {\n autoTraceState.activeRoots -= 1\n throw error\n }\n\n if (isAutoTraceAsyncGenerator(result)) {\n autoTraceState.activeRoots -= 1\n return wrapAutoTraceAsyncGenerator(context, result) as T\n }\n\n if (result instanceof Promise) {\n return result.finally(() => {\n autoTraceState.activeRoots -= 1\n }) as T\n }\n\n autoTraceState.activeRoots -= 1\n return result\n}\n\nfunction isAutoTraceAsyncGenerator(\n value: unknown,\n): value is AutoTraceAsyncGenerator {\n if (value === null || typeof value !== \"object\") {\n return false\n }\n const candidate = value as Record<PropertyKey, unknown>\n return (\n typeof candidate.next === \"function\" &&\n typeof candidate.return === \"function\" &&\n typeof candidate.throw === \"function\" &&\n typeof candidate[Symbol.asyncIterator] === \"function\"\n )\n}\n\nfunction wrapAutoTraceAsyncGenerator(\n context: AutoTraceContext,\n source: AutoTraceAsyncGenerator,\n): AutoTraceAsyncGenerator {\n const step = (\n method: \"next\" | \"return\" | \"throw\",\n value?: unknown,\n ): Promise<IteratorResult<unknown, unknown>> =>\n runWithAutoTraceRootContext(context, () => source[method](value))\n const wrapped: AutoTraceAsyncGenerator = {\n next: (value) => step(\"next\", value),\n return: (value) => step(\"return\", value),\n throw: (error) => step(\"throw\", error),\n [Symbol.asyncIterator]: () => wrapped,\n }\n return wrapped\n}\n\nfunction wrapAutoTraceNodeAsyncGenerator(\n nodeConfiguration: AutoTraceNodeConfiguration,\n source: AutoTraceAsyncGenerator,\n): AutoTraceAsyncGenerator {\n const step = (\n method: \"next\" | \"return\" | \"throw\",\n value?: unknown,\n ): Promise<IteratorResult<unknown, unknown>> =>\n runWithAutoTraceNodeConfiguration(nodeConfiguration, () =>\n source[method](value),\n )\n const wrapped: AutoTraceAsyncGenerator = {\n next: (value) => step(\"next\", value),\n return: (value) => step(\"return\", value),\n throw: (error) => step(\"throw\", error),\n [Symbol.asyncIterator]: () => wrapped,\n }\n return wrapped\n}\n\nexport function __bitfabAutoSpan<T>(\n definition: AutoTraceFunctionDefinition,\n inputs: unknown[],\n fn: () => T,\n): T {\n const scope = currentAutoTraceScope()\n if (!scope) {\n return fn()\n }\n const nameParts = definition.name.split(\".\")\n const simpleName = nameParts[nameParts.length - 1]\n const nodeConfiguration =\n simpleName === scope.nodeConfiguration?.functionName\n ? scope.nodeConfiguration\n : undefined\n return scope.context.invoke(\n definition,\n inputs,\n fn,\n scope.depth,\n nodeConfiguration,\n )\n}\n\n/**\n * Preserve a function's original call arguments for transform cases where\n * parameter bindings discard them, such as destructured arrow parameters.\n *\n * This helper is internal transform/runtime protocol. The proxy preserves the\n * target's callability, arity, async identity, and non-constructibility while\n * only allocating a trace closure beneath an active automatic trace root.\n *\n * @experimental The automatic tracing protocol may change.\n */\nexport function __bitfabAutoWrap<T extends (...args: never[]) => unknown>(\n definition: AutoTraceFunctionDefinition,\n fn: T,\n): T {\n if (fn.name === \"\") {\n const nameParts = definition.name.split(\".\")\n const inferredName = nameParts[nameParts.length - 1]\n if (inferredName !== undefined) {\n Object.defineProperty(fn, \"name\", {\n configurable: true,\n value: inferredName,\n })\n }\n }\n\n const target = fn as unknown as (...args: unknown[]) => unknown\n return new Proxy(target, {\n apply(callTarget, thisArg, args) {\n if (!__bitfabAutoTraceActive()) {\n return Reflect.apply(callTarget, thisArg, args)\n }\n return __bitfabAutoSpan(definition, args, () =>\n Reflect.apply(callTarget, thisArg, args),\n )\n },\n }) as unknown as T\n}\n\n/**\n * Return whether the current call is inside an automatic trace root.\n *\n * Build transforms use this before allocating function metadata, captured\n * inputs, or an invocation closure. It is internal transform/runtime protocol,\n * not a supported application API.\n *\n * @experimental The automatic tracing protocol may change.\n */\nexport function __bitfabAutoTraceActive(): boolean {\n if (autoTraceState.activeRoots === 0) {\n return false\n }\n return currentAutoTraceScope() !== undefined\n}\n\nfunction currentAutoTraceScope(): AutoTraceScope | undefined {\n initializeAutoTraceStorage()\n return autoTraceState.storage?.getStore() ?? autoTraceState.browserScope\n}\n\nexport function __setBitfabAutoTraceCapturePolicy(\n client: object,\n traceFunctionKey: string,\n functionIds: Iterable<string>,\n): void {\n const policies = autoTraceState.capturePolicies.get(client) ?? new Map()\n policies.set(traceFunctionKey, new Set(functionIds))\n autoTraceState.capturePolicies.set(client, policies)\n}\n\nexport function getAutoTraceCapturePolicy(\n client: object,\n traceFunctionKey: string,\n): ReadonlySet<string> {\n return (\n autoTraceState.capturePolicies.get(client)?.get(traceFunctionKey) ??\n new Set()\n )\n}\n","/**\n * Shared AsyncLocalStorage loader.\n *\n * Provides two ways to initialize AsyncLocalStorage:\n *\n * 1. **Synchronous registration** (preferred for Node.js):\n * `asyncStorageNode.ts` calls `registerAsyncLocalStorageClass()` at module\n * evaluation time, so the class is available immediately - no async gap.\n * The `node.ts` entry point imports it before anything else.\n *\n * 2. **Async dynamic import** (fallback for the default entry point):\n * Loads `node:async_hooks` via a bundler-safe dynamic import. This is used\n * by the default `index.ts` entry point so the SDK works in browsers\n * (where the import silently fails) and in Node.js when imported via the\n * default entry point.\n *\n * ## Why the dynamic import looks like this\n *\n * We need to handle three environments:\n *\n * 1. **Pure Node.js** - `import(\"node:async_hooks\")` works natively.\n * 2. **Webpack/Turbopack (Next.js server)** - The bundler processes\n * `import()` calls at build time. The `webpackIgnore` magic comment tells\n * webpack (and turbopack) to emit a native `import()` call instead of\n * trying to resolve it, so Node.js handles it at runtime.\n * 3. **Browsers / Edge** - The `process.versions?.node` guard prevents\n * execution entirely. If it somehow runs, `.catch(() => {})` swallows\n * the failure.\n */\n\nexport interface AsyncLocalStorageLike<T> {\n getStore(): T | undefined\n run<R>(store: T, fn: () => R): R\n}\n\nlet AsyncLocalStorageClass: (new () => AsyncLocalStorageLike<unknown>) | null =\n null\nlet initDone = false\n\n/**\n * Register the AsyncLocalStorage class synchronously.\n *\n * Called by `asyncStorageNode.ts` at module evaluation time so the class\n * is available before any span is created - no async gap, no race condition.\n *\n * Safe to call multiple times; subsequent calls are no-ops.\n */\nexport function registerAsyncLocalStorageClass(\n cls: new () => AsyncLocalStorageLike<unknown>,\n): void {\n if (!AsyncLocalStorageClass) {\n AsyncLocalStorageClass = cls\n }\n initDone = true\n}\n\n/**\n * Assert that AsyncLocalStorage was registered successfully.\n *\n * Called by `node.ts` after importing `asyncStorageNode.ts` to catch\n * import-order bugs at startup rather than silently degrading to the\n * browser fallback (flat spans with no nesting).\n *\n * This should ONLY be called from the Node.js entry point where we\n * know `node:async_hooks` must be available.\n */\nexport function assertAsyncStorageRegistered(): void {\n if (!AsyncLocalStorageClass) {\n console.warn(\n \"Bitfab: AsyncLocalStorage not available - nested span context will not propagate.\",\n )\n }\n}\n\nexport const asyncStorageReady: Promise<void> = (\n typeof process !== \"undefined\" && process.versions?.node\n ? // The join trick hides \"node:async_hooks\" from static analysis so\n // bundlers that ban Node.js built-ins don't fail at build time.\n // webpackIgnore tells webpack/turbopack to emit a native import()\n // so Node.js can resolve the module at runtime.\n import(\n /* webpackIgnore: true */\n [\"node\", \"async_hooks\"].join(\":\")\n )\n .then(\n (mod: {\n AsyncLocalStorage: new () => AsyncLocalStorageLike<unknown>\n }) => {\n registerAsyncLocalStorageClass(mod.AsyncLocalStorage)\n },\n )\n .catch(() => {})\n : Promise.resolve()\n).then(() => {\n initDone = true\n})\n\nexport function isAsyncStorageInitDone(): boolean {\n return initDone\n}\n\nexport function createAsyncLocalStorage<T>(): AsyncLocalStorageLike<T> | null {\n return AsyncLocalStorageClass\n ? (new AsyncLocalStorageClass() as AsyncLocalStorageLike<T>)\n : null\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/autoTrace.ts","../src/asyncStorage.ts"],"sourcesContent":["import {\n type AsyncLocalStorageLike,\n createAsyncLocalStorage,\n} from \"./asyncStorage.js\"\n\nexport interface AutoTraceFunctionDefinition {\n id: string\n name: string\n file: string\n line: number\n column: number\n async?: boolean\n wrapper?: boolean\n}\n\nexport interface AutoTraceNodeConfiguration {\n functionName: string\n name?: string\n type?: \"llm\" | \"agent\" | \"function\" | \"guardrail\" | \"handoff\" | \"custom\"\n capture: boolean\n testRunId?: string\n mockOnReplay?: boolean\n // biome-ignore lint/suspicious/noExplicitAny: node finalizers receive the configured function's result, whose type is owned by the caller\n finalize?: (result: any) => unknown | Promise<unknown>\n}\n\nexport interface AutoTraceContext {\n invoke<T>(\n definition: AutoTraceFunctionDefinition,\n inputs: unknown[],\n fn: () => T,\n depth: number,\n nodeConfiguration?: AutoTraceNodeConfiguration,\n ): T\n}\n\ninterface AutoTraceScope {\n context: AutoTraceContext\n depth: number\n nodeConfiguration?: AutoTraceNodeConfiguration\n}\n\ninterface AutoTraceState {\n storage: AsyncLocalStorageLike<AutoTraceScope> | null\n browserScope: AutoTraceScope | undefined\n capturePolicies: WeakMap<object, Map<string, ReadonlySet<string>>>\n activeRoots: number\n}\n\ninterface AutoTraceGlobal {\n __bitfabAutoTraceStateV3?: AutoTraceState\n}\n\ninterface AutoTraceAsyncGenerator {\n next(value?: unknown): Promise<IteratorResult<unknown, unknown>>\n return(value?: unknown): Promise<IteratorResult<unknown, unknown>>\n throw(error?: unknown): Promise<IteratorResult<unknown, unknown>>\n [Symbol.asyncIterator](): AutoTraceAsyncGenerator\n}\n\nconst autoTraceGlobal = globalThis as unknown as AutoTraceGlobal\nconst autoTraceState: AutoTraceState =\n autoTraceGlobal.__bitfabAutoTraceStateV3 ?? {\n storage: null,\n browserScope: undefined,\n capturePolicies: new WeakMap(),\n activeRoots: 0,\n }\nautoTraceGlobal.__bitfabAutoTraceStateV3 = autoTraceState\n\nfunction initializeAutoTraceStorage(): void {\n autoTraceState.storage ??= createAsyncLocalStorage<AutoTraceScope>()\n}\n\nexport function runWithAutoTraceContext<T>(\n context: AutoTraceContext,\n fn: () => T,\n depth = 0,\n): T {\n initializeAutoTraceStorage()\n const scope = { context, depth }\n if (autoTraceState.storage) {\n return autoTraceState.storage.run(scope, fn)\n }\n\n const previous = autoTraceState.browserScope\n autoTraceState.browserScope = scope\n try {\n return fn()\n } finally {\n autoTraceState.browserScope = previous\n }\n}\n\nexport function runWithAutoTraceNodeConfiguration<T>(\n nodeConfiguration: AutoTraceNodeConfiguration,\n fn: () => T,\n): T {\n const scope = currentAutoTraceScope()\n if (!scope) {\n return fn()\n }\n\n const configuredScope = { ...scope, nodeConfiguration }\n let result: T\n if (autoTraceState.storage) {\n result = autoTraceState.storage.run(configuredScope, fn)\n } else {\n const previous = autoTraceState.browserScope\n autoTraceState.browserScope = configuredScope\n try {\n result = fn()\n } finally {\n autoTraceState.browserScope = previous\n }\n }\n\n if (isAutoTraceAsyncGenerator(result)) {\n return wrapAutoTraceNodeAsyncGenerator(nodeConfiguration, result) as T\n }\n return result\n}\n\nexport function runWithAutoTraceRootContext<T>(\n context: AutoTraceContext,\n fn: () => T,\n): T {\n autoTraceState.activeRoots += 1\n let result: T\n try {\n result = runWithAutoTraceContext(context, fn)\n } catch (error) {\n autoTraceState.activeRoots -= 1\n throw error\n }\n\n if (isAutoTraceAsyncGenerator(result)) {\n autoTraceState.activeRoots -= 1\n return wrapAutoTraceAsyncGenerator(context, result) as T\n }\n\n if (result instanceof Promise) {\n return result.finally(() => {\n autoTraceState.activeRoots -= 1\n }) as T\n }\n\n autoTraceState.activeRoots -= 1\n return result\n}\n\nfunction isAutoTraceAsyncGenerator(\n value: unknown,\n): value is AutoTraceAsyncGenerator {\n if (value === null || typeof value !== \"object\") {\n return false\n }\n const candidate = value as Record<PropertyKey, unknown>\n return (\n typeof candidate.next === \"function\" &&\n typeof candidate.return === \"function\" &&\n typeof candidate.throw === \"function\" &&\n typeof candidate[Symbol.asyncIterator] === \"function\"\n )\n}\n\nfunction wrapAutoTraceAsyncGenerator(\n context: AutoTraceContext,\n source: AutoTraceAsyncGenerator,\n): AutoTraceAsyncGenerator {\n const step = (\n method: \"next\" | \"return\" | \"throw\",\n value?: unknown,\n ): Promise<IteratorResult<unknown, unknown>> =>\n runWithAutoTraceRootContext(context, () => source[method](value))\n const wrapped: AutoTraceAsyncGenerator = {\n next: (value) => step(\"next\", value),\n return: (value) => step(\"return\", value),\n throw: (error) => step(\"throw\", error),\n [Symbol.asyncIterator]: () => wrapped,\n }\n return wrapped\n}\n\nfunction wrapAutoTraceNodeAsyncGenerator(\n nodeConfiguration: AutoTraceNodeConfiguration,\n source: AutoTraceAsyncGenerator,\n): AutoTraceAsyncGenerator {\n const step = (\n method: \"next\" | \"return\" | \"throw\",\n value?: unknown,\n ): Promise<IteratorResult<unknown, unknown>> =>\n runWithAutoTraceNodeConfiguration(nodeConfiguration, () =>\n source[method](value),\n )\n const wrapped: AutoTraceAsyncGenerator = {\n next: (value) => step(\"next\", value),\n return: (value) => step(\"return\", value),\n throw: (error) => step(\"throw\", error),\n [Symbol.asyncIterator]: () => wrapped,\n }\n return wrapped\n}\n\nexport function __bitfabAutoSpan<T>(\n definition: AutoTraceFunctionDefinition,\n inputs: unknown[],\n fn: () => T,\n): T {\n const scope = currentAutoTraceScope()\n if (!scope) {\n return fn()\n }\n const nameParts = definition.name.split(\".\")\n const simpleName = nameParts[nameParts.length - 1]\n const nodeConfiguration =\n simpleName === scope.nodeConfiguration?.functionName\n ? scope.nodeConfiguration\n : undefined\n return scope.context.invoke(\n definition,\n inputs,\n fn,\n scope.depth,\n nodeConfiguration,\n )\n}\n\n/**\n * Preserve a function's original call arguments for transform cases where\n * parameter bindings discard them, such as destructured arrow parameters.\n *\n * This helper is internal transform/runtime protocol. The proxy preserves the\n * target's callability, arity, async identity, and non-constructibility while\n * only allocating a trace closure beneath an active automatic trace root.\n *\n * @experimental The automatic tracing protocol may change.\n */\nexport function __bitfabAutoWrap<T extends (...args: never[]) => unknown>(\n definition: AutoTraceFunctionDefinition,\n fn: T,\n): T {\n if (fn.name === \"\") {\n const nameParts = definition.name.split(\".\")\n const inferredName = nameParts[nameParts.length - 1]\n if (inferredName !== undefined) {\n Object.defineProperty(fn, \"name\", {\n configurable: true,\n value: inferredName,\n })\n }\n }\n\n const target = fn as unknown as (...args: unknown[]) => unknown\n return new Proxy(target, {\n apply(callTarget, thisArg, args) {\n if (!__bitfabAutoTraceActive()) {\n return Reflect.apply(callTarget, thisArg, args)\n }\n return __bitfabAutoSpan(definition, args, () =>\n Reflect.apply(callTarget, thisArg, args),\n )\n },\n }) as unknown as T\n}\n\n/**\n * Return whether the current call is inside an automatic trace root.\n *\n * Build transforms use this before allocating function metadata, captured\n * inputs, or an invocation closure. It is internal transform/runtime protocol,\n * not a supported application API.\n *\n * @experimental The automatic tracing protocol may change.\n */\nexport function __bitfabAutoTraceActive(): boolean {\n if (autoTraceState.activeRoots === 0) {\n return false\n }\n return currentAutoTraceScope() !== undefined\n}\n\nfunction currentAutoTraceScope(): AutoTraceScope | undefined {\n initializeAutoTraceStorage()\n return autoTraceState.storage?.getStore() ?? autoTraceState.browserScope\n}\n\nexport function __setBitfabAutoTraceCapturePolicy(\n client: object,\n traceFunctionKey: string,\n functionIds: Iterable<string> | undefined,\n): void {\n const policies = autoTraceState.capturePolicies.get(client) ?? new Map()\n if (functionIds === undefined) {\n policies.delete(traceFunctionKey)\n if (policies.size === 0) {\n autoTraceState.capturePolicies.delete(client)\n }\n return\n }\n policies.set(traceFunctionKey, new Set(functionIds))\n autoTraceState.capturePolicies.set(client, policies)\n}\n\nexport function getAutoTraceCapturePolicy(\n client: object,\n traceFunctionKey: string,\n): ReadonlySet<string> | undefined {\n return autoTraceState.capturePolicies.get(client)?.get(traceFunctionKey)\n}\n","/**\n * Shared AsyncLocalStorage loader.\n *\n * Provides two ways to initialize AsyncLocalStorage:\n *\n * 1. **Synchronous registration** (preferred for Node.js):\n * `asyncStorageNode.ts` calls `registerAsyncLocalStorageClass()` at module\n * evaluation time, so the class is available immediately - no async gap.\n * The `node.ts` entry point imports it before anything else.\n *\n * 2. **Async dynamic import** (fallback for the default entry point):\n * Loads `node:async_hooks` via a bundler-safe dynamic import. This is used\n * by the default `index.ts` entry point so the SDK works in browsers\n * (where the import silently fails) and in Node.js when imported via the\n * default entry point.\n *\n * ## Why the dynamic import looks like this\n *\n * We need to handle three environments:\n *\n * 1. **Pure Node.js** - `import(\"node:async_hooks\")` works natively.\n * 2. **Webpack/Turbopack (Next.js server)** - The bundler processes\n * `import()` calls at build time. The `webpackIgnore` magic comment tells\n * webpack (and turbopack) to emit a native `import()` call instead of\n * trying to resolve it, so Node.js handles it at runtime.\n * 3. **Browsers / Edge** - The `process.versions?.node` guard prevents\n * execution entirely. If it somehow runs, `.catch(() => {})` swallows\n * the failure.\n */\n\nexport interface AsyncLocalStorageLike<T> {\n getStore(): T | undefined\n run<R>(store: T, fn: () => R): R\n}\n\nlet AsyncLocalStorageClass: (new () => AsyncLocalStorageLike<unknown>) | null =\n null\nlet initDone = false\n\n/**\n * Register the AsyncLocalStorage class synchronously.\n *\n * Called by `asyncStorageNode.ts` at module evaluation time so the class\n * is available before any span is created - no async gap, no race condition.\n *\n * Safe to call multiple times; subsequent calls are no-ops.\n */\nexport function registerAsyncLocalStorageClass(\n cls: new () => AsyncLocalStorageLike<unknown>,\n): void {\n if (!AsyncLocalStorageClass) {\n AsyncLocalStorageClass = cls\n }\n initDone = true\n}\n\n/**\n * Assert that AsyncLocalStorage was registered successfully.\n *\n * Called by `node.ts` after importing `asyncStorageNode.ts` to catch\n * import-order bugs at startup rather than silently degrading to the\n * browser fallback (flat spans with no nesting).\n *\n * This should ONLY be called from the Node.js entry point where we\n * know `node:async_hooks` must be available.\n */\nexport function assertAsyncStorageRegistered(): void {\n if (!AsyncLocalStorageClass) {\n console.warn(\n \"Bitfab: AsyncLocalStorage not available - nested span context will not propagate.\",\n )\n }\n}\n\nexport const asyncStorageReady: Promise<void> = (\n typeof process !== \"undefined\" && process.versions?.node\n ? // The join trick hides \"node:async_hooks\" from static analysis so\n // bundlers that ban Node.js built-ins don't fail at build time.\n // webpackIgnore tells webpack/turbopack to emit a native import()\n // so Node.js can resolve the module at runtime.\n import(\n /* webpackIgnore: true */\n [\"node\", \"async_hooks\"].join(\":\")\n )\n .then(\n (mod: {\n AsyncLocalStorage: new () => AsyncLocalStorageLike<unknown>\n }) => {\n registerAsyncLocalStorageClass(mod.AsyncLocalStorage)\n },\n )\n .catch(() => {})\n : Promise.resolve()\n).then(() => {\n initDone = true\n})\n\nexport function isAsyncStorageInitDone(): boolean {\n return initDone\n}\n\nexport function createAsyncLocalStorage<T>(): AsyncLocalStorageLike<T> | null {\n return AsyncLocalStorageClass\n ? (new AsyncLocalStorageClass() as AsyncLocalStorageLike<T>)\n : null\n}\n"],"mappings":"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","names":[]}
|
package/dist/autoTrace.d.cts
CHANGED
|
@@ -44,7 +44,7 @@ declare function __bitfabAutoWrap<T extends (...args: never[]) => unknown>(defin
|
|
|
44
44
|
* @experimental The automatic tracing protocol may change.
|
|
45
45
|
*/
|
|
46
46
|
declare function __bitfabAutoTraceActive(): boolean;
|
|
47
|
-
declare function __setBitfabAutoTraceCapturePolicy(client: object, traceFunctionKey: string, functionIds: Iterable<string>): void;
|
|
48
|
-
declare function getAutoTraceCapturePolicy(client: object, traceFunctionKey: string): ReadonlySet<string
|
|
47
|
+
declare function __setBitfabAutoTraceCapturePolicy(client: object, traceFunctionKey: string, functionIds: Iterable<string> | undefined): void;
|
|
48
|
+
declare function getAutoTraceCapturePolicy(client: object, traceFunctionKey: string): ReadonlySet<string> | undefined;
|
|
49
49
|
|
|
50
50
|
export { type AutoTraceContext, type AutoTraceFunctionDefinition, type AutoTraceNodeConfiguration, __bitfabAutoSpan, __bitfabAutoTraceActive, __bitfabAutoWrap, __setBitfabAutoTraceCapturePolicy, getAutoTraceCapturePolicy, runWithAutoTraceContext, runWithAutoTraceNodeConfiguration, runWithAutoTraceRootContext };
|
package/dist/autoTrace.d.ts
CHANGED
|
@@ -44,7 +44,7 @@ declare function __bitfabAutoWrap<T extends (...args: never[]) => unknown>(defin
|
|
|
44
44
|
* @experimental The automatic tracing protocol may change.
|
|
45
45
|
*/
|
|
46
46
|
declare function __bitfabAutoTraceActive(): boolean;
|
|
47
|
-
declare function __setBitfabAutoTraceCapturePolicy(client: object, traceFunctionKey: string, functionIds: Iterable<string>): void;
|
|
48
|
-
declare function getAutoTraceCapturePolicy(client: object, traceFunctionKey: string): ReadonlySet<string
|
|
47
|
+
declare function __setBitfabAutoTraceCapturePolicy(client: object, traceFunctionKey: string, functionIds: Iterable<string> | undefined): void;
|
|
48
|
+
declare function getAutoTraceCapturePolicy(client: object, traceFunctionKey: string): ReadonlySet<string> | undefined;
|
|
49
49
|
|
|
50
50
|
export { type AutoTraceContext, type AutoTraceFunctionDefinition, type AutoTraceNodeConfiguration, __bitfabAutoSpan, __bitfabAutoTraceActive, __bitfabAutoWrap, __setBitfabAutoTraceCapturePolicy, getAutoTraceCapturePolicy, runWithAutoTraceContext, runWithAutoTraceNodeConfiguration, runWithAutoTraceRootContext };
|
package/dist/autoTrace.js
CHANGED
|
@@ -5,11 +5,12 @@ import {
|
|
|
5
5
|
runWithAutoTraceContext,
|
|
6
6
|
runWithAutoTraceNodeConfiguration,
|
|
7
7
|
runWithAutoTraceRootContext
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-ZUD7OFYB.js";
|
|
9
9
|
import {
|
|
10
10
|
BitfabError,
|
|
11
11
|
DEFAULT_SERVICE_URL,
|
|
12
12
|
HttpClient,
|
|
13
|
+
NO_MOCK_OVERRIDE,
|
|
13
14
|
deserializeValue,
|
|
14
15
|
getReplayContext,
|
|
15
16
|
randomUuid,
|
|
@@ -18,7 +19,7 @@ import {
|
|
|
18
19
|
toJsonSafe,
|
|
19
20
|
toJsonSafeReport,
|
|
20
21
|
warnOnce
|
|
21
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-QTTKZMHM.js";
|
|
22
23
|
import {
|
|
23
24
|
__privateAdd,
|
|
24
25
|
__privateGet,
|
|
@@ -2392,8 +2393,9 @@ var Bitfab = class {
|
|
|
2392
2393
|
* Decorate a class method as an automatically expanded trace root.
|
|
2393
2394
|
*
|
|
2394
2395
|
* Build instrumentation turns repository functions called beneath this
|
|
2395
|
-
* method into nested spans
|
|
2396
|
-
*
|
|
2396
|
+
* method into nested spans that capture inputs, outputs, and errors by
|
|
2397
|
+
* default. A confirmed capture policy can narrow rich capture to selected
|
|
2398
|
+
* function IDs.
|
|
2397
2399
|
* Without a compatible build transform, this still records the decorated
|
|
2398
2400
|
* method as a normal rich root span but cannot discover child calls.
|
|
2399
2401
|
*
|
|
@@ -2603,7 +2605,7 @@ var Bitfab = class {
|
|
|
2603
2605
|
type: nodeConfiguration?.type ?? "function",
|
|
2604
2606
|
captureWhen: "nested",
|
|
2605
2607
|
functionId: definition.id,
|
|
2606
|
-
captureContent: nodeConfiguration !== void 0 || capturePolicy.has(definition.id),
|
|
2608
|
+
captureContent: nodeConfiguration !== void 0 || capturePolicy === void 0 || capturePolicy.has(definition.id),
|
|
2607
2609
|
autoTraceDefinition: definition,
|
|
2608
2610
|
...nodeConfiguration?.testRunId !== void 0 && {
|
|
2609
2611
|
testRunId: nodeConfiguration.testRunId
|
|
@@ -2668,7 +2670,11 @@ var Bitfab = class {
|
|
|
2668
2670
|
const functionIds = Array.isArray(policy.functionIds) ? policy.functionIds.filter(
|
|
2669
2671
|
(id) => typeof id === "string" && id.startsWith(`${AUTO_TRACE_PROTOCOL}:`)
|
|
2670
2672
|
).slice(0, DEFAULT_AUTO_TRACE_MAX_SPANS) : [];
|
|
2671
|
-
__setBitfabAutoTraceCapturePolicy(
|
|
2673
|
+
__setBitfabAutoTraceCapturePolicy(
|
|
2674
|
+
this,
|
|
2675
|
+
traceFunctionKey,
|
|
2676
|
+
policy.revision === null ? void 0 : functionIds
|
|
2677
|
+
);
|
|
2672
2678
|
state.refreshAfter = Date.now() + AUTO_TRACE_POLICY_REFRESH_MS;
|
|
2673
2679
|
}).catch(() => {
|
|
2674
2680
|
state.refreshAfter = Date.now() + AUTO_TRACE_POLICY_RETRY_MS;
|
|
@@ -3280,6 +3286,49 @@ var Bitfab = class {
|
|
|
3280
3286
|
} catch {
|
|
3281
3287
|
}
|
|
3282
3288
|
};
|
|
3289
|
+
const recordSpan = (result) => {
|
|
3290
|
+
if (options.finalize) {
|
|
3291
|
+
void self.httpClient.trackDeferred(
|
|
3292
|
+
Promise.resolve().then(() => options.finalize(result)).then((output) => sendSpan({ result: output })).catch(
|
|
3293
|
+
(error) => sendSpan({
|
|
3294
|
+
result: void 0,
|
|
3295
|
+
error: error instanceof Error ? `finalize failed: ${error.message}` : `finalize failed: ${String(error)}`
|
|
3296
|
+
})
|
|
3297
|
+
)
|
|
3298
|
+
);
|
|
3299
|
+
} else {
|
|
3300
|
+
void sendSpan({ result });
|
|
3301
|
+
}
|
|
3302
|
+
};
|
|
3303
|
+
executeWithContext = () => {
|
|
3304
|
+
let result;
|
|
3305
|
+
try {
|
|
3306
|
+
result = fn.apply(this, args);
|
|
3307
|
+
} catch (error) {
|
|
3308
|
+
void sendSpan({
|
|
3309
|
+
result: void 0,
|
|
3310
|
+
error: error instanceof Error ? error.message : String(error)
|
|
3311
|
+
});
|
|
3312
|
+
throw error;
|
|
3313
|
+
}
|
|
3314
|
+
if (result instanceof Promise) {
|
|
3315
|
+
return result.then((resolvedResult) => {
|
|
3316
|
+
recordSpan(resolvedResult);
|
|
3317
|
+
return resolvedResult;
|
|
3318
|
+
}).catch((error) => {
|
|
3319
|
+
void sendSpan({
|
|
3320
|
+
result: void 0,
|
|
3321
|
+
error: error instanceof Error ? error.message : String(error)
|
|
3322
|
+
});
|
|
3323
|
+
throw error;
|
|
3324
|
+
});
|
|
3325
|
+
}
|
|
3326
|
+
if (isAsyncGenerator(result)) {
|
|
3327
|
+
return wrapAsyncGenerator(result, newStack, sendSpan);
|
|
3328
|
+
}
|
|
3329
|
+
recordSpan(result);
|
|
3330
|
+
return result;
|
|
3331
|
+
};
|
|
3283
3332
|
const replayCtxForMock = getReplayContext();
|
|
3284
3333
|
if (replayCtxForMock?.mockTree && !isRootSpan) {
|
|
3285
3334
|
const counters = replayCtxForMock.callCounters;
|
|
@@ -3338,6 +3387,7 @@ var Bitfab = class {
|
|
|
3338
3387
|
}
|
|
3339
3388
|
return output;
|
|
3340
3389
|
};
|
|
3390
|
+
const shouldMockWithBaseStrategy = replayCtxForMock.mockStrategy === "all" || replayCtxForMock.mockStrategy === "marked" && options.mockOnReplay === true;
|
|
3341
3391
|
if (replayCtxForMock.mockOverrides?.length) {
|
|
3342
3392
|
const nodeMeta = {
|
|
3343
3393
|
traceFunctionKey,
|
|
@@ -3345,28 +3395,75 @@ var Bitfab = class {
|
|
|
3345
3395
|
type: options.type ?? "custom",
|
|
3346
3396
|
originalSpanId: mockSpan?.sourceSpanId
|
|
3347
3397
|
};
|
|
3348
|
-
const
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3398
|
+
const overrideCtx = {
|
|
3399
|
+
node: nodeMeta,
|
|
3400
|
+
inputs: args,
|
|
3401
|
+
getOriginalOutput: () => Promise.resolve(resolveRecordedOutput())
|
|
3402
|
+
};
|
|
3403
|
+
const resolveOverrideFrom = (startIndex) => {
|
|
3404
|
+
for (let index = startIndex; index < replayCtxForMock.mockOverrides.length; index += 1) {
|
|
3405
|
+
const override = replayCtxForMock.mockOverrides[index];
|
|
3406
|
+
if (!override?.match(nodeMeta)) {
|
|
3407
|
+
continue;
|
|
3408
|
+
}
|
|
3409
|
+
const injected = resolveMockValue(override.value, overrideCtx);
|
|
3410
|
+
if (injected instanceof Promise) {
|
|
3411
|
+
return injected.then(
|
|
3412
|
+
(output) => output === NO_MOCK_OVERRIDE ? resolveOverrideFrom(index + 1) : { matched: true, output }
|
|
3413
|
+
);
|
|
3414
|
+
}
|
|
3415
|
+
if (injected !== NO_MOCK_OVERRIDE) {
|
|
3416
|
+
return { matched: true, output: injected };
|
|
3417
|
+
}
|
|
3418
|
+
}
|
|
3419
|
+
return { matched: false };
|
|
3420
|
+
};
|
|
3421
|
+
const resolution = resolveOverrideFrom(0);
|
|
3422
|
+
if (resolution instanceof Promise) {
|
|
3423
|
+
if (!fnReturnsPromise) {
|
|
3424
|
+
throw new BitfabError(
|
|
3425
|
+
`Cannot resolve an asynchronous mock override for synchronous span "${traceFunctionKey}". Make the wrapped function async or return NO_MOCK_OVERRIDE synchronously.`
|
|
3426
|
+
);
|
|
3359
3427
|
}
|
|
3360
|
-
return
|
|
3428
|
+
return runWithSpanStack(newStack, async () => {
|
|
3429
|
+
const resolved = await resolution;
|
|
3430
|
+
if (resolved.matched) {
|
|
3431
|
+
void sendSpan({
|
|
3432
|
+
result: resolved.output,
|
|
3433
|
+
mocked: true,
|
|
3434
|
+
mockTarget: "output",
|
|
3435
|
+
mockSource: "override"
|
|
3436
|
+
});
|
|
3437
|
+
return resolved.output;
|
|
3438
|
+
}
|
|
3439
|
+
if (shouldMockWithBaseStrategy && !mockSpan) {
|
|
3440
|
+
throw new BitfabError(
|
|
3441
|
+
`Replay selected span "${traceFunctionKey}:${baseSpanParams.spanName}" for mocking, but recorded occurrence ${callIndex + 1} is unavailable. The real span was not executed.`
|
|
3442
|
+
);
|
|
3443
|
+
}
|
|
3444
|
+
if (shouldMockWithBaseStrategy) {
|
|
3445
|
+
const output = await resolveRecordedOutput();
|
|
3446
|
+
void sendSpan({
|
|
3447
|
+
result: output,
|
|
3448
|
+
mocked: true,
|
|
3449
|
+
mockTarget: "output",
|
|
3450
|
+
mockSource: "recorded"
|
|
3451
|
+
});
|
|
3452
|
+
return output;
|
|
3453
|
+
}
|
|
3454
|
+
return executeWithContext();
|
|
3455
|
+
});
|
|
3456
|
+
}
|
|
3457
|
+
if (resolution.matched) {
|
|
3458
|
+
return emitMock(resolution.output, "override");
|
|
3361
3459
|
}
|
|
3362
3460
|
}
|
|
3363
|
-
|
|
3364
|
-
if (shouldMock && !mockSpan) {
|
|
3461
|
+
if (shouldMockWithBaseStrategy && !mockSpan) {
|
|
3365
3462
|
throw new BitfabError(
|
|
3366
3463
|
`Replay selected span "${traceFunctionKey}:${baseSpanParams.spanName}" for mocking, but recorded occurrence ${callIndex + 1} is unavailable. The real span was not executed.`
|
|
3367
3464
|
);
|
|
3368
3465
|
}
|
|
3369
|
-
if (
|
|
3466
|
+
if (shouldMockWithBaseStrategy) {
|
|
3370
3467
|
const recorded = resolveRecordedOutput();
|
|
3371
3468
|
if (recorded instanceof Promise) {
|
|
3372
3469
|
return emitMockAsync(recorded, "recorded");
|
|
@@ -3374,49 +3471,6 @@ var Bitfab = class {
|
|
|
3374
3471
|
return emitMock(recorded, "recorded");
|
|
3375
3472
|
}
|
|
3376
3473
|
}
|
|
3377
|
-
const recordSpan = (result) => {
|
|
3378
|
-
if (options.finalize) {
|
|
3379
|
-
void self.httpClient.trackDeferred(
|
|
3380
|
-
Promise.resolve().then(() => options.finalize(result)).then((output) => sendSpan({ result: output })).catch(
|
|
3381
|
-
(error) => sendSpan({
|
|
3382
|
-
result: void 0,
|
|
3383
|
-
error: error instanceof Error ? `finalize failed: ${error.message}` : `finalize failed: ${String(error)}`
|
|
3384
|
-
})
|
|
3385
|
-
)
|
|
3386
|
-
);
|
|
3387
|
-
} else {
|
|
3388
|
-
void sendSpan({ result });
|
|
3389
|
-
}
|
|
3390
|
-
};
|
|
3391
|
-
executeWithContext = () => {
|
|
3392
|
-
let result;
|
|
3393
|
-
try {
|
|
3394
|
-
result = fn.apply(this, args);
|
|
3395
|
-
} catch (error) {
|
|
3396
|
-
void sendSpan({
|
|
3397
|
-
result: void 0,
|
|
3398
|
-
error: error instanceof Error ? error.message : String(error)
|
|
3399
|
-
});
|
|
3400
|
-
throw error;
|
|
3401
|
-
}
|
|
3402
|
-
if (result instanceof Promise) {
|
|
3403
|
-
return result.then((resolvedResult) => {
|
|
3404
|
-
recordSpan(resolvedResult);
|
|
3405
|
-
return resolvedResult;
|
|
3406
|
-
}).catch((error) => {
|
|
3407
|
-
void sendSpan({
|
|
3408
|
-
result: void 0,
|
|
3409
|
-
error: error instanceof Error ? error.message : String(error)
|
|
3410
|
-
});
|
|
3411
|
-
throw error;
|
|
3412
|
-
});
|
|
3413
|
-
}
|
|
3414
|
-
if (isAsyncGenerator(result)) {
|
|
3415
|
-
return wrapAsyncGenerator(result, newStack, sendSpan);
|
|
3416
|
-
}
|
|
3417
|
-
recordSpan(result);
|
|
3418
|
-
return result;
|
|
3419
|
-
};
|
|
3420
3474
|
} catch (setupError) {
|
|
3421
3475
|
if (registeredTraceId) {
|
|
3422
3476
|
activeTraceStates.delete(registeredTraceId);
|
|
@@ -3703,8 +3757,40 @@ var Bitfab = class {
|
|
|
3703
3757
|
...params.mockSource && { mockSource: params.mockSource }
|
|
3704
3758
|
});
|
|
3705
3759
|
}
|
|
3706
|
-
registerMockOverride(
|
|
3707
|
-
|
|
3760
|
+
registerMockOverride(overrideOrResolverOrMatch, ...values) {
|
|
3761
|
+
let override;
|
|
3762
|
+
if (typeof overrideOrResolverOrMatch === "string") {
|
|
3763
|
+
const keyedOverride = values[0];
|
|
3764
|
+
if (values.length !== 1 || keyedOverride === void 0) {
|
|
3765
|
+
throw new BitfabError(
|
|
3766
|
+
"registerMockOverride(traceFunctionKey, override) requires a resolver function or { match, value } override."
|
|
3767
|
+
);
|
|
3768
|
+
}
|
|
3769
|
+
if (typeof keyedOverride === "function") {
|
|
3770
|
+
override = {
|
|
3771
|
+
match: (node) => node.traceFunctionKey === overrideOrResolverOrMatch,
|
|
3772
|
+
value: keyedOverride
|
|
3773
|
+
};
|
|
3774
|
+
} else if (typeof keyedOverride === "object" && keyedOverride !== null && "match" in keyedOverride && "value" in keyedOverride) {
|
|
3775
|
+
override = {
|
|
3776
|
+
match: (node) => node.traceFunctionKey === overrideOrResolverOrMatch && keyedOverride.match(node),
|
|
3777
|
+
value: keyedOverride.value
|
|
3778
|
+
};
|
|
3779
|
+
} else {
|
|
3780
|
+
throw new BitfabError(
|
|
3781
|
+
"registerMockOverride(traceFunctionKey, override) requires a resolver function or { match, value } override."
|
|
3782
|
+
);
|
|
3783
|
+
}
|
|
3784
|
+
} else if (typeof overrideOrResolverOrMatch !== "function") {
|
|
3785
|
+
override = overrideOrResolverOrMatch;
|
|
3786
|
+
} else if (values.length === 0) {
|
|
3787
|
+
override = { match: () => true, value: overrideOrResolverOrMatch };
|
|
3788
|
+
} else {
|
|
3789
|
+
override = {
|
|
3790
|
+
match: overrideOrResolverOrMatch,
|
|
3791
|
+
value: values[0]
|
|
3792
|
+
};
|
|
3793
|
+
}
|
|
3708
3794
|
this.mockOverrides.push(override);
|
|
3709
3795
|
}
|
|
3710
3796
|
/** Remove all overrides registered via {@link registerMockOverride}. */
|
|
@@ -3725,7 +3811,7 @@ var Bitfab = class {
|
|
|
3725
3811
|
`Function is wrapped with trace function key '${wrappedKey}' but replay was called with '${traceFunctionKey}'. Pass matching keys, or pass the unwrapped function to replay it under the explicit key.`
|
|
3726
3812
|
);
|
|
3727
3813
|
}
|
|
3728
|
-
const { replay: doReplay } = await import("./replay-
|
|
3814
|
+
const { replay: doReplay } = await import("./replay-H3AS4IF2.js");
|
|
3729
3815
|
return doReplay(
|
|
3730
3816
|
this.httpClient,
|
|
3731
3817
|
this.serviceUrl,
|
|
@@ -3969,4 +4055,4 @@ export {
|
|
|
3969
4055
|
finalizers,
|
|
3970
4056
|
defineReplayRegistry
|
|
3971
4057
|
};
|
|
3972
|
-
//# sourceMappingURL=chunk-
|
|
4058
|
+
//# sourceMappingURL=chunk-P2MYK27A.js.map
|