refactor: update CSV comment syntax for declarations

Update the syntax for type declarations and reverse reference
declarations in CSV files to be more explicit.

- Change type declarations from `# TypeName := schema` to
  `# type TypeName = schema`
- Change reverse reference declarations from `# fieldName :=
  ~table(key)`
  to `# inject fieldName = ~table(key)`
This commit is contained in:
hypercross 2026-04-21 14:36:02 +08:00
parent e5332f506d
commit 721544e7b2
5 changed files with 43 additions and 46 deletions

View File

@ -1,4 +1,4 @@
# orders := ~order_rev(user) # inject orders = ~order_rev(user)
id,name id,name
string,string string,string
u01,Alice u01,Alice

1 # orders := ~order_rev(user) # inject orders = ~order_rev(user)
2 id,name id,name
3 string,string string,string
4 u01,Alice u01,Alice

View File

@ -247,7 +247,7 @@ describe("csvToModule - reverse reference output", () => {
const csv = [ const csv = [
"id,name", "id,name",
"string,string", "string,string",
"# orders := ~orders(customer)", "# inject orders = ~orders(customer)",
"1,Alice", "1,Alice",
].join("\n"); ].join("\n");
@ -263,7 +263,7 @@ describe("csvToModule - reverse reference output", () => {
const csv = [ const csv = [
"id,name", "id,name",
"string,string", "string,string",
"# orders := ~orders(customer)?", "# inject orders = ~orders(customer)?",
"1,Alice", "1,Alice",
].join("\n"); ].join("\n");
@ -278,7 +278,7 @@ describe("csvToModule - reverse reference output", () => {
const csv = [ const csv = [
"id,name", "id,name",
"string,string", "string,string",
"# orders := ~orders(customer)", "# inject orders = ~orders(customer)",
"1,Alice", "1,Alice",
].join("\n"); ].join("\n");
@ -291,7 +291,7 @@ describe("csvToModule - reverse reference output", () => {
const csv = [ const csv = [
"id,name", "id,name",
"string,string", "string,string",
"# children := ~self_ref(parent)", "# inject children = ~self_ref(parent)",
"1,Root", "1,Root",
"2,Child", "2,Child",
].join("\n"); ].join("\n");
@ -311,7 +311,7 @@ describe("csvToModule - reverse reference output", () => {
const csv = [ const csv = [
"id,name", "id,name",
"string,string", "string,string",
"# orders := ~orders(customer)", "# inject orders = ~orders(customer)",
"1,Alice", "1,Alice",
].join("\n"); ].join("\n");
@ -329,7 +329,7 @@ describe("csvToModule - reverse reference output", () => {
const csv = [ const csv = [
"id,name", "id,name",
"string,string", "string,string",
"# orders := ~orders(customer)?", "# inject orders = ~orders(customer)?",
"1,Alice", "1,Alice",
].join("\n"); ].join("\n");
@ -346,7 +346,7 @@ describe("csvToModule - reverse reference output", () => {
const csv = [ const csv = [
"id,name,manager", "id,name,manager",
"string,string,@users", "string,string,@users",
"# reports := ~users(manager)", "# inject reports = ~users(manager)",
"1,Alice,2", "1,Alice,2",
"2,Bob,", "2,Bob,",
].join("\n"); ].join("\n");
@ -365,7 +365,7 @@ describe("csvToModule - reverse reference output", () => {
const csv = [ const csv = [
"id,name,creator", "id,name,creator",
"string,string,@users", "string,string,@users",
"# reviews := ~users(reviewer)", "# inject reviews = ~users(reviewer)",
"1,Doc,1", "1,Doc,1",
].join("\n"); ].join("\n");

View File

@ -20,7 +20,7 @@ describe("parseCsv - reverse reference resolution", () => {
const csv = [ const csv = [
"id,name", "id,name",
"string,string", "string,string",
"# orders := ~rev_orders(customer)", "# inject orders = ~rev_orders(customer)",
"1,Alice", "1,Alice",
"2,Bob", "2,Bob",
].join("\n"); ].join("\n");
@ -57,7 +57,7 @@ describe("parseCsv - reverse reference resolution", () => {
const csv = [ const csv = [
"id,name", "id,name",
"string,string", "string,string",
"# orders := ~rev_orders(customer)", "# inject orders = ~rev_orders(customer)",
"1,Alice", "1,Alice",
"99,Nobody", "99,Nobody",
].join("\n"); ].join("\n");
@ -79,7 +79,7 @@ describe("parseCsv - reverse reference resolution", () => {
const csv = [ const csv = [
"id,name", "id,name",
"string,string", "string,string",
"# orders := ~orders(customer)?", "# inject orders = ~orders(customer)?",
"99,Nobody", "99,Nobody",
].join("\n"); ].join("\n");
@ -96,7 +96,7 @@ describe("parseCsv - reverse reference resolution", () => {
const csv = [ const csv = [
"id,name", "id,name",
"string,string", "string,string",
"# orders := ~orders(customer)", "# inject orders = ~orders(customer)",
"1,Alice", "1,Alice",
].join("\n"); ].join("\n");
@ -124,7 +124,7 @@ describe("parseCsv - reverse reference resolution", () => {
const csv = [ const csv = [
"id,name", "id,name",
"string,string", "string,string",
"# orders := ~orders(customer)", "# inject orders = ~orders(customer)",
"1,Alice", "1,Alice",
].join("\n"); ].join("\n");
@ -140,8 +140,8 @@ describe("parseCsv - reverse reference resolution", () => {
const csv = [ const csv = [
"id,name", "id,name",
"string,string", "string,string",
"# orders := ~orders(customer)", "# inject orders = ~orders(customer)",
"# parts := ~parts(user)", "# inject parts = ~parts(user)",
"1,Alice", "1,Alice",
].join("\n"); ].join("\n");
@ -162,7 +162,7 @@ describe("parseCsv - reverse reference resolution", () => {
"id,name", "id,name",
"string,string", "string,string",
"# This is just a comment", "# This is just a comment",
"# orders := ~orders(customer)", "# inject orders = ~orders(customer)",
"1,Alice", "1,Alice",
].join("\n"); ].join("\n");
@ -190,7 +190,7 @@ describe("parseCsv - reverse reference resolution", () => {
const csv = [ const csv = [
"# id: id of user", "# id: id of user",
"# orders: list of related orders", "# orders: list of related orders",
"# orders := ~order(user)", "# inject orders = ~order(user)",
"id,name", "id,name",
"string,string", "string,string",
"u01,Alice", "u01,Alice",
@ -225,7 +225,7 @@ describe("parseCsv - reverse reference with resolveReferences: false", () => {
const csv = [ const csv = [
"id,name", "id,name",
"string,string", "string,string",
"# orders := ~orders(customer)", "# inject orders = ~orders(customer)",
"1,Alice", "1,Alice",
].join("\n"); ].join("\n");
@ -255,7 +255,7 @@ describe("parseCsv - reverse reference with resolveReferences: false", () => {
const csv = [ const csv = [
"id,name", "id,name",
"string,string", "string,string",
"# nonexistent := ~nonexistent(some_key)", "# inject nonexistent = ~nonexistent(some_key)",
"1,Alice", "1,Alice",
].join("\n"); ].join("\n");

View File

@ -6,7 +6,7 @@ import { fixturesDir } from "../test-utils";
describe("parseCsv - type declarations", () => { describe("parseCsv - type declarations", () => {
it("should parse type declaration from comment line", () => { it("should parse type declaration from comment line", () => {
const csv = [ const csv = [
"# Trigger := 'onPlay' | 'onDraw' | 'onDiscard'", "# type Trigger = 'onPlay' | 'onDraw' | 'onDiscard'",
"id,trigger", "id,trigger",
"string,Trigger", "string,Trigger",
"attack,onPlay", "attack,onPlay",
@ -30,7 +30,7 @@ describe("parseCsv - type declarations", () => {
it("should use declared type as column schema", () => { it("should use declared type as column schema", () => {
const csv = [ const csv = [
"# Trigger := 'onPlay' | 'onDraw' | 'onDiscard'", "# type Trigger = 'onPlay' | 'onDraw' | 'onDiscard'",
"id,trigger", "id,trigger",
"string,Trigger", "string,Trigger",
"attack,onPlay", "attack,onPlay",
@ -44,7 +44,7 @@ describe("parseCsv - type declarations", () => {
it("should include declared types in type definition", () => { it("should include declared types in type definition", () => {
const csv = [ const csv = [
"# Trigger := 'onPlay' | 'onDraw' | 'onDiscard'", "# type Trigger = 'onPlay' | 'onDraw' | 'onDiscard'",
"id,trigger", "id,trigger",
"string,Trigger", "string,Trigger",
"attack,onPlay", "attack,onPlay",
@ -64,8 +64,8 @@ describe("parseCsv - type declarations", () => {
it("should parse multiple type declarations", () => { it("should parse multiple type declarations", () => {
const csv = [ const csv = [
"# Trigger := 'onPlay' | 'onDraw'", "# type Trigger = 'onPlay' | 'onDraw'",
"# Status := 'active' | 'inactive'", "# type Status = 'active' | 'inactive'",
"id,trigger,status", "id,trigger,status",
"string,Trigger,Status", "string,Trigger,Status",
"attack,onPlay,active", "attack,onPlay,active",
@ -80,8 +80,8 @@ describe("parseCsv - type declarations", () => {
it("should include multiple type declarations in type definition", () => { it("should include multiple type declarations in type definition", () => {
const csv = [ const csv = [
"# Trigger := 'onPlay' | 'onDraw'", "# type Trigger = 'onPlay' | 'onDraw'",
"# Status := 'active' | 'inactive'", "# type Status = 'active' | 'inactive'",
"id,trigger,status", "id,trigger,status",
"string,Trigger,Status", "string,Trigger,Status",
"attack,onPlay,active", "attack,onPlay,active",
@ -100,7 +100,7 @@ describe("parseCsv - type declarations", () => {
it("should ignore comment lines that are not type declarations", () => { it("should ignore comment lines that are not type declarations", () => {
const csv = [ const csv = [
"# This is just a comment", "# This is just a comment",
"# Trigger := 'onPlay' | 'onDraw'", "# type Trigger = 'onPlay' | 'onDraw'",
"id,trigger", "id,trigger",
"string,Trigger", "string,Trigger",
"attack,onPlay", "attack,onPlay",
@ -114,7 +114,7 @@ describe("parseCsv - type declarations", () => {
it("should handle type declaration with array schema", () => { it("should handle type declaration with array schema", () => {
const csv = [ const csv = [
"# Tags := string[]", "# type Tags = string[]",
"id,tags", "id,tags",
"string,Tags", "string,Tags",
"1,[dev; admin; user]", "1,[dev; admin; user]",
@ -129,7 +129,7 @@ describe("parseCsv - type declarations", () => {
it("should include type declaration before table type in output", () => { it("should include type declaration before table type in output", () => {
const csv = [ const csv = [
"# Status := 'active' | 'inactive'", "# type Status = 'active' | 'inactive'",
"id,status", "id,status",
"string,Status", "string,Status",
"1,active", "1,active",
@ -150,7 +150,7 @@ describe("parseCsv - type declarations", () => {
it("should work with type declarations alongside reverse references", () => { it("should work with type declarations alongside reverse references", () => {
const csv = [ const csv = [
"# Trigger := 'onPlay' | 'onDraw'", "# type Trigger = 'onPlay' | 'onDraw'",
"id,trigger", "id,trigger",
"string,Trigger", "string,Trigger",
"attack,onPlay", "attack,onPlay",
@ -164,8 +164,8 @@ describe("parseCsv - type declarations", () => {
it("should resolve type references inside tuple type declarations", () => { it("should resolve type references inside tuple type declarations", () => {
const csv = [ const csv = [
"# Trigger := 'onPlay' | 'onDraw' | 'onDiscard'", "# type Trigger = 'onPlay' | 'onDraw' | 'onDiscard'",
"# Effect := [Trigger; @effect; int]", "# type Effect = [Trigger; @effect; int]",
"id,trigger", "id,trigger",
"string,Trigger", "string,Trigger",
"attack,onPlay", "attack,onPlay",
@ -182,8 +182,8 @@ describe("parseCsv - type declarations", () => {
it("should include resolved type references in generated type definition", () => { it("should include resolved type references in generated type definition", () => {
const csv = [ const csv = [
"# Trigger := 'onPlay' | 'onDraw' | 'onDiscard'", "# type Trigger = 'onPlay' | 'onDraw' | 'onDiscard'",
"# Effect := [Trigger; @effect; int]", "# type Effect = [Trigger; @effect; int]",
"id,trigger", "id,trigger",
"string,Trigger", "string,Trigger",
"attack,onPlay", "attack,onPlay",
@ -206,7 +206,7 @@ describe("parseCsv - type declarations", () => {
describe("parseCsv - type declarations with resolveReferences: false", () => { describe("parseCsv - type declarations with resolveReferences: false", () => {
it("should populate typeDeclarations even when resolveReferences is false", () => { it("should populate typeDeclarations even when resolveReferences is false", () => {
const csv = [ const csv = [
"# Trigger := 'onPlay' | 'onDraw'", "# type Trigger = 'onPlay' | 'onDraw'",
"id,trigger", "id,trigger",
"string,Trigger", "string,Trigger",
"attack,onPlay", "attack,onPlay",

View File

@ -1,7 +1,4 @@
import type { import type { Schema, ReverseReferenceSchema } from "../types.js";
Schema,
ReverseReferenceSchema,
} from "../types.js";
import { parseSchema } from "../parser.js"; import { parseSchema } from "../parser.js";
export interface ReverseReferenceDeclaration { export interface ReverseReferenceDeclaration {
@ -19,7 +16,7 @@ export interface TypeDeclaration {
/** /**
* Parse a type declaration from a comment line. * Parse a type declaration from a comment line.
* Format: # TypeName := schema * Format: # type TypeName = schema
* Returns null if the line is not a type declaration. * Returns null if the line is not a type declaration.
*/ */
export function parseTypeDeclaration( export function parseTypeDeclaration(
@ -32,8 +29,8 @@ export function parseTypeDeclaration(
const content = trimmed.slice(commentChar.length).trim(); const content = trimmed.slice(commentChar.length).trim();
// Match pattern: TypeName := schema // Match pattern: type TypeName = schema
const match = content.match(/^([A-Z][a-zA-Z0-9]*)\s*:=\s*(.+)$/); const match = content.match(/^type\s+([A-Z][a-zA-Z0-9]*)\s*=\s*(.+)$/);
if (!match) return null; if (!match) return null;
const [, typeName, schemaString] = match; const [, typeName, schemaString] = match;
@ -214,7 +211,7 @@ export function resolveTypeDeclarationSchema(
/** /**
* Parse a reverse reference declaration from a comment line. * Parse a reverse reference declaration from a comment line.
* Format: # fieldName := ~tableName(foreignKey) * Format: # inject fieldName = ~tableName(foreignKey)
* Returns null if the line is not a reverse reference declaration. * Returns null if the line is not a reverse reference declaration.
*/ */
export function parseReverseReferenceDeclaration( export function parseReverseReferenceDeclaration(
@ -227,8 +224,8 @@ export function parseReverseReferenceDeclaration(
const content = trimmed.slice(commentChar.length).trim(); const content = trimmed.slice(commentChar.length).trim();
// Match pattern: fieldName := ~tableName(foreignKey) // Match pattern: inject fieldName = ~tableName(foreignKey)
const match = content.match(/^(\w+)\s*:=\s*~(\w+)\((\w+)\)(\?)?$/); const match = content.match(/^inject\s+(\w+)\s*=\s*~(\w+)\((\w+)\)(\?)?$/);
if (!match) return null; if (!match) return null;
const [, fieldName, tableName, foreignKey, optionalMark] = match; const [, fieldName, tableName, foreignKey, optionalMark] = match;