From 525ae262fdbe53f5fabf8e4a0c9a932526164b6c Mon Sep 17 00:00:00 2001 From: hyper Date: Tue, 31 Mar 2026 15:54:38 +0800 Subject: [PATCH] feat: add writeToDisk option for dev server support - Add writeToDisk option to write .d.ts files directly to disk - Useful for rsbuild/rspack dev server which uses in-memory FS - Set writeToDisk: true in dev mode to see generated types Co-authored-by: Qwen-Coder --- csv-loader.md | 2 ++ dist/csv-loader/loader.d.mts | 2 ++ dist/csv-loader/loader.d.ts | 2 ++ dist/csv-loader/loader.js | 10 +++++++++- dist/csv-loader/loader.mjs | 10 +++++++++- src/csv-loader/loader.ts | 18 +++++++++++++++--- 6 files changed, 39 insertions(+), 5 deletions(-) diff --git a/csv-loader.md b/csv-loader.md index 166c55d..453b005 100644 --- a/csv-loader.md +++ b/csv-loader.md @@ -43,6 +43,7 @@ module.exports = { trim: true, // 修剪表头和值的前后空格 (默认 true) // emitTypes: false, // 禁用类型定义生成 (默认 true) // typesOutputDir: 'types', // 类型文件输出目录 (可选) + // writeToDisk: true, // 在 dev server 下写入磁盘 (默认 false) }, }, }, @@ -96,6 +97,7 @@ import type { RowType } from './data.schema.csv'; | `trim` | boolean | `true` | Trim headers and values | | `emitTypes` | boolean | `true` | Generate TypeScript declaration file (.d.ts) | | `typesOutputDir` | string | `''` | Output directory for generated type files (relative to output path) | +| `writeToDisk` | boolean | `false` | Write .d.ts files directly to disk (useful for dev server) | ## Schema Syntax diff --git a/dist/csv-loader/loader.d.mts b/dist/csv-loader/loader.d.mts index f3f881e..607e045 100644 --- a/dist/csv-loader/loader.d.mts +++ b/dist/csv-loader/loader.d.mts @@ -11,6 +11,8 @@ interface CsvLoaderOptions { emitTypes?: boolean; /** Output directory for generated type files (relative to output path) */ typesOutputDir?: string; + /** Write .d.ts files to disk (useful for dev server) */ + writeToDisk?: boolean; } declare function csvLoader(this: LoaderContext, content: string): string | Buffer; diff --git a/dist/csv-loader/loader.d.ts b/dist/csv-loader/loader.d.ts index f3f881e..607e045 100644 --- a/dist/csv-loader/loader.d.ts +++ b/dist/csv-loader/loader.d.ts @@ -11,6 +11,8 @@ interface CsvLoaderOptions { emitTypes?: boolean; /** Output directory for generated type files (relative to output path) */ typesOutputDir?: string; + /** Write .d.ts files to disk (useful for dev server) */ + writeToDisk?: boolean; } declare function csvLoader(this: LoaderContext, content: string): string | Buffer; diff --git a/dist/csv-loader/loader.js b/dist/csv-loader/loader.js index 062be01..11c72d0 100644 --- a/dist/csv-loader/loader.js +++ b/dist/csv-loader/loader.js @@ -365,6 +365,7 @@ function createValidator(schema) { // src/csv-loader/loader.ts var path = __toESM(require("path")); +var fs = __toESM(require("fs")); function schemaToTypeString(schema) { switch (schema.type) { case "string": @@ -411,6 +412,7 @@ function csvLoader(content) { const trim = options?.trim ?? true; const emitTypes = options?.emitTypes ?? true; const typesOutputDir = options?.typesOutputDir ?? ""; + const writeToDisk = options?.writeToDisk ?? false; const records = (0, import_sync.parse)(content, { delimiter, quote, @@ -475,7 +477,13 @@ function csvLoader(content) { const dtsFileName = relativePath.replace(/\.csv$/, ".d.ts"); const outputPath = typesOutputDir ? path.join(typesOutputDir, dtsFileName) : dtsFileName; const dtsContent = generateTypeDefinition(this.resourcePath, propertyConfigs, `./${relativePath}`); - this.emitFile?.(outputPath, dtsContent); + if (writeToDisk) { + const absolutePath = path.join(this.context || process.cwd(), typesOutputDir || "", dtsFileName); + fs.mkdirSync(path.dirname(absolutePath), { recursive: true }); + fs.writeFileSync(absolutePath, dtsContent); + } else { + this.emitFile?.(outputPath, dtsContent); + } } return `export default ${json};`; } diff --git a/dist/csv-loader/loader.mjs b/dist/csv-loader/loader.mjs index 27ab9ca..47f4b76 100644 --- a/dist/csv-loader/loader.mjs +++ b/dist/csv-loader/loader.mjs @@ -331,6 +331,7 @@ function createValidator(schema) { // src/csv-loader/loader.ts import * as path from "path"; +import * as fs from "fs"; function schemaToTypeString(schema) { switch (schema.type) { case "string": @@ -377,6 +378,7 @@ function csvLoader(content) { const trim = options?.trim ?? true; const emitTypes = options?.emitTypes ?? true; const typesOutputDir = options?.typesOutputDir ?? ""; + const writeToDisk = options?.writeToDisk ?? false; const records = parse(content, { delimiter, quote, @@ -441,7 +443,13 @@ function csvLoader(content) { const dtsFileName = relativePath.replace(/\.csv$/, ".d.ts"); const outputPath = typesOutputDir ? path.join(typesOutputDir, dtsFileName) : dtsFileName; const dtsContent = generateTypeDefinition(this.resourcePath, propertyConfigs, `./${relativePath}`); - this.emitFile?.(outputPath, dtsContent); + if (writeToDisk) { + const absolutePath = path.join(this.context || process.cwd(), typesOutputDir || "", dtsFileName); + fs.mkdirSync(path.dirname(absolutePath), { recursive: true }); + fs.writeFileSync(absolutePath, dtsContent); + } else { + this.emitFile?.(outputPath, dtsContent); + } } return `export default ${json};`; } diff --git a/src/csv-loader/loader.ts b/src/csv-loader/loader.ts index 3f17ff6..a41e61f 100644 --- a/src/csv-loader/loader.ts +++ b/src/csv-loader/loader.ts @@ -3,6 +3,7 @@ import { parse } from 'csv-parse/sync'; import { parseSchema, createValidator, parseValue } from '../index.js'; import type { Schema } from '../types.js'; import * as path from 'path'; +import * as fs from 'fs'; export interface CsvLoaderOptions { delimiter?: string; @@ -15,6 +16,8 @@ export interface CsvLoaderOptions { emitTypes?: boolean; /** Output directory for generated type files (relative to output path) */ typesOutputDir?: string; + /** Write .d.ts files to disk (useful for dev server) */ + writeToDisk?: boolean; } interface PropertyConfig { @@ -91,6 +94,7 @@ export default function csvLoader( const trim = options?.trim ?? true; const emitTypes = options?.emitTypes ?? true; const typesOutputDir = options?.typesOutputDir ?? ''; + const writeToDisk = options?.writeToDisk ?? false; const records = parse(content, { delimiter, @@ -162,15 +166,23 @@ export default function csvLoader( relativePath = relativePath.substring(1); } relativePath = relativePath.replace(/\\/g, '/'); - + // Replace .csv with .d.ts for the output filename const dtsFileName = relativePath.replace(/\.csv$/, '.d.ts'); - const outputPath = typesOutputDir + const outputPath = typesOutputDir ? path.join(typesOutputDir, dtsFileName) : dtsFileName; const dtsContent = generateTypeDefinition(this.resourcePath, propertyConfigs, `./${relativePath}`); - this.emitFile?.(outputPath, dtsContent); + if (writeToDisk) { + // Write directly to disk (useful for dev server) + const absolutePath = path.join(this.context || process.cwd(), typesOutputDir || '', dtsFileName); + fs.mkdirSync(path.dirname(absolutePath), { recursive: true }); + fs.writeFileSync(absolutePath, dtsContent); + } else { + // Emit to in-memory filesystem (for production build) + this.emitFile?.(outputPath, dtsContent); + } } return `export default ${json};`;