refactor: table name deduction & readonly type

This commit is contained in:
hypercross 2026-04-05 12:38:33 +08:00
parent f656a62606
commit 4eb6a17e9f
2 changed files with 29 additions and 15 deletions

View File

@ -53,17 +53,17 @@ function schemaToTypeString(schema: Schema): string {
if (schema.element.type === 'tuple') { if (schema.element.type === 'tuple') {
const tupleElements = schema.element.elements.map((el) => { const tupleElements = schema.element.elements.map((el) => {
const typeStr = schemaToTypeString(el.schema); const typeStr = schemaToTypeString(el.schema);
return el.name ? `${el.name}: ${typeStr}` : typeStr; return el.name ? `readonly ${el.name}: ${typeStr}` : typeStr;
}); });
return `[${tupleElements.join(', ')}]`; return `readonly [${tupleElements.join(', ')}]`;
} }
return `${schemaToTypeString(schema.element)}[]`; return `readonly ${schemaToTypeString(schema.element)}[]`;
case 'tuple': case 'tuple':
const tupleElements = schema.elements.map((el) => { const tupleElements = schema.elements.map((el) => {
const typeStr = schemaToTypeString(el.schema); const typeStr = schemaToTypeString(el.schema);
return el.name ? `${el.name}: ${typeStr}` : typeStr; return el.name ? `readonly ${el.name}: ${typeStr}` : typeStr;
}); });
return `[${tupleElements.join(', ')}]`; return `readonly [${tupleElements.join(', ')}]`;
default: default:
return 'unknown'; return 'unknown';
} }
@ -76,15 +76,16 @@ function generateTypeDefinition(
resourceName: string, resourceName: string,
propertyConfigs: PropertyConfig[] propertyConfigs: PropertyConfig[]
): string { ): string {
const typeName = resourceName ? `${resourceName}Table` : 'Table';
const properties = propertyConfigs const properties = propertyConfigs
.map((config) => ` ${config.name}: ${schemaToTypeString(config.schema)};`) .map((config) => ` readonly ${config.name}: ${schemaToTypeString(config.schema)};`)
.join('\n'); .join('\n');
return `type Table = { return `type ${typeName} = readonly {
${properties} ${properties}
}[]; }[];
declare const data: Table; declare const data: ${typeName};
export default data; export default data;
`; `;
} }
@ -99,7 +100,7 @@ export default data;
*/ */
export function parseCsv( export function parseCsv(
content: string, content: string,
options: CsvLoaderOptions = {} options: CsvLoaderOptions & { resourceName?: string } = {}
): CsvParseResult { ): CsvParseResult {
const delimiter = options.delimiter ?? ','; const delimiter = options.delimiter ?? ',';
const quote = options.quote ?? '"'; const quote = options.quote ?? '"';
@ -174,7 +175,7 @@ export function parseCsv(
}; };
if (emitTypes) { if (emitTypes) {
result.typeDefinition = generateTypeDefinition('', propertyConfigs); result.typeDefinition = generateTypeDefinition(options.resourceName || '', propertyConfigs);
} }
return result; return result;
@ -190,7 +191,7 @@ export function parseCsv(
*/ */
export function csvToModule( export function csvToModule(
content: string, content: string,
options: CsvLoaderOptions = {} options: CsvLoaderOptions & { resourceName?: string } = {}
): { js: string; dts?: string } { ): { js: string; dts?: string } {
const result = parseCsv(content, options); const result = parseCsv(content, options);
@ -212,7 +213,13 @@ export default function csvLoader(
const typesOutputDir = options?.typesOutputDir ?? ''; const typesOutputDir = options?.typesOutputDir ?? '';
const writeToDisk = options?.writeToDisk ?? false; const writeToDisk = options?.writeToDisk ?? false;
const result = parseCsv(content, options); // Infer resource name from filename
const fileName = path.basename(this.resourcePath, '.csv').split('.')[0];
const resourceName = fileName
.replace(/[-_\s]+(.)?/g, (_, char) => char ? char.toUpperCase() : '')
.replace(/^(.)/, (_, char) => char.toUpperCase());
const result = parseCsv(content, { ...options, resourceName });
// Emit type definition file if enabled // Emit type definition file if enabled
if (emitTypes && result.typeDefinition) { if (emitTypes && result.typeDefinition) {

View File

@ -73,9 +73,16 @@ export function csvLoader(options: CsvRollupOptions = {}): RollupPlugin {
// Only process .csv files // Only process .csv files
if (!id.endsWith('.csv')) return null; if (!id.endsWith('.csv')) return null;
// Infer resource name from filename
const fileName = path.basename(id, '.csv').split('.')[0];
const resourceName = fileName
.replace(/[-_\s]+(.)?/g, (_, char) => char ? char.toUpperCase() : '')
.replace(/^(.)/, (_, char) => char.toUpperCase());
const result = csvToModule(code, { const result = csvToModule(code, {
...parseOptions, ...parseOptions,
emitTypes, emitTypes,
resourceName,
}); });
// Emit type definition file if enabled // Emit type definition file if enabled