Files
inline-schema/src/csv-loader/rollup.ts
T

127 lines
3.3 KiB
TypeScript

import * as path from "path";
import * as fs from "fs";
import { csvToModule } from "./module-gen";
import { CsvLoaderOptions } from "./types";
export interface CsvRollupOptions extends CsvLoaderOptions {
/** Include pattern for CSV files (default: /\.csv$/) */
include?: RegExp | string | Array<RegExp | string>;
/** Exclude pattern for CSV files */
exclude?: RegExp | string | Array<RegExp | string>;
/** Base directory for resolving referenced CSV files (default: directory of current file) */
refBaseDir?: string;
/** Primary key field name for referenced tables (default: 'id') */
defaultPrimaryKey?: string;
}
function matchesPattern(
id: string,
pattern: RegExp | string | Array<RegExp | string> | undefined,
): boolean {
if (!pattern) return true;
const patterns = Array.isArray(pattern) ? pattern : [pattern];
return patterns.some((p) => {
if (p instanceof RegExp) {
return p.test(id);
}
return id.includes(p);
});
}
interface TransformResult {
code: string;
map: null;
}
interface EmitFileOptions {
type: "asset";
fileName: string;
source: string;
}
interface PluginContext {
emitFile: (options: EmitFileOptions) => string;
}
interface RollupPlugin {
name: string;
transform: (
this: PluginContext,
code: string,
id: string,
) => TransformResult | null;
}
/**
* Rollup plugin for loading CSV files with typed-csv validation.
* Works with both Vite and Tsup (esbuild).
*/
export function csvLoader(options: CsvRollupOptions = {}): RollupPlugin {
const {
include = /\.csv$/,
exclude,
emitTypes = true,
typesOutputDir = "",
writeToDisk = false,
...parseOptions
} = options;
return {
name: "typed-csv",
transform(code: string, id: string) {
// Check if file matches the include/exclude patterns
if (!matchesPattern(id, include)) return null;
if (exclude && matchesPattern(id, exclude)) return null;
// 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,
currentFilePath: id,
refBaseDir: options.refBaseDir,
defaultPrimaryKey: options.defaultPrimaryKey,
});
// Emit type definition file if enabled
if (emitTypes && result.dts) {
const dtsPath = typesOutputDir
? path.join(typesOutputDir, path.basename(id) + ".d.ts")
: id + ".d.ts";
if (writeToDisk) {
// Write directly to disk
const absolutePath = path.isAbsolute(dtsPath)
? dtsPath
: path.join(process.cwd(), dtsPath);
fs.mkdirSync(path.dirname(absolutePath), { recursive: true });
fs.writeFileSync(absolutePath, result.dts);
} else {
// Emit to Rollup's virtual module system
this.emitFile({
type: "asset",
fileName: dtsPath,
source: result.dts,
});
}
}
return {
code: result.js,
map: null,
};
},
};
}
export default csvLoader;