Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/crosswalk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ export type OneWayRule = z.infer<typeof OneWayRuleSchema>;
export const CrosswalkSchema: z.ZodType<Crosswalk> & { is: (value: unknown) => value is Crosswalk } = define(
z
.object({
$schema: z.string().optional(),
source: z.string(),
target: z.string(),
rules: z.array(TwoWayRuleSchema).default([]),
Expand All @@ -219,6 +220,8 @@ function keptPath(path: string): MoveRule {
return { op: "move", from: path, to: path };
}
export interface Crosswalk {
/** The address of the JSON Schema the document declares itself written against, which editors read to validate and complete it. It has no part in encoding, decoding or validation. */
readonly $schema?: string | undefined;
readonly source: string;
readonly target: string;
readonly rules: readonly TwoWayRule[];
Expand Down
14 changes: 14 additions & 0 deletions src/crosswalk.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,20 @@ describe("parseCrosswalk", () => {
});
});

describe("$schema", () => {
it("is accepted as the address of the document's own schema and carries no rule", () => {
const parsed = parseCrosswalk({ $schema: "https://example.com/crossmap.schema.json", source: "a", target: "b", keep: ["x"] });
expect(parsed.$schema).toBe("https://example.com/crossmap.schema.json");
expect(parsed.rules).toEqual([{ op: "move", from: "x", to: "x" }]);
expect(validateCrosswalk(parsed)).toEqual([]);
});

it("is optional and must be text", () => {
expect(parseCrosswalk({ source: "a", target: "b" }).$schema).toBeUndefined();
expect(() => parseCrosswalk({ $schema: 1, source: "a", target: "b" })).toThrow(CrosswalkSyntaxError);
});
});

describe("keep", () => {
it("reads each kept path as an identity move appended after the rules, in order", () => {
const parsed = parseCrosswalk({ source: "a", target: "b", rules: [{ op: "scale", from: "w", to: "weight", factor: 2 }], keep: ["meta", "nodes[].id"] });
Expand Down