bitfab 0.38.3 → 0.38.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -51,7 +51,7 @@ var __version__, __packageName__;
51
51
  var init_version_generated = __esm({
52
52
  "src/version.generated.ts"() {
53
53
  "use strict";
54
- __version__ = "0.38.3";
54
+ __version__ = "0.38.4";
55
55
  __packageName__ = "bitfab";
56
56
  }
57
57
  });
@@ -3797,6 +3797,29 @@ function runWithAutoTraceContext(context, fn, depth = 0) {
3797
3797
  autoTraceState.browserScope = previous;
3798
3798
  }
3799
3799
  }
3800
+ function runWithAutoTraceNodeConfiguration(nodeConfiguration, fn) {
3801
+ const scope = currentAutoTraceScope();
3802
+ if (!scope) {
3803
+ return fn();
3804
+ }
3805
+ const configuredScope = { ...scope, nodeConfiguration };
3806
+ let result;
3807
+ if (autoTraceState.storage) {
3808
+ result = autoTraceState.storage.run(configuredScope, fn);
3809
+ } else {
3810
+ const previous = autoTraceState.browserScope;
3811
+ autoTraceState.browserScope = configuredScope;
3812
+ try {
3813
+ result = fn();
3814
+ } finally {
3815
+ autoTraceState.browserScope = previous;
3816
+ }
3817
+ }
3818
+ if (isAutoTraceAsyncGenerator(result)) {
3819
+ return wrapAutoTraceNodeAsyncGenerator(nodeConfiguration, result);
3820
+ }
3821
+ return result;
3822
+ }
3800
3823
  function runWithAutoTraceRootContext(context, fn) {
3801
3824
  autoTraceState.activeRoots += 1;
3802
3825
  let result;
@@ -3835,6 +3858,29 @@ function wrapAutoTraceAsyncGenerator(context, source) {
3835
3858
  };
3836
3859
  return wrapped;
3837
3860
  }
