@forinda/kickjs-cli 5.7.0 → 5.8.1
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.
- package/README.md +1 -1
- package/dist/{builtins-BIpoT6cb.mjs → builtins-CF4q3JIg.mjs} +2 -2
- package/dist/cli.mjs +117 -117
- package/dist/{config-BQUzGk6m.mjs → config-v6vsVMtc.mjs} +3 -3
- package/dist/{config-BQUzGk6m.mjs.map → config-v6vsVMtc.mjs.map} +1 -1
- package/dist/{generator-extension-Cd2DU_XX.mjs → generator-extension-ChoCJW23.mjs} +60 -60
- package/dist/{generator-extension-Cd2DU_XX.mjs.map → generator-extension-ChoCJW23.mjs.map} +1 -1
- package/dist/index.d.mts +41 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/{plugin-B6ANfh7O.mjs → plugin-1Oiz9_TD.mjs} +3 -3
- package/dist/{plugin-B6ANfh7O.mjs.map → plugin-1Oiz9_TD.mjs.map} +1 -1
- package/dist/{project-root-Dsxhm7OL.mjs → project-root-BaUzB3D7.mjs} +3 -3
- package/dist/{project-root-Dsxhm7OL.mjs.map → project-root-BaUzB3D7.mjs.map} +1 -1
- package/dist/{rolldown-runtime-jjtMmVBF.mjs → rolldown-runtime-vNCSDkuE.mjs} +1 -1
- package/dist/{run-plugins-DaO1FtZb.mjs → run-plugins-Bg8kTYfa.mjs} +6 -6
- package/dist/run-plugins-Bg8kTYfa.mjs.map +1 -0
- package/dist/{typegen-D-1Q9yBD.mjs → typegen-B8lAhWXz.mjs} +4 -4
- package/dist/{typegen-D-1Q9yBD.mjs.map → typegen-B8lAhWXz.mjs.map} +1 -1
- package/dist/{types-Du3p7CZ5.mjs → types-BG2NeDgK.mjs} +2 -2
- package/dist/types-BG2NeDgK.mjs.map +1 -0
- package/package.json +5 -5
- package/dist/run-plugins-DaO1FtZb.mjs.map +0 -1
- package/dist/types-Du3p7CZ5.mjs.map +0 -1
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @forinda/kickjs-cli v5.
|
|
2
|
+
* @forinda/kickjs-cli v5.8.1
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Felix Orinda
|
|
5
5
|
*
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
|
-
import{createRequire as e}from"node:module";import{Command as t}from"commander";import{cpSync as n,existsSync as r,mkdirSync as i,readFileSync as a,readdirSync as o,rmSync as s,statSync as c,writeFileSync as l}from"node:fs";import u,{basename as d,dirname as f,extname as p,isAbsolute as m,join as h,parse as g,relative as _,resolve as v,sep as y}from"node:path";import{fileURLToPath as b,pathToFileURL as x}from"node:url";import{execFileSync as ee,execSync as S,fork as te,spawn as ne,spawnSync as re}from"node:child_process";import{access as ie,copyFile as ae,mkdir as oe,readFile as C,readdir as se,rm as ce,stat as le,unlink as ue,writeFile as w}from"node:fs/promises";import*as T from"@clack/prompts";import E from"picocolors";import de from"pluralize";import{glob as fe,globSync as pe}from"glob";import{groupAssetKeys as me}from"@forinda/kickjs";import{arch as he,platform as ge,release as _e}from"node:os";import{detectCompositeReferences as ve,generate as ye,migrateDown as be,migrateLatest as xe,migrateRollback as Se,migrateStatus as Ce,migrateUp as we,renderSchemaSource as Te,resolveDbConfig as Ee}from"@forinda/kickjs-db";var De=Object.defineProperty,D=(e,t)=>{let n={};for(var r in e)De(n,r,{get:e[r],enumerable:!0});return t||De(n,Symbol.toStringTag,{value:`Module`}),n};function Oe(e,t,n){S(e,{cwd:t,stdio:`inherit`,env:n?{...process.env,...n}:process.env})}function ke(e,t,n){let r=re(process.execPath,[e],{cwd:n,stdio:`inherit`,env:{...process.env,...t}});r.status!==0&&process.exit(r.status??1)}function Ae(e,t){if(!t?.commands?.length)return;let n=new Set(e.commands.map(e=>e.name()));for(let r of t.commands){if(n.has(r.name)){console.warn(` Warning: custom command '${r.name}' skipped — conflicts with a built-in command`);continue}je(e,r)}}function je(e,t){let n=e.command(t.name).description(t.description);if(t.aliases)for(let e of t.aliases)n.alias(e);n.allowUnknownOption(!0),n.argument(`[args...]`,`Additional arguments passed to the command`),n.action(e=>{let n=e.join(` `),r=Array.isArray(t.steps)?t.steps:[t.steps];for(let e of r){let r=n?`${e} ${n}`:e;console.log(` $ ${r}`);try{Oe(r)}catch{console.error(` Command failed: ${t.name}`),process.exitCode=1;return}}})}var Me=D({BUILTIN_REPO_TYPES:()=>Pe,PACKAGE_MANAGERS:()=>Ne,defineConfig:()=>Fe,loadKickConfig:()=>k,resolveModuleConfig:()=>O,resolveTokenScope:()=>Ie,validateAssetMap:()=>ze});const Ne=[`pnpm`,`npm`,`yarn`,`bun`],Pe=[`drizzle`,`inmemory`,`prisma`];function Fe(e){return e}function Ie(e,t){if(e?.tokenScope&&typeof e.tokenScope==`string`&&e.tokenScope.length>0){let t=Le(e.tokenScope);if(t.length>0)return t}try{let e=h(t,`package.json`);if(r(e)){let t=JSON.parse(a(e,`utf-8`));if(typeof t.name==`string`&&t.name.length>0){let e=t.name.match(/^@([^/]+)\//),n=Le(e?e[1]:t.name);if(n.length>0)return n}}}catch{}return`app`}function Le(e){return e.toLowerCase().replace(/[^a-z0-9-]/g,`-`).replace(/^-+|-+$/g,``).replace(/-{2,}/g,`-`)}function O(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`&&!Pe.includes(t.repo)&&console.warn(` Warning: modules.repo '${t.repo}' is not a built-in type (${Pe.join(`, `)}). It will generate a stub repository. Use { name: '${t.repo}' } to silence this warning.`),t}const Re=[`kick.config.ts`,`kick.config.js`,`kick.config.mjs`,`kick.config.json`];async function k(e){let{findProjectRoot:t}=await Promise.resolve().then(()=>
|
|
11
|
+
import{createRequire as e}from"node:module";import{Command as t}from"commander";import{cpSync as n,existsSync as r,mkdirSync as i,readFileSync as a,readdirSync as o,rmSync as s,statSync as c,writeFileSync as l}from"node:fs";import u,{basename as d,dirname as f,extname as p,isAbsolute as m,join as h,parse as g,relative as _,resolve as v,sep as y}from"node:path";import{fileURLToPath as b,pathToFileURL as x}from"node:url";import{execFileSync as ee,execSync as S,fork as te,spawn as ne,spawnSync as re}from"node:child_process";import{access as ie,copyFile as ae,mkdir as oe,readFile as C,readdir as se,rm as ce,stat as le,unlink as ue,writeFile as w}from"node:fs/promises";import*as T from"@clack/prompts";import E from"picocolors";import de from"pluralize";import{glob as fe,globSync as pe}from"glob";import{groupAssetKeys as me}from"@forinda/kickjs";import{arch as he,platform as ge,release as _e}from"node:os";import{detectCompositeReferences as ve,generate as ye,migrateDown as be,migrateLatest as xe,migrateRollback as Se,migrateStatus as Ce,migrateUp as we,renderSchemaSource as Te,resolveDbConfig as Ee}from"@forinda/kickjs-db";var De=Object.defineProperty,D=(e,t)=>{let n={};for(var r in e)De(n,r,{get:e[r],enumerable:!0});return t||De(n,Symbol.toStringTag,{value:`Module`}),n};function Oe(e,t,n){S(e,{cwd:t,stdio:`inherit`,env:n?{...process.env,...n}:process.env})}function ke(e,t,n){let r=re(process.execPath,[e],{cwd:n,stdio:`inherit`,env:{...process.env,...t}});r.status!==0&&process.exit(r.status??1)}function Ae(e,t){if(!t?.commands?.length)return;let n=new Set(e.commands.map(e=>e.name()));for(let r of t.commands){if(n.has(r.name)){console.warn(` Warning: custom command '${r.name}' skipped — conflicts with a built-in command`);continue}je(e,r)}}function je(e,t){let n=e.command(t.name).description(t.description);if(t.aliases)for(let e of t.aliases)n.alias(e);n.allowUnknownOption(!0),n.argument(`[args...]`,`Additional arguments passed to the command`),n.action(e=>{let n=e.join(` `),r=Array.isArray(t.steps)?t.steps:[t.steps];for(let e of r){let r=n?`${e} ${n}`:e;console.log(` $ ${r}`);try{Oe(r)}catch{console.error(` Command failed: ${t.name}`),process.exitCode=1;return}}})}var Me=D({BUILTIN_REPO_TYPES:()=>Pe,PACKAGE_MANAGERS:()=>Ne,defineConfig:()=>Fe,loadKickConfig:()=>k,resolveModuleConfig:()=>O,resolveTokenScope:()=>Ie,validateAssetMap:()=>ze});const Ne=[`pnpm`,`npm`,`yarn`,`bun`],Pe=[`drizzle`,`inmemory`,`prisma`];function Fe(e){return e}function Ie(e,t){if(e?.tokenScope&&typeof e.tokenScope==`string`&&e.tokenScope.length>0){let t=Le(e.tokenScope);if(t.length>0)return t}try{let e=h(t,`package.json`);if(r(e)){let t=JSON.parse(a(e,`utf-8`));if(typeof t.name==`string`&&t.name.length>0){let e=t.name.match(/^@([^/]+)\//),n=Le(e?e[1]:t.name);if(n.length>0)return n}}}catch{}return`app`}function Le(e){return e.toLowerCase().replace(/[^a-z0-9-]/g,`-`).replace(/^-+|-+$/g,``).replace(/-{2,}/g,`-`)}function O(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`&&!Pe.includes(t.repo)&&console.warn(` Warning: modules.repo '${t.repo}' is not a built-in type (${Pe.join(`, `)}). It will generate a stub repository. Use { name: '${t.repo}' } to silence this warning.`),t}const Re=[`kick.config.ts`,`kick.config.js`,`kick.config.mjs`,`kick.config.json`];async function k(e){let{findProjectRoot:t}=await Promise.resolve().then(()=>Zt),n=t(e);for(let e of Re){let t=h(n,e);try{await ie(t)}catch{continue}if(e.endsWith(`.json`)){let e=await C(t,`utf-8`);return JSON.parse(e)}if(e.endsWith(`.ts`)){let r;try{r=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 r.createJiti(n,{interopDefault:!0,fsCache:!1}).import(t,{default:!0}),i=ze(e,n);for(let e of i)console.warn(` Warning: ${e}`);return 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`),r=await import(e(t).href),i=r.default??r,a=ze(i,n);for(let e of a)console.warn(` Warning: ${e}`);return i}catch(t){let n=t instanceof Error?t.message:String(t);console.warn(`Warning: Failed to load ${e}: ${n}`);continue}}return null}function ze(e,t){let n=[];if(!e?.assetMap)return n;let i=v(t);for(let[a,o]of Object.entries(e.assetMap)){if(!a||a.includes(`/`)){n.push(`assetMap key '${a}' is invalid — must be a non-empty string without '/'`);continue}if(typeof o?.src!=`string`||o.src.length===0){n.push(`assetMap.${a} is missing a non-empty 'src' field`);continue}r(v(t,o.src))||n.push(`assetMap.${a}.src ('${o.src}') does not exist — typegen + build will fail`),o.dest&&Be(v(t,o.dest),i)&&n.push(`assetMap.${a}.dest ('${o.dest}') resolves outside the project root — refusing to copy`)}return n}function Be(e,t){let n=_(t,e);return n===``?!1:n.startsWith(`..`)||m(n)}function A(e){return e}var Ve=class extends Error{constructor(e,t,n){super(`Two plugins registered the same ${e} '${t}': ${n.join(`, `)}. Plugins must use unique ${e} names.`),this.name=`KickPluginConflictError`}};function He(e,t=[]){let n=new Map;for(let t of e){let e=(n.get(t.name)??0)+1;if(n.set(t.name,e),e===2)throw new Ve(`plugin`,t.name,[t.name,t.name])}let r=new Map,i=[];for(let t of e)for(let e of t.commands??[]){let n=r.get(e.name);if(n)throw new Ve(`command`,e.name,[n,t.name]);r.set(e.name,t.name),i.push(e)}let a=new Set(t.map(e=>e.name)),o=[...i.filter(e=>!a.has(e.name)),...t],s=new Map,c=[];for(let t of e)for(let e of t.typegens??[]){let n=s.get(e.id);if(n)throw new Ve(`typegen`,e.id,[n,t.name]);s.set(e.id,t.name),c.push(e)}let l=new Map,u=[];for(let t of e)for(let e of t.generators??[]){let n=l.get(e.name);if(n)throw new Ve(`generator`,e.name,[n,t.name]);l.set(e.name,t.name),u.push({source:t.name,spec:e})}return{commands:o,typegens:c,generators:u,register:async(t,n)=>{let r;if(n)r={generators:u,...n};else{let{findProjectRoot:e}=await Promise.resolve().then(()=>Zt),t=process.cwd();r={cwd:t,projectRoot:e(t),config:null,log:()=>{},generators:u}}for(let n of e)n.register&&await n.register(t,r)}}}var Ue=D({mergeCliPlugins:()=>He});let We=!1;function j(e){We=e}const Ge=new Set([`.ts`,`.tsx`,`.js`,`.jsx`,`.mjs`,`.cjs`,`.json`,`.md`]);async function M(e,t){We||(await oe(f(e),{recursive:!0}),await w(e,t,`utf-8`),Ge.has(p(e))&&await Je(e,t).catch(()=>{}))}let Ke;async function qe(t){if(Ke!==void 0)return Ke;try{Ke=await import(e(h(t,`package.json`)).resolve(`oxfmt`))}catch{Ke=null}return Ke}async function Je(e,t){let n=await qe(process.cwd());if(!n)return;let r=await Ye(e);if(r===null)return;let i=await n.format(e,t,r);i.code!==t&&await w(e,i.code,`utf-8`)}const N=new Map;async function Ye(e){let t=f(e),n=t;if(N.has(n))return N.get(n);for(;;){let e=h(t,`.oxfmtrc.json`);if(r(e))try{let t=await C(e,`utf-8`),r=JSON.parse(t);return delete r.$schema,delete r.ignorePatterns,N.set(n,r),r}catch{return N.set(n,null),null}let i=f(t);if(i===t)return N.set(n,null),null;t=i}}async function Xe(e){try{return await ie(e),!0}catch{return!1}}const Ze={swagger:`@forinda/kickjs-swagger`,ws:`@forinda/kickjs-ws`,queue:`@forinda/kickjs-queue`,devtools:`@forinda/kickjs-devtools`};function Qe(e,t){let n=e[t];if(!n)throw Error(`generatePackageJson: missing resolved version for ${t}. Add it to SIBLING_PACKAGES in generators/project.ts.`);return n}function $e(e,t,n,r=[]){let i={"@forinda/kickjs":Qe(n,`@forinda/kickjs`),dotenv:`^17.3.1`,express:`^5.1.0`,"reflect-metadata":`^0.2.2`,zod:`^4.3.6`,pino:`^10.3.1`,"pino-pretty":`^13.1.3`};for(let e of r){let t=Ze[e];t&&!i[t]&&(i[t]=Qe(n,t))}return JSON.stringify({name:e,version:`0.0.0`,type:`module`,scripts:{dev:`vite`,"dev:debug":`kick dev:debug`,build:`kick build`,start:`kick start`,test:`vitest run`,"test:watch":`vitest`,typecheck:`tsc --noEmit`,typegen:`kick typegen`,lint:`eslint src/`,format:`prettier --write src/`},dependencies:i,devDependencies:{"@forinda/kickjs-cli":Qe(n,`@forinda/kickjs-cli`),"@forinda/kickjs-vite":Qe(n,`@forinda/kickjs-vite`),"@swc/core":`^1.15.21`,"@types/express":`^5.0.6`,"@types/node":`^25.0.0`,"unplugin-swc":`^1.5.9`,vite:`^8.0.3`,vitest:`^4.1.2`,typescript:`^6.0.3`,prettier:`^3.8.1`}},null,2)}function et(){return`import { defineConfig } from 'vite'
|
|
12
12
|
import { resolve } from 'node:path'
|
|
13
13
|
import swc from 'unplugin-swc'
|
|
14
14
|
import { kickjsVitePlugin, envWatchPlugin } from '@forinda/kickjs-vite'
|
|
@@ -1403,15 +1403,15 @@ Codex / Cursor / Gemini / Claude Code without copy-pasting.
|
|
|
1403
1403
|
CLI template. Hand-edited content is overwritten — keep customisation
|
|
1404
1404
|
in \`.agents/COPILOT.local.md\`.
|
|
1405
1405
|
`}const Ct=f(b(import.meta.url)),wt=JSON.parse(a(h(Ct,`..`,`package.json`),`utf-8`)),Tt=`^${wt.version}`,Et=[`@forinda/kickjs`,`@forinda/kickjs-cli`,`@forinda/kickjs-vite`,`@forinda/kickjs-swagger`,`@forinda/kickjs-ws`,`@forinda/kickjs-queue`,`@forinda/kickjs-devtools`,`@forinda/kickjs-testing`];async function Dt(){let e=await Promise.all(Et.map(async e=>{try{let t=ee(`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,Tt]}));return Object.fromEntries(e)}async function Ot(e){let{name:t,directory:n,packageManager:r=`pnpm`,template:i=`rest`,defaultRepo:a=`inmemory`,packages:o=[]}=e,s=n,c=e=>console.log(` ${e}`);console.log(`\n Creating KickJS project: ${t}\n`),c(`Resolving package versions...`);let l=await Dt();if(await M(h(s,`package.json`),$e(t,i,l,o)),await M(h(s,`vite.config.ts`),et()),await M(h(s,`tsconfig.json`),tt()),await M(h(s,`.prettierrc`),nt()),await M(h(s,`.editorconfig`),rt()),await M(h(s,`.gitignore`),it()),await M(h(s,`.gitattributes`),at()),await M(h(s,`.env`),ot()),await M(h(s,`.env.example`),st()),await M(h(s,`src/config/index.ts`),dt()),await M(h(s,`src/index.ts`),lt(t,i,wt.version,o)),await M(h(s,`src/modules/index.ts`),ut()),await M(h(s,`src/modules/hello/hello.service.ts`),ft()),await M(h(s,`src/modules/hello/hello.controller.ts`),pt()),await M(h(s,`src/modules/hello/hello.module.ts`),mt()),await M(h(s,`kick.config.ts`),ht(i,a,r)),await M(h(s,`vitest.config.ts`),ct()),await M(h(s,`README.md`),gt(t,i,r)),await M(h(s,`CLAUDE.md`),_t(t,i,r)),await M(h(s,`AGENTS.md`),vt(t,i,r)),await M(h(s,`kickjs-skills.md`),bt(t,i,r)),e.installDeps){console.log(`\n Installing dependencies with ${r}...\n`);try{S(`${r} install`,{cwd:s,stdio:`inherit`}),console.log(`
|
|
1406
|
-
Dependencies installed successfully!`)}catch{console.log(`\n Warning: ${r} install failed. Run it manually.`)}}try{let{runTypegen:e}=await Promise.resolve().then(()=>
|
|
1407
|
-
Project scaffolded successfully!`),console.log();let u=s!==process.cwd();c(`Next steps:`),u&&c(` cd ${t}`),e.installDeps||c(` ${r} install`);let d={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`};c(` ${d[i]??d.rest}`),c(` kick dev`),c(``),c(`Commands:`),c(` kick dev Start dev server with Vite HMR`),c(` kick build Production build via Vite`),c(` kick start Run production build`),c(``),c(`Generators:`),c(` kick g module <name> Full DDD module (controller, DTOs, use-cases, repo)`),c(` kick g scaffold <n> <f..> CRUD module from field definitions`),c(` kick g controller <name> Standalone controller`),c(` kick g service <name> @Service() class`),c(` kick g middleware <name> Express middleware`),c(` kick g guard <name> Route guard (auth, roles, etc.)`),c(` kick g adapter <name> AppAdapter with lifecycle hooks`),c(` kick g dto <name> Zod DTO schema`),i===`cqrs`&&c(` kick g job <name> Queue job processor`),c(` kick g config Generate kick.config.ts`),c(``),c(`Add packages:`),c(` kick add <pkg> Install a KickJS package + peers`),c(` kick add --list Show all available packages`),c(``),c(`Available: auth, swagger, drizzle, prisma, ws, queue, devtools, mcp, testing`),c(``)}const kt={GET:E.green,POST:E.cyan,PUT:E.yellow,PATCH:E.magenta,DELETE:E.red};function At(e){return(kt[e]??E.dim)(e.padEnd(7))}function jt(e){let t=`[${e}]`.padEnd(10);switch(e){case`CRITICAL`:return E.red(t);case`WARNING`:return E.yellow(t);case`INFO`:return E.blue(E.dim(t));default:return t}}E.green(`✓`),E.red(`✖`),E.yellow(`⚠`),E.blue(`ℹ`);function Mt(e){T.intro(E.bgCyan(E.black(` ${e} `)))}function Nt(e){T.outro(e)}function Pt(e){T.isCancel(e)&&(T.cancel(`Operation cancelled.`),process.exit(0))}async function Ft(e){let t=await T.text(e);return Pt(t),t}async function It(e){let t=await T.select(e);return Pt(t),t}async function Lt(e){let t=await T.multiselect(e);return Pt(t),t}async function P(e){let t=await T.confirm(e);return Pt(t),t}function Rt(){return T.spinner()}const F=T.log,zt={kickjs:{pkg:`@forinda/kickjs`,peers:[`express`],description:`Unified framework: DI, decorators, routing, middleware`,core:!0},vite:{pkg:`@forinda/kickjs-vite`,peers:[`vite`],description:`Vite plugin: dev server, HMR, module discovery`,dev:!0,core:!0},cli:{pkg:`@forinda/kickjs-cli`,peers:[],description:`CLI tool and code generators`,dev:!0,core:!0},swagger:{pkg:`@forinda/kickjs-swagger`,peers:[],description:`OpenAPI spec + Swagger UI + ReDoc`},db:{pkg:`@forinda/kickjs-db`,peers:[],description:`kick/db core — schema DSL, migrations, KickDbClient, customType`},"db-pg":{pkg:`@forinda/kickjs-db-pg`,peers:[`pg`],description:`kick/db PostgreSQL dialect + adapter (pgDialect, pgAdapter)`},drizzle:{pkg:`@forinda/kickjs-drizzle`,peers:[`drizzle-orm`],description:`Drizzle ORM adapter + query builder`},prisma:{pkg:`@forinda/kickjs-prisma`,peers:[`@prisma/client`],description:`Prisma adapter + query builder`},ws:{pkg:`@forinda/kickjs-ws`,peers:[`socket.io`],description:`WebSocket with @WsController decorators`},devtools:{pkg:`@forinda/kickjs-devtools`,peers:[],description:`Development dashboard — routes, DI, metrics, health`,dev:!0},queue:{pkg:`@forinda/kickjs-queue`,peers:[],description:`Queue adapter (BullMQ/RabbitMQ/Kafka)`},"queue:bullmq":{pkg:`@forinda/kickjs-queue`,peers:[`bullmq`,`ioredis`],description:`Queue with BullMQ + Redis`},"queue:rabbitmq":{pkg:`@forinda/kickjs-queue`,peers:[`amqplib`],description:`Queue with RabbitMQ`},"queue:kafka":{pkg:`@forinda/kickjs-queue`,peers:[`kafkajs`],description:`Queue with Kafka`},mcp:{pkg:`@forinda/kickjs-mcp`,peers:[`@modelcontextprotocol/sdk`],description:`Model Context Protocol server — expose @Controller endpoints as AI tools`},testing:{pkg:`@forinda/kickjs-testing`,peers:[],description:`Test utilities and TestModule builder`,dev:!0}};function Bt(e,t=process.cwd()){let n=t;for(;;){if(r(v(n,e)))return n;let t=f(n);if(t===n)return null;n=t}}function Vt(){return Bt(`pnpm-lock.yaml`)?`pnpm`:Bt(`yarn.lock`)?`yarn`:Bt(`bun.lockb`)||Bt(`bun.lock`)?`bun`:Bt(`package-lock.json`)?`npm`:null}function Ht(){let e=process.cwd();for(;e;){let t=v(e,`package.json`);if(r(t))try{let e=JSON.parse(a(t,`utf-8`)).packageManager;if(typeof e==`string`){let t=e.split(`@`)[0];if(Ne.includes(t))return t}}catch{}let n=f(e);if(n===e)return null;e=n}return null}async function Ut(e){if(e&&Ne.includes(e))return{pm:e,source:`flag`};let t=await k(process.cwd());if(t?.packageManager&&Ne.includes(t.packageManager))return{pm:t.packageManager,source:`config`};let n=Ht();if(n)return{pm:n,source:`package.json`};let r=Vt();return r?{pm:r,source:`lockfile`}:{pm:`npm`,source:`default`}}async function Wt(e){let{pm:t}=await Ut(e);return t}function Gt(e=!1){let t=Object.entries(zt),n=Math.max(...t.map(([e])=>e.length)),r=t.filter(([,e])=>e.core),i=t.filter(([,e])=>!e.core),a=([e,t])=>{let r=e.padEnd(n+2),i=t.peers.length?` (+ ${t.peers.join(`, `)})`:``;return` ${r} ${t.description}${i}`};console.log(`
|
|
1406
|
+
Dependencies installed successfully!`)}catch{console.log(`\n Warning: ${r} install failed. Run it manually.`)}}try{let{runTypegen:e}=await Promise.resolve().then(()=>la);await e({cwd:s,allowDuplicates:!0,silent:!0})}catch{}if(e.initGit)try{S(`git init`,{cwd:s,stdio:`pipe`}),S(`git branch -M main`,{cwd:s,stdio:`pipe`}),S(`git add -A`,{cwd:s,stdio:`pipe`}),S(`git commit -m "chore: initial commit from kick new"`,{cwd:s,stdio:`pipe`}),c(`Git repository initialized`)}catch{c(`Warning: git init failed (git may not be installed)`)}console.log(`
|
|
1407
|
+
Project scaffolded successfully!`),console.log();let u=s!==process.cwd();c(`Next steps:`),u&&c(` cd ${t}`),e.installDeps||c(` ${r} install`);let d={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`};c(` ${d[i]??d.rest}`),c(` kick dev`),c(``),c(`Commands:`),c(` kick dev Start dev server with Vite HMR`),c(` kick build Production build via Vite`),c(` kick start Run production build`),c(``),c(`Generators:`),c(` kick g module <name> Full DDD module (controller, DTOs, use-cases, repo)`),c(` kick g scaffold <n> <f..> CRUD module from field definitions`),c(` kick g controller <name> Standalone controller`),c(` kick g service <name> @Service() class`),c(` kick g middleware <name> Express middleware`),c(` kick g guard <name> Route guard (auth, roles, etc.)`),c(` kick g adapter <name> AppAdapter with lifecycle hooks`),c(` kick g dto <name> Zod DTO schema`),i===`cqrs`&&c(` kick g job <name> Queue job processor`),c(` kick g config Generate kick.config.ts`),c(``),c(`Add packages:`),c(` kick add <pkg> Install a KickJS package + peers`),c(` kick add --list Show all available packages`),c(``),c(`Available: auth, swagger, drizzle, prisma, ws, queue, devtools, mcp, testing`),c(``)}const kt={GET:E.green,POST:E.cyan,PUT:E.yellow,PATCH:E.magenta,DELETE:E.red};function At(e){return(kt[e]??E.dim)(e.padEnd(7))}function jt(e){let t=`[${e}]`.padEnd(10);switch(e){case`CRITICAL`:return E.red(t);case`WARNING`:return E.yellow(t);case`INFO`:return E.blue(E.dim(t));default:return t}}E.green(`✓`),E.red(`✖`),E.yellow(`⚠`),E.blue(`ℹ`);function Mt(e){T.intro(E.bgCyan(E.black(` ${e} `)))}function Nt(e){T.outro(e)}function Pt(e){T.isCancel(e)&&(T.cancel(`Operation cancelled.`),process.exit(0))}async function Ft(e){let t=await T.text(e);return Pt(t),t}async function It(e){let t=await T.select(e);return Pt(t),t}async function Lt(e){let t=await T.multiselect(e);return Pt(t),t}async function P(e){let t=await T.confirm(e);return Pt(t),t}function Rt(){return T.spinner()}const F=T.log,zt={kickjs:{pkg:`@forinda/kickjs`,peers:[`express`],description:`Unified framework: DI, decorators, routing, middleware`,core:!0},vite:{pkg:`@forinda/kickjs-vite`,peers:[`vite`],description:`Vite plugin: dev server, HMR, module discovery`,dev:!0,core:!0},cli:{pkg:`@forinda/kickjs-cli`,peers:[],description:`CLI tool and code generators`,dev:!0,core:!0},swagger:{pkg:`@forinda/kickjs-swagger`,peers:[],description:`OpenAPI spec + Swagger UI + ReDoc`},db:{pkg:`@forinda/kickjs-db`,peers:[],description:`kick/db core — schema DSL, migrations, KickDbClient, customType`},"db-pg":{pkg:`@forinda/kickjs-db-pg`,peers:[`pg`],description:`kick/db PostgreSQL dialect + adapter (pgDialect, pgAdapter)`},drizzle:{pkg:`@forinda/kickjs-drizzle`,peers:[`drizzle-orm`],description:`Drizzle ORM adapter + query builder`},prisma:{pkg:`@forinda/kickjs-prisma`,peers:[`@prisma/client`],description:`Prisma adapter + query builder`},ws:{pkg:`@forinda/kickjs-ws`,peers:[`socket.io`],description:`WebSocket with @WsController decorators`},devtools:{pkg:`@forinda/kickjs-devtools`,peers:[],description:`Development dashboard — routes, DI, metrics, health`,dev:!0},queue:{pkg:`@forinda/kickjs-queue`,peers:[],description:`Queue adapter (BullMQ/RabbitMQ/Kafka)`},"queue:bullmq":{pkg:`@forinda/kickjs-queue`,peers:[`bullmq`,`ioredis`],description:`Queue with BullMQ + Redis`},"queue:rabbitmq":{pkg:`@forinda/kickjs-queue`,peers:[`amqplib`],description:`Queue with RabbitMQ`},"queue:kafka":{pkg:`@forinda/kickjs-queue`,peers:[`kafkajs`],description:`Queue with Kafka`},"queue:redis-pubsub":{pkg:`@forinda/kickjs-queue`,peers:[`ioredis`],description:`Lightweight pub/sub via Redis (no persistence)`},mcp:{pkg:`@forinda/kickjs-mcp`,peers:[`@modelcontextprotocol/sdk`],description:`Model Context Protocol server — expose @Controller endpoints as AI tools`},testing:{pkg:`@forinda/kickjs-testing`,peers:[],description:`Test utilities and TestModule builder`,dev:!0}};function Bt(e,t=process.cwd()){let n=t;for(;;){if(r(v(n,e)))return n;let t=f(n);if(t===n)return null;n=t}}function Vt(){return Bt(`pnpm-lock.yaml`)?`pnpm`:Bt(`yarn.lock`)?`yarn`:Bt(`bun.lockb`)||Bt(`bun.lock`)?`bun`:Bt(`package-lock.json`)?`npm`:null}function Ht(){let e=process.cwd();for(;e;){let t=v(e,`package.json`);if(r(t))try{let e=JSON.parse(a(t,`utf-8`)).packageManager;if(typeof e==`string`){let t=e.split(`@`)[0];if(Ne.includes(t))return t}}catch{}let n=f(e);if(n===e)return null;e=n}return null}async function Ut(e){if(e&&Ne.includes(e))return{pm:e,source:`flag`};let t=await k(process.cwd());if(t?.packageManager&&Ne.includes(t.packageManager))return{pm:t.packageManager,source:`config`};let n=Ht();if(n)return{pm:n,source:`package.json`};let r=Vt();return r?{pm:r,source:`lockfile`}:{pm:`npm`,source:`default`}}async function Wt(e){let{pm:t}=await Ut(e);return t}function Gt(e=!1){let t=Object.entries(zt),n=Math.max(...t.map(([e])=>e.length)),r=t.filter(([,e])=>e.core),i=t.filter(([,e])=>!e.core),a=([e,t])=>{let r=e.padEnd(n+2),i=t.peers.length?` (+ ${t.peers.join(`, `)})`:``;return` ${r} ${t.description}${i}`};console.log(`
|
|
1408
1408
|
Core packages (always installed by \`kick new\`):
|
|
1409
1409
|
`);for(let e of r)console.log(a(e));if(e){console.log(`
|
|
1410
1410
|
Optional packages (add as needed):
|
|
1411
1411
|
`);for(let e of i)console.log(a(e))}else console.log(`\n Plus ${i.length} optional packages (auth, swagger, db, queue, …).`),console.log(" Run `kick add --list --all` for the full catalog.");console.log(`
|
|
1412
1412
|
Usage: kick add auth drizzle swagger`),console.log(` kick add queue:bullmq`),console.log()}function Kt(e){e.command(`list`).alias(`ls`).description(`List KickJS packages (core only; pair with --all for the full catalog)`).option(`--all`,`Include the full optional catalog`).action(e=>{Gt(!!e.all)})}function qt(e){e.command(`add [packages...]`).description(`Add KickJS packages with their required dependencies`).option(`--pm <manager>`,`Package manager override`).option(`-D, --dev`,`Install as dev dependency`).option(`--list`,`List packages (core only by default; pair with --all)`).option(`--all`,`When listing, include the full optional catalog`).action(async(e,t)=>{if(t.list||e.length===0){Gt(!!t.all);return}let{pm:n,source:r}=await Ut(t.pm);console.log(`\n Using ${n} (resolved from ${r})`);let i=t.dev,a=new Set,o=new Set,s=[];for(let t of e){let e=zt[t];if(!e){s.push(t);continue}let n=i||e.dev?o:a;n.add(e.pkg);for(let t of e.peers)n.add(t)}if(!(s.length>0&&(console.log(`\n Unknown packages: ${s.join(`, `)}`),console.log(` Run "kick add --list" to see available packages.
|
|
1413
1413
|
`),a.size===0&&o.size===0))){if(a.size>0){let e=Array.from(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{S(t,{stdio:`inherit`})}catch{console.log(`\n Installation failed. Run manually:\n ${t}\n`)}}if(o.size>0){let e=Array.from(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{S(t,{stdio:`inherit`})}catch{console.log(`\n Installation failed. Run manually:\n ${t}\n`)}}console.log(` Done!
|
|
1414
|
-
`)}})}const Jt=[{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 Yt(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 | ddd | cqrs | minimal`).option(`-r, --repo <type>`,`Default repository: prisma | drizzle | inmemory | custom`).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)=>{Mt(`KickJS — Create a new project`);let n=!!(t.yes||t.nonInteractive);e||=n?`my-api`:await Ft({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)F.warn(`Clearing existing files in ${i}`);else if(n){F.warn(`Directory "${e}" is not empty. Pass --force to clear it.`),Nt(`Aborted.`);return}else{F.warn(`Directory "${e}" is not empty:`);let t=r.slice(0,5);for(let e of t)F.message(` - ${e}`);if(r.length>5&&F.message(` ... and ${r.length-5} more`),!await P({message:E.red(`Remove all existing files and proceed?`),initialValue:!1})){Nt(`Aborted.`);return}}for(let e of r)s(v(i,e),{recursive:!0,force:!0})}}let a=t.template;a||=n?`minimal`:await It({message:`Project template`,options:[{value:`rest`,label:`REST API`,hint:`Express + Swagger`},{value:`ddd`,label:`DDD`,hint:`Domain-Driven Design modules`},{value:`cqrs`,label:`CQRS`,hint:`Commands, Queries, Events + WS/Queue`},{value:`minimal`,label:`Minimal`,hint:`bare Express`}]});let c=t.pm;c||=n?await Wt(void 0):await It({message:`Package manager`,options:[{value:`pnpm`,label:`pnpm`},{value:`npm`,label:`npm`},{value:`yarn`,label:`yarn`},{value:`bun`,label:`bun`}]});let l=t.repo;l||(n?l=`inmemory`:(l=await It({message:`Default repository/ORM`,options:[{value:`prisma`,label:`Prisma`},{value:`drizzle`,label:`Drizzle`},{value:`inmemory`,label:`In-Memory`},{value:`custom`,label:`Custom`,hint:`specify later`}]}),l===`custom`&&(l=await Ft({message:`Custom repository name`,defaultValue:`custom`}))));let u;if(t.packages!==void 0){let e=t.packages.trim().toLowerCase();u=e===``||e===`none`||e===`false`?[]:t.packages.split(`,`).map(e=>e.trim()).filter(Boolean)}else u=n?[]:await Lt({message:`Select packages to include`,options:[...Jt],required:!1});let f;f=t.git===void 0?n?!0:await P({message:`Initialize git repository?`,initialValue:!0}):t.git;let p;p=t.install===void 0?n?!0:await P({message:`Install dependencies?`,initialValue:!0}):t.install,await Ot({name:e,directory:i,packageManager:c,initGit:f,installDeps:p,template:a,defaultRepo:l,packages:u}),Nt(`Done! Next steps: ${E.cyan(`cd ${e} && ${c} dev`)}`)})}function I(e){return e.replace(/[-_\s]+(.)?/g,(e,t)=>t?t.toUpperCase():``).replace(/^(.)/,e=>e.toUpperCase())}function L(e){let t=I(e);return t.charAt(0).toLowerCase()+t.slice(1)}function R(e){return e.replace(/([a-z])([A-Z])/g,`$1-$2`).replace(/[\s_]+/g,`-`).toLowerCase()}function z(e){return de.plural(e)}function Xt(e){return de.plural(e)}
|
|
1414
|
+
`)}})}const Jt=[{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 Yt(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 | ddd | cqrs | minimal`).option(`-r, --repo <type>`,`Default repository: prisma | drizzle | inmemory | custom`).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)=>{Mt(`KickJS — Create a new project`);let n=!!(t.yes||t.nonInteractive);e||=n?`my-api`:await Ft({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)F.warn(`Clearing existing files in ${i}`);else if(n){F.warn(`Directory "${e}" is not empty. Pass --force to clear it.`),Nt(`Aborted.`);return}else{F.warn(`Directory "${e}" is not empty:`);let t=r.slice(0,5);for(let e of t)F.message(` - ${e}`);if(r.length>5&&F.message(` ... and ${r.length-5} more`),!await P({message:E.red(`Remove all existing files and proceed?`),initialValue:!1})){Nt(`Aborted.`);return}}for(let e of r)s(v(i,e),{recursive:!0,force:!0})}}let a=t.template;a||=n?`minimal`:await It({message:`Project template`,options:[{value:`rest`,label:`REST API`,hint:`Express + Swagger`},{value:`ddd`,label:`DDD`,hint:`Domain-Driven Design modules`},{value:`cqrs`,label:`CQRS`,hint:`Commands, Queries, Events + WS/Queue`},{value:`minimal`,label:`Minimal`,hint:`bare Express`}]});let c=t.pm;c||=n?await Wt(void 0):await It({message:`Package manager`,options:[{value:`pnpm`,label:`pnpm`},{value:`npm`,label:`npm`},{value:`yarn`,label:`yarn`},{value:`bun`,label:`bun`}]});let l=t.repo;l||(n?l=`inmemory`:(l=await It({message:`Default repository/ORM`,options:[{value:`prisma`,label:`Prisma`},{value:`drizzle`,label:`Drizzle`},{value:`inmemory`,label:`In-Memory`},{value:`custom`,label:`Custom`,hint:`specify later`}]}),l===`custom`&&(l=await Ft({message:`Custom repository name`,defaultValue:`custom`}))));let u;if(t.packages!==void 0){let e=t.packages.trim().toLowerCase();u=e===``||e===`none`||e===`false`?[]:t.packages.split(`,`).map(e=>e.trim()).filter(Boolean)}else u=n?[]:await Lt({message:`Select packages to include`,options:[...Jt],required:!1});let f;f=t.git===void 0?n?!0:await P({message:`Initialize git repository?`,initialValue:!0}):t.git;let p;p=t.install===void 0?n?!0:await P({message:`Install dependencies?`,initialValue:!0}):t.install,await Ot({name:e,directory:i,packageManager:c,initGit:f,installDeps:p,template:a,defaultRepo:l,packages:u}),Nt(`Done! Next steps: ${E.cyan(`cd ${e} && ${c} dev`)}`)})}function I(e){return e.replace(/[-_\s]+(.)?/g,(e,t)=>t?t.toUpperCase():``).replace(/^(.)/,e=>e.toUpperCase())}function L(e){let t=I(e);return t.charAt(0).toLowerCase()+t.slice(1)}function R(e){return e.replace(/([a-z])([A-Z])/g,`$1-$2`).replace(/[\s_]+/g,`-`).toLowerCase()}function z(e){return de.plural(e)}function Xt(e){return de.plural(e)}var Zt=D({findProjectRoot:()=>$t});const Qt=[`kick.config.ts`,`kick.config.js`,`kick.config.mjs`,`kick.config.json`];function $t(e=process.cwd()){let t=v(e),{root:n}=g(t),i=null,a=t;for(;;){for(let e of Qt)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 en(e){return R(e).replace(/-/g,`_`)}function tn(e){let t=e.cwd??process.cwd(),n=e.projectRoot??$t(t),r=e.pluralize??!0,i=I(e.name),a=L(e.name),o=R(e.name),s=en(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=z(o);c.pluralKebab=e,c.pluralPascal=I(e),c.pluralCamel=L(e)}return c}function nn(e,t){return v(e.cwd,t)}async function rn(e){return import(x(e).href)}const an=new Map;async function on(e){let t=an.get(e);if(t)return t;let n=sn(e);return an.set(e,n),n}async function sn(t){let n=v(t,`package.json`);if(!r(n))return{generators:[],loaded:[],failed:[]};let i=cn(JSON.parse(await C(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 C(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 rn(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(!ln(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 cn(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 ln(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.name==`string`&&typeof t.files==`function`}async function un(e,t=[]){let n=e.cwd??process.cwd(),r=t.find(t=>t.spec.name===e.generatorName);if(r)return pn(r.spec,r.source,e,n);let i=fn(await on(n),e.generatorName);return i?pn(i.spec,i.source,e,n):null}async function dn(e,t=[]){let n=await on(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 fn(e,t){return e.generators.find(e=>e.spec.name===t)}async function pn(e,t,n,r){let i=tn({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=nn(i,e.path);await M(t,e.content),o.push(t)}return{files:o,source:t}}function B(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}const mn={inmemory:`in-memory`,drizzle:`Drizzle`,prisma:`Prisma`};function hn(e){return e.charAt(0).toUpperCase()+e.slice(1).replace(/-([a-z])/g,(e,t)=>t.toUpperCase())}function gn(e){return e.replace(/([a-z])([A-Z])/g,`$1-$2`).toLowerCase()}function _n(e){return mn[e]??hn(e)}function vn(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]??`${hn(n)}${e}Repository`,repoFile:i[n]??`${gn(n)}-${t}`}}function yn(e){return e??`define`}function bn(e){let{pascal:t,kebab:n,plural:r=``,repo:i,style:a}=e,{repoClass:o,repoFile:s}=vn(t,n,i),c=yn(a),l=`/**
|
|
1415
1415
|
* ${t} Module
|
|
1416
1416
|
*
|
|
1417
1417
|
* Self-contained feature module following Domain-Driven Design (DDD).
|
|
@@ -1421,7 +1421,7 @@ in \`.agents/COPILOT.local.md\`.
|
|
|
1421
1421
|
* presentation/ — HTTP controllers (entry points)
|
|
1422
1422
|
* application/ — Use cases (orchestration) and DTOs (validation)
|
|
1423
1423
|
* domain/ — Entities, value objects, repository interfaces, domain services
|
|
1424
|
-
* infrastructure/ — Repository implementations (currently ${
|
|
1424
|
+
* infrastructure/ — Repository implementations (currently ${_n(i)})
|
|
1425
1425
|
*/`,u=`import { ${t.toUpperCase()}_REPOSITORY } from './domain/repositories/${n}.repository'
|
|
1426
1426
|
import { ${o} } from './infrastructure/repositories/${s}.repository'
|
|
1427
1427
|
import { ${t}Controller } from './presentation/${n}.controller'
|
|
@@ -1455,7 +1455,7 @@ export class ${t}Module implements AppModule {
|
|
|
1455
1455
|
/**
|
|
1456
1456
|
* Register module dependencies in the DI container.
|
|
1457
1457
|
* Bind repository interface tokens to their implementations here.
|
|
1458
|
-
* Currently wired to ${
|
|
1458
|
+
* Currently wired to ${_n(i)}. To swap implementations, change the factory target.
|
|
1459
1459
|
*/
|
|
1460
1460
|
register(container: Container): void {
|
|
1461
1461
|
container.registerFactory(${t.toUpperCase()}_REPOSITORY, () =>
|
|
@@ -1481,7 +1481,7 @@ export const ${t}Module = defineModule({
|
|
|
1481
1481
|
/**
|
|
1482
1482
|
* Register module dependencies in the DI container.
|
|
1483
1483
|
* Bind repository interface tokens to their implementations here.
|
|
1484
|
-
* Currently wired to ${
|
|
1484
|
+
* Currently wired to ${_n(i)}. To swap implementations, change the factory target.
|
|
1485
1485
|
*/
|
|
1486
1486
|
register(container) {
|
|
1487
1487
|
container.registerFactory(${t.toUpperCase()}_REPOSITORY, () =>
|
|
@@ -1498,7 +1498,7 @@ ${d}
|
|
|
1498
1498
|
},
|
|
1499
1499
|
}),
|
|
1500
1500
|
})
|
|
1501
|
-
`}function
|
|
1501
|
+
`}function xn(e){let{pascal:t,kebab:n,plural:r=``,repo:i,style:a}=e,{repoClass:o,repoFile:s}=vn(t,n,i),c=yn(a),l=`/**
|
|
1502
1502
|
* ${t} Module
|
|
1503
1503
|
*
|
|
1504
1504
|
* REST module with a flat folder structure.
|
|
@@ -1570,7 +1570,7 @@ ${d}
|
|
|
1570
1570
|
},
|
|
1571
1571
|
}),
|
|
1572
1572
|
})
|
|
1573
|
-
`}function
|
|
1573
|
+
`}function Sn(e){let{pascal:t,kebab:n,plural:r=``,style:i}=e,a=yn(i),o=` /**
|
|
1574
1574
|
* Declare HTTP routes. Return value shape:
|
|
1575
1575
|
*
|
|
1576
1576
|
* - \`path\` — URL prefix for this route set.
|
|
@@ -1610,7 +1610,7 @@ ${o}
|
|
|
1610
1610
|
},
|
|
1611
1611
|
}),
|
|
1612
1612
|
})
|
|
1613
|
-
`}function
|
|
1613
|
+
`}function Cn(e){let{pascal:t,kebab:n,plural:r=``,pluralPascal:i=``}=e;return`import { Controller, Get, Post, Put, Delete, Autowired, ApiQueryParams, type Ctx } from '@forinda/kickjs'
|
|
1614
1614
|
import { ApiTags } from '@forinda/kickjs-swagger'
|
|
1615
1615
|
import { Create${t}UseCase } from '../application/use-cases/create-${n}.use-case'
|
|
1616
1616
|
import { Get${t}UseCase } from '../application/use-cases/get-${n}.use-case'
|
|
@@ -1673,7 +1673,7 @@ export class ${t}Controller {
|
|
|
1673
1673
|
ctx.noContent()
|
|
1674
1674
|
}
|
|
1675
1675
|
}
|
|
1676
|
-
`}function
|
|
1676
|
+
`}function wn(e){let{pascal:t,kebab:n}=e,r=t.charAt(0).toLowerCase()+t.slice(1);return`import { Controller, Get, Post, Put, Delete, Autowired, ApiQueryParams, type Ctx } from '@forinda/kickjs'
|
|
1677
1677
|
import { ApiTags } from '@forinda/kickjs-swagger'
|
|
1678
1678
|
import { ${t}Service } from './${n}.service'
|
|
1679
1679
|
import { create${t}Schema } from './dtos/create-${n}.dto'
|
|
@@ -1728,14 +1728,14 @@ export class ${t}Controller {
|
|
|
1728
1728
|
ctx.noContent()
|
|
1729
1729
|
}
|
|
1730
1730
|
}
|
|
1731
|
-
`}function
|
|
1731
|
+
`}function Tn(e){let{pascal:t}=e;return`import type { QueryParamsConfig } from '@forinda/kickjs'
|
|
1732
1732
|
|
|
1733
1733
|
export const ${t.toUpperCase()}_QUERY_CONFIG: QueryParamsConfig = {
|
|
1734
1734
|
filterable: ['name'],
|
|
1735
1735
|
sortable: ['name', 'createdAt'],
|
|
1736
1736
|
searchable: ['name'],
|
|
1737
1737
|
}
|
|
1738
|
-
`}function
|
|
1738
|
+
`}function En(e){let{pascal:t}=e;return`import { z } from 'zod'
|
|
1739
1739
|
|
|
1740
1740
|
/**
|
|
1741
1741
|
* Create ${t} DTO — Zod schema for validating POST request bodies.
|
|
@@ -1751,20 +1751,20 @@ export const create${t}Schema = z.object({
|
|
|
1751
1751
|
})
|
|
1752
1752
|
|
|
1753
1753
|
export type Create${t}DTO = z.infer<typeof create${t}Schema>
|
|
1754
|
-
`}function
|
|
1754
|
+
`}function Dn(e){let{pascal:t}=e;return`import { z } from 'zod'
|
|
1755
1755
|
|
|
1756
1756
|
export const update${t}Schema = z.object({
|
|
1757
1757
|
name: z.string().min(1).max(200).optional(),
|
|
1758
1758
|
})
|
|
1759
1759
|
|
|
1760
1760
|
export type Update${t}DTO = z.infer<typeof update${t}Schema>
|
|
1761
|
-
`}function
|
|
1761
|
+
`}function On(e){let{pascal:t}=e;return`export interface ${t}ResponseDTO {
|
|
1762
1762
|
id: string
|
|
1763
1763
|
name: string
|
|
1764
1764
|
createdAt: string
|
|
1765
1765
|
updatedAt: string
|
|
1766
1766
|
}
|
|
1767
|
-
`}function
|
|
1767
|
+
`}function kn(e){let{pascal:t,kebab:n,plural:r=``,pluralPascal:i=``}=e;return[{file:`create-${n}.use-case.ts`,content:`/**
|
|
1768
1768
|
* Create ${t} Use Case
|
|
1769
1769
|
*
|
|
1770
1770
|
* Application layer — orchestrates a single business operation.
|
|
@@ -1842,7 +1842,7 @@ export class Delete${t}UseCase {
|
|
|
1842
1842
|
await this.repo.delete(id)
|
|
1843
1843
|
}
|
|
1844
1844
|
}
|
|
1845
|
-
`}]}function
|
|
1845
|
+
`}]}function An(e){let{pascal:t,kebab:n,dtoPrefix:r=`../../application/dtos`,tokenScope:i=`app`}=e;return`/**
|
|
1846
1846
|
* ${t} Repository Interface
|
|
1847
1847
|
*
|
|
1848
1848
|
* Defines the contract for data access.
|
|
@@ -1937,7 +1937,7 @@ export class InMemory${t}Repository implements I${t}Repository {
|
|
|
1937
1937
|
this.store.delete(id)
|
|
1938
1938
|
}
|
|
1939
1939
|
}
|
|
1940
|
-
`}function
|
|
1940
|
+
`}function jn(e){let{pascal:t,kebab:n,repoType:r=``,repoPrefix:i=`../../domain/repositories`,dtoPrefix:a=`../../application/dtos`}=e,o=r.charAt(0).toUpperCase()+r.slice(1).replace(/-([a-z])/g,(e,t)=>t.toUpperCase());return`/**
|
|
1941
1941
|
* ${o} ${t} Repository
|
|
1942
1942
|
*
|
|
1943
1943
|
* Stub implementation for a custom '${r}' repository.
|
|
@@ -2006,7 +2006,7 @@ export class ${o}${t}Repository implements I${t}Repository {
|
|
|
2006
2006
|
this.store.delete(id)
|
|
2007
2007
|
}
|
|
2008
2008
|
}
|
|
2009
|
-
`}function
|
|
2009
|
+
`}function Mn(e){let{pascal:t,kebab:n}=e;return`/**
|
|
2010
2010
|
* ${t} Domain Service
|
|
2011
2011
|
*
|
|
2012
2012
|
* Domain layer — contains business rules that don't belong to a single entity.
|
|
@@ -2029,7 +2029,7 @@ export class ${t}DomainService {
|
|
|
2029
2029
|
}
|
|
2030
2030
|
}
|
|
2031
2031
|
}
|
|
2032
|
-
`}function
|
|
2032
|
+
`}function Nn(e){let{pascal:t,kebab:n}=e;return`/**
|
|
2033
2033
|
* ${t} Entity
|
|
2034
2034
|
*
|
|
2035
2035
|
* Domain layer — the core business object.
|
|
@@ -2098,7 +2098,7 @@ export class ${t} {
|
|
|
2098
2098
|
}
|
|
2099
2099
|
}
|
|
2100
2100
|
}
|
|
2101
|
-
`}function
|
|
2101
|
+
`}function Pn(e){let{pascal:t}=e;return`/**
|
|
2102
2102
|
* ${t} ID Value Object
|
|
2103
2103
|
*
|
|
2104
2104
|
* Domain layer — wraps a primitive ID with type safety and validation.
|
|
@@ -2132,7 +2132,7 @@ export class ${t}Id {
|
|
|
2132
2132
|
return this.value === other.value
|
|
2133
2133
|
}
|
|
2134
2134
|
}
|
|
2135
|
-
`}function
|
|
2135
|
+
`}function Fn(e){let{pascal:t,kebab:n,plural:r=``}=e;return`import { describe, it, expect, beforeEach } from 'vitest'
|
|
2136
2136
|
import { Container } from '@forinda/kickjs'
|
|
2137
2137
|
|
|
2138
2138
|
describe('${t}Controller', () => {
|
|
@@ -2184,7 +2184,7 @@ describe('${t}Controller', () => {
|
|
|
2184
2184
|
})
|
|
2185
2185
|
})
|
|
2186
2186
|
})
|
|
2187
|
-
`}function
|
|
2187
|
+
`}function In(e){let{pascal:t,kebab:n,plural:r=``,repoPrefix:i=`../infrastructure/repositories/in-memory-${n}.repository`}=e;return`import { describe, it, expect, beforeEach } from 'vitest'
|
|
2188
2188
|
import { InMemory${t}Repository } from '${i}'
|
|
2189
2189
|
|
|
2190
2190
|
describe('InMemory${t}Repository', () => {
|
|
@@ -2246,7 +2246,7 @@ describe('InMemory${t}Repository', () => {
|
|
|
2246
2246
|
expect(found).toBeNull()
|
|
2247
2247
|
})
|
|
2248
2248
|
})
|
|
2249
|
-
`}function
|
|
2249
|
+
`}function Ln(e){let{pascal:t,kebab:n}=e;return`import { Service, Inject, HttpException } from '@forinda/kickjs'
|
|
2250
2250
|
import type { ParsedQuery } from '@forinda/kickjs'
|
|
2251
2251
|
import { ${t.toUpperCase()}_REPOSITORY, type I${t}Repository } from './${n}.repository'
|
|
2252
2252
|
import type { ${t}ResponseDTO } from './dtos/${n}-response.dto'
|
|
@@ -2283,14 +2283,14 @@ export class ${t}Service {
|
|
|
2283
2283
|
await this.repo.delete(id)
|
|
2284
2284
|
}
|
|
2285
2285
|
}
|
|
2286
|
-
`}function
|
|
2286
|
+
`}function Rn(e){let{pascal:t}=e;return`import type { QueryFieldConfig } from '@forinda/kickjs'
|
|
2287
2287
|
|
|
2288
2288
|
export const ${t.toUpperCase()}_QUERY_CONFIG: QueryFieldConfig = {
|
|
2289
2289
|
filterable: ['name'],
|
|
2290
2290
|
sortable: ['name', 'createdAt'],
|
|
2291
2291
|
searchable: ['name'],
|
|
2292
2292
|
}
|
|
2293
|
-
`}function
|
|
2293
|
+
`}function zn(e){let{pascal:t,kebab:n,plural:r=``,repo:i,style:a}=e,o={inmemory:`InMemory${t}Repository`,drizzle:`Drizzle${t}Repository`,prisma:`Prisma${t}Repository`},s={inmemory:`in-memory-${n}`,drizzle:`drizzle-${n}`,prisma:`prisma-${n}`},c=o[i]??o.inmemory,l=s[i]??s.inmemory,u=a??`define`,d=`/**
|
|
2294
2294
|
* ${t} Module — CQRS Pattern
|
|
2295
2295
|
*
|
|
2296
2296
|
* Separates read (queries) and write (commands) operations.
|
|
@@ -2369,7 +2369,7 @@ ${p}
|
|
|
2369
2369
|
},
|
|
2370
2370
|
}),
|
|
2371
2371
|
})
|
|
2372
|
-
`}function
|
|
2372
|
+
`}function Bn(e){let{pascal:t,kebab:n,plural:r=``,pluralPascal:i=``}=e;return`import { Controller, Get, Post, Put, Delete, Autowired, ApiQueryParams, type Ctx } from '@forinda/kickjs'
|
|
2373
2373
|
import { ApiTags } from '@forinda/kickjs-swagger'
|
|
2374
2374
|
import { Create${t}Command } from './commands/create-${n}.command'
|
|
2375
2375
|
import { Update${t}Command } from './commands/update-${n}.command'
|
|
@@ -2432,7 +2432,7 @@ export class ${t}Controller {
|
|
|
2432
2432
|
ctx.noContent()
|
|
2433
2433
|
}
|
|
2434
2434
|
}
|
|
2435
|
-
`}function
|
|
2435
|
+
`}function Vn(e){let{pascal:t,kebab:n}=e;return[{file:`create-${n}.command.ts`,content:`import { Service, Inject } from '@forinda/kickjs'
|
|
2436
2436
|
import { ${t.toUpperCase()}_REPOSITORY, type I${t}Repository } from '../${n}.repository'
|
|
2437
2437
|
import type { Create${t}DTO } from '../dtos/create-${n}.dto'
|
|
2438
2438
|
import type { ${t}ResponseDTO } from '../dtos/${n}-response.dto'
|
|
@@ -2486,7 +2486,7 @@ export class Delete${t}Command {
|
|
|
2486
2486
|
this.events.emit('${n}.deleted', { id })
|
|
2487
2487
|
}
|
|
2488
2488
|
}
|
|
2489
|
-
`}]}function
|
|
2489
|
+
`}]}function Hn(e){let{pascal:t,kebab:n,plural:r=``,pluralPascal:i=``}=e;return[{file:`get-${n}.query.ts`,content:`import { Service, Inject } from '@forinda/kickjs'
|
|
2490
2490
|
import { ${t.toUpperCase()}_REPOSITORY, type I${t}Repository } from '../${n}.repository'
|
|
2491
2491
|
import type { ${t}ResponseDTO } from '../dtos/${n}-response.dto'
|
|
2492
2492
|
|
|
@@ -2514,7 +2514,7 @@ export class List${i}Query {
|
|
|
2514
2514
|
return this.repo.findPaginated(parsed)
|
|
2515
2515
|
}
|
|
2516
2516
|
}
|
|
2517
|
-
`}]}function
|
|
2517
|
+
`}]}function Un(e){let{pascal:t,kebab:n}=e;return[{file:`${n}.events.ts`,content:`import { Service } from '@forinda/kickjs'
|
|
2518
2518
|
import { EventEmitter } from 'node:events'
|
|
2519
2519
|
import type { ${t}ResponseDTO } from '../dtos/${n}-response.dto'
|
|
2520
2520
|
|
|
@@ -2600,7 +2600,7 @@ export class On${t}ChangeHandler {
|
|
|
2600
2600
|
})
|
|
2601
2601
|
}
|
|
2602
2602
|
}
|
|
2603
|
-
`}]}function
|
|
2603
|
+
`}]}function Wn(e){let{pascal:t,kebab:n,repoPrefix:r=`../../domain/repositories`,dtoPrefix:i=`../../application/dtos`}=e;return`/**
|
|
2604
2604
|
* Drizzle ${t} Repository
|
|
2605
2605
|
*
|
|
2606
2606
|
* Implements the repository interface using Drizzle ORM.
|
|
@@ -2682,7 +2682,7 @@ export class Drizzle${t}Repository implements I${t}Repository {
|
|
|
2682
2682
|
throw new Error('Drizzle ${t} repository not yet implemented')
|
|
2683
2683
|
}
|
|
2684
2684
|
}
|
|
2685
|
-
`}function
|
|
2685
|
+
`}function Gn(e){let{pascal:t,kebab:n}=e;return`import type { DrizzleQueryParamsConfig } from '@forinda/kickjs-drizzle'
|
|
2686
2686
|
// TODO: Import your schema table and reference actual columns for type safety
|
|
2687
2687
|
// import { ${n}s } from '@/db/schema'
|
|
2688
2688
|
|
|
@@ -2700,7 +2700,7 @@ export const ${t.toUpperCase()}_QUERY_CONFIG: DrizzleQueryParamsConfig = {
|
|
|
2700
2700
|
// ${n}s.name,
|
|
2701
2701
|
],
|
|
2702
2702
|
}
|
|
2703
|
-
`}function
|
|
2703
|
+
`}function Kn(e){let{pascal:t,kebab:n,repoPrefix:r=`../../domain/repositories`,dtoPrefix:i=`../../application/dtos`}=e,a=n.replace(/-([a-z])/g,(e,t)=>t.toUpperCase());return`/**
|
|
2704
2704
|
* Prisma ${t} Repository
|
|
2705
2705
|
*
|
|
2706
2706
|
* Implements the repository interface using Prisma Client.
|
|
@@ -2758,7 +2758,7 @@ export class Prisma${t}Repository implements I${t}Repository {
|
|
|
2758
2758
|
await this.prisma.${a}.deleteMany({ where: { id } })
|
|
2759
2759
|
}
|
|
2760
2760
|
}
|
|
2761
|
-
`}async function
|
|
2761
|
+
`}async function qn(e){let{pascal:t,kebab:n,plural:r,style:i,write:a}=e;await a(`${n}.module.ts`,Sn({pascal:t,kebab:n,plural:r,style:i})),await a(`${n}.controller.ts`,`import { Controller, Get, type Ctx } from '@forinda/kickjs'
|
|
2762
2762
|
|
|
2763
2763
|
// \`Ctx<KickRoutes.${t}Controller['<method>']>\` is generated by
|
|
2764
2764
|
// \`kick typegen\` (auto-run on \`kick dev\`).
|
|
@@ -2770,7 +2770,7 @@ export class ${t}Controller {
|
|
|
2770
2770
|
ctx.json({ message: '${t} list' })
|
|
2771
2771
|
}
|
|
2772
2772
|
}
|
|
2773
|
-
`)}async function
|
|
2773
|
+
`)}async function Jn(e){let{pascal:t,kebab:n,plural:r,pluralPascal:i,repo:a,noTests:o,prismaClientPath:s,tokenScope:c,style:l,write:u}=e;await u(`${n}.module.ts`,xn({pascal:t,kebab:n,plural:r,repo:a,style:l})),await u(`${n}.constants.ts`,Rn({pascal:t,kebab:n})),await u(`${n}.controller.ts`,wn({pascal:t,kebab:n,plural:r,pluralPascal:i})),await u(`${n}.service.ts`,Ln({pascal:t,kebab:n})),await u(`dtos/create-${n}.dto.ts`,En({pascal:t,kebab:n})),await u(`dtos/update-${n}.dto.ts`,Dn({pascal:t,kebab:n})),await u(`dtos/${n}-response.dto.ts`,On({pascal:t,kebab:n})),await u(`${n}.repository.ts`,An({pascal:t,kebab:n,dtoPrefix:`./dtos`,tokenScope:c}));let d={inmemory:`in-memory-${n}`,drizzle:`drizzle-${n}`,prisma:`prisma-${n}`},f={inmemory:()=>V({pascal:t,kebab:n,repoPrefix:`.`,dtoPrefix:`./dtos`}),drizzle:()=>Wn({pascal:t,kebab:n,repoPrefix:`.`,dtoPrefix:`./dtos`}),prisma:()=>Kn({pascal:t,kebab:n,repoPrefix:`.`,dtoPrefix:`./dtos`,prismaClientPath:s})},p=d[a]??`${R(a)}-${n}`,m=f[a]??(()=>jn({pascal:t,kebab:n,repoType:a,repoPrefix:`.`,dtoPrefix:`./dtos`}));await u(`${p}.repository.ts`,m()),o||(a!==`inmemory`&&await u(`in-memory-${n}.repository.ts`,V({pascal:t,kebab:n,repoPrefix:`.`,dtoPrefix:`./dtos`})),await u(`__tests__/${n}.controller.test.ts`,Fn({pascal:t,kebab:n,plural:r})),await u(`__tests__/${n}.repository.test.ts`,In({pascal:t,kebab:n,plural:r,repoPrefix:`../${d.inmemory??`in-memory-${n}`}.repository`})))}async function Yn(e){let{pascal:t,kebab:n,plural:r,pluralPascal:i,repo:a,noTests:o,prismaClientPath:s,tokenScope:c,style:l,write:u}=e;await u(`${n}.module.ts`,zn({pascal:t,kebab:n,plural:r,repo:a,style:l})),await u(`${n}.constants.ts`,Rn({pascal:t,kebab:n})),await u(`${n}.controller.ts`,Bn({pascal:t,kebab:n,plural:r,pluralPascal:i})),await u(`dtos/create-${n}.dto.ts`,En({pascal:t,kebab:n})),await u(`dtos/update-${n}.dto.ts`,Dn({pascal:t,kebab:n})),await u(`dtos/${n}-response.dto.ts`,On({pascal:t,kebab:n}));let d=Vn({pascal:t,kebab:n});for(let e of d)await u(`commands/${e.file}`,e.content);let f=Hn({pascal:t,kebab:n,plural:r,pluralPascal:i});for(let e of f)await u(`queries/${e.file}`,e.content);let p=Un({pascal:t,kebab:n});for(let e of p)await u(`events/${e.file}`,e.content);await u(`${n}.repository.ts`,An({pascal:t,kebab:n,dtoPrefix:`./dtos`,tokenScope:c}));let m={inmemory:`in-memory-${n}`,drizzle:`drizzle-${n}`,prisma:`prisma-${n}`},h={inmemory:()=>V({pascal:t,kebab:n,repoPrefix:`.`,dtoPrefix:`./dtos`}),drizzle:()=>Wn({pascal:t,kebab:n,repoPrefix:`.`,dtoPrefix:`./dtos`}),prisma:()=>Kn({pascal:t,kebab:n,repoPrefix:`.`,dtoPrefix:`./dtos`,prismaClientPath:s})},g=m[a]??`${R(a)}-${n}`,_=h[a]??(()=>jn({pascal:t,kebab:n,repoType:a,repoPrefix:`.`,dtoPrefix:`./dtos`}));await u(`${g}.repository.ts`,_()),o||(a!==`inmemory`&&await u(`in-memory-${n}.repository.ts`,V({pascal:t,kebab:n,repoPrefix:`.`,dtoPrefix:`./dtos`})),await u(`__tests__/${n}.controller.test.ts`,Fn({pascal:t,kebab:n,plural:r})),await u(`__tests__/${n}.repository.test.ts`,In({pascal:t,kebab:n,plural:r,repoPrefix:`../${m.inmemory??`in-memory-${n}`}.repository`})))}async function Xn(e){let{pascal:t,kebab:n,plural:r,pluralPascal:i,repo:a,noEntity:o,noTests:s,prismaClientPath:c,tokenScope:l,style:u,write:d}=e;await d(`${n}.module.ts`,bn({pascal:t,kebab:n,plural:r,repo:a,style:u})),await d(`constants.ts`,a===`drizzle`?Gn({pascal:t,kebab:n}):Tn({pascal:t,kebab:n})),await d(`presentation/${n}.controller.ts`,Cn({pascal:t,kebab:n,plural:r,pluralPascal:i})),await d(`application/dtos/create-${n}.dto.ts`,En({pascal:t,kebab:n})),await d(`application/dtos/update-${n}.dto.ts`,Dn({pascal:t,kebab:n})),await d(`application/dtos/${n}-response.dto.ts`,On({pascal:t,kebab:n}));let f=kn({pascal:t,kebab:n,plural:r,pluralPascal:i});for(let e of f)await d(`application/use-cases/${e.file}`,e.content);await d(`domain/repositories/${n}.repository.ts`,An({pascal:t,kebab:n,tokenScope:l})),await d(`domain/services/${n}-domain.service.ts`,Mn({pascal:t,kebab:n}));let p={inmemory:`in-memory-${n}`,drizzle:`drizzle-${n}`,prisma:`prisma-${n}`},m={inmemory:()=>V({pascal:t,kebab:n}),drizzle:()=>Wn({pascal:t,kebab:n}),prisma:()=>Kn({pascal:t,kebab:n,prismaClientPath:c})},h=p[a]??`${R(a)}-${n}`,g=m[a]??(()=>jn({pascal:t,kebab:n,repoType:a}));await d(`infrastructure/repositories/${h}.repository.ts`,g()),o||(await d(`domain/entities/${n}.entity.ts`,Nn({pascal:t,kebab:n})),await d(`domain/value-objects/${n}-id.vo.ts`,Pn({pascal:t,kebab:n}))),s||(a!==`inmemory`&&await d(`infrastructure/repositories/in-memory-${n}.repository.ts`,V({pascal:t,kebab:n})),await d(`__tests__/${n}.controller.test.ts`,Fn({pascal:t,kebab:n,plural:r})),await d(`__tests__/${n}.repository.test.ts`,In({pascal:t,kebab:n,plural:r})))}function Zn(e){return e?typeof e==`string`?e:e.name:`inmemory`}async function Qn(e){let{name:t,modulesDir:n,noEntity:r,noTests:i,repo:a=`inmemory`,force:o,dryRun:s}=e,c=e.pluralize!==!1,l=e.pattern??`ddd`;e.minimal&&(l=`minimal`);let u=R(t),d=I(t),f=c?z(u):u,p=c?Xt(d):d,m=h(n,f),g=[],_=o??!1,v={kebab:u,pascal:d,plural:f,pluralPascal:p,moduleDir:m,repo:a,noEntity:r??!1,noTests:i??!1,prismaClientPath:e.prismaClientPath??`@prisma/client`,tokenScope:e.tokenScope??`app`,style:e.style??`define`,write:async(e,t)=>{let n=h(m,e);if(s){g.push(n);return}if(!_&&await Xe(n)&&!await P({message:`File exists: ${E.dim(e)}. Overwrite?`,initialValue:!1})){F.warn(`Skipped: ${e}`);return}await M(n,t),g.push(n)},files:g};switch(l){case`minimal`:await qn(v);break;case`rest`:await Jn(v);break;case`cqrs`:await Yn(v);break;default:await Xn(v);break}return s||await $n(n,d,f,u,v.style),g}async function $n(e,t,n,r,i=`define`){let a=h(e,`index.ts`),o=await Xe(a),s=`./${n}/${r}.module`,c=i===`class`?`${t}Module`:`${t}Module()`;if(!o){await M(a,i===`class`?`import type { AppModuleEntry } from '@forinda/kickjs'
|
|
2774
2774
|
import { ${t}Module } from '${s}'
|
|
2775
2775
|
|
|
2776
2776
|
export const modules: AppModuleEntry[] = [${c}]
|
|
@@ -2781,8 +2781,8 @@ export const modules = defineModules().mount(${c})
|
|
|
2781
2781
|
`);return}let l=await C(a,`utf-8`),u=`import { ${t}Module } from '${s}'`,d=B(s);if(!RegExp(`^import\\s*\\{[^}]*\\b${B(t)}Module\\b[^}]*\\}\\s*from\\s*['"]${d}['"]`,`m`).test(l)){let e=l.lastIndexOf(`import `);if(e!==-1){let t=l.indexOf(`
|
|
2782
2782
|
`,e);l=l.slice(0,t+1)+u+`
|
|
2783
2783
|
`+l.slice(t+1)}else l=u+`
|
|
2784
|
-
`+l}let f=
|
|
2785
|
-
`;)t++;return t}if(n===`/*`){for(t+=2;t+1<e.length&&!(e[t]===`*`&&e[t+1]===`/`);)t++;return t+2}return t}function
|
|
2784
|
+
`+l}let f=tr(l);if(f){let e=l.slice(f.rhsStart,f.rhsEnd+1);RegExp(`\\b${B(t)}Module\\b`).test(e)||(l=er(l,c))}else l=er(l,c);await w(a,l,`utf-8`)}function er(e,t){let n=tr(e);if(!n)return e;if(n.shape===`array`){let r=e.slice(n.rhsStart+1,n.rhsEnd),i=r.trim(),a;if(!i)a=`[${t}]`;else{let e=i.endsWith(`,`)?``:`,`;a=`[${r.trimEnd()}${e} ${t}]`}return e.slice(0,n.rhsStart)+a+e.slice(n.rhsEnd+1)}return`${e.slice(0,n.chainEnd)}\n .mount(${t})${e.slice(n.chainEnd)}`}function tr(e){let t=/export\s+const\s+modules\b[^=]*=/.exec(e);if(!t)return null;let n=t.index+t[0].length;for(;n<e.length&&/\s/.test(e[n]??``);)n++;if(e[n]===`[`){let t=ir(e,n);return t===-1?null:{shape:`array`,rhsStart:n,rhsEnd:t}}if(e.slice(n,n+13)===`defineModules`){let t=nr(e,n);return t===-1?null:{shape:`chain`,rhsStart:n,rhsEnd:t-1,chainEnd:t}}return null}function nr(e,t=0){let n=/defineModules\s*\(/g;n.lastIndex=t;let r=n.exec(e);if(!r)return-1;let i=r.index+r[0].length-1;if(e[i]!==`(`||(i=ar(e,i),i===-1))return-1;for(i++;;){let t=i;for(;t<e.length&&/\s/.test(e[t]??``);)t++;if(e[t]!==`.`||e.slice(t,t+6)!==`.mount`)break;for(t+=6;t<e.length&&/\s/.test(e[t]??``);)t++;if(e[t]!==`(`)break;let n=ar(e,t);if(n===-1)break;i=n+1}return i}function rr(e,t){let n=e.slice(t,t+2);if(n===`//`){for(t+=2;t<e.length&&e[t]!==`
|
|
2785
|
+
`;)t++;return t}if(n===`/*`){for(t+=2;t+1<e.length&&!(e[t]===`*`&&e[t+1]===`/`);)t++;return t+2}return t}function ir(e,t){if(e[t]!==`[`)return-1;let n=1,r=t+1;for(;r<e.length;){let t=e.slice(r,r+2);if(t===`//`||t===`/*`){r=rr(e,r);continue}let i=e[r]??``;if(i===`'`||i===`"`||i==="`"){let t=i;for(r++;r<e.length&&e[r]!==t;)e[r]===`\\`&&r++,r++;r<e.length&&r++;continue}if(i===`[`)n++;else if(i===`]`&&(n--,n===0))return r;r++}return-1}function ar(e,t){if(e[t]!==`(`)return-1;let n=1,r=t+1;for(;r<e.length;){let t=e.slice(r,r+2);if(t===`//`||t===`/*`){r=rr(e,r);continue}let i=e[r]??``;if(i===`'`||i===`"`||i==="`"){let t=i;for(r++;r<e.length&&e[r]!==t;)e[r]===`\\`&&r++,r++;r<e.length&&r++;continue}if(i===`(`)n++;else if(i===`)`&&(n--,n===0))return r;r++}return-1}async function or(e){let{name:t,outDir:n}=e,r=R(t),i=I(t),a=[],o=h(n,`${r}.adapter.ts`);return await M(o,`import {
|
|
2786
2786
|
defineAdapter,
|
|
2787
2787
|
type AdapterContext,
|
|
2788
2788
|
type AdapterMiddleware,
|
|
@@ -2951,7 +2951,7 @@ export const ${i}Adapter = defineAdapter<${i}AdapterConfig>({
|
|
|
2951
2951
|
}
|
|
2952
2952
|
},
|
|
2953
2953
|
})
|
|
2954
|
-
`),a.push(o),a}async function
|
|
2954
|
+
`),a.push(o),a}async function sr(e){let{name:t,outDir:n}=e,r=R(t),i=I(t),a=[],o=h(n,`${r}.plugin.ts`);return await M(o,`import {
|
|
2955
2955
|
definePlugin,
|
|
2956
2956
|
type AppAdapter,
|
|
2957
2957
|
type AppModuleEntry,
|
|
@@ -3095,7 +3095,7 @@ export const ${i}Plugin = definePlugin<${i}PluginConfig>({
|
|
|
3095
3095
|
},
|
|
3096
3096
|
}),
|
|
3097
3097
|
})
|
|
3098
|
-
`),a.push(o),a}const
|
|
3098
|
+
`),a.push(o),a}const cr={controller:`presentation`,service:`domain/services`,dto:`application/dtos`,guard:`presentation/guards`,middleware:`middleware`},lr={controller:``,service:``,dto:`dtos`,guard:`guards`,middleware:`middleware`},ur={controller:``,service:``,dto:`dtos`,guard:`guards`,middleware:`middleware`,command:`commands`,query:`queries`,event:`events`};function dr(e){let{type:t,outDir:n,moduleName:r,modulesDir:i=`src/modules`,defaultDir:a,pattern:o=`ddd`,shouldPluralize:s=!0}=e;if(n)return v(n);if(r){let e=o===`ddd`?cr:o===`cqrs`?ur:lr,n=R(r),a=s?z(n):n,c=e[t]??``,l=h(i,a);return v(c?h(l,c):l)}return v(a)}async function fr(e){let{name:t,moduleName:n,modulesDir:r,pattern:i}=e,a=dr({type:`middleware`,outDir:e.outDir,moduleName:n,modulesDir:r,defaultDir:`src/middleware`,pattern:i,shouldPluralize:e.pluralize??!0}),o=R(t),s=L(t),c=[],l=h(a,`${o}.middleware.ts`);return await M(l,`import type { Request, Response, NextFunction } from 'express'
|
|
3099
3099
|
|
|
3100
3100
|
export interface ${I(t)}Options {
|
|
3101
3101
|
// Add configuration options here. The factory below closes over the
|
|
@@ -3145,7 +3145,7 @@ export function ${s}(options: ${I(t)}Options = {}) {
|
|
|
3145
3145
|
next()
|
|
3146
3146
|
}
|
|
3147
3147
|
}
|
|
3148
|
-
`),c.push(l),c}async function
|
|
3148
|
+
`),c.push(l),c}async function pr(e){let{name:t,moduleName:n,modulesDir:r,pattern:i}=e,a=dr({type:`guard`,outDir:e.outDir,moduleName:n,modulesDir:r,defaultDir:`src/guards`,pattern:i,shouldPluralize:e.pluralize??!0}),o=R(t),s=L(t),c=I(t),l=[],u=h(a,`${o}.guard.ts`);return await M(u,`import { Container, HttpException } from '@forinda/kickjs'
|
|
3149
3149
|
import type { RequestContext } from '@forinda/kickjs'
|
|
3150
3150
|
|
|
3151
3151
|
/**
|
|
@@ -3181,7 +3181,7 @@ export async function ${s}Guard(ctx: RequestContext, next: () => void): Promise<
|
|
|
3181
3181
|
ctx.res.status(401).json({ message: 'Invalid or expired token' })
|
|
3182
3182
|
}
|
|
3183
3183
|
}
|
|
3184
|
-
`),l.push(u),l}async function
|
|
3184
|
+
`),l.push(u),l}async function mr(e){let{name:t,moduleName:n,modulesDir:r,pattern:i}=e,a=dr({type:`service`,outDir:e.outDir,moduleName:n,modulesDir:r,defaultDir:`src/services`,pattern:i,shouldPluralize:e.pluralize??!0}),o=R(t),s=I(t),c=[],l=h(a,`${o}.service.ts`);return await M(l,`import { Service } from '@forinda/kickjs'
|
|
3185
3185
|
|
|
3186
3186
|
@Service()
|
|
3187
3187
|
export class ${s}Service {
|
|
@@ -3190,7 +3190,7 @@ export class ${s}Service {
|
|
|
3190
3190
|
// @Inject(MY_REPO) private readonly repo: IMyRepository,
|
|
3191
3191
|
// ) {}
|
|
3192
3192
|
}
|
|
3193
|
-
`),c.push(l),c}async function
|
|
3193
|
+
`),c.push(l),c}async function hr(e){let{name:t,moduleName:n,modulesDir:r,pattern:i}=e,a=dr({type:`controller`,outDir:e.outDir,moduleName:n,modulesDir:r,defaultDir:`src/controllers`,pattern:i,shouldPluralize:e.pluralize??!0}),o=R(t),s=I(t),c=[],l=h(a,`${o}.controller.ts`);return await M(l,`import { Controller, Get, Post, type Ctx } from '@forinda/kickjs'
|
|
3194
3194
|
|
|
3195
3195
|
// \`Ctx<KickRoutes.${s}Controller['<method>']>\` is generated by
|
|
3196
3196
|
// \`kick typegen\` (auto-run on \`kick dev\`). After the first run, your IDE
|
|
@@ -3211,7 +3211,7 @@ export class ${s}Controller {
|
|
|
3211
3211
|
ctx.created({ message: '${s} created', data: ctx.body })
|
|
3212
3212
|
}
|
|
3213
3213
|
}
|
|
3214
|
-
`),c.push(l),c}async function
|
|
3214
|
+
`),c.push(l),c}async function gr(e){let{name:t,moduleName:n,modulesDir:r,pattern:i}=e,a=dr({type:`dto`,outDir:e.outDir,moduleName:n,modulesDir:r,defaultDir:`src/dtos`,pattern:i,shouldPluralize:e.pluralize??!0}),o=R(t),s=I(t),c=L(t),l=[],u=h(a,`${o}.dto.ts`);return await M(u,`import { z } from 'zod'
|
|
3215
3215
|
|
|
3216
3216
|
export const ${c}Schema = z.object({
|
|
3217
3217
|
// Define your schema fields here
|
|
@@ -3219,7 +3219,7 @@ export const ${c}Schema = z.object({
|
|
|
3219
3219
|
})
|
|
3220
3220
|
|
|
3221
3221
|
export type ${s}DTO = z.infer<typeof ${c}Schema>
|
|
3222
|
-
`),l.push(u),l}async function
|
|
3222
|
+
`),l.push(u),l}async function _r(e){let t=h(e.outDir,`kick.config.ts`),n=e.modulesDir??`src/modules`,i=e.defaultRepo??`inmemory`;return r(t)&&!e.force&&!await P({message:`kick.config.ts already exists. Overwrite?`,initialValue:!1})?(console.log(`
|
|
3223
3223
|
Skipped — existing kick.config.ts preserved.`),[]):(await M(t,`import { defineConfig } from '@forinda/kickjs-cli'
|
|
3224
3224
|
|
|
3225
3225
|
export default defineConfig({
|
|
@@ -3257,18 +3257,18 @@ export default defineConfig({
|
|
|
3257
3257
|
},
|
|
3258
3258
|
],
|
|
3259
3259
|
})
|
|
3260
|
-
`),[t])}const
|
|
3260
|
+
`),[t])}const vr=`.agents`,yr=new Set([`rest`,`ddd`,`cqrs`,`minimal`]);function br(e,t){if(t)return t;try{let t=JSON.parse(a(h(e,`package.json`),`utf-8`));if(t.name)return t.name.replace(/^@[^/]+\//,``)}catch{}return e.split(`/`).findLast(Boolean)??`app`}function xr(e,t){if(t)return t;try{let t=JSON.parse(a(h(e,`package.json`),`utf-8`));if(t.packageManager)return t.packageManager.split(`@`)[0]}catch{}return`pnpm`}async function Sr(e,t){if(t)return t;try{let t=(await k(e))?.pattern;if(t&&yr.has(t))return t}catch{}return`ddd`}async function Cr(e){let t=e.only??`all`,n=br(e.outDir,e.name),i=xr(e.outDir,e.pm),a=await Sr(e.outDir,e.template),o=t===`agents`||t===`both`||t===`all`,s=t===`claude`||t===`both`||t===`all`,c=t===`skills`||t===`all`,l=t===`gemini`||t===`all`,u=t===`copilot`||t===`all`,d=[];if(o&&d.push({file:h(e.outDir,vr,`AGENTS.md`),render:()=>vt(n,a,i)}),s&&d.push({file:h(e.outDir,`CLAUDE.md`),render:()=>_t(n,a,i)}),c)for(let t of yt(n,a,i))d.push({file:h(e.outDir,vr,`skills`,t.slug,`SKILL.md`),render:()=>t.content});l&&d.push({file:h(e.outDir,vr,`GEMINI.md`),render:()=>xt(n,a,i)}),u&&d.push({file:h(e.outDir,vr,`COPILOT.md`),render:()=>St(n,a,i)});let f=[];for(let{file:t,render:n}of d){if(r(t)&&!e.force&&!await P({message:`${t.replace(e.outDir+`/`,``)} already exists. Overwrite?`,initialValue:!1})){console.log(` Skipped — existing ${t.replace(e.outDir+`/`,``)} preserved.`);continue}await M(t,n()),f.push(t)}return f}function wr(e,t){if(e[t]!==`{`)return-1;let n=1;for(let r=t+1;r<e.length;r++){let t=e[r];if(t===`{`)n++;else if(t===`}`&&(n--,n===0))return r}return-1}function H(e,t){let n=t.exec(e);if(!n)return null;let r=n.index+n[0].length-1,i=wr(e,r);return i===-1?null:e.slice(r+1,i)}function U(e,t,n){let r=` `.repeat(n);return e.split(`
|
|
3261
3261
|
`).map(e=>{if(e.trim()===``)return e;let n=RegExp(`^ {0,${t}}`);return r+e.replace(n,``)}).join(`
|
|
3262
|
-
`)}function
|
|
3262
|
+
`)}function Tr(e){return e.replaceAll(/import\s*\{\s*([^}]+)\s*\}\s*from\s*'@forinda\/kickjs'/g,(e,t)=>{let n=t.split(`,`).map(e=>e.trim()).filter(e=>e&&e!==`Container`&&e!==`type Container`&&e!==`type AppModule`&&e!==`AppModule`&&e!==`type ModuleRoutes`&&e!==`ModuleRoutes`);return n.includes(`defineModule`)||n.push(`defineModule`),`import { ${n.join(`, `)} } from '@forinda/kickjs'`})}function Er(e,t){return e.replaceAll(/import\s*\{\s*([^}]+)\s*\}\s*from\s*'@forinda\/kickjs'/g,(e,n)=>{let r=n.split(`,`).map(e=>e.trim()).filter(e=>e&&e!==`defineModule`);return t.container&&!r.includes(`Container`)&&r.push(`Container`),t.appModule&&!r.some(e=>e===`AppModule`||e===`type AppModule`)&&r.push(`type AppModule`),t.moduleRoutes&&!r.some(e=>e===`ModuleRoutes`||e===`type ModuleRoutes`)&&r.push(`type ModuleRoutes`),t.contributorRegistrations&&!r.some(e=>e===`ContributorRegistrations`||e===`type ContributorRegistrations`)&&r.push(`type ContributorRegistrations`),`import { ${r.join(`, `)} } from '@forinda/kickjs'`})}function Dr(e){if(/\bdefineModule\s*\(/.test(e))return{migrated:null,reason:`already in target form`};let t=[...e.matchAll(/export\s+class\s+(\w+Module)\s+implements\s+AppModule\s*\{/g)];if(t.length===0)return{migrated:null,reason:`no class form detected`};if(t.length>1)return{migrated:null,reason:`multiple module classes in one file — migrate manually`};let n=t[0],r=n[1],i=n.index+n[0].length-1,a=wr(e,i);if(a===-1)return{migrated:null,reason:`unbalanced class braces`};let o=e.slice(i+1,a),s=e.slice(0,n.index),c=e.slice(a+1),l=H(o,/register\s*\(([^)]*)\)\s*:\s*void\s*\{/),u=H(o,/contributors\s*\(\s*\)\s*:\s*ContributorRegistrations\s*\{/),d=H(o,/routes\s*\(\s*\)\s*:\s*[A-Za-z|[\]\s]+\{/);if(!d)return{migrated:null,reason:`routes() method missing or signature unrecognized`};let f=Tr(s),p=``;return l&&(p+=` register(container) {${U(l,4,6)} },\n\n`),u&&(p+=` contributors() {${U(u,4,6)} },\n\n`),p+=` routes() {${U(d,4,6)} },`,{migrated:`${f}${`export const ${r} = defineModule({
|
|
3263
3263
|
name: '${r}',
|
|
3264
3264
|
build: () => ({
|
|
3265
3265
|
${p}
|
|
3266
3266
|
}),
|
|
3267
|
-
})`}${c}`}}function
|
|
3268
|
-
`||e[l]===`\r`);)l++;let u=e.slice(l),d=/build\s*:\s*\([^)]*\)\s*=>\s*\(\s*\{/g.exec(s);if(!d)return{migrated:null,reason:`build: () => ({...}) not found in defineModule`};let f=d.index+d[0].length-1,p=
|
|
3267
|
+
})`}${c}`}}function Or(e){if(/export\s+class\s+\w+Module\s+implements\s+AppModule\s*\{/.test(e))return{migrated:null,reason:`already in target form`};let t=[...e.matchAll(/export\s+const\s+(\w+Module)\s*=\s*defineModule\s*\(\s*\{/g)];if(t.length===0)return{migrated:null,reason:`no defineModule form detected`};if(t.length>1)return{migrated:null,reason:`multiple defineModule blocks in one file — migrate manually`};let n=t[0],r=n[1],i=n.index+n[0].length-1,a=wr(e,i);if(a===-1)return{migrated:null,reason:`unbalanced defineModule braces`};let o=e.indexOf(`)`,a);if(o===-1)return{migrated:null,reason:`unbalanced defineModule call parens`};let s=e.slice(i+1,a),c=e.slice(0,n.index),l=o+1;for(;l<e.length&&(e[l]===`
|
|
3268
|
+
`||e[l]===`\r`);)l++;let u=e.slice(l),d=/build\s*:\s*\([^)]*\)\s*=>\s*\(\s*\{/g.exec(s);if(!d)return{migrated:null,reason:`build: () => ({...}) not found in defineModule`};let f=d.index+d[0].length-1,p=wr(s,f);if(p===-1)return{migrated:null,reason:`unbalanced build() braces`};let m=s.slice(f+1,p),h=H(m,/register\s*\(([^)]*)\)\s*\{/),g=H(m,/contributors\s*\(\s*\)\s*\{/),_=H(m,/routes\s*\(\s*\)\s*\{/);if(!_)return{migrated:null,reason:`routes() method missing inside build()`};let v=Er(c,{container:h!==null,appModule:!0,moduleRoutes:!0,contributorRegistrations:g!==null}),y=``;return h!==null&&(y+=` register(container: Container): void {${U(h,6,4)} }\n\n`),g!==null&&(y+=` contributors(): ContributorRegistrations {${U(g,6,4)} }\n\n`),y+=` routes(): ModuleRoutes {${U(_,6,4)} }`,{migrated:`${v}${`export class ${r} implements AppModule {
|
|
3269
3269
|
${y}
|
|
3270
3270
|
}
|
|
3271
|
-
`}${u}`}}function
|
|
3271
|
+
`}${u}`}}function kr(e,t){return t===`class`?Or(e):Dr(e)}function Ar(e,t){let n=e,r=!1;if(t===`define`){/\bAppModuleClass\b/.test(n)&&(n=n.replaceAll(/\bAppModuleClass\b/g,`AppModuleEntry`),r=!0);let e=/(=\s*\[)([\s\S]*?)(])/,t=e.exec(n);if(t){let i=t[1],a=t[3],o=t[2],s=o.replaceAll(/(\b\w+Module)(?![(.])/g,`$1()`);s!==o&&(n=n.replace(e,`${i}${s}${a}`),r=!0)}}else{/\bAppModuleEntry\b/.test(n)&&(n=n.replaceAll(/\bAppModuleEntry\b/g,`AppModuleClass`),r=!0);let e=/(=\s*\[)([\s\S]*?)(])/,t=e.exec(n);if(t){let i=t[1],a=t[3],o=t[2],s=o.replaceAll(/(\b\w+Module)\s*\(\s*\)/g,`$1`);s!==o&&(n=n.replace(e,`${i}${s}${a}`),r=!0)}}return r?{migrated:n}:{migrated:null,reason:`no changes needed`}}async function jr(e){let t=[];return await n(v(e),0),t;async function n(e,r){let i;try{i=await se(e)}catch{return}for(let a of i){if(a===`node_modules`||a===`dist`||a===`.kickjs`)continue;let i=h(e,a),o;try{o=await le(i)}catch{continue}o.isDirectory()?await n(i,r+1):(a.endsWith(`.module.ts`)||a===`index.ts`&&r===1)&&t.push(i)}}}async function Mr(e,t){let n=0;return await r(e,t),n;async function r(e,t){let i;try{i=await se(e)}catch{return}await oe(t,{recursive:!0});for(let a of i){if(a===`node_modules`||a===`dist`||a===`.kickjs`)continue;let i=h(e,a),o=h(t,a),s;try{s=await le(i)}catch{continue}s.isDirectory()?await r(i,o):(await ae(i,o),n++)}}}function Nr(e){return h(e,`.kickjs`,`codemod-backups`,`${new Date().toISOString().replaceAll(/[:.]/g,`-`)}-modules`)}async function Pr(e,t){let{dryRun:n=!1,cwd:r=process.cwd(),target:i}=t,a=t.backup??!n,o=await jr(e),s=await C(h(e,`index.ts`),`utf-8`).then(()=>!0,()=>!1),c=null;a&&(o.length>0||s)&&(c=Nr(r),await Mr(e,c));let l=[];for(let e of o){let t=kr(await C(e,`utf-8`),i);if(t.migrated==null){l.push({path:e,status:`skipped`,reason:t.reason});continue}n||await w(e,t.migrated,`utf-8`),l.push({path:e,status:`migrated`})}let u=h(e,`index.ts`),d=null;try{d=await C(u,`utf-8`)}catch{return{target:i,files:l,indexStatus:`not-found`,indexPath:u,backupDir:c}}let f=Ar(d,i);return f.migrated==null?{target:i,files:l,indexStatus:`skipped`,indexPath:u,indexReason:f.reason,backupDir:c}:(n||await w(u,f.migrated,`utf-8`),{target:i,files:l,indexStatus:`migrated`,indexPath:u,backupDir:c})}async function Fr(e,t){let n=await jr(e),r=[],i=t===`define`?/export\s+class\s+\w+Module\s+implements\s+AppModule\s*\{/:/export\s+const\s+\w+Module\s*=\s*defineModule\s*\(/;for(let e of n){let t=await C(e,`utf-8`);i.test(t)&&r.push(e)}return r}async function Ir(e){let{name:t,outDir:n}=e,r=I(t),i=R(t),a=L(t),o=e.queue??`${i}-queue`,s=[];return await(async(e,t)=>{let r=h(n,e);await M(r,t),s.push(r)})(`${i}.job.ts`,`import { Inject } from '@forinda/kickjs'
|
|
3272
3272
|
import { Job, Process, QUEUE_MANAGER, type QueueService } from '@forinda/kickjs-queue'
|
|
3273
3273
|
|
|
3274
3274
|
/**
|
|
@@ -3301,7 +3301,7 @@ export class ${r}Job {
|
|
|
3301
3301
|
// Handle high-priority variant of this job
|
|
3302
3302
|
}
|
|
3303
3303
|
}
|
|
3304
|
-
`),s}const
|
|
3304
|
+
`),s}const Lr={string:{ts:`string`,zod:`z.string()`},text:{ts:`string`,zod:`z.string()`},number:{ts:`number`,zod:`z.number()`},int:{ts:`number`,zod:`z.number().int()`},float:{ts:`number`,zod:`z.number()`},boolean:{ts:`boolean`,zod:`z.boolean()`},date:{ts:`string`,zod:`z.string().datetime()`},email:{ts:`string`,zod:`z.string().email()`},url:{ts:`string`,zod:`z.string().url()`},uuid:{ts:`string`,zod:`z.string().uuid()`},json:{ts:`any`,zod:`z.any()`}};function Rr(e){return e.map(e=>{let t=e.indexOf(`:`);if(t===-1)throw Error(`Invalid field: "${e}". Use format: name:type (e.g. title:string)`);let n=e.slice(0,t),r=e.slice(t+1);if(!n||!r)throw Error(`Invalid field: "${e}". Use format: name:type (e.g. title:string)`);let i=!1;r.endsWith(`:optional`)&&(r=r.slice(0,-9),i=!0),n.endsWith(`?`)&&(n=n.slice(0,-1),i=!0),r.endsWith(`?`)&&(r=r.slice(0,-1),i=!0);let a=r;if(a.startsWith(`enum:`)){let e=a.slice(5).split(`,`);return{name:n,type:`enum`,tsType:e.map(e=>`'${e}'`).join(` | `),zodType:`z.enum([${e.map(e=>`'${e}'`).join(`, `)}])`,optional:i}}let o=Lr[a];if(!o){let e=[...Object.keys(Lr),`enum:a,b,c`].join(`, `);throw Error(`Unknown field type: "${a}". Valid types: ${e}`)}return{name:n,type:a,tsType:o.ts,zodType:o.zod,optional:i}})}async function zr(e){let{name:t,fields:n,modulesDir:r,noEntity:i,noTests:a,repo:o=`inmemory`,tokenScope:s=`app`,style:c=`define`}=e,l=e.pluralize!==!1,u=R(t),d=I(t);L(t);let f=l?z(u):u,p=l?Xt(d):d,m=h(r,f),g=[],_=async(e,t)=>{let n=h(m,e);await M(n,t),g.push(n)};await _(`${u}.module.ts`,qr(d,u,f,c)),await _(`constants.ts`,Ur(d,n)),await _(`presentation/${u}.controller.ts`,Jr(d,u,f,p)),await _(`application/dtos/create-${u}.dto.ts`,Br(d,n)),await _(`application/dtos/update-${u}.dto.ts`,Vr(d,n)),await _(`application/dtos/${u}-response.dto.ts`,Hr(d,n));let v=Zr(d,u,f,p);for(let e of v)await _(`application/use-cases/${e.file}`,e.content);return await _(`domain/repositories/${u}.repository.ts`,Yr(d,u,s)),await _(`domain/services/${u}-domain.service.ts`,Xr(d,u)),o===`inmemory`&&await _(`infrastructure/repositories/in-memory-${u}.repository.ts`,Wr(d,u,n)),i||(await _(`domain/entities/${u}.entity.ts`,Gr(d,u,n)),await _(`domain/value-objects/${u}-id.vo.ts`,Kr(d))),await $n(r,d,f,u,c),g}function Br(e,t){return`import { z } from 'zod'
|
|
3305
3305
|
|
|
3306
3306
|
export const create${e}Schema = z.object({
|
|
3307
3307
|
${t.map(e=>{let t=e.zodType;return` ${e.name}: ${t}${e.optional?`.optional()`:``},`}).join(`
|
|
@@ -3309,7 +3309,7 @@ ${t.map(e=>{let t=e.zodType;return` ${e.name}: ${t}${e.optional?`.optional()`:`
|
|
|
3309
3309
|
})
|
|
3310
3310
|
|
|
3311
3311
|
export type Create${e}DTO = z.infer<typeof create${e}Schema>
|
|
3312
|
-
`}function
|
|
3312
|
+
`}function Vr(e,t){return`import { z } from 'zod'
|
|
3313
3313
|
|
|
3314
3314
|
export const update${e}Schema = z.object({
|
|
3315
3315
|
${t.map(e=>` ${e.name}: ${e.zodType}.optional(),`).join(`
|
|
@@ -3317,21 +3317,21 @@ ${t.map(e=>` ${e.name}: ${e.zodType}.optional(),`).join(`
|
|
|
3317
3317
|
})
|
|
3318
3318
|
|
|
3319
3319
|
export type Update${e}DTO = z.infer<typeof update${e}Schema>
|
|
3320
|
-
`}function
|
|
3320
|
+
`}function Hr(e,t){return`export interface ${e}ResponseDTO {
|
|
3321
3321
|
id: string
|
|
3322
3322
|
${t.map(e=>` ${e.name}${e.optional?`?`:``}: ${e.tsType}`).join(`
|
|
3323
3323
|
`)}
|
|
3324
3324
|
createdAt: string
|
|
3325
3325
|
updatedAt: string
|
|
3326
3326
|
}
|
|
3327
|
-
`}function
|
|
3327
|
+
`}function Ur(e,t){let n=t.filter(e=>e.tsType===`string`).map(e=>`'${e.name}'`);t.filter(e=>e.tsType===`number`).map(e=>`'${e.name}'`);let r=t.map(e=>`'${e.name}'`),i=[...r].join(`, `),a=[...r,`'createdAt'`,`'updatedAt'`].join(`, `),o=n.length>0?n.join(`, `):`'name'`;return`import type { ApiQueryParamsConfig } from '@forinda/kickjs'
|
|
3328
3328
|
|
|
3329
3329
|
export const ${e.toUpperCase()}_QUERY_CONFIG: ApiQueryParamsConfig = {
|
|
3330
3330
|
filterable: [${i}],
|
|
3331
3331
|
sortable: [${a}],
|
|
3332
3332
|
searchable: [${o}],
|
|
3333
3333
|
}
|
|
3334
|
-
`}function
|
|
3334
|
+
`}function Wr(e,t,n){return`import { randomUUID } from 'node:crypto'
|
|
3335
3335
|
import { Repository, HttpException } from '@forinda/kickjs'
|
|
3336
3336
|
import type { ParsedQuery } from '@forinda/kickjs'
|
|
3337
3337
|
import type { I${e}Repository } from '../../domain/repositories/${t}.repository'
|
|
@@ -3383,7 +3383,7 @@ ${n.map(e=>` ${e.name}: dto.${e.name},`).join(`
|
|
|
3383
3383
|
this.store.delete(id)
|
|
3384
3384
|
}
|
|
3385
3385
|
}
|
|
3386
|
-
`}function
|
|
3386
|
+
`}function Gr(e,t,n){return`import { ${e}Id } from '../value-objects/${t}-id.vo'
|
|
3387
3387
|
|
|
3388
3388
|
interface ${e}Props {
|
|
3389
3389
|
id: ${e}Id
|
|
@@ -3429,7 +3429,7 @@ ${n.map(e=>` ${e.name}: this.props.${e.name},`).join(`
|
|
|
3429
3429
|
}
|
|
3430
3430
|
}
|
|
3431
3431
|
}
|
|
3432
|
-
`}function
|
|
3432
|
+
`}function Kr(e){return`import { randomUUID } from 'node:crypto'
|
|
3433
3433
|
|
|
3434
3434
|
export class ${e}Id {
|
|
3435
3435
|
private constructor(private readonly value: string) {}
|
|
@@ -3444,7 +3444,7 @@ export class ${e}Id {
|
|
|
3444
3444
|
toString(): string { return this.value }
|
|
3445
3445
|
equals(other: ${e}Id): boolean { return this.value === other.value }
|
|
3446
3446
|
}
|
|
3447
|
-
`}function
|
|
3447
|
+
`}function qr(e,t,n,r=`define`){let i=`import { ${e}Controller } from './presentation/${t}.controller'
|
|
3448
3448
|
import { ${e.toUpperCase()}_REPOSITORY } from './domain/repositories/${t}.repository'
|
|
3449
3449
|
import { InMemory${e}Repository } from './infrastructure/repositories/in-memory-${t}.repository'
|
|
3450
3450
|
|
|
@@ -3517,7 +3517,7 @@ ${a}
|
|
|
3517
3517
|
},
|
|
3518
3518
|
}),
|
|
3519
3519
|
})
|
|
3520
|
-
`}function
|
|
3520
|
+
`}function Jr(e,t,n,r){return`import { Controller, Get, Post, Put, Delete, Autowired, ApiQueryParams, type Ctx } from '@forinda/kickjs'
|
|
3521
3521
|
import { ApiTags } from '@forinda/kickjs-swagger'
|
|
3522
3522
|
import { Create${e}UseCase } from '../application/use-cases/create-${t}.use-case'
|
|
3523
3523
|
import { Get${e}UseCase } from '../application/use-cases/get-${t}.use-case'
|
|
@@ -3580,7 +3580,7 @@ export class ${e}Controller {
|
|
|
3580
3580
|
ctx.noContent()
|
|
3581
3581
|
}
|
|
3582
3582
|
}
|
|
3583
|
-
`}function
|
|
3583
|
+
`}function Yr(e,t,n){return`import { createToken } from '@forinda/kickjs'
|
|
3584
3584
|
import type { ${e}ResponseDTO } from '../../application/dtos/${t}-response.dto'
|
|
3585
3585
|
import type { Create${e}DTO } from '../../application/dtos/create-${t}.dto'
|
|
3586
3586
|
import type { Update${e}DTO } from '../../application/dtos/update-${t}.dto'
|
|
@@ -3606,7 +3606,7 @@ export interface I${e}Repository {
|
|
|
3606
3606
|
* adopters must NOT use the reserved \`'kick/'\` namespace.
|
|
3607
3607
|
*/
|
|
3608
3608
|
export const ${e.toUpperCase()}_REPOSITORY = createToken<I${e}Repository>('${n}/${e}/repository')
|
|
3609
|
-
`}function
|
|
3609
|
+
`}function Xr(e,t){return`import { Service, Inject, HttpException } from '@forinda/kickjs'
|
|
3610
3610
|
import { ${e.toUpperCase()}_REPOSITORY, type I${e}Repository } from '../repositories/${t}.repository'
|
|
3611
3611
|
|
|
3612
3612
|
@Service()
|
|
@@ -3620,7 +3620,7 @@ export class ${e}DomainService {
|
|
|
3620
3620
|
if (!entity) throw HttpException.notFound('${e} not found')
|
|
3621
3621
|
}
|
|
3622
3622
|
}
|
|
3623
|
-
`}function
|
|
3623
|
+
`}function Zr(e,t,n,r){return[{file:`create-${t}.use-case.ts`,content:`import { Service, Inject } from '@forinda/kickjs'
|
|
3624
3624
|
import { ${e.toUpperCase()}_REPOSITORY, type I${e}Repository } from '../../domain/repositories/${t}.repository'
|
|
3625
3625
|
import type { Create${e}DTO } from '../dtos/create-${t}.dto'
|
|
3626
3626
|
|
|
@@ -3663,7 +3663,7 @@ export class Delete${e}UseCase {
|
|
|
3663
3663
|
constructor(@Inject(${e.toUpperCase()}_REPOSITORY) private repo: I${e}Repository) {}
|
|
3664
3664
|
async execute(id: string) { return this.repo.delete(id) }
|
|
3665
3665
|
}
|
|
3666
|
-
`}]}async function
|
|
3666
|
+
`}]}async function Qr(e){let{name:t,moduleName:n,modulesDir:r}=e,i=e.pluralize??!0,a=R(t),o=I(t),s=[],c;if(e.outDir)c=v(e.outDir);else if(n){let e=R(n),t=i?z(e):e;c=v(h(r??`src/modules`,t,`__tests__`))}else c=v(`src/__tests__`);let l=h(c,`${a}.test.ts`);return await M(l,`import { describe, it, expect, beforeEach } from 'vitest'
|
|
3667
3667
|
import { Container } from '@forinda/kickjs'
|
|
3668
3668
|
|
|
3669
3669
|
describe('${o}', () => {
|
|
@@ -3686,9 +3686,9 @@ describe('${o}', () => {
|
|
|
3686
3686
|
expect(true).toBe(true)
|
|
3687
3687
|
})
|
|
3688
3688
|
})
|
|
3689
|
-
`),s.push(l),s}const
|
|
3690
|
-
`:t===`t`?` `:t===`r`?`\r`:t)}const
|
|
3691
|
-
`)}function
|
|
3689
|
+
`),s.push(l),s}const $r=[`Service`,`Controller`,`Repository`,`Injectable`,`Component`,`Module`],ei=[`.ts`,`.tsx`,`.mts`,`.cts`],ti=[`node_modules`,`.kickjs`,`dist`,`build`,`.test.`,`.spec.`,`.d.ts`],ni=new RegExp(String.raw`@(${$r.join(`|`)})\s*\([^)]*\)`+String.raw`(?:\s*@[A-Z]\w*(?:\s*\([^)]*\))?)*`+String.raw`\s*export\s+(default\s+)?(?:abstract\s+)?class\s+(\w+)`,`g`),ri=new RegExp(String.raw`export\s+(default\s+)?(?:abstract\s+)?class\s+(\w+)`+String.raw`(?:\s+extends\s+\w+(?:<[^>]*>)?)?`+String.raw`\s+implements\s+[^{]*\bAppModule\b`,`g`),ii=/(?:export\s+)?const\s+(\w+)\s*(?::\s*[^=]+)?=\s*createToken\s*(?:<[^>]*>)?\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g,ai=/createToken\s*(?:<[^>]*>)?\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g,oi=/@Inject\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g,si=/\b(defineAdapter|definePlugin)\s*(?:<[^>]*>)?\s*\(/g,ci=new RegExp(String.raw`export\s+(?:default\s+)?(?:abstract\s+)?class\s+(\w+)`+String.raw`(?:\s+extends\s+\w+(?:<[^>]*>)?)?`+String.raw`\s+implements\s+[^{]*\bAppAdapter\b`,`g`),li=/\bname\s*(?::\s*[^=]+)?=\s*['"`]([^'"`]+)['"`]/,ui=/\bdefineAugmentation\s*\(\s*['"`]([^'"`]+)['"`]\s*(,\s*\{)?/g,di=new RegExp(String.raw`@(${[`Get`,`Post`,`Put`,`Delete`,`Patch`].join(`|`)})\s*\(`,`g`);function fi(e,t){let n=1;for(let r=t+1;r<e.length;r++){let t=e[r];if(t===`(`)n++;else if(t===`)`&&(n--,n===0))return r}return-1}function pi(e,t){let n=t;for(;n<e.length;){for(;n<e.length&&/\s/.test(e[n]);)n++;if(e[n]!==`@`)break;let t=e.slice(n).match(/^@([A-Z]\w*)/);if(!t)break;for(n+=t[0].length;n<e.length&&/\s/.test(e[n]);)n++;if(e[n]===`(`){let t=fi(e,n);if(t<0)return null;n=t+1}}for(;n<e.length&&/\s/.test(e[n]);)n++;for(let t of[`public`,`private`,`protected`])if(e.slice(n,n+t.length)===t&&/\s/.test(e.charAt(n+t.length))){for(n+=t.length;n<e.length&&/\s/.test(e[n]);)n++;break}if(e.slice(n,n+5)===`async`&&/\s/.test(e.charAt(n+5)))for(n+=5;n<e.length&&/\s/.test(e[n]);)n++;let r=e.slice(n).match(/^([a-zA-Z_]\w*)\s*\(/);return r?{methodName:r[1],endPos:n+r[0].length}:null}function mi(e){return(e.match(/:([a-zA-Z_]\w*)/g)??[]).map(e=>e.slice(1))}function hi(e,t){let n=e.endsWith(`/`)?e.slice(0,-1):e;return!t||t===`/`?n||`/`:n+(t.startsWith(`/`)?t:`/`+t)||`/`}const gi=/\b(?:public\s+|private\s+|protected\s+)?routes\s*\([^)]*\)\s*(?::\s*[A-Za-z_][\w<>[\]\s,|]*\s*)?\{/g,_i=/\bpath\s*:\s*['"`]([^'"`]*)['"`]/g,vi=/\bcontroller\s*:\s*([A-Z]\w*)\b/g,yi=/\bimport\.meta\.glob\s*\(/g;function bi(e){let t=[];for(yi.lastIndex=0;yi.exec(e)!==null;){let n=yi.lastIndex-1,r=fi(e,n);if(r<0)continue;let i=e.slice(n+1,r),a=/['"`]([^'"`]+)['"`]/g,o;for(;(o=a.exec(i))!==null;)t.push(o[1])}return t}function xi(e){let t=e.replace(/[.+^$()|[\]\\]/g,`\\$&`).replace(/\?/g,`.`).replace(/\*\*\//g,`___DOUBLESTAR_SLASH___`).replace(/\*\*/g,`___DOUBLESTAR___`).replace(/\*/g,`[^/]*`).replace(/___DOUBLESTAR_SLASH___/g,`(?:.+/)?`).replace(/___DOUBLESTAR___/g,`.*`);return RegExp(`^`+t+`$`)}function Si(e,t){let n=e.startsWith(`./`)?e:`./`+e,r=!1;for(let e of t){let t=e.startsWith(`!`);xi(t?e.slice(1):e).test(n)&&(r=!t)}return r}function Ci(e){let t=[];gi.lastIndex=0;let n;for(;(n=gi.exec(e))!==null;){let r=e.indexOf(`{`,n.index+n[0].length-1);if(r<0)continue;let i=Fi(e,r);if(i<0)continue;let a=e.slice(r+1,i),o=[];_i.lastIndex=0;let s;for(;(s=_i.exec(a))!==null;)o.push(s[1]??``);let c=[];vi.lastIndex=0;let l;for(;(l=vi.exec(a))!==null;)c.push(l[1]);let u=Math.min(o.length,c.length);for(let e=0;e<u;e++)t.push({controller:c[e],mountPath:o[e]})}return t}function wi(e,t){let n=new RegExp(String.raw`\b${t}\s*:\s*([A-Za-z_$][\w$]*)`,`g`).exec(e);return n?n[1]:null}function Ti(e,t){let n=new RegExp(String.raw`import\s*(?:type\s+)?\{[^}]*\b${t}\b[^}]*\}\s*from\s*['"\`]([^'"\`]+)['"\`]`).exec(e);if(n)return n[1];let r=new RegExp(String.raw`import\s+(?:type\s+)?${t}\s+from\s*['"\`]([^'"\`]+)['"\`]`).exec(e);if(r)return r[1];let i=new RegExp(String.raw`import\s*\*\s*as\s+${t}\s+from\s*['"\`]([^'"\`]+)['"\`]`).exec(e);return i?i[1]:new RegExp(String.raw`(?:^|\n)\s*(?:export\s+)?const\s+${t}\b`).test(e)?``:null}function Ei(e,t){let n=/@ApiQueryParams\s*\(\s*([\s\S]*?)\s*\)\s*$/.exec(e);if(!n){let n=/@ApiQueryParams\s*\(([\s\S]*?)\)/.exec(e);return n?Di(n[1].trim(),t):null}return Di(n[1].trim(),t)}function Di(e,t){if(e.startsWith(`{`))return ki(e);let n=/^([A-Za-z_]\w*)/.exec(e);if(n){let e=n[1],r=new RegExp(String.raw`const\s+${e}\s*(?::\s*[^=]+)?=\s*(\{[\s\S]*?\n\})`,`m`).exec(t);if(r)return ki(r[1])}return{filterable:[],sortable:[],searchable:[]}}function Oi(e,t){let n=new RegExp(String.raw`${t}\s*:\s*\[([\s\S]*?)\]`).exec(e);return n?Array.from(n[1].matchAll(/['"`]([^'"`]+)['"`]/g)).map(e=>e[1]):[]}function ki(e){return{filterable:Oi(e,`filterable`),sortable:Oi(e,`sortable`),searchable:Oi(e,`searchable`)}}async function Ai(e,t){let n=t.extensions??ei,r=t.exclude??ti,i=[],a;try{a=await se(e,{withFileTypes:!0,encoding:`utf-8`})}catch{return i}for(let o of a){let a=h(e,o.name),s=_(t.cwd,a);r.some(e=>s.includes(e))||(o.isDirectory()?i.push(...await Ai(a,t)):o.isFile()&&n.some(e=>o.name.endsWith(e))&&i.push(a))}return i}function W(e,t){return _(t,e).split(y).join(`/`)}function ji(e,t,n){let r=[],i=W(t,n);ni.lastIndex=0;let a;for(;(a=ni.exec(e))!==null;){let[,e,n,o]=a;r.push({className:o,decorator:e,filePath:t,relativePath:i,isDefault:!!n})}ri.lastIndex=0;let o;for(;(o=ri.exec(e))!==null;){let[,e,n]=o;r.some(e=>e.className===n&&e.filePath===t)||r.push({className:n,decorator:`Module`,filePath:t,relativePath:i,isDefault:!!e})}return r}function Mi(e,t,n){let r=[],i=W(t,n),a=new Set;ii.lastIndex=0;let o;for(;(o=ii.exec(e))!==null;){let[e,n,s]=o;a.add(e),r.push({name:s,variable:n,filePath:t,relativePath:i})}for(ai.lastIndex=0;(o=ai.exec(e))!==null;)a.has(o[0])||r.push({name:o[1],variable:null,filePath:t,relativePath:i});return r}function Ni(e,t,n,r,i=new Map){let a=[];if(r.length===0)return a;let o=W(t,n),s=[];for(let t of r){let n=new RegExp(String.raw`class\s+${t.className}\b`).exec(e);n?.index!==void 0&&s.push({cls:t,start:n.index})}s.sort((e,t)=>e.start-t.start);for(let n=0;n<s.length;n++){let{cls:r,start:c}=s[n],l=n+1<s.length?s[n+1].start:e.length,u=e.slice(c,l);di.lastIndex=0;let d;for(;(d=di.exec(u))!==null;){let n=d[1],s=d.index,c=di.lastIndex-1,l=fi(u,c);if(l<0)continue;let f=u.slice(c+1,l),p=f.match(/^\s*['"`]([^'"`]*)['"`]/),m=p&&p[1].length>0?p[1]:`/`,h=pi(u,l+1);if(!h)continue;let{methodName:g,endPos:_}=h;di.lastIndex=_;let v=Ei(u.slice(s,_),e),y=wi(f,`body`),b=wi(f,`query`),x=wi(f,`params`),ee=i.get(r.className)??``,S=ee?hi(ee,m):m;a.push({controller:r.className,method:g,httpMethod:n.toUpperCase(),path:m,pathParams:mi(S),queryFilterable:v?.filterable??null,querySortable:v?.sortable??null,querySearchable:v?.searchable??null,bodySchema:y?{identifier:y,source:Ti(e,y)}:null,querySchema:b?{identifier:b,source:Ti(e,b)}:null,paramsSchema:x?{identifier:x,source:Ti(e,x)}:null,filePath:t,relativePath:o})}}return a}function Pi(e,t,n){let r=[],i=W(t,n);oi.lastIndex=0;let a;for(;(a=oi.exec(e))!==null;)r.push({name:a[1],filePath:t,relativePath:i});return r}function Fi(e,t){let n=1;for(let r=t+1;r<e.length;r++){let t=e[r];if(t===`{`)n++;else if(t===`}`&&(n--,n===0))return r}return-1}function Ii(e,t,n){let r=[],i=W(t,n),a=new Set;si.lastIndex=0;let o;for(;(o=si.exec(e))!==null;){let n=o[1],s=si.lastIndex-1,c=fi(e,s);if(c<0)continue;let l=e.slice(s+1,c),u=/\bname\s*:\s*['"`]([^'"`]+)['"`]/.exec(l);if(!u)continue;let d=u[1],f=`${n}::${d}::${t}`;a.has(f)||(a.add(f),r.push({kind:n===`definePlugin`?`plugin`:`adapter`,name:d,filePath:t,relativePath:i}))}ci.lastIndex=0;let s;for(;(s=ci.exec(e))!==null;){let n=s.index,o=e.indexOf(`{`,n);if(o<0)continue;let c=Fi(e,o);if(c<0)continue;let l=e.slice(o+1,c),u=li.exec(l);if(!u)continue;let d=u[1],f=`class::${d}::${t}`;a.has(f)||(a.add(f),r.push({kind:`adapter`,name:d,filePath:t,relativePath:i}))}return r}function Li(e,t,n){let r=[],i=W(t,n);ui.lastIndex=0;let a;for(;(a=ui.exec(e))!==null;){let n=a[1],o=null,s=null;if(a[2]){let t=e.indexOf(`{`,a.index+a[0].length-1);if(t>=0){let n=Fi(e,t);if(n>=0){let r=e.slice(t+1,n);o=Ri(r,`description`),s=Ri(r,`example`)}}}r.push({name:n,description:o,example:s,filePath:t,relativePath:i})}return r}function Ri(e,t){let n=RegExp(`\\b${t}\\s*:\\s*(['"\`])`,`g`).exec(e);if(!n)return null;let r=n[1],i=n.index+n[0].length,a=i,o=null;for(;a<e.length;){let t=e[a];if(t===`\\`){a+=2;continue}if(t===r){o=e.slice(i,a);break}a++}return o===null?null:o.replace(/\\(.)/g,(e,t)=>t===`n`?`
|
|
3690
|
+
`:t===`t`?` `:t===`r`?`\r`:t)}const zi=[`src/config/index.ts`,`src/config/env.ts`,`src/config.ts`,`src/env.ts`];async function Bi(e,t){let n=t===`src/env.ts`?zi:[t];for(let t of n){let n=v(e,t),r;try{r=await C(n,`utf-8`)}catch{continue}if(/\bdefineEnv\s*\(/.test(r)&&/export\s+default\b/.test(r))return{filePath:n,relativePath:W(n,e)}}return null}function Vi(e){let t=new Map;for(let n of e){let e=t.get(n.className)??[];e.push(n),t.set(n.className,e)}let n=[];for(let[e,r]of t)new Set(r.map(e=>e.filePath)).size>1&&n.push({className:e,classes:r});return n.sort((e,t)=>e.className.localeCompare(t.className)),n}async function Hi(e){let t=await Ai(v(e.root),e),n=[],r=[],i=[],a=[],o=[],s=[],c=new Map;for(let r of t){let t;try{t=await C(r,`utf-8`)}catch{continue}c.set(r,t),n.push(...ji(t,r,e.cwd)),i.push(...Mi(t,r,e.cwd)),a.push(...Pi(t,r,e.cwd)),o.push(...Ii(t,r,e.cwd)),s.push(...Li(t,r,e.cwd))}let l=new Map;for(let[,e]of c)for(let{controller:t,mountPath:n}of Ci(e))l.has(t)||l.set(t,n);for(let[t,i]of c){let a=n.filter(e=>e.filePath===t);r.push(...Ni(i,t,e.cwd,a,l))}let u=[];for(let[e,t]of c){if(!/\.module\.[mc]?[tj]sx?$/.test(e))continue;let r=bi(t);if(r.length===0)continue;let i=e.replaceAll(y,`/`),a=i.slice(0,i.lastIndexOf(`/`));for(let t of n){if(t.decorator===`Module`)continue;let n=t.filePath.replaceAll(y,`/`);n.startsWith(a+`/`)&&n!==i&&(Si(n.slice(a.length+1),r)||u.push({className:t.className,filePath:t.filePath,relativePath:t.relativePath,moduleFilePath:e,decorator:t.decorator}))}}n.sort((e,t)=>e.className===t.className?e.relativePath.localeCompare(t.relativePath):e.className.localeCompare(t.className)),i.sort((e,t)=>e.name.localeCompare(t.name)||e.relativePath.localeCompare(t.relativePath)),a.sort((e,t)=>e.name.localeCompare(t.name)||e.relativePath.localeCompare(t.relativePath)),r.sort((e,t)=>e.controller.localeCompare(t.controller)||e.method.localeCompare(t.method)),o.sort((e,t)=>e.name.localeCompare(t.name)||e.relativePath.localeCompare(t.relativePath)),s.sort((e,t)=>e.name.localeCompare(t.name)||e.relativePath.localeCompare(t.relativePath));let d=Vi(n),f=await Bi(e.cwd,e.envFile??`src/env.ts`);return u.sort((e,t)=>e.relativePath.localeCompare(t.relativePath)||e.className.localeCompare(t.className)),{classes:n,routes:r,tokens:i,injects:a,collisions:d,env:f,pluginsAndAdapters:o,augmentations:s,orphanedClasses:u}}const G="/* eslint-disable */\n// AUTO-GENERATED by `kick typegen`. DO NOT EDIT.\n// Re-run with `kick typegen` or rely on `kick dev` to refresh.\n",Ui=new Set([`Service`,`Repository`,`Injectable`,`Component`]);var Wi=class extends Error{collisions;constructor(e){super(Gi(e)),this.name=`TokenCollisionError`,this.collisions=e}};function Gi(e){let t=[`kick typegen: token collision detected`];for(let n of e){t.push(``),t.push(` ${n.classes.length} classes named '${n.className}':`);for(let e of n.classes)t.push(` - ${e.relativePath}`)}return t.push(``),t.push(`Resolutions:`),t.push(` (a) Rename one of the classes`),t.push(` (b) Use createToken<T>('namespaced/Name') and import the token explicitly — see @forinda/kickjs`),t.push(` (c) Pass --allow-duplicates to namespace the registry keys automatically`),t.push(` (e.g. 'modules/users/UserService' instead of 'UserService')`),t.join(`
|
|
3691
|
+
`)}function Ki(e,t){let n=_(f(t),e).split(y).join(`/`);return n=n.replace(/\.(ts|tsx|mts|cts)$/i,``),n.startsWith(`.`)||(n=`./`+n),n}function qi(e){let t=e.relativePath.replace(/^src\//,``).replace(/\.(ts|tsx|mts|cts)$/i,``).split(`/`);t.pop();let n=t.join(`/`);return n?`${n}/${e.className}`:e.className}function Ji(e,t,n){let r=new Set,i=[];for(let a of e){if(!Ui.has(a.decorator))continue;let e=n.has(a.className)?qi(a):a.className;if(r.has(e))continue;r.add(e);let o=Ki(a.filePath,t),s=a.isDefault?`import('${o}').default`:`import('${o}').${a.className}`;i.push(` '${e}': ${s}`)}return`${G}
|
|
3692
3692
|
declare module '@forinda/kickjs' {
|
|
3693
3693
|
interface KickJsRegistry {
|
|
3694
3694
|
${i.length?i.join(`
|
|
@@ -3697,14 +3697,14 @@ ${i.length?i.join(`
|
|
|
3697
3697
|
}
|
|
3698
3698
|
|
|
3699
3699
|
export {}
|
|
3700
|
-
`}function
|
|
3700
|
+
`}function Yi(e,t,n){return t.length===0?`${G}
|
|
3701
3701
|
// ${n}
|
|
3702
3702
|
export type ${e} = never
|
|
3703
3703
|
`:`${G}
|
|
3704
3704
|
export type ${e} =
|
|
3705
3705
|
${[...new Set(t)].toSorted().map(e=>` | '${e}'`).join(`
|
|
3706
3706
|
`)}
|
|
3707
|
-
`}function
|
|
3707
|
+
`}function Xi(e,t){return`${G}
|
|
3708
3708
|
export type { ServiceToken } from './services'
|
|
3709
3709
|
export type { ModuleToken } from './modules'
|
|
3710
3710
|
|
|
@@ -3720,7 +3720,7 @@ import './plugins'
|
|
|
3720
3720
|
import './augmentations'
|
|
3721
3721
|
${t?`import './kick__assets'
|
|
3722
3722
|
`:``}${e?`import './kick__env'
|
|
3723
|
-
`:``}`}function
|
|
3723
|
+
`:``}`}function Zi(e){let t=new Map;for(let n of e)t.has(n.name)||t.set(n.name,n);return`${G}
|
|
3724
3724
|
declare module '@forinda/kickjs' {
|
|
3725
3725
|
/**
|
|
3726
3726
|
* Map of every plugin/adapter \`name\` discovered in the project. The
|
|
@@ -3735,7 +3735,7 @@ ${[...t.values()].toSorted((e,t)=>e.name.localeCompare(t.name)).map(e=>` '${e
|
|
|
3735
3735
|
}
|
|
3736
3736
|
|
|
3737
3737
|
export {}
|
|
3738
|
-
`}function
|
|
3738
|
+
`}function Qi(e){if(e.length===0)return`${G}
|
|
3739
3739
|
// No augmentations discovered.
|
|
3740
3740
|
//
|
|
3741
3741
|
// Plugins advertise augmentable interfaces via:
|
|
@@ -3759,9 +3759,9 @@ export {}
|
|
|
3759
3759
|
${n.join(`
|
|
3760
3760
|
|
|
3761
3761
|
`)}
|
|
3762
|
-
`}async function
|
|
3762
|
+
`}async function $i(e){let{classes:t,routes:n=[],tokens:r=[],injects:i=[],collisions:a=[],env:o=null,pluginsAndAdapters:s=[],augmentations:c=[],assets:l={entries:[],count:0},outDir:u,allowDuplicates:d=!1,schemaValidator:p=!1}=e;if(a.length>0&&!d)throw new Wi(a);await oe(u,{recursive:!0});let m=h(u,`registry.d.ts`),g=h(u,`services.d.ts`),_=h(u,`modules.d.ts`),v=h(u,`plugins.d.ts`),y=h(u,`augmentations.d.ts`),b=h(u,`index.d.ts`),x=new Set(a.map(e=>e.className)),ee=Ji(t,m,x),S=t.filter(e=>Ui.has(e.decorator)).map(e=>x.has(e.className)?qi(e):e.className),te=r.map(e=>e.name),ne=i.map(e=>e.name),re=[...S,...te,...ne],ie=t.filter(e=>e.decorator===`Module`).map(e=>e.className),ae=Yi(`ServiceToken`,re,"(no tokens discovered — declare with createToken<T>() or `kick g service <name>`)"),C=Yi(`ModuleToken`,ie,"(no @Module classes discovered — `kick g module <name>` to add one)"),se=Zi(s),ce=Qi(c),le=Xi(o!==null,l.count>0);await w(m,ee,`utf-8`),await w(g,ae,`utf-8`),await w(_,C,`utf-8`),await w(v,se,`utf-8`),await w(y,ce,`utf-8`),await w(b,le,`utf-8`);let ue=[m,g,_,v,y,b];await w(h(f(u),`.gitignore`),`# Auto-generated by kick typegen
|
|
3763
3763
|
*
|
|
3764
|
-
`,`utf-8`);let T=new Set(s.map(e=>e.name)).size,E=new Set(c.map(e=>e.name)).size;return{registryEntries:S.length,serviceTokens:new Set(re).size,moduleTokens:ie.length,routeEntries:n.length,pluginEntries:T,augmentationEntries:E,assetEntries:l.count,envWritten:o!==null,written:ue,resolvedCollisions:a.length}}const
|
|
3764
|
+
`,`utf-8`);let T=new Set(s.map(e=>e.name)).size,E=new Set(c.map(e=>e.name)).size;return{registryEntries:S.length,serviceTokens:new Set(re).size,moduleTokens:ie.length,routeEntries:n.length,pluginEntries:T,augmentationEntries:E,assetEntries:l.count,envWritten:o!==null,written:ue,resolvedCollisions:a.length}}const ea=/^(kick\/)?([a-z][\w-]*\/[A-Z]\w*)(\/.+)?(:[a-z][\w-]+(:[a-z][\w-]+)*)?$/;function ta(e){let t=[];for(let n of e){let e=n.name;e.startsWith(`kickjs.`)||ea.test(e)||t.push({token:e,variable:n.variable,filePath:n.relativePath,reason:"does not match `<scope>/<PascalKey>[/<suffix>][:<instance>]`",suggestion:na(e)})}return t}function na(e){if(/^[A-Z]\w*$/.test(e))return`'<scope>/${e}' (e.g. 'mycorp/${e}')`;if(e.includes(`.`))return`consider '<scope>/PascalKey' instead of dotted form`;let t=/^([a-z][\w-]*)\/([a-z]\w*)$/.exec(e);if(t){let[,e,n]=t;return`'${e}/${n.charAt(0).toUpperCase()}${n.slice(1)}'`}}function ra(e,t){if(!e)return{entries:[],count:0};let n=new Map;for(let[r,i]of Object.entries(e)){if(!i||typeof i.src!=`string`)continue;let e=v(t,i.src);if(!ca(e))continue;let a=pe(i.glob??`**/*`,{cwd:e,nodir:!0,dot:!1,posix:!0});a.sort();let{pairs:o}=me(r,a,{strategy:i.keys??`auto`});for(let{key:e}of o){let t=e.slice(r.length+1);n.set(e,{namespace:r,key:t})}}return{entries:[...n.values()],count:n.size}}function ia(e){let t="/* eslint-disable */\n// AUTO-GENERATED by `kick typegen`. DO NOT EDIT.\n// Re-run with `kick typegen` or rely on `kick dev` to refresh.\n";if(e.entries.length===0)return`${t}
|
|
3765
3765
|
declare module '@forinda/kickjs' {
|
|
3766
3766
|
/**
|
|
3767
3767
|
* Map of every typed asset discovered in the project's assetMap.
|
|
@@ -3772,7 +3772,7 @@ declare module '@forinda/kickjs' {
|
|
|
3772
3772
|
}
|
|
3773
3773
|
|
|
3774
3774
|
export {}
|
|
3775
|
-
`;let n={};for(let t of e.entries){let e=`${t.namespace}/${t.key}`.split(`/`),r=n;for(let t=0;t<e.length-1;t++){let n=e[t],i=r[n];if(i===
|
|
3775
|
+
`;let n={};for(let t of e.entries){let e=`${t.namespace}/${t.key}`.split(`/`),r=n;for(let t=0;t<e.length-1;t++){let n=e[t],i=r[n];if(i===aa){let e={};r[n]=e,r=e}else i||(r[n]={}),r=r[n]}let i=e[e.length-1];typeof r[i]!=`object`&&(r[i]=aa)}return`${t}
|
|
3776
3776
|
declare module '@forinda/kickjs' {
|
|
3777
3777
|
/**
|
|
3778
3778
|
* Map of every typed asset discovered in the project's assetMap.
|
|
@@ -3781,30 +3781,30 @@ declare module '@forinda/kickjs' {
|
|
|
3781
3781
|
* prod → dist).
|
|
3782
3782
|
*/
|
|
3783
3783
|
interface KickAssets {
|
|
3784
|
-
${
|
|
3784
|
+
${oa(n,` `)}
|
|
3785
3785
|
}
|
|
3786
3786
|
}
|
|
3787
3787
|
|
|
3788
3788
|
export {}
|
|
3789
|
-
`}const
|
|
3790
|
-
`)}function
|
|
3789
|
+
`}const aa=Symbol(`asset-leaf`);function oa(e,t){let n=Object.keys(e).toSorted(),r=[];for(let i of n){let n=e[i],a=sa(i)?i:JSON.stringify(i);n===aa?r.push(`${t}${a}: () => string`):(r.push(`${t}${a}: {`),r.push(oa(n,`${t} `)),r.push(`${t}}`))}return r.join(`
|
|
3790
|
+
`)}function sa(e){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(e)}function ca(e){try{return c(e).isDirectory()}catch{return!1}}var la=D({runTypegen:()=>K,sweepStaleTypegen:()=>pa,watchTypegen:()=>da});function ua(e){let t=e.cwd??process.cwd();return{cwd:t,srcDir:v(t,e.srcDir??`src`),outDir:v(t,e.outDir??`.kickjs/types`),silent:e.silent??!1,allowDuplicates:e.allowDuplicates??!1,schemaValidator:e.schemaValidator??!1,envFile:e.envFile??`src/env.ts`}}async function K(e={}){let{cwd:t,srcDir:n,outDir:r,silent:i,allowDuplicates:a,schemaValidator:o,envFile:s}=ua(e),c=Date.now(),l=await Hi({root:n,cwd:t,envFile:s===!1?void 0:s}),u=ra(e.assetMap,t),d=await $i({classes:l.classes,routes:l.routes,tokens:l.tokens,injects:l.injects,collisions:l.collisions,env:s===!1?null:l.env,pluginsAndAdapters:l.pluginsAndAdapters,augmentations:l.augmentations,assets:u,outDir:r,allowDuplicates:a,schemaValidator:o}),f=[];if(e.runPlugins!==!1)try{let{runAllPluginTypegens:e}=await Promise.resolve().then(()=>wa),{loadKickConfig:n}=await Promise.resolve().then(()=>Me);f=await e({cwd:t,config:await n(t),silent:!0})}catch(e){if(!i){let t=e instanceof Error?e.message:String(e);console.warn(` kick typegen: plugin pipeline failed (${t}) — continuing`)}}e.runPlugins!==!1&&await pa(r,d.written,f,i);let p=ta(l.tokens),m=Date.now()-c;if(!i){let e=r.replace(t+`/`,``),n=d.resolvedCollisions>0?`, ${d.resolvedCollisions} collisions namespaced`:``,i=d.envWritten?`, env typed`:``,a=d.pluginEntries>0?`, ${d.pluginEntries} plugins/adapters`:``,o=d.augmentationEntries>0?`, ${d.augmentationEntries} augmentations`:``,s=d.assetEntries>0?`, ${d.assetEntries} assets`:``;if(console.log(` kick typegen → ${d.serviceTokens} services, ${d.routeEntries} routes, ${d.moduleTokens} modules${a}${o}${s}${i}${n} → ${e} (${m}ms)`),p.length>0){console.warn(` kick typegen: ${p.length} token(s) don't match the §22.2 convention:`);for(let e of p){let t=e.variable?` [${e.variable}]`:``;console.warn(` '${e.token}' (${e.filePath})${t} — ${e.reason}`),e.suggestion&&console.warn(` → suggestion: ${e.suggestion}`)}}if(l.orphanedClasses.length>0){console.warn(` kick typegen: ${l.orphanedClasses.length} decorated class(es) not matched by any module's import.meta.glob():`);for(let e of l.orphanedClasses)console.warn(` @${e.decorator} ${e.className} (${e.relativePath})`),console.warn(` → not picked up by any glob in ${e.moduleFilePath}`)}}return{scan:l,result:d,tokenWarnings:p}}async function da(e={}){let t=ua(e),{srcDir:n,silent:r,cwd:i}=t,a={...t,allowDuplicates:!0,runPlugins:!1},o=process.env.KICKJS_WATCH_POLLING===`1`||process.env.KICKJS_WATCH_POLLING===`true`,[{runAllPluginTypegens:s},{loadKickConfig:c}]=await Promise.all([Promise.resolve().then(()=>wa),Promise.resolve().then(()=>Me)]),l=await c(i),u=[],d=async()=>{try{u=(await K({...a})).result.written}catch(e){if(r)return;if(e instanceof Wi)console.error(`
|
|
3791
3791
|
`+e.message+`
|
|
3792
|
-
`);else{let t=e instanceof Error?e.message:String(e);console.error(` kick typegen failed: ${t}`)}}},f=async()=>{try{let e=await s({cwd:i,config:l,silent:!0});await
|
|
3792
|
+
`);else{let t=e instanceof Error?e.message:String(e);console.error(` kick typegen failed: ${t}`)}}},f=async()=>{try{let e=await s({cwd:i,config:l,silent:!0});await pa(t.outDir,u,e,!0)}catch{}};await d(),await f();let{watch:p}=await import(`node:fs`),m=null,h=e=>{e&&/\.(ts|tsx|mts|cts)$/.test(e)&&(e.includes(`.kickjs`)||e.endsWith(`.d.ts`)||(m&&clearTimeout(m),m=setTimeout(()=>{d().then(f)},100)))};if(o){r||console.log(` kick typegen: polling mode (KICKJS_WATCH_POLLING)`);let e=setInterval(()=>{fa({...a,silent:!0},!0)},2e3);return()=>clearInterval(e)}let g;try{g=p(n,{recursive:!0},(e,t)=>{h(t)})}catch(e){r||console.warn(` kick typegen: watch mode unavailable (${e?.message??e}). Falling back to polling.`);let t=setInterval(()=>{fa({...a,silent:!0},!0)},2e3);return()=>clearInterval(t)}return()=>{m&&clearTimeout(m),g.close()}}async function fa(e,t){try{await K(e)}catch(e){if(t)return;if(e instanceof Wi)console.error(`
|
|
3793
3793
|
`+e.message+`
|
|
3794
|
-
`);else{let t=e instanceof Error?e.message:String(e);console.error(` kick typegen failed: ${t}`)}}}async function
|
|
3795
|
-
(dry run — no files were written)`),console.log()}async function
|
|
3794
|
+
`);else{let t=e instanceof Error?e.message:String(e);console.error(` kick typegen failed: ${t}`)}}}async function pa(e,t,n,r){let i=new Set;for(let e of t)i.add(d(e));for(let e of n)e.outFile&&i.add(d(e.outFile));let a;try{a=await se(e)}catch{return[]}let o=[];for(let t of a){if(i.has(t))continue;let n=v(e,t);try{if(!(await le(n)).isFile())continue;await ue(n),o.push(t)}catch{}}return o.length>0&&!r&&console.log(` kick typegen: swept ${o.length} stale file(s): ${o.join(`, `)}`),o}const ma=[`agents`,`claude`,`skills`,`gemini`,`copilot`,`both`,`all`];function q(e){return e.parent?.opts()?.dryRun??!1}function J(e,t=!1){let n=process.cwd();console.log(`\n ${t?`Would generate`:`Generated`} ${e.length} file${e.length===1?``:`s`}:`);for(let t of e)console.log(` ${t.replace(n+`/`,``)}`);t&&console.log(`
|
|
3795
|
+
(dry run — no files were written)`),console.log()}async function ha(e){if(!e)try{let e=await k(process.cwd());await K({cwd:process.cwd(),allowDuplicates:!0,silent:!0,schemaValidator:e?.typegen?.schemaValidator??`zod`,envFile:e?.typegen?.envFile,srcDir:e?.typegen?.srcDir,outDir:e?.typegen?.outDir})}catch{}}const ga=[{name:`module <name>`,description:`Full DDD module (controller, DTOs, use-cases, repo)`},{name:`scaffold <name> <fields...>`,description:`CRUD module from field definitions`},{name:`controller <name>`,description:`@Controller() class [-m module]`},{name:`service <name>`,description:`@Service() singleton [-m module]`},{name:`middleware <name>`,description:`Express middleware function [-m module]`},{name:`guard <name>`,description:`Route guard (auth, roles, etc.) [-m module]`},{name:`dto <name>`,description:`Zod DTO schema [-m module]`},{name:`adapter <name>`,description:`AppAdapter with lifecycle hooks (app-level only)`},{name:`test <name>`,description:`Vitest test scaffold [-m module]`},{name:`job <name>`,description:`Queue @Job processor`},{name:`config`,description:`Generate kick.config.ts`},{name:`agents`,description:`Regenerate AGENTS.md + CLAUDE.md + kickjs-skills.md from upstream templates`}];async function _a(){console.log(`
|
|
3796
3796
|
Built-in generators:
|
|
3797
|
-
`);let e=Math.max(...
|
|
3797
|
+
`);let e=Math.max(...ga.map(e=>e.name.length));for(let t of ga)console.log(` kick g ${t.name.padEnd(e+2)} ${t.description}`);let t=await k(process.cwd()),n=He(t?.plugins??[],t?.commands??[]),r=await dn(process.cwd(),n.generators);if(r.generators.length>0){console.log(`
|
|
3798
3798
|
Plugin generators:
|
|
3799
3799
|
`);let e=Math.max(...r.generators.map(e=>`${e.spec.name} <name>`.length));for(let{source:t,spec:n}of r.generators){let r=`${n.name} <name>`;console.log(` kick g ${r.padEnd(e+2)} ${n.description} [${t}]`)}}if(r.failed.length>0){console.log(`
|
|
3800
3800
|
Failed to load:
|
|
3801
|
-
`);for(let{source:e,reason:t}of r.failed)console.log(` ${e} — ${t}`)}console.log()}async function
|
|
3802
|
-
Use -m to scope it to a module: kick g middleware auth -m users`).option(`-o, --out <dir>`,`Output directory (overrides --module)`).option(`-m, --module <module>`,`Place inside a module folder`).action(async(e,t,n)=>{let r=q(n);j(r);let i=await k(process.cwd()),a=O(i),o=a.dir??`src/modules`;J(await
|
|
3803
|
-
Use -m to scope it to a module: kick g guard admin -m users`).option(`-o, --out <dir>`,`Output directory (overrides --module)`).option(`-m, --module <module>`,`Place inside a module folder`).action(async(e,t,n)=>{let r=q(n);j(r);let i=await k(process.cwd()),a=O(i),o=a.dir??`src/modules`;J(await
|
|
3804
|
-
Use -m to scope it to a module: kick g service payment -m orders`).option(`-o, --out <dir>`,`Output directory (overrides --module)`).option(`-m, --module <module>`,`Place inside a module folder`).action(async(e,t,n)=>{let r=q(n);j(r);let i=await k(process.cwd()),a=O(i),o=a.dir??`src/modules`;J(await
|
|
3805
|
-
Use -m to scope it to a module: kick g controller auth -m users`).option(`-o, --out <dir>`,`Output directory (overrides --module)`).option(`-m, --module <module>`,`Place inside a module folder`).action(async(e,t,n)=>{let r=q(n);j(r);let i=await k(process.cwd()),a=O(i),o=a.dir??`src/modules`;J(await
|
|
3806
|
-
Use -m to scope it to a module: kick g dto create-user -m users`).option(`-o, --out <dir>`,`Output directory (overrides --module)`).option(`-m, --module <module>`,`Place inside a module folder`).action(async(e,t,n)=>{let r=q(n);j(r);let i=await k(process.cwd()),a=O(i),o=a.dir??`src/modules`;J(await
|
|
3807
|
-
Use -m to scope it to a module: kick g test user-service -m users`).option(`-o, --out <dir>`,`Output directory (overrides --module)`).option(`-m, --module <module>`,`Place inside a module's __tests__/ folder`).action(async(e,t,n)=>{let r=q(n);j(r);let i=O(await k(process.cwd())),a=i.dir??`src/modules`;J(await
|
|
3801
|
+
`);for(let{source:e,reason:t}of r.failed)console.log(` ${e} — ${t}`)}console.log()}async function va(e,t,n){let r=await k(process.cwd()),i=O(r),a=t.modulesDir??i.dir??`src/modules`,o=t.repo??Zn(i.repo),s=t.pattern??r?.pattern??`ddd`,c=t.pluralize===!1?!1:i.pluralize??!0,l=Ie(r,process.cwd()),u=i.style??`define`;if(!n&&u===`define`){let e=await Fr(v(a),`define`);if(e.length>0){console.error(`\n ${E.red(`Error:`)} ${e.length} module file(s) still use the legacy \`class … implements AppModule\` shape.\n ${E.dim(`Project setting:`)} modules.style: 'define' (default)\n\n ${E.bold(`Files needing migration:`)}`);for(let t of e.slice(0,5))console.error(` - ${t}`);e.length>5&&console.error(` … and ${e.length-5} more`),console.error(`\n ${E.bold(`Pick one:`)}\n 1. Migrate everything to defineModule:\n ${E.dim(`$`)} kick codemod modules --experimental --apply\n 2. Keep the class form — pin it in kick.config.ts:\n ${E.dim(`// kick.config.ts`)}\n ${E.dim(`export default defineConfig({ modules: { style: 'class' } })`)}\n`),process.exit(1)}}let d=[];for(let r of e){let e=await Qn({name:r,modulesDir:v(a),noEntity:t.entity===!1,noTests:t.tests===!1,repo:o,minimal:t.minimal,force:t.force,pattern:s,dryRun:n,pluralize:c,prismaClientPath:i.prismaClientPath,tokenScope:l,style:i.style});d.push(...e)}J(d,n),await ha(n)}function ya(e,t){let n=e.command(`generate [names...]`).alias(`g`).description("Generate code scaffolds — bare form `kick g <name>` is shorthand for `kick g module <name>`").option(`--list`,`List all available generators`).option(`--dry-run`,`Preview files that would be generated without writing them`).option(`--no-entity`,`Skip entity and value object generation (module shortcut)`).option(`--no-tests`,`Skip test file generation (module shortcut)`).option(`--repo <type>`,`Repository implementation: inmemory | drizzle | prisma`).option(`--pattern <pattern>`,`Override project pattern: rest | ddd | cqrs | minimal`).option(`--minimal`,`Shorthand for --pattern minimal`).option(`--modules-dir <dir>`,`Modules directory`).option(`--no-pluralize`,`Use singular names (skip auto-pluralization)`).option(`-f, --force`,`Overwrite existing files without prompting`).action(async(e,r,i)=>{if(r.list){await _a();return}if(!e||e.length===0){n.help();return}let a=q(i);j(a);let[o,s,...c]=e;if(o){let e=await k(process.cwd()),n=He(e?.plugins??[],e?.commands??[]),i=await un({generatorName:o,itemName:s??``,args:c,flags:r,cwd:process.cwd(),projectRoot:t?.projectRoot},n.generators);if(i){J(i.files,a);return}}await va(e,r,a)});n.command(`module <names...>`).description(`Generate one or more modules (e.g. kick g module user task project)`).option(`--no-entity`,`Skip entity and value object generation`).option(`--no-tests`,`Skip test file generation`).option(`--repo <type>`,`Repository implementation: inmemory | drizzle | prisma`).option(`--pattern <pattern>`,`Override project pattern: rest | ddd | cqrs | minimal`).option(`--minimal`,`Shorthand for --pattern minimal`).option(`--modules-dir <dir>`,`Modules directory`).option(`--no-pluralize`,`Use singular names (skip auto-pluralization)`).option(`-f, --force`,`Overwrite existing files without prompting`).action(async(e,t,n)=>{let r=q(n);j(r),await va(e,{...n.optsWithGlobals(),...t},r)}),n.command(`adapter <name>`).description(`Generate an AppAdapter with lifecycle hooks and middleware support`).option(`-o, --out <dir>`,`Output directory`,`src/adapters`).action(async(e,t,n)=>{let r=q(n);j(r),J(await or({name:e,outDir:v(t.out)}),r)}),n.command(`plugin <name>`).description(`Generate a KickPlugin with DI, modules, adapters, middleware, and lifecycle hooks`).option(`-o, --out <dir>`,`Output directory`,`src/plugins`).action(async(e,t,n)=>{let r=q(n);j(r),J(await sr({name:e,outDir:v(t.out)}),r)}),n.command(`middleware <name>`).description(`Generate an Express middleware function
|
|
3802
|
+
Use -m to scope it to a module: kick g middleware auth -m users`).option(`-o, --out <dir>`,`Output directory (overrides --module)`).option(`-m, --module <module>`,`Place inside a module folder`).action(async(e,t,n)=>{let r=q(n);j(r);let i=await k(process.cwd()),a=O(i),o=a.dir??`src/modules`;J(await fr({name:e,outDir:t.out,moduleName:t.module,modulesDir:o,pattern:i?.pattern,pluralize:a.pluralize??!0}),r)}),n.command(`guard <name>`).description(`Generate a route guard (auth, roles, etc.)
|
|
3803
|
+
Use -m to scope it to a module: kick g guard admin -m users`).option(`-o, --out <dir>`,`Output directory (overrides --module)`).option(`-m, --module <module>`,`Place inside a module folder`).action(async(e,t,n)=>{let r=q(n);j(r);let i=await k(process.cwd()),a=O(i),o=a.dir??`src/modules`;J(await pr({name:e,outDir:t.out,moduleName:t.module,modulesDir:o,pattern:i?.pattern,pluralize:a.pluralize??!0}),r)}),n.command(`service <name>`).description(`Generate a @Service() class
|
|
3804
|
+
Use -m to scope it to a module: kick g service payment -m orders`).option(`-o, --out <dir>`,`Output directory (overrides --module)`).option(`-m, --module <module>`,`Place inside a module folder`).action(async(e,t,n)=>{let r=q(n);j(r);let i=await k(process.cwd()),a=O(i),o=a.dir??`src/modules`;J(await mr({name:e,outDir:t.out,moduleName:t.module,modulesDir:o,pattern:i?.pattern,pluralize:a.pluralize??!0}),r)}),n.command(`controller <name>`).description(`Generate a @Controller() class with basic routes
|
|
3805
|
+
Use -m to scope it to a module: kick g controller auth -m users`).option(`-o, --out <dir>`,`Output directory (overrides --module)`).option(`-m, --module <module>`,`Place inside a module folder`).action(async(e,t,n)=>{let r=q(n);j(r);let i=await k(process.cwd()),a=O(i),o=a.dir??`src/modules`;J(await hr({name:e,outDir:t.out,moduleName:t.module,modulesDir:o,pattern:i?.pattern,pluralize:a.pluralize??!0}),r),await ha(r)}),n.command(`dto <name>`).description(`Generate a Zod DTO schema
|
|
3806
|
+
Use -m to scope it to a module: kick g dto create-user -m users`).option(`-o, --out <dir>`,`Output directory (overrides --module)`).option(`-m, --module <module>`,`Place inside a module folder`).action(async(e,t,n)=>{let r=q(n);j(r);let i=await k(process.cwd()),a=O(i),o=a.dir??`src/modules`;J(await gr({name:e,outDir:t.out,moduleName:t.module,modulesDir:o,pattern:i?.pattern,pluralize:a.pluralize??!0}),r)}),n.command(`test <name>`).description(`Generate a Vitest test scaffold
|
|
3807
|
+
Use -m to scope it to a module: kick g test user-service -m users`).option(`-o, --out <dir>`,`Output directory (overrides --module)`).option(`-m, --module <module>`,`Place inside a module's __tests__/ folder`).action(async(e,t,n)=>{let r=q(n);j(r);let i=O(await k(process.cwd())),a=i.dir??`src/modules`;J(await Qr({name:e,outDir:t.out,moduleName:t.module,modulesDir:a,pluralize:i.pluralize??!0}),r)}),n.command(`job <name>`).description(`Generate a @Job queue processor with @Process handlers`).option(`-o, --out <dir>`,`Output directory`,`src/jobs`).option(`-q, --queue <name>`,`Queue name (default: <name>-queue)`).action(async(e,t,n)=>{let r=q(n);j(r),J(await Ir({name:e,outDir:v(t.out),queue:t.queue}),r)}),n.command(`scaffold <name> [fields...]`).description(`Generate a full CRUD module from field definitions
|
|
3808
3808
|
Example: kick g scaffold Post title:string body:text:optional published:boolean:optional
|
|
3809
3809
|
Types: string, text, number, int, float, boolean, date, email, url, uuid, json, enum:a,b,c
|
|
3810
3810
|
Optional: append :optional (shell-safe): description:text:optional
|
|
@@ -3813,11 +3813,11 @@ export {}
|
|
|
3813
3813
|
Usage: kick g scaffold <name> <field:type> [field:type...]
|
|
3814
3814
|
Example: kick g scaffold Post title:string body:text:optional published:boolean:optional
|
|
3815
3815
|
Optional: append :optional (shell-safe, no quoting needed)
|
|
3816
|
-
`),process.exit(1));let a=await k(process.cwd()),o=O(a),s=n.modulesDir??o.dir??`src/modules`,c=
|
|
3817
|
-
`,d=``;if(r(c)&&(d=await C(c,`utf8`)),d===l){o.push({id:n.id,status:`unchanged`,outFile:c});continue}if(e.check)throw Error(`kick typegen --check: drift detected for ${n.id} (${c})`);await w(c,l,`utf8`),o.push({id:n.id,status:`written`,outFile:c})}return o}function
|
|
3818
|
-
`,`utf-8`),s(` ✓ wrote manifest → ${_(n,p)} (${Object.keys(d).length} entries)`),{manifestPath:p,entries:u,manifest:f}}async function
|
|
3816
|
+
`),process.exit(1));let a=await k(process.cwd()),o=O(a),s=n.modulesDir??o.dir??`src/modules`,c=Rr(t),l=Ie(a,process.cwd()),u=a?.pattern??`ddd`;u!==`ddd`&&(console.error(`\n Error: 'kick g scaffold' currently only supports the DDD pattern.\n Detected project pattern: '${u}'.\n Workarounds:\n - Run 'kick g module ${e}' for the ${u} layout (no fields), then add fields manually.\n - Override the pattern for this scaffold by setting kick.config.ts pattern: 'ddd'.\n`),process.exit(1));let d=await zr({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)`:``}`);J(d,i),await ha(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>`,`Default repository type: inmemory | drizzle | prisma`,`inmemory`).option(`-f, --force`,`Overwrite existing kick.config.ts without prompting`).action(async(e,t)=>{let n=q(t);j(n),J(await _r({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 | ddd | cqrs | minimal`).option(`-f, --force`,`Overwrite existing files without prompting`).action(async(e,t)=>{let n=q(t);j(n);let r=e.only??`all`;if(!ma.includes(r)){console.error(` Invalid --only value: ${r}. Expected: ${ma.join(` | `)}`),process.exitCode=1;return}J(await Cr({outDir:v(`.`),only:r,name:e.name,pm:e.pm,template:e.template,force:e.force}),n)});for(let e of t?.generators??[])ba(n,e,t?.projectRoot)}function ba(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=q(o);j(s);let c=await un({generatorName:i.name,itemName:e??``,args:r??[],flags:a,cwd:process.cwd(),projectRoot:n},[t]);c&&J(c.files,s)})}async function xa(e){let t=u.resolve(e.cwd,`.kickjs/types`);await oe(t,{recursive:!0});let n=new Map,i=e.scan??Hi,a={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 oe(u.dirname(r),{recursive:!0}),await w(r,n,`utf8`)},getScanResult:e=>{let t=Sa(e),r=n.get(t);return r||(r=i(e),n.set(t,r)),r},log:console},o=[];for(let n of e.plugins){let i=await n.generate(a);if(i===null){o.push({id:n.id,status:`skipped`});continue}let s=n.outExtension??`.d.ts`,c=u.join(t,`${n.id.replace(/\//g,`__`)}${s}`),l=`/* AUTO-GENERATED by kick typegen — do not edit. Plugin: ${n.id} */\n\n`+i+`
|
|
3817
|
+
`,d=``;if(r(c)&&(d=await C(c,`utf8`)),d===l){o.push({id:n.id,status:`unchanged`,outFile:c});continue}if(e.check)throw Error(`kick typegen --check: drift detected for ${n.id} (${c})`);await w(c,l,`utf8`),o.push({id:n.id,status:`written`,outFile:c})}return o}function Sa(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 Ca(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 wa=D({applyDisableFilter:()=>Ca,runAllPluginTypegens:()=>Ta});async function Ta(e){let{enabled:t,skipped:n,unknown:r}=Ca(He([...ls,...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 xa({cwd:e.cwd,config:e.config??{},plugins:t,check:e.check});if(!e.silent)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[]}}async function Ea(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 Da(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)+`
|
|
3818
|
+
`,`utf-8`),s(` ✓ wrote manifest → ${_(n,p)} (${Object.keys(d).length} entries)`),{manifestPath:p,entries:u,manifest:f}}async function Da(e,t,a,o){let s=v(a,t.src),c=t.dest?v(a,t.dest):h(o,e);if(ka(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)||!Aa(s))return{entrySummary:{namespace:e,src:t.src,dest:_(a,c),filesCopied:0},manifestSlice:{}};let l=await fe(t.glob??`**/*`,{cwd:s,nodir:!0,dot:!1,posix:!0});i(c,{recursive:!0});let u={},{pairs:d,collisionGroupsResolved:p}=me(e,[...l].toSorted(),{strategy:t.keys??`auto`});for(let{rel:e,key:t}of d){let r=h(s,e),a=h(c,e);i(f(a),{recursive:!0}),n(r,a),u[t]=Oa(o,a)}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:l.length},manifestSlice:u}}function Oa(e,t){return _(e,t).split(/[\\/]/).filter(Boolean).join(`/`)}function ka(e,t){let n=_(t,e);return n===``?!1:n.startsWith(`..`)||m(n)}function Aa(e){try{return c(e).isDirectory()}catch{return!1}}function ja(e){if(typeof e==`boolean`)return e;let t=process.env.KICKJS_WATCH_POLLING;return t===`1`||t===`true`}async function Ma(e,t,n={}){t&&(process.env.PORT=t);let r=ja(n.polling),i=process.cwd(),a=await k(i),o=a?.typegen?.schemaValidator??`zod`,s=a?.typegen?.envFile;try{await K({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})`)}await Ta({cwd:i,config:a});let{createRequire:c}=await import(`node:module`),{createServer:l}=await import(x(c(v(`package.json`)).resolve(`vite`)).href),u=await l({configFile:v(`vite.config.ts`),server:{port:t?parseInt(t,10):void 0,...r?{watch:{usePolling:!0,interval:100}}:{}}}),d=a?.assetMap?Object.values(a.assetMap).map(e=>e?.src).filter(e=>typeof e==`string`&&e.length>0).map(e=>v(i,e)):[],f=e=>d.some(t=>e===t||e.startsWith(`${t}/`)),p=null,m=e=>{if(e.includes(`.kickjs`)||e.endsWith(`.d.ts`))return;let t=/\.(ts|tsx|mts|cts)$/.test(e),n=f(e);!t&&!n||(p&&clearTimeout(p),p=setTimeout(()=>{K({cwd:i,silent:!0,allowDuplicates:!0,schemaValidator:o,envFile:s,srcDir:a?.typegen?.srcDir,outDir:a?.typegen?.outDir,assetMap:a?.assetMap,runPlugins:!1}).catch(()=>{}),Ta({cwd:i,config:a,silent:!0}).catch(()=>{})},100))};u.watcher.on(`add`,m),u.watcher.on(`unlink`,m),u.watcher.on(`change`,m),d.length>0&&u.watcher.add(d),await u.listen(),u.printUrls(),console.log(`
|
|
3819
3819
|
KickJS dev server running (Vite + @forinda/kickjs-vite)
|
|
3820
|
-
`);let h=async()=>{p&&clearTimeout(p),await u.close(),process.exit(0)};process.on(`SIGINT`,h),process.on(`SIGTERM`,h)}function
|
|
3820
|
+
`);let h=async()=>{p&&clearTimeout(p),await u.close(),process.exit(0)};process.on(`SIGINT`,h),process.on(`SIGTERM`,h)}function Na(e){e.command(`dev`).description(`Start development server with Vite HMR (zero-downtime reload)`).option(`-e, --entry <file>`,`Entry file`,`src/index.ts`).option(`-p, --port <port>`,`Port number`).option(`--polling`,`Force chokidar to poll for file changes (Docker / WSL / NFS / older kernels)`).action(async e=>{try{await Ma(e.entry,e.port,{polling:e.polling})}catch(e){e.code===`ERR_MODULE_NOT_FOUND`&&e.message?.includes(`vite`)?console.error(`
|
|
3821
3821
|
Error: vite is not installed.
|
|
3822
3822
|
Run: pnpm add -D vite unplugin-swc
|
|
3823
3823
|
`):console.error(`
|
|
@@ -3825,13 +3825,13 @@ export {}
|
|
|
3825
3825
|
Building for production...
|
|
3826
3826
|
`);let{createRequire:e}=await import(`node:module`),{build:t}=await import(x(e(v(`package.json`)).resolve(`vite`)).href);await t({configFile:v(`vite.config.ts`)});let a=await k(process.cwd()),o=a?.copyDirs??[];if(o.length>0){console.log(`
|
|
3827
3827
|
Copying directories to dist...`);for(let e of o){let t=typeof e==`string`?e:e.src,a=typeof e==`string`?h(`dist`,e):e.dest??h(`dist`,t),o=v(t),s=v(a);if(!r(o)){console.log(` ⚠ Skipped ${t} (not found)`);continue}i(s,{recursive:!0}),n(o,s,{recursive:!0}),console.log(` ✓ ${t} → ${a}`)}}if(a?.assetMap&&Object.keys(a.assetMap).length>0){console.log(`
|
|
3828
|
-
Building asset map...`);try{await
|
|
3828
|
+
Building asset map...`);try{await Ea(a,{cwd:process.cwd()})}catch(e){console.error(` ✗ asset build failed: ${e instanceof Error?e.message:String(e)}`),process.exit(1)}}console.log(`
|
|
3829
3829
|
Build complete.
|
|
3830
3830
|
`)}),e.command(`build:assets`).description(`Rebuild the .kickjs-assets.json manifest under the configured outDir (no JS rebuild)`).action(async()=>{let e=await k(process.cwd());if(!e?.assetMap||Object.keys(e.assetMap).length===0){console.log(` No assetMap entries — nothing to build.`);return}console.log(`
|
|
3831
|
-
Building asset map...`);try{await
|
|
3831
|
+
Building asset map...`);try{await Ea(e,{cwd:process.cwd()}),console.log(`
|
|
3832
3832
|
Asset build complete.
|
|
3833
|
-
`)}catch(e){console.error(` ✗ ${e instanceof Error?e.message:String(e)}`),process.exit(1)}}),e.command(`start`).description(`Start production server`).option(`-e, --entry <file>`,`Entry file`,`dist/index.js`).option(`-p, --port <port>`,`Port number`).action(e=>{let t={NODE_ENV:`production`};e.port&&(t.PORT=String(e.port)),ke(e.entry,t)}),e.command(`dev:debug`).description(`Start dev server with Node.js inspector attached`).option(`-e, --entry <file>`,`Entry file`,`src/index.ts`).option(`-p, --port <port>`,`Port number`).option(`--inspect-port <port>`,`Inspector port`,`9229`).action(async e=>{let t=e.inspectPort??`9229`;process.env.NODE_OPTIONS=`--inspect=0.0.0.0:${t}`,console.log(` Debugger: ws://0.0.0.0:${t}`);try{await
|
|
3834
|
-
Dev server (debug) failed:`,e.message??e),process.exit(1)}})}function
|
|
3833
|
+
`)}catch(e){console.error(` ✗ ${e instanceof Error?e.message:String(e)}`),process.exit(1)}}),e.command(`start`).description(`Start production server`).option(`-e, --entry <file>`,`Entry file`,`dist/index.js`).option(`-p, --port <port>`,`Port number`).action(e=>{let t={NODE_ENV:`production`};e.port&&(t.PORT=String(e.port)),ke(e.entry,t)}),e.command(`dev:debug`).description(`Start dev server with Node.js inspector attached`).option(`-e, --entry <file>`,`Entry file`,`src/index.ts`).option(`-p, --port <port>`,`Port number`).option(`--inspect-port <port>`,`Inspector port`,`9229`).action(async e=>{let t=e.inspectPort??`9229`;process.env.NODE_OPTIONS=`--inspect=0.0.0.0:${t}`,console.log(` Debugger: ws://0.0.0.0:${t}`);try{await Ma(e.entry,e.port)}catch(e){console.error(`
|
|
3834
|
+
Dev server (debug) failed:`,e.message??e),process.exit(1)}})}function Pa(e){e.command(`info`).description(`Print system and framework info`).action(()=>{console.log(`
|
|
3835
3835
|
KickJS CLI
|
|
3836
3836
|
|
|
3837
3837
|
System:
|
|
@@ -3842,7 +3842,7 @@ export {}
|
|
|
3842
3842
|
@forinda/kickjs workspace
|
|
3843
3843
|
@forinda/kickjs-vite workspace
|
|
3844
3844
|
@forinda/kickjs-cli workspace
|
|
3845
|
-
`)})}const{bold:Y,dim:X,green:
|
|
3845
|
+
`)})}const{bold:Y,dim:X,green:Fa,red:Ia,yellow:La,blue:Ra}=E;function za(e){let t=Math.floor(e/86400),n=Math.floor(e%86400/3600),r=Math.floor(e%3600/60),i=e%60,a=[];return t&&a.push(`${t}d`),n&&a.push(`${n}h`),r&&a.push(`${r}m`),a.push(`${i}s`),a.join(` `)}async function Ba(e){let t=await fetch(e,{signal:AbortSignal.timeout(5e3)});if(!t.ok)throw Error(`${t.status} ${t.statusText}`);return t.json()}async function Va(e,t){try{return await Ba(`${e}${t}`)}catch{return null}}async function Ha(e){let[t,n,r,i,a]=await Promise.all([Va(e,`/health`),Va(e,`/metrics`),Va(e,`/routes`),Va(e,`/container`),Va(e,`/ws`)]);return{health:t,metrics:n,routes:r,container:i,ws:a}}function Ua(e,t){let{health:n,metrics:r,routes:i,container:a,ws:o}=t,s=X(`─`.repeat(60));if(console.log(),console.log(Y(` KickJS Inspector`)+X(` → ${e}`)),console.log(s),n){let e=n.status===`healthy`?Fa(`● healthy`):Ia(`● `+n.status);console.log(` ${Y(`Health:`)} ${e}`)}else console.log(` ${Y(`Health:`)} ${Ia(`● unreachable`)}`);if(r){let e=((r.errorRate??0)*100).toFixed(1),t=r.errorRate>.1?Ia:r.errorRate>0?La:Fa;console.log(` ${Y(`Uptime:`)} ${za(r.uptimeSeconds)}`),console.log(` ${Y(`Requests:`)} ${r.requests}`),console.log(` ${Y(`Errors:`)} ${r.serverErrors} server, ${r.clientErrors??0} client ${X(`(`)}${t(e+`%`)}${X(`)`)}`)}if(a&&console.log(` ${Y(`DI:`)} ${a.count} bindings`),o&&o.enabled&&console.log(` ${Y(`WS:`)} ${o.connections??0} connections, ${o.namespaces??0} namespaces`),i?.routes?.length){console.log(),console.log(Y(` Routes`)),console.log(s),console.log(` ${X(`METHOD`)} ${X(`PATH`.padEnd(36))} ${X(`CONTROLLER`)}`);for(let e of i.routes){let t=e.path.length>36?e.path.slice(0,33)+`...`:e.path.padEnd(36);console.log(` ${At(e.method)} ${t} ${Ra(e.controller)}.${X(e.handler)}`)}}console.log(s),console.log()}function Wa(e){e.command(`inspect [url]`).description(`Connect to a running KickJS app and display debug info`).option(`-p, --port <port>`,`Override port`).option(`-w, --watch`,`Poll every 5 seconds`).option(`-j, --json`,`Output raw JSON`).action(async(e,t)=>{let n=e??`http://localhost:3000`;if(t.port)try{let e=new URL(n);e.port=t.port,n=e.origin}catch{n=`http://localhost:${t.port}`}let r=`${n.replace(/\/$/,``)}/_debug`,i=async()=>{try{let e=await Ha(r);t.json?console.log(JSON.stringify(e,null,2)):Ua(n,e)}catch(e){t.json?console.log(JSON.stringify({error:String(e)})):(console.error(Ia(` ✖ Could not connect to ${n}`)),console.error(X(` ${e instanceof Error?e.message:String(e)}`))),t.watch||(process.exitCode=1)}};if(t.watch){let e=async()=>{process.stdout.write(`\x1B[2J\x1B[H`),await i()};await e(),setInterval(e,5e3)}else await i()})}function Ga(e,t){let n=e.toLowerCase();return t.every(e=>n.includes(e.toLowerCase()))}function Z(e,t){let n=e.toLowerCase();return t.some(e=>n.includes(e.toLowerCase()))}const Ka=[{match(e,t){let n=Ga(e,[`config`,`get`])&&Z(e,[`undefined`,`null`]),r=e.includes(`@Value`)&&Z(e,[`undefined`,`is not defined`]);return!n&&!r?null:{confidence:n&&r?90:75,diagnosis:{id:`env-schema-not-registered`,title:`ConfigService.get() returns undefined for user-defined keys`,explanation:`Your src/index.ts is missing \`import "./config"\`. That side-effect import
|
|
3846
3846
|
registers the env schema with kickjs at module-load time. Without it,
|
|
3847
3847
|
ConfigService falls back to the base schema (PORT/NODE_ENV/LOG_LEVEL only)
|
|
3848
3848
|
and every user-defined key reads as undefined. @Value() may *appear* to
|
|
@@ -3864,7 +3864,7 @@ describe('UserController', () => {
|
|
|
3864
3864
|
beforeEach(() => Container.reset())
|
|
3865
3865
|
|
|
3866
3866
|
it('does the thing', async () => { /* ... */ })
|
|
3867
|
-
})`,docs:`https://forinda.github.io/kick-js/guide/testing.html`}}:null}},{match(e,t){return e.includes(`@Module`)||
|
|
3867
|
+
})`,docs:`https://forinda.github.io/kick-js/guide/testing.html`}}:null}},{match(e,t){return e.includes(`@Module`)||Ga(e,[`Module`,`is not a function`])||Ga(e,[`Module`,`no exported member`])?{confidence:80,diagnosis:{id:`module-decorator-not-found`,title:`KickJS does not have a @Module decorator (different pattern from NestJS)`,explanation:`NestJS uses @Module({ controllers, providers }). KickJS uses an interface
|
|
3868
3868
|
pattern instead: a class implements AppModule and exposes routes() that
|
|
3869
3869
|
returns the controller wiring. This was a deliberate choice — modules
|
|
3870
3870
|
become explicit values rather than metadata, which makes them easier to
|
|
@@ -3916,24 +3916,24 @@ drop the entry.`,fix:`Open src/modules/index.ts and verify the module is in the
|
|
|
3916
3916
|
import { UserModule } from './users/user.module'
|
|
3917
3917
|
import { TaskModule } from './tasks/task.module' // ← was this missing?
|
|
3918
3918
|
|
|
3919
|
-
export const modules: AppModuleEntry[] = [UserModule(), TaskModule()]`,docs:`https://forinda.github.io/kick-js/guide/project-structure.html`}}:null}}];function
|
|
3919
|
+
export const modules: AppModuleEntry[] = [UserModule(), TaskModule()]`,docs:`https://forinda.github.io/kick-js/guide/project-structure.html`}}:null}}];function qa(e,t){let n=null;for(let r of Ka){let i=null;try{i=r.match(e,t)}catch{continue}!i||i.confidence<40||(!n||i.confidence>n.confidence)&&(n=i)}return n}async function Ja(e){let t=e.provider??`openai`,n=process.env.OPENAI_API_KEY;if(t===`openai`&&!n)return{kind:`unavailable`,reason:`OPENAI_API_KEY environment variable is not set`,suggestion:`Set OPENAI_API_KEY in your shell, e.g.
|
|
3920
3920
|
export OPENAI_API_KEY="sk-..."
|
|
3921
3921
|
|
|
3922
3922
|
Then re-run \`kick explain --ai "<your error>"\`.`};let r;try{r=await import(`@forinda/kickjs-ai`)}catch{return{kind:`unavailable`,reason:`@forinda/kickjs-ai is not installed`,suggestion:`Install the AI package to enable the LLM fallback:
|
|
3923
3923
|
kick add ai
|
|
3924
3924
|
|
|
3925
3925
|
Or manually:
|
|
3926
|
-
pnpm add @forinda/kickjs-ai`}}let{OpenAIProvider:i}=r,a=new i({apiKey:n,defaultChatModel:e.model??`gpt-4o-mini`}),o=
|
|
3927
|
-
`)}function
|
|
3926
|
+
pnpm add @forinda/kickjs-ai`}}let{OpenAIProvider:i}=r,a=new i({apiKey:n,defaultChatModel:e.model??`gpt-4o-mini`}),o=Ya(e.cwd),s=`Error or stack trace:\n\n${e.input.trim()}`;try{let e=Xa((await a.chat({messages:[{role:`system`,content:o},{role:`user`,content:s}]})).content);return e?{kind:`ok`,diagnosis:e}:{kind:`error`,message:`The LLM responded but the payload was not valid JSON in the expected shape. Try again, or file an issue with the error text.`}}catch(e){return{kind:`error`,message:`LLM request failed: ${e instanceof Error?e.message:String(e)}`}}}function Ya(e){return[`You are a diagnostic assistant for KickJS, a decorator-driven Node.js`,`framework built on Express 5 and TypeScript. KickJS projects use:`,` - @Controller, @Get, @Post, @Autowired, @Service, @Value decorators`,` - An AppModule interface with a routes() method (NOT a @Module decorator)`,` - Zod schemas as both runtime validators and OpenAPI sources`,` - Ctx<KickRoutes.ControllerName['method']> for typed request context`,` - src/config/index.ts with defineEnv/loadEnv for env schema`,' - A side-effect `import "./config"` in src/index.ts to register the schema',` - Container.reset() in beforeEach for DI test isolation`,``,`When the user gives you an error message or stack trace, produce a`,`structured diagnosis that helps them fix the bug. You MUST respond`,`with a single JSON object (no surrounding prose, no markdown fences)`,`matching this shape:`,``,`{`,` "id": "<kebab-case-identifier>",`,` "title": "<one-line problem summary>",`,` "explanation": "<multi-line explanation of what is wrong>",`,` "fix": "<multi-line instructions for fixing the problem>",`,` "codeBefore": "<optional: broken code snippet>",`,` "codeAfter": "<optional: corrected code snippet>",`,` "docs": "<optional: KickJS doc URL that discusses this topic>"`,`}`,``,`The KickJS docs live at https://forinda.github.io/kick-js/ — prefer`,`that domain for any doc links you suggest.`,e?`The project is located at ${e}.`:``].filter(e=>e.length>0).join(`
|
|
3927
|
+
`)}function Xa(e){let t=[e,Za(e),Qa(e)].filter(e=>e!==null);for(let e of t)try{let t=JSON.parse(e);if($a(t))return t}catch{continue}return null}function Za(e){let t=e.match(/```(?:json)?\s*\n([\s\S]*?)```/);return t?t[1]?.trim()??null:null}function Qa(e){let t=e.indexOf(`{`);if(t===-1)return null;let n=0,r=!1,i=!1;for(let a=t;a<e.length;a++){let o=e[a];if(i){i=!1;continue}if(o===`\\`&&r){i=!0;continue}if(o===`"`){r=!r;continue}if(!r&&(o===`{`&&n++,o===`}`&&(n--,n===0)))return e.slice(t,a+1)}return null}function $a(e){if(typeof e!=`object`||!e)return!1;let t=e;return typeof t.id==`string`&&typeof t.title==`string`&&typeof t.explanation==`string`&&typeof t.fix==`string`}function eo(e){e.command(`explain [message]`).description(`Explain a KickJS error and suggest a fix`).option(`-m, --message <text>`,`Error message to explain (alternative to positional arg)`).option(`--ai`,`Fall back to LLM if no known-issue matches (requires @forinda/kickjs-ai)`).option(`--model <name>`,`Model name for the --ai fallback`,`gpt-4o-mini`).option(`--json`,`Output the diagnosis as JSON for tooling integration`).action(async(e,t)=>{let n=await ro(e,t.message);(!n||n.trim().length===0)&&(process.stderr.write(`Error: no input provided.
|
|
3928
3928
|
|
|
3929
3929
|
Pass a message as a positional arg, --message flag, or pipe via stdin:
|
|
3930
3930
|
kick explain "config.get returned undefined"
|
|
3931
3931
|
pnpm test 2>&1 | kick explain
|
|
3932
|
-
`),process.exit(1));let r=
|
|
3933
|
-
`);return}if(i){
|
|
3934
|
-
`),process.exit(2)),
|
|
3935
|
-
`),process.exit(a.kind===`ok`?0:2))
|
|
3936
|
-
`)}function
|
|
3932
|
+
`),process.exit(1));let r=ao(),i=qa(n,r);if(t.json&&i){process.stdout.write(JSON.stringify({matched:!0,...i},null,2)+`
|
|
3933
|
+
`);return}if(i){oo(n,i.diagnosis,i.confidence);return}t.ai||(t.json&&(process.stdout.write(JSON.stringify({matched:!1},null,2)+`
|
|
3934
|
+
`),process.exit(2)),so(n,!1),process.exit(2));let a=await Ja({input:n,model:t.model,cwd:r.cwd});t.json&&(process.stdout.write(JSON.stringify(to(a),null,2)+`
|
|
3935
|
+
`),process.exit(a.kind===`ok`?0:2)),no(n,a),process.exit(a.kind===`ok`?0:2)})}function to(e){return e.kind===`ok`?{matched:!0,source:`ai`,diagnosis:e.diagnosis}:e.kind===`unavailable`?{matched:!1,aiUnavailable:!0,reason:e.reason}:{matched:!1,aiError:!0,error:e.message}}function no(e,t){if(t.kind===`ok`){oo(e,t.diagnosis,-1,!0);return}if(t.kind===`unavailable`){process.stdout.write(`\n Explaining: ${lo(e.trim(),200)}\n\n`),process.stdout.write(` AI fallback unavailable: ${t.reason}\n\n`),process.stdout.write(`${co(t.suggestion,` `)}\n\n`);return}process.stdout.write(`\n Explaining: ${lo(e.trim(),200)}\n\n`),process.stdout.write(` AI fallback error: ${t.message}\n\n`)}async function ro(e,t){return e&&e.trim().length>0?e:t&&t.trim().length>0?t:process.stdin.isTTY?``:io()}function io(){return new Promise((e,t)=>{let n=``;process.stdin.setEncoding(`utf8`),process.stdin.on(`data`,e=>{n+=e}),process.stdin.on(`end`,()=>e(n)),process.stdin.on(`error`,t)})}function ao(){let e=process.cwd();return{cwd:e,hasFile:t=>r(v(e,t))}}function oo(e,t,n,r=!1){let i=lo(e.trim(),200),a=r?`AI-generated — verify before applying`:uo(n);process.stdout.write(`\n Explaining: ${i}\n`),process.stdout.write(`\n Match: ${t.id} (${a})\n`),process.stdout.write(` Title: ${t.title}\n`),process.stdout.write(`\n Diagnosis:\n${co(t.explanation,` `)}\n`),process.stdout.write(`\n Fix:\n${co(t.fix,` `)}\n`),t.codeBefore&&process.stdout.write(`\n Before:\n${co(t.codeBefore,` `)}\n`),t.codeAfter&&process.stdout.write(`\n After:\n${co(t.codeAfter,` `)}\n`),t.docs&&process.stdout.write(`\n Docs: ${t.docs}\n`),process.stdout.write(`
|
|
3936
|
+
`)}function so(e,t){let n=lo(e.trim(),200);process.stdout.write(`\n Explaining: ${n}\n\n`),t?process.stdout.write(` No known-issue matched, and --ai fallback is not yet wired.
|
|
3937
3937
|
When @forinda/kickjs-ai ships its provider implementations,
|
|
3938
3938
|
this command will call the configured LLM with the error +
|
|
3939
3939
|
project context and return a structured fix.
|
|
@@ -3950,12 +3950,12 @@ Pass a message as a positional arg, --message flag, or pipe via stdin:
|
|
|
3950
3950
|
3. File an issue with the error text:
|
|
3951
3951
|
https://github.com/forinda/kick-js/issues/new
|
|
3952
3952
|
|
|
3953
|
-
`)}function
|
|
3953
|
+
`)}function co(e,t){return e.split(`
|
|
3954
3954
|
`).map(e=>`${t}${e}`).join(`
|
|
3955
|
-
`)}function
|
|
3956
|
-
`,`utf8`),process.stdout.write(`\n ✓ Wrote MCP server entry "${i}" to ${o}\n\n To activate it:\n 1. Build your app: kick build\n 2. Restart your MCP client (Claude Code, Cursor, Zed)\n 3. The server should appear in the client's tool picker\n\n`)}function
|
|
3955
|
+
`)}function lo(e,t){return e.length<=t?e:e.slice(0,t-1)+`…`}function uo(e){return e>=90?`high confidence`:e>=70?`good match`:e>=50?`medium confidence`:`low confidence — verify manually`}function fo(e){let t=e.command(`mcp`).description(`Model Context Protocol commands (start | init)`);t.command(`start`,{isDefault:!0}).description(`Run the built application as an MCP server over stdio`).option(`-e, --entry <file>`,`Entry file`,`dist/index.js`).option(`--node-arg <arg...>`,`Extra arguments to pass to node`).action(po),t.command(`init`).description(`Generate .mcp.json for Claude Code / Cursor / Zed`).option(`-n, --name <name>`,`Server name (defaults to package.json name)`).option(`-o, --out <file>`,`Output file`,`.mcp.json`).option(`-f, --force`,`Overwrite an existing entry without prompting`).option(`--global`,`Write to ~/.mcp.json instead of the project root`).action(mo)}function po(e){let t=v(e.entry);r(t)||(process.stderr.write(`Error: entry file not found: ${t}\n\nBuild the app first with \`kick build\`, or pass a custom entry:\n kick mcp -e dist/server.js\n`),process.exit(1));let n=[...e.nodeArg??[],t],i=ne(process.execPath,n,{stdio:`inherit`,env:{...process.env,KICK_MCP_STDIO:`1`,NODE_ENV:process.env.NODE_ENV??`production`}});i.on(`error`,e=>{process.stderr.write(`Failed to start MCP server: ${e.message}\n`),process.exit(1)}),i.on(`exit`,(e,t)=>{if(t){process.kill(process.pid,t);return}process.exit(e??0)});let a=e=>{i.killed||i.kill(e)};process.on(`SIGINT`,()=>a(`SIGINT`)),process.on(`SIGTERM`,()=>a(`SIGTERM`))}function mo(e){let t=process.cwd(),n=ho(t)??d(t),i=e.name??n,o=e.global?v(process.env.HOME??`.`,`.mcp.json`):v(t,e.out),s={command:`kick`,args:[`mcp`],cwd:t},c={mcpServers:{}};if(r(o))try{let e=a(o,`utf8`),t=JSON.parse(e);t&&typeof t==`object`&&t.mcpServers&&(c={mcpServers:{...t.mcpServers}})}catch(e){let t=e instanceof Error?e.message:String(e);process.stderr.write(`Error: existing ${o} is not valid JSON (${t}).\nFix the file or pass --force to overwrite the entry.\n`),process.exit(1)}c.mcpServers[i]&&!e.force&&(process.stderr.write(`Error: an entry for "${i}" already exists in ${o}.\nPass --force to overwrite it, or use --name to pick a different key.\n`),process.exit(1)),c.mcpServers[i]=s,l(o,JSON.stringify(c,null,2)+`
|
|
3956
|
+
`,`utf8`),process.stdout.write(`\n ✓ Wrote MCP server entry "${i}" to ${o}\n\n To activate it:\n 1. Build your app: kick build\n 2. Restart your MCP client (Claude Code, Cursor, Zed)\n 3. The server should appear in the client's tool picker\n\n`)}function ho(e){let t=v(e,`package.json`);if(!r(t))return null;try{let e=a(t,`utf8`),n=JSON.parse(e);return typeof n.name==`string`?n.name:null}catch{return null}}function go(e){e.command(`tinker`).description(`Interactive REPL with DI container and services loaded`).option(`-e, --entry <file>`,`Entry file to load`,`src/index.ts`).action(async e=>{let t=process.cwd(),n=v(t,e.entry);r(n)||(console.error(`\n Error: ${e.entry} not found.\n`),process.exit(1));let i=vo(t,`tsx`);i||(console.error(`
|
|
3957
3957
|
Error: tsx not found. Install it: pnpm add -D tsx
|
|
3958
|
-
`),process.exit(1));let a=
|
|
3958
|
+
`),process.exit(1));let a=_o(n,e.entry),o=h(t,`.kick-tinker.mjs`),{writeFileSync:s,unlinkSync:c}=await import(`node:fs`);s(o,a,`utf-8`);try{let e=te(o,[],{cwd:t,execPath:i,stdio:`inherit`});await new Promise(t=>{e.on(`exit`,()=>t())})}finally{try{c(o)}catch{}}})}function _o(e,t){return`
|
|
3959
3959
|
import 'reflect-metadata'
|
|
3960
3960
|
|
|
3961
3961
|
// Prevent bootstrap() from starting the HTTP server
|
|
@@ -4009,15 +4009,15 @@ server.on('exit', () => {
|
|
|
4009
4009
|
console.log('\\n Goodbye!\\n')
|
|
4010
4010
|
process.exit(0)
|
|
4011
4011
|
})
|
|
4012
|
-
`}function
|
|
4012
|
+
`}function vo(e,t){let n=e;for(;;){let e=h(n,`node_modules`,`.bin`,t);if(r(e))return e;let i=v(n,`..`);if(i===n)break;n=i}return null}function yo(e,t){let n=RegExp(`^\\s*${B(t)}Module\\b`),r=!1,i=0,a=e;for(;;){let e=a.indexOf(`.mount(`,i);if(e===-1)break;let t=e+7,o=1,s=t;for(;s<a.length&&o>0;){let e=a.slice(s,s+2);if(e===`//`||e===`/*`){if(e===`//`)for(s+=2;s<a.length&&a[s]!==`
|
|
4013
4013
|
`;)s++;else{for(s+=2;s+1<a.length&&!(a[s]===`*`&&a[s+1]===`/`);)s++;s+=2}continue}let t=a[s]??``;if(t===`'`||t===`"`||t==="`"){let e=t;for(s++;s<a.length&&a[s]!==e;)a[s]===`\\`&&s++,s++}else if(t===`(`)o++;else if(t===`)`&&(o--,o===0))break;s++}if(o!==0)break;let c=a.slice(t,s);if(n.test(c)){let t=e;for(;t>0&&(a[t-1]===` `||a[t-1]===` `||a[t-1]===`
|
|
4014
|
-
`);)t--;a=a.slice(0,t)+a.slice(s+1),r=!0,i=t;continue}i=s+1}return{content:a,changed:r}}function
|
|
4014
|
+
`);)t--;a=a.slice(0,t)+a.slice(s+1),r=!0,i=t;continue}i=s+1}return{content:a,changed:r}}function bo(e,t){let n=tr(e);if(!n)return e;let r=n.rhsStart,i=n.rhsEnd+1,a=e.slice(r,i);return a=yo(a,t).content,a=a.replace(RegExp(`\\s*,?\\s*${B(t)}Module\\b(?:\\s*\\(\\s*\\))?\\s*,?`,`g`),e=>{let t=e.trimStart().startsWith(`,`),n=e.trimEnd().endsWith(`,`);return t&&n?`,`:``}),a=a.replace(/,(\s*])/,`$1`),e.slice(0,r)+a+e.slice(i)}async function xo(e){let{name:t,modulesDir:n,force:r}=e,i=e.pluralize!==!1,a=R(t),o=I(t),s=i?z(a):a,c=h(n,s);if(!await Xe(c)){console.log(`\n Module not found: ${c}\n`);return}if(!r&&!await P({message:E.red(`Delete module '${s}' at ${c}? This cannot be undone.`),initialValue:!1})){console.log(`
|
|
4015
4015
|
Cancelled.
|
|
4016
|
-
`);return}await ce(c,{recursive:!0,force:!0}),console.log(` Deleted: ${c}`);let l=h(n,`index.ts`);if(await Xe(l)){let e=await C(l,`utf-8`),t=e,n=RegExp(`^import\\s*\\{\\s*${B(o)}Module\\s*\\}\\s*from\\s*['"][^'"]*${B(s)}(?:/[^'"]*)?['"].*\\n?`,`gm`);e=e.replace(n,``),e=
|
|
4016
|
+
`);return}await ce(c,{recursive:!0,force:!0}),console.log(` Deleted: ${c}`);let l=h(n,`index.ts`);if(await Xe(l)){let e=await C(l,`utf-8`),t=e,n=RegExp(`^import\\s*\\{\\s*${B(o)}Module\\s*\\}\\s*from\\s*['"][^'"]*${B(s)}(?:/[^'"]*)?['"].*\\n?`,`gm`);e=e.replace(n,``),e=bo(e,o),e=e.replace(/\n{3,}/g,`
|
|
4017
4017
|
|
|
4018
|
-
`),e!==t&&(await w(l,e,`utf-8`),console.log(` Unregistered: ${o}Module from ${l}`))}console.log(`\n Module '${s}' removed.\n`)}function
|
|
4018
|
+
`),e!==t&&(await w(l,e,`utf-8`),console.log(` Unregistered: ${o}Module from ${l}`))}console.log(`\n Module '${s}' removed.\n`)}function So(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=O(await k(process.cwd())),r=t.modulesDir??n.dir??`src/modules`,i=t.pluralize===!1?!1:n.pluralize??!0;for(let n of e)await xo({name:n,modulesDir:v(r),force:t.force,pluralize:i})})}function Co(e){if(e!==void 0){if(e===`false`||e===`off`||e===`none`)return!1;if(e===`zod`)return`zod`;console.warn(` kick typegen: unknown --schema-validator '${e}' (only 'zod' and 'false' are supported). Falling back to project config.`)}}function wo(e){if(e!==void 0)return e===`false`||e===`off`||e===`none`?!1:e}function To(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(`--list`,"List every registered typegen plugin id (use to populate `typegen.disable`)").action(async e=>{let t=$t(process.cwd()),n=await k(t);if(e.list){let{mergeCliPlugins:e}=await Promise.resolve().then(()=>Ue),{builtinCliPlugins:t}=await Promise.resolve().then(()=>cs),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(`
|
|
4019
4019
|
Registered typegen plugins:
|
|
4020
|
-
`);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=Co(e.schemaValidator)??n?.typegen?.schemaValidator??`zod`,i=wo(e.envFile)??n?.typegen?.envFile,a={cwd:t,srcDir:e.src??n?.typegen?.srcDir,outDir:e.out??n?.typegen?.outDir,silent:e.silent,allowDuplicates:e.allowDuplicates,schemaValidator:r,envFile:i,assetMap:n?.assetMap,runPlugins:!1};try{if(e.watch){let t=await
|
|
4020
|
+
`);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=Co(e.schemaValidator)??n?.typegen?.schemaValidator??`zod`,i=wo(e.envFile)??n?.typegen?.envFile,a={cwd:t,srcDir:e.src??n?.typegen?.srcDir,outDir:e.out??n?.typegen?.outDir,silent:e.silent,allowDuplicates:e.allowDuplicates,schemaValidator:r,envFile:i,assetMap:n?.assetMap,runPlugins:!1};try{if(e.watch){let t=await da(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{let{result:r}=await K(a),i=await Ta({cwd:t,config:n??null,silent:e.silent,check:e.check});e.check&&i.some(e=>e.status===`written`)&&process.exit(1),e.check||await pa(v(t,e.out??n?.typegen?.outDir??`.kickjs/types`),r.written,i,e.silent??!1)}}catch(e){e instanceof Wi?console.error(`
|
|
4021
4021
|
`+e.message+`
|
|
4022
4022
|
`):e instanceof Error?console.error(`\n kick typegen failed: ${e.message}`):console.error(`\n kick typegen failed: ${JSON.stringify(e)}`),process.exit(1)}})}function Eo(e){let t=[];if(!r(e))return t;let n=o(e,{withFileTypes:!0});for(let r of n){let n=h(e,r.name);if(r.isDirectory()){if([`node_modules`,`dist`,`.kickjs`,`.git`].includes(r.name))continue;t.push(...Eo(n))}else r.isFile()&&/\.tsx?$/.test(r.name)&&!r.name.endsWith(`.d.ts`)&&t.push(n)}return t}function Do(e){try{return a(e,`utf-8`)}catch{return``}}const Oo=new Set([`secret`,`changeme`,`password`,`test`,`default`,``]);function ko(e,t){let n=Do(h(e,`.env`));if(n){let e=n.match(/^JWT_SECRET\s*=\s*['"]?([^'"\n]*)['"]?/m);if(e){let t=e[1].trim();if(Oo.has(t.toLowerCase())||t.length<32)return{severity:`CRITICAL`,message:`JWT_SECRET appears to be a default value or too short (< 32 chars) — change it`}}}for(let e of t)for(let t of[/JWT_SECRET['"]?\s*[:=]\s*['"]?(secret|changeme|password|test|default)['"]?/i,/secret\s*[:=]\s*['"]?(secret|changeme|password|test|default)['"]?/i])if(t.test(e))return{severity:`CRITICAL`,message:`JWT_SECRET appears to be a default value in source code — use an environment variable`};return null}function Ao(e){for(let t of e)if(/cors\s*\(/.test(t)&&/origin\s*:\s*['"]\*['"]/.test(t))return{severity:`CRITICAL`,message:`CORS origin is '*' — restrict to your domains`};return null}function jo(e){for(let t of e)if(/rateLimit/i.test(t)||/@RateLimit/i.test(t))return null;return{severity:`WARNING`,message:`No rate limiting detected — add rateLimit() middleware or @RateLimit decorator`}}function Mo(){return process.env.NODE_ENV===`production`?null:{severity:`WARNING`,message:`NODE_ENV is '${process.env.NODE_ENV??`undefined`}', not 'production'`}}function No(e){let t=!1,n=!1;for(let r of e)/tokenStore/i.test(r)&&(t=!0),/MemoryTokenStore/i.test(r)&&(n=!0);return n?{severity:`WARNING`,message:`MemoryTokenStore detected — use a persistent store (Redis, DB) for production deployments`}:t?null:{severity:`WARNING`,message:`No token revocation store detected — consider adding one for auth token management`}}function Po(e){for(let t of e)if(/helmet\s*\(/.test(t))return/security\s*\.\s*helmet\s*.*false/.test(t)?{severity:`WARNING`,message:`Helmet security headers are disabled — enable them for production`}:{severity:`INFO`,message:`Helmet security headers active`};return{severity:`WARNING`,message:`Helmet not detected — add helmet() middleware for security headers`}}function Fo(e){for(let t of e)if(/AuthAdapter/i.test(t))return{severity:`INFO`,message:`AuthAdapter configured`};return{severity:`INFO`,message:`No AuthAdapter detected — add one if your app requires authentication`}}function Io(e){let t=Eo(h(e,`src`)).map(e=>Do(e)),n=[],r=ko(e,t);r&&n.push(r);let i=Ao(t);i&&n.push(i);let a=jo(t);a&&n.push(a);let o=Mo();o&&n.push(o);let s=No(t);return s&&n.push(s),n.push(Po(t)),n.push(Fo(t)),n}function Lo(e){e.command(`check`).description(`Audit project for common issues`).option(`--deploy`,`Run production readiness checks`).action(e=>{if(!e.deploy){console.log(`
|
|
4023
4023
|
Usage: kick check --deploy
|
|
@@ -4033,8 +4033,8 @@ server.on('exit', () => {
|
|
|
4033
4033
|
The regex-based rewrite handles the shapes our templates produce.
|
|
4034
4034
|
Hand-rolled modules with non-standard structures may be skipped.
|
|
4035
4035
|
Always commit before running with --apply.
|
|
4036
|
-
`),process.exit(1));let r=O(await k(process.cwd())),i=v(e.modulesDir??r.dir??`src/modules`),a;e.target===`define`||e.target===`class`?a=e.target:e.target===void 0?a=r.style??`define`:(console.error(`\n ${E.red(`Error:`)} --target must be 'define' or 'class' (got '${e.target}').\n`),process.exit(1));let o=E.dim(`→ ${a}`),s=n?E.dim(`(dry-run)`):E.bold(`(applying)`);console.log(`\n ${E.bold(`kick codemod modules`)} ${o} ${s}`),console.log(` modulesDir: ${E.dim(i)}\n`);let c=e.backup!==!1&&!n,l=await
|
|
4037
|
-
`)}});function Go(e){for(let t of Uo){let n=u.resolve(e,t);if(t.endsWith(`.ts`)){if(r(n))return n}else{let e=u.join(n,`index.ts`);if(r(e))return e}}return null}function Ko(e){return e.replace(/\\/g,`/`)}const qo=()=>({id:`kick/assets`,inputs:[`kick.config.ts`,`kick.config.js`,`kick.config.mjs`],async generate(e){if(!r(u.resolve(e.cwd,`kick.config.ts`)))return null;let t=await k(e.cwd);if(!t?.assetMap)return null;let n=
|
|
4036
|
+
`),process.exit(1));let r=O(await k(process.cwd())),i=v(e.modulesDir??r.dir??`src/modules`),a;e.target===`define`||e.target===`class`?a=e.target:e.target===void 0?a=r.style??`define`:(console.error(`\n ${E.red(`Error:`)} --target must be 'define' or 'class' (got '${e.target}').\n`),process.exit(1));let o=E.dim(`→ ${a}`),s=n?E.dim(`(dry-run)`):E.bold(`(applying)`);console.log(`\n ${E.bold(`kick codemod modules`)} ${o} ${s}`),console.log(` modulesDir: ${E.dim(i)}\n`);let c=e.backup!==!1&&!n,l=await Pr(i,{dryRun:n,target:a,backup:c});if(l.backupDir){let e=l.backupDir;console.log(` ${E.green(`✓`)} backup: ${E.dim(e)}\n ${E.dim(`(restore: rm -rf <modulesDir> && mv "<backup>" <modulesDir>)`)}\n`)}else !n&&e.backup===!1&&console.log(` ${E.dim(`(--no-backup — skipping snapshot)`)}\n`);let u=0,d=0;for(let e of l.files)if(e.status===`migrated`)u++,console.log(` ${E.green(`✓`)} ${e.path}`);else{d++;let t=E.dim(`(${e.reason??`skipped`})`);console.log(` ${E.dim(`-`)} ${e.path} ${t}`)}if(console.log(),l.indexStatus===`migrated`)console.log(` ${E.green(`✓`)} ${l.indexPath}`);else if(l.indexStatus===`skipped`){let e=E.dim(`(${l.indexReason??`skipped`})`);console.log(` ${E.dim(`-`)} ${l.indexPath} ${e}`)}else console.log(` ${E.dim(`-`)} ${l.indexPath} ${E.dim(`(not found)`)}`);let f=n?E.dim(` (dry-run — pass --apply to write)`):``;console.log(`\n ${E.bold(String(u))} migrated, ${E.bold(String(d))} skipped${f}\n`)})}const Uo=[`src/db/schema.ts`,`src/db/schema/index.ts`,`src/db/schema`],Wo=()=>({id:`kick/db`,inputs:[`src/db/schema.ts`,`src/db/schema/**/*.ts`],async generate(e){let t=Go(e.cwd);if(!t)return null;let n=u.resolve(e.cwd,`.kickjs/types`);return[`import type { SchemaToTypes, SchemaToRelationsRegister, KickDbClient } from '@forinda/kickjs-db'`,`import type * as appSchema from '${Ko(u.relative(n,t)).replace(/\.ts$/,``).replace(/\/index$/,``)}'`,``,`declare global {`,` interface KickDbSchema extends SchemaToTypes<typeof appSchema> {}`,`}`,``,`declare module '@forinda/kickjs-db' {`,` interface KickDbRegister {`,` db: KickDbClient<KickDbSchema>`,` }`,``,` interface KickDbRelationsRegister {`,` db: SchemaToRelationsRegister<typeof appSchema>`,` }`,`}`].join(`
|
|
4037
|
+
`)}});function Go(e){for(let t of Uo){let n=u.resolve(e,t);if(t.endsWith(`.ts`)){if(r(n))return n}else{let e=u.join(n,`index.ts`);if(r(e))return e}}return null}function Ko(e){return e.replace(/\\/g,`/`)}const qo=()=>({id:`kick/assets`,inputs:[`kick.config.ts`,`kick.config.js`,`kick.config.mjs`],async generate(e){if(!r(u.resolve(e.cwd,`kick.config.ts`)))return null;let t=await k(e.cwd);if(!t?.assetMap)return null;let n=ra(t.assetMap,e.cwd);return n.count===0?null:ia(n)}}),Jo="/* eslint-disable */\n// AUTO-GENERATED by `kick typegen`. DO NOT EDIT.\n// Re-run with `kick typegen` or rely on `kick dev` to refresh.\n";function Yo(e,t,n){if(e.length===0)return`${Jo}
|
|
4038
4038
|
// (no routes discovered yet — annotate a controller method with
|
|
4039
4039
|
// @Get/@Post/@Put/@Delete/@Patch and re-run \`kick typegen\`)
|
|
4040
4040
|
declare global {
|
|
@@ -4092,4 +4092,4 @@ declare global {
|
|
|
4092
4092
|
}
|
|
4093
4093
|
|
|
4094
4094
|
export {}
|
|
4095
|
-
`}const as=()=>({id:`kick/env`,outExtension:`.ts`,inputs:[`src/env.ts`,`src/**/env.ts`,`src/**/*.env.ts`],async generate(e){let t=ss(e);if(t===!1)return null;let n=await e.getScanResult({root:os(e),cwd:e.cwd,envFile:t});if(!n.env)return null;let r=u.resolve(e.cwd,`.kickjs/types/kick__env.ts`);return is(n.env,r)}});function os(e){return u.resolve(e.cwd,e.config?.typegen?.srcDir??`src`)}function ss(e){return e.config?.typegen?.envFile}var cs=D({builtinCliPlugins:()=>ls});const ls=[A({name:`kick/init`,register:Yt}),A({name:`kick/generate`,register:
|
|
4095
|
+
`}const as=()=>({id:`kick/env`,outExtension:`.ts`,inputs:[`src/env.ts`,`src/**/env.ts`,`src/**/*.env.ts`],async generate(e){let t=ss(e);if(t===!1)return null;let n=await e.getScanResult({root:os(e),cwd:e.cwd,envFile:t});if(!n.env)return null;let r=u.resolve(e.cwd,`.kickjs/types/kick__env.ts`);return is(n.env,r)}});function os(e){return u.resolve(e.cwd,e.config?.typegen?.srcDir??`src`)}function ss(e){return e.config?.typegen?.envFile}var cs=D({builtinCliPlugins:()=>ls});const ls=[A({name:`kick/init`,register:Yt}),A({name:`kick/generate`,register:ya}),A({name:`kick/run`,register:Na}),A({name:`kick/info`,register:Pa}),A({name:`kick/inspect`,register:Wa}),A({name:`kick/add`,register:qt}),A({name:`kick/list`,register:Kt}),A({name:`kick/explain`,register:eo}),A({name:`kick/mcp`,register:fo}),A({name:`kick/tinker`,register:go}),A({name:`kick/remove`,register:So}),A({name:`kick/typegen`,register:To}),A({name:`kick/check`,register:Lo}),A({name:`kick/db`,register:Bo,typegens:[Wo()]}),A({name:`kick/codemod`,register:Ho}),A({name:`kick/assets`,typegens:[qo()]}),A({name:`kick/routes`,typegens:[ts()]}),A({name:`kick/env`,typegens:[as()]})],us=f(b(import.meta.url)),ds=JSON.parse(a(h(us,`..`,`package.json`),`utf-8`));async function fs(){let e=new t;e.name(`kick`).description(`KickJS — A production-grade, decorator-driven Node.js framework`).version(ds.version);let n=$t(process.cwd()),r=n,i=await k(r)??{},a=He([...ls,...i.plugins??[]],i.commands??[]);await a.register(e,{cwd:r,projectRoot:n,config:i,log:e=>console.log(e)}),Ae(e,{...i,commands:a.commands}),e.showHelpAfterError(),await e.parseAsync(process.argv)}fs().catch(e=>{console.error(e instanceof Error?e.message:e),process.exitCode=1});export{};
|