Compare commits
No commits in common. "e0317946d5262c434ea65b3662389aaebd2ac048" and "f101c1209715fcf399561d0dbf8d3751071e6bd7" have entirely different histories.
e0317946d5
...
f101c12097
|
|
@ -160,11 +160,7 @@ export function parseCsv(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse type declarations with expansion of type name references
|
// Parse type declarations with expansion of type name references
|
||||||
const typeDeclarationsParsed: {
|
const typeDeclarationsParsed: { name: string; schema: Schema }[] = [];
|
||||||
name: string;
|
|
||||||
schema: Schema;
|
|
||||||
schemaString: string;
|
|
||||||
}[] = [];
|
|
||||||
for (const decl of typeDeclarationsRaw) {
|
for (const decl of typeDeclarationsRaw) {
|
||||||
// Expand any type name references before parsing
|
// Expand any type name references before parsing
|
||||||
const expandedSchema = expandSchemaString(
|
const expandedSchema = expandSchemaString(
|
||||||
|
|
@ -172,11 +168,7 @@ export function parseCsv(
|
||||||
declaredSchemaStrings,
|
declaredSchemaStrings,
|
||||||
);
|
);
|
||||||
const schema = parseSchema(expandedSchema.trim());
|
const schema = parseSchema(expandedSchema.trim());
|
||||||
typeDeclarationsParsed.push({
|
typeDeclarationsParsed.push({ name: decl.typeName, schema });
|
||||||
name: decl.typeName,
|
|
||||||
schema,
|
|
||||||
schemaString: decl.schemaString,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build declared types map
|
// Build declared types map
|
||||||
|
|
@ -189,11 +181,7 @@ export function parseCsv(
|
||||||
const typeDeclarations: TypeDeclaration[] = [];
|
const typeDeclarations: TypeDeclaration[] = [];
|
||||||
for (const decl of typeDeclarationsParsed) {
|
for (const decl of typeDeclarationsParsed) {
|
||||||
const resolvedSchema = resolveTypeReferences(decl.schema, declaredTypes);
|
const resolvedSchema = resolveTypeReferences(decl.schema, declaredTypes);
|
||||||
typeDeclarations.push({
|
typeDeclarations.push({ name: decl.name, schema: resolvedSchema });
|
||||||
name: decl.name,
|
|
||||||
schema: resolvedSchema,
|
|
||||||
schemaString: decl.schemaString,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update declaredTypes with resolved schemas for column schema lookup
|
// Update declaredTypes with resolved schemas for column schema lookup
|
||||||
|
|
@ -209,21 +197,11 @@ export function parseCsv(
|
||||||
// Check if schema string matches a declared type name
|
// Check if schema string matches a declared type name
|
||||||
let schema: Schema;
|
let schema: Schema;
|
||||||
let declaredTypeName: string | undefined;
|
let declaredTypeName: string | undefined;
|
||||||
let columnSchemaString: string | undefined;
|
|
||||||
if (declaredTypes.has(schemaString)) {
|
if (declaredTypes.has(schemaString)) {
|
||||||
schema = declaredTypes.get(schemaString)!;
|
schema = declaredTypes.get(schemaString)!;
|
||||||
declaredTypeName = schemaString;
|
declaredTypeName = schemaString;
|
||||||
} else {
|
} else {
|
||||||
// Expand any custom type name references before parsing
|
schema = parseSchema(schemaString);
|
||||||
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 = {
|
const config: PropertyConfig = {
|
||||||
|
|
@ -232,7 +210,6 @@ export function parseCsv(
|
||||||
validator: createValidator(schema),
|
validator: createValidator(schema),
|
||||||
parser: (valueString: string) => parseValue(schema, valueString),
|
parser: (valueString: string) => parseValue(schema, valueString),
|
||||||
declaredTypeName,
|
declaredTypeName,
|
||||||
schemaString: columnSchemaString,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (schema.type === "reference") {
|
if (schema.type === "reference") {
|
||||||
|
|
|
||||||
|
|
@ -56,9 +56,9 @@ describe("parseCsv - type declarations", () => {
|
||||||
currentFilePath: path.join(fixturesDir, "card.csv"),
|
currentFilePath: path.join(fixturesDir, "card.csv"),
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(result.typeDefinition).toContain("export type Trigger =");
|
expect(result.typeDefinition).toContain("type Trigger =");
|
||||||
expect(result.typeDefinition).toContain(
|
expect(result.typeDefinition).toContain(
|
||||||
"'onPlay' | 'onDraw' | 'onDiscard'",
|
'"onPlay" | "onDraw" | "onDiscard"',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -93,8 +93,8 @@ describe("parseCsv - type declarations", () => {
|
||||||
currentFilePath: path.join(fixturesDir, "card.csv"),
|
currentFilePath: path.join(fixturesDir, "card.csv"),
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(result.typeDefinition).toContain("export type Trigger =");
|
expect(result.typeDefinition).toContain("type Trigger =");
|
||||||
expect(result.typeDefinition).toContain("export type Status =");
|
expect(result.typeDefinition).toContain("type Status =");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should ignore comment lines that are not type declarations", () => {
|
it("should ignore comment lines that are not type declarations", () => {
|
||||||
|
|
@ -196,96 +196,11 @@ describe("parseCsv - type declarations", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Both type declarations should appear
|
// Both type declarations should appear
|
||||||
expect(result.typeDefinition).toContain("export type Trigger =");
|
expect(result.typeDefinition).toContain("type Trigger =");
|
||||||
expect(result.typeDefinition).toContain("export type Effect =");
|
expect(result.typeDefinition).toContain("type Effect =");
|
||||||
// Column should use the declared type name, not expanded union
|
// Column should use the declared type name, not expanded union
|
||||||
expect(result.typeDefinition).toContain("readonly trigger: Trigger;");
|
expect(result.typeDefinition).toContain("readonly trigger: Trigger;");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should expand custom type names inside tuples and arrays", () => {
|
|
||||||
const csv = [
|
|
||||||
"# type IntentEffectTarget = 'user' | 'eachEnemy' | 'randomEnemy' | 'player'",
|
|
||||||
"# type IntentEffect = [IntentEffectTarget; string; int]",
|
|
||||||
"# type IntentEffects = IntentEffect[]",
|
|
||||||
"id,effects",
|
|
||||||
"string,IntentEffects",
|
|
||||||
"boost,[user;spike;1];[user;defend;4]",
|
|
||||||
].join("\n");
|
|
||||||
|
|
||||||
const result = parseCsv(csv, { emitTypes: false });
|
|
||||||
|
|
||||||
expect(result.typeDeclarations).toHaveLength(3);
|
|
||||||
const intentEffect = result.typeDeclarations.find(
|
|
||||||
(d) => d.name === "IntentEffect",
|
|
||||||
)!;
|
|
||||||
expect(intentEffect.schema.type).toBe("tuple");
|
|
||||||
// First element should be resolved to union, not a string "IntentEffectTarget"
|
|
||||||
const firstEl = (
|
|
||||||
intentEffect.schema as { elements: { schema: { type: string } }[] }
|
|
||||||
).elements[0].schema;
|
|
||||||
expect(firstEl.type).toBe("union");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should use declared type names in generated type definition for tuple arrays", () => {
|
|
||||||
const csv = [
|
|
||||||
"# type IntentEffectTarget = 'user' | 'eachEnemy' | 'randomEnemy' | 'player'",
|
|
||||||
"# type IntentEffect = [IntentEffectTarget; string; int]",
|
|
||||||
"# type IntentEffects = IntentEffect[]",
|
|
||||||
"id,effects",
|
|
||||||
"string,IntentEffects",
|
|
||||||
"boost,[user;spike;1];[user;defend;4]",
|
|
||||||
].join("\n");
|
|
||||||
|
|
||||||
const result = parseCsv(csv, {
|
|
||||||
emitTypes: true,
|
|
||||||
resourceName: "intent",
|
|
||||||
currentFilePath: path.join(fixturesDir, "intent.csv"),
|
|
||||||
});
|
|
||||||
|
|
||||||
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;");
|
|
||||||
});
|
|
||||||
|
|
||||||
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", () => {
|
describe("parseCsv - type declarations with resolveReferences: false", () => {
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ export function generateTypeDefinition(
|
||||||
? typeDeclarations
|
? typeDeclarations
|
||||||
.map(
|
.map(
|
||||||
(decl) =>
|
(decl) =>
|
||||||
`export type ${decl.name} = ${decl.schemaString ?? schemaToTypeString(decl.schema, resourceNames)};`,
|
`export type ${decl.name} = ${schemaToTypeString(decl.schema, resourceNames)};`,
|
||||||
)
|
)
|
||||||
.join("\n") + "\n\n"
|
.join("\n") + "\n\n"
|
||||||
: "";
|
: "";
|
||||||
|
|
@ -60,8 +60,7 @@ export function generateTypeDefinition(
|
||||||
.map((config) => {
|
.map((config) => {
|
||||||
const typeStr = config.declaredTypeName
|
const typeStr = config.declaredTypeName
|
||||||
? config.declaredTypeName
|
? config.declaredTypeName
|
||||||
: (config.schemaString ??
|
: schemaToTypeString(config.schema, resourceNames);
|
||||||
schemaToTypeString(config.schema, resourceNames));
|
|
||||||
return ` readonly ${config.name}: ${typeStr};`;
|
return ` readonly ${config.name}: ${typeStr};`;
|
||||||
})
|
})
|
||||||
.join("\n");
|
.join("\n");
|
||||||
|
|
|
||||||
|
|
@ -78,8 +78,6 @@ export interface PropertyConfig {
|
||||||
reverseReferenceForeignKey?: string;
|
reverseReferenceForeignKey?: string;
|
||||||
/** When a column uses a declared type name, this stores that name */
|
/** When a column uses a declared type name, this stores that name */
|
||||||
declaredTypeName?: string;
|
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 */
|
/** Parsed reverse reference declaration from a comment line */
|
||||||
|
|
@ -100,8 +98,6 @@ export interface ReverseReferenceDeclaration {
|
||||||
export interface TypeDeclaration {
|
export interface TypeDeclaration {
|
||||||
/** Name of the type being defined */
|
/** Name of the type being defined */
|
||||||
name: string;
|
name: string;
|
||||||
/** The original schema string (preserves type name references for output) */
|
|
||||||
schemaString: string;
|
|
||||||
/** The parsed schema for this type */
|
/** The parsed schema for this type */
|
||||||
schema: Schema;
|
schema: Schema;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue