Files

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;