feat(csv-loader): preserve original schema strings in type generation

Store the original schema string during CSV parsing to prevent
unnecessary expansion of type name references in the generated
TypeScript definitions. This ensures that declared types reference
each other by name rather than inlining their full definitions.
This commit is contained in:
hypercross 2026-04-22 17:08:06 +08:00
parent ea362d4229
commit 46504a53dd
4 changed files with 33 additions and 14 deletions

View File

@ -160,7 +160,11 @@ export function parseCsv(
}
// Parse type declarations with expansion of type name references
const typeDeclarationsParsed: { name: string; schema: Schema }[] = [];
const typeDeclarationsParsed: {
name: string;
schema: Schema;
schemaString: string;
}[] = [];
for (const decl of typeDeclarationsRaw) {
// Expand any type name references before parsing
const expandedSchema = expandSchemaString(
@ -168,7 +172,11 @@ export function parseCsv(
declaredSchemaStrings,
);
const schema = parseSchema(expandedSchema.trim());
typeDeclarationsParsed.push({ name: decl.typeName, schema });
typeDeclarationsParsed.push({
name: decl.typeName,
schema,
schemaString: decl.schemaString,
});
}
// Build declared types map
@ -181,7 +189,11 @@ export function parseCsv(
const typeDeclarations: TypeDeclaration[] = [];
for (const decl of typeDeclarationsParsed) {
const resolvedSchema = resolveTypeReferences(decl.schema, declaredTypes);
typeDeclarations.push({ name: decl.name, schema: resolvedSchema });
typeDeclarations.push({
name: decl.name,
schema: resolvedSchema,
schemaString: decl.schemaString,
});
}
// Update declaredTypes with resolved schemas for column schema lookup

View File

@ -56,9 +56,9 @@ describe("parseCsv - type declarations", () => {
currentFilePath: path.join(fixturesDir, "card.csv"),
});
expect(result.typeDefinition).toContain("type Trigger =");
expect(result.typeDefinition).toContain("export type Trigger =");
expect(result.typeDefinition).toContain(
'"onPlay" | "onDraw" | "onDiscard"',
"'onPlay' | 'onDraw' | 'onDiscard'",
);
});
@ -93,8 +93,8 @@ describe("parseCsv - type declarations", () => {
currentFilePath: path.join(fixturesDir, "card.csv"),
});
expect(result.typeDefinition).toContain("type Trigger =");
expect(result.typeDefinition).toContain("type Status =");
expect(result.typeDefinition).toContain("export type Trigger =");
expect(result.typeDefinition).toContain("export type Status =");
});
it("should ignore comment lines that are not type declarations", () => {
@ -196,8 +196,8 @@ describe("parseCsv - type declarations", () => {
});
// Both type declarations should appear
expect(result.typeDefinition).toContain("type Trigger =");
expect(result.typeDefinition).toContain("type Effect =");
expect(result.typeDefinition).toContain("export type Trigger =");
expect(result.typeDefinition).toContain("export type Effect =");
// Column should use the declared type name, not expanded union
expect(result.typeDefinition).toContain("readonly trigger: Trigger;");
});
@ -242,10 +242,15 @@ describe("parseCsv - type declarations", () => {
currentFilePath: path.join(fixturesDir, "intent.csv"),
});
expect(result.typeDefinition).toContain("type IntentEffectTarget =");
expect(result.typeDefinition).toContain("type IntentEffect =");
expect(result.typeDefinition).toContain("type IntentEffects =");
expect(result.typeDefinition).toContain("export type IntentEffectTarget =");
expect(result.typeDefinition).toContain("export type IntentEffect =");
expect(result.typeDefinition).toContain("export type IntentEffects =");
// IntentEffect should reference IntentEffectTarget, not expand it
expect(result.typeDefinition).toContain(
"[IntentEffectTarget; string; int]",
);
// IntentEffects should reference IntentEffect, not expand it
expect(result.typeDefinition).toContain("IntentEffect[]");
// Column should reference IntentEffects, not inline expansion
expect(result.typeDefinition).toContain("readonly effects: IntentEffects;");
});

View File

@ -51,7 +51,7 @@ export function generateTypeDefinition(
? typeDeclarations
.map(
(decl) =>
`export type ${decl.name} = ${schemaToTypeString(decl.schema, resourceNames)};`,
`export type ${decl.name} = ${decl.schemaString ?? schemaToTypeString(decl.schema, resourceNames)};`,
)
.join("\n") + "\n\n"
: "";

View File

@ -98,6 +98,8 @@ export interface ReverseReferenceDeclaration {
export interface TypeDeclaration {
/** Name of the type being defined */
name: string;
/** The original schema string (preserves type name references for output) */
schemaString: string;
/** The parsed schema for this type */
schema: Schema;
}