TypeScript macro expansion engine - write compile-time macros in Rust
This crate provides a TypeScript macro expansion engine that brings Rust-like derive macros to TypeScript. It is designed to be used via NAPI bindings from Node.js, enabling compile-time code generation for TypeScript projects.
Macroforge processes TypeScript source files containing @derive decorators and expands them
into concrete implementations. For example, a class decorated with @derive(Debug, Clone)
will have toString() and clone() methods automatically generated.
The crate is organized into several key components:
- NAPI Bindings (
NativePlugin,expand_sync,transform_sync): Entry points for Node.js - Position Mapping (
NativePositionMapper,NativeMapper): Bidirectional source mapping for IDE integration - Macro Host (
hostmodule): Core expansion engine with registry and dispatcher - Built-in Macros (
builtinmodule): Standard derive macros (Debug, Clone, Serialize, etc.)
- Uses a 32MB thread stack to prevent stack overflow during deep SWC AST recursion
- Implements early bailout for files without
@derivedecorators - Caches expansion results keyed by filepath and version
- Uses binary search for O(log n) position mapping lookups
const { NativePlugin, expand_sync } = require('macroforge-ts');
// Create a plugin instance with caching
const plugin = new NativePlugin();
// Process a file (uses cache if version matches)
const result = plugin.process_file(filepath, code, { version: '1.0' });
// Or use the sync function directly
const result = expand_sync(code, filepath, { keep_decorators: false });This crate re-exports several dependencies for convenience when writing custom macros:
ts_syn: TypeScript syntax types for AST manipulationmacros: Macro attributes and quote templatesswc_core,swc_common,swc_ecma_ast: SWC compiler infrastructure
Add this to your Cargo.toml:
[dependencies]
macroforge_ts = "0.1.38"TransformResult- Result of transforming TypeScript code through the macro system.MacroDiagnostic- A diagnostic message produced during macro expansion.MappingSegmentResult- A segment mapping a range in the original source to a range in the expanded source.GeneratedRegionResult- A region in the expanded source that was generated by a macro.SourceMappingResult- Complete source mapping information for a macro expansion.ExpandResult- Result of expanding macros in TypeScript source code.ImportSourceResult- Information about an imported identifier from a TypeScript module.SyntaxCheckResult- Result of checking TypeScript syntax validity.SpanResult- A span (range) in source code, represented as start position and length.JsDiagnostic- A diagnostic from the TypeScript/JavaScript compiler or IDE.- ... and 8 more
unchanged- Creates a no-op result with the original code unchanged.new- Creates a new position mapper from source mapping data.is_empty- Checks if this mapper has no mapping data.original_to_expanded- Converts a position in the original source to the corresponding position in expanded source.expanded_to_original- Converts a position in the expanded source back to the original source position.generated_by- Returns the name of the macro that generated code at the given position.map_span_to_original- Maps a span (start + length) from expanded source to original source.map_span_to_expanded- Maps a span (start + length) from original source to expanded source.is_in_generated- Checks if a position is inside macro-generated code.new- Creates a new mapper wrapping the given source mapping.- ... and 23 more
See the full API documentation on the Macroforge website.
MIT