feat(csv-loader): expand custom type references in schemas
Allow custom type names to be expanded before parsing the schema string. This enables using declared types within complex structures like tuples or arrays. The original schema string is preserved for type generation to ensure the output uses the named type rather than the expanded inline definition.
This commit is contained in:
parent
46504a53dd
commit
e0317946d5
|
|
@ -209,11 +209,21 @@ export function parseCsv(
|
|||
// Check if schema string matches a declared type name
|
||||
let schema: Schema;
|
||||
let declaredTypeName: string | undefined;
|
||||
let columnSchemaString: string | undefined;
|
||||
if (declaredTypes.has(schemaString)) {
|
||||
schema = declaredTypes.get(schemaString)!;
|
||||
declaredTypeName = schemaString;
|
||||
} else {
|
||||
schema = parseSchema(schemaString);
|
||||
// Expand any custom type name references before parsing
|
||||
const expandedSchema = expandSchemaString(
|
||||
schemaString,
|
||||
declaredSchemaStrings,
|
||||
);
|
||||
schema = parseSchema(expandedSchema.trim());
|
||||
// Only preserve the original schema string if expansion actually changed it
|
||||
if (expandedSchema !== schemaString) {
|
||||
columnSchemaString = schemaString;
|
||||
}
|
||||
}
|
||||
|
||||
const config: PropertyConfig = {
|
||||
|
|
@ -222,6 +232,7 @@ export function parseCsv(
|
|||
validator: createValidator(schema),
|
||||
parser: (valueString: string) => parseValue(schema, valueString),
|
||||
declaredTypeName,
|
||||
schemaString: columnSchemaString,
|
||||
};
|
||||
|
||||
if (schema.type === "reference") {
|
||||
|
|
|
|||
|
|
@ -254,6 +254,38 @@ describe("parseCsv - type declarations", () => {
|
|||
// Column should reference IntentEffects, not inline expansion
|
||||
expect(result.typeDefinition).toContain("readonly effects: IntentEffects;");
|
||||
});
|
||||
|
||||
it("should handle custom type inside a tuple used as an array element", () => {
|
||||
const csv = [
|
||||
'# type Type = "apple" | "orange"',
|
||||
"id,items",
|
||||
"string,[Type; int][]",
|
||||
"001,[apple;2];[orange;3]",
|
||||
].join("\n");
|
||||
|
||||
const result = parseCsv(csv, { emitTypes: false });
|
||||
|
||||
expect(result.data).toHaveLength(1);
|
||||
expect(result.data[0]).toEqual({
|
||||
id: "001",
|
||||
items: [
|
||||
["apple", 2],
|
||||
["orange", 3],
|
||||
],
|
||||
});
|
||||
|
||||
const typeResult = parseCsv(csv, {
|
||||
emitTypes: true,
|
||||
resourceName: "item",
|
||||
currentFilePath: path.join(fixturesDir, "item.csv"),
|
||||
});
|
||||
|
||||
expect(typeResult.typeDefinition).toContain("export type Type =");
|
||||
expect(typeResult.typeDefinition).toContain("[Type; int][]");
|
||||
expect(typeResult.typeDefinition).toContain(
|
||||
"readonly items: [Type; int][];",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("parseCsv - type declarations with resolveReferences: false", () => {
|
||||
|
|
|
|||
|
|
@ -60,7 +60,8 @@ export function generateTypeDefinition(
|
|||
.map((config) => {
|
||||
const typeStr = config.declaredTypeName
|
||||
? config.declaredTypeName
|
||||
: schemaToTypeString(config.schema, resourceNames);
|
||||
: (config.schemaString ??
|
||||
schemaToTypeString(config.schema, resourceNames));
|
||||
return ` readonly ${config.name}: ${typeStr};`;
|
||||
})
|
||||
.join("\n");
|
||||
|
|
|
|||
|
|
@ -78,6 +78,8 @@ export interface PropertyConfig {
|
|||
reverseReferenceForeignKey?: string;
|
||||
/** When a column uses a declared type name, this stores that name */
|
||||
declaredTypeName?: string;
|
||||
/** The original schema string for the column (preserves type name references for output) */
|
||||
schemaString?: string;
|
||||
}
|
||||
|
||||
/** Parsed reverse reference declaration from a comment line */
|
||||
|
|
|
|||
Loading…
Reference in New Issue