70 lines
2.2 KiB
TypeScript
70 lines
2.2 KiB
TypeScript
import { transform, type TransformOptions } from './transformer.ts';
|
|
|
|
export interface SerializerPluginOptions extends TransformOptions {
|
|
/**
|
|
* Glob patterns to include. Defaults to all `.ts` / `.tsx` / `.mts` / `.cts` files.
|
|
*/
|
|
include?: RegExp;
|
|
/**
|
|
* Glob patterns to exclude (in addition to node_modules which is always excluded).
|
|
*/
|
|
exclude?: RegExp;
|
|
}
|
|
|
|
/**
|
|
* Vite plugin for compile-time codec generation.
|
|
*
|
|
* Add to vite.config.ts:
|
|
*
|
|
* import { serializerCodegen } from '@perf/serializer/codegen/vite';
|
|
*
|
|
* export default {
|
|
* plugins: [serializerCodegen()],
|
|
* };
|
|
*
|
|
* In source code, write:
|
|
*
|
|
* import { type, u53, f64, str } from '@perf/serializer';
|
|
* const Ticker = type('Ticker', { symbol: str, last: f64 });
|
|
*
|
|
* The plugin replaces each `type(...)` / `oneOf(...)` call with an inline IIFE
|
|
* that produces the same codec, eliminating runtime `new Function` compilation.
|
|
*/
|
|
export interface VitePlugin {
|
|
name: string;
|
|
enforce?: 'pre' | 'post';
|
|
transform(code: string, id: string): { code: string; map: null } | null;
|
|
}
|
|
|
|
export function serializerCodegen(options: SerializerPluginOptions = {}): VitePlugin {
|
|
const include = options.include ?? /\.(?:ts|tsx|mts|cts)$/;
|
|
const exclude = options.exclude;
|
|
|
|
return {
|
|
name: 'perf-serializer-codegen',
|
|
enforce: 'pre',
|
|
transform(code: string, id: string) {
|
|
if (id.includes('node_modules')) return null;
|
|
if (!include.test(id)) return null;
|
|
if (exclude && exclude.test(id)) return null;
|
|
// Quick negative: file doesn't even contain the word `type` or `oneOf`
|
|
if (!code.includes('type(') && !code.includes('oneOf(')) return null;
|
|
|
|
try {
|
|
const result = transform(code, id, options);
|
|
if (result.transformedCount === 0) return null;
|
|
return { code: result.code, map: null };
|
|
} catch (err) {
|
|
// Don't break the build on parse errors — leave source as-is so the
|
|
// runtime fallback handles it.
|
|
const msg = (err as Error).message ?? String(err);
|
|
// eslint-disable-next-line no-console
|
|
console.warn(`[perf-serializer-codegen] skipped ${id}: ${msg}`);
|
|
return null;
|
|
}
|
|
},
|
|
};
|
|
}
|
|
|
|
export default serializerCodegen;
|