npm package: @genzai/core
Description: Core code generation framework with template composition and middleware pipeline
Latest version: 0.2.0

# @genzai/core

Minimal code generation framework with composable templates and middleware pipeline.

## Installation

```bash
npm install @genzai/core
# or
pnpm add @genzai/core
```

## Quick Start

```typescript
import { generate, file, folder } from "@genzai/core";
import type { Node } from "@genzai/core";

// Define your generator - a function that takes context and returns nodes
const myGenerator = (ctx: { projectName: string }): Node[] => [
  folder("src", [
    file("index.ts", `export const name = "${ctx.projectName}";`),
    file("config.ts", () => `export const config = { name: "${ctx.projectName}" };`),
  ]),
  file("README.md", `# ${ctx.projectName}\n\nGenerated with Genzai!`),
];

// Generate to filesystem
await generate(myGenerator, "./output", { projectName: "my-app" });
```

## Core Concepts

### Generator

A generator is simply a function that takes context and returns an array of nodes (sync or async):

```typescript
type Generator<C, Meta = {}> = (ctx: C) => Node<Meta>[] | Promise<Node<Meta>[]>;
```

### Nodes

Two types of nodes:

- `FileNode` - Represents a file with lazy-loaded content
- `FolderNode` - Represents a folder with child nodes

## API

### `file(name, content, meta?)`

Creates a file node.

```typescript
// Static content
file("hello.txt", "Hello, World!")

// Dynamic content (function)
file("config.json", () => JSON.stringify({ version: "1.0.0" }))

// Async content
file("data.json", async () => {
  const data = await fetchData();
  return JSON.stringify(data);
})

// With metadata
file("output.txt", "content", { priority: 10 })
```

**Parameters:**
- `name`: `string | (() => string)` - File name or function returning name
- `content`: `string | (() => string | Promise<string>)` - Content or function returning content
- `meta?`: `Meta` - Optional metadata object

**Returns:** `FileNode<Meta>`

### `folder(name, children, meta?)`

Creates a folder node containing children.

```typescript
folder("src", [
  file("index.ts", "export {}"),
  file("utils.ts", "export const helper = () => {}"),
])

// With dynamic name
folder(() => "dist", [...])

// With metadata
folder("build", [...], { temporary: true })
```

**Parameters:**
- `name`: `string | (() => string)` - Folder name or function returning name
- `children`: `Node<Meta>[]` - Array of child nodes
- `meta?`: `Meta` - Optional metadata object

**Returns:** `FolderNode<Meta>`

### `generate(generator, destRoot, context, config?)`

Executes generator and writes to filesystem.

```typescript
await generate(
  myGenerator,
  "./output",
  { projectName: "my-app" },
  { middlewares: [loggingMiddleware] }
);
```

**Parameters:**
- `generator`: `Generator<C, Meta>` - Generator function
- `destRoot`: `string` - Output directory
- `context`: `C` - Context passed to generator
- `config?`: `MiddlewareConfig<Meta>` - Optional middleware configuration

## Patterns

### Iteration

Use native JavaScript for iteration:

```typescript
const generator = (ctx: { users: User[] }): Node[] => [
  folder("users",
    ctx.users.map(user =>
      file(`${user.name}.json`, JSON.stringify(user))
    )
  ),
];
```

### Conditionals

Use ternaries or conditionals:

```typescript
const generator = (ctx: { includeTests: boolean }): Node[] => [
  file("index.ts", "export {}"),
  ...(ctx.includeTests ? [file("test.ts", "// tests")] : []),
];
```

### Nested Structures

```typescript
const generator = (ctx: { screens: Screen[] }): Node[] =>
  ctx.screens.map(screen =>
    folder(screen.name.toLowerCase(), [
      file("page.tsx", () => makePageTemplate(screen, ctx)),
      file("types.ts", () => makeTypesTemplate(screen)),
    ])
  );
```



## Default Middleware

The `defaultMiddleware` array provides file markers and regeneration strategy handling out of the box:

```typescript
import { generate, file, folder, defaultMiddleware } from "@genzai/core";

await generate(myGenerator, "./output", ctx, {
  middlewares: defaultMiddleware,
});
```

Generated files will include metadata markers:

```typescript
/**
 * @generated genzai
 * @regenerationStrategy overwrite
 */
export const name = "my-app";
```

### Regeneration Strategies

Control how files are handled on regeneration:

- `"overwrite"` (default) - File is regenerated every time
- `"preserve-edits"` - File is skipped if it already exists with this strategy

```typescript
import { file } from "@genzai/core";
import type { RegenerationStrategyMeta } from "@genzai/core";

const generator = (): Node<RegenerationStrategyMeta>[] => [
  // Always regenerated
  file("generated.ts", () => `// generated code`),

  // Preserved after first generation
  file<RegenerationStrategyMeta>("config.ts", () => `export default {}`, {
    regenerationStrategy: "preserve-edits",
  }),
];
```

## Custom Middleware

Middleware intercepts the write process for transformations, logging, etc.

```typescript
import { Middleware } from "@genzai/core";

const loggingMiddleware: Middleware = async (context, next) => {
  console.log(`Writing: ${context.path}`);
  return next(context);
};

const uppercaseMiddleware: Middleware = async (context, next) => {
  if (context.nodeType === "file") {
    return next({
      ...context,
      content: context.content.toUpperCase(),
    });
  }
  return next(context);
};

await generate(myGenerator, "./output", ctx, {
  middlewares: [loggingMiddleware, uppercaseMiddleware],
});
```

## Metadata

Attach custom metadata to nodes for middleware processing:

```typescript
type MyMeta = {
  file: {
    overwrite?: boolean;
    format?: string;
  }
  folder: Record<string, any>;
};

const generator = (): Node<MyMeta>[] => [
  file("config.json", "{}", { overwrite: false, format: "json" }),
];

// Middleware can access metadata via node.meta
const formatMiddleware: Middleware<MyMeta> = async (ctx, next) => {
  if (ctx.nodeType === "file" && ctx.node.meta?.format === "json") {
    const formatted = JSON.stringify(JSON.parse(ctx.content), null, 2);
    return next({ ...ctx, content: formatted });
  }
  return next(ctx);
};
```

## Related Packages

- `@genzai/templates` - Load generators from template directories
- `@genzai/slots` - Slot-based content preservation
- `@genzai/logging` - Logging middleware
- `@genzai/prettier` - Code formatting middleware

## License

MIT