refactor: reorg/remove webpack dependency
This commit is contained in:
parent
77ee96d70c
commit
ad38976e86
21
package.json
21
package.json
|
|
@ -15,10 +15,20 @@
|
|||
"import": "./dist/csv-loader/loader.mjs",
|
||||
"require": "./dist/csv-loader/loader.js"
|
||||
},
|
||||
"./csv-loader/webpack": {
|
||||
"types": "./dist/csv-loader/webpack.d.ts",
|
||||
"import": "./dist/csv-loader/webpack.mjs",
|
||||
"require": "./dist/csv-loader/webpack.js"
|
||||
},
|
||||
"./csv-loader/rollup": {
|
||||
"types": "./dist/csv-loader/rollup.d.ts",
|
||||
"import": "./dist/csv-loader/rollup.mjs",
|
||||
"require": "./dist/csv-loader/rollup.js"
|
||||
},
|
||||
"./csv-loader/esbuild": {
|
||||
"types": "./dist/csv-loader/esbuild.d.ts",
|
||||
"import": "./dist/csv-loader/esbuild.mjs",
|
||||
"require": "./dist/csv-loader/esbuild.js"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
|
|
@ -49,6 +59,15 @@
|
|||
"typescript": "^5.9.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@rspack/core": "^1.x"
|
||||
"@rspack/core": "^1.x",
|
||||
"esbuild": "*"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@rspack/core": {
|
||||
"optional": true
|
||||
},
|
||||
"esbuild": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import type { CsvLoaderOptions } from './loader.js';
|
|||
import { csvToModule } from './loader.js';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import type { Plugin, OnLoadArgs, OnLoadResult } from 'esbuild';
|
||||
import type { Plugin, OnLoadResult } from 'esbuild';
|
||||
|
||||
export interface CsvEsbuildOptions extends CsvLoaderOptions {
|
||||
/** Include pattern for CSV files (default: /\.csv$/) */
|
||||
|
|
@ -11,12 +11,27 @@ export interface CsvEsbuildOptions extends CsvLoaderOptions {
|
|||
exclude?: RegExp | string | Array<RegExp | string>;
|
||||
}
|
||||
|
||||
function matchesFilter(
|
||||
path: string,
|
||||
filter: RegExp | undefined
|
||||
function createFilter(
|
||||
pattern: RegExp | string | Array<RegExp | string>
|
||||
): RegExp {
|
||||
if (pattern instanceof RegExp) return pattern;
|
||||
if (Array.isArray(pattern)) {
|
||||
const first = pattern[0];
|
||||
return first instanceof RegExp ? first : new RegExp(first);
|
||||
}
|
||||
return new RegExp(pattern);
|
||||
}
|
||||
|
||||
function matchesPattern(
|
||||
id: string,
|
||||
pattern: RegExp | string | Array<RegExp | string> | undefined
|
||||
): boolean {
|
||||
if (!filter) return true;
|
||||
return filter.test(path);
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -32,22 +47,15 @@ export function csvLoader(options: CsvEsbuildOptions = {}): Plugin {
|
|||
...parseOptions
|
||||
} = options;
|
||||
|
||||
// Convert include/exclude to RegExp for esbuild filter
|
||||
const includeFilter = includeToRegExp(include);
|
||||
const excludeFilter = exclude ? includeToRegExp(exclude) : undefined;
|
||||
const includeFilter = createFilter(include);
|
||||
|
||||
return {
|
||||
name: 'inline-schema-csv',
|
||||
|
||||
setup(build) {
|
||||
build.onLoad({ filter: includeFilter }, async (args: OnLoadArgs) => {
|
||||
build.onLoad({ filter: includeFilter }, async (args) => {
|
||||
// Check exclude pattern
|
||||
if (excludeFilter && !matchesFilter(args.path, excludeFilter)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Only process .csv files
|
||||
if (!args.path.endsWith('.csv')) {
|
||||
if (exclude && !matchesPattern(args.path, exclude)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -58,7 +66,7 @@ export function csvLoader(options: CsvEsbuildOptions = {}): Plugin {
|
|||
} catch (error) {
|
||||
return {
|
||||
errors: [{ text: `Failed to read file: ${args.path}` }],
|
||||
};
|
||||
} as OnLoadResult;
|
||||
}
|
||||
|
||||
// Infer resource name from filename
|
||||
|
|
@ -80,39 +88,21 @@ export function csvLoader(options: CsvEsbuildOptions = {}): Plugin {
|
|||
: args.path + '.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);
|
||||
}
|
||||
// Note: esbuild doesn't have a direct emitFile API like Rollup
|
||||
// For type generation with writeToDisk: false, you'd need to
|
||||
// use a separate type generation step or plugin
|
||||
}
|
||||
|
||||
const onLoadResult: OnLoadResult = {
|
||||
return {
|
||||
contents: result.js,
|
||||
loader: 'js',
|
||||
loader: 'js' as const,
|
||||
};
|
||||
|
||||
return onLoadResult;
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function includeToRegExp(include: RegExp | string | Array<RegExp | string>): RegExp {
|
||||
if (include instanceof RegExp) {
|
||||
return include;
|
||||
}
|
||||
if (Array.isArray(include)) {
|
||||
// Use the first pattern or create a combined pattern
|
||||
const first = include[0];
|
||||
return first instanceof RegExp ? first : new RegExp(first);
|
||||
}
|
||||
return new RegExp(include);
|
||||
}
|
||||
|
||||
export default csvLoader;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
import type { LoaderContext } from '@rspack/core';
|
||||
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;
|
||||
|
|
@ -203,50 +200,3 @@ export function csvToModule(
|
|||
dts: result.typeDefinition,
|
||||
};
|
||||
}
|
||||
|
||||
export default function csvLoader(
|
||||
this: LoaderContext<CsvLoaderOptions>,
|
||||
content: string
|
||||
): string | Buffer {
|
||||
const options = this.getOptions() as CsvLoaderOptions | undefined;
|
||||
const emitTypes = options?.emitTypes ?? true;
|
||||
const typesOutputDir = options?.typesOutputDir ?? '';
|
||||
const writeToDisk = options?.writeToDisk ?? false;
|
||||
|
||||
// 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) {
|
||||
const context = this.context || '';
|
||||
// Get relative path from context, normalize to forward slashes
|
||||
let relativePath = this.resourcePath.replace(context, '');
|
||||
if (relativePath.startsWith('\\') || relativePath.startsWith('/')) {
|
||||
relativePath = relativePath.substring(1);
|
||||
}
|
||||
relativePath = relativePath.replace(/\\/g, '/');
|
||||
|
||||
// Replace .csv with .csv.d.ts for the output filename
|
||||
const dtsFileName = `${relativePath}.d.ts`;
|
||||
const outputPath = typesOutputDir
|
||||
? path.join(typesOutputDir, dtsFileName)
|
||||
: dtsFileName;
|
||||
|
||||
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, result.typeDefinition);
|
||||
} else {
|
||||
// Emit to in-memory filesystem (for production build)
|
||||
this.emitFile?.(outputPath, result.typeDefinition);
|
||||
}
|
||||
}
|
||||
|
||||
return `export default ${JSON.stringify(result.data, null, 2)};`;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
import type { LoaderContext } from '@rspack/core';
|
||||
import type { CsvLoaderOptions } from './loader.js';
|
||||
import { parseCsv } from './loader.js';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
|
||||
export interface CsvWebpackLoaderOptions extends CsvLoaderOptions {
|
||||
/** Output directory for generated type files (relative to output path) */
|
||||
typesOutputDir?: string;
|
||||
/** Write .d.ts files to disk (useful for dev server) */
|
||||
writeToDisk?: boolean;
|
||||
}
|
||||
|
||||
export default function csvLoader(
|
||||
this: LoaderContext<CsvWebpackLoaderOptions>,
|
||||
content: string
|
||||
): string | Buffer {
|
||||
const options = this.getOptions() as CsvWebpackLoaderOptions | undefined;
|
||||
const emitTypes = options?.emitTypes ?? true;
|
||||
const typesOutputDir = options?.typesOutputDir ?? '';
|
||||
const writeToDisk = options?.writeToDisk ?? false;
|
||||
|
||||
// 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) {
|
||||
const context = this.context || '';
|
||||
// Get relative path from context, normalize to forward slashes
|
||||
let relativePath = this.resourcePath.replace(context, '');
|
||||
if (relativePath.startsWith('\\') || relativePath.startsWith('/')) {
|
||||
relativePath = relativePath.substring(1);
|
||||
}
|
||||
relativePath = relativePath.replace(/\\/g, '/');
|
||||
|
||||
// Replace .csv with .csv.d.ts for the output filename
|
||||
const dtsFileName = `${relativePath}.d.ts`;
|
||||
const outputPath = typesOutputDir
|
||||
? path.join(typesOutputDir, dtsFileName)
|
||||
: dtsFileName;
|
||||
|
||||
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, result.typeDefinition);
|
||||
} else {
|
||||
// Emit to in-memory filesystem (for production build)
|
||||
this.emitFile?.(outputPath, result.typeDefinition);
|
||||
}
|
||||
}
|
||||
|
||||
return `export default ${JSON.stringify(result.data, null, 2)};`;
|
||||
}
|
||||
|
|
@ -16,6 +16,14 @@ export default defineConfig([
|
|||
external: ['@rspack/core', 'csv-parse'],
|
||||
clean: false,
|
||||
},
|
||||
{
|
||||
entry: ['src/csv-loader/webpack.ts'],
|
||||
format: ['cjs', 'esm'],
|
||||
dts: true,
|
||||
outDir: 'dist/csv-loader',
|
||||
external: ['@rspack/core', 'csv-parse'],
|
||||
clean: false,
|
||||
},
|
||||
{
|
||||
entry: ['src/csv-loader/rollup.ts'],
|
||||
format: ['cjs', 'esm'],
|
||||
|
|
@ -24,4 +32,12 @@ export default defineConfig([
|
|||
external: ['rollup', 'csv-parse'],
|
||||
clean: false,
|
||||
},
|
||||
{
|
||||
entry: ['src/csv-loader/esbuild.ts'],
|
||||
format: ['cjs', 'esm'],
|
||||
dts: true,
|
||||
outDir: 'dist/csv-loader',
|
||||
external: ['esbuild', 'csv-parse'],
|
||||
clean: false,
|
||||
},
|
||||
]);
|
||||
|
|
|
|||
Loading…
Reference in New Issue