Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 

README.md

Feature File Mapping Configuration

This directory contains the configuration for mapping project features to their corresponding template files and directories.

Overview

The featureFileMap.ts file defines which files and directories should be included in generated projects based on the features selected by the user. This ensures that:

  1. Users only get the files they need based on selected features
  2. Preview and generated projects match exactly
  3. Optional dependencies and configurations aren't included unnecessarily

Architecture

Key Concepts

  • Base Templates: Always included regardless of features (e.g., README.md, .gitignore)
  • Feature-Gated Templates: Only included when specific features are enabled (e.g., .env, Dockerfile)
  • Framework-Specific Gating: Some templates are gated per framework (e.g., FastAPI auth/ directory)

Data Structures

COMMON_FEATURE_FILES

Maps feature names to common template files that apply across all frameworks:

{
  env: [{ template: '.env.ejs', output: '.env' }],
  docker: [
    { template: 'Dockerfile.ejs', output: 'Dockerfile' },
    { template: 'docker-compose.yml.ejs', output: 'docker-compose.yml' }
  ]
}

FRAMEWORK_FEATURE_FILES

Maps features to framework-specific templates and directories:

{
  fastapi: {
    auth: [{ directoryPattern: 'auth/' }],
    testing: [{ directoryPattern: 'tests/' }]
  },
  django: {
    rest_framework: [{ directoryPattern: 'apps/core/api/' }],
    migrations: [{ directoryPattern: 'apps/core/migrations/' }]
  },
  flask: {
    auth: [{ directoryPattern: 'app/auth/' }]
  }
}

Usage

In Template Renderer

The TemplateRenderer class uses these functions to determine which templates to render:

import { getCommonTemplates, shouldIncludeTemplate } from '../config/featureFileMap';

// Get list of common templates based on features
const templates = getCommonTemplates(framework, enabledFeatures);

// Check if a framework template should be included
if (shouldIncludeTemplate(templatePath, framework, enabledFeatures)) {
  // Render template
}

In Generators

Generators use feature checks to conditionally create files:

// Only create .env if 'env' feature is enabled
if (config.features.includes('env')) {
  const envFile = createEnvFile(config);
  await fs.writeFile(path.join(projectDir, '.env'), envFile);
}

Adding New Feature-Gated Files

To add a new optional file or directory:

  1. Identify the scope: Is it common across frameworks or framework-specific?

  2. Update the mapping:

    For common files:

    export const COMMON_FEATURE_FILES: Record<string, FeatureFileMapping[]> = {
      // ... existing mappings
      myFeature: [
        {
          template: 'myfile.ejs',
          output: 'myfile.txt',
          frameworks: ['fastapi', 'django', 'flask']
        }
      ]
    };

    For framework-specific files:

    export const FRAMEWORK_FEATURE_FILES = {
      fastapi: {
        // ... existing mappings
        myFeature: [
          {
            directoryPattern: 'mydir/',
            frameworks: ['fastapi']
          }
        ]
      }
    };
  3. Update the feature definition in client/src/lib/constants.ts:

    {
      value: "myFeature",
      label: "My Feature",
      description: "Description of what this enables",
      supportedFrameworks: ["fastapi", "django", "flask"],
      default: false
    }
  4. Test:

    • Add test cases to server/tests/preview.test.ts
    • Run npm run test:preview
    • Perform manual QA using server/tests/MANUAL_QA.md

File vs Directory Patterns

File Mapping

Used when you want to gate specific template files:

{
  template: 'source.ejs',  // Template file in templates/common or templates/{framework}
  output: 'destination.txt', // Output path in generated project
  frameworks: ['fastapi']    // Optional: limit to specific frameworks
}

Directory Pattern

Used when you want to gate entire directories:

{
  directoryPattern: 'mydir/', // Directory path to match (all files in this dir)
  frameworks: ['fastapi']      // Optional: limit to specific frameworks
}

The shouldIncludeTemplate() function checks if a template path starts with any excluded directory pattern.

Testing Strategy

  1. Unit Tests: Test mapping functions directly
  2. Integration Tests: Test /api/preview/structure endpoint with various feature combinations
  3. Manual QA: Visual verification in UI that feature toggles work correctly

Best Practices

  1. Always specify frameworks: Even for "common" files, explicitly list supported frameworks
  2. Use directory patterns for related files: If a feature includes multiple files in a directory, use directory pattern
  3. Update tests when adding features: Keep test coverage comprehensive
  4. Document in CHANGELOG: Note any breaking changes to default feature sets
  5. Consider backwards compatibility: If changing default features, provide migration guide

Troubleshooting

Files appearing when they shouldn't

  • Check if the file is in BASE_COMMON_TEMPLATES (always included)
  • Verify the feature is actually disabled in the config
  • Check if the directory pattern is matching correctly

Files not appearing when they should

  • Verify the feature is enabled in the config
  • Check framework compatibility in the mapping
  • Ensure template file exists in the templates directory
  • Check for typos in template or output paths

Preview doesn't match generated project

  • Verify both TemplateRenderer and generator code use the same feature checks
  • For Django/Flask inline generators, ensure feature gates match the mapping config
  • Check that useProjectPreview dependency array includes features