mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-05 23:37:25 +00:00
75 lines
3.7 KiB
TypeScript
75 lines
3.7 KiB
TypeScript
// `defineTable` (slice 6a §5): what a declaration materializes, the checks it makes, and its fingerprint.
|
|
|
|
import { describe, expect, it } from "vitest";
|
|
import { int, obj, opt, str } from "../../src/contracts/index.ts";
|
|
import { json } from "../../src/store/json-column.ts";
|
|
import { defineTable, type KeyOf } from "../../src/store/table.ts";
|
|
|
|
const columns = { id: str(), path: str(), at: int(), note: opt(str()), meta: json(obj({}), { version: 1 }) };
|
|
|
|
describe("defineTable", () => {
|
|
it("materializes columns, key, indexes and the record", () => {
|
|
const Edits = defineTable("edits", { version: 2, columns, key: ["id"], indexes: { by_path: ["path", "at"] } });
|
|
expect(Edits.name).toBe("edits");
|
|
expect(Edits.version).toBe(2);
|
|
expect(Edits.key).toEqual(["id"]);
|
|
expect([...Edits.indexes]).toEqual([["by_path", ["path", "at"]]]);
|
|
expect(Object.keys(Edits.record)).toEqual(["id", "path", "at", "note", "meta"]);
|
|
expect(Edits.rows.physical).toEqual(["id", "path", "at", "note", "meta", "meta$v", "$v"]);
|
|
});
|
|
|
|
it("checks the table name, the version, key, index names and index columns", () => {
|
|
expect(() => defineTable("Edits", { version: 1, columns, key: ["id"] })).toThrow("expected lowercase");
|
|
expect(() => defineTable("a:b", { version: 1, columns, key: ["id"] })).toThrow("expected lowercase");
|
|
expect(defineTable("@pi/file-history.edits", { version: 1, columns, key: ["id"] }).name).toBe(
|
|
"@pi/file-history.edits",
|
|
);
|
|
expect(() => defineTable("edits", { version: 0, columns, key: ["id"] })).toThrow("positive integer");
|
|
expect(() => defineTable("edits", { version: 1, columns, key: [] })).toThrow("no column");
|
|
expect(() => defineTable("edits", { version: 1, columns, key: ["note" as "id"] })).toThrow(
|
|
"non-opt str() or int()",
|
|
);
|
|
expect(() => defineTable("edits", { version: 1, columns, key: ["meta" as "id"] })).toThrow(
|
|
"non-opt str() or int()",
|
|
);
|
|
expect(() => defineTable("edits", { version: 1, columns, key: ["id", "id"] })).toThrow("occurs twice");
|
|
expect(() => defineTable("edits", { version: 1, columns, key: ["nope" as "id"] })).toThrow('no column "nope"');
|
|
expect(() => defineTable("edits", { version: 1, columns, key: ["id"], indexes: { ByPath: ["path"] } })).toThrow(
|
|
"[a-z0-9_]+",
|
|
);
|
|
expect(() =>
|
|
defineTable("edits", { version: 1, columns, key: ["id"], indexes: { by: ["note" as "path"] } }),
|
|
).toThrow("non-opt");
|
|
});
|
|
|
|
it("fingerprints columns, key and indexes, not their declaration order", () => {
|
|
const a = defineTable("edits", { version: 1, columns, key: ["id"], indexes: { x: ["path"], y: ["at"] } });
|
|
const reordered = { meta: columns.meta, note: columns.note, at: columns.at, path: columns.path, id: columns.id };
|
|
const b = defineTable("edits", {
|
|
version: 1,
|
|
columns: reordered,
|
|
key: ["id"],
|
|
indexes: { y: ["at"], x: ["path"] },
|
|
});
|
|
expect(b.fingerprint).toBe(a.fingerprint);
|
|
expect(defineTable("edits", { version: 1, columns, key: ["id"] }).fingerprint).not.toBe(a.fingerprint);
|
|
expect(
|
|
defineTable("edits", { version: 1, columns, key: ["id", "at"], indexes: { x: ["path"], y: ["at"] } })
|
|
.fingerprint,
|
|
).not.toBe(a.fingerprint);
|
|
const otherMeta = { ...columns, meta: json(obj({ a: int() }), { version: 1 }) };
|
|
expect(
|
|
defineTable("edits", { version: 1, columns: otherMeta, key: ["id"], indexes: { x: ["path"], y: ["at"] } })
|
|
.fingerprint,
|
|
).not.toBe(a.fingerprint);
|
|
});
|
|
});
|
|
|
|
describe("keys", () => {
|
|
it("type an int() key column as a number and a str() one as a string (tutorial, 2026-11-03)", () => {
|
|
const byNumber = { id: int(), text: str() };
|
|
const key: KeyOf<typeof byNumber, ["id"]> = { id: 7 };
|
|
const mixed: KeyOf<typeof columns, ["id", "at"]> = { id: "a", at: 1 };
|
|
expect([key, mixed]).toEqual([{ id: 7 }, { id: "a", at: 1 }]);
|
|
});
|
|
});
|