diff --git a/src/csv-loader/loader.ts b/src/csv-loader/loader.ts index 7f741af..9dfa32b 100644 --- a/src/csv-loader/loader.ts +++ b/src/csv-loader/loader.ts @@ -493,7 +493,7 @@ class ReferenceValueParser { /** * Convert a schema to TypeScript type string */ -function schemaToTypeString(schema: Schema, resourceNames?: Map): string { +export function schemaToTypeString(schema: Schema, resourceNames?: Map): string { switch (schema.type) { case 'string': return 'string'; @@ -519,7 +519,7 @@ function schemaToTypeString(schema: Schema, resourceNames?: Map) const typeStr = schemaToTypeString(el.schema, resourceNames); return el.name ? `${el.name}: ${typeStr}` : typeStr; }); - return `[${tupleElements.join(', ')}]`; + return `[${tupleElements.join(', ')}][]`; } // Wrap union types in parentheses to maintain correct precedence const elementType = schemaToTypeString(schema.element, resourceNames); diff --git a/src/index.ts b/src/index.ts index 87e89d3..78ff52b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -15,4 +15,5 @@ export function defineSchema(schemaString: string): ParsedSchema { } export { parseSchema, parseValue, createValidator, ParseError }; +export { schemaToTypeString } from './csv-loader/loader.js'; export type { Schema, PrimitiveSchema, TupleSchema, ArraySchema, ReferenceSchema, StringLiteralSchema, UnionSchema, ParsedSchema }; diff --git a/src/type-gen.test.ts b/src/type-gen.test.ts index 4d4ac69..42183c9 100644 --- a/src/type-gen.test.ts +++ b/src/type-gen.test.ts @@ -1,5 +1,5 @@ import { describe, it, expect } from 'vitest'; -import { defineSchema, parseSchema } from './index'; +import { defineSchema, parseSchema, schemaToTypeString } from './index'; import type { Schema, StringLiteralSchema, UnionSchema } from './types'; describe('Type generation for string literals and unions', () => { @@ -136,64 +136,39 @@ describe('Type generation for string literals and unions', () => { }); describe('Type string generation', () => { - // Helper function to test type generation - function generateType(schema: Schema): string { - function toType(s: Schema): string { - switch (s.type) { - case 'string': return 'string'; - case 'number': - case 'int': - case 'float': return 'number'; - case 'boolean': return 'boolean'; - case 'stringLiteral': return `"${s.value}"`; - case 'union': return s.members.map(m => toType(m)).join(' | '); - case 'array': - const elemType = toType(s.element); - if (s.element.type === 'union') { - return `(${elemType})[]`; - } - return `${elemType}[]`; - case 'tuple': - const elements = s.elements.map(el => { - const typeStr = toType(el.schema); - return el.name ? `${el.name}: ${typeStr}` : typeStr; - }); - return `[${elements.join(', ')}]`; - default: return 'unknown'; - } - } - return toType(schema); - } - it('should generate "on" for string literal', () => { const schema = parseSchema('"on"'); - expect(generateType(schema)).toBe('"on"'); + expect(schemaToTypeString(schema)).toBe('"on"'); }); it('should generate "on" | "off" for union of string literals', () => { const schema = parseSchema('"on" | "off"'); - expect(generateType(schema)).toBe('"on" | "off"'); + expect(schemaToTypeString(schema)).toBe('"on" | "off"'); }); it('should generate correct type for array of string literals', () => { const schema = parseSchema('"item"[]'); - expect(generateType(schema)).toBe('"item"[]'); + expect(schemaToTypeString(schema)).toBe('"item"[]'); }); it('should generate correct type for array of unions', () => { const schema = parseSchema('("pending" | "approved" | "rejected")[]'); - // Union types in arrays need parentheses for correct precedence - expect(generateType(schema)).toBe('("pending" | "approved" | "rejected")[]'); + expect(schemaToTypeString(schema)).toBe('("pending" | "approved" | "rejected")[]'); }); it('should generate correct type for tuple with union field', () => { const schema = parseSchema('[name: string; status: "active" | "inactive"]'); - expect(generateType(schema)).toBe('[name: string, status: "active" | "inactive"]'); + expect(schemaToTypeString(schema)).toBe('[name: string, status: "active" | "inactive"]'); }); it('should generate correct type for complex union', () => { const schema = parseSchema('string | number | "special"'); - expect(generateType(schema)).toBe('string | number | "special"'); + expect(schemaToTypeString(schema)).toBe('string | number | "special"'); + }); + + it('should generate correct type for nested tuple with references', () => { + const schema = parseSchema('[data: @enemy; hp: int; ([effect: @effect;stacks: int])[]][]'); + expect(schemaToTypeString(schema)).toBe('[data: Enemy, hp: number, [effect: Effect, stacks: number][]][]'); }); }); });