import { describe, expect, it } from "vitest"; import { DATA_ADAPTERS } from "../../src/core/adapters"; import { EXPORT_ADAPTERS, convertDocument } from "../../src/core/convert"; import { applyNodeEdit, parseEditValue } from "../../src/core/edit"; import { normalizeValue } from "../../src/core/model"; import { IMPORT_ADAPTERS, parseDataDocument } from "../../src/core/parse"; import { inferSchema, serializeSchema } from "../../src/core/schema"; import { DATA_FORMATS } from "../../src/core/types"; describe("modular adapters", () => { it("has an explicit import and export implementation for every descriptor", () => { expect(DATA_ADAPTERS.map((adapter) => adapter.format)).toEqual( DATA_FORMATS, ); expect(Object.keys(IMPORT_ADAPTERS)).toEqual([...DATA_FORMATS]); expect(Object.keys(EXPORT_ADAPTERS)).toEqual([...DATA_FORMATS]); }); }); describe("loss-aware schema inference", () => { it("merges record samples, presence and exact numeric representation", () => { const document = parseDataDocument({ source: '{"people":[{"id":9007199254740993123456789,"name":"Ada"},{"id":2,"nickname":null}]}', format: "json", }); const inference = inferSchema(document.root); expect(inference.fields).toEqual( expect.arrayContaining([ expect.objectContaining({ pointer: "/people/*/id", required: true, types: ["integer"], }), expect.objectContaining({ pointer: "/people/*/name", required: false }), expect.objectContaining({ pointer: "/people/*/nickname", nullable: true, }), ]), ); const schema = JSON.parse(serializeSchema(inference)) as Record< string, unknown >; expect(schema.$schema).toBe("https://json-schema.org/draft/2020-12/schema"); expect(JSON.stringify(schema)).toContain("9007199254740993123456789"); }); it("enforces the field budget across nested objects", () => { const branch = (prefix: string) => Object.fromEntries( Array.from({ length: 3_000 }, (_, index) => [ `${prefix}${index}`, index, ]), ); const inference = inferSchema( normalizeValue({ left: branch("a"), right: branch("b") }), ); expect(inference.fields).toHaveLength(5_000); expect(inference.truncated).toBe(true); }); }); describe("reviewable structural editing", () => { const document = parseDataDocument({ source: '{"items":[1,2],"name":"before"}', format: "json", }); it("uses strict scalar syntax and immutable RFC 6901 operations", () => { const replaced = applyNodeEdit(document.root, { operation: "replace", pointer: "/name", value: parseEditValue("string", "after"), }); const inserted = applyNodeEdit(replaced, { operation: "add", pointer: "/items/1", value: parseEditValue("number", "9007199254740993123456789"), }); expect( convertDocument({ ...document, root: inserted }, "json").text, ).toContain("9007199254740993123456789"); expect(convertDocument(document, "json").text).toContain( '"name": "before"', ); expect(() => parseEditValue("number", "01")).toThrow(/strict JSON/iu); expect(() => applyNodeEdit(document.root, { operation: "add", pointer: "/__proto__", value: parseEditValue("null", ""), }), ).toThrow(/prohibited/iu); }); it("exposes serialization loss before an edit is applied", () => { const toml = parseDataDocument({ source: "answer = 42\n", format: "toml", }); const edited = applyNodeEdit(toml.root, { operation: "add", pointer: "/missing", value: parseEditValue("null", ""), }); expect(convertDocument({ ...toml, root: edited }, "toml").events).toEqual( expect.arrayContaining([ expect.objectContaining({ code: "toml.null", severity: "loss" }), ]), ); }); });