import { DEFAULT_EMOJI } from '@types' import { readdirSync, readFileSync, statSync } from 'fs' import { join, relative } from 'path' export type TemplateType = 'ssr' | 'bare' | 'spa' export type AppTemplates = Record interface TemplateOptions { tool?: boolean } interface TemplateVars { APP_EMOJI: string APP_NAME: string } const SHARED_FILES = ['.gitignore', '.npmrc', 'package.json', 'tsconfig.json'] const TEMPLATES_DIR = join(import.meta.dir, '../../templates') function readDir(dir: string): string[] { const files: string[] = [] for (const entry of readdirSync(dir)) { const path = join(dir, entry) if (statSync(path).isDirectory()) { files.push(...readDir(path)) } else { files.push(path) } } return files } function replaceVars(content: string, vars: TemplateVars): string { return content .replace(/\$\$APP_NAME\$\$/g, vars.APP_NAME) .replace(/\$\$APP_EMOJI\$\$/g, vars.APP_EMOJI) } export function generateTemplates(appName: string, template: TemplateType = 'ssr', options: TemplateOptions = {}): AppTemplates { const vars: TemplateVars = { APP_EMOJI: DEFAULT_EMOJI, APP_NAME: appName, } const result: AppTemplates = {} // Read shared files from templates/ for (const filename of SHARED_FILES) { const path = join(TEMPLATES_DIR, filename) let content = readFileSync(path, 'utf-8') content = replaceVars(content, vars) // Add tool option to package.json if specified if (filename === 'package.json' && options.tool) { const pkg = JSON.parse(content) pkg.toes.tool = true content = JSON.stringify(pkg, null, 2) + '\n' } result[filename] = content } // Read template-specific files const templateDir = join(TEMPLATES_DIR, template) for (const path of readDir(templateDir)) { const filename = relative(templateDir, path) const content = readFileSync(path, 'utf-8') result[filename] = replaceVars(content, vars) } return result }