feat(serializer): add aot serializer
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user