@forinda/kickjs-cli 5.4.1 → 5.4.2
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/dist/{builtins-BbJqgLmS.mjs → builtins-CB0cpCRy.mjs} +101 -101
- package/dist/{builtins-BCRm8cUp.mjs → builtins-DNnIUbGs.mjs} +76 -76
- package/dist/{builtins-BCRm8cUp.mjs.map → builtins-DNnIUbGs.mjs.map} +1 -1
- package/dist/cli.mjs +2 -2
- package/dist/{config-q_jBP6Ln.mjs → config-CAjDTnMg.mjs} +2 -2
- package/dist/{config-cyBKEKWL.mjs → config-f_GHcOYT.mjs} +3 -3
- package/dist/{config-cyBKEKWL.mjs.map → config-f_GHcOYT.mjs.map} +1 -1
- package/dist/{generator-extension-CsT2e6Fj.mjs → generator-extension-Ds2fzYZS.mjs} +3 -3
- package/dist/{generator-extension-CsT2e6Fj.mjs.map → generator-extension-Ds2fzYZS.mjs.map} +1 -1
- package/dist/index.mjs +2 -2
- package/dist/{plugin-8R67gfJG.mjs → plugin-CiWyeMpX.mjs} +3 -3
- package/dist/{plugin-8R67gfJG.mjs.map → plugin-CiWyeMpX.mjs.map} +1 -1
- package/dist/{plugin-D6nfJWY0.mjs → plugin-Dz0Yu4Ow.mjs} +2 -2
- package/dist/{rolldown-runtime-B9Lxtctb.mjs → rolldown-runtime-iJll81ez.mjs} +1 -1
- package/dist/{run-plugins-CYRt77yP.mjs → run-plugins-DBOc1G96.mjs} +2 -2
- package/dist/typegen-COBqEd4w.mjs +116 -0
- package/dist/typegen-DzmDwZvN.mjs +117 -0
- package/dist/typegen-DzmDwZvN.mjs.map +1 -0
- package/dist/{types-dPuCyHXz.mjs → types-DucsCMzP.mjs} +2 -2
- package/dist/{types-dPuCyHXz.mjs.map → types-DucsCMzP.mjs.map} +1 -1
- package/package.json +1 -1
- package/dist/typegen-CgWQM1FH.mjs +0 -114
- package/dist/typegen-SyGEEyKv.mjs +0 -115
- package/dist/typegen-SyGEEyKv.mjs.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @forinda/kickjs-cli v5.4.
|
|
2
|
+
* @forinda/kickjs-cli v5.4.2
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Felix Orinda
|
|
5
5
|
*
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
|
-
import{t as e}from"./rolldown-runtime-
|
|
11
|
+
import{t as e}from"./rolldown-runtime-iJll81ez.mjs";import{a as t,i as n,r,t as i}from"./config-CAjDTnMg.mjs";import{n as a,r as o}from"./plugin-Dz0Yu4Ow.mjs";import{a as s,c,i as l,n as u,o as d,s as f,t as p}from"./typegen-COBqEd4w.mjs";import{createRequire as m}from"node:module";import{cpSync as h,existsSync as g,mkdirSync as _,readFileSync as v,readdirSync as y,rmSync as ee,statSync as te,writeFileSync as ne}from"node:fs";import b,{basename as re,dirname as x,extname as ie,isAbsolute as ae,join as S,relative as C,resolve as w,sep as oe}from"node:path";import{fileURLToPath as se,pathToFileURL as T}from"node:url";import{execFileSync as ce,execSync as E,fork as le,spawn as ue,spawnSync as de}from"node:child_process";import{access as fe,copyFile as pe,mkdir as me,readFile as D,readdir as he,rm as ge,stat as _e,writeFile as O}from"node:fs/promises";import*as k from"@clack/prompts";import A from"picocolors";import ve from"pluralize";import{glob as ye}from"glob";import{groupAssetKeys as be}from"@forinda/kickjs";import{arch as xe,platform as Se,release as Ce}from"node:os";import{generate as we,migrateDown as Te,migrateLatest as Ee,migrateRollback as De,migrateStatus as Oe,migrateUp as ke,renderSchemaSource as Ae,resolveDbConfig as je}from"@forinda/kickjs-db";function Me(e,t,n){E(e,{cwd:t,stdio:`inherit`,env:n?{...process.env,...n}:process.env})}function Ne(e,t,n){let r=de(process.execPath,[e],{cwd:n,stdio:`inherit`,env:{...process.env,...t}});r.status!==0&&process.exit(r.status??1)}let Pe=!1;function j(e){Pe=e}const Fe=new Set([`.ts`,`.tsx`,`.js`,`.jsx`,`.mjs`,`.cjs`,`.json`,`.md`]);async function M(e,t){Pe||(await me(x(e),{recursive:!0}),await O(e,t,`utf-8`),Fe.has(ie(e))&&await Le(e,t).catch(()=>{}))}let N;async function Ie(e){if(N!==void 0)return N;try{N=await import(m(S(e,`package.json`)).resolve(`oxfmt`))}catch{N=null}return N}async function Le(e,t){let n=await Ie(process.cwd());if(!n)return;let r=await Re(e);if(r===null)return;let i=await n.format(e,t,r);i.code!==t&&await O(e,i.code,`utf-8`)}const P=new Map;async function Re(e){let t=x(e),n=t;if(P.has(n))return P.get(n);for(;;){let e=S(t,`.oxfmtrc.json`);if(g(e))try{let t=await D(e,`utf-8`),r=JSON.parse(t);return delete r.$schema,delete r.ignorePatterns,P.set(n,r),r}catch{return P.set(n,null),null}let r=x(t);if(r===t)return P.set(n,null),null;t=r}}async function ze(e){try{return await fe(e),!0}catch{return!1}}const Be={auth:`@forinda/kickjs-auth`,swagger:`@forinda/kickjs-swagger`,ws:`@forinda/kickjs-ws`,queue:`@forinda/kickjs-queue`,devtools:`@forinda/kickjs-devtools`};function Ve(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 He(e,t,n,r=[]){let i={"@forinda/kickjs":Ve(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=Be[e];t&&!i[t]&&(i[t]=Ve(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":Ve(n,`@forinda/kickjs-cli`),"@forinda/kickjs-vite":Ve(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 Ue(){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'
|
|
@@ -43,7 +43,7 @@ export default defineConfig({
|
|
|
43
43
|
},
|
|
44
44
|
},
|
|
45
45
|
})
|
|
46
|
-
`}function
|
|
46
|
+
`}function We(){return JSON.stringify({compilerOptions:{target:`ES2022`,module:`ESNext`,moduleResolution:`bundler`,lib:[`ES2022`],types:[`node`,`vite/client`],strict:!0,esModuleInterop:!0,skipLibCheck:!0,sourceMap:!0,declaration:!0,experimentalDecorators:!0,emitDecoratorMetadata:!0,outDir:`dist`,paths:{"@/*":[`./src/*`]}},include:[`src`,`.kickjs/types/**/*.d.ts`,`.kickjs/types/**/*.ts`]},null,2)}function Ge(){return JSON.stringify({semi:!1,singleQuote:!0,trailingComma:`all`,printWidth:100,tabWidth:2},null,2)}function Ke(){return`# https://editorconfig.org
|
|
47
47
|
root = true
|
|
48
48
|
|
|
49
49
|
[*]
|
|
@@ -56,14 +56,14 @@ insert_final_newline = true
|
|
|
56
56
|
|
|
57
57
|
[*.md]
|
|
58
58
|
trim_trailing_whitespace = false
|
|
59
|
-
`}function
|
|
59
|
+
`}function qe(){return`node_modules/
|
|
60
60
|
dist/
|
|
61
61
|
.env
|
|
62
62
|
coverage/
|
|
63
63
|
.DS_Store
|
|
64
64
|
*.tsbuildinfo
|
|
65
65
|
.kickjs/
|
|
66
|
-
`}function
|
|
66
|
+
`}function Je(){return`# Auto-detect text files and normalise line endings to LF
|
|
67
67
|
* text=auto eol=lf
|
|
68
68
|
|
|
69
69
|
# Explicitly mark generated / binary files
|
|
@@ -81,11 +81,11 @@ coverage/
|
|
|
81
81
|
pnpm-lock.yaml -diff linguist-generated
|
|
82
82
|
yarn.lock -diff linguist-generated
|
|
83
83
|
package-lock.json -diff linguist-generated
|
|
84
|
-
`}function
|
|
84
|
+
`}function Ye(){return`PORT=3000
|
|
85
85
|
NODE_ENV=development
|
|
86
|
-
`}function
|
|
86
|
+
`}function Xe(){return`PORT=3000
|
|
87
87
|
NODE_ENV=development
|
|
88
|
-
`}function
|
|
88
|
+
`}function Ze(){return`import { defineConfig } from 'vitest/config'
|
|
89
89
|
import swc from 'unplugin-swc'
|
|
90
90
|
|
|
91
91
|
export default defineConfig({
|
|
@@ -96,7 +96,7 @@ export default defineConfig({
|
|
|
96
96
|
include: ['src/**/*.test.ts'],
|
|
97
97
|
},
|
|
98
98
|
})
|
|
99
|
-
`}function
|
|
99
|
+
`}function Qe(e,t,n,r=[]){switch(t){case`cqrs`:{let t=[],i=[];return r.includes(`devtools`)&&(t.push(`import { DevToolsAdapter } from '@forinda/kickjs-devtools'`),i.push(` DevToolsAdapter(),`)),r.includes(`swagger`)&&(t.push(`import { SwaggerAdapter } from '@forinda/kickjs-swagger'`),i.push(` SwaggerAdapter({\n info: { title: '${e}', version: '${n}' },\n }),`)),`import 'reflect-metadata'
|
|
100
100
|
// Side-effect import — registers the extended env schema with kickjs
|
|
101
101
|
// **before** any controller / service / @Value gets resolved. Without
|
|
102
102
|
// this line ConfigService.get('YOUR_KEY') returns undefined because the
|
|
@@ -166,14 +166,14 @@ export const app = await bootstrap({
|
|
|
166
166
|
express.json(),
|
|
167
167
|
],
|
|
168
168
|
})
|
|
169
|
-
`}}}function
|
|
169
|
+
`}}}function $e(){return`import { defineModules } from '@forinda/kickjs'
|
|
170
170
|
import { HelloModule } from './hello/hello.module'
|
|
171
171
|
|
|
172
172
|
// Remove HelloModule and run: kick g module <name>
|
|
173
173
|
// \`defineModules()\` returns a chainable list — \`kick g module\` appends
|
|
174
174
|
// \`.mount(NewModule())\` to the chain on every generation.
|
|
175
175
|
export const modules = defineModules().mount(HelloModule())
|
|
176
|
-
`}function
|
|
176
|
+
`}function et(){return`import { defineEnv, loadEnv } from '@forinda/kickjs/config'
|
|
177
177
|
import { z } from 'zod'
|
|
178
178
|
|
|
179
179
|
/**
|
|
@@ -208,7 +208,7 @@ const envSchema = defineEnv((base) =>
|
|
|
208
208
|
export const env = loadEnv(envSchema)
|
|
209
209
|
|
|
210
210
|
export default envSchema
|
|
211
|
-
`}function
|
|
211
|
+
`}function tt(){return`import { Service } from '@forinda/kickjs'
|
|
212
212
|
|
|
213
213
|
@Service()
|
|
214
214
|
export class HelloService {
|
|
@@ -220,7 +220,7 @@ export class HelloService {
|
|
|
220
220
|
return { status: 'ok', uptime: process.uptime() }
|
|
221
221
|
}
|
|
222
222
|
}
|
|
223
|
-
`}function
|
|
223
|
+
`}function nt(){return`import { Controller, Get, Autowired, type Ctx } from '@forinda/kickjs'
|
|
224
224
|
import { HelloService } from './hello.service'
|
|
225
225
|
|
|
226
226
|
// \`Ctx<KickRoutes.HelloController['<method>']>\` is generated by
|
|
@@ -242,7 +242,7 @@ export class HelloController {
|
|
|
242
242
|
ctx.json(this.helloService.healthCheck())
|
|
243
243
|
}
|
|
244
244
|
}
|
|
245
|
-
`}function
|
|
245
|
+
`}function rt(){return`import { defineModule } from '@forinda/kickjs'
|
|
246
246
|
import { HelloController } from './hello.controller'
|
|
247
247
|
|
|
248
248
|
export const HelloModule = defineModule({
|
|
@@ -263,7 +263,7 @@ export const HelloModule = defineModule({
|
|
|
263
263
|
},
|
|
264
264
|
}),
|
|
265
265
|
})
|
|
266
|
-
`}function
|
|
266
|
+
`}function it(e,t=`inmemory`,n=`pnpm`){return`import { defineConfig } from '@forinda/kickjs-cli'
|
|
267
267
|
|
|
268
268
|
export default defineConfig({
|
|
269
269
|
pattern: '${e}',
|
|
@@ -307,7 +307,7 @@ export default defineConfig({
|
|
|
307
307
|
},
|
|
308
308
|
],
|
|
309
309
|
})
|
|
310
|
-
`}function
|
|
310
|
+
`}function at(e,t,n){let r={rest:`REST API`,ddd:`Domain-Driven Design`,cqrs:`CQRS + Event-Driven`,minimal:`Minimal`},i=[`@forinda/kickjs`,`@forinda/kickjs-vite`];return t!==`minimal`&&i.push(`@forinda/kickjs-swagger`,`@forinda/kickjs-devtools`),t===`cqrs`&&i.push(`@forinda/kickjs-queue`,`@forinda/kickjs-ws`),`# ${e}
|
|
311
311
|
|
|
312
312
|
A **${r[t]??`REST API`}** built with [KickJS](https://forinda.github.io/kick-js/) — a decorator-driven Node.js framework on Express 5 and TypeScript.
|
|
313
313
|
|
|
@@ -370,7 +370,7 @@ Copy \`.env.example\` to \`.env\` and configure:
|
|
|
370
370
|
|
|
371
371
|
- [KickJS Documentation](https://forinda.github.io/kick-js/)
|
|
372
372
|
- [CLI Reference](https://forinda.github.io/kick-js/api/cli.html)
|
|
373
|
-
`}function
|
|
373
|
+
`}function ot(e,t,n){return`# CLAUDE.md — ${e}
|
|
374
374
|
|
|
375
375
|
**Read \`./AGENTS.md\` first.** It is the canonical, multi-agent
|
|
376
376
|
reference for this project (Claude, Copilot, Codex, Gemini, etc.) —
|
|
@@ -436,7 +436,7 @@ When generating or modifying code in this project, stay aligned with the v4 conv
|
|
|
436
436
|
- **Refresh these files**: \`kick g agents -f\` regenerates \`AGENTS.md\` + \`CLAUDE.md\` from the latest CLI templates. Hand-edited content is overwritten — keep customisation in \`AGENTS.local.md\`.
|
|
437
437
|
|
|
438
438
|
For everything else (controllers, services, modules, RequestContext API, generators, CLI commands, package additions, env wiring, troubleshooting) → \`AGENTS.md\`.
|
|
439
|
-
`}function
|
|
439
|
+
`}function st(e,t,n){return`# AGENTS.md — AI Agent Guide for ${e}
|
|
440
440
|
|
|
441
441
|
This guide is the **canonical, multi-agent reference** for this KickJS
|
|
442
442
|
application — Claude, Copilot, Codex, Gemini, etc. all read it first.
|
|
@@ -943,7 +943,7 @@ ${t===`cqrs`?`### Background Jobs
|
|
|
943
943
|
- [Decorators Guide](https://forinda.github.io/kick-js/guide/decorators.html)
|
|
944
944
|
- [DI System](https://forinda.github.io/kick-js/guide/dependency-injection.html)
|
|
945
945
|
- [Testing](https://forinda.github.io/kick-js/api/testing.html)
|
|
946
|
-
`}function
|
|
946
|
+
`}function ct(e,t,n){return`# kickjs-skills.md — Task Skills for AI Agents (${e})
|
|
947
947
|
|
|
948
948
|
This file is the agent-facing **skills index** for KickJS work in this
|
|
949
949
|
repo. Each block below is a short, rigid workflow keyed to a specific
|
|
@@ -1192,16 +1192,16 @@ description: Patterns to refuse outright when the user asks for them — they br
|
|
|
1192
1192
|
- [Decorators](https://forinda.github.io/kick-js/guide/decorators.html)
|
|
1193
1193
|
- [Context Decorators](https://forinda.github.io/kick-js/guide/context-decorators.html)
|
|
1194
1194
|
- [Testing](https://forinda.github.io/kick-js/api/testing.html)
|
|
1195
|
-
`}const
|
|
1196
|
-
Dependencies installed successfully!`)}catch{console.log(`\n Warning: ${r} install failed. Run it manually.`)}}try{let{runTypegen:e}=await import(`./typegen-
|
|
1197
|
-
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
|
|
1195
|
+
`}const lt=x(se(import.meta.url)),ut=JSON.parse(v(S(lt,`..`,`package.json`),`utf-8`)),dt=`^${ut.version}`,ft=[`@forinda/kickjs`,`@forinda/kickjs-cli`,`@forinda/kickjs-vite`,`@forinda/kickjs-auth`,`@forinda/kickjs-swagger`,`@forinda/kickjs-ws`,`@forinda/kickjs-queue`,`@forinda/kickjs-devtools`,`@forinda/kickjs-testing`];async function pt(){let e=await Promise.all(ft.map(async e=>{try{let t=ce(`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,dt]}));return Object.fromEntries(e)}async function mt(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 pt();if(await M(S(s,`package.json`),He(t,i,l,o)),await M(S(s,`vite.config.ts`),Ue()),await M(S(s,`tsconfig.json`),We()),await M(S(s,`.prettierrc`),Ge()),await M(S(s,`.editorconfig`),Ke()),await M(S(s,`.gitignore`),qe()),await M(S(s,`.gitattributes`),Je()),await M(S(s,`.env`),Ye()),await M(S(s,`.env.example`),Xe()),await M(S(s,`src/config/index.ts`),et()),await M(S(s,`src/index.ts`),Qe(t,i,ut.version,o)),await M(S(s,`src/modules/index.ts`),$e()),await M(S(s,`src/modules/hello/hello.service.ts`),tt()),await M(S(s,`src/modules/hello/hello.controller.ts`),nt()),await M(S(s,`src/modules/hello/hello.module.ts`),rt()),await M(S(s,`kick.config.ts`),it(i,a,r)),await M(S(s,`vitest.config.ts`),Ze()),await M(S(s,`README.md`),at(t,i,r)),await M(S(s,`CLAUDE.md`),ot(t,i,r)),await M(S(s,`AGENTS.md`),st(t,i,r)),await M(S(s,`kickjs-skills.md`),ct(t,i,r)),e.installDeps){console.log(`\n Installing dependencies with ${r}...\n`);try{E(`${r} install`,{cwd:s,stdio:`inherit`}),console.log(`
|
|
1196
|
+
Dependencies installed successfully!`)}catch{console.log(`\n Warning: ${r} install failed. Run it manually.`)}}try{let{runTypegen:e}=await import(`./typegen-COBqEd4w.mjs`).then(e=>e.r);await e({cwd:s,allowDuplicates:!0,silent:!0})}catch{}if(e.initGit)try{E(`git init`,{cwd:s,stdio:`pipe`}),E(`git branch -M main`,{cwd:s,stdio:`pipe`}),E(`git add -A`,{cwd:s,stdio:`pipe`}),E(`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(`
|
|
1197
|
+
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 ht={GET:A.green,POST:A.cyan,PUT:A.yellow,PATCH:A.magenta,DELETE:A.red};function gt(e){return(ht[e]??A.dim)(e.padEnd(7))}function _t(e){let t=`[${e}]`.padEnd(10);switch(e){case`CRITICAL`:return A.red(t);case`WARNING`:return A.yellow(t);case`INFO`:return A.blue(A.dim(t));default:return t}}A.green(`✓`),A.red(`✖`),A.yellow(`⚠`),A.blue(`ℹ`);function vt(e){k.intro(A.bgCyan(A.black(` ${e} `)))}function yt(e){k.outro(e)}function bt(e){k.isCancel(e)&&(k.cancel(`Operation cancelled.`),process.exit(0))}async function xt(e){let t=await k.text(e);return bt(t),t}async function St(e){let t=await k.select(e);return bt(t),t}async function Ct(e){let t=await k.multiselect(e);return bt(t),t}async function F(e){let t=await k.confirm(e);return bt(t),t}function wt(){return k.spinner()}const I=k.log,Tt={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},auth:{pkg:`@forinda/kickjs-auth`,peers:[`jsonwebtoken`],description:`Authentication — JWT, API key, and custom strategies`},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 L(e,t=process.cwd()){let n=t;for(;;){if(g(w(n,e)))return n;let t=x(n);if(t===n)return null;n=t}}function Et(){return L(`pnpm-lock.yaml`)?`pnpm`:L(`yarn.lock`)?`yarn`:L(`bun.lockb`)||L(`bun.lock`)?`bun`:L(`package-lock.json`)?`npm`:null}function Dt(){let e=process.cwd();for(;e;){let t=w(e,`package.json`);if(g(t))try{let e=JSON.parse(v(t,`utf-8`)).packageManager;if(typeof e==`string`){let t=e.split(`@`)[0];if(i.includes(t))return t}}catch{}let n=x(e);if(n===e)return null;e=n}return null}async function Ot(e){if(e&&i.includes(e))return{pm:e,source:`flag`};let t=await r(process.cwd());if(t?.packageManager&&i.includes(t.packageManager))return{pm:t.packageManager,source:`config`};let n=Dt();if(n)return{pm:n,source:`package.json`};let a=Et();return a?{pm:a,source:`lockfile`}:{pm:`npm`,source:`default`}}async function kt(e){let{pm:t}=await Ot(e);return t}function At(e=!1){let t=Object.entries(Tt),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(`
|
|
1198
1198
|
Core packages (always installed by \`kick new\`):
|
|
1199
1199
|
`);for(let e of r)console.log(a(e));if(e){console.log(`
|
|
1200
1200
|
Optional packages (add as needed):
|
|
1201
1201
|
`);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(`
|
|
1202
1202
|
Usage: kick add auth drizzle swagger`),console.log(` kick add queue:bullmq`),console.log()}function jt(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=>{At(!!e.all)})}function Mt(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){At(!!t.all);return}let{pm:n,source:r}=await Ot(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=Tt[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.
|
|
1203
|
-
`),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{
|
|
1204
|
-
`)}})}const Nt=[{value:`auth`,label:`Auth`,hint:`JWT, OAuth, API keys`},{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 Pt(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)=>{
|
|
1203
|
+
`),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{E(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{E(t,{stdio:`inherit`})}catch{console.log(`\n Installation failed. Run manually:\n ${t}\n`)}}console.log(` Done!
|
|
1204
|
+
`)}})}const Nt=[{value:`auth`,label:`Auth`,hint:`JWT, OAuth, API keys`},{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 Pt(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)=>{vt(`KickJS — Create a new project`);let n=!!(t.yes||t.nonInteractive);e||=n?`my-api`:await xt({message:`Project name`,placeholder:`my-api`,defaultValue:`my-api`});let r;if(e===`.`?(r=w(`.`),e=re(r)):r=w(t.directory||e),g(r)){let i=y(r);if(i.length>0){if(t.force)I.warn(`Clearing existing files in ${r}`);else if(n){I.warn(`Directory "${e}" is not empty. Pass --force to clear it.`),yt(`Aborted.`);return}else{I.warn(`Directory "${e}" is not empty:`);let t=i.slice(0,5);for(let e of t)I.message(` - ${e}`);if(i.length>5&&I.message(` ... and ${i.length-5} more`),!await F({message:A.red(`Remove all existing files and proceed?`),initialValue:!1})){yt(`Aborted.`);return}}for(let e of i)ee(w(r,e),{recursive:!0,force:!0})}}let i=t.template;i||=n?`minimal`:await St({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 a=t.pm;a||=n?await kt(void 0):await St({message:`Package manager`,options:[{value:`pnpm`,label:`pnpm`},{value:`npm`,label:`npm`},{value:`yarn`,label:`yarn`},{value:`bun`,label:`bun`}]});let o=t.repo;o||(n?o=`inmemory`:(o=await St({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`}]}),o===`custom`&&(o=await xt({message:`Custom repository name`,defaultValue:`custom`}))));let s;if(t.packages!==void 0){let e=t.packages.trim().toLowerCase();s=e===``||e===`none`||e===`false`?[]:t.packages.split(`,`).map(e=>e.trim()).filter(Boolean)}else s=n?[]:await Ct({message:`Select packages to include`,options:[...Nt],required:!1});let c;c=t.git===void 0?n?!0:await F({message:`Initialize git repository?`,initialValue:!0}):t.git;let l;l=t.install===void 0?n?!0:await F({message:`Install dependencies?`,initialValue:!0}):t.install,await mt({name:e,directory:r,packageManager:a,initGit:c,installDeps:l,template:i,defaultRepo:o,packages:s}),yt(`Done! Next steps: ${A.cyan(`cd ${e} && ${a} dev`)}`)})}function R(e){return e.replace(/[-_\s]+(.)?/g,(e,t)=>t?t.toUpperCase():``).replace(/^(.)/,e=>e.toUpperCase())}function z(e){let t=R(e);return t.charAt(0).toLowerCase()+t.slice(1)}function B(e){return e.replace(/([a-z])([A-Z])/g,`$1-$2`).replace(/[\s_]+/g,`-`).toLowerCase()}function V(e){return ve.plural(e)}function Ft(e){return ve.plural(e)}function It(e){return B(e).replace(/-/g,`_`)}function Lt(e){let t=e.cwd??process.cwd(),n=e.pluralize??!0,r=R(e.name),i=z(e.name),a=B(e.name),o=It(e.name),s={name:e.name,pascal:r,camel:i,kebab:a,snake:o,modulesDir:e.modulesDir??`src/modules`,cwd:t,args:e.args??[],flags:e.flags??{}};if(n){let e=V(a);s.pluralKebab=e,s.pluralPascal=R(e),s.pluralCamel=z(e)}return s}function Rt(e,t){return w(e.cwd,t)}async function zt(e){return import(T(e).href)}const Bt=new Map;async function Vt(e){let t=Bt.get(e);if(t)return t;let n=Ht(e);return Bt.set(e,n),n}async function Ht(e){let t=w(e,`package.json`);if(!g(t))return{generators:[],loaded:[],failed:[]};let n=Ut(JSON.parse(await D(t,`utf-8`))),r=m(w(e,`package.json`)),i=[],a=[],o=[];for(let e of n){let t;try{t=r.resolve(`${e}/package.json`)}catch{continue}let n;try{n=JSON.parse(await D(t,`utf-8`))}catch(t){o.push({source:e,reason:`failed to parse package.json: ${t}`});continue}if(!n.kickjs?.generators)continue;let s=n.kickjs.generators,c=w(x(t),s);if(!g(c)){o.push({source:e,reason:`kickjs.generators points to missing file: ${s}`});continue}let l;try{l=await zt(c)}catch(t){o.push({source:e,reason:`failed to import manifest: ${t}`});continue}let u=l.default;if(!Array.isArray(u)){o.push({source:e,reason:`manifest's default export is not an array of GeneratorSpec`});continue}for(let t of u){if(!Wt(t)){o.push({source:e,reason:`manifest entry is not a valid GeneratorSpec (missing name/files)`});continue}i.push({source:e,spec:t})}a.push(e)}return{generators:i,loaded:a,failed:o}}function Ut(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 Wt(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.name==`string`&&typeof t.files==`function`}async function Gt(e,t=[]){let n=e.cwd??process.cwd(),r=t.find(t=>t.spec.name===e.generatorName);if(r)return Jt(r.spec,r.source,e,n);let i=qt(await Vt(n),e.generatorName);return i?Jt(i.spec,i.source,e,n):null}async function Kt(e,t=[]){let n=await Vt(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 qt(e,t){return e.generators.find(e=>e.spec.name===t)}async function Jt(e,t,n,r){let i=Lt({name:n.itemName,args:n.args,flags:n.flags,modulesDir:n.modulesDir,pluralize:n.pluralize,cwd:r}),a=await e.files(i),o=[];for(let e of a){let t=Rt(i,e.path);await M(t,e.content),o.push(t)}return{files:o,source:t}}function H(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}const Yt={inmemory:`in-memory`,drizzle:`Drizzle`,prisma:`Prisma`};function Xt(e){return e.charAt(0).toUpperCase()+e.slice(1).replace(/-([a-z])/g,(e,t)=>t.toUpperCase())}function Zt(e){return e.replace(/([a-z])([A-Z])/g,`$1-$2`).toLowerCase()}function Qt(e){return Yt[e]??Xt(e)}function $t(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]??`${Xt(n)}${e}Repository`,repoFile:i[n]??`${Zt(n)}-${t}`}}function en(e){return e??`define`}function tn(e){let{pascal:t,kebab:n,plural:r=``,repo:i,style:a}=e,{repoClass:o,repoFile:s}=$t(t,n,i),c=en(a),l=`/**
|
|
1205
1205
|
* ${t} Module
|
|
1206
1206
|
*
|
|
1207
1207
|
* Self-contained feature module following Domain-Driven Design (DDD).
|
|
@@ -1667,7 +1667,7 @@ export interface I${t}Repository {
|
|
|
1667
1667
|
* adopters must NOT use the reserved \`'kick/'\` namespace.
|
|
1668
1668
|
*/
|
|
1669
1669
|
export const ${t.toUpperCase()}_REPOSITORY = createToken<I${t}Repository>('${i}/${t}/repository')
|
|
1670
|
-
`}function
|
|
1670
|
+
`}function U(e){let{pascal:t,kebab:n,repoPrefix:r=`../../domain/repositories`,dtoPrefix:i=`../../application/dtos`}=e;return`/**
|
|
1671
1671
|
* In-Memory ${t} Repository
|
|
1672
1672
|
*
|
|
1673
1673
|
* Implements the repository interface using a Map.
|
|
@@ -2560,7 +2560,7 @@ export class ${t}Controller {
|
|
|
2560
2560
|
ctx.json({ message: '${t} list' })
|
|
2561
2561
|
}
|
|
2562
2562
|
}
|
|
2563
|
-
`)}async function An(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`,nn({pascal:t,kebab:n,plural:r,repo:a,style:l})),await u(`${n}.constants.ts`,bn({pascal:t,kebab:n})),await u(`${n}.controller.ts`,on({pascal:t,kebab:n,plural:r,pluralPascal:i})),await u(`${n}.service.ts`,yn({pascal:t,kebab:n})),await u(`dtos/create-${n}.dto.ts`,cn({pascal:t,kebab:n})),await u(`dtos/update-${n}.dto.ts`,ln({pascal:t,kebab:n})),await u(`dtos/${n}-response.dto.ts`,un({pascal:t,kebab:n})),await u(`${n}.repository.ts`,fn({pascal:t,kebab:n,dtoPrefix:`./dtos`,tokenScope:c}));let d={inmemory:`in-memory-${n}`,drizzle:`drizzle-${n}`,prisma:`prisma-${n}`},f={inmemory:()=>
|
|
2563
|
+
`)}async function An(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`,nn({pascal:t,kebab:n,plural:r,repo:a,style:l})),await u(`${n}.constants.ts`,bn({pascal:t,kebab:n})),await u(`${n}.controller.ts`,on({pascal:t,kebab:n,plural:r,pluralPascal:i})),await u(`${n}.service.ts`,yn({pascal:t,kebab:n})),await u(`dtos/create-${n}.dto.ts`,cn({pascal:t,kebab:n})),await u(`dtos/update-${n}.dto.ts`,ln({pascal:t,kebab:n})),await u(`dtos/${n}-response.dto.ts`,un({pascal:t,kebab:n})),await u(`${n}.repository.ts`,fn({pascal:t,kebab:n,dtoPrefix:`./dtos`,tokenScope:c}));let d={inmemory:`in-memory-${n}`,drizzle:`drizzle-${n}`,prisma:`prisma-${n}`},f={inmemory:()=>U({pascal:t,kebab:n,repoPrefix:`.`,dtoPrefix:`./dtos`}),drizzle:()=>En({pascal:t,kebab:n,repoPrefix:`.`,dtoPrefix:`./dtos`}),prisma:()=>On({pascal:t,kebab:n,repoPrefix:`.`,dtoPrefix:`./dtos`,prismaClientPath:s})},p=d[a]??`${B(a)}-${n}`,m=f[a]??(()=>pn({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`,U({pascal:t,kebab:n,repoPrefix:`.`,dtoPrefix:`./dtos`})),await u(`__tests__/${n}.controller.test.ts`,_n({pascal:t,kebab:n,plural:r})),await u(`__tests__/${n}.repository.test.ts`,vn({pascal:t,kebab:n,plural:r,repoPrefix:`../${d.inmemory??`in-memory-${n}`}.repository`})))}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`,bn({pascal:t,kebab:n})),await u(`${n}.controller.ts`,Sn({pascal:t,kebab:n,plural:r,pluralPascal:i})),await u(`dtos/create-${n}.dto.ts`,cn({pascal:t,kebab:n})),await u(`dtos/update-${n}.dto.ts`,ln({pascal:t,kebab:n})),await u(`dtos/${n}-response.dto.ts`,un({pascal:t,kebab:n}));let d=Cn({pascal:t,kebab:n});for(let e of d)await u(`commands/${e.file}`,e.content);let f=wn({pascal:t,kebab:n,plural:r,pluralPascal:i});for(let e of f)await u(`queries/${e.file}`,e.content);let p=Tn({pascal:t,kebab:n});for(let e of p)await u(`events/${e.file}`,e.content);await u(`${n}.repository.ts`,fn({pascal:t,kebab:n,dtoPrefix:`./dtos`,tokenScope:c}));let m={inmemory:`in-memory-${n}`,drizzle:`drizzle-${n}`,prisma:`prisma-${n}`},h={inmemory:()=>U({pascal:t,kebab:n,repoPrefix:`.`,dtoPrefix:`./dtos`}),drizzle:()=>En({pascal:t,kebab:n,repoPrefix:`.`,dtoPrefix:`./dtos`}),prisma:()=>On({pascal:t,kebab:n,repoPrefix:`.`,dtoPrefix:`./dtos`,prismaClientPath:s})},g=m[a]??`${B(a)}-${n}`,_=h[a]??(()=>pn({pascal:t,kebab:n,repoType:a,repoPrefix:`.`,dtoPrefix:`./dtos`}));await u(`${g}.repository.ts`,_()),o||(a!==`inmemory`&&await u(`in-memory-${n}.repository.ts`,U({pascal:t,kebab:n,repoPrefix:`.`,dtoPrefix:`./dtos`})),await u(`__tests__/${n}.controller.test.ts`,_n({pascal:t,kebab:n,plural:r})),await u(`__tests__/${n}.repository.test.ts`,vn({pascal:t,kebab:n,plural:r,repoPrefix:`../${m.inmemory??`in-memory-${n}`}.repository`})))}async function Mn(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`,tn({pascal:t,kebab:n,plural:r,repo:a,style:u})),await d(`constants.ts`,a===`drizzle`?Dn({pascal:t,kebab:n}):sn({pascal:t,kebab:n})),await d(`presentation/${n}.controller.ts`,an({pascal:t,kebab:n,plural:r,pluralPascal:i})),await d(`application/dtos/create-${n}.dto.ts`,cn({pascal:t,kebab:n})),await d(`application/dtos/update-${n}.dto.ts`,ln({pascal:t,kebab:n})),await d(`application/dtos/${n}-response.dto.ts`,un({pascal:t,kebab:n}));let f=dn({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`,fn({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:()=>U({pascal:t,kebab:n}),drizzle:()=>En({pascal:t,kebab:n}),prisma:()=>On({pascal:t,kebab:n,prismaClientPath:c})},h=p[a]??`${B(a)}-${n}`,g=m[a]??(()=>pn({pascal:t,kebab:n,repoType:a}));await d(`infrastructure/repositories/${h}.repository.ts`,g()),o||(await d(`domain/entities/${n}.entity.ts`,hn({pascal:t,kebab:n})),await d(`domain/value-objects/${n}-id.vo.ts`,gn({pascal:t,kebab:n}))),s||(a!==`inmemory`&&await d(`infrastructure/repositories/in-memory-${n}.repository.ts`,U({pascal:t,kebab:n})),await d(`__tests__/${n}.controller.test.ts`,_n({pascal:t,kebab:n,plural:r})),await d(`__tests__/${n}.repository.test.ts`,vn({pascal:t,kebab:n,plural:r})))}function Nn(e){return e?typeof e==`string`?e:e.name:`inmemory`}async function Pn(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=B(t),d=R(t),f=c?V(u):u,p=c?Ft(d):d,m=S(n,f),h=[],g=o??!1,_={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=S(m,e);if(s){h.push(n);return}if(!g&&await ze(n)&&!await F({message:`File exists: ${A.dim(e)}. Overwrite?`,initialValue:!1})){I.warn(`Skipped: ${e}`);return}await M(n,t),h.push(n)},files:h};switch(l){case`minimal`:await kn(_);break;case`rest`:await An(_);break;case`cqrs`:await jn(_);break;default:await Mn(_);break}return s||await Fn(n,d,f,u,_.style),h}async function Fn(e,t,n,r,i=`define`){let a=S(e,`index.ts`),o=await ze(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'
|
|
2564
2564
|
import { ${t}Module } from '${s}'
|
|
2565
2565
|
|
|
2566
2566
|
export const modules: AppModuleEntry[] = [${c}]
|
|
@@ -2568,11 +2568,11 @@ export const modules: AppModuleEntry[] = [${c}]
|
|
|
2568
2568
|
import { ${t}Module } from '${s}'
|
|
2569
2569
|
|
|
2570
2570
|
export const modules = defineModules().mount(${c})
|
|
2571
|
-
`);return}let l=await
|
|
2571
|
+
`);return}let l=await D(a,`utf-8`),u=`import { ${t}Module } from '${s}'`,d=H(s);if(!RegExp(`^import\\s*\\{[^}]*\\b${H(t)}Module\\b[^}]*\\}\\s*from\\s*['"]${d}['"]`,`m`).test(l)){let e=l.lastIndexOf(`import `);if(e!==-1){let t=l.indexOf(`
|
|
2572
2572
|
`,e);l=l.slice(0,t+1)+u+`
|
|
2573
2573
|
`+l.slice(t+1)}else l=u+`
|
|
2574
|
-
`+l}let f=Ln(l);if(f){let e=l.slice(f.rhsStart,f.rhsEnd+1);RegExp(`\\b${
|
|
2575
|
-
`;)t++;return t}if(n===`/*`){for(t+=2;t+1<e.length&&!(e[t]===`*`&&e[t+1]===`/`);)t++;return t+2}return t}function Bn(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=zn(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 Vn(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=zn(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 Hn(e){let{name:t,outDir:n}=e,r=
|
|
2574
|
+
`+l}let f=Ln(l);if(f){let e=l.slice(f.rhsStart,f.rhsEnd+1);RegExp(`\\b${H(t)}Module\\b`).test(e)||(l=In(l,c))}else l=In(l,c);await O(a,l,`utf-8`)}function In(e,t){let n=Ln(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 Ln(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=Bn(e,n);return t===-1?null:{shape:`array`,rhsStart:n,rhsEnd:t}}if(e.slice(n,n+13)===`defineModules`){let t=Rn(e,n);return t===-1?null:{shape:`chain`,rhsStart:n,rhsEnd:t-1,chainEnd:t}}return null}function Rn(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=Vn(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=Vn(e,t);if(n===-1)break;i=n+1}return i}function zn(e,t){let n=e.slice(t,t+2);if(n===`//`){for(t+=2;t<e.length&&e[t]!==`
|
|
2575
|
+
`;)t++;return t}if(n===`/*`){for(t+=2;t+1<e.length&&!(e[t]===`*`&&e[t+1]===`/`);)t++;return t+2}return t}function Bn(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=zn(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 Vn(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=zn(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 Hn(e){let{name:t,outDir:n}=e,r=B(t),i=R(t),a=[],o=S(n,`${r}.adapter.ts`);return await M(o,`import {
|
|
2576
2576
|
defineAdapter,
|
|
2577
2577
|
type AdapterContext,
|
|
2578
2578
|
type AdapterMiddleware,
|
|
@@ -2741,7 +2741,7 @@ export const ${i}Adapter = defineAdapter<${i}AdapterConfig>({
|
|
|
2741
2741
|
}
|
|
2742
2742
|
},
|
|
2743
2743
|
})
|
|
2744
|
-
`),a.push(o),a}async function Un(e){let{name:t,outDir:n}=e,r=
|
|
2744
|
+
`),a.push(o),a}async function Un(e){let{name:t,outDir:n}=e,r=B(t),i=R(t),a=[],o=S(n,`${r}.plugin.ts`);return await M(o,`import {
|
|
2745
2745
|
definePlugin,
|
|
2746
2746
|
type AppAdapter,
|
|
2747
2747
|
type AppModuleEntry,
|
|
@@ -2885,14 +2885,14 @@ export const ${i}Plugin = definePlugin<${i}PluginConfig>({
|
|
|
2885
2885
|
},
|
|
2886
2886
|
}),
|
|
2887
2887
|
})
|
|
2888
|
-
`),a.push(o),a}const Wn={controller:`presentation`,service:`domain/services`,dto:`application/dtos`,guard:`presentation/guards`,middleware:`middleware`},Gn={controller:``,service:``,dto:`dtos`,guard:`guards`,middleware:`middleware`},Kn={controller:``,service:``,dto:`dtos`,guard:`guards`,middleware:`middleware`,command:`commands`,query:`queries`,event:`events`};function
|
|
2888
|
+
`),a.push(o),a}const Wn={controller:`presentation`,service:`domain/services`,dto:`application/dtos`,guard:`presentation/guards`,middleware:`middleware`},Gn={controller:``,service:``,dto:`dtos`,guard:`guards`,middleware:`middleware`},Kn={controller:``,service:``,dto:`dtos`,guard:`guards`,middleware:`middleware`,command:`commands`,query:`queries`,event:`events`};function W(e){let{type:t,outDir:n,moduleName:r,modulesDir:i=`src/modules`,defaultDir:a,pattern:o=`ddd`,shouldPluralize:s=!0}=e;if(n)return w(n);if(r){let e=o===`ddd`?Wn:o===`cqrs`?Kn:Gn,n=B(r),a=s?V(n):n,c=e[t]??``,l=S(i,a);return w(c?S(l,c):l)}return w(a)}async function qn(e){let{name:t,moduleName:n,modulesDir:r,pattern:i}=e,a=W({type:`middleware`,outDir:e.outDir,moduleName:n,modulesDir:r,defaultDir:`src/middleware`,pattern:i,shouldPluralize:e.pluralize??!0}),o=B(t),s=z(t),c=[],l=S(a,`${o}.middleware.ts`);return await M(l,`import type { Request, Response, NextFunction } from 'express'
|
|
2889
2889
|
|
|
2890
|
-
export interface ${
|
|
2890
|
+
export interface ${R(t)}Options {
|
|
2891
2891
|
// Add configuration options here
|
|
2892
2892
|
}
|
|
2893
2893
|
|
|
2894
2894
|
/**
|
|
2895
|
-
* ${
|
|
2895
|
+
* ${R(t)} middleware.
|
|
2896
2896
|
*
|
|
2897
2897
|
* Usage in bootstrap:
|
|
2898
2898
|
* middleware: [${s}()]
|
|
@@ -2903,13 +2903,13 @@ export interface ${L(t)}Options {
|
|
|
2903
2903
|
* Usage with @Middleware decorator:
|
|
2904
2904
|
* @Middleware(${s}())
|
|
2905
2905
|
*/
|
|
2906
|
-
export function ${s}(options: ${
|
|
2906
|
+
export function ${s}(options: ${R(t)}Options = {}) {
|
|
2907
2907
|
return (req: Request, res: Response, next: NextFunction) => {
|
|
2908
2908
|
// Implement your middleware logic here
|
|
2909
2909
|
next()
|
|
2910
2910
|
}
|
|
2911
2911
|
}
|
|
2912
|
-
`),c.push(l),c}async function Jn(e){let{name:t,moduleName:n,modulesDir:r,pattern:i}=e,a=
|
|
2912
|
+
`),c.push(l),c}async function Jn(e){let{name:t,moduleName:n,modulesDir:r,pattern:i}=e,a=W({type:`guard`,outDir:e.outDir,moduleName:n,modulesDir:r,defaultDir:`src/guards`,pattern:i,shouldPluralize:e.pluralize??!0}),o=B(t),s=z(t),c=R(t),l=[],u=S(a,`${o}.guard.ts`);return await M(u,`import { Container, HttpException } from '@forinda/kickjs'
|
|
2913
2913
|
import type { RequestContext } from '@forinda/kickjs'
|
|
2914
2914
|
|
|
2915
2915
|
/**
|
|
@@ -2945,7 +2945,7 @@ export async function ${s}Guard(ctx: RequestContext, next: () => void): Promise<
|
|
|
2945
2945
|
ctx.res.status(401).json({ message: 'Invalid or expired token' })
|
|
2946
2946
|
}
|
|
2947
2947
|
}
|
|
2948
|
-
`),l.push(u),l}async function Yn(e){let{name:t,moduleName:n,modulesDir:r,pattern:i}=e,a=
|
|
2948
|
+
`),l.push(u),l}async function Yn(e){let{name:t,moduleName:n,modulesDir:r,pattern:i}=e,a=W({type:`service`,outDir:e.outDir,moduleName:n,modulesDir:r,defaultDir:`src/services`,pattern:i,shouldPluralize:e.pluralize??!0}),o=B(t),s=R(t),c=[],l=S(a,`${o}.service.ts`);return await M(l,`import { Service } from '@forinda/kickjs'
|
|
2949
2949
|
|
|
2950
2950
|
@Service()
|
|
2951
2951
|
export class ${s}Service {
|
|
@@ -2954,7 +2954,7 @@ export class ${s}Service {
|
|
|
2954
2954
|
// @Inject(MY_REPO) private readonly repo: IMyRepository,
|
|
2955
2955
|
// ) {}
|
|
2956
2956
|
}
|
|
2957
|
-
`),c.push(l),c}async function Xn(e){let{name:t,moduleName:n,modulesDir:r,pattern:i}=e,a=
|
|
2957
|
+
`),c.push(l),c}async function Xn(e){let{name:t,moduleName:n,modulesDir:r,pattern:i}=e,a=W({type:`controller`,outDir:e.outDir,moduleName:n,modulesDir:r,defaultDir:`src/controllers`,pattern:i,shouldPluralize:e.pluralize??!0}),o=B(t),s=R(t),c=[],l=S(a,`${o}.controller.ts`);return await M(l,`import { Controller, Get, Post, type Ctx } from '@forinda/kickjs'
|
|
2958
2958
|
|
|
2959
2959
|
// \`Ctx<KickRoutes.${s}Controller['<method>']>\` is generated by
|
|
2960
2960
|
// \`kick typegen\` (auto-run on \`kick dev\`). After the first run, your IDE
|
|
@@ -2975,7 +2975,7 @@ export class ${s}Controller {
|
|
|
2975
2975
|
ctx.created({ message: '${s} created', data: ctx.body })
|
|
2976
2976
|
}
|
|
2977
2977
|
}
|
|
2978
|
-
`),c.push(l),c}async function Zn(e){let{name:t,moduleName:n,modulesDir:r,pattern:i}=e,a=
|
|
2978
|
+
`),c.push(l),c}async function Zn(e){let{name:t,moduleName:n,modulesDir:r,pattern:i}=e,a=W({type:`dto`,outDir:e.outDir,moduleName:n,modulesDir:r,defaultDir:`src/dtos`,pattern:i,shouldPluralize:e.pluralize??!0}),o=B(t),s=R(t),c=z(t),l=[],u=S(a,`${o}.dto.ts`);return await M(u,`import { z } from 'zod'
|
|
2979
2979
|
|
|
2980
2980
|
export const ${c}Schema = z.object({
|
|
2981
2981
|
// Define your schema fields here
|
|
@@ -2983,8 +2983,8 @@ export const ${c}Schema = z.object({
|
|
|
2983
2983
|
})
|
|
2984
2984
|
|
|
2985
2985
|
export type ${s}DTO = z.infer<typeof ${c}Schema>
|
|
2986
|
-
`),l.push(u),l}async function Qn(e){let t=
|
|
2987
|
-
Skipped — existing kick.config.ts preserved.`),[]):(await
|
|
2986
|
+
`),l.push(u),l}async function Qn(e){let t=S(e.outDir,`kick.config.ts`),n=e.modulesDir??`src/modules`,r=e.defaultRepo??`inmemory`;return g(t)&&!e.force&&!await F({message:`kick.config.ts already exists. Overwrite?`,initialValue:!1})?(console.log(`
|
|
2987
|
+
Skipped — existing kick.config.ts preserved.`),[]):(await M(t,`import { defineConfig } from '@forinda/kickjs-cli'
|
|
2988
2988
|
|
|
2989
2989
|
export default defineConfig({
|
|
2990
2990
|
modules: {
|
|
@@ -3021,18 +3021,18 @@ export default defineConfig({
|
|
|
3021
3021
|
},
|
|
3022
3022
|
],
|
|
3023
3023
|
})
|
|
3024
|
-
`),[t])}const $n=new Set([`rest`,`ddd`,`cqrs`,`minimal`]);function er(e,t){if(t)return t;try{let t=JSON.parse(
|
|
3024
|
+
`),[t])}const $n=new Set([`rest`,`ddd`,`cqrs`,`minimal`]);function er(e,t){if(t)return t;try{let t=JSON.parse(v(S(e,`package.json`),`utf-8`));if(t.name)return t.name.replace(/^@[^/]+\//,``)}catch{}return e.split(`/`).findLast(Boolean)??`app`}function tr(e,t){if(t)return t;try{let t=JSON.parse(v(S(e,`package.json`),`utf-8`));if(t.packageManager)return t.packageManager.split(`@`)[0]}catch{}return`pnpm`}async function nr(e,t){if(t)return t;try{let t=(await r(e))?.pattern;if(t&&$n.has(t))return t}catch{}return`ddd`}async function rr(e){let t=e.only??`all`,n=er(e.outDir,e.name),r=tr(e.outDir,e.pm),i=await nr(e.outDir,e.template),a=t===`agents`||t===`both`||t===`all`,o=t===`claude`||t===`both`||t===`all`,s=t===`skills`||t===`all`,c=[];a&&c.push({file:S(e.outDir,`AGENTS.md`),render:()=>st(n,i,r)}),o&&c.push({file:S(e.outDir,`CLAUDE.md`),render:()=>ot(n,i,r)}),s&&c.push({file:S(e.outDir,`kickjs-skills.md`),render:()=>ct(n,i,r)});let l=[];for(let{file:t,render:n}of c){if(g(t)&&!e.force&&!await F({message:`${t.replace(e.outDir+`/`,``)} already exists. Overwrite?`,initialValue:!1})){console.log(` Skipped — existing ${t.replace(e.outDir+`/`,``)} preserved.`);continue}await M(t,n()),l.push(t)}return l}function ir(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 G(e,t){let n=t.exec(e);if(!n)return null;let r=n.index+n[0].length-1,i=ir(e,r);return i===-1?null:e.slice(r+1,i)}function K(e,t,n){let r=` `.repeat(n);return e.split(`
|
|
3025
3025
|
`).map(e=>{if(e.trim()===``)return e;let n=RegExp(`^ {0,${t}}`);return r+e.replace(n,``)}).join(`
|
|
3026
|
-
`)}function ar(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 or(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 sr(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=ir(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=
|
|
3026
|
+
`)}function ar(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 or(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 sr(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=ir(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=G(o,/register\s*\(([^)]*)\)\s*:\s*void\s*\{/),u=G(o,/contributors\s*\(\s*\)\s*:\s*ContributorRegistrations\s*\{/),d=G(o,/routes\s*\(\s*\)\s*:\s*[A-Za-z|[\]\s]+\{/);if(!d)return{migrated:null,reason:`routes() method missing or signature unrecognized`};let f=ar(s),p=``;return l&&(p+=` register(container) {${K(l,4,6)} },\n\n`),u&&(p+=` contributors() {${K(u,4,6)} },\n\n`),p+=` routes() {${K(d,4,6)} },`,{migrated:`${f}${`export const ${r} = defineModule({
|
|
3027
3027
|
name: '${r}',
|
|
3028
3028
|
build: () => ({
|
|
3029
3029
|
${p}
|
|
3030
3030
|
}),
|
|
3031
3031
|
})`}${c}`}}function cr(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=ir(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]===`
|
|
3032
|
-
`||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=ir(s,f);if(p===-1)return{migrated:null,reason:`unbalanced build() braces`};let m=s.slice(f+1,p),h=
|
|
3033
|
-
${
|
|
3032
|
+
`||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=ir(s,f);if(p===-1)return{migrated:null,reason:`unbalanced build() braces`};let m=s.slice(f+1,p),h=G(m,/register\s*\(([^)]*)\)\s*\{/),g=G(m,/contributors\s*\(\s*\)\s*\{/),_=G(m,/routes\s*\(\s*\)\s*\{/);if(!_)return{migrated:null,reason:`routes() method missing inside build()`};let v=or(c,{container:h!==null,appModule:!0,moduleRoutes:!0,contributorRegistrations:g!==null}),y=``;return h!==null&&(y+=` register(container: Container): void {${K(h,6,4)} }\n\n`),g!==null&&(y+=` contributors(): ContributorRegistrations {${K(g,6,4)} }\n\n`),y+=` routes(): ModuleRoutes {${K(_,6,4)} }`,{migrated:`${v}${`export class ${r} implements AppModule {
|
|
3033
|
+
${y}
|
|
3034
3034
|
}
|
|
3035
|
-
`}${u}`}}function lr(e,t){return t===`class`?cr(e):sr(e)}function ur(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 dr(e){let t=[];return await n(
|
|
3035
|
+
`}${u}`}}function lr(e,t){return t===`class`?cr(e):sr(e)}function ur(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 dr(e){let t=[];return await n(w(e),0),t;async function n(e,r){let i;try{i=await he(e)}catch{return}for(let a of i){if(a===`node_modules`||a===`dist`||a===`.kickjs`)continue;let i=S(e,a),o;try{o=await _e(i)}catch{continue}o.isDirectory()?await n(i,r+1):(a.endsWith(`.module.ts`)||a===`index.ts`&&r===1)&&t.push(i)}}}async function fr(e,t){let n=0;return await r(e,t),n;async function r(e,t){let i;try{i=await he(e)}catch{return}await me(t,{recursive:!0});for(let a of i){if(a===`node_modules`||a===`dist`||a===`.kickjs`)continue;let i=S(e,a),o=S(t,a),s;try{s=await _e(i)}catch{continue}s.isDirectory()?await r(i,o):(await pe(i,o),n++)}}}function pr(e){return S(e,`.kickjs`,`codemod-backups`,`${new Date().toISOString().replaceAll(/[:.]/g,`-`)}-modules`)}async function mr(e,t){let{dryRun:n=!1,cwd:r=process.cwd(),target:i}=t,a=t.backup??!n,o=await dr(e),s=await D(S(e,`index.ts`),`utf-8`).then(()=>!0,()=>!1),c=null;a&&(o.length>0||s)&&(c=pr(r),await fr(e,c));let l=[];for(let e of o){let t=lr(await D(e,`utf-8`),i);if(t.migrated==null){l.push({path:e,status:`skipped`,reason:t.reason});continue}n||await O(e,t.migrated,`utf-8`),l.push({path:e,status:`migrated`})}let u=S(e,`index.ts`),d=null;try{d=await D(u,`utf-8`)}catch{return{target:i,files:l,indexStatus:`not-found`,indexPath:u,backupDir:c}}let f=ur(d,i);return f.migrated==null?{target:i,files:l,indexStatus:`skipped`,indexPath:u,indexReason:f.reason,backupDir:c}:(n||await O(u,f.migrated,`utf-8`),{target:i,files:l,indexStatus:`migrated`,indexPath:u,backupDir:c})}async function hr(e,t){let n=await dr(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 D(e,`utf-8`);i.test(t)&&r.push(e)}return r}async function gr(e={}){let t=e.strategy??`jwt`,n=e.outDir??`src/modules/auth`,r=S(n,`dto`),i=[],a=S(n,`auth.module.ts`);await M(a,`import { Module } from '@forinda/kickjs'
|
|
3036
3036
|
import { AuthController } from './auth.controller'
|
|
3037
3037
|
import { AuthService } from './auth.service'
|
|
3038
3038
|
|
|
@@ -3041,7 +3041,7 @@ import { AuthService } from './auth.service'
|
|
|
3041
3041
|
services: [AuthService],
|
|
3042
3042
|
})
|
|
3043
3043
|
export class AuthModule {}
|
|
3044
|
-
`),i.push(a);let o=
|
|
3044
|
+
`),i.push(a);let o=S(n,`auth.controller.ts`);await M(o,t===`jwt`?_r():yr()),i.push(o);let s=S(n,`auth.service.ts`);await M(s,t===`jwt`?vr():br()),i.push(s);let c=S(r,`register.dto.ts`);await M(c,`import { z } from 'zod'
|
|
3045
3045
|
|
|
3046
3046
|
export const RegisterDto = z.object({
|
|
3047
3047
|
email: z.string().email(),
|
|
@@ -3050,7 +3050,7 @@ export const RegisterDto = z.object({
|
|
|
3050
3050
|
})
|
|
3051
3051
|
|
|
3052
3052
|
export type RegisterInput = z.infer<typeof RegisterDto>
|
|
3053
|
-
`),i.push(c);let l=
|
|
3053
|
+
`),i.push(c);let l=S(r,`login.dto.ts`);await M(l,`import { z } from 'zod'
|
|
3054
3054
|
|
|
3055
3055
|
export const LoginDto = z.object({
|
|
3056
3056
|
email: z.string().email(),
|
|
@@ -3058,7 +3058,7 @@ export const LoginDto = z.object({
|
|
|
3058
3058
|
})
|
|
3059
3059
|
|
|
3060
3060
|
export type LoginInput = z.infer<typeof LoginDto>
|
|
3061
|
-
`),i.push(l);let u=
|
|
3061
|
+
`),i.push(l);let u=S(n,`auth.test.ts`);if(await M(u,`import { describe, it, expect } from 'vitest'
|
|
3062
3062
|
|
|
3063
3063
|
describe('Auth Module', () => {
|
|
3064
3064
|
it.todo('POST /register — creates a new user')
|
|
@@ -3067,7 +3067,7 @@ describe('Auth Module', () => {
|
|
|
3067
3067
|
it.todo('POST /logout — invalidates session/token')
|
|
3068
3068
|
it.todo('GET /me — returns authenticated user')
|
|
3069
3069
|
})
|
|
3070
|
-
`),i.push(u),e.roleGuards!==!1){let e=
|
|
3070
|
+
`),i.push(u),e.roleGuards!==!1){let e=S(n,`auth.guard.ts`);await M(e,`import { Roles } from '@forinda/kickjs-auth'
|
|
3071
3071
|
|
|
3072
3072
|
/**
|
|
3073
3073
|
* Role-based access guard.
|
|
@@ -3229,7 +3229,7 @@ export class AuthService {
|
|
|
3229
3229
|
return { id: user.id, email: user.email, name: user.name }
|
|
3230
3230
|
}
|
|
3231
3231
|
}
|
|
3232
|
-
`}async function xr(e){let{name:t,outDir:n}=e,r=
|
|
3232
|
+
`}async function xr(e){let{name:t,outDir:n}=e,r=R(t),i=B(t),a=z(t),o=e.queue??`${i}-queue`,s=[];return await(async(e,t)=>{let r=S(n,e);await M(r,t),s.push(r)})(`${i}.job.ts`,`import { Inject } from '@forinda/kickjs'
|
|
3233
3233
|
import { Job, Process, QUEUE_MANAGER, type QueueService } from '@forinda/kickjs-queue'
|
|
3234
3234
|
|
|
3235
3235
|
/**
|
|
@@ -3262,7 +3262,7 @@ export class ${r}Job {
|
|
|
3262
3262
|
// Handle high-priority variant of this job
|
|
3263
3263
|
}
|
|
3264
3264
|
}
|
|
3265
|
-
`),s}const Sr={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 Cr(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=Sr[a];if(!o){let e=[...Object.keys(Sr),`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 wr(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=
|
|
3265
|
+
`),s}const Sr={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 Cr(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=Sr[a];if(!o){let e=[...Object.keys(Sr),`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 wr(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=B(t),d=R(t);z(t);let f=l?V(u):u,p=l?Ft(d):d,m=S(r,f),h=[],g=async(e,t)=>{let n=S(m,e);await M(n,t),h.push(n)};await g(`${u}.module.ts`,Mr(d,u,f,c)),await g(`constants.ts`,Or(d,n)),await g(`presentation/${u}.controller.ts`,Nr(d,u,f,p)),await g(`application/dtos/create-${u}.dto.ts`,Tr(d,n)),await g(`application/dtos/update-${u}.dto.ts`,Er(d,n)),await g(`application/dtos/${u}-response.dto.ts`,Dr(d,n));let _=Ir(d,u,f,p);for(let e of _)await g(`application/use-cases/${e.file}`,e.content);return await g(`domain/repositories/${u}.repository.ts`,Pr(d,u,s)),await g(`domain/services/${u}-domain.service.ts`,Fr(d,u)),o===`inmemory`&&await g(`infrastructure/repositories/in-memory-${u}.repository.ts`,kr(d,u,n)),i||(await g(`domain/entities/${u}.entity.ts`,Ar(d,u,n)),await g(`domain/value-objects/${u}-id.vo.ts`,jr(d))),await Fn(r,d,f,u,c),h}function Tr(e,t){return`import { z } from 'zod'
|
|
3266
3266
|
|
|
3267
3267
|
export const create${e}Schema = z.object({
|
|
3268
3268
|
${t.map(e=>{let t=e.zodType;return` ${e.name}: ${t}${e.optional?`.optional()`:``},`}).join(`
|
|
@@ -3624,7 +3624,7 @@ export class Delete${e}UseCase {
|
|
|
3624
3624
|
constructor(@Inject(${e.toUpperCase()}_REPOSITORY) private repo: I${e}Repository) {}
|
|
3625
3625
|
async execute(id: string) { return this.repo.delete(id) }
|
|
3626
3626
|
}
|
|
3627
|
-
`}]}async function Lr(e){let{name:t,moduleName:n,modulesDir:r}=e,i=e.pluralize??!0,a=
|
|
3627
|
+
`}]}async function Lr(e){let{name:t,moduleName:n,modulesDir:r}=e,i=e.pluralize??!0,a=B(t),o=R(t),s=[],c;if(e.outDir)c=w(e.outDir);else if(n){let e=B(n),t=i?V(e):e;c=w(S(r??`src/modules`,t,`__tests__`))}else c=w(`src/__tests__`);let l=S(c,`${a}.test.ts`);return await M(l,`import { describe, it, expect, beforeEach } from 'vitest'
|
|
3628
3628
|
import { Container } from '@forinda/kickjs'
|
|
3629
3629
|
|
|
3630
3630
|
describe('${o}', () => {
|
|
@@ -3647,32 +3647,32 @@ describe('${o}', () => {
|
|
|
3647
3647
|
expect(true).toBe(true)
|
|
3648
3648
|
})
|
|
3649
3649
|
})
|
|
3650
|
-
`),s.push(l),s}const Rr=[`agents`,`claude`,`skills`,`both`,`all`];function
|
|
3651
|
-
(dry run — no files were written)`),console.log()}async function zr(e){if(!e)try{let e=await r(process.cwd());await
|
|
3650
|
+
`),s.push(l),s}const Rr=[`agents`,`claude`,`skills`,`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(`
|
|
3651
|
+
(dry run — no files were written)`),console.log()}async function zr(e){if(!e)try{let e=await r(process.cwd());await p({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 Br=[{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 Vr(){console.log(`
|
|
3652
3652
|
Built-in generators:
|
|
3653
3653
|
`);let e=Math.max(...Br.map(e=>e.name.length));for(let t of Br)console.log(` kick g ${t.name.padEnd(e+2)} ${t.description}`);let t=await r(process.cwd()),n=a(t?.plugins??[],t?.commands??[]),i=await Kt(process.cwd(),n.generators);if(i.generators.length>0){console.log(`
|
|
3654
3654
|
Plugin generators:
|
|
3655
3655
|
`);let e=Math.max(...i.generators.map(e=>`${e.spec.name} <name>`.length));for(let{source:t,spec:n}of i.generators){let r=`${n.name} <name>`;console.log(` kick g ${r.padEnd(e+2)} ${n.description} [${t}]`)}}if(i.failed.length>0){console.log(`
|
|
3656
3656
|
Failed to load:
|
|
3657
|
-
`);for(let{source:e,reason:t}of i.failed)console.log(` ${e} — ${t}`)}console.log()}async function Hr(e,i,a){let o=await r(process.cwd()),s=n(o),c=i.modulesDir??s.dir??`src/modules`,l=i.repo??Nn(s.repo),u=i.pattern??o?.pattern??`ddd`,d=i.pluralize===!1?!1:s.pluralize??!0,f=t(o,process.cwd()),p=s.style??`define`;if(!a&&p===`define`){let e=await hr(
|
|
3658
|
-
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,i)=>{let a=
|
|
3659
|
-
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,i)=>{let a=
|
|
3660
|
-
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,i)=>{let a=
|
|
3661
|
-
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,i)=>{let a=
|
|
3662
|
-
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,i)=>{let a=
|
|
3663
|
-
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,i)=>{let a=
|
|
3657
|
+
`);for(let{source:e,reason:t}of i.failed)console.log(` ${e} — ${t}`)}console.log()}async function Hr(e,i,a){let o=await r(process.cwd()),s=n(o),c=i.modulesDir??s.dir??`src/modules`,l=i.repo??Nn(s.repo),u=i.pattern??o?.pattern??`ddd`,d=i.pluralize===!1?!1:s.pluralize??!0,f=t(o,process.cwd()),p=s.style??`define`;if(!a&&p===`define`){let e=await hr(w(c),`define`);if(e.length>0){console.error(`\n ${A.red(`Error:`)} ${e.length} module file(s) still use the legacy \`class … implements AppModule\` shape.\n ${A.dim(`Project setting:`)} modules.style: 'define' (default)\n\n ${A.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 ${A.bold(`Pick one:`)}\n 1. Migrate everything to defineModule:\n ${A.dim(`$`)} kick codemod modules --experimental --apply\n 2. Keep the class form — pin it in kick.config.ts:\n ${A.dim(`// kick.config.ts`)}\n ${A.dim(`export default defineConfig({ modules: { style: 'class' } })`)}\n`),process.exit(1)}}let m=[];for(let t of e){let e=await Pn({name:t,modulesDir:w(c),noEntity:i.entity===!1,noTests:i.tests===!1,repo:l,minimal:i.minimal,force:i.force,pattern:u,dryRun:a,pluralize:d,prismaClientPath:s.prismaClientPath,tokenScope:f,style:s.style});m.push(...e)}J(m,a),await zr(a)}function Ur(e){let i=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,t,n)=>{if(t.list){await Vr();return}if(!e||e.length===0){i.help();return}let o=q(n);if(j(o),e.length>=2){let[n,i,...s]=e,c=await r(process.cwd()),l=a(c?.plugins??[],c?.commands??[]),u=await Gt({generatorName:n,itemName:i,args:s,flags:t,cwd:process.cwd()},l.generators);if(u){J(u.files,o);return}}await Hr(e,t,o)});i.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 Hr(e,{...n.optsWithGlobals(),...t},r)}),i.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 Hn({name:e,outDir:w(t.out)}),r)}),i.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 Un({name:e,outDir:w(t.out)}),r)}),i.command(`middleware <name>`).description(`Generate an Express middleware function
|
|
3658
|
+
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,i)=>{let a=q(i);j(a);let o=await r(process.cwd()),s=n(o),c=s.dir??`src/modules`;J(await qn({name:e,outDir:t.out,moduleName:t.module,modulesDir:c,pattern:o?.pattern,pluralize:s.pluralize??!0}),a)}),i.command(`guard <name>`).description(`Generate a route guard (auth, roles, etc.)
|
|
3659
|
+
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,i)=>{let a=q(i);j(a);let o=await r(process.cwd()),s=n(o),c=s.dir??`src/modules`;J(await Jn({name:e,outDir:t.out,moduleName:t.module,modulesDir:c,pattern:o?.pattern,pluralize:s.pluralize??!0}),a)}),i.command(`service <name>`).description(`Generate a @Service() class
|
|
3660
|
+
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,i)=>{let a=q(i);j(a);let o=await r(process.cwd()),s=n(o),c=s.dir??`src/modules`;J(await Yn({name:e,outDir:t.out,moduleName:t.module,modulesDir:c,pattern:o?.pattern,pluralize:s.pluralize??!0}),a)}),i.command(`controller <name>`).description(`Generate a @Controller() class with basic routes
|
|
3661
|
+
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,i)=>{let a=q(i);j(a);let o=await r(process.cwd()),s=n(o),c=s.dir??`src/modules`;J(await Xn({name:e,outDir:t.out,moduleName:t.module,modulesDir:c,pattern:o?.pattern,pluralize:s.pluralize??!0}),a),await zr(a)}),i.command(`dto <name>`).description(`Generate a Zod DTO schema
|
|
3662
|
+
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,i)=>{let a=q(i);j(a);let o=await r(process.cwd()),s=n(o),c=s.dir??`src/modules`;J(await Zn({name:e,outDir:t.out,moduleName:t.module,modulesDir:c,pattern:o?.pattern,pluralize:s.pluralize??!0}),a)}),i.command(`test <name>`).description(`Generate a Vitest test scaffold
|
|
3663
|
+
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,i)=>{let a=q(i);j(a);let o=n(await r(process.cwd())),s=o.dir??`src/modules`;J(await Lr({name:e,outDir:t.out,moduleName:t.module,modulesDir:s,pluralize:o.pluralize??!0}),a)}),i.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 xr({name:e,outDir:w(t.out),queue:t.queue}),r)}),i.command(`scaffold <name> [fields...]`).description(`Generate a full CRUD module from field definitions
|
|
3664
3664
|
Example: kick g scaffold Post title:string body:text:optional published:boolean:optional
|
|
3665
3665
|
Types: string, text, number, int, float, boolean, date, email, url, uuid, json, enum:a,b,c
|
|
3666
3666
|
Optional: append :optional (shell-safe): description:text:optional
|
|
3667
|
-
or use ? with quoting: "description:text?" or "description?:text"`).option(`--no-entity`,`Skip entity and value object generation`).option(`--no-tests`,`Skip test file generation`).option(`--no-pluralize`,`Use singular names (skip auto-pluralization)`).option(`--modules-dir <dir>`,`Modules directory`).action(async(e,i,a,o)=>{let s=
|
|
3667
|
+
or use ? with quoting: "description:text?" or "description?:text"`).option(`--no-entity`,`Skip entity and value object generation`).option(`--no-tests`,`Skip test file generation`).option(`--no-pluralize`,`Use singular names (skip auto-pluralization)`).option(`--modules-dir <dir>`,`Modules directory`).action(async(e,i,a,o)=>{let s=q(o);j(s),i.length===0&&(console.error(`
|
|
3668
3668
|
Error: At least one field is required.
|
|
3669
3669
|
Usage: kick g scaffold <name> <field:type> [field:type...]
|
|
3670
3670
|
Example: kick g scaffold Post title:string body:text:optional published:boolean:optional
|
|
3671
3671
|
Optional: append :optional (shell-safe, no quoting needed)
|
|
3672
|
-
`),process.exit(1));let c=await r(process.cwd()),l=n(c),u=a.modulesDir??l.dir??`src/modules`,d=Cr(i),f=t(c,process.cwd()),p=c?.pattern??`ddd`;p!==`ddd`&&(console.error(`\n Error: 'kick g scaffold' currently only supports the DDD pattern.\n Detected project pattern: '${p}'.\n Workarounds:\n - Run 'kick g module ${e}' for the ${p} 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 m=await wr({name:e,fields:d,modulesDir:
|
|
3673
|
-
Includes controller, service, DTOs, and test stubs.`).option(`-s, --strategy <type>`,`Auth strategy: jwt | session`).option(`--role-guards`,`Generate role-based guards (default: true)`).option(`--no-role-guards`,`Skip role-based guard generation`).option(`-o, --out <dir>`,`Output directory`,`src/modules/auth`).action(async(e,t)=>{let n=
|
|
3674
|
-
`,l=``;if(
|
|
3675
|
-
`,`utf-8`),o(` ✓ wrote manifest → ${
|
|
3672
|
+
`),process.exit(1));let c=await r(process.cwd()),l=n(c),u=a.modulesDir??l.dir??`src/modules`,d=Cr(i),f=t(c,process.cwd()),p=c?.pattern??`ddd`;p!==`ddd`&&(console.error(`\n Error: 'kick g scaffold' currently only supports the DDD pattern.\n Detected project pattern: '${p}'.\n Workarounds:\n - Run 'kick g module ${e}' for the ${p} 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 m=await wr({name:e,fields:d,modulesDir:w(u),noEntity:a.entity===!1,noTests:a.tests===!1,pluralize:a.pluralize===!1?!1:l.pluralize??!0,tokenScope:f,style:l.style});console.log(`\n Scaffolded ${e} with ${d.length} field(s):`);for(let e of d)console.log(` ${e.name}: ${e.type}${e.optional?` (optional)`:``}`);J(m,s),await zr(s)}),i.command(`auth-scaffold`).description(`Generate a complete auth module (register, login, logout, password hashing)
|
|
3673
|
+
Includes controller, service, DTOs, and test stubs.`).option(`-s, --strategy <type>`,`Auth strategy: jwt | session`).option(`--role-guards`,`Generate role-based guards (default: true)`).option(`--no-role-guards`,`Skip role-based guard generation`).option(`-o, --out <dir>`,`Output directory`,`src/modules/auth`).action(async(e,t)=>{let n=q(t);j(n);let r=e.strategy;r||=await St({message:`Auth strategy`,options:[{value:`jwt`,label:`JWT`,hint:`stateless token-based auth`},{value:`session`,label:`Session`,hint:`server-side session with cookies`}]});let i=e.roleGuards;i===void 0&&(i=await F({message:`Generate role-based guards?`,initialValue:!0})),J(await gr({strategy:r,outDir:e.out,roleGuards:i}),n)}),i.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 Qn({outDir:w(`.`),modulesDir:e.modulesDir,defaultRepo:e.repo,force:e.force}),n)}),i.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(!Rr.includes(r)){console.error(` Invalid --only value: ${r}. Expected: ${Rr.join(` | `)}`),process.exitCode=1;return}J(await rr({outDir:w(`.`),only:r,name:e.name,pm:e.pm,template:e.template,force:e.force}),n)})}async function Wr(e){let t=b.resolve(e.cwd,`.kickjs/types`);await me(t,{recursive:!0});let n=new Map,r=e.scan??c,i={cwd:e.cwd,config:e.config,async importTs(e){return await import(T(e).href)},async writeFile(t,n){let r=b.resolve(e.cwd,t);await me(b.dirname(r),{recursive:!0}),await O(r,n,`utf8`)},getScanResult:e=>{let t=Gr(e),i=n.get(t);return i||(i=r(e),n.set(t,i)),i},log:console},a=[];for(let n of e.plugins){let r=await n.generate(i);if(r===null){a.push({id:n.id,status:`skipped`});continue}let o=n.outExtension??`.d.ts`,s=b.join(t,`${n.id.replace(/\//g,`__`)}${o}`),c=`/* AUTO-GENERATED by kick typegen — do not edit. Plugin: ${n.id} */\n\n`+r+`
|
|
3674
|
+
`,l=``;if(g(s)&&(l=await D(s,`utf8`)),l===c){a.push({id:n.id,status:`unchanged`,outFile:s});continue}if(e.check)throw Error(`kick typegen --check: drift detected for ${n.id} (${s})`);await O(s,c,`utf8`),a.push({id:n.id,status:`written`,outFile:s})}return a}function Gr(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 Kr(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 qr=e({applyDisableFilter:()=>Kr,runAllPluginTypegens:()=>Jr});async function Jr(e){let{enabled:t,skipped:n,unknown:r}=Kr(a([...Aa,...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 Wr({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 Yr(e,t){let{cwd:n,silent:r=!1}=t,i=t.distDir??e?.build?.outDir??`dist`,a=e?.assetMap;if(!a||Object.keys(a).length===0)return null;let o=r?()=>{}:console.log,s=w(n,i);_(s,{recursive:!0});let c=[],l={};for(let[e,t]of Object.entries(a)){let r=await Xr(e,t,n,s);c.push(r.entrySummary),Object.assign(l,r.manifestSlice),o(` ✓ ${e}: ${r.entrySummary.filesCopied} file(s) → ${r.entrySummary.dest}`)}let u={version:1,entries:l},d=S(s,`.kickjs-assets.json`);return ne(d,JSON.stringify(u,null,2)+`
|
|
3675
|
+
`,`utf-8`),o(` ✓ wrote manifest → ${C(n,d)} (${Object.keys(l).length} entries)`),{manifestPath:d,entries:c,manifest:u}}async function Xr(e,t,n,r){let i=w(n,t.src),a=t.dest?w(n,t.dest):S(r,e);if(Qr(a,n))return console.warn(` ⚠ assetMap.${e}.dest ('${t.dest}') resolves outside the project root — skipping copy`),{entrySummary:{namespace:e,src:t.src,dest:C(n,a),filesCopied:0},manifestSlice:{}};if(!g(i)||!$r(i))return{entrySummary:{namespace:e,src:t.src,dest:C(n,a),filesCopied:0},manifestSlice:{}};let o=await ye(t.glob??`**/*`,{cwd:i,nodir:!0,dot:!1,posix:!0});_(a,{recursive:!0});let s={},{pairs:c,collisionGroupsResolved:l}=be(e,[...o].toSorted(),{strategy:t.keys??`auto`});for(let{rel:e,key:t}of c){let n=S(i,e),o=S(a,e);_(x(o),{recursive:!0}),h(n,o),s[t]=Zr(r,o)}return l>0&&console.log(` ℹ assetMap.${e}: auto-resolved ${l} 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:C(n,a),filesCopied:o.length},manifestSlice:s}}function Zr(e,t){return C(e,t).split(/[\\/]/).filter(Boolean).join(`/`)}function Qr(e,t){let n=C(t,e);return n===``?!1:n.startsWith(`..`)||ae(n)}function $r(e){try{return te(e).isDirectory()}catch{return!1}}function ei(e){if(typeof e==`boolean`)return e;let t=process.env.KICKJS_WATCH_POLLING;return t===`1`||t===`true`}async function ti(e,t,n={}){t&&(process.env.PORT=t);let i=ei(n.polling),a=process.cwd(),o=await r(a),s=o?.typegen?.schemaValidator??`zod`,c=o?.typegen?.envFile;try{await p({cwd:a,allowDuplicates:!0,schemaValidator:s,envFile:c,srcDir:o?.typegen?.srcDir,outDir:o?.typegen?.outDir,assetMap:o?.assetMap,runPlugins:!1})}catch(e){console.warn(` kick typegen: skipped (${e?.message??e})`)}await Jr({cwd:a,config:o});let{createRequire:l}=await import(`node:module`),{createServer:u}=await import(T(l(w(`package.json`)).resolve(`vite`)).href),d=await u({configFile:w(`vite.config.ts`),server:{port:t?parseInt(t,10):void 0,...i?{watch:{usePolling:!0,interval:100}}:{}}}),f=o?.assetMap?Object.values(o.assetMap).map(e=>e?.src).filter(e=>typeof e==`string`&&e.length>0).map(e=>w(a,e)):[],m=e=>f.some(t=>e===t||e.startsWith(`${t}/`)),h=null,g=e=>{if(e.includes(`.kickjs`)||e.endsWith(`.d.ts`))return;let t=/\.(ts|tsx|mts|cts)$/.test(e),n=m(e);!t&&!n||(h&&clearTimeout(h),h=setTimeout(()=>{p({cwd:a,silent:!0,allowDuplicates:!0,schemaValidator:s,envFile:c,srcDir:o?.typegen?.srcDir,outDir:o?.typegen?.outDir,assetMap:o?.assetMap,runPlugins:!1}).catch(()=>{}),Jr({cwd:a,config:o,silent:!0}).catch(()=>{})},100))};d.watcher.on(`add`,g),d.watcher.on(`unlink`,g),d.watcher.on(`change`,g),f.length>0&&d.watcher.add(f),await d.listen(),d.printUrls(),console.log(`
|
|
3676
3676
|
KickJS dev server running (Vite + @forinda/kickjs-vite)
|
|
3677
3677
|
`);let _=async()=>{h&&clearTimeout(h),await d.close(),process.exit(0)};process.on(`SIGINT`,_),process.on(`SIGTERM`,_)}function ni(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 ti(e.entry,e.port,{polling:e.polling})}catch(e){e.code===`ERR_MODULE_NOT_FOUND`&&e.message?.includes(`vite`)?console.error(`
|
|
3678
3678
|
Error: vite is not installed.
|
|
@@ -3680,26 +3680,26 @@ describe('${o}', () => {
|
|
|
3680
3680
|
`):console.error(`
|
|
3681
3681
|
Dev server failed:`,e.message??e),process.exit(1)}}),e.command(`build`).description(`Build for production via Vite`).action(async()=>{console.log(`
|
|
3682
3682
|
Building for production...
|
|
3683
|
-
`);let{createRequire:e}=await import(`node:module`),{build:t}=await import(
|
|
3684
|
-
Copying directories to dist...`);for(let e of i){let t=typeof e==`string`?e:e.src,n=typeof e==`string`?
|
|
3683
|
+
`);let{createRequire:e}=await import(`node:module`),{build:t}=await import(T(e(w(`package.json`)).resolve(`vite`)).href);await t({configFile:w(`vite.config.ts`)});let n=await r(process.cwd()),i=n?.copyDirs??[];if(i.length>0){console.log(`
|
|
3684
|
+
Copying directories to dist...`);for(let e of i){let t=typeof e==`string`?e:e.src,n=typeof e==`string`?S(`dist`,e):e.dest??S(`dist`,t),r=w(t),i=w(n);if(!g(r)){console.log(` ⚠ Skipped ${t} (not found)`);continue}_(i,{recursive:!0}),h(r,i,{recursive:!0}),console.log(` ✓ ${t} → ${n}`)}}if(n?.assetMap&&Object.keys(n.assetMap).length>0){console.log(`
|
|
3685
3685
|
Building asset map...`);try{await Yr(n,{cwd:process.cwd()})}catch(e){console.error(` ✗ asset build failed: ${e instanceof Error?e.message:String(e)}`),process.exit(1)}}console.log(`
|
|
3686
3686
|
Build complete.
|
|
3687
3687
|
`)}),e.command(`build:assets`).description(`Rebuild the .kickjs-assets.json manifest under the configured outDir (no JS rebuild)`).action(async()=>{let e=await r(process.cwd());if(!e?.assetMap||Object.keys(e.assetMap).length===0){console.log(` No assetMap entries — nothing to build.`);return}console.log(`
|
|
3688
3688
|
Building asset map...`);try{await Yr(e,{cwd:process.cwd()}),console.log(`
|
|
3689
3689
|
Asset build complete.
|
|
3690
|
-
`)}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)),
|
|
3690
|
+
`)}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)),Ne(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 ti(e.entry,e.port)}catch(e){console.error(`
|
|
3691
3691
|
Dev server (debug) failed:`,e.message??e),process.exit(1)}})}function ri(e){e.command(`info`).description(`Print system and framework info`).action(()=>{console.log(`
|
|
3692
3692
|
KickJS CLI
|
|
3693
3693
|
|
|
3694
3694
|
System:
|
|
3695
|
-
OS: ${
|
|
3695
|
+
OS: ${Se()} ${Ce()} (${xe()})
|
|
3696
3696
|
Node: ${process.version}
|
|
3697
3697
|
|
|
3698
3698
|
Packages:
|
|
3699
3699
|
@forinda/kickjs workspace
|
|
3700
3700
|
@forinda/kickjs-vite workspace
|
|
3701
3701
|
@forinda/kickjs-cli workspace
|
|
3702
|
-
`)})}const{bold:
|
|
3702
|
+
`)})}const{bold:Y,dim:X,green:ii,red:ai,yellow:oi,blue:si}=A;function ci(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 li(e){let t=await fetch(e,{signal:AbortSignal.timeout(5e3)});if(!t.ok)throw Error(`${t.status} ${t.statusText}`);return t.json()}async function ui(e,t){try{return await li(`${e}${t}`)}catch{return null}}async function di(e){let[t,n,r,i,a]=await Promise.all([ui(e,`/health`),ui(e,`/metrics`),ui(e,`/routes`),ui(e,`/container`),ui(e,`/ws`)]);return{health:t,metrics:n,routes:r,container:i,ws:a}}function fi(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`?ii(`● healthy`):ai(`● `+n.status);console.log(` ${Y(`Health:`)} ${e}`)}else console.log(` ${Y(`Health:`)} ${ai(`● unreachable`)}`);if(r){let e=((r.errorRate??0)*100).toFixed(1),t=r.errorRate>.1?ai:r.errorRate>0?oi:ii;console.log(` ${Y(`Uptime:`)} ${ci(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(` ${gt(e.method)} ${t} ${si(e.controller)}.${X(e.handler)}`)}}console.log(s),console.log()}function pi(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 di(r);t.json?console.log(JSON.stringify(e,null,2)):fi(n,e)}catch(e){t.json?console.log(JSON.stringify({error:String(e)})):(console.error(ai(` ✖ 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 mi(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 hi=[{match(e,t){let n=mi(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
|
|
3703
3703
|
registers the env schema with kickjs at module-load time. Without it,
|
|
3704
3704
|
ConfigService falls back to the base schema (PORT/NODE_ENV/LOG_LEVEL only)
|
|
3705
3705
|
and every user-defined key reads as undefined. @Value() may *appear* to
|
|
@@ -3721,7 +3721,7 @@ describe('UserController', () => {
|
|
|
3721
3721
|
beforeEach(() => Container.reset())
|
|
3722
3722
|
|
|
3723
3723
|
it('does the thing', async () => { /* ... */ })
|
|
3724
|
-
})`,docs:`https://forinda.github.io/kick-js/guide/testing.html`}}:null}},{match(e,t){return e.includes(`@Module`)||
|
|
3724
|
+
})`,docs:`https://forinda.github.io/kick-js/guide/testing.html`}}:null}},{match(e,t){return e.includes(`@Module`)||mi(e,[`Module`,`is not a function`])||mi(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
|
|
3725
3725
|
pattern instead: a class implements AppModule and exposes routes() that
|
|
3726
3726
|
returns the controller wiring. This was a deliberate choice — modules
|
|
3727
3727
|
become explicit values rather than metadata, which makes them easier to
|
|
@@ -3773,24 +3773,24 @@ drop the entry.`,fix:`Open src/modules/index.ts and verify the module is in the
|
|
|
3773
3773
|
import { UserModule } from './users/user.module'
|
|
3774
3774
|
import { TaskModule } from './tasks/task.module' // ← was this missing?
|
|
3775
3775
|
|
|
3776
|
-
export const modules: AppModuleEntry[] = [UserModule(), TaskModule()]`,docs:`https://forinda.github.io/kick-js/guide/project-structure.html`}}:null}}];function
|
|
3776
|
+
export const modules: AppModuleEntry[] = [UserModule(), TaskModule()]`,docs:`https://forinda.github.io/kick-js/guide/project-structure.html`}}:null}}];function gi(e,t){let n=null;for(let r of hi){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 _i(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.
|
|
3777
3777
|
export OPENAI_API_KEY="sk-..."
|
|
3778
3778
|
|
|
3779
3779
|
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:
|
|
3780
3780
|
kick add ai
|
|
3781
3781
|
|
|
3782
3782
|
Or manually:
|
|
3783
|
-
pnpm add @forinda/kickjs-ai`}}let{OpenAIProvider:i}=r,a=new i({apiKey:n,defaultChatModel:e.model??`gpt-4o-mini`}),o=
|
|
3784
|
-
`)}function
|
|
3783
|
+
pnpm add @forinda/kickjs-ai`}}let{OpenAIProvider:i}=r,a=new i({apiKey:n,defaultChatModel:e.model??`gpt-4o-mini`}),o=vi(e.cwd),s=`Error or stack trace:\n\n${e.input.trim()}`;try{let e=yi((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 vi(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(`
|
|
3784
|
+
`)}function yi(e){let t=[e,bi(e),xi(e)].filter(e=>e!==null);for(let e of t)try{let t=JSON.parse(e);if(Si(t))return t}catch{continue}return null}function bi(e){let t=e.match(/```(?:json)?\s*\n([\s\S]*?)```/);return t?t[1]?.trim()??null:null}function xi(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 Si(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 Ci(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 Ei(e,t.message);(!n||n.trim().length===0)&&(process.stderr.write(`Error: no input provided.
|
|
3785
3785
|
|
|
3786
3786
|
Pass a message as a positional arg, --message flag, or pipe via stdin:
|
|
3787
3787
|
kick explain "config.get returned undefined"
|
|
3788
3788
|
pnpm test 2>&1 | kick explain
|
|
3789
|
-
`),process.exit(1));let r=
|
|
3790
|
-
`);return}if(i){
|
|
3791
|
-
`),process.exit(2)),
|
|
3792
|
-
`),process.exit(a.kind===`ok`?0:2)),
|
|
3793
|
-
`)}function
|
|
3789
|
+
`),process.exit(1));let r=Oi(),i=gi(n,r);if(t.json&&i){process.stdout.write(JSON.stringify({matched:!0,...i},null,2)+`
|
|
3790
|
+
`);return}if(i){ki(n,i.diagnosis,i.confidence);return}t.ai||(t.json&&(process.stdout.write(JSON.stringify({matched:!1},null,2)+`
|
|
3791
|
+
`),process.exit(2)),Ai(n,!1),process.exit(2));let a=await _i({input:n,model:t.model,cwd:r.cwd});t.json&&(process.stdout.write(JSON.stringify(wi(a),null,2)+`
|
|
3792
|
+
`),process.exit(a.kind===`ok`?0:2)),Ti(n,a),process.exit(a.kind===`ok`?0:2)})}function wi(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 Ti(e,t){if(t.kind===`ok`){ki(e,t.diagnosis,-1,!0);return}if(t.kind===`unavailable`){process.stdout.write(`\n Explaining: ${Mi(e.trim(),200)}\n\n`),process.stdout.write(` AI fallback unavailable: ${t.reason}\n\n`),process.stdout.write(`${ji(t.suggestion,` `)}\n\n`);return}process.stdout.write(`\n Explaining: ${Mi(e.trim(),200)}\n\n`),process.stdout.write(` AI fallback error: ${t.message}\n\n`)}async function Ei(e,t){return e&&e.trim().length>0?e:t&&t.trim().length>0?t:process.stdin.isTTY?``:Di()}function Di(){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 Oi(){let e=process.cwd();return{cwd:e,hasFile:t=>g(w(e,t))}}function ki(e,t,n,r=!1){let i=Mi(e.trim(),200),a=r?`AI-generated — verify before applying`:Ni(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${ji(t.explanation,` `)}\n`),process.stdout.write(`\n Fix:\n${ji(t.fix,` `)}\n`),t.codeBefore&&process.stdout.write(`\n Before:\n${ji(t.codeBefore,` `)}\n`),t.codeAfter&&process.stdout.write(`\n After:\n${ji(t.codeAfter,` `)}\n`),t.docs&&process.stdout.write(`\n Docs: ${t.docs}\n`),process.stdout.write(`
|
|
3793
|
+
`)}function Ai(e,t){let n=Mi(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.
|
|
3794
3794
|
When @forinda/kickjs-ai ships its provider implementations,
|
|
3795
3795
|
this command will call the configured LLM with the error +
|
|
3796
3796
|
project context and return a structured fix.
|
|
@@ -3807,12 +3807,12 @@ Pass a message as a positional arg, --message flag, or pipe via stdin:
|
|
|
3807
3807
|
3. File an issue with the error text:
|
|
3808
3808
|
https://github.com/forinda/kick-js/issues/new
|
|
3809
3809
|
|
|
3810
|
-
`)}function
|
|
3810
|
+
`)}function ji(e,t){return e.split(`
|
|
3811
3811
|
`).map(e=>`${t}${e}`).join(`
|
|
3812
|
-
`)}function
|
|
3813
|
-
`,`utf8`),process.stdout.write(`\n ✓ Wrote MCP server entry "${r}" to ${i}\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
|
|
3812
|
+
`)}function Mi(e,t){return e.length<=t?e:e.slice(0,t-1)+`…`}function Ni(e){return e>=90?`high confidence`:e>=70?`good match`:e>=50?`medium confidence`:`low confidence — verify manually`}function Pi(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(Fi),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(Ii)}function Fi(e){let t=w(e.entry);g(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],r=ue(process.execPath,n,{stdio:`inherit`,env:{...process.env,KICK_MCP_STDIO:`1`,NODE_ENV:process.env.NODE_ENV??`production`}});r.on(`error`,e=>{process.stderr.write(`Failed to start MCP server: ${e.message}\n`),process.exit(1)}),r.on(`exit`,(e,t)=>{if(t){process.kill(process.pid,t);return}process.exit(e??0)});let i=e=>{r.killed||r.kill(e)};process.on(`SIGINT`,()=>i(`SIGINT`)),process.on(`SIGTERM`,()=>i(`SIGTERM`))}function Ii(e){let t=process.cwd(),n=Li(t)??re(t),r=e.name??n,i=e.global?w(process.env.HOME??`.`,`.mcp.json`):w(t,e.out),a={command:`kick`,args:[`mcp`],cwd:t},o={mcpServers:{}};if(g(i))try{let e=v(i,`utf8`),t=JSON.parse(e);t&&typeof t==`object`&&t.mcpServers&&(o={mcpServers:{...t.mcpServers}})}catch(e){let t=e instanceof Error?e.message:String(e);process.stderr.write(`Error: existing ${i} is not valid JSON (${t}).\nFix the file or pass --force to overwrite the entry.\n`),process.exit(1)}o.mcpServers[r]&&!e.force&&(process.stderr.write(`Error: an entry for "${r}" already exists in ${i}.\nPass --force to overwrite it, or use --name to pick a different key.\n`),process.exit(1)),o.mcpServers[r]=a,ne(i,JSON.stringify(o,null,2)+`
|
|
3813
|
+
`,`utf8`),process.stdout.write(`\n ✓ Wrote MCP server entry "${r}" to ${i}\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 Li(e){let t=w(e,`package.json`);if(!g(t))return null;try{let e=v(t,`utf8`),n=JSON.parse(e);return typeof n.name==`string`?n.name:null}catch{return null}}function Ri(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=w(t,e.entry);g(n)||(console.error(`\n Error: ${e.entry} not found.\n`),process.exit(1));let r=Bi(t,`tsx`);r||(console.error(`
|
|
3814
3814
|
Error: tsx not found. Install it: pnpm add -D tsx
|
|
3815
|
-
`),process.exit(1));let i=
|
|
3815
|
+
`),process.exit(1));let i=zi(n,e.entry),a=S(t,`.kick-tinker.mjs`),{writeFileSync:o,unlinkSync:s}=await import(`node:fs`);o(a,i,`utf-8`);try{let e=le(a,[],{cwd:t,execPath:r,stdio:`inherit`});await new Promise(t=>{e.on(`exit`,()=>t())})}finally{try{s(a)}catch{}}})}function zi(e,t){return`
|
|
3816
3816
|
import 'reflect-metadata'
|
|
3817
3817
|
|
|
3818
3818
|
// Prevent bootstrap() from starting the HTTP server
|
|
@@ -3837,7 +3837,7 @@ try {
|
|
|
3837
3837
|
|
|
3838
3838
|
// Load entry to trigger decorator registration
|
|
3839
3839
|
try {
|
|
3840
|
-
await import('${
|
|
3840
|
+
await import('${T(e).href}')
|
|
3841
3841
|
} catch (err) {
|
|
3842
3842
|
console.warn(' Warning: ' + err.message)
|
|
3843
3843
|
console.warn(' Container may be partially initialized.\\n')
|
|
@@ -3866,32 +3866,32 @@ server.on('exit', () => {
|
|
|
3866
3866
|
console.log('\\n Goodbye!\\n')
|
|
3867
3867
|
process.exit(0)
|
|
3868
3868
|
})
|
|
3869
|
-
`}function
|
|
3869
|
+
`}function Bi(e,t){let n=e;for(;;){let e=S(n,`node_modules`,`.bin`,t);if(g(e))return e;let r=w(n,`..`);if(r===n)break;n=r}return null}function Vi(e,t){let n=RegExp(`^\\s*${H(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]!==`
|
|
3870
3870
|
`;)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]===`
|
|
3871
|
-
`);)t--;a=a.slice(0,t)+a.slice(s+1),r=!0,i=t;continue}i=s+1}return{content:a,changed:r}}function
|
|
3871
|
+
`);)t--;a=a.slice(0,t)+a.slice(s+1),r=!0,i=t;continue}i=s+1}return{content:a,changed:r}}function Hi(e,t){let n=Ln(e);if(!n)return e;let r=n.rhsStart,i=n.rhsEnd+1,a=e.slice(r,i);return a=Vi(a,t).content,a=a.replace(RegExp(`\\s*,?\\s*${H(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 Ui(e){let{name:t,modulesDir:n,force:r}=e,i=e.pluralize!==!1,a=B(t),o=R(t),s=i?V(a):a,c=S(n,s);if(!await ze(c)){console.log(`\n Module not found: ${c}\n`);return}if(!r&&!await F({message:A.red(`Delete module '${s}' at ${c}? This cannot be undone.`),initialValue:!1})){console.log(`
|
|
3872
3872
|
Cancelled.
|
|
3873
|
-
`);return}await
|
|
3873
|
+
`);return}await ge(c,{recursive:!0,force:!0}),console.log(` Deleted: ${c}`);let l=S(n,`index.ts`);if(await ze(l)){let e=await D(l,`utf-8`),t=e,n=RegExp(`^import\\s*\\{\\s*${H(o)}Module\\s*\\}\\s*from\\s*['"][^'"]*${H(s)}(?:/[^'"]*)?['"].*\\n?`,`gm`);e=e.replace(n,``),e=Hi(e,o),e=e.replace(/\n{3,}/g,`
|
|
3874
3874
|
|
|
3875
|
-
`),e!==t&&(await
|
|
3875
|
+
`),e!==t&&(await O(l,e,`utf-8`),console.log(` Unregistered: ${o}Module from ${l}`))}console.log(`\n Module '${s}' removed.\n`)}function Wi(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 i=n(await r(process.cwd())),a=t.modulesDir??i.dir??`src/modules`,o=t.pluralize===!1?!1:i.pluralize??!0;for(let n of e)await Ui({name:n,modulesDir:w(a),force:t.force,pluralize:o})})}function Gi(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 Ki(e){if(e!==void 0)return e===`false`||e===`off`||e===`none`?!1:e}function qi(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=process.cwd(),n=await r(t);if(e.list){let{mergeCliPlugins:e}=await import(`./plugin-Dz0Yu4Ow.mjs`).then(e=>e.t),{builtinCliPlugins:t}=await Promise.resolve().then(()=>ka),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(`
|
|
3876
3876
|
Registered typegen plugins:
|
|
3877
|
-
`);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 i=
|
|
3877
|
+
`);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 i=Gi(e.schemaValidator)??n?.typegen?.schemaValidator??`zod`,a=Ki(e.envFile)??n?.typegen?.envFile,o={cwd:t,srcDir:e.src??n?.typegen?.srcDir,outDir:e.out??n?.typegen?.outDir,silent:e.silent,allowDuplicates:e.allowDuplicates,schemaValidator:i,envFile:a,assetMap:n?.assetMap,runPlugins:!1};try{if(e.watch){let t=await l(o);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 p(o),i=await Jr({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 u(w(t,e.out??n?.typegen?.outDir??`.kickjs/types`),r.written,i,e.silent??!1)}}catch(e){e instanceof f?console.error(`
|
|
3878
3878
|
`+e.message+`
|
|
3879
|
-
`):e instanceof Error?console.error(`\n kick typegen failed: ${e.message}`):console.error(`\n kick typegen failed: ${JSON.stringify(e)}`),process.exit(1)}})}function
|
|
3879
|
+
`):e instanceof Error?console.error(`\n kick typegen failed: ${e.message}`):console.error(`\n kick typegen failed: ${JSON.stringify(e)}`),process.exit(1)}})}function Ji(e){let t=[];if(!g(e))return t;let n=y(e,{withFileTypes:!0});for(let r of n){let n=S(e,r.name);if(r.isDirectory()){if([`node_modules`,`dist`,`.kickjs`,`.git`].includes(r.name))continue;t.push(...Ji(n))}else r.isFile()&&/\.tsx?$/.test(r.name)&&!r.name.endsWith(`.d.ts`)&&t.push(n)}return t}function Yi(e){try{return v(e,`utf-8`)}catch{return``}}const Xi=new Set([`secret`,`changeme`,`password`,`test`,`default`,``]);function Zi(e,t){let n=Yi(S(e,`.env`));if(n){let e=n.match(/^JWT_SECRET\s*=\s*['"]?([^'"\n]*)['"]?/m);if(e){let t=e[1].trim();if(Xi.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 Qi(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 $i(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 ea(){return process.env.NODE_ENV===`production`?null:{severity:`WARNING`,message:`NODE_ENV is '${process.env.NODE_ENV??`undefined`}', not 'production'`}}function ta(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 na(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 ra(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 ia(e){let t=Ji(S(e,`src`)).map(e=>Yi(e)),n=[],r=Zi(e,t);r&&n.push(r);let i=Qi(t);i&&n.push(i);let a=$i(t);a&&n.push(a);let o=ea();o&&n.push(o);let s=ta(t);return s&&n.push(s),n.push(na(t)),n.push(ra(t)),n}function aa(e){e.command(`check`).description(`Audit project for common issues`).option(`--deploy`,`Run production readiness checks`).action(e=>{if(!e.deploy){console.log(`
|
|
3880
3880
|
Usage: kick check --deploy
|
|
3881
3881
|
|
|
3882
3882
|
Available checks:
|
|
3883
3883
|
--deploy Audit for production readiness (security, config, best practices)
|
|
3884
|
-
`);return}let t=process.cwd();
|
|
3884
|
+
`);return}let t=process.cwd();vt(`KickJS Deploy Check`);let n=wt();n.start(`Scanning project...`);let r=ia(t);n.stop(`Scan complete`);let i={CRITICAL:0,WARNING:1,INFO:2};r.sort((e,t)=>i[e.severity]-i[t.severity]);for(let e of r)I.message(`${_t(e.severity)} ${e.message}`);let a=r.filter(e=>e.severity===`CRITICAL`).length,o=r.filter(e=>e.severity===`WARNING`).length,s=r.filter(e=>e.severity===`INFO`).length,c=o===1?`warning`:`warnings`,l=[a>0?A.red(`${a} critical`):`${a} critical`,o>0?A.yellow(`${o} ${c}`):`${o} ${c}`,`${s} info`].join(`, `);a>0?(yt(A.red(`${l} — fix critical issues before deploying`)),process.exit(1)):yt(A.green(`${l} — looking good!`))})}async function Q(e){return je({configPath:b.resolve(process.cwd(),e.config)})}async function $(e){if(e.adapter){let t=await e.adapter();return{adapter:t,cleanup:async()=>t.close()}}if(!e.connectionString)throw Error(`kickjs-db: no adapter resolved — set db.connectionString (or DATABASE_URL) in kick.config.ts, or supply db.adapter() factory`);let t=e.dialect??`postgres`;if(t!==`postgres`)throw Error(`kickjs-db: built-in CLI adapter only supports postgres in M1 (dialect=${t}); use db.adapter() factory for other dialects`);let[{pgAdapter:n},r]=await Promise.all([import(`@forinda/kickjs-db-pg`),import(`pg`)]),i=new r.default.Pool({connectionString:e.connectionString}),a=n({pool:i});return{adapter:a,cleanup:async()=>{await a.close(),await i.end()}}}function oa(e){if(e.length===0){console.log(`No migrations.`);return}console.table(e.map(e=>({id:e.id,state:e.state,batch:e.batch??`-`,reviewed:e.reviewed,applied:e.appliedAt??`-`})))}function sa(e){let t=e.command(`db`).description(`Database commands (kickjs-db)`);t.command(`generate <name>`).description(`Generate a new migration from schema diff`).option(`-c, --config <path>`,`Path to kick.config.ts`,`kick.config.ts`).option(`-e, --empty`,`Skip schema diff and create an empty migration shell (data migration, seed, freeform SQL)`).action(async(e,t)=>{let n=process.cwd(),r=await we({name:e,config:await Q(t),cwd:n,empty:t.empty});if(r.status===`no-changes`){console.log(`No schema changes detected.`);return}if(r.empty){console.log(`Created empty migration ${r.migrationDir} (author up.sql + down.sql).`);return}let i=r.changeCount===1?``:`s`;console.log(`Created migration ${r.migrationDir} (${r.changeCount} change${i}).`)});let n=t.command(`migrate`).description(`Migration runner subcommands`);n.command(`latest`).description(`Apply all pending migrations in a new batch`).option(`-c, --config <path>`,`Path to kick.config.ts`,`kick.config.ts`).option(`--confirm-enum-drop`,"Allow migrations carrying the `-- KICK ENUM REMOVE` header to apply",!1).action(async e=>{let t=await Q(e),{adapter:n,cleanup:r}=await $(t);try{let r=await Ee({adapter:n,migrationsDir:t.migrationsDir,confirmEnumDrop:e.confirmEnumDrop});r.applied.length===0?console.log(`No pending migrations.`):console.log(`Applied batch ${r.batch}: ${r.applied.join(`, `)}`)}finally{await r()}}),n.command(`up`).description(`Apply the next single pending migration`).option(`-c, --config <path>`,`Path to kick.config.ts`,`kick.config.ts`).option(`--confirm-enum-drop`,"Allow migrations carrying the `-- KICK ENUM REMOVE` header to apply",!1).action(async e=>{let t=await Q(e),{adapter:n,cleanup:r}=await $(t);try{let r=await ke({adapter:n,migrationsDir:t.migrationsDir,confirmEnumDrop:e.confirmEnumDrop});r.applied.length===0?console.log(`No pending migrations.`):console.log(`Applied ${r.applied[0]} (batch ${r.batch})`)}finally{await r()}}),n.command(`down`).description(`Reverse the most recent applied migration`).option(`-c, --config <path>`,`Path to kick.config.ts`,`kick.config.ts`).action(async e=>{let t=await Q(e),{adapter:n,cleanup:r}=await $(t);try{let e=await Te({adapter:n,migrationsDir:t.migrationsDir});e.reversed?console.log(`Reversed ${e.reversed}.`):console.log(`Nothing to reverse.`)}finally{await r()}}),n.command(`rollback`).description(`Reverse the entire last batch as a single unit`).option(`-c, --config <path>`,`Path to kick.config.ts`,`kick.config.ts`).action(async e=>{let t=await Q(e),{adapter:n,cleanup:r}=await $(t);try{let e=await De({adapter:n,migrationsDir:t.migrationsDir});e.reversed.length===0?console.log(`Nothing to roll back.`):console.log(`Rolled back batch ${e.batch}: ${e.reversed.join(`, `)}`)}finally{await r()}}),n.command(`status`).description(`Print applied + pending migrations`).option(`-c, --config <path>`,`Path to kick.config.ts`,`kick.config.ts`).action(async e=>{let t=await Q(e),{adapter:n,cleanup:r}=await $(t);try{oa(await Oe({adapter:n,migrationsDir:t.migrationsDir}))}finally{await r()}}),t.command(`introspect`).description(`Generate a TypeScript schema file from a live database`).option(`-c, --config <path>`,`Path to kick.config.ts`,`kick.config.ts`).option(`--out <path>`,`Output file (defaults to db.schemaPath from config)`).option(`--json`,`Print the raw SchemaSnapshot JSON to stdout instead of writing TS source`).action(async e=>{let t=await Q(e),{adapter:n,cleanup:r}=await $(t);try{let r=await n.introspect();if(e.json){console.log(JSON.stringify(r,null,2));return}let i=e.out??t.schemaPath;await O(i,Ae(r),`utf8`);let a=Object.keys(r.tables).length;console.log(`Wrote ${i} (${a} table${a===1?``:`s`}).`)}finally{await r()}})}function ca(e){return e.optsWithGlobals().dryRun??!1}function la(e){e.command(`codemod`).description(`Codebase migration commands (AST-style rewrites — distinct from db migrate)`).command(`modules`).description(`Rewrite module declarations between class form and the defineModule factory.
|
|
3885
3885
|
Direction defaults to \`modules.style\` from kick.config (or "define").
|
|
3886
3886
|
--target define|class Override the migration direction.
|
|
3887
3887
|
--apply Apply the changes (default: dry-run preview).
|
|
3888
|
-
--experimental Acknowledge that AST migration is experimental.`).option(`--modules-dir <dir>`,`Modules directory (default: src/modules from kick.config)`).option(`--apply`,`Apply the migration to disk (default: dry-run)`).option(`--experimental`,`Acknowledge that this command is experimental`).option(`--target <style>`,`Migration direction — 'define' or 'class'`).option(`--no-backup`,`Skip the .kickjs/codemod-backups/ snapshot (default: backup on)`).action(async(e,t)=>{let i=
|
|
3889
|
-
`+
|
|
3888
|
+
--experimental Acknowledge that AST migration is experimental.`).option(`--modules-dir <dir>`,`Modules directory (default: src/modules from kick.config)`).option(`--apply`,`Apply the migration to disk (default: dry-run)`).option(`--experimental`,`Acknowledge that this command is experimental`).option(`--target <style>`,`Migration direction — 'define' or 'class'`).option(`--no-backup`,`Skip the .kickjs/codemod-backups/ snapshot (default: backup on)`).action(async(e,t)=>{let i=ca(t)||!e.apply;j(i),e.experimental||(console.error(`
|
|
3889
|
+
`+A.red(`Error:`)+` kick codemod modules is experimental — pass --experimental to acknowledge.
|
|
3890
3890
|
The regex-based rewrite handles the shapes our templates produce.
|
|
3891
3891
|
Hand-rolled modules with non-standard structures may be skipped.
|
|
3892
3892
|
Always commit before running with --apply.
|
|
3893
|
-
`),process.exit(1));let a=n(await r(process.cwd())),o=
|
|
3894
|
-
`)}});function
|
|
3893
|
+
`),process.exit(1));let a=n(await r(process.cwd())),o=w(e.modulesDir??a.dir??`src/modules`),s;e.target===`define`||e.target===`class`?s=e.target:e.target===void 0?s=a.style??`define`:(console.error(`\n ${A.red(`Error:`)} --target must be 'define' or 'class' (got '${e.target}').\n`),process.exit(1));let c=A.dim(`→ ${s}`),l=i?A.dim(`(dry-run)`):A.bold(`(applying)`);console.log(`\n ${A.bold(`kick codemod modules`)} ${c} ${l}`),console.log(` modulesDir: ${A.dim(o)}\n`);let u=e.backup!==!1&&!i,d=await mr(o,{dryRun:i,target:s,backup:u});if(d.backupDir){let e=d.backupDir;console.log(` ${A.green(`✓`)} backup: ${A.dim(e)}\n ${A.dim(`(restore: rm -rf <modulesDir> && mv "<backup>" <modulesDir>)`)}\n`)}else !i&&e.backup===!1&&console.log(` ${A.dim(`(--no-backup — skipping snapshot)`)}\n`);let f=0,p=0;for(let e of d.files)if(e.status===`migrated`)f++,console.log(` ${A.green(`✓`)} ${e.path}`);else{p++;let t=A.dim(`(${e.reason??`skipped`})`);console.log(` ${A.dim(`-`)} ${e.path} ${t}`)}if(console.log(),d.indexStatus===`migrated`)console.log(` ${A.green(`✓`)} ${d.indexPath}`);else if(d.indexStatus===`skipped`){let e=A.dim(`(${d.indexReason??`skipped`})`);console.log(` ${A.dim(`-`)} ${d.indexPath} ${e}`)}else console.log(` ${A.dim(`-`)} ${d.indexPath} ${A.dim(`(not found)`)}`);let m=i?A.dim(` (dry-run — pass --apply to write)`):``;console.log(`\n ${A.bold(String(f))} migrated, ${A.bold(String(p))} skipped${m}\n`)})}const ua=[`src/db/schema.ts`,`src/db/schema/index.ts`,`src/db/schema`],da=()=>({id:`kick/db`,inputs:[`src/db/schema.ts`,`src/db/schema/**/*.ts`],async generate(e){let t=fa(e.cwd);if(!t)return null;let n=b.resolve(e.cwd,`.kickjs/types`);return[`import type { SchemaToTypes, SchemaToRelationsRegister, KickDbClient } from '@forinda/kickjs-db'`,`import type * as appSchema from '${pa(b.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(`
|
|
3894
|
+
`)}});function fa(e){for(let t of ua){let n=b.resolve(e,t);if(t.endsWith(`.ts`)){if(g(n))return n}else{let e=b.join(n,`index.ts`);if(g(e))return e}}return null}function pa(e){return e.replace(/\\/g,`/`)}const ma=()=>({id:`kick/assets`,inputs:[`kick.config.ts`,`kick.config.js`,`kick.config.mjs`],async generate(e){if(!g(b.resolve(e.cwd,`kick.config.ts`)))return null;let t=await r(e.cwd);if(!t?.assetMap)return null;let n=s(t.assetMap,e.cwd);return n.count===0?null:d(n)}}),ha="/* 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 ga(e,t,n){if(e.length===0)return`${ha}
|
|
3895
3895
|
// (no routes discovered yet — annotate a controller method with
|
|
3896
3896
|
// @Get/@Post/@Put/@Delete/@Patch and re-run \`kick typegen\`)
|
|
3897
3897
|
declare global {
|
|
@@ -3900,8 +3900,8 @@ declare global {
|
|
|
3900
3900
|
}
|
|
3901
3901
|
|
|
3902
3902
|
export {}
|
|
3903
|
-
`;let r=new Map;for(let t of e){let e=r.get(t.controller)??[];e.push(t),r.set(t.controller,e)}let i=new Map,a=(e,r)=>{let a=
|
|
3904
|
-
`))}return`${
|
|
3903
|
+
`;let r=new Map;for(let t of e){let e=r.get(t.controller)??[];e.push(t),r.set(t.controller,e)}let i=new Map,a=(e,r)=>{let a=ya(e,r,t,n,i);return a?`import('zod').infer<typeof ${a}>`:null},o=[];for(let[e,t]of r){let n=[` interface ${e} {`];for(let e of t){let t=e.pathParams.length>0?`{ ${e.pathParams.map(e=>`${e}: string`).join(`; `)} }`:`{}`,r=a(e.bodySchema,e.filePath),i=a(e.querySchema,e.filePath),o=a(e.paramsSchema,e.filePath)??t,s=r??`unknown`,c=i??_a(e),l=va(e);n.push(` /**`,` * ${e.httpMethod} ${e.path}`,...l.map(e=>` * ${e}`),` */`,` ${e.method}: {`,` params: ${o}`,` body: ${s}`,` query: ${c}`,` response: unknown`,` }`)}n.push(` }`),o.push(n.join(`
|
|
3904
|
+
`))}return`${ha}${ba(i)}
|
|
3905
3905
|
declare global {
|
|
3906
3906
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
3907
3907
|
namespace KickRoutes {
|
|
@@ -3911,9 +3911,9 @@ ${o.join(`
|
|
|
3911
3911
|
}
|
|
3912
3912
|
|
|
3913
3913
|
export {}
|
|
3914
|
-
`}function
|
|
3914
|
+
`}function _a(e){if(e.queryFilterable===null)return`unknown`;let t=e.querySortable??[];return`{ filter?: string | string[]; sort?: ${t.length>0?t.flatMap(e=>[`'${e}'`,`'-${e}'`]).join(` | `):`string`}; q?: string; page?: string; limit?: string }`}function va(e){let t=[];return e.queryFilterable&&e.queryFilterable.length>0&&t.push(`Filterable: ${e.queryFilterable.join(`, `)}`),e.querySortable&&e.querySortable.length>0&&t.push(`Sortable: ${e.querySortable.join(`, `)}`),e.querySearchable&&e.querySearchable.length>0&&t.push(`Searchable: ${e.querySearchable.join(`, `)}`),t}function ya(e,t,n,r,i){if(!e||r!==`zod`||e.source===null)return null;let a=xa(e.source,t,n);if(a===`unknown`)return null;let o=`${a}::${e.identifier}`,s=i.get(o)?.specifier;return s?s=i.get(o).specifier:(s=`_S${i.size}`,i.set(o,{identifier:e.identifier,specifier:s})),s}function ba(e){if(e.size===0)return``;let t=[];for(let[n,r]of e){let[e]=n.split(`::`);t.push(`import type { ${r.identifier} as ${r.specifier} } from '${e}'`)}return t.join(`
|
|
3915
3915
|
`)+`
|
|
3916
|
-
`}function
|
|
3916
|
+
`}function xa(e,t,n){if(e===null)return`unknown`;let r=x(n);if(e===``){let e=C(r,t).split(oe).join(`/`);return e=e.replace(/\.(ts|tsx|mts|cts)$/i,``),e.startsWith(`.`)||(e=`./`+e),e}if(!e.startsWith(`.`)&&!e.startsWith(`/`))return e;let i=C(r,w(x(t),e)).split(oe).join(`/`);return i=i.replace(/\.(ts|tsx|mts|cts)$/i,``),i.startsWith(`.`)||(i=`./`+i),i}const Sa=()=>({id:`kick/routes`,outExtension:`.ts`,inputs:[`src/**/*.controller.ts`,`src/**/*.module.ts`],async generate(e){let t=await e.getScanResult({root:Ca(e),cwd:e.cwd,envFile:wa(e)}),n=e.config?.typegen?.schemaValidator??`zod`,r=b.resolve(e.cwd,`.kickjs/types/kick__routes.ts`);return ga(t.routes,r,n)}});function Ca(e){return b.resolve(e.cwd,e.config?.typegen?.srcDir??`src`)}function wa(e){let t=e.config?.typegen?.envFile;if(t!==!1)return t}function Ta(e,t){if(!e)return null;let n=C(x(t),e.filePath).split(oe).join(`/`);return n=n.replace(/\.(ts|tsx|mts|cts)$/i,``),n.startsWith(`.`)||(n=`./`+n),`/* eslint-disable */
|
|
3917
3917
|
// AUTO-GENERATED by \`kick typegen\`. DO NOT EDIT.
|
|
3918
3918
|
// Re-run with \`kick typegen\` or rely on \`kick dev\` to refresh.
|
|
3919
3919
|
|
|
@@ -3949,4 +3949,4 @@ declare global {
|
|
|
3949
3949
|
}
|
|
3950
3950
|
|
|
3951
3951
|
export {}
|
|
3952
|
-
`}const
|
|
3952
|
+
`}const Ea=()=>({id:`kick/env`,outExtension:`.ts`,inputs:[`src/env.ts`,`src/**/env.ts`,`src/**/*.env.ts`],async generate(e){let t=Oa(e);if(t===!1)return null;let n=await e.getScanResult({root:Da(e),cwd:e.cwd,envFile:t});if(!n.env)return null;let r=b.resolve(e.cwd,`.kickjs/types/kick__env.ts`);return Ta(n.env,r)}});function Da(e){return b.resolve(e.cwd,e.config?.typegen?.srcDir??`src`)}function Oa(e){return e.config?.typegen?.envFile}var ka=e({builtinCliPlugins:()=>Aa});const Aa=[o({name:`kick/init`,register:Pt}),o({name:`kick/generate`,register:Ur}),o({name:`kick/run`,register:ni}),o({name:`kick/info`,register:ri}),o({name:`kick/inspect`,register:pi}),o({name:`kick/add`,register:Mt}),o({name:`kick/list`,register:jt}),o({name:`kick/explain`,register:Ci}),o({name:`kick/mcp`,register:Pi}),o({name:`kick/tinker`,register:Ri}),o({name:`kick/remove`,register:Wi}),o({name:`kick/typegen`,register:qi}),o({name:`kick/check`,register:aa}),o({name:`kick/db`,register:sa,typegens:[da()]}),o({name:`kick/codemod`,register:la}),o({name:`kick/assets`,typegens:[ma()]}),o({name:`kick/routes`,typegens:[Sa()]}),o({name:`kick/env`,typegens:[Ea()]})];export{Me as i,ka as n,qr as r,Aa as t};
|