@forinda/kickjs-cli 6.6.1 → 6.7.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 (31) hide show
  1. package/dist/{agent-docs-Du-kAfnd.mjs → agent-docs-tlau7tZv.mjs} +3 -3
  2. package/dist/{agent-docs-Du-kAfnd.mjs.map → agent-docs-tlau7tZv.mjs.map} +1 -1
  3. package/dist/{build-DGTo6Lbp.mjs → build-CDi72mKz.mjs} +3 -3
  4. package/dist/{build-DGTo6Lbp.mjs.map → build-CDi72mKz.mjs.map} +1 -1
  5. package/dist/{builtins-C5YZMX7U.mjs → builtins-BiTg6p4D.mjs} +2 -2
  6. package/dist/cli.mjs +17 -14
  7. package/dist/{config-COL9zMB5.mjs → config-D6C74vFp.mjs} +3 -3
  8. package/dist/{config-COL9zMB5.mjs.map → config-D6C74vFp.mjs.map} +1 -1
  9. package/dist/{doctor-BCMp4UCQ.mjs → doctor-BHnei8KS.mjs} +4 -4
  10. package/dist/{doctor-BCMp4UCQ.mjs.map → doctor-BHnei8KS.mjs.map} +1 -1
  11. package/dist/{fullstack-Cqm_v3sf.mjs → fullstack-Cmedpn8G.mjs} +4 -4
  12. package/dist/{fullstack-Cqm_v3sf.mjs.map → fullstack-Cmedpn8G.mjs.map} +1 -1
  13. package/dist/{fullstack-C8u97QC-.mjs → fullstack-e-wuEMD0.mjs} +1 -1
  14. package/dist/index.mjs +2 -2
  15. package/dist/{plugin-BHLfFlki.mjs → plugin-BlWy4Nbd.mjs} +3 -3
  16. package/dist/{plugin-BHLfFlki.mjs.map → plugin-BlWy4Nbd.mjs.map} +1 -1
  17. package/dist/{project-YM9dH4O_.mjs → project-CnU7KcYI.mjs} +5 -5
  18. package/dist/{project-YM9dH4O_.mjs.map → project-CnU7KcYI.mjs.map} +1 -1
  19. package/dist/{project-docs-VwSwcfVt.mjs → project-docs-BV-h5EmP.mjs} +2 -2
  20. package/dist/{project-docs-VwSwcfVt.mjs.map → project-docs-BV-h5EmP.mjs.map} +1 -1
  21. package/dist/{project-root-DRTGL9O5.mjs → project-root-CdqXle6R.mjs} +3 -3
  22. package/dist/{project-root-DRTGL9O5.mjs.map → project-root-CdqXle6R.mjs.map} +1 -1
  23. package/dist/{prompts-BJywkbEr.mjs → prompts-D7bKHNce.mjs} +2 -2
  24. package/dist/{prompts-BJywkbEr.mjs.map → prompts-D7bKHNce.mjs.map} +1 -1
  25. package/dist/{rolldown-runtime-BKn_X0JJ.mjs → rolldown-runtime-DiP_G7eI.mjs} +1 -1
  26. package/dist/{run-plugins-C1wpiuKz.mjs → run-plugins-C5kGYAsD.mjs} +18 -15
  27. package/dist/{run-plugins-C1wpiuKz.mjs.map → run-plugins-C5kGYAsD.mjs.map} +1 -1
  28. package/dist/{typegen-Dh-JBQSr.mjs → typegen-qeQ5co2C.mjs} +5 -5
  29. package/dist/{typegen-Dh-JBQSr.mjs.map → typegen-qeQ5co2C.mjs.map} +1 -1
  30. package/dist/{types-B2DQMqCA.mjs → types-BNOSmSFj.mjs} +1 -1
  31. package/package.json +3 -3
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs-cli v6.6.1
2
+ * @forinda/kickjs-cli v6.7.0
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,5 +8,5 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import{t as e}from"./rolldown-runtime-BKn_X0JJ.mjs";import{a as t,i as n,l as r,n as i,r as a,t as o}from"./project-docs-VwSwcfVt.mjs";import{t as s}from"./prompts-BJywkbEr.mjs";import{i as c}from"./config-COL9zMB5.mjs";import{join as l}from"node:path";import{existsSync as u,readFileSync as d}from"node:fs";var f=e({generateAgentDocs:()=>v});const p=`.agents`,m=new Set([`rest`,`minimal`,`fullstack`]);function h(e,t){if(t)return t;try{let t=JSON.parse(d(l(e,`package.json`),`utf-8`));if(t.name)return t.name.replace(/^@[^/]+\//,``)}catch{}return e.split(`/`).findLast(Boolean)??`app`}function g(e,t){if(t)return t;try{let t=JSON.parse(d(l(e,`package.json`),`utf-8`));if(t.packageManager)return t.packageManager.split(`@`)[0]}catch{}return`pnpm`}async function _(e,t){if(t)return t;try{let t=(await c(e))?.pattern;if(t&&m.has(t))return t}catch{}return`rest`}async function v(e){let c=e.only??`all`,d=h(e.outDir,e.name),f=g(e.outDir,e.pm),m=await _(e.outDir,e.template),v=c===`agents`||c===`both`||c===`all`,y=c===`claude`||c===`both`||c===`all`,b=c===`skills`||c===`all`,x=c===`gemini`||c===`all`,S=c===`copilot`||c===`all`,C=[];if(v&&C.push({file:l(e.outDir,p,`AGENTS.md`),render:()=>o(d,m,f)}),y&&C.push({file:l(e.outDir,`CLAUDE.md`),render:()=>i(d,m,f)}),b)for(let n of t(d,m,f))C.push({file:l(e.outDir,p,`skills`,n.slug,`SKILL.md`),render:()=>n.content});x&&C.push({file:l(e.outDir,p,`GEMINI.md`),render:()=>n(d,m,f)}),S&&C.push({file:l(e.outDir,p,`COPILOT.md`),render:()=>a(d,m,f)});let w=[];for(let{file:t,render:n}of C){if(u(t)&&!e.force&&!await s({message:`${t.replace(e.outDir+`/`,``)} already exists. Overwrite?`,initialValue:!1})){console.log(` Skipped — existing ${t.replace(e.outDir+`/`,``)} preserved.`);continue}await r(t,n()),w.push(t)}return w}export{v as n,f as t};
12
- //# sourceMappingURL=agent-docs-Du-kAfnd.mjs.map
11
+ import{t as e}from"./rolldown-runtime-DiP_G7eI.mjs";import{a as t,i as n,l as r,n as i,r as a,t as o}from"./project-docs-BV-h5EmP.mjs";import{t as s}from"./prompts-D7bKHNce.mjs";import{i as c}from"./config-D6C74vFp.mjs";import{join as l}from"node:path";import{existsSync as u,readFileSync as d}from"node:fs";var f=e({generateAgentDocs:()=>v});const p=`.agents`,m=new Set([`rest`,`minimal`,`fullstack`]);function h(e,t){if(t)return t;try{let t=JSON.parse(d(l(e,`package.json`),`utf-8`));if(t.name)return t.name.replace(/^@[^/]+\//,``)}catch{}return e.split(`/`).findLast(Boolean)??`app`}function g(e,t){if(t)return t;try{let t=JSON.parse(d(l(e,`package.json`),`utf-8`));if(t.packageManager)return t.packageManager.split(`@`)[0]}catch{}return`pnpm`}async function _(e,t){if(t)return t;try{let t=(await c(e))?.pattern;if(t&&m.has(t))return t}catch{}return`rest`}async function v(e){let c=e.only??`all`,d=h(e.outDir,e.name),f=g(e.outDir,e.pm),m=await _(e.outDir,e.template),v=c===`agents`||c===`both`||c===`all`,y=c===`claude`||c===`both`||c===`all`,b=c===`skills`||c===`all`,x=c===`gemini`||c===`all`,S=c===`copilot`||c===`all`,C=[];if(v&&C.push({file:l(e.outDir,p,`AGENTS.md`),render:()=>o(d,m,f)}),y&&C.push({file:l(e.outDir,`CLAUDE.md`),render:()=>i(d,m,f)}),b)for(let n of t(d,m,f))C.push({file:l(e.outDir,p,`skills`,n.slug,`SKILL.md`),render:()=>n.content});x&&C.push({file:l(e.outDir,p,`GEMINI.md`),render:()=>n(d,m,f)}),S&&C.push({file:l(e.outDir,p,`COPILOT.md`),render:()=>a(d,m,f)});let w=[];for(let{file:t,render:n}of C){if(u(t)&&!e.force&&!await s({message:`${t.replace(e.outDir+`/`,``)} already exists. Overwrite?`,initialValue:!1})){console.log(` Skipped — existing ${t.replace(e.outDir+`/`,``)} preserved.`);continue}await r(t,n()),w.push(t)}return w}export{v as n,f as t};
12
+ //# sourceMappingURL=agent-docs-tlau7tZv.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"agent-docs-Du-kAfnd.mjs","names":[],"sources":["../src/generators/agent-docs.ts"],"sourcesContent":["import { join } from 'node:path'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { writeFileSafe } from '../utils/fs'\nimport { confirm } from '../utils/prompts'\nimport {\n generateClaude,\n generateAgents,\n generateKickJsSkillFiles,\n generateGemini,\n generateCopilot,\n} from './templates/project-docs'\nimport { loadKickConfig } from '../config'\n\ntype ProjectTemplate = 'rest' | 'minimal' | 'fullstack'\n\n/**\n * Subdirectory (relative to the project root) where every shared\n * agent-context file lands. CLAUDE.md is the only exception — it stays\n * at the project root because Claude Code auto-loads CLAUDE.md from\n * there. CLAUDE.md is generated as a thin pointer that tells Claude\n * to read `.agents/AGENTS.md` first.\n *\n * Existing root-level AGENTS.md / kickjs-skills.md files (from older\n * scaffolds before this restructure) are left untouched — the\n * generator emits the new layout alongside them and leaves migration\n * to the adopter.\n */\nconst AGENTS_DIR = '.agents'\n\nexport interface GenerateAgentDocsOptions {\n outDir: string\n /** Override project name (defaults to package.json `name`). */\n name?: string\n /** Override package manager (defaults to package.json `packageManager` field, then 'pnpm'). */\n pm?: string\n /** Override template (defaults to kick.config.ts `pattern`, then 'ddd'). */\n template?: ProjectTemplate\n /**\n * Which file(s) to (re)generate. All `.agents/`-bound files land in\n * the project's `.agents/` subdirectory; `claude` is the only file\n * that stays at the project root.\n *\n * - `agents` → `.agents/AGENTS.md`\n * - `claude` → `CLAUDE.md` (root; thin pointer to .agents/)\n * - `skills` → `.agents/kickjs-skills.md`\n * - `gemini` → `.agents/GEMINI.md`\n * - `copilot` → `.agents/COPILOT.md`\n * - `both` → `.agents/AGENTS.md` + `CLAUDE.md` (legacy alias)\n * - `all` → every file above\n */\n only?: 'agents' | 'claude' | 'skills' | 'gemini' | 'copilot' | 'both' | 'all'\n /** Skip the overwrite prompt. */\n force?: boolean\n}\n\nconst VALID_TEMPLATES = new Set<ProjectTemplate>(['rest', 'minimal', 'fullstack'])\n\nfunction detectName(outDir: string, override?: string): string {\n if (override) return override\n try {\n const pkg = JSON.parse(readFileSync(join(outDir, 'package.json'), 'utf-8')) as { name?: string }\n if (pkg.name) return pkg.name.replace(/^@[^/]+\\//, '')\n } catch {\n // No package.json — fall back to folder name\n }\n return outDir.split('/').findLast(Boolean) ?? 'app'\n}\n\nfunction detectPm(outDir: string, override?: string): string {\n if (override) return override\n try {\n const pkg = JSON.parse(readFileSync(join(outDir, 'package.json'), 'utf-8')) as {\n packageManager?: string\n }\n if (pkg.packageManager) return pkg.packageManager.split('@')[0]\n } catch {\n // ignore\n }\n return 'pnpm'\n}\n\nasync function detectTemplate(\n outDir: string,\n override?: ProjectTemplate,\n): Promise<ProjectTemplate> {\n if (override) return override\n try {\n const cfg = await loadKickConfig(outDir)\n const pattern = cfg?.pattern as ProjectTemplate | undefined\n if (pattern && VALID_TEMPLATES.has(pattern)) return pattern\n } catch {\n // ignore\n }\n return 'rest'\n}\n\nexport async function generateAgentDocs(options: GenerateAgentDocsOptions): Promise<string[]> {\n const only = options.only ?? 'all'\n const name = detectName(options.outDir, options.name)\n const pm = detectPm(options.outDir, options.pm)\n const template = await detectTemplate(options.outDir, options.template)\n\n const wantsAgents = only === 'agents' || only === 'both' || only === 'all'\n const wantsClaude = only === 'claude' || only === 'both' || only === 'all'\n const wantsSkills = only === 'skills' || only === 'all'\n const wantsGemini = only === 'gemini' || only === 'all'\n const wantsCopilot = only === 'copilot' || only === 'all'\n\n // CLAUDE.md stays at the project root because Claude Code auto-loads\n // it from there. Every other shared-context file lands under\n // `.agents/` so the root stays uncluttered. `writeFileSafe` creates\n // parent directories automatically — no need to pre-mkdir.\n const targets: { file: string; render: () => string }[] = []\n if (wantsAgents) {\n targets.push({\n file: join(options.outDir, AGENTS_DIR, 'AGENTS.md'),\n render: () => generateAgents(name, template, pm),\n })\n }\n if (wantsClaude) {\n targets.push({\n file: join(options.outDir, 'CLAUDE.md'),\n render: () => generateClaude(name, template, pm),\n })\n }\n if (wantsSkills) {\n // Per-skill SKILL.md under `.agents/skills/<slug>/` so agents that\n // auto-discover skills (Claude Code, Copilot CLI plugins, Gemini's\n // activate_skill) pick each up by its frontmatter without needing\n // a separate index file.\n for (const skill of generateKickJsSkillFiles(name, template, pm)) {\n targets.push({\n file: join(options.outDir, AGENTS_DIR, 'skills', skill.slug, 'SKILL.md'),\n render: () => skill.content,\n })\n }\n }\n if (wantsGemini) {\n targets.push({\n file: join(options.outDir, AGENTS_DIR, 'GEMINI.md'),\n render: () => generateGemini(name, template, pm),\n })\n }\n if (wantsCopilot) {\n targets.push({\n file: join(options.outDir, AGENTS_DIR, 'COPILOT.md'),\n render: () => generateCopilot(name, template, pm),\n })\n }\n\n const written: string[] = []\n for (const { file, render } of targets) {\n if (existsSync(file) && !options.force) {\n const overwrite = await confirm({\n message: `${file.replace(options.outDir + '/', '')} already exists. Overwrite?`,\n initialValue: false,\n })\n if (!overwrite) {\n console.log(` Skipped — existing ${file.replace(options.outDir + '/', '')} preserved.`)\n continue\n }\n }\n await writeFileSafe(file, render())\n written.push(file)\n }\n return written\n}\n"],"mappings":";;;;;;;;;;uVA2BA,MAAM,EAAa,UA4Bb,EAAkB,IAAI,IAAqB,CAAC,OAAQ,UAAW,WAAW,CAAC,EAEjF,SAAS,EAAW,EAAgB,EAA2B,CAC7D,GAAI,EAAU,OAAO,EACrB,GAAI,CACF,IAAM,EAAM,KAAK,MAAM,EAAa,EAAK,EAAQ,cAAc,EAAG,OAAO,CAAC,EAC1E,GAAI,EAAI,KAAM,OAAO,EAAI,KAAK,QAAQ,YAAa,EAAE,CACvD,MAAQ,CAER,CACA,OAAO,EAAO,MAAM,GAAG,CAAC,CAAC,SAAS,OAAO,GAAK,KAChD,CAEA,SAAS,EAAS,EAAgB,EAA2B,CAC3D,GAAI,EAAU,OAAO,EACrB,GAAI,CACF,IAAM,EAAM,KAAK,MAAM,EAAa,EAAK,EAAQ,cAAc,EAAG,OAAO,CAAC,EAG1E,GAAI,EAAI,eAAgB,OAAO,EAAI,eAAe,MAAM,GAAG,CAAC,CAAC,EAC/D,MAAQ,CAER,CACA,MAAO,MACT,CAEA,eAAe,EACb,EACA,EAC0B,CAC1B,GAAI,EAAU,OAAO,EACrB,GAAI,CAEF,IAAM,GAAU,MADE,EAAe,CAAM,EAAA,EAClB,QACrB,GAAI,GAAW,EAAgB,IAAI,CAAO,EAAG,OAAO,CACtD,MAAQ,CAER,CACA,MAAO,MACT,CAEA,eAAsB,EAAkB,EAAsD,CAC5F,IAAM,EAAO,EAAQ,MAAQ,MACvB,EAAO,EAAW,EAAQ,OAAQ,EAAQ,IAAI,EAC9C,EAAK,EAAS,EAAQ,OAAQ,EAAQ,EAAE,EACxC,EAAW,MAAM,EAAe,EAAQ,OAAQ,EAAQ,QAAQ,EAEhE,EAAc,IAAS,UAAY,IAAS,QAAU,IAAS,MAC/D,EAAc,IAAS,UAAY,IAAS,QAAU,IAAS,MAC/D,EAAc,IAAS,UAAY,IAAS,MAC5C,EAAc,IAAS,UAAY,IAAS,MAC5C,EAAe,IAAS,WAAa,IAAS,MAM9C,EAAoD,CAAC,EAa3D,GAZI,GACF,EAAQ,KAAK,CACX,KAAM,EAAK,EAAQ,OAAQ,EAAY,WAAW,EAClD,WAAc,EAAe,EAAM,EAAU,CAAE,CACjD,CAAC,EAEC,GACF,EAAQ,KAAK,CACX,KAAM,EAAK,EAAQ,OAAQ,WAAW,EACtC,WAAc,EAAe,EAAM,EAAU,CAAE,CACjD,CAAC,EAEC,EAKF,IAAK,IAAM,KAAS,EAAyB,EAAM,EAAU,CAAE,EAC7D,EAAQ,KAAK,CACX,KAAM,EAAK,EAAQ,OAAQ,EAAY,SAAU,EAAM,KAAM,UAAU,EACvE,WAAc,EAAM,OACtB,CAAC,EAGD,GACF,EAAQ,KAAK,CACX,KAAM,EAAK,EAAQ,OAAQ,EAAY,WAAW,EAClD,WAAc,EAAe,EAAM,EAAU,CAAE,CACjD,CAAC,EAEC,GACF,EAAQ,KAAK,CACX,KAAM,EAAK,EAAQ,OAAQ,EAAY,YAAY,EACnD,WAAc,EAAgB,EAAM,EAAU,CAAE,CAClD,CAAC,EAGH,IAAM,EAAoB,CAAC,EAC3B,IAAK,GAAM,CAAE,OAAM,YAAY,EAAS,CACtC,GAAI,EAAW,CAAI,GAAK,CAAC,EAAQ,OAK3B,CAAC,MAJmB,EAAQ,CAC9B,QAAS,GAAG,EAAK,QAAQ,EAAQ,OAAS,IAAK,EAAE,EAAE,6BACnD,aAAc,EAChB,CAAC,EACe,CACd,QAAQ,IAAI,wBAAwB,EAAK,QAAQ,EAAQ,OAAS,IAAK,EAAE,EAAE,YAAY,EACvF,QACF,CAEF,MAAM,EAAc,EAAM,EAAO,CAAC,EAClC,EAAQ,KAAK,CAAI,CACnB,CACA,OAAO,CACT"}
1
+ {"version":3,"file":"agent-docs-tlau7tZv.mjs","names":[],"sources":["../src/generators/agent-docs.ts"],"sourcesContent":["import { join } from 'node:path'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { writeFileSafe } from '../utils/fs'\nimport { confirm } from '../utils/prompts'\nimport {\n generateClaude,\n generateAgents,\n generateKickJsSkillFiles,\n generateGemini,\n generateCopilot,\n} from './templates/project-docs'\nimport { loadKickConfig } from '../config'\n\ntype ProjectTemplate = 'rest' | 'minimal' | 'fullstack'\n\n/**\n * Subdirectory (relative to the project root) where every shared\n * agent-context file lands. CLAUDE.md is the only exception — it stays\n * at the project root because Claude Code auto-loads CLAUDE.md from\n * there. CLAUDE.md is generated as a thin pointer that tells Claude\n * to read `.agents/AGENTS.md` first.\n *\n * Existing root-level AGENTS.md / kickjs-skills.md files (from older\n * scaffolds before this restructure) are left untouched — the\n * generator emits the new layout alongside them and leaves migration\n * to the adopter.\n */\nconst AGENTS_DIR = '.agents'\n\nexport interface GenerateAgentDocsOptions {\n outDir: string\n /** Override project name (defaults to package.json `name`). */\n name?: string\n /** Override package manager (defaults to package.json `packageManager` field, then 'pnpm'). */\n pm?: string\n /** Override template (defaults to kick.config.ts `pattern`, then 'ddd'). */\n template?: ProjectTemplate\n /**\n * Which file(s) to (re)generate. All `.agents/`-bound files land in\n * the project's `.agents/` subdirectory; `claude` is the only file\n * that stays at the project root.\n *\n * - `agents` → `.agents/AGENTS.md`\n * - `claude` → `CLAUDE.md` (root; thin pointer to .agents/)\n * - `skills` → `.agents/kickjs-skills.md`\n * - `gemini` → `.agents/GEMINI.md`\n * - `copilot` → `.agents/COPILOT.md`\n * - `both` → `.agents/AGENTS.md` + `CLAUDE.md` (legacy alias)\n * - `all` → every file above\n */\n only?: 'agents' | 'claude' | 'skills' | 'gemini' | 'copilot' | 'both' | 'all'\n /** Skip the overwrite prompt. */\n force?: boolean\n}\n\nconst VALID_TEMPLATES = new Set<ProjectTemplate>(['rest', 'minimal', 'fullstack'])\n\nfunction detectName(outDir: string, override?: string): string {\n if (override) return override\n try {\n const pkg = JSON.parse(readFileSync(join(outDir, 'package.json'), 'utf-8')) as { name?: string }\n if (pkg.name) return pkg.name.replace(/^@[^/]+\\//, '')\n } catch {\n // No package.json — fall back to folder name\n }\n return outDir.split('/').findLast(Boolean) ?? 'app'\n}\n\nfunction detectPm(outDir: string, override?: string): string {\n if (override) return override\n try {\n const pkg = JSON.parse(readFileSync(join(outDir, 'package.json'), 'utf-8')) as {\n packageManager?: string\n }\n if (pkg.packageManager) return pkg.packageManager.split('@')[0]\n } catch {\n // ignore\n }\n return 'pnpm'\n}\n\nasync function detectTemplate(\n outDir: string,\n override?: ProjectTemplate,\n): Promise<ProjectTemplate> {\n if (override) return override\n try {\n const cfg = await loadKickConfig(outDir)\n const pattern = cfg?.pattern as ProjectTemplate | undefined\n if (pattern && VALID_TEMPLATES.has(pattern)) return pattern\n } catch {\n // ignore\n }\n return 'rest'\n}\n\nexport async function generateAgentDocs(options: GenerateAgentDocsOptions): Promise<string[]> {\n const only = options.only ?? 'all'\n const name = detectName(options.outDir, options.name)\n const pm = detectPm(options.outDir, options.pm)\n const template = await detectTemplate(options.outDir, options.template)\n\n const wantsAgents = only === 'agents' || only === 'both' || only === 'all'\n const wantsClaude = only === 'claude' || only === 'both' || only === 'all'\n const wantsSkills = only === 'skills' || only === 'all'\n const wantsGemini = only === 'gemini' || only === 'all'\n const wantsCopilot = only === 'copilot' || only === 'all'\n\n // CLAUDE.md stays at the project root because Claude Code auto-loads\n // it from there. Every other shared-context file lands under\n // `.agents/` so the root stays uncluttered. `writeFileSafe` creates\n // parent directories automatically — no need to pre-mkdir.\n const targets: { file: string; render: () => string }[] = []\n if (wantsAgents) {\n targets.push({\n file: join(options.outDir, AGENTS_DIR, 'AGENTS.md'),\n render: () => generateAgents(name, template, pm),\n })\n }\n if (wantsClaude) {\n targets.push({\n file: join(options.outDir, 'CLAUDE.md'),\n render: () => generateClaude(name, template, pm),\n })\n }\n if (wantsSkills) {\n // Per-skill SKILL.md under `.agents/skills/<slug>/` so agents that\n // auto-discover skills (Claude Code, Copilot CLI plugins, Gemini's\n // activate_skill) pick each up by its frontmatter without needing\n // a separate index file.\n for (const skill of generateKickJsSkillFiles(name, template, pm)) {\n targets.push({\n file: join(options.outDir, AGENTS_DIR, 'skills', skill.slug, 'SKILL.md'),\n render: () => skill.content,\n })\n }\n }\n if (wantsGemini) {\n targets.push({\n file: join(options.outDir, AGENTS_DIR, 'GEMINI.md'),\n render: () => generateGemini(name, template, pm),\n })\n }\n if (wantsCopilot) {\n targets.push({\n file: join(options.outDir, AGENTS_DIR, 'COPILOT.md'),\n render: () => generateCopilot(name, template, pm),\n })\n }\n\n const written: string[] = []\n for (const { file, render } of targets) {\n if (existsSync(file) && !options.force) {\n const overwrite = await confirm({\n message: `${file.replace(options.outDir + '/', '')} already exists. Overwrite?`,\n initialValue: false,\n })\n if (!overwrite) {\n console.log(` Skipped — existing ${file.replace(options.outDir + '/', '')} preserved.`)\n continue\n }\n }\n await writeFileSafe(file, render())\n written.push(file)\n }\n return written\n}\n"],"mappings":";;;;;;;;;;uVA2BA,MAAM,EAAa,UA4Bb,EAAkB,IAAI,IAAqB,CAAC,OAAQ,UAAW,WAAW,CAAC,EAEjF,SAAS,EAAW,EAAgB,EAA2B,CAC7D,GAAI,EAAU,OAAO,EACrB,GAAI,CACF,IAAM,EAAM,KAAK,MAAM,EAAa,EAAK,EAAQ,cAAc,EAAG,OAAO,CAAC,EAC1E,GAAI,EAAI,KAAM,OAAO,EAAI,KAAK,QAAQ,YAAa,EAAE,CACvD,MAAQ,CAER,CACA,OAAO,EAAO,MAAM,GAAG,CAAC,CAAC,SAAS,OAAO,GAAK,KAChD,CAEA,SAAS,EAAS,EAAgB,EAA2B,CAC3D,GAAI,EAAU,OAAO,EACrB,GAAI,CACF,IAAM,EAAM,KAAK,MAAM,EAAa,EAAK,EAAQ,cAAc,EAAG,OAAO,CAAC,EAG1E,GAAI,EAAI,eAAgB,OAAO,EAAI,eAAe,MAAM,GAAG,CAAC,CAAC,EAC/D,MAAQ,CAER,CACA,MAAO,MACT,CAEA,eAAe,EACb,EACA,EAC0B,CAC1B,GAAI,EAAU,OAAO,EACrB,GAAI,CAEF,IAAM,GAAU,MADE,EAAe,CAAM,EAAA,EAClB,QACrB,GAAI,GAAW,EAAgB,IAAI,CAAO,EAAG,OAAO,CACtD,MAAQ,CAER,CACA,MAAO,MACT,CAEA,eAAsB,EAAkB,EAAsD,CAC5F,IAAM,EAAO,EAAQ,MAAQ,MACvB,EAAO,EAAW,EAAQ,OAAQ,EAAQ,IAAI,EAC9C,EAAK,EAAS,EAAQ,OAAQ,EAAQ,EAAE,EACxC,EAAW,MAAM,EAAe,EAAQ,OAAQ,EAAQ,QAAQ,EAEhE,EAAc,IAAS,UAAY,IAAS,QAAU,IAAS,MAC/D,EAAc,IAAS,UAAY,IAAS,QAAU,IAAS,MAC/D,EAAc,IAAS,UAAY,IAAS,MAC5C,EAAc,IAAS,UAAY,IAAS,MAC5C,EAAe,IAAS,WAAa,IAAS,MAM9C,EAAoD,CAAC,EAa3D,GAZI,GACF,EAAQ,KAAK,CACX,KAAM,EAAK,EAAQ,OAAQ,EAAY,WAAW,EAClD,WAAc,EAAe,EAAM,EAAU,CAAE,CACjD,CAAC,EAEC,GACF,EAAQ,KAAK,CACX,KAAM,EAAK,EAAQ,OAAQ,WAAW,EACtC,WAAc,EAAe,EAAM,EAAU,CAAE,CACjD,CAAC,EAEC,EAKF,IAAK,IAAM,KAAS,EAAyB,EAAM,EAAU,CAAE,EAC7D,EAAQ,KAAK,CACX,KAAM,EAAK,EAAQ,OAAQ,EAAY,SAAU,EAAM,KAAM,UAAU,EACvE,WAAc,EAAM,OACtB,CAAC,EAGD,GACF,EAAQ,KAAK,CACX,KAAM,EAAK,EAAQ,OAAQ,EAAY,WAAW,EAClD,WAAc,EAAe,EAAM,EAAU,CAAE,CACjD,CAAC,EAEC,GACF,EAAQ,KAAK,CACX,KAAM,EAAK,EAAQ,OAAQ,EAAY,YAAY,EACnD,WAAc,EAAgB,EAAM,EAAU,CAAE,CAClD,CAAC,EAGH,IAAM,EAAoB,CAAC,EAC3B,IAAK,GAAM,CAAE,OAAM,YAAY,EAAS,CACtC,GAAI,EAAW,CAAI,GAAK,CAAC,EAAQ,OAK3B,CAAC,MAJmB,EAAQ,CAC9B,QAAS,GAAG,EAAK,QAAQ,EAAQ,OAAS,IAAK,EAAE,EAAE,6BACnD,aAAc,EAChB,CAAC,EACe,CACd,QAAQ,IAAI,wBAAwB,EAAK,QAAQ,EAAQ,OAAS,IAAK,EAAE,EAAE,YAAY,EACvF,QACF,CAEF,MAAM,EAAc,EAAM,EAAO,CAAC,EAClC,EAAQ,KAAK,CAAI,CACnB,CACA,OAAO,CACT"}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs-cli v6.6.1
2
+ * @forinda/kickjs-cli v6.7.0
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,6 +8,6 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import{t as e}from"./rolldown-runtime-BKn_X0JJ.mjs";import{dirname as t,isAbsolute as n,join as r,relative as i,resolve as a}from"node:path";import{cpSync as o,existsSync as s,mkdirSync as c,statSync as l,writeFileSync as u}from"node:fs";import{glob as d}from"glob";import{groupAssetKeys as f}from"@forinda/kickjs";var p=e({ASSET_MANIFEST_VERSION:()=>1,buildAssets:()=>m});async function m(e,t){let{cwd:n,silent:o=!1}=t,s=t.distDir??e?.build?.outDir??`dist`,l=e?.assetMap;if(!l||Object.keys(l).length===0)return null;let d=o?()=>{}:console.log,f=a(n,s);c(f,{recursive:!0});let p=[],m={};for(let[e,t]of Object.entries(l)){let r=await h(e,t,n,f);p.push(r.entrySummary),Object.assign(m,r.manifestSlice),d(` ✓ ${e}: ${r.entrySummary.filesCopied} file(s) → ${r.entrySummary.dest}`)}let g={version:1,entries:m},_=r(f,`.kickjs-assets.json`);return u(_,JSON.stringify(g,null,2)+`
11
+ import{t as e}from"./rolldown-runtime-DiP_G7eI.mjs";import{dirname as t,isAbsolute as n,join as r,relative as i,resolve as a}from"node:path";import{cpSync as o,existsSync as s,mkdirSync as c,statSync as l,writeFileSync as u}from"node:fs";import{glob as d}from"glob";import{groupAssetKeys as f}from"@forinda/kickjs";var p=e({ASSET_MANIFEST_VERSION:()=>1,buildAssets:()=>m});async function m(e,t){let{cwd:n,silent:o=!1}=t,s=t.distDir??e?.build?.outDir??`dist`,l=e?.assetMap;if(!l||Object.keys(l).length===0)return null;let d=o?()=>{}:console.log,f=a(n,s);c(f,{recursive:!0});let p=[],m={};for(let[e,t]of Object.entries(l)){let r=await h(e,t,n,f);p.push(r.entrySummary),Object.assign(m,r.manifestSlice),d(` ✓ ${e}: ${r.entrySummary.filesCopied} file(s) → ${r.entrySummary.dest}`)}let g={version:1,entries:m},_=r(f,`.kickjs-assets.json`);return u(_,JSON.stringify(g,null,2)+`
12
12
  `,`utf-8`),d(` ✓ wrote manifest → ${i(n,_)} (${Object.keys(m).length} entries)`),{manifestPath:_,entries:p,manifest:g}}async function h(e,n,l,u){let p=a(l,n.src),m=n.dest?a(l,n.dest):r(u,e);if(v(m,l))return console.warn(` ⚠ assetMap.${e}.dest ('${n.dest}') resolves outside the project root — skipping copy`),{entrySummary:{namespace:e,src:n.src,dest:i(l,m),filesCopied:0},manifestSlice:{}};if(!s(p)||!y(p))return{entrySummary:{namespace:e,src:n.src,dest:i(l,m),filesCopied:0},manifestSlice:{}};let h=await d(n.glob??`**/*`,{cwd:p,nodir:!0,dot:!1,posix:!0});c(m,{recursive:!0});let b={},{pairs:x,collisionGroupsResolved:S}=f(e,[...h].toSorted(),{strategy:n.keys??`auto`}),C=0;for(let{rel:e,key:n}of x){let i=r(p,e),a=r(m,e);b[n]=_(u,a),!g(i,a)&&(c(t(a),{recursive:!0}),o(i,a),C++)}return S>0&&console.log(` ℹ assetMap.${e}: auto-resolved ${S} basename collision(s) by keeping extensions (set 'keys: "strip"' to opt back into legacy last-write-wins behaviour, or 'keys: "with-extension"' to keep all keys verbose).`),{entrySummary:{namespace:e,src:n.src,dest:i(l,m),filesCopied:C},manifestSlice:b}}function g(e,t){if(!s(t))return!1;try{let n=l(e),r=l(t);return r.size===n.size&&r.mtimeMs>=n.mtimeMs}catch{return!1}}function _(e,t){return i(e,t).split(/[\\/]/).filter(Boolean).join(`/`)}function v(e,t){let r=i(t,e);return r===``?!1:r.startsWith(`..`)||n(r)}function y(e){try{return l(e).isDirectory()}catch{return!1}}export{p as n,m as t};
13
- //# sourceMappingURL=build-DGTo6Lbp.mjs.map
13
+ //# sourceMappingURL=build-CDi72mKz.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"build-DGTo6Lbp.mjs","names":[],"sources":["../src/asset-manager/build.ts"],"sourcesContent":["/**\n * Build pipeline for `assetMap` entries (asset-manager PR 2).\n *\n * For each entry, walks `src/<...>` matching the configured `glob`,\n * copies matches into `dest` (default `dist/<name>/`), then emits a\n * `dist/.kickjs-assets.json` manifest mapping logical\n * `<namespace>/<key>` keys to repo-relative paths inside `dist/`.\n *\n * Pure function on top of `node:fs` + `glob` — no shell, no side\n * effects beyond the configured directory writes. The build entry-\n * point in `commands/run.ts` calls `buildAssets` after the existing\n * `copyDirs` step.\n *\n * @module @forinda/kickjs-cli/asset-manager/build\n */\n\nimport { cpSync, existsSync, mkdirSync, statSync, writeFileSync } from 'node:fs'\nimport { dirname, isAbsolute, join, relative, resolve } from 'node:path'\nimport { glob } from 'glob'\nimport { groupAssetKeys } from '@forinda/kickjs'\nimport type { AssetMapEntry, KickConfig } from '../config'\n\n/** Wire-format version for `dist/.kickjs-assets.json`. Bump on shape change. */\nexport const ASSET_MANIFEST_VERSION = 1 as const\n\n/** On-disk manifest format (`dist/.kickjs-assets.json`). */\nexport interface AssetManifest {\n version: typeof ASSET_MANIFEST_VERSION\n /**\n * Logical key → manifest-relative path. Logical key is\n * `<namespace>/<key>` where `<key>` is the file path under `src`\n * with the extension stripped + path separators normalised.\n *\n * Path values are relative to the manifest file's directory so the\n * runtime can resolve them with a single `path.resolve(manifestDir,\n * entry)` regardless of where dist/ lives.\n */\n entries: Record<string, string>\n}\n\nexport interface BuildAssetsOptions {\n /** Project root — resolved for every relative path in the entry. */\n cwd: string\n /**\n * Output dir for the manifest + per-namespace asset copies. When\n * omitted, falls back to `config.build?.outDir` (resolved against\n * `cwd`), then to `dist/` under cwd. Adopters with a custom Vite\n * `build.outDir` should set `kick.config.ts.build.outDir` to match.\n */\n distDir?: string\n /** Suppress per-entry log lines. Default: false. */\n silent?: boolean\n}\n\n/** One entry in the per-build summary returned by `buildAssets`. */\nexport interface BuildAssetsEntryResult {\n namespace: string\n src: string\n dest: string\n /**\n * Number of files actually written this run. On an incremental\n * rebuild where nothing changed this is 0 even though the manifest\n * still lists every matched file.\n */\n filesCopied: number\n}\n\n/** Aggregated outcome of `buildAssets`. */\nexport interface BuildAssetsResult {\n manifestPath: string\n entries: BuildAssetsEntryResult[]\n /** `entries` merged into a single record — useful for tests + tooling. */\n manifest: AssetManifest\n}\n\n/**\n * Run the full asset build for a loaded config:\n *\n * 1. For each `assetMap` entry, glob → copy → manifest stub.\n * 2. Write `dist/.kickjs-assets.json`.\n *\n * Returns a summary including the manifest contents. No-op (and no\n * manifest written) when `assetMap` is empty / missing — the build\n * pipeline shouldn't litter `dist/` with empty manifests for\n * adopters who don't use the feature.\n */\nexport async function buildAssets(\n config: KickConfig | null,\n opts: BuildAssetsOptions,\n): Promise<BuildAssetsResult | null> {\n const { cwd, silent = false } = opts\n // Resolution order: explicit opts.distDir → config.build.outDir → 'dist'.\n // The CLI build command passes nothing explicit, so adopters control\n // the output via kick.config.ts.build.outDir alone.\n const distDir = opts.distDir ?? config?.build?.outDir ?? 'dist'\n const map = config?.assetMap\n if (!map || Object.keys(map).length === 0) return null\n\n const log = silent ? () => {} : console.log\n\n const distAbs = resolve(cwd, distDir)\n mkdirSync(distAbs, { recursive: true })\n\n const summary: BuildAssetsEntryResult[] = []\n const manifestEntries: Record<string, string> = {}\n\n for (const [namespace, entry] of Object.entries(map)) {\n const result = await processEntry(namespace, entry, cwd, distAbs)\n summary.push(result.entrySummary)\n Object.assign(manifestEntries, result.manifestSlice)\n log(\n ` ✓ ${namespace}: ${result.entrySummary.filesCopied} file(s) → ${result.entrySummary.dest}`,\n )\n }\n\n const manifest: AssetManifest = {\n version: ASSET_MANIFEST_VERSION,\n entries: manifestEntries,\n }\n const manifestPath = join(distAbs, '.kickjs-assets.json')\n writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\\n', 'utf-8')\n log(\n ` ✓ wrote manifest → ${relative(cwd, manifestPath)} (${Object.keys(manifestEntries).length} entries)`,\n )\n\n return { manifestPath, entries: summary, manifest }\n}\n\n/** Per-entry inner pipeline — extracted for unit-test reuse. */\nasync function processEntry(\n namespace: string,\n entry: AssetMapEntry,\n cwd: string,\n distAbs: string,\n): Promise<{\n entrySummary: BuildAssetsEntryResult\n manifestSlice: Record<string, string>\n}> {\n const srcAbs = resolve(cwd, entry.src)\n const destAbs = entry.dest ? resolve(cwd, entry.dest) : join(distAbs, namespace)\n\n // Defensive: refuse to write outside the project root (cwd) even\n // though validateAssetMap warned about it at config-load time. The\n // build step shouldn't trust upstream warnings — a typo like\n // `dest: '../../'` would otherwise sprinkle files outside the\n // workspace despite the warning being printed.\n if (escapesRoot(destAbs, cwd)) {\n console.warn(\n ` ⚠ assetMap.${namespace}.dest ('${entry.dest}') resolves outside the project root — skipping copy`,\n )\n return {\n entrySummary: { namespace, src: entry.src, dest: relative(cwd, destAbs), filesCopied: 0 },\n manifestSlice: {},\n }\n }\n\n // Treat src-not-a-directory the same as src-missing — `glob` would\n // throw if pointed at a file, surfacing as a generic build failure\n // instead of a clean 0-files entry. Matches the validator's warning\n // shape (already emitted at config-load time for the missing case).\n if (!existsSync(srcAbs) || !isDirectorySync(srcAbs)) {\n return {\n entrySummary: { namespace, src: entry.src, dest: relative(cwd, destAbs), filesCopied: 0 },\n manifestSlice: {},\n }\n }\n\n const pattern = entry.glob ?? '**/*'\n // `glob` returns paths relative to `cwd` when `cwd` is set —\n // exactly the slugs we want for the manifest keys.\n const matches = await glob(pattern, {\n cwd: srcAbs,\n nodir: true,\n dot: false,\n posix: true,\n })\n\n mkdirSync(destAbs, { recursive: true })\n\n const manifestSlice: Record<string, string> = {}\n // Sort the walk so the manifest is byte-stable across platforms.\n // The `groupAssetKeys` helper preserves input order, so a stable\n // sort here makes the resulting manifest stable too.\n const sorted = [...matches].toSorted()\n const { pairs, collisionGroupsResolved } = groupAssetKeys(namespace, sorted, {\n strategy: entry.keys ?? 'auto',\n })\n\n // Copy the files and write the keyed manifest slice. Both come from\n // the same `pairs` order so the on-disk layout matches the\n // manifest's iteration order — easier to grep in cold-start\n // debugging.\n //\n // Incremental: skip the copy when the destination is already\n // up-to-date (exists, same size, mtime ≥ source). `cpSync` stamps the\n // copy with the current time, so an unchanged source always satisfies\n // `dest.mtime ≥ src.mtime` on the next run — turning a re-build into a\n // pure stat sweep instead of re-copying every asset. The manifest\n // slice is written unconditionally so the manifest stays complete.\n let filesCopied = 0\n for (const { rel: relPath, key } of pairs) {\n const srcFile = join(srcAbs, relPath)\n const destFile = join(destAbs, relPath)\n manifestSlice[key] = toManifestRelative(distAbs, destFile)\n if (isUpToDate(srcFile, destFile)) continue\n mkdirSync(dirname(destFile), { recursive: true })\n cpSync(srcFile, destFile)\n filesCopied++\n }\n\n if (collisionGroupsResolved > 0) {\n console.log(\n ` ℹ assetMap.${namespace}: auto-resolved ${collisionGroupsResolved} basename collision(s) by keeping extensions ` +\n `(set 'keys: \"strip\"' to opt back into legacy last-write-wins behaviour, or 'keys: \"with-extension\"' to keep all keys verbose).`,\n )\n }\n\n return {\n entrySummary: {\n namespace,\n src: entry.src,\n dest: relative(cwd, destAbs),\n filesCopied,\n },\n manifestSlice,\n }\n}\n\n/**\n * Is `destFile` already a current copy of `srcFile`? True when the\n * destination exists with the same byte size and an mtime no older than\n * the source. Used to skip redundant copies on an incremental rebuild.\n */\nfunction isUpToDate(srcFile: string, destFile: string): boolean {\n if (!existsSync(destFile)) return false\n try {\n const s = statSync(srcFile)\n const d = statSync(destFile)\n return d.size === s.size && d.mtimeMs >= s.mtimeMs\n } catch {\n return false\n }\n}\n\n/**\n * Make `destFile` relative to the manifest's directory + force POSIX\n * separators so the manifest is byte-stable across platforms.\n */\nfunction toManifestRelative(manifestDir: string, destFile: string): string {\n const rel = relative(manifestDir, destFile)\n // path.relative returns OS-native separators; the manifest is JSON\n // and the runtime uses path.resolve which handles either, but a\n // forward-slash manifest is grep-friendly + diff-stable.\n return rel.split(/[\\\\/]/).filter(Boolean).join('/')\n}\n\n/**\n * Pure manifest writer — handy for tests that want to assert against\n * a hand-crafted manifest without exercising the full pipeline.\n */\nexport function writeAssetManifest(distDir: string, manifest: AssetManifest): string {\n const path = join(distDir, '.kickjs-assets.json')\n mkdirSync(distDir, { recursive: true })\n writeFileSync(path, JSON.stringify(manifest, null, 2) + '\\n', 'utf-8')\n return path\n}\n\n/**\n * Read + parse a manifest from disk. Returns `null` on missing or\n * malformed file rather than throwing — the runtime resolver wants\n * to fall through to dev-mode lookup in that case.\n */\nexport function readAssetManifest(distDir: string): AssetManifest | null {\n const path = join(distDir, '.kickjs-assets.json')\n if (!existsSync(path)) return null\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const fs = require('node:fs') as typeof import('node:fs')\n const raw = fs.readFileSync(path, 'utf-8')\n const parsed = JSON.parse(raw) as Partial<AssetManifest>\n if (parsed.version !== ASSET_MANIFEST_VERSION) return null\n if (!parsed.entries || typeof parsed.entries !== 'object') return null\n return parsed as AssetManifest\n } catch {\n return null\n }\n}\n\n/**\n * Project-root escape check that's safe across symlinks + drive letters.\n * `path.relative` returns `..` segments when the target sits above root,\n * and an absolute path when the two live on different roots (Windows).\n * `startsWith(root)` would miss both cases.\n */\nfunction escapesRoot(path: string, root: string): boolean {\n const rel = relative(root, path)\n if (rel === '') return false\n return rel.startsWith('..') || isAbsolute(rel)\n}\n\n/** Pure helper — `false` for missing, non-dir, or unreadable paths. */\nfunction isDirectorySync(path: string): boolean {\n try {\n return statSync(path).isDirectory()\n } catch {\n return false\n }\n}\n"],"mappings":";;;;;;;;;;qXAsFA,eAAsB,EACpB,EACA,EACmC,CACnC,GAAM,CAAE,MAAK,SAAS,IAAU,EAI1B,EAAU,EAAK,SAAW,GAAQ,OAAO,QAAU,OACnD,EAAM,GAAQ,SACpB,GAAI,CAAC,GAAO,OAAO,KAAK,CAAG,CAAC,CAAC,SAAW,EAAG,OAAO,KAElD,IAAM,EAAM,MAAe,CAAC,EAAI,QAAQ,IAElC,EAAU,EAAQ,EAAK,CAAO,EACpC,EAAU,EAAS,CAAE,UAAW,EAAK,CAAC,EAEtC,IAAM,EAAoC,CAAC,EACrC,EAA0C,CAAC,EAEjD,IAAK,GAAM,CAAC,EAAW,KAAU,OAAO,QAAQ,CAAG,EAAG,CACpD,IAAM,EAAS,MAAM,EAAa,EAAW,EAAO,EAAK,CAAO,EAChE,EAAQ,KAAK,EAAO,YAAY,EAChC,OAAO,OAAO,EAAiB,EAAO,aAAa,EACnD,EACE,SAAS,EAAU,IAAI,EAAO,aAAa,YAAY,aAAa,EAAO,aAAa,MAC1F,CACF,CAEA,IAAM,EAA0B,CAC9B,QAAA,EACA,QAAS,CACX,EACM,EAAe,EAAK,EAAS,qBAAqB,EAMxD,OALA,EAAc,EAAc,KAAK,UAAU,EAAU,KAAM,CAAC,EAAI;EAAM,OAAO,EAC7E,EACE,0BAA0B,EAAS,EAAK,CAAY,EAAE,IAAI,OAAO,KAAK,CAAe,CAAC,CAAC,OAAO,UAChG,EAEO,CAAE,eAAc,QAAS,EAAS,UAAS,CACpD,CAGA,eAAe,EACb,EACA,EACA,EACA,EAIC,CACD,IAAM,EAAS,EAAQ,EAAK,EAAM,GAAG,EAC/B,EAAU,EAAM,KAAO,EAAQ,EAAK,EAAM,IAAI,EAAI,EAAK,EAAS,CAAS,EAO/E,GAAI,EAAY,EAAS,CAAG,EAI1B,OAHA,QAAQ,KACN,gBAAgB,EAAU,UAAU,EAAM,KAAK,qDACjD,EACO,CACL,aAAc,CAAE,YAAW,IAAK,EAAM,IAAK,KAAM,EAAS,EAAK,CAAO,EAAG,YAAa,CAAE,EACxF,cAAe,CAAC,CAClB,EAOF,GAAI,CAAC,EAAW,CAAM,GAAK,CAAC,EAAgB,CAAM,EAChD,MAAO,CACL,aAAc,CAAE,YAAW,IAAK,EAAM,IAAK,KAAM,EAAS,EAAK,CAAO,EAAG,YAAa,CAAE,EACxF,cAAe,CAAC,CAClB,EAMF,IAAM,EAAU,MAAM,EAHN,EAAM,MAAQ,OAGM,CAClC,IAAK,EACL,MAAO,GACP,IAAK,GACL,MAAO,EACT,CAAC,EAED,EAAU,EAAS,CAAE,UAAW,EAAK,CAAC,EAEtC,IAAM,EAAwC,CAAC,EAKzC,CAAE,QAAO,2BAA4B,EAAe,EAD3C,CAAC,GAAG,CAAO,CAAC,CAAC,SAC8C,EAAG,CAC3E,SAAU,EAAM,MAAQ,MAC1B,CAAC,EAaG,EAAc,EAClB,IAAK,GAAM,CAAE,IAAK,EAAS,SAAS,EAAO,CACzC,IAAM,EAAU,EAAK,EAAQ,CAAO,EAC9B,EAAW,EAAK,EAAS,CAAO,EACtC,EAAc,GAAO,EAAmB,EAAS,CAAQ,EACrD,GAAW,EAAS,CAAQ,IAChC,EAAU,EAAQ,CAAQ,EAAG,CAAE,UAAW,EAAK,CAAC,EAChD,EAAO,EAAS,CAAQ,EACxB,IACF,CASA,OAPI,EAA0B,GAC5B,QAAQ,IACN,gBAAgB,EAAU,kBAAkB,EAAwB,4KAEtE,EAGK,CACL,aAAc,CACZ,YACA,IAAK,EAAM,IACX,KAAM,EAAS,EAAK,CAAO,EAC3B,aACF,EACA,eACF,CACF,CAOA,SAAS,EAAW,EAAiB,EAA2B,CAC9D,GAAI,CAAC,EAAW,CAAQ,EAAG,MAAO,GAClC,GAAI,CACF,IAAM,EAAI,EAAS,CAAO,EACpB,EAAI,EAAS,CAAQ,EAC3B,OAAO,EAAE,OAAS,EAAE,MAAQ,EAAE,SAAW,EAAE,OAC7C,MAAQ,CACN,MAAO,EACT,CACF,CAMA,SAAS,EAAmB,EAAqB,EAA0B,CAKzE,OAJY,EAAS,EAAa,CAIzB,CAAC,CAAC,MAAM,OAAO,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,CACpD,CAwCA,SAAS,EAAY,EAAc,EAAuB,CACxD,IAAM,EAAM,EAAS,EAAM,CAAI,EAE/B,OADI,IAAQ,GAAW,GAChB,EAAI,WAAW,IAAI,GAAK,EAAW,CAAG,CAC/C,CAGA,SAAS,EAAgB,EAAuB,CAC9C,GAAI,CACF,OAAO,EAAS,CAAI,CAAC,CAAC,YAAY,CACpC,MAAQ,CACN,MAAO,EACT,CACF"}
1
+ {"version":3,"file":"build-CDi72mKz.mjs","names":[],"sources":["../src/asset-manager/build.ts"],"sourcesContent":["/**\n * Build pipeline for `assetMap` entries (asset-manager PR 2).\n *\n * For each entry, walks `src/<...>` matching the configured `glob`,\n * copies matches into `dest` (default `dist/<name>/`), then emits a\n * `dist/.kickjs-assets.json` manifest mapping logical\n * `<namespace>/<key>` keys to repo-relative paths inside `dist/`.\n *\n * Pure function on top of `node:fs` + `glob` — no shell, no side\n * effects beyond the configured directory writes. The build entry-\n * point in `commands/run.ts` calls `buildAssets` after the existing\n * `copyDirs` step.\n *\n * @module @forinda/kickjs-cli/asset-manager/build\n */\n\nimport { cpSync, existsSync, mkdirSync, statSync, writeFileSync } from 'node:fs'\nimport { dirname, isAbsolute, join, relative, resolve } from 'node:path'\nimport { glob } from 'glob'\nimport { groupAssetKeys } from '@forinda/kickjs'\nimport type { AssetMapEntry, KickConfig } from '../config'\n\n/** Wire-format version for `dist/.kickjs-assets.json`. Bump on shape change. */\nexport const ASSET_MANIFEST_VERSION = 1 as const\n\n/** On-disk manifest format (`dist/.kickjs-assets.json`). */\nexport interface AssetManifest {\n version: typeof ASSET_MANIFEST_VERSION\n /**\n * Logical key → manifest-relative path. Logical key is\n * `<namespace>/<key>` where `<key>` is the file path under `src`\n * with the extension stripped + path separators normalised.\n *\n * Path values are relative to the manifest file's directory so the\n * runtime can resolve them with a single `path.resolve(manifestDir,\n * entry)` regardless of where dist/ lives.\n */\n entries: Record<string, string>\n}\n\nexport interface BuildAssetsOptions {\n /** Project root — resolved for every relative path in the entry. */\n cwd: string\n /**\n * Output dir for the manifest + per-namespace asset copies. When\n * omitted, falls back to `config.build?.outDir` (resolved against\n * `cwd`), then to `dist/` under cwd. Adopters with a custom Vite\n * `build.outDir` should set `kick.config.ts.build.outDir` to match.\n */\n distDir?: string\n /** Suppress per-entry log lines. Default: false. */\n silent?: boolean\n}\n\n/** One entry in the per-build summary returned by `buildAssets`. */\nexport interface BuildAssetsEntryResult {\n namespace: string\n src: string\n dest: string\n /**\n * Number of files actually written this run. On an incremental\n * rebuild where nothing changed this is 0 even though the manifest\n * still lists every matched file.\n */\n filesCopied: number\n}\n\n/** Aggregated outcome of `buildAssets`. */\nexport interface BuildAssetsResult {\n manifestPath: string\n entries: BuildAssetsEntryResult[]\n /** `entries` merged into a single record — useful for tests + tooling. */\n manifest: AssetManifest\n}\n\n/**\n * Run the full asset build for a loaded config:\n *\n * 1. For each `assetMap` entry, glob → copy → manifest stub.\n * 2. Write `dist/.kickjs-assets.json`.\n *\n * Returns a summary including the manifest contents. No-op (and no\n * manifest written) when `assetMap` is empty / missing — the build\n * pipeline shouldn't litter `dist/` with empty manifests for\n * adopters who don't use the feature.\n */\nexport async function buildAssets(\n config: KickConfig | null,\n opts: BuildAssetsOptions,\n): Promise<BuildAssetsResult | null> {\n const { cwd, silent = false } = opts\n // Resolution order: explicit opts.distDir → config.build.outDir → 'dist'.\n // The CLI build command passes nothing explicit, so adopters control\n // the output via kick.config.ts.build.outDir alone.\n const distDir = opts.distDir ?? config?.build?.outDir ?? 'dist'\n const map = config?.assetMap\n if (!map || Object.keys(map).length === 0) return null\n\n const log = silent ? () => {} : console.log\n\n const distAbs = resolve(cwd, distDir)\n mkdirSync(distAbs, { recursive: true })\n\n const summary: BuildAssetsEntryResult[] = []\n const manifestEntries: Record<string, string> = {}\n\n for (const [namespace, entry] of Object.entries(map)) {\n const result = await processEntry(namespace, entry, cwd, distAbs)\n summary.push(result.entrySummary)\n Object.assign(manifestEntries, result.manifestSlice)\n log(\n ` ✓ ${namespace}: ${result.entrySummary.filesCopied} file(s) → ${result.entrySummary.dest}`,\n )\n }\n\n const manifest: AssetManifest = {\n version: ASSET_MANIFEST_VERSION,\n entries: manifestEntries,\n }\n const manifestPath = join(distAbs, '.kickjs-assets.json')\n writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\\n', 'utf-8')\n log(\n ` ✓ wrote manifest → ${relative(cwd, manifestPath)} (${Object.keys(manifestEntries).length} entries)`,\n )\n\n return { manifestPath, entries: summary, manifest }\n}\n\n/** Per-entry inner pipeline — extracted for unit-test reuse. */\nasync function processEntry(\n namespace: string,\n entry: AssetMapEntry,\n cwd: string,\n distAbs: string,\n): Promise<{\n entrySummary: BuildAssetsEntryResult\n manifestSlice: Record<string, string>\n}> {\n const srcAbs = resolve(cwd, entry.src)\n const destAbs = entry.dest ? resolve(cwd, entry.dest) : join(distAbs, namespace)\n\n // Defensive: refuse to write outside the project root (cwd) even\n // though validateAssetMap warned about it at config-load time. The\n // build step shouldn't trust upstream warnings — a typo like\n // `dest: '../../'` would otherwise sprinkle files outside the\n // workspace despite the warning being printed.\n if (escapesRoot(destAbs, cwd)) {\n console.warn(\n ` ⚠ assetMap.${namespace}.dest ('${entry.dest}') resolves outside the project root — skipping copy`,\n )\n return {\n entrySummary: { namespace, src: entry.src, dest: relative(cwd, destAbs), filesCopied: 0 },\n manifestSlice: {},\n }\n }\n\n // Treat src-not-a-directory the same as src-missing — `glob` would\n // throw if pointed at a file, surfacing as a generic build failure\n // instead of a clean 0-files entry. Matches the validator's warning\n // shape (already emitted at config-load time for the missing case).\n if (!existsSync(srcAbs) || !isDirectorySync(srcAbs)) {\n return {\n entrySummary: { namespace, src: entry.src, dest: relative(cwd, destAbs), filesCopied: 0 },\n manifestSlice: {},\n }\n }\n\n const pattern = entry.glob ?? '**/*'\n // `glob` returns paths relative to `cwd` when `cwd` is set —\n // exactly the slugs we want for the manifest keys.\n const matches = await glob(pattern, {\n cwd: srcAbs,\n nodir: true,\n dot: false,\n posix: true,\n })\n\n mkdirSync(destAbs, { recursive: true })\n\n const manifestSlice: Record<string, string> = {}\n // Sort the walk so the manifest is byte-stable across platforms.\n // The `groupAssetKeys` helper preserves input order, so a stable\n // sort here makes the resulting manifest stable too.\n const sorted = [...matches].toSorted()\n const { pairs, collisionGroupsResolved } = groupAssetKeys(namespace, sorted, {\n strategy: entry.keys ?? 'auto',\n })\n\n // Copy the files and write the keyed manifest slice. Both come from\n // the same `pairs` order so the on-disk layout matches the\n // manifest's iteration order — easier to grep in cold-start\n // debugging.\n //\n // Incremental: skip the copy when the destination is already\n // up-to-date (exists, same size, mtime ≥ source). `cpSync` stamps the\n // copy with the current time, so an unchanged source always satisfies\n // `dest.mtime ≥ src.mtime` on the next run — turning a re-build into a\n // pure stat sweep instead of re-copying every asset. The manifest\n // slice is written unconditionally so the manifest stays complete.\n let filesCopied = 0\n for (const { rel: relPath, key } of pairs) {\n const srcFile = join(srcAbs, relPath)\n const destFile = join(destAbs, relPath)\n manifestSlice[key] = toManifestRelative(distAbs, destFile)\n if (isUpToDate(srcFile, destFile)) continue\n mkdirSync(dirname(destFile), { recursive: true })\n cpSync(srcFile, destFile)\n filesCopied++\n }\n\n if (collisionGroupsResolved > 0) {\n console.log(\n ` ℹ assetMap.${namespace}: auto-resolved ${collisionGroupsResolved} basename collision(s) by keeping extensions ` +\n `(set 'keys: \"strip\"' to opt back into legacy last-write-wins behaviour, or 'keys: \"with-extension\"' to keep all keys verbose).`,\n )\n }\n\n return {\n entrySummary: {\n namespace,\n src: entry.src,\n dest: relative(cwd, destAbs),\n filesCopied,\n },\n manifestSlice,\n }\n}\n\n/**\n * Is `destFile` already a current copy of `srcFile`? True when the\n * destination exists with the same byte size and an mtime no older than\n * the source. Used to skip redundant copies on an incremental rebuild.\n */\nfunction isUpToDate(srcFile: string, destFile: string): boolean {\n if (!existsSync(destFile)) return false\n try {\n const s = statSync(srcFile)\n const d = statSync(destFile)\n return d.size === s.size && d.mtimeMs >= s.mtimeMs\n } catch {\n return false\n }\n}\n\n/**\n * Make `destFile` relative to the manifest's directory + force POSIX\n * separators so the manifest is byte-stable across platforms.\n */\nfunction toManifestRelative(manifestDir: string, destFile: string): string {\n const rel = relative(manifestDir, destFile)\n // path.relative returns OS-native separators; the manifest is JSON\n // and the runtime uses path.resolve which handles either, but a\n // forward-slash manifest is grep-friendly + diff-stable.\n return rel.split(/[\\\\/]/).filter(Boolean).join('/')\n}\n\n/**\n * Pure manifest writer — handy for tests that want to assert against\n * a hand-crafted manifest without exercising the full pipeline.\n */\nexport function writeAssetManifest(distDir: string, manifest: AssetManifest): string {\n const path = join(distDir, '.kickjs-assets.json')\n mkdirSync(distDir, { recursive: true })\n writeFileSync(path, JSON.stringify(manifest, null, 2) + '\\n', 'utf-8')\n return path\n}\n\n/**\n * Read + parse a manifest from disk. Returns `null` on missing or\n * malformed file rather than throwing — the runtime resolver wants\n * to fall through to dev-mode lookup in that case.\n */\nexport function readAssetManifest(distDir: string): AssetManifest | null {\n const path = join(distDir, '.kickjs-assets.json')\n if (!existsSync(path)) return null\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const fs = require('node:fs') as typeof import('node:fs')\n const raw = fs.readFileSync(path, 'utf-8')\n const parsed = JSON.parse(raw) as Partial<AssetManifest>\n if (parsed.version !== ASSET_MANIFEST_VERSION) return null\n if (!parsed.entries || typeof parsed.entries !== 'object') return null\n return parsed as AssetManifest\n } catch {\n return null\n }\n}\n\n/**\n * Project-root escape check that's safe across symlinks + drive letters.\n * `path.relative` returns `..` segments when the target sits above root,\n * and an absolute path when the two live on different roots (Windows).\n * `startsWith(root)` would miss both cases.\n */\nfunction escapesRoot(path: string, root: string): boolean {\n const rel = relative(root, path)\n if (rel === '') return false\n return rel.startsWith('..') || isAbsolute(rel)\n}\n\n/** Pure helper — `false` for missing, non-dir, or unreadable paths. */\nfunction isDirectorySync(path: string): boolean {\n try {\n return statSync(path).isDirectory()\n } catch {\n return false\n }\n}\n"],"mappings":";;;;;;;;;;qXAsFA,eAAsB,EACpB,EACA,EACmC,CACnC,GAAM,CAAE,MAAK,SAAS,IAAU,EAI1B,EAAU,EAAK,SAAW,GAAQ,OAAO,QAAU,OACnD,EAAM,GAAQ,SACpB,GAAI,CAAC,GAAO,OAAO,KAAK,CAAG,CAAC,CAAC,SAAW,EAAG,OAAO,KAElD,IAAM,EAAM,MAAe,CAAC,EAAI,QAAQ,IAElC,EAAU,EAAQ,EAAK,CAAO,EACpC,EAAU,EAAS,CAAE,UAAW,EAAK,CAAC,EAEtC,IAAM,EAAoC,CAAC,EACrC,EAA0C,CAAC,EAEjD,IAAK,GAAM,CAAC,EAAW,KAAU,OAAO,QAAQ,CAAG,EAAG,CACpD,IAAM,EAAS,MAAM,EAAa,EAAW,EAAO,EAAK,CAAO,EAChE,EAAQ,KAAK,EAAO,YAAY,EAChC,OAAO,OAAO,EAAiB,EAAO,aAAa,EACnD,EACE,SAAS,EAAU,IAAI,EAAO,aAAa,YAAY,aAAa,EAAO,aAAa,MAC1F,CACF,CAEA,IAAM,EAA0B,CAC9B,QAAA,EACA,QAAS,CACX,EACM,EAAe,EAAK,EAAS,qBAAqB,EAMxD,OALA,EAAc,EAAc,KAAK,UAAU,EAAU,KAAM,CAAC,EAAI;EAAM,OAAO,EAC7E,EACE,0BAA0B,EAAS,EAAK,CAAY,EAAE,IAAI,OAAO,KAAK,CAAe,CAAC,CAAC,OAAO,UAChG,EAEO,CAAE,eAAc,QAAS,EAAS,UAAS,CACpD,CAGA,eAAe,EACb,EACA,EACA,EACA,EAIC,CACD,IAAM,EAAS,EAAQ,EAAK,EAAM,GAAG,EAC/B,EAAU,EAAM,KAAO,EAAQ,EAAK,EAAM,IAAI,EAAI,EAAK,EAAS,CAAS,EAO/E,GAAI,EAAY,EAAS,CAAG,EAI1B,OAHA,QAAQ,KACN,gBAAgB,EAAU,UAAU,EAAM,KAAK,qDACjD,EACO,CACL,aAAc,CAAE,YAAW,IAAK,EAAM,IAAK,KAAM,EAAS,EAAK,CAAO,EAAG,YAAa,CAAE,EACxF,cAAe,CAAC,CAClB,EAOF,GAAI,CAAC,EAAW,CAAM,GAAK,CAAC,EAAgB,CAAM,EAChD,MAAO,CACL,aAAc,CAAE,YAAW,IAAK,EAAM,IAAK,KAAM,EAAS,EAAK,CAAO,EAAG,YAAa,CAAE,EACxF,cAAe,CAAC,CAClB,EAMF,IAAM,EAAU,MAAM,EAHN,EAAM,MAAQ,OAGM,CAClC,IAAK,EACL,MAAO,GACP,IAAK,GACL,MAAO,EACT,CAAC,EAED,EAAU,EAAS,CAAE,UAAW,EAAK,CAAC,EAEtC,IAAM,EAAwC,CAAC,EAKzC,CAAE,QAAO,2BAA4B,EAAe,EAD3C,CAAC,GAAG,CAAO,CAAC,CAAC,SAC8C,EAAG,CAC3E,SAAU,EAAM,MAAQ,MAC1B,CAAC,EAaG,EAAc,EAClB,IAAK,GAAM,CAAE,IAAK,EAAS,SAAS,EAAO,CACzC,IAAM,EAAU,EAAK,EAAQ,CAAO,EAC9B,EAAW,EAAK,EAAS,CAAO,EACtC,EAAc,GAAO,EAAmB,EAAS,CAAQ,EACrD,GAAW,EAAS,CAAQ,IAChC,EAAU,EAAQ,CAAQ,EAAG,CAAE,UAAW,EAAK,CAAC,EAChD,EAAO,EAAS,CAAQ,EACxB,IACF,CASA,OAPI,EAA0B,GAC5B,QAAQ,IACN,gBAAgB,EAAU,kBAAkB,EAAwB,4KAEtE,EAGK,CACL,aAAc,CACZ,YACA,IAAK,EAAM,IACX,KAAM,EAAS,EAAK,CAAO,EAC3B,aACF,EACA,eACF,CACF,CAOA,SAAS,EAAW,EAAiB,EAA2B,CAC9D,GAAI,CAAC,EAAW,CAAQ,EAAG,MAAO,GAClC,GAAI,CACF,IAAM,EAAI,EAAS,CAAO,EACpB,EAAI,EAAS,CAAQ,EAC3B,OAAO,EAAE,OAAS,EAAE,MAAQ,EAAE,SAAW,EAAE,OAC7C,MAAQ,CACN,MAAO,EACT,CACF,CAMA,SAAS,EAAmB,EAAqB,EAA0B,CAKzE,OAJY,EAAS,EAAa,CAIzB,CAAC,CAAC,MAAM,OAAO,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,CACpD,CAwCA,SAAS,EAAY,EAAc,EAAuB,CACxD,IAAM,EAAM,EAAS,EAAM,CAAI,EAE/B,OADI,IAAQ,GAAW,GAChB,EAAI,WAAW,IAAI,GAAK,EAAW,CAAG,CAC/C,CAGA,SAAS,EAAgB,EAAuB,CAC9C,GAAI,CACF,OAAO,EAAS,CAAI,CAAC,CAAC,YAAY,CACpC,MAAQ,CACN,MAAO,EACT,CACF"}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs-cli v6.6.1
2
+ * @forinda/kickjs-cli v6.7.0
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,4 +8,4 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import{t as e}from"./run-plugins-C1wpiuKz.mjs";export{e as builtinCliPlugins};
11
+ import{t as e}from"./run-plugins-C5kGYAsD.mjs";export{e as builtinCliPlugins};
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs-cli v6.6.1
2
+ * @forinda/kickjs-cli v6.7.0
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -1268,7 +1268,7 @@ in \`.agents/COPILOT.local.md\`.
1268
1268
  `),a.length===0&&o.length===0))){if(a.length>0){let e=a,t=`${n} add ${e.join(` `)}`;console.log(`\n Installing ${e.length} dependency(ies):`);for(let t of e)console.log(` + ${t}`);console.log();try{C(t,{stdio:`inherit`})}catch{console.log(`\n Installation failed. Run manually:\n ${t}\n`)}}if(o.length>0){let e=o,t=`${n} add -D ${e.join(` `)}`;console.log(`\n Installing ${e.length} dev dependency(ies):`);for(let t of e)console.log(` + ${t} (dev)`);console.log();try{C(t,{stdio:`inherit`})}catch{console.log(`\n Installation failed. Run manually:\n ${t}\n`)}}console.log(` Done!
1269
1269
  `)}})}const Nt=f(b(import.meta.url)),Pt=JSON.parse(a(h(Nt,`..`,`package.json`),`utf-8`)),Ft=`^${Pt.version}`,It=[`@forinda/kickjs`,`@forinda/kickjs-cli`,`@forinda/kickjs-schema`,`@forinda/kickjs-vite`,`@forinda/kickjs-swagger`,`@forinda/kickjs-ws`,`@forinda/kickjs-queue`,`@forinda/kickjs-devtools`,`@forinda/kickjs-testing`,`@forinda/kickjs-client`];async function Lt(){let e=await Promise.all(It.map(async e=>{try{let t=S(`npm`,[`view`,e,`version`],{encoding:`utf-8`,timeout:5e3,stdio:[`ignore`,`pipe`,`ignore`]}).toString().trim();if(t&&/^\d+\.\d+\.\d+/.test(t))return[e,`^${t}`]}catch{}return[e,Ft]}));return Object.fromEntries(e)}function Rt(e,t){try{let n=S(`npm`,[`view`,`${e}@${t}`,`version`],{encoding:`utf-8`,timeout:5e3,stdio:[`ignore`,`pipe`,`ignore`]}).toString().trim();return n&&/^\d+\.\d+\.\d+/.test(n)?n:null}catch{return null}}function zt(e){return(e??``).replace(/^[\^~>=<\s]+/,``)}function Bt(e,t){let n=e=>zt(e).split(`-`)[0].split(`.`).map(e=>Number.parseInt(e,10)||0),[r=0,i=0,a=0]=n(e),[o=0,s=0,c=0]=n(t);return r===o?i===s?a>=c:i>s:r>o}function Vt(e,t,n){try{let r=S(`npm`,[`view`,`${e}@${t}`,`exports`,`--json`],{encoding:`utf-8`,timeout:5e3,stdio:[`ignore`,`pipe`,`ignore`]}).toString().trim();if(!r)return!1;let i=JSON.parse(r);return Object.prototype.hasOwnProperty.call(i,n)}catch{return!1}}async function Ht(e){let{name:t,directory:n,packageManager:r=`pnpm`,template:i=`rest`,defaultRepo:a=`inmemory`,packages:o=[],schemaLib:s=`zod`,runtime:c=`express`}=e,l=n,u=e=>console.log(` ${e}`);console.log(`\n Creating KickJS project: ${t}\n`),u(`Resolving package versions...`);let d=await Lt();if(c!==`express`)if(Vt(`@forinda/kickjs`,`latest`,`./${c}`))u(`Using @forinda/kickjs@latest (stable ships the ${c} runtime)`);else{let e=[`@forinda/kickjs`,`@forinda/kickjs-cli`,`@forinda/kickjs-vite`],t=[],n=!1;for(let r of e){let e=Rt(r,`alpha`);e&&Bt(e,zt(d[r]))&&(d[r]=`^${e}`,t.push(`${r}@^${e}`),r===`@forinda/kickjs`&&(n=!0))}u(n?`Using the alpha channel for the ${c} runtime: ${t.join(`, `)}`:`WARNING: could not resolve @forinda/kickjs@alpha — the ${c} runtime subpath may be missing. After install, run: ${r} add @forinda/kickjs@alpha`)}await N(h(l,`package.json`),Ye(t,i,d,o,s,c)),await N(h(l,`vite.config.ts`),Xe()),await N(h(l,`tsconfig.json`),Ze()),await N(h(l,`.prettierrc`),Qe()),await N(h(l,`.editorconfig`),$e()),await N(h(l,`.gitignore`),et()),await N(h(l,`.gitattributes`),tt()),await N(h(l,`.env`),nt()),await N(h(l,`.env.example`),rt()),await N(h(l,`src/config/index.ts`),ct(s)),await N(h(l,`src/index.ts`),ot(t,i,Pt.version,o,c)),await N(h(l,`src/modules/index.ts`),st()),await N(h(l,`src/modules/hello/hello.service.ts`),lt()),await N(h(l,`src/modules/hello/hello.controller.ts`),ut()),await N(h(l,`src/modules/hello/hello.module.ts`),dt()),await N(h(l,`kick.config.ts`),ft(i,a,r,c)),await N(h(l,`vitest.config.ts`),it()),await N(h(l,`README.md`),pt(t,i,r));let{generateAgentDocs:f}=await Promise.resolve().then(()=>ar);if(await f({outDir:l,name:t,pm:r,template:i,only:`all`,force:!0}),e.installDeps){console.log(`\n Installing dependencies with ${r}...\n`);try{C(`${r} install`,{cwd:l,stdio:`inherit`}),console.log(`
1270
1270
  Dependencies installed successfully!`)}catch{console.log(`\n Warning: ${r} install failed. Run it manually.`)}}try{let{runTypegen:e}=await Promise.resolve().then(()=>Aa);await e({cwd:l,allowDuplicates:!0,silent:!0})}catch{}if(e.initGit)try{C(`git init`,{cwd:l,stdio:`pipe`}),C(`git branch -M main`,{cwd:l,stdio:`pipe`}),C(`git add -A`,{cwd:l,stdio:`pipe`}),C(`git commit -m "chore: initial commit from kick new"`,{cwd:l,stdio:`pipe`}),u(`Git repository initialized`)}catch{u(`Warning: git init failed (git may not be installed)`)}console.log(`
1271
- Project scaffolded successfully!`),console.log();let p=l!==process.cwd();u(`Next steps:`),p&&u(` cd ${t}`),e.installDeps||u(` ${r} install`);let m={rest:`kick g module user`,ddd:`kick g module user --repo drizzle`,cqrs:`kick g module user --pattern cqrs`,minimal:`# add your routes to src/index.ts`};u(` ${m[i]??m.rest}`),u(` kick dev`),u(``),u(`Commands:`),u(` kick dev Start dev server with Vite HMR`),u(` kick build Production build via Vite`),u(` kick start Run production build`),u(``),u(`Generators:`),u(` kick g module <name> Full DDD module (controller, DTOs, use-cases, repo)`),u(` kick g scaffold <n> <f..> CRUD module from field definitions`),u(` kick g controller <name> Standalone controller`),u(` kick g service <name> @Service() class`),u(` kick g middleware <name> Express middleware`),u(` kick g guard <name> Route guard (auth, roles, etc.)`),u(` kick g adapter <name> AppAdapter with lifecycle hooks`),u(` kick g dto <name> Zod DTO schema`),u(` kick g config Generate kick.config.ts`),u(``),u(`Add packages:`),u(` kick add <pkg> Install a KickJS package + peers`),u(` kick add --list Show all available packages`),u(``),u(`Available: ${bt}`),u(``)}const Ut={GET:O.green,POST:O.cyan,PUT:O.yellow,PATCH:O.magenta,DELETE:O.red};function Wt(e){return(Ut[e]??O.dim)(e.padEnd(7))}function Gt(e){let t=`[${e}]`.padEnd(10);switch(e){case`CRITICAL`:return O.red(t);case`WARNING`:return O.yellow(t);case`INFO`:return O.blue(O.dim(t));default:return t}}O.green(`✓`),O.red(`✖`),O.yellow(`⚠`),O.blue(`ℹ`);function Kt(e){D.intro(O.bgCyan(O.black(` ${e} `)))}function P(e){D.outro(e)}function qt(e){D.isCancel(e)&&(D.cancel(`Operation cancelled.`),process.exit(0))}async function Jt(e){let t=await D.text(e);return qt(t),t}async function Yt(e){let t=await D.select(e);return qt(t),t}async function Xt(e){let t=await D.multiselect(e);return qt(t),t}async function F(e){let t=await D.confirm(e);return qt(t),t}function Zt(){return D.spinner()}const I=D.log,Qt=[{value:`swagger`,label:`Swagger`,hint:`OpenAPI docs`},{value:`ws`,label:`WebSocket`,hint:`rooms, heartbeat`},{value:`queue`,label:`Queue`,hint:`BullMQ/RabbitMQ/Kafka`},{value:`devtools`,label:`DevTools`,hint:`debug dashboard`}];function $t(e){e.command(`new [name]`).alias(`init`).description(`Create a new KickJS project (use "." for current directory)`).option(`-d, --directory <dir>`,`Target directory (defaults to project name)`).option(`--pm <manager>`,`Package manager: pnpm | npm | yarn | bun`).option(`--git`,`Initialize git repository`).option(`--no-git`,`Skip git initialization`).option(`--install`,`Install dependencies after scaffolding`).option(`--no-install`,`Skip dependency installation`).option(`-f, --force`,`Remove existing files without prompting`).option(`-t, --template <type>`,`Project template: rest | minimal | fullstack`).option(`--runtime <engine>`,`HTTP runtime: express | fastify | h3`).option(`-r, --repo <type>`,`Repository name (inmemory, or any DB name e.g. postgres)`).option(`-s, --schema <lib>`,`Schema library for env / DTOs: zod | valibot | yup (default: zod)`).option(`--packages <packages>`,`Comma-separated packages to include (e.g. auth,swagger,ws,queue)`).option(`-y, --yes`,`Pick safe defaults for every prompt (template=minimal, repo=inmemory, no extras, git+install on)`).option(`--non-interactive`,`alias for --yes`).action(async(e,t)=>{Kt(`KickJS — Create a new project`);let n=!!(t.yes||t.nonInteractive);e||=n?`my-api`:await Jt({message:`Project name`,placeholder:`my-api`,defaultValue:`my-api`});let i;if(e===`.`?(i=v(`.`),e=d(i)):i=v(t.directory||e),r(i)){let r=o(i);if(r.length>0){if(t.force)I.warn(`Clearing existing files in ${i}`);else if(n){I.warn(`Directory "${e}" is not empty. Pass --force to clear it.`),P(`Aborted.`);return}else{I.warn(`Directory "${e}" is not empty:`);let t=r.slice(0,5);for(let e of t)I.message(` - ${e}`);if(r.length>5&&I.message(` ... and ${r.length-5} more`),!await F({message:O.red(`Remove all existing files and proceed?`),initialValue:!1})){P(`Aborted.`);return}}for(let e of r)s(v(i,e),{recursive:!0,force:!0})}}let a=t.template;a||=n?`minimal`:await Yt({message:`Project template`,options:[{value:`rest`,label:`REST API`,hint:`Express + Swagger`},{value:`minimal`,label:`Minimal`,hint:`bare Express`},{value:`fullstack`,label:`Fullstack`,hint:`server + Vite React web, typed client`}]});let c=t.runtime;c||=n?`express`:await Yt({message:`HTTP runtime`,options:[{value:`express`,label:`Express`,hint:`default, zero-config`},{value:`fastify`,label:`Fastify`,hint:`fastify + @fastify/middie`},{value:`h3`,label:`h3`,hint:`Nitro / Nuxt engine`}]});let l=t.pm;l||=n?await Ot(void 0):await Yt({message:`Package manager`,options:[{value:`pnpm`,label:`pnpm`},{value:`npm`,label:`npm`},{value:`yarn`,label:`yarn`},{value:`bun`,label:`bun`}]});let u=t.repo;u||=n?`inmemory`:await Jt({message:`Repository name`,placeholder:`inmemory (or a DB name, e.g. postgres)`,defaultValue:`inmemory`}),Oe(u);let f=t.schema;f||=n?`zod`:await Yt({message:`Schema library (env + DTO validation)`,options:[{value:`zod`,label:`Zod`,hint:`default — broad ecosystem`},{value:`valibot`,label:`Valibot`,hint:`smaller bundle`},{value:`yup`,label:`Yup`,hint:`classic API`}]}),[`zod`,`valibot`,`yup`].includes(f)||(I.warn(`Unknown --schema "${f}", falling back to zod.`),f=`zod`);let p;if(t.packages!==void 0){let e=t.packages.trim().toLowerCase();p=e===``||e===`none`||e===`false`?[]:t.packages.split(`,`).map(e=>e.trim()).filter(Boolean)}else p=n?[]:await Xt({message:`Select packages to include`,options:[...Qt],required:!1});let m;m=t.git===void 0?n?!0:await F({message:`Initialize git repository?`,initialValue:!0}):t.git;let h;if(h=t.install===void 0?n?!0:await F({message:`Install dependencies?`,initialValue:!0}):t.install,a===`fullstack`){let{initFullstackProject:t}=await import(`./fullstack-C8u97QC-.mjs`);await t({name:e,directory:i,packageManager:l,initGit:m,installDeps:h,schemaLib:f,runtime:c}),P(`Done! Next steps: ${O.cyan(`cd ${e} && ${l}${l===`pnpm`?` dev`:` run dev:server`}`)}`);return}await Ht({name:e,directory:i,packageManager:l,initGit:m,installDeps:h,template:a,defaultRepo:u,packages:p,schemaLib:f,runtime:c}),P(`Done! Next steps: ${O.cyan(`cd ${e} && ${l} dev`)}`)})}function L(e){return e.replace(/[-_\s]+(.)?/g,(e,t)=>t?t.toUpperCase():``).replace(/^(.)/,e=>e.toUpperCase())}function R(e){let t=L(e);return t.charAt(0).toLowerCase()+t.slice(1)}function z(e){return e.replace(/([a-z])([A-Z])/g,`$1-$2`).replace(/[\s_]+/g,`-`).toLowerCase()}function B(e){return de.plural(e)}function en(e){return de.plural(e)}var tn=k({findProjectRoot:()=>rn});const nn=[`kick.config.ts`,`kick.config.js`,`kick.config.mjs`,`kick.config.json`];function rn(e=process.cwd()){let t=v(e),{root:n}=g(t),i=null,a=t;for(;;){for(let e of nn)if(r(v(a,e)))return a;if(i===null&&r(v(a,`package.json`))&&(i=a),a===n)break;let e=f(a);if(e===a)break;a=e}return i??t}function an(e){return z(e).replace(/-/g,`_`)}function on(e){let t=e.cwd??process.cwd(),n=e.projectRoot??rn(t),r=e.pluralize??!0,i=L(e.name),a=R(e.name),o=z(e.name),s=an(e.name),c={name:e.name,pascal:i,camel:a,kebab:o,snake:s,modulesDir:e.modulesDir??`src/modules`,cwd:t,projectRoot:n,args:e.args??[],flags:e.flags??{}};if(r){let e=B(o);c.pluralKebab=e,c.pluralPascal=L(e),c.pluralCamel=R(e)}return c}function sn(e,t){return v(e.cwd,t)}async function cn(e){return import(x(e).href)}const ln=new Map;async function un(e){let t=ln.get(e);if(t)return t;let n=dn(e);return ln.set(e,n),n}async function dn(t){let n=v(t,`package.json`);if(!r(n))return{generators:[],loaded:[],failed:[]};let i=fn(JSON.parse(await w(n,`utf-8`))),a=e(v(t,`package.json`)),o=[],s=[],c=[];for(let e of i){let t;try{t=a.resolve(`${e}/package.json`)}catch{continue}let n;try{n=JSON.parse(await w(t,`utf-8`))}catch(t){c.push({source:e,reason:`failed to parse package.json: ${t}`});continue}if(!n.kickjs?.generators)continue;let i=n.kickjs.generators,l=v(f(t),i);if(!r(l)){c.push({source:e,reason:`kickjs.generators points to missing file: ${i}`});continue}let u;try{u=await cn(l)}catch(t){c.push({source:e,reason:`failed to import manifest: ${t}`});continue}let d=u.default;if(!Array.isArray(d)){c.push({source:e,reason:`manifest's default export is not an array of GeneratorSpec`});continue}for(let t of d){if(!pn(t)){c.push({source:e,reason:`manifest entry is not a valid GeneratorSpec (missing name/files)`});continue}o.push({source:e,spec:t})}s.push(e)}return{generators:o,loaded:s,failed:c}}function fn(e){let t=new Set;for(let n of[e.dependencies,e.devDependencies,e.peerDependencies])if(n)for(let e of Object.keys(n))t.add(e);return Array.from(t)}function pn(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.name==`string`&&typeof t.files==`function`}async function mn(e,t=[]){let n=e.cwd??process.cwd(),r=t.find(t=>t.spec.name===e.generatorName);if(r)return _n(r.spec,r.source,e,n);let i=gn(await un(n),e.generatorName);return i?_n(i.spec,i.source,e,n):null}async function hn(e,t=[]){let n=await un(e),r=new Set(t.map(e=>e.spec.name)),i=n.generators.filter(e=>!r.has(e.spec.name));return{generators:[...t,...i],loaded:n.loaded,failed:n.failed}}function gn(e,t){return e.generators.find(e=>e.spec.name===t)}async function _n(e,t,n,r){let i=on({name:n.itemName,args:n.args,flags:n.flags,modulesDir:n.modulesDir,pluralize:n.pluralize,cwd:r,projectRoot:n.projectRoot}),a=await e.files(i),o=[];for(let e of a){let t=sn(i,e.path);await N(t,e.content),o.push(t)}return{files:o,source:t}}function V(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function vn(e){return e.charAt(0).toUpperCase()+e.slice(1).replace(/-([a-z])/g,(e,t)=>t.toUpperCase())}function yn(e){return e.replace(/([a-z])([A-Z])/g,`$1-$2`).toLowerCase()}function bn(e,t,n){let r={inmemory:`InMemory${e}Repository`,drizzle:`Drizzle${e}Repository`,prisma:`Prisma${e}Repository`},i={inmemory:`in-memory-${t}`,drizzle:`drizzle-${t}`,prisma:`prisma-${t}`};return{repoClass:r[n]??`${vn(n)}${e}Repository`,repoFile:i[n]??`${yn(n)}-${t}`}}function xn(e){return e??`define`}function Sn(e){let{pascal:t,kebab:n,plural:r=``,repo:i,style:a}=e,{repoClass:o,repoFile:s}=bn(t,n,i),c=xn(a),l=`/**
1271
+ Project scaffolded successfully!`),console.log();let p=l!==process.cwd();u(`Next steps:`),p&&u(` cd ${t}`),e.installDeps||u(` ${r} install`);let m={rest:`kick g module user`,ddd:`kick g module user --repo drizzle`,cqrs:`kick g module user --pattern cqrs`,minimal:`# add your routes to src/index.ts`};u(` ${m[i]??m.rest}`),u(` kick dev`),u(``),u(`Commands:`),u(` kick dev Start dev server with Vite HMR`),u(` kick build Production build via Vite`),u(` kick start Run production build`),u(``),u(`Generators:`),u(` kick g module <name> Full DDD module (controller, DTOs, use-cases, repo)`),u(` kick g scaffold <n> <f..> CRUD module from field definitions`),u(` kick g controller <name> Standalone controller`),u(` kick g service <name> @Service() class`),u(` kick g middleware <name> Express middleware`),u(` kick g guard <name> Route guard (auth, roles, etc.)`),u(` kick g adapter <name> AppAdapter with lifecycle hooks`),u(` kick g dto <name> Zod DTO schema`),u(` kick g config Generate kick.config.ts`),u(``),u(`Add packages:`),u(` kick add <pkg> Install a KickJS package + peers`),u(` kick add --list Show all available packages`),u(``),u(`Available: ${bt}`),u(``)}const Ut={GET:O.green,POST:O.cyan,PUT:O.yellow,PATCH:O.magenta,DELETE:O.red};function Wt(e){return(Ut[e]??O.dim)(e.padEnd(7))}function Gt(e){let t=`[${e}]`.padEnd(10);switch(e){case`CRITICAL`:return O.red(t);case`WARNING`:return O.yellow(t);case`INFO`:return O.blue(O.dim(t));default:return t}}O.green(`✓`),O.red(`✖`),O.yellow(`⚠`),O.blue(`ℹ`);function Kt(e){D.intro(O.bgCyan(O.black(` ${e} `)))}function P(e){D.outro(e)}function qt(e){D.isCancel(e)&&(D.cancel(`Operation cancelled.`),process.exit(0))}async function Jt(e){let t=await D.text(e);return qt(t),t}async function Yt(e){let t=await D.select(e);return qt(t),t}async function Xt(e){let t=await D.multiselect(e);return qt(t),t}async function F(e){let t=await D.confirm(e);return qt(t),t}function Zt(){return D.spinner()}const I=D.log,Qt=[{value:`swagger`,label:`Swagger`,hint:`OpenAPI docs`},{value:`ws`,label:`WebSocket`,hint:`rooms, heartbeat`},{value:`queue`,label:`Queue`,hint:`BullMQ/RabbitMQ/Kafka`},{value:`devtools`,label:`DevTools`,hint:`debug dashboard`}];function $t(e){e.command(`new [name]`).alias(`init`).description(`Create a new KickJS project (use "." for current directory)`).option(`-d, --directory <dir>`,`Target directory (defaults to project name)`).option(`--pm <manager>`,`Package manager: pnpm | npm | yarn | bun`).option(`--git`,`Initialize git repository`).option(`--no-git`,`Skip git initialization`).option(`--install`,`Install dependencies after scaffolding`).option(`--no-install`,`Skip dependency installation`).option(`-f, --force`,`Remove existing files without prompting`).option(`-t, --template <type>`,`Project template: rest | minimal | fullstack`).option(`--runtime <engine>`,`HTTP runtime: express | fastify | h3`).option(`-r, --repo <type>`,`Repository name (inmemory, or any DB name e.g. postgres)`).option(`-s, --schema <lib>`,`Schema library for env / DTOs: zod | valibot | yup (default: zod)`).option(`--packages <packages>`,`Comma-separated packages to include (e.g. auth,swagger,ws,queue)`).option(`-y, --yes`,`Pick safe defaults for every prompt (template=minimal, repo=inmemory, no extras, git+install on)`).option(`--non-interactive`,`alias for --yes`).action(async(e,t)=>{Kt(`KickJS — Create a new project`);let n=!!(t.yes||t.nonInteractive);e||=n?`my-api`:await Jt({message:`Project name`,placeholder:`my-api`,defaultValue:`my-api`});let i;if(e===`.`?(i=v(`.`),e=d(i)):i=v(t.directory||e),r(i)){let r=o(i);if(r.length>0){if(t.force)I.warn(`Clearing existing files in ${i}`);else if(n){I.warn(`Directory "${e}" is not empty. Pass --force to clear it.`),P(`Aborted.`);return}else{I.warn(`Directory "${e}" is not empty:`);let t=r.slice(0,5);for(let e of t)I.message(` - ${e}`);if(r.length>5&&I.message(` ... and ${r.length-5} more`),!await F({message:O.red(`Remove all existing files and proceed?`),initialValue:!1})){P(`Aborted.`);return}}for(let e of r)s(v(i,e),{recursive:!0,force:!0})}}let a=t.template;a||=n?`minimal`:await Yt({message:`Project template`,options:[{value:`rest`,label:`REST API`,hint:`Express + Swagger`},{value:`minimal`,label:`Minimal`,hint:`bare Express`},{value:`fullstack`,label:`Fullstack`,hint:`server + Vite React web, typed client`}]});let c=t.runtime;c||=n?`express`:await Yt({message:`HTTP runtime`,options:[{value:`express`,label:`Express`,hint:`default, zero-config`},{value:`fastify`,label:`Fastify`,hint:`fastify + @fastify/middie`},{value:`h3`,label:`h3`,hint:`Nitro / Nuxt engine`}]});let l=t.pm;l||=n?await Ot(void 0):await Yt({message:`Package manager`,options:[{value:`pnpm`,label:`pnpm`},{value:`npm`,label:`npm`},{value:`yarn`,label:`yarn`},{value:`bun`,label:`bun`}]});let u=t.repo;u||=n?`inmemory`:await Jt({message:`Repository name`,placeholder:`inmemory (or a DB name, e.g. postgres)`,defaultValue:`inmemory`}),Oe(u);let f=t.schema;f||=n?`zod`:await Yt({message:`Schema library (env + DTO validation)`,options:[{value:`zod`,label:`Zod`,hint:`default — broad ecosystem`},{value:`valibot`,label:`Valibot`,hint:`smaller bundle`},{value:`yup`,label:`Yup`,hint:`classic API`}]}),[`zod`,`valibot`,`yup`].includes(f)||(I.warn(`Unknown --schema "${f}", falling back to zod.`),f=`zod`);let p;if(t.packages!==void 0){let e=t.packages.trim().toLowerCase();p=e===``||e===`none`||e===`false`?[]:t.packages.split(`,`).map(e=>e.trim()).filter(Boolean)}else p=n?[]:await Xt({message:`Select packages to include`,options:[...Qt],required:!1});let m;m=t.git===void 0?n?!0:await F({message:`Initialize git repository?`,initialValue:!0}):t.git;let h;if(h=t.install===void 0?n?!0:await F({message:`Install dependencies?`,initialValue:!0}):t.install,a===`fullstack`){let{initFullstackProject:t}=await import(`./fullstack-e-wuEMD0.mjs`);await t({name:e,directory:i,packageManager:l,initGit:m,installDeps:h,schemaLib:f,runtime:c}),P(`Done! Next steps: ${O.cyan(`cd ${e} && ${l}${l===`pnpm`?` dev`:` run dev:server`}`)}`);return}await Ht({name:e,directory:i,packageManager:l,initGit:m,installDeps:h,template:a,defaultRepo:u,packages:p,schemaLib:f,runtime:c}),P(`Done! Next steps: ${O.cyan(`cd ${e} && ${l} dev`)}`)})}function L(e){return e.replace(/[-_\s]+(.)?/g,(e,t)=>t?t.toUpperCase():``).replace(/^(.)/,e=>e.toUpperCase())}function R(e){let t=L(e);return t.charAt(0).toLowerCase()+t.slice(1)}function z(e){return e.replace(/([a-z])([A-Z])/g,`$1-$2`).replace(/[\s_]+/g,`-`).toLowerCase()}function B(e){return de.plural(e)}function en(e){return de.plural(e)}var tn=k({findProjectRoot:()=>rn});const nn=[`kick.config.ts`,`kick.config.js`,`kick.config.mjs`,`kick.config.json`];function rn(e=process.cwd()){let t=v(e),{root:n}=g(t),i=null,a=t;for(;;){for(let e of nn)if(r(v(a,e)))return a;if(i===null&&r(v(a,`package.json`))&&(i=a),a===n)break;let e=f(a);if(e===a)break;a=e}return i??t}function an(e){return z(e).replace(/-/g,`_`)}function on(e){let t=e.cwd??process.cwd(),n=e.projectRoot??rn(t),r=e.pluralize??!0,i=L(e.name),a=R(e.name),o=z(e.name),s=an(e.name),c={name:e.name,pascal:i,camel:a,kebab:o,snake:s,modulesDir:e.modulesDir??`src/modules`,cwd:t,projectRoot:n,args:e.args??[],flags:e.flags??{}};if(r){let e=B(o);c.pluralKebab=e,c.pluralPascal=L(e),c.pluralCamel=R(e)}return c}function sn(e,t){return v(e.cwd,t)}async function cn(e){return import(x(e).href)}const ln=new Map;async function un(e){let t=ln.get(e);if(t)return t;let n=dn(e);return ln.set(e,n),n}async function dn(t){let n=v(t,`package.json`);if(!r(n))return{generators:[],loaded:[],failed:[]};let i=fn(JSON.parse(await w(n,`utf-8`))),a=e(v(t,`package.json`)),o=[],s=[],c=[];for(let e of i){let t;try{t=a.resolve(`${e}/package.json`)}catch{continue}let n;try{n=JSON.parse(await w(t,`utf-8`))}catch(t){c.push({source:e,reason:`failed to parse package.json: ${t}`});continue}if(!n.kickjs?.generators)continue;let i=n.kickjs.generators,l=v(f(t),i);if(!r(l)){c.push({source:e,reason:`kickjs.generators points to missing file: ${i}`});continue}let u;try{u=await cn(l)}catch(t){c.push({source:e,reason:`failed to import manifest: ${t}`});continue}let d=u.default;if(!Array.isArray(d)){c.push({source:e,reason:`manifest's default export is not an array of GeneratorSpec`});continue}for(let t of d){if(!pn(t)){c.push({source:e,reason:`manifest entry is not a valid GeneratorSpec (missing name/files)`});continue}o.push({source:e,spec:t})}s.push(e)}return{generators:o,loaded:s,failed:c}}function fn(e){let t=new Set;for(let n of[e.dependencies,e.devDependencies,e.peerDependencies])if(n)for(let e of Object.keys(n))t.add(e);return Array.from(t)}function pn(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.name==`string`&&typeof t.files==`function`}async function mn(e,t=[]){let n=e.cwd??process.cwd(),r=t.find(t=>t.spec.name===e.generatorName);if(r)return _n(r.spec,r.source,e,n);let i=gn(await un(n),e.generatorName);return i?_n(i.spec,i.source,e,n):null}async function hn(e,t=[]){let n=await un(e),r=new Set(t.map(e=>e.spec.name)),i=n.generators.filter(e=>!r.has(e.spec.name));return{generators:[...t,...i],loaded:n.loaded,failed:n.failed}}function gn(e,t){return e.generators.find(e=>e.spec.name===t)}async function _n(e,t,n,r){let i=on({name:n.itemName,args:n.args,flags:n.flags,modulesDir:n.modulesDir,pluralize:n.pluralize,cwd:r,projectRoot:n.projectRoot}),a=await e.files(i),o=[];for(let e of a){let t=sn(i,e.path);await N(t,e.content),o.push(t)}return{files:o,source:t}}function V(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function vn(e){return e.charAt(0).toUpperCase()+e.slice(1).replace(/-([a-z])/g,(e,t)=>t.toUpperCase())}function yn(e){return e.replace(/([a-z])([A-Z])/g,`$1-$2`).toLowerCase()}function bn(e,t,n){let r={inmemory:`InMemory${e}Repository`,drizzle:`Drizzle${e}Repository`,prisma:`Prisma${e}Repository`},i={inmemory:`in-memory-${t}`,drizzle:`drizzle-${t}`,prisma:`prisma-${t}`};return{repoClass:r[n]??`${vn(n)}${e}Repository`,repoFile:i[n]??`${yn(n)}-${t}`}}function xn(e){return e??`define`}function Sn(e){let{pascal:t,kebab:n,plural:r=``,repo:i,style:a}=e,{repoClass:o,repoFile:s}=bn(t,n,i),c=xn(a),l=`/**
1272
1272
  * ${t} Module
1273
1273
  *
1274
1274
  * REST module with a flat folder structure.
@@ -2548,7 +2548,7 @@ export {}
2548
2548
  Example: kick g scaffold Post title:string body:text:optional published:boolean:optional
2549
2549
  Optional: append :optional (shell-safe, no quoting needed)
2550
2550
  `),process.exit(1));let a=await j(process.cwd()),o=A(a),s=n.modulesDir??o.dir??`src/modules`,c=Or(t),l=Ae(a,process.cwd()),u=await kr({name:e,fields:c,modulesDir:v(s),noEntity:n.entity===!1,noTests:n.tests===!1,pluralize:n.pluralize===!1?!1:o.pluralize??!0,tokenScope:l,style:o.style});console.log(`\n Scaffolded ${e} with ${c.length} field(s):`);for(let e of c)console.log(` ${e.name}: ${e.type}${e.optional?` (optional)`:``}`);X(u,i),await Ba(i)}),n.command(`config`).description(`Generate a kick.config.ts at the project root`).option(`--modules-dir <dir>`,`Modules directory path`,`src/modules`).option(`--repo <type>`,`Repository name: inmemory (default) or any DB name`,`inmemory`).option(`-f, --force`,`Overwrite existing kick.config.ts without prompting`).action(async(e,t)=>{let n=Y(t);M(n),X(await ir({outDir:v(`.`),modulesDir:e.modulesDir,defaultRepo:e.repo,force:e.force}),n)}),n.command(`agents`).alias(`agent-docs`).alias(`ai-docs`).description(`Regenerate AGENTS.md + CLAUDE.md + kickjs-skills.md (sync after framework upgrades)`).option(`--only <which>`,`Limit scope: agents | claude | skills | both (agents+claude) | all (default: all)`,`all`).option(`--name <name>`,`Project name (defaults to package.json name)`).option(`--pm <pm>`,`Package manager (defaults to package.json packageManager)`).option(`--template <template>`,`Template: rest | minimal`).option(`-f, --force`,`Overwrite existing files without prompting`).action(async(e,t)=>{let n=Y(t);M(n);let r=e.only??`all`;if(!za.includes(r)){console.error(` Invalid --only value: ${r}. Expected: ${za.join(` | `)}`),process.exitCode=1;return}X(await dr({outDir:v(`.`),only:r,name:e.name,pm:e.pm,template:e.template,force:e.force}),n)});for(let e of t?.generators??[])Ka(n,e,t?.projectRoot)}function Ka(e,t,n){let{source:r,spec:i}=t,a=i.args?.[0],o=a?.name??`itemName`,s=a?.required?`<${o}>`:`[${o}]`,c=`${i.name} ${s} [extraArgs...]`,l=e.command(c).description(`${i.description} [${r}]`);for(let e of i.flags??[]){let t=e.takesValue?`--${e.name} <value>`:`--${e.name}`,n=e.alias?`-${e.alias}, ${t}`:t;l.option(n,e.description??``)}l.action(async(e,r,a,o)=>{let s=Y(o);M(s);let c=await mn({generatorName:i.name,itemName:e??``,args:r??[],flags:a,cwd:process.cwd(),projectRoot:n},[t]);c&&X(c.files,s)})}async function qa(e){let t=u.resolve(e.cwd,`.kickjs/types`);await ae(t,{recursive:!0});let n=new Map,i=e.scan??Xi,a=u.resolve(e.cwd,`.kickjs`,`cache`),o=e.scan?void 0:e.changedFiles,s={cwd:e.cwd,config:e.config,async importTs(e){return await import(x(e).href)},async writeFile(t,n){let r=u.resolve(e.cwd,t);await ae(u.dirname(r),{recursive:!0}),await T(r,n,`utf8`)},getScanResult:e=>{let t=Ja(e),r=n.get(t);if(!r){let s={cacheDir:a,...e};r=o?Qi(s,o):i(s),n.set(t,r)}return r},log:console},c=[];for(let n of e.plugins){let i=n.outExtension??`.d.ts`,a=u.join(t,`${n.id.replace(/\//g,`__`)}${i}`),o;try{o=await n.generate(s)}catch(e){let t=e instanceof Error?e.message:String(e);s.log.error(` ${n.id}: typegen failed (${t}) — keeping previous output`),c.push({id:n.id,status:`error`,outFile:a});continue}if(o===null){c.push({id:n.id,status:`skipped`});continue}let l=`/* AUTO-GENERATED by kick typegen — do not edit. Plugin: ${n.id} */\n\n`+o+`
2551
- `,d=``;if(r(a)&&(d=await w(a,`utf8`)),d===l){c.push({id:n.id,status:`unchanged`,outFile:a});continue}if(e.check)throw Error(`kick typegen --check: drift detected for ${n.id} (${a})`);await T(a,l,`utf8`),c.push({id:n.id,status:`written`,outFile:a})}return c}function Ja(e){let t=(e.extensions??[]).slice().toSorted().join(`,`),n=(e.exclude??[]).slice().toSorted().join(`,`);return[`root=${e.root}`,`cwd=${e.cwd}`,`extensions=${t}`,`exclude=${n}`,`envFile=${e.envFile??``}`].join(`|`)}function Ya(e,t){let n=new Set(t),r=[],i=[],a=new Set;for(let t of e)n.has(t.id)?(i.push(t),a.add(t.id)):r.push(t);return{enabled:r,skipped:i,unknown:[...n].filter(e=>!a.has(e))}}var Xa=k({applyDisableFilter:()=>Ya,runAllPluginTypegens:()=>Qa});function Za(){let e=(process.env.LOG_LEVEL??process.env.KICKJS_LOG_LEVEL??``).toLowerCase();return e===`debug`||e===`trace`}async function Qa(e){let{enabled:t,skipped:n,unknown:r}=Ya(Ie([...Cc,...e.config?.plugins??[]],e.config?.commands??[]).typegens,e.config?.typegen?.disable??[]);if(!e.silent&&n.length>0)for(let e of n)console.log(` ${e.id}: disabled (typegen.disable)`);if(!e.silent&&r.length>0&&console.warn(` kick typegen: disable list references unknown id(s): ${r.map(e=>`'${e}'`).join(`, `)}. Run \`kick typegen --list\` to see registered ids.`),t.length===0)return[];try{let n=await qa({cwd:e.cwd,config:e.config??{},plugins:t,check:e.check,changedFiles:e.changedFiles});if(!e.silent&&Za())for(let e of n)console.log(` ${e.id}: ${e.status}`);return n}catch(t){if(!e.silent){let e=t instanceof Error?t.message:String(t);console.warn(` kick typegen plugins: skipped (${e})`)}return[]}}var $a=k({ASSET_MANIFEST_VERSION:()=>1,buildAssets:()=>eo});async function eo(e,t){let{cwd:n,silent:r=!1}=t,a=t.distDir??e?.build?.outDir??`dist`,o=e?.assetMap;if(!o||Object.keys(o).length===0)return null;let s=r?()=>{}:console.log,c=v(n,a);i(c,{recursive:!0});let u=[],d={};for(let[e,t]of Object.entries(o)){let r=await to(e,t,n,c);u.push(r.entrySummary),Object.assign(d,r.manifestSlice),s(` ✓ ${e}: ${r.entrySummary.filesCopied} file(s) → ${r.entrySummary.dest}`)}let f={version:1,entries:d},p=h(c,`.kickjs-assets.json`);return l(p,JSON.stringify(f,null,2)+`
2551
+ `,d=``;if(r(a)&&(d=await w(a,`utf8`)),d===l){c.push({id:n.id,status:`unchanged`,outFile:a});continue}if(e.check)throw Error(`kick typegen --check: drift detected for ${n.id} (${a})`);await T(a,l,`utf8`),c.push({id:n.id,status:`written`,outFile:a})}return c}function Ja(e){let t=(e.extensions??[]).slice().toSorted().join(`,`),n=(e.exclude??[]).slice().toSorted().join(`,`);return[`root=${e.root}`,`cwd=${e.cwd}`,`extensions=${t}`,`exclude=${n}`,`envFile=${e.envFile??``}`].join(`|`)}function Ya(e,t){let n=new Set(t),r=[],i=[],a=new Set;for(let t of e)n.has(t.id)?(i.push(t),a.add(t.id)):r.push(t);return{enabled:r,skipped:i,unknown:[...n].filter(e=>!a.has(e))}}var Xa=k({applyDisableFilter:()=>Ya,runAllPluginTypegens:()=>Qa});function Za(){let e=(process.env.LOG_LEVEL??process.env.KICKJS_LOG_LEVEL??``).toLowerCase();return e===`debug`||e===`trace`}async function Qa(e){let{enabled:t,skipped:n,unknown:r}=Ya(Ie([...wc,...e.config?.plugins??[]],e.config?.commands??[]).typegens,e.config?.typegen?.disable??[]);if(!e.silent&&n.length>0)for(let e of n)console.log(` ${e.id}: disabled (typegen.disable)`);if(!e.silent&&r.length>0&&console.warn(` kick typegen: disable list references unknown id(s): ${r.map(e=>`'${e}'`).join(`, `)}. Run \`kick typegen --list\` to see registered ids.`),t.length===0)return[];try{let n=await qa({cwd:e.cwd,config:e.config??{},plugins:t,check:e.check,changedFiles:e.changedFiles});if(!e.silent&&Za())for(let e of n)console.log(` ${e.id}: ${e.status}`);return n}catch(t){if(!e.silent){let e=t instanceof Error?t.message:String(t);console.warn(` kick typegen plugins: skipped (${e})`)}return[]}}var $a=k({ASSET_MANIFEST_VERSION:()=>1,buildAssets:()=>eo});async function eo(e,t){let{cwd:n,silent:r=!1}=t,a=t.distDir??e?.build?.outDir??`dist`,o=e?.assetMap;if(!o||Object.keys(o).length===0)return null;let s=r?()=>{}:console.log,c=v(n,a);i(c,{recursive:!0});let u=[],d={};for(let[e,t]of Object.entries(o)){let r=await to(e,t,n,c);u.push(r.entrySummary),Object.assign(d,r.manifestSlice),s(` ✓ ${e}: ${r.entrySummary.filesCopied} file(s) → ${r.entrySummary.dest}`)}let f={version:1,entries:d},p=h(c,`.kickjs-assets.json`);return l(p,JSON.stringify(f,null,2)+`
2552
2552
  `,`utf-8`),s(` ✓ wrote manifest → ${_(n,p)} (${Object.keys(d).length} entries)`),{manifestPath:p,entries:u,manifest:f}}async function to(e,t,a,o){let s=v(a,t.src),c=t.dest?v(a,t.dest):h(o,e);if(io(c,a))return console.warn(` ⚠ assetMap.${e}.dest ('${t.dest}') resolves outside the project root — skipping copy`),{entrySummary:{namespace:e,src:t.src,dest:_(a,c),filesCopied:0},manifestSlice:{}};if(!r(s)||!ao(s))return{entrySummary:{namespace:e,src:t.src,dest:_(a,c),filesCopied:0},manifestSlice:{}};let l=await pe(t.glob??`**/*`,{cwd:s,nodir:!0,dot:!1,posix:!0});i(c,{recursive:!0});let u={},{pairs:d,collisionGroupsResolved:p}=he(e,[...l].toSorted(),{strategy:t.keys??`auto`}),m=0;for(let{rel:e,key:t}of d){let r=h(s,e),a=h(c,e);u[t]=ro(o,a),!no(r,a)&&(i(f(a),{recursive:!0}),n(r,a),m++)}return p>0&&console.log(` ℹ assetMap.${e}: auto-resolved ${p} basename collision(s) by keeping extensions (set 'keys: "strip"' to opt back into legacy last-write-wins behaviour, or 'keys: "with-extension"' to keep all keys verbose).`),{entrySummary:{namespace:e,src:t.src,dest:_(a,c),filesCopied:m},manifestSlice:u}}function no(e,t){if(!r(t))return!1;try{let n=c(e),r=c(t);return r.size===n.size&&r.mtimeMs>=n.mtimeMs}catch{return!1}}function ro(e,t){return _(e,t).split(/[\\/]/).filter(Boolean).join(`/`)}function io(e,t){let n=_(t,e);return n===``?!1:n.startsWith(`..`)||m(n)}function ao(e){try{return c(e).isDirectory()}catch{return!1}}function oo(e){let t=new Map;return{report(n,r){let i=r instanceof Error?r.message:String(r);t.get(n)!==i&&(t.set(n,i),e(` kick typegen: ${n} pass failed (${i}) — types in .kickjs/types may be stale`))},clear(e){t.delete(e)}}}function so(e){let{cwd:t,config:n}=e,r=e.debounceMs??100,i=e.pipeline??{runTypegen:async e=>(await Promise.resolve().then(()=>Aa)).runTypegen(e),runAllPluginTypegens:async e=>(await Promise.resolve().then(()=>Xa)).runAllPluginTypegens(e),writeTypegenArtifacts:async(e,t,n)=>(await Promise.resolve().then(()=>Aa)).writeTypegenArtifacts(e,t,n),buildAssets:async(e,t)=>(await Promise.resolve().then(()=>$a)).buildAssets(e,t)},a=n?.typegen?.schemaValidator??`zod`,o=n?.typegen?.envFile,s=u.resolve(t,n?.typegen?.outDir??`.kickjs/types`),c=n?.assetMap?Object.values(n.assetMap).map(e=>e?.src).filter(e=>typeof e==`string`&&e.length>0).map(e=>u.resolve(t,e)):[],l=!!n?.assetMap&&Object.keys(n.assetMap).length>0,d=e=>e.replaceAll(`\\`,`/`),f=c.map(d),p=e=>{let t=d(e);return f.some(e=>t===e||t.startsWith(`${e}/`))},m=oo(e.emitWarning),h=null,g=!1,_=new Set,v=new Set,y=!1,b=!1;function x(r,c){i.runTypegen({cwd:t,silent:!0,allowDuplicates:!0,schemaValidator:a,envFile:o,srcDir:n?.typegen?.srcDir,outDir:n?.typegen?.outDir,assetMap:n?.assetMap,changedFiles:r,runPlugins:!1}).then(()=>m.clear(`scan`)).catch(e=>m.report(`scan`,e)),i.runAllPluginTypegens({cwd:t,config:n,silent:!0,changedFiles:r}).then(e=>i.writeTypegenArtifacts(s,e,!0)).then(()=>m.clear(`plugins`)).catch(e=>m.report(`plugins`,e)).finally(()=>e.onPassComplete?.()),c&&n&&i.buildAssets(n,{cwd:t,silent:!0}).catch(()=>{})}function S(){let e=y?void 0:{changed:[..._],removed:[...v]},t=b;_.clear(),v.clear(),y=!1,b=!1,x(e,t)}return{assetSrcRoots:c,handleWatchEvent(e,t){if(!g&&!d(t).includes(`/.kickjs/`)){if(e===`unlinkDir`)y=!0,l&&(b=!0);else{if(t.endsWith(`.d.ts`))return;let n=/\.(ts|tsx|mts|cts)$/.test(t),r=p(t);if(!n&&!r)return;r&&l&&(b=!0),n&&(e===`unlink`?(v.add(t),_.delete(t)):(_.add(t),v.delete(t)))}h&&clearTimeout(h),h=setTimeout(S,r)}},runOnce(){g||x(void 0,l)},dispose(){g=!0,h&&clearTimeout(h),h=null}}}function co(e){let t=h(e,`node_modules`,`.bin`),n=process.platform===`win32`;for(let e of[`tsgo`,`tsc`]){let i=n?[`${e}.CMD`,`${e}.cmd`,`${e}.exe`]:[e];for(let a of i){let i=h(t,a);if(r(i))return{cmd:i,args:[`--noEmit`],shell:n,kind:e}}}return null}function lo(e){let t=e.spawnFn??te,n=null,r=0,i=!1;return{schedule(){if(i)return;let a=++r;n&&=(n.kill(),null);let o=Date.now(),s=t(e.bin.cmd,e.bin.args,{cwd:e.cwd,shell:e.bin.shell,stdio:[`ignore`,`pipe`,`pipe`]});n=s;let c=``;s.stdout?.on(`data`,e=>{c+=e.toString()}),s.stderr?.on(`data`,e=>{c+=e.toString()}),s.on(`error`,()=>{a===r&&(n=null)}),s.on(`close`,t=>{i||a!==r||(n=null,e.onResult({ok:t===0,output:c,durationMs:Date.now()-o,kind:e.bin.kind}))})},dispose(){i=!0,n&&=(n.kill(),null)}}}function uo(e,t=12){let n=e.trim().split(/\r?\n/);return n.length<=t?n.join(`
2553
2553
  `):`${n.slice(0,t).join(`
2554
2554
  `)}\n… ${n.length-t} more line(s)`}function fo(e){if(typeof e==`boolean`)return e;let t=process.env.KICKJS_WATCH_POLLING;return t===`1`||t===`true`}async function po(e,t,n={}){t&&(process.env.PORT=t);let r=fo(n.polling),i=process.cwd(),a=await j(i),o=a?.typegen?.schemaValidator??`zod`,s=a?.typegen?.envFile;try{await Ma({cwd:i,allowDuplicates:!0,schemaValidator:o,envFile:s,srcDir:a?.typegen?.srcDir,outDir:a?.typegen?.outDir,assetMap:a?.assetMap,runPlugins:!1})}catch(e){console.warn(` kick typegen: skipped (${e?.message??e})`)}let c=v(i,a?.typegen?.outDir??`.kickjs/types`);try{await Fa(c,await Qa({cwd:i,config:a}),!1)}catch(e){console.warn(` kick typegen: plugin pass skipped (${e?.message??e})`)}let{createRequire:l}=await import(`node:module`),{createServer:u}=await import(x(l(v(`package.json`)).resolve(`vite`)).href);globalThis.__kickjs_typegen_owner=`kick-dev`;let d=await u({configFile:v(`vite.config.ts`),server:{port:t?parseInt(t,10):void 0,...r?{watch:{usePolling:!0,interval:100}}:{}}}),f=n.typecheck??a?.dev?.typecheck??!1,p=null,m=!0;if(f){let e=co(i);e?p=lo({cwd:i,bin:e,onResult:e=>{d.hot.send({type:`custom`,event:`kickjs:typecheck`,data:{ok:e.ok,output:e.output,durationMs:e.durationMs}}),e.ok?m||(m=!0,console.log(` kick typecheck: clean again (${e.kind}, ${e.durationMs}ms)`)):(m=!1,console.warn(`\n kick typecheck (${e.kind}, ${e.durationMs}ms):`),console.warn(uo(e.output).replace(/^/gm,` `)))}}):console.warn(` kick dev: --typecheck requested but neither tsgo (@typescript/native-preview) nor typescript is installed in this project — skipping type checks.`)}let h=so({cwd:i,config:a,emitWarning:e=>{console.warn(e),d.hot.send({type:`custom`,event:`kickjs:typegen-error`,data:{message:e,timestamp:Date.now()}})},onPassComplete:()=>p?.schedule()});d.watcher.on(`add`,e=>h.handleWatchEvent(`add`,e)),d.watcher.on(`unlink`,e=>h.handleWatchEvent(`unlink`,e)),d.watcher.on(`change`,e=>h.handleWatchEvent(`change`,e)),d.watcher.on(`unlinkDir`,e=>h.handleWatchEvent(`unlinkDir`,e)),h.assetSrcRoots.length>0&&d.watcher.add([...h.assetSrcRoots]),await d.listen(),d.printUrls(),console.log(`
@@ -2741,7 +2741,7 @@ server.on('exit', () => {
2741
2741
  Cancelled.
2742
2742
  `);return}await se(c,{recursive:!0,force:!0}),console.log(` Deleted: ${c}`);let l=h(n,`index.ts`);if(await Ge(l)){let e=await w(l,`utf-8`),t=e,n=RegExp(`^import\\s*\\{\\s*${V(o)}Module\\s*\\}\\s*from\\s*['"][^'"]*${V(s)}(?:/[^'"]*)?['"].*\\n?`,`gm`);e=e.replace(n,``),e=is(e,o),e=e.replace(/\n{3,}/g,`
2743
2743
 
2744
- `),e!==t&&(await T(l,e,`utf-8`),console.log(` Unregistered: ${o}Module from ${l}`))}console.log(`\n Module '${s}' removed.\n`)}function os(e){e.command(`remove`).alias(`rm`).description(`Remove generated code`).command(`module <names...>`).description(`Remove one or more modules (e.g. kick rm module user task)`).option(`--modules-dir <dir>`,`Modules directory`).option(`--no-pluralize`,`Use singular module name`).option(`-f, --force`,`Skip confirmation prompt`).action(async(e,t)=>{let n=A(await j(process.cwd())),r=t.modulesDir??n.dir??`src/modules`,i=t.pluralize===!1?!1:n.pluralize??!0;for(let n of e)await as({name:n,modulesDir:v(r),force:t.force,pluralize:i})})}function ss(e){if(e!==void 0){if(e===`false`||e===`off`||e===`none`)return!1;if(e===`zod`)return`zod`;if(e===`kickjs-schema`||e===`schema`)return`kickjs-schema`;console.warn(` kick typegen: unknown --schema-validator '${e}' (supported: 'zod', 'kickjs-schema', 'false'). Falling back to project config.`)}}function cs(e){if(e!==void 0)return e===`false`||e===`off`||e===`none`?!1:e}function ls(e){e.command(`typegen`).description(`Generate type-safe DI registry and module types into .kickjs/types/`).option(`-w, --watch`,`Watch source files and regenerate on change`).option(`-s, --src <dir>`,`Source directory to scan`,`src`).option(`-o, --out <dir>`,`Output directory`,`.kickjs/types`).option(`--silent`,`Suppress output`).option(`--allow-duplicates`,`Auto-namespace duplicate class names instead of failing (use with caution)`).option(`--schema-validator <name>`,`Schema validator for body/query/params typing (currently 'zod' or 'false')`).option(`--env-file <path>`,`Path to env schema file for KickEnv typing (default 'src/env.ts'; pass 'false' to disable)`).option(`--check`,`CI gate: fail on plugin-typegen drift instead of writing`).option(`--fix`,`Patch module import.meta.glob() calls to cover decorated classes that aren't loaded by any glob (orphans)`).option(`--list`,"List every registered typegen plugin id (use to populate `typegen.disable`)").option(`--no-cache`,`Disable the persistent scan cache; re-read + re-extract every file from cold`).action(async e=>{let t=rn(process.cwd()),n=await j(t);if(e.list){let{mergeCliPlugins:e}=await Promise.resolve().then(()=>Le),{builtinCliPlugins:t}=await Promise.resolve().then(()=>Sc),r=e([...t,...n?.plugins??[]],n?.commands??[]),i=new Set(n?.typegen?.disable??[]);if(r.typegens.length===0){console.log(` No typegen plugins registered.`);return}let a=Math.max(...r.typegens.map(e=>e.id.length));console.log(`
2744
+ `),e!==t&&(await T(l,e,`utf-8`),console.log(` Unregistered: ${o}Module from ${l}`))}console.log(`\n Module '${s}' removed.\n`)}function os(e){e.command(`remove`).alias(`rm`).description(`Remove generated code`).command(`module <names...>`).description(`Remove one or more modules (e.g. kick rm module user task)`).option(`--modules-dir <dir>`,`Modules directory`).option(`--no-pluralize`,`Use singular module name`).option(`-f, --force`,`Skip confirmation prompt`).action(async(e,t)=>{let n=A(await j(process.cwd())),r=t.modulesDir??n.dir??`src/modules`,i=t.pluralize===!1?!1:n.pluralize??!0;for(let n of e)await as({name:n,modulesDir:v(r),force:t.force,pluralize:i})})}function ss(e){if(e!==void 0){if(e===`false`||e===`off`||e===`none`)return!1;if(e===`zod`)return`zod`;if(e===`kickjs-schema`||e===`schema`)return`kickjs-schema`;console.warn(` kick typegen: unknown --schema-validator '${e}' (supported: 'zod', 'kickjs-schema', 'false'). Falling back to project config.`)}}function cs(e){if(e!==void 0)return e===`false`||e===`off`||e===`none`?!1:e}function ls(e){e.command(`typegen`).description(`Generate type-safe DI registry and module types into .kickjs/types/`).option(`-w, --watch`,`Watch source files and regenerate on change`).option(`-s, --src <dir>`,`Source directory to scan`,`src`).option(`-o, --out <dir>`,`Output directory`,`.kickjs/types`).option(`--silent`,`Suppress output`).option(`--allow-duplicates`,`Auto-namespace duplicate class names instead of failing (use with caution)`).option(`--schema-validator <name>`,`Schema validator for body/query/params typing (currently 'zod' or 'false')`).option(`--env-file <path>`,`Path to env schema file for KickEnv typing (default 'src/env.ts'; pass 'false' to disable)`).option(`--check`,`CI gate: fail on plugin-typegen drift instead of writing`).option(`--fix`,`Patch module import.meta.glob() calls to cover decorated classes that aren't loaded by any glob (orphans)`).option(`--list`,"List every registered typegen plugin id (use to populate `typegen.disable`)").option(`--no-cache`,`Disable the persistent scan cache; re-read + re-extract every file from cold`).action(async e=>{let t=rn(process.cwd()),n=await j(t);if(e.list){let{mergeCliPlugins:e}=await Promise.resolve().then(()=>Le),{builtinCliPlugins:t}=await Promise.resolve().then(()=>Cc),r=e([...t,...n?.plugins??[]],n?.commands??[]),i=new Set(n?.typegen?.disable??[]);if(r.typegens.length===0){console.log(` No typegen plugins registered.`);return}let a=Math.max(...r.typegens.map(e=>e.id.length));console.log(`
2745
2745
  Registered typegen plugins:
2746
2746
  `);for(let e of r.typegens){let t=i.has(e.id)?` (disabled)`:``;console.log(` ${e.id.padEnd(a+2)}inputs: ${e.inputs.join(`, `)||`(none)`}${t}`)}console.log();return}let r=ss(e.schemaValidator)??n?.typegen?.schemaValidator??`zod`,i=cs(e.envFile)??n?.typegen?.envFile,a={cwd:t,srcDir:e.src??n?.typegen?.srcDir,outDir:e.out??n?.typegen?.outDir,silent:e.silent,fix:e.fix,allowDuplicates:e.allowDuplicates,noCache:e.cache===!1,schemaValidator:r,envFile:i,assetMap:n?.assetMap,runPlugins:!1};try{if(e.watch){let t=await Ia(a);e.silent||console.log(` kick typegen: watching for changes (Ctrl-C to exit)`);let n=()=>{t(),process.exit(0)};process.on(`SIGINT`,n),process.on(`SIGTERM`,n),await new Promise(()=>{})}else{await Ma(a);let r=await Qa({cwd:t,config:n??null,silent:e.silent,check:e.check});e.check&&r.some(e=>e.status===`written`)&&process.exit(1),e.check||await Fa(v(t,e.out??n?.typegen?.outDir??`.kickjs/types`),r,e.silent??!1)}}catch(e){e instanceof la?console.error(`
2747
2747
  `+e.message+`
@@ -2782,27 +2782,30 @@ declare global {
2782
2782
  type KickApi = KickRoutes.Api
2783
2783
  }
2784
2784
 
2785
- export {}
2785
+ /** Empty until the first route exists — see kick typegen. */
2786
+ export const kickRpc = {} as const
2786
2787
  `;let i=new Map;for(let t of e){let e=i.get(t.controller)??[];e.push(t),i.set(t.controller,e)}let a=new Map,o=new Map,s=e=>{let t=`${e.filePath}::${e.controller}`,n=o.get(t);return n||(n=`_C${o.size}`,o.set(t,n)),n},c=(e,i,o)=>{let s=tc(e,i.filePath,t,n,a);if(!s){if(e&&n!==!1){let t=o===`params`?`URL-pattern params`:o===`query`&&i.queryFilterable!==null?`the @ApiQueryParams-derived query shape`:`'unknown'`;r.onWarn?.(`route ${i.controller}.${i.method} (${i.httpMethod} ${i.path}): ${o} schema '${e.identifier}' could not be statically resolved — falling back to ${t}. Export the schema from the controller file or import it with a static specifier.`)}return null}return n===`kickjs-schema`?`import('@forinda/kickjs-schema').InferSchemaOutput<typeof ${s}>`:`import('zod').infer<typeof ${s}>`},l=[];for(let[e,t]of i){let n=[` interface ${e} {`];for(let e of t){let t=e.pathParams.length>0?`{ ${e.pathParams.map(e=>`${e}: string`).join(`; `)} }`:`{}`,r=c(e.bodySchema,e,`body`),i=c(e.querySchema,e,`query`),a=c(e.paramsSchema,e,`params`)??t,o=r??`unknown`,l=i??$s(e),u=c(e.responseSchema??null,e,`response`),d=s(e),f=u??`import('@forinda/kickjs').InferHandlerResponse<${d}['${e.method}']>`,p=ec(e);n.push(` /**`,` * ${e.httpMethod} ${e.path}`,...p.map(e=>` * ${e}`),` */`,` ${e.method}: {`,` params: ${a}`,` body: ${o}`,` query: ${l}`,` response: ${f}`,` }`)}n.push(` }`),l.push(n.join(`
2787
- `))}let u=[],d=new Set;i.has(`Api`)&&r.onWarn?.(`controller class 'Api' collides with the reserved KickRoutes.Api client map — its interface declaration-merges into the flat route map. Rename the controller.`);for(let[e,t]of i)for(let n of t){let t=`${n.httpMethod} ${n.mountedPath??n.path}`;if(d.has(t)){r.onWarn?.(`duplicate route '${t}' (${e}.${n.method}) — two handlers claim the same verb+path at runtime. KickRoutes.Api keeps the first (scan order, which may not match runtime dispatch); resolve the conflict in the modules.`);continue}d.add(t),u.push(` '${t}': ${e}['${n.method}']`)}let f=[` interface Api {`,...u,` }`].join(`
2788
- `);l.push(f);let p=[],m=new Map;for(let t of e)m.set(`${t.filePath}::${t.controller}`,t);for(let[e,n]of o){let r=m.get(e),i=rc(``,r.filePath,t),a=r.controllerIsDefaultExport?`default as ${n}`:`${r.controller} as ${n}`;p.push(`import type { ${a} } from '${i}'`)}let h=p.length>0?p.join(`
2788
+ `))}let u=[],d=new Set,f=new Set;i.has(`Api`)&&r.onWarn?.(`controller class 'Api' collides with the reserved KickRoutes.Api client map — its interface declaration-merges into the flat route map. Rename the controller.`);for(let[e,t]of i)for(let n of t){let t=`${n.httpMethod} ${n.mountedPath??n.path}`;if(d.has(t)){r.onWarn?.(`duplicate route '${t}' (${e}.${n.method}) — two handlers claim the same verb+path at runtime. KickRoutes.Api keeps the first (scan order, which may not match runtime dispatch); resolve the conflict in the modules.`);continue}d.add(t),f.add(`${e}.${n.method}`),u.push(` '${t}': ${e}['${n.method}']`)}let p=[` interface Api {`,...u,` }`].join(`
2789
+ `);l.push(p);let m=[],h=new Set;for(let[e,t]of i){let n=ic(e);if(h.has(n)){r.onWarn?.(`RPC manifest: controller key '${n}' (from ${e}) collides with another controller — keeping the first; rename one class for distinct RPC namespaces.`);continue}h.add(n);let i=[];for(let n of t){if(!f.has(`${e}.${n.method}`))continue;let t=`${n.httpMethod} ${n.mountedPath??n.path}`;i.push(` ${n.method}: '${t}',`)}i.length>0&&m.push(` ${n}: {\n${i.join(`
2790
+ `)}\n },`)}let g=[`/**`,` * Runtime route manifest for the tRPC-style sugar:`," * `createRpc(api, kickRpc)` from @forinda/kickjs-client.",` */`,`export const kickRpc = {`,...m,`} as const`].join(`
2791
+ `),_=[],v=new Map;for(let t of e)v.set(`${t.filePath}::${t.controller}`,t);for(let[e,n]of o){let r=v.get(e),i=rc(``,r.filePath,t),a=r.controllerIsDefaultExport?`default as ${n}`:`${r.controller} as ${n}`;_.push(`import type { ${a} } from '${i}'`)}let y=_.length>0?_.join(`
2789
2792
  `)+`
2790
- `:``,g=nc(a)+h,_=l.join(`
2791
- `);return`${Zs}${g}
2793
+ `:``,b=nc(a)+y,x=l.join(`
2794
+ `);return`${Zs}${b}
2792
2795
  declare global {
2793
2796
  // eslint-disable-next-line @typescript-eslint/no-namespace
2794
2797
  namespace KickRoutes {
2795
- ${_}
2798
+ ${x}
2796
2799
  }
2797
2800
 
2798
2801
  /** Short alias for \`KickRoutes.Api\` — \`createClient<KickApi>(...)\`. */
2799
2802
  type KickApi = KickRoutes.Api
2800
2803
  }
2801
2804
 
2802
- export {}
2805
+ ${g}
2803
2806
  `}function $s(e){if(e.queryFilterable===null)return`unknown`;let t=e.querySortable??[];return`{ filter?: string | string[]; sort?: ${t.length>0?t.flatMap(e=>[`'${e}'`,`'-${e}'`]).join(` | `):`string`}; q?: string; page?: string; limit?: string }`}function ec(e){let t=[];return e.queryFilterable&&e.queryFilterable.length>0&&t.push(`Filterable: ${e.queryFilterable.join(`, `)}`),e.querySortable&&e.querySortable.length>0&&t.push(`Sortable: ${e.querySortable.join(`, `)}`),e.querySearchable&&e.querySearchable.length>0&&t.push(`Searchable: ${e.querySearchable.join(`, `)}`),t}function tc(e,t,n,r,i){if(!e||r===!1||e.source===null)return null;let a=rc(e.source,t,n);if(a===`unknown`)return null;let o=`${a}::${e.identifier}`,s=i.get(o)?.specifier;return s?s=i.get(o).specifier:(s=`_S${i.size}`,i.set(o,{identifier:e.identifier,specifier:s})),s}function nc(e){if(e.size===0)return``;let t=[];for(let[n,r]of e){let[e]=n.split(`::`);t.push(`import type { ${r.identifier} as ${r.specifier} } from '${e}'`)}return t.join(`
2804
2807
  `)+`
2805
- `}function rc(e,t,n){if(e===null)return`unknown`;let r=f(n);if(e===``){let e=_(r,t).split(y).join(`/`);return e=e.replace(/\.(ts|tsx|mts|cts)$/i,``),e.startsWith(`.`)||(e=`./`+e),e}if(!e.startsWith(`.`)&&!e.startsWith(`/`))return e;let i=_(r,v(f(t),e)).split(y).join(`/`);return i=i.replace(/\.(ts|tsx|mts|cts)$/i,``),i.startsWith(`.`)||(i=`./`+i),i}const ic=()=>({id:`kick/routes`,outExtension:`.ts`,inputs:[`src/**/*.controller.ts`,`src/**/*.module.ts`],async generate(e){let t=await e.getScanResult({root:ac(e),cwd:e.cwd,envFile:oc(e)}),n=e.config?.typegen?.schemaValidator??`zod`,r=u.resolve(e.cwd,`.kickjs/types/kick__routes.ts`);return Qs(t.routes,r,n,{onWarn:t=>e.log.warn(t)})}});function ac(e){return u.resolve(e.cwd,e.config?.typegen?.srcDir??`src`)}function oc(e){let t=e.config?.typegen?.envFile;if(t!==!1)return t}function sc(e,t,n=`zod`){if(!e)return null;let r=_(f(t),e.filePath).split(y).join(`/`);return r=r.replace(/\.(ts|tsx|mts|cts)$/i,``),r.startsWith(`.`)||(r=`./`+r),`/* eslint-disable */
2808
+ `}function rc(e,t,n){if(e===null)return`unknown`;let r=f(n);if(e===``){let e=_(r,t).split(y).join(`/`);return e=e.replace(/\.(ts|tsx|mts|cts)$/i,``),e.startsWith(`.`)||(e=`./`+e),e}if(!e.startsWith(`.`)&&!e.startsWith(`/`))return e;let i=_(r,v(f(t),e)).split(y).join(`/`);return i=i.replace(/\.(ts|tsx|mts|cts)$/i,``),i.startsWith(`.`)||(i=`./`+i),i}function ic(e){let t=e.endsWith(`Controller`)?e.slice(0,-10):e,n=t.length>0?t:e;return n.charAt(0).toLowerCase()+n.slice(1)}const ac=()=>({id:`kick/routes`,outExtension:`.ts`,inputs:[`src/**/*.controller.ts`,`src/**/*.module.ts`],async generate(e){let t=await e.getScanResult({root:oc(e),cwd:e.cwd,envFile:sc(e)}),n=e.config?.typegen?.schemaValidator??`zod`,r=u.resolve(e.cwd,`.kickjs/types/kick__routes.ts`);return Qs(t.routes,r,n,{onWarn:t=>e.log.warn(t)})}});function oc(e){return u.resolve(e.cwd,e.config?.typegen?.srcDir??`src`)}function sc(e){let t=e.config?.typegen?.envFile;if(t!==!1)return t}function cc(e,t,n=`zod`){if(!e)return null;let r=_(f(t),e.filePath).split(y).join(`/`);return r=r.replace(/\.(ts|tsx|mts|cts)$/i,``),r.startsWith(`.`)||(r=`./`+r),`/* eslint-disable */
2806
2809
  // AUTO-GENERATED by \`kick typegen\`. DO NOT EDIT.
2807
2810
  // Re-run with \`kick typegen\` or rely on \`kick dev\` to refresh.
2808
2811
 
@@ -2840,5 +2843,5 @@ declare global {
2840
2843
  }
2841
2844
 
2842
2845
  export {}
2843
- `}const cc=()=>({id:`kick/env`,outExtension:`.ts`,inputs:[`src/env.ts`,`src/**/env.ts`,`src/**/*.env.ts`],async generate(e){let t=uc(e);if(t===!1)return null;let n=await e.getScanResult({root:lc(e),cwd:e.cwd,envFile:t});if(!n.env)return null;let r=e.config?.typegen?.schemaValidator??`zod`,i=u.resolve(e.cwd,`.kickjs/types/kick__env.ts`);return sc(n.env,i,r)}});function lc(e){return u.resolve(e.cwd,e.config?.typegen?.srcDir??`src`)}function uc(e){return e.config?.typegen?.envFile}function dc(e){return u.resolve(e.cwd,e.config?.typegen?.srcDir??`src`)}function fc(e){let t=e.config?.typegen?.envFile;if(t!==!1)return t}function pc(e){return{root:dc(e),cwd:e.cwd,envFile:fc(e)}}const mc=()=>({id:`kick/registry`,inputs:[`src/**/*.ts`],async generate(e){let t=await e.getScanResult(pc(e)),n=u.resolve(e.cwd,`.kickjs/types/kick__registry.d.ts`),r=new Set(t.collisions.map(e=>e.className));return pa(t.classes,n,r)}}),hc=()=>({id:`kick/services`,inputs:[`src/**/*.ts`],async generate(e){let t=await e.getScanResult(pc(e)),n=new Set(t.collisions.map(e=>e.className));return ga(`ServiceToken`,_a(t.classes,t.tokens,t.injects,n),"(no tokens discovered — declare with createToken<T>() or `kick g service <name>`)")}}),gc=()=>({id:`kick/modules`,inputs:[`src/**/*.ts`],async generate(e){return ga(`ModuleToken`,va((await e.getScanResult(pc(e))).classes),"(no @Module classes discovered — `kick g module <name>` to add one)")}}),_c=()=>({id:`kick/plugins`,inputs:[`src/**/*.ts`],async generate(e){return ya((await e.getScanResult(pc(e))).pluginsAndAdapters)}}),vc=()=>({id:`kick/augmentations`,inputs:[`src/**/*.ts`],async generate(e){return ba((await e.getScanResult(pc(e))).augmentations)}}),yc=()=>({id:`kick/context`,inputs:[`src/**/*.ts`],async generate(e){let t=await e.getScanResult(pc(e));return t.contextKeys.length===0?null:ha(t.contextKeys)}}),bc={fastify:{subpath:`@forinda/kickjs/fastify`,typeName:`FastifyRuntimeTypes`},h3:{subpath:`@forinda/kickjs/h3`,typeName:`H3RuntimeTypes`}},xc=()=>({id:`kick/runtime`,outExtension:`.ts`,inputs:[`kick.config.ts`,`kick.config.js`,`kick.config.mjs`,`kick.config.json`],async generate(e){let t=e.config?.runtime;if(t!==`fastify`&&t!==`h3`)return null;let{subpath:n,typeName:r}=bc[t];return[`// Runtime escape-hatch types for the '${t}' engine (kick.config runtime).`,`declare module '@forinda/kickjs' {`,` interface KickRuntimeRegister {`,` runtime: import('${n}').${r}`,` }`,`}`,``,`export {}`,``].join(`
2844
- `)}});var Sc=k({builtinCliPlugins:()=>Cc});const Cc=[E({name:`kick/init`,register:$t}),E({name:`kick/generate`,register:Ga}),E({name:`kick/run`,register:mo}),E({name:`kick/info`,register:yo}),E({name:`kick/inspect`,register:ko}),E({name:`kick/add`,register:Mt}),E({name:`kick/list`,register:jt}),E({name:`kick/explain`,register:zo}),E({name:`kick/mcp`,register:Xo}),E({name:`kick/tinker`,register:es}),E({name:`kick/remove`,register:os}),E({name:`kick/typegen`,register:ls}),E({name:`kick/check`,register:xs}),E({name:`kick/doctor`,register:qs}),E({name:`kick/codemod`,register:Ys}),E({name:`kick/registry`,typegens:[mc()]}),E({name:`kick/services`,typegens:[hc()]}),E({name:`kick/modules`,typegens:[gc()]}),E({name:`kick/plugins`,typegens:[_c()]}),E({name:`kick/augmentations`,typegens:[vc()]}),E({name:`kick/context`,typegens:[yc()]}),E({name:`kick/assets`,typegens:[Xs()]}),E({name:`kick/routes`,typegens:[ic()]}),E({name:`kick/env`,typegens:[cc()]}),E({name:`kick/runtime`,typegens:[xc()]})],wc=f(b(import.meta.url)),Tc=JSON.parse(a(h(wc,`..`,`package.json`),`utf-8`));async function Ec(){let e=new t;e.name(`kick`).description(`KickJS — A production-grade, decorator-driven Node.js framework`).version(Tc.version);let n=rn(process.cwd()),r=n,i=await j(r)??{},a=Ie([...Cc,...i.plugins??[]],i.commands??[]);await a.register(e,{cwd:r,projectRoot:n,config:i,log:e=>console.log(e)}),Se(e,{...i,commands:a.commands}),e.showHelpAfterError();let o=process.argv.map(e=>e===`-v`?`--version`:e);await e.parseAsync(o)}Ec().catch(e=>{console.error(e instanceof Error?e.message:e),process.exitCode=1});export{N as a,Lt as i,ar as n,Ht as r,Aa as t};
2846
+ `}const lc=()=>({id:`kick/env`,outExtension:`.ts`,inputs:[`src/env.ts`,`src/**/env.ts`,`src/**/*.env.ts`],async generate(e){let t=dc(e);if(t===!1)return null;let n=await e.getScanResult({root:uc(e),cwd:e.cwd,envFile:t});if(!n.env)return null;let r=e.config?.typegen?.schemaValidator??`zod`,i=u.resolve(e.cwd,`.kickjs/types/kick__env.ts`);return cc(n.env,i,r)}});function uc(e){return u.resolve(e.cwd,e.config?.typegen?.srcDir??`src`)}function dc(e){return e.config?.typegen?.envFile}function fc(e){return u.resolve(e.cwd,e.config?.typegen?.srcDir??`src`)}function pc(e){let t=e.config?.typegen?.envFile;if(t!==!1)return t}function mc(e){return{root:fc(e),cwd:e.cwd,envFile:pc(e)}}const hc=()=>({id:`kick/registry`,inputs:[`src/**/*.ts`],async generate(e){let t=await e.getScanResult(mc(e)),n=u.resolve(e.cwd,`.kickjs/types/kick__registry.d.ts`),r=new Set(t.collisions.map(e=>e.className));return pa(t.classes,n,r)}}),gc=()=>({id:`kick/services`,inputs:[`src/**/*.ts`],async generate(e){let t=await e.getScanResult(mc(e)),n=new Set(t.collisions.map(e=>e.className));return ga(`ServiceToken`,_a(t.classes,t.tokens,t.injects,n),"(no tokens discovered — declare with createToken<T>() or `kick g service <name>`)")}}),_c=()=>({id:`kick/modules`,inputs:[`src/**/*.ts`],async generate(e){return ga(`ModuleToken`,va((await e.getScanResult(mc(e))).classes),"(no @Module classes discovered — `kick g module <name>` to add one)")}}),vc=()=>({id:`kick/plugins`,inputs:[`src/**/*.ts`],async generate(e){return ya((await e.getScanResult(mc(e))).pluginsAndAdapters)}}),yc=()=>({id:`kick/augmentations`,inputs:[`src/**/*.ts`],async generate(e){return ba((await e.getScanResult(mc(e))).augmentations)}}),bc=()=>({id:`kick/context`,inputs:[`src/**/*.ts`],async generate(e){let t=await e.getScanResult(mc(e));return t.contextKeys.length===0?null:ha(t.contextKeys)}}),xc={fastify:{subpath:`@forinda/kickjs/fastify`,typeName:`FastifyRuntimeTypes`},h3:{subpath:`@forinda/kickjs/h3`,typeName:`H3RuntimeTypes`}},Sc=()=>({id:`kick/runtime`,outExtension:`.ts`,inputs:[`kick.config.ts`,`kick.config.js`,`kick.config.mjs`,`kick.config.json`],async generate(e){let t=e.config?.runtime;if(t!==`fastify`&&t!==`h3`)return null;let{subpath:n,typeName:r}=xc[t];return[`// Runtime escape-hatch types for the '${t}' engine (kick.config runtime).`,`declare module '@forinda/kickjs' {`,` interface KickRuntimeRegister {`,` runtime: import('${n}').${r}`,` }`,`}`,``,`export {}`,``].join(`
2847
+ `)}});var Cc=k({builtinCliPlugins:()=>wc});const wc=[E({name:`kick/init`,register:$t}),E({name:`kick/generate`,register:Ga}),E({name:`kick/run`,register:mo}),E({name:`kick/info`,register:yo}),E({name:`kick/inspect`,register:ko}),E({name:`kick/add`,register:Mt}),E({name:`kick/list`,register:jt}),E({name:`kick/explain`,register:zo}),E({name:`kick/mcp`,register:Xo}),E({name:`kick/tinker`,register:es}),E({name:`kick/remove`,register:os}),E({name:`kick/typegen`,register:ls}),E({name:`kick/check`,register:xs}),E({name:`kick/doctor`,register:qs}),E({name:`kick/codemod`,register:Ys}),E({name:`kick/registry`,typegens:[hc()]}),E({name:`kick/services`,typegens:[gc()]}),E({name:`kick/modules`,typegens:[_c()]}),E({name:`kick/plugins`,typegens:[vc()]}),E({name:`kick/augmentations`,typegens:[yc()]}),E({name:`kick/context`,typegens:[bc()]}),E({name:`kick/assets`,typegens:[Xs()]}),E({name:`kick/routes`,typegens:[ac()]}),E({name:`kick/env`,typegens:[lc()]}),E({name:`kick/runtime`,typegens:[Sc()]})],Tc=f(b(import.meta.url)),Ec=JSON.parse(a(h(Tc,`..`,`package.json`),`utf-8`));async function Dc(){let e=new t;e.name(`kick`).description(`KickJS — A production-grade, decorator-driven Node.js framework`).version(Ec.version);let n=rn(process.cwd()),r=n,i=await j(r)??{},a=Ie([...wc,...i.plugins??[]],i.commands??[]);await a.register(e,{cwd:r,projectRoot:n,config:i,log:e=>console.log(e)}),Se(e,{...i,commands:a.commands}),e.showHelpAfterError();let o=process.argv.map(e=>e===`-v`?`--version`:e);await e.parseAsync(o)}Dc().catch(e=>{console.error(e instanceof Error?e.message:e),process.exitCode=1});export{N as a,Lt as i,ar as n,Ht as r,Aa as t};
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs-cli v6.6.1
2
+ * @forinda/kickjs-cli v6.7.0
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,6 +8,6 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import{t as e}from"./rolldown-runtime-BKn_X0JJ.mjs";import{isAbsolute as t,join as n,relative as r,resolve as i}from"node:path";import{existsSync as a,mkdirSync as o,readFileSync as s,writeFileSync as c}from"node:fs";import{access as l,readFile as u}from"node:fs/promises";var d=e({BUILTIN_REPO_TYPES:()=>p,DEPRECATED_REPO_TYPES:()=>m,PACKAGE_MANAGERS:()=>f,defineConfig:()=>g,loadKickConfig:()=>x,resolveModuleConfig:()=>y,resolveTokenScope:()=>_,validateAssetMap:()=>C,warnIfDeprecatedRepo:()=>h,writeAssetConfigSnapshot:()=>S});const f=[`pnpm`,`npm`,`yarn`,`bun`],p=[`inmemory`],m=[`prisma`,`drizzle`];function h(e){return m.includes(e)?(console.warn(` Note: the '${e}' repository preset is deprecated. Generating a generic custom repository named '${e}' instead — wire it to your DB by hand. Pass any name via \`--repo <name>\` or \`modules.repo: { name: '<name>' }\`.`),!0):!1}function g(e){return e}function _(e,t){if(e?.tokenScope&&typeof e.tokenScope==`string`&&e.tokenScope.length>0){let t=v(e.tokenScope);if(t.length>0)return t}try{let e=n(t,`package.json`);if(a(e)){let t=JSON.parse(s(e,`utf-8`));if(typeof t.name==`string`&&t.name.length>0){let e=t.name.match(/^@([^/]+)\//),n=v(e?e[1]:t.name);if(n.length>0)return n}}}catch{}return`app`}function v(e){return e.toLowerCase().replace(/[^a-z0-9-]/g,`-`).replace(/^-+|-+$/g,``).replace(/-{2,}/g,`-`)}function y(e){if(!e)return{};let t={dir:e.modules?.dir,repo:e.modules?.repo,schemaDir:e.modules?.schemaDir,pluralize:e.modules?.pluralize,prismaClientPath:e.modules?.prismaClientPath,style:e.modules?.style};return t.style!==void 0&&t.style!==`define`&&t.style!==`class`&&(console.warn(` Warning: modules.style '${t.style}' is not a valid value (expected 'define' or 'class'). Falling back to 'define'.`),t.style=`define`),t.repo&&typeof t.repo==`string`&&!p.includes(t.repo)&&(h(t.repo)||console.warn(` Warning: modules.repo '${t.repo}' is not a built-in type (${p.join(`, `)}). It will generate a stub repository. Use { name: '${t.repo}' } to silence this warning.`)),t}const b=[`kick.config.ts`,`kick.config.js`,`kick.config.mjs`,`kick.config.json`];async function x(e){let{findProjectRoot:t}=await import(`./project-root-DRTGL9O5.mjs`).then(e=>e.n),r=t(e);for(let e of b){let t=n(r,e);try{await l(t)}catch{continue}if(e.endsWith(`.json`)){let e=await u(t,`utf-8`);return JSON.parse(e)}if(e.endsWith(`.ts`)){let n;try{n=await import(`jiti`)}catch(t){let n=t instanceof Error?t.message:String(t);n.includes(`Cannot find package 'jiti'`)||n.includes(`ERR_MODULE_NOT_FOUND`)?console.warn(`Warning: Failed to load ${e} — 'jiti' is required for TypeScript configs. Run \`pnpm add -D jiti\` (or your package manager's equivalent), or rename the file to kick.config.js / kick.config.mjs / kick.config.json.`):console.warn(`Warning: Failed to initialize jiti for ${e}: ${n}`);continue}try{let e=await n.createJiti(r,{interopDefault:!0,fsCache:!1}).import(t,{default:!0}),i=C(e,r);for(let e of i)console.warn(` Warning: ${e}`);return S(r,e),e}catch(t){let n=t instanceof Error?t.message:String(t);console.warn(`Warning: Failed to load ${e}: ${n}`);continue}}try{let{pathToFileURL:e}=await import(`node:url`),n=await import(e(t).href),i=n.default??n,a=C(i,r);for(let e of a)console.warn(` Warning: ${e}`);return S(r,i),i}catch(t){let n=t instanceof Error?t.message:String(t);console.warn(`Warning: Failed to load ${e}: ${n}`);continue}}return null}function S(e,t){if(!(!t?.assetMap||Object.keys(t.assetMap).length===0))try{let r=n(e,`.kickjs`);o(r,{recursive:!0});let i={version:1,assetMap:t.assetMap,...t.build?.outDir?{build:{outDir:t.build.outDir}}:{}};c(n(r,`kick.config.json`),JSON.stringify(i,null,2)+`
11
+ import{t as e}from"./rolldown-runtime-DiP_G7eI.mjs";import{isAbsolute as t,join as n,relative as r,resolve as i}from"node:path";import{existsSync as a,mkdirSync as o,readFileSync as s,writeFileSync as c}from"node:fs";import{access as l,readFile as u}from"node:fs/promises";var d=e({BUILTIN_REPO_TYPES:()=>p,DEPRECATED_REPO_TYPES:()=>m,PACKAGE_MANAGERS:()=>f,defineConfig:()=>g,loadKickConfig:()=>x,resolveModuleConfig:()=>y,resolveTokenScope:()=>_,validateAssetMap:()=>C,warnIfDeprecatedRepo:()=>h,writeAssetConfigSnapshot:()=>S});const f=[`pnpm`,`npm`,`yarn`,`bun`],p=[`inmemory`],m=[`prisma`,`drizzle`];function h(e){return m.includes(e)?(console.warn(` Note: the '${e}' repository preset is deprecated. Generating a generic custom repository named '${e}' instead — wire it to your DB by hand. Pass any name via \`--repo <name>\` or \`modules.repo: { name: '<name>' }\`.`),!0):!1}function g(e){return e}function _(e,t){if(e?.tokenScope&&typeof e.tokenScope==`string`&&e.tokenScope.length>0){let t=v(e.tokenScope);if(t.length>0)return t}try{let e=n(t,`package.json`);if(a(e)){let t=JSON.parse(s(e,`utf-8`));if(typeof t.name==`string`&&t.name.length>0){let e=t.name.match(/^@([^/]+)\//),n=v(e?e[1]:t.name);if(n.length>0)return n}}}catch{}return`app`}function v(e){return e.toLowerCase().replace(/[^a-z0-9-]/g,`-`).replace(/^-+|-+$/g,``).replace(/-{2,}/g,`-`)}function y(e){if(!e)return{};let t={dir:e.modules?.dir,repo:e.modules?.repo,schemaDir:e.modules?.schemaDir,pluralize:e.modules?.pluralize,prismaClientPath:e.modules?.prismaClientPath,style:e.modules?.style};return t.style!==void 0&&t.style!==`define`&&t.style!==`class`&&(console.warn(` Warning: modules.style '${t.style}' is not a valid value (expected 'define' or 'class'). Falling back to 'define'.`),t.style=`define`),t.repo&&typeof t.repo==`string`&&!p.includes(t.repo)&&(h(t.repo)||console.warn(` Warning: modules.repo '${t.repo}' is not a built-in type (${p.join(`, `)}). It will generate a stub repository. Use { name: '${t.repo}' } to silence this warning.`)),t}const b=[`kick.config.ts`,`kick.config.js`,`kick.config.mjs`,`kick.config.json`];async function x(e){let{findProjectRoot:t}=await import(`./project-root-CdqXle6R.mjs`).then(e=>e.n),r=t(e);for(let e of b){let t=n(r,e);try{await l(t)}catch{continue}if(e.endsWith(`.json`)){let e=await u(t,`utf-8`);return JSON.parse(e)}if(e.endsWith(`.ts`)){let n;try{n=await import(`jiti`)}catch(t){let n=t instanceof Error?t.message:String(t);n.includes(`Cannot find package 'jiti'`)||n.includes(`ERR_MODULE_NOT_FOUND`)?console.warn(`Warning: Failed to load ${e} — 'jiti' is required for TypeScript configs. Run \`pnpm add -D jiti\` (or your package manager's equivalent), or rename the file to kick.config.js / kick.config.mjs / kick.config.json.`):console.warn(`Warning: Failed to initialize jiti for ${e}: ${n}`);continue}try{let e=await n.createJiti(r,{interopDefault:!0,fsCache:!1}).import(t,{default:!0}),i=C(e,r);for(let e of i)console.warn(` Warning: ${e}`);return S(r,e),e}catch(t){let n=t instanceof Error?t.message:String(t);console.warn(`Warning: Failed to load ${e}: ${n}`);continue}}try{let{pathToFileURL:e}=await import(`node:url`),n=await import(e(t).href),i=n.default??n,a=C(i,r);for(let e of a)console.warn(` Warning: ${e}`);return S(r,i),i}catch(t){let n=t instanceof Error?t.message:String(t);console.warn(`Warning: Failed to load ${e}: ${n}`);continue}}return null}function S(e,t){if(!(!t?.assetMap||Object.keys(t.assetMap).length===0))try{let r=n(e,`.kickjs`);o(r,{recursive:!0});let i={version:1,assetMap:t.assetMap,...t.build?.outDir?{build:{outDir:t.build.outDir}}:{}};c(n(r,`kick.config.json`),JSON.stringify(i,null,2)+`
12
12
  `,`utf-8`)}catch{}}function C(e,t){let n=[];if(!e?.assetMap)return n;let r=i(t);for(let[o,s]of Object.entries(e.assetMap)){if(!o||o.includes(`/`)){n.push(`assetMap key '${o}' is invalid — must be a non-empty string without '/'`);continue}if(typeof s?.src!=`string`||s.src.length===0){n.push(`assetMap.${o} is missing a non-empty 'src' field`);continue}a(i(t,s.src))||n.push(`assetMap.${o}.src ('${s.src}') does not exist — typegen + build will fail`),s.dest&&w(i(t,s.dest),r)&&n.push(`assetMap.${o}.dest ('${s.dest}') resolves outside the project root — refusing to copy`)}return n}function w(e,n){let i=r(n,e);return i===``?!1:i.startsWith(`..`)||t(i)}export{y as a,x as i,d as n,_ as o,g as r,h as s,f as t};
13
- //# sourceMappingURL=config-COL9zMB5.mjs.map
13
+ //# sourceMappingURL=config-D6C74vFp.mjs.map