3861
+ function wrapAutoTraceNodeAsyncGenerator(nodeConfiguration, source) {
3862
+ const step = (method, value) => runWithAutoTraceNodeConfiguration(
3863
+ nodeConfiguration,
3864
+ () => source[method](value)
3865
+ );
3866
+ const wrapped = {
3867
+ next: (value) => step("next", value),
3868
+ return: (value) => step("return", value),
3869
+ throw: (error) => step("throw", error),
3870
+ [Symbol.asyncIterator]: () => wrapped
3871
+ };
3872
+ return wrapped;
3873
+ }
3874
+ function __bitfabAutoTraceActive() {
3875
+ if (autoTraceState.activeRoots === 0) {
3876
+ return false;
3877
+ }
3878
+ return currentAutoTraceScope() !== void 0;
3879
+ }
3880
+ function currentAutoTraceScope() {
3881
+ initializeAutoTraceStorage();
3882
+ return autoTraceState.storage?.getStore() ?? autoTraceState.browserScope;
3883
+ }
3838
3884
  function __setBitfabAutoTraceCapturePolicy(client, traceFunctionKey, functionIds) {
3839
3885
  const policies = autoTraceState.capturePolicies.get(client) ?? /* @__PURE__ */ new Map();
3840
3886
  policies.set(traceFunctionKey, new Set(functionIds));
@@ -5687,6 +5733,102 @@ var Bitfab = class {
5687
5733
  const name = fn.name !== "" ? fn.name : traceFunctionKey;
5688
5734
  return this.createAutoTraceRoot(traceFunctionKey, name, options, fn);
5689
5735
  }
5736
+ /**
5737
+ * Configure a transformed class method when it is discovered beneath a
5738
+ * {@link Bitfab.trace} root.
5739
+ *
5740
+ * The decorator creates no span or trace by itself. Beneath an active trace,
5741
+ * it can rename or retype the discovered call, capture its contents, mark it
5742
+ * for recorded-output replay, finalize its output, or omit it while leaving
5743
+ * captured descendants attached to the nearest captured parent.
5744
+ *
5745
+ * @param options - Trace-owned call configuration.
5746
+ * @experimental Automatic child-call instrumentation is experimental.
5747
+ */
5748
+ node(options = {}) {
5749
+ const configuration = this.resolveNodeConfiguration(options);
5750
+ const decorator = (...args) => {
5751
+ if (args.length === 3) {
5752
+ const descriptor = args[2];
5753
+ if (!descriptor || typeof descriptor.value !== "function") {
5754
+ throw new BitfabError("@bitfab.node can only decorate methods");
5755
+ }
5756
+ if (!this.explicitlyEnabled) {
5757
+ return;
5758
+ }
5759
+ descriptor.value = this.createAutoTraceNode(
5760
+ configuration,
5761
+ descriptor.value,
5762
+ String(args[1])
5763
+ );
5764
+ return;
5765
+ }
5766
+ const method = args[0];
5767
+ const context = args[1];
5768
+ if (typeof method !== "function" || context?.kind !== "method") {
5769
+ throw new BitfabError("@bitfab.node can only decorate methods");
5770
+ }
5771
+ if (!this.explicitlyEnabled) {
5772
+ return method;
5773
+ }
5774
+ return this.createAutoTraceNode(
5775
+ configuration,
5776
+ method,
5777
+ String(context.name)
5778
+ );
5779
+ };
5780
+ return decorator;
5781
+ }
5782
+ withNode(optionsOrFn, maybeFn, internalFunctionName) {
5783
+ const options = typeof optionsOrFn === "function" ? {} : optionsOrFn;
5784
+ const fn = typeof optionsOrFn === "function" ? optionsOrFn : maybeFn;
5785
+ if (!fn) {
5786
+ throw new BitfabError("bitfab.withNode requires a function");
5787
+ }
5788
+ const configuration = this.resolveNodeConfiguration(options);
5789
+ if (!this.explicitlyEnabled) {
5790
+ return fn;
5791
+ }
5792
+ const functionName = internalFunctionName ?? fn.name;
5793
+ if (functionName === "") {
5794
+ throw new BitfabError(
5795
+ "bitfab.withNode requires a named function so the subtree transform can bind its configuration to the correct call."
5796
+ );
5797
+ }
5798
+ return this.createAutoTraceNode(configuration, fn, functionName);
5799
+ }
5800
+ resolveNodeConfiguration(options) {
5801
+ const capture = options.capture ?? true;
5802
+ if (!capture && options.mockOnReplay === true) {
5803
+ throw new BitfabError(
5804
+ "bitfab.node({ capture: false }) cannot use mockOnReplay: true because an uncaptured node has no recorded output."
5805
+ );
5806
+ }
5807
+ return {
5808
+ capture,
5809
+ type: options.type ?? "custom",
5810
+ ...options.name !== void 0 && { name: options.name },
5811
+ ...options.testRunId !== void 0 && {
5812
+ testRunId: options.testRunId
5813
+ },
5814
+ ...options.mockOnReplay !== void 0 && {
5815
+ mockOnReplay: options.mockOnReplay
5816
+ },
5817
+ ...options.finalize !== void 0 && { finalize: options.finalize }
5818
+ };
5819
+ }
5820
+ createAutoTraceNode(configuration, fn, functionName) {
5821
+ const nodeConfiguration = { ...configuration, functionName };
5822
+ return function(...args) {
5823
+ if (!__bitfabAutoTraceActive()) {
5824
+ return fn.apply(this, args);
5825
+ }
5826
+ return runWithAutoTraceNodeConfiguration(
5827
+ nodeConfiguration,
5828
+ () => fn.apply(this, args)
5829
+ );
5830
+ };
5831
+ }
5690
5832
  createAutoTraceRoot(traceFunctionKey, name, options, fn) {
5691
5833
  const self = this;
5692
5834
  const maxDepth = autoTraceLimit(
@@ -5725,29 +5867,51 @@ var Bitfab = class {
5725
5867
  );
5726
5868
  };
5727
5869
  const autoTraceContext = {
5728
- invoke(definition, inputs, invokeFn, depth) {
5870
+ invoke(definition, inputs, invokeFn, depth, nodeConfiguration) {
5729
5871
  const nameParts = definition.name.split(".");
5730
5872
  const simpleName = nameParts[nameParts.length - 1];
5731
- if (excluded.has(definition.name) || simpleName !== void 0 && excluded.has(simpleName) || definition.wrapper === true && !includeWrappers) {
5732
- return invokeFn();
5873
+ const invokeWithoutNode = () => nodeConfiguration === void 0 ? invokeFn() : runWithAutoTraceContext(autoTraceContext, invokeFn, depth);
5874
+ if (excluded.has(definition.name) || simpleName !== void 0 && excluded.has(simpleName) || nodeConfiguration === void 0 && definition.wrapper === true && !includeWrappers) {
5875
+ return invokeWithoutNode();
5876
+ }
5877
+ if (nodeConfiguration?.capture === false) {
5878
+ return runWithAutoTraceContext(autoTraceContext, invokeFn, depth);
5733
5879
  }
5734
5880
  if (depth >= maxDepth || spansUsed >= maxSpans) {
5735
5881
  warnTruncated();
5736
- return invokeFn();
5882
+ return invokeWithoutNode();
5737
5883
  }
5738
5884
  spansUsed += 1;
5739
5885
  const childOptions = {
5740
- name: definition.name,
5741
- type: "function",
5886
+ name: nodeConfiguration?.name ?? definition.name,
5887
+ type: nodeConfiguration?.type ?? "function",
5742
5888
  captureWhen: "nested",
5743
5889
  functionId: definition.id,
5744
- captureContent: capturePolicy.has(definition.id),
5745
- autoTraceDefinition: definition
5890
+ captureContent: nodeConfiguration !== void 0 || capturePolicy.has(definition.id),
5891
+ autoTraceDefinition: definition,
5892
+ ...nodeConfiguration?.testRunId !== void 0 && {
5893
+ testRunId: nodeConfiguration.testRunId
5894
+ },
5895
+ ...nodeConfiguration?.mockOnReplay !== void 0 && {
5896
+ mockOnReplay: nodeConfiguration.mockOnReplay
5897
+ },
5898
+ ...nodeConfiguration?.finalize !== void 0 && {
5899
+ finalize: nodeConfiguration.finalize
5900
+ }
5746
5901
  };
5902
+ const invokeWithAutoTraceContext = () => runWithAutoTraceContext(autoTraceContext, invokeFn, depth + 1);
5903
+ if (definition.async === true) {
5904
+ const tracedAsyncChild = self.withSpan(
5905
+ traceFunctionKey,
5906
+ childOptions,
5907
+ async (..._inputs) => await invokeWithAutoTraceContext()
5908
+ );
5909
+ return tracedAsyncChild(...inputs);
5910
+ }
5747
5911
  const tracedChild = self.withSpan(
5748
5912
  traceFunctionKey,
5749
5913
  childOptions,
5750
- (..._inputs) => runWithAutoTraceContext(autoTraceContext, invokeFn, depth + 1)
5914
+ (..._inputs) => invokeWithAutoTraceContext()
5751
5915
  );
5752
5916
  return tracedChild(...inputs);
5753
5917
  }
@@ -6317,18 +6481,17 @@ var Bitfab = class {
6317
6481
  newStack = [...currentStack, newContext];
6318
6482
  const inputs = args;
6319
6483
  const startedAt = (/* @__PURE__ */ new Date()).toISOString();
6484
+ const replayCtxAtStart = getReplayContext();
6485
+ const testRunId = replayCtxAtStart?.testRunId ?? options.testRunId;
6320
6486
  if (isRootSpan && !activeTraceStates.has(traceId)) {
6321
- const replayCtxAtRoot = getReplayContext();
6322
6487
  const dbSnapshotRef = buildSnapshotRef(self.dbSnapshot, startedAt);
6323
6488
  activeTraceStates.set(traceId, {
6324
6489
  traceId,
6325
6490
  startedAt,
6326
6491
  contexts: [],
6327
- ...replayCtxAtRoot?.testRunId && {
6328
- testRunId: replayCtxAtRoot.testRunId
6329
- },
6330
- ...replayCtxAtRoot?.inputSourceTraceId && {
6331
- inputSourceTraceId: replayCtxAtRoot.inputSourceTraceId
6492
+ ...testRunId !== void 0 && { testRunId },
6493
+ ...replayCtxAtStart?.inputSourceTraceId && {
6494
+ inputSourceTraceId: replayCtxAtStart.inputSourceTraceId
6332
6495
  },
6333
6496
  dbSnapshotRef
6334
6497
  });
@@ -6361,9 +6524,7 @@ var Bitfab = class {
6361
6524
  contexts: newContext.contexts,
6362
6525
  prompt: newContext.prompt,
6363
6526
  endedAt,
6364
- ...replayCtx?.testRunId && {
6365
- testRunId: replayCtx.testRunId
6366
- },
6527
+ ...testRunId !== void 0 && { testRunId },
6367
6528
  ...replayCtx?.inputSourceSpanId && {
6368
6529
  inputSourceSpanId: replayCtx.inputSourceSpanId
6369
6530
  }