vectorjson 0.2.1 → 0.3.0
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 +101 -1
- package/dist/engine-wasm.generated.d.ts +1 -1
- package/dist/engine.wasm +0 -0
- package/dist/index.d.ts +36 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -5
- package/dist/index.js.map +4 -4
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -308,6 +308,73 @@ parser.onText((text) => thinkingPanel.append(text)); // opt-in
|
|
|
308
308
|
parser.feed(llmOutput);
|
|
309
309
|
```
|
|
310
310
|
|
|
311
|
+
### Field picking — only parse what you need
|
|
312
|
+
|
|
313
|
+
When streaming a large tool call, you often only need 2-3 fields. `pick` tells the parser to skip everything else during byte scanning — skipped fields never allocate JS objects:
|
|
314
|
+
|
|
315
|
+
```js
|
|
316
|
+
import { createParser } from "vectorjson";
|
|
317
|
+
|
|
318
|
+
const parser = createParser({ pick: ["name", "age"] });
|
|
319
|
+
parser.feed('{"name":"Alice","age":30,"bio":"...10KB of text...","metadata":{}}');
|
|
320
|
+
parser.getValue(); // { name: "Alice", age: 30 } — bio and metadata never materialized
|
|
321
|
+
parser.destroy();
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
Nested paths work with dot notation:
|
|
325
|
+
|
|
326
|
+
```js
|
|
327
|
+
const parser = createParser({ pick: ["user.name", "user.age"] });
|
|
328
|
+
parser.feed('{"user":{"name":"Bob","age":25,"role":"admin"},"extra":"data"}');
|
|
329
|
+
parser.getValue(); // { user: { name: "Bob", age: 25 } }
|
|
330
|
+
parser.destroy();
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### `for await` — pull-based streaming from any source
|
|
334
|
+
|
|
335
|
+
Pass a `source` (ReadableStream or AsyncIterable) and iterate with `for await`. Each iteration yields the growing partial value:
|
|
336
|
+
|
|
337
|
+
```js
|
|
338
|
+
import { createParser } from "vectorjson";
|
|
339
|
+
|
|
340
|
+
const parser = createParser({ source: response.body });
|
|
341
|
+
|
|
342
|
+
for await (const partial of parser) {
|
|
343
|
+
console.log(partial);
|
|
344
|
+
// { name: "Ali" }
|
|
345
|
+
// { name: "Alice" }
|
|
346
|
+
// { name: "Alice", age: 30 }
|
|
347
|
+
}
|
|
348
|
+
// Parser auto-destroys when the source ends or you break out of the loop
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
Combine `pick` + `source` for minimal allocation streaming:
|
|
352
|
+
|
|
353
|
+
```js
|
|
354
|
+
const parser = createParser({
|
|
355
|
+
pick: ["name", "age"],
|
|
356
|
+
source: response.body,
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
for await (const partial of parser) {
|
|
360
|
+
updateUI(partial); // only picked fields, growing incrementally
|
|
361
|
+
}
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
Works with any async source — fetch body, WebSocket wrapper, SSE adapter, or a plain async generator:
|
|
365
|
+
|
|
366
|
+
```js
|
|
367
|
+
async function* chunks() {
|
|
368
|
+
yield '{"status":"';
|
|
369
|
+
yield 'ok","data":';
|
|
370
|
+
yield '[1,2,3]}';
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
for await (const partial of createParser({ source: chunks() })) {
|
|
374
|
+
console.log(partial);
|
|
375
|
+
}
|
|
376
|
+
```
|
|
377
|
+
|
|
311
378
|
### Schema validation
|
|
312
379
|
|
|
313
380
|
Validate and auto-infer types with Zod, Valibot, ArkType, or any lib with `.safeParse()`. Works on all three APIs:
|
|
@@ -449,8 +516,33 @@ interface ParseResult {
|
|
|
449
516
|
- **`invalid`** — broken JSON
|
|
450
517
|
|
|
451
518
|
### `createParser(schema?): StreamingParser<T>`
|
|
519
|
+
### `createParser(options?): StreamingParser<T>`
|
|
520
|
+
|
|
521
|
+
Each `feed()` processes only new bytes — O(n) total. Three overloads:
|
|
522
|
+
|
|
523
|
+
```ts
|
|
524
|
+
createParser(); // no validation
|
|
525
|
+
createParser(schema); // schema validation (Zod, Valibot, etc.)
|
|
526
|
+
createParser({ pick, schema, source }); // options object
|
|
527
|
+
```
|
|
452
528
|
|
|
453
|
-
|
|
529
|
+
**Options object:**
|
|
530
|
+
|
|
531
|
+
```ts
|
|
532
|
+
interface CreateParserOptions<T = unknown> {
|
|
533
|
+
pick?: string[]; // only include these fields (dot-separated paths)
|
|
534
|
+
schema?: ZodLike<T>; // validate on complete
|
|
535
|
+
source?: ReadableStream<Uint8Array> | AsyncIterable<Uint8Array | string>;
|
|
536
|
+
}
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
When `source` is provided, the parser becomes async-iterable — use `for await` to consume partial values:
|
|
540
|
+
|
|
541
|
+
```ts
|
|
542
|
+
for await (const partial of createParser({ source: stream, pick: ["name"] })) {
|
|
543
|
+
console.log(partial); // growing object with only picked fields
|
|
544
|
+
}
|
|
545
|
+
```
|
|
454
546
|
|
|
455
547
|
```ts
|
|
456
548
|
interface StreamingParser<T = unknown> {
|
|
@@ -460,6 +552,7 @@ interface StreamingParser<T = unknown> {
|
|
|
460
552
|
getRawBuffer(): ArrayBuffer | null; // transferable buffer for Worker postMessage
|
|
461
553
|
getStatus(): FeedStatus;
|
|
462
554
|
destroy(): void;
|
|
555
|
+
[Symbol.asyncIterator](): AsyncIterableIterator<T | undefined>; // requires source
|
|
463
556
|
}
|
|
464
557
|
type FeedStatus = "incomplete" | "complete" | "error" | "end_early";
|
|
465
558
|
```
|
|
@@ -644,6 +737,13 @@ node --expose-gc bench/deep-compare.mjs # deep compare: VJ vs JS deepEq
|
|
|
644
737
|
|
|
645
738
|
Benchmark numbers in this README were measured on GitHub Actions (Ubuntu, x86_64). Results vary by machine but relative speedups are consistent.
|
|
646
739
|
|
|
740
|
+
## Acknowledgments
|
|
741
|
+
|
|
742
|
+
VectorJSON is built on the work of:
|
|
743
|
+
|
|
744
|
+
- **[zimdjson](https://github.com/EzequielRamis/zimdjson)** by Ezequiel Ramis — a Zig port of simdjson that powers the WASM engine
|
|
745
|
+
- **[simdjson](https://simdjson.org/)** by Daniel Lemire & Geoff Langdale — the SIMD-accelerated JSON parsing research that started it all
|
|
746
|
+
|
|
647
747
|
## License
|
|
648
748
|
|
|
649
749
|
Apache-2.0
|