1test("values round trip through the database, with nested bytes stored raw", () => {
2 const db = new incremental.Database(null);
3 const value = {
4 text: "hello",
5 number: Infinity,
6 negativeZero: -0,
7 missing: undefined,
8 when: new Date("2024-01-02T03:04:05.000Z"),
9 set: new Set<incremental.Serializable>([1, "two"]),
10 map: new Map<incremental.Serializable, incremental.Serializable>([["three", 3], [4, "four"]]),
11 image: { width: 2, height: 1, pixels: new Uint8Array([4, 5, 6, 7]) },
12 nested: { $clover: "escaped", blob: new Uint8Array([7, 8, 9]) },
13 } satisfies incremental.Serializable;
14 const id = write(db, "value", value);
15
16 const roundTrip = db.readValue(id) as typeof value;
17 assert.deepEqual(roundTrip, value);
18 assert.notEqual(roundTrip, value);
19 assert.ok(Object.is(roundTrip.negativeZero, -0));
20 const blobs = db.sql.prepare("select content from blobs order by idx").all() as Array<{ content: Uint8Array }>;
21 assert.deepEqual(blobs.map((blob) => Array.from(blob.content)), [[4, 5, 6, 7], [7, 8, 9]]);
22});
23
24test("strings and bytes at the top level are stored as is", () => {
25 const db = new incremental.Database(null);
26 assert.equal(db.readValue(write(db, "string", "<p>hi</p>")), "<p>hi</p>");
27 assert.deepEqual(db.readValue(write(db, "bytes", new Uint8Array([1, 2]))), new Uint8Array([1, 2]));
28 const types = db.sql.prepare("select type from steps order by id").all() as Array<{ type: string }>;
29 assert.deepEqual(types.map((row) => row.type), ["s", "b"]);
30});
31
32test("a key named __proto__ stays a key", () => {
33 const db = new incremental.Database(null);
34 const value = JSON.parse("{\"__proto__\": {\"x\": 1}, \"y\": 2}") as incremental.Serializable;
35 const roundTrip = db.readValue(write(db, "proto", value)) as object;
36 assert.deepEqual(Object.keys(roundTrip), ["__proto__", "y"]);
37 assert.equal(Object.getPrototypeOf(roundTrip), Object.prototype);
38});
39
40function write(db: incremental.Database, key: string, value: incremental.Serializable) {
41 return db.writeStep({
42 key,
43 label: key,
44 hash: key,
45 error: null,
46 value,
47 errors: [],
48 inputs: [],
49 steps: [],
50 outputs: [],
51 });
52}
53
54import assert from "node:assert/strict";
55import { test } from "vitest";
56import * as incremental from "../incremental.ts";