@forinda/kickjs-cli 8.13.1 → 8.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/{agent-docs-Dq_azKfQ.mjs → agent-docs-BBIVix8s.mjs} +2 -2
  2. package/dist/{agent-docs-BxuvlGy4.mjs → agent-docs-DR1PRHV4.mjs} +3 -3
  3. package/dist/{agent-docs-BxuvlGy4.mjs.map → agent-docs-DR1PRHV4.mjs.map} +1 -1
  4. package/dist/{build-t8pGkT7W.mjs → build-CA0uDYP4.mjs} +2 -2
  5. package/dist/{build-eFEdQsTj.mjs → build-DvcK_Feg.mjs} +3 -3
  6. package/dist/{build-eFEdQsTj.mjs.map → build-DvcK_Feg.mjs.map} +1 -1
  7. package/dist/{builtins-ubUekPfw.mjs → builtins-DWzysfuk.mjs} +2 -2
  8. package/dist/{builtins-DCvidf69.mjs → builtins-QqgoF4jk.mjs} +142 -131
  9. package/dist/cli.mjs +2 -2
  10. package/dist/{config-BIlu1hs0.mjs → config-ChYZE_ER.mjs} +2 -2
  11. package/dist/{config-D0zuz3Fx.mjs → config-Cz2-AJbR.mjs} +3 -3
  12. package/dist/{config-D0zuz3Fx.mjs.map → config-Cz2-AJbR.mjs.map} +1 -1
  13. package/dist/{doctor-BDlJqXWX.mjs → doctor-CNra8Yf_.mjs} +4 -4
  14. package/dist/{doctor-BDlJqXWX.mjs.map → doctor-CNra8Yf_.mjs.map} +1 -1
  15. package/dist/{fullstack-BWdQFw3R.mjs → fullstack-B6QDnu27.mjs} +5 -5
  16. package/dist/{fullstack-BWdQFw3R.mjs.map → fullstack-B6QDnu27.mjs.map} +1 -1
  17. package/dist/{fullstack-C6hCr30Z.mjs → fullstack-en-ECevz.mjs} +4 -4
  18. package/dist/index.d.mts.map +1 -1
  19. package/dist/index.mjs +2 -2
  20. package/dist/{package-manager-CSsqVTZ-.mjs → package-manager-D8W1-xh-.mjs} +3 -3
  21. package/dist/{package-manager-CSsqVTZ-.mjs.map → package-manager-D8W1-xh-.mjs.map} +1 -1
  22. package/dist/{package-manager-D5grCG_d.mjs → package-manager-vl66Np0J.mjs} +2 -2
  23. package/dist/{plugin-CGlWHBFX.mjs → plugin-C22PThnC.mjs} +2 -2
  24. package/dist/{plugin-BXckYw0A.mjs → plugin-C4ZvjEuo.mjs} +2 -2
  25. package/dist/project-BO5joAFY.mjs +134 -0
  26. package/dist/project-BO5joAFY.mjs.map +1 -0
  27. package/dist/project-BxGXkPHR.mjs +133 -0
  28. package/dist/{project-root-B1zLyHn6.mjs → project-root-CH1Dy_HW.mjs} +2 -2
  29. package/dist/{project-root-DYJU7ROd.mjs → project-root-DVa7AoaZ.mjs} +3 -3
  30. package/dist/{project-root-DYJU7ROd.mjs.map → project-root-DVa7AoaZ.mjs.map} +1 -1
  31. package/dist/{rolldown-runtime-Bn82Wzut.mjs → rolldown-runtime-V3xbKk8u.mjs} +1 -1
  32. package/dist/{run-plugins-B8vUgyD4.mjs → run-plugins-9IDaa4U7.mjs} +99 -88
  33. package/dist/run-plugins-9IDaa4U7.mjs.map +1 -0
  34. package/dist/{typegen-CAni3mL3.mjs → typegen-BKa7OeBf.mjs} +4 -4
  35. package/dist/{typegen-B3mw3F07.mjs → typegen-CiKLo3iV.mjs} +5 -5
  36. package/dist/{typegen-B3mw3F07.mjs.map → typegen-CiKLo3iV.mjs.map} +1 -1
  37. package/dist/{types-DJMtN7wo.mjs → types-Zu0gh9vO.mjs} +1 -1
  38. package/package.json +2 -2
  39. package/dist/project-BE7J8TpW.mjs +0 -133
  40. package/dist/project-B_yEOLE4.mjs +0 -134
  41. package/dist/project-B_yEOLE4.mjs.map +0 -1
  42. package/dist/run-plugins-B8vUgyD4.mjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-BO5joAFY.mjs","names":["indentBlock","writeFileSafe","confirm","runScript","loadKickConfig","here","dirname","fileURLToPath","TEMPLATES_DIR","join","existsSync","dir","outputPath","templatePath","segment","renderLayers","templatesDir","options","files","dependencies","devDependencies","builds","integrations","scripts","layer","layers","manifestPath","manifest","readFileSync","root","rel","readdirSync","abs","statSync","contents","path","sep","target","vars","fill","text","key","all","renderSlots","d","fillVars","MARKER","lines","source","slots","line","active","i","out","match","indent","slot","rendered","renderImports","entry","indentBlock$1","code","byModule","spec","specs","name","from","def","names","n","take","v","versions","pinned","packageManagerSpec","version","execFileSync","pm","specVersion","yarnrc","major","generatePackageJson","packageManager","packages","setAllowBuilds","entries","yaml","unquote","quote","block","start","create","end","answers","allow","index","answered","lists","range","NODE_IMAGE","PM","script","YARN_BERRY","RUN_HINT","generateDockerfile","minor","p","setup","prismaSkip","copyManifests","kind","file","header","what","generateDockerignore","DEPLOY_TARGETS","KICK_CONFIGS","hasKickConfig","f","isWorkspaceRoot","parseDeployTargets","input","unknown","readJson","workspaceScript","platform","generateDeploy","workspace","app","pkgFile","pkg","appPkg","resolvePackageManager","inertia","serverless","targets","written","relative","missing","execFileAsync","promisify","execFile","CMD_UNSAFE","shellSafeInvocation","args","a","command","captureCommand","invocation","opts","runCommand","runNodeWithEnv","result","spawnSync","env","captureCommandAsync","stdout","SLOT_PROPERTY","wireIntegrations","integration","property","call","callName","program","parseSync","findBootstrapOptions","prop","local","localName","firstLine","appendEntry","addProperty","addImport","found","visit","node","specifier","imported","body","l","leading","lineIndent","offset","indentBlock","elements","items","arrayIndent","array","inner","open","close","last","comma","at","SCHEMA_LIBS","wireEnvSchema","findEnvSchemaObject","lib","object","envKeyOf","objectLiteralOf","wrappers","s","wrapped","objects","w","imports","existing","have","named","FEATURE_LAYERS","planWiring","findEntry","cwd","dirtyFiles","findEnvSchema","wireEnv","SOURCE","sourceFilesInTheWay","applyLayerFiles","created","updated","current","envKey","importsAny","posix","paths","rebaseImports","wireEntry","projectVars","readPackageJson","manualSnippet","PACKAGE_REGISTRY","AVAILABLE_ADD_PACKAGES","ENGINE_PEERS","UPLOAD_DRIVERS","parseRuntimeFlag","value","resolveAppRuntime","resolveAppRuntimeDetailed","fromConfig","detectRuntimeFromDepsDetailed","ENGINE_BY_PACKAGE","findUp","prod","dev","resolve","inProd","r","inDev","candidates","fromDir","parent","printPackageList","maxName","k","core","info","optional","formatRow","padded","resolved","runtime","engineNote","peers","deprecated","row","TEMPLATE_BUILDS","approveInstallScripts","before","after","writeFileSync","changed","trusted","installRoot","buildsFor","planAddPackages","prodDeps","devDeps","warnings","notices","driver","forceDev","peer","types","enginePeers","registerListCommand","registerAddCommand","resolvePackageManagerWithSource","fromFlag","detection","plan","wiring","envEntries","envSchema","dirty","warning","notice","installed","deps","cmd","dep","execSync","kept","blocked","toWire","envManual","manual","fillBlocked","__dirname","commandVars","execBin","cliPkg","SIBLING_PACKAGES","THIRD_PARTY_PACKAGES","parseNpmVersion","output","trimmed","parsed","fallbackRange","mapWithConcurrency","results","next","workers","limit","task","resolveSiblingVersions","queries","deadline","remaining","fallback","cap","resolveVersionAtTag","tag","stripRange","baseVersionGte","a0","a1","a2","b0","b1","b2","b","cliVersion","newerCliRelease","latest","isBehind","tagExportsSubpath","exportsMap","subpath","initProject","directory","log","msg","unresolved","RUNTIME_PKGS","kickjsPinned","alpha","project","scaffoldLayers","defaultRepo","spaIntegration","pmSpec","yarnConfig","template","randomBytes","generateAgentDocs","runTypegen","needsCd","kick","genHint","rows","width","list","singleQuoted","clientDir","selection"],"sources":["../src/scaffold/overlay.ts","../src/generators/templates/project-config.ts","../src/generators/templates/docker.ts","../src/generators/deploy.ts","../src/utils/shell.ts","../src/scaffold/wire.ts","../src/commands/add-wire.ts","../src/commands/add.ts","../src/generators/project.ts"],"sourcesContent":["/**\n * Overlay scaffolding — project files as real directories instead of TS\n * functions that return strings.\n *\n * A layer is a directory under `packages/cli/templates/`:\n *\n * - `files/` mirrors the project. Layers render in order; a later layer's\n * file replaces an earlier one at the same path, and a `<name>.append` file\n * is added to the end of `<name>` instead.\n * - `feature.json` (optional) lists the packages the layer needs and its\n * **integrations**: entries for the slots that shared files expose.\n *\n * File names: a `_dot_` path segment prefix becomes `.` (`_dot_gitignore` →\n * `.gitignore`), because npm publish drops or rewrites real dotfiles.\n *\n * Slots: a shared file marks where layers plug in with a comment line.\n * `// @kick:imports` becomes the merged import statements of every rendered\n * integration; `// @kick:<slot>` becomes that slot's entries, one `code,` per\n * line at the marker's indentation. An empty slot inside its own `key: [` …\n * `],` block drops the whole block, so an app with no adapters has no\n * `adapters: []`. This is what keeps layers out of each other's way: swagger\n * never edits the entry file, it declares an `adapter` entry.\n */\nimport { existsSync, readdirSync, readFileSync, statSync } from 'node:fs'\nimport { dirname, join, sep } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst here = dirname(fileURLToPath(import.meta.url))\n\n/**\n * `packages/cli/templates` — one level above the bundle (`dist/*.mjs`), two\n * above this source file (`src/scaffold/overlay.ts`), so tests can import it\n * from source.\n */\nexport const TEMPLATES_DIR = [\n join(here, '..', 'templates'),\n join(here, '..', '..', 'templates'),\n].find((dir) => existsSync(join(dir, 'base')))!\n\n/** An import an integration needs. Merged per module across integrations. */\nexport interface ImportSpec {\n from: string\n names?: string[]\n default?: string\n}\n\n/**\n * What a layer contributes to shared files. With a `slot`, `code` is\n * rendered there and `import` only when that slot exists in the file — so an\n * `express.json()` middleware doesn't leave an unused `express` import in a\n * template without a middleware list. Without a `slot`, `import` is always\n * rendered.\n */\nexport interface Integration {\n import?: ImportSpec\n slot?: string\n code?: string\n}\n\n/** `feature.json`. Package versions come from the scaffold's resolved version map. */\nexport interface FeatureManifest {\n dependencies?: string[]\n devDependencies?: string[]\n /** Install-script answers for packages this layer pulls in (see `approveInstallScripts`). */\n builds?: Record<string, boolean>\n integrations?: Integration[]\n /** package.json scripts this layer adds or replaces. */\n scripts?: Record<string, string>\n}\n\nexport interface RenderedProject {\n files: Map<string, string>\n dependencies: string[]\n devDependencies: string[]\n builds: Record<string, boolean>\n /** Every layer's integrations plus `extra`, in layer order — `kick add` wires these. */\n integrations: Integration[]\n /** package.json scripts, later layers winning. */\n scripts: Record<string, string>\n}\n\n/** The project path a template file lands at: `_dot_` segment prefixes become `.`. */\nexport function outputPath(templatePath: string): string {\n return templatePath\n .split('/')\n .map((segment) => (segment.startsWith('_dot_') ? `.${segment.slice(5)}` : segment))\n .join('/')\n}\n\n/**\n * Render layers into project files plus the packages they need. Pure apart\n * from reading the template directories; the caller writes the files.\n *\n * `extra` adds integrations computed at scaffold time (a value the user\n * typed can't live in a static layer). `vars` fills `{{name}}` in\n * integration code.\n */\nexport function renderLayers(\n layers: readonly string[],\n options: {\n templatesDir?: string\n extra?: Integration[]\n vars?: Record<string, string>\n } = {},\n): RenderedProject {\n const templatesDir = options.templatesDir ?? TEMPLATES_DIR\n const files = new Map<string, string>()\n const dependencies: string[] = []\n const devDependencies: string[] = []\n const builds: Record<string, boolean> = {}\n const integrations: Integration[] = []\n const scripts: Record<string, string> = {}\n\n for (const layer of layers) {\n const dir = join(templatesDir, layer)\n if (!existsSync(dir)) throw new Error(`Unknown scaffold layer \"${layer}\" (${dir})`)\n\n const manifestPath = join(dir, 'feature.json')\n if (existsSync(manifestPath)) {\n const manifest = JSON.parse(readFileSync(manifestPath, 'utf-8')) as FeatureManifest\n dependencies.push(...(manifest.dependencies ?? []))\n devDependencies.push(...(manifest.devDependencies ?? []))\n Object.assign(builds, manifest.builds)\n integrations.push(...(manifest.integrations ?? []))\n Object.assign(scripts, manifest.scripts)\n }\n\n const root = join(dir, 'files')\n if (!existsSync(root)) continue\n // String entries, not Dirents: `Dirent.parentPath` needs Node 20.12.\n for (const rel of readdirSync(root, { recursive: true, encoding: 'utf-8' }).toSorted()) {\n const abs = join(root, rel)\n if (!statSync(abs).isFile()) continue\n const contents = readFileSync(abs, 'utf-8')\n const path = outputPath(rel.split(sep).join('/'))\n if (path.endsWith('.append')) {\n const target = path.slice(0, -'.append'.length)\n files.set(target, (files.get(target) ?? '') + contents)\n } else {\n files.set(path, contents)\n }\n }\n }\n\n integrations.push(...(options.extra ?? []))\n const vars = options.vars ?? {}\n const fill = (text: string) => text.replace(/\\{\\{(\\w+)\\}\\}/g, (all, key) => vars[key] ?? all)\n for (const [path, contents] of files) {\n if (contents.includes('// @kick:')) files.set(path, renderSlots(contents, integrations, fill))\n }\n\n return {\n files,\n dependencies: [...new Set(dependencies)],\n // A package a layer needs at runtime (ws for WsAdapter) stays out of devDependencies.\n devDependencies: [...new Set(devDependencies)].filter((d) => !dependencies.includes(d)),\n builds,\n integrations,\n scripts,\n }\n}\n\n/**\n * Fill `{{name}}` placeholders in rendered files. Separate from rendering so\n * a value can depend on the result (README lists the packages the layers\n * chose). Unknown names are left as written.\n */\nexport function fillVars(\n files: ReadonlyMap<string, string>,\n vars: Record<string, string>,\n): Map<string, string> {\n const fill = (text: string) =>\n text.replace(/\\{\\{(\\w+)\\}\\}/g, (all, key: string) => (key in vars ? vars[key]! : all))\n return new Map([...files].map(([path, contents]) => [path, fill(contents)]))\n}\n\nconst MARKER = /^([ \\t]*)\\/\\/ @kick:([\\w-]+)[ \\t]*$/\n\n/** Fill one file's slot markers. */\nexport function renderSlots(\n source: string,\n integrations: readonly Integration[],\n fill: (text: string) => string = (text) => text,\n): string {\n const lines = source.split('\\n')\n const slots = new Set(lines.map((line) => MARKER.exec(line)?.[2]).filter(Boolean))\n const active = integrations.filter((i) => !i.slot || slots.has(i.slot))\n\n const out: string[] = []\n for (let i = 0; i < lines.length; i++) {\n const match = MARKER.exec(lines[i]!)\n if (!match) {\n out.push(lines[i]!)\n continue\n }\n const [, indent, slot] = match as unknown as [string, string, string]\n const rendered =\n slot === 'imports'\n ? renderImports(active.flatMap((entry) => (entry.import ? [entry.import] : [])))\n : active\n .filter((entry) => entry.slot === slot && entry.code)\n .map((entry) => indentBlock(`${fill(entry.code!)},`, indent))\n if (rendered.length > 0) {\n out.push(...rendered)\n continue\n }\n // Empty: drop an enclosing `key: [` … `],` block that holds only this marker.\n const prev = out.at(-1)\n if (prev?.trimEnd().endsWith('[') && lines[i + 1]?.trim().startsWith(']')) {\n out.pop()\n i++\n }\n }\n return out.join('\\n')\n}\n\nfunction indentBlock(code: string, indent: string): string {\n return code\n .split('\\n')\n .map((line) => (line ? indent + line : line))\n .join('\\n')\n}\n\n/** One statement per module, names merged in first-seen order; wrapped past 100 columns. */\nexport function renderImports(specs: readonly ImportSpec[]): string[] {\n const byModule = new Map<string, { names: string[]; default?: string }>()\n for (const spec of specs) {\n const entry = byModule.get(spec.from) ?? { names: [] }\n entry.default ??= spec.default\n for (const name of spec.names ?? []) if (!entry.names.includes(name)) entry.names.push(name)\n byModule.set(spec.from, entry)\n }\n return [...byModule].map(([from, { names, default: def }]) => {\n const parts = [def, names.length ? `{ ${names.join(', ')} }` : undefined].filter(Boolean)\n const line = `import ${parts.join(', ')} from '${from}'`\n if (line.length <= 100 || names.length === 0) return line\n const head = def ? `${def}, ` : ''\n return `import ${head}{\\n${names.map((n) => ` ${n},`).join('\\n')}\\n} from '${from}'`\n })\n}\n","import { execFileSync } from 'node:child_process'\n// `SchemaLib` is defined next to `resolveSchemaLib` in ../../config, so the\n// scaffold that installs the library and the generators that import from it\n// read the same list. Re-exported here for existing importers.\nexport type { SchemaLib } from '../../config'\n\n/**\n * Map of package name → semver range string (`^x.y.z`). Resolved\n * from `npm view <name> version` upstream so per-package independent\n * versioning is honoured at scaffold time. Every package a scaffold layer\n * lists must appear here; missing keys throw during package.json generation\n * (loud failure beats silently shipping `^undefined`).\n */\nexport type SiblingVersions = Record<string, string>\n\nfunction take(versions: SiblingVersions, name: string): string {\n const v = versions[name]\n if (!v) {\n throw new Error(\n `generatePackageJson: missing resolved version for ${name}. ` +\n `Add it to SIBLING_PACKAGES or THIRD_PARTY_PACKAGES in generators/project.ts.`,\n )\n }\n return v\n}\n\n/** Name → resolved range, sorted by name (the order npm and pnpm write). */\nfunction pinned(names: readonly string[], versions: SiblingVersions): Record<string, string> {\n return Object.fromEntries(names.toSorted().map((name) => [name, take(versions, name)]))\n}\n\n/**\n * Generate package.json. Which packages it lists comes from the scaffold\n * layers (`templates/<layer>/feature.json`); the ranges come from `versions`.\n */\n/**\n * `pnpm@11.24.0` for the package manager on this machine, for package.json's\n * `packageManager`: corepack then installs that same version in CI and in\n * the Docker image, so the lockfile is read by the tool that wrote it.\n * Undefined when the version can't be read.\n */\nexport function packageManagerSpec(pm: string): string | undefined {\n try {\n const version = execFileSync(pm, ['--version'], {\n encoding: 'utf-8',\n stdio: ['ignore', 'pipe', 'ignore'],\n timeout: 10_000,\n }).trim()\n return /^\\d+\\.\\d+\\.\\d+$/.test(version) ? `${pm}@${version}` : undefined\n } catch {\n return undefined\n }\n}\n\n/** `[major, minor]` of a `packageManager` spec — `yarn@4.1.0` → `[4, 1]`. */\nexport function specVersion(spec: string | undefined): [number, number] | undefined {\n const match = spec?.match(/@(\\d+)\\.(\\d+)\\./)\n return match ? [Number(match[1]), Number(match[2])] : undefined\n}\n\n/**\n * Yarn 2+ installs with Plug'n'Play by default: no `node_modules`, which the\n * CLI (typecheck, typegen, deploy), Vite and the Dockerfile all read. Yarn\n * reads this file before it installs, so it goes in with the project.\n */\nexport function yarnrc(pm: string, spec: string | undefined): string | undefined {\n const major = specVersion(spec)?.[0]\n return pm === 'yarn' && major !== undefined && major >= 2\n ? 'nodeLinker: node-modules\\n'\n : undefined\n}\n\nexport function generatePackageJson(\n name: string,\n versions: SiblingVersions,\n packages: {\n dependencies: readonly string[]\n devDependencies: readonly string[]\n /** Scripts a scaffold layer adds or replaces. */\n scripts?: Record<string, string>\n },\n packageManager?: string,\n): string {\n return JSON.stringify(\n {\n name,\n ...(packageManager ? { packageManager } : {}),\n // Project starts at 0.0.0 — adopters bump as they ship. Tying\n // the project version to the CLI version (the previous\n // behaviour) made every scaffolded app `5.4.0` on day one,\n // which broke npm publishing for adopters trying their first\n // release.\n version: '0.0.0',\n type: 'module',\n scripts: {\n // `kick dev` (not bare `vite`): it boots Vite itself AND owns the\n // typegen-on-save watcher. Plain `vite` gives working HMR but\n // frozen `.kickjs/types` — new routes silently lose their typing\n // until a manual `kick typegen`.\n // Four scripts, not ten. Everything dropped from here is still one\n // command away — `kick dev:debug`, `kick typegen`, `pnpm exec vitest`,\n // `pnpm exec tsc --noEmit` — and a scaffold that opens with a wall of\n // aliases teaches less than one that shows the binary.\n //\n // `lint: 'eslint src/'` used to be here without eslint ever being a\n // dependency, so `lint` failed with \"command not found\" in every\n // generated project.\n dev: 'kick dev',\n build: 'kick build',\n start: 'kick start',\n test: 'vitest run --passWithNoTests',\n // Deploy scripts come with `kick g deploy netlify | vercel`.\n ...packages.scripts,\n },\n dependencies: pinned(packages.dependencies, versions),\n devDependencies: pinned(packages.devDependencies, versions),\n },\n null,\n 2,\n )\n}\n\n/**\n * Answer pnpm's build-script approvals for `builds` in pnpm-workspace.yaml text,\n * in both formats pnpm has used, so any pnpm 10+ reads them:\n *\n * - `allowBuilds` (pnpm 10.26+; pnpm 11 reads only this)\n * - `onlyBuiltDependencies` / `ignoredBuiltDependencies` (pnpm before 10.26)\n *\n * Each version ignores the format it doesn't read. An existing answer wins: an\n * `allowBuilds` key set to true/false, or a name already in either list, is left\n * alone. A missing key or pnpm's `set this to true or false` placeholder is filled in.\n */\nexport function setAllowBuilds(yaml: string, builds: Record<string, boolean>): string {\n const entries = Object.entries(builds)\n if (entries.length === 0) return yaml\n const lines = yaml === '' ? [] : yaml.replace(/\\n$/, '').split('\\n')\n const unquote = (text: string) => text.trim().replace(/^['\"]|['\"]$/g, '')\n const quote = (name: string) => (/^[\\w-]+$/.test(name) ? name : `'${name}'`)\n\n /** Line range of a top-level block's indented entries; appended when missing and `create`. */\n const block = (key: string, create: boolean): { start: number; end: number } | undefined => {\n let start = lines.findIndex((line) => line.replace(/\\s+$/, '') === `${key}:`)\n if (start === -1) {\n if (!create) return undefined\n if (lines.length > 0 && lines[lines.length - 1] !== '') lines.push('')\n lines.push(`${key}:`)\n start = lines.length - 1\n }\n // The block runs to the next unindented line; blank lines inside it don't end it.\n let end = start + 1\n for (let i = start + 1; i < lines.length && /^(\\s|$)/.test(lines[i]); i++) {\n if (lines[i].trim() !== '') end = i + 1\n }\n return { start, end }\n }\n\n const answers: Array<[string, boolean]> = []\n for (const [name, allow] of entries) {\n const { start, end } = block('allowBuilds', true)!\n const index = lines\n .slice(start + 1, end)\n .findIndex((line) => unquote(line.split(':')[0]) === name)\n const answered =\n index === -1 ? undefined : /:\\s*(true|false)\\s*$/.exec(lines[start + 1 + index])\n if (answered) {\n answers.push([name, answered[1] === 'true'])\n continue\n }\n const entry = ` ${quote(name)}: ${allow}`\n if (index === -1) lines.splice(end, 0, entry)\n else lines[start + 1 + index] = entry\n answers.push([name, allow])\n }\n\n const lists = ['onlyBuiltDependencies', 'ignoredBuiltDependencies']\n for (const [name, allow] of answers) {\n const listed = lists.some((key) => {\n const range = block(key, false)\n return (\n range !== undefined &&\n lines\n .slice(range.start + 1, range.end)\n .some((line) => unquote(line.replace(/^\\s*-/, '')) === name)\n )\n })\n if (listed) continue\n const { end } = block(allow ? lists[0] : lists[1], true)!\n lines.splice(end, 0, ` - ${quote(name)}`)\n }\n return `${lines.join('\\n')}\\n`\n}\n","/**\n * Dockerfile + .dockerignore for a scaffolded project — one image that runs\n * the long-running server (`node dist/index.js`), for any host that runs\n * containers.\n *\n * Three stages: production dependencies, the build, and a slim runtime that\n * copies both. The runtime has no package manager and no dev dependencies —\n * the `kick` CLI included, which is why it starts `node` directly rather than\n * `kick start`.\n */\nimport { specVersion } from './project-config'\n\nexport type DockerProjectKind = 'api' | 'inertia' | 'fullstack'\nexport type DockerPackageManager = 'pnpm' | 'npm' | 'yarn' | 'bun'\n\ninterface PmCommands {\n lockfile: string\n /** Extra files the install reads, beside package.json and the lockfile. */\n installFiles: string[]\n install: string\n installProd: string\n run: (script: string) => string\n /** Image the install and build run in. */\n image: string\n setup?: string\n}\n\nconst NODE_IMAGE = 'node:22-slim'\n\nconst PM: Record<DockerPackageManager, PmCommands> = {\n pnpm: {\n lockfile: 'pnpm-lock.yaml',\n // allowBuilds (which install scripts may run) lives here.\n installFiles: ['pnpm-workspace.yaml'],\n install: 'pnpm install --frozen-lockfile',\n installProd: 'pnpm install --prod --frozen-lockfile',\n run: (script) => `pnpm run ${script}`,\n image: NODE_IMAGE,\n setup: 'RUN corepack enable',\n },\n npm: {\n lockfile: 'package-lock.json',\n installFiles: [],\n install: 'npm ci',\n installProd: 'npm ci --omit=dev',\n run: (script) => `npm run ${script}`,\n image: NODE_IMAGE,\n },\n yarn: {\n lockfile: 'yarn.lock',\n installFiles: [],\n install: 'yarn install --frozen-lockfile',\n installProd: 'yarn install --production --frozen-lockfile',\n run: (script) => `yarn run ${script}`,\n image: NODE_IMAGE,\n setup: 'RUN corepack enable',\n },\n bun: {\n lockfile: 'bun.lock',\n installFiles: [],\n install: 'bun install --frozen-lockfile',\n installProd: 'bun install --production --frozen-lockfile',\n run: (script) => `bun run ${script}`,\n image: 'oven/bun:1',\n },\n}\n\nconst YARN_BERRY: PmCommands = {\n lockfile: 'yarn.lock',\n installFiles: ['.yarnrc.yml'],\n install: 'yarn install --immutable',\n installProd: 'yarn workspaces focus --all --production',\n run: (script) => `yarn run ${script}`,\n image: NODE_IMAGE,\n setup: 'RUN corepack enable',\n}\n\nconst RUN_HINT: Record<DockerProjectKind, string> = {\n api: 'docker run -p 3000:3000 <name>',\n inertia:\n 'docker run -p 3000:3000 -e SESSION_SECRET=<a long random string> -e APP_URL=<https://your.site> <name>',\n fullstack: 'docker run -p 3000:3000 <name>',\n}\n\n/**\n * `spec` is the project's `packageManager` (`yarn@4.1.0`): Yarn 2+ installs\n * differently from Yarn 1, and Bun before 1.2 writes `bun.lockb`.\n */\nexport function generateDockerfile(\n kind: DockerProjectKind,\n pm: DockerPackageManager,\n name: string,\n spec?: string,\n): string {\n const [major = 0, minor = 0] = specVersion(spec) ?? []\n const p =\n pm === 'yarn' && major >= 2\n ? major >= 4\n ? YARN_BERRY\n : // `workspaces focus` needs the workspace-tools plugin, built in from\n // Yarn 4 only: install everything rather than fail the image.\n { ...YARN_BERRY, installProd: YARN_BERRY.install }\n : pm === 'bun' && spec && (major < 1 || (major === 1 && minor < 2))\n ? { ...PM.bun, lockfile: 'bun.lockb' }\n : PM[pm]\n // Native addons (better-sqlite3 from `kick add sqlite`, bcrypt, …) compile\n // when no prebuilt binary fits, and the slim images have no toolchain. Only\n // the install stages get it; the runtime image stays slim.\n const toolchain =\n '\\n# Compilers for native addons (better-sqlite3, …) that have no prebuilt binary.\\n' +\n 'RUN apt-get update && apt-get install -y --no-install-recommends python3 make g++ \\\\\\n' +\n ' && rm -rf /var/lib/apt/lists/*'\n const setup = `${p.setup ? `\\n${p.setup}` : ''}${toolchain}`\n // A production install has no Prisma CLI (a dev dependency), so\n // @prisma/client's postinstall `prisma generate` would fail it. The build\n // stage generates the client; the runtime copies it from there.\n const prismaSkip =\n '# The build stage generates the Prisma client, if any.\\nENV PRISMA_SKIP_POSTINSTALL_GENERATE=1'\n const manifests =\n kind === 'fullstack'\n ? // A workspace installs from every member's manifest.\n ['package.json', p.lockfile, ...p.installFiles, 'server/package.json', 'web/package.json']\n : ['package.json', p.lockfile, ...p.installFiles]\n // Each COPY names its destination, so members keep their directories.\n const copyManifests = manifests\n .map(\n (file) =>\n `COPY ${file} ./${file.includes('/') ? file.slice(0, file.lastIndexOf('/') + 1) : ''}`,\n )\n .join('\\n')\n\n const header = `# syntax=docker/dockerfile:1\n# ${name} — the long-running server in one image.\n#\n# docker build -t ${name} .\n# ${RUN_HINT[kind].replace('<name>', name)}\n#\n# Environment comes from the platform or \\`docker run\\`; .env files are not\n# copied into the image. The lockfile must be committed — installs are frozen.\n`\n\n if (kind === 'fullstack') {\n return `${header}\nFROM ${p.image} AS base\nWORKDIR /app${setup}\n\n# Production dependencies of every workspace member.\nFROM base AS deps\n${prismaSkip}\n${copyManifests}\nRUN ${p.installProd}\n# Hoisting may leave a member without its own node_modules; the runtime copies both.\nRUN mkdir -p node_modules server/node_modules\n\n# The server bundle and the built web app.\nFROM base AS build\n${copyManifests}\nRUN ${p.install}\nCOPY . .\nRUN ${p.run('build')}\n# The generated Prisma client lands beside whichever install holds @prisma/client.\nRUN mkdir -p node_modules/.prisma server/node_modules/.prisma\n\nFROM ${NODE_IMAGE}\nENV NODE_ENV=production PORT=3000\nWORKDIR /app\nCOPY --from=deps /app/node_modules ./node_modules\nCOPY --from=deps /app/server/node_modules ./server/node_modules\nCOPY --from=build /app/node_modules/.prisma ./node_modules/.prisma\nCOPY --from=build /app/server/node_modules/.prisma ./server/node_modules/.prisma\nCOPY --from=build /app/package.json ./\nCOPY --from=build /app/server/package.json ./server/\nCOPY --from=build /app/server/dist ./server/dist\n# SpaAdapter serves ../web/dist relative to the server.\nCOPY --from=build /app/web/dist ./web/dist\nWORKDIR /app/server\nUSER node\nEXPOSE 3000\nCMD [\"node\", \"dist/index.js\"]\n`\n }\n\n const what =\n kind === 'inertia'\n ? '# The server, the pages (dist/client) and the SSR bundle (dist/ssr).'\n : '# The server bundle.'\n return `${header}\nFROM ${p.image} AS base\nWORKDIR /app${setup}\n\nFROM base AS deps\n${prismaSkip}\n${copyManifests}\nRUN ${p.installProd}\n\n${what}\nFROM base AS build\n${copyManifests}\nRUN ${p.install}\nCOPY . .\nRUN ${p.run('build')}\nRUN mkdir -p node_modules/.prisma\n\nFROM ${NODE_IMAGE}\nENV NODE_ENV=production PORT=3000\nWORKDIR /app\nCOPY --from=deps /app/node_modules ./node_modules\n# A Prisma client generated into node_modules (empty otherwise).\nCOPY --from=build /app/node_modules/.prisma ./node_modules/.prisma\nCOPY --from=build /app/package.json ./\nCOPY --from=build /app/dist ./dist\n# The image's filesystem is replaced on every deploy. Keep a SQLite file (or\n# uploads) in /app/data and mount a volume there: docker run -v ${name}-data:/app/data\nRUN mkdir -p data && chown node:node data\nUSER node\nEXPOSE 3000\nCMD [\"node\", \"dist/index.js\"]\n`\n}\n\nexport function generateDockerignore(): string {\n const lines = [\n '# Rebuilt inside the image.',\n '**/node_modules',\n '**/dist',\n '**/.kickjs',\n '# Secrets stay out of the image; pass them at run time.',\n '**/.env',\n '**/.env.*',\n '!**/.env.example',\n '# Platform and tooling output.',\n '.netlify',\n '.vercel',\n '.git',\n '**/coverage',\n '*.log',\n ]\n return `${lines.join('\\n')}\\n`\n}\n","/**\n * `kick g deploy <netlify|vercel|docker…>` — the files a deploy target needs,\n * added when the project needs them rather than by every `kick new`:\n *\n * - netlify: `netlify.toml`, the serverless entry, a `build:netlify` script\n * - vercel: `vercel.json`, the serverless entry, a `build:vercel` script\n * - docker: `Dockerfile`, `.dockerignore`\n *\n * A fullstack workspace (a `server/` kick project beside `web/`) gets them\n * where it needs them: config and scripts at the root, the entry in server/.\n */\nimport { existsSync, readFileSync } from 'node:fs'\nimport { join, relative } from 'node:path'\nimport { fillVars, renderLayers } from '../scaffold/overlay'\nimport { writeFileSafe } from '../utils/fs'\nimport { confirm } from '../utils/prompts'\nimport { resolvePackageManager } from '../utils/package-manager'\nimport { generateDockerfile, generateDockerignore } from './templates/docker'\n\nexport const DEPLOY_TARGETS = ['netlify', 'vercel', 'docker'] as const\nexport type DeployTarget = (typeof DEPLOY_TARGETS)[number]\n\nexport interface GenerateDeployOptions {\n /** The project — or, for a fullstack app, the workspace root. */\n dir: string\n targets: readonly DeployTarget[]\n /** Overwrite existing files without asking. */\n force?: boolean\n /** Package manager; detected when omitted. */\n pm?: string\n}\n\nconst KICK_CONFIGS = ['kick.config.ts', 'kick.config.js', 'kick.config.mjs', 'kick.config.json']\nconst hasKickConfig = (dir: string) => KICK_CONFIGS.some((f) => existsSync(join(dir, f)))\n\n/** A fullstack workspace root: a kick project in server/, a frontend in web/. */\nexport function isWorkspaceRoot(dir: string): boolean {\n return hasKickConfig(join(dir, 'server')) && existsSync(join(dir, 'web'))\n}\n\n/** Parse `\"netlify, docker\"` / `['netlify', 'docker']`, rejecting unknown names. */\nexport function parseDeployTargets(input: string | readonly string[]): DeployTarget[] {\n const names = (typeof input === 'string' ? input.split(',') : input)\n .map((name) => name.trim().toLowerCase())\n .filter(Boolean)\n const unknown = names.filter((name) => !DEPLOY_TARGETS.includes(name as DeployTarget))\n if (unknown.length > 0) {\n throw new Error(\n `Unknown deploy target: ${unknown.join(', ')} — expected ${DEPLOY_TARGETS.join(', ')}`,\n )\n }\n return [...new Set(names)] as DeployTarget[]\n}\n\nfunction readJson(file: string): Record<string, any> {\n return JSON.parse(readFileSync(file, 'utf-8'))\n}\n\n/** `build:netlify` / `build:vercel` for a fullstack workspace root. */\nfunction workspaceScript(pm: string, platform: 'netlify' | 'vercel'): string {\n return pm === 'pnpm'\n ? `pnpm build && pnpm --filter ./server exec kick build:${platform}`\n : `${pm} run build && cd server && kick build:${platform}`\n}\n\n/** Write the files and scripts `targets` need; returns the paths written. */\nexport async function generateDeploy(options: GenerateDeployOptions): Promise<string[]> {\n const { dir, targets } = options\n const workspace = isWorkspaceRoot(dir)\n if (!workspace && !hasKickConfig(dir)) {\n throw new Error(\n `${dir} is not a KickJS project (no kick.config) — run kick g deploy from the project, or from a fullstack workspace's root.`,\n )\n }\n const app = workspace ? join(dir, 'server') : dir\n const pkgFile = join(dir, 'package.json')\n const pkg = readJson(pkgFile)\n const appPkg = workspace ? readJson(join(app, 'package.json')) : pkg\n const pm = await resolvePackageManager(options.pm, dir)\n const deps = { ...appPkg.dependencies, ...appPkg.devDependencies }\n const inertia = '@forinda/kickjs-inertia' in deps\n\n const files = new Map<string, string>()\n const scripts: Record<string, string> = {}\n const serverless = () => {\n for (const [path, text] of renderLayers(['deploy-serverless']).files) {\n files.set(join(app, path), text)\n }\n }\n const platform = (name: 'netlify' | 'vercel', layer: string) => {\n const rendered = fillVars(renderLayers([layer]).files, {\n packageManager: pm,\n // Netlify serves this before the function: an Inertia app's built\n // pages, else an empty directory so nothing shadows the API.\n netlifyPublish: inertia ? 'dist/client' : 'dist/public',\n })\n for (const [path, text] of rendered) files.set(join(dir, path), text)\n serverless()\n scripts[`build:${name}`] = workspace\n ? workspaceScript(pm, name)\n : // After the project's own build — an Inertia app's also builds the pages.\n `${pkg.scripts?.build ?? 'kick build'} && kick build:${name}`\n }\n\n for (const target of targets) {\n if (target === 'netlify') {\n platform('netlify', workspace ? 'deploy-netlify-workspace' : 'deploy-netlify')\n } else if (target === 'vercel') {\n platform('vercel', 'deploy-vercel')\n } else {\n const kind = workspace ? 'fullstack' : inertia ? 'inertia' : 'api'\n files.set(\n join(dir, 'Dockerfile'),\n generateDockerfile(kind, pm, String(pkg.name ?? 'app'), pkg.packageManager),\n )\n files.set(join(dir, '.dockerignore'), generateDockerignore())\n }\n }\n\n const written: string[] = []\n for (const [file, text] of files) {\n if (existsSync(file) && !options.force) {\n // The serverless entry is shared by Netlify and Vercel: one already\n // there is the one to keep.\n if (file.endsWith(join('src', 'serverless.ts'))) continue\n const overwrite = await confirm({\n message: `${relative(dir, file)} already exists. Overwrite?`,\n initialValue: false,\n })\n if (!overwrite) continue\n }\n await writeFileSafe(file, text)\n written.push(file)\n }\n\n // Scripts: added, never replacing one the project already has.\n const missing = Object.entries(scripts).filter(([name]) => !pkg.scripts?.[name])\n if (missing.length > 0) {\n pkg.scripts = { ...pkg.scripts, ...Object.fromEntries(missing) }\n await writeFileSafe(pkgFile, `${JSON.stringify(pkg, null, 2)}\\n`)\n written.push(pkgFile)\n }\n return written\n}\n","import { execFile, execFileSync, execSync, spawnSync } from 'node:child_process'\nimport { promisify } from 'node:util'\n\nconst execFileAsync = promisify(execFile)\n\n/**\n * Characters an argument may not contain when it has to travel through\n * `cmd.exe`.\n *\n * The first group is shell syntax — `cmd.exe` would interpret these rather\n * than pass them through. The trailing `\\\\` is different in kind: a backslash\n * is not shell syntax, but Windows command-line quoting mangles it. Node's\n * argv encoder doubles trailing backslashes, and a backslash immediately\n * before a closing quote escapes that quote, so a single argument silently\n * splits in two:\n *\n * ['C:\\\\some path\\\\'] → cmd receives ['\"C:\\\\some', 'path\\\\\"']\n * ['no-space\\\\'] → cmd receives ['no-space\\\\\\\\']\n *\n * Correct escaping is possible but fiddly, and no caller in this CLI needs it\n * — arguments here are package names, dist-tags, subcommands and flags, and\n * working directories travel via the `cwd` option rather than as arguments.\n * So a backslash is rejected outright: a loud `null` beats a silently\n * corrupted argument, which is the exact failure mode this module exists to\n * eliminate.\n */\nconst CMD_UNSAFE = /[&|<>^\"'`(){}[\\];!%\\r\\n\\\\]/\n\n/**\n * Build the `[file, args]` pair to hand to `execFileSync`, routing through\n * `cmd.exe` on Windows so `.cmd` shims are launchable.\n *\n * On Windows, `npm` / `pnpm` / `yarn` / `bun` are `.cmd` batch shims, not\n * `.exe`s, and `execFileSync` cannot launch either spelling:\n *\n * - `execFileSync('npm', …)` → ENOENT (there is no `npm.exe` on PATH)\n * - `execFileSync('npm.cmd', …)` → EINVAL (Node >= 18.20 / 20.12 refuses to\n * spawn batch files without a\n * shell — CVE-2024-27980)\n *\n * Both failures are silent wherever the caller swallows the error, so the\n * command looks like it \"returned nothing\" rather than \"never ran\".\n *\n * `/d` skips AutoRun registry commands, `/s` makes cmd treat everything after\n * `/c` as one verbatim string (it strips only the outer quote pair Node adds).\n * Returns `null` when an argument is unsafe to pass through — refusing to run\n * beats running something the shell rewrote.\n *\n * `platform` is injectable so both branches are unit-testable from any host\n * OS; production callers use the default. It is read per call rather than\n * captured at import time for the same reason.\n */\nexport function shellSafeInvocation(\n file: string,\n args: string[],\n platform: NodeJS.Platform = process.platform,\n): [string, string[]] | null {\n if (platform !== 'win32') return [file, args]\n if (CMD_UNSAFE.test(file) || args.some((a) => CMD_UNSAFE.test(a))) return null\n const command = [file, ...args].map((a) => (a.includes(' ') ? `\"${a}\"` : a)).join(' ')\n return [process.env.ComSpec || 'cmd.exe', ['/d', '/s', '/c', command]]\n}\n\n/**\n * Run a command and capture its trimmed stdout, cross-platform.\n *\n * Returns `null` if the command is missing, exits non-zero, times out, or\n * carries arguments unsafe to pass through `cmd.exe`. Callers treat `null` as\n * \"unknown\" and fall back — the point of this helper is that a Windows `.cmd`\n * shim no longer masquerades as a failed command.\n */\nexport function captureCommand(\n file: string,\n args: string[],\n opts: { timeout?: number; cwd?: string } = {},\n): string | null {\n const invocation = shellSafeInvocation(file, args)\n if (!invocation) return null\n try {\n const out = execFileSync(invocation[0], invocation[1], {\n encoding: 'utf-8',\n timeout: opts.timeout ?? 5000,\n cwd: opts.cwd,\n stdio: ['ignore', 'pipe', 'ignore'],\n windowsHide: true,\n })\n const trimmed = out.toString().trim()\n return trimmed || null\n } catch {\n return null\n }\n}\n\n/**\n * Run a command with inherited stdio, cross-platform. Throws on failure so\n * callers can decide whether a missing package manager is fatal.\n */\nexport function runCommand(file: string, args: string[], opts: { cwd?: string } = {}): void {\n const invocation = shellSafeInvocation(file, args)\n if (!invocation) throw new Error(`Refusing to run '${file}': unsafe arguments`)\n execFileSync(invocation[0], invocation[1], {\n cwd: opts.cwd,\n stdio: 'inherit',\n windowsHide: true,\n })\n}\n\n/**\n * Run a shell command synchronously, printing output.\n *\n * On Windows, `execSync` spawns via `cmd.exe` by default, which means\n * POSIX-style inline env prefixes like `FOO=bar node app.js` do NOT work.\n * Callers that need environment variables should pass them in the `env`\n * option instead of prepending them to the command string — see\n * `runNodeWithEnv` for the cross-platform helper that avoids a shell\n * entirely.\n */\nexport function runShellCommand(command: string, cwd?: string, env?: NodeJS.ProcessEnv): void {\n execSync(command, {\n cwd,\n stdio: 'inherit',\n env: env ? { ...process.env, ...env } : process.env,\n })\n}\n\n/**\n * Cross-platform way to launch a Node.js process with a set of\n * environment variables. Uses `spawnSync` with an argument array so no\n * shell is involved — the `VAR=value node ...` POSIX prefix syntax that\n * `runShellCommand` relied on breaks on cmd.exe and PowerShell.\n */\nexport function runNodeWithEnv(entry: string, env: NodeJS.ProcessEnv, cwd?: string): void {\n const result = spawnSync(process.execPath, [entry], {\n cwd,\n stdio: 'inherit',\n env: { ...process.env, ...env },\n })\n if (result.status !== 0) {\n process.exit(result.status ?? 1)\n }\n}\n\n/**\n * Async twin of `captureCommand` — same Windows `.cmd` routing, same\n * `null`-on-any-failure contract, but genuinely concurrent.\n *\n * `captureCommand` is `execFileSync`, so `Promise.all` over it runs the\n * commands one after another. Callers that fan out over a list of network\n * queries (`npm view` per package) need real concurrency, otherwise the\n * per-call timeout multiplies by the list length.\n */\nexport async function captureCommandAsync(\n file: string,\n args: string[],\n opts: { timeout?: number; cwd?: string } = {},\n): Promise<string | null> {\n const invocation = shellSafeInvocation(file, args)\n if (!invocation) return null\n try {\n const { stdout } = await execFileAsync(invocation[0], invocation[1], {\n encoding: 'utf-8',\n timeout: opts.timeout ?? 5000,\n cwd: opts.cwd,\n windowsHide: true,\n })\n return stdout.toString().trim() || null\n } catch {\n return null\n }\n}\n","/**\n * Apply a layer's integrations to an EXISTING entry file — what `kick add`\n * does after installing a package that has a scaffold layer.\n *\n * `kick new` renders slots into a template it owns. An existing\n * `src/index.ts` is the user's file, so this never re-renders it: it finds\n * the `bootstrap({ ... })` call with oxc and splices text in — an entry at\n * the end of `adapters: [...]` (the array is created when missing), and the\n * import merged into an existing one from the same module or added after the\n * last import. Everything else in the file is left byte-for-byte alone.\n *\n * Idempotent: an entry whose call (`SwaggerAdapter(`) is already in the\n * array is skipped. When the file doesn't have the expected shape (no\n * `bootstrap({ ... })`, or `adapters` isn't an array literal), the entry is\n * returned as `manual` for the caller to print instead of guessing.\n */\nimport { parseSync } from 'oxc-parser'\n\nimport type { ImportSpec, Integration } from './overlay'\n\n/** Which `bootstrap()` option each slot appends to. */\nconst SLOT_PROPERTY: Record<string, string> = {\n adapter: 'adapters',\n middleware: 'middlewares',\n}\n\nexport interface WireResult {\n source: string\n /** Entries added, by the call they make (`SwaggerAdapter`). */\n added: string[]\n /** Entries already present. */\n present: string[]\n /** Entries that couldn't be placed — print them for the user. */\n manual: Integration[]\n}\n\ntype Node = { type: string; start: number; end: number; [key: string]: any }\n\nexport function wireIntegrations(\n source: string,\n integrations: readonly Integration[],\n fill: (text: string) => string = (text) => text,\n file = 'src/index.ts',\n): WireResult {\n const result: WireResult = { source, added: [], present: [], manual: [] }\n for (const integration of integrations) {\n if (!integration.slot || !integration.code) continue\n // The env schema's entries, wired by wireEnvSchema.\n if (integration.slot.startsWith('env-')) continue\n const property = SLOT_PROPERTY[integration.slot]\n const code = fill(integration.code)\n const call = callName(code)\n const program = parseSync(file, result.source).program as unknown as Node\n const options = property ? findBootstrapOptions(program) : undefined\n if (!options) {\n result.manual.push({ ...integration, code })\n continue\n }\n\n const prop = options.properties.find(\n (p: Node) => p.type === 'Property' && (p.key?.name ?? p.key?.value) === property,\n ) as Node | undefined\n if (prop && prop.value.type !== 'ArrayExpression') {\n result.manual.push({ ...integration, code })\n continue\n }\n // Under the name this file calls it: `import { SwaggerAdapter as SA }` → `SA(`.\n const local =\n call && integration.import ? localName(program, integration.import.from, call) : call\n if (\n prop &&\n local &&\n result.source.slice(prop.value.start, prop.value.end).includes(`${local}(`)\n ) {\n result.present.push(call ?? firstLine(code))\n continue\n }\n\n result.source = prop\n ? appendEntry(result.source, prop.value, prop.value.elements, code)\n : addProperty(result.source, options, property!, code)\n if (integration.import) result.source = addImport(result.source, integration.import, file)\n result.added.push(call ?? firstLine(code))\n }\n return result\n}\n\n/** The object literal passed to the first `bootstrap(...)` call. */\nfunction findBootstrapOptions(program: Node): Node | undefined {\n let found: Node | undefined\n const visit = (node: unknown): void => {\n if (found || !node || typeof node !== 'object') return\n if (Array.isArray(node)) return node.forEach(visit)\n const n = node as Node\n if (\n n.type === 'CallExpression' &&\n n.callee?.type === 'Identifier' &&\n n.callee.name === 'bootstrap' &&\n n.arguments?.[0]?.type === 'ObjectExpression'\n ) {\n found = n.arguments[0]\n return\n }\n for (const key in n) visit(n[key])\n }\n visit(program)\n return found\n}\n\n/** The local binding of `imported` from `from`, when this file imports it (possibly renamed). */\nfunction localName(program: Node, from: string, imported: string): string {\n for (const node of program.body as Node[]) {\n if (node.type !== 'ImportDeclaration' || node.source.value !== from) continue\n for (const specifier of node.specifiers as Node[]) {\n const name = specifier.imported?.name ?? specifier.imported?.value\n if (specifier.type === 'ImportSpecifier' && name === imported) return specifier.local.name\n }\n }\n return imported\n}\n\n/**\n * `SwaggerAdapter` for `// comment\\nSwaggerAdapter({ ... })`; for an entry\n * that doesn't start with a call (`...(flag ? [(await import('x')).DevToolsAdapter()] : [])`),\n * the first call in it other than `import(`.\n */\nfunction callName(code: string): string | undefined {\n const body = code\n .split('\\n')\n .filter((l) => !l.trim().startsWith('//'))\n .join('\\n')\n const leading = /^\\s*([A-Za-z_$][\\w$.]*)\\s*\\(/.exec(body)?.[1]\n if (leading) return leading\n for (const match of body.matchAll(/(?<![\\w$])([A-Za-z_$][\\w$]*)\\s*\\(/g)) {\n if (match[1] !== 'import') return match[1]\n }\n return undefined\n}\n\nconst firstLine = (code: string) =>\n code\n .split('\\n')\n .find((l) => l.trim() && !l.trim().startsWith('//'))\n ?.trim() ?? code\n\nconst lineIndent = (source: string, offset: number) =>\n /^[ \\t]*/.exec(source.slice(source.lastIndexOf('\\n', offset - 1) + 1))![0]\n\nconst indentBlock = (code: string, indent: string) =>\n code\n .split('\\n')\n .map((line) => (line ? indent + line : line))\n .join('\\n')\n\n/** Append `code` to an array literal's elements or an object literal's properties. */\nfunction appendEntry(source: string, array: Node, items: Array<Node | null>, code: string): string {\n const elements = items.filter(Boolean) as Node[]\n const arrayIndent = lineIndent(source, array.start)\n if (elements.length === 0) {\n const inner = indentBlock(`${code},`, `${arrayIndent} `)\n const [open, close] = array.type === 'ObjectExpression' ? ['{', '}'] : ['[', ']']\n return `${source.slice(0, array.start)}${open}\\n${inner}\\n${arrayIndent}${close}${source.slice(array.end)}`\n }\n const last = elements.at(-1)!\n const indent = lineIndent(source, last.start)\n // After the last element's trailing comma when it has one.\n const after = source.slice(last.end, array.end - 1)\n const comma = after.match(/^\\s*,/)\n const at = comma ? last.end + comma[0].length : last.end\n const entry = `\\n${indentBlock(`${code},`, indent)}`\n return comma\n ? source.slice(0, at) + entry + source.slice(at)\n : `${source.slice(0, at)},${entry.replace(/,$/, '')}${source.slice(at)}`\n}\n\nconst SCHEMA_LIBS = ['zod', 'valibot', 'yup'] as const\ntype SchemaLib = (typeof SCHEMA_LIBS)[number]\n\n/**\n * Add a layer's env keys to an existing env schema in `src/config/index.ts`\n * — the `<lib>.object({ ... })` passed to `fromZod` / `fromValibot` /\n * `fromYup` (the one the default export names, when there are several). The\n * wrapper picks the library, and the entries are the integrations for its\n * slot (`env-zod`, …). A file without such a wrapper falls back to its first\n * `x.object({ ... })` and the first of the three libraries it imports. A key\n * the schema already declares is left as it is. When there is no schema\n * object, or the library is unknown, the entries come back as `manual`\n * (zod's, the default library, when the library is unknown).\n */\nexport function wireEnvSchema(\n source: string,\n integrations: readonly Integration[],\n file = 'src/config/index.ts',\n): WireResult {\n const result: WireResult = { source, added: [], present: [], manual: [] }\n const { lib, object } = findEnvSchemaObject(parseSync(file, source).program as unknown as Node)\n const entries = integrations.filter((i) => i.slot === `env-${lib ?? 'zod'}` && i.code)\n if (entries.length === 0) return result\n if (!lib || !object) {\n result.manual.push(...entries)\n return result\n }\n for (const entry of entries) {\n const key = envKeyOf(entry.code!)\n const object = findEnvSchemaObject(\n parseSync(file, result.source).program as unknown as Node,\n ).object!\n const declared = (object.properties as Node[]).some(\n (p) => p.type === 'Property' && (p.key?.name ?? p.key?.value) === key,\n )\n if (declared) {\n result.present.push(key)\n continue\n }\n result.source = appendEntry(result.source, object, object.properties, entry.code!)\n result.added.push(key)\n }\n return result\n}\n\n/** `REDIS_HOST` for `// comment\\nREDIS_HOST: z.string()`. */\nconst envKeyOf = (code: string) => /^\\s*['\"]?(\\w+)['\"]?\\s*:/m.exec(code)?.[1] ?? firstLine(code)\n\n/** The object literal of `x.object({ ... })`, when `node` is that call. */\nconst objectLiteralOf = (node: Node | undefined): Node | undefined =>\n node?.type === 'CallExpression' &&\n node.callee?.type === 'MemberExpression' &&\n node.callee.property?.name === 'object' &&\n node.arguments?.[0]?.type === 'ObjectExpression'\n ? node.arguments[0]\n : undefined\n\n/** The env schema's object literal and the library it is written in; see `wireEnvSchema`. */\nfunction findEnvSchemaObject(program: Node): { lib?: SchemaLib; object?: Node } {\n const body = program.body as Node[]\n // `fromZod` (or its local rename) → 'zod', from `@forinda/kickjs-schema/zod`.\n const wrappers = new Map<string, SchemaLib>()\n for (const lib of SCHEMA_LIBS) {\n const from = `from${lib[0].toUpperCase()}${lib.slice(1)}`\n const imported = body.some(\n (n) =>\n n.type === 'ImportDeclaration' &&\n n.source.value === `@forinda/kickjs-schema/${lib}` &&\n n.specifiers.some((s: Node) => (s.imported?.name ?? s.imported?.value) === from),\n )\n if (imported) wrappers.set(localName(program, `@forinda/kickjs-schema/${lib}`, from), lib)\n }\n\n const wrapped: Array<{ call: Node; lib: SchemaLib; object: Node }> = []\n const objects: Node[] = []\n const visit = (node: unknown): void => {\n if (!node || typeof node !== 'object') return\n if (Array.isArray(node)) return node.forEach(visit)\n const n = node as Node\n const object = objectLiteralOf(n)\n if (object) objects.push(object)\n const lib = n.type === 'CallExpression' ? wrappers.get(n.callee?.name) : undefined\n const inner = objectLiteralOf(n.arguments?.[0])\n if (lib && inner) wrapped.push({ call: n, lib, object: inner })\n for (const key in n) visit(n[key])\n }\n visit(program)\n\n if (wrapped.length > 0) {\n // `export default envSchema` → `const envSchema = fromZod(...)`.\n let target = body.find((n) => n.type === 'ExportDefaultDeclaration')?.declaration as\n | Node\n | undefined\n if (target?.type === 'Identifier') {\n const name = target.name\n target = body\n .map((n) => (n.type === 'ExportNamedDeclaration' ? n.declaration : n))\n .filter((n) => n?.type === 'VariableDeclaration')\n .flatMap((n) => n.declarations as Node[])\n .find((d) => d.id?.name === name)?.init\n }\n const { lib, object } = wrapped.find((w) => w.call === target) ?? wrapped[0]\n return { lib, object }\n }\n const lib = SCHEMA_LIBS.find((name) =>\n body.some((n) => n.type === 'ImportDeclaration' && n.source.value === name),\n )\n return { lib, object: objects[0] }\n}\n\nfunction addProperty(source: string, object: Node, property: string, code: string): string {\n const props = object.properties as Node[]\n const last = props.at(-1)\n const indent = last ? lineIndent(source, last.start) : `${lineIndent(source, object.start)} `\n const block = `${indent}${property}: [\\n${indentBlock(`${code},`, `${indent} `)}\\n${indent}],`\n if (!last) {\n return `${source.slice(0, object.start)}{\\n${block}\\n${lineIndent(source, object.start)}}${source.slice(object.end)}`\n }\n const after = source.slice(last.end, object.end - 1)\n const comma = after.match(/^\\s*,/)\n const at = comma ? last.end + comma[0].length : last.end\n // A one-line `bootstrap({ modules })` becomes multi-line; the project's\n // formatter tidies the rest.\n return `${source.slice(0, at)}${comma ? '' : ','}\\n${block}${source.slice(at)}`\n}\n\n/** Add `spec`'s names to an import from the same module, or a new import after the last one. */\nexport function addImport(source: string, spec: ImportSpec, file = 'src/index.ts'): string {\n const program = parseSync(file, source).program as unknown as Node\n const imports = (program.body as Node[]).filter((n) => n.type === 'ImportDeclaration')\n const existing = imports.find(\n (n) =>\n n.source.value === spec.from &&\n n.importKind !== 'type' &&\n // A side-effect `import 'x'` has nothing to merge into.\n n.specifiers.length > 0 &&\n !n.specifiers.some((s: Node) => s.type === 'ImportNamespaceSpecifier'),\n )\n const names = spec.names ?? []\n\n if (existing) {\n const have = new Set(existing.specifiers.map((s: Node) => s.local?.name))\n const missing = names.filter((name) => !have.has(name))\n if (missing.length === 0) return source\n const named = existing.specifiers.filter((s: Node) => s.type === 'ImportSpecifier')\n if (named.length > 0) {\n const at = named.at(-1).end\n return `${source.slice(0, at)}, ${missing.join(', ')}${source.slice(at)}`\n }\n // Only a default import: `import d from 'x'` → `import d, { a } from 'x'`.\n const def = existing.specifiers[0]\n return `${source.slice(0, def.end)}, { ${missing.join(', ')} }${source.slice(def.end)}`\n }\n\n const parts = [spec.default, names.length ? `{ ${names.join(', ')} }` : undefined].filter(Boolean)\n const line = `import ${parts.join(', ')} from '${spec.from}'`\n const last = imports.at(-1)\n if (!last) return `${line}\\n${source}`\n return `${source.slice(0, last.end)}\\n${line}${source.slice(last.end)}`\n}\n","/**\n * `kick add` wiring — apply a package's scaffold layer to an existing app:\n * its packages join the install, its `.env` lines are added, and its adapter\n * is spliced into the entry file (see `scaffold/wire.ts`).\n */\nimport { execFileSync } from 'node:child_process'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { join, posix } from 'node:path'\n\nimport { writeFileSafe } from '../utils/fs'\nimport { renderLayers, type Integration, type RenderedProject } from '../scaffold/overlay'\nimport { wireEnvSchema, wireIntegrations, type WireResult } from '../scaffold/wire'\n\n/**\n * `kick add` names with a layer. `queue` means BullMQ, as it does in\n * `kick new`; `queue:rabbitmq` / `queue:kafka` pick another provider, which\n * the layer doesn't configure, so they install only.\n */\nexport const FEATURE_LAYERS: Record<string, string> = {\n swagger: 'feature-swagger',\n devtools: 'feature-devtools',\n ws: 'feature-ws',\n queue: 'feature-queue',\n 'queue:bullmq': 'feature-queue',\n storage: 'feature-storage',\n}\n\n/** The layers `packages` bring, rendered — or undefined when none has one. */\nexport function planWiring(packages: readonly string[]): RenderedProject | undefined {\n const layers = [...new Set(packages.map((name) => FEATURE_LAYERS[name]).filter(Boolean))]\n return layers.length > 0 ? renderLayers(layers as string[]) : undefined\n}\n\n/** The entry file to wire: `--entry`, else `src/index.ts` / `src/main.ts`. */\nexport function findEntry(cwd: string, entry?: string): string | undefined {\n const candidates = entry ? [entry] : ['src/index.ts', 'src/main.ts']\n return candidates.find((file) => existsSync(join(cwd, file)))\n}\n\n/**\n * Tracked files among `files` whose working copy differs from the index —\n * edits `git diff` would mix with kick add's. Untracked files (a fresh\n * `kick new`, before its first commit or inside a parent repo) and staged\n * changes don't count: kick add's edits still show as their own diff.\n * Outside a git repository (or without git) nothing counts as dirty.\n */\nexport function dirtyFiles(cwd: string, files: readonly string[]): string[] {\n try {\n const out = execFileSync('git', ['ls-files', '--modified', '--', ...files], {\n cwd,\n encoding: 'utf-8',\n stdio: ['ignore', 'pipe', 'ignore'],\n })\n return [...new Set(out.split('\\n').filter(Boolean))]\n } catch {\n return []\n }\n}\n\n/** The env schema file: `src/config/index.ts` (what `kick new` writes), else an older `src/env.ts`. */\nexport function findEnvSchema(cwd: string): string | undefined {\n return ['src/config/index.ts', 'src/env.ts'].find((file) => existsSync(join(cwd, file)))\n}\n\n/** Add the layers' env keys to the schema in `file` and write it back when it changed. */\nexport async function wireEnv(\n cwd: string,\n file: string,\n integrations: readonly Integration[],\n): Promise<WireResult> {\n const abs = join(cwd, file)\n const source = readFileSync(abs, 'utf-8')\n const result = wireEnvSchema(source, integrations, file)\n if (result.source !== source) await writeFileSafe(abs, result.source)\n return result\n}\n\n/** Source files: never merged line by line — appending a module duplicates its declarations. */\nconst SOURCE = /\\.(?:[cm]?[jt]sx?)$/\n\n/**\n * A layer's source files that already exist with other contents — the app's\n * own `src/adapters/storage.ts`, say. They're left alone, and what imports them isn't\n * wired: merging is the user's call.\n */\nexport function sourceFilesInTheWay(cwd: string, files: ReadonlyMap<string, string>): string[] {\n return [...files]\n .filter(([path, contents]) => {\n const abs = join(cwd, path)\n return SOURCE.test(path) && existsSync(abs) && readFileSync(abs, 'utf-8') !== contents\n })\n .map(([path]) => path)\n}\n\n/**\n * Write a layer's non-entry files. A missing one is created. An existing one\n * only gains the lines it doesn't already have (`.env` keeps its values) —\n * except a source file, which is left as it is (see {@link sourceFilesInTheWay}).\n * Returns the paths created and the existing ones that changed.\n */\nexport async function applyLayerFiles(\n cwd: string,\n files: ReadonlyMap<string, string>,\n): Promise<{ created: string[]; updated: string[] }> {\n const created: string[] = []\n const updated: string[] = []\n for (const [path, contents] of files) {\n const abs = join(cwd, path)\n if (!existsSync(abs)) {\n await writeFileSafe(abs, contents)\n created.push(path)\n continue\n }\n if (SOURCE.test(path)) continue\n const current = readFileSync(abs, 'utf-8')\n const have = new Set(current.split('\\n').map((line) => envKey(line) ?? line))\n const missing = contents\n .split('\\n')\n .filter((line) => line.trim() && !have.has(envKey(line) ?? line))\n if (missing.length === 0) continue\n const sep = current === '' || current.endsWith('\\n') ? '' : '\\n'\n await writeFileSafe(abs, `${current}${sep}${missing.join('\\n')}\\n`)\n updated.push(path)\n }\n return { created, updated }\n}\n\n/**\n * Whether an integration imports one of `paths` (relative to the entry):\n * `./adapters/storage` from `src/index.ts` is `src/adapters/storage.ts`.\n */\nexport function importsAny(\n integration: Integration,\n entry: string,\n paths: readonly string[],\n): boolean {\n const from = integration.import?.from\n if (!from?.startsWith('.')) return false\n const target = posix.join(posix.dirname(entry.replaceAll('\\\\', '/')), from)\n return paths.some((path) => path.replace(SOURCE, '') === target)\n}\n\n/**\n * Layers write their imports for `src/index.ts` (`./adapters/queue`); point\n * them at the same files from `entry` — `../adapters/queue` from `src/app/index.ts`.\n */\nexport function rebaseImports(integrations: readonly Integration[], entry: string): Integration[] {\n const dir = posix.dirname(entry.replaceAll('\\\\', '/'))\n return integrations.map((integration) => {\n const from = integration.import?.from\n if (!from?.startsWith('.')) return integration\n const path = posix.relative(dir, posix.join('src', from))\n return {\n ...integration,\n import: { ...integration.import!, from: path.startsWith('.') ? path : `./${path}` },\n }\n })\n}\n\n/** `REDIS_HOST` for `REDIS_HOST=…`, so an existing value counts as present. */\nconst envKey = (line: string) => /^\\s*([A-Za-z_][\\w]*)\\s*=/.exec(line)?.[1]\n\n/** Splice the integrations into the entry file and write it back when it changed. */\nexport async function wireEntry(\n cwd: string,\n entry: string,\n integrations: readonly Integration[],\n): Promise<WireResult> {\n const abs = join(cwd, entry)\n const source = readFileSync(abs, 'utf-8')\n const result = wireIntegrations(source, integrations, projectVars(cwd), entry)\n if (result.source !== source) await writeFileSafe(abs, result.source)\n return result\n}\n\n/** Fill `{{name}}` / `{{version}}` from the project's package.json. */\nexport function projectVars(cwd: string): (text: string) => string {\n const pkg = readPackageJson(cwd)\n const vars: Record<string, string> = {\n name: String(pkg.name ?? 'app'),\n version: String(pkg.version ?? '0.0.0'),\n }\n return (text) => text.replace(/\\{\\{(\\w+)\\}\\}/g, (all, key) => vars[key] ?? all)\n}\n\nfunction readPackageJson(cwd: string): Record<string, unknown> {\n try {\n return JSON.parse(readFileSync(join(cwd, 'package.json'), 'utf-8'))\n } catch {\n return {}\n }\n}\n\n/** What to paste by hand for entries that couldn't be placed. */\nexport function manualSnippet(entries: readonly Integration[]): string {\n const imports = entries\n .flatMap((e) => (e.import ? [e.import] : []))\n .map((spec) => {\n const parts = [spec.default, spec.names?.length ? `{ ${spec.names.join(', ')} }` : undefined]\n return `import ${parts.filter(Boolean).join(', ')} from '${spec.from}'`\n })\n const code = entries.map((e) => `${e.code},`)\n return [...imports, '', '// in bootstrap({ adapters: [ ... ] }):', ...code].join('\\n')\n}\n","import { execSync } from 'node:child_process'\nimport { existsSync, readFileSync, writeFileSync } from 'node:fs'\nimport { dirname, resolve } from 'node:path'\nimport type { Command } from 'commander'\nimport { loadKickConfig, type PackageManager } from '../config'\nimport { setAllowBuilds } from '../generators/templates/project-config'\nimport { resolvePackageManagerWithSource } from '../utils/package-manager'\n\nexport {\n resolvePackageManager,\n resolvePackageManagerWithSource,\n type PackageManagerSource,\n} from '../utils/package-manager'\nimport {\n applyLayerFiles,\n dirtyFiles,\n findEntry,\n findEnvSchema,\n manualSnippet,\n planWiring,\n projectVars,\n wireEntry,\n wireEnv,\n importsAny,\n rebaseImports,\n sourceFilesInTheWay,\n} from './add-wire'\n\ninterface PackageEntry {\n pkg: string\n peers: string[]\n /**\n * Peers depend on the project's HTTP engine, so they are resolved from\n * {@link resolveAppRuntime} rather than listed statically. Set on the\n * framework package itself: the engine is chosen at `bootstrap({ runtime })`,\n * so a Fastify project must not be handed `express`.\n */\n enginePeers?: boolean\n description: string\n dev?: boolean\n /** Type packages for peers that ship without their own types — installed as dev dependencies. */\n typePeers?: string[]\n /**\n * `true` for packages every project needs (framework + Vite plugin +\n * CLI). `kick new` installs these regardless of options chosen, and\n * future package-removal flows refuse to drop them.\n */\n core?: boolean\n /**\n * Set when the package still installs but should no longer be the\n * default choice. The string is the migration hint shown both in\n * `kick add --list --all` and as a warning when the package is added.\n */\n deprecated?: string\n /**\n * Install-script answers for dependencies this package pulls in.\n * Package managers block or skip unanswered scripts (see approveInstallScripts),\n * so `kick add` and `kick new` record these answers before installing.\n */\n builds?: Record<string, boolean>\n}\n\n/** Registry of KickJS packages and their required peer dependencies */\nexport const PACKAGE_REGISTRY: Record<string, PackageEntry> = {\n // Core (always installed by kick new — required for the framework to run)\n kickjs: {\n pkg: '@forinda/kickjs',\n // Resolved per runtime — see `enginePeers` / ENGINE_PEERS.\n peers: [],\n enginePeers: true,\n description: 'Unified framework: DI, decorators, routing, middleware',\n core: true,\n },\n vite: {\n pkg: '@forinda/kickjs-vite',\n peers: ['vite'],\n description: 'Vite plugin: dev server, HMR, module discovery',\n dev: true,\n core: true,\n },\n cli: {\n pkg: '@forinda/kickjs-cli',\n peers: [],\n description: 'CLI tool and code generators',\n dev: true,\n core: true,\n },\n\n // Schema validation — the validator backing env + DTO + OpenAPI\n // schemas. `@forinda/kickjs-schema` (a core dep) wraps whichever one\n // you pick behind `KickSchema`, but the validator itself is an\n // optional peer of `@forinda/kickjs`, so it must be installed\n // explicitly or the app errors at startup (\"Cannot find module\n // 'zod'\"). `kick new` installs the chosen one; `kick add` lets an\n // existing project add/switch.\n zod: {\n pkg: 'zod',\n peers: [],\n description: 'Zod schema validation (env, DTOs, OpenAPI) — wrap with fromZod()',\n },\n valibot: {\n pkg: 'valibot',\n peers: [],\n description: 'Valibot schema validation — wrap with fromValibot()',\n },\n yup: {\n pkg: 'yup',\n peers: [],\n description: 'Yup schema validation — wrap with fromYup()',\n },\n\n // AI — requires zod (^4) for tool/schema definitions.\n ai: {\n pkg: '@forinda/kickjs-ai',\n peers: ['zod'],\n description: 'AI toolkit — LLM providers, tool definitions from controllers',\n },\n\n // Files — memory, disk, S3 / R2 / MinIO. No SDK peers.\n storage: {\n pkg: '@forinda/kickjs-storage',\n peers: [],\n description: 'File storage — memory, disk, S3-compatible buckets, signed URLs',\n },\n\n // API\n swagger: {\n pkg: '@forinda/kickjs-swagger',\n peers: [],\n description: 'OpenAPI spec + Swagger UI + ReDoc',\n // swagger-ui-dist depends on @scarf/scarf, which has a postinstall script.\n builds: { '@scarf/scarf': true },\n },\n // Database — the dialect adapters now ship as subpaths of\n // `@forinda/kickjs-db` (`/pg`, `/sqlite`, `/mysql`), so each `kick add`\n // pulls the core package plus the one driver you need.\n db: {\n pkg: '@forinda/kickjs-db',\n peers: [],\n description: 'kick/db core — schema DSL, migrations, KickDbClient, customType',\n },\n pg: {\n pkg: '@forinda/kickjs-db',\n peers: ['pg'],\n typePeers: ['@types/pg'],\n description: 'kick/db + PostgreSQL driver (use @forinda/kickjs-db/pg)',\n },\n sqlite: {\n pkg: '@forinda/kickjs-db',\n peers: ['better-sqlite3'],\n // A native addon — its install script compiles or downloads the binary,\n // and pnpm 10+ fails the install (ERR_PNPM_IGNORED_BUILDS) until it's allowed.\n builds: { 'better-sqlite3': true },\n typePeers: ['@types/better-sqlite3'],\n description: 'kick/db + SQLite driver (use @forinda/kickjs-db/sqlite)',\n },\n mysql: {\n pkg: '@forinda/kickjs-db',\n peers: ['mysql2'],\n description: 'kick/db + MySQL driver (use @forinda/kickjs-db/mysql)',\n },\n\n // Real-time\n ws: {\n pkg: '@forinda/kickjs-ws',\n peers: ['ws'],\n description: 'WebSocket with @WsController decorators',\n },\n\n // DevTools\n devtools: {\n pkg: '@forinda/kickjs-devtools',\n peers: ['ws'],\n description: 'Development dashboard — routes, DI, metrics, health',\n dev: true,\n },\n\n // Queue\n queue: {\n pkg: '@forinda/kickjs-queue',\n peers: [],\n description: 'Queue adapter (BullMQ/RabbitMQ/Kafka)',\n },\n 'queue:bullmq': {\n pkg: '@forinda/kickjs-queue',\n peers: ['bullmq', 'ioredis'],\n // bullmq → msgpackr → msgpackr-extract (optional native addon). msgpackr\n // falls back to JS without it, so the script is declined — but it must be\n // answered, or pnpm 10+ fails the install (ERR_PNPM_IGNORED_BUILDS).\n builds: { 'msgpackr-extract': false },\n description: 'Queue with BullMQ + Redis',\n },\n 'queue:rabbitmq': {\n pkg: '@forinda/kickjs-queue',\n peers: ['amqplib'],\n description: 'Queue with RabbitMQ',\n },\n 'queue:kafka': {\n pkg: '@forinda/kickjs-queue',\n peers: ['kafkajs'],\n description: 'Queue with Kafka',\n },\n 'queue:redis-pubsub': {\n pkg: '@forinda/kickjs-queue',\n peers: ['ioredis'],\n description: 'Lightweight pub/sub via Redis (no persistence)',\n },\n\n // MCP — Model Context Protocol server\n mcp: {\n pkg: '@forinda/kickjs-mcp',\n peers: ['@modelcontextprotocol/server'],\n description: 'Model Context Protocol server — expose @Controller endpoints as AI tools',\n },\n\n // Testing\n testing: {\n pkg: '@forinda/kickjs-testing',\n peers: [],\n description: 'Test utilities and TestModule builder',\n dev: true,\n },\n}\n\n/**\n * Headline `kick add` packages shown after scaffolding — derived from\n * {@link PACKAGE_REGISTRY} so it can never advertise a deprecated package (the\n * old hardcoded list included auth / drizzle / prisma, all three since removed).\n * Excludes core packages\n * (already installed), deprecated ones, `:` sub-variants (e.g. `queue:bullmq`),\n * and the db-dialect / schema-lib duplicates that clutter a one-line summary.\n * `upload` isn't in the registry (it installs the runtime's multipart driver,\n * see {@link UPLOAD_DRIVERS}) but is a `kick add` name, so it's listed too.\n * `kick add --list` shows the full catalog.\n */\nexport const AVAILABLE_ADD_PACKAGES = Object.entries(PACKAGE_REGISTRY)\n .filter(\n ([name, entry]) =>\n !entry.core &&\n !entry.deprecated &&\n !name.includes(':') &&\n !['pg', 'sqlite', 'mysql', 'zod', 'valibot', 'yup'].includes(name),\n )\n .map(([name]) => name)\n .concat('upload')\n .join(', ')\n\n/**\n * The `upload` catalog name is special — file uploads ship inside\n * `@forinda/kickjs` itself, so there's no package to install. What an app\n * needs is the multipart DRIVER for its HTTP runtime, and that differs per\n * engine. `planAddPackages` resolves `upload` against the configured runtime\n * (see {@link KickConfig.runtime}); `kick doctor` validates the same mapping.\n */\n/**\n * Engine peers per runtime — the same set `kick new` scaffolds for the chosen\n * engine (`generators/templates/project-config.ts`). `@forinda/kickjs` declares\n * all three as optional peers; which ones a project actually needs is decided\n * by `bootstrap({ runtime })`, so installing them is a runtime-dependent\n * question, not a static dependency.\n */\nexport const ENGINE_PEERS: Record<'express' | 'fastify' | 'h3', readonly string[]> = {\n express: ['express'],\n // `serve-static` rather than express for static files — no express dependency.\n fastify: ['fastify', '@fastify/middie', 'serve-static'],\n // Pinned so a later h3 v3 is not picked up unseen.\n h3: ['h3@^2', 'serve-static'],\n}\n\nexport const UPLOAD_DRIVERS: Record<\n 'express' | 'fastify' | 'h3',\n { prod?: string; dev?: string; note: string }\n> = {\n express: {\n prod: 'multer',\n dev: '@types/multer',\n note: 'Express uploads use multer (memory/disk storage, ctx.file / ctx.files).',\n },\n fastify: {\n prod: '@fastify/multipart',\n note: 'Fastify uploads use @fastify/multipart (buffered into ctx.file / ctx.files).',\n },\n h3: {\n note: 'h3 parses multipart natively (readMultipartFormData) — no driver to install.',\n },\n}\n\nexport type AppRuntime = 'express' | 'fastify' | 'h3'\n\n/**\n * Resolve the project's HTTP runtime: the `runtime` field in kick.config\n * (authoritative — `kick new` writes it), falling back to sniffing installed\n * deps in the nearest package.json (`fastify` → fastify, `h3` → h3), else\n * `express` (the default engine). Lets `kick add upload` / `kick doctor` pick\n * the engine-correct multipart driver even in projects scaffolded before the\n * `runtime` field existed.\n */\n/** Validate `--runtime`, returning undefined when absent and exiting on a bad value. */\nexport function parseRuntimeFlag(value: unknown): AppRuntime | undefined {\n if (value === undefined) return undefined\n if (value === 'express' || value === 'fastify' || value === 'h3') return value\n throw new Error(`Invalid --runtime '${String(value)}'. Expected express, fastify or h3.`)\n}\n\nexport async function resolveAppRuntime(cwd = process.cwd()): Promise<AppRuntime> {\n return (await resolveAppRuntimeDetailed(cwd)).runtime\n}\n\n/**\n * As {@link resolveAppRuntime}, but says whether the answer was a guess.\n *\n * `kick.config.ts`'s `runtime` is authoritative and never ambiguous. Sniffing\n * is, so callers that act on the result — installing engine peers — surface the\n * ambiguity instead of silently picking.\n */\nexport async function resolveAppRuntimeDetailed(\n cwd = process.cwd(),\n): Promise<RuntimeDetection & { fromConfig: boolean }> {\n const config = await loadKickConfig(cwd)\n const fromConfig = (config as { runtime?: AppRuntime } | null)?.runtime\n if (fromConfig === 'express' || fromConfig === 'fastify' || fromConfig === 'h3') {\n return { runtime: fromConfig, candidates: [fromConfig], ambiguous: false, fromConfig: true }\n }\n return { ...detectRuntimeFromDepsDetailed(cwd), fromConfig: false }\n}\n\n/** Sniff the runtime from installed deps when kick.config has no `runtime`. */\n/**\n * Sniff result, with enough detail for a caller to say when it is guessing.\n *\n * `ambiguous` means more than one engine is installed and nothing settles which\n * one the app boots on. That happens legitimately — a project on Express with\n * Fastify in devDependencies for a benchmark — and the old precedence order\n * (fastify first, whether prod or dev) answered `fastify` there, which installed\n * the wrong engine peers.\n */\nexport interface RuntimeDetection {\n runtime: AppRuntime\n /** Engines found, in `dependencies` then `devDependencies`. */\n candidates: AppRuntime[]\n ambiguous: boolean\n}\n\nconst ENGINE_BY_PACKAGE: ReadonlyArray<readonly [string, AppRuntime]> = [\n ['express', 'express'],\n ['fastify', 'fastify'],\n ['h3', 'h3'],\n]\n\n/** Sniff the runtime from installed deps when kick.config has no `runtime`. */\nexport function detectRuntimeFromDepsDetailed(cwd = process.cwd()): RuntimeDetection {\n const dir = findUp('package.json', cwd)\n if (!dir) return { runtime: 'express', candidates: [], ambiguous: false }\n\n let prod: Record<string, unknown> = {}\n let dev: Record<string, unknown> = {}\n try {\n const pkg = JSON.parse(readFileSync(resolve(dir, 'package.json'), 'utf-8'))\n prod = (pkg.dependencies ?? {}) as Record<string, unknown>\n dev = (pkg.devDependencies ?? {}) as Record<string, unknown>\n } catch {\n return { runtime: 'express', candidates: [], ambiguous: false }\n }\n\n const inProd = ENGINE_BY_PACKAGE.filter(([p]) => p in prod).map(([, r]) => r)\n const inDev = ENGINE_BY_PACKAGE.filter(([p]) => p in dev && !(p in prod)).map(([, r]) => r)\n const candidates = [...inProd, ...inDev]\n\n // A runtime dependency outranks a dev one: you deploy on what you ship. That\n // IS a resolution, so it is not ambiguous — reporting otherwise made the\n // refusal below block the exact case this rule exists to allow (an Express\n // app keeping fastify in devDependencies for a benchmark).\n if (inProd.length === 1) return { runtime: inProd[0], candidates, ambiguous: false }\n if (inProd.length === 0 && inDev.length === 1) {\n return { runtime: inDev[0], candidates, ambiguous: false }\n }\n if (candidates.length === 0) return { runtime: 'express', candidates, ambiguous: false }\n\n // Two or more engines at the same level — nothing here can tell them apart.\n // Default to the framework default and let the caller say it is guessing.\n return { runtime: 'express', candidates, ambiguous: true }\n}\n\n/** Back-compat wrapper — the runtime only. */\nexport function detectRuntimeFromDeps(cwd = process.cwd()): AppRuntime {\n return detectRuntimeFromDepsDetailed(cwd).runtime\n}\n\n/**\n * Walk up from `fromDir` to filesystem root, returning the first\n * directory that contains `name`. Lets monorepo sub-packages pick up\n * lockfiles and `packageManager` fields living at the workspace root.\n */\nfunction findUp(name: string, fromDir = process.cwd()): string | null {\n let current = fromDir\n while (true) {\n if (existsSync(resolve(current, name))) return current\n const parent = dirname(current)\n if (parent === current) return null\n current = parent\n }\n}\n\n/**\n * Print the package catalog. By default shows just the three core\n * packages every project always has — the optional list churns\n * (packages added, deprecated, removed) and a long enumeration in CLI\n * output / docs goes stale within a release. Pass `all = true` to dump\n * everything; that's what `kick add --list --all` triggers when an\n * adopter genuinely wants the live catalog.\n */\nexport function printPackageList(all = false, runtime?: 'express' | 'fastify' | 'h3'): void {\n const entries = Object.entries(PACKAGE_REGISTRY)\n const maxName = Math.max(...entries.map(([k]) => k.length))\n const core = entries.filter(([, info]) => info.core)\n const optional = entries.filter(([, info]) => !info.core)\n\n const formatRow = ([name, info]: [string, PackageEntry]): string => {\n const padded = name.padEnd(maxName + 2)\n // Engine peers depend on the runtime, so name it rather than printing a\n // list that would be wrong for two projects out of three.\n const resolved = info.enginePeers\n ? [...info.peers, ...ENGINE_PEERS[runtime ?? 'express']]\n : info.peers\n const engineNote = info.enginePeers ? ` [${runtime ?? 'express'} engine]` : ''\n const peers = resolved.length ? ` (+ ${resolved.join(', ')})${engineNote}` : ''\n const deprecated = info.deprecated ? ` [DEPRECATED — ${info.deprecated}]` : ''\n return ` ${padded} ${info.description}${peers}${deprecated}`\n }\n\n console.log('\\n Core packages (always installed by `kick new`):\\n')\n for (const row of core) console.log(formatRow(row))\n\n if (all) {\n console.log('\\n Optional packages (add as needed):\\n')\n for (const row of optional) console.log(formatRow(row))\n } else {\n console.log(`\\n Plus ${optional.length} optional packages (swagger, db, queue, …).`)\n console.log(' Run `kick add --list --all` for the full catalog.')\n }\n\n console.log('\\n Usage: kick add ai db swagger')\n console.log(' kick add queue:bullmq')\n console.log(' kick add upload # installs the multipart driver for your runtime')\n console.log()\n}\n\n/** Build tools every template installs: swc compiles the decorators, esbuild is Vite's. */\nexport const TEMPLATE_BUILDS: Record<string, boolean> = { '@swc/core': true, esbuild: true }\n\n/**\n * Record install-script answers where `pm` reads them, in `dir`:\n *\n * - pnpm 10+: pnpm-workspace.yaml, in both approval formats (see setAllowBuilds).\n * Unanswered scripts are skipped with a warning before pnpm 11; pnpm 11 fails\n * the install and every later `pnpm exec` with ERR_PNPM_IGNORED_BUILDS.\n * - npm 11.19+: `allowScripts` in package.json. Unanswered scripts are skipped\n * with a warning.\n * - bun: `trustedDependencies` in package.json. Untrusted scripts are skipped.\n * Only approvals are written; bun has no deny entry.\n * - yarn runs dependency scripts, so there is nothing to write.\n *\n * Existing answers win: a scaffold or `kick add` never overrides a decision\n * already in the file. Returns the file it changed, if any.\n */\nexport function approveInstallScripts(\n pm: PackageManager,\n dir: string,\n builds: Record<string, boolean>,\n): string | undefined {\n if (pm === 'pnpm') {\n const file = resolve(dir, 'pnpm-workspace.yaml')\n const before = existsSync(file) ? readFileSync(file, 'utf-8') : ''\n const after = setAllowBuilds(before, builds)\n if (after === before) return undefined\n writeFileSync(file, after)\n return file\n }\n if (pm !== 'npm' && pm !== 'bun') return undefined\n\n const file = resolve(dir, 'package.json')\n if (!existsSync(file)) return undefined\n const pkg = JSON.parse(readFileSync(file, 'utf-8'))\n let changed = false\n if (pm === 'npm') {\n const allow: Record<string, boolean> = pkg.allowScripts ?? {}\n for (const [name, value] of Object.entries(builds)) {\n // npm also accepts version-pinned keys (`esbuild@0.28.2`).\n if (Object.keys(allow).some((key) => key === name || key.startsWith(`${name}@`))) continue\n allow[name] = value\n changed = true\n }\n pkg.allowScripts = allow\n } else {\n const trusted: string[] = pkg.trustedDependencies ?? []\n for (const [name, value] of Object.entries(builds)) {\n if (!value || trusted.includes(name)) continue\n trusted.push(name)\n changed = true\n }\n pkg.trustedDependencies = trusted\n }\n if (!changed) return undefined\n writeFileSync(file, `${JSON.stringify(pkg, null, 2)}\\n`)\n return file\n}\n\n/**\n * Where `pm` reads install-script answers from: the workspace root when the\n * project is a workspace member (fullstack server/), else the current directory.\n */\nfunction installRoot(pm: PackageManager): string {\n if (pm === 'pnpm') return findUp('pnpm-workspace.yaml') ?? process.cwd()\n for (let dir = process.cwd(); ; dir = dirname(dir)) {\n try {\n if (JSON.parse(readFileSync(resolve(dir, 'package.json'), 'utf-8')).workspaces) return dir\n } catch {\n // no package.json here, or not JSON — keep walking\n }\n if (dirname(dir) === dir) return process.cwd()\n }\n}\n\n/** Merged install-script answers for catalog entries (unknown names skipped). */\nexport function buildsFor(packages: string[]): Record<string, boolean> {\n return Object.assign({}, ...packages.map((name) => PACKAGE_REGISTRY[name]?.builds ?? {}))\n}\n\nexport interface AddPlan {\n prodDeps: string[]\n devDeps: string[]\n unknown: string[]\n /** Deprecation notices for requested entries — print, then install anyway. */\n warnings: string[]\n /** Informational notes (e.g. the upload driver chosen for the runtime). */\n notices: string[]\n}\n\n/**\n * Pure resolution step for `kick add` — maps requested catalog names to\n * the npm packages (plus peers) to install, split prod/dev. Kept free\n * of I/O so the catalog rules (dev defaults, deprecations, unknown\n * handling) are unit-testable without spawning a package manager.\n */\nexport function planAddPackages(\n packages: string[],\n forceDev: boolean,\n runtime: AppRuntime = 'express',\n): AddPlan {\n const prodDeps = new Set<string>()\n const devDeps = new Set<string>()\n const unknown: string[] = []\n const warnings: string[] = []\n const notices: string[] = []\n\n for (const name of packages) {\n // `upload` isn't a package — it's the runtime's multipart driver. File\n // uploads ship in @forinda/kickjs; only the engine backend needs adding.\n if (name === 'upload') {\n const driver = UPLOAD_DRIVERS[runtime]\n notices.push(`upload (${runtime}): ${driver.note}`)\n if (driver.prod) (forceDev ? devDeps : prodDeps).add(driver.prod)\n if (driver.dev) devDeps.add(driver.dev)\n continue\n }\n\n const entry = PACKAGE_REGISTRY[name]\n if (!entry) {\n unknown.push(name)\n continue\n }\n if (entry.deprecated) {\n warnings.push(`'${name}' (${entry.pkg}) is deprecated — ${entry.deprecated}`)\n }\n const target = forceDev || entry.dev ? devDeps : prodDeps\n target.add(entry.pkg)\n for (const peer of entry.peers) {\n target.add(peer)\n }\n for (const types of entry.typePeers ?? []) devDeps.add(types)\n if (entry.enginePeers) {\n const enginePeers = ENGINE_PEERS[runtime]\n for (const peer of enginePeers) target.add(peer)\n notices.push(`${name} (${runtime}): engine peers ${enginePeers.join(', ')}`)\n }\n }\n\n return { prodDeps: [...prodDeps], devDeps: [...devDeps], unknown, warnings, notices }\n}\n\nexport function registerListCommand(program: Command): void {\n program\n .command('list')\n .alias('ls')\n .description('List KickJS packages (core only; pair with --all for the full catalog)')\n .option('--all', 'Include the full optional catalog')\n .option('--runtime <engine>', 'HTTP engine to show peers for: express | fastify | h3')\n .action(async (opts: { all?: boolean; runtime?: string }) => {\n printPackageList(\n Boolean(opts.all),\n parseRuntimeFlag(opts.runtime) ?? (await resolveAppRuntime()),\n )\n })\n}\n\nexport function registerAddCommand(program: Command): void {\n program\n .command('add [packages...]')\n .description('Add KickJS packages with their required dependencies')\n .option('--pm <manager>', 'Package manager override')\n .option('-D, --dev', 'Install as dev dependency')\n .option('--list', 'List packages (core only by default; pair with --all)')\n .option(\n '--runtime <engine>',\n 'HTTP engine for peer resolution: express | fastify | h3 (overrides kick.config.ts)',\n )\n .option('--all', 'When listing, include the full optional catalog')\n .option('--no-wire', 'Install only — do not add adapters to the entry file or .env')\n .option('--entry <file>', 'Entry file to wire (default: src/index.ts, then src/main.ts)')\n .option('-f, --force', 'Wire even when the files it edits have uncommitted changes')\n .action(async (packages: string[], opts: any) => {\n // List mode\n if (opts.list || packages.length === 0) {\n printPackageList(\n Boolean(opts.all),\n parseRuntimeFlag(opts.runtime) ?? (await resolveAppRuntime()),\n )\n return\n }\n\n const { pm, source } = await resolvePackageManagerWithSource(opts.pm)\n console.log(`\\n Using ${pm} (resolved from ${source})`)\n // Resolve the runtime so `kick add upload` installs the right multipart\n // driver (express → multer, fastify → @fastify/multipart, h3 → none) and\n // the framework gets the engine peers it actually runs on.\n const fromFlag = parseRuntimeFlag(opts.runtime)\n const detection = await resolveAppRuntimeDetailed(process.cwd())\n const runtime = fromFlag ?? detection.runtime\n\n // Two engines at the same dependency level and nothing to break the tie.\n // Installing writes package.json and node_modules, so guessing here\n // leaves an adopter to undo it by hand — refuse instead, with both ways\n // to say what the app actually boots on.\n if (!fromFlag && detection.ambiguous) {\n console.error(\n `\\n Cannot tell which HTTP engine this app boots on: found ` +\n `${detection.candidates.join(', ')} in package.json.\\n` +\n `\\n Installing engine peers for the wrong one is worse than not installing them, so:\\n` +\n ` • set \\`runtime: '<engine>'\\` in kick.config.ts (permanent, also fixes kick doctor), or\\n` +\n ` • pass --runtime <${detection.candidates.join('|')}> for this command\\n`,\n )\n process.exitCode = 1\n return\n }\n const plan = planAddPackages(packages, Boolean(opts.dev), runtime)\n const { unknown, warnings, notices } = plan\n let { prodDeps, devDeps } = plan\n\n // Packages with a scaffold layer (swagger, devtools, ws, queue, storage) are also\n // wired: their adapter goes into the entry file and their .env lines in.\n // The entry file imports them, so they install as regular dependencies\n // with the peers the layer uses — except devtools, imported only under\n // `kick dev`, which stays a dev dependency.\n const cwd = process.cwd()\n // A mistyped --entry would otherwise install first and only then say\n // there was nothing to wire.\n if (opts.entry && !existsSync(resolve(cwd, opts.entry))) {\n console.error(`\\n --entry ${opts.entry} does not exist.\\n`)\n process.exitCode = 1\n return\n }\n const wiring = opts.wire === false ? undefined : planWiring(packages)\n const entry = wiring ? findEntry(cwd, opts.entry) : undefined\n if (wiring && entry) wiring.integrations = rebaseImports(wiring.integrations, entry)\n const envEntries = wiring?.integrations.filter((i) => i.slot?.startsWith('env-')) ?? []\n const envSchema = envEntries.length > 0 ? findEnvSchema(cwd) : undefined\n if (wiring) {\n prodDeps = [...new Set([...prodDeps, ...wiring.dependencies])]\n devDeps = [\n ...new Set([...devDeps, ...wiring.devDependencies].filter((d) => !prodDeps.includes(d))),\n ]\n // Wiring edits files in place; refuse over uncommitted work there, so\n // the change stays reviewable (and revertable) as its own diff.\n const dirty = dirtyFiles(cwd, [\n ...(entry ? [entry] : []),\n ...(envSchema ? [envSchema] : []),\n ...wiring.files.keys(),\n ])\n if (dirty.length > 0 && !opts.force) {\n console.error(\n `\\n ${dirty.join(', ')} ${dirty.length === 1 ? 'has' : 'have'} uncommitted changes, ` +\n `and kick add would edit ${dirty.length === 1 ? 'it' : 'them'}.\\n` +\n ` Commit, stage (git add) or stash them first, rerun with --force to edit anyway, ` +\n `or with --no-wire to install only.\\n`,\n )\n process.exitCode = 1\n return\n }\n }\n\n for (const warning of warnings) {\n console.warn(`\\n WARNING: ${warning}`)\n }\n\n for (const notice of notices) {\n console.log(`\\n ${notice}`)\n }\n\n if (unknown.length > 0) {\n console.log(`\\n Unknown packages: ${unknown.join(', ')}`)\n console.log(' Run \"kick add --list\" to see available packages.\\n')\n if (prodDeps.length === 0 && devDeps.length === 0) return\n }\n\n // Answer install-script approvals before installing, so the package\n // manager doesn't block the scripts these packages bring in.\n const builds = { ...buildsFor(packages), ...wiring?.builds }\n if (Object.keys(builds).length > 0) {\n const file = approveInstallScripts(pm, installRoot(pm), builds)\n if (file) console.log(`\\n Approved install scripts in ${file}`)\n }\n\n let installed = true\n // Install production dependencies\n if (prodDeps.length > 0) {\n const deps = prodDeps\n const cmd = `${pm} add ${deps.join(' ')}`\n console.log(`\\n Installing ${deps.length} dependency(ies):`)\n for (const dep of deps) console.log(` + ${dep}`)\n console.log()\n try {\n execSync(cmd, { stdio: 'inherit' })\n } catch {\n installed = false\n console.log(`\\n Installation failed. Run manually:\\n ${cmd}\\n`)\n }\n }\n\n // Install dev dependencies\n if (devDeps.length > 0) {\n const deps = devDeps\n const cmd = `${pm} add -D ${deps.join(' ')}`\n console.log(`\\n Installing ${deps.length} dev dependency(ies):`)\n for (const dep of deps) console.log(` + ${dep} (dev)`)\n console.log()\n try {\n execSync(cmd, { stdio: 'inherit' })\n } catch {\n installed = false\n console.log(`\\n Installation failed. Run manually:\\n ${cmd}\\n`)\n }\n }\n\n if (wiring) {\n if (!installed) {\n console.log(' Skipped wiring — the install did not finish.\\n')\n } else {\n // The app's own file where the layer would write one (src/adapters/storage.ts):\n // keep it, and leave what imports it for the user to wire.\n const kept = sourceFilesInTheWay(cwd, wiring.files)\n const { created, updated } = await applyLayerFiles(cwd, wiring.files)\n for (const path of created) console.log(` Created ${path}`)\n for (const path of updated) console.log(` Updated ${path}`)\n const blocked = entry ? wiring.integrations.filter((i) => importsAny(i, entry, kept)) : []\n const toWire = wiring.integrations.filter((i) => !blocked.includes(i))\n const result = entry ? await wireEntry(cwd, entry, toWire) : undefined\n for (const name of result?.added ?? []) console.log(` Added ${name} to ${entry}`)\n for (const name of result?.present ?? []) console.log(` ${name} is already in ${entry}`)\n // The env keys the adapter reads go into the env schema, typed and validated.\n const env = envSchema ? await wireEnv(cwd, envSchema, envEntries) : undefined\n if (env?.added.length) console.log(` Declared ${env.added.join(', ')} in ${envSchema}`)\n const envManual = env ? env.manual : envEntries.filter((i) => i.slot === 'env-zod')\n if (envManual.length > 0) {\n console.log(\n `\\n ${envSchema ? `Could not find the env schema object in ${envSchema}` : 'No env schema (src/config/index.ts) found'}` +\n ' — declare these keys in it yourself:\\n',\n )\n console.log(\n envManual\n .map((i) => `${i.code},`)\n .join('\\n')\n .replace(/^/gm, ' '),\n )\n console.log()\n }\n const fill = projectVars(cwd)\n const manual = result\n ? result.manual\n : wiring.integrations\n .filter((i) => i.slot && i.code && !i.slot.startsWith('env-'))\n .map((i) => ({ ...i, code: fill(i.code!) }))\n if (kept.length > 0) {\n const fillBlocked = blocked.map((i) => ({ ...i, code: fill(i.code ?? '') }))\n console.log(\n `\\n ${kept.join(', ')} already exist${kept.length === 1 ? 's' : ''} — left as ${kept.length === 1 ? 'it is' : 'they are'}.` +\n ' Merge in what the layer needs, then wire it yourself:\\n',\n )\n console.log(`${manualSnippet(fillBlocked)}`.replace(/^/gm, ' '))\n console.log()\n }\n if (manual.length > 0) {\n console.log(\n `\\n ${entry ? `Could not find bootstrap({ adapters: [...] }) in ${entry}` : 'No entry file found'}` +\n ' — add this yourself:\\n',\n )\n console.log(manualSnippet(manual).replace(/^/gm, ' '))\n console.log()\n }\n }\n }\n\n if (installed) {\n console.log(' Done!\\n')\n } else {\n console.log(' Finished with errors — the install above did not complete.\\n')\n process.exitCode = 1\n }\n })\n}\n","import { join, dirname } from 'node:path'\nimport { execSync } from 'node:child_process'\nimport { randomBytes } from 'node:crypto'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\nimport { writeFileSafe } from '../utils/fs'\nimport { execBin, runScript, type PackageManager } from '../config'\nimport { fillVars, renderLayers, TEMPLATES_DIR, type Integration } from '../scaffold/overlay'\nimport { generateDeploy, type DeployTarget } from './deploy'\nimport { captureCommand, captureCommandAsync } from '../utils/shell'\nimport { generatePackageJson, packageManagerSpec, yarnrc } from './templates/project-config'\nimport {\n AVAILABLE_ADD_PACKAGES,\n TEMPLATE_BUILDS,\n approveInstallScripts,\n buildsFor,\n} from '../commands/add'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n\n/** Template vars for the commands a project's docs print, spelled for `pm`. */\nexport function commandVars(pm: PackageManager): Record<string, string> {\n return {\n kick: execBin(pm, 'kick'),\n runDev: runScript(pm, 'dev'),\n runBuild: runScript(pm, 'build'),\n runStart: runScript(pm, 'start'),\n runTest: runScript(pm, 'test'),\n }\n}\n\n/**\n * The CLI's own package.json sits one level up from the bundle\n * (`dist/project-*.mjs`) but two levels up from this source file\n * (`src/generators/project.ts`). Checking both is what lets this module be\n * imported from a test at all — reading only the bundle-relative path threw\n * ENOENT the moment anything imported it from source, which is why the\n * version-resolution path shipped untested.\n */\nconst cliPkg = JSON.parse(\n readFileSync(\n [join(__dirname, '..', 'package.json'), join(__dirname, '..', '..', 'package.json')].find(\n existsSync,\n )!,\n 'utf-8',\n ),\n)\n\n/**\n * Sibling `@forinda/kickjs-*` packages whose versions are resolved\n * independently when scaffolding a new project. Each entry is queried\n * via `npm view <name> version`; failure falls back to `latest`\n * (see `fallbackRange`).\n *\n * Per-package independent versioning landed with changesets — before\n * that, every sibling shipped in lockstep with the CLI so a single\n * pin was correct. Now `@forinda/kickjs@5.5.0` may pair with\n * `@forinda/kickjs-cli@5.4.2` and `@forinda/kickjs-swagger@5.3.1`;\n * pinning them all to the CLI's version under-installs adopters.\n */\nexport const SIBLING_PACKAGES = [\n '@forinda/kickjs',\n '@forinda/kickjs-cli',\n '@forinda/kickjs-schema',\n '@forinda/kickjs-vite',\n '@forinda/kickjs-swagger',\n '@forinda/kickjs-ws',\n '@forinda/kickjs-queue',\n '@forinda/kickjs-devtools',\n '@forinda/kickjs-testing',\n '@forinda/kickjs-client',\n '@forinda/kickjs-inertia',\n '@forinda/kickjs-storage',\n] as const\n\n/**\n * Third-party dependencies the templates install, resolved at scaffold time\n * instead of pinned here — a pin means every React, Vitest or oxlint release\n * needs a CLI release to reach new projects, and the pins drift apart (the\n * fullstack web app shipped vite ^7 while the server template was on ^8).\n *\n * `cap` is the range a package may float within, for the ones where a new\n * major changes what the templates generate or what KickJS peers on: the\n * engine packages, the schema libraries, and the toolchain the generated\n * configs are written against. Everything else tracks `latest`.\n *\n * The value is the fallback: what gets written when `npm view` says nothing\n * (offline, registry down), so a scaffold without network still installs.\n */\nexport const THIRD_PARTY_PACKAGES: Record<string, { fallback: string; cap?: string }> = {\n // Frontend — the fullstack web app. Nothing the template writes is\n // version-specific (`createRoot`, JSX, a plugin call), so these float.\n react: { fallback: '^19.0.0' },\n 'react-dom': { fallback: '^19.0.0' },\n '@types/react': { fallback: '^19.0.0' },\n '@types/react-dom': { fallback: '^19.0.0' },\n '@vitejs/plugin-react': { fallback: '^5.0.0' },\n // Inertia template — the client adapter and its protocol types.\n '@inertiajs/react': { fallback: '^3.9.0', cap: '^3' },\n '@inertiajs/core': { fallback: '^3.9.0', cap: '^3' },\n // Toolchain.\n '@types/node': { fallback: '^25.0.0' },\n '@types/supertest': { fallback: '^7.2.1' },\n supertest: { fallback: '^7.2.2' },\n vitest: { fallback: '^4.1.2' },\n '@swc/core': { fallback: '^1.15.21' },\n 'unplugin-swc': { fallback: '^1.5.9' },\n oxfmt: { fallback: '^0.65.0' },\n oxlint: { fallback: '^1.80.0' },\n // Capped: an optional peer of @forinda/kickjs at this major. Uncapped,\n // `latest` (18) installed with an unmet-peer warning on every scaffold.\n dotenv: { fallback: '^17.3.1', cap: '^17' },\n 'reflect-metadata': { fallback: '^0.2.2' },\n // Capped — a new major here breaks the generated project, not just its deps.\n // vite: `@forinda/kickjs-vite` peers on it and the generated vite.config.ts\n // is written against this major.\n vite: { fallback: '^8.0.3', cap: '^8' },\n // typescript: the generated tsconfig.json targets this major.\n typescript: { fallback: '^7.0.2', cap: '^7' },\n '@typescript/typescript6': { fallback: '^6.0.2', cap: '^6' },\n // HTTP engines: `bootstrap({ runtime })` peers on the major.\n express: { fallback: '^5.1.0', cap: '^5' },\n '@types/express': { fallback: '^5.0.6', cap: '^5' },\n fastify: { fallback: '^5.0.0', cap: '^5' },\n '@fastify/middie': { fallback: '^9.0.0', cap: '^9' },\n h3: { fallback: '^2.0.2', cap: '^2' },\n 'serve-static': { fallback: '^2.2.0', cap: '^2' },\n // Schema libraries: `@forinda/kickjs-schema` adapts one major each.\n zod: { fallback: '^4.3.6', cap: '^4' },\n valibot: { fallback: '^1.4.1', cap: '^1' },\n // Valibot's JSON Schema converter — Swagger needs it for Valibot schemas.\n '@valibot/to-json-schema': { fallback: '^1.8.0', cap: '^1' },\n yup: { fallback: '^1.7.1', cap: '^1' },\n // Peers of the optional packages (`--packages ws,queue`), capped at the\n // major those packages peer on.\n ws: { fallback: '^8.18.0', cap: '^8' },\n bullmq: { fallback: '^5.0.0', cap: '^5' },\n ioredis: { fallback: '^5.0.0', cap: '^5' },\n}\n\n/**\n * Newest version matching `spec`. A bare name asks for the `latest` tag and\n * npm prints one version; a range prints every match as JSON, newest last.\n */\nexport function parseNpmVersion(output: string | null): string | null {\n if (!output) return null\n const trimmed = output.trim()\n if (/^\\d+\\.\\d+\\.\\d+/.test(trimmed)) return trimmed.split(/\\s/)[0]!\n try {\n const parsed = JSON.parse(trimmed) as unknown\n const list = Array.isArray(parsed) ? parsed : [parsed]\n const versions = list.filter((v): v is string => typeof v === 'string')\n return versions.length > 0 ? versions[versions.length - 1]! : null\n } catch {\n return null\n }\n}\n\n/**\n * Range to write when `npm view <name> version` gives us nothing.\n *\n * It must never be the CLI's own version. Sibling packages version\n * independently, so `@forinda/kickjs-vite@^${cliVersion}` names a release\n * that does not exist — the scaffold then dies at install time with\n * `npm error 404 '@forinda/kickjs-vite@^6.14.1' is not in this registry`,\n * which is worse than the under-install this fallback was meant to avoid.\n * `latest` is the one range that is always resolvable and always current.\n *\n * The CLI itself is the exception: its version IS the CLI's version, and\n * pinning it keeps a scaffold reproducible against the CLI that made it.\n */\nfunction fallbackRange(name: string): string {\n return name === '@forinda/kickjs-cli' ? `^${cliPkg.version}` : 'latest'\n}\n\n/**\n * Resolve the latest published version of every sibling package via\n * `npm view <name> version` (through `captureCommandAsync`, which routes\n * around Windows' `.cmd` shims — see utils/shell.ts).\n *\n * The timeout is generous and the queries are genuinely concurrent: a\n * warm `npm view` against the public registry measures 0.6–3.6s per\n * package, so the old 5s budget was one slow response away from expiring,\n * and the sync `captureCommand` under `Promise.all` ran all ten serially\n * — making the per-call budget the only thing standing between a scaffold\n * and a package.json full of fallbacks.\n */\n/**\n * Run `task` over every item, at most `limit` at a time. Each `npm view` is a\n * process; the full list is 37 of them, and firing all of them at once can\n * exhaust process or memory limits on a small machine (CI containers, a\n * Raspberry Pi) — which fails the scaffold rather than slowing it.\n */\nasync function mapWithConcurrency<T, R>(\n items: readonly T[],\n limit: number,\n task: (item: T) => Promise<R>,\n): Promise<R[]> {\n const results: R[] = Array.from({ length: items.length })\n let next = 0\n const workers = Array.from({ length: Math.min(limit, items.length) }, async () => {\n while (next < items.length) {\n const index = next++\n results[index] = await task(items[index]!)\n }\n })\n await Promise.all(workers)\n return results\n}\n\n/**\n * How long the whole resolution may take before the rest of the packages take\n * their fallback ranges. Node's `timeout` applies per child process, so a\n * stalled registry would otherwise cost one timeout per wave of the worker\n * pool — 37 lookups, 8 at a time, is five waves and over a minute of a\n * scaffold sitting still.\n */\nexport const VERSION_LOOKUP_BUDGET_MS = 20_000\n\nexport async function resolveSiblingVersions(): Promise<Record<string, string>> {\n const queries = [\n ...SIBLING_PACKAGES.map((name) => ({ name, fallback: fallbackRange(name), cap: undefined })),\n ...Object.entries(THIRD_PARTY_PACKAGES).map(([name, entry]) => ({ name, ...entry })),\n ]\n\n const deadline = Date.now() + VERSION_LOOKUP_BUDGET_MS\n\n const resolved = await mapWithConcurrency(queries, 8, async ({ name, fallback, cap }) => {\n // Out of budget: take the fallback rather than start another probe.\n const remaining = deadline - Date.now()\n if (remaining <= 0) return [name, fallback] as const\n\n // Network failure / package not yet published / npm unavailable all\n // surface as null → fall back to a range that always resolves.\n const spec = cap ? `${name}@${cap}` : name\n const out = await captureCommandAsync(\n 'npm',\n // A capped query matches many versions; npm prints them as JSON.\n cap ? ['view', spec, 'version', '--json'] : ['view', spec, 'version'],\n { timeout: remaining },\n )\n const version = parseNpmVersion(out)\n return [name, version ? `^${version}` : fallback] as const\n })\n\n return Object.fromEntries(resolved)\n}\n\n/**\n * Resolve the published version of a package at a given dist-tag\n * (`npm view <name>@<tag> version`). Returns `null` on any failure. Used\n * to pin `@forinda/kickjs` to the `alpha` channel when scaffolding a\n * Fastify / h3 app — the engine subpaths (`@forinda/kickjs/fastify`,\n * `/h3`) ship only on the alpha until the runtimes land in a stable\n * release, so the default `latest` resolution would install a kickjs\n * that doesn't export them (→ Vite \"./h3 is not exported\" at boot).\n * Returns the bare version; the caller applies a `^` range so the project\n * floats to newer alphas and auto-graduates to stable (a caret over a\n * prerelease matches same-tuple prereleases ≥ it, plus later stables `< next\n * major`).\n */\nfunction resolveVersionAtTag(name: string, tag: string): string | null {\n const out = captureCommand('npm', ['view', `${name}@${tag}`, 'version'], { timeout: 20_000 })\n return out && /^\\d+\\.\\d+\\.\\d+/.test(out) ? out : null\n}\n\n/**\n * Whether the package at a given dist-tag exports a subpath (e.g. `./h3`).\n * Reads the `exports` map via `npm view <name>@<tag> exports --json`. Used to\n * gate the alpha-pin: if `latest` already ships the engine subpath, the runtime\n * has graduated to stable and we should NOT downgrade to an older alpha.\n * Returns `false` on any failure (missing field / network / unparseable) so the\n * caller treats \"unknown\" as \"not present\" and falls through to the alpha path.\n */\n/** Strip a leading range operator (`^1.2.3` / `~1.2.3` → `1.2.3`). */\nfunction stripRange(range: string | undefined): string {\n return (range ?? '').replace(/^[\\^~>=<\\s]+/, '')\n}\n\n/**\n * Compare the release cores (major.minor.patch, ignoring any `-prerelease`\n * suffix) of two versions: is `a` >= `b`? Used to guard the alpha-pin so a\n * package is never downgraded onto a stale prerelease whose stable line has\n * already moved past it. A coarse compare is enough here — we only need\n * \"is this alpha at least as new as the stable we'd otherwise install\".\n */\nfunction baseVersionGte(a: string, b: string): boolean {\n const core = (v: string): number[] =>\n stripRange(v)\n .split('-')[0]!\n .split('.')\n .map((n) => Number.parseInt(n, 10) || 0)\n const [a0 = 0, a1 = 0, a2 = 0] = core(a)\n const [b0 = 0, b1 = 0, b2 = 0] = core(b)\n if (a0 !== b0) return a0 > b0\n if (a1 !== b1) return a1 > b1\n return a2 >= b2\n}\n\n/** This CLI's version. */\nexport const cliVersion: string = cliPkg.version\n\n/**\n * The latest published CLI when it's newer than this one — else null: current\n * already, offline, or npm missing. An old global `kick` silently lacks the\n * templates and options released since, so `kick new` says so.\n */\nexport async function newerCliRelease(): Promise<string | null> {\n const latest = parseNpmVersion(\n // Short: an aborted `kick new` waits for this before it exits.\n await captureCommandAsync('npm', ['view', '@forinda/kickjs-cli', 'version'], {\n timeout: 5000,\n }),\n )\n return latest && isBehind(cliVersion, latest) ? latest : null\n}\n\n/** Whether `current` is an older release than `latest` — a prerelease is behind its stable. */\nexport function isBehind(current: string, latest: string): boolean {\n if (current.split('-')[0] === latest.split('-')[0]) {\n return current.includes('-') && !latest.includes('-')\n }\n return !baseVersionGte(current, latest)\n}\n\nfunction tagExportsSubpath(name: string, tag: string, subpath: string): boolean {\n const out = captureCommand('npm', ['view', `${name}@${tag}`, 'exports', '--json'], {\n timeout: 20_000,\n })\n if (!out) return false\n try {\n const exportsMap = JSON.parse(out) as Record<string, unknown>\n return Object.prototype.hasOwnProperty.call(exportsMap, subpath)\n } catch {\n return false\n }\n}\n\ntype ProjectTemplate = 'rest' | 'minimal' | 'inertia'\ntype SchemaLib = 'zod' | 'valibot' | 'yup'\n\ninterface InitProjectOptions {\n name: string\n directory: string\n packageManager?: 'pnpm' | 'npm' | 'yarn' | 'bun'\n initGit?: boolean\n installDeps?: boolean\n template?: ProjectTemplate\n defaultRepo?: string\n packages?: string[]\n /** Schema library to scaffold env / DTOs with. Defaults to `zod`. */\n schemaLib?: SchemaLib\n /** HTTP engine to scaffold. Defaults to `express`. */\n runtime?: 'express' | 'fastify' | 'h3'\n /** Wire `SpaAdapter` at this clientDir (fullstack template). */\n spaClientDir?: string\n /**\n * Layers rendered after the selection's — `server-fullstack` for the\n * fullstack workspace's server (strict port, client route map, TS 6 pin).\n */\n extraLayers?: string[]\n /**\n * Record install-script approvals for the package manager (pnpm-workspace.yaml,\n * or package.json for npm/bun). Default true; false when the project is a\n * member of a workspace whose root records them.\n */\n approveInstallScripts?: boolean\n /**\n * A standalone project. False for a workspace member: the root owns the\n * `packageManager` field and the deploy files.\n */\n platformConfig?: boolean\n /** Deploy targets to write files for — `kick new --deploy` / `kick g deploy`. */\n deploy?: DeployTarget[]\n /**\n * Ranges resolved by the caller. The fullstack generator passes one map for\n * the whole workspace: resolving per package lets a failed lookup fall back\n * on one side and succeed on the other, which is how server/ and web/ end\n * up on different vite or TypeScript majors.\n */\n versions?: Record<string, string>\n}\n\n/** Scaffold a new KickJS project */\n/**\n * Scaffold a project. Returns the install-script answers it needs, so a\n * caller that installs from elsewhere (the fullstack workspace root) can\n * record them there.\n */\nexport async function initProject(\n options: InitProjectOptions,\n): Promise<{ builds: Record<string, boolean> }> {\n const {\n name,\n directory,\n packageManager = 'pnpm',\n template = 'rest',\n defaultRepo = 'inmemory',\n packages = [],\n schemaLib = 'zod',\n runtime = 'express',\n } = options\n const dir = directory\n\n const log = (msg: string) => console.log(` ${msg}`)\n\n console.log(`\\n Creating KickJS project: ${name}\\n`)\n\n // Resolve published version of every sibling kickjs package in\n // parallel. Per-package independent versioning means\n // `@forinda/kickjs@5.5.0` may pair with `@forinda/kickjs-cli@5.4.2`\n // and `@forinda/kickjs-swagger@5.3.1`; pinning every dep to the\n // CLI's own version under-installs adopters whenever a sibling\n // bumps independently. `npm view` fallback keeps the scaffold\n // working offline.\n if (!options.versions) log('Resolving package versions...')\n const versions = options.versions ?? (await resolveSiblingVersions())\n\n // A 'latest' range means the registry query failed for that package. The\n // install still works, but the pin is looser than intended and the user\n // should know why their package.json does not read like the docs.\n const unresolved = Object.keys(versions).filter((name) => versions[name] === 'latest')\n if (unresolved.length > 0) {\n log(`WARNING: could not reach npm for ${unresolved.join(', ')} — pinned to 'latest'`)\n }\n\n // The pluggable-runtimes work (Fastify / h3 engine subpaths, the\n // `kick/runtime` typegen, `kick add upload`, `kick doctor` runtime checks)\n // ships only on the `alpha` channel until it lands in a stable release. So a\n // non-Express scaffold needs the alpha of every package that carries runtime\n // behavior, not just `@forinda/kickjs`:\n // - `@forinda/kickjs` — the `./fastify` / `./h3` export subpaths the\n // app imports (stable lacks them → Vite boot\n // error `\"./h3\" is not exported`).\n // - `@forinda/kickjs-cli` — `--runtime`, `kick add upload`, `kick doctor`,\n // the `kick/runtime` typegen plugin.\n // - `@forinda/kickjs-vite` — the dev loop co-versioned with the above.\n // Gated on whether `@forinda/kickjs@latest` already exports the chosen engine\n // subpath: once that's true the runtimes are stable and we keep `latest` for\n // everything (self-retiring — no code change needed at graduation). Each pin\n // is guarded so it never DOWNGRADES (an alpha can be older than latest — e.g.\n // a package whose stable moved on past an old prerelease). Express is exempt.\n if (runtime !== 'express') {\n const subpath = `./${runtime}` // './fastify' | './h3'\n if (tagExportsSubpath('@forinda/kickjs', 'latest', subpath)) {\n log(`Using @forinda/kickjs@latest (stable ships the ${runtime} runtime)`)\n } else {\n const RUNTIME_PKGS = ['@forinda/kickjs', '@forinda/kickjs-cli', '@forinda/kickjs-vite']\n const pinned: string[] = []\n let kickjsPinned = false\n for (const pkg of RUNTIME_PKGS) {\n const alpha = resolveVersionAtTag(pkg, 'alpha')\n // Only switch when the alpha is newer-or-equal to the stable we'd\n // otherwise install — never downgrade onto a stale prerelease. Use a\n // `^` range (not an exact pin) so the project picks up newer alphas and\n // auto-graduates to the stable release once it ships.\n if (alpha && baseVersionGte(alpha, stripRange(versions[pkg]))) {\n versions[pkg] = `^${alpha}`\n pinned.push(`${pkg}@^${alpha}`)\n if (pkg === '@forinda/kickjs') kickjsPinned = true\n }\n }\n if (kickjsPinned) {\n log(`Using the alpha channel for the ${runtime} runtime: ${pinned.join(', ')}`)\n } else {\n log(\n `WARNING: could not resolve @forinda/kickjs@alpha — the ${runtime} runtime subpath ` +\n `may be missing. After install, run: ${packageManager} add @forinda/kickjs@alpha`,\n )\n }\n }\n }\n\n // ── Layers — templates/<layer>/ ──────────────────────────────────\n // Everything that follows from the options: the entry file (runtime,\n // adapters), the env schema, .env additions and the package lists.\n const unknown = packages.filter((pkg) => !existsSync(join(TEMPLATES_DIR, `feature-${pkg}`)))\n if (unknown.length > 0) {\n log(\n `WARNING: skipping unknown package(s): ${unknown.join(', ')} — add them later with kick add`,\n )\n }\n const project = renderLayers(\n [...scaffoldLayers({ template, runtime, schemaLib, packages }), ...(options.extraLayers ?? [])],\n {\n vars: { name, version: cliPkg.version },\n extra: [\n // `inmemory` is the only built-in; any other name is a `{ name }` custom repo.\n {\n slot: 'repo',\n code:\n defaultRepo === 'inmemory'\n ? `repo: 'inmemory'`\n : `repo: { name: '${defaultRepo.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\")}' }`,\n },\n ...(options.spaClientDir ? [spaIntegration(options.spaClientDir)] : []),\n ],\n },\n )\n\n // ── package.json ─────────────────────────────────────────────────────\n // A workspace member inherits the root's.\n const pmSpec = options.platformConfig !== false ? packageManagerSpec(packageManager) : undefined\n await writeFileSafe(\n join(dir, 'package.json'),\n generatePackageJson(name, versions, project, pmSpec),\n )\n const yarnConfig = yarnrc(packageManager, pmSpec)\n if (yarnConfig) await writeFileSafe(join(dir, '.yarnrc.yml'), yarnConfig)\n\n // tsconfig, vite/vitest/kick config, formatter/editor/git config, .env\n // files (`.env.test` is read INSTEAD of `.env` under a test run, so\n // shipping it isolates a new project's tests), README, the hello module,\n // `src/config/index.ts` (the typed env schema `kick typegen` reads) and\n // `src/index.ts`.\n const files = fillVars(project.files, {\n name,\n template,\n runtime,\n packageManager,\n ...commandVars(packageManager),\n templateLabel: { rest: 'REST API', minimal: 'Minimal', inertia: 'Inertia (React)' }[template],\n // A fresh secret per project, written to the gitignored .env.\n sessionSecret: randomBytes(32).toString('hex'),\n packages: [...project.dependencies, ...project.devDependencies]\n .filter((pkg) => pkg.startsWith('@forinda/'))\n .map((pkg) => `- \\`${pkg}\\``)\n .join('\\n'),\n })\n for (const [path, contents] of files) {\n await writeFileSafe(join(dir, path), contents)\n }\n\n // Deploy files only for the targets asked for — `kick g deploy` adds the\n // rest later. A workspace member leaves them to the workspace root.\n if (options.deploy?.length && options.platformConfig !== false) {\n await generateDeploy({ dir, targets: options.deploy, pm: packageManager, force: true })\n }\n\n // ── Agent docs ──────────────────────────────────────────────────────\n // Delegate to `generateAgentDocs()` so `kick new` emits the same\n // `.agents/` subfolder layout as `kick g agents -f`. Otherwise the\n // two paths drifted: kick new was writing the legacy flat layout\n // (root-level AGENTS.md + kickjs-skills.md) while kick g agents\n // emits the per-skill SKILL.md format under .agents/. `force: true`\n // because the project directory is fresh — no overwrite prompts\n // make sense during init.\n const { generateAgentDocs } = await import('./agent-docs')\n await generateAgentDocs({\n outDir: dir,\n name,\n pm: packageManager,\n template,\n // AGENTS.md and CLAUDE.md; skills and the Gemini / Copilot files are one\n // `kick g agents` away.\n only: 'both',\n force: true,\n })\n\n // ── Install-script approvals ─────────────────────────────────────────\n // Before install; see approveInstallScripts.\n const builds = { ...TEMPLATE_BUILDS, ...buildsFor(packages), ...project.builds }\n if (options.approveInstallScripts !== false) {\n approveInstallScripts(packageManager, dir, builds)\n }\n\n // ── Install Dependencies ────────────────────────────────────────────\n // Install BEFORE git init so the lockfile is included in the first commit.\n if (options.installDeps) {\n console.log(`\\n Installing dependencies with ${packageManager}...\\n`)\n try {\n execSync(`${packageManager} install`, { cwd: dir, stdio: 'inherit' })\n console.log('\\n Dependencies installed successfully!')\n } catch {\n console.log(`\\n Warning: ${packageManager} install failed. Run it manually.`)\n }\n }\n\n // ── Initial typegen ────────────────────────────────────────────────\n // Run typegen once so the freshly-scaffolded HelloController's\n // `Ctx<KickRoutes.HelloController['index']>` references resolve in\n // the user's editor immediately. Failures are non-fatal.\n try {\n const { runTypegen } = await import('../typegen')\n await runTypegen({ cwd: dir, allowDuplicates: true, silent: true })\n } catch {\n // First-run typegen errors are non-fatal — `kick dev` will retry.\n }\n\n // ── Git Init ─────────────────────────────────────────────────────────\n // Runs after install + typegen so lockfile and generated types are\n // included in the initial commit.\n if (options.initGit) {\n try {\n execSync('git init', { cwd: dir, stdio: 'pipe' })\n execSync('git branch -M main', { cwd: dir, stdio: 'pipe' })\n execSync('git add -A', { cwd: dir, stdio: 'pipe' })\n execSync('git commit -m \"chore: initial commit from kick new\"', {\n cwd: dir,\n stdio: 'pipe',\n })\n log('Git repository initialized')\n } catch {\n log('Warning: git init failed (git may not be installed)')\n }\n }\n\n console.log('\\n Project scaffolded successfully!')\n console.log()\n\n const needsCd = dir !== process.cwd()\n log('Next steps:')\n if (needsCd) log(` cd ${name}`)\n if (!options.installDeps) log(` ${packageManager} install`)\n\n const kick = execBin(packageManager, 'kick')\n const genHint: Record<string, string> = {\n rest: `${kick} g module user`,\n minimal: '# add your routes to src/index.ts',\n inertia: '# pages: src/modules/pages + src/client/pages',\n }\n log(` ${genHint[template] ?? genHint.rest}`)\n log(` ${runScript(packageManager, 'dev')}`)\n const rows = (list: [string, string][]) => {\n const width = Math.max(...list.map(([cmd]) => cmd.length)) + 2\n for (const [cmd, what] of list) log(` ${cmd.padEnd(width)}${what}`)\n }\n log('')\n log('Commands:')\n rows([\n [runScript(packageManager, 'dev'), 'Start dev server with Vite HMR'],\n [runScript(packageManager, 'build'), 'Production build via Vite'],\n [runScript(packageManager, 'start'), 'Run production build'],\n ])\n log('')\n log('Generators:')\n rows([\n [`${kick} g module <name>`, 'REST module (controller, service, DTOs, repository)'],\n [`${kick} g scaffold <n> <f..>`, 'CRUD module from field definitions'],\n [`${kick} g controller <name>`, 'Standalone controller'],\n [`${kick} g service <name>`, '@Service() class'],\n [`${kick} g middleware <name>`, 'Global connect-style middleware'],\n [`${kick} g guard <name>`, 'Route guard (auth, roles, etc.)'],\n [`${kick} g adapter <name>`, 'AppAdapter with lifecycle hooks'],\n [`${kick} g dto <name>`, 'DTO schema (Zod / Valibot / Yup)'],\n [`${kick} g config`, 'Generate kick.config.ts'],\n ])\n log('')\n log('Add packages:')\n rows([\n [`${kick} add <pkg>`, 'Install a KickJS package + peers'],\n [`${kick} add --list`, 'Show all available packages'],\n ])\n log('')\n log(`Available: ${AVAILABLE_ADD_PACKAGES}`)\n log('')\n\n return { builds }\n}\n\n/** A single-quoted JS string literal: JSON's escapes, with `'` escaped instead of `\"`. */\nconst singleQuoted = (text: string) =>\n `'${JSON.stringify(text).slice(1, -1).replaceAll('\\\\\"', '\"').replaceAll(\"'\", \"\\\\'\")}'`\n\n/**\n * `SpaAdapter` for the fullstack server, which serves `web/`'s build from the\n * API's origin in production. The path is text the caller chose, so it goes\n * in escaped — a quote, backslash or newline in it would otherwise break the\n * emitted module or change the path it resolves — and single-quoted, as\n * oxfmt writes it.\n */\nexport function spaIntegration(clientDir: string): Integration {\n return {\n import: { from: '@forinda/kickjs/spa', names: ['SpaAdapter'] },\n slot: 'adapter',\n code:\n '// Serves the built frontend from this origin in production.\\n' +\n '// Inert until the client build exists, so `kick dev` (where Vite\\n' +\n '// serves the client and proxies /api here) is unaffected.\\n' +\n `SpaAdapter({ clientDir: ${singleQuoted(clientDir)} })`,\n }\n}\n\n/**\n * The layers a `kick new` selection renders, in order. Unknown package\n * names are left out (the caller warns about them).\n */\nexport function scaffoldLayers(selection: {\n template: ProjectTemplate\n runtime: 'express' | 'fastify' | 'h3'\n schemaLib: SchemaLib\n packages: readonly string[]\n}): string[] {\n return [\n 'base',\n `template-${selection.template}`,\n `runtime-${selection.runtime}`,\n `schema-${selection.schemaLib}`,\n ...selection.packages\n .filter((pkg) => existsSync(join(TEMPLATES_DIR, `feature-${pkg}`)))\n .map((pkg) => `feature-${pkg}`),\n ]\n}\n"],"mappings":"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"}