{"version":3,"sources":["/home/pitok/Projects/framework-bun/packages/buntok-core/dist/cli/index.cjs","../../src/cli/commands/build.ts","../../src/cli/commands/check.ts","../../src/cli/commands/create.ts","../../src/cli/generators/barrel.ts","../../src/cli/generators/controller.ts","../../src/cli/generators/repository.ts","../../src/cli/generators/schema.ts","../../src/cli/generators/service.ts","../../src/cli/commands/db.ts","../../src/cli/commands/debug-routes.ts","../../src/cli/commands/dev.ts","../../src/cli/commands/init.ts","../../src/cli/commands/make-docs.ts","../../src/cli/commands/make-factory.ts","../../src/cli/utils.ts","../../src/cli/commands/make-middleware.ts","../../src/cli/commands/make-seeder.ts","../../src/cli/commands/make-test.ts","../../src/cli/commands/make-test-e2e.ts","../../src/cli/index.ts"],"names":["join","existsSync","getDrizzleType","getTypeORMType","getPrismaType","toPascalCase","readFileSync","findInsertionIndex","collectImportedControllers","rcSingleMatch","rcArrayMatch","ensureImport","resolve","execSync","createInterface","mkdirSync"],"mappings":"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","file":"/home/pitok/Projects/framework-bun/packages/buntok-core/dist/cli/index.cjs","sourcesContent":[null,"import { join } from \"node:path\";\nimport { existsSync } from \"node:fs\";\n\nexport async function buildCommand() {\n\tconst projectRoot = process.cwd();\n\tconst entryPoint = join(projectRoot, \"server.ts\");\n\tconst outDir = join(projectRoot, \".buntok\");\n\n\tif (!existsSync(entryPoint)) {\n\t\tconsole.error(\"\\x1b[31m❌ server.ts not found\\x1b[0m\");\n\t\tprocess.exitCode = 1;\n\t\treturn;\n\t}\n\n\t// Read user's package.json to know their dependencies\n\tlet userDeps: string[] = [];\n\tconst pkgPath = join(projectRoot, \"package.json\");\n\tif (existsSync(pkgPath)) {\n\t\tconst pkg = await Bun.file(pkgPath).json();\n\t\tuserDeps = [\n\t\t\t...Object.keys(pkg.dependencies || {}),\n\t\t\t...Object.keys(pkg.devDependencies || {}),\n\t\t];\n\t}\n\n\t// BunTok peer deps (optional, user installs these)\n\tconst peerDeps = [\n\t\t\"@apollo/server\",\n\t\t\"graphql\",\n\t\t\"graphql-yoga\",\n\t\t\"@opentelemetry/api\",\n\t\t\"@opentelemetry/sdk-node\",\n\t\t\"@opentelemetry/resources\",\n\t\t\"@opentelemetry/semantic-conventions\",\n\t\t\"@opentelemetry/sdk-trace-node\",\n\t\t\"@opentelemetry/exporter-trace-otlp-http\",\n\t\t\"ioredis\",\n\t\t\"bullmq\",\n\t\t\"amqplib\",\n\t];\n\n\tconst external = [...new Set([...peerDeps, ...userDeps])];\n\n\tconsole.log(\"\\x1b[36m🔨 Building project...\\x1b[0m\");\n\n\tconst result = await Bun.build({\n\t\tentrypoints: [entryPoint],\n\t\toutdir: outDir,\n\t\ttarget: \"bun\",\n\t\ttsconfig: join(projectRoot, \"tsconfig.json\"),\n\t\texternal,\n\t});\n\n\tif (!result.success) {\n\t\tconsole.error(\"\\x1b[31m❌ Build failed:\\x1b[0m\");\n\t\tfor (const log of result.logs) {\n\t\t\tconsole.error(log);\n\t\t}\n\t\tprocess.exitCode = 1;\n\t\treturn;\n\t}\n\n\tconsole.log(\"\\x1b[32m✅ Build successful → .buntok/server.js\\x1b[0m\");\n\tconsole.log(\"\\x1b[90m  Deploy: copy .buntok/ + node_modules/ + package.json to server\\x1b[0m\");\n}\n","import { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\ninterface TSError {\n\tfile: string;\n\tline: number;\n\tcol: number;\n\tcode: string;\n\tmessage: string;\n}\n\nfunction stripAnsi(str: string): string {\n\t// biome-ignore lint/suspicious/noControlCharactersInRegex: ANSI escape codes\n\treturn str.replace(/\\x1B\\[[0-9;]*[mK]/g, \"\");\n}\n\nfunction parseTSErrors(output: string): TSError[] {\n\tconst clean = stripAnsi(output);\n\tconst lines = clean.split(\"\\n\");\n\tconst errors: TSError[] = [];\n\n\tfor (const line of lines) {\n\t\t// Format without --pretty: \"file.ts(1,7): error TS2322: message\"\n\t\t// Format with --pretty: \"file.ts:1:7 - error TS2322: message\"\n\t\tconst match =\n\t\t\tline.match(/^(.+?)\\((\\d+),(\\d+)\\): error (TS\\d+): (.+)$/) ||\n\t\t\tline.match(/^(.+?):(\\d+):(\\d+) - error (TS\\d+): (.+)$/);\n\t\tif (match && match[1] && match[2] && match[3] && match[4] && match[5]) {\n\t\t\terrors.push({\n\t\t\t\tfile: match[1],\n\t\t\t\tline: Number.parseInt(match[2], 10),\n\t\t\t\tcol: Number.parseInt(match[3], 10),\n\t\t\t\tcode: match[4],\n\t\t\t\tmessage: match[5],\n\t\t\t});\n\t\t}\n\t}\n\n\treturn errors;\n}\n\nfunction getUniqueFiles(errors: TSError[]): string[] {\n\treturn [...new Set(errors.map((e) => e.file))];\n}\n\nexport async function checkCommand(flags: string[] = []): Promise<void> {\n\tconst cwd = process.cwd();\n\tconst tsconfigPath = join(cwd, \"tsconfig.json\");\n\tconst isJson = flags.includes(\"--json\");\n\tconst isPlain = flags.includes(\"--plain\");\n\n\tif (!existsSync(tsconfigPath)) {\n\t\tif (isJson) {\n\t\t\tconsole.log(\n\t\t\t\tJSON.stringify({\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: \"tsconfig.json not found. Run `buntok init` first.\",\n\t\t\t\t\terrors: [],\n\t\t\t\t\terrorCount: 0,\n\t\t\t\t\tfileCount: 0,\n\t\t\t\t}),\n\t\t\t);\n\t\t} else {\n\t\t\tconsole.error(\n\t\t\t\t\"\\x1b[31mError: tsconfig.json not found. Run `buntok init` first.\\x1b[0m\",\n\t\t\t);\n\t\t}\n\t\tprocess.exitCode = 1;\n\t\treturn;\n\t}\n\n\tif (!isJson) {\n\t\tif (isPlain) {\n\t\t\tconsole.log(\"  Running type check...\\n\");\n\t\t} else {\n\t\t\tconsole.log(\"\\x1b[36m  Running type check...\\x1b[0m\\n\");\n\t\t}\n\t}\n\n\tconst proc = Bun.spawnSync(\n\t\t[\"bunx\", \"tsc\", \"--noEmit\", \"--pretty\", \"--project\", tsconfigPath],\n\t\t{ cwd },\n\t);\n\n\tconst output = proc.stdout?.toString() || \"\";\n\tconst errors = parseTSErrors(output);\n\tconst files = getUniqueFiles(errors);\n\tconst errorCount = errors.length;\n\tconst fileCount = files.length;\n\n\tif (proc.exitCode === 0) {\n\t\tif (isJson) {\n\t\t\tconsole.log(\n\t\t\t\tJSON.stringify({\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\terrors: [],\n\t\t\t\t\terrorCount: 0,\n\t\t\t\t\tfileCount: 0,\n\t\t\t\t}),\n\t\t\t);\n\t\t} else {\n\t\t\tif (isPlain) {\n\t\t\t\tconsole.log(\"\\n  ✓ No errors found\\n\");\n\t\t\t} else {\n\t\t\t\tconsole.log(\n\t\t\t\t\t`\\n\\x1b[32m  ✓ No errors found\\x1b[0m\\n`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tprocess.exitCode = 0;\n\t\treturn;\n\t}\n\n\t// Errors found\n\tif (isJson) {\n\t\tconsole.log(\n\t\t\tJSON.stringify({\n\t\t\t\tsuccess: false,\n\t\t\t\terrors,\n\t\t\t\terrorCount,\n\t\t\t\tfileCount,\n\t\t\t}),\n\t\t);\n\t} else {\n\t\t// Show errors (limit to 50 for readability)\n\t\tconst maxErrors = 50;\n\t\tconst shownErrors = errors.slice(0, maxErrors);\n\n\t\tfor (const err of shownErrors) {\n\t\t\tconst file = isPlain ? err.file : `\\x1b[36m${err.file}\\x1b[0m`;\n\t\t\tconst line = isPlain ? `${err.line}` : `\\x1b[33m${err.line}\\x1b[0m`;\n\t\t\tconst col = isPlain ? `${err.col}` : `\\x1b[33m${err.col}\\x1b[0m`;\n\t\t\tconst code = isPlain ? err.code : `\\x1b[31m${err.code}\\x1b[0m`;\n\t\t\tconst msg = isPlain ? err.message : `\\x1b[31m${err.message}\\x1b[0m`;\n\n\t\t\tconsole.log(`${file}(${line},${col}): error ${code}: ${msg}`);\n\t\t}\n\n\t\tif (errorCount > maxErrors) {\n\t\t\tconsole.log(\n\t\t\t\t`\\n  ... and ${errorCount - maxErrors} more errors`,\n\t\t\t);\n\t\t}\n\n\t\t// Summary\n\t\tconst fileStr = fileCount === 1 ? \"file\" : \"files\";\n\t\tif (isPlain) {\n\t\t\tconsole.log(\n\t\t\t\t`\\n  ✗ ${errorCount} error${errorCount === 1 ? \"\" : \"s\"} in ${fileCount} ${fileStr}\\n`,\n\t\t\t);\n\t\t} else {\n\t\t\tconsole.log(\n\t\t\t\t`\\n\\x1b[31m  ✗ ${errorCount} error${errorCount === 1 ? \"\" : \"s\"} in ${fileCount} ${fileStr}\\x1b[0m\\n`,\n\t\t\t);\n\t\t}\n\t}\n\n\tprocess.exitCode = proc.exitCode ?? 1;\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { generateBarrel } from \"../generators/barrel.js\";\nimport { generateController } from \"../generators/controller.js\";\nimport { detectORM, type ORM } from \"../generators/repository.js\";\nimport { generateRepository } from \"../generators/repository.js\";\nimport { generateSchemaFile } from \"../generators/schema.js\";\nimport { generateService } from \"../generators/service.js\";\n\ninterface CreateOptions {\n\trepo: boolean;\n\tservice: boolean;\n\tcontroller: boolean;\n\tschema: boolean;\n\tall: boolean;\n\tdryRun: boolean;\n\torm?: ORM;\n}\n\nfunction parseOptions(args: string[]): CreateOptions {\n\tconst options: CreateOptions = {\n\t\trepo: false,\n\t\tservice: false,\n\t\tcontroller: false,\n\t\tschema: false,\n\t\tall: true,\n\t\tdryRun: false,\n\t};\n\n\tfor (const arg of args) {\n\t\tswitch (arg) {\n\t\t\tcase \"--repo\":\n\t\t\t\toptions.repo = true;\n\t\t\t\toptions.all = false;\n\t\t\t\tbreak;\n\t\t\tcase \"--service\":\n\t\t\t\toptions.service = true;\n\t\t\t\toptions.all = false;\n\t\t\t\tbreak;\n\t\t\tcase \"--controller\":\n\t\t\t\toptions.controller = true;\n\t\t\t\toptions.all = false;\n\t\t\t\tbreak;\n\t\t\tcase \"--schema\":\n\t\t\t\toptions.schema = true;\n\t\t\t\toptions.all = false;\n\t\t\t\tbreak;\n\t\t\tcase \"--dry-run\":\n\t\t\t\toptions.dryRun = true;\n\t\t\t\tbreak;\n\t\t\tcase \"--prisma\":\n\t\t\t\toptions.orm = \"prisma\";\n\t\t\t\tbreak;\n\t\t\tcase \"--drizzle\":\n\t\t\t\toptions.orm = \"drizzle\";\n\t\t\t\tbreak;\n\t\t\tcase \"--typeorm\":\n\t\t\t\toptions.orm = \"typeorm\";\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t// If any specific option is set, don't generate all\n\tif (!options.all) {\n\t\treturn options;\n\t}\n\n\t// Generate all by default\n\treturn {\n\t\trepo: true,\n\t\tservice: true,\n\t\tcontroller: true,\n\t\tschema: true,\n\t\tall: false,\n\t\tdryRun: options.dryRun,\n\t\torm: options.orm,\n\t};\n}\n\nfunction toPascalCase(str: string): string {\n\treturn str\n\t\t.split(/[-_]/)\n\t\t.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n\t\t.join(\"\");\n}\n\nexport async function createCommand(entityName: string, args: string[]) {\n\tconst options = parseOptions(args);\n\tconst pascalName = toPascalCase(entityName);\n\tconst orm = options.orm ?? detectORM();\n\tconst moduleDir = join(\"src/modules\", entityName);\n\n\tconst prefix = options.dryRun ? \"\\x1b[33m[DRY RUN]\\x1b[0m \" : \"\";\n\tconsole.log(`\\n${prefix}\\x1b[36mCreating ${pascalName} entity (orm: ${orm})...\\x1b[0m\\n`);\n\n\t// Ensure module directory exists (skip in dry-run)\n\tif (!options.dryRun) {\n\t\tif (!existsSync(moduleDir)) {\n\t\t\tawait fs.mkdir(moduleDir, { recursive: true });\n\t\t}\n\t}\n\n\tconst results: string[] = [];\n\tconst generatedFiles: string[] = [];\n\tconst tasks: Promise<void>[] = [];\n\n\t// Helper to generate file asynchronously\n\tconst generateFile = async (\n\t\tpath: string,\n\t\tcontentGenerator: () => string,\n\t\ttype: string,\n\t) => {\n\t\tif (options.dryRun) {\n\t\t\tconst content = contentGenerator();\n\t\t\tresults.push(`[DRY RUN] ${type}: ${path}`);\n\t\t\tconsole.log(`\\n\\x1b[90m--- ${path} ---\\x1b[0m`);\n\t\t\tconsole.log(content);\n\t\t\tconsole.log(`\\x1b[90m--- end ---\\x1b[0m\\n`);\n\t\t\treturn;\n\t\t}\n\t\tif (!existsSync(path)) {\n\t\t\tawait fs.writeFile(path, contentGenerator());\n\t\t\tresults.push(`✓ ${type}: ${path}`);\n\t\t\tgeneratedFiles.push(path);\n\t\t} else {\n\t\t\tresults.push(`• ${type}: ${path} (already exists)`);\n\t\t}\n\t};\n\n\tif (options.repo) {\n\t\ttasks.push(\n\t\t\tgenerateFile(\n\t\t\t\tjoin(moduleDir, `${entityName}.repository.ts`),\n\t\t\t\t() => generateRepository(entityName, pascalName, orm),\n\t\t\t\t\"Repository\",\n\t\t\t),\n\t\t);\n\t}\n\n\tif (options.service) {\n\t\ttasks.push(\n\t\t\tgenerateFile(\n\t\t\t\tjoin(moduleDir, `${entityName}.service.ts`),\n\t\t\t\t() => generateService(entityName, pascalName, options.repo, orm),\n\t\t\t\t\"Service\",\n\t\t\t),\n\t\t);\n\t}\n\n\tif (options.controller) {\n\t\ttasks.push(\n\t\t\tgenerateFile(\n\t\t\t\tjoin(moduleDir, `${entityName}.controller.ts`),\n\t\t\t\t() => generateController(entityName, pascalName, options.service, orm),\n\t\t\t\t\"Controller\",\n\t\t\t),\n\t\t);\n\t}\n\n\tif (options.schema) {\n\t\tconst schemaPath = join(moduleDir, `${entityName}.schema.ts`);\n\t\tif (!options.dryRun) {\n\t\t\tconst result = await generateSchemaFile(entityName, moduleDir);\n\t\t\tif (result) {\n\t\t\t\tresults.push(`✓ Schema: ${result}`);\n\t\t\t\tgeneratedFiles.push(result);\n\t\t\t} else {\n\t\t\t\tresults.push(`• Schema: ${schemaPath} (already exists)`);\n\t\t\t}\n\t\t} else {\n\t\t\tresults.push(`[DRY RUN] Schema: ${schemaPath}`);\n\t\t}\n\t}\n\n\t// Execute all file generations concurrently\n\tawait Promise.all(tasks);\n\n\t// Generate barrel export (always generate)\n\tconst barrelPath = join(moduleDir, \"index.ts\");\n\tif (!options.dryRun && !existsSync(barrelPath)) {\n\t\tconst barrelContent = generateBarrel(entityName, pascalName, {\n\t\t\trepository: options.repo,\n\t\t\tservice: options.service,\n\t\t\tcontroller: options.controller,\n\t\t\tschema: options.schema,\n\t\t});\n\t\tawait fs.writeFile(barrelPath, barrelContent);\n\t\tresults.push(`✓ Barrel: ${barrelPath}`);\n\t\tgeneratedFiles.push(barrelPath);\n\t} else if (existsSync(barrelPath)) {\n\t\tresults.push(`• Barrel: ${barrelPath} (already exists)`);\n\t}\n\n\t// Auto-format generated files with Biome if available (skip in dry-run)\n\tif (generatedFiles.length > 0 && !options.dryRun) {\n\t\tconst biomeProc = Bun.spawnSync(\n\t\t\t[\"bunx\", \"biome\", \"format\", \"--write\", ...generatedFiles],\n\t\t\t{\n\t\t\t\tstdio: [\"ignore\", \"ignore\", \"ignore\"],\n\t\t\t},\n\t\t);\n\t\tif (biomeProc.exitCode === 0) {\n\t\t\tconsole.log(\n\t\t\t\t\"\\x1b[90m✨ Auto-formatted generated files with Biome\\x1b[0m\\n\",\n\t\t\t);\n\t\t}\n\t}\n\n\t// Auto-register in src/index.ts (skip in dry-run)\n\tconst indexPath = join(\"src\", \"index.ts\");\n\tif (existsSync(indexPath) && !options.dryRun && options.controller) {\n\t\tconst indexContent = readFileSync(indexPath, \"utf-8\");\n\t\tconst controllerName = `${pascalName}Controller`;\n\t\tconst controllerImport = `import { ${controllerName} } from \"@/modules/${entityName}\";`;\n\n\t\t// Determine registration type based on whether controller has @Dependencies\n\t\tconst useContainer = options.service;\n\n\t\t// Check if this controller is already registered\n\t\tconst rcSingleRegex = /app\\.registerController\\((\\w+)\\)\\s*;/;\n\t\tconst rcArrayRegex = /app\\.registerController\\(\\[([^\\]]*)\\]\\)\\s*;/;\n\t\tconst scanRegex = /(?:app\\.getContainer\\(\\)|container)\\.scan\\(\\[([^\\]]*)\\]\\)\\s*;/;\n\n\t\tconst rcSingleMatch = indexContent.match(rcSingleRegex);\n\t\tconst rcArrayMatch = indexContent.match(rcArrayRegex);\n\t\tconst scanMatch = indexContent.match(scanRegex);\n\n\t\tlet alreadyRegistered = false;\n\t\tif (useContainer && scanMatch?.[1]) {\n\t\t\talreadyRegistered = scanMatch[1].includes(controllerName);\n\t\t} else if (!useContainer && rcSingleMatch?.[1]) {\n\t\t\talreadyRegistered = rcSingleMatch[1] === controllerName;\n\t\t} else if (!useContainer && rcArrayMatch?.[1]) {\n\t\t\talreadyRegistered = rcArrayMatch[1].includes(controllerName);\n\t\t}\n\n\t\tif (!alreadyRegistered) {\n\t\t\tlet content = indexContent;\n\n\t\t\t// Helper: find insertion point with fallback chain\n\t\t\tfunction findInsertionIndex(src: string): { index: number; before: string } {\n\t\t\t\t// Pattern 1: app.listen(\n\t\t\t\tconst listenMatch = src.match(/(app\\.listen\\s*\\()/);\n\t\t\t\tif (listenMatch?.index !== undefined && listenMatch[1]) {\n\t\t\t\t\treturn { index: listenMatch.index, before: listenMatch[1] };\n\t\t\t\t}\n\t\t\t\t// Pattern 2: app.get( or app.post( etc (route handlers)\n\t\t\t\tconst routeMatch = src.match(/\\n(app\\.(get|post|put|delete|patch|all|use)\\s*\\()/);\n\t\t\t\tif (routeMatch?.index !== undefined && routeMatch[1]) {\n\t\t\t\t\treturn { index: routeMatch.index + 1, before: routeMatch[1] };\n\t\t\t\t}\n\t\t\t\t// Pattern 3: export default app\n\t\t\t\tconst exportDefaultMatch = src.match(/\\n(export\\s+default\\s+app)/);\n\t\t\t\tif (exportDefaultMatch?.index !== undefined && exportDefaultMatch[1]) {\n\t\t\t\t\treturn { index: exportDefaultMatch.index + 1, before: exportDefaultMatch[1] };\n\t\t\t\t}\n\t\t\t\t// Pattern 4: export const app (insert after)\n\t\t\t\tconst exportConstMatch = src.match(/(export\\s+const\\s+app\\s*=\\s*new\\s+App\\(\\))/);\n\t\t\t\tif (exportConstMatch?.index !== undefined) {\n\t\t\t\t\treturn { index: exportConstMatch.index + exportConstMatch[0].length, before: \"\" };\n\t\t\t\t}\n\t\t\t\t// Fallback: append at end\n\t\t\t\treturn { index: src.length, before: \"\" };\n\t\t\t}\n\n\t\t\t// Helper: add import if missing\n\t\t\tfunction ensureImport(src: string, imp: string): string {\n\t\t\t\tif (src.includes(imp)) return src;\n\t\t\t\tconst lines = src.split(\"\\n\");\n\t\t\t\tlet lastImportIndex = -1;\n\t\t\t\tfor (let i = 0; i < lines.length; i++) {\n\t\t\t\t\tif (lines[i]?.startsWith(\"import \")) {\n\t\t\t\t\t\tlastImportIndex = i;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (lastImportIndex !== -1) {\n\t\t\t\t\tlines.splice(lastImportIndex + 1, 0, imp);\n\t\t\t\t} else {\n\t\t\t\t\tlines.unshift(imp);\n\t\t\t\t}\n\t\t\t\treturn lines.join(\"\\n\");\n\t\t\t}\n\n\t\t\t// Helper: add/merge into existing array\n\t\t\tfunction mergeIntoArray(src: string, regex: RegExp, newController: string): string {\n\t\t\t\tconst match = src.match(regex);\n\t\t\t\tif (match?.[1]) {\n\t\t\t\t\tconst existing = match[1].trim();\n\t\t\t\t\tconst merged = existing ? `${existing}, ${newController}` : newController;\n\t\t\t\t\treturn src.replace(regex, `container.scan([${merged}]);`);\n\t\t\t\t}\n\t\t\t\treturn \"\";\n\t\t\t}\n\n\t\t\t// Helper: collect all imported controllers\n\t\t\t// excludeFromScan: filter out controllers already registered in registerController\n\t\t\tfunction collectImportedControllers(src: string, excludeFromScan: boolean): string[] {\n\t\t\t\tconst imports = src.match(/import\\s*\\{\\s*(\\w+Controller)\\s*\\}\\s*from\\s*[\"']@\\/modules\\/\\w+[\"']/g);\n\t\t\t\tconst controllers: string[] = [];\n\t\t\t\tif (imports) {\n\t\t\t\t\tfor (const imp of imports) {\n\t\t\t\t\t\tconst match = imp.match(/\\{\\s*(\\w+Controller)\\s*\\}/);\n\t\t\t\t\t\tif (match?.[1]) {\n\t\t\t\t\t\t\t// If excludeFromScan, skip controllers already in registerController\n\t\t\t\t\t\t\tif (excludeFromScan) {\n\t\t\t\t\t\t\t\tconst rcSingleMatch = src.match(new RegExp(`app\\\\.registerController\\\\((${match[1]})\\\\)`));\n\t\t\t\t\t\t\t\tconst rcArrayMatch = src.match(new RegExp(`app\\\\.registerController\\\\(\\\\[([^\\\\]]*?${match[1]}[^\\\\]]*?)\\\\]\\\\)`));\n\t\t\t\t\t\t\t\tif (rcSingleMatch || rcArrayMatch) continue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcontrollers.push(match[1]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn controllers;\n\t\t\t}\n\n\t\t\tif (useContainer) {\n\t\t\t\t// === container.scan() + registerController() flow ===\n\n\t\t\t\t// Step 1: Add Container import if missing\n\t\t\t\tconst containerImportRegex = /import\\s*\\{[^}]*Container[^}]*\\}\\s*from\\s*[\"']@buntok\\/core[\"']/;\n\t\t\t\tif (!containerImportRegex.test(content)) {\n\t\t\t\t\t// Add Container to existing @buntok/core import\n\t\t\t\t\tcontent = content.replace(\n\t\t\t\t\t\t/import\\s*\\{([^}]+)\\}\\s*from\\s*[\"']@buntok\\/core[\"']/,\n\t\t\t\t\t\t(_match, imports: string) => {\n\t\t\t\t\t\t\tif (imports.includes(\"Container\")) return _match;\n\t\t\t\t\t\t\treturn `import { ${imports.trim()}, Container } from \"@buntok/core\"`;\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Step 2: Add controller import if missing\n\t\t\t\tcontent = ensureImport(content, controllerImport);\n\n\t\t\t\t// Step 3: Add \"const container = new Container();\" if missing\n\t\t\t\tconst containerDeclRegex = /(?:const|let|var)\\s+container\\s*=\\s*new\\s+Container\\(\\)/;\n\t\t\t\tif (!containerDeclRegex.test(content)) {\n\t\t\t\t\tconst insertAfterApp = content.match(/(const\\s+app\\s*=\\s*new\\s+App\\(\\)\\s*;?)/);\n\t\t\t\t\tif (insertAfterApp?.index !== undefined) {\n\t\t\t\t\t\tconst insertPos = insertAfterApp.index + insertAfterApp[0].length;\n\t\t\t\t\t\tcontent = content.slice(0, insertPos) + \"\\nconst container = new Container();\" + content.slice(insertPos);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Step 4: Add/merge container.scan()\n\t\t\t\tconst existingScan = content.match(scanRegex);\n\t\t\t\tif (existingScan?.[1]) {\n\t\t\t\t\t// Already has scan — merge\n\t\t\t\t\tconst existing = existingScan[1].trim();\n\t\t\t\t\tconst merged = existing ? `${existing}, ${controllerName}` : controllerName;\n\t\t\t\t\tcontent = content.replace(scanRegex, `container.scan([${merged}]);`);\n\t\t\t\t} else {\n\t\t\t\t\t// No scan found — collect all imported @Dependencies controllers and create scan\n\t\t\t\t\tconst allControllers = collectImportedControllers(content, true);\n\t\t\t\t\tif (!allControllers.includes(controllerName)) {\n\t\t\t\t\t\tallControllers.push(controllerName);\n\t\t\t\t\t}\n\t\t\t\t\tconst scanLine = `container.scan([${allControllers.join(\", \")}]);`;\n\t\t\t\t\tconst insertion = findInsertionIndex(content);\n\t\t\t\t\tcontent = content.slice(0, insertion.index) + scanLine + \"\\n\\n\" + content.slice(insertion.index);\n\t\t\t\t}\n\n\t\t\t\t// Step 5: Add app.setContainer(container) if missing\n\t\t\t\tconst setContainerRegex = /app\\.setContainer\\s*\\(\\s*container\\s*\\)\\s*;/;\n\t\t\t\tif (!setContainerRegex.test(content)) {\n\t\t\t\t\tconst insertion = findInsertionIndex(content);\n\t\t\t\t\tcontent = content.slice(0, insertion.index) + \"app.setContainer(container);\\n\\n\" + content.slice(insertion.index);\n\t\t\t\t}\n\n\t\t\t\t// Step 6: Add/merge registerController() — required for API endpoint registration\n\t\t\t\tconst rcSingleNew = content.match(rcSingleRegex);\n\t\t\t\tconst rcArrayNew = content.match(rcArrayRegex);\n\n\t\t\t\tif (rcArrayNew?.[1]) {\n\t\t\t\t\t// Already has array — merge\n\t\t\t\t\tconst existing = rcArrayNew[1].trim();\n\t\t\t\t\tconst merged = existing ? `${existing}, ${controllerName}` : controllerName;\n\t\t\t\t\tcontent = content.replace(rcArrayRegex, `app.registerController([${merged}]);`);\n\t\t\t\t} else if (rcSingleNew?.[1]) {\n\t\t\t\t\t// Has single — convert to array\n\t\t\t\t\tcontent = content.replace(\n\t\t\t\t\t\trcSingleRegex,\n\t\t\t\t\t\t`app.registerController([${rcSingleNew[1]}, ${controllerName}]);`,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\t// No registration — create new\n\t\t\t\t\tconst registerLine = `app.registerController([${controllerName}]);`;\n\t\t\t\t\tconst insertion = findInsertionIndex(content);\n\t\t\t\t\tcontent = content.slice(0, insertion.index) + registerLine + \"\\n\\n\" + content.slice(insertion.index);\n\t\t\t\t}\n\n\t\t\t\tconsole.log(`\\x1b[32m✔ Registered ${controllerName} in container.scan() + registerController()\\x1b[0m`);\n\t\t\t} else {\n\t\t\t\t// === registerController() flow ===\n\n\t\t\t\t// Step 1: Add controller import if missing\n\t\t\t\tcontent = ensureImport(content, controllerImport);\n\n\t\t\t\t// Step 2: Smart registerController merge\n\t\t\t\tconst rcSingleNew = content.match(rcSingleRegex);\n\t\t\t\tconst rcArrayNew = content.match(rcArrayRegex);\n\n\t\t\t\tif (rcArrayNew?.[1]) {\n\t\t\t\t\t// Already has array — merge\n\t\t\t\t\tconst existing = rcArrayNew[1].trim();\n\t\t\t\t\tconst merged = existing ? `${existing}, ${controllerName}` : controllerName;\n\t\t\t\t\tcontent = content.replace(rcArrayRegex, `app.registerController([${merged}]);`);\n\t\t\t\t} else if (rcSingleNew?.[1]) {\n\t\t\t\t\t// Has single — convert to array\n\t\t\t\t\tcontent = content.replace(\n\t\t\t\t\t\trcSingleRegex,\n\t\t\t\t\t\t`app.registerController([${rcSingleNew[1]}, ${controllerName}]);`,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\t// No registration — create new\n\t\t\t\t\tconst registerLine = `app.registerController([${controllerName}]);`;\n\t\t\t\t\tconst insertion = findInsertionIndex(content);\n\t\t\t\t\tcontent = content.slice(0, insertion.index) + registerLine + \"\\n\\n\" + content.slice(insertion.index);\n\t\t\t\t}\n\n\t\t\t\tconsole.log(`\\x1b[32m✔ Registered ${controllerName} in src/index.ts\\x1b[0m`);\n\t\t\t}\n\n\t\t\tawait fs.writeFile(indexPath, content);\n\t\t} else {\n\t\t\tconst location = useContainer ? \"container.scan()\" : \"registerController\";\n\t\t\tconsole.log(\n\t\t\t\t`\\x1b[90m• src/index.ts: ${controllerName} already registered in ${location}\\x1b[0m`,\n\t\t\t);\n\t\t}\n\t}\n\n\t// Print results\n\tconsole.log(options.dryRun ? \"\\x1b[33mWould generate:\\x1b[0m\" : \"\\x1b[32mGenerated files:\\x1b[0m\");\n\tfor (const result of results.sort()) {\n\t\tconsole.log(`  ${result}`);\n\t}\n\n\tif (options.dryRun) {\n\t\tconsole.log(`\\n\\x1b[33mRun without --dry-run to create these files.\\x1b[0m\\n`);\n\t} else {\n\t\tconsole.log(`\n\\x1b[36mNext steps:\\x1b[0m\n  1. Start dev server: \\x1b[33mbun run dev\\x1b[0m\n`);\n\t}\n}\n","function toPascalCase(str: string): string {\n\treturn str\n\t\t.split(/[-_]/)\n\t\t.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n\t\t.join(\"\");\n}\n\nexport function generateBarrel(\n\tname: string,\n\tpascalName: string,\n\toptions: {\n\t\trepository: boolean;\n\t\tservice: boolean;\n\t\tcontroller: boolean;\n\t\tschema: boolean;\n\t},\n): string {\n\tconst exports: string[] = [];\n\n\tif (options.repository) {\n\t\texports.push(`export { ${pascalName}Repository } from \"./${name}.repository\";`);\n\t}\n\n\tif (options.service) {\n\t\texports.push(`export { ${pascalName}Service } from \"./${name}.service\";`);\n\t}\n\n\tif (options.controller) {\n\t\texports.push(`export { ${pascalName}Controller } from \"./${name}.controller\";`);\n\t}\n\n\tif (options.schema) {\n\t\texports.push(\n\t\t\t`export { Create${pascalName}Schema, Update${pascalName}Schema } from \"./${name}.schema\";`,\n\t\t\t`export type { Create${pascalName}Input, Update${pascalName}Input } from \"./${name}.schema\";`,\n\t\t);\n\t}\n\n\treturn exports.join(\"\\n\") + \"\\n\";\n}\n","import type { ORM } from \"./repository.js\";\n\nfunction getPrismaType(pascalName: string): string {\n\treturn `import type { ${pascalName} } from \"@prisma/client\";`;\n}\n\nfunction getDrizzleType(_entityName: string): string {\n\tconst pascalName = _entityName.charAt(0).toUpperCase() + _entityName.slice(1);\n\treturn `import type { InferSelectModel } from \"drizzle-orm\";\nimport { ${_entityName} } from \"@/lib/db/schema\";\n\ntype ${pascalName} = InferSelectModel<typeof ${_entityName}>;`;\n}\n\nfunction getTypeORMType(pascalName: string): string {\n\treturn `import type { ${pascalName} } from \"@/lib/entities/${pascalName}\";`;\n}\n\nexport function generateController(\n\tentityName: string,\n\tpascalName: string,\n\twithService: boolean = true,\n\torm?: ORM,\n): string {\n\tif (withService) {\n\t\tconst detectedOrm = orm ?? \"prisma\";\n\t\tlet typeImport: string;\n\t\tlet typeRef: string;\n\n\t\tswitch (detectedOrm) {\n\t\t\tcase \"drizzle\":\n\t\t\t\ttypeImport = getDrizzleType(entityName);\n\t\t\t\ttypeRef = `${pascalName}`;\n\t\t\t\tbreak;\n\t\t\tcase \"typeorm\":\n\t\t\t\ttypeImport = getTypeORMType(pascalName);\n\t\t\t\ttypeRef = `${pascalName}`;\n\t\t\t\tbreak;\n\t\t\tcase \"prisma\":\n\t\t\tdefault:\n\t\t\t\ttypeImport = getPrismaType(pascalName);\n\t\t\t\ttypeRef = `${pascalName}`;\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn `import { Dependencies, Controller } from \"@buntok/core\";\nimport { BaseController } from \"@buntok/core/base\";\nimport { ${pascalName}Service } from \"./${entityName}.service\";\n${typeImport}\n\n@Dependencies(${pascalName}Service)\n@Controller(\"/${entityName}s\")\nexport class ${pascalName}Controller extends BaseController<${typeRef}> {\n  constructor(private readonly ${entityName}Service: ${pascalName}Service) {\n    super(${entityName}Service);\n  }\n}\n`;\n\t}\n\n\treturn `import { Controller, Get, Post, Put, Delete } from \"@buntok/core\";\nimport type { Context } from \"@buntok/core\";\n\n@Controller(\"/${entityName}s\")\nexport class ${pascalName}Controller {\n  @Get(\"/\")\n  async getAll(ctx: Context) {\n    return ctx.success([], \"Records retrieved successfully\");\n  }\n\n  @Get(\"/:id\")\n  async getById(ctx: Context) {\n    return ctx.success({ id: ctx.params.id }, \"Record retrieved successfully\");\n  }\n\n  @Post(\"/\")\n  async create(ctx: Context) {\n    const data = await ctx.body<any>();\n    return ctx.success(data, \"Record created successfully\", 201);\n  }\n\n  @Put(\"/:id\")\n  async update(ctx: Context) {\n    const data = await ctx.body<any>();\n    return ctx.success({ id: ctx.params.id, ...data }, \"Record updated successfully\");\n  }\n\n  @Delete(\"/:id\")\n  async delete(ctx: Context) {\n    return ctx.success(null, \"Record deleted successfully\");\n  }\n}\n`;\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport type ORM = \"prisma\" | \"drizzle\" | \"typeorm\";\n\n/**\n * Auto-detect ORM from project dependencies\n */\nexport function detectORM(): ORM {\n\tconst pkgPath = join(process.cwd(), \"package.json\");\n\tif (existsSync(pkgPath)) {\n\t\ttry {\n\t\t\tconst pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\"));\n\t\t\tconst deps = { ...pkg.dependencies, ...pkg.devDependencies };\n\n\t\t\tif (deps[\"@prisma/client\"] || deps[\"prisma\"]) {\n\t\t\t\treturn \"prisma\";\n\t\t\t}\n\t\t\tif (deps[\"drizzle-orm\"] || deps[\"drizzle-kit\"]) {\n\t\t\t\treturn \"drizzle\";\n\t\t\t}\n\t\t\tif (deps[\"typeorm\"]) {\n\t\t\t\treturn \"typeorm\";\n\t\t\t}\n\t\t} catch {\n\t\t\t// ignore parse errors\n\t\t}\n\t}\n\n\t// Fallback: check for config files\n\tif (existsSync(join(process.cwd(), \"prisma/schema.prisma\"))) return \"prisma\";\n\tif (existsSync(join(process.cwd(), \"drizzle.config.ts\"))) return \"drizzle\";\n\tif (existsSync(join(process.cwd(), \"ormconfig.json\"))) return \"typeorm\";\n\n\t// Default to Prisma\n\treturn \"prisma\";\n}\n\nfunction generatePrismaRepository(entityName: string, pascalName: string): string {\n\treturn `import { BaseRepository } from \"@buntok/prisma\";\nimport { prisma } from \"@/lib/prisma\";\nimport type { ${pascalName}, Prisma } from \"@prisma/client\";\n\nexport class ${pascalName}Repository extends BaseRepository<\n  ${pascalName},\n  Prisma.${pascalName}CreateInput,\n  Prisma.${pascalName}UpdateInput\n> {\n  constructor() {\n    super(prisma, \"${entityName}\");\n  }\n}\n`;\n}\n\nfunction generateDrizzleRepository(entityName: string, pascalName: string): string {\n\treturn `import { eq } from \"drizzle-orm\";\nimport { db } from \"@/lib/db\";\nimport { ${entityName} } from \"@/lib/db/schema\";\n\nexport class ${pascalName}Repository {\n  async findAll() {\n    return db.select().from(${entityName});\n  }\n\n  async findById(id: number) {\n    const results = await db.select().from(${entityName}).where(eq(${entityName}.id, id));\n    return results[0] ?? null;\n  }\n\n  async create(data: typeof ${entityName}.$inferInsert) {\n    const results = await db.insert(${entityName}).values(data).returning();\n    return results[0];\n  }\n\n  async update(id: number, data: typeof ${entityName}.$inferUpdate) {\n    const results = await db.update(${entityName}).set(data).where(eq(${entityName}.id, id)).returning();\n    return results[0];\n  }\n\n  async delete(id: number) {\n    await db.delete(${entityName}).where(eq(${entityName}.id, id));\n    return true;\n  }\n}\n`;\n}\n\nfunction generateTypeORMRepository(entityName: string, pascalName: string): string {\n\treturn `import { AppDataSource } from \"@/lib/data-source\";\nimport { ${pascalName} } from \"@/lib/entities/${pascalName}\";\n\nexport class ${pascalName}Repository {\n  private repo = AppDataSource.getRepository(${pascalName});\n\n  async findAll() {\n    return this.repo.find();\n  }\n\n  async findById(id: number) {\n    return this.repo.findOneBy({ id });\n  }\n\n  async create(data: Partial<${pascalName}>) {\n    return this.repo.save(this.repo.create(data));\n  }\n\n  async update(id: number, data: Partial<${pascalName}>) {\n    await this.repo.update(id, data);\n    return this.repo.findOneBy({ id });\n  }\n\n  async delete(id: number) {\n    await this.repo.delete(id);\n    return true;\n  }\n}\n`;\n}\n\n/**\n * Generate repository file content based on ORM\n */\nexport function generateRepository(\n\tentityName: string,\n\tpascalName: string,\n\torm?: ORM,\n): string {\n\tconst detectedOrm = orm ?? detectORM();\n\n\tswitch (detectedOrm) {\n\t\tcase \"drizzle\":\n\t\t\treturn generateDrizzleRepository(entityName, pascalName);\n\t\tcase \"typeorm\":\n\t\t\treturn generateTypeORMRepository(entityName, pascalName);\n\t\tcase \"prisma\":\n\t\tdefault:\n\t\t\treturn generatePrismaRepository(entityName, pascalName);\n\t}\n}\n","import { existsSync } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nfunction toPascalCase(str: string): string {\n\treturn str\n\t\t.split(/[-_]/)\n\t\t.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n\t\t.join(\"\");\n}\n\nfunction generateSchema(name: string, pascalName: string): string {\n\treturn `import { z } from \"@buntok/core/middlewares/validator\";\n\nexport const Create${pascalName}Schema = z.object({\n  name: z.string().min(1).max(100),\n  // TODO: Add more fields\n});\n\nexport const Update${pascalName}Schema = Create${pascalName}Schema.partial();\n\nexport type Create${pascalName}Input = z.infer<typeof Create${pascalName}Schema>;\nexport type Update${pascalName}Input = z.infer<typeof Update${pascalName}Schema>;\n`;\n}\n\nexport async function generateSchemaFile(name: string, moduleDir: string): Promise<string | null> {\n\tconst pascalName = toPascalCase(name);\n\tconst filePath = join(moduleDir, `${name}.schema.ts`);\n\n\tif (existsSync(filePath)) {\n\t\treturn null;\n\t}\n\n\tawait fs.writeFile(filePath, generateSchema(name, pascalName));\n\treturn filePath;\n}\n","import type { ORM } from \"./repository.js\";\n\nfunction getPrismaType(pascalName: string): string {\n\treturn `import type { ${pascalName} } from \"@prisma/client\";`;\n}\n\nfunction getDrizzleType(_entityName: string): string {\n\treturn `import type { InferSelectModel } from \"drizzle-orm\";\nimport { ${_entityName} } from \"@/lib/db/schema\";\n\ntype ${_entityName.charAt(0).toUpperCase() + _entityName.slice(1)} = InferSelectModel<typeof ${_entityName}>;`;\n}\n\nfunction getTypeORMType(pascalName: string): string {\n\treturn `import type { ${pascalName} } from \"@/lib/entities/${pascalName}\";`;\n}\n\nexport function generateService(\n\tentityName: string,\n\tpascalName: string,\n\twithRepo: boolean = true,\n\torm?: ORM,\n): string {\n\tif (withRepo) {\n\t\tconst detectedOrm = orm ?? \"prisma\";\n\t\tlet typeImport: string;\n\t\tlet typeRef: string;\n\n\t\tswitch (detectedOrm) {\n\t\t\tcase \"drizzle\":\n\t\t\t\ttypeImport = getDrizzleType(entityName);\n\t\t\t\ttypeRef = `${pascalName}`;\n\t\t\t\tbreak;\n\t\t\tcase \"typeorm\":\n\t\t\t\ttypeImport = getTypeORMType(pascalName);\n\t\t\t\ttypeRef = `${pascalName}`;\n\t\t\t\tbreak;\n\t\t\tcase \"prisma\":\n\t\t\tdefault:\n\t\t\t\ttypeImport = getPrismaType(pascalName);\n\t\t\t\ttypeRef = `${pascalName}`;\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn `import { Dependencies } from \"@buntok/core\";\nimport { BaseService } from \"@buntok/core/base\";\nimport { ${pascalName}Repository } from \"./${entityName}.repository\";\n${typeImport}\n\n@Dependencies(${pascalName}Repository)\nexport class ${pascalName}Service extends BaseService<${typeRef}> {\n  constructor(private readonly ${entityName}Repository: ${pascalName}Repository) {\n    super(${entityName}Repository);\n  }\n}\n`;\n\t}\n\n\treturn `export class ${pascalName}Service {\n  async getAll(): Promise<any[]> {\n    return [];\n  }\n\n  async getById(id: string): Promise<any> {\n    return { id };\n  }\n\n  async create(data: any): Promise<any> {\n    return data;\n  }\n\n  async update(id: string, data: any): Promise<any> {\n    return { id, ...data };\n  }\n\n  async delete(id: string): Promise<boolean> {\n    return true;\n  }\n}\n`;\n}\n","import { execSync } from \"node:child_process\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { createInterface } from \"node:readline\";\n\ntype DbCommand = \"migrate\" | \"seed\" | \"reset\" | \"generate\" | \"studio\" | \"status\";\n\nfunction detectOrm(): \"prisma\" | \"drizzle\" | \"typeorm\" | null {\n\t// Check for Prisma\n\tif (existsSync(\"prisma/schema.prisma\") || existsSync(\"prisma/schema.ts\")) {\n\t\treturn \"prisma\";\n\t}\n\n\t// Check for Drizzle\n\tif (existsSync(\"drizzle.config.ts\") || existsSync(\"drizzle.config.js\")) {\n\t\treturn \"drizzle\";\n\t}\n\n\t// Check for TypeORM\n\tif (existsSync(\"ormconfig.json\") || existsSync(\"ormconfig.ts\") || existsSync(\"ormconfig.js\")) {\n\t\treturn \"typeorm\";\n\t}\n\n\t// Check package.json dependencies\n\tif (existsSync(\"package.json\")) {\n\t\tconst pkg = JSON.parse(readFileSync(\"package.json\", \"utf-8\"));\n\t\tconst allDeps = { ...pkg.dependencies, ...pkg.devDependencies };\n\n\t\tif (allDeps[\"@prisma/client\"] || allDeps[\"prisma\"]) return \"prisma\";\n\t\tif (allDeps[\"drizzle-orm\"] || allDeps[\"drizzle-kit\"]) return \"drizzle\";\n\t\tif (allDeps[\"typeorm\"]) return \"typeorm\";\n\t}\n\n\treturn null;\n}\n\nfunction runCommand(cmd: string, dryRun = false): void {\n\tif (dryRun) {\n\t\tconsole.log(`\\x1b[90m[dry-run] Would execute: ${cmd}\\x1b[0m`);\n\t\treturn;\n\t}\n\tconsole.log(`\\x1b[90m$ ${cmd}\\x1b[0m`);\n\ttry {\n\t\texecSync(cmd, { stdio: \"inherit\", cwd: process.cwd() });\n\t} catch {\n\t\t// Command already printed its error\n\t\tprocess.exitCode = 1;\n\t}\n}\n\nasync function confirm(message: string): Promise<boolean> {\n\tconst rl = createInterface({ input: process.stdin, output: process.stdout });\n\treturn new Promise((resolve) => {\n\t\trl.question(`\\x1b[33m${message} (y/N): \\x1b[0m`, (answer) => {\n\t\t\trl.close();\n\t\t\tresolve(answer.toLowerCase() === \"y\" || answer.toLowerCase() === \"yes\");\n\t\t});\n\t});\n}\n\nfunction prismaCommand(subcommand: string, args: string[], dryRun = false): void {\n\tconst cmd = `npx prisma ${subcommand} ${args.join(\" \")}`.trim();\n\trunCommand(cmd, dryRun);\n}\n\nfunction drizzleCommand(subcommand: string, args: string[], dryRun = false): void {\n\tconst commands: Record<string, string> = {\n\t\tmigrate: \"drizzle-kit generate\",\n\t\tseed: \"drizzle-kit seed\",\n\t\treset: \"drizzle-kit drop\",\n\t\tstatus: \"drizzle-kit check\",\n\t\tgenerate: \"drizzle-kit generate\",\n\t\tstudio: \"drizzle-kit studio\",\n\t};\n\tconst cmd = `${commands[subcommand] ?? subcommand} ${args.join(\" \")}`.trim();\n\trunCommand(cmd, dryRun);\n}\n\nfunction typeormCommand(subcommand: string, args: string[], dryRun = false): void {\n\tconst commands: Record<string, string> = {\n\t\tmigrate: \"typeorm migration:run\",\n\t\tseed: \"typeorm seed\",\n\t\treset: \"typeorm migration:revert\",\n\t\tgenerate: \"typeorm migration:generate\",\n\t\tstatus: \"typeorm migration:show\",\n\t\tstudio: \"echo 'TypeORM does not have a built-in studio command'\",\n\t};\n\tconst cmd = `${commands[subcommand] ?? subcommand} ${args.join(\" \")}`.trim();\n\trunCommand(cmd, dryRun);\n}\n\nfunction printUsage(): void {\n\tconsole.log(`\n\\x1b[36mUsage:\\x1b[0m\n  buntok db <command> [args] [flags]\n\n\\x1b[36mCommands:\\x1b[0m\n  migrate [name]      Run pending migrations\n  seed                Seed database\n  reset               Reset database (drop & recreate)\n  generate            Generate migration from schema changes\n  studio              Open database GUI\n  status              Show migration status\n\n\\x1b[36mFlags:\\x1b[0m\n  --dry-run           Preview command without executing\n\n\\x1b[36mSupported ORMs:\\x1b[0m\n  Prisma, Drizzle, TypeORM (auto-detected)\n\n\\x1b[36mExamples:\\x1b[0m\n  buntok db migrate                    # Run pending migrations\n  buntok db migrate add user_table     # Create new migration\n  buntok db seed                       # Seed database\n  buntok db studio                     # Open Prisma Studio / etc\n  buntok db reset --dry-run            # Preview reset command\n`);\n}\n\nconst DESTRUCTIVE_COMMANDS: DbCommand[] = [\"reset\"];\n\nexport async function dbCommand(args: string[]): Promise<void> {\n\tconst subcommand = args[0] as DbCommand | undefined;\n\n\tif (!subcommand) {\n\t\tprintUsage();\n\t\treturn;\n\t}\n\n\tconst validCommands: DbCommand[] = [\"migrate\", \"seed\", \"reset\", \"generate\", \"studio\", \"status\"];\n\tif (!validCommands.includes(subcommand)) {\n\t\tconsole.error(`\\x1b[31mUnknown command: ${subcommand}\\x1b[0m`);\n\t\tprintUsage();\n\t\tprocess.exitCode = 1;\n\t\treturn;\n\t}\n\n\tconst orm = detectOrm();\n\tif (!orm) {\n\t\tconsole.error(\"\\x1b[31mCould not detect ORM.\\x1b[0m\");\n\t\tconsole.error(\"Supported: Prisma, Drizzle, TypeORM\");\n\t\tconsole.error(\"Make sure you have one installed in package.json.\");\n\t\tprocess.exitCode = 1;\n\t\treturn;\n\t}\n\n\tconst dryRun = args.includes(\"--dry-run\");\n\tconst subArgs = args.slice(1).filter((a) => a !== \"--dry-run\");\n\n\tconsole.log(`\\x1b[36mDetected ORM: ${orm}\\x1b[0m`);\n\n\t// Confirmation for destructive commands\n\tif (DESTRUCTIVE_COMMANDS.includes(subcommand) && !dryRun) {\n\t\tconst confirmed = await confirm(\n\t\t\t`\\x1b[31mWARNING: This will ${subcommand} the database. Continue?\\x1b[0m`,\n\t\t);\n\t\tif (!confirmed) {\n\t\t\tconsole.log(\"\\x1b[90mAborted.\\x1b[0m\");\n\t\t\treturn;\n\t\t}\n\t}\n\n\tswitch (orm) {\n\t\tcase \"prisma\":\n\t\t\tprismaCommand(subcommand, subArgs, dryRun);\n\t\t\tbreak;\n\t\tcase \"drizzle\":\n\t\t\tdrizzleCommand(subcommand, subArgs, dryRun);\n\t\t\tbreak;\n\t\tcase \"typeorm\":\n\t\t\ttypeormCommand(subcommand, subArgs, dryRun);\n\t\t\tbreak;\n\t}\n}\n","import { resolve } from \"node:path\";\nimport { existsSync } from \"node:fs\";\nimport { pathToFileURL } from \"node:url\";\n\nfunction getMethodColor(method: string): string {\n\tswitch (method) {\n\t\tcase \"GET\": return \"\\x1b[32m\";    // green\n\t\tcase \"POST\": return \"\\x1b[33m\";   // yellow\n\t\tcase \"PUT\": return \"\\x1b[34m\";    // blue\n\t\tcase \"PATCH\": return \"\\x1b[35m\";  // magenta\n\t\tcase \"DELETE\": return \"\\x1b[31m\"; // red\n\t\tcase \"OPTIONS\": return \"\\x1b[36m\"; // cyan\n\t\tcase \"HEAD\": return \"\\x1b[37m\";   // white\n\t\tdefault: return \"\\x1b[37m\";      // white\n\t}\n}\n\nfunction printRouteTable(routes: any[]): void {\n\tif (routes.length === 0) {\n\t\tconsole.log(\"\\x1b[33mNo routes found.\\x1b[0m\");\n\t\treturn;\n\t}\n\n\t// Calculate column widths\n\tconst methodWidth = Math.max(6, ...routes.map((r: any) => r.method.length));\n\tconst pathWidth = Math.max(4, ...routes.map((r: any) => r.path.length));\n\tconst mwWidth = Math.max(11, ...routes.map((r: any) => {\n\t\tconst mw = (r.middlewares || []).join(\", \");\n\t\treturn mw.length > 40 ? 40 : mw.length;\n\t}));\n\tconst handlerWidth = Math.max(7, ...routes.map((r: any) => (r.handler || \"anonymous\").length));\n\n\t// Print header\n\tconst header = [\n\t\t\"Method\".padEnd(methodWidth),\n\t\t\"Path\".padEnd(pathWidth),\n\t\t\"Middlewares\".padEnd(mwWidth),\n\t\t\"Handler\".padEnd(handlerWidth),\n\t].join(\" │ \");\n\n\tconst separator = [\n\t\t\"─\".repeat(methodWidth),\n\t\t\"─\".repeat(pathWidth),\n\t\t\"─\".repeat(mwWidth),\n\t\t\"─\".repeat(handlerWidth),\n\t].join(\"─┼─\");\n\n\tconsole.log(`\\x1b[1m${header}\\x1b[0m`);\n\tconsole.log(separator);\n\n\t// Print rows\n\tfor (const route of routes) {\n\t\tconst methodColor = getMethodColor(route.method);\n\t\tconst mwStr = (route.middlewares || []).length > 0 ? route.middlewares.join(\", \") : \"—\";\n\t\tconst truncatedMw = mwStr.length > 40 ? mwStr.slice(0, 37) + \"...\" : mwStr;\n\n\t\tconst row = [\n\t\t\t`${methodColor}${route.method.padEnd(methodWidth)}\\x1b[0m`,\n\t\t\troute.path.padEnd(pathWidth),\n\t\t\ttruncatedMw.padEnd(mwWidth),\n\t\t\t(route.handler || \"anonymous\").padEnd(handlerWidth),\n\t\t].join(\" │ \");\n\n\t\tconsole.log(row);\n\t}\n\n\t// Print summary\n\tconsole.log(`\\n\\x1b[36m${routes.length} routes registered\\x1b[0m`);\n}\n\nfunction printSourceSummary(routes: any[]): void {\n\tconst bySource: Record<string, any[]> = {};\n\tfor (const route of routes) {\n\t\tconst key = route.controller || route.group || route.source || \"direct\";\n\t\tif (!bySource[key]) bySource[key] = [];\n\t\tbySource[key].push(route);\n\t}\n\n\tconst sources = Object.keys(bySource);\n\tif (sources.length <= 1) return;\n\n\tconsole.log(`\\n\\x1b[36mBy source:\\x1b[0m`);\n\tfor (const source of sources) {\n\t\tconst count = bySource[source]?.length ?? 0;\n\t\tconsole.log(`  ${source}: ${count} routes`);\n\t}\n}\n\nexport async function debugRoutesCommand(flags: string[]): Promise<void> {\n\tconst isJson = flags.includes(\"--json\");\n\tconst targetDir = process.cwd();\n\n\t// Find the user's app entry point\n\tconst possibleFiles = [\n\t\t\"src/index.ts\",\n\t\t\"src/main.ts\",\n\t\t\"src/app.ts\",\n\t\t\"src/server.ts\",\n\t];\n\n\tlet entryFile: string | null = null;\n\tfor (const file of possibleFiles) {\n\t\tconst filePath = resolve(targetDir, file);\n\t\tif (existsSync(filePath)) {\n\t\t\tentryFile = filePath;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (!entryFile) {\n\t\tconsole.error(\"\\x1b[31mError: Could not find app entry point (src/index.ts, src/main.ts, src/app.ts, or src/server.ts)\\x1b[0m\");\n\t\tprocess.exitCode = 1;\n\t\treturn;\n\t}\n\n\ttry {\n\t\t// Import the user's app to trigger route registration\n\t\tconst fileUrl = pathToFileURL(entryFile).href;\n\t\tconst mod = await import(fileUrl);\n\n\t\t// Find the app instance — check default export and named exports\n\t\tlet app: any = null;\n\t\tif (mod.default && mod.default.routeDebugInfo) {\n\t\t\tapp = mod.default;\n\t\t} else {\n\t\t\t// Search all exports for an app-like object\n\t\t\tfor (const key of Object.keys(mod)) {\n\t\t\t\tif (mod[key] && mod[key].routeDebugInfo) {\n\t\t\t\t\tapp = mod[key];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!app) {\n\t\t\tconsole.error(\"\\x1b[31mError: Could not find App instance with routeDebugInfo. Make sure your entry point exports a Buntok App instance.\\x1b[0m\");\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\n\t\tconst routes = app.routeDebugInfo || [];\n\n\t\tif (isJson) {\n\t\t\tconsole.log(JSON.stringify(routes, null, 2));\n\t\t} else {\n\t\t\tprintRouteTable(routes);\n\t\t\tprintSourceSummary(routes);\n\t\t}\n\t} catch (err: any) {\n\t\tconsole.error(`\\x1b[31mError importing app: ${err.message}\\x1b[0m`);\n\t\tif (err.stack) {\n\t\t\tconsole.error(`\\x1b[90m${err.stack}\\x1b[0m`);\n\t\t}\n\t\tprocess.exitCode = 1;\n\t}\n}\n","import { resolve } from \"node:path\";\nimport { existsSync } from \"node:fs\";\n\nexport async function devCommand(flags: string[]): Promise<void> {\n\tconst isExpose = flags.includes(\"--expose\");\n\tconst port = flags.find(f => f.startsWith(\"--port=\"))?.split(\"=\")[1] || \"1212\";\n\n\tconst targetDir = process.cwd();\n\n\t// Find the user's entry point\n\tconst possibleFiles = [\n\t\t\"server.ts\",\n\t\t\"src/index.ts\",\n\t\t\"src/main.ts\",\n\t\t\"src/app.ts\",\n\t\t\"src/server.ts\",\n\t];\n\n\tlet entryFile: string | null = null;\n\tfor (const file of possibleFiles) {\n\t\tconst filePath = resolve(targetDir, file);\n\t\tif (existsSync(filePath)) {\n\t\t\tentryFile = filePath;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (!entryFile) {\n\t\tconsole.error(\"\\x1b[31mError: Could not find app entry point (server.ts, src/index.ts, src/main.ts, src/app.ts, or src/server.ts)\\x1b[0m\");\n\t\tprocess.exitCode = 1;\n\t\treturn;\n\t}\n\n\t// Build dev command\n\tconst args = [\"--watch\", entryFile];\n\tconst env: Record<string, string> = {\n\t\t...process.env as Record<string, string>,\n\t\tNODE_ENV: \"development\",\n\t\tPORT: port,\n\t};\n\n\tif (isExpose) {\n\t\t// Install localtunnel if not present\n\t\tconsole.log(\"\\x1b[36mStarting development server with tunnel...\\x1b[0m\\n\");\n\n\t\ttry {\n\t\t\t// Try to import localtunnel\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: optional dynamic import\n\t\t\tconst lt = await import(\"localtunnel\" as string);\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: optional dynamic import\n\t\t\tconst tunnel = await (lt as any).default({\n\t\t\t\tport: Number.parseInt(port),\n\t\t\t\tsubdomain: `buntok-${Date.now()}`,\n\t\t\t});\n\n\t\t\tconsole.log(`\\x1b[32m  Server running at http://localhost:${port}\\x1b[0m`);\n\t\t\tconsole.log(`\\x1b[36m  Tunnel: ${tunnel.url} → http://localhost:${port}\\x1b[0m`);\n\t\t\tconsole.log(`\\n  Press Ctrl+C to stop\\n`);\n\n\t\t\t// Spawn the dev server\n\t\t\tconst proc = Bun.spawn([\"bun\", \"run\", ...args], {\n\t\t\t\tstdio: [\"inherit\", \"inherit\", \"inherit\"],\n\t\t\t\tenv,\n\t\t\t\tcwd: targetDir,\n\t\t\t});\n\n\t\t\t// Handle cleanup\n\t\t\tconst cleanup = async () => {\n\t\t\t\tproc.kill();\n\t\t\t\tawait tunnel.close();\n\t\t\t\tprocess.exit(0);\n\t\t\t};\n\n\t\t\tprocess.on(\"SIGINT\", cleanup);\n\t\t\tprocess.on(\"SIGTERM\", cleanup);\n\n\t\t\tawait proc.exited;\n\t\t} catch (err: any) {\n\t\t\tif (err.message?.includes(\"Cannot find module\") || err.code === \"ERR_MODULE_NOT_FOUND\") {\n\t\t\t\tconsole.error(\"\\x1b[31mError: localtunnel is required for --expose flag\\x1b[0m\");\n\t\t\t\tconsole.error(\"Install it with: \\x1b[36mbun add -d localtunnel\\x1b[0m\");\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthrow err;\n\t\t}\n\t} else {\n\t\t// Regular dev mode\n\t\tconsole.log(`\\x1b[36mStarting development server...\\x1b[0m\\n`);\n\t\tconsole.log(`\\x1b[32m  Server running at http://localhost:${port}\\x1b[0m`);\n\t\tconsole.log(`\\n  Press Ctrl+C to stop\\n`);\n\n\t\tconst proc = Bun.spawn([\"bun\", \"run\", ...args], {\n\t\t\tstdio: [\"inherit\", \"inherit\", \"inherit\"],\n\t\t\tenv,\n\t\t\tcwd: targetDir,\n\t\t});\n\n\t\tawait proc.exited;\n\t}\n}\n","import { existsSync, readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { execSync } from \"node:child_process\";\nimport { createInterface } from \"node:readline\";\n\nconst __dirname = import.meta.dir;\n\nfunction askQuestion(question: string, defaultValue = true): Promise<boolean> {\n\treturn new Promise((resolve) => {\n\t\tconst rl = createInterface({\n\t\t\tinput: process.stdin,\n\t\t\toutput: process.stdout,\n\t\t});\n\n\t\trl.question(question, (answer) => {\n\t\t\trl.close();\n\t\t\tconst normalized = answer.trim().toLowerCase();\n\t\t\tif (normalized === \"\") return resolve(defaultValue);\n\t\t\tresolve(normalized === \"y\" || normalized === \"yes\");\n\t\t});\n\t});\n}\n\nconst REQUIRED_SCRIPTS: Record<string, string> = {\n\tdev: \"bun --watch server.ts\",\n\tbuild: \"bunx buntok build\",\n\tstart: \"bun .buntok/server.js\",\n\tcheck: \"bunx @biomejs/biome check --write .\",\n\tformat: \"bunx @biomejs/biome format --write .\",\n\tlint: \"bunx @biomejs/biome lint .\",\n};\n\nconst BIOME_CONFIG = {\n\tvcs: {\n\t\tenabled: true,\n\t\tclientKind: \"git\",\n\t\tuseIgnoreFile: true,\n\t},\n\tfiles: {\n\t\tignoreUnknown: true,\n\t\tincludes: [\"**\", \"!**/node_modules\", \"!**/dist\", \"!**/.buntok\", \"!**/coverage\"],\n\t},\n\tformatter: {\n\t\tenabled: true,\n\t\tindentStyle: \"tab\",\n\t\tindentWidth: 2,\n\t\tlineWidth: 100,\n\t\tlineEnding: \"lf\",\n\t},\n\tlinter: {\n\t\tenabled: true,\n\t\trules: {\n\t\t\tpreset: \"recommended\",\n\t\t\tcorrectness: {\n\t\t\t\tnoUnusedImports: {\n\t\t\t\t\tlevel: \"warn\",\n\t\t\t\t\tfix: \"safe\",\n\t\t\t\t},\n\t\t\t},\n\t\t\tsuspicious: {\n\t\t\t\tnoExplicitAny: \"off\",\n\t\t\t},\n\t\t},\n\t},\n\tjavascript: {\n\t\tformatter: {\n\t\t\tquoteStyle: \"double\",\n\t\t\ttrailingCommas: \"all\",\n\t\t},\n\t},\n};\n\n\nconst TSCONFIG_TEMPLATE = {\n\tcompilerOptions: {\n\t\t// Environment setup & latest features\n\t\tlib: [\"ESNext\"],\n\t\ttarget: \"ESNext\",\n\t\tmodule: \"Preserve\",\n\t\tmoduleDetection: \"force\",\n\t\tjsx: \"react-jsx\",\n\t\tallowJs: true,\n\t\ttypes: [\"bun\", \"node\"],\n\n\t\t// Bundler mode\n\t\tmoduleResolution: \"bundler\",\n\t\tallowImportingTsExtensions: true,\n\t\tverbatimModuleSyntax: true,\n\t\tnoEmit: true,\n\n\t\t// Strictness Options for TS 7+\n\t\tstrict: true,\n\t\tnoUncheckedIndexedAccess: true,\n\t\texactOptionalPropertyTypes: true,\n\t\tnoImplicitOverride: true,\n\t\tnoFallthroughCasesInSwitch: true,\n\t\tisolatedModules: true,\n\t\tskipLibCheck: true,\n\n\t\t// Path alias\n\t\tpaths: {\n\t\t\t\"@/*\": [\"./src/*\"],\n\t\t},\n\t},\n\tinclude: [\"src/**/*\"],\n\texclude: [\"node_modules\", \".buntok\"],\n};\n\nconst VSCODE_SETTINGS = {\n\t\"editor.formatOnSave\": true,\n\t\"editor.defaultFormatter\": \"biomejs.biome\",\n\t\"editor.codeActionsOnSave\": {\n\t\t\"source.fixAll.biome\": \"explicit\",\n\t\t\"source.organizeImports.biome\": \"explicit\",\n\t},\n\t\"[javascript]\": {\n\t\t\"editor.defaultFormatter\": \"biomejs.biome\",\n\t},\n\t\"[typescript]\": {\n\t\t\"editor.defaultFormatter\": \"biomejs.biome\",\n\t},\n\t\"[typescriptreact]\": {\n\t\t\"editor.defaultFormatter\": \"biomejs.biome\",\n\t},\n\t\"[json]\": {\n\t\t\"editor.defaultFormatter\": \"biomejs.biome\",\n\t},\n\t\"[jsonc]\": {\n\t\t\"editor.defaultFormatter\": \"biomejs.biome\",\n\t},\n\t\"[html]\": {\n\t\t\"editor.defaultFormatter\": \"biomejs.biome\",\n\t},\n\t\"[css]\": {\n\t\t\"editor.defaultFormatter\": \"biomejs.biome\",\n\t},\n};\n\nconst INDEX_TEMPLATE = `import { App } from \"@buntok/core\";\nimport \"./env\";\n\nexport const app = new App();\n\napp.get(\"/\", (ctx) => {\n  return ctx.json({ message: \"Hello from Buntok!\" });\n});\n`;\n\nconst ENV_TS_TEMPLATE = `import { App } from \"@buntok/core\";\nimport { z } from \"@buntok/core/middlewares/validator\";\n\nexport const env = App.validateEnv({\n\tPORT: z.coerce.number().default(1212),\n\tAUTH_STORE: z.enum([\"header\", \"cookie\"]).default(\"header\"),\n\tAUTH_COOKIE: z.string().default(\"session\"),\n\tNODE_ENV: z.enum([\"development\", \"production\", \"test\"]).default(\"development\"),\n});\n`;\n\nfunction findSkillMdSource(): string | null {\n\t// 1. Relative path (works when running from @buntok/core package)\n\tconst relativePath = join(\n\t\t__dirname,\n\t\t\"..\",\n\t\t\"..\",\n\t\t\"scripts\",\n\t\t\"buntok-skill\",\n\t\t\"SKILL.md\",\n\t);\n\tif (existsSync(relativePath)) return relativePath;\n\n\t// 2. Resolve from @buntok/core package (works when running from buntok CLI)\n\ttry {\n\t\t// biome-ignore lint: dynamic import for package resolution\n\t\tconst pkgJson = require.resolve(\"@buntok/core/package.json\");\n\t\tconst pkgDir = dirname(pkgJson);\n\t\tconst skillPath = join(pkgDir, \"scripts\", \"buntok-skill\", \"SKILL.md\");\n\t\tif (existsSync(skillPath)) return skillPath;\n\t} catch {\n\t\t// package not found\n\t}\n\n\treturn null;\n}\n\nfunction copySkillMd(projectRoot: string): boolean {\n\tconst sourceSkill = findSkillMdSource();\n\n\tif (!sourceSkill) {\n\t\tconsole.warn(\n\t\t\t\"\\x1b[33m⚠ SKILL.md not found in @buntok/core, skipping.\\x1b[0m\",\n\t\t);\n\t\treturn false;\n\t}\n\n\tconst skillDir = join(projectRoot, \".agents\", \"skills\", \"buntok-skill\");\n\tconst destSkill = join(skillDir, \"SKILL.md\");\n\n\tif (!existsSync(skillDir)) {\n\t\tmkdirSync(skillDir, { recursive: true });\n\t}\n\n\twriteFileSync(destSkill, readFileSync(sourceSkill, \"utf-8\"), \"utf-8\");\n\tconsole.log(`\\x1b[32m✓ Created\\x1b[0m .agents/skills/buntok-skill/SKILL.md`);\n\treturn true;\n}\n\nfunction updatePackageJson(projectRoot: string): boolean {\n\tconst pkgPath = join(projectRoot, \"package.json\");\n\n\tlet pkg: { name?: string; scripts?: Record<string, string>; devDependencies?: Record<string, string> };\n\tif (existsSync(pkgPath)) {\n\t\tpkg = JSON.parse(readFileSync(pkgPath, \"utf-8\"));\n\t} else {\n\t\tconst folderName = projectRoot.split(\"/\").pop() || \"my-app\";\n\t\tpkg = { name: folderName, scripts: {}, devDependencies: {} };\n\t}\n\n\tif (!pkg.scripts) pkg.scripts = {};\n\n\tlet added = 0;\n\tfor (const [key, value] of Object.entries(REQUIRED_SCRIPTS)) {\n\t\tif (!pkg.scripts[key]) {\n\t\t\tpkg.scripts[key] = value;\n\t\t\tadded++;\n\t\t}\n\t}\n\n\tif (added === 0) {\n\t\tconsole.log(\"\\x1b[90m• package.json: all scripts already present\\x1b[0m\");\n\t\treturn false;\n\t}\n\n\twriteFileSync(pkgPath, JSON.stringify(pkg, null, 2) + \"\\n\", \"utf-8\");\n\tconsole.log(`\\x1b[32m✓ Updated\\x1b[0m package.json (added ${added} scripts)`);\n\treturn true;\n}\n\nfunction stripJsonComments(text: string): string {\n\t// Remove single-line comments (// ...) but not inside strings\n\treturn text.replace(/(?<![\"':].*)\\/\\/.*$/gm, \"\");\n}\n\nfunction setupTsconfig(projectRoot: string): boolean {\n\tconst tsconfigPath = join(projectRoot, \"tsconfig.json\");\n\n\tif (existsSync(tsconfigPath)) {\n\t\t// Merge paths into existing tsconfig\n\t\tconst raw = readFileSync(tsconfigPath, \"utf-8\");\n\t\tconst existing = JSON.parse(stripJsonComments(raw));\n\t\tif (!existing.compilerOptions) existing.compilerOptions = {};\n\t\tif (!existing.compilerOptions.paths) {\n\t\t\texisting.compilerOptions.paths = { \"@/*\": [\"./src/*\"] };\n\t\t\twriteFileSync(tsconfigPath, JSON.stringify(existing, null, 2) + \"\\n\", \"utf-8\");\n\t\t\tconsole.log(\"\\x1b[32m✓ Updated\\x1b[0m tsconfig.json (added path alias)\");\n\t\t\treturn true;\n\t\t}\n\t\tif (!existing.compilerOptions.paths[\"@/*\"]) {\n\t\t\texisting.compilerOptions.paths[\"@/*\"] = [\"./src/*\"];\n\t\t\twriteFileSync(tsconfigPath, JSON.stringify(existing, null, 2) + \"\\n\", \"utf-8\");\n\t\t\tconsole.log(\"\\x1b[32m✓ Updated\\x1b[0m tsconfig.json (added path alias)\");\n\t\t\treturn true;\n\t\t}\n\t\tconsole.log(\"\\x1b[90m• tsconfig.json: path alias already present\\x1b[0m\");\n\t\treturn false;\n\t}\n\n\t// Create new tsconfig\n\twriteFileSync(tsconfigPath, JSON.stringify(TSCONFIG_TEMPLATE, null, 2) + \"\\n\", \"utf-8\");\n\tconsole.log(\"\\x1b[32m✓ Created\\x1b[0m tsconfig.json\");\n\treturn true;\n}\n\nfunction setupBiome(projectRoot: string): boolean {\n\tconst biomePath = join(projectRoot, \"biome.json\");\n\n\tif (existsSync(biomePath)) {\n\t\tconsole.log(\"\\x1b[90m• biome.json: already exists, skipping\\x1b[0m\");\n\t\treturn false;\n\t}\n\n\t// Check if @biomejs/biome is installed\n\tconst pkgPath = join(projectRoot, \"package.json\");\n\tlet needsInstall = false;\n\tif (existsSync(pkgPath)) {\n\t\tconst pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\"));\n\t\tconst allDeps = {\n\t\t\t...pkg.dependencies,\n\t\t\t...pkg.devDependencies,\n\t\t};\n\t\tneedsInstall = !allDeps[\"@biomejs/biome\"];\n\t}\n\n\tif (needsInstall) {\n\t\tconsole.log(\"\\x1b[90m• Installing @biomejs/biome...\\x1b[0m\");\n\t\ttry {\n\t\t\texecSync(\"bun add -d @biomejs/biome\", {\n\t\t\t\tcwd: projectRoot,\n\t\t\t\tstdio: \"ignore\",\n\t\t\t});\n\t\t\tconsole.log(\"\\x1b[32m✓ Installed\\x1b[0m @biomejs/biome\");\n\t\t} catch {\n\t\t\tconsole.warn(\n\t\t\t\t\"\\x1b[33m⚠ Failed to install @biomejs/biome, please install manually\\x1b[0m\",\n\t\t\t);\n\t\t}\n\t}\n\n\twriteFileSync(biomePath, JSON.stringify(BIOME_CONFIG, null, 2) + \"\\n\", \"utf-8\");\n\tconsole.log(\"\\x1b[32m✓ Created\\x1b[0m biome.json\");\n\treturn true;\n}\n\nfunction createIndexFile(projectRoot: string): boolean {\n\tconst srcDir = join(projectRoot, \"src\");\n\tconst indexPath = join(srcDir, \"index.ts\");\n\n\tif (existsSync(indexPath)) {\n\t\tconsole.log(\"\\x1b[90m• src/index.ts: already exists, skipping\\x1b[0m\");\n\t\treturn false;\n\t}\n\n\tif (!existsSync(srcDir)) {\n\t\tmkdirSync(srcDir, { recursive: true });\n\t}\n\n\twriteFileSync(indexPath, INDEX_TEMPLATE, \"utf-8\");\n\tconsole.log(\"\\x1b[32m✓ Created\\x1b[0m src/index.ts\");\n\treturn true;\n}\n\nfunction createEnvTsFile(projectRoot: string): boolean {\n\tconst srcDir = join(projectRoot, \"src\");\n\tconst envTsPath = join(srcDir, \"env.ts\");\n\n\tif (existsSync(envTsPath)) {\n\t\tconsole.log(\"\\x1b[90m• src/env.ts: already exists, skipping\\x1b[0m\");\n\t\treturn false;\n\t}\n\n\tif (!existsSync(srcDir)) {\n\t\tmkdirSync(srcDir, { recursive: true });\n\t}\n\n\twriteFileSync(envTsPath, ENV_TS_TEMPLATE, \"utf-8\");\n\tconsole.log(\"\\x1b[32m✓ Created\\x1b[0m src/env.ts\");\n\treturn true;\n}\n\nfunction setupVscode(projectRoot: string): boolean {\n\tconst vscodeDir = join(projectRoot, \".vscode\");\n\tconst settingsPath = join(vscodeDir, \"settings.json\");\n\n\tif (existsSync(settingsPath)) {\n\t\tconsole.log(\"\\x1b[90m• .vscode/settings.json: already exists, skipping\\x1b[0m\");\n\t\treturn false;\n\t}\n\n\tif (!existsSync(vscodeDir)) {\n\t\tmkdirSync(vscodeDir, { recursive: true });\n\t}\n\n\twriteFileSync(settingsPath, JSON.stringify(VSCODE_SETTINGS, null, 2) + \"\\n\", \"utf-8\");\n\tconsole.log(\"\\x1b[32m✓ Created\\x1b[0m .vscode/settings.json\");\n\treturn true;\n}\n\nconst ENV_CONTENT = `# Buntok Configuration\nPORT=1212\nAUTH_STORE=header\nAUTH_COOKIE=session\n`;\n\nconst ENV_EXAMPLE_CONTENT = `# Buntok Configuration\n#\n# PORT: port is using for the app\n# AUTH_STORE: Where to store/read JWT tokens\n#   - \"header\" (default): Read from Authorization: Bearer <token> header\n#   - \"cookie\": Read from HttpOnly cookie (set AUTH_COOKIE for cookie name)\n#\n# AUTH_COOKIE: Cookie name for JWT storage (only used when AUTH_STORE=cookie)\n#\nPORT=1212\nAUTH_STORE=header\nAUTH_COOKIE=session\n`;\n\nconst VERCEL_JSON_TEMPLATE = {\n\t$schema: \"https://openapi.vercel.sh/vercel.json\",\n\tframework: \"bun\",\n\tbunVersion: \"1.4.x\",\n};\n\nconst SERVER_TS_TEMPLATE = `import { app } from \"./src/index\";\nimport { env } from \"./src/env\";\n\napp.listen(env.PORT);\n`;\n\nconst GITIGNORE_CONTENT = `# Dependencies\nnode_modules/\n\n# Build output\n.buntok/\n\n# Environment\n.env\n.env.local\n.env.*.local\n\n# IDE\n.vscode/\n.idea/\n*.swp\n*.swo\n*~\npublic/swagger.json\n\n# OS\n.DS_Store\nThumbs.db\n\n# Buntok\n.buntok/\n\n# Logs\n*.log\nnpm-debug.log*\n\n# Coverage\ncoverage/\n`;\n\nconst DOCKERFILE_TEMPLATE = `# Builder\nFROM oven/bun:1-alpine AS builder\nWORKDIR /app\n\nCOPY package.json bun.lock* ./\nRUN bun install --frozen-lockfile --production\n\nCOPY src/ src/\nCOPY server.ts ./\nCOPY tsconfig.json ./\nCOPY package.json ./\n\nRUN bunx buntok build\n\n# Production\nFROM oven/bun:1-alpine\nWORKDIR /app\n\nCOPY --from=builder /app/.buntok .buntok\nCOPY --from=builder /app/node_modules node_modules\nCOPY --from=builder /app/package.json ./\n\nEXPOSE 1212\n\nENV NODE_ENV=production\nENV PORT=1212\n\nCMD [\"bun\", \".buntok/server.js\"]\n`;\n\nconst DOCKERIGNORE_CONTENT = `node_modules\ndist\n.buntok\n*.log\n.env\n.env.*\ncoverage\n`;\n\nfunction createEnvFiles(projectRoot: string): boolean {\n\tconst envPath = join(projectRoot, \".env\");\n\tconst envExamplePath = join(projectRoot, \".env.example\");\n\tlet created = false;\n\n\tif (!existsSync(envPath)) {\n\t\twriteFileSync(envPath, ENV_CONTENT, \"utf-8\");\n\t\tconsole.log(\"\\x1b[32m✓ Created\\x1b[0m .env\");\n\t\tcreated = true;\n\t} else {\n\t\tconsole.log(\"\\x1b[90m• .env: already exists, skipping\\x1b[0m\");\n\t}\n\n\tif (!existsSync(envExamplePath)) {\n\t\twriteFileSync(envExamplePath, ENV_EXAMPLE_CONTENT, \"utf-8\");\n\t\tconsole.log(\"\\x1b[32m✓ Created\\x1b[0m .env.example\");\n\t\tcreated = true;\n\t} else {\n\t\tconsole.log(\"\\x1b[90m• .env.example: already exists, skipping\\x1b[0m\");\n\t}\n\n\treturn created;\n}\n\nfunction createGitignore(projectRoot: string): boolean {\n\tconst gitignorePath = join(projectRoot, \".gitignore\");\n\n\tif (existsSync(gitignorePath)) {\n\t\tconsole.log(\"\\x1b[90m• .gitignore: already exists, skipping\\x1b[0m\");\n\t\treturn false;\n\t}\n\n\twriteFileSync(gitignorePath, GITIGNORE_CONTENT, \"utf-8\");\n\tconsole.log(\"\\x1b[32m✓ Created\\x1b[0m .gitignore\");\n\treturn true;\n}\n\nfunction createVercelJson(projectRoot: string): boolean {\n\tconst vercelPath = join(projectRoot, \"vercel.json\");\n\n\tif (existsSync(vercelPath)) {\n\t\tconsole.log(\"\\x1b[90m• vercel.json: already exists, skipping\\x1b[0m\");\n\t\treturn false;\n\t}\n\n\twriteFileSync(vercelPath, JSON.stringify(VERCEL_JSON_TEMPLATE, null, 2) + \"\\n\", \"utf-8\");\n\tconsole.log(\"\\x1b[32m✓ Created\\x1b[0m vercel.json\");\n\n\t// Create empty public/ directory (Vercel requires it for static files)\n\tconst publicDir = join(projectRoot, \"public\");\n\tif (!existsSync(publicDir)) {\n\t\tmkdirSync(publicDir, { recursive: true });\n\t\twriteFileSync(join(publicDir, \".gitkeep\"), \"\");\n\t}\n\n\treturn true;\n}\n\nfunction createServerTsFile(projectRoot: string): boolean {\n\tconst serverPath = join(projectRoot, \"server.ts\");\n\n\tif (existsSync(serverPath)) {\n\t\tconsole.log(\"\\x1b[90m• server.ts: already exists, skipping\\x1b[0m\");\n\t\treturn false;\n\t}\n\n\twriteFileSync(serverPath, SERVER_TS_TEMPLATE, \"utf-8\");\n\tconsole.log(\"\\x1b[32m✓ Created\\x1b[0m server.ts\");\n\treturn true;\n}\n\nfunction updateDevScript(projectRoot: string): boolean {\n\tconst pkgPath = join(projectRoot, \"package.json\");\n\tif (!existsSync(pkgPath)) return false;\n\n\tconst pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\"));\n\tif (!pkg.scripts) return false;\n\n\tif (pkg.scripts.dev === \"bun --watch src/index.ts\") {\n\t\tpkg.scripts.dev = \"bun --watch server.ts\";\n\t\twriteFileSync(pkgPath, JSON.stringify(pkg, null, 2) + \"\\n\", \"utf-8\");\n\t\tconsole.log(\"\\x1b[32m✓ Updated\\x1b[0m package.json (dev → server.ts)\");\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\nfunction createDockerfile(projectRoot: string): boolean {\n\tconst dockerfilePath = join(projectRoot, \"Dockerfile\");\n\tconst dockerignorePath = join(projectRoot, \".dockerignore\");\n\n\tlet created = false;\n\n\tif (!existsSync(dockerfilePath)) {\n\t\twriteFileSync(dockerfilePath, DOCKERFILE_TEMPLATE, \"utf-8\");\n\t\tconsole.log(\"\\x1b[32m✓ Created\\x1b[0m Dockerfile\");\n\t\tcreated = true;\n\t} else {\n\t\tconsole.log(\"\\x1b[90m• Dockerfile: already exists, skipping\\x1b[0m\");\n\t}\n\n\tif (!existsSync(dockerignorePath)) {\n\t\twriteFileSync(dockerignorePath, DOCKERIGNORE_CONTENT, \"utf-8\");\n\t\tconsole.log(\"\\x1b[32m✓ Created\\x1b[0m .dockerignore\");\n\t\tcreated = true;\n\t} else {\n\t\tconsole.log(\"\\x1b[90m• .dockerignore: already exists, skipping\\x1b[0m\");\n\t}\n\n\treturn created;\n}\n\nexport async function initCommand() {\n\tconst projectRoot = process.cwd();\n\n\tcopySkillMd(projectRoot);\n\tupdatePackageJson(projectRoot);\n\tsetupTsconfig(projectRoot);\n\tsetupBiome(projectRoot);\n\tsetupVscode(projectRoot);\n\tcreateEnvTsFile(projectRoot);\n\tcreateIndexFile(projectRoot);\n\tcreateEnvFiles(projectRoot);\n\tcreateGitignore(projectRoot);\n\tupdateDevScript(projectRoot);\n\n\tconst vercelPath = join(projectRoot, \"vercel.json\");\n\tif (!existsSync(vercelPath)) {\n\t\tconsole.log(\"\");\n\t\tconst useVercel = await askQuestion(\n\t\t\t\"\\x1b[36mDo you want to deploy to Vercel? (y/N): \\x1b[0m\",\n\t\t\tfalse,\n\t\t);\n\t\tif (useVercel) {\n\t\t\tcreateVercelJson(projectRoot);\n\t\t}\n\t} else {\n\t\tconsole.log(\"\\x1b[90m• vercel.json: already exists, skipping\\x1b[0m\");\n\t}\n\n\tcreateServerTsFile(projectRoot);\n\n\tconst dockerfilePath = join(projectRoot, \"Dockerfile\");\n\tif (!existsSync(dockerfilePath)) {\n\t\tconsole.log(\"\");\n\t\tconst useDocker = await askQuestion(\n\t\t\t\"\\x1b[36mDo you want to add Docker support? (Y/n): \\x1b[0m\",\n\t\t\ttrue,\n\t\t);\n\t\tif (useDocker) {\n\t\t\tcreateDockerfile(projectRoot);\n\t\t}\n\t} else {\n\t\tconsole.log(\"\\x1b[90m• Dockerfile: already exists, skipping\\x1b[0m\");\n\t}\n}\n","import { mkdirSync, writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { generateOpenApiDocument } from \"../../helpers/openapi\";\n\nexport async function makeDocsCommand() {\n\tconsole.log(\"\\x1b[36mGenerating OpenAPI documentation...\\x1b[0m\");\n\n\t// Prevent the user's app from starting its HTTP server during import\n\tprocess.env.BUNTOK_DOCS_BUILD = \"1\";\n\n\tconst entryPath = resolve(process.cwd(), \"src/index.ts\");\n\n\ttry {\n\t\tconsole.log(`\\x1b[90mLoading app from ${entryPath}...\\x1b[0m`);\n\n\t\tconst userApp = await import(entryPath);\n\t\tconst appInstance = userApp.app || userApp.default;\n\n\t\tif (!appInstance?.openApiDocs) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Could not find an exported 'app' instance in src/index.ts. Make sure you export your app: `export const app = new App();`\",\n\t\t\t);\n\t\t}\n\n\t\tconst docsConfig = appInstance._apiDocsConfig;\n\n\t\tconst document = generateOpenApiDocument({\n\t\t\topenApiDocs: appInstance.openApiDocs,\n\t\t\ttitle: docsConfig?.title,\n\t\t\tversion: docsConfig?.version,\n\t\t\tdescription: docsConfig?.description,\n\t\t});\n\n\t\tif (!document) {\n\t\t\tconsole.warn(\n\t\t\t\t\"\\x1b[33m  ⚠ No routes with OpenAPI metadata found. Add zValidator() or zResponse() to your routes.\\x1b[0m\",\n\t\t\t);\n\t\t\tprocess.exit(0);\n\t\t}\n\n\t\t// Output directory: public/docs/\n\t\tconst docsDir = resolve(process.cwd(), \"public/docs\");\n\t\tmkdirSync(docsDir, { recursive: true });\n\n\t\tconst swaggerPath = resolve(docsDir, \"swagger.json\");\n\t\twriteFileSync(swaggerPath, JSON.stringify(document, null, 2));\n\t\tconsole.log(\n\t\t\t`\\x1b[32m✔ swagger.json generated at public/docs/swagger.json\\x1b[0m`,\n\t\t);\n\n\t\tprocess.exit(0);\n\t} catch (error) {\n\t\tconsole.error(\"\\x1b[31mFailed to generate docs:\\x1b[0m\");\n\t\tconsole.error(error);\n\t\tprocess.exit(1);\n\t}\n}\n","import { resolve, join } from \"node:path\";\nimport { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { toPascalCase, toSnakeCase } from \"../utils.js\";\n\nfunction generateFactoryTemplate(entityName: string): string {\n\tconst className = toPascalCase(entityName) + \"Factory\";\n\tconst interfaceName = toPascalCase(entityName);\n\n\treturn `import { Factory } from \"@buntok/core/factory\";\nimport { faker } from \"@faker-js/faker\";\nimport type { ${interfaceName} } from \"@prisma/client\";\n\nexport const ${className} = Factory.define<${interfaceName}>(() => ({\n  // TODO: Define your factory fields here\n  // Example:\n  // id: faker.number.int({ max: 10000 }),\n  // name: faker.person.fullName(),\n  // email: faker.internet.email(),\n  // role: faker.helpers.arrayElement([\"user\", \"admin\"]),\n}));\n`;\n}\n\nexport async function makeFactoryCommand(entityName: string, flags: string[]): Promise<void> {\n\tconst targetDir = process.cwd();\n\tconst isDryRun = flags.includes(\"--dry-run\");\n\n\t// Resolve paths\n\tconst modulesDir = resolve(targetDir, \"src\", \"modules\");\n\tconst factoryDir = resolve(targetDir, \"src\", \"factories\");\n\n\t// Ensure factories directory exists\n\tif (!existsSync(factoryDir)) {\n\t\tif (!isDryRun) {\n\t\t\tmkdirSync(factoryDir, { recursive: true });\n\t\t}\n\t\tconsole.log(`Created directory: src/factories/`);\n\t}\n\n\tconst fileName = `${toSnakeCase(entityName)}.factory.ts`;\n\tconst filePath = join(factoryDir, fileName);\n\tconst content = generateFactoryTemplate(entityName);\n\n\tif (isDryRun) {\n\t\tconsole.log(`\\n\\x1b[36m[DRY RUN] Would create:\\x1b[0m`);\n\t\tconsole.log(`  ${filePath}`);\n\t\tconsole.log(`\\n\\x1b[36mContent:\\x1b[0m`);\n\t\tconsole.log(content);\n\t\treturn;\n\t}\n\n\t// Check if file already exists\n\tif (existsSync(filePath)) {\n\t\tconsole.error(`\\x1b[31mError: Factory file already exists: ${filePath}\\x1b[0m`);\n\t\tprocess.exitCode = 1;\n\t\treturn;\n\t}\n\n\t// Write factory file\n\twriteFileSync(filePath, content, \"utf-8\");\n\tconsole.log(`Created: src/factories/${fileName}`);\n\n\t// Print usage hint\n\tconst className = toPascalCase(entityName) + \"Factory\";\n\tconsole.log(`\\n\\x1b[36mUsage:\\x1b[0m`);\n\tconsole.log(`  import { ${className} } from \"@/factories/${fileName.replace(\".ts\", \"\")}\";`);\n\tconsole.log(``);\n\tconsole.log(`  const user = await ${className}.create();`);\n\tconsole.log(`  const users = await ${className}.createMany(10);`);\n\tconsole.log(`  const admin = await ${className}.create({ role: \"admin\" });`);\n}\n","export function toSnakeCase(str: string): string {\n\treturn str\n\t\t.replace(/([A-Z])/g, \"_$1\")\n\t\t.toLowerCase()\n\t\t.replace(/^_/, \"\")\n\t\t.replace(/-/g, \"_\");\n}\n\nexport function toPascalCase(str: string): string {\n\treturn str\n\t\t.split(/[-_]/)\n\t\t.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n\t\t.join(\"\");\n}\n","import { existsSync } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nfunction toPascalCase(str: string): string {\n\treturn str\n\t\t.split(/[-_]/)\n\t\t.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n\t\t.join(\"\");\n}\n\nfunction generateMiddleware(_name: string, pascalName: string): string {\n\treturn `import type { Context, Middleware } from \"@buntok/core\";\n\nexport const ${pascalName}Middleware: Middleware = async (ctx: Context, next: () => Promise<Response> | Response) => {\n  const start = performance.now();\n\n  const response = await next();\n\n  const end = performance.now();\n  const url = new URL(ctx.request.url);\n  console.log(\\`[\\${ctx.request.method}] \\${url.pathname} - \\${Math.round(end - start)}ms\\`);\n\n  return response;\n}\n`;\n}\n\nexport async function makeMiddlewareCommand(name: string, flags: string[] = []) {\n\tconst pascalName = toPascalCase(name);\n\tconst dryRun = flags.includes(\"--dry-run\");\n\tconsole.log(`\\n\\x1b[36mCreating ${pascalName} Middleware${dryRun ? \" (dry-run)\" : \"\"}...\\x1b[0m\\n`);\n\n\tconst middlewaresDir = \"src/middlewares\";\n\n\tif (!existsSync(middlewaresDir)) {\n\t\tif (dryRun) {\n\t\t\tconsole.log(`\\x1b[90mWould create directory: ${middlewaresDir}\\x1b[0m`);\n\t\t} else {\n\t\t\tawait fs.mkdir(middlewaresDir, { recursive: true });\n\t\t}\n\t}\n\n\tconst filePath = join(middlewaresDir, `${name}.middleware.ts`);\n\n\tif (existsSync(filePath)) {\n\t\tconsole.error(\n\t\t\t`\\x1b[31mError: Middleware file already exists at ${filePath}\\x1b[0m`,\n\t\t);\n\t\tprocess.exitCode = 1;\n\t\treturn;\n\t}\n\n\tconst content = generateMiddleware(name, pascalName);\n\n\tif (dryRun) {\n\t\tconsole.log(`\\x1b[90mWould create file: ${filePath}\\x1b[0m`);\n\t\tconsole.log(`\\n\\x1b[36m--- Generated content ---\\x1b[0m\\n`);\n\t\tconsole.log(content);\n\t\treturn;\n\t}\n\n\tawait fs.writeFile(filePath, content);\n\n\t// Auto-format generated file with Biome if available\n\tconst biomeProc = Bun.spawnSync(\n\t\t[\"bunx\", \"biome\", \"format\", \"--write\", filePath],\n\t\t{\n\t\t\tstdio: [\"ignore\", \"ignore\", \"ignore\"],\n\t\t},\n\t);\n\n\tif (biomeProc.exitCode === 0) {\n\t\tconsole.log(\"\\x1b[90m✨ Auto-formatted generated file with Biome\\x1b[0m\");\n\t}\n\n\tconsole.log(`\\x1b[32m✓ Generated middleware:\\x1b[0m ${filePath}`);\n\n\tconsole.log(`\n\\x1b[36mUsage:\\x1b[0m\n  Import and apply it globally in src/index.ts:\n     \\x1b[32mapp.use(${pascalName}Middleware);\\x1b[0m\n\n  Or apply it to a specific controller:\n     \\x1b[32m@Use(${pascalName}Middleware)\\x1b[0m\n     \\x1b[32mexport class MyController { ... }\\x1b[0m\n`);\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { detectORM, type ORM } from \"../generators/repository.js\";\n\nfunction toPascalCase(str: string): string {\n\treturn str\n\t\t.split(/[-_]/)\n\t\t.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n\t\t.join(\"\");\n}\n\nfunction generatePrismaSeeder(name: string, pascalName: string, useFactory: boolean): string {\n\tif (useFactory) {\n\t\treturn `import { prisma } from \"@/lib/prisma\";\nimport { ${pascalName}Factory } from \"@/factories/${name}.factory\";\n\nexport async function seed${pascalName}() {\n  console.log(\"Seeding ${pascalName}...\");\n\n  const items = ${pascalName}Factory.buildMany(100);\n  await prisma.${name}.createMany({ data: items });\n\n  console.log(\"✓ ${pascalName} seeded successfully (100 records)\");\n}\n`;\n\t}\n\treturn `import { prisma } from \"@/lib/prisma\";\n\nexport async function seed${pascalName}() {\n  console.log(\"Seeding ${pascalName}...\");\n\n  // TODO: Insert your dummy data here\n  // await prisma.${name}.createMany({\n  //   data: [\n  //     { name: \"Dummy 1\" },\n  //     { name: \"Dummy 2\" },\n  //   ],\n  // });\n\n  console.log(\"✓ ${pascalName} seeded successfully\");\n}\n`;\n}\n\nfunction generateDrizzleSeeder(name: string, pascalName: string, useFactory: boolean): string {\n\tif (useFactory) {\n\t\treturn `import { db } from \"@/lib/db\";\nimport { ${name} } from \"@/lib/db/schema\";\nimport { ${pascalName}Factory } from \"@/factories/${name}.factory\";\n\nexport async function seed${pascalName}() {\n  console.log(\"Seeding ${pascalName}...\");\n\n  const items = ${pascalName}Factory.buildMany(100);\n  await db.insert(${name}).values(items);\n\n  console.log(\"✓ ${pascalName} seeded successfully (100 records)\");\n}\n`;\n\t}\n\treturn `import { db } from \"@/lib/db\";\nimport { ${name} } from \"@/lib/db/schema\";\n\nexport async function seed${pascalName}() {\n  console.log(\"Seeding ${pascalName}...\");\n\n  // TODO: Insert your dummy data here\n  // await db.insert(${name}).values([\n  //   { name: \"Dummy 1\" },\n  //   { name: \"Dummy 2\" },\n  // ]);\n\n  console.log(\"✓ ${pascalName} seeded successfully\");\n}\n`;\n}\n\nfunction generateTypeORMSeeder(name: string, pascalName: string, useFactory: boolean): string {\n\tif (useFactory) {\n\t\treturn `import { AppDataSource } from \"@/lib/data-source\";\nimport { ${pascalName} } from \"@/lib/entities/${pascalName}\";\nimport { ${pascalName}Factory } from \"@/factories/${name}.factory\";\n\nexport async function seed${pascalName}() {\n  console.log(\"Seeding ${pascalName}...\");\n\n  const repo = AppDataSource.getRepository(${pascalName});\n  const items = ${pascalName}Factory.buildMany(100);\n  await repo.save(items.map(item => repo.create(item)));\n\n  console.log(\"✓ ${pascalName} seeded successfully (100 records)\");\n}\n`;\n\t}\n\treturn `import { AppDataSource } from \"@/lib/data-source\";\nimport { ${pascalName} } from \"@/lib/entities/${pascalName}\";\n\nexport async function seed${pascalName}() {\n  console.log(\"Seeding ${pascalName}...\");\n\n  const repo = AppDataSource.getRepository(${pascalName});\n\n  // TODO: Insert your dummy data here\n  // await repo.save(repo.create({ name: \"Dummy 1\" }));\n  // await repo.save(repo.create({ name: \"Dummy 2\" }));\n\n  console.log(\"✓ ${pascalName} seeded successfully\");\n}\n`;\n}\n\nfunction generateSeeder(name: string, pascalName: string, orm: ORM, useFactory: boolean): string {\n\tswitch (orm) {\n\t\tcase \"drizzle\":\n\t\t\treturn generateDrizzleSeeder(name, pascalName, useFactory);\n\t\tcase \"typeorm\":\n\t\t\treturn generateTypeORMSeeder(name, pascalName, useFactory);\n\t\tcase \"prisma\":\n\t\tdefault:\n\t\t\treturn generatePrismaSeeder(name, pascalName, useFactory);\n\t}\n}\n\nexport async function makeSeederCommand(name: string, flags: string[] = []) {\n\tconst pascalName = toPascalCase(name);\n\tconst orm = detectORM();\n\tconst useFactory = flags.includes(\"--factory\");\n\tconst dryRun = flags.includes(\"--dry-run\");\n\tconsole.log(`\\n\\x1b[36mScaffolding Seeder for ${pascalName} (orm: ${orm}${useFactory ? \", using factory\" : \"\"}${dryRun ? \", dry-run\" : \"\"})...\\x1b[0m\\n`);\n\n\tconst seederDir = \"src/db/seeders\";\n\n\tif (!existsSync(seederDir)) {\n\t\tif (dryRun) {\n\t\t\tconsole.log(`\\x1b[90mWould create directory: ${seederDir}\\x1b[0m`);\n\t\t} else {\n\t\t\tawait fs.mkdir(seederDir, { recursive: true });\n\t\t}\n\t}\n\n\tconst filePath = join(seederDir, `${name}.seeder.ts`);\n\n\tif (existsSync(filePath)) {\n\t\tconsole.error(\n\t\t\t`\\x1b[31mError: Seeder file already exists at ${filePath}\\x1b[0m`,\n\t\t);\n\t\tprocess.exitCode = 1;\n\t\treturn;\n\t}\n\n\tconst content = generateSeeder(name, pascalName, orm, useFactory);\n\n\tif (dryRun) {\n\t\tconsole.log(`\\x1b[90mWould create file: ${filePath}\\x1b[0m`);\n\t\tconsole.log(`\\n\\x1b[36m--- Generated content ---\\x1b[0m\\n`);\n\t\tconsole.log(content);\n\t\treturn;\n\t}\n\n\tawait fs.writeFile(filePath, content);\n\n\tconst biomeProc = Bun.spawnSync(\n\t\t[\"bunx\", \"biome\", \"format\", \"--write\", filePath],\n\t\t{\n\t\t\tstdio: [\"ignore\", \"ignore\", \"ignore\"],\n\t\t},\n\t);\n\n\tif (biomeProc.exitCode === 0) {\n\t\tconsole.log(\n\t\t\t\"\\x1b[90m✨ Auto-formatted generated seeder file with Biome\\x1b[0m\",\n\t\t);\n\t}\n\n\tconsole.log(`\\x1b[32m✓ Generated seeder:\\x1b[0m ${filePath}`);\n\n\tif (useFactory) {\n\t\t// Check if factory file exists\n\t\tconst factoryPath = `src/factories/${name}.factory.ts`;\n\t\tif (!existsSync(factoryPath)) {\n\t\t\tconsole.log(`\\n\\x1b[33m⚠ Warning: Factory file not found at ${factoryPath}\\x1b[0m`);\n\t\t\tconsole.log(`  Run \\x1b[36mbuntok make:factory ${name}\\x1b[0m to create it first.`);\n\t\t}\n\t}\n}\n","import { existsSync } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nfunction toPascalCase(str: string): string {\n\treturn str\n\t\t.split(/[-_]/)\n\t\t.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n\t\t.join(\"\");\n}\n\nfunction generateTest(name: string, pascalName: string): string {\n\treturn `import { describe, it, expect, beforeEach, mock } from \"bun:test\";\nimport { ${pascalName}Service } from \"@/modules/${name}/${name}.service\";\nimport { ${pascalName}Repository } from \"@/modules/${name}/${name}.repository\";\n\ndescribe(\"${pascalName}Service\", () => {\n  let service: ${pascalName}Service;\n  let mockRepo: any;\n\n  beforeEach(() => {\n    // 1. Mock the repository layer\n    mockRepo = {\n      findAll: mock(() => Promise.resolve([])),\n      findById: mock((id: number) => Promise.resolve({ id, name: \"Test ${pascalName}\" })),\n      create: mock((data: any) => Promise.resolve({ id: 1, ...data })),\n      update: mock((id: number, data: any) => Promise.resolve({ id, ...data })),\n      delete: mock((id: number) => Promise.resolve({ id })),\n    };\n\n    // 2. Inject mock repo into the service\n    service = new ${pascalName}Service(mockRepo as unknown as ${pascalName}Repository);\n  });\n\n  it(\"should be defined\", () => {\n    expect(service).toBeDefined();\n  });\n\n  it(\"should return an array of items\", async () => {\n    const result = await service.findAll();\n    expect(result).toBeInstanceOf(Array);\n    expect(mockRepo.findAll).toHaveBeenCalledTimes(1);\n  });\n\n  it(\"should return a single item by id\", async () => {\n    const result = await service.findById(1);\n    expect(result).toHaveProperty(\"id\", 1);\n    expect(result).toHaveProperty(\"name\", \"Test ${pascalName}\");\n    expect(mockRepo.findById).toHaveBeenCalledWith(1);\n  });\n\n  // TODO: Add more business logic tests here\n});\n`;\n}\n\nexport async function makeTestCommand(name: string, flags: string[] = []) {\n\tconst pascalName = toPascalCase(name);\n\tconst dryRun = flags.includes(\"--dry-run\");\n\tconsole.log(`\\n\\x1b[36mScaffolding Unit Test for ${pascalName}${dryRun ? \" (dry-run)\" : \"\"}...\\x1b[0m\\n`);\n\n\tconst testsDir = \"tests\";\n\n\tif (!existsSync(testsDir)) {\n\t\tif (dryRun) {\n\t\t\tconsole.log(`\\x1b[90mWould create directory: ${testsDir}\\x1b[0m`);\n\t\t} else {\n\t\t\tawait fs.mkdir(testsDir, { recursive: true });\n\t\t}\n\t}\n\n\tconst filePath = join(testsDir, `${name}.spec.ts`);\n\n\tif (existsSync(filePath)) {\n\t\tconsole.error(\n\t\t\t`\\x1b[31mError: Test file already exists at ${filePath}\\x1b[0m`,\n\t\t);\n\t\tprocess.exitCode = 1;\n\t\treturn;\n\t}\n\n\tconst content = generateTest(name, pascalName);\n\n\tif (dryRun) {\n\t\tconsole.log(`\\x1b[90mWould create file: ${filePath}\\x1b[0m`);\n\t\tconsole.log(`\\n\\x1b[36m--- Generated content ---\\x1b[0m\\n`);\n\t\tconsole.log(content);\n\t\treturn;\n\t}\n\n\tawait fs.writeFile(filePath, content);\n\n\t// Auto-format generated file with Biome if available\n\tconst biomeProc = Bun.spawnSync(\n\t\t[\"bunx\", \"biome\", \"format\", \"--write\", filePath],\n\t\t{\n\t\t\tstdio: [\"ignore\", \"ignore\", \"ignore\"],\n\t\t},\n\t);\n\n\tif (biomeProc.exitCode === 0) {\n\t\tconsole.log(\n\t\t\t\"\\x1b[90m✨ Auto-formatted generated test file with Biome\\x1b[0m\",\n\t\t);\n\t}\n\n\tconsole.log(`\\x1b[32m✓ Generated test suite:\\x1b[0m ${filePath}`);\n\n\tconsole.log(`\n\\x1b[36mNext steps:\\x1b[0m\n  Run your test suite instantly using Bun's native test runner:\n     \\x1b[33mbun test\\x1b[0m\n     \\x1b[33mbun test --watch\\x1b[0m  (For TDD / Live Reload)\n`);\n}\n","import { existsSync } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nfunction toPascalCase(str: string): string {\n\treturn str\n\t\t.split(/[-_]/)\n\t\t.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n\t\t.join(\"\");\n}\n\nfunction generateE2ETest(name: string, pascalName: string): string {\n\treturn `import { describe, it, expect } from \"bun:test\";\nimport { app } from \"@/index\";\n\ndescribe(\"${pascalName} API (E2E)\", () => {\n  it(\"should return a list of items (GET /${name}s)\", async () => {\n    const response = await app.request(\"/${name}s\", {\n      method: \"GET\",\n    });\n\n    expect(response.status).toBe(200);\n\n    // const body = await response.json();\n    // expect(Array.isArray(body)).toBe(true);\n  });\n\n  it(\"should create a new item (POST /${name}s)\", async () => {\n    const response = await app.request(\"/${name}s\", {\n      method: \"POST\",\n      headers: {\n        \"Content-Type\": \"application/json\",\n      },\n      body: JSON.stringify({\n        // TODO: add payload here\n      }),\n    });\n\n    // expect(response.status).toBe(201);\n  });\n\n  it(\"should handle not found items (GET /${name}s/999999)\", async () => {\n    const response = await app.request(\"/${name}s/999999\", {\n      method: \"GET\",\n    });\n\n    // expect(response.status).toBe(404);\n  });\n});\n`;\n}\n\nexport async function makeTestE2ECommand(name: string) {\n\tconst pascalName = toPascalCase(name);\n\tconsole.log(\n\t\t`\\n\\x1b[36mScaffolding E2E Test for ${pascalName} API...\\x1b[0m\\n`,\n\t);\n\n\tconst testsDir = \"tests/e2e\";\n\n\tif (!existsSync(testsDir)) {\n\t\tawait fs.mkdir(testsDir, { recursive: true });\n\t}\n\n\tconst filePath = join(testsDir, `${name}.e2e.spec.ts`);\n\n\tif (existsSync(filePath)) {\n\t\tconsole.error(\n\t\t\t`\\x1b[31mError: E2E Test file already exists at ${filePath}\\x1b[0m`,\n\t\t);\n\t\tprocess.exitCode = 1;\n\t\treturn;\n\t}\n\n\tconst content = generateE2ETest(name, pascalName);\n\tawait fs.writeFile(filePath, content);\n\n\t// Auto-format generated file with Biome if available\n\tconst biomeProc = Bun.spawnSync(\n\t\t[\"bunx\", \"biome\", \"format\", \"--write\", filePath],\n\t\t{\n\t\t\tstdio: [\"ignore\", \"ignore\", \"ignore\"],\n\t\t},\n\t);\n\n\tif (biomeProc.exitCode === 0) {\n\t\tconsole.log(\n\t\t\t\"\\x1b[90m✨ Auto-formatted generated E2E test file with Biome\\x1b[0m\",\n\t\t);\n\t}\n\n\tconsole.log(`\\x1b[32m✓ Generated E2E test suite:\\x1b[0m ${filePath}`);\n\n\tconsole.log(`\n\\x1b[36mNext steps:\\x1b[0m\n  Run all E2E tests:\n     \\x1b[33mbun test tests/e2e\\x1b[0m\n`);\n}\n","#!/usr/bin/env bun\n\nimport { buildCommand } from \"./commands/build.js\";\nimport { checkCommand } from \"./commands/check.js\";\nimport { createCommand } from \"./commands/create.js\";\nimport { dbCommand } from \"./commands/db.js\";\nimport { debugRoutesCommand } from \"./commands/debug-routes.js\";\nimport { devCommand } from \"./commands/dev.js\";\nimport { initCommand } from \"./commands/init.js\";\nimport { makeDocsCommand } from \"./commands/make-docs.js\";\nimport { makeFactoryCommand } from \"./commands/make-factory.js\";\nimport { makeMiddlewareCommand } from \"./commands/make-middleware.js\";\nimport { makeSeederCommand } from \"./commands/make-seeder.js\";\nimport { makeTestCommand } from \"./commands/make-test.js\";\nimport { makeTestE2ECommand } from \"./commands/make-test-e2e.js\";\nimport { VERSION } from \"../core-exports.js\";\n\nfunction printBanner() {\n\tconsole.log(`\n\\x1b[36m  Buntok CLI v${VERSION}\\x1b[0m\n`);\n}\n\nfunction printUsage() {\n\tconsole.log(`\n\\x1b[36mUsage:\\x1b[0m\n  buntok <command> [arguments] [options]\n\n\\x1b[36mCommands:\\x1b[0m\n  init                   Setup project: copy SKILL.md + configure package.json + generate env.ts\n  dev                    Start development server with hot reload\n  build                  Build project for production (output → .buntok/)\n  check                  Run TypeScript type check\n  create <entity>        Generate all files for entity (repo, service, controller, schema)\n  db <command>           Database operations (migrate, seed, reset, generate, studio, status)\n  debug:routes           Show all registered routes with middleware chains\n  make:docs              Generate OpenAPI documentation automatically\n  make:factory <entity>  Generate data factory for entity\n  make:test <entity>     Generate unit test for entity\n  make:test:e2e <entity> Generate E2E test for entity\n  make:seeder <entity>   Generate database seeder for entity\n  make:middleware <name>  Generate middleware file\n\n\\x1b[36mOptions (for create command):\\x1b[0m\n  --repo                 Generate only repository\n  --service              Generate only service\n  --controller           Generate only controller\n  --schema               Generate only schema\n  --prisma               Use Prisma ORM (default: auto-detect)\n  --drizzle              Use Drizzle ORM\n  --typeorm              Use TypeORM\n  --dry-run              Preview files without writing\n\n\\x1b[36mOptions (for check command):\\x1b[0m\n  --json                 Output results as JSON\n  --plain                Plain text output without colors\n\n\\x1b[36mOptions (for make:seeder command):\\x1b[0m\n  --factory              Generate seeder using factory pattern\n\n\\x1b[36mAliases:\\x1b[0m\n  g, gen, generate       Shortcut for create\n\n\\x1b[36mExamples:\\x1b[0m\n  buntok init                             # Initialize project setup\n  buntok dev                              # Start development server\n  buntok dev --expose                     # Start with public tunnel URL\n  buntok dev --expose --port=3000         # Start with tunnel on port 3000\n  buntok build                            # Build project for production\n  buntok check                            # Run TypeScript type check\n  buntok create user                      # Generate all files for user entity\n  buntok g user --repo --service          # Generate repository and service only\n  buntok g user --drizzle                 # Generate with Drizzle ORM\n  buntok g user --dry-run                 # Preview what would be generated\n  buntok db migrate                       # Run pending migrations\n  buntok db seed                          # Seed database\n  buntok debug:routes                     # Show all registered routes\n  buntok debug:routes --json              # Output routes as JSON\n  buntok make:factory user                # Generate user data factory\n  buntok make:docs                        # Generate OpenAPI documentation\n  buntok make:test user                   # Generate unit test for user\n  buntok make:test:e2e user               # Generate E2E test for user API\n  buntok make:seeder user                 # Generate user seeder\n  buntok make:middleware auth             # Generate auth middleware\n`);\n}\n\nexport async function main() {\n\tconst args = process.argv.slice(2);\n\tconst command = args[0];\n\tconst arg1 = args[1];\n\n\tif (!command) {\n\t\tprintBanner();\n\t\tprintUsage();\n\t\tprocess.exitCode = 1;\n\t\treturn;\n\t}\n\n\tswitch (command) {\n\t\tcase \"init\":\n\t\t\tawait initCommand();\n\t\t\tbreak;\n\t\tcase \"build\":\n\t\t\tawait buildCommand();\n\t\t\tbreak;\n\t\tcase \"check\":\n\t\t\tawait checkCommand(args.slice(1));\n\t\t\tbreak;\n\t\tcase \"dev\":\n\t\t\tawait devCommand(args.slice(1));\n\t\t\tbreak;\n\t\tcase \"g\":\n\t\tcase \"gen\":\n\t\tcase \"generate\":\n\t\tcase \"create\":\n\t\t\tif (!arg1) {\n\t\t\t\tconsole.error(\n\t\t\t\t\t\"\\x1b[31mError: entity name is required for create command\\x1b[0m\",\n\t\t\t\t);\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait createCommand(arg1, args.slice(2));\n\t\t\tbreak;\n\t\tcase \"db\":\n\t\t\tawait dbCommand(args.slice(1));\n\t\t\tbreak;\n\t\tcase \"debug:routes\":\n\t\t\tawait debugRoutesCommand(args.slice(1));\n\t\t\tbreak;\n\t\tcase \"make:docs\":\n\t\t\tawait makeDocsCommand();\n\t\t\tbreak;\n\t\tcase \"make:factory\":\n\t\t\tif (!arg1) {\n\t\t\t\tconsole.error(\n\t\t\t\t\t\"\\x1b[31mError: entity name is required for make:factory command\\x1b[0m\",\n\t\t\t\t);\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait makeFactoryCommand(arg1, args.slice(2));\n\t\t\tbreak;\n\t\tcase \"make:test\":\n\t\t\tif (!arg1) {\n\t\t\t\tconsole.error(\n\t\t\t\t\t\"\\x1b[31mError: entity name is required for make:test command\\x1b[0m\",\n\t\t\t\t);\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait makeTestCommand(arg1, args.slice(2));\n\t\t\tbreak;\n\t\tcase \"make:test:e2e\":\n\t\t\tif (!arg1) {\n\t\t\t\tconsole.error(\n\t\t\t\t\t\"\\x1b[31mError: entity name is required for make:test:e2e command\\x1b[0m\",\n\t\t\t\t);\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait makeTestE2ECommand(arg1);\n\t\t\tbreak;\n\t\tcase \"make:seeder\":\n\t\t\tif (!arg1) {\n\t\t\t\tconsole.error(\n\t\t\t\t\t\"\\x1b[31mError: entity name is required for make:seeder command\\x1b[0m\",\n\t\t\t\t);\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait makeSeederCommand(arg1, args.slice(2));\n\t\t\tbreak;\n\t\tcase \"make:middleware\":\n\t\t\tif (!arg1) {\n\t\t\t\tconsole.error(\n\t\t\t\t\t\"\\x1b[31mError: middleware name is required for make:middleware command\\x1b[0m\",\n\t\t\t\t);\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait makeMiddlewareCommand(arg1, args.slice(2));\n\t\t\tbreak;\n\t\tdefault: {\n\t\t\tconst commands = [\n\t\t\t\t\"init\",\n\t\t\t\t\"dev\",\n\t\t\t\t\"build\",\n\t\t\t\t\"check\",\n\t\t\t\t\"create\",\n\t\t\t\t\"g\",\n\t\t\t\t\"db\",\n\t\t\t\t\"debug:routes\",\n\t\t\t\t\"make:docs\",\n\t\t\t\t\"make:factory\",\n\t\t\t\t\"make:test\",\n\t\t\t\t\"make:test:e2e\",\n\t\t\t\t\"make:seeder\",\n\t\t\t\t\"make:middleware\",\n\t\t\t];\n\t\t\t// Simple fuzzy match: prefix or contains\n\t\t\tconst closest = commands.find(\n\t\t\t\t(c) =>\n\t\t\t\t\tc.startsWith(command) ||\n\t\t\t\t\tcommand.startsWith(c) ||\n\t\t\t\t\tc.includes(command) ||\n\t\t\t\t\tcommand.includes(c),\n\t\t\t);\n\t\t\tconst hint = closest ? `\\n  Did you mean: buntok ${closest}?` : \"\";\n\t\t\tconsole.error(`\\x1b[31mUnknown command: ${command}\\x1b[0m${hint}`);\n\t\t\tprintUsage();\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn;\n\t\t}\n\t}\n}\n\nmain();\n"]}