| 1 | test("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 | |
| 24 | test("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 | |
| 32 | test("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 | |
| 40 | function 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 | |
| 54 | import assert from "node:assert/strict"; |
| 55 | import { test } from "vitest"; |
| 56 | import * as incremental from "../incremental.ts"; |