Template-driven engine that turns structured API definitions into production-ready artifacts. Powered by Typeweaver 🧵✨
npm install @rexeus/typeweaver-gen


Typeweaver is a type-safe HTTP API framework built for API-first development with a focus on
developer experience. Use typeweaver to specify your HTTP APIs in TypeScript and Zod, and generate
clients, validators, routers, and more ✨
Provides the core components for generating code with typeweaver. This package forms the basis for
all plugins.
---
``bash`
npm install -D @rexeus/typeweaver-gen
Most users don’t depend on this package directly — use the CLI instead:
@rexeus/typeweaver. If you’re writing a plugin, start here.
`ts
import { BasePlugin, type GeneratorContext } from "@rexeus/typeweaver-gen";
export default class MyPlugin extends BasePlugin {
// Give your plugin a unique name
name = "my-plugin";
// Use the generate phase to render templates and write files
async generate(context: GeneratorContext) {
for (const [entity, { operations }] of Object.entries(context.resources.entityResources)) {
const content = context.renderTemplate("Entity.ejs", {
entity,
operations,
coreDir: context.coreDir,
});
context.writeFile(${entity}/${entity}Stuff.ts, content);`
}
}
}
Templates live under your plugin’s src/templates. They receive your data object as EJS locals.
- Base classes: BasePlugin, BaseTemplatePlugin for lifecycle defaults, EJS helpers, and libTypeweaverPlugin
copying.
- Types & contexts: , PluginContext, GeneratorContext with writeFile,renderTemplate
, and file tracking.PluginRegistry
- Registry: to register and query plugins; the CLI orchestrates lifecycleGetResourcesResult
execution.
- Resource model: , EntityResources, representing the normalized API data
derived from your definition.
The lifecycle keeps concerns separated and makes it easy to compose multiple plugins. Implement only
what you need.
`ts`
type TypeweaverPlugin = {
name: string;
initialize?(context: PluginContext): void | Promise
collectResources?(
resources: GetResourcesResult
): GetResourcesResult | Promise
generate?(context: GeneratorContext): void | Promise
finalize?(context: PluginContext): void | Promise
};
- Initialize phase (initialize): Load and validate plugin configuration, check prerequisites.collectResources
- Collect Resources phase (): Inspect the normalized API model; derive or enrichgenerate
metadata (naming, groupings), filter or reorder resources, and share derived artifacts across
plugins if needed.
- Generate phase (): Render templates and emit code using context.writeFile (tracked);finalize
copy or produce any runtime libraries required by the generated code.
- Finalize phase (): Post-process outputs, clean stale generated files, and perform final
organization steps.
The GeneratorContext describes the generation phase: it provides access to resolved paths,generate
configuration, the normalized resources, and helper methods for safe file emission and templating.
You receive it only inside the lifecycle method.
`ts`
type GeneratorContext = {
inputDir: string;
outputDir: string;
templateDir: string;
coreDir: string;
config: PluginConfig;
resources: GetResourcesResult;
writeFile(rel: string, content: string): void; // mkdir -p + write + track
// Tracked files are automatically exported via a generated barrel index.ts
renderTemplate(tplPath: string, data: unknown): string; // EJS render
addGeneratedFile(rel: string): void; // track only
getGeneratedFiles(): string[]; // list tracked files
};
Sometimes your generated code needs small reusable runtime pieces (e.g., abstract classes, adapters,
validators, utils etc.). Ship them with your plugin and copy them into the consumer’s generated
output.
- Where to put them: Place TypeScript files under your plugin’s src/lib. They will compile todist/lib
when you build the plugin.
- Copy them:
`ts
import path from "node:path";
import { fileURLToPath } from "node:url";
import { BasePlugin, type GeneratorContext } from "@rexeus/typeweaver-gen";
// Resolve the directory of the current module
const moduleDir = path.dirname(fileURLToPath(import.meta.url));
export default class MyPlugin extends BasePlugin {
name = "my-plugin";
generate(context: GeneratorContext) {
const libSourceDir = path.join(moduleDir, "lib");
this.copyLibFiles(context, libSourceDir, this.name); // ->
- Plugins are configured/executed by the CLI (@rexeus/typeweaver). See the CLI optionsGeneratorContext.writeFile` over manual fs writes for tracking and directory setup.
here.
- Keep plugins focused: one concern per plugin (clients, routers, infra).
- Prefer
Apache 2.0 © Dennis Wentzien 2025