API Stability Notice
Macroforge is under active development. The API is not yet stable and may change between versions. Some documentation sections may be outdated.
Custom Macros
Macroforge allows you to create custom derive macros in Rust. Your macros have full access to the class AST and can generate any TypeScript code.
Overview
Custom macros are written in Rust and compiled to native Node.js addons. The process involves:
- Creating a Rust crate with NAPI bindings
- Defining macro functions with
#[ts_macro_derive] - Using
macroforge_ts_quoteto generate TypeScript code - Building and publishing as an npm package
Quick Example
Rust
use macroforge_ts::macros::{ts_macro_derive, body};
use macroforge_ts::ts_syn::{Data, DeriveInput, MacroforgeError, TsStream, parse_ts_macro_input};
#[ts_macro_derive(
JSON,
description = "Generates toJSON() returning a plain object"
)]
pub fn derive_json(mut input: TsStream) -> Result<TsStream, MacroforgeError> {
let input = parse_ts_macro_input!(input as DeriveInput);
match &input.data {
Data::Class(class) => {
Ok(body! {
toJSON(): Record<string, unknown> {
return {
{#for field in class.field_names()}
@{field}: this.@{field},
{/for}
};
}
})
}
_ => Err(MacroforgeError::new(
input.decorator_span(),
"@derive(JSON) only works on classes",
)),
}
}Using Custom Macros
Once your macro package is published, users can import and use it:
TypeScript
/** import macro { JSON } from "@my/macros"; */
/** @derive(JSON) */
class User {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
const user = new User("Alice", 30);
console.log(user.toJSON()); // { name: "Alice", age: 30 } Note
The
import macro comment tells Macroforge which package provides the macro.Getting Started
Follow these guides to create your own macros: