Files
gh-vanman2024-cli-builder-p…/skills/gluegun-patterns/examples/template-generator/README.md
2025-11-30 09:04:14 +08:00

6.4 KiB

Template Generator Example

Advanced template patterns for Gluegun CLI generators.

Structure

template-generator/
├── src/
│   └── commands/
│       ├── new-app.ts          # Multi-file generator
│       ├── new-feature.ts      # Feature scaffold
│       └── new-config.ts       # Config generator
├── templates/
│   ├── app/
│   │   ├── package.json.ejs
│   │   ├── tsconfig.json.ejs
│   │   ├── src/
│   │   │   └── index.ts.ejs
│   │   └── README.md.ejs
│   ├── feature/
│   │   ├── component.tsx.ejs
│   │   ├── test.spec.ts.ejs
│   │   └── styles.css.ejs
│   └── config/
│       └── config.json.ejs
└── README.md

Features

  • Multi-file generation from template sets
  • Conditional template sections
  • Nested directory creation
  • Template composition
  • Helper functions for common operations

Patterns

1. Multi-File Generation

Generate complete project structure:

await template.generate({
  template: 'app/package.json.ejs',
  target: `${name}/package.json`,
  props: { name, version }
})

await template.generate({
  template: 'app/src/index.ts.ejs',
  target: `${name}/src/index.ts`,
  props: { name }
})

2. Conditional Templates

Templates with conditional sections:

<% if (includeTests) { %>
import { test } from 'vitest'

test('<%= name %> works', () => {
  // Test implementation
})
<% } %>

3. Template Loops

Generate repetitive structures:

<% features.forEach(feature => { %>
export { <%= feature.name %> } from './<%= feature.path %>'
<% }) %>

4. Nested Templates

Organize templates in directories:

templates/
├── react-app/
│   ├── components/
│   │   └── Component.tsx.ejs
│   ├── pages/
│   │   └── Page.tsx.ejs
│   └── layouts/
│       └── Layout.tsx.ejs

5. Template Helpers

Use helper functions in templates:

/**
 * <%= helpers.titleCase(name) %> Component
 * File: <%= helpers.kebabCase(name) %>.ts
 */

export class <%= helpers.pascalCase(name) %> {
  // Implementation
}

Commands

new-app

Create complete application structure:

./bin/cli new-app my-project --typescript --tests

Options:

  • --typescript: Include TypeScript configuration
  • --tests: Include test setup
  • --git: Initialize git repository
  • --install: Run npm install

new-feature

Scaffold a new feature with tests and styles:

./bin/cli new-feature UserProfile --redux --tests

Options:

  • --redux: Include Redux setup
  • --tests: Generate test files
  • --styles: Include CSS/SCSS files

new-config

Generate configuration files:

./bin/cli new-config --eslint --prettier --jest

Options:

  • --eslint: ESLint configuration
  • --prettier: Prettier configuration
  • --jest: Jest configuration
  • --typescript: TypeScript configuration

Template Variables

Common Props

{
  name: string              // Component/project name
  description: string       // Description
  author: string           // Author name
  version: string          // Version number
  timestamp: string        // ISO timestamp
  year: number            // Current year
}

Feature-Specific Props

{
  // React component
  componentType: 'class' | 'function'
  withHooks: boolean
  withState: boolean

  // Configuration
  includeESLint: boolean
  includePrettier: boolean
  includeTests: boolean

  // Dependencies
  dependencies: string[]
  devDependencies: string[]
}

Advanced Techniques

1. Template Composition

Combine multiple templates:

// Base component template
await template.generate({
  template: 'base/component.ts.ejs',
  target: 'src/components/Base.ts',
  props: baseProps
})

// Extended component using base
await template.generate({
  template: 'extended/component.ts.ejs',
  target: 'src/components/Extended.ts',
  props: { ...baseProps, extends: 'Base' }
})

2. Dynamic Template Selection

Choose templates based on user input:

const framework = await prompt.select('Framework:', [
  'React',
  'Vue',
  'Angular'
])

const templatePath = `${framework.toLowerCase()}/component.ejs`
await template.generate({
  template: templatePath,
  target: `src/components/${name}.tsx`,
  props: { name }
})

3. Template Preprocessing

Modify props before generation:

const props = {
  name,
  pascalName: strings.pascalCase(name),
  kebabName: strings.kebabCase(name),
  dependencies: dependencies.sort(),
  imports: generateImports(dependencies)
}

await template.generate({
  template: 'component.ts.ejs',
  target: `src/${props.kebabName}.ts`,
  props
})

4. Post-Generation Actions

Run actions after template generation:

// Generate files
await template.generate({ /* ... */ })

// Format generated code
await system.run('npm run format')

// Run initial build
await system.run('npm run build')

// Initialize git
if (options.git) {
  await system.run('git init')
  await system.run('git add .')
  await system.run('git commit -m "Initial commit"')
}

5. Template Validation

Validate templates before generation:

// Check if template exists
if (!filesystem.exists(`templates/${templatePath}`)) {
  print.error(`Template not found: ${templatePath}`)
  return
}

// Validate template syntax
const templateContent = await filesystem.read(`templates/${templatePath}`)
if (!validateEJS(templateContent)) {
  print.error('Invalid EJS syntax in template')
  return
}

Best Practices

  1. Organize Templates: Group related templates in directories
  2. Use Helpers: Extract common logic into helper functions
  3. Validate Input: Check user input before generation
  4. Provide Feedback: Show progress with spinners
  5. Handle Errors: Gracefully handle missing templates
  6. Document Variables: Comment template variables
  7. Test Templates: Generate samples to verify output

Testing Generated Code

# Generate sample
./bin/cli new-app test-project --all

# Verify structure
cd test-project
npm install
npm test
npm run build

Template Development Workflow

  1. Create template file with .ejs extension
  2. Add template variables with <%= %> syntax
  3. Test template with sample props
  4. Add conditional sections with <% if %> blocks
  5. Validate generated output
  6. Document template variables and options