npm package: @genzai/slots
Description: Slot-based content preservation for code generation
Latest version: 0.2.2

# @genzai/slots

Slot-based content preservation for code generation. Preserve user-written code across regeneration cycles.

## Installation

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

## Overview

`@genzai/slots` allows you to mark sections of generated code that should be preserved when files are regenerated. This is essential for code generators that need to support both generated and hand-written code in the same files.

## Features

- 📍 **Slot Markers**: Define preservable regions with JSDoc-style markers
- 🔄 **Content Preservation**: Automatically restore slot content during regeneration
- 🏷️ **Metadata Support**: Attach metadata to slots for advanced use cases
- 🔌 **Middleware Integration**: Seamlessly integrates with `@genzai/core`

## Quick Start

```typescript
import { write } from "@genzai/core";
import { slot, slotMiddleware } from "@genzai/slots";

// In your template
const template = () => `
export class MyClass {
  ${slot.begin("custom-methods")}
  // Add your custom methods here
  ${slot.end}
}
`;

// Use the middleware when writing
await write(plan, "./output", [], {
  middlewares: [slotMiddleware],
});
```

## Slot Syntax

Slots are defined using JSDoc-style comments:

```typescript
/**
 * @slot custom-code - Content will be preserved across regeneration
 */
// Your custom code here
/** @end-slot */
```

### Using the Helper

```typescript
import { slot } from "@genzai/slots";

const code = `
class Example {
  ${slot.begin("methods")}
  // Custom methods go here
  ${slot.end}
}
`;
```

### With Metadata

```typescript
const code = `
${slot.begin("config", { version: 1, required: true })}
// Configuration code
${slot.end}
`;
```

## API Reference

### `slot`

Helper object for creating slot markers.

#### `slot.begin(name, meta?)`

Creates a begin marker for a slot.

- `name` - Unique identifier for the slot
- `meta` - Optional metadata object

```typescript
slot.begin("custom-code");
slot.begin("config", { version: 1, editable: true });
```

#### `slot.end`

The end marker for a slot (constant string).

```typescript
slot.end; // /** @end-slot */
```

### `extractSlots(fileContent)`

Extracts all slots from file content.

```typescript
import { extractSlots } from "@genzai/slots";

const content = `
/**
 * @slot test - Test slot
 * @version 1
 */
const custom = "code";
/** @end-slot */
`;

const slots = extractSlots(content);
// {
//   test: {
//     id: "test",
//     content: "\nconst custom = \"code\";\n",
//     meta: { version: 1 },
//     definitionStartLine: 2,
//     contentStartLine: 5,
//     contentEndLine: 7,
//     definitionEndLine: 7
//   }
// }
```

### `applySlots(generatedContent, savedSlots)`

Applies saved slot contents to newly generated content.

```typescript
import { applySlots, extractSlots } from "@genzai/slots";

// Extract slots from existing file
const existingContent = await fs.readFile("file.ts", "utf8");
const savedSlots = extractSlots(existingContent);

// Apply to new generated content
const newContent = generateContent();
const merged = applySlots(newContent, savedSlots);
```

### `slotMiddleware`

Middleware that automatically extracts and applies slots during the write process.

```typescript
import { write } from "@genzai/core";
import { slotMiddleware } from "@genzai/slots";

await write(plan, "./output", [], {
  middlewares: [slotMiddleware],
});
```

## Types

### `Slot`

```typescript
type Slot = {
  id: string;
  content: string;
  meta: SlotMetaData;
  definitionStartLine: number;
  contentStartLine: number;
  contentEndLine: number;
  definitionEndLine: number;
};
```

### `SlotMetaData`

```typescript
type SlotMetaData = Record<string, string | number | boolean>;
```

## How It Works

1. **First Generation**: Slots are created with empty or default content
2. **User Edits**: Users add their custom code inside slot markers
3. **Regeneration**: The middleware extracts existing slot content
4. **Merging**: Saved content is reinserted into newly generated slots
5. **Writing**: Final merged content is written to disk

## Example: React Component Generator

```typescript
import { file } from "@genzai/core";
import { slot } from "@genzai/slots";

const componentGenerator = (name: string) => file(
  `${name}.tsx`,
  () => `
import React from 'react';

interface ${name}Props {
  ${slot.begin("props")}
  // Add your custom props here
  ${slot.end}
}

export const ${name}: React.FC<${name}Props> = (props) => {
  ${slot.begin("hooks")}
  // Add your custom hooks here
  ${slot.end}

  return (
    <div>
      ${slot.begin("jsx")}
      <p>Default content</p>
      ${slot.end}
    </div>
  );
};

${slot.begin("exports")}
// Add additional exports here
${slot.end}
`
);
```

After first generation, users can add their code:

```typescript
export const Button: React.FC<ButtonProps> = (props) => {
  /**
   * @slot hooks - Custom hooks
   */
  const [count, setCount] = useState(0);
  const theme = useTheme();
  /** @end-slot */

  return (
    <div>
      {/* ... */}
    </div>
  );
};
```

On regeneration, the custom hooks are preserved!

## Best Practices

1. **Unique Names**: Use descriptive, unique slot names
2. **Documentation**: Add comments in slot markers explaining their purpose
3. **Sensible Defaults**: Provide helpful default content in slots
4. **Metadata**: Use metadata to version slots or mark them as required
5. **Indentation**: The middleware preserves original indentation

## Related Packages

- `@genzai/core` - Core generation framework (required)
- `@genzai/merge-strategy` - File conflict resolution
- `@genzai/logging` - Logging middleware

## License

MIT