| name | bun-macros |
| description | Evaluate JavaScript at bundle time and inline results. Use when optimizing compile-time code generation, embedding files, inlining environment variables, or executing code during the bundling process. |
| metadata | {"version":"1.0.0"} |
| license | MIT |
Bun Macros
Bun macros run JavaScript at bundle time and inline the results into the output.
Quick Start
export function getVersion() {
return "1.0.0";
}
export function getBuildTime() {
return new Date().toISOString();
}
import { getVersion, getBuildTime } from "./config" with { type: "macro" };
const version = "1.0.0";
const buildTime = "2024-01-15T12:00:00.000Z";
Macro Syntax
import { fn } from "./macro-file" with { type: "macro" };
const result = fn();
Common Use Cases
Environment Inlining
export function env(key: string): string {
return process.env[key] ?? "";
}
import { env } from "./macros/env" with { type: "macro" };
const apiUrl = env("API_URL");
Git Information
export function gitCommit(): string {
return Bun.spawnSync(["git", "rev-parse", "HEAD"])
.stdout.toString().trim();
}
export function gitBranch(): string {
return Bun.spawnSync(["git", "branch", "--show-current"])
.stdout.toString().trim();
}
import { gitCommit, gitBranch } from "./macros/git" with { type: "macro" };
const BUILD_INFO = {
commit: gitCommit(),
branch: gitBranch(),
};
File Embedding
export function embedFile(path: string): string {
return Bun.file(path).text();
}
export function embedJSON(path: string): unknown {
return Bun.file(path).json();
}
import { embedFile, embedJSON } from "./macros/embed" with { type: "macro" };
const license = embedFile("./LICENSE");
const config = embedJSON("./config.json");
Build Constants
export function isDev(): boolean {
return process.env.NODE_ENV !== "production";
}
export function buildDate(): number {
return Date.now();
}
export function randomId(): string {
return Math.random().toString(36).slice(2);
}
import { isDev, buildDate, randomId } from "./macros/constants" with { type: "macro" };
if (isDev()) {
console.log("Development mode");
}
const BUILD_ID = randomId();
Directory Listing
import { readdirSync } from "fs";
export function listRoutes(): string[] {
return readdirSync("./src/routes")
.filter(f => f.endsWith(".tsx"))
.map(f => f.replace(".tsx", ""));
}
import { listRoutes } from "./macros/files" with { type: "macro" };
const routes = listRoutes();
Code Generation
export function generateTypes(schema: string): string {
const types = parseSchemaToTypes(schema);
return types;
}
export function generateAPI(spec: string): string {
const openapi = JSON.parse(Bun.file(spec).text());
return generateClientFromOpenAPI(openapi);
}
Return Types
Macros can return:
export function getString(): string { return "hello"; }
export function getNumber(): number { return 42; }
export function getBoolean(): boolean { return true; }
export function getNull(): null { return null; }
export function getObject(): object {
return { key: "value", nested: { a: 1 } };
}
export function getArray(): string[] {
return ["a", "b", "c"];
}
export function getResponse(): {
(, {
: { : },
});
}
Async Macros
export async function fetchSchema(): Promise<object> {
const response = await fetch("https://api.example.com/schema.json");
return response.json();
}
import { fetchSchema } from "./macros/fetch" with { type: "macro" };
const schema = await fetchSchema();
Parameters
export function repeat(str: string, count: number): string {
return str.repeat(count);
}
export function formatDate(format: string): string {
return new Date().toLocaleDateString("en-US", {
dateStyle: format as any,
});
}
import { repeat, formatDate } from "./macros/parameterized" with { type: "macro" };
const separator = repeat("-", 20);
const date = formatDate("long");
Conditional Code
export function platform(): "node" | "bun" | "browser" {
if (typeof Bun !== "undefined") return "bun";
if (typeof process !== "undefined") return "node";
return "browser";
}
import { platform } from "./macros/platform" with { type: "macro" };
if (platform() === "bun") {
console.log("Running on Bun");
}
Bundle-Only Execution
Macros ONLY run during bundling:
bun build src/index.ts --outdir=dist
bun run src/index.ts
Error Handling
export function requireEnv(key: string): string {
const value = process.env[key];
if (!value) {
throw new Error(`Missing required env var: ${key}`);
}
return value;
}
import { requireEnv } from "./macros/safe" with { type: "macro" };
const secret = requireEnv("API_SECRET");
Debugging Macros
export function debug(label: string, value: unknown): unknown {
console.log(`[MACRO] ${label}:`, value);
return value;
}
bun build src/index.ts --outdir=dist
Best Practices
- Keep macros pure - Avoid side effects
- Return serializable values - Must be JSON-compatible
- Handle errors - Throw meaningful errors for build failures
- Document dependencies - Note what files/env vars are required
- Test separately - Macros can be tested as regular functions
Common Errors
| Error | Cause | Fix |
|---|
Cannot find module | Wrong import path | Check macro file location |
Not serializable | Function/class returned | Return plain data |
Macro failed | Runtime error in macro | Debug macro separately |
Not evaluated | Missing with { type: "macro" } | Add import attribute |
When to Load References
Load references/advanced-patterns.md when:
- Complex code generation
- Plugin integration
- Build pipelines
Retrieve and present patterns for custom macro implementations, integration examples with build systems, and advanced bundler plugin workflows.
Load references/debugging.md when:
- Macro not evaluating
- Unexpected output
- Performance issues
Retrieve debugging techniques, provide step-by-step diagnostics, and offer optimization strategies tied to the user's specific issue.