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.
Rust Setup
Create a new Rust crate that will contain your custom macros. It compiles to WebAssembly, packaged as an npm package that Macroforge loads.
Prerequisites
- A Rust toolchain with the WebAssembly target:
rustup target add wasm32-unknown-unknown - The Macroforge CLI:
cargo install macroforge_ts wasm-bindgen-cliat the version of thewasm-bindgencrate your macro crate builds with. After addingmacroforge_tsbelow,cargo tree -i wasm-bindgen --depth 0prints it; install that version withcargo install wasm-bindgen-cli --version <version> --locked.
Create the Project
Bash
cargo new --lib my-macros
cd my-macrosConfigure Cargo.toml
Cargo.toml
[package]
name = "my-macros"
version = "0.1.0"
edition = "2024"
[lib]
crate-type = ["cdylib", "rlib"]
[dependencies]
macroforge_ts = "0.4"
[profile.release]
lto = true
strip = trueCreate src/lib.rs
src/lib.rs
use macroforge_ts::macros::{ts_macro_derive, ts_template};
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(ts_template!(Within {
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",
)),
}
}Create package.json
macroforge build writes the package into pkg/, named
after the library target: my_macros for this crate.
package.json
{
"name": "@my-org/macros",
"version": "0.1.0",
"main": "pkg/my_macros.js",
"types": "pkg/my_macros.d.ts",
"files": ["pkg"],
"scripts": {
"build": "macroforge build . --out pkg"
}
}Build the Package
Bash
npm run build
# This creates, in pkg/:
# - my_macros.js (JavaScript bindings)
# - my_macros.d.ts (TypeScript types)
# - my_macros_bg.wasm (the macros) Tip
The WebAssembly module runs on every platform, so one build serves every OS.