feat(core): source record snapshots with stable hash and gzipped versions
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
33631aef3c
commit
37a0b0ba94
@@ -0,0 +1,31 @@
|
||||
import { expect, test } from "bun:test";
|
||||
import type { SourceRecord } from "@sttracker/plugin-sdk/types";
|
||||
import { decodeVersion, encodeVersion, hashRecord, normalizeRecord } from "../../src/sync/snapshot.ts";
|
||||
|
||||
const rec = (raw: unknown, entry: Record<string, unknown>): SourceRecord =>
|
||||
({ key: "k", kind: "entry", work: { title: "T", mediaType: "book", externalIds: { a: "1", b: "2" } }, entry, raw }) as SourceRecord;
|
||||
|
||||
test("hash ignores raw payload and key order", async () => {
|
||||
const a = rec({ x: 1 }, { rating: 1, status: "planned" });
|
||||
const b = rec({ y: 2 }, { status: "planned", rating: 1 });
|
||||
expect(await hashRecord(a)).toBe(await hashRecord(b));
|
||||
expect(await hashRecord(a)).toMatch(/^[0-9a-f]{64}$/);
|
||||
});
|
||||
|
||||
test("hash covers normalised fields, deleted and mergedIntoKey", async () => {
|
||||
const base = rec({}, { rating: 1 });
|
||||
const h = await hashRecord(base);
|
||||
expect(await hashRecord(rec({}, { rating: 2 }))).not.toBe(h);
|
||||
expect(await hashRecord({ ...base, deleted: true })).not.toBe(h);
|
||||
expect(await hashRecord({ ...base, mergedIntoKey: "z" })).not.toBe(h);
|
||||
expect(await hashRecord({ ...base, deleted: false })).toBe(h);
|
||||
});
|
||||
|
||||
test("versions round-trip the normalised record and the raw payload", () => {
|
||||
const r = rec({ deep: { list: [1, 2] } }, { rating: 5 });
|
||||
const encoded = encodeVersion(r);
|
||||
expect(typeof encoded).toBe("string");
|
||||
const v = decodeVersion(encoded);
|
||||
expect(v.raw).toEqual({ deep: { list: [1, 2] } });
|
||||
expect(v.normalized).toEqual(normalizeRecord(r));
|
||||
});
|
||||
Reference in New Issue
Block a user