bitfab 0.9.2
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/README.md +292 -0
- package/dist/chunk-VGALEXKQ.js +346 -0
- package/dist/chunk-VGALEXKQ.js.map +1 -0
- package/dist/chunk-WUJR72QY.js +1214 -0
- package/dist/chunk-WUJR72QY.js.map +1 -0
- package/dist/index.cjs +1731 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +568 -0
- package/dist/index.d.ts +568 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/node.cjs +1749 -0
- package/dist/node.cjs.map +1 -0
- package/dist/node.d.cts +2 -0
- package/dist/node.d.ts +2 -0
- package/dist/node.js +36 -0
- package/dist/node.js.map +1 -0
- package/dist/replay-DJ2HXTHQ.js +100 -0
- package/dist/replay-DJ2HXTHQ.js.map +1 -0
- package/package.json +88 -0
package/README.md
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
# Bitfab TypeScript SDK
|
|
2
|
+
|
|
3
|
+
Bitfab client for provider-based API calls.
|
|
4
|
+
|
|
5
|
+
## Monorepo Setup
|
|
6
|
+
|
|
7
|
+
This package is part of a **pnpm workspace** monorepo. The workspace structure separates concerns:
|
|
8
|
+
|
|
9
|
+
- **Root `package.json`**: Contains only shared dev dependencies (Biome, TypeScript, Vitest, Knip, Madge)
|
|
10
|
+
- **Package `package.json`**: Contains runtime dependencies specific to this package
|
|
11
|
+
- You can run tests and validation from the root directory: `pnpm test` or `pnpm validate`
|
|
12
|
+
- No need to manually update shared dev tooling versions across packages
|
|
13
|
+
|
|
14
|
+
### Installing Dependencies
|
|
15
|
+
|
|
16
|
+
Always install dependencies from the **root directory**:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# From the root directory
|
|
20
|
+
pnpm install
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Updating pnpm
|
|
24
|
+
|
|
25
|
+
To update pnpm across the monorepo:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# From the root directory
|
|
29
|
+
pnpm pnpm:update
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
This automatically updates pnpm and syncs the version in `package.json` and CI/CD workflows.
|
|
33
|
+
|
|
34
|
+
### Running Commands
|
|
35
|
+
|
|
36
|
+
You can run commands from this directory or from the root:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# From this directory
|
|
40
|
+
pnpm test
|
|
41
|
+
pnpm build
|
|
42
|
+
pnpm validate
|
|
43
|
+
|
|
44
|
+
# From the root directory (runs across all packages)
|
|
45
|
+
pnpm test # Run all tests
|
|
46
|
+
pnpm validate # Run lint + tsc + test
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Available Development Tools
|
|
50
|
+
|
|
51
|
+
This package includes the following shared development tools:
|
|
52
|
+
|
|
53
|
+
| Tool | Purpose | Command |
|
|
54
|
+
|------|---------|---------|
|
|
55
|
+
| **Vitest** | Unit testing with coverage | `pnpm test` |
|
|
56
|
+
| **Biome** | Fast linting & formatting | `pnpm lint` |
|
|
57
|
+
| **TypeScript** | Type checking | `pnpm tsc` |
|
|
58
|
+
| **Knip** | Find unused dependencies/exports | `pnpm knip` |
|
|
59
|
+
| **Madge** | Detect circular dependencies | `pnpm madge` |
|
|
60
|
+
|
|
61
|
+
**Run individual tools:**
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# Run tests with coverage
|
|
65
|
+
pnpm test
|
|
66
|
+
|
|
67
|
+
# Lint and format code
|
|
68
|
+
pnpm lint
|
|
69
|
+
|
|
70
|
+
# Type check without building
|
|
71
|
+
pnpm tsc
|
|
72
|
+
|
|
73
|
+
# Find unused dependencies
|
|
74
|
+
pnpm knip
|
|
75
|
+
|
|
76
|
+
# Check for circular dependencies
|
|
77
|
+
pnpm madge
|
|
78
|
+
|
|
79
|
+
# Run all validation checks
|
|
80
|
+
pnpm validate
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Installation
|
|
84
|
+
|
|
85
|
+
### Basic Installation
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
npm install @goharvest/bitfab
|
|
89
|
+
# or
|
|
90
|
+
pnpm add @goharvest/bitfab
|
|
91
|
+
# or
|
|
92
|
+
yarn add @goharvest/bitfab
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### With OpenAI Agents SDK Tracing
|
|
96
|
+
|
|
97
|
+
If you want to use the OpenAI Agents SDK tracing integration:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
npm install @goharvest/bitfab @openai/agents
|
|
101
|
+
# or
|
|
102
|
+
pnpm add @goharvest/bitfab @openai/agents
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
The `@openai/agents` package is an optional peer dependency - the SDK works fine without it unless you need tracing functionality.
|
|
106
|
+
|
|
107
|
+
## Local Development
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
cd bitfab-typescript-sdk
|
|
111
|
+
pnpm build
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
To link for local development:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
# In this directory
|
|
118
|
+
pnpm link --global
|
|
119
|
+
|
|
120
|
+
# In your app directory
|
|
121
|
+
pnpm link --global @harvest/bitfab
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
To switch back to npm version:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
pnpm unlink @harvest/bitfab
|
|
128
|
+
pnpm add @harvest/bitfab
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Usage
|
|
132
|
+
|
|
133
|
+
### Basic Usage (Local Execution)
|
|
134
|
+
|
|
135
|
+
By default, the SDK executes BAML functions **locally on the client** by fetching the BAML prompt from the server and running it with your own API keys:
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
import { Bitfab } from "@goharvest/bitfab";
|
|
139
|
+
|
|
140
|
+
const client = new Bitfab({
|
|
141
|
+
apiKey: "sf_your_api_key_here", // Required: Your Bitfab API key
|
|
142
|
+
serviceUrl: "https://bitfab.ai", // Optional
|
|
143
|
+
envVars: {
|
|
144
|
+
OPENAI_API_KEY: process.env.OPENAI_API_KEY, // Your LLM provider API keys
|
|
145
|
+
},
|
|
146
|
+
executeLocally: true, // Default: true
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
const result = await client.call("method_name", {
|
|
150
|
+
arg1: "value1",
|
|
151
|
+
arg2: "value2",
|
|
152
|
+
});
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Server-Side Execution
|
|
156
|
+
|
|
157
|
+
If you prefer to execute BAML on the server (using the server's API keys), set `executeLocally: false`:
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
const client = new Bitfab({
|
|
161
|
+
apiKey: "sf_your_api_key_here",
|
|
162
|
+
executeLocally: false, // Execute on server instead of locally
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
const result = await client.call("method_name", {
|
|
166
|
+
arg1: "value1",
|
|
167
|
+
arg2: "value2",
|
|
168
|
+
});
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### With TypeScript Generics
|
|
172
|
+
|
|
173
|
+
You can specify the return type for type safety:
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
interface MyResponse {
|
|
177
|
+
answer: string;
|
|
178
|
+
confidence: number;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const result = await client.call<MyResponse>("analyze", {
|
|
182
|
+
text: "Hello world",
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
console.log(result.answer); // TypeScript knows this is a string
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Error Handling
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
import { Bitfab, BitfabError } from "@goharvest/bitfab";
|
|
192
|
+
|
|
193
|
+
const client = new Bitfab({
|
|
194
|
+
apiKey: "sf_your_api_key_here",
|
|
195
|
+
serviceUrl: "https://your-bitfab-instance.com",
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
try {
|
|
199
|
+
const result = await client.call("method_name", { input: "value" });
|
|
200
|
+
} catch (error) {
|
|
201
|
+
if (error instanceof BitfabError) {
|
|
202
|
+
console.error("Bitfab error:", error.message);
|
|
203
|
+
if (error.url) {
|
|
204
|
+
console.error("Configure at:", error.url);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## Configuration
|
|
211
|
+
|
|
212
|
+
| Option | Required | Description |
|
|
213
|
+
| ---------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
|
214
|
+
| `apiKey` | Yes | Your Bitfab API key (generate from your Bitfab dashboard) |
|
|
215
|
+
| `serviceUrl` | No | The base URL for the Bitfab API (default: https://bitfab.ai) |
|
|
216
|
+
| `timeout` | No | Request timeout in milliseconds (default: 120000) |
|
|
217
|
+
| `envVars` | No | Environment variables for LLM provider API keys (e.g., `{ OPENAI_API_KEY: "..." }`). Required for local execution. |
|
|
218
|
+
| `executeLocally` | No | Whether to execute BAML locally on the client (default: true). Set to false to execute on the server with the server's API keys. |
|
|
219
|
+
|
|
220
|
+
## Execution Modes
|
|
221
|
+
|
|
222
|
+
### Local Execution (Default)
|
|
223
|
+
|
|
224
|
+
When `executeLocally: true` (default), the SDK:
|
|
225
|
+
|
|
226
|
+
1. Fetches the BAML function definition from the Bitfab server
|
|
227
|
+
2. Executes the BAML locally using the `@boundaryml/baml` runtime
|
|
228
|
+
3. Uses your own LLM provider API keys (passed via `envVars`)
|
|
229
|
+
4. Returns the result directly to you
|
|
230
|
+
|
|
231
|
+
**Benefits:**
|
|
232
|
+
|
|
233
|
+
- Full control over API keys and costs
|
|
234
|
+
- Lower latency (no server round-trip for execution)
|
|
235
|
+
- Privacy: Your data doesn't go through the Bitfab server
|
|
236
|
+
|
|
237
|
+
**Requirements:**
|
|
238
|
+
|
|
239
|
+
- You must provide LLM provider API keys via `envVars`
|
|
240
|
+
- The BAML runtime runs in your environment (Node.js, browser with polyfills, etc.)
|
|
241
|
+
|
|
242
|
+
### Server-Side Execution
|
|
243
|
+
|
|
244
|
+
When `executeLocally: false`, the SDK:
|
|
245
|
+
|
|
246
|
+
1. Sends the function name and inputs to the Bitfab server
|
|
247
|
+
2. The server executes the BAML using its own API keys
|
|
248
|
+
3. Returns the result to you
|
|
249
|
+
|
|
250
|
+
**Benefits:**
|
|
251
|
+
|
|
252
|
+
- No need to manage LLM provider API keys
|
|
253
|
+
- Simpler setup
|
|
254
|
+
- Works in any environment
|
|
255
|
+
|
|
256
|
+
**Requirements:**
|
|
257
|
+
|
|
258
|
+
- The Bitfab server must have the necessary API keys configured
|
|
259
|
+
|
|
260
|
+
## Environment Variables
|
|
261
|
+
|
|
262
|
+
- `BITFAB_URL`: The base URL for the Bitfab API (used if `serviceUrl` is not provided)
|
|
263
|
+
- `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, etc.: LLM provider API keys (required for local execution)
|
|
264
|
+
|
|
265
|
+
## Testing
|
|
266
|
+
|
|
267
|
+
A test script is provided to verify both local and server-side execution:
|
|
268
|
+
|
|
269
|
+
```bash
|
|
270
|
+
# Set up environment variables
|
|
271
|
+
export BITFAB_API_KEY="sf_your_api_key"
|
|
272
|
+
export OPENAI_API_KEY="your_openai_key"
|
|
273
|
+
|
|
274
|
+
# Run the test script
|
|
275
|
+
pnpm tsx test-local-execution.ts [function-name] [query]
|
|
276
|
+
|
|
277
|
+
# Example
|
|
278
|
+
pnpm tsx test-local-execution.ts extract-entities "What is the capital of France?"
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
The test script will:
|
|
282
|
+
|
|
283
|
+
1. Test local execution with your API keys
|
|
284
|
+
2. Test server-side execution
|
|
285
|
+
3. Compare results and performance
|
|
286
|
+
|
|
287
|
+
## Publishing
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
pnpm build
|
|
291
|
+
npm publish --access public
|
|
292
|
+
```
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
// src/asyncStorage.ts
|
|
2
|
+
var AsyncLocalStorageClass = null;
|
|
3
|
+
var initDone = false;
|
|
4
|
+
function registerAsyncLocalStorageClass(cls) {
|
|
5
|
+
if (!AsyncLocalStorageClass) {
|
|
6
|
+
AsyncLocalStorageClass = cls;
|
|
7
|
+
}
|
|
8
|
+
initDone = true;
|
|
9
|
+
}
|
|
10
|
+
function assertAsyncStorageRegistered() {
|
|
11
|
+
if (!AsyncLocalStorageClass) {
|
|
12
|
+
console.warn(
|
|
13
|
+
"Bitfab: AsyncLocalStorage not available \u2014 nested span context will not propagate."
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
var asyncStorageReady = (typeof process !== "undefined" && process.versions?.node ? (
|
|
18
|
+
// The join trick hides "node:async_hooks" from static analysis so
|
|
19
|
+
// bundlers that ban Node.js built-ins don't fail at build time.
|
|
20
|
+
// webpackIgnore tells webpack/turbopack to emit a native import()
|
|
21
|
+
// so Node.js can resolve the module at runtime.
|
|
22
|
+
import(
|
|
23
|
+
/* webpackIgnore: true */
|
|
24
|
+
["node", "async_hooks"].join(":")
|
|
25
|
+
).then(
|
|
26
|
+
(mod) => {
|
|
27
|
+
registerAsyncLocalStorageClass(mod.AsyncLocalStorage);
|
|
28
|
+
}
|
|
29
|
+
).catch(() => {
|
|
30
|
+
})
|
|
31
|
+
) : Promise.resolve()).then(() => {
|
|
32
|
+
initDone = true;
|
|
33
|
+
});
|
|
34
|
+
function isAsyncStorageInitDone() {
|
|
35
|
+
return initDone;
|
|
36
|
+
}
|
|
37
|
+
function createAsyncLocalStorage() {
|
|
38
|
+
return AsyncLocalStorageClass ? new AsyncLocalStorageClass() : null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// src/version.generated.ts
|
|
42
|
+
var __version__ = "0.9.2";
|
|
43
|
+
|
|
44
|
+
// src/constants.ts
|
|
45
|
+
var DEFAULT_SERVICE_URL = "https://bitfab.ai";
|
|
46
|
+
|
|
47
|
+
// src/http.ts
|
|
48
|
+
var BitfabError = class extends Error {
|
|
49
|
+
constructor(message, url) {
|
|
50
|
+
super(message);
|
|
51
|
+
this.url = url;
|
|
52
|
+
this.name = "BitfabError";
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
var pendingTracePromises = /* @__PURE__ */ new Set();
|
|
56
|
+
function awaitOnExit(promise) {
|
|
57
|
+
pendingTracePromises.add(promise);
|
|
58
|
+
void promise.finally(() => {
|
|
59
|
+
pendingTracePromises.delete(promise);
|
|
60
|
+
}).catch(() => {
|
|
61
|
+
});
|
|
62
|
+
return promise;
|
|
63
|
+
}
|
|
64
|
+
async function flushTraces(timeoutMs = 5e3) {
|
|
65
|
+
if (pendingTracePromises.size === 0) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
await Promise.race([
|
|
69
|
+
Promise.allSettled(Array.from(pendingTracePromises)),
|
|
70
|
+
new Promise((resolve) => setTimeout(resolve, timeoutMs))
|
|
71
|
+
]);
|
|
72
|
+
}
|
|
73
|
+
if (typeof process !== "undefined" && process.versions != null && process.versions.node != null) {
|
|
74
|
+
let isFlushing = false;
|
|
75
|
+
process.on("beforeExit", () => {
|
|
76
|
+
if (pendingTracePromises.size > 0 && !isFlushing) {
|
|
77
|
+
isFlushing = true;
|
|
78
|
+
Promise.allSettled(
|
|
79
|
+
Array.from(pendingTracePromises).map(
|
|
80
|
+
(p) => p.catch(() => {
|
|
81
|
+
})
|
|
82
|
+
)
|
|
83
|
+
).then(() => {
|
|
84
|
+
isFlushing = false;
|
|
85
|
+
}).catch(() => {
|
|
86
|
+
isFlushing = false;
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
var HttpClient = class {
|
|
92
|
+
constructor(config) {
|
|
93
|
+
this.apiKey = config.apiKey;
|
|
94
|
+
this.serviceUrl = config.serviceUrl;
|
|
95
|
+
this.timeout = config.timeout ?? 12e4;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Make an HTTP POST request to the Bitfab API.
|
|
99
|
+
*
|
|
100
|
+
* @param endpoint - The API endpoint (without base URL)
|
|
101
|
+
* @param payload - The request body
|
|
102
|
+
* @param options - Optional request options
|
|
103
|
+
* @returns The parsed JSON response
|
|
104
|
+
* @throws {BitfabError} If the request fails
|
|
105
|
+
*/
|
|
106
|
+
async request(endpoint, payload, options) {
|
|
107
|
+
const url = `${this.serviceUrl}${endpoint}`;
|
|
108
|
+
const timeout = options?.timeout ?? this.timeout;
|
|
109
|
+
const controller = new AbortController();
|
|
110
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
111
|
+
let body;
|
|
112
|
+
let serializationError;
|
|
113
|
+
try {
|
|
114
|
+
body = JSON.stringify(payload);
|
|
115
|
+
} catch (error) {
|
|
116
|
+
serializationError = error instanceof Error ? error.message : String(error);
|
|
117
|
+
body = JSON.stringify({
|
|
118
|
+
...Object.fromEntries(
|
|
119
|
+
Object.entries(payload).filter(
|
|
120
|
+
([, v]) => typeof v === "string" || typeof v === "number"
|
|
121
|
+
)
|
|
122
|
+
),
|
|
123
|
+
rawSpan: {},
|
|
124
|
+
errors: [{ step: "json_serialize", error: serializationError }]
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
try {
|
|
128
|
+
const response = await fetch(url, {
|
|
129
|
+
method: "POST",
|
|
130
|
+
headers: {
|
|
131
|
+
"Content-Type": "application/json",
|
|
132
|
+
Authorization: `Bearer ${this.apiKey}`
|
|
133
|
+
},
|
|
134
|
+
body,
|
|
135
|
+
signal: controller.signal
|
|
136
|
+
});
|
|
137
|
+
if (!response.ok) {
|
|
138
|
+
const errorText = await response.text();
|
|
139
|
+
throw new BitfabError(
|
|
140
|
+
`HTTP ${response.status}: ${errorText.slice(0, 500)}`
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
const result = await response.json();
|
|
144
|
+
if (result.error) {
|
|
145
|
+
if (result.url) {
|
|
146
|
+
throw new BitfabError(
|
|
147
|
+
`${result.error} Configure it at: ${this.serviceUrl}${result.url}`,
|
|
148
|
+
result.url
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
throw new BitfabError(result.error);
|
|
152
|
+
}
|
|
153
|
+
return result;
|
|
154
|
+
} catch (error) {
|
|
155
|
+
if (error instanceof BitfabError) {
|
|
156
|
+
throw error;
|
|
157
|
+
}
|
|
158
|
+
if (error instanceof Error) {
|
|
159
|
+
if (error.name === "AbortError") {
|
|
160
|
+
throw new BitfabError(`Request timed out after ${timeout}ms`);
|
|
161
|
+
}
|
|
162
|
+
throw new BitfabError(error.message);
|
|
163
|
+
}
|
|
164
|
+
throw new BitfabError("Unknown error occurred");
|
|
165
|
+
} finally {
|
|
166
|
+
clearTimeout(timeoutId);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Look up a function by name.
|
|
171
|
+
* Blocks until complete - needed for function execution.
|
|
172
|
+
*/
|
|
173
|
+
async lookupFunction(name) {
|
|
174
|
+
return this.request("/api/sdk/functions/lookup", { name });
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Send an internal trace (from BAML execution).
|
|
178
|
+
* Fire-and-forget with awaitOnExit - doesn't block the caller.
|
|
179
|
+
*/
|
|
180
|
+
sendInternalTrace(functionId, payload) {
|
|
181
|
+
void awaitOnExit(
|
|
182
|
+
this.request(`/api/sdk/functions/${functionId}/traces`, {
|
|
183
|
+
...payload,
|
|
184
|
+
sdkVersion: __version__
|
|
185
|
+
})
|
|
186
|
+
).catch((error) => {
|
|
187
|
+
try {
|
|
188
|
+
console.error("Bitfab: Failed to create trace:", error);
|
|
189
|
+
} catch {
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Send an external span (from withSpan wrapper or OpenAI tracing).
|
|
195
|
+
* Fire-and-forget with awaitOnExit - doesn't block the caller.
|
|
196
|
+
* Returns the tracked promise so callers can optionally await it.
|
|
197
|
+
*/
|
|
198
|
+
sendExternalSpan(payload) {
|
|
199
|
+
return awaitOnExit(
|
|
200
|
+
this.request("/api/sdk/externalSpans", {
|
|
201
|
+
...payload,
|
|
202
|
+
sdkVersion: __version__
|
|
203
|
+
})
|
|
204
|
+
).catch((error) => {
|
|
205
|
+
try {
|
|
206
|
+
console.error("Bitfab: Failed to create external span:", error);
|
|
207
|
+
} catch {
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Send an external trace (from OpenAI tracing).
|
|
213
|
+
* Fire-and-forget with awaitOnExit - doesn't block the caller.
|
|
214
|
+
*/
|
|
215
|
+
sendExternalTrace(payload) {
|
|
216
|
+
void awaitOnExit(
|
|
217
|
+
this.request("/api/sdk/externalTraces", {
|
|
218
|
+
...payload,
|
|
219
|
+
sdkVersion: __version__
|
|
220
|
+
})
|
|
221
|
+
).catch((error) => {
|
|
222
|
+
try {
|
|
223
|
+
console.error("Bitfab: Failed to create external trace:", error);
|
|
224
|
+
} catch {
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Start a replay session by fetching historical traces.
|
|
230
|
+
* Blocking call — creates a test run and returns lightweight item references.
|
|
231
|
+
*/
|
|
232
|
+
async startReplay(traceFunctionKey, limit, traceIds) {
|
|
233
|
+
const payload = { traceFunctionKey, limit };
|
|
234
|
+
if (traceIds) {
|
|
235
|
+
payload.traceIds = traceIds;
|
|
236
|
+
}
|
|
237
|
+
return this.request("/api/sdk/replay/start", payload, {
|
|
238
|
+
timeout: 3e4
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Fetch an external span by ID.
|
|
243
|
+
* Blocking GET request.
|
|
244
|
+
*/
|
|
245
|
+
async getExternalSpan(spanId) {
|
|
246
|
+
const url = `${this.serviceUrl}/api/sdk/externalSpans/${spanId}`;
|
|
247
|
+
const controller = new AbortController();
|
|
248
|
+
const timeoutId = setTimeout(() => controller.abort(), 3e4);
|
|
249
|
+
try {
|
|
250
|
+
const response = await fetch(url, {
|
|
251
|
+
method: "GET",
|
|
252
|
+
headers: { Authorization: `Bearer ${this.apiKey}` },
|
|
253
|
+
signal: controller.signal
|
|
254
|
+
});
|
|
255
|
+
if (!response.ok) {
|
|
256
|
+
const errorText = await response.text();
|
|
257
|
+
throw new BitfabError(
|
|
258
|
+
`HTTP ${response.status}: ${errorText.slice(0, 500)}`
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
return await response.json();
|
|
262
|
+
} catch (error) {
|
|
263
|
+
if (error instanceof BitfabError) {
|
|
264
|
+
throw error;
|
|
265
|
+
}
|
|
266
|
+
if (error instanceof Error) {
|
|
267
|
+
if (error.name === "AbortError") {
|
|
268
|
+
throw new BitfabError("Request timed out after 30000ms");
|
|
269
|
+
}
|
|
270
|
+
throw new BitfabError(error.message);
|
|
271
|
+
}
|
|
272
|
+
throw new BitfabError("Unknown error occurred");
|
|
273
|
+
} finally {
|
|
274
|
+
clearTimeout(timeoutId);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Mark a replay test run as completed.
|
|
279
|
+
* Blocking call.
|
|
280
|
+
*/
|
|
281
|
+
async completeReplay(testRunId) {
|
|
282
|
+
return this.request(
|
|
283
|
+
"/api/sdk/replay/complete",
|
|
284
|
+
{ testRunId },
|
|
285
|
+
{ timeout: 3e4 }
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
// src/replayContext.ts
|
|
291
|
+
var replayContextStorage = null;
|
|
292
|
+
var replayContextReady = asyncStorageReady.then(() => {
|
|
293
|
+
replayContextStorage = createAsyncLocalStorage();
|
|
294
|
+
});
|
|
295
|
+
function getReplayContext() {
|
|
296
|
+
return replayContextStorage?.getStore() ?? null;
|
|
297
|
+
}
|
|
298
|
+
function runWithReplayContext(ctx, fn) {
|
|
299
|
+
if (replayContextStorage) {
|
|
300
|
+
return replayContextStorage.run(ctx, fn);
|
|
301
|
+
}
|
|
302
|
+
return fn();
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// src/serialize.ts
|
|
306
|
+
import superjson from "superjson";
|
|
307
|
+
function serializeValue(value) {
|
|
308
|
+
try {
|
|
309
|
+
const { json, meta } = superjson.serialize(value);
|
|
310
|
+
return meta ? { json, meta } : { json };
|
|
311
|
+
} catch {
|
|
312
|
+
try {
|
|
313
|
+
return { json: JSON.parse(JSON.stringify(value)) };
|
|
314
|
+
} catch {
|
|
315
|
+
return { json: String(value) };
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
function deserializeValue(serialized) {
|
|
320
|
+
if (serialized.meta === void 0) {
|
|
321
|
+
return serialized.json;
|
|
322
|
+
}
|
|
323
|
+
return superjson.deserialize({
|
|
324
|
+
json: serialized.json,
|
|
325
|
+
meta: serialized.meta
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
export {
|
|
330
|
+
registerAsyncLocalStorageClass,
|
|
331
|
+
assertAsyncStorageRegistered,
|
|
332
|
+
asyncStorageReady,
|
|
333
|
+
isAsyncStorageInitDone,
|
|
334
|
+
createAsyncLocalStorage,
|
|
335
|
+
__version__,
|
|
336
|
+
DEFAULT_SERVICE_URL,
|
|
337
|
+
BitfabError,
|
|
338
|
+
flushTraces,
|
|
339
|
+
HttpClient,
|
|
340
|
+
replayContextReady,
|
|
341
|
+
getReplayContext,
|
|
342
|
+
runWithReplayContext,
|
|
343
|
+
serializeValue,
|
|
344
|
+
deserializeValue
|
|
345
|
+
};
|
|
346
|
+
//# sourceMappingURL=chunk-VGALEXKQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/asyncStorage.ts","../src/version.generated.ts","../src/constants.ts","../src/http.ts","../src/replayContext.ts","../src/serialize.ts"],"sourcesContent":["/**\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","/**\n * Auto-generated version file.\n * This file is generated by scripts/generate-version.ts during build.\n * DO NOT EDIT MANUALLY.\n */\n\n/**\n * SDK version from package.json (injected at build time)\n */\nexport const __version__ = \"0.9.2\"\n","/**\n * Constants for the Bitfab SDK.\n */\n\n/**\n * Default service URL for Bitfab API.\n */\nexport const DEFAULT_SERVICE_URL = \"https://bitfab.ai\"\n\n/**\n * SDK version from package.json (injected at build time)\n *\n * The version is generated at build time by scripts/generate-version.ts\n * to ensure compatibility with both Node.js and browser environments.\n */\nexport { __version__ } from \"./version.generated.js\"\n","/**\n * HTTP client utilities for Bitfab API requests.\n *\n * This module provides:\n * - HttpClient class for making API requests\n * - awaitOnExit helper for fire-and-forget operations that must complete before process exit\n */\n\nimport { __version__ } from \"./constants.js\"\n\n/**\n * Error class for Bitfab API errors.\n */\nexport class BitfabError extends Error {\n constructor(\n message: string,\n public readonly url?: string,\n ) {\n super(message)\n this.name = \"BitfabError\"\n }\n}\n\n// Global set to track pending trace creation promises\n// This prevents promises from being garbage collected before they complete\nconst pendingTracePromises = new Set<Promise<unknown>>()\n\n/**\n * Track a promise to prevent it from being garbage collected.\n * The promise will be removed from tracking when it completes (success or failure).\n * Useful for fire-and-forget operations that need to complete before process exit.\n *\n * @param promise - The promise to track\n * @returns The same promise (for chaining)\n */\nexport function awaitOnExit<T>(promise: Promise<T>): Promise<T> {\n pendingTracePromises.add(promise)\n // Use void to prevent unhandled rejection warnings from the .finally() chain\n // The actual error handling is done by the caller's .catch() on the returned promise\n void promise\n .finally(() => {\n pendingTracePromises.delete(promise)\n })\n .catch(() => {\n // Swallow rejection in this chain - the caller handles errors via their own .catch()\n })\n return promise\n}\n\n/**\n * Wait for all pending fire-and-forget operations (spans, traces) to complete.\n * Useful in tests and scripts to ensure all data has been sent before asserting or exiting.\n *\n * @param timeoutMs - Maximum time to wait in milliseconds (default: 5000)\n */\nexport async function flushTraces(timeoutMs: number = 5000): Promise<void> {\n if (pendingTracePromises.size === 0) {\n return\n }\n await Promise.race([\n Promise.allSettled(Array.from(pendingTracePromises)),\n new Promise<void>((resolve) => setTimeout(resolve, timeoutMs)),\n ])\n}\n\n// Register beforeExit handler to wait for pending traces (Node.js only)\n// This ensures traces are sent before the process exits (for scripts)\nif (\n typeof process !== \"undefined\" &&\n process.versions != null &&\n process.versions.node != null\n) {\n let isFlushing = false\n process.on(\"beforeExit\", () => {\n if (pendingTracePromises.size > 0 && !isFlushing) {\n isFlushing = true\n // Wait for all pending traces to complete\n // This keeps the event loop alive until promises resolve\n Promise.allSettled(\n Array.from(pendingTracePromises).map((p) =>\n p.catch(() => {\n // Silently ignore individual trace failures\n }),\n ),\n )\n .then(() => {\n isFlushing = false\n })\n .catch(() => {\n isFlushing = false\n })\n }\n })\n}\n\nexport interface HttpClientConfig {\n apiKey?: string\n serviceUrl: string\n timeout?: number\n}\n\n/**\n * HTTP client for Bitfab API requests.\n *\n * Provides methods for different API endpoints with proper error handling,\n * timeouts, and authentication.\n */\nexport class HttpClient {\n private readonly apiKey: string | undefined\n private readonly serviceUrl: string\n private readonly timeout: number\n\n constructor(config: HttpClientConfig) {\n this.apiKey = config.apiKey\n this.serviceUrl = config.serviceUrl\n this.timeout = config.timeout ?? 120000\n }\n\n /**\n * Make an HTTP POST request to the Bitfab API.\n *\n * @param endpoint - The API endpoint (without base URL)\n * @param payload - The request body\n * @param options - Optional request options\n * @returns The parsed JSON response\n * @throws {BitfabError} If the request fails\n */\n async request<T>(\n endpoint: string,\n payload: Record<string, unknown>,\n options?: { timeout?: number },\n ): Promise<T> {\n const url = `${this.serviceUrl}${endpoint}`\n const timeout = options?.timeout ?? this.timeout\n\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), timeout)\n\n // Serialize payload, handling circular references\n let body: string\n let serializationError: string | undefined\n try {\n body = JSON.stringify(payload)\n } catch (error) {\n serializationError =\n error instanceof Error ? error.message : String(error)\n // Create fallback payload with error info\n body = JSON.stringify({\n ...Object.fromEntries(\n Object.entries(payload).filter(\n ([, v]) => typeof v === \"string\" || typeof v === \"number\",\n ),\n ),\n rawSpan: {},\n errors: [{ step: \"json_serialize\", error: serializationError }],\n })\n }\n\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.apiKey}`,\n },\n body,\n signal: controller.signal,\n })\n\n if (!response.ok) {\n const errorText = await response.text()\n throw new BitfabError(\n `HTTP ${response.status}: ${errorText.slice(0, 500)}`,\n )\n }\n\n const result = await response.json()\n\n // Check for errors in the response\n if (result.error) {\n if (result.url) {\n throw new BitfabError(\n `${result.error} Configure it at: ${this.serviceUrl}${result.url}`,\n result.url,\n )\n }\n throw new BitfabError(result.error)\n }\n\n return result as T\n } catch (error) {\n if (error instanceof BitfabError) {\n throw error\n }\n if (error instanceof Error) {\n if (error.name === \"AbortError\") {\n throw new BitfabError(`Request timed out after ${timeout}ms`)\n }\n throw new BitfabError(error.message)\n }\n throw new BitfabError(\"Unknown error occurred\")\n } finally {\n clearTimeout(timeoutId)\n }\n }\n\n /**\n * Look up a function by name.\n * Blocks until complete - needed for function execution.\n */\n async lookupFunction<T>(name: string): Promise<T> {\n return this.request<T>(\"/api/sdk/functions/lookup\", { name })\n }\n\n /**\n * Send an internal trace (from BAML execution).\n * Fire-and-forget with awaitOnExit - doesn't block the caller.\n */\n sendInternalTrace(\n functionId: string,\n payload: Record<string, unknown>,\n ): void {\n void awaitOnExit(\n this.request(`/api/sdk/functions/${functionId}/traces`, {\n ...payload,\n sdkVersion: __version__,\n }),\n ).catch((error) => {\n try {\n console.error(\"Bitfab: Failed to create trace:\", error)\n } catch {}\n })\n }\n\n /**\n * Send an external span (from withSpan wrapper or OpenAI tracing).\n * Fire-and-forget with awaitOnExit - doesn't block the caller.\n * Returns the tracked promise so callers can optionally await it.\n */\n sendExternalSpan(payload: Record<string, unknown>): Promise<unknown> {\n return awaitOnExit(\n this.request(\"/api/sdk/externalSpans\", {\n ...payload,\n sdkVersion: __version__,\n }),\n ).catch((error) => {\n try {\n console.error(\"Bitfab: Failed to create external span:\", error)\n } catch {}\n })\n }\n\n /**\n * Send an external trace (from OpenAI tracing).\n * Fire-and-forget with awaitOnExit - doesn't block the caller.\n */\n sendExternalTrace(payload: Record<string, unknown>): void {\n void awaitOnExit(\n this.request(\"/api/sdk/externalTraces\", {\n ...payload,\n sdkVersion: __version__,\n }),\n ).catch((error) => {\n try {\n console.error(\"Bitfab: Failed to create external trace:\", error)\n } catch {}\n })\n }\n\n /**\n * Start a replay session by fetching historical traces.\n * Blocking call — creates a test run and returns lightweight item references.\n */\n async startReplay(\n traceFunctionKey: string,\n limit: number,\n traceIds?: string[],\n ): Promise<StartReplayResponse> {\n const payload: Record<string, unknown> = { traceFunctionKey, limit }\n if (traceIds) {\n payload.traceIds = traceIds\n }\n return this.request<StartReplayResponse>(\"/api/sdk/replay/start\", payload, {\n timeout: 30_000,\n })\n }\n\n /**\n * Fetch an external span by ID.\n * Blocking GET request.\n */\n async getExternalSpan(spanId: string): Promise<ExternalSpanResponse> {\n const url = `${this.serviceUrl}/api/sdk/externalSpans/${spanId}`\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), 30_000)\n\n try {\n const response = await fetch(url, {\n method: \"GET\",\n headers: { Authorization: `Bearer ${this.apiKey}` },\n signal: controller.signal,\n })\n\n if (!response.ok) {\n const errorText = await response.text()\n throw new BitfabError(\n `HTTP ${response.status}: ${errorText.slice(0, 500)}`,\n )\n }\n\n return (await response.json()) as ExternalSpanResponse\n } catch (error) {\n if (error instanceof BitfabError) {\n throw error\n }\n if (error instanceof Error) {\n if (error.name === \"AbortError\") {\n throw new BitfabError(\"Request timed out after 30000ms\")\n }\n throw new BitfabError(error.message)\n }\n throw new BitfabError(\"Unknown error occurred\")\n } finally {\n clearTimeout(timeoutId)\n }\n }\n\n /**\n * Mark a replay test run as completed.\n * Blocking call.\n */\n async completeReplay(testRunId: string): Promise<CompleteReplayResponse> {\n return this.request<CompleteReplayResponse>(\n \"/api/sdk/replay/complete\",\n { testRunId },\n { timeout: 30_000 },\n )\n }\n}\n\nexport interface StartReplayResponse {\n testRunId: string\n testRunUrl: string\n items: Array<{\n traceId: string\n externalSpanId: string\n }>\n}\n\nexport interface ExternalSpanResponse {\n id: string\n externalTraceId: string\n rawData: {\n span_data: {\n input: unknown\n output: unknown\n input_meta?: unknown\n output_meta?: unknown\n input_serialized?: { json: unknown; meta: unknown }\n output_serialized?: { json: unknown; meta: unknown }\n }\n }\n}\n\nexport interface CompleteReplayResponse {\n id: string\n status: string\n}\n","/**\n * Replay context propagation via AsyncLocalStorage.\n *\n * When set, the withSpan wrapper injects testRunId into the span payload\n * so that new spans created during replay are linked to the test run.\n */\n\nimport {\n type AsyncLocalStorageLike,\n asyncStorageReady,\n createAsyncLocalStorage,\n} from \"./asyncStorage.js\"\n\nexport interface ReplayContext {\n testRunId: string\n inputSourceSpanId?: string\n}\n\nlet replayContextStorage: AsyncLocalStorageLike<ReplayContext | null> | null =\n null\n\nexport const replayContextReady: Promise<void> = asyncStorageReady.then(() => {\n replayContextStorage = createAsyncLocalStorage<ReplayContext | null>()\n})\n\n/** Get the current replay context, if any. */\nexport function getReplayContext(): ReplayContext | null {\n return replayContextStorage?.getStore() ?? null\n}\n\n/** Run a function within a replay context. */\nexport function runWithReplayContext<T>(ctx: ReplayContext, fn: () => T): T {\n if (replayContextStorage) {\n return replayContextStorage.run(ctx, fn)\n }\n return fn()\n}\n","/**\n * Serialization utilities for Bitfab SDK.\n *\n * This module provides serialization with type metadata preservation,\n * using superjson for handling special JavaScript types like Date, Map,\n * Set, BigInt, undefined, etc.\n */\n\nimport superjson from \"superjson\"\n\n/**\n * Serialized value with JSON data and optional superjson meta for type preservation.\n *\n * The json field contains the JSON-serializable data.\n * The meta field (if present) contains superjson type information for deserializing\n * special types like Date, Map, Set, BigInt, etc.\n */\nexport interface SerializedValue {\n json: unknown\n meta?: unknown\n}\n\n/**\n * Serialize a value using superjson for trace storage.\n *\n * Handles arbitrary JavaScript values including:\n * - Date, RegExp, Error\n * - Map, Set\n * - BigInt\n * - undefined (in objects/arrays)\n * - Circular references\n *\n * @param value - Any JavaScript value to serialize\n * @returns SerializedValue with 'json' field containing the data.\n * If type metadata is needed for reconstruction, includes 'meta' field.\n *\n * @example\n * ```typescript\n * const result = serializeValue(new Date('2024-01-15T10:30:00Z'))\n * // result.json contains the ISO string\n * // result.meta contains type info for Date reconstruction\n * ```\n */\nexport function serializeValue(value: unknown): SerializedValue {\n try {\n const { json, meta } = superjson.serialize(value)\n return meta ? { json, meta } : { json }\n } catch {\n // Fallback to basic JSON serialization\n try {\n return { json: JSON.parse(JSON.stringify(value)) }\n } catch {\n return { json: String(value) }\n }\n }\n}\n\n/**\n * Deserialize a value that was serialized with serializeValue.\n *\n * @param serialized - A SerializedValue object with 'json' and optional 'meta'\n * @returns The reconstructed JavaScript value\n *\n * @example\n * ```typescript\n * const serialized = serializeValue(new Date('2024-01-15'))\n * const date = deserializeValue(serialized)\n * // date is a Date object\n * ```\n */\nexport function deserializeValue(serialized: SerializedValue): unknown {\n if (serialized.meta === undefined) {\n // No metadata, return as-is\n return serialized.json\n }\n\n // Use superjson to deserialize with type reconstruction\n // Cast json to the expected superjson type\n type SuperJSONResult = Parameters<typeof superjson.deserialize>[0]\n return superjson.deserialize({\n json: serialized.json as SuperJSONResult[\"json\"],\n meta: serialized.meta as SuperJSONResult[\"meta\"],\n })\n}\n"],"mappings":"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","names":[]}
|