langsmith 0.5.23 → 0.5.25
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/client.cjs +102 -11
- package/dist/client.d.ts +38 -0
- package/dist/client.js +103 -12
- package/dist/evaluation/_runner.cjs +3 -3
- package/dist/evaluation/_runner.js +1 -1
- package/dist/evaluation/evaluate_comparative.cjs +10 -10
- package/dist/evaluation/evaluate_comparative.js +1 -1
- package/dist/evaluation/evaluator.cjs +2 -2
- package/dist/evaluation/evaluator.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/run_trees.cjs +8 -7
- package/dist/run_trees.d.ts +7 -0
- package/dist/run_trees.js +7 -6
- package/dist/schemas.d.ts +4 -0
- package/dist/singletons/otel.cjs +3 -2
- package/dist/singletons/otel.js +4 -3
- package/dist/traceable.cjs +1 -2
- package/dist/traceable.js +1 -2
- package/dist/utils/_uuid.cjs +2 -2
- package/dist/utils/_uuid.js +1 -1
- package/dist/utils/env.cjs +33 -0
- package/dist/utils/env.d.ts +9 -0
- package/dist/utils/env.js +32 -0
- package/dist/utils/fast-safe-stringify/index.cjs +10 -35
- package/dist/utils/fast-safe-stringify/index.d.ts +14 -1
- package/dist/utils/fast-safe-stringify/index.js +10 -35
- package/dist/utils/jestlike/index.cjs +5 -5
- package/dist/utils/jestlike/index.js +1 -1
- package/dist/utils/jestlike/vendor/evaluatedBy.cjs +3 -3
- package/dist/utils/jestlike/vendor/evaluatedBy.js +1 -1
- package/dist/utils/serialize_worker.cjs +389 -0
- package/dist/utils/serialize_worker.d.ts +67 -0
- package/dist/utils/serialize_worker.js +383 -0
- package/dist/utils/uuid/src/index.cjs +24 -0
- package/dist/utils/uuid/src/index.d.ts +10 -0
- package/dist/utils/uuid/src/index.js +9 -0
- package/dist/utils/uuid/src/max.cjs +3 -0
- package/dist/utils/uuid/src/max.d.ts +2 -0
- package/dist/utils/uuid/src/max.js +1 -0
- package/dist/utils/uuid/src/nil.cjs +3 -0
- package/dist/utils/uuid/src/nil.d.ts +2 -0
- package/dist/utils/uuid/src/nil.js +1 -0
- package/dist/utils/uuid/src/parse.cjs +23 -0
- package/dist/utils/uuid/src/parse.d.ts +3 -0
- package/dist/utils/uuid/src/parse.js +18 -0
- package/dist/utils/uuid/src/regex.cjs +3 -0
- package/dist/utils/uuid/src/regex.d.ts +2 -0
- package/dist/utils/uuid/src/regex.js +1 -0
- package/dist/utils/uuid/src/rng.cjs +10 -0
- package/dist/utils/uuid/src/rng.d.ts +1 -0
- package/dist/utils/uuid/src/rng.js +7 -0
- package/dist/utils/uuid/src/sha1.cjs +75 -0
- package/dist/utils/uuid/src/sha1.d.ts +2 -0
- package/dist/utils/uuid/src/sha1.js +73 -0
- package/dist/utils/uuid/src/stringify.cjs +55 -0
- package/dist/utils/uuid/src/stringify.d.ts +3 -0
- package/dist/utils/uuid/src/stringify.js +49 -0
- package/dist/utils/uuid/src/types.cjs +2 -0
- package/dist/utils/uuid/src/types.d.ts +22 -0
- package/dist/utils/uuid/src/types.js +1 -0
- package/dist/utils/uuid/src/v35.cjs +52 -0
- package/dist/utils/uuid/src/v35.d.ts +7 -0
- package/dist/utils/uuid/src/v35.js +44 -0
- package/dist/utils/uuid/src/v4.cjs +40 -0
- package/dist/utils/uuid/src/v4.d.ts +4 -0
- package/dist/utils/uuid/src/v4.js +35 -0
- package/dist/utils/uuid/src/v5.cjs +50 -0
- package/dist/utils/uuid/src/v5.d.ts +9 -0
- package/dist/utils/uuid/src/v5.js +9 -0
- package/dist/utils/uuid/src/v7.cjs +88 -0
- package/dist/utils/uuid/src/v7.d.ts +9 -0
- package/dist/utils/uuid/src/v7.js +82 -0
- package/dist/utils/uuid/src/validate.cjs +10 -0
- package/dist/utils/uuid/src/validate.d.ts +2 -0
- package/dist/utils/uuid/src/validate.js +5 -0
- package/dist/utils/uuid/src/version.cjs +13 -0
- package/dist/utils/uuid/src/version.d.ts +2 -0
- package/dist/utils/uuid/src/version.js +8 -0
- package/dist/utils/worker_threads.browser.cjs +16 -0
- package/dist/utils/worker_threads.browser.d.ts +14 -0
- package/dist/utils/worker_threads.browser.js +13 -0
- package/dist/utils/worker_threads.cjs +16 -0
- package/dist/utils/worker_threads.d.ts +13 -0
- package/dist/utils/worker_threads.js +13 -0
- package/dist/uuid.cjs +2 -2
- package/dist/uuid.js +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Off-thread serialization using Node worker_threads.
|
|
3
|
+
*
|
|
4
|
+
* Gated behind LANGSMITH_PERF_OPTIMIZATION=true. Falls back silently to
|
|
5
|
+
* synchronous serialize() when:
|
|
6
|
+
* - worker_threads is unavailable (browsers, Deno, Bun without compat,
|
|
7
|
+
* Cloudflare Workers, Vercel Edge, React Native)
|
|
8
|
+
* - the worker cannot be constructed (bundler/runtime constraints)
|
|
9
|
+
* - DataCloneError is thrown for a payload containing non-cloneable
|
|
10
|
+
* values (functions, class instances with non-cloneable state, etc.)
|
|
11
|
+
* - the worker crashes or throws
|
|
12
|
+
*
|
|
13
|
+
* Protocol:
|
|
14
|
+
* main -> worker: { id, op, payload }
|
|
15
|
+
* op = "serialize" -> worker returns bytes as a transferable ArrayBuffer
|
|
16
|
+
* worker -> main: { id, bytes?: ArrayBuffer, error?: string }
|
|
17
|
+
*
|
|
18
|
+
* The worker source is inlined as a string so the library bundles cleanly
|
|
19
|
+
* under webpack/esbuild/ncc without requiring a separate asset file.
|
|
20
|
+
*/
|
|
21
|
+
import { Worker as WorkerCtor, WORKER_THREADS_AVAILABLE, } from "./worker_threads.js";
|
|
22
|
+
// The worker script: a self-contained mirror of the hot path of
|
|
23
|
+
// src/utils/fast-safe-stringify/index.ts#serialize(). We deliberately
|
|
24
|
+
// don't import the TS module -- the worker runs as a standalone script.
|
|
25
|
+
const WORKER_SOURCE = /* js */ `
|
|
26
|
+
const { parentPort } = require("worker_threads");
|
|
27
|
+
|
|
28
|
+
const CIRCULAR_REPLACE_NODE = { result: "[Circular]" };
|
|
29
|
+
|
|
30
|
+
function serializeWellKnownTypes(val) {
|
|
31
|
+
if (val && typeof val === "object") {
|
|
32
|
+
if (val instanceof Map) return Object.fromEntries(val);
|
|
33
|
+
if (val instanceof Set) return Array.from(val);
|
|
34
|
+
if (val instanceof Date) return val.toISOString();
|
|
35
|
+
if (val instanceof RegExp) return val.toString();
|
|
36
|
+
if (val instanceof Error) return { name: val.name, message: val.message };
|
|
37
|
+
} else if (typeof val === "bigint") {
|
|
38
|
+
return val.toString();
|
|
39
|
+
}
|
|
40
|
+
return val;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function defaultReplacer(_key, val) {
|
|
44
|
+
return serializeWellKnownTypes(val);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Decirculate in-place: replace circular refs with { result: "[Circular]" }
|
|
48
|
+
// then restore after stringify. Mirrors fast-safe-stringify's decirc().
|
|
49
|
+
const restoreStack = [];
|
|
50
|
+
function decirc(val, k, stack, parent) {
|
|
51
|
+
if (typeof val === "object" && val !== null) {
|
|
52
|
+
for (let i = 0; i < stack.length; i++) {
|
|
53
|
+
if (stack[i] === val) {
|
|
54
|
+
const orig = parent[k];
|
|
55
|
+
parent[k] = CIRCULAR_REPLACE_NODE;
|
|
56
|
+
restoreStack.push([parent, k, orig]);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
stack.push(val);
|
|
61
|
+
if (Array.isArray(val)) {
|
|
62
|
+
for (let i = 0; i < val.length; i++) decirc(val[i], i, stack, val);
|
|
63
|
+
} else {
|
|
64
|
+
const normalized = serializeWellKnownTypes(val);
|
|
65
|
+
// Only recurse into normalized if it's still an object (arrays/objects),
|
|
66
|
+
// else it was replaced with a primitive (e.g. Date -> string).
|
|
67
|
+
if (normalized === val) {
|
|
68
|
+
const keys = Object.keys(val);
|
|
69
|
+
for (let i = 0; i < keys.length; i++) decirc(val[keys[i]], keys[i], stack, val);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
stack.pop();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function serialize(obj) {
|
|
77
|
+
try {
|
|
78
|
+
return JSON.stringify(obj, defaultReplacer);
|
|
79
|
+
} catch (e) {
|
|
80
|
+
if (!String(e && e.message).includes("Converting circular structure to JSON")) {
|
|
81
|
+
return "[Unserializable]";
|
|
82
|
+
}
|
|
83
|
+
decirc(obj, "", [], { "": obj });
|
|
84
|
+
try {
|
|
85
|
+
return JSON.stringify(obj, defaultReplacer);
|
|
86
|
+
} catch (_) {
|
|
87
|
+
return "[unable to serialize, circular reference is too complex to analyze]";
|
|
88
|
+
} finally {
|
|
89
|
+
while (restoreStack.length) {
|
|
90
|
+
const [p, k, v] = restoreStack.pop();
|
|
91
|
+
p[k] = v;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
parentPort.on("message", (msg) => {
|
|
98
|
+
const { id, op, payload } = msg;
|
|
99
|
+
try {
|
|
100
|
+
if (op === "serialize") {
|
|
101
|
+
const str = serialize(payload);
|
|
102
|
+
const buf = Buffer.from(str, "utf8");
|
|
103
|
+
// Slice into its own ArrayBuffer so we can transfer without dragging
|
|
104
|
+
// unrelated bytes from any shared pool buffer.
|
|
105
|
+
const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
|
|
106
|
+
parentPort.postMessage({ id, bytes: ab, length: buf.byteLength }, [ab]);
|
|
107
|
+
} else if (op === "ping") {
|
|
108
|
+
parentPort.postMessage({ id });
|
|
109
|
+
} else {
|
|
110
|
+
parentPort.postMessage({ id, error: "unknown op: " + op });
|
|
111
|
+
}
|
|
112
|
+
} catch (e) {
|
|
113
|
+
parentPort.postMessage({ id, error: String((e && e.message) || e) });
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
`;
|
|
117
|
+
export class SerializeWorker {
|
|
118
|
+
constructor() {
|
|
119
|
+
Object.defineProperty(this, "worker", {
|
|
120
|
+
enumerable: true,
|
|
121
|
+
configurable: true,
|
|
122
|
+
writable: true,
|
|
123
|
+
value: null
|
|
124
|
+
});
|
|
125
|
+
Object.defineProperty(this, "nextId", {
|
|
126
|
+
enumerable: true,
|
|
127
|
+
configurable: true,
|
|
128
|
+
writable: true,
|
|
129
|
+
value: 1
|
|
130
|
+
});
|
|
131
|
+
Object.defineProperty(this, "pending", {
|
|
132
|
+
enumerable: true,
|
|
133
|
+
configurable: true,
|
|
134
|
+
writable: true,
|
|
135
|
+
value: new Map()
|
|
136
|
+
});
|
|
137
|
+
Object.defineProperty(this, "disabled", {
|
|
138
|
+
enumerable: true,
|
|
139
|
+
configurable: true,
|
|
140
|
+
writable: true,
|
|
141
|
+
value: false
|
|
142
|
+
});
|
|
143
|
+
Object.defineProperty(this, "startPromise", {
|
|
144
|
+
enumerable: true,
|
|
145
|
+
configurable: true,
|
|
146
|
+
writable: true,
|
|
147
|
+
value: null
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Try to construct the worker. Returns false if the runtime can't support
|
|
152
|
+
* it -- in that case callers must fall back to synchronous serialization.
|
|
153
|
+
* Kept async so callers don't have to branch on runtime -- the promise
|
|
154
|
+
* resolves synchronously on the microtask queue when the worker module
|
|
155
|
+
* is available, which is the common Node CJS/ESM path.
|
|
156
|
+
*/
|
|
157
|
+
async ensureStarted() {
|
|
158
|
+
if (this.disabled)
|
|
159
|
+
return false;
|
|
160
|
+
if (this.worker !== null)
|
|
161
|
+
return true;
|
|
162
|
+
if (this.startPromise !== null)
|
|
163
|
+
return this.startPromise;
|
|
164
|
+
this.startPromise = this._start();
|
|
165
|
+
try {
|
|
166
|
+
return await this.startPromise;
|
|
167
|
+
}
|
|
168
|
+
finally {
|
|
169
|
+
this.startPromise = null;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
async _start() {
|
|
173
|
+
// In browser / edge builds the `worker_threads` module is swapped with
|
|
174
|
+
// a stub that reports unavailability via the package.json `browser`
|
|
175
|
+
// field. Bail out before touching any Node-only surface.
|
|
176
|
+
if (!WORKER_THREADS_AVAILABLE || WorkerCtor === null) {
|
|
177
|
+
this.disabled = true;
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
try {
|
|
181
|
+
const worker = new WorkerCtor(WORKER_SOURCE, { eval: true });
|
|
182
|
+
worker.on("message", (msg) => {
|
|
183
|
+
const p = this.pending.get(msg.id);
|
|
184
|
+
if (!p)
|
|
185
|
+
return;
|
|
186
|
+
this.pending.delete(msg.id);
|
|
187
|
+
if (msg.error) {
|
|
188
|
+
p.reject(new Error(msg.error));
|
|
189
|
+
}
|
|
190
|
+
else if (msg.bytes && typeof msg.length === "number") {
|
|
191
|
+
p.resolve(new Uint8Array(msg.bytes, 0, msg.length));
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
p.reject(new Error("worker returned malformed message"));
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
worker.on("error", (err) => {
|
|
198
|
+
// Reject all pending and disable; caller will fall back.
|
|
199
|
+
for (const [, p] of this.pending)
|
|
200
|
+
p.reject(err);
|
|
201
|
+
this.pending.clear();
|
|
202
|
+
this.disabled = true;
|
|
203
|
+
this.worker = null;
|
|
204
|
+
});
|
|
205
|
+
worker.on("exit", (code) => {
|
|
206
|
+
// Reject all pending requests regardless of exit code. Even a clean
|
|
207
|
+
// exit (code 0) with in-flight requests means those promises would
|
|
208
|
+
// otherwise hang forever.
|
|
209
|
+
for (const [, p] of this.pending) {
|
|
210
|
+
p.reject(new Error(`worker exited with code ${code}`));
|
|
211
|
+
}
|
|
212
|
+
this.pending.clear();
|
|
213
|
+
this.worker = null;
|
|
214
|
+
});
|
|
215
|
+
// Don't let the worker keep the process alive.
|
|
216
|
+
worker.unref();
|
|
217
|
+
this.worker = worker;
|
|
218
|
+
return true;
|
|
219
|
+
}
|
|
220
|
+
catch {
|
|
221
|
+
this.disabled = true;
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Serialize a payload off-thread. Rejects with DataCloneError (or similar)
|
|
227
|
+
* if the payload contains non-cloneable values -- callers must catch and
|
|
228
|
+
* fall back to synchronous serialize().
|
|
229
|
+
*
|
|
230
|
+
* Resolves with null if the worker subsystem is unavailable entirely,
|
|
231
|
+
* so the caller can fall back without paying try/catch overhead.
|
|
232
|
+
*/
|
|
233
|
+
async serialize(payload) {
|
|
234
|
+
const ok = await this.ensureStarted();
|
|
235
|
+
if (!ok)
|
|
236
|
+
return null;
|
|
237
|
+
const id = this.nextId++;
|
|
238
|
+
return new Promise((resolve, reject) => {
|
|
239
|
+
this.pending.set(id, { resolve, reject });
|
|
240
|
+
try {
|
|
241
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
242
|
+
this.worker.postMessage({ id, op: "serialize", payload });
|
|
243
|
+
}
|
|
244
|
+
catch (e) {
|
|
245
|
+
// postMessage throws synchronously for DataCloneError, unclonable
|
|
246
|
+
// values, detached buffers, etc.
|
|
247
|
+
this.pending.delete(id);
|
|
248
|
+
reject(e);
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
async terminate() {
|
|
253
|
+
if (this.worker) {
|
|
254
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
255
|
+
await this.worker.terminate();
|
|
256
|
+
this.worker = null;
|
|
257
|
+
}
|
|
258
|
+
for (const [, p] of this.pending) {
|
|
259
|
+
p.reject(new Error("worker terminated"));
|
|
260
|
+
}
|
|
261
|
+
this.pending.clear();
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
let sharedWorker = null;
|
|
265
|
+
/**
|
|
266
|
+
* Process-wide shared worker. One worker serves all Client instances to
|
|
267
|
+
* avoid spawning multiple threads per process.
|
|
268
|
+
*/
|
|
269
|
+
export function getSharedSerializeWorker() {
|
|
270
|
+
if (sharedWorker === null)
|
|
271
|
+
sharedWorker = new SerializeWorker();
|
|
272
|
+
return sharedWorker;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Minimum string length (in UTF-16 code units) that justifies the overhead
|
|
276
|
+
* of dispatching serialization to a worker thread.
|
|
277
|
+
*
|
|
278
|
+
* Rationale: V8's postMessage / structuredClone fast-paths large strings
|
|
279
|
+
* across isolates by refcounting their underlying storage rather than
|
|
280
|
+
* copying the bytes. This makes worker offload a big win for payloads
|
|
281
|
+
* dominated by a handful of multi-hundred-KB strings (the classic case is
|
|
282
|
+
* base64-encoded images or audio in LLM messages), but a net loss for
|
|
283
|
+
* payloads whose bulk is structural -- thousands of keys, deep nesting,
|
|
284
|
+
* many small strings -- because every object node must still be walked
|
|
285
|
+
* and cloned.
|
|
286
|
+
*
|
|
287
|
+
* 64KB sits comfortably above typical "chunk of agent state" or "long
|
|
288
|
+
* prompt" values (a few KB) and below typical base64 media payloads
|
|
289
|
+
* (hundreds of KB to several MB).
|
|
290
|
+
*/
|
|
291
|
+
const LARGE_STRING_THRESHOLD = 64 * 1024;
|
|
292
|
+
/**
|
|
293
|
+
* Maximum number of nodes to inspect before giving up and assuming the
|
|
294
|
+
* payload is not worth offloading. Prevents the check itself from becoming
|
|
295
|
+
* expensive on pathologically structural payloads (many thousands of small
|
|
296
|
+
* keys / array elements).
|
|
297
|
+
*
|
|
298
|
+
* When the budget is exhausted without finding a large string we return
|
|
299
|
+
* false (do not offload). This is the conservative choice: such payloads
|
|
300
|
+
* are structural by nature and worker offload empirically regresses them.
|
|
301
|
+
*/
|
|
302
|
+
const NODE_BUDGET = 2048;
|
|
303
|
+
/**
|
|
304
|
+
* Cheap, short-circuiting walk that returns true iff the payload contains
|
|
305
|
+
* at least one string of length >= threshold anywhere in its graph.
|
|
306
|
+
*
|
|
307
|
+
* - Terminates immediately on the first qualifying string.
|
|
308
|
+
* - Caps total nodes visited at `nodeBudget` so cost is bounded for huge
|
|
309
|
+
* structural payloads.
|
|
310
|
+
* - Avoids allocation in the common path: uses an array as a stack and a
|
|
311
|
+
* Set only for cycle detection.
|
|
312
|
+
* - Uses `string.length` (UTF-16 units), not UTF-8 byte length, because
|
|
313
|
+
* that's what V8's string-sharing fast path keys on and because it's
|
|
314
|
+
* an O(1) property access. For ASCII content this is identical to the
|
|
315
|
+
* UTF-8 byte count; for non-ASCII text the two differ by at most 4x,
|
|
316
|
+
* well within the safety margin of the threshold.
|
|
317
|
+
*/
|
|
318
|
+
export function hasLargeString(value, threshold = LARGE_STRING_THRESHOLD, nodeBudget = NODE_BUDGET) {
|
|
319
|
+
if (value === null || typeof value !== "object") {
|
|
320
|
+
return typeof value === "string" && value.length >= threshold;
|
|
321
|
+
}
|
|
322
|
+
const stack = [value];
|
|
323
|
+
const seen = new Set();
|
|
324
|
+
let visited = 0;
|
|
325
|
+
while (stack.length > 0) {
|
|
326
|
+
if (visited++ >= nodeBudget)
|
|
327
|
+
return false;
|
|
328
|
+
const cur = stack.pop();
|
|
329
|
+
if (cur === null || cur === undefined)
|
|
330
|
+
continue;
|
|
331
|
+
const t = typeof cur;
|
|
332
|
+
if (t === "string") {
|
|
333
|
+
if (cur.length >= threshold)
|
|
334
|
+
return true;
|
|
335
|
+
continue;
|
|
336
|
+
}
|
|
337
|
+
if (t !== "object")
|
|
338
|
+
continue;
|
|
339
|
+
const obj = cur;
|
|
340
|
+
if (seen.has(obj))
|
|
341
|
+
continue;
|
|
342
|
+
seen.add(obj);
|
|
343
|
+
// Skip well-known opaque types -- none of their enumerable own
|
|
344
|
+
// properties produce large strings in practice, and ArrayBuffer views
|
|
345
|
+
// would inflate the node budget if iterated element by element.
|
|
346
|
+
/* eslint-disable no-instanceof/no-instanceof */
|
|
347
|
+
if (obj instanceof Date ||
|
|
348
|
+
obj instanceof RegExp ||
|
|
349
|
+
obj instanceof Error ||
|
|
350
|
+
obj instanceof ArrayBuffer ||
|
|
351
|
+
ArrayBuffer.isView(obj)) {
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
if (Array.isArray(obj)) {
|
|
355
|
+
// Iterate in reverse so the first element is popped first (stable
|
|
356
|
+
// left-to-right discovery order, harmless but nice for predictable
|
|
357
|
+
// short-circuits in tests).
|
|
358
|
+
for (let i = obj.length - 1; i >= 0; i--)
|
|
359
|
+
stack.push(obj[i]);
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
if (obj instanceof Map) {
|
|
363
|
+
for (const [, v] of obj)
|
|
364
|
+
stack.push(v);
|
|
365
|
+
continue;
|
|
366
|
+
}
|
|
367
|
+
if (obj instanceof Set) {
|
|
368
|
+
for (const v of obj)
|
|
369
|
+
stack.push(v);
|
|
370
|
+
continue;
|
|
371
|
+
}
|
|
372
|
+
/* eslint-enable no-instanceof/no-instanceof */
|
|
373
|
+
// Push keys in reverse so they pop in declared order. Combined with
|
|
374
|
+
// the similar reverse-push for arrays above, this makes discovery
|
|
375
|
+
// order a stable depth-first walk in source order -- which matters
|
|
376
|
+
// for predictable short-circuit behavior under a node budget.
|
|
377
|
+
const keys = Object.keys(obj);
|
|
378
|
+
for (let i = keys.length - 1; i >= 0; i--) {
|
|
379
|
+
stack.push(obj[keys[i]]);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
return false;
|
|
383
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.version = exports.validate = exports.v7 = exports.v5 = exports.v4 = exports.stringify = exports.parse = exports.NIL = exports.MAX = void 0;
|
|
7
|
+
var max_js_1 = require("./max.cjs");
|
|
8
|
+
Object.defineProperty(exports, "MAX", { enumerable: true, get: function () { return __importDefault(max_js_1).default; } });
|
|
9
|
+
var nil_js_1 = require("./nil.cjs");
|
|
10
|
+
Object.defineProperty(exports, "NIL", { enumerable: true, get: function () { return __importDefault(nil_js_1).default; } });
|
|
11
|
+
var parse_js_1 = require("./parse.cjs");
|
|
12
|
+
Object.defineProperty(exports, "parse", { enumerable: true, get: function () { return __importDefault(parse_js_1).default; } });
|
|
13
|
+
var stringify_js_1 = require("./stringify.cjs");
|
|
14
|
+
Object.defineProperty(exports, "stringify", { enumerable: true, get: function () { return __importDefault(stringify_js_1).default; } });
|
|
15
|
+
var v4_js_1 = require("./v4.cjs");
|
|
16
|
+
Object.defineProperty(exports, "v4", { enumerable: true, get: function () { return __importDefault(v4_js_1).default; } });
|
|
17
|
+
var v5_js_1 = require("./v5.cjs");
|
|
18
|
+
Object.defineProperty(exports, "v5", { enumerable: true, get: function () { return __importDefault(v5_js_1).default; } });
|
|
19
|
+
var v7_js_1 = require("./v7.cjs");
|
|
20
|
+
Object.defineProperty(exports, "v7", { enumerable: true, get: function () { return __importDefault(v7_js_1).default; } });
|
|
21
|
+
var validate_js_1 = require("./validate.cjs");
|
|
22
|
+
Object.defineProperty(exports, "validate", { enumerable: true, get: function () { return __importDefault(validate_js_1).default; } });
|
|
23
|
+
var version_js_1 = require("./version.cjs");
|
|
24
|
+
Object.defineProperty(exports, "version", { enumerable: true, get: function () { return __importDefault(version_js_1).default; } });
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { default as MAX } from "./max.js";
|
|
2
|
+
export { default as NIL } from "./nil.js";
|
|
3
|
+
export { default as parse } from "./parse.js";
|
|
4
|
+
export { default as stringify } from "./stringify.js";
|
|
5
|
+
export type * from "./types.js";
|
|
6
|
+
export { default as v4 } from "./v4.js";
|
|
7
|
+
export { default as v5 } from "./v5.js";
|
|
8
|
+
export { default as v7 } from "./v7.js";
|
|
9
|
+
export { default as validate } from "./validate.js";
|
|
10
|
+
export { default as version } from "./version.js";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { default as MAX } from "./max.js";
|
|
2
|
+
export { default as NIL } from "./nil.js";
|
|
3
|
+
export { default as parse } from "./parse.js";
|
|
4
|
+
export { default as stringify } from "./stringify.js";
|
|
5
|
+
export { default as v4 } from "./v4.js";
|
|
6
|
+
export { default as v5 } from "./v5.js";
|
|
7
|
+
export { default as v7 } from "./v7.js";
|
|
8
|
+
export { default as validate } from "./validate.js";
|
|
9
|
+
export { default as version } from "./version.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default "ffffffff-ffff-ffff-ffff-ffffffffffff";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default "00000000-0000-0000-0000-000000000000";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const validate_js_1 = __importDefault(require("./validate.cjs"));
|
|
7
|
+
function parse(uuid) {
|
|
8
|
+
if (!(0, validate_js_1.default)(uuid)) {
|
|
9
|
+
throw TypeError("Invalid UUID");
|
|
10
|
+
}
|
|
11
|
+
let v;
|
|
12
|
+
return Uint8Array.of((v = parseInt(uuid.slice(0, 8), 16)) >>> 24, (v >>> 16) & 0xff, (v >>> 8) & 0xff, v & 0xff,
|
|
13
|
+
// Parse ........-####-....-....-............
|
|
14
|
+
(v = parseInt(uuid.slice(9, 13), 16)) >>> 8, v & 0xff,
|
|
15
|
+
// Parse ........-....-####-....-............
|
|
16
|
+
(v = parseInt(uuid.slice(14, 18), 16)) >>> 8, v & 0xff,
|
|
17
|
+
// Parse ........-....-....-####-............
|
|
18
|
+
(v = parseInt(uuid.slice(19, 23), 16)) >>> 8, v & 0xff,
|
|
19
|
+
// Parse ........-....-....-....-############
|
|
20
|
+
// (Use "/" to avoid 32-bit truncation when bit-shifting high-order bytes)
|
|
21
|
+
((v = parseInt(uuid.slice(24, 36), 16)) / 0x10000000000) & 0xff, (v / 0x100000000) & 0xff, (v >>> 24) & 0xff, (v >>> 16) & 0xff, (v >>> 8) & 0xff, v & 0xff);
|
|
22
|
+
}
|
|
23
|
+
exports.default = parse;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import validate from "./validate.js";
|
|
2
|
+
function parse(uuid) {
|
|
3
|
+
if (!validate(uuid)) {
|
|
4
|
+
throw TypeError("Invalid UUID");
|
|
5
|
+
}
|
|
6
|
+
let v;
|
|
7
|
+
return Uint8Array.of((v = parseInt(uuid.slice(0, 8), 16)) >>> 24, (v >>> 16) & 0xff, (v >>> 8) & 0xff, v & 0xff,
|
|
8
|
+
// Parse ........-####-....-....-............
|
|
9
|
+
(v = parseInt(uuid.slice(9, 13), 16)) >>> 8, v & 0xff,
|
|
10
|
+
// Parse ........-....-####-....-............
|
|
11
|
+
(v = parseInt(uuid.slice(14, 18), 16)) >>> 8, v & 0xff,
|
|
12
|
+
// Parse ........-....-....-####-............
|
|
13
|
+
(v = parseInt(uuid.slice(19, 23), 16)) >>> 8, v & 0xff,
|
|
14
|
+
// Parse ........-....-....-....-############
|
|
15
|
+
// (Use "/" to avoid 32-bit truncation when bit-shifting high-order bytes)
|
|
16
|
+
((v = parseInt(uuid.slice(24, 36), 16)) / 0x10000000000) & 0xff, (v / 0x100000000) & 0xff, (v >>> 24) & 0xff, (v >>> 16) & 0xff, (v >>> 8) & 0xff, v & 0xff);
|
|
17
|
+
}
|
|
18
|
+
export default parse;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/i;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = rng;
|
|
4
|
+
// RNG values for use in UUID generation. This *must* use a high-quality source
|
|
5
|
+
// of entropy, such as `crypto.getRandomValues()`. And we reuse an array for
|
|
6
|
+
// performance.
|
|
7
|
+
const rnds8 = new Uint8Array(16);
|
|
8
|
+
function rng() {
|
|
9
|
+
return crypto.getRandomValues(rnds8);
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function rng(): Uint8Array<ArrayBuffer>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// RNG values for use in UUID generation. This *must* use a high-quality source
|
|
2
|
+
// of entropy, such as `crypto.getRandomValues()`. And we reuse an array for
|
|
3
|
+
// performance.
|
|
4
|
+
const rnds8 = new Uint8Array(16);
|
|
5
|
+
export default function rng() {
|
|
6
|
+
return crypto.getRandomValues(rnds8);
|
|
7
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
// Adapted from Chris Veness' SHA1 code at
|
|
4
|
+
// http://www.movable-type.co.uk/scripts/sha1.html
|
|
5
|
+
function f(s, x, y, z) {
|
|
6
|
+
switch (s) {
|
|
7
|
+
case 0:
|
|
8
|
+
return (x & y) ^ (~x & z);
|
|
9
|
+
case 1:
|
|
10
|
+
return x ^ y ^ z;
|
|
11
|
+
case 2:
|
|
12
|
+
return (x & y) ^ (x & z) ^ (y & z);
|
|
13
|
+
case 3:
|
|
14
|
+
return x ^ y ^ z;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function ROTL(x, n) {
|
|
18
|
+
return (x << n) | (x >>> (32 - n));
|
|
19
|
+
}
|
|
20
|
+
function sha1(bytes) {
|
|
21
|
+
const K = [0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6];
|
|
22
|
+
const H = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0];
|
|
23
|
+
const newBytes = new Uint8Array(bytes.length + 1);
|
|
24
|
+
newBytes.set(bytes);
|
|
25
|
+
newBytes[bytes.length] = 0x80;
|
|
26
|
+
bytes = newBytes;
|
|
27
|
+
const l = bytes.length / 4 + 2;
|
|
28
|
+
const N = Math.ceil(l / 16);
|
|
29
|
+
const M = new Array(N);
|
|
30
|
+
for (let i = 0; i < N; ++i) {
|
|
31
|
+
const arr = new Uint32Array(16);
|
|
32
|
+
for (let j = 0; j < 16; ++j) {
|
|
33
|
+
arr[j] =
|
|
34
|
+
(bytes[i * 64 + j * 4] << 24) |
|
|
35
|
+
(bytes[i * 64 + j * 4 + 1] << 16) |
|
|
36
|
+
(bytes[i * 64 + j * 4 + 2] << 8) |
|
|
37
|
+
bytes[i * 64 + j * 4 + 3];
|
|
38
|
+
}
|
|
39
|
+
M[i] = arr;
|
|
40
|
+
}
|
|
41
|
+
M[N - 1][14] = ((bytes.length - 1) * 8) / 2 ** 32;
|
|
42
|
+
M[N - 1][14] = Math.floor(M[N - 1][14]);
|
|
43
|
+
M[N - 1][15] = ((bytes.length - 1) * 8) & 0xffffffff;
|
|
44
|
+
for (let i = 0; i < N; ++i) {
|
|
45
|
+
const W = new Uint32Array(80);
|
|
46
|
+
for (let t = 0; t < 16; ++t) {
|
|
47
|
+
W[t] = M[i][t];
|
|
48
|
+
}
|
|
49
|
+
for (let t = 16; t < 80; ++t) {
|
|
50
|
+
W[t] = ROTL(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16], 1);
|
|
51
|
+
}
|
|
52
|
+
let a = H[0];
|
|
53
|
+
let b = H[1];
|
|
54
|
+
let c = H[2];
|
|
55
|
+
let d = H[3];
|
|
56
|
+
let e = H[4];
|
|
57
|
+
for (let t = 0; t < 80; ++t) {
|
|
58
|
+
const s = Math.floor(t / 20);
|
|
59
|
+
const T = (ROTL(a, 5) + f(s, b, c, d) + e + K[s] + W[t]) >>> 0;
|
|
60
|
+
e = d;
|
|
61
|
+
d = c;
|
|
62
|
+
c = ROTL(b, 30) >>> 0;
|
|
63
|
+
b = a;
|
|
64
|
+
a = T;
|
|
65
|
+
}
|
|
66
|
+
H[0] = (H[0] + a) >>> 0;
|
|
67
|
+
H[1] = (H[1] + b) >>> 0;
|
|
68
|
+
H[2] = (H[2] + c) >>> 0;
|
|
69
|
+
H[3] = (H[3] + d) >>> 0;
|
|
70
|
+
H[4] = (H[4] + e) >>> 0;
|
|
71
|
+
}
|
|
72
|
+
// Note: Uint8Array.of() does `& 0xff` for each value
|
|
73
|
+
return Uint8Array.of(H[0] >> 24, H[0] >> 16, H[0] >> 8, H[0], H[1] >> 24, H[1] >> 16, H[1] >> 8, H[1], H[2] >> 24, H[2] >> 16, H[2] >> 8, H[2], H[3] >> 24, H[3] >> 16, H[3] >> 8, H[3], H[4] >> 24, H[4] >> 16, H[4] >> 8, H[4]);
|
|
74
|
+
}
|
|
75
|
+
exports.default = sha1;
|