{"version":3,"sources":["../../src/starter-templates.ts","../../src/lib/starter-templates/consts.ts","../../src/lib/starter-templates/vfs.ts","../../src/lib/starter-templates/base-files/package-json.ts","../../src/version.ts","../../src/lib/starter-templates/base-files/ensure-gitignore.ts","../../src/lib/starter-templates/internal-utils.ts","../../src/lib/starter-templates/base-files/ensure-gitkeep.ts","../../src/lib/starter-templates/base-files/ensure-tsconfig.ts","../../src/lib/starter-templates/base-files/ensure-editor-config.ts","../../src/lib/starter-templates/base-files/ensure-prettier-config.ts","../../src/lib/starter-templates/base-files/ensure-prettier-ignore.ts","../../src/lib/starter-templates/base-files/ensure-eslint-config.ts","../../src/lib/starter-templates/base-files/ensure-vscode-extensions.ts","../../src/lib/starter-templates/base-files/ensure-vscode-settings.ts","../../src/lib/starter-templates/base-files/gitkeep-files-src.ts","../../src/lib/starter-templates/internal-helpers.ts","../../src/lib/starter-templates/validate-name.ts","../../src/lib/starter-templates/repo-utils.ts"],"sourcesContent":["/**\n * Unirend Starter Templates\n *\n * Programmatic API for creating new projects from templates.\n * This is the same functionality used by the CLI, but available as a library.\n *\n * NOTE: These starter template utility functions and the files they generate\n * are Bun-focused since they power the CLI (src/cli.ts), which targets Bun\n * for a simple, out-of-the-box experience. The generated package.json scripts\n * use Bun commands, and the SSR server build uses Bun.build() for bundling.\n *\n * The framework itself avoids Bun-specific APIs and supports both Bun and Node\n * runtimes when bundled. See \"Runtime requirements\" in README.md for rationale\n * and Node setup thoughts (out-of-the-box Node tooling is currently out of scope).\n */\n\nimport {\n  STARTER_TEMPLATES,\n  REPO_CONFIG_FILE,\n  DEFAULT_REPO_NAME,\n} from './lib/starter-templates/consts';\nimport type {\n  TemplateInfo,\n  RepoConfig,\n  LoggerFunction,\n  StarterTemplateOptions,\n  InitRepoOptions,\n  CreateProjectResult,\n  RepoConfigResult,\n  InitRepoResult,\n} from './lib/starter-templates/types';\nimport {\n  createRepoConfigObject,\n  addProjectToRepo,\n  ensureBaseFiles,\n  getTemplateConfig,\n  createProjectSpecificFiles,\n} from './lib/starter-templates/internal-helpers';\nimport { validateName } from './lib/starter-templates/validate-name';\nimport type { FileRoot } from './lib/starter-templates/vfs';\nimport {\n  vfsDisplayPath,\n  vfsEnsureDir,\n  vfsExists,\n  vfsReadJSON,\n  vfsWrite,\n  vfsWriteJSON,\n} from './lib/starter-templates/vfs';\nimport {\n  initGitRepo,\n  installDependencies,\n  autoFormatCode,\n} from './lib/starter-templates/repo-utils';\nimport { isRepoDirEmptyish } from './lib/starter-templates/internal-utils';\n\n/**\n * Create a new project from a starter template\n * @returns Promise<CreateProjectResult> - Result object with success status and metadata\n */\nexport async function createProject(\n  options: StarterTemplateOptions,\n): Promise<CreateProjectResult> {\n  const repoRootDisplay = vfsDisplayPath(options.repoRoot);\n\n  // Default logger that does nothing if none provided\n  const log: LoggerFunction = options.logger || (() => {});\n\n  // Compute project path: src/apps/{projectName}\n  const projectPath = `src/apps/${options.projectName}`;\n  const projectPathDisplay = vfsDisplayPath(options.repoRoot, projectPath);\n\n  // Get template-specific configuration (scripts, dependencies, devDependencies)\n  const templateConfig = getTemplateConfig(\n    options.projectName,\n    options.templateID,\n    projectPath,\n    options.serverBuildTarget,\n  );\n\n  try {\n    log('info', '🚀 Starting project creation...');\n    log('info', `Template: ${options.templateID}`);\n    log('info', `Project Name: ${options.projectName}`);\n    log('info', `Repo Path: ${repoRootDisplay}`);\n    log('info', `Project Path: ${projectPathDisplay}`);\n\n    if (options.starterFiles && Object.keys(options.starterFiles).length > 0) {\n      log(\n        'info',\n        `Custom starter files: ${Object.keys(options.starterFiles).length}`,\n      );\n    }\n\n    // Validate project name\n    const nameValidation = validateName(options.projectName);\n\n    if (!nameValidation.valid) {\n      log(\n        'error',\n        `❌ Invalid project name: ${nameValidation.error ?? 'Invalid name'}`,\n      );\n      log('info', '');\n      log('info', 'Valid names must:');\n      log('info', '  - Contain at least one alphanumeric character');\n      log('info', '  - Not start or end with special characters');\n      log('info', '  - Not contain invalid filesystem characters');\n      log('info', '  - Not be reserved system names');\n\n      return {\n        success: false,\n        error: nameValidation.error ?? 'Invalid project name',\n        metadata: {\n          templateID: options.templateID,\n          projectName: options.projectName,\n          repoPath: repoRootDisplay,\n        },\n      };\n    }\n\n    // Validate template exists\n    if (!templateExists(options.templateID)) {\n      const available = listAvailableTemplates();\n\n      log(\n        'error',\n        `❌ Template \"${options.templateID}\" not found. Available templates: ${available.join(', ')}`,\n      );\n\n      return {\n        success: false,\n        error: `Template \"${options.templateID}\" not found`,\n        metadata: {\n          templateID: options.templateID,\n          projectName: options.projectName,\n          repoPath: repoRootDisplay,\n        },\n      };\n    }\n\n    // Check if project path already exists\n    const doesProjectExist = await vfsExists(options.repoRoot, projectPath);\n\n    if (doesProjectExist) {\n      log(\n        'error',\n        `❌ Project directory already exists: ${projectPathDisplay}`,\n      );\n      log('info', '');\n      log(\n        'info',\n        'Please choose a different project name or remove the existing directory.',\n      );\n\n      return {\n        success: false,\n        error: `Project directory already exists: ${projectPath}`,\n        metadata: {\n          templateID: options.templateID,\n          projectName: options.projectName,\n          repoPath: repoRootDisplay,\n        },\n      };\n    }\n\n    // Repo root directory is the workspace root where projects live\n    const configFullPathDisplay = vfsDisplayPath(\n      options.repoRoot,\n      REPO_CONFIG_FILE,\n    );\n\n    // Step 1: Read repository configuration (if present)\n    let repoStatus = await readRepoConfig(options.repoRoot);\n\n    if (repoStatus.status === 'parse_error') {\n      log(\n        'error',\n        `❌ Found ${configFullPathDisplay} but it contains invalid JSON`,\n      );\n\n      if (repoStatus.errorMessage) {\n        log('error', `   ${repoStatus.errorMessage}`);\n      }\n\n      log('info', '');\n      log(\n        'info',\n        'Please fix the JSON syntax or delete the file to start fresh.',\n      );\n\n      return {\n        success: false,\n        error: `${REPO_CONFIG_FILE} contains invalid JSON`,\n        metadata: {\n          templateID: options.templateID,\n          projectName: options.projectName,\n          repoPath: repoRootDisplay,\n        },\n      };\n    } else if (repoStatus.status === 'read_error') {\n      log('error', `❌ Found ${configFullPathDisplay} but cannot read it`);\n\n      if (repoStatus.errorMessage) {\n        log('error', `   ${repoStatus.errorMessage}`);\n      }\n\n      return {\n        success: false,\n        error: `Cannot read ${REPO_CONFIG_FILE}`,\n        metadata: {\n          templateID: options.templateID,\n          projectName: options.projectName,\n          repoPath: repoRootDisplay,\n        },\n      };\n    } else if (repoStatus.status === 'not_found') {\n      // Auto-initialize repo if missing to keep flow simple\n      // (initRepo will perform safety checks on its own)\n      const repoName = DEFAULT_REPO_NAME;\n      log(\n        'info',\n        `📦 No repository found, auto-initializing as \"${repoName}\"...`,\n      );\n      log('info', '');\n\n      // Skip git init, dependency installation, and auto-format here.\n      // createProject will handle these in Steps 5, 7, and 8\n      const initResult = await initRepo(options.repoRoot, {\n        name: repoName,\n        logger: log,\n        initGit: false,\n        installDependencies: false,\n        autoFormat: false,\n      });\n\n      if (initResult.success) {\n        repoStatus = { status: 'found', config: initResult.config };\n      } else {\n        log('error', '❌ Failed to initialize repository configuration');\n\n        if (initResult.errorMessage) {\n          log('error', `   ${initResult.errorMessage}`);\n        }\n\n        return {\n          success: false,\n          error: 'Failed to initialize repository configuration',\n          metadata: {\n            templateID: options.templateID,\n            projectName: options.projectName,\n            repoPath: repoRootDisplay,\n          },\n        };\n      }\n    } else if (repoStatus.status !== 'found') {\n      log('error', '❌ Unsupported repository status returned');\n\n      return {\n        success: false,\n        error: 'Unsupported repository status returned',\n        metadata: {\n          templateID: options.templateID,\n          projectName: options.projectName,\n          repoPath: repoRootDisplay,\n        },\n      };\n    }\n\n    const result: CreateProjectResult = {\n      success: true,\n      metadata: {\n        templateID: options.templateID,\n        projectName: options.projectName,\n        repoPath: repoRootDisplay,\n      },\n    };\n\n    // Step 2: Update repo config to add project entry\n    try {\n      if (repoStatus.status === 'found') {\n        const updated = addProjectToRepo(\n          repoStatus.config,\n          options.projectName,\n          options.templateID,\n          projectPath,\n        );\n\n        await vfsWriteJSON(options.repoRoot, REPO_CONFIG_FILE, updated);\n\n        log('info', `📝 Updated ${REPO_CONFIG_FILE}`);\n      }\n    } catch (error) {\n      log(\n        'error',\n        `❌ Failed to update ${REPO_CONFIG_FILE}, Aborting project creation`,\n      );\n\n      const errorMessage =\n        error instanceof Error ? error.message : String(error);\n\n      if (errorMessage) {\n        log('error', `   ${errorMessage}`);\n      }\n\n      return {\n        success: false,\n        error: `Failed to update ${REPO_CONFIG_FILE}`,\n        metadata: {\n          templateID: options.templateID,\n          projectName: options.projectName,\n          repoPath: repoRootDisplay,\n        },\n      };\n    }\n\n    // Step 3: Ensure base workspace files (root package.json, etc.)\n    try {\n      await ensureBaseFiles(\n        options.repoRoot,\n        repoStatus.status === 'found'\n          ? repoStatus.config.name\n          : DEFAULT_REPO_NAME,\n        {\n          log,\n          templateScripts: templateConfig.scripts,\n          templateDependencies: templateConfig.dependencies,\n          templateDevDependencies: templateConfig.devDependencies,\n          templateGitignoreSectionHeader: templateConfig.gitignoreSectionHeader,\n          templateGitignoreEntries: templateConfig.gitignoreEntries,\n        },\n      );\n    } catch (error) {\n      const errorMessage =\n        error instanceof Error ? error.message : String(error);\n      log('error', '❌ Failed to ensure base files, aborting project creation');\n\n      if (errorMessage) {\n        log('error', `   ${errorMessage}`);\n      }\n\n      return {\n        success: false,\n        error: 'Failed to ensure base files',\n        metadata: {\n          templateID: options.templateID,\n          projectName: options.projectName,\n          repoPath: repoRootDisplay,\n        },\n      };\n    }\n\n    // Step 4: Write provided starter files\n    if (options.starterFiles && Object.keys(options.starterFiles).length > 0) {\n      try {\n        log(\n          'info',\n          `📄 Writing ${Object.keys(options.starterFiles).length} starter files`,\n        );\n\n        for (const [relPath, content] of Object.entries(options.starterFiles)) {\n          await vfsWrite(options.repoRoot, relPath, content);\n          log('info', `   ${vfsDisplayPath(options.repoRoot, relPath)}`);\n        }\n      } catch (error) {\n        const errorMessage =\n          error instanceof Error ? error.message : String(error);\n        log('error', '❌ Failed to write starter files');\n\n        if (errorMessage) {\n          log('error', `   ${errorMessage}`);\n        }\n\n        return {\n          success: false,\n          error: 'Failed to write starter files',\n          metadata: {\n            templateID: options.templateID,\n            projectName: options.projectName,\n            repoPath: repoRootDisplay,\n          },\n        };\n      }\n    }\n\n    // Step 5: Initialize git repository (optional, default: true)\n    if (options.initGit !== false) {\n      await initGitRepo(options.repoRoot, log);\n    }\n\n    // Step 6: Create project-specific files from template\n    try {\n      await createProjectSpecificFiles(\n        options.repoRoot,\n        projectPath,\n        options.projectName,\n        options.templateID,\n        options.serverBuildTarget,\n        log,\n      );\n    } catch (error) {\n      const errorMessage =\n        error instanceof Error ? error.message : String(error);\n\n      log(\n        'error',\n        '❌ Failed to create project-specific files, aborting project creation',\n      );\n\n      if (errorMessage) {\n        log('error', `   ${errorMessage}`);\n      }\n\n      return {\n        success: false,\n        error: 'Failed to create project-specific files',\n        metadata: {\n          templateID: options.templateID,\n          projectName: options.projectName,\n          repoPath: repoRootDisplay,\n        },\n      };\n    }\n\n    // Step 7: Install dependencies (optional, default: true)\n    if (options.installDependencies !== false) {\n      await installDependencies(options.repoRoot, log);\n    }\n\n    // Step 8: Auto-format code (optional, default: true)\n    // Runs independently - checks if prettier is installed before formatting\n    if (options.autoFormat !== false) {\n      await autoFormatCode(options.repoRoot, log);\n    }\n\n    return result;\n  } catch (error) {\n    const errorMessage = error instanceof Error ? error.message : String(error);\n    log('error', `❌ Failed to create project: ${errorMessage}`);\n\n    return {\n      success: false,\n      error: errorMessage,\n      metadata: {\n        templateID: options.templateID,\n        projectName: options.projectName,\n        repoPath: repoRootDisplay,\n      },\n    };\n  }\n}\n\n/**\n * Check if a template exists in the registry\n */\nexport function templateExists(templateID: string): boolean {\n  return templateID in STARTER_TEMPLATES;\n}\n\n/**\n * Get list of available starter template IDs\n */\nexport function listAvailableTemplates(): string[] {\n  return Object.keys(STARTER_TEMPLATES);\n}\n\n/**\n * Get template information by ID\n */\nexport function getTemplateInfo(templateID: string): TemplateInfo | undefined {\n  return STARTER_TEMPLATES[templateID] as TemplateInfo | undefined;\n}\n\n/**\n * Get available template IDs with info objects\n */\nexport function listAvailableTemplatesWithInfo(): TemplateInfo[] {\n  return Object.values(STARTER_TEMPLATES) as TemplateInfo[];\n}\n\n/**\n * Read repository configuration from a directory\n * Returns an object with status and config\n * - found: true, config: RepoConfig - Successfully read and parsed\n * - found: false - Config file doesn't exist\n * - found: false, error: \"parse_error\" - Config file exists but has invalid JSON\n * - found: false, error: \"read_error\" - Config file exists but can't be read\n */\nexport async function readRepoConfig(\n  dirPath: FileRoot,\n): Promise<RepoConfigResult> {\n  const result = await vfsReadJSON<RepoConfig>(dirPath, REPO_CONFIG_FILE);\n\n  if (!result.ok) {\n    if (result.code === 'ENOENT') {\n      return { status: 'not_found' };\n    } else if (result.code === 'PARSE_ERROR') {\n      return { status: 'parse_error', errorMessage: result.message };\n    } else {\n      return { status: 'read_error', errorMessage: result.message };\n    }\n  }\n\n  return { status: 'found', config: result.data };\n}\n\nexport async function initRepo(\n  dirPath: FileRoot,\n  options: InitRepoOptions = {},\n): Promise<InitRepoResult> {\n  // Default logger that does nothing if none provided\n  const log: LoggerFunction = options.logger || (() => {});\n  const repoRootDisplay = vfsDisplayPath(dirPath);\n\n  log('info', '🏗️  Initializing repository...');\n  log('info', `Repo Path: ${repoRootDisplay}`);\n\n  // Check for existing or problematic config first\n  const existing = await readRepoConfig(dirPath);\n\n  if (existing.status === 'found') {\n    log('error', `❌ Repository already initialized at ${repoRootDisplay}`);\n    return { success: false, error: 'already_exists' };\n  } else if (existing.status === 'parse_error') {\n    log('error', `❌ Found ${REPO_CONFIG_FILE} but it contains invalid JSON`);\n\n    if (existing.errorMessage) {\n      log('error', `   ${existing.errorMessage}`);\n    }\n\n    log('info', '');\n    log(\n      'info',\n      'Please fix the JSON syntax or delete the file to start fresh.',\n    );\n\n    return {\n      success: false,\n      error: 'parse_error',\n      errorMessage: existing.errorMessage,\n    };\n  } else if (existing.status === 'read_error') {\n    log('error', `❌ Found ${REPO_CONFIG_FILE} but cannot read it`);\n\n    if (existing.errorMessage) {\n      log('error', `   ${existing.errorMessage}`);\n    }\n\n    return {\n      success: false,\n      error: 'read_error',\n      errorMessage: existing.errorMessage,\n    };\n  } else if (existing.status !== 'not_found') {\n    // Guard for any future status values we don't explicitly handle yet\n    const statusValue = (existing as Record<string, unknown>).status;\n    const statusString =\n      typeof statusValue === 'string' || typeof statusValue === 'number'\n        ? String(statusValue)\n        : 'unknown';\n\n    log('error', `❌ Unsupported repository status: ${statusString}`);\n    return {\n      success: false,\n      error: 'unsupported_status',\n      errorMessage: `Unsupported repo status: ${statusString}`,\n    };\n  }\n\n  // Check if directory is empty or empty-ish (only .git/.gitignore)\n  const emptyCheck = await isRepoDirEmptyish(dirPath);\n\n  if (!emptyCheck.safe) {\n    log('error', '❌ Cannot initialize repository in this directory');\n    log('error', `   ${emptyCheck.reason}`);\n    log('info', '');\n    log(\n      'info',\n      'Please use an empty directory or a directory with only .git/.gitignore.',\n    );\n\n    return {\n      success: false,\n      error: 'unsafe_directory',\n      errorMessage: emptyCheck.reason,\n    };\n  }\n\n  const repoName = options.name || DEFAULT_REPO_NAME;\n  log('info', `Repo Name: ${repoName}`);\n\n  const validation = validateName(repoName);\n\n  if (!validation.valid) {\n    log(\n      'error',\n      `❌ Invalid repository name: ${validation.error ?? 'Invalid name'}`,\n    );\n    log('info', '');\n    log('info', 'Valid names must:');\n    log('info', '  - Contain at least one alphanumeric character');\n    log('info', '  - Not start or end with special characters');\n    log('info', '  - Not contain invalid filesystem characters');\n    log('info', '  - Not be reserved system names');\n\n    return {\n      success: false,\n      error: 'invalid_name',\n      errorMessage: validation.error,\n    };\n  }\n\n  const config = createRepoConfigObject(repoName);\n\n  try {\n    // Ensure target directory exists (noop for in-memory)\n    await vfsEnsureDir(dirPath);\n\n    // Write repo config file\n    await vfsWriteJSON(dirPath, REPO_CONFIG_FILE, config);\n    log('info', `🛠️  Created ${REPO_CONFIG_FILE}`);\n\n    // Ensure base files exist (package.json, tsconfig.json, .editorconfig, etc.)\n    try {\n      await ensureBaseFiles(dirPath, repoName, { log });\n      log('info', '✅ Repository initialized successfully');\n    } catch (error) {\n      // Log warning but don't fail - createProject will retry\n      const errorMessage =\n        error instanceof Error ? error.message : String(error);\n\n      log(\n        'warning',\n        '⚠️  Failed to create some base files (will retry when creating first project)',\n      );\n\n      if (errorMessage) {\n        log('warning', `   ${errorMessage}`);\n      }\n    }\n\n    // Initialize git repository (optional, default: true)\n    if (options.initGit !== false) {\n      await initGitRepo(dirPath, log);\n    }\n\n    // Install dependencies (optional, default: true)\n    if (options.installDependencies !== false) {\n      await installDependencies(dirPath, log);\n    }\n\n    // Auto-format code (optional, default: true)\n    // Runs independently - checks if prettier is installed before formatting\n    if (options.autoFormat !== false) {\n      await autoFormatCode(dirPath, log);\n    }\n\n    // Return success result\n    return { success: true, config };\n  } catch (error) {\n    // Return error result\n    const errorMessage =\n      error instanceof Error ? error.message : 'Failed to write file';\n    log('error', `❌ Failed to initialize repository: ${errorMessage}`);\n\n    return {\n      success: false,\n      error: 'write_error',\n      errorMessage,\n    };\n  }\n}\n\n// Re-export constants for public API consumers\nexport {\n  STARTER_TEMPLATES,\n  REPO_CONFIG_FILE,\n  DEFAULT_REPO_NAME,\n} from './lib/starter-templates/consts';\n\n// Re-export types for public API consumers\nexport type {\n  TemplateInfo,\n  ProjectEntry,\n  RepoConfig,\n  LoggerFunction,\n  LogLevel,\n  ServerBuildTarget,\n  StarterTemplateOptions,\n  InitRepoOptions,\n  NameValidationResult,\n  CreateProjectResult,\n  RepoConfigResult,\n  InitRepoResult,\n} from './lib/starter-templates/types';\n\nexport type {\n  InMemoryDir,\n  FileRoot,\n  FileContent,\n} from './lib/starter-templates/vfs';\n\n// Re-export validation function\nexport { validateName } from './lib/starter-templates/validate-name';\n","// Constants for starter templates and repository config\n\nexport const STARTER_TEMPLATES: Record<\n  string,\n  { templateID: string; name: string; description: string }\n> = {\n  ssg: {\n    templateID: 'ssg',\n    name: 'Static Site Generation (SSG)',\n    description:\n      'Pre-rendered static site with React Router and Vite build system',\n  },\n  ssr: {\n    templateID: 'ssr',\n    name: 'Server-Side Rendering (SSR)',\n    description:\n      'Full-stack React app with server-side rendering, API routes, and plugin support',\n  },\n  api: {\n    templateID: 'api',\n    name: 'API Server',\n    description: 'Standalone JSON API server with WebSocket and plugin support',\n  },\n};\n\nexport const REPO_CONFIG_FILE = 'unirend-repo.json';\nexport const DEFAULT_REPO_NAME = 'unirend-projects';\n","import {\n  readFile as fsReadFile,\n  writeFile as fsWriteFile,\n  mkdir as fsMkdir,\n  rm as fsRm,\n  stat as fsStat,\n  readdir as fsReaddir,\n} from 'fs/promises';\nimport { join } from 'path';\n\n/**\n * Virtual File System (VFS) helpers\n *\n * These utilities operate on a \"file root\" that can be either:\n * - a real filesystem directory path (string), or\n * - an in-memory object mapping normalized relative paths to content.\n *\n * Design notes:\n * - All relative paths are normalized with forward slashes and without leading separators.\n * - Text/binary reads are symmetric: strings are UTF-8 encoded to bytes for binary reads,\n *   and Uint8Array is UTF-8 decoded to string for text reads.\n * - Read APIs return a discriminated result with { ok: false, code: \"ENOENT\" | \"READ_ERROR\" } on failure.\n * - \"..\" segments that escape the root are rejected by normalization; display helpers keep raw when invalid.\n */\n/** In-memory directory object mapping normalized relative paths to content */\nexport type InMemoryDir = Record<string, FileContent>;\n/** File root: real filesystem directory path or in-memory object */\nexport type FileRoot = string | InMemoryDir;\n/** File content as UTF-8 string or binary bytes */\nexport type FileContent = string | Uint8Array;\n\n/**\n * Normalize a relative path for VFS operations.\n * - Removes leading separators\n * - Collapses repeated separators and dot segments\n * - Uses forward slashes\n * - Throws if traversal would escape the root (leading to an empty stack)\n */\nexport function normalizeRelPath(relPath: string): string {\n  const trimmed = relPath.replace(/^[\\\\/]+/, '');\n  const raw = trimmed.split(/[\\\\/]+/);\n  const parts: string[] = [];\n\n  for (const part of raw) {\n    if (!part || part === '.') {\n      continue;\n    }\n\n    if (part === '..') {\n      if (parts.length === 0) {\n        throw new Error('Path traversal outside root is not allowed');\n      }\n\n      parts.pop();\n    } else {\n      parts.push(part);\n    }\n  }\n\n  return parts.join('/');\n}\n\nexport function isInMemoryFileRoot(root: FileRoot): root is InMemoryDir {\n  return typeof root === 'object' && root !== null;\n}\n\n/** Ensure the directory exists when using a real filesystem root. No-op for in-memory roots. */\nexport async function vfsEnsureDir(root: FileRoot): Promise<void> {\n  if (!isInMemoryFileRoot(root)) {\n    await fsMkdir(root, { recursive: true });\n  }\n}\n\n/**\n * Write a file under the provided root at the normalized relative path.\n * - In-memory: stores the provided content as-is (string or Uint8Array)\n * - Filesystem: creates parent directories and writes the file\n */\nexport async function vfsWrite(\n  root: FileRoot,\n  relPath: string,\n  content: FileContent,\n): Promise<void> {\n  const norm = normalizeRelPath(relPath);\n\n  if (isInMemoryFileRoot(root)) {\n    root[norm] = content;\n    return;\n  }\n\n  const abs = join(root, norm);\n  await fsMkdir(join(abs, '..'), { recursive: true }).catch(() => {});\n  await fsWriteFile(abs, content);\n}\n\n/** Unified internal reader used by text/binary readers */\nasync function vfsReadRaw(\n  root: FileRoot,\n  relPath: string,\n  desired: 'text' | 'Uint8Array',\n): Promise<\n  | { ok: true; data: string | Uint8Array }\n  | { ok: false; code: 'ENOENT' | 'READ_ERROR'; message?: string }\n> {\n  try {\n    if (isInMemoryFileRoot(root)) {\n      const norm = normalizeRelPath(relPath);\n      const data = root[norm];\n\n      if (data === undefined) {\n        return { ok: false, code: 'ENOENT' };\n      }\n\n      if (desired === 'Uint8Array') {\n        if (data instanceof Uint8Array) {\n          return { ok: true, data };\n        }\n\n        return { ok: true, data: new TextEncoder().encode(String(data)) };\n      }\n\n      // desired text\n      if (typeof data === 'string') {\n        return { ok: true, data };\n      }\n\n      return { ok: true, data: new TextDecoder().decode(data as Uint8Array) };\n    }\n\n    const norm = normalizeRelPath(relPath);\n    const abs = join(root, norm);\n    const buf = await fsReadFile(abs);\n\n    if (desired === 'Uint8Array') {\n      return { ok: true, data: buf };\n    }\n\n    return { ok: true, data: buf.toString('utf8') };\n  } catch (error) {\n    if (\n      error &&\n      typeof error === 'object' &&\n      'code' in error &&\n      (error as { code?: unknown }).code === 'ENOENT'\n    ) {\n      return { ok: false, code: 'ENOENT' };\n    }\n\n    return {\n      ok: false,\n      code: 'READ_ERROR',\n      message: error instanceof Error ? error.message : String(error),\n    };\n  }\n}\n\n/** Read a file as UTF-8 text with consistent result shape across roots. */\nexport async function vfsReadText(\n  root: FileRoot,\n  relPath: string,\n): Promise<\n  | { ok: true; text: string }\n  | { ok: false; code: 'ENOENT' | 'READ_ERROR'; message?: string }\n> {\n  const res = await vfsReadRaw(root, relPath, 'text');\n\n  if (!res.ok) {\n    return res;\n  }\n\n  return { ok: true, text: res.data as string };\n}\n\n/** Read a file as raw bytes (Uint8Array) with consistent result shape across roots. */\nexport async function vfsReadBinary(\n  root: FileRoot,\n  relPath: string,\n): Promise<\n  | { ok: true; data: Uint8Array }\n  | { ok: false; code: 'ENOENT' | 'READ_ERROR'; message?: string }\n> {\n  const res = await vfsReadRaw(root, relPath, 'Uint8Array');\n\n  if (!res.ok) {\n    return res;\n  }\n\n  return { ok: true, data: res.data as Uint8Array };\n}\n\n/**\n * Delete a file at the normalized relative path.\n * Returns true if the file was deleted, false if it didn't exist.\n * NOTE: This function is designed for files only. It does not support deleting directories (recursive or otherwise).\n */\nexport async function vfsDeleteFile(\n  root: FileRoot,\n  relPath: string,\n): Promise<boolean> {\n  const norm = normalizeRelPath(relPath);\n\n  if (isInMemoryFileRoot(root)) {\n    if (root[norm] !== undefined) {\n      delete root[norm];\n      return true;\n    }\n\n    return false;\n  }\n\n  const abs = join(root, norm);\n  try {\n    await fsRm(abs);\n    return true;\n  } catch (error) {\n    // If file doesn't exist, return false\n    if (\n      error &&\n      typeof error === 'object' &&\n      'code' in error &&\n      (error as { code?: unknown }).code === 'ENOENT'\n    ) {\n      return false;\n    }\n\n    // Other errors (permissions, etc.) should propagate\n    throw error;\n  }\n}\n\n/**\n * Check if a path exists in the file root (file or directory).\n * This function checks for the existence of any path, whether it's a file or directory.\n * @param root - File root (filesystem path or in-memory object)\n * @param relPath - Relative path to check\n * @returns true if the path exists (file or directory), false otherwise\n */\nexport async function vfsExists(\n  root: FileRoot,\n  relPath: string,\n): Promise<boolean> {\n  const norm = normalizeRelPath(relPath);\n\n  if (isInMemoryFileRoot(root)) {\n    return root[norm] !== undefined;\n  }\n\n  // For filesystem, use stat to check if path exists\n  const abs = join(root, norm);\n\n  try {\n    await fsStat(abs);\n    return true;\n  } catch (error) {\n    // Path doesn't exist\n    if (\n      error &&\n      typeof error === 'object' &&\n      'code' in error &&\n      (error as { code?: unknown }).code === 'ENOENT'\n    ) {\n      return false;\n    }\n\n    // Other errors (permissions, etc.) should propagate\n    throw error;\n  }\n}\n\n/**\n * Write a file only if it doesn't already exist.\n * Returns true if the file was written, false if it already existed.\n * @param root - File root (filesystem path or in-memory object)\n * @param relPath - Relative path to the file\n * @param content - Content to write (string or Uint8Array)\n * @throws {Error} If filesystem operation fails (e.g., permission denied, read-only filesystem)\n */\nexport async function vfsWriteIfNotExists(\n  root: FileRoot,\n  relPath: string,\n  content: FileContent,\n): Promise<boolean> {\n  const norm = normalizeRelPath(relPath);\n\n  if (isInMemoryFileRoot(root)) {\n    if (root[norm] !== undefined) {\n      return false;\n    }\n\n    root[norm] = content;\n    return true;\n  }\n\n  // For filesystem, use stat to check if file exists (more efficient than reading)\n  const abs = join(root, norm);\n\n  try {\n    await fsStat(abs);\n    // File exists, don't overwrite\n    return false;\n  } catch (error) {\n    // Only proceed if file doesn't exist (ENOENT)\n    if (\n      error &&\n      typeof error === 'object' &&\n      'code' in error &&\n      (error as { code?: unknown }).code === 'ENOENT'\n    ) {\n      await vfsWrite(root, relPath, content);\n      return true;\n    }\n\n    // Other errors (permissions, read-only filesystem, etc.) should propagate\n    throw error;\n  }\n}\n\n/**\n * Write JSON data to a file with optional human-readable formatting.\n * @param root - File root (filesystem path or in-memory object)\n * @param relPath - Relative path to the JSON file\n * @param data - Data to serialize as JSON\n * @param useHumanFormat - Whether to format with indentation (default: true)\n */\nexport async function vfsWriteJSON(\n  root: FileRoot,\n  relPath: string,\n  data: unknown,\n  useHumanFormat = true,\n): Promise<void> {\n  const jsonString = useHumanFormat\n    ? JSON.stringify(data, null, 2)\n    : JSON.stringify(data);\n\n  await vfsWrite(root, relPath, jsonString);\n}\n\n/**\n * Read and parse JSON data from a file.\n * Returns a discriminated result with parse error handling.\n */\nexport async function vfsReadJSON<T = unknown>(\n  root: FileRoot,\n  relPath: string,\n): Promise<\n  | { ok: true; data: T }\n  | {\n      ok: false;\n      code: 'ENOENT' | 'READ_ERROR' | 'PARSE_ERROR';\n      message?: string;\n    }\n> {\n  const textResult = await vfsReadText(root, relPath);\n\n  if (!textResult.ok) {\n    return textResult;\n  }\n\n  try {\n    const data = JSON.parse(textResult.text) as T;\n\n    return { ok: true, data };\n  } catch (parseError) {\n    return {\n      ok: false,\n      code: 'PARSE_ERROR',\n      message:\n        parseError instanceof Error ? parseError.message : 'Invalid JSON',\n    };\n  }\n}\n\n/**\n * List directory contents (files and subdirectories) at the specified path.\n * Returns an array of entry names (not full paths).\n * @param root - File root (filesystem path or in-memory object)\n * @param relPath - Relative path to list (default: root)\n * @param excludes - Array of filenames to exclude from the result\n * @returns Array of entry names in the directory\n */\nexport async function vfsListDir(\n  root: FileRoot,\n  relPath = '',\n  excludes: string[] = [],\n): Promise<string[]> {\n  let entries: string[] = [];\n\n  if (isInMemoryFileRoot(root)) {\n    // For in-memory roots, we simulate directory listing by checking path prefixes\n    // keys are normalized relative paths like \"a/b/c.txt\"\n    const norm = normalizeRelPath(relPath);\n    const prefix = norm ? norm + '/' : '';\n    const entrySet = new Set<string>();\n\n    for (const path of Object.keys(root)) {\n      // Check if this file is within the requested directory\n      if (path.startsWith(prefix) && path !== norm) {\n        // We found a file inside the target directory (possibly deep inside)\n        // \"sub\" is the path relative to the target directory\n        const sub = path.slice(prefix.length);\n        const firstSlash = sub.indexOf('/');\n\n        if (firstSlash === -1) {\n          // No slashes means it's a direct child file\n          entrySet.add(sub);\n        } else {\n          // Slashes mean it's in a subdirectory, so we add the subdirectory name\n          entrySet.add(sub.substring(0, firstSlash));\n        }\n      }\n    }\n\n    entries = Array.from(entrySet).sort();\n  } else {\n    // For filesystem, use standard readdir\n    try {\n      const norm = normalizeRelPath(relPath);\n      const abs = join(root, norm);\n      const fsEntries = await fsReaddir(abs);\n      entries = fsEntries.sort();\n    } catch (error) {\n      // If directory doesn't exist or can't be read, return empty array\n      if (\n        error &&\n        typeof error === 'object' &&\n        'code' in error &&\n        (error as { code?: unknown }).code === 'ENOENT'\n      ) {\n        return [];\n      }\n\n      // Other errors should propagate\n      throw error;\n    }\n  }\n\n  if (excludes.length > 0) {\n    return entries.filter((e) => !excludes.includes(e));\n  }\n\n  return entries;\n}\n\n/**\n * Display helper for logging/debugging paths in a consistent format across roots.\n * - Memory roots: \"[in-memory]\" optionally followed by normalized (or raw if invalid) path\n * - Filesystem roots: absolute path via join(root, normalizedRelPath) or join(root, rawRelPath) if invalid\n */\nexport function vfsDisplayPath(root: FileRoot, relPath?: string): string {\n  if (isInMemoryFileRoot(root)) {\n    if (!relPath) {\n      return `[in-memory]`;\n    }\n\n    let norm = relPath;\n\n    try {\n      norm = normalizeRelPath(relPath);\n    } catch {\n      // keep raw\n    }\n\n    return `[in-memory] ${norm}`;\n  }\n\n  if (!relPath) {\n    return root;\n  }\n\n  let norm = relPath;\n\n  try {\n    norm = normalizeRelPath(relPath);\n  } catch {\n    // keep raw\n  }\n\n  return join(root, norm);\n}\n","import { vfsReadJSON, vfsWriteJSON } from '../vfs';\nimport type { FileRoot } from '../vfs';\nimport type { LoggerFunction } from '../types';\nimport semver from 'semver';\nimport sortPackageJson from 'sort-package-json';\nimport { PKG_VERSION } from '../../../version';\n\nconst defaultScripts = {\n  'type-check': 'tsc --noEmit',\n  test: 'bun test',\n  lint: 'eslint .',\n  'lint:fix': 'eslint . --fix',\n  format: 'prettier --write \"**/*.{js,jsx,ts,tsx,json,css,md}\"',\n  'format:check': 'prettier --check \"**/*.{js,jsx,ts,tsx,json,css,md}\"',\n};\n\nexport const devDependencies = {\n  '@eslint/js': '^9.39.1',\n  '@tailwindcss/vite': '^4.1.17',\n  '@types/bun': '^1.3.2',\n  '@types/node': '^24.10.0',\n  '@types/react': '^19.2.4',\n  '@types/react-dom': '^19.2.2',\n  '@typescript-eslint/eslint-plugin': '^8.46.3',\n  '@typescript-eslint/parser': '^8.46.3',\n  '@vitejs/plugin-react': '^6.0.1',\n  eslint: '^9.39.1',\n  'eslint-import-resolver-typescript': '^4.4.4',\n  'eslint-plugin-check-file': '^3.3.1',\n  'eslint-plugin-import': '^2.32.0',\n  'eslint-plugin-jsx-a11y': '^6.10.2',\n  'eslint-plugin-react': '^7.37.5',\n  'eslint-plugin-react-hooks': '^7.0.1',\n  'eslint-plugin-react-refresh': '^0.5.2',\n  'eslint-plugin-unicorn': '^62.0.0',\n  prettier: '^3.6.2',\n  'prettier-plugin-tailwindcss': '^0.7.1',\n  tailwindcss: '^4.1.17',\n  typescript: '^5.9.3',\n  'typescript-eslint': '^8.46.3',\n  vite: '^8.0.0',\n  'rollup-plugin-visualizer': '^7.0.1',\n};\n\nexport const dependencies = {\n  lifecycleion: '^0.0.14',\n  react: '^19.2.1',\n  'react-dom': '^19.2.1',\n  'react-router': '^7.0.0',\n  unirend: `^${PKG_VERSION}`,\n};\n\n/**\n * Helper function to merge dependencies, updating if the template version is newer\n * or if the dependency doesn't exist in the target.\n */\nfunction mergeDependencies(\n  target: Record<string, unknown>,\n  source: Record<string, string>,\n  depKey: 'dependencies' | 'devDependencies',\n): boolean {\n  let didChange = false;\n\n  // Ensure the dependencies object exists\n  if (!Object.prototype.hasOwnProperty.call(target, depKey)) {\n    target[depKey] = {};\n    didChange = true;\n  }\n\n  const targetDeps = target[depKey] as Record<string, string>;\n\n  for (const [pkg, templateVersion] of Object.entries(source)) {\n    const existingVersion = targetDeps[pkg];\n\n    if (!existingVersion) {\n      // Package doesn't exist, add it\n      targetDeps[pkg] = templateVersion;\n      didChange = true;\n    } else {\n      // Package exists, compare versions\n      try {\n        // Extract version numbers from semver ranges (e.g., \"^1.2.3\" -> \"1.2.3\")\n        const templateClean = semver.minVersion(templateVersion);\n        const existingClean = semver.minVersion(existingVersion);\n\n        if (templateClean && existingClean) {\n          // Only update if template version is newer\n          if (semver.gt(templateClean, existingClean)) {\n            targetDeps[pkg] = templateVersion;\n            didChange = true;\n          }\n        }\n        // If we can't parse versions, leave existing version unchanged\n      } catch {\n        // If semver comparison fails, leave existing version unchanged\n      }\n    }\n  }\n\n  return didChange;\n}\n\n/**\n * Helper function to merge scripts, only adding if the script name doesn't exist.\n * Never overwrites existing scripts.\n */\nfunction mergeScripts(\n  target: Record<string, unknown>,\n  source: Record<string, string>,\n): boolean {\n  let didChange = false;\n\n  // Ensure the scripts object exists\n  if (!Object.prototype.hasOwnProperty.call(target, 'scripts')) {\n    target.scripts = {};\n    didChange = true;\n  }\n\n  const targetScripts = target.scripts as Record<string, string>;\n\n  for (const [scriptName, scriptCommand] of Object.entries(source)) {\n    if (!targetScripts[scriptName]) {\n      // Script doesn't exist, add it\n      targetScripts[scriptName] = scriptCommand;\n      didChange = true;\n    }\n\n    // If script exists, leave it unchanged (never overwrite user's scripts)\n  }\n\n  return didChange;\n}\n\n/**\n * Options for customizing package.json generation\n */\nexport interface EnsurePackageJSONOptions {\n  /** Optional logger function */\n  log?: LoggerFunction;\n  /** Template-specific scripts to merge with defaults */\n  templateScripts?: Record<string, string>;\n  /** Template-specific dependencies to merge with defaults */\n  templateDependencies?: Record<string, string>;\n  /** Template-specific devDependencies to merge with defaults */\n  templateDevDependencies?: Record<string, string>;\n}\n\n/**\n * Ensure package.json exists at the repo root with required fields.\n * Creates a new package.json if missing, or updates existing one with missing fields.\n * Never overwrites existing user-defined fields.\n * @throws {Error} If package.json has invalid JSON or cannot be read/written\n */\n\nexport async function ensurePackageJSON(\n  repoRoot: FileRoot,\n  repoName: string,\n  options?: EnsurePackageJSONOptions,\n): Promise<void> {\n  // Attempt to read an existing package.json at the repo root\n  const pkgResult = await vfsReadJSON<Record<string, unknown>>(\n    repoRoot,\n    'package.json',\n  );\n\n  // Creation path: no package.json found; create a minimal one\n  if (!pkgResult.ok) {\n    if (pkgResult.code === 'ENOENT') {\n      const pkg = {\n        name: repoName,\n        version: '0.0.1',\n        type: 'module',\n        private: true,\n        license: 'UNLICENSED',\n        scripts: { ...defaultScripts, ...options?.templateScripts },\n        dependencies: { ...dependencies, ...options?.templateDependencies },\n        devDependencies: {\n          ...devDependencies,\n          ...options?.templateDevDependencies,\n        },\n      };\n\n      // Sort the package.json for consistency\n      const sortedPkg = sortPackageJson(pkg);\n\n      await vfsWriteJSON(repoRoot, 'package.json', sortedPkg);\n\n      if (options?.log) {\n        options.log('info', 'Created repo root package.json');\n      }\n\n      // Package.json created successfully, return early as we don't need to update it\n      return;\n    } else if (pkgResult.code === 'PARSE_ERROR') {\n      throw new Error(\n        `Invalid JSON in repo root package.json: ${pkgResult.message}`,\n      );\n    } else {\n      throw new Error(\n        `Failed to read repo root package.json: ${pkgResult.message}`,\n      );\n    }\n  }\n\n  // Update path: package.json exists and was successfully parsed — add missing fields only, never overwrite\n  const parsed = pkgResult.data;\n\n  let didChange = false;\n\n  // Add defaults only when these fields are absent\n  if (!Object.prototype.hasOwnProperty.call(parsed, 'name')) {\n    (parsed as { name: string }).name = repoName;\n    didChange = true;\n  }\n\n  if (!Object.prototype.hasOwnProperty.call(parsed, 'private')) {\n    (parsed as { private: boolean }).private = true;\n    didChange = true;\n  }\n\n  if (!Object.prototype.hasOwnProperty.call(parsed, 'license')) {\n    (parsed as { license: string }).license = 'UNLICENSED';\n    didChange = true;\n  }\n\n  if (!Object.prototype.hasOwnProperty.call(parsed, 'version')) {\n    (parsed as { version: string }).version = '0.0.1';\n    didChange = true;\n  }\n\n  if (!Object.prototype.hasOwnProperty.call(parsed, 'type')) {\n    (parsed as { type: string }).type = 'module';\n    didChange = true;\n  }\n\n  // Merge scripts (only add missing scripts, never overwrite)\n  // Combine default scripts with template-specific scripts\n  const allScripts = { ...defaultScripts, ...options?.templateScripts };\n  if (mergeScripts(parsed, allScripts)) {\n    didChange = true;\n  }\n\n  // Merge dependencies and devDependencies (only update if newer)\n  // Combine default dependencies with template-specific dependencies\n  const allDependencies = { ...dependencies, ...options?.templateDependencies };\n\n  if (mergeDependencies(parsed, allDependencies, 'dependencies')) {\n    didChange = true;\n  }\n\n  const allDevDependencies = {\n    ...devDependencies,\n    ...options?.templateDevDependencies,\n  };\n\n  if (mergeDependencies(parsed, allDevDependencies, 'devDependencies')) {\n    didChange = true;\n  }\n\n  // Sort the package.json and check if sorting changed anything\n  const beforeSort = JSON.stringify(parsed);\n  const sortedParsed = sortPackageJson(parsed);\n  const afterSort = JSON.stringify(sortedParsed);\n\n  if (beforeSort !== afterSort) {\n    didChange = true;\n  }\n\n  // write updated package.json only if we actually changed something\n  if (didChange) {\n    await vfsWriteJSON(repoRoot, 'package.json', sortedParsed);\n\n    if (options?.log) {\n      options.log(\n        'info',\n        'Updated repo root package.json (added missing fields)',\n      );\n    }\n  }\n}\n","/**\n * Auto-generated version file\n * DO NOT EDIT MANUALLY - This file is generated by scripts/sync-version.ts\n * Run 'bun run sync-version' to update\n */\n\nexport const PKG_VERSION = '0.0.23';\n","import { vfsReadText, vfsWrite } from '../vfs';\nimport type { FileRoot } from '../vfs';\nimport type { LoggerFunction } from '../types';\n\n// NOTE: Keep this in sync with ensure-prettier-ignore.ts\n// Both .gitignore and .prettierignore should have the same patterns\nconst fileSrc = `# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\n# Dependencies\nnode_modules\n\n# Package manager lockfiles\n# This project uses Bun - ignore npm/yarn/pnpm lockfiles to avoid confusion\npackage-lock.json\nyarn.lock\npnpm-lock.yaml\n# Ignore Bun's binary lockfile (bun.lock JSON format is preferred and should be committed)\nbun.lockb\n\n# Environment variables\n# Keep secrets out of source control! Document required variables in README or create .env.example\n*.local\n.env\n.env.local\n.env.*.local\n\n# AI Development Tools\n# Claude Code local settings (personal preferences not shared with team)\n.claude/**/*.local*\n\n# Build outputs\ndist/\nbuild/\ncoverage/\n.nyc_output/\n*.tsbuildinfo\n.eslintcache\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n!.vscode/settings.json\n.idea\n.DS_Store\nThumbs.db\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n\n# Temporary files\ntmp/`;\n\nconst defaultTemplateSectionHeader = '# Template-specific';\n\nexport interface EnsureGitignoreOptions {\n  /** Optional logger function */\n  log?: LoggerFunction;\n  /** Header used for template-specific .gitignore entries */\n  templateSectionHeader?: string;\n  /** Template-specific .gitignore entries to append if missing */\n  templateEntries?: string[];\n}\n\nfunction normalizeEntry(entry: string): string {\n  return entry.trim();\n}\n\nfunction findTemplateSectionInsertIndex(\n  lines: string[],\n  sectionHeader: string,\n): number | undefined {\n  const headerIndex = lines.findIndex((line) => line.trim() === sectionHeader);\n\n  if (headerIndex === -1) {\n    return undefined;\n  }\n\n  let insertIndex = lines.length;\n\n  // Treat a section as ending at the next comment header. Most generated\n  // .gitignore sections are separated by a blank line, but existing user files\n  // may put headers directly adjacent, so handle both shapes.\n  for (let index = headerIndex + 1; index < lines.length; index += 1) {\n    const currentLine = lines[index]?.trim() ?? '';\n    const nextLine = lines[index + 1]?.trim() ?? '';\n\n    if (currentLine.startsWith('#') && currentLine !== sectionHeader) {\n      insertIndex = index;\n      break;\n    }\n\n    if (\n      currentLine === '' &&\n      nextLine.startsWith('#') &&\n      nextLine !== sectionHeader\n    ) {\n      insertIndex = index;\n      break;\n    }\n  }\n\n  return insertIndex;\n}\n\nfunction appendMissingEntries(\n  existing: string,\n  sectionHeader: string,\n  entries: string[],\n): string {\n  // Normalize caller-provided entries so whitespace-only differences do not\n  // create duplicate ignore patterns.\n  const normalizedEntries = entries.map(normalizeEntry).filter(Boolean);\n\n  if (normalizedEntries.length === 0) {\n    return existing;\n  }\n\n  // Dedup against the whole file, not only this template section. If a user\n  // already ignores the path somewhere else, leave their grouping untouched.\n  const existingEntries = new Set(\n    existing.split(/\\r?\\n/).map(normalizeEntry).filter(Boolean),\n  );\n\n  const missingEntries = normalizedEntries.filter(\n    (entry) => !existingEntries.has(entry),\n  );\n\n  if (missingEntries.length === 0) {\n    return existing;\n  }\n\n  // Work with a trimmed line list for insertion. This removes trailing blank\n  // lines so new entries land in the section body instead of after file-end\n  // whitespace, then split on either Unix or Windows line endings.\n  const lines = existing.replace(/\\s*$/, '').split(/\\r?\\n/);\n  const insertIndex = findTemplateSectionInsertIndex(lines, sectionHeader);\n\n  // Reuse the existing section when present, rather than creating another\n  // section with the same header at the end of the file.\n  if (insertIndex !== undefined) {\n    lines.splice(insertIndex, 0, ...missingEntries);\n\n    // If inserting directly before the next section header, keep sections\n    // visually separated even when the original file omitted the blank line.\n    if (lines[insertIndex + missingEntries.length]?.trim().startsWith('#')) {\n      lines.splice(insertIndex + missingEntries.length, 0, '');\n    }\n\n    return lines.join('\\n');\n  }\n\n  const trimmedEnd = existing.replace(/\\s*$/, '');\n  const prefix = trimmedEnd.length > 0 ? `${trimmedEnd}\\n\\n` : '';\n\n  return `${prefix}${sectionHeader}\\n${missingEntries.join('\\n')}`;\n}\n\n/**\n * Ensure .gitignore exists at the repo root.\n * Creates the file if it doesn't exist, and appends template-specific entries\n * to an existing file when they are missing.\n * @throws {Error} If file creation fails\n */\nexport async function ensureGitignore(\n  repoRoot: FileRoot,\n  options?: EnsureGitignoreOptions,\n): Promise<void> {\n  const templateEntries = options?.templateEntries ?? [];\n  const templateSectionHeader =\n    options?.templateSectionHeader ?? defaultTemplateSectionHeader;\n\n  try {\n    // Read first so the create and update paths are explicit. A missing file is\n    // the normal creation path, while other read problems are surfaced.\n    const existing = await vfsReadText(repoRoot, '.gitignore');\n\n    if (!existing.ok) {\n      if (existing.code !== 'ENOENT') {\n        throw new Error(existing.message ?? existing.code);\n      }\n\n      // New repos get the standard ignore file plus any template-specific\n      // entries in one write.\n      const initialSrc = appendMissingEntries(\n        fileSrc,\n        templateSectionHeader,\n        templateEntries,\n      );\n\n      await vfsWrite(repoRoot, '.gitignore', initialSrc);\n\n      if (options?.log) {\n        options.log('info', 'Created repo root .gitignore');\n      }\n\n      return;\n    }\n\n    // Existing files do not need to be rewritten unless the template has\n    // additional ignore patterns to merge.\n    if (templateEntries.length === 0) {\n      return;\n    }\n\n    // Append only the missing template entries. appendMissingEntries also\n    // handles grouping under an existing custom/default section header.\n    const updated = appendMissingEntries(\n      existing.text,\n      templateSectionHeader,\n      templateEntries,\n    );\n\n    if (updated !== existing.text) {\n      await vfsWrite(repoRoot, '.gitignore', updated);\n\n      if (options?.log) {\n        options.log(\n          'info',\n          'Updated repo root .gitignore (added template entries)',\n        );\n      }\n    }\n  } catch (error) {\n    // Keep callers insulated from the exact VFS/filesystem error shape.\n    const errorMessage = error instanceof Error ? error.message : String(error);\n    throw new Error(`Failed to ensure .gitignore: ${errorMessage}`);\n  }\n}\n","import { vfsListDir } from './vfs';\nimport type { FileRoot } from './vfs';\n\n/**\n * Check if a directory is empty or \"empty-ish\" (safe to initialize as a new unirend repo).\n *\n * A directory is considered empty-ish if it:\n * - Is completely empty\n * - Has only .git and/or .gitignore (empty git repo, not yet in use)\n *\n * A directory is NOT empty-ish if it:\n * - Contains other files/folders (suggests it's already in use)\n *\n * @param dirPath - Directory to check\n * @returns Object with safe status and optional error message\n */\nexport async function isRepoDirEmptyish(\n  dirPath: FileRoot,\n): Promise<{ safe: boolean; reason?: string }> {\n  // List directory contents\n  const entries = await vfsListDir(dirPath);\n\n  // Empty directory is safe\n  if (entries.length === 0) {\n    return { safe: true };\n  }\n\n  // Filter out .git and .gitignore (these are OK for an \"empty\" repo)\n  // as somebody might have ran `git init` but not added any files yet\n  const nonGitEntries = entries.filter(\n    (entry) => entry !== '.git' && entry !== '.gitignore',\n  );\n\n  // If only .git/.gitignore exist (or directory is empty), it's safe\n  if (nonGitEntries.length === 0) {\n    return { safe: true };\n  }\n\n  // If other files/folders exist, it's unsafe (directory in use)\n  return {\n    safe: false,\n    reason: `Directory is not empty and not a unirend repository. Found: ${nonGitEntries.slice(0, 5).join(', ')}${nonGitEntries.length > 5 ? '...' : ''}`,\n  };\n}\n\n/**\n * Check if a directory is completely empty, optionally excluding specific files.\n *\n * @param root - Root directory\n * @param relPath - Relative path to check (default: '')\n * @param excludes - Array of filenames to ignore (e.g. ['.gitkeep'])\n * @returns true if directory is empty (after filtering excludes), false otherwise\n */\nexport async function isDirEmpty(\n  root: FileRoot,\n  relPath = '',\n  excludes: string[] = [],\n): Promise<boolean> {\n  const entries = await vfsListDir(root, relPath, excludes);\n  return entries.length === 0;\n}\n","import { vfsWriteIfNotExists, vfsDeleteFile } from '../vfs';\nimport type { FileRoot } from '../vfs';\nimport { isDirEmpty } from '../internal-utils';\nimport type { LoggerFunction } from '../types';\n\n/**\n * Ensure a directory has a .gitkeep file if it is empty (or only has .gitkeep).\n * If the directory has other files, the .gitkeep file is deleted.\n *\n * @param repoRoot - Repository root\n * @param dirName - Directory name to check (e.g. 'scripts')\n * @param fileSrc - Content for the .gitkeep file\n * @param log - Optional logger\n */\nexport async function ensureGitkeep(\n  repoRoot: FileRoot,\n  dirName: string,\n  fileSrc: string,\n  log?: LoggerFunction,\n): Promise<void> {\n  // Check if directory is empty, ignoring existing .gitkeep\n  // Returns true if empty or only contains .gitkeep\n  const isEmpty = await isDirEmpty(repoRoot, dirName, ['.gitkeep']);\n\n  if (isEmpty) {\n    // Directory is empty (or only has .gitkeep), so ensure .gitkeep exists\n    const didWrite = await vfsWriteIfNotExists(\n      repoRoot,\n      `${dirName}/.gitkeep`,\n      fileSrc,\n    );\n\n    if (didWrite && log) {\n      log('info', `Created .gitkeep in ${dirName}`);\n    }\n  } else {\n    // Directory has other files, so delete .gitkeep if it exists\n    const didDelete = await vfsDeleteFile(repoRoot, `${dirName}/.gitkeep`);\n\n    if (didDelete && log) {\n      log(\n        'info',\n        `Removed .gitkeep from ${dirName} (directory is no longer empty)`,\n      );\n    }\n  }\n}\n","import { vfsWriteIfNotExists } from '../vfs';\nimport type { FileRoot } from '../vfs';\nimport type { LoggerFunction } from '../types';\n\nconst fileSrc = `{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"types\": [\"node\"],\n    \"module\": \"ESNext\",\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n    \"jsx\": \"react-jsx\",\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"esModuleInterop\": true,\n    \"forceConsistentCasingInFileNames\": true,\n\n    /* Path Aliases */\n    \"baseUrl\": \".\",\n    \"paths\": {\n      \"@/*\": [\"./src/*\"]\n    }\n  },\n  \"include\": [\"src\", \"scripts/**/*\", \"**/*.ts\", \"**/*.tsx\"],\n  \"exclude\": [\"node_modules\", \"dist\"]\n}`;\n\n/**\n * Ensure tsconfig.json exists at the repo root.\n * Only creates the file if it doesn't exist - never overwrites.\n * @throws {Error} If file creation fails\n */\nexport async function ensureTsConfig(\n  repoRoot: FileRoot,\n  log?: LoggerFunction,\n): Promise<void> {\n  try {\n    const didWrite = await vfsWriteIfNotExists(\n      repoRoot,\n      'tsconfig.json',\n      fileSrc,\n    );\n\n    if (didWrite && log) {\n      log('info', 'Created repo root tsconfig.json');\n    }\n  } catch (error) {\n    const errorMessage = error instanceof Error ? error.message : String(error);\n    throw new Error(`Failed to ensure tsconfig.json: ${errorMessage}`);\n  }\n}\n","import { vfsWriteIfNotExists } from '../vfs';\nimport type { FileRoot } from '../vfs';\nimport type { LoggerFunction } from '../types';\n\nconst fileSrc = `# EditorConfig is awesome: https://EditorConfig.org\n\n# top-most EditorConfig file\nroot = true\n\n# Unix-style newlines with a newline ending every file\n[*]\nend_of_line = lf\ninsert_final_newline = true\ncharset = utf-8\ntrim_trailing_whitespace = true\n\n# TypeScript and JavaScript files\n[*.{ts,tsx,js,jsx}]\nindent_style = space\nindent_size = 2\n\n# JSON files\n[*.json]\nindent_style = space\nindent_size = 2\n\n# CSS files\n[*.{css,scss,sass}]\nindent_style = space\nindent_size = 2\n\n# HTML files\n[*.{html,htm}]\nindent_style = space\nindent_size = 2\n\n# Markdown files\n[*.md]\ntrim_trailing_whitespace = false`;\n\n/**\n * Ensure .editorconfig exists at the repo root.\n * Only creates the file if it doesn't exist - never overwrites.\n * @throws {Error} If file creation fails\n */\nexport async function ensureEditorConfig(\n  repoRoot: FileRoot,\n  log?: LoggerFunction,\n): Promise<void> {\n  try {\n    const didWrite = await vfsWriteIfNotExists(\n      repoRoot,\n      '.editorconfig',\n      fileSrc,\n    );\n\n    if (didWrite && log) {\n      log('info', 'Created repo root .editorconfig');\n    }\n  } catch (error) {\n    const errorMessage = error instanceof Error ? error.message : String(error);\n    throw new Error(`Failed to ensure .editorconfig: ${errorMessage}`);\n  }\n}\n","import { vfsWriteIfNotExists } from '../vfs';\nimport type { FileRoot } from '../vfs';\nimport type { LoggerFunction } from '../types';\n\nconst fileSrc = `/** @type {import(\"prettier\").Config} */\nexport default {\n  // Intentionally minimal: rely on Prettier 3 defaults except:\n  singleQuote: true, // Use single quotes in JS/TS\n  jsxSingleQuote: false, // Keep double quotes in JSX (HTML convention)\n};\n`;\n\n/**\n * Ensure prettier.config.js exists at the repo root.\n * Only creates the file if it doesn't exist - never overwrites.\n * @throws {Error} If file creation fails\n */\nexport async function ensurePrettierConfig(\n  repoRoot: FileRoot,\n  log?: LoggerFunction,\n): Promise<void> {\n  try {\n    const didWrite = await vfsWriteIfNotExists(\n      repoRoot,\n      'prettier.config.js',\n      fileSrc,\n    );\n\n    if (didWrite && log) {\n      log('info', 'Created repo root prettier.config.js');\n    }\n  } catch (error) {\n    const errorMessage = error instanceof Error ? error.message : String(error);\n    throw new Error(`Failed to ensure prettier.config.js: ${errorMessage}`);\n  }\n}\n","import { vfsWriteIfNotExists } from '../vfs';\nimport type { FileRoot } from '../vfs';\nimport type { LoggerFunction } from '../types';\n\n// NOTE: Keep this in sync with ensure-gitignore.ts\n// Both .gitignore and .prettierignore should have the same patterns\nconst fileSrc = `# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\n# Dependencies\nnode_modules\n\n# Package manager lockfiles\n# This project uses Bun - ignore npm/yarn/pnpm lockfiles to avoid confusion\npackage-lock.json\nyarn.lock\npnpm-lock.yaml\n# Ignore Bun's binary lockfile (bun.lock JSON format is preferred and should be committed)\nbun.lockb\n\n# Environment variables\n# Keep secrets out of source control! Document required variables in README or create .env.example\n*.local\n.env\n.env.local\n.env.*.local\n\n# AI Development Tools\n# Claude Code local settings (personal preferences not shared with team)\n.claude/**/*.local*\n\n# Build outputs\ndist/\nbuild/\ncoverage/\n.nyc_output/\n*.tsbuildinfo\n.eslintcache\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n!.vscode/settings.json\n.idea\n.DS_Store\nThumbs.db\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n\n# Temporary files\ntmp/`;\n\n/**\n * Ensure .prettierignore exists at the repo root.\n * Only creates the file if it doesn't exist - never overwrites.\n * @throws {Error} If file creation fails\n */\nexport async function ensurePrettierIgnore(\n  repoRoot: FileRoot,\n  log?: LoggerFunction,\n): Promise<void> {\n  try {\n    const didWrite = await vfsWriteIfNotExists(\n      repoRoot,\n      '.prettierignore',\n      fileSrc,\n    );\n\n    if (didWrite && log) {\n      log('info', 'Created repo root .prettierignore');\n    }\n  } catch (error) {\n    const errorMessage = error instanceof Error ? error.message : String(error);\n    throw new Error(`Failed to ensure .prettierignore: ${errorMessage}`);\n  }\n}\n","import { vfsWriteIfNotExists } from '../vfs';\nimport type { FileRoot } from '../vfs';\nimport type { LoggerFunction } from '../types';\n\nconst fileSrc = `import eslint from '@eslint/js';\nimport tseslint from 'typescript-eslint';\nimport react from 'eslint-plugin-react';\nimport reactHooks from 'eslint-plugin-react-hooks';\nimport jsxA11y from 'eslint-plugin-jsx-a11y';\nimport importPlugin from 'eslint-plugin-import';\nimport unicorn from 'eslint-plugin-unicorn';\nimport checkFile from 'eslint-plugin-check-file';\nimport reactRefresh from 'eslint-plugin-react-refresh';\n\nexport default [\n  eslint.configs.recommended,\n  ...tseslint.configs.recommendedTypeChecked,\n  {\n    ignores: [\n      // Build outputs\n      '**/dist/**',\n      '**/build/**',\n      '**/coverage/**',\n      '**/tmp/**',\n      // Dependencies\n      '**/node_modules/**',\n      // Config files\n      '*.config.js',\n      '*.config.mjs',\n      '*.config.ts',\n      // Logs\n      '**/*.log',\n      '**/npm-debug.log*',\n      '**/yarn-debug.log*',\n      '**/yarn-error.log*',\n    ],\n  },\n  {\n    // Base config for all TypeScript files\n    files: ['**/*.ts', '**/*.tsx'],\n    plugins: {\n      import: importPlugin,\n      unicorn,\n    },\n    languageOptions: {\n      parserOptions: {\n        projectService: true,\n        tsconfigRootDir: import.meta.dirname,\n        ecmaVersion: 'latest',\n        sourceType: 'module',\n      },\n    },\n    settings: {\n      'import/resolver': {\n        typescript: {\n          alwaysTryTypes: true,\n        },\n      },\n    },\n    rules: {\n      // Enforce naming conventions\n      '@typescript-eslint/naming-convention': [\n        'error',\n        // Types and Interfaces: Must be PascalCase, no I prefix (except IO, IP, ID), uppercase acronyms (ID not Id, IP not Ip, etc.)\n        {\n          selector: 'typeLike',\n          format: ['PascalCase'],\n          custom: {\n            // Reject: I-prefix (but not IO, IP, ID) OR lowercase acronyms anywhere (Id, Ip, Api, etc.)\n            regex:\n              '^I(?!O|P|D)[A-Z]|(^|[A-Z][a-z]+)(Id|Ip|Io|Ui|Api|Url|Html|Css|Json|Xml|Svg|Pdf|Uri|Uuid|Jwt|Sql|Http|Https|Ws|Wss|Sse|Db|Os|Cpu|Gpu|Ram|Usb|Ms)([A-Z]|$)',\n            match: false,\n          },\n        },\n        // Classes: PascalCase with uppercase acronyms (ID not Id, IP not Ip, etc.)\n        {\n          selector: 'class',\n          format: ['PascalCase'],\n          custom: {\n            // Reject: lowercase acronyms anywhere (Id, Ip, Api, etc.)\n            regex:\n              '(^|[A-Z][a-z]+)(Id|Ip|Io|Ui|Api|Url|Html|Css|Json|Xml|Svg|Pdf|Uri|Uuid|Jwt|Sql|Http|Https|Ws|Wss|Sse|Db|Os|Cpu|Gpu|Ram|Usb|Ms)([A-Z]|$)',\n            match: false,\n          },\n        },\n        // Quoted properties: Allow any format (for config files like '@': '...', 'some-key': '...', etc.)\n        {\n          selector: 'property',\n          modifiers: ['requiresQuotes'],\n          format: null,\n        },\n        // Properties: Allow snake_case for API compatibility (interfaces/types)\n        {\n          selector: 'property',\n          format: ['camelCase', 'UPPER_CASE', 'PascalCase', 'snake_case'],\n          custom: {\n            // Reject: lowercase acronyms in camelCase/PascalCase (but allow snake_case like user_id)\n            // Matches: userId, getUserId but NOT user_id, USER_ID, or PascalCase like ComponentType\n            regex:\n              '[a-z](?!_)(Id|Ip|Io|Ui|Api|Url|Html|Css|Json|Xml|Svg|Pdf|Uri|Uuid|Jwt|Sql|Http|Https|Ws|Wss|Sse|Db|Os|Cpu|Gpu|Ram|Usb|Ms)([A-Z_]|$)',\n            match: false,\n          },\n          leadingUnderscore: 'allow',\n        },\n        // Variables: camelCase, UPPER_CASE, or PascalCase\n        // Note: PascalCase is allowed for React patterns like const ThemeContext = createContext(...)\n        {\n          selector: 'variable',\n          format: ['camelCase', 'UPPER_CASE', 'PascalCase'],\n          custom: {\n            // Reject: lowercase acronyms in camelCase/PascalCase (but allow PascalCase variables)\n            // Matches: userId, getUserId but NOT userID, UserID, UPPER_CASE\n            regex:\n              '[a-z](Id|Ip|Io|Ui|Api|Url|Html|Css|Json|Xml|Svg|Pdf|Uri|Uuid|Jwt|Sql|Http|Https|Ws|Wss|Sse|Db|Os|Cpu|Gpu|Ram|Usb|Ms)([A-Z]|$)',\n            match: false,\n          },\n          leadingUnderscore: 'allow',\n        },\n        // Parameters/methods/functions: camelCase or PascalCase with uppercase acronyms\n        {\n          selector: ['parameter', 'method', 'function'],\n          format: ['camelCase', 'PascalCase'],\n          custom: {\n            // Reject: lowercase acronyms after lowercase letter (userId, getUserId, etc.)\n            regex:\n              '[a-z](Id|Ip|Io|Ui|Api|Url|Html|Css|Json|Xml|Svg|Pdf|Uri|Uuid|Jwt|Sql|Http|Https|Ws|Wss|Sse|Db|Os|Cpu|Gpu|Ram|Usb|Ms)([A-Z]|$)',\n            match: false,\n          },\n          leadingUnderscore: 'allow',\n        },\n        // Boolean variables with prefix requirement\n        {\n          selector: 'variable',\n          types: ['boolean'],\n          format: ['PascalCase', 'UPPER_CASE'],\n          prefix: [\n            'is',\n            'has',\n            'should',\n            'can',\n            'did',\n            'will',\n            'was',\n            'does',\n            'enable',\n            'allow',\n            'use',\n            'show',\n          ],\n          // Enforce acronyms stay uppercase\n          custom: {\n            regex:\n              '(Id|Ip|Io|Ui|Api|Url|Html|Css|Json|Xml|Svg|Pdf|Uri|Uuid|Jwt|Sql|Http|Https|Ws|Wss|Sse|Db|Os|Cpu|Gpu|Ram|Usb|Ms)([A-Z]|$)',\n            match: false,\n          },\n          // Allow UPPER_CASE without prefix for constants\n          filter: {\n            regex: '^[A-Z][A-Z0-9_]*$',\n            match: false,\n          },\n        },\n        {\n          // Allow uppercase constants without prefix requirement\n          selector: 'variable',\n          types: ['boolean'],\n          format: ['UPPER_CASE'],\n        },\n        {\n          selector: 'parameter',\n          types: ['boolean'],\n          format: ['PascalCase'],\n          prefix: [\n            'is',\n            'has',\n            'should',\n            'can',\n            'did',\n            'will',\n            'was',\n            'does',\n            'enable',\n            'allow',\n            'use',\n            'show',\n          ],\n          // Enforce acronyms stay uppercase\n          custom: {\n            regex:\n              '(Id|Ip|Io|Ui|Api|Url|Html|Css|Json|Xml|Svg|Pdf|Uri|Uuid|Jwt|Sql|Http|Https|Ws|Wss|Sse|Db|Os|Cpu|Gpu|Ram|Usb|Ms)([A-Z]|$)',\n            match: false,\n          },\n          // Allow unused parameters prefixed with _ to bypass the naming requirement\n          filter: {\n            regex: '^_',\n            match: false,\n          },\n        },\n      ],\n      // Detect unused variables\n      'no-unused-vars': 'off',\n      '@typescript-eslint/no-unused-vars': [\n        'error',\n        {\n          vars: 'all',\n          args: 'after-used',\n          ignoreRestSiblings: true,\n          argsIgnorePattern: '^_',\n          varsIgnorePattern: '^_',\n        },\n      ],\n      // TypeScript specific rules\n      '@typescript-eslint/no-explicit-any': 'warn',\n      '@typescript-eslint/explicit-function-return-type': 'off',\n      '@typescript-eslint/explicit-module-boundary-types': 'off',\n      '@typescript-eslint/no-non-null-assertion': 'warn',\n      // Enforce consistent type imports and prevent inline imports\n      '@typescript-eslint/consistent-type-imports': [\n        'error',\n        {\n          prefer: 'type-imports',\n          disallowTypeAnnotations: true, // Prevent inline imports like import('...').Type\n          fixStyle: 'separate-type-imports',\n        },\n      ],\n      '@typescript-eslint/no-import-type-side-effects': 'error',\n      // General code quality rules\n      'no-console': 'warn',\n      'no-debugger': 'error',\n      'prefer-const': 'error',\n      'no-var': 'error',\n      // Import/export rules\n      'no-duplicate-imports': 'off',\n      'import/no-duplicates': 'error',\n      'import/first': 'error',\n      // Enforce case-sensitive import paths (prevents macOS/Windows vs Linux issues)\n      'import/no-unresolved': [\n        'error',\n        {\n          caseSensitive: true,\n          // Ignore runtime-provided built-in modules and generated files that\n          // may not exist on a fresh checkout (e.g. current-build-info.ts).\n          ignore: ['^bun:', '^electron$', 'current-build-info'],\n        },\n      ],\n      // Forbid importing deprecated modules/exports\n      'import/no-deprecated': 'warn',\n      // Forbid importing packages not listed in dependencies\n      'import/no-extraneous-dependencies': [\n        'error',\n        {\n          devDependencies: [\n            // *.test.ts naming convention is preferred\n            // Both *.test.ts and *.spec.ts are supported for compatibility\n            '**/*.test.ts',\n            '**/*.test.tsx',\n            '**/*.spec.ts',\n            '**/*.spec.tsx',\n            '**/vite.config.ts',\n            '**/vitest.config.ts',\n            'scripts/**/*.ts',\n          ],\n        },\n      ],\n      // Forbid mutable exports (helps with predictable module behavior)\n      'import/no-mutable-exports': 'error',\n      // Best practices\n      eqeqeq: ['error', 'always'],\n      curly: ['error', 'all'],\n      'no-eval': 'error',\n      'no-implied-eval': 'error',\n      'import/newline-after-import': 'error',\n      // Disallow unnecessary /index in import paths (prefer ./foo over ./foo/index)\n      'import/no-useless-path-segments': ['error', { noUselessIndex: true }],\n      // Prevent function declarations inside blocks\n      'no-inner-declarations': 'error',\n      // Limit callback nesting to prevent callback hell\n      'max-nested-callbacks': ['error', 3],\n      // Class member accessibility - require explicit public/private/protected\n      '@typescript-eslint/explicit-member-accessibility': [\n        'error',\n        {\n          accessibility: 'explicit',\n          overrides: {\n            constructors: 'no-public', // Don't require public on constructors\n          },\n        },\n      ],\n      // Class member ordering - public first, then protected, then private\n      '@typescript-eslint/member-ordering': [\n        'error',\n        {\n          default: [\n            'public-field',\n            'protected-field',\n            'private-field',\n            'constructor',\n            'public-method',\n            'protected-method',\n            'private-method',\n          ],\n        },\n      ],\n      // Enforce filename conventions - kebab-case for regular TS files\n      'unicorn/filename-case': [\n        'error',\n        {\n          case: 'kebabCase',\n        },\n      ],\n      // Enforce using 'new' for builtins (except String, Number, Boolean, Symbol, BigInt)\n      'unicorn/new-for-builtins': 'error',\n      // Enforce Buffer.from() and Buffer.alloc() instead of deprecated new Buffer()\n      'unicorn/no-new-buffer': 'error',\n      // Enforce throwing TypeError in type checking conditions\n      'unicorn/prefer-type-error': 'error',\n      // Enforce consistent parameter name in catch clauses\n      'unicorn/catch-error-name': 'error',\n      // Prefer Date.now() over new Date().getTime()\n      'unicorn/prefer-date-now': 'error',\n      // Prefer new Date(date) over new Date(date.getTime())\n      'unicorn/consistent-date-clone': 'error',\n      // Prefer for...of over array.forEach()\n      'unicorn/no-array-for-each': 'error',\n      // Prefer for...of over traditional for loops\n      'unicorn/no-for-loop': 'error',\n      // Disallow named usage of default import/export\n      'unicorn/no-named-default': 'error',\n      // Prefer export...from when re-exporting\n      'unicorn/prefer-export-from': 'error',\n      // Disallow direct use of document.cookie (prefer helper functions/Cookie Store API)\n      'unicorn/no-document-cookie': 'error',\n      // Enforce Unicode escapes over hex escapes for better readability\n      'unicorn/no-hex-escape': 'error',\n      // Disallow assigning 'this' to a variable (use arrow functions instead)\n      'unicorn/no-this-assignment': 'error',\n      // Disallow unreadable IIFEs\n      'unicorn/no-unreadable-iife': 'error',\n      // Prefer .includes() over .indexOf() for checking existence\n      'unicorn/prefer-includes': 'error',\n      // Prefer Math.trunc() over bitwise operations for truncation\n      'unicorn/prefer-math-trunc': 'error',\n    },\n  },\n  {\n    // React/JSX specific config for TSX files\n    files: ['**/*.tsx'],\n    plugins: {\n      react,\n      'react-hooks': reactHooks,\n      'jsx-a11y': jsxA11y,\n      'react-refresh': reactRefresh,\n    },\n    languageOptions: {\n      parserOptions: {\n        projectService: true,\n        tsconfigRootDir: import.meta.dirname,\n        ecmaVersion: 'latest',\n        sourceType: 'module',\n        ecmaFeatures: {\n          jsx: true,\n        },\n      },\n    },\n    settings: {\n      react: {\n        version: 'detect',\n      },\n    },\n    rules: {\n      // React-specific rules\n      'react/jsx-uses-react': 'error',\n      'react/jsx-uses-vars': 'error',\n      'react/react-in-jsx-scope': 'off', // Not needed for React 17+\n      // React Hooks rules (recommended config)\n      ...reactHooks.configs.recommended.rules,\n      // JSX Accessibility rules\n      ...jsxA11y.flatConfigs.recommended.rules,\n      // React Refresh: only export components (required for Fast Refresh / HMR)\n      'react-refresh/only-export-components': [\n        'warn',\n        { allowConstantExport: true },\n      ],\n    },\n  },\n  {\n    // React components: enforce PascalCase for TSX files\n    // ignore: entry-point files use all-caps acronyms (EntrySSR, EntrySSG) — unicorn normalizes these to EntrySsr/EntrySsg but we prefer the full acronym form\n    files: ['**/*.tsx'],\n    rules: {\n      'unicorn/filename-case': [\n        'error',\n        {\n          case: 'pascalCase',\n          ignore: [/^Entry[A-Z]{2,}/],\n        },\n      ],\n    },\n  },\n  {\n    // React/JSX specific config for JSX files\n    files: ['**/*.jsx'],\n    plugins: {\n      react,\n      'react-hooks': reactHooks,\n      'jsx-a11y': jsxA11y,\n      'react-refresh': reactRefresh,\n    },\n    languageOptions: {\n      parserOptions: {\n        ecmaVersion: 'latest',\n        sourceType: 'module',\n        ecmaFeatures: {\n          jsx: true,\n        },\n      },\n    },\n    settings: {\n      react: {\n        version: 'detect',\n      },\n    },\n    rules: {\n      // React-specific rules\n      'react/jsx-uses-react': 'error',\n      'react/jsx-uses-vars': 'error',\n      'react/react-in-jsx-scope': 'off', // Not needed for React 17+\n      // React Hooks rules (recommended config)\n      ...reactHooks.configs.recommended.rules,\n      // JSX Accessibility rules\n      ...jsxA11y.flatConfigs.recommended.rules,\n      // React Refresh: only export components (required for Fast Refresh / HMR)\n      'react-refresh/only-export-components': [\n        'warn',\n        { allowConstantExport: true },\n      ],\n    },\n  },\n  {\n    // Warn about *.spec.ts files - prefer *.test.ts instead\n    files: ['**/*.spec.ts', '**/*.spec.tsx'],\n    plugins: {\n      'check-file': checkFile,\n    },\n    rules: {\n      'check-file/filename-blocklist': [\n        'warn',\n        {\n          '**/*.spec.ts': '*.test.ts',\n          '**/*.spec.tsx': '*.test.tsx',\n        },\n      ],\n    },\n  },\n  {\n    // Test files: allow console and any for mocking\n    files: [\n      '**/*.test.ts',\n      '**/*.test.tsx',\n      '**/*.test.js',\n      '**/*.test.jsx',\n      '**/*.spec.ts',\n      '**/*.spec.tsx',\n      '**/*.spec.js',\n      '**/*.spec.jsx',\n    ],\n    rules: {\n      'no-console': 'off',\n      '@typescript-eslint/no-explicit-any': 'off',\n      '@typescript-eslint/no-unsafe-argument': 'off',\n      '@typescript-eslint/no-unsafe-assignment': 'off',\n      '@typescript-eslint/no-unsafe-member-access': 'off',\n      '@typescript-eslint/no-unsafe-return': 'off',\n      '@typescript-eslint/no-unsafe-call': 'off',\n      'max-nested-callbacks': 'off', // Test frameworks naturally have deep nesting\n      'react-refresh/only-export-components': 'off', // Test files export utilities/mocks, not just components\n    },\n  },\n  {\n    // Scripts: allow console for CLI output\n    files: ['scripts/**/*.ts'],\n    rules: {\n      'no-console': 'off',\n    },\n  },\n  {\n    // Disable type-checked rules for JavaScript files\n    ...tseslint.configs.disableTypeChecked,\n    files: ['**/*.js', '**/*.jsx', '**/*.cjs', '**/*.mjs'],\n  },\n];`;\n\n/**\n * Ensure eslint.config.js exists at the repo root.\n * Only creates the file if it doesn't exist - never overwrites.\n * @throws {Error} If file creation fails\n */\nexport async function ensureEslintConfig(\n  repoRoot: FileRoot,\n  log?: LoggerFunction,\n): Promise<void> {\n  try {\n    const didWrite = await vfsWriteIfNotExists(\n      repoRoot,\n      'eslint.config.js',\n      fileSrc,\n    );\n\n    if (didWrite && log) {\n      log('info', 'Created repo root eslint.config.js');\n    }\n  } catch (error) {\n    const errorMessage = error instanceof Error ? error.message : String(error);\n    throw new Error(`Failed to ensure eslint.config.js: ${errorMessage}`);\n  }\n}\n","import { vfsReadJSON, vfsWriteJSON } from '../vfs';\nimport type { FileRoot } from '../vfs';\nimport type { LoggerFunction } from '../types';\n\nconst defaultExtensions = [\n  'dbaeumer.vscode-eslint',\n  'esbenp.prettier-vscode',\n  'streetsidesoftware.code-spell-checker',\n  'Gruntfuggly.todo-tree',\n  'jmbeach.list-symbols',\n  'firsttris.vscode-jest-runner',\n  'bradlc.vscode-tailwindcss',\n];\n\ninterface VSCodeExtensions {\n  recommendations?: string[];\n  [key: string]: unknown;\n}\n\n/**\n * Ensure .vscode/extensions.json exists at the repo root with recommended extensions.\n * If the file exists, merges in any missing extensions from the default list.\n * Never removes existing extensions.\n *\n * @throws {Error} If file read/write fails\n */\nexport async function ensureVSCodeExtensions(\n  repoRoot: FileRoot,\n  log?: LoggerFunction,\n): Promise<void> {\n  try {\n    const filePath = '.vscode/extensions.json';\n    const readResult = await vfsReadJSON(repoRoot, filePath);\n\n    let extensionsData: VSCodeExtensions;\n    let didChange = false;\n\n    if (readResult.ok && readResult.data) {\n      // File exists, merge extensions\n      extensionsData = readResult.data as VSCodeExtensions;\n\n      // Ensure recommendations array exists\n      if (!Array.isArray(extensionsData.recommendations)) {\n        extensionsData.recommendations = [];\n        didChange = true;\n      }\n\n      // Add missing extensions\n      const existingExtensions = new Set(extensionsData.recommendations);\n      for (const ext of defaultExtensions) {\n        if (!existingExtensions.has(ext)) {\n          extensionsData.recommendations.push(ext);\n          didChange = true;\n        }\n      }\n\n      if (didChange) {\n        // Sort recommendations alphabetically for consistency\n        extensionsData.recommendations.sort();\n\n        await vfsWriteJSON(repoRoot, filePath, extensionsData);\n\n        if (log) {\n          log(\n            'info',\n            'Updated .vscode/extensions.json with missing extensions',\n          );\n        }\n      }\n    } else {\n      // File doesn't exist, create it\n      extensionsData = {\n        recommendations: [...defaultExtensions].sort(),\n      };\n\n      await vfsWriteJSON(repoRoot, filePath, extensionsData);\n\n      if (log) {\n        log('info', 'Created .vscode/extensions.json');\n      }\n    }\n  } catch (error) {\n    const errorMessage = error instanceof Error ? error.message : String(error);\n    throw new Error(\n      `Failed to ensure .vscode/extensions.json: ${errorMessage}`,\n    );\n  }\n}\n","import { vfsReadJSON, vfsWriteJSON } from '../vfs';\nimport type { FileRoot } from '../vfs';\nimport type { LoggerFunction } from '../types';\n\n// jestrunner.jestCommand assumes bun, as current scope is bun being used for dev/build tooling\nconst defaultSettings = {\n  'css.lint.unknownAtRules': 'ignore',\n  'editor.defaultFormatter': 'esbenp.prettier-vscode',\n  'editor.formatOnSave': true,\n  'editor.formatOnPaste': true,\n  'editor.codeActionsOnSave': {\n    'source.fixAll.eslint': 'explicit',\n  },\n  'editor.snippetSuggestions': 'top',\n  'files.autoSave': 'afterDelay',\n  'prettier.prettierPath': './node_modules/prettier',\n  'prettier.requireConfig': true,\n  'jestrunner.jestCommand': 'bun test',\n};\n\ninterface VSCodeSettings {\n  [key: string]: unknown;\n}\n\n/**\n * Ensure .vscode/settings.json exists at the repo root with recommended settings.\n * If the file exists, merges in any missing settings from the default list.\n * Never overwrites existing settings - only adds missing ones.\n *\n * @throws {Error} If file read/write fails\n */\nexport async function ensureVSCodeSettings(\n  repoRoot: FileRoot,\n  log?: LoggerFunction,\n): Promise<void> {\n  try {\n    const filePath = '.vscode/settings.json';\n    const readResult = await vfsReadJSON(repoRoot, filePath);\n\n    let settingsData: VSCodeSettings;\n    let didChange = false;\n\n    if (readResult.ok && readResult.data) {\n      // File exists, merge settings\n      settingsData = readResult.data as VSCodeSettings;\n\n      // Add missing settings (only if key doesn't exist)\n      for (const [key, value] of Object.entries(defaultSettings)) {\n        if (!(key in settingsData)) {\n          settingsData[key] = value;\n          didChange = true;\n        }\n      }\n\n      if (didChange) {\n        await vfsWriteJSON(repoRoot, filePath, settingsData);\n\n        if (log) {\n          log('info', 'Updated .vscode/settings.json with missing settings');\n        }\n      }\n    } else {\n      // File doesn't exist, create it\n      settingsData = { ...defaultSettings };\n\n      await vfsWriteJSON(repoRoot, filePath, settingsData);\n\n      if (log) {\n        log('info', 'Created .vscode/settings.json');\n      }\n    }\n  } catch (error) {\n    const errorMessage = error instanceof Error ? error.message : String(error);\n    throw new Error(`Failed to ensure .vscode/settings.json: ${errorMessage}`);\n  }\n}\n","export const SCRIPTS_GIT_KEEP_FILE_SRC = [\n  '# Scripts Directory',\n  '',\n  'Place custom build scripts, utilities (such as database migrations), and automation tools here.',\n  '',\n  'These scripts can use the @/ alias to import from src/:',\n  '',\n  '```typescript',\n  \"import { formatCount } from '@/libs/utils/format';\",\n  '```',\n  '',\n  'Run scripts with:',\n  '',\n  '```bash',\n  'bun run scripts/your-script.ts',\n  '```',\n  '',\n  'Or add a shortcut to package.json:',\n  '',\n  '```json',\n  '\"scripts\": {',\n  '  \"script:name\": \"bun run scripts/your-script.ts\"',\n  '}',\n  '```',\n].join('\\n');\n\nexport const LIBS_GIT_KEEP_FILE_SRC = [\n  '# Libs Directory',\n  '',\n  'Shared libraries and utilities that can be used across apps, scripts, and other libs.',\n  '',\n  'Organize by feature or type:',\n  '```',\n  'src/libs/',\n  '├── utils/          # General utilities',\n  '├── hooks/          # React hooks',\n  '├── components/     # Shared React components',\n  '├── types/          # TypeScript types',\n  '└── api/            # API clients',\n  '```',\n  '',\n  'Import using the @/ alias:',\n  '```typescript',\n  \"import { formatCount } from '@/libs/utils/format';\",\n  \"import { useDebounce } from '@/libs/hooks/useDebounce';\",\n  '```',\n].join('\\n');\n\nexport const APPS_GIT_KEEP_FILE_SRC = [\n  '# Apps Directory',\n  '',\n  'Each application lives in its own subdirectory with its own configuration.',\n  '',\n  'Create new apps using the unirend CLI:',\n  '```bash',\n  '# SSG (Static Site Generation)',\n  'bunx unirend create ssg my-blog',\n  '',\n  '# SSR (Server-Side Rendering)',\n  'bunx unirend create ssr my-app',\n  '',\n  '# API Server',\n  'bunx unirend create api my-api',\n  '```',\n  '',\n  'Apps can import from shared libs:',\n  '```typescript',\n  \"import { formatCount } from '@/libs/utils/format';\",\n  \"import { useDebounce } from '@/libs/hooks/useDebounce';\",\n  '```',\n].join('\\n');\n","/* eslint-disable @typescript-eslint/no-unused-vars */\n// todo: reenable @typescript-eslint/no-unused-vars once we implement the functions\nimport { ensurePackageJSON } from './base-files/package-json';\nimport type { EnsurePackageJSONOptions } from './base-files/package-json';\nimport { ensureGitignore } from './base-files/ensure-gitignore';\nimport { ensureGitkeep } from './base-files/ensure-gitkeep';\nimport { ensureTsConfig } from './base-files/ensure-tsconfig';\nimport { ensureEditorConfig } from './base-files/ensure-editor-config';\nimport { ensurePrettierConfig } from './base-files/ensure-prettier-config';\nimport { ensurePrettierIgnore } from './base-files/ensure-prettier-ignore';\nimport { ensureEslintConfig } from './base-files/ensure-eslint-config';\nimport { ensureVSCodeExtensions } from './base-files/ensure-vscode-extensions';\nimport { ensureVSCodeSettings } from './base-files/ensure-vscode-settings';\nimport type { RepoConfig, ServerBuildTarget, LoggerFunction } from './types';\nimport type { FileRoot } from './vfs';\nimport {\n  APPS_GIT_KEEP_FILE_SRC,\n  LIBS_GIT_KEEP_FILE_SRC,\n  SCRIPTS_GIT_KEEP_FILE_SRC,\n} from './base-files/gitkeep-files-src';\n\nexport function createRepoConfigObject(name: string): RepoConfig {\n  return {\n    version: '1.0',\n    name,\n    created: new Date().toISOString(),\n    projects: {},\n  };\n}\n\nexport function addProjectToRepo(\n  config: RepoConfig,\n  projectName: string,\n  templateID: string,\n  relativePath: string,\n): RepoConfig {\n  return {\n    ...config,\n    projects: {\n      ...config.projects,\n      [projectName]: {\n        templateID,\n        path: relativePath,\n        createdAt: new Date().toISOString(),\n      },\n    },\n  };\n}\n\n/**\n * Options for ensureBaseFiles function\n * Inherits package.json options, plus template-specific .gitignore entries:\n * - log: Logger function\n * - templateScripts: Template-specific scripts\n * - templateDependencies: Template-specific dependencies\n * - templateDevDependencies: Template-specific devDependencies\n * - templateGitignoreSectionHeader: Header for template-specific .gitignore entries\n * - templateGitignoreEntries: Template-specific .gitignore entries\n */\nexport type EnsureBaseFilesOptions = EnsurePackageJSONOptions & {\n  /** Header for template-specific .gitignore entries */\n  templateGitignoreSectionHeader?: string;\n  /** Template-specific .gitignore entries to append if missing */\n  templateGitignoreEntries?: string[];\n};\n\n/**\n * Ensure base repo files exist at the workspace root.\n * Creates standard configuration files (.gitignore, package.json, tsconfig.json, .editorconfig, prettier.config.js, etc.)\n * Most files are only created if missing, package.json is updated to ensure required fields exist.\n *\n * @throws {Error} If any file creation/update fails\n */\nexport async function ensureBaseFiles(\n  repoRoot: FileRoot,\n  repoName: string,\n  options?: EnsureBaseFilesOptions,\n): Promise<void> {\n  // Each separate helper function will throw on error, allowing errors to propagate to the caller\n\n  // Ensure .gitignore exists first (only creates if missing)\n  await ensureGitignore(repoRoot, {\n    log: options?.log,\n    templateSectionHeader: options?.templateGitignoreSectionHeader,\n    templateEntries: options?.templateGitignoreEntries,\n  });\n\n  // Ensure standard directories have .gitkeep if empty (scripts, src/apps and src/libs)\n  await ensureGitkeep(\n    repoRoot,\n    'scripts',\n    SCRIPTS_GIT_KEEP_FILE_SRC,\n    options?.log,\n  );\n\n  await ensureGitkeep(\n    repoRoot,\n    'src/apps',\n    APPS_GIT_KEEP_FILE_SRC,\n    options?.log,\n  );\n\n  await ensureGitkeep(\n    repoRoot,\n    'src/libs',\n    LIBS_GIT_KEEP_FILE_SRC,\n    options?.log,\n  );\n\n  // Ensure package.json exists with required fields\n  await ensurePackageJSON(repoRoot, repoName, options);\n\n  // Ensure tsconfig.json exists (only creates if missing)\n  await ensureTsConfig(repoRoot, options?.log);\n\n  // Ensure .editorconfig exists (only creates if missing)\n  await ensureEditorConfig(repoRoot, options?.log);\n\n  // Ensure prettier.config.js exists (only creates if missing)\n  await ensurePrettierConfig(repoRoot, options?.log);\n\n  // Ensure .prettierignore exists (only creates if missing)\n  await ensurePrettierIgnore(repoRoot, options?.log);\n\n  // Ensure eslint.config.js exists (only creates if missing)\n  await ensureEslintConfig(repoRoot, options?.log);\n\n  // Ensure .vscode/extensions.json exists (creates or updates with missing extensions)\n  await ensureVSCodeExtensions(repoRoot, options?.log);\n\n  // Ensure .vscode/settings.json exists (creates or updates with missing settings)\n  await ensureVSCodeSettings(repoRoot, options?.log);\n}\n\n/**\n * Template-specific configuration returned by getTemplateConfig\n */\nexport interface TemplateConfig {\n  /** Template-specific package.json scripts */\n  scripts?: Record<string, string>;\n  /** Template-specific dependencies */\n  dependencies?: Record<string, string>;\n  /** Template-specific devDependencies */\n  devDependencies?: Record<string, string>;\n  /** Template-specific .gitignore entries */\n  gitignoreEntries?: string[];\n  /** Header for template-specific .gitignore entries */\n  gitignoreSectionHeader?: string;\n}\n\n/**\n * Get template-specific configuration (scripts, dependencies, devDependencies)\n * based on the template type, project name, and project path.\n *\n * @param projectName - Name of the project being created\n * @param templateID - Template identifier (e.g., \"basic-ssr\", \"basic-ssg\")\n * @param projectPath - Relative path to the project (e.g., \"src/apps/my-project\")\n * @param serverBuildTarget - Target runtime for server build/bundle\n * @returns Template configuration object with optional scripts/deps\n */\nexport function getTemplateConfig(\n  projectName: string,\n  templateID: string,\n  projectPath: string,\n  serverBuildTarget?: ServerBuildTarget,\n): TemplateConfig {\n  // todo: when building serve, got to remember if we're goin to target bun or node...\n  // this changes the bun buidl target and if we call bun or node when running.\n  return {};\n}\n\n/**\n * Create project-specific files and directory structure based on template identifier.\n * Writes all template-specific starter files to the project directory.\n *\n * @param root - File root (filesystem path or in-memory object)\n * @param projectPath - Relative path to the project directory (e.g., \"src/apps/my-project\")\n * @param projectName - Name of the project being created\n * @param templateID - Template identifier (e.g., \"ssg\", \"ssr\", \"api\")\n * @param serverBuildTarget - Target runtime for server build/bundle\n * @param log - Optional logger function for output\n */\n\nexport async function createProjectSpecificFiles(\n  root: FileRoot,\n  projectPath: string,\n  projectName: string,\n  templateID: string,\n  serverBuildTarget: ServerBuildTarget | undefined,\n  log?: LoggerFunction,\n): Promise<void> {\n  // todo: implement\n}\n","import { builtinModules } from 'module';\nimport type { NameValidationResult } from './types';\n\n/**\n * Validate a project or repo name\n * Returns an object with validation result and optional error message\n *\n * This validator is compatible with NPM package naming rules while being stricter:\n * - NPM rules: https://www.npmjs.com/package/validate-npm-package-name\n * - Maximum 214 characters\n * - Lowercase only\n * - Cannot start with dots, underscores, or dashes\n * - Cannot end with special characters\n * - No consecutive special characters\n * - No non-URL-safe characters\n * - No Node.js core module names or system reserved names\n * - Additional filesystem safety checks\n */\nexport function validateName(name: string): NameValidationResult {\n  // Must not be empty\n  if (!name || name.trim().length === 0) {\n    return { valid: false, error: 'Name cannot be empty' };\n  }\n\n  // NPM Rule: Must not exceed 214 characters\n  if (name.length > 214) {\n    return {\n      valid: false,\n      error: 'Name cannot exceed 214 characters',\n    };\n  }\n\n  // NPM Rule: Must be lowercase only (no uppercase letters)\n  if (/[A-Z]/.test(name)) {\n    return {\n      valid: false,\n      error: 'Name must be lowercase only',\n    };\n  }\n\n  // NPM Rule: Cannot start with a dot, underscore, or dash\n  if (/^[._-]/.test(name)) {\n    return {\n      valid: false,\n      error: 'Name cannot start with a dot, underscore, or dash',\n    };\n  }\n\n  // Must not end with special characters (stricter than npm)\n  if (/[-_.]$/.test(name)) {\n    return {\n      valid: false,\n      error: 'Name cannot end with a dash, underscore, or dot',\n    };\n  }\n\n  // NPM Rule: Cannot contain spaces\n  if (/\\s/.test(name)) {\n    return {\n      valid: false,\n      error: 'Name cannot contain spaces',\n    };\n  }\n\n  // NPM Rule: Cannot contain non-URL-safe characters\n  // Allowed: lowercase letters, digits, hyphens, dots, underscores\n  // Prohibited: all other characters including ~)('!* and filesystem-unsafe chars\n  if (!/^[a-z0-9._-]+$/.test(name)) {\n    return {\n      valid: false,\n      error:\n        'Name contains invalid characters. Only lowercase letters, numbers, hyphens, dots, and underscores are allowed',\n    };\n  }\n\n  // Must not contain consecutive special characters (dash, underscore, dot)\n  // Special characters must be surrounded by alphanumeric characters\n  // Examples: \"foo-bar\" ✓, \"foo--bar\" ✗, \"foo_.bar\" ✗, \"foo..bar\" ✗\n  const specialChars = new Set(['.', '_', '-']);\n  for (let i = 0; i < name.length - 1; i++) {\n    const current = name[i];\n    const next = name[i + 1];\n\n    // If current char is special and next char is also special, it's invalid\n    if (specialChars.has(current) && specialChars.has(next)) {\n      return {\n        valid: false,\n        error: `Name cannot contain consecutive special characters (found \"${current}${next}\"). Special characters must be surrounded by letters or numbers.`,\n      };\n    }\n  }\n\n  // NPM Rule: Cannot be Node.js core modules or reserved names\n  // Use Node.js's built-in list of core modules (automatically stays up-to-date)\n  // builtinModules may include \"node:\" prefixed versions, so we filter to base names only\n  const nodeBuiltins = builtinModules\n    .filter((mod) => !mod.startsWith('node:'))\n    .map((mod) => mod.toLowerCase());\n\n  // Additional reserved names (npm and filesystem)\n  const additionalReserved = [\n    // Runtime name it self\n    'node',\n    // NPM reserved\n    'node_modules',\n    'favicon.ico',\n    // Windows reserved names\n    'con',\n    'prn',\n    'aux',\n    'nul',\n    'com1',\n    'com2',\n    'com3',\n    'com4',\n    'com5',\n    'com6',\n    'com7',\n    'com8',\n    'com9',\n    'lpt1',\n    'lpt2',\n    'lpt3',\n    'lpt4',\n    'lpt5',\n    'lpt6',\n    'lpt7',\n    'lpt8',\n    'lpt9',\n    // Relative path references\n    '.',\n    '..',\n  ];\n\n  const allReserved = [...nodeBuiltins, ...additionalReserved];\n\n  if (allReserved.includes(name.toLowerCase())) {\n    return {\n      valid: false,\n      error: `Name \"${name}\" is reserved (Node.js core module, npm reserved name, or system reserved name)`,\n    };\n  }\n\n  return { valid: true };\n}\n","import { spawn } from 'child_process';\nimport { isInMemoryFileRoot, vfsExists } from './vfs';\nimport type { FileRoot } from './vfs';\nimport type { LoggerFunction } from './types';\n\n/**\n * Run a command asynchronously, capturing stdout/stderr and surfacing spawn errors.\n * Resolves once, via either 'error' or 'close'.\n * Never throws; callers should inspect the returned shape.\n */\nasync function runCommand(\n  command: string,\n  args: string[],\n  cwd: string,\n): Promise<{\n  exitCode: number | null;\n  stdout: string;\n  stderr: string;\n  error?: Error;\n}> {\n  return new Promise((resolve) => {\n    const child = spawn(command, args, {\n      cwd,\n      stdio: 'pipe',\n    });\n\n    let isResolved = false;\n    let stdout = '';\n    let stderr = '';\n\n    child.stdout?.setEncoding('utf8').on('data', (data: string) => {\n      stdout += data;\n    });\n\n    child.stderr?.setEncoding('utf8').on('data', (data: string) => {\n      stderr += data;\n    });\n\n    const safeResolve = (payload: {\n      exitCode: number | null;\n      stdout: string;\n      stderr: string;\n      error?: Error;\n    }) => {\n      if (isResolved) {\n        return;\n      }\n      isResolved = true;\n      resolve(payload);\n    };\n\n    child.on('error', (err: Error) => {\n      safeResolve({ exitCode: null, stdout, stderr, error: err });\n    });\n\n    child.on('close', (code: number | null) => {\n      safeResolve({ exitCode: code, stdout, stderr });\n    });\n  });\n}\n\n/**\n * Initialize git repository if not already initialized.\n * Only works for filesystem mode - gracefully skips for in-memory.\n * Fails gracefully if git command is not found.\n * Never throws - all errors are logged as warnings.\n *\n * @param root - File root (filesystem path or in-memory object)\n * @param log - Optional logger function for output\n */\nexport async function initGitRepo(\n  root: FileRoot,\n  log?: LoggerFunction,\n): Promise<void> {\n  // Skip for in-memory mode\n  if (isInMemoryFileRoot(root)) {\n    return;\n  }\n\n  try {\n    // Check if .git directory already exists\n    const doesGitExist = await vfsExists(root, '.git');\n\n    if (doesGitExist) {\n      if (log) {\n        log('info', 'Git repository already initialized');\n      }\n\n      return;\n    }\n\n    // Try to run `git init` in the repo root\n    const result = await runCommand('git', ['init'], root);\n\n    if (result.error) {\n      const msg = result.error.message;\n\n      if (log) {\n        if (msg.includes('ENOENT') || msg.includes('not found')) {\n          log('warning', '⚠️  Git not found - skipping git init');\n          log(\n            'warning',\n            '   Install git to enable automatic repository initialization',\n          );\n        } else {\n          log('warning', `⚠️  Failed to spawn git: ${msg}`);\n        }\n      }\n\n      return;\n    }\n\n    if (result.exitCode === 0) {\n      if (log) {\n        log('info', '🔧 Initialized git repository');\n      }\n    } else {\n      if (log) {\n        log('warning', '⚠️  Failed to initialize git repository');\n        if (result.stderr?.trim()) {\n          log('warning', `   ${result.stderr.trim()}`);\n        }\n      }\n    }\n  } catch (error) {\n    // Handle all errors gracefully - never throw\n    if (log) {\n      const msg = error instanceof Error ? error.message : String(error);\n\n      // Check if git command not found\n      if (\n        msg.includes('ENOENT') ||\n        msg.includes('not found') ||\n        msg.includes('No such file')\n      ) {\n        log('warning', '⚠️  Git not found - skipping git init');\n        log(\n          'warning',\n          '   Install git to enable automatic repository initialization',\n        );\n      } else {\n        log('warning', `⚠️  Failed to initialize git: ${msg}`);\n      }\n    }\n  }\n}\n\n/**\n * Install dependencies in a directory using bun install.\n * Gracefully handles errors (e.g., bun not found) by logging warnings.\n * Never throws - always returns successfully even if installation fails.\n *\n * @param root - File root (filesystem path or in-memory object)\n * @param log - Optional logger function for output\n */\nexport async function installDependencies(\n  root: FileRoot,\n  log?: LoggerFunction,\n): Promise<void> {\n  // Skip for in-memory mode\n  if (isInMemoryFileRoot(root)) {\n    return;\n  }\n\n  try {\n    if (log) {\n      log('info', '📦 Installing dependencies...');\n    }\n\n    // Run `bun install` in the directory\n    const result = await runCommand('bun', ['install'], root);\n\n    if (result.error) {\n      const msg = result.error.message;\n\n      if (log) {\n        if (msg.includes('ENOENT') || msg.includes('not found')) {\n          log(\n            'warning',\n            '⚠️  Bun not found - skipping dependency installation',\n          );\n          log(\n            'warning',\n            '   Run `bun install` manually to install dependencies',\n          );\n        } else {\n          log('warning', `⚠️  Failed to spawn bun: ${msg}`);\n        }\n      }\n      return;\n    }\n\n    if (result.exitCode === 0) {\n      if (log) {\n        log('info', '✅ Dependencies installed successfully');\n      }\n    } else {\n      if (log) {\n        log('warning', '⚠️  Failed to install dependencies');\n        if (result.stderr?.trim()) {\n          log('warning', `   ${result.stderr.trim()}`);\n        }\n      }\n    }\n  } catch (error) {\n    // Handle all errors gracefully - never throw\n    if (log) {\n      const msg = error instanceof Error ? error.message : String(error);\n      log('warning', `⚠️  Failed to install dependencies: ${msg}`);\n    }\n  }\n}\n\n/**\n * Auto-format code in a directory using bun run format.\n *\n * Checks if node_modules/prettier exists before attempting to format.\n * Gracefully handles errors (e.g., prettier not installed) by logging warnings.\n * Never throws - always returns successfully even if formatting fails.\n *\n * @param root - File root (filesystem path or in-memory object)\n * @param log - Optional logger function for output\n */\nexport async function autoFormatCode(\n  root: FileRoot,\n  log?: LoggerFunction,\n): Promise<void> {\n  // Skip for in-memory mode\n  if (isInMemoryFileRoot(root)) {\n    return;\n  }\n\n  try {\n    // Check if node_modules/prettier exists before attempting to format\n    const hasPrettier = await vfsExists(root, 'node_modules/prettier');\n\n    if (!hasPrettier) {\n      if (log) {\n        log(\n          'info',\n          '⏭️  Skipping auto-format (dependencies - prettier not installed)',\n        );\n      }\n\n      return;\n    }\n\n    if (log) {\n      log('info', '✨ Auto-formatting code...');\n    }\n\n    // Run `bun run format` in the directory\n    const result = await runCommand('bun', ['run', 'format'], root);\n\n    if (result.error) {\n      const msg = result.error.message;\n\n      if (log) {\n        if (msg.includes('ENOENT') || msg.includes('not found')) {\n          log('warning', '⚠️  Bun not found - skipping auto-format');\n          log('warning', '   Run `bun run format` manually to format code');\n        } else {\n          log('warning', `⚠️  Failed to spawn bun: ${msg}`);\n        }\n      }\n\n      return;\n    }\n\n    if (result.exitCode === 0) {\n      if (log) {\n        log('info', '✅ Code formatted successfully');\n      }\n    } else {\n      if (log) {\n        log('warning', '⚠️  Failed to format code');\n\n        if (result.stderr?.trim()) {\n          log('warning', `   ${result.stderr.trim()}`);\n        }\n      }\n    }\n  } catch (error) {\n    // Handle all errors gracefully - never throw\n    if (log) {\n      const msg = error instanceof Error ? error.message : String(error);\n      log('warning', `⚠️  Failed to format code: ${msg}`);\n    }\n  }\n}\n"],"mappings":"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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;A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","names":["fsMkdir","fsWriteFile","norm","fsReadFile","fsRm","fsStat","fsReaddir","norm","semver","sortPackageJson","fileSrc","fileSrc","fileSrc","fileSrc","fileSrc","fileSrc"]}