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') {
const tupleElements = schema.element.elements.map((el) => {
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':
const tupleElements = schema.elements.map((el) => {
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:
return 'unknown';
}
@ -76,15 +76,16 @@ function generateTypeDefinition(
resourceName: string,
propertyConfigs: PropertyConfig[]
): string {
const typeName = resourceName ? `${resourceName}Table` : 'Table';
const properties = propertyConfigs
.map((config) => ` ${config.name}: ${schemaToTypeString(config.schema)};`)
.map((config) => ` readonly ${config.name}: ${schemaToTypeString(config.schema)};`)
.join('\n');
return `type Table = {
${properties}
}[];
declare const data: Table;
return `type ${typeName} = readonly {
${properties}
}[];
declare const data: ${typeName};
export default data;
`;
}
@ -99,7 +100,7 @@ export default data;
*/
export function parseCsv(
content: string,
options: CsvLoaderOptions = {}
options: CsvLoaderOptions & { resourceName?: string } = {}
): CsvParseResult {
const delimiter = options.delimiter ?? ',';
const quote = options.quote ?? '"';
@ -174,7 +175,7 @@ export function parseCsv(
};
if (emitTypes) {
result.typeDefinition = generateTypeDefinition('', propertyConfigs);
result.typeDefinition = generateTypeDefinition(options.resourceName || '', propertyConfigs);
}
return result;
@ -190,7 +191,7 @@ export function parseCsv(
*/
export function csvToModule(
content: string,
options: CsvLoaderOptions = {}
options: CsvLoaderOptions & { resourceName?: string } = {}
): { js: string; dts?: string } {
const result = parseCsv(content, options);
@ -212,7 +213,13 @@ export default function csvLoader(
const typesOutputDir = options?.typesOutputDir ?? '';
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
if (emitTypes && result.typeDefinition) {

View File

@ -73,9 +73,16 @@ export function csvLoader(options: CsvRollupOptions = {}): RollupPlugin {
// Only process .csv files
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, {
...parseOptions,
emitTypes,
resourceName,
});
// Emit type definition file if enabled