bitfab 0.11.6 → 0.12.1
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-MTHBHBOD.js → chunk-NU52P7HA.js} +29 -3
- package/dist/chunk-NU52P7HA.js.map +1 -0
- package/dist/{chunk-VOSASRED.js → chunk-OOKZ6S64.js} +38 -2
- package/dist/chunk-OOKZ6S64.js.map +1 -0
- package/dist/index.cjs +95 -4
- 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 +95 -4
- 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-DSVTUTGT.js → replay-UQP2XXBZ.js} +35 -5
- package/dist/replay-UQP2XXBZ.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-MTHBHBOD.js.map +0 -1
- package/dist/chunk-VOSASRED.js.map +0 -1
- package/dist/replay-DSVTUTGT.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.1";
|
|
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,11 +460,37 @@ 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
|
+
walk(rootNode);
|
|
482
|
+
return { spans };
|
|
483
|
+
}
|
|
484
|
+
async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy) {
|
|
428
485
|
const span = await httpClient.getExternalSpan(serverItem.externalSpanId);
|
|
429
486
|
const spanData = span.rawData?.span_data ?? {};
|
|
430
487
|
const inputs = deserializeInputs(spanData);
|
|
431
488
|
const originalOutput = deserializeOutput(spanData);
|
|
489
|
+
let mockTree;
|
|
490
|
+
if (mockStrategy === "all" || mockStrategy === "marked") {
|
|
491
|
+
const treeResponse = await httpClient.getSpanTree(serverItem.externalSpanId);
|
|
492
|
+
mockTree = buildMockTree(treeResponse.root);
|
|
493
|
+
}
|
|
432
494
|
let result;
|
|
433
495
|
let error = null;
|
|
434
496
|
try {
|
|
@@ -436,7 +498,10 @@ async function processItem(httpClient, serverItem, fn, testRunId) {
|
|
|
436
498
|
{
|
|
437
499
|
testRunId,
|
|
438
500
|
inputSourceSpanId: span.id,
|
|
439
|
-
inputSourceTraceId: span.externalTraceId
|
|
501
|
+
inputSourceTraceId: span.externalTraceId,
|
|
502
|
+
mockTree,
|
|
503
|
+
callCounters: mockTree ? /* @__PURE__ */ new Map() : void 0,
|
|
504
|
+
mockStrategy
|
|
440
505
|
},
|
|
441
506
|
() => fn(...inputs)
|
|
442
507
|
);
|
|
@@ -483,9 +548,10 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options) {
|
|
|
483
548
|
options?.codeChangeDescription,
|
|
484
549
|
options?.codeChangeFiles
|
|
485
550
|
);
|
|
551
|
+
const mockStrategy = options?.mock ?? "none";
|
|
486
552
|
const maxConcurrency = options?.maxConcurrency ?? 10;
|
|
487
553
|
const tasks = serverItems.map(
|
|
488
|
-
(serverItem) => () => processItem(httpClient, serverItem, fn, testRunId)
|
|
554
|
+
(serverItem) => () => processItem(httpClient, serverItem, fn, testRunId, mockStrategy)
|
|
489
555
|
);
|
|
490
556
|
const resultItems = await mapWithConcurrency(tasks, maxConcurrency);
|
|
491
557
|
await flushTraces();
|
|
@@ -2625,6 +2691,31 @@ var Bitfab = class {
|
|
|
2625
2691
|
} catch {
|
|
2626
2692
|
}
|
|
2627
2693
|
};
|
|
2694
|
+
const replayCtxForMock = getReplayContext();
|
|
2695
|
+
if (replayCtxForMock?.mockTree && !isRootSpan) {
|
|
2696
|
+
const counters = replayCtxForMock.callCounters;
|
|
2697
|
+
const callIndex = counters.get(traceFunctionKey) ?? 0;
|
|
2698
|
+
counters.set(traceFunctionKey, callIndex + 1);
|
|
2699
|
+
const shouldMock = replayCtxForMock.mockStrategy === "all" || replayCtxForMock.mockStrategy === "marked" && options.mockOnReplay === true;
|
|
2700
|
+
if (shouldMock) {
|
|
2701
|
+
const mockKey = `${traceFunctionKey}:${callIndex}`;
|
|
2702
|
+
const mockSpan = replayCtxForMock.mockTree.spans.get(mockKey);
|
|
2703
|
+
if (mockSpan) {
|
|
2704
|
+
let output = mockSpan.output;
|
|
2705
|
+
if (mockSpan.outputMeta !== void 0 && mockSpan.outputMeta !== null) {
|
|
2706
|
+
output = deserializeValue({
|
|
2707
|
+
json: mockSpan.output,
|
|
2708
|
+
meta: mockSpan.outputMeta
|
|
2709
|
+
});
|
|
2710
|
+
}
|
|
2711
|
+
void sendSpan({ result: output });
|
|
2712
|
+
if (fn.constructor.name === "AsyncFunction") {
|
|
2713
|
+
return Promise.resolve(output);
|
|
2714
|
+
}
|
|
2715
|
+
return output;
|
|
2716
|
+
}
|
|
2717
|
+
}
|
|
2718
|
+
}
|
|
2628
2719
|
const executeWithContext = () => {
|
|
2629
2720
|
const result = fn(...args);
|
|
2630
2721
|
if (result instanceof Promise) {
|