Include Files Conditionally
How to include files based on user choices
How to Include Files Conditionally
Include or exclude files based on user input for customizable templates.
Basic Pattern
Use conditional logic to add file groups:
const files = [];// Always include base filesfiles.push({ root: 'templates/base', glob: '**/*', exclude: [], type: GlobType.Template });// Conditionally add TypeScript filesif (useTypescript) {files.push({ root: 'templates/typescript', glob: '**/*', exclude: [], type: GlobType.Template });}// Conditionally add Docker filesif (useDocker) {files.push({ root: 'templates/docker', glob: '**/*', exclude: [], type: GlobType.Template });}return {processors: [{name: 'cyan/default',files,config: { vars: { /* ... */ } }}],plugins: []};
Complete Example
import { StartTemplateWithLambda, GlobType } from '@atomicloud/cyan-sdk';StartTemplateWithLambda(async (i, d) => {// Ask configuration questionsconst typescript = await i.confirm('Use TypeScript?', 'project.typescript', 'Add TS config');const framework = await i.select('Framework?',['React', 'Vue', 'Svelte', 'None'],'project.framework','Choose framework');const docker = await i.confirm('Add Docker?', 'project.docker', 'Include Dockerfile');const testing = await i.confirm('Add testing?', 'project.testing', 'Include test setup');const ci = await i.select('CI/CD?',['None', 'GitHub Actions', 'GitLab CI'],'project.ci','Choose CI platform');// Build file list conditionallyconst files = [// Base files always included{ root: 'templates/base', glob: '**/*', exclude: [], type: GlobType.Template }];// TypeScript configurationif (typescript) {files.push({ root: 'templates/typescript', glob: '**/*', exclude: [], type: GlobType.Template });}// Framework-specific filesif (framework !== 'None') {files.push({root: `templates/frameworks/${framework.toLowerCase()}`,glob: '**/*',exclude: [],type: GlobType.Template});}// Docker filesif (docker) {files.push({ root: 'templates/docker', glob: '**/*', exclude: [], type: GlobType.Template });}// Testing setupif (testing) {files.push({ root: 'templates/testing', glob: '**/*', exclude: [], type: GlobType.Copy });}// CI/CD configurationif (ci !== 'None') {files.push({root: `templates/ci/${ci.toLowerCase().replace(' ', '-')}`,glob: '**/*',exclude: [],type: GlobType.Template});}return {processors: [{name: 'cyan/default',files,config: {vars: {typescript: typescript ? 'true' : 'false',framework,docker: docker ? 'true' : 'false',testing: testing ? 'true' : 'false',ci}}}],plugins: []};});
Conditional Directory Structure
Organize templates by feature. Note that root paths are relative to the cyan/ directory in your template package:
cyan/templates/├── base/ # Always included│ ├── README.md│ └── package.json├── typescript/ # TypeScript config│ ├── tsconfig.json│ └── src/│ └── index.ts├── frameworks/│ ├── react/ # React setup│ │ └── App.tsx│ ├── vue/ # Vue setup│ │ └── App.vue│ └── svelte/ # Svelte setup│ └── App.svelte├── docker/ # Docker setup│ ├── Dockerfile│ └── docker-compose.yml└── ci/├── github-actions/ # GitHub Actions│ └── main.yml└── gitlab-ci/ # GitLab CI└── .gitlab-ci.yml
Using Array Spread
Clean syntax for conditional additions. Use array spread for a functional style, or the push method shown earlier for an imperative approach:
const files = [// Base files{ root: 'templates/base', glob: '**/*', exclude: [], type: GlobType.Template },// Conditional files using spread...(typescript ? [{ root: 'templates/typescript', glob: '**/*', exclude: [], type: GlobType.Template }] : []),...(docker ? [{ root: 'templates/docker', glob: '**/*', exclude: [], type: GlobType.Template }] : []),...(testing ? [{ root: 'templates/testing', glob: '**/*', exclude: [], type: GlobType.Copy }] : [])];
Exclude Patterns
Conditionally exclude files. This is an alternative approach to adding separate file groups — instead of including different directories, you include everything and exclude unwanted files:
const exclude = [];if (!typescript) {exclude.push('**/*.ts', '**/*.tsx');}if (!testing) {exclude.push('**/*.test.*', '**/*.spec.*');}files.push({root: 'templates',glob: '**/*',exclude,type: GlobType.Template});
GlobType: Template vs Copy
The type property determines how files are processed:
GlobType.Template— Files are processed through the template engine, enabling variable substitution (e.g.,{{projectName}}in your files will be replaced with actual values)GlobType.Copy— Files are copied as-is without any processing
Use GlobType.Copy for binary files, static assets, or any files that shouldn't be modified.
Related
- Changing Glob Patterns - Tutorial on glob patterns
- Full Example - Complete template with conditionals
- Globbing Reference - Glob syntax