@validkeys/ollypop-ts
Version:
Automatic TypeScript barrel file generator CLI.
370 lines (290 loc) • 10.5 kB
Markdown
# Ollypop
> **Automatic TypeScript Barrel File Generation**
## Overview
Ollypop is a CLI tool for generating TypeScript barrel files (`index.ts`) automatically. It uses a powerful variable-based template system to scan directories and files, creating export statements based on your configuration. The system supports both directory-based and file-based patterns, with intelligent file existence filtering and path resolution relative to the output file location.
## Features
- **Variable-based export templates**: Use `{dir}` or `{file}` placeholders in your export statements
- **Chained transformations**: Apply casing, singular/plural, prefix/suffix, and more
- **Automatic pattern detection**: Scans for files or directories based on your template
- **File existence filtering**: Only exports items that actually exist
- **Partial replace mode**: Update only the auto-generated section of a file
- **No `cwd` required**: All paths are resolved relative to the output file
- **Dry run mode**: Preview changes before writing
## Quick Start
1. **Install dependencies**
```bash
pnpm install
```
2. **Create a configuration file**
```bash
pnpm exec ollypop init
# Or copy and edit barrel.config.json
```
3. **Generate barrels**
```bash
pnpm exec ollypop generate
```
4. **Run examples**
```bash
# Run all examples to see different patterns
pnpm run examples
# Or run individual examples
pnpm run example:basic # File-based without extensions
pnpm run example:directory # Directory-based without extensions
pnpm run example:with-extensions # File-based with .js extensions
pnpm run example:directory-extensions # Directory-based with .js extensions
```
## Configuration
Configuration is defined in `barrel.config.json`:
```json
{
"version": "1.0",
"barrels": [
{
"name": "handlers",
"output": "./src/handlers/index.ts",
"template": {
"name": "variable-template",
"export": "export * from './{dir:raw}/index.js'"
},
"options": {
"preserveExtensions": true,
"extensions": [".ts"],
"validateExports": false,
"dryRun": false
}
},
{
"name": "interfaces",
"output": "./src/index.browser.ts",
"template": {
"name": "variable-template",
"export": "export * from './handlers/{dir:raw}/interface.js'",
"mode": "partial-replace"
},
"options": {
"preserveExtensions": true,
"extensions": [".ts"],
"validateExports": false,
"dryRun": false
}
}
]
}
```
### Template System
- **Variables**: `{dir}` for directory names, `{file}` for file names
- **Transforms**: `{dir:raw}`, `{dir:camel}`, `{dir:pascal}`, `{dir:kebab}`, `{dir:singular}`, `{dir:plural}`, `{dir:trimPrefix:foo-}`, `{dir:addSuffix:Bar}`
- **Chaining**: `{dir:trimPrefix:foo-|pascal|plural}`
- **Partial Replace**: Use `mode: "partial-replace"` to update only the marked section of a file
## Transformations Reference
The variable template system supports a wide range of transformations for directory and file names. You can chain multiple transformations using the pipe (`|`) operator.
| Syntax | Description | Example Input | Example Output |
| ------------------------------------ | ---------------------------------------- | -------------------- | ------------------ |
| `{dir}` | PascalCase (default) | `user-profile` | `UserProfile` |
| `{dir:raw}` | Preserve original | `user-profile` | `user-profile` |
| `{dir:camel}` | camelCase | `user-profile` | `userProfile` |
| `{dir:kebab}` | kebab-case | `UserProfile` | `user-profile` |
| `{dir:pascal}` | PascalCase | `user-profile` | `UserProfile` |
| `{dir:singular}` | Singularize (inflection) | `account-balances` | `account-balance` |
| `{dir:plural}` | Pluralize (inflection) | `account-balance` | `account-balances` |
| `{dir:trimPrefix:warehouse-,ops-}` | Remove specified prefixes | `warehouse-accounts` | `accounts` |
| `{dir:trimSuffix:Service,Manager}` | Remove specified suffixes | `AccountService` | `Account` |
| `{dir:addPrefix:I,Base}` | Add specified prefix | `Account` | `IAccount` |
| `{dir:addSuffix:Factory,Service}` | Add specified suffix | `Account` | `AccountFactory` |
| `{dir:replace:old,new;acct,account}` | Replace text (semicolon-separated pairs) | `old-acct-data` | `new-account-data` |
| `{dir:uppercase}` | Convert to uppercase | `account` | `ACCOUNT` |
| `{dir:lowercase}` | Convert to lowercase | `ACCOUNT` | `account` |
| `{dir:capitalize}` | Capitalize first letter | `account` | `Account` |
| `{dir:uncapitalize}` | Lowercase first letter | `Account` | `account` |
### Chained Transformations
You can chain multiple transformations using the pipe operator:
```json
{
"template": {
"name": "variable-template",
"export": "export * as {dir:trimPrefix:warehouse-,ops-|singular|pascal}Factory from './{dir:raw}/factory.js'"
}
}
```
**Transformation Flow:**
1. `warehouse-account-balances` → **trimPrefix** → `account-balances`
2. `account-balances` → **singular** → `account-balance`
3. `account-balance` → **pascal** → `AccountBalance`
4. Final result: `AccountBalanceFactory`
---
## Configuration Examples & Resulting Barrel Output
### 1. Directory-Based Barrel
**Config:**
```json
{
"template": {
"name": "variable-template",
"export": "export * from './{dir:raw}/index.js'"
}
}
```
**Directory Structure:**
```
src/handlers/
├── createUser/
│ └── index.ts
├── updateProfile/
│ └── index.ts
└── deleteAccount/
└── interface.ts
```
**Resulting Barrel:**
```typescript
export * from './createUser/index.js';
export * from './updateProfile/index.js';
// deleteAccount excluded (no index.ts)
```
### 2. File-Based Barrel
**Config:**
```json
{
"template": {
"name": "variable-template",
"export": "export * from './{file:raw}.ts'"
}
}
```
**Directory Structure:**
```
src/primitives/
├── accountType.ts
├── assetType.ts
├── currency.ts
├── index.ts (barrel file, auto-excluded)
└── logging.ts
```
**Resulting Barrel:**
```typescript
export * from './accountType.ts';
export * from './assetType.ts';
export * from './currency.ts';
export * from './logging.ts';
// index.ts excluded automatically
```
### 3. Interface Barrel (Partial Replace)
**Config:**
```json
{
"template": {
"name": "variable-template",
"export": "export * from './handlers/{dir:raw}/interface.js'",
"mode": "partial-replace"
}
}
```
**Directory Structure:**
```
src/handlers/
├── createUser/
│ ├── index.ts
│ └── interface.ts
├── updateProfile/
│ └── index.ts (no interface.ts)
└── deleteAccount/
└── interface.ts
```
**Resulting Barrel Section:**
```typescript
// AUTO-GENERATED EXPORTS - START
export * from './handlers/createUser/interface.js';
export * from './handlers/deleteAccount/interface.js';
// AUTO-GENERATED EXPORTS - END
```
### 4. Advanced Naming with Chained Transforms
**Config:**
```json
{
"template": {
"name": "variable-template",
"export": "export * as {dir:singular|pascal}Service from './{dir:raw}/service.js'"
}
}
```
**Directory Structure:**
```
src/services/
├── accounts/
│ └── service.ts
├── payments/
│ └── service.ts
```
**Resulting Barrel:**
```typescript
export * as AccountService from './accounts/service.js';
export * as PaymentService from './payments/service.js';
```
### 5. Multi-Level Variables (Future/Advanced)
**Config:**
```json
{
"template": {
"name": "variable-template",
"export": "export * as {namespace:raw}{Entity:pascal}Factory from './{namespace:raw}/{Entity:raw}/factory.js'"
}
}
```
**Directory Structure:**
```
src/domains/
├── warehouse/
│ └── product/
│ └── factory.ts
├── retail/
│ └── customer/
│ └── factory.ts
```
**Resulting Barrel:**
```typescript
export * as warehouseProductFactory from './warehouse/product/factory.js';
export * as retailCustomerFactory from './retail/customer/factory.js';
```
## CLI Commands
Ollypop provides several commands for managing barrel file generation:
### Generate
Generate barrel files based on your configuration:
```bash
ollypop generate [options]
```
**Options:**
- `--config <path>` - Path to configuration file (default: "barrel.config.json")
- `--dry-run` - Preview changes without writing files
- `--verbose` - Show detailed generation information
**Example:**
```bash
ollypop generate --config my-config.json --verbose
```
### Validate
Validate your configuration file for syntax errors:
```bash
ollypop validate [options]
```
**Options:**
- `--config <path>` - Path to configuration file (default: "barrel.config.json")
**Example:**
```bash
ollypop validate --config my-config.json
```
This command validates:
- Export template syntax (proper quoting, variables)
- Configuration file structure
- Path resolution logic
### Initialize
Create a sample configuration file:
```bash
ollypop init [options]
```
**Options:**
- `--config <path>` - Path for new configuration file (default: "barrel.config.json")
## Common Template Errors
If you encounter template syntax errors, see [Export Template Validation](docs/EXPORT_TEMPLATE_VALIDATION.md) for detailed troubleshooting guide.
**Quick fixes for common issues:**
- Ensure paths are quoted: `"./handlers/{handler}"` not `./handlers/{handler}`
- Use matching quotes: `"..."` or `'...'` but not mixed
- Include variables: `{variable}` in curly braces
---