@bitfab/sdk 0.38.2 → 0.38.3
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-CWXCVY75.js → chunk-RJPHMJWO.js} +10 -4
- package/dist/chunk-RJPHMJWO.js.map +1 -0
- package/dist/{chunk-SU7EAKOV.js → chunk-WX6AEFCP.js} +7 -2
- package/dist/{chunk-SU7EAKOV.js.map → chunk-WX6AEFCP.js.map} +1 -1
- package/dist/index.cjs +15 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +40 -4
- package/dist/index.d.ts +40 -4
- package/dist/index.js +4 -2
- package/dist/node.cjs +15 -1
- 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 +4 -2
- package/dist/node.js.map +1 -1
- package/dist/{replay-A5UVFNZ3.js → replay-FAO7D7CG.js} +2 -2
- package/dist/replayCli.js +620 -0
- package/dist/replayCli.js.map +1 -0
- package/package.json +6 -2
- package/dist/chunk-CWXCVY75.js.map +0 -1
- /package/dist/{replay-A5UVFNZ3.js.map → replay-FAO7D7CG.js.map} +0 -0
package/dist/node.d.cts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { ActiveSpanContext, AdaptContext, AdaptInputsFn, AllowedEnvVars, BITFAB_PROGRESS_PREFIX, BamlExecutionResult, Bitfab, BitfabClaudeAgentHandler, BitfabConfig, BitfabError, BitfabFunction, BitfabLangChainCallbackHandler, BitfabLangChainCallbackHandler as BitfabLangGraphCallbackHandler, BitfabLanguageModelMiddleware, BitfabOpenAIAgentHandler, BitfabOpenAITracingProcessor, BitfabVercelAiHandler, CaptureWhen, CapturedSpan, CodeChangeFile, CurrentSpan, CurrentTrace, DEFAULT_SERVICE_URL, DbBranchOptions, DbBranchReplayError, DbBranchTimings, DbSnapshotConfig, DbSnapshotProvider, DbSnapshotRef, DetachedTrace, HttpClient, MockOverride, MockOverrideCtx, MockStrategy, MockValue, NodeMatcher, ProviderDefinition, ReplayBranch, ReplayError, ReplayItem, ReplayItemFinishProgress, ReplayItemStartProgress, ReplayOptions, ReplayProgress, ReplayProgressItem, ReplayResult, SUPPORTED_PROVIDERS, SpanLookup, SpanMethodDecorator, SpanMethodDecoratorContext, SpanNodeMeta, SpanOccurrence, SpanOptions, SpanType, TokenUsage, TraceResponse, TracingProcessor, VercelCallParams, VercelGenerateResult, VercelStreamResult, WrapBAMLOptions, WrappedBamlFn, __version__, finalizers, flushTraces, getCurrentReplayBranch, getCurrentSpan, getCurrentTrace, reportReplayProgress, serializeReplayResult } from './index.cjs';
|
|
1
|
+
export { ActiveSpanContext, AdaptContext, AdaptInputsFn, AllowedEnvVars, BITFAB_PROGRESS_PREFIX, BamlExecutionResult, Bitfab, BitfabClaudeAgentHandler, BitfabConfig, BitfabError, BitfabFunction, BitfabLangChainCallbackHandler, BitfabLangChainCallbackHandler as BitfabLangGraphCallbackHandler, BitfabLanguageModelMiddleware, BitfabOpenAIAgentHandler, BitfabOpenAITracingProcessor, BitfabVercelAiHandler, CaptureWhen, CapturedSpan, CodeChangeFile, CurrentSpan, CurrentTrace, DEFAULT_SERVICE_URL, DbBranchOptions, DbBranchReplayError, DbBranchTimings, DbSnapshotConfig, DbSnapshotProvider, DbSnapshotRef, DetachedTrace, HttpClient, MockOverride, MockOverrideCtx, MockStrategy, MockValue, NodeMatcher, ProviderDefinition, ReplayBranch, ReplayError, ReplayItem, ReplayItemFinishProgress, ReplayItemStartProgress, ReplayOptions, ReplayOptionsFactory, ReplayProgress, ReplayProgressItem, ReplayRegistration, ReplayRegistry, ReplayRegistryContext, ReplayRegistryOptions, ReplayResult, SUPPORTED_PROVIDERS, SpanLookup, SpanMethodDecorator, SpanMethodDecoratorContext, SpanNodeMeta, SpanOccurrence, SpanOptions, SpanType, TokenUsage, TraceResponse, TracingProcessor, VercelCallParams, VercelGenerateResult, VercelStreamResult, WrapBAMLOptions, WrappedBamlFn, __version__, defineReplayRegistry, finalizers, flushTraces, getCurrentReplayBranch, getCurrentSpan, getCurrentTrace, reportReplayProgress, serializeReplayResult } from './index.cjs';
|
package/dist/node.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { ActiveSpanContext, AdaptContext, AdaptInputsFn, AllowedEnvVars, BITFAB_PROGRESS_PREFIX, BamlExecutionResult, Bitfab, BitfabClaudeAgentHandler, BitfabConfig, BitfabError, BitfabFunction, BitfabLangChainCallbackHandler, BitfabLangChainCallbackHandler as BitfabLangGraphCallbackHandler, BitfabLanguageModelMiddleware, BitfabOpenAIAgentHandler, BitfabOpenAITracingProcessor, BitfabVercelAiHandler, CaptureWhen, CapturedSpan, CodeChangeFile, CurrentSpan, CurrentTrace, DEFAULT_SERVICE_URL, DbBranchOptions, DbBranchReplayError, DbBranchTimings, DbSnapshotConfig, DbSnapshotProvider, DbSnapshotRef, DetachedTrace, HttpClient, MockOverride, MockOverrideCtx, MockStrategy, MockValue, NodeMatcher, ProviderDefinition, ReplayBranch, ReplayError, ReplayItem, ReplayItemFinishProgress, ReplayItemStartProgress, ReplayOptions, ReplayProgress, ReplayProgressItem, ReplayResult, SUPPORTED_PROVIDERS, SpanLookup, SpanMethodDecorator, SpanMethodDecoratorContext, SpanNodeMeta, SpanOccurrence, SpanOptions, SpanType, TokenUsage, TraceResponse, TracingProcessor, VercelCallParams, VercelGenerateResult, VercelStreamResult, WrapBAMLOptions, WrappedBamlFn, __version__, finalizers, flushTraces, getCurrentReplayBranch, getCurrentSpan, getCurrentTrace, reportReplayProgress, serializeReplayResult } from './index.js';
|
|
1
|
+
export { ActiveSpanContext, AdaptContext, AdaptInputsFn, AllowedEnvVars, BITFAB_PROGRESS_PREFIX, BamlExecutionResult, Bitfab, BitfabClaudeAgentHandler, BitfabConfig, BitfabError, BitfabFunction, BitfabLangChainCallbackHandler, BitfabLangChainCallbackHandler as BitfabLangGraphCallbackHandler, BitfabLanguageModelMiddleware, BitfabOpenAIAgentHandler, BitfabOpenAITracingProcessor, BitfabVercelAiHandler, CaptureWhen, CapturedSpan, CodeChangeFile, CurrentSpan, CurrentTrace, DEFAULT_SERVICE_URL, DbBranchOptions, DbBranchReplayError, DbBranchTimings, DbSnapshotConfig, DbSnapshotProvider, DbSnapshotRef, DetachedTrace, HttpClient, MockOverride, MockOverrideCtx, MockStrategy, MockValue, NodeMatcher, ProviderDefinition, ReplayBranch, ReplayError, ReplayItem, ReplayItemFinishProgress, ReplayItemStartProgress, ReplayOptions, ReplayOptionsFactory, ReplayProgress, ReplayProgressItem, ReplayRegistration, ReplayRegistry, ReplayRegistryContext, ReplayRegistryOptions, ReplayResult, SUPPORTED_PROVIDERS, SpanLookup, SpanMethodDecorator, SpanMethodDecoratorContext, SpanNodeMeta, SpanOccurrence, SpanOptions, SpanType, TokenUsage, TraceResponse, TracingProcessor, VercelCallParams, VercelGenerateResult, VercelStreamResult, WrapBAMLOptions, WrappedBamlFn, __version__, defineReplayRegistry, finalizers, flushTraces, getCurrentReplayBranch, getCurrentSpan, getCurrentTrace, reportReplayProgress, serializeReplayResult } from './index.js';
|
package/dist/node.js
CHANGED
|
@@ -7,11 +7,12 @@ import {
|
|
|
7
7
|
BitfabOpenAITracingProcessor,
|
|
8
8
|
BitfabVercelAiHandler,
|
|
9
9
|
SUPPORTED_PROVIDERS,
|
|
10
|
+
defineReplayRegistry,
|
|
10
11
|
finalizers,
|
|
11
12
|
getCurrentReplayBranch,
|
|
12
13
|
getCurrentSpan,
|
|
13
14
|
getCurrentTrace
|
|
14
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-RJPHMJWO.js";
|
|
15
16
|
import "./chunk-GFBQ2AMO.js";
|
|
16
17
|
import {
|
|
17
18
|
BITFAB_PROGRESS_PREFIX,
|
|
@@ -24,7 +25,7 @@ import {
|
|
|
24
25
|
flushTraces,
|
|
25
26
|
reportReplayProgress,
|
|
26
27
|
serializeReplayResult
|
|
27
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-WX6AEFCP.js";
|
|
28
29
|
import {
|
|
29
30
|
assertAsyncStorageRegistered,
|
|
30
31
|
registerAsyncLocalStorageClass
|
|
@@ -55,6 +56,7 @@ export {
|
|
|
55
56
|
ReplayError,
|
|
56
57
|
SUPPORTED_PROVIDERS,
|
|
57
58
|
__version__,
|
|
59
|
+
defineReplayRegistry,
|
|
58
60
|
finalizers,
|
|
59
61
|
flushTraces,
|
|
60
62
|
getCurrentReplayBranch,
|
package/dist/node.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/asyncStorageNode.ts","../src/node.ts"],"sourcesContent":["/**\n * Synchronous AsyncLocalStorage registration for Node.js.\n *\n * This module is a side-effect-only import: it registers the Node.js\n * AsyncLocalStorage class into the shared registry so span nesting\n * works immediately - no async gap, no microtask delay.\n *\n * It is imported by `node.ts` (the Node.js-specific entry point) as\n * the FIRST import, before `index.ts` or `client.ts` are evaluated.\n *\n * This file must ONLY be imported in Node.js environments (not browsers).\n * It uses a static `import` of `node:async_hooks`, which will fail in\n * browser bundlers. The `node.ts` entry point is conditionally selected\n * via package.json `exports` conditions, so browsers never see this file.\n */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\"\nimport type { AsyncLocalStorageLike } from \"./asyncStorage.js\"\nimport { registerAsyncLocalStorageClass } from \"./asyncStorage.js\"\n\nregisterAsyncLocalStorageClass(\n AsyncLocalStorage as unknown as new () => AsyncLocalStorageLike<unknown>,\n)\n","/**\n * Node.js-specific entry point for the Bitfab SDK.\n *\n * Selected automatically via package.json `exports` conditions when the\n * consumer's runtime or bundler supports the \"node\" condition (Node.js,\n * most server-side bundlers).\n *\n * This entry point differs from the default (`index.ts`) in one way:\n * it synchronously registers Node.js's `AsyncLocalStorage` before any\n * other SDK code evaluates. This eliminates the async initialization\n * gap that the default entry point has (where the first span might\n * execute before the dynamic import of `node:async_hooks` resolves).\n *\n * The default entry point (`index.ts`) is used for browsers and other\n * environments where `node:async_hooks` is unavailable. There, span\n * nesting degrades gracefully to a shared stack (correct for sequential\n * async, but not for concurrent Promise.all patterns).\n */\n\n// ⚠️ IMPORT ORDER MATTERS\n// asyncStorageNode MUST be imported before index.js.\n// It registers the AsyncLocalStorage class synchronously during module\n// evaluation. index.js (via client.ts) reads from that registration at\n// span creation time. If this import is moved after index.js or removed,\n// span nesting silently degrades to the browser fallback (flat spans).\nimport \"./asyncStorageNode.js\"\n\nexport * from \"./index.js\"\n\n// Verify registration succeeded. This turns a silent degradation into a\n// loud error if someone reorders the imports above or if asyncStorageNode.ts\n// fails to register for any reason. Only runs in the Node.js entry point\n// where we know node:async_hooks must be available.\nimport { assertAsyncStorageRegistered } from \"./asyncStorage.js\"\n\nassertAsyncStorageRegistered()\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/asyncStorageNode.ts","../src/node.ts"],"sourcesContent":["/**\n * Synchronous AsyncLocalStorage registration for Node.js.\n *\n * This module is a side-effect-only import: it registers the Node.js\n * AsyncLocalStorage class into the shared registry so span nesting\n * works immediately - no async gap, no microtask delay.\n *\n * It is imported by `node.ts` (the Node.js-specific entry point) as\n * the FIRST import, before `index.ts` or `client.ts` are evaluated.\n *\n * This file must ONLY be imported in Node.js environments (not browsers).\n * It uses a static `import` of `node:async_hooks`, which will fail in\n * browser bundlers. The `node.ts` entry point is conditionally selected\n * via package.json `exports` conditions, so browsers never see this file.\n */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\"\nimport type { AsyncLocalStorageLike } from \"./asyncStorage.js\"\nimport { registerAsyncLocalStorageClass } from \"./asyncStorage.js\"\n\nregisterAsyncLocalStorageClass(\n AsyncLocalStorage as unknown as new () => AsyncLocalStorageLike<unknown>,\n)\n","/**\n * Node.js-specific entry point for the Bitfab SDK.\n *\n * Selected automatically via package.json `exports` conditions when the\n * consumer's runtime or bundler supports the \"node\" condition (Node.js,\n * most server-side bundlers).\n *\n * This entry point differs from the default (`index.ts`) in one way:\n * it synchronously registers Node.js's `AsyncLocalStorage` before any\n * other SDK code evaluates. This eliminates the async initialization\n * gap that the default entry point has (where the first span might\n * execute before the dynamic import of `node:async_hooks` resolves).\n *\n * The default entry point (`index.ts`) is used for browsers and other\n * environments where `node:async_hooks` is unavailable. There, span\n * nesting degrades gracefully to a shared stack (correct for sequential\n * async, but not for concurrent Promise.all patterns).\n */\n\n// ⚠️ IMPORT ORDER MATTERS\n// asyncStorageNode MUST be imported before index.js.\n// It registers the AsyncLocalStorage class synchronously during module\n// evaluation. index.js (via client.ts) reads from that registration at\n// span creation time. If this import is moved after index.js or removed,\n// span nesting silently degrades to the browser fallback (flat spans).\nimport \"./asyncStorageNode.js\"\n\nexport * from \"./index.js\"\n\n// Verify registration succeeded. This turns a silent degradation into a\n// loud error if someone reorders the imports above or if asyncStorageNode.ts\n// fails to register for any reason. Only runs in the Node.js entry point\n// where we know node:async_hooks must be available.\nimport { assertAsyncStorageRegistered } from \"./asyncStorage.js\"\n\nassertAsyncStorageRegistered()\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgBA,SAAS,yBAAyB;AAIlC;AAAA,EACE;AACF;;;ACaA,6BAA6B;","names":[]}
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
serializeReplayResult,
|
|
8
8
|
sleepForReplayPersistence,
|
|
9
9
|
waitForReplayPersistence
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-WX6AEFCP.js";
|
|
11
11
|
import "./chunk-H6LZRFMN.js";
|
|
12
12
|
export {
|
|
13
13
|
BITFAB_PROGRESS_PREFIX,
|
|
@@ -19,4 +19,4 @@ export {
|
|
|
19
19
|
sleepForReplayPersistence,
|
|
20
20
|
waitForReplayPersistence
|
|
21
21
|
};
|
|
22
|
-
//# sourceMappingURL=replay-
|
|
22
|
+
//# sourceMappingURL=replay-FAO7D7CG.js.map
|
|
@@ -0,0 +1,620 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/replayCli.ts
|
|
4
|
+
import { tsImport } from "tsx/esm/api";
|
|
5
|
+
|
|
6
|
+
// src/errors.ts
|
|
7
|
+
var BitfabError = class extends Error {
|
|
8
|
+
constructor(message, url, status, retryAfterMs) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.url = url;
|
|
11
|
+
this.status = status;
|
|
12
|
+
this.retryAfterMs = retryAfterMs;
|
|
13
|
+
this.name = "BitfabError";
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// src/codeChange.ts
|
|
18
|
+
var NUL = String.fromCharCode(0);
|
|
19
|
+
|
|
20
|
+
// src/compress.ts
|
|
21
|
+
var gzipNode;
|
|
22
|
+
var _nodeGzipReady = (typeof process !== "undefined" && process.versions?.node ? (
|
|
23
|
+
// The join trick hides "node:zlib" from static analysis so bundlers that
|
|
24
|
+
// ban Node.js built-ins don't fail at build time. webpackIgnore tells
|
|
25
|
+
// webpack/turbopack to emit a native import() so Node.js can resolve the
|
|
26
|
+
// module at runtime. Same pattern as `asyncStorage.ts`.
|
|
27
|
+
import(
|
|
28
|
+
/* webpackIgnore: true */
|
|
29
|
+
["node", "zlib"].join(":")
|
|
30
|
+
).then(({ gzip }) => {
|
|
31
|
+
gzipNode = (data) => new Promise((resolve, reject) => {
|
|
32
|
+
gzip(data, (error, result) => {
|
|
33
|
+
if (error) {
|
|
34
|
+
reject(error);
|
|
35
|
+
} else {
|
|
36
|
+
resolve(result);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
}).catch(() => {
|
|
41
|
+
})
|
|
42
|
+
) : Promise.resolve()).then(() => {
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// src/asyncStorage.ts
|
|
46
|
+
var AsyncLocalStorageClass = null;
|
|
47
|
+
var initDone = false;
|
|
48
|
+
function registerAsyncLocalStorageClass(cls) {
|
|
49
|
+
if (!AsyncLocalStorageClass) {
|
|
50
|
+
AsyncLocalStorageClass = cls;
|
|
51
|
+
}
|
|
52
|
+
initDone = true;
|
|
53
|
+
}
|
|
54
|
+
var asyncStorageReady = (typeof process !== "undefined" && process.versions?.node ? (
|
|
55
|
+
// The join trick hides "node:async_hooks" from static analysis so
|
|
56
|
+
// bundlers that ban Node.js built-ins don't fail at build time.
|
|
57
|
+
// webpackIgnore tells webpack/turbopack to emit a native import()
|
|
58
|
+
// so Node.js can resolve the module at runtime.
|
|
59
|
+
import(
|
|
60
|
+
/* webpackIgnore: true */
|
|
61
|
+
["node", "async_hooks"].join(":")
|
|
62
|
+
).then(
|
|
63
|
+
(mod) => {
|
|
64
|
+
registerAsyncLocalStorageClass(mod.AsyncLocalStorage);
|
|
65
|
+
}
|
|
66
|
+
).catch(() => {
|
|
67
|
+
})
|
|
68
|
+
) : Promise.resolve()).then(() => {
|
|
69
|
+
initDone = true;
|
|
70
|
+
});
|
|
71
|
+
function createAsyncLocalStorage() {
|
|
72
|
+
return AsyncLocalStorageClass ? new AsyncLocalStorageClass() : null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// src/replayContext.ts
|
|
76
|
+
var replayContextStorage = null;
|
|
77
|
+
var REPLAY_CONTEXT_STORAGE_SYMBOL = /* @__PURE__ */ Symbol.for("bitfab.replayContextStorage");
|
|
78
|
+
var replayContextReady = asyncStorageReady.then(() => {
|
|
79
|
+
const shared = globalThis;
|
|
80
|
+
const existing = shared[REPLAY_CONTEXT_STORAGE_SYMBOL];
|
|
81
|
+
if (existing) {
|
|
82
|
+
replayContextStorage = existing;
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const created = createAsyncLocalStorage();
|
|
86
|
+
if (created) {
|
|
87
|
+
shared[REPLAY_CONTEXT_STORAGE_SYMBOL] = created;
|
|
88
|
+
replayContextStorage = created;
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// src/payloadBudget.ts
|
|
93
|
+
var textEncoder = typeof TextEncoder !== "undefined" ? new TextEncoder() : null;
|
|
94
|
+
|
|
95
|
+
// src/otel.ts
|
|
96
|
+
import { SpanStatusCode } from "@opentelemetry/api";
|
|
97
|
+
import {
|
|
98
|
+
ExportResultCode
|
|
99
|
+
} from "@opentelemetry/core";
|
|
100
|
+
import { resourceFromAttributes } from "@opentelemetry/resources";
|
|
101
|
+
import {
|
|
102
|
+
AlwaysOnSampler,
|
|
103
|
+
BasicTracerProvider,
|
|
104
|
+
BatchSpanProcessor
|
|
105
|
+
} from "@opentelemetry/sdk-trace-base";
|
|
106
|
+
var DEFAULT_LIFECYCLE_TIMEOUT_MS = 3e4;
|
|
107
|
+
var liveTransports = /* @__PURE__ */ new Set();
|
|
108
|
+
async function forEachLiveTransport(timeoutMs, run) {
|
|
109
|
+
const deadline = Date.now() + Math.max(timeoutMs, 0);
|
|
110
|
+
let succeeded = true;
|
|
111
|
+
for (const transport of [...liveTransports]) {
|
|
112
|
+
succeeded = await run(transport, Math.max(0, deadline - Date.now())) && succeeded;
|
|
113
|
+
}
|
|
114
|
+
return succeeded;
|
|
115
|
+
}
|
|
116
|
+
function shutdownOtelTransports(timeoutMs = DEFAULT_LIFECYCLE_TIMEOUT_MS) {
|
|
117
|
+
return forEachLiveTransport(
|
|
118
|
+
timeoutMs,
|
|
119
|
+
(transport, remaining) => transport.shutdown(remaining)
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// src/transport.ts
|
|
124
|
+
function shutdownTraceTransports(timeoutMs) {
|
|
125
|
+
return shutdownOtelTransports(timeoutMs);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// src/http.ts
|
|
129
|
+
var EXIT_FLUSH_TIMEOUT_MS = 5e3;
|
|
130
|
+
var pendingTracePromises = /* @__PURE__ */ new Set();
|
|
131
|
+
if (typeof process !== "undefined" && process.versions != null && process.versions.node != null) {
|
|
132
|
+
let isFlushing = false;
|
|
133
|
+
process.on("beforeExit", () => {
|
|
134
|
+
if (isFlushing) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
isFlushing = true;
|
|
138
|
+
void Promise.allSettled([
|
|
139
|
+
...Array.from(pendingTracePromises).map((p) => p.catch(() => {
|
|
140
|
+
})),
|
|
141
|
+
shutdownTraceTransports(EXIT_FLUSH_TIMEOUT_MS).catch(() => false)
|
|
142
|
+
]).then(() => {
|
|
143
|
+
isFlushing = false;
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// src/serialize.ts
|
|
149
|
+
import superjson from "superjson";
|
|
150
|
+
|
|
151
|
+
// src/replay.ts
|
|
152
|
+
var BITFAB_PROGRESS_PREFIX = "@@bitfab:progress ";
|
|
153
|
+
function reportReplayProgress(progress) {
|
|
154
|
+
const stderr = typeof process !== "undefined" ? process.stderr : void 0;
|
|
155
|
+
if (!stderr) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
stderr.write(
|
|
160
|
+
`${BITFAB_PROGRESS_PREFIX}${JSON.stringify(progress, replayJsonReplacer)}
|
|
161
|
+
`
|
|
162
|
+
);
|
|
163
|
+
} catch {
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
var ReplayError = class extends BitfabError {
|
|
167
|
+
constructor(message, items, testRunId, testRunUrl, cause) {
|
|
168
|
+
super(message, testRunUrl);
|
|
169
|
+
this.items = items;
|
|
170
|
+
this.testRunId = testRunId;
|
|
171
|
+
this.testRunUrl = testRunUrl;
|
|
172
|
+
this.cause = cause;
|
|
173
|
+
this.name = "ReplayError";
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
var DbBranchReplayError = class extends BitfabError {
|
|
177
|
+
constructor(code, message, originalTraceId, cause) {
|
|
178
|
+
super(message);
|
|
179
|
+
this.code = code;
|
|
180
|
+
this.originalTraceId = originalTraceId;
|
|
181
|
+
this.cause = cause;
|
|
182
|
+
this.name = "DbBranchReplayError";
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
function replayJsonReplacer(_key, value) {
|
|
186
|
+
if (value instanceof Error) {
|
|
187
|
+
const serialized = {
|
|
188
|
+
name: value.name,
|
|
189
|
+
message: value.message,
|
|
190
|
+
stack: value.stack
|
|
191
|
+
};
|
|
192
|
+
if (value instanceof DbBranchReplayError) {
|
|
193
|
+
serialized.code = value.code;
|
|
194
|
+
serialized.originalTraceId = value.originalTraceId;
|
|
195
|
+
if (value.cause !== void 0) {
|
|
196
|
+
serialized.cause = value.cause;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return serialized;
|
|
200
|
+
}
|
|
201
|
+
return value;
|
|
202
|
+
}
|
|
203
|
+
function serializeReplayResult(result) {
|
|
204
|
+
return JSON.stringify(result, replayJsonReplacer, 2);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// src/replayRegistry.ts
|
|
208
|
+
var VALUE_FLAGS = /* @__PURE__ */ new Set([
|
|
209
|
+
"--limit",
|
|
210
|
+
"--trace-ids",
|
|
211
|
+
"--name",
|
|
212
|
+
"--concurrency",
|
|
213
|
+
"--max-concurrency",
|
|
214
|
+
"--code-change",
|
|
215
|
+
"--experiment-group-id",
|
|
216
|
+
"--dataset-id",
|
|
217
|
+
"--grader-ids",
|
|
218
|
+
"--mock",
|
|
219
|
+
"--param",
|
|
220
|
+
"--params"
|
|
221
|
+
]);
|
|
222
|
+
var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
223
|
+
"--db-branch",
|
|
224
|
+
"--no-db-branch",
|
|
225
|
+
"--no-code-change"
|
|
226
|
+
]);
|
|
227
|
+
var HELP_FLAGS = /* @__PURE__ */ new Set(["--help", "-h"]);
|
|
228
|
+
function usage(registry) {
|
|
229
|
+
return `Usage: bitfab-replay --registry <path> <${Object.keys(registry).join("|")}> [options]
|
|
230
|
+
|
|
231
|
+
Options:
|
|
232
|
+
--limit N
|
|
233
|
+
--trace-ids id1,id2
|
|
234
|
+
--name NAME
|
|
235
|
+
--concurrency N, --max-concurrency N
|
|
236
|
+
--code-change PATH, --no-code-change
|
|
237
|
+
--experiment-group-id UUID
|
|
238
|
+
--dataset-id UUID
|
|
239
|
+
--grader-ids id1,id2
|
|
240
|
+
--mock none|all|marked
|
|
241
|
+
--db-branch, --no-db-branch
|
|
242
|
+
--params PATH
|
|
243
|
+
--param name=value (repeatable)
|
|
244
|
+
-h, --help`;
|
|
245
|
+
}
|
|
246
|
+
var ReplayCliHelp = class extends Error {
|
|
247
|
+
};
|
|
248
|
+
function requirePositiveInteger(flag, raw) {
|
|
249
|
+
const value = Number(raw);
|
|
250
|
+
if (!Number.isInteger(value) || value < 1) {
|
|
251
|
+
throw new BitfabError(
|
|
252
|
+
`${flag} must be a positive integer (received '${raw}').`
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
return value;
|
|
256
|
+
}
|
|
257
|
+
function commaSeparated(flag, raw) {
|
|
258
|
+
const values = raw.split(",").map((value) => value.trim()).filter((value) => value.length > 0);
|
|
259
|
+
if (values.length === 0) {
|
|
260
|
+
throw new BitfabError(`${flag} must contain at least one value.`);
|
|
261
|
+
}
|
|
262
|
+
return values;
|
|
263
|
+
}
|
|
264
|
+
function parseReplayCliArgs(registry, argv) {
|
|
265
|
+
if (argv.some((value) => HELP_FLAGS.has(value))) {
|
|
266
|
+
throw new ReplayCliHelp(usage(registry));
|
|
267
|
+
}
|
|
268
|
+
const pipeline = argv[0];
|
|
269
|
+
if (pipeline === void 0 || registry[pipeline] === void 0) {
|
|
270
|
+
throw new BitfabError(usage(registry));
|
|
271
|
+
}
|
|
272
|
+
const parsed = { pipeline, params: [] };
|
|
273
|
+
for (let index = 1; index < argv.length; index += 1) {
|
|
274
|
+
const flag = argv[index];
|
|
275
|
+
if (BOOLEAN_FLAGS.has(flag)) {
|
|
276
|
+
switch (flag) {
|
|
277
|
+
case "--db-branch":
|
|
278
|
+
if (parsed.dbBranch === false) {
|
|
279
|
+
throw new BitfabError(
|
|
280
|
+
"--db-branch and --no-db-branch cannot be used together."
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
parsed.dbBranch = true;
|
|
284
|
+
break;
|
|
285
|
+
case "--no-db-branch":
|
|
286
|
+
if (parsed.dbBranch === true) {
|
|
287
|
+
throw new BitfabError(
|
|
288
|
+
"--db-branch and --no-db-branch cannot be used together."
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
parsed.dbBranch = false;
|
|
292
|
+
break;
|
|
293
|
+
case "--no-code-change":
|
|
294
|
+
parsed.noCodeChange = true;
|
|
295
|
+
break;
|
|
296
|
+
}
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
if (!VALUE_FLAGS.has(flag)) {
|
|
300
|
+
throw new BitfabError(
|
|
301
|
+
`Unknown replay option '${flag}'.
|
|
302
|
+
${usage(registry)}`
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
const raw = argv[index + 1];
|
|
306
|
+
if (raw === void 0 || raw.startsWith("--")) {
|
|
307
|
+
throw new BitfabError(`${flag} requires a value.`);
|
|
308
|
+
}
|
|
309
|
+
index += 1;
|
|
310
|
+
switch (flag) {
|
|
311
|
+
case "--limit":
|
|
312
|
+
parsed.limit = requirePositiveInteger(flag, raw);
|
|
313
|
+
break;
|
|
314
|
+
case "--trace-ids":
|
|
315
|
+
parsed.traceIds = commaSeparated(flag, raw);
|
|
316
|
+
break;
|
|
317
|
+
case "--name":
|
|
318
|
+
parsed.name = raw;
|
|
319
|
+
break;
|
|
320
|
+
case "--concurrency":
|
|
321
|
+
case "--max-concurrency":
|
|
322
|
+
parsed.maxConcurrency = requirePositiveInteger(flag, raw);
|
|
323
|
+
break;
|
|
324
|
+
case "--code-change":
|
|
325
|
+
parsed.codeChangePath = raw;
|
|
326
|
+
break;
|
|
327
|
+
case "--experiment-group-id":
|
|
328
|
+
parsed.experimentGroupId = raw;
|
|
329
|
+
break;
|
|
330
|
+
case "--dataset-id":
|
|
331
|
+
parsed.datasetId = raw;
|
|
332
|
+
break;
|
|
333
|
+
case "--grader-ids":
|
|
334
|
+
parsed.graderIds = commaSeparated(flag, raw);
|
|
335
|
+
break;
|
|
336
|
+
case "--mock":
|
|
337
|
+
if (raw !== "none" && raw !== "all" && raw !== "marked") {
|
|
338
|
+
throw new BitfabError(
|
|
339
|
+
`--mock must be one of: none, all, marked (received '${raw}').`
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
parsed.mock = raw;
|
|
343
|
+
break;
|
|
344
|
+
case "--params":
|
|
345
|
+
parsed.paramsPath = raw;
|
|
346
|
+
break;
|
|
347
|
+
case "--param":
|
|
348
|
+
parsed.params.push(raw);
|
|
349
|
+
break;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
if (parsed.traceIds !== void 0 && parsed.datasetId !== void 0) {
|
|
353
|
+
throw new BitfabError(
|
|
354
|
+
"--trace-ids and --dataset-id select different replay sources and cannot be used together."
|
|
355
|
+
);
|
|
356
|
+
}
|
|
357
|
+
if (parsed.codeChangePath !== void 0 && parsed.noCodeChange === true) {
|
|
358
|
+
throw new BitfabError(
|
|
359
|
+
"--code-change and --no-code-change cannot be used together."
|
|
360
|
+
);
|
|
361
|
+
}
|
|
362
|
+
return parsed;
|
|
363
|
+
}
|
|
364
|
+
function resolveTraceFunctionKey(registration) {
|
|
365
|
+
const wrappedKey = registration.fn._bitfabTraceFunctionKey;
|
|
366
|
+
const key = registration.traceFunctionKey ?? wrappedKey;
|
|
367
|
+
if (key === void 0) {
|
|
368
|
+
throw new BitfabError(
|
|
369
|
+
"Replay registry entry uses a plain function. Set traceFunctionKey to the key its production handler records."
|
|
370
|
+
);
|
|
371
|
+
}
|
|
372
|
+
return key;
|
|
373
|
+
}
|
|
374
|
+
async function defaultReadFile(path) {
|
|
375
|
+
const fs = await import("fs/promises").catch(() => null);
|
|
376
|
+
if (fs === null) {
|
|
377
|
+
throw new BitfabError(
|
|
378
|
+
"--code-change requires a runtime that can read local files."
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
return fs.readFile(path, "utf8");
|
|
382
|
+
}
|
|
383
|
+
async function loadCodeChange(path, readFile) {
|
|
384
|
+
if (path === void 0) {
|
|
385
|
+
return void 0;
|
|
386
|
+
}
|
|
387
|
+
const value = JSON.parse(await readFile(path));
|
|
388
|
+
if (typeof value.description !== "string" || !Array.isArray(value.files)) {
|
|
389
|
+
throw new BitfabError(
|
|
390
|
+
`Invalid --code-change file '${path}': expected { description, files }.`
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
return { description: value.description, files: value.files };
|
|
394
|
+
}
|
|
395
|
+
function parseParameter(raw) {
|
|
396
|
+
const separator = raw.indexOf("=");
|
|
397
|
+
const key = raw.slice(0, separator).trim();
|
|
398
|
+
if (separator < 1 || key.length === 0) {
|
|
399
|
+
throw new BitfabError(
|
|
400
|
+
`Invalid --param '${raw}': expected a non-empty name=value pair.`
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
const value = raw.slice(separator + 1);
|
|
404
|
+
try {
|
|
405
|
+
return [key, JSON.parse(value)];
|
|
406
|
+
} catch {
|
|
407
|
+
return [key, value];
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
async function loadParameters(path, rawParameters, readFile) {
|
|
411
|
+
let params = {};
|
|
412
|
+
if (path !== void 0) {
|
|
413
|
+
const value = JSON.parse(await readFile(path));
|
|
414
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
415
|
+
throw new BitfabError(
|
|
416
|
+
`Invalid --params file '${path}': expected a JSON object.`
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
params = { ...value };
|
|
420
|
+
}
|
|
421
|
+
for (const raw of rawParameters) {
|
|
422
|
+
const [key, value] = parseParameter(raw);
|
|
423
|
+
params[key] = value;
|
|
424
|
+
}
|
|
425
|
+
return params;
|
|
426
|
+
}
|
|
427
|
+
function valuesEqual(left, right) {
|
|
428
|
+
try {
|
|
429
|
+
return JSON.stringify(left) === JSON.stringify(right);
|
|
430
|
+
} catch {
|
|
431
|
+
return Object.is(left, right);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
function renderSummary(pipeline, result, stderr) {
|
|
435
|
+
let same = 0;
|
|
436
|
+
let changed = 0;
|
|
437
|
+
let errors = 0;
|
|
438
|
+
for (const item of result.items) {
|
|
439
|
+
if (item.error !== null) {
|
|
440
|
+
errors += 1;
|
|
441
|
+
} else if (valuesEqual(item.result, item.originalOutput)) {
|
|
442
|
+
same += 1;
|
|
443
|
+
} else {
|
|
444
|
+
changed += 1;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
stderr("\n\u2500\u2500\u2500 Summary \u2500\u2500\u2500");
|
|
448
|
+
stderr(` Pipeline: ${pipeline}`);
|
|
449
|
+
stderr(` Replayed: ${result.items.length}`);
|
|
450
|
+
stderr(` Same: ${same}`);
|
|
451
|
+
stderr(` Changed: ${changed}`);
|
|
452
|
+
if (errors > 0) {
|
|
453
|
+
stderr(` Errors: ${errors}`);
|
|
454
|
+
}
|
|
455
|
+
stderr(`
|
|
456
|
+
${result.testRunUrl}`);
|
|
457
|
+
}
|
|
458
|
+
function reportReplayError(error, stderr) {
|
|
459
|
+
for (const item of error.items) {
|
|
460
|
+
stderr(
|
|
461
|
+
`${item.originalTraceId}: ${String(item.traceError ?? item.replayError ?? item.error)}`
|
|
462
|
+
);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
async function runReplayCli(registry, argv = typeof process === "undefined" ? [] : process.argv.slice(2), io = {}) {
|
|
466
|
+
const stdout = io.stdout ?? console.log;
|
|
467
|
+
const stderr = io.stderr ?? console.error;
|
|
468
|
+
const args = parseReplayCliArgs(registry, argv);
|
|
469
|
+
const registration = registry[args.pipeline];
|
|
470
|
+
const traceFunctionKey = resolveTraceFunctionKey(registration);
|
|
471
|
+
const readFile = io.readFile ?? defaultReadFile;
|
|
472
|
+
const params = await loadParameters(args.paramsPath, args.params, readFile);
|
|
473
|
+
const dynamicOptions = await registration.optionsFactory?.({ params });
|
|
474
|
+
const registrationOptions = {
|
|
475
|
+
...registration.options,
|
|
476
|
+
...dynamicOptions
|
|
477
|
+
};
|
|
478
|
+
if (registrationOptions.traceIds !== void 0 && registrationOptions.datasetId !== void 0) {
|
|
479
|
+
throw new BitfabError(
|
|
480
|
+
"Replay registry options traceIds and datasetId select different sources and cannot be used together."
|
|
481
|
+
);
|
|
482
|
+
}
|
|
483
|
+
const codeChange = await loadCodeChange(args.codeChangePath, readFile);
|
|
484
|
+
const options = {
|
|
485
|
+
...registrationOptions,
|
|
486
|
+
...args.name === void 0 ? {} : { name: args.name },
|
|
487
|
+
...args.maxConcurrency === void 0 ? {} : { maxConcurrency: args.maxConcurrency },
|
|
488
|
+
...args.experimentGroupId === void 0 ? {} : { experimentGroupId: args.experimentGroupId },
|
|
489
|
+
...args.datasetId === void 0 ? {} : { datasetId: args.datasetId },
|
|
490
|
+
...args.graderIds === void 0 ? {} : { graderIds: args.graderIds },
|
|
491
|
+
...args.mock === void 0 ? {} : { mock: args.mock },
|
|
492
|
+
...args.dbBranch === void 0 ? {} : {
|
|
493
|
+
dbBranch: args.dbBranch && registrationOptions.dbBranch !== void 0 && registrationOptions.dbBranch !== false ? registrationOptions.dbBranch : args.dbBranch
|
|
494
|
+
},
|
|
495
|
+
...args.noCodeChange === true ? { codeChangeDescription: null, codeChangeFiles: null } : {},
|
|
496
|
+
...codeChange === void 0 ? {} : {
|
|
497
|
+
codeChangeDescription: codeChange.description,
|
|
498
|
+
codeChangeFiles: codeChange.files
|
|
499
|
+
},
|
|
500
|
+
onItemStart: reportReplayProgress,
|
|
501
|
+
onItemFinish: reportReplayProgress
|
|
502
|
+
};
|
|
503
|
+
if (args.traceIds !== void 0) {
|
|
504
|
+
options.traceIds = args.traceIds;
|
|
505
|
+
options.datasetId = void 0;
|
|
506
|
+
options.limit = void 0;
|
|
507
|
+
} else if (args.datasetId !== void 0) {
|
|
508
|
+
options.traceIds = void 0;
|
|
509
|
+
options.limit = void 0;
|
|
510
|
+
} else if (args.limit !== void 0) {
|
|
511
|
+
options.traceIds = void 0;
|
|
512
|
+
options.datasetId = void 0;
|
|
513
|
+
options.limit = args.limit;
|
|
514
|
+
} else if (registrationOptions.traceIds !== void 0 || registrationOptions.datasetId !== void 0) {
|
|
515
|
+
options.limit = void 0;
|
|
516
|
+
} else {
|
|
517
|
+
options.limit = registrationOptions.limit ?? 10;
|
|
518
|
+
}
|
|
519
|
+
stderr(
|
|
520
|
+
`[replay] Replaying ${options.traceIds?.length ?? options.limit ?? "dataset"} traces from "${traceFunctionKey}"...`
|
|
521
|
+
);
|
|
522
|
+
try {
|
|
523
|
+
const result = await registration.client.replay(
|
|
524
|
+
traceFunctionKey,
|
|
525
|
+
registration.fn,
|
|
526
|
+
options
|
|
527
|
+
);
|
|
528
|
+
renderSummary(args.pipeline, result, stderr);
|
|
529
|
+
stdout(serializeReplayResult(result));
|
|
530
|
+
return result;
|
|
531
|
+
} catch (error) {
|
|
532
|
+
if (error instanceof ReplayError) {
|
|
533
|
+
reportReplayError(error, stderr);
|
|
534
|
+
}
|
|
535
|
+
throw error;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
// src/replayCli.ts
|
|
540
|
+
var USAGE = "Usage: bitfab-replay --registry <path> <pipeline> [options]\nRun bitfab-replay --registry <path> --help to list replay options.";
|
|
541
|
+
async function parseCommandArgs(argv) {
|
|
542
|
+
if (argv.some((value) => value === "--help" || value === "-h") && !argv.includes("--registry")) {
|
|
543
|
+
throw new ReplayCliHelp(USAGE);
|
|
544
|
+
}
|
|
545
|
+
const registryFlagIndex = argv.indexOf("--registry");
|
|
546
|
+
const registryPath = argv[registryFlagIndex + 1];
|
|
547
|
+
if (registryFlagIndex === -1 || registryPath === void 0 || registryPath.startsWith("--")) {
|
|
548
|
+
throw new BitfabError(USAGE);
|
|
549
|
+
}
|
|
550
|
+
const replayArgs = argv.filter(
|
|
551
|
+
(_value, index) => index !== registryFlagIndex && index !== registryFlagIndex + 1
|
|
552
|
+
);
|
|
553
|
+
if (replayArgs.length === 0) {
|
|
554
|
+
throw new BitfabError(USAGE);
|
|
555
|
+
}
|
|
556
|
+
const { resolve } = await import("path");
|
|
557
|
+
return { registryPath: resolve(registryPath), replayArgs };
|
|
558
|
+
}
|
|
559
|
+
async function importRegistry(path) {
|
|
560
|
+
const { pathToFileURL } = await import("url");
|
|
561
|
+
return tsImport(pathToFileURL(path).href, import.meta.url);
|
|
562
|
+
}
|
|
563
|
+
function resolveRegistry(moduleValue, path) {
|
|
564
|
+
if (typeof moduleValue !== "object" || moduleValue === null) {
|
|
565
|
+
throw new BitfabError(
|
|
566
|
+
`Replay registry '${path}' must export a default registry.`
|
|
567
|
+
);
|
|
568
|
+
}
|
|
569
|
+
const registry = moduleValue.default;
|
|
570
|
+
if (typeof registry !== "object" || registry === null) {
|
|
571
|
+
throw new BitfabError(
|
|
572
|
+
`Replay registry '${path}' must export a default registry.`
|
|
573
|
+
);
|
|
574
|
+
}
|
|
575
|
+
return registry;
|
|
576
|
+
}
|
|
577
|
+
async function runReplayCommand(argv, io = {}, importer = importRegistry) {
|
|
578
|
+
const { registryPath, replayArgs } = await parseCommandArgs(argv);
|
|
579
|
+
const registry = resolveRegistry(await importer(registryPath), registryPath);
|
|
580
|
+
return runReplayCli(registry, replayArgs, io);
|
|
581
|
+
}
|
|
582
|
+
async function runReplayMain(argv, io = {}) {
|
|
583
|
+
const stdout = io.stdout ?? console.log;
|
|
584
|
+
const stderr = io.stderr ?? console.error;
|
|
585
|
+
try {
|
|
586
|
+
await runReplayCommand(argv, io);
|
|
587
|
+
return 0;
|
|
588
|
+
} catch (error) {
|
|
589
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
590
|
+
if (error instanceof ReplayCliHelp) {
|
|
591
|
+
stdout(message);
|
|
592
|
+
return 0;
|
|
593
|
+
}
|
|
594
|
+
stderr(message);
|
|
595
|
+
return 1;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
async function isEntrypoint() {
|
|
599
|
+
const executablePath = process.argv[1];
|
|
600
|
+
if (executablePath === void 0) {
|
|
601
|
+
return false;
|
|
602
|
+
}
|
|
603
|
+
const [{ realpath }, { fileURLToPath }] = await Promise.all([
|
|
604
|
+
import("fs/promises"),
|
|
605
|
+
import("url")
|
|
606
|
+
]);
|
|
607
|
+
return await realpath(executablePath) === await realpath(fileURLToPath(import.meta.url));
|
|
608
|
+
}
|
|
609
|
+
void isEntrypoint().then((entrypoint) => {
|
|
610
|
+
if (entrypoint) {
|
|
611
|
+
void runReplayMain(process.argv.slice(2)).then((exitCode) => {
|
|
612
|
+
process.exitCode = exitCode;
|
|
613
|
+
});
|
|
614
|
+
}
|
|
615
|
+
});
|
|
616
|
+
export {
|
|
617
|
+
runReplayCommand,
|
|
618
|
+
runReplayMain
|
|
619
|
+
};
|
|
620
|
+
//# sourceMappingURL=replayCli.js.map
|