bitfab 0.11.5 → 0.12.0
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/{chunk-GWHHP5PL.js → chunk-QUCK3IU2.js} +34 -4
- package/dist/chunk-QUCK3IU2.js.map +1 -0
- package/dist/{chunk-KSUI74KL.js → chunk-VMJPNYAG.js} +38 -2
- package/dist/chunk-VMJPNYAG.js.map +1 -0
- package/dist/index.cjs +106 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -2
- package/dist/index.d.ts +21 -2
- package/dist/index.js +2 -2
- package/dist/node.cjs +106 -5
- 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 +2 -2
- package/dist/{replay-RR4IVBXE.js → replay-6FKD2UEU.js} +41 -5
- package/dist/replay-6FKD2UEU.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-GWHHP5PL.js.map +0 -1
- package/dist/chunk-KSUI74KL.js.map +0 -1
- package/dist/replay-RR4IVBXE.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -35,7 +35,7 @@ var __version__;
|
|
|
35
35
|
var init_version_generated = __esm({
|
|
36
36
|
"src/version.generated.ts"() {
|
|
37
37
|
"use strict";
|
|
38
|
-
__version__ = "0.
|
|
38
|
+
__version__ = "0.12.0";
|
|
39
39
|
}
|
|
40
40
|
});
|
|
41
41
|
|
|
@@ -290,6 +290,42 @@ var init_http = __esm({
|
|
|
290
290
|
clearTimeout(timeoutId);
|
|
291
291
|
}
|
|
292
292
|
}
|
|
293
|
+
/**
|
|
294
|
+
* Fetch the span tree for a root span.
|
|
295
|
+
* Blocking GET request.
|
|
296
|
+
*/
|
|
297
|
+
async getSpanTree(externalSpanId) {
|
|
298
|
+
const url = `${this.serviceUrl}/api/sdk/replay/spanTree/${externalSpanId}`;
|
|
299
|
+
const controller = new AbortController();
|
|
300
|
+
const timeoutId = setTimeout(() => controller.abort(), 3e4);
|
|
301
|
+
try {
|
|
302
|
+
const response = await fetch(url, {
|
|
303
|
+
method: "GET",
|
|
304
|
+
headers: { Authorization: `Bearer ${this.apiKey}` },
|
|
305
|
+
signal: controller.signal
|
|
306
|
+
});
|
|
307
|
+
if (!response.ok) {
|
|
308
|
+
const errorText = await response.text();
|
|
309
|
+
throw new BitfabError(
|
|
310
|
+
`HTTP ${response.status}: ${errorText.slice(0, 500)}`
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
return await response.json();
|
|
314
|
+
} catch (error) {
|
|
315
|
+
if (error instanceof BitfabError) {
|
|
316
|
+
throw error;
|
|
317
|
+
}
|
|
318
|
+
if (error instanceof Error) {
|
|
319
|
+
if (error.name === "AbortError") {
|
|
320
|
+
throw new BitfabError("Request timed out after 30000ms");
|
|
321
|
+
}
|
|
322
|
+
throw new BitfabError(error.message);
|
|
323
|
+
}
|
|
324
|
+
throw new BitfabError("Unknown error occurred");
|
|
325
|
+
} finally {
|
|
326
|
+
clearTimeout(timeoutId);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
293
329
|
/**
|
|
294
330
|
* Mark a replay test run as completed.
|
|
295
331
|
* Blocking call.
|
|
@@ -424,16 +460,51 @@ function deserializeOutput(spanData) {
|
|
|
424
460
|
}
|
|
425
461
|
return rawOutput;
|
|
426
462
|
}
|
|
427
|
-
|
|
463
|
+
function buildMockTree(rootNode) {
|
|
464
|
+
const spans = /* @__PURE__ */ new Map();
|
|
465
|
+
const counters = /* @__PURE__ */ new Map();
|
|
466
|
+
function walk(node) {
|
|
467
|
+
const key = node.traceFunctionKey;
|
|
468
|
+
if (key) {
|
|
469
|
+
const index = counters.get(key) ?? 0;
|
|
470
|
+
counters.set(key, index + 1);
|
|
471
|
+
spans.set(`${key}:${index}`, {
|
|
472
|
+
sourceSpanId: node.sourceSpanId,
|
|
473
|
+
output: node.output,
|
|
474
|
+
outputMeta: node.outputMeta
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
for (const child of node.children) {
|
|
478
|
+
walk(child);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
for (const child of rootNode.children) {
|
|
482
|
+
walk(child);
|
|
483
|
+
}
|
|
484
|
+
return { spans };
|
|
485
|
+
}
|
|
486
|
+
async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy) {
|
|
428
487
|
const span = await httpClient.getExternalSpan(serverItem.externalSpanId);
|
|
429
488
|
const spanData = span.rawData?.span_data ?? {};
|
|
430
489
|
const inputs = deserializeInputs(spanData);
|
|
431
490
|
const originalOutput = deserializeOutput(spanData);
|
|
491
|
+
let mockTree;
|
|
492
|
+
if (mockStrategy === "all" || mockStrategy === "marked") {
|
|
493
|
+
const treeResponse = await httpClient.getSpanTree(serverItem.externalSpanId);
|
|
494
|
+
mockTree = buildMockTree(treeResponse.root);
|
|
495
|
+
}
|
|
432
496
|
let result;
|
|
433
497
|
let error = null;
|
|
434
498
|
try {
|
|
435
499
|
const maybePromise = runWithReplayContext(
|
|
436
|
-
{
|
|
500
|
+
{
|
|
501
|
+
testRunId,
|
|
502
|
+
inputSourceSpanId: span.id,
|
|
503
|
+
inputSourceTraceId: span.externalTraceId,
|
|
504
|
+
mockTree,
|
|
505
|
+
callCounters: mockTree ? /* @__PURE__ */ new Map() : void 0,
|
|
506
|
+
mockStrategy
|
|
507
|
+
},
|
|
437
508
|
() => fn(...inputs)
|
|
438
509
|
);
|
|
439
510
|
result = maybePromise instanceof Promise ? await maybePromise : maybePromise;
|
|
@@ -479,9 +550,10 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options) {
|
|
|
479
550
|
options?.codeChangeDescription,
|
|
480
551
|
options?.codeChangeFiles
|
|
481
552
|
);
|
|
553
|
+
const mockStrategy = options?.mock ?? "none";
|
|
482
554
|
const maxConcurrency = options?.maxConcurrency ?? 10;
|
|
483
555
|
const tasks = serverItems.map(
|
|
484
|
-
(serverItem) => () => processItem(httpClient, serverItem, fn, testRunId)
|
|
556
|
+
(serverItem) => () => processItem(httpClient, serverItem, fn, testRunId, mockStrategy)
|
|
485
557
|
);
|
|
486
558
|
const resultItems = await mapWithConcurrency(tasks, maxConcurrency);
|
|
487
559
|
await flushTraces();
|
|
@@ -2555,6 +2627,9 @@ var Bitfab = class {
|
|
|
2555
2627
|
contexts: [],
|
|
2556
2628
|
...replayCtxAtRoot?.testRunId && {
|
|
2557
2629
|
testRunId: replayCtxAtRoot.testRunId
|
|
2630
|
+
},
|
|
2631
|
+
...replayCtxAtRoot?.inputSourceTraceId && {
|
|
2632
|
+
inputSourceTraceId: replayCtxAtRoot.inputSourceTraceId
|
|
2558
2633
|
}
|
|
2559
2634
|
});
|
|
2560
2635
|
pendingSpanPromises.set(traceId, []);
|
|
@@ -2603,7 +2678,8 @@ var Bitfab = class {
|
|
|
2603
2678
|
sessionId: traceState?.sessionId,
|
|
2604
2679
|
metadata: traceState?.metadata,
|
|
2605
2680
|
contexts: traceState?.contexts ?? [],
|
|
2606
|
-
testRunId: traceState?.testRunId
|
|
2681
|
+
testRunId: traceState?.testRunId,
|
|
2682
|
+
inputSourceTraceId: traceState?.inputSourceTraceId
|
|
2607
2683
|
});
|
|
2608
2684
|
activeTraceStates.delete(traceId);
|
|
2609
2685
|
} else {
|
|
@@ -2617,6 +2693,28 @@ var Bitfab = class {
|
|
|
2617
2693
|
} catch {
|
|
2618
2694
|
}
|
|
2619
2695
|
};
|
|
2696
|
+
const replayCtxForMock = getReplayContext();
|
|
2697
|
+
if (replayCtxForMock?.mockTree && !isRootSpan) {
|
|
2698
|
+
const counters = replayCtxForMock.callCounters;
|
|
2699
|
+
const callIndex = counters.get(traceFunctionKey) ?? 0;
|
|
2700
|
+
counters.set(traceFunctionKey, callIndex + 1);
|
|
2701
|
+
const shouldMock = replayCtxForMock.mockStrategy === "all" || replayCtxForMock.mockStrategy === "marked" && options.mockOnReplay === true;
|
|
2702
|
+
if (shouldMock) {
|
|
2703
|
+
const mockKey = `${traceFunctionKey}:${callIndex}`;
|
|
2704
|
+
const mockSpan = replayCtxForMock.mockTree.spans.get(mockKey);
|
|
2705
|
+
if (mockSpan) {
|
|
2706
|
+
let output = mockSpan.output;
|
|
2707
|
+
if (mockSpan.outputMeta !== void 0 && mockSpan.outputMeta !== null) {
|
|
2708
|
+
output = deserializeValue({
|
|
2709
|
+
json: mockSpan.output,
|
|
2710
|
+
meta: mockSpan.outputMeta
|
|
2711
|
+
});
|
|
2712
|
+
}
|
|
2713
|
+
void sendSpan({ result: output });
|
|
2714
|
+
return output;
|
|
2715
|
+
}
|
|
2716
|
+
}
|
|
2717
|
+
}
|
|
2620
2718
|
const executeWithContext = () => {
|
|
2621
2719
|
const result = fn(...args);
|
|
2622
2720
|
if (result instanceof Promise) {
|
|
@@ -2680,6 +2778,9 @@ var Bitfab = class {
|
|
|
2680
2778
|
if (params.contexts && params.contexts.length > 0) {
|
|
2681
2779
|
rawTrace.contexts = params.contexts;
|
|
2682
2780
|
}
|
|
2781
|
+
if (params.inputSourceTraceId) {
|
|
2782
|
+
rawTrace.input_source_trace_id = params.inputSourceTraceId;
|
|
2783
|
+
}
|
|
2683
2784
|
this.httpClient.sendExternalTrace({
|
|
2684
2785
|
type: "sdk-function",
|
|
2685
2786
|
source: "typescript-sdk-function",
|