import * as path from "path"; import { schemaToTypeString } from "../index.js"; import type { PropertyConfig, TypeDeclaration } from "./types.js"; function resolveReferencesInSchemaString( schemaString: string, resourceNames: Map, ): string { return schemaString .replace(/@([a-zA-Z0-9\-_]+)(\[\])?/g, (_match, tableName, arraySuffix) => { const typeName = resourceNames.get(tableName) || tableName.charAt(0).toUpperCase() + tableName.slice(1); return arraySuffix ? `${typeName}[]` : typeName; }) .replace(/; ?/g, ", "); } /** * Generate TypeScript interface for the CSV data */ export function generateTypeDefinition( resourceName: string, propertyConfigs: PropertyConfig[], references: Set, currentFilePath?: string, typeDeclarations: TypeDeclaration[] = [], ): string { const typeName = resourceName ? `${resourceName}Table` : "Table"; const currentTableName = currentFilePath ? path.basename(currentFilePath, path.extname(currentFilePath)) : undefined; const singularType = resourceName ? resourceName.charAt(0).toUpperCase() + resourceName.slice(1) : `${typeName}[number]`; // Generate import statements for referenced tables const imports: string[] = []; const resourceNames = new Map(); references.forEach((tableName) => { if (tableName === currentTableName) { resourceNames.set(tableName, singularType); return; } // Convert table name to type name by capitalizing const typeBase = tableName.charAt(0).toUpperCase() + tableName.slice(1); resourceNames.set(tableName, typeBase); // Generate import path based on current file path let importPath: string; if (currentFilePath) { importPath = `./${tableName}.csv`; } else { importPath = `../${tableName}.csv`; } imports.push(`import type { ${typeBase} } from '${importPath}';`); }); const importSection = imports.length > 0 ? imports.join("\n") + "\n\n" : ""; // Generate type declarations for user-defined types const typeDeclarationSection = typeDeclarations.length > 0 ? typeDeclarations .map( (decl) => `export type ${decl.name} = ${decl.schemaString ? resolveReferencesInSchemaString(decl.schemaString, resourceNames) : schemaToTypeString(decl.schema, resourceNames)};`, ) .join("\n") + "\n\n" : ""; const properties = propertyConfigs .map((config) => { const typeStr = config.declaredTypeName ? config.declaredTypeName : config.schemaString ? resolveReferencesInSchemaString(config.schemaString, resourceNames) : schemaToTypeString(config.schema, resourceNames); return ` readonly ${config.name}: ${typeStr};`; }) .join("\n"); let exportAlias = ""; if (resourceName) { const singularType = resourceName.charAt(0).toUpperCase() + resourceName.slice(1); exportAlias = `\nexport type ${singularType} = ${typeName}[number];`; } return `${importSection}${typeDeclarationSection}type ${typeName} = readonly { ${properties} }[]; ${exportAlias} declare function getData(): ${typeName}; export default getData; `; }