@forinda/kickjs-cli 6.3.1 → 6.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-docs-Xlt6Fk-e.mjs +12 -0
- package/dist/{agent-docs-CCJdXCYA.mjs.map → agent-docs-Xlt6Fk-e.mjs.map} +1 -1
- package/dist/{build-BQX6_8F5.mjs → build-RlkRhDyM.mjs} +3 -3
- package/dist/{build-BQX6_8F5.mjs.map → build-RlkRhDyM.mjs.map} +1 -1
- package/dist/{builtins-ynssA76A.mjs → builtins-Ce5uoK6s.mjs} +2 -2
- package/dist/cli.mjs +121 -110
- package/dist/{config-DHUTbe0Z.mjs → config-xEbwXlmo.mjs} +3 -3
- package/dist/{config-DHUTbe0Z.mjs.map → config-xEbwXlmo.mjs.map} +1 -1
- package/dist/doctor-DCFgdlJ3.mjs +860 -0
- package/dist/doctor-DCFgdlJ3.mjs.map +1 -0
- package/dist/fullstack-iuAdYQmC.mjs +137 -0
- package/dist/fullstack-pPl60src.mjs +138 -0
- package/dist/fullstack-pPl60src.mjs.map +1 -0
- package/dist/index.d.mts +14 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/dist/{plugin-BTwlPxl6.mjs → plugin-B_40AQRr.mjs} +3 -3
- package/dist/{plugin-BTwlPxl6.mjs.map → plugin-B_40AQRr.mjs.map} +1 -1
- package/dist/project-D_8okjEO.mjs +390 -0
- package/dist/project-D_8okjEO.mjs.map +1 -0
- package/dist/{project-docs-DXV06Vu3.mjs → project-docs-MYPeTYsJ.mjs} +9 -9
- package/dist/project-docs-MYPeTYsJ.mjs.map +1 -0
- package/dist/{project-root-BFvDNNZY.mjs → project-root-CWcfpTV4.mjs} +3 -3
- package/dist/{project-root-BFvDNNZY.mjs.map → project-root-CWcfpTV4.mjs.map} +1 -1
- package/dist/prompts-D0mIvDKz.mjs +12 -0
- package/dist/prompts-D0mIvDKz.mjs.map +1 -0
- package/dist/{rolldown-runtime-D__qoJwR.mjs → rolldown-runtime-wP2RwkAN.mjs} +1 -1
- package/dist/{run-plugins-Cyv_2-7g.mjs → run-plugins-USrmMITe.mjs} +66 -59
- package/dist/run-plugins-USrmMITe.mjs.map +1 -0
- package/dist/{typegen-Dhfw8V1k.mjs → typegen-Do1rVRd1.mjs} +18 -18
- package/dist/typegen-Do1rVRd1.mjs.map +1 -0
- package/dist/{types-CA3g1Lw4.mjs → types-CjDOGs_1.mjs} +1 -1
- package/package.json +10 -10
- package/dist/agent-docs-CCJdXCYA.mjs +0 -12
- package/dist/doctor-Dj_h900X.mjs +0 -1234
- package/dist/doctor-Dj_h900X.mjs.map +0 -1
- package/dist/project-docs-DXV06Vu3.mjs.map +0 -1
- package/dist/run-plugins-Cyv_2-7g.mjs.map +0 -1
- package/dist/typegen-Dhfw8V1k.mjs.map +0 -1
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @forinda/kickjs-cli v6.
|
|
2
|
+
* @forinda/kickjs-cli v6.5.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Felix Orinda
|
|
5
5
|
*
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
|
-
import{createRequire as e}from"node:module";import{Command as t}from"commander";import{cpSync as n,existsSync as r,mkdirSync as i,readFileSync as a,readdirSync as o,rmSync as s,statSync as c,writeFileSync as l}from"node:fs";import u,{basename as d,dirname as f,extname as p,isAbsolute as m,join as h,parse as g,relative as _,resolve as v,sep as y}from"node:path";import{fileURLToPath as b,pathToFileURL as x}from"node:url";import{execFileSync as
|
|
12
|
-
`,`utf-8`)}catch{}}function
|
|
11
|
+
import{createRequire as e}from"node:module";import{Command as t}from"commander";import{cpSync as n,existsSync as r,mkdirSync as i,readFileSync as a,readdirSync as o,rmSync as s,statSync as c,writeFileSync as l}from"node:fs";import u,{basename as d,dirname as f,extname as p,isAbsolute as m,join as h,parse as g,relative as _,resolve as v,sep as y}from"node:path";import{fileURLToPath as b,pathToFileURL as x}from"node:url";import{execFileSync as ee,execSync as S,fork as te,spawn as ne,spawnSync as re}from"node:child_process";import{access as ie,copyFile as ae,mkdir as C,readFile as w,readdir as oe,rm as se,stat as ce,unlink as le,writeFile as T}from"node:fs/promises";import{KickPluginConflictError as ue,defineCliPlugin as E}from"@forinda/kickjs-cli-kit";import*as D from"@clack/prompts";import O from"picocolors";import de from"pluralize";import{parseSync as fe}from"oxc-parser";import{glob as pe,globSync as me}from"glob";import{groupAssetKeys as he}from"@forinda/kickjs";import{arch as ge,platform as _e,release as ve}from"node:os";var ye=Object.defineProperty,k=(e,t)=>{let n={};for(var r in e)ye(n,r,{get:e[r],enumerable:!0});return t||ye(n,Symbol.toStringTag,{value:`Module`}),n};function be(e,t,n){S(e,{cwd:t,stdio:`inherit`,env:n?{...process.env,...n}:process.env})}function xe(e,t,n){let r=re(process.execPath,[e],{cwd:n,stdio:`inherit`,env:{...process.env,...t}});r.status!==0&&process.exit(r.status??1)}function Se(e,t){if(!t?.commands?.length)return;let n=new Set(e.commands.map(e=>e.name()));for(let r of t.commands){if(n.has(r.name)){console.warn(` Warning: custom command '${r.name}' skipped — conflicts with a built-in command`);continue}Ce(e,r)}}function Ce(e,t){let n=e.command(t.name).description(t.description);if(t.aliases)for(let e of t.aliases)n.alias(e);n.allowUnknownOption(!0),n.argument(`[args...]`,`Additional arguments passed to the command`),n.action(e=>{let n=e.join(` `),r=Array.isArray(t.steps)?t.steps:[t.steps];for(let e of r){let r=n?`${e} ${n}`:e;console.log(` $ ${r}`);try{be(r)}catch{console.error(` Command failed: ${t.name}`),process.exitCode=1;return}}})}var we=k({BUILTIN_REPO_TYPES:()=>Ee,DEPRECATED_REPO_TYPES:()=>De,PACKAGE_MANAGERS:()=>Te,defineConfig:()=>ke,loadKickConfig:()=>j,resolveModuleConfig:()=>A,resolveTokenScope:()=>Ae,validateAssetMap:()=>Pe,warnIfDeprecatedRepo:()=>Oe,writeAssetConfigSnapshot:()=>Ne});const Te=[`pnpm`,`npm`,`yarn`,`bun`],Ee=[`inmemory`],De=[`prisma`,`drizzle`];function Oe(e){return De.includes(e)?(console.warn(` Note: the '${e}' repository preset is deprecated. Generating a generic custom repository named '${e}' instead — wire it to your DB by hand. Pass any name via \`--repo <name>\` or \`modules.repo: { name: '<name>' }\`.`),!0):!1}function ke(e){return e}function Ae(e,t){if(e?.tokenScope&&typeof e.tokenScope==`string`&&e.tokenScope.length>0){let t=je(e.tokenScope);if(t.length>0)return t}try{let e=h(t,`package.json`);if(r(e)){let t=JSON.parse(a(e,`utf-8`));if(typeof t.name==`string`&&t.name.length>0){let e=t.name.match(/^@([^/]+)\//),n=je(e?e[1]:t.name);if(n.length>0)return n}}}catch{}return`app`}function je(e){return e.toLowerCase().replace(/[^a-z0-9-]/g,`-`).replace(/^-+|-+$/g,``).replace(/-{2,}/g,`-`)}function A(e){if(!e)return{};let t={dir:e.modules?.dir,repo:e.modules?.repo,schemaDir:e.modules?.schemaDir,pluralize:e.modules?.pluralize,prismaClientPath:e.modules?.prismaClientPath,style:e.modules?.style};return t.style!==void 0&&t.style!==`define`&&t.style!==`class`&&(console.warn(` Warning: modules.style '${t.style}' is not a valid value (expected 'define' or 'class'). Falling back to 'define'.`),t.style=`define`),t.repo&&typeof t.repo==`string`&&!Ee.includes(t.repo)&&(Oe(t.repo)||console.warn(` Warning: modules.repo '${t.repo}' is not a built-in type (${Ee.join(`, `)}). It will generate a stub repository. Use { name: '${t.repo}' } to silence this warning.`)),t}const Me=[`kick.config.ts`,`kick.config.js`,`kick.config.mjs`,`kick.config.json`];async function j(e){let{findProjectRoot:t}=await Promise.resolve().then(()=>tn),n=t(e);for(let e of Me){let t=h(n,e);try{await ie(t)}catch{continue}if(e.endsWith(`.json`)){let e=await w(t,`utf-8`);return JSON.parse(e)}if(e.endsWith(`.ts`)){let r;try{r=await import(`jiti`)}catch(t){let n=t instanceof Error?t.message:String(t);n.includes(`Cannot find package 'jiti'`)||n.includes(`ERR_MODULE_NOT_FOUND`)?console.warn(`Warning: Failed to load ${e} — 'jiti' is required for TypeScript configs. Run \`pnpm add -D jiti\` (or your package manager's equivalent), or rename the file to kick.config.js / kick.config.mjs / kick.config.json.`):console.warn(`Warning: Failed to initialize jiti for ${e}: ${n}`);continue}try{let e=await r.createJiti(n,{interopDefault:!0,fsCache:!1}).import(t,{default:!0}),i=Pe(e,n);for(let e of i)console.warn(` Warning: ${e}`);return Ne(n,e),e}catch(t){let n=t instanceof Error?t.message:String(t);console.warn(`Warning: Failed to load ${e}: ${n}`);continue}}try{let{pathToFileURL:e}=await import(`node:url`),r=await import(e(t).href),i=r.default??r,a=Pe(i,n);for(let e of a)console.warn(` Warning: ${e}`);return Ne(n,i),i}catch(t){let n=t instanceof Error?t.message:String(t);console.warn(`Warning: Failed to load ${e}: ${n}`);continue}}return null}function Ne(e,t){if(!(!t?.assetMap||Object.keys(t.assetMap).length===0))try{let n=h(e,`.kickjs`);i(n,{recursive:!0});let r={version:1,assetMap:t.assetMap,...t.build?.outDir?{build:{outDir:t.build.outDir}}:{}};l(h(n,`kick.config.json`),JSON.stringify(r,null,2)+`
|
|
12
|
+
`,`utf-8`)}catch{}}function Pe(e,t){let n=[];if(!e?.assetMap)return n;let i=v(t);for(let[a,o]of Object.entries(e.assetMap)){if(!a||a.includes(`/`)){n.push(`assetMap key '${a}' is invalid — must be a non-empty string without '/'`);continue}if(typeof o?.src!=`string`||o.src.length===0){n.push(`assetMap.${a} is missing a non-empty 'src' field`);continue}r(v(t,o.src))||n.push(`assetMap.${a}.src ('${o.src}') does not exist — typegen + build will fail`),o.dest&&Fe(v(t,o.dest),i)&&n.push(`assetMap.${a}.dest ('${o.dest}') resolves outside the project root — refusing to copy`)}return n}function Fe(e,t){let n=_(t,e);return n===``?!1:n.startsWith(`..`)||m(n)}function Ie(e,t=[]){let n=new Map;for(let t of e){let e=(n.get(t.name)??0)+1;if(n.set(t.name,e),e===2)throw new ue(`plugin`,t.name,[t.name,t.name])}let r=new Map,i=[];for(let t of e)for(let e of t.commands??[]){let n=r.get(e.name);if(n)throw new ue(`command`,e.name,[n,t.name]);r.set(e.name,t.name),i.push(e)}let a=new Set(t.map(e=>e.name)),o=[...i.filter(e=>!a.has(e.name)),...t],s=new Map,c=[];for(let t of e)for(let e of t.typegens??[]){let n=s.get(e.id);if(n)throw new ue(`typegen`,e.id,[n,t.name]);s.set(e.id,t.name),c.push(e)}let l=new Map,u=[];for(let t of e)for(let e of t.generators??[]){let n=l.get(e.name);if(n)throw new ue(`generator`,e.name,[n,t.name]);l.set(e.name,t.name),u.push({source:t.name,spec:e})}return{commands:o,typegens:c,generators:u,register:async(t,n)=>{let r;if(n)r={generators:u,...n};else{let{findProjectRoot:e}=await Promise.resolve().then(()=>tn),t=process.cwd();r={cwd:t,projectRoot:e(t),config:null,log:()=>{},generators:u}}for(let n of e)n.register&&await n.register(t,r)}}}var Le=k({mergeCliPlugins:()=>Ie});let Re=!1;function M(e){Re=e}const ze=new Set([`.ts`,`.tsx`,`.js`,`.jsx`,`.mjs`,`.cjs`,`.json`,`.md`]);async function N(e,t){Re||(await C(f(e),{recursive:!0}),await T(e,t,`utf-8`),ze.has(p(e))&&await He(e,t).catch(()=>{}))}let Be;async function Ve(t){if(Be!==void 0)return Be;try{Be=await import(e(h(t,`package.json`)).resolve(`oxfmt`))}catch{Be=null}return Be}async function He(e,t){let n=await Ve(process.cwd());if(!n)return;let r=await We(e);if(r===null)return;let i=await n.format(e,t,r);i.code!==t&&await T(e,i.code,`utf-8`)}const Ue=new Map;async function We(e){let t=f(e),n=t;if(Ue.has(n))return Ue.get(n);for(;;){let e=h(t,`.oxfmtrc.json`);if(r(e))try{let t=await w(e,`utf-8`),r=JSON.parse(t);return delete r.$schema,delete r.ignorePatterns,Ue.set(n,r),r}catch{return Ue.set(n,null),null}let i=f(t);if(i===t)return Ue.set(n,null),null;t=i}}async function Ge(e){try{return await ie(e),!0}catch{return!1}}const Ke={swagger:`@forinda/kickjs-swagger`,ws:`@forinda/kickjs-ws`,queue:`@forinda/kickjs-queue`,devtools:`@forinda/kickjs-devtools`},qe={zod:{name:`zod`,range:`^4.3.6`},valibot:{name:`valibot`,range:`^1.4.1`},yup:{name:`yup`,range:`^1.7.1`}};function Je(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 Ye(e,t,n,r=[],i=`zod`,a=`express`){let o=qe[i],s={"@forinda/kickjs":Je(n,`@forinda/kickjs`),"@forinda/kickjs-schema":Je(n,`@forinda/kickjs-schema`),dotenv:`^17.3.1`,"reflect-metadata":`^0.2.2`,[o.name]:o.range};a===`express`?s.express=`^5.1.0`:a===`fastify`?(s.fastify=`^5.0.0`,s[`@fastify/middie`]=`^9.0.0`,s[`serve-static`]=`^2.2.0`):a===`h3`&&(s.h3=`^1.0.0`,s[`serve-static`]=`^2.2.0`);for(let e of r){let t=Ke[e];t&&!s[t]&&(s[t]=Je(n,t))}return JSON.stringify({name:e,version:`0.0.0`,type:`module`,scripts:{dev:`kick dev`,"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:s,devDependencies:{"@forinda/kickjs-cli":Je(n,`@forinda/kickjs-cli`),"@forinda/kickjs-vite":Je(n,`@forinda/kickjs-vite`),"@swc/core":`^1.15.21`,...a===`express`?{"@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 Xe(){return`import { defineConfig } from 'vite'
|
|
13
13
|
import { resolve } from 'node:path'
|
|
14
14
|
import swc from 'unplugin-swc'
|
|
15
15
|
import { kickjsVitePlugin, envWatchPlugin } from '@forinda/kickjs-vite'
|
|
@@ -39,7 +39,7 @@ export default defineConfig({
|
|
|
39
39
|
},
|
|
40
40
|
},
|
|
41
41
|
})
|
|
42
|
-
`}function
|
|
42
|
+
`}function Ze(){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 Qe(){return JSON.stringify({semi:!1,singleQuote:!0,trailingComma:`all`,printWidth:100,tabWidth:2},null,2)}function $e(){return`# https://editorconfig.org
|
|
43
43
|
root = true
|
|
44
44
|
|
|
45
45
|
[*]
|
|
@@ -52,14 +52,14 @@ insert_final_newline = true
|
|
|
52
52
|
|
|
53
53
|
[*.md]
|
|
54
54
|
trim_trailing_whitespace = false
|
|
55
|
-
`}function
|
|
55
|
+
`}function et(){return`node_modules/
|
|
56
56
|
dist/
|
|
57
57
|
.env
|
|
58
58
|
coverage/
|
|
59
59
|
.DS_Store
|
|
60
60
|
*.tsbuildinfo
|
|
61
61
|
.kickjs/
|
|
62
|
-
`}function
|
|
62
|
+
`}function tt(){return`# Auto-detect text files and normalise line endings to LF
|
|
63
63
|
* text=auto eol=lf
|
|
64
64
|
|
|
65
65
|
# Explicitly mark generated / binary files
|
|
@@ -77,11 +77,11 @@ coverage/
|
|
|
77
77
|
pnpm-lock.yaml -diff linguist-generated
|
|
78
78
|
yarn.lock -diff linguist-generated
|
|
79
79
|
package-lock.json -diff linguist-generated
|
|
80
|
-
`}function tt(){return`PORT=3000
|
|
81
|
-
NODE_ENV=development
|
|
82
80
|
`}function nt(){return`PORT=3000
|
|
83
81
|
NODE_ENV=development
|
|
84
|
-
`}function rt(){return`
|
|
82
|
+
`}function rt(){return`PORT=3000
|
|
83
|
+
NODE_ENV=development
|
|
84
|
+
`}function it(){return`import { defineConfig } from 'vitest/config'
|
|
85
85
|
import swc from 'unplugin-swc'
|
|
86
86
|
|
|
87
87
|
export default defineConfig({
|
|
@@ -92,7 +92,7 @@ export default defineConfig({
|
|
|
92
92
|
include: ['src/**/*.test.ts'],
|
|
93
93
|
},
|
|
94
94
|
})
|
|
95
|
-
`}const
|
|
95
|
+
`}const at={express:{from:`@forinda/kickjs`,name:`expressRuntime`},fastify:{from:`@forinda/kickjs/fastify`,name:`fastifyRuntime`},h3:{from:`@forinda/kickjs/h3`,name:`h3Runtime`}};function ot(e,t,n,r=[],i=`express`){let a=at[i],o=i===`express`;switch(t){case`minimal`:{let t=[],i=[],s=o?`import { bootstrap, ${a.name} } from '@forinda/kickjs'`:`import { bootstrap } from '@forinda/kickjs'\nimport { ${a.name} } from '${a.from}'`;r.includes(`swagger`)&&(t.push(`import { SwaggerAdapter } from '@forinda/kickjs-swagger'`),i.push(` SwaggerAdapter({ info: { title: '${e}', version: '${n}' } }),`)),r.includes(`devtools`)&&(t.push(`import { DevToolsAdapter } from '@forinda/kickjs-devtools'`),i.push(` DevToolsAdapter(),`));let c=t.length?t.join(`
|
|
96
96
|
`)+`
|
|
97
97
|
`:``,l=i.length?`,\n adapters: [\n${i.join(`
|
|
98
98
|
`)}\n ]`:``;return`import 'reflect-metadata'
|
|
@@ -132,14 +132,14 @@ export const app = await bootstrap({
|
|
|
132
132
|
requestLogger(),${d}
|
|
133
133
|
],
|
|
134
134
|
})
|
|
135
|
-
`}}}function
|
|
135
|
+
`}}}function st(){return`import { defineModules } from '@forinda/kickjs'
|
|
136
136
|
import { HelloModule } from './hello/hello.module'
|
|
137
137
|
|
|
138
138
|
// Remove HelloModule and run: kick g module <name>
|
|
139
139
|
// \`defineModules()\` returns a chainable list — \`kick g module\` appends
|
|
140
140
|
// \`.mount(NewModule())\` to the chain on every generation.
|
|
141
141
|
export const modules = defineModules().mount(HelloModule())
|
|
142
|
-
`}function
|
|
142
|
+
`}function ct(e=`zod`){return e===`valibot`?`import { loadEnvFromSchema } from '@forinda/kickjs/config'
|
|
143
143
|
import { fromValibot } from '@forinda/kickjs-schema/valibot'
|
|
144
144
|
import * as v from 'valibot'
|
|
145
145
|
|
|
@@ -267,7 +267,7 @@ const envSchema = fromZod(
|
|
|
267
267
|
export const env = loadEnvFromSchema(envSchema)
|
|
268
268
|
|
|
269
269
|
export default envSchema
|
|
270
|
-
`}function
|
|
270
|
+
`}function lt(){return`import { Service } from '@forinda/kickjs'
|
|
271
271
|
|
|
272
272
|
@Service()
|
|
273
273
|
export class HelloService {
|
|
@@ -279,7 +279,7 @@ export class HelloService {
|
|
|
279
279
|
return { status: 'ok', uptime: process.uptime() }
|
|
280
280
|
}
|
|
281
281
|
}
|
|
282
|
-
`}function
|
|
282
|
+
`}function ut(){return`import { Controller, Get, Autowired, type Ctx } from '@forinda/kickjs'
|
|
283
283
|
import { HelloService } from './hello.service'
|
|
284
284
|
|
|
285
285
|
// \`Ctx<KickRoutes.HelloController['<method>']>\` is generated by
|
|
@@ -291,17 +291,21 @@ import { HelloService } from './hello.service'
|
|
|
291
291
|
export class HelloController {
|
|
292
292
|
@Autowired() private readonly helloService!: HelloService
|
|
293
293
|
|
|
294
|
+
// Return-value handlers: the runtime sends the returned payload as
|
|
295
|
+
// 200 json, and \`kick typegen\` infers the response type into
|
|
296
|
+
// \`KickRoutes.Api\` — which is what makes the typed client
|
|
297
|
+
// (@forinda/kickjs-client) end-to-end type-safe.
|
|
294
298
|
@Get('/')
|
|
295
|
-
index(
|
|
296
|
-
|
|
299
|
+
index(_ctx: Ctx<KickRoutes.HelloController['index']>) {
|
|
300
|
+
return this.helloService.greet('World')
|
|
297
301
|
}
|
|
298
302
|
|
|
299
303
|
@Get('/health')
|
|
300
|
-
health(
|
|
301
|
-
|
|
304
|
+
health(_ctx: Ctx<KickRoutes.HelloController['health']>) {
|
|
305
|
+
return this.helloService.healthCheck()
|
|
302
306
|
}
|
|
303
307
|
}
|
|
304
|
-
`}function
|
|
308
|
+
`}function dt(){return`import { defineModule } from '@forinda/kickjs'
|
|
305
309
|
import { HelloController } from './hello.controller'
|
|
306
310
|
|
|
307
311
|
export const HelloModule = defineModule({
|
|
@@ -322,7 +326,7 @@ export const HelloModule = defineModule({
|
|
|
322
326
|
},
|
|
323
327
|
}),
|
|
324
328
|
})
|
|
325
|
-
`}function
|
|
329
|
+
`}function ft(e,t=`inmemory`,n=`pnpm`,r=`express`){return`import { defineConfig } from '@forinda/kickjs-cli'
|
|
326
330
|
|
|
327
331
|
export default defineConfig({
|
|
328
332
|
pattern: '${e}',
|
|
@@ -374,7 +378,7 @@ export default defineConfig({
|
|
|
374
378
|
},
|
|
375
379
|
],
|
|
376
380
|
})
|
|
377
|
-
`}function
|
|
381
|
+
`}function pt(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`),`# ${e}
|
|
378
382
|
|
|
379
383
|
A **${r[t]??`REST API`}** built with [KickJS](https://kickjs.app/) — a decorator-driven Node.js framework for TypeScript that runs on Express, Fastify, or h3 (swap the engine in one line).
|
|
380
384
|
|
|
@@ -437,7 +441,7 @@ Copy \`.env.example\` to \`.env\` and configure:
|
|
|
437
441
|
|
|
438
442
|
- [KickJS Documentation](https://kickjs.app/)
|
|
439
443
|
- [CLI Reference](https://kickjs.app/api/cli.html)
|
|
440
|
-
`}function
|
|
444
|
+
`}function mt(e,t,n){return`# CLAUDE.md — ${e}
|
|
441
445
|
|
|
442
446
|
**Read \`./.agents/AGENTS.md\` first.** It is the canonical, multi-agent
|
|
443
447
|
reference for this project (Claude, Copilot, Codex, Gemini, etc.) —
|
|
@@ -512,7 +516,7 @@ When generating or modifying code in this project, stay aligned with the v4 conv
|
|
|
512
516
|
- **Refresh these files**: \`kick g agents -f\` regenerates \`CLAUDE.md\` at the project root and \`.agents/AGENTS.md\` + \`.agents/GEMINI.md\` + \`.agents/COPILOT.md\` + every \`.agents/skills/<name>/SKILL.md\` from the latest CLI templates. Hand-edited content is overwritten — keep customisation in \`.agents/AGENTS.local.md\` or per-skill \`SKILL.local.md\` files alongside.
|
|
513
517
|
|
|
514
518
|
For everything else (controllers, services, modules, RequestContext API, generators, CLI commands, package additions, env wiring, troubleshooting) → \`.agents/AGENTS.md\`.
|
|
515
|
-
`}function
|
|
519
|
+
`}function ht(e,t,n){return`# AGENTS.md — AI Agent Guide for ${e}
|
|
516
520
|
|
|
517
521
|
This guide is the **canonical, multi-agent reference** for this KickJS
|
|
518
522
|
application — Claude, Copilot, Codex, Gemini, etc. all read it first.
|
|
@@ -1027,7 +1031,7 @@ Full guide: <https://kickjs.app/guide/context-decorators>.
|
|
|
1027
1031
|
- [Decorators Guide](https://kickjs.app/guide/decorators.html)
|
|
1028
1032
|
- [DI System](https://kickjs.app/guide/dependency-injection.html)
|
|
1029
1033
|
- [Testing](https://kickjs.app/api/testing.html)
|
|
1030
|
-
`}function
|
|
1034
|
+
`}function gt(e,t,n){let r=`<!-- Generated by \`kick g agents\` for ${e}. Edits are overwritten on the next refresh; keep customisation in a SKILL.local.md alongside. -->`;return[{slug:`add-module`,frontmatterName:`kickjs-add-module`,description:`Use when the user asks to add a new feature module (controller + service + repo + DTOs).`,body:`**Trigger phrases**: "add a users module", "scaffold tasks", "new feature for X".
|
|
1031
1035
|
|
|
1032
1036
|
**Steps**:
|
|
1033
1037
|
1. Run \`kick g module <name>\` (use plural form if the project pluralizes — check \`kick.config.ts\`).
|
|
@@ -1162,7 +1166,7 @@ description: ${e.description}
|
|
|
1162
1166
|
${r}
|
|
1163
1167
|
|
|
1164
1168
|
${e.body}
|
|
1165
|
-
`}))}function
|
|
1169
|
+
`}))}function _t(e,t,n){return`# GEMINI.md — ${e}
|
|
1166
1170
|
|
|
1167
1171
|
**Read \`./AGENTS.md\` first.** It is the canonical, multi-agent
|
|
1168
1172
|
reference for this project — every convention, structure, decorator
|
|
@@ -1196,7 +1200,7 @@ without us copy-pasting.
|
|
|
1196
1200
|
\`kick g agents --only gemini -f\` regenerates this file from the
|
|
1197
1201
|
CLI template. Hand-edited content is overwritten — keep customisation
|
|
1198
1202
|
in \`.agents/GEMINI.local.md\`.
|
|
1199
|
-
`}function
|
|
1203
|
+
`}function vt(e,t,n){return`# COPILOT.md — ${e}
|
|
1200
1204
|
|
|
1201
1205
|
**Read \`./AGENTS.md\` first.** It is the canonical, multi-agent
|
|
1202
1206
|
reference for this project — every convention, structure, decorator
|
|
@@ -1229,16 +1233,16 @@ Codex / Cursor / Gemini / Claude Code without copy-pasting.
|
|
|
1229
1233
|
\`kick g agents --only copilot -f\` regenerates this file from the
|
|
1230
1234
|
CLI template. Hand-edited content is overwritten — keep customisation
|
|
1231
1235
|
in \`.agents/COPILOT.local.md\`.
|
|
1232
|
-
`}const
|
|
1236
|
+
`}const yt={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},zod:{pkg:`zod`,peers:[],description:`Zod schema validation (env, DTOs, OpenAPI) — wrap with fromZod()`},valibot:{pkg:`valibot`,peers:[],description:`Valibot schema validation — wrap with fromValibot()`},yup:{pkg:`yup`,peers:[],description:`Yup schema validation — wrap with fromYup()`},auth:{pkg:`@forinda/kickjs-auth`,peers:[`jsonwebtoken`],description:`JWT, API key, OAuth strategies, @Public, @Roles (+ optional argon2/bcryptjs)`,deprecated:`auth is moving to BYO — compose @LoadAuthUser/@RequireRole/@Public from defineContextDecorator (see the BYO Auth recipe in the docs)`},ai:{pkg:`@forinda/kickjs-ai`,peers:[`zod`],description:`AI toolkit — LLM providers, tool definitions from controllers`},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`},pg:{pkg:`@forinda/kickjs-db`,peers:[`pg`],description:`kick/db + PostgreSQL driver (use @forinda/kickjs-db/pg)`},sqlite:{pkg:`@forinda/kickjs-db`,peers:[`better-sqlite3`],description:`kick/db + SQLite driver (use @forinda/kickjs-db/sqlite)`},mysql:{pkg:`@forinda/kickjs-db`,peers:[`mysql2`],description:`kick/db + MySQL driver (use @forinda/kickjs-db/mysql)`},drizzle:{pkg:`@forinda/kickjs-drizzle`,peers:[`drizzle-orm`],description:`Drizzle ORM adapter + query builder`,deprecated:"early-adoption adapter, no longer maintained — wire Drizzle directly (BYO), or use @forinda/kickjs-db, the built-in Kick ORM (`kick add db` / pg / sqlite / mysql)"},prisma:{pkg:`@forinda/kickjs-prisma`,peers:[`@prisma/client`],description:`Prisma adapter + query builder`,deprecated:"early-adoption adapter, no longer maintained — wire Prisma directly (BYO), or use @forinda/kickjs-db, the built-in Kick ORM (`kick add db` / pg / sqlite / mysql)"},ws:{pkg:`@forinda/kickjs-ws`,peers:[`ws`],description:`WebSocket with @WsController decorators`},devtools:{pkg:`@forinda/kickjs-devtools`,peers:[],description:`Development dashboard — routes, DI, metrics, health`,dev:!0},queue:{pkg:`@forinda/kickjs-queue`,peers:[],description:`Queue adapter (BullMQ/RabbitMQ/Kafka)`},"queue:bullmq":{pkg:`@forinda/kickjs-queue`,peers:[`bullmq`,`ioredis`],description:`Queue with BullMQ + Redis`},"queue:rabbitmq":{pkg:`@forinda/kickjs-queue`,peers:[`amqplib`],description:`Queue with RabbitMQ`},"queue:kafka":{pkg:`@forinda/kickjs-queue`,peers:[`kafkajs`],description:`Queue with Kafka`},"queue:redis-pubsub":{pkg:`@forinda/kickjs-queue`,peers:[`ioredis`],description:`Lightweight pub/sub via Redis (no persistence)`},mcp:{pkg:`@forinda/kickjs-mcp`,peers:[`@modelcontextprotocol/sdk`],description:`Model Context Protocol server — expose @Controller endpoints as AI tools`},testing:{pkg:`@forinda/kickjs-testing`,peers:[],description:`Test utilities and TestModule builder`,dev:!0}},bt=Object.entries(yt).filter(([e,t])=>!t.core&&!t.deprecated&&!e.includes(`:`)&&![`pg`,`sqlite`,`mysql`,`zod`,`valibot`,`yup`].includes(e)).map(([e])=>e).join(`, `),xt={express:{prod:`multer`,dev:`@types/multer`,note:`Express uploads use multer (memory/disk storage, ctx.file / ctx.files).`},fastify:{prod:`@fastify/multipart`,note:`Fastify uploads use @fastify/multipart (buffered into ctx.file / ctx.files).`},h3:{note:`h3 parses multipart natively (readMultipartFormData) — no driver to install.`}};async function St(e=process.cwd()){let t=(await j(e))?.runtime;return t===`express`||t===`fastify`||t===`h3`?t:Ct(e)}function Ct(e=process.cwd()){let t=wt(`package.json`,e);if(t)try{let e=JSON.parse(a(v(t,`package.json`),`utf-8`)),n={...e.dependencies,...e.devDependencies};if(`fastify`in n)return`fastify`;if(`h3`in n)return`h3`}catch{}return`express`}function wt(e,t=process.cwd()){let n=t;for(;;){if(r(v(n,e)))return n;let t=f(n);if(t===n)return null;n=t}}function Tt(){return wt(`pnpm-lock.yaml`)?`pnpm`:wt(`yarn.lock`)?`yarn`:wt(`bun.lockb`)||wt(`bun.lock`)?`bun`:wt(`package-lock.json`)?`npm`:null}function Et(){let e=process.cwd();for(;e;){let t=v(e,`package.json`);if(r(t))try{let e=JSON.parse(a(t,`utf-8`)).packageManager;if(typeof e==`string`){let t=e.split(`@`)[0];if(Te.includes(t))return t}}catch{}let n=f(e);if(n===e)return null;e=n}return null}async function Dt(e){if(e&&Te.includes(e))return{pm:e,source:`flag`};let t=await j(process.cwd());if(t?.packageManager&&Te.includes(t.packageManager))return{pm:t.packageManager,source:`config`};let n=Et();if(n)return{pm:n,source:`package.json`};let r=Tt();return r?{pm:r,source:`lockfile`}:{pm:`npm`,source:`default`}}async function Ot(e){let{pm:t}=await Dt(e);return t}function kt(e=!1){let t=Object.entries(yt),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(`, `)})`:``,a=t.deprecated?` [DEPRECATED — ${t.deprecated}]`:``;return` ${r} ${t.description}${i}${a}`};console.log(`
|
|
1233
1237
|
Core packages (always installed by \`kick new\`):
|
|
1234
1238
|
`);for(let e of r)console.log(a(e));if(e){console.log(`
|
|
1235
1239
|
Optional packages (add as needed):
|
|
1236
1240
|
`);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(`
|
|
1237
|
-
Usage: kick add ai db swagger`),console.log(` kick add queue:bullmq`),console.log(` kick add upload # installs the multipart driver for your runtime`),console.log()}function
|
|
1238
|
-
`),a.length===0&&o.length===0))){if(a.length>0){let e=a,t=`${n} add ${e.join(` `)}`;console.log(`\n Installing ${e.length} dependency(ies):`);for(let t of e)console.log(` + ${t}`);console.log();try{
|
|
1239
|
-
`)}})}const
|
|
1240
|
-
Dependencies installed successfully!`)}catch{console.log(`\n Warning: ${r} install failed. Run it manually.`)}}try{let{runTypegen:e}=await Promise.resolve().then(()=>Aa);await e({cwd:l,allowDuplicates:!0,silent:!0})}catch{}if(e.initGit)try{
|
|
1241
|
-
Project scaffolded successfully!`),console.log();let p=l!==process.cwd();u(`Next steps:`),p&&u(` cd ${t}`),e.installDeps||u(` ${r} install`);let m={rest:`kick g module user`,ddd:`kick g module user --repo drizzle`,cqrs:`kick g module user --pattern cqrs`,minimal:`# add your routes to src/index.ts`};u(` ${m[i]??m.rest}`),u(` kick dev`),u(``),u(`Commands:`),u(` kick dev Start dev server with Vite HMR`),u(` kick build Production build via Vite`),u(` kick start Run production build`),u(``),u(`Generators:`),u(` kick g module <name> Full DDD module (controller, DTOs, use-cases, repo)`),u(` kick g scaffold <n> <f..> CRUD module from field definitions`),u(` kick g controller <name> Standalone controller`),u(` kick g service <name> @Service() class`),u(` kick g middleware <name> Express middleware`),u(` kick g guard <name> Route guard (auth, roles, etc.)`),u(` kick g adapter <name> AppAdapter with lifecycle hooks`),u(` kick g dto <name> Zod DTO schema`),u(` kick g config Generate kick.config.ts`),u(``),u(`Add packages:`),u(` kick add <pkg> Install a KickJS package + peers`),u(` kick add --list Show all available packages`),u(``),u(`Available: ${yt}`),u(``)}const Ht={GET:k.green,POST:k.cyan,PUT:k.yellow,PATCH:k.magenta,DELETE:k.red};function Ut(e){return(Ht[e]??k.dim)(e.padEnd(7))}function Wt(e){let t=`[${e}]`.padEnd(10);switch(e){case`CRITICAL`:return k.red(t);case`WARNING`:return k.yellow(t);case`INFO`:return k.blue(k.dim(t));default:return t}}k.green(`✓`),k.red(`✖`),k.yellow(`⚠`),k.blue(`ℹ`);function Gt(e){O.intro(k.bgCyan(k.black(` ${e} `)))}function F(e){O.outro(e)}function Kt(e){O.isCancel(e)&&(O.cancel(`Operation cancelled.`),process.exit(0))}async function qt(e){let t=await O.text(e);return Kt(t),t}async function Jt(e){let t=await O.select(e);return Kt(t),t}async function Yt(e){let t=await O.multiselect(e);return Kt(t),t}async function I(e){let t=await O.confirm(e);return Kt(t),t}function Xt(){return O.spinner()}const L=O.log,Zt=[{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 Qt(e){e.command(`new [name]`).alias(`init`).description(`Create a new KickJS project (use "." for current directory)`).option(`-d, --directory <dir>`,`Target directory (defaults to project name)`).option(`--pm <manager>`,`Package manager: pnpm | npm | yarn | bun`).option(`--git`,`Initialize git repository`).option(`--no-git`,`Skip git initialization`).option(`--install`,`Install dependencies after scaffolding`).option(`--no-install`,`Skip dependency installation`).option(`-f, --force`,`Remove existing files without prompting`).option(`-t, --template <type>`,`Project template: rest | minimal`).option(`--runtime <engine>`,`HTTP runtime: express | fastify | h3`).option(`-r, --repo <type>`,`Repository name (inmemory, or any DB name e.g. postgres)`).option(`-s, --schema <lib>`,`Schema library for env / DTOs: zod | valibot | yup (default: zod)`).option(`--packages <packages>`,`Comma-separated packages to include (e.g. auth,swagger,ws,queue)`).option(`-y, --yes`,`Pick safe defaults for every prompt (template=minimal, repo=inmemory, no extras, git+install on)`).option(`--non-interactive`,`alias for --yes`).action(async(e,t)=>{Gt(`KickJS — Create a new project`);let n=!!(t.yes||t.nonInteractive);e||=n?`my-api`:await qt({message:`Project name`,placeholder:`my-api`,defaultValue:`my-api`});let i;if(e===`.`?(i=v(`.`),e=d(i)):i=v(t.directory||e),r(i)){let r=o(i);if(r.length>0){if(t.force)L.warn(`Clearing existing files in ${i}`);else if(n){L.warn(`Directory "${e}" is not empty. Pass --force to clear it.`),F(`Aborted.`);return}else{L.warn(`Directory "${e}" is not empty:`);let t=r.slice(0,5);for(let e of t)L.message(` - ${e}`);if(r.length>5&&L.message(` ... and ${r.length-5} more`),!await I({message:k.red(`Remove all existing files and proceed?`),initialValue:!1})){F(`Aborted.`);return}}for(let e of r)s(v(i,e),{recursive:!0,force:!0})}}let a=t.template;a||=n?`minimal`:await Jt({message:`Project template`,options:[{value:`rest`,label:`REST API`,hint:`Express + Swagger`},{value:`minimal`,label:`Minimal`,hint:`bare Express`}]});let c=t.runtime;c||=n?`express`:await Jt({message:`HTTP runtime`,options:[{value:`express`,label:`Express`,hint:`default, zero-config`},{value:`fastify`,label:`Fastify`,hint:`fastify + @fastify/middie`},{value:`h3`,label:`h3`,hint:`Nitro / Nuxt engine`}]});let l=t.pm;l||=n?await Dt(void 0):await Jt({message:`Package manager`,options:[{value:`pnpm`,label:`pnpm`},{value:`npm`,label:`npm`},{value:`yarn`,label:`yarn`},{value:`bun`,label:`bun`}]});let u=t.repo;u||=n?`inmemory`:await qt({message:`Repository name`,placeholder:`inmemory (or a DB name, e.g. postgres)`,defaultValue:`inmemory`}),De(u);let f=t.schema;f||=n?`zod`:await Jt({message:`Schema library (env + DTO validation)`,options:[{value:`zod`,label:`Zod`,hint:`default — broad ecosystem`},{value:`valibot`,label:`Valibot`,hint:`smaller bundle`},{value:`yup`,label:`Yup`,hint:`classic API`}]}),[`zod`,`valibot`,`yup`].includes(f)||(L.warn(`Unknown --schema "${f}", falling back to zod.`),f=`zod`);let p;if(t.packages!==void 0){let e=t.packages.trim().toLowerCase();p=e===``||e===`none`||e===`false`?[]:t.packages.split(`,`).map(e=>e.trim()).filter(Boolean)}else p=n?[]:await Yt({message:`Select packages to include`,options:[...Zt],required:!1});let m;m=t.git===void 0?n?!0:await I({message:`Initialize git repository?`,initialValue:!0}):t.git;let h;h=t.install===void 0?n?!0:await I({message:`Install dependencies?`,initialValue:!0}):t.install,await Vt({name:e,directory:i,packageManager:l,initGit:m,installDeps:h,template:a,defaultRepo:u,packages:p,schemaLib:f,runtime:c}),F(`Done! Next steps: ${k.cyan(`cd ${e} && ${l} 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 $t(e){return ue.plural(e)}function en(e){return ue.plural(e)}var tn=A({findProjectRoot:()=>rn});const nn=[`kick.config.ts`,`kick.config.js`,`kick.config.mjs`,`kick.config.json`];function rn(e=process.cwd()){let t=v(e),{root:n}=g(t),i=null,a=t;for(;;){for(let e of nn)if(r(v(a,e)))return a;if(i===null&&r(v(a,`package.json`))&&(i=a),a===n)break;let e=f(a);if(e===a)break;a=e}return i??t}function an(e){return B(e).replace(/-/g,`_`)}function on(e){let t=e.cwd??process.cwd(),n=e.projectRoot??rn(t),r=e.pluralize??!0,i=R(e.name),a=z(e.name),o=B(e.name),s=an(e.name),c={name:e.name,pascal:i,camel:a,kebab:o,snake:s,modulesDir:e.modulesDir??`src/modules`,cwd:t,projectRoot:n,args:e.args??[],flags:e.flags??{}};if(r){let e=$t(o);c.pluralKebab=e,c.pluralPascal=R(e),c.pluralCamel=z(e)}return c}function sn(e,t){return v(e.cwd,t)}async function cn(e){return import(x(e).href)}const ln=new Map;async function un(e){let t=ln.get(e);if(t)return t;let n=dn(e);return ln.set(e,n),n}async function dn(t){let n=v(t,`package.json`);if(!r(n))return{generators:[],loaded:[],failed:[]};let i=fn(JSON.parse(await T(n,`utf-8`))),a=e(v(t,`package.json`)),o=[],s=[],c=[];for(let e of i){let t;try{t=a.resolve(`${e}/package.json`)}catch{continue}let n;try{n=JSON.parse(await T(t,`utf-8`))}catch(t){c.push({source:e,reason:`failed to parse package.json: ${t}`});continue}if(!n.kickjs?.generators)continue;let i=n.kickjs.generators,l=v(f(t),i);if(!r(l)){c.push({source:e,reason:`kickjs.generators points to missing file: ${i}`});continue}let u;try{u=await cn(l)}catch(t){c.push({source:e,reason:`failed to import manifest: ${t}`});continue}let d=u.default;if(!Array.isArray(d)){c.push({source:e,reason:`manifest's default export is not an array of GeneratorSpec`});continue}for(let t of d){if(!pn(t)){c.push({source:e,reason:`manifest entry is not a valid GeneratorSpec (missing name/files)`});continue}o.push({source:e,spec:t})}s.push(e)}return{generators:o,loaded:s,failed:c}}function fn(e){let t=new Set;for(let n of[e.dependencies,e.devDependencies,e.peerDependencies])if(n)for(let e of Object.keys(n))t.add(e);return Array.from(t)}function pn(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.name==`string`&&typeof t.files==`function`}async function mn(e,t=[]){let n=e.cwd??process.cwd(),r=t.find(t=>t.spec.name===e.generatorName);if(r)return _n(r.spec,r.source,e,n);let i=gn(await un(n),e.generatorName);return i?_n(i.spec,i.source,e,n):null}async function hn(e,t=[]){let n=await un(e),r=new Set(t.map(e=>e.spec.name)),i=n.generators.filter(e=>!r.has(e.spec.name));return{generators:[...t,...i],loaded:n.loaded,failed:n.failed}}function gn(e,t){return e.generators.find(e=>e.spec.name===t)}async function _n(e,t,n,r){let i=on({name:n.itemName,args:n.args,flags:n.flags,modulesDir:n.modulesDir,pluralize:n.pluralize,cwd:r,projectRoot:n.projectRoot}),a=await e.files(i),o=[];for(let e of a){let t=sn(i,e.path);await P(t,e.content),o.push(t)}return{files:o,source:t}}function V(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function vn(e){return e.charAt(0).toUpperCase()+e.slice(1).replace(/-([a-z])/g,(e,t)=>t.toUpperCase())}function yn(e){return e.replace(/([a-z])([A-Z])/g,`$1-$2`).toLowerCase()}function bn(e,t,n){let r={inmemory:`InMemory${e}Repository`,drizzle:`Drizzle${e}Repository`,prisma:`Prisma${e}Repository`},i={inmemory:`in-memory-${t}`,drizzle:`drizzle-${t}`,prisma:`prisma-${t}`};return{repoClass:r[n]??`${vn(n)}${e}Repository`,repoFile:i[n]??`${yn(n)}-${t}`}}function xn(e){return e??`define`}function Sn(e){let{pascal:t,kebab:n,plural:r=``,repo:i,style:a}=e,{repoClass:o,repoFile:s}=bn(t,n,i),c=xn(a),l=`/**
|
|
1241
|
+
Usage: kick add ai db swagger`),console.log(` kick add queue:bullmq`),console.log(` kick add upload # installs the multipart driver for your runtime`),console.log()}function At(e,t,n=`express`){let r=new Set,i=new Set,a=[],o=[],s=[];for(let c of e){if(c===`upload`){let e=xt[n];s.push(`upload (${n}): ${e.note}`),e.prod&&(t?i:r).add(e.prod),e.dev&&i.add(e.dev);continue}let e=yt[c];if(!e){a.push(c);continue}e.deprecated&&o.push(`'${c}' (${e.pkg}) is deprecated — ${e.deprecated}`);let l=t||e.dev?i:r;l.add(e.pkg);for(let t of e.peers)l.add(t)}return{prodDeps:[...r],devDeps:[...i],unknown:a,warnings:o,notices:s}}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=>{kt(!!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){kt(!!t.all);return}let{pm:n,source:r}=await Dt(t.pm);console.log(`\n Using ${n} (resolved from ${r})`);let i=await St(process.cwd()),{prodDeps:a,devDeps:o,unknown:s,warnings:c,notices:l}=At(e,!!t.dev,i);for(let e of c)console.warn(`\n WARNING: ${e}`);for(let e of l)console.log(`\n ${e}`);if(!(s.length>0&&(console.log(`\n Unknown packages: ${s.join(`, `)}`),console.log(` Run "kick add --list" to see available packages.
|
|
1242
|
+
`),a.length===0&&o.length===0))){if(a.length>0){let e=a,t=`${n} add ${e.join(` `)}`;console.log(`\n Installing ${e.length} dependency(ies):`);for(let t of e)console.log(` + ${t}`);console.log();try{S(t,{stdio:`inherit`})}catch{console.log(`\n Installation failed. Run manually:\n ${t}\n`)}}if(o.length>0){let e=o,t=`${n} add -D ${e.join(` `)}`;console.log(`\n Installing ${e.length} dev dependency(ies):`);for(let t of e)console.log(` + ${t} (dev)`);console.log();try{S(t,{stdio:`inherit`})}catch{console.log(`\n Installation failed. Run manually:\n ${t}\n`)}}console.log(` Done!
|
|
1243
|
+
`)}})}const Nt=f(b(import.meta.url)),Pt=JSON.parse(a(h(Nt,`..`,`package.json`),`utf-8`)),Ft=`^${Pt.version}`,It=[`@forinda/kickjs`,`@forinda/kickjs-cli`,`@forinda/kickjs-schema`,`@forinda/kickjs-vite`,`@forinda/kickjs-swagger`,`@forinda/kickjs-ws`,`@forinda/kickjs-queue`,`@forinda/kickjs-devtools`,`@forinda/kickjs-testing`,`@forinda/kickjs-client`];async function Lt(){let e=await Promise.all(It.map(async e=>{try{let t=ee(`npm`,[`view`,e,`version`],{encoding:`utf-8`,timeout:5e3,stdio:[`ignore`,`pipe`,`ignore`]}).toString().trim();if(t&&/^\d+\.\d+\.\d+/.test(t))return[e,`^${t}`]}catch{}return[e,Ft]}));return Object.fromEntries(e)}function Rt(e,t){try{let n=ee(`npm`,[`view`,`${e}@${t}`,`version`],{encoding:`utf-8`,timeout:5e3,stdio:[`ignore`,`pipe`,`ignore`]}).toString().trim();return n&&/^\d+\.\d+\.\d+/.test(n)?n:null}catch{return null}}function zt(e){return(e??``).replace(/^[\^~>=<\s]+/,``)}function Bt(e,t){let n=e=>zt(e).split(`-`)[0].split(`.`).map(e=>Number.parseInt(e,10)||0),[r=0,i=0,a=0]=n(e),[o=0,s=0,c=0]=n(t);return r===o?i===s?a>=c:i>s:r>o}function Vt(e,t,n){try{let r=ee(`npm`,[`view`,`${e}@${t}`,`exports`,`--json`],{encoding:`utf-8`,timeout:5e3,stdio:[`ignore`,`pipe`,`ignore`]}).toString().trim();if(!r)return!1;let i=JSON.parse(r);return Object.prototype.hasOwnProperty.call(i,n)}catch{return!1}}async function Ht(e){let{name:t,directory:n,packageManager:r=`pnpm`,template:i=`rest`,defaultRepo:a=`inmemory`,packages:o=[],schemaLib:s=`zod`,runtime:c=`express`}=e,l=n,u=e=>console.log(` ${e}`);console.log(`\n Creating KickJS project: ${t}\n`),u(`Resolving package versions...`);let d=await Lt();if(c!==`express`)if(Vt(`@forinda/kickjs`,`latest`,`./${c}`))u(`Using @forinda/kickjs@latest (stable ships the ${c} runtime)`);else{let e=[`@forinda/kickjs`,`@forinda/kickjs-cli`,`@forinda/kickjs-vite`],t=[],n=!1;for(let r of e){let e=Rt(r,`alpha`);e&&Bt(e,zt(d[r]))&&(d[r]=`^${e}`,t.push(`${r}@^${e}`),r===`@forinda/kickjs`&&(n=!0))}u(n?`Using the alpha channel for the ${c} runtime: ${t.join(`, `)}`:`WARNING: could not resolve @forinda/kickjs@alpha — the ${c} runtime subpath may be missing. After install, run: ${r} add @forinda/kickjs@alpha`)}await N(h(l,`package.json`),Ye(t,i,d,o,s,c)),await N(h(l,`vite.config.ts`),Xe()),await N(h(l,`tsconfig.json`),Ze()),await N(h(l,`.prettierrc`),Qe()),await N(h(l,`.editorconfig`),$e()),await N(h(l,`.gitignore`),et()),await N(h(l,`.gitattributes`),tt()),await N(h(l,`.env`),nt()),await N(h(l,`.env.example`),rt()),await N(h(l,`src/config/index.ts`),ct(s)),await N(h(l,`src/index.ts`),ot(t,i,Pt.version,o,c)),await N(h(l,`src/modules/index.ts`),st()),await N(h(l,`src/modules/hello/hello.service.ts`),lt()),await N(h(l,`src/modules/hello/hello.controller.ts`),ut()),await N(h(l,`src/modules/hello/hello.module.ts`),dt()),await N(h(l,`kick.config.ts`),ft(i,a,r,c)),await N(h(l,`vitest.config.ts`),it()),await N(h(l,`README.md`),pt(t,i,r));let{generateAgentDocs:f}=await Promise.resolve().then(()=>ar);if(await f({outDir:l,name:t,pm:r,template:i,only:`all`,force:!0}),e.installDeps){console.log(`\n Installing dependencies with ${r}...\n`);try{S(`${r} install`,{cwd:l,stdio:`inherit`}),console.log(`
|
|
1244
|
+
Dependencies installed successfully!`)}catch{console.log(`\n Warning: ${r} install failed. Run it manually.`)}}try{let{runTypegen:e}=await Promise.resolve().then(()=>Aa);await e({cwd:l,allowDuplicates:!0,silent:!0})}catch{}if(e.initGit)try{S(`git init`,{cwd:l,stdio:`pipe`}),S(`git branch -M main`,{cwd:l,stdio:`pipe`}),S(`git add -A`,{cwd:l,stdio:`pipe`}),S(`git commit -m "chore: initial commit from kick new"`,{cwd:l,stdio:`pipe`}),u(`Git repository initialized`)}catch{u(`Warning: git init failed (git may not be installed)`)}console.log(`
|
|
1245
|
+
Project scaffolded successfully!`),console.log();let p=l!==process.cwd();u(`Next steps:`),p&&u(` cd ${t}`),e.installDeps||u(` ${r} install`);let m={rest:`kick g module user`,ddd:`kick g module user --repo drizzle`,cqrs:`kick g module user --pattern cqrs`,minimal:`# add your routes to src/index.ts`};u(` ${m[i]??m.rest}`),u(` kick dev`),u(``),u(`Commands:`),u(` kick dev Start dev server with Vite HMR`),u(` kick build Production build via Vite`),u(` kick start Run production build`),u(``),u(`Generators:`),u(` kick g module <name> Full DDD module (controller, DTOs, use-cases, repo)`),u(` kick g scaffold <n> <f..> CRUD module from field definitions`),u(` kick g controller <name> Standalone controller`),u(` kick g service <name> @Service() class`),u(` kick g middleware <name> Express middleware`),u(` kick g guard <name> Route guard (auth, roles, etc.)`),u(` kick g adapter <name> AppAdapter with lifecycle hooks`),u(` kick g dto <name> Zod DTO schema`),u(` kick g config Generate kick.config.ts`),u(``),u(`Add packages:`),u(` kick add <pkg> Install a KickJS package + peers`),u(` kick add --list Show all available packages`),u(``),u(`Available: ${bt}`),u(``)}const Ut={GET:O.green,POST:O.cyan,PUT:O.yellow,PATCH:O.magenta,DELETE:O.red};function Wt(e){return(Ut[e]??O.dim)(e.padEnd(7))}function Gt(e){let t=`[${e}]`.padEnd(10);switch(e){case`CRITICAL`:return O.red(t);case`WARNING`:return O.yellow(t);case`INFO`:return O.blue(O.dim(t));default:return t}}O.green(`✓`),O.red(`✖`),O.yellow(`⚠`),O.blue(`ℹ`);function Kt(e){D.intro(O.bgCyan(O.black(` ${e} `)))}function P(e){D.outro(e)}function qt(e){D.isCancel(e)&&(D.cancel(`Operation cancelled.`),process.exit(0))}async function Jt(e){let t=await D.text(e);return qt(t),t}async function Yt(e){let t=await D.select(e);return qt(t),t}async function Xt(e){let t=await D.multiselect(e);return qt(t),t}async function F(e){let t=await D.confirm(e);return qt(t),t}function Zt(){return D.spinner()}const I=D.log,Qt=[{value:`swagger`,label:`Swagger`,hint:`OpenAPI docs`},{value:`ws`,label:`WebSocket`,hint:`rooms, heartbeat`},{value:`queue`,label:`Queue`,hint:`BullMQ/RabbitMQ/Kafka`},{value:`devtools`,label:`DevTools`,hint:`debug dashboard`}];function $t(e){e.command(`new [name]`).alias(`init`).description(`Create a new KickJS project (use "." for current directory)`).option(`-d, --directory <dir>`,`Target directory (defaults to project name)`).option(`--pm <manager>`,`Package manager: pnpm | npm | yarn | bun`).option(`--git`,`Initialize git repository`).option(`--no-git`,`Skip git initialization`).option(`--install`,`Install dependencies after scaffolding`).option(`--no-install`,`Skip dependency installation`).option(`-f, --force`,`Remove existing files without prompting`).option(`-t, --template <type>`,`Project template: rest | minimal | fullstack`).option(`--runtime <engine>`,`HTTP runtime: express | fastify | h3`).option(`-r, --repo <type>`,`Repository name (inmemory, or any DB name e.g. postgres)`).option(`-s, --schema <lib>`,`Schema library for env / DTOs: zod | valibot | yup (default: zod)`).option(`--packages <packages>`,`Comma-separated packages to include (e.g. auth,swagger,ws,queue)`).option(`-y, --yes`,`Pick safe defaults for every prompt (template=minimal, repo=inmemory, no extras, git+install on)`).option(`--non-interactive`,`alias for --yes`).action(async(e,t)=>{Kt(`KickJS — Create a new project`);let n=!!(t.yes||t.nonInteractive);e||=n?`my-api`:await Jt({message:`Project name`,placeholder:`my-api`,defaultValue:`my-api`});let i;if(e===`.`?(i=v(`.`),e=d(i)):i=v(t.directory||e),r(i)){let r=o(i);if(r.length>0){if(t.force)I.warn(`Clearing existing files in ${i}`);else if(n){I.warn(`Directory "${e}" is not empty. Pass --force to clear it.`),P(`Aborted.`);return}else{I.warn(`Directory "${e}" is not empty:`);let t=r.slice(0,5);for(let e of t)I.message(` - ${e}`);if(r.length>5&&I.message(` ... and ${r.length-5} more`),!await F({message:O.red(`Remove all existing files and proceed?`),initialValue:!1})){P(`Aborted.`);return}}for(let e of r)s(v(i,e),{recursive:!0,force:!0})}}let a=t.template;a||=n?`minimal`:await Yt({message:`Project template`,options:[{value:`rest`,label:`REST API`,hint:`Express + Swagger`},{value:`minimal`,label:`Minimal`,hint:`bare Express`},{value:`fullstack`,label:`Fullstack`,hint:`server + Vite React web, typed client`}]});let c=t.runtime;c||=n?`express`:await Yt({message:`HTTP runtime`,options:[{value:`express`,label:`Express`,hint:`default, zero-config`},{value:`fastify`,label:`Fastify`,hint:`fastify + @fastify/middie`},{value:`h3`,label:`h3`,hint:`Nitro / Nuxt engine`}]});let l=t.pm;l||=n?await Ot(void 0):await Yt({message:`Package manager`,options:[{value:`pnpm`,label:`pnpm`},{value:`npm`,label:`npm`},{value:`yarn`,label:`yarn`},{value:`bun`,label:`bun`}]});let u=t.repo;u||=n?`inmemory`:await Jt({message:`Repository name`,placeholder:`inmemory (or a DB name, e.g. postgres)`,defaultValue:`inmemory`}),Oe(u);let f=t.schema;f||=n?`zod`:await Yt({message:`Schema library (env + DTO validation)`,options:[{value:`zod`,label:`Zod`,hint:`default — broad ecosystem`},{value:`valibot`,label:`Valibot`,hint:`smaller bundle`},{value:`yup`,label:`Yup`,hint:`classic API`}]}),[`zod`,`valibot`,`yup`].includes(f)||(I.warn(`Unknown --schema "${f}", falling back to zod.`),f=`zod`);let p;if(t.packages!==void 0){let e=t.packages.trim().toLowerCase();p=e===``||e===`none`||e===`false`?[]:t.packages.split(`,`).map(e=>e.trim()).filter(Boolean)}else p=n?[]:await Xt({message:`Select packages to include`,options:[...Qt],required:!1});let m;m=t.git===void 0?n?!0:await F({message:`Initialize git repository?`,initialValue:!0}):t.git;let h;if(h=t.install===void 0?n?!0:await F({message:`Install dependencies?`,initialValue:!0}):t.install,a===`fullstack`){let{initFullstackProject:t}=await import(`./fullstack-iuAdYQmC.mjs`);await t({name:e,directory:i,packageManager:l,initGit:m,installDeps:h,schemaLib:f,runtime:c}),P(`Done! Next steps: ${O.cyan(`cd ${e} && ${l}${l===`pnpm`?` dev`:` run dev:server`}`)}`);return}await Ht({name:e,directory:i,packageManager:l,initGit:m,installDeps:h,template:a,defaultRepo:u,packages:p,schemaLib:f,runtime:c}),P(`Done! Next steps: ${O.cyan(`cd ${e} && ${l} dev`)}`)})}function L(e){return e.replace(/[-_\s]+(.)?/g,(e,t)=>t?t.toUpperCase():``).replace(/^(.)/,e=>e.toUpperCase())}function R(e){let t=L(e);return t.charAt(0).toLowerCase()+t.slice(1)}function z(e){return e.replace(/([a-z])([A-Z])/g,`$1-$2`).replace(/[\s_]+/g,`-`).toLowerCase()}function B(e){return de.plural(e)}function en(e){return de.plural(e)}var tn=k({findProjectRoot:()=>rn});const nn=[`kick.config.ts`,`kick.config.js`,`kick.config.mjs`,`kick.config.json`];function rn(e=process.cwd()){let t=v(e),{root:n}=g(t),i=null,a=t;for(;;){for(let e of nn)if(r(v(a,e)))return a;if(i===null&&r(v(a,`package.json`))&&(i=a),a===n)break;let e=f(a);if(e===a)break;a=e}return i??t}function an(e){return z(e).replace(/-/g,`_`)}function on(e){let t=e.cwd??process.cwd(),n=e.projectRoot??rn(t),r=e.pluralize??!0,i=L(e.name),a=R(e.name),o=z(e.name),s=an(e.name),c={name:e.name,pascal:i,camel:a,kebab:o,snake:s,modulesDir:e.modulesDir??`src/modules`,cwd:t,projectRoot:n,args:e.args??[],flags:e.flags??{}};if(r){let e=B(o);c.pluralKebab=e,c.pluralPascal=L(e),c.pluralCamel=R(e)}return c}function sn(e,t){return v(e.cwd,t)}async function cn(e){return import(x(e).href)}const ln=new Map;async function un(e){let t=ln.get(e);if(t)return t;let n=dn(e);return ln.set(e,n),n}async function dn(t){let n=v(t,`package.json`);if(!r(n))return{generators:[],loaded:[],failed:[]};let i=fn(JSON.parse(await w(n,`utf-8`))),a=e(v(t,`package.json`)),o=[],s=[],c=[];for(let e of i){let t;try{t=a.resolve(`${e}/package.json`)}catch{continue}let n;try{n=JSON.parse(await w(t,`utf-8`))}catch(t){c.push({source:e,reason:`failed to parse package.json: ${t}`});continue}if(!n.kickjs?.generators)continue;let i=n.kickjs.generators,l=v(f(t),i);if(!r(l)){c.push({source:e,reason:`kickjs.generators points to missing file: ${i}`});continue}let u;try{u=await cn(l)}catch(t){c.push({source:e,reason:`failed to import manifest: ${t}`});continue}let d=u.default;if(!Array.isArray(d)){c.push({source:e,reason:`manifest's default export is not an array of GeneratorSpec`});continue}for(let t of d){if(!pn(t)){c.push({source:e,reason:`manifest entry is not a valid GeneratorSpec (missing name/files)`});continue}o.push({source:e,spec:t})}s.push(e)}return{generators:o,loaded:s,failed:c}}function fn(e){let t=new Set;for(let n of[e.dependencies,e.devDependencies,e.peerDependencies])if(n)for(let e of Object.keys(n))t.add(e);return Array.from(t)}function pn(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.name==`string`&&typeof t.files==`function`}async function mn(e,t=[]){let n=e.cwd??process.cwd(),r=t.find(t=>t.spec.name===e.generatorName);if(r)return _n(r.spec,r.source,e,n);let i=gn(await un(n),e.generatorName);return i?_n(i.spec,i.source,e,n):null}async function hn(e,t=[]){let n=await un(e),r=new Set(t.map(e=>e.spec.name)),i=n.generators.filter(e=>!r.has(e.spec.name));return{generators:[...t,...i],loaded:n.loaded,failed:n.failed}}function gn(e,t){return e.generators.find(e=>e.spec.name===t)}async function _n(e,t,n,r){let i=on({name:n.itemName,args:n.args,flags:n.flags,modulesDir:n.modulesDir,pluralize:n.pluralize,cwd:r,projectRoot:n.projectRoot}),a=await e.files(i),o=[];for(let e of a){let t=sn(i,e.path);await N(t,e.content),o.push(t)}return{files:o,source:t}}function V(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function vn(e){return e.charAt(0).toUpperCase()+e.slice(1).replace(/-([a-z])/g,(e,t)=>t.toUpperCase())}function yn(e){return e.replace(/([a-z])([A-Z])/g,`$1-$2`).toLowerCase()}function bn(e,t,n){let r={inmemory:`InMemory${e}Repository`,drizzle:`Drizzle${e}Repository`,prisma:`Prisma${e}Repository`},i={inmemory:`in-memory-${t}`,drizzle:`drizzle-${t}`,prisma:`prisma-${t}`};return{repoClass:r[n]??`${vn(n)}${e}Repository`,repoFile:i[n]??`${yn(n)}-${t}`}}function xn(e){return e??`define`}function Sn(e){let{pascal:t,kebab:n,plural:r=``,repo:i,style:a}=e,{repoClass:o,repoFile:s}=bn(t,n,i),c=xn(a),l=`/**
|
|
1242
1246
|
* ${t} Module
|
|
1243
1247
|
*
|
|
1244
1248
|
* REST module with a flat folder structure.
|
|
@@ -1773,7 +1777,7 @@ export class ${t}Controller {
|
|
|
1773
1777
|
ctx.json({ message: '${t} list' })
|
|
1774
1778
|
}
|
|
1775
1779
|
}
|
|
1776
|
-
`)}async function In(e){let{pascal:t,kebab:n,plural:r,pluralPascal:i,repo:a,noTests:o,tokenScope:s,style:c,write:l}=e;await l(`${n}.module.ts`,Sn({pascal:t,kebab:n,plural:r,repo:a,style:c})),await l(`${n}.constants.ts`,Pn({pascal:t,kebab:n})),await l(`${n}.controller.ts`,wn({pascal:t,kebab:n,plural:r,pluralPascal:i})),await l(`${n}.service.ts`,Nn({pascal:t,kebab:n})),await l(`dtos/create-${n}.dto.ts`,Tn({pascal:t,kebab:n})),await l(`dtos/update-${n}.dto.ts`,En({pascal:t,kebab:n})),await l(`dtos/${n}-response.dto.ts`,Dn({pascal:t,kebab:n})),await l(`${n}.repository.ts`,On({pascal:t,kebab:n,dtoPrefix:`./dtos`,tokenScope:s}));let u=a===`inmemory`,d=u?`in-memory-${n}`:`${
|
|
1780
|
+
`)}async function In(e){let{pascal:t,kebab:n,plural:r,pluralPascal:i,repo:a,noTests:o,tokenScope:s,style:c,write:l}=e;await l(`${n}.module.ts`,Sn({pascal:t,kebab:n,plural:r,repo:a,style:c})),await l(`${n}.constants.ts`,Pn({pascal:t,kebab:n})),await l(`${n}.controller.ts`,wn({pascal:t,kebab:n,plural:r,pluralPascal:i})),await l(`${n}.service.ts`,Nn({pascal:t,kebab:n})),await l(`dtos/create-${n}.dto.ts`,Tn({pascal:t,kebab:n})),await l(`dtos/update-${n}.dto.ts`,En({pascal:t,kebab:n})),await l(`dtos/${n}-response.dto.ts`,Dn({pascal:t,kebab:n})),await l(`${n}.repository.ts`,On({pascal:t,kebab:n,dtoPrefix:`./dtos`,tokenScope:s}));let u=a===`inmemory`,d=u?`in-memory-${n}`:`${z(a)}-${n}`,f=u?kn({pascal:t,kebab:n,repoPrefix:`.`,dtoPrefix:`./dtos`}):An({pascal:t,kebab:n,repoType:a,repoPrefix:`.`,dtoPrefix:`./dtos`});await l(`${d}.repository.ts`,f),o||(a!==`inmemory`&&await l(`in-memory-${n}.repository.ts`,kn({pascal:t,kebab:n,repoPrefix:`.`,dtoPrefix:`./dtos`})),await l(`__tests__/${n}.controller.test.ts`,jn({pascal:t,kebab:n,plural:r})),await l(`__tests__/${n}.repository.test.ts`,Mn({pascal:t,kebab:n,plural:r,repoPrefix:`../in-memory-${n}.repository`})))}function Ln(e){return e?typeof e==`string`?e:e.name:`inmemory`}async function Rn(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??`rest`;e.minimal&&(l=`minimal`);let u=z(t),d=L(t),f=c?B(u):u,p=c?en(d):d,m=h(n,f),g=[],_=o??!1,v={kebab:u,pascal:d,plural:f,pluralPascal:p,moduleDir:m,repo:a,noEntity:r??!1,noTests:i??!1,prismaClientPath:e.prismaClientPath??`@prisma/client`,tokenScope:e.tokenScope??`app`,style:e.style??`define`,write:async(e,t)=>{let n=h(m,e);if(s){g.push(n);return}if(!_&&await Ge(n)&&!await F({message:`File exists: ${O.dim(e)}. Overwrite?`,initialValue:!1})){I.warn(`Skipped: ${e}`);return}await N(n,t),g.push(n)},files:g};switch(l){case`minimal`:await Fn(v);break;default:await In(v);break}return s||await zn(n,d,f,u,v.style),g}async function zn(e,t,n,r,i=`define`){let a=h(e,`index.ts`),o=await Ge(a),s=`./${n}/${r}.module`,c=i===`class`?`${t}Module`:`${t}Module()`;if(!o){await N(a,i===`class`?`import type { AppModuleEntry } from '@forinda/kickjs'
|
|
1777
1781
|
import { ${t}Module } from '${s}'
|
|
1778
1782
|
|
|
1779
1783
|
export const modules: AppModuleEntry[] = [${c}]
|
|
@@ -1781,11 +1785,11 @@ export const modules: AppModuleEntry[] = [${c}]
|
|
|
1781
1785
|
import { ${t}Module } from '${s}'
|
|
1782
1786
|
|
|
1783
1787
|
export const modules = defineModules().mount(${c})
|
|
1784
|
-
`);return}let l=await
|
|
1788
|
+
`);return}let l=await w(a,`utf-8`),u=`import { ${t}Module } from '${s}'`,d=V(s);if(!RegExp(`^import\\s*\\{[^}]*\\b${V(t)}Module\\b[^}]*\\}\\s*from\\s*['"]${d}['"]`,`m`).test(l)){let e=l.lastIndexOf(`import `);if(e!==-1){let t=l.indexOf(`
|
|
1785
1789
|
`,e);l=l.slice(0,t+1)+u+`
|
|
1786
1790
|
`+l.slice(t+1)}else l=u+`
|
|
1787
|
-
`+l}let f=Vn(l);if(f){let e=l.slice(f.rhsStart,f.rhsEnd+1);RegExp(`\\b${V(t)}Module\\b`).test(e)||(l=Bn(l,c))}else l=Bn(l,c);await
|
|
1788
|
-
`;)t++;return t}if(n===`/*`){for(t+=2;t+1<e.length&&!(e[t]===`*`&&e[t+1]===`/`);)t++;return t+2}return t}function Wn(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=Un(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 Gn(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=Un(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 Kn(e){let{name:t,outDir:n}=e,r=
|
|
1791
|
+
`+l}let f=Vn(l);if(f){let e=l.slice(f.rhsStart,f.rhsEnd+1);RegExp(`\\b${V(t)}Module\\b`).test(e)||(l=Bn(l,c))}else l=Bn(l,c);await T(a,l,`utf-8`)}function Bn(e,t){let n=Vn(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 Vn(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=Wn(e,n);return t===-1?null:{shape:`array`,rhsStart:n,rhsEnd:t}}if(e.slice(n,n+13)===`defineModules`){let t=Hn(e,n);return t===-1?null:{shape:`chain`,rhsStart:n,rhsEnd:t-1,chainEnd:t}}return null}function Hn(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=Gn(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=Gn(e,t);if(n===-1)break;i=n+1}return i}function Un(e,t){let n=e.slice(t,t+2);if(n===`//`){for(t+=2;t<e.length&&e[t]!==`
|
|
1792
|
+
`;)t++;return t}if(n===`/*`){for(t+=2;t+1<e.length&&!(e[t]===`*`&&e[t+1]===`/`);)t++;return t+2}return t}function Wn(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=Un(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 Gn(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=Un(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 Kn(e){let{name:t,outDir:n}=e,r=z(t),i=L(t),a=[],o=h(n,`${r}.adapter.ts`);return await N(o,`import {
|
|
1789
1793
|
defineAdapter,
|
|
1790
1794
|
type AdapterContext,
|
|
1791
1795
|
type AdapterMiddleware,
|
|
@@ -1954,7 +1958,7 @@ export const ${i}Adapter = defineAdapter<${i}AdapterConfig>({
|
|
|
1954
1958
|
}
|
|
1955
1959
|
},
|
|
1956
1960
|
})
|
|
1957
|
-
`),a.push(o),a}async function qn(e){let{name:t,outDir:n}=e,r=
|
|
1961
|
+
`),a.push(o),a}async function qn(e){let{name:t,outDir:n}=e,r=z(t),i=L(t),a=[],o=h(n,`${r}.plugin.ts`);return await N(o,`import {
|
|
1958
1962
|
definePlugin,
|
|
1959
1963
|
type AppAdapter,
|
|
1960
1964
|
type AppModuleEntry,
|
|
@@ -2098,9 +2102,9 @@ export const ${i}Plugin = definePlugin<${i}PluginConfig>({
|
|
|
2098
2102
|
},
|
|
2099
2103
|
}),
|
|
2100
2104
|
})
|
|
2101
|
-
`),a.push(o),a}const Jn={controller:``,service:``,dto:`dtos`,guard:`guards`,middleware:`middleware`,contributor:`contributors`};function Yn(e){let{type:t,outDir:n,moduleName:r,modulesDir:i=`src/modules`,defaultDir:a,shouldPluralize:o=!0}=e;if(n)return v(n);if(r){let e=Jn,n=
|
|
2105
|
+
`),a.push(o),a}const Jn={controller:``,service:``,dto:`dtos`,guard:`guards`,middleware:`middleware`,contributor:`contributors`};function Yn(e){let{type:t,outDir:n,moduleName:r,modulesDir:i=`src/modules`,defaultDir:a,shouldPluralize:o=!0}=e;if(n)return v(n);if(r){let e=Jn,n=z(r),a=o?B(n):n,s=e[t]??``,c=h(i,a);return v(s?h(c,s):c)}return v(a)}async function Xn(e){let{name:t,moduleName:n,modulesDir:r,pattern:i}=e,a=Yn({type:`middleware`,outDir:e.outDir,moduleName:n,modulesDir:r,defaultDir:`src/middleware`,pattern:i,shouldPluralize:e.pluralize??!0}),o=z(t),s=R(t),c=[],l=h(a,`${o}.middleware.ts`);return await N(l,`import type { Request, Response, NextFunction } from 'express'
|
|
2102
2106
|
|
|
2103
|
-
export interface ${
|
|
2107
|
+
export interface ${L(t)}Options {
|
|
2104
2108
|
// Add configuration options here. The factory below closes over the
|
|
2105
2109
|
// resolved options object; pass them at the call site —
|
|
2106
2110
|
// \`${s}({ foo: 'bar' })\` — and the closure preserves them across
|
|
@@ -2108,7 +2112,7 @@ export interface ${R(t)}Options {
|
|
|
2108
2112
|
}
|
|
2109
2113
|
|
|
2110
2114
|
/**
|
|
2111
|
-
* ${
|
|
2115
|
+
* ${L(t)} middleware.
|
|
2112
2116
|
*
|
|
2113
2117
|
* Usage in bootstrap (fires on every request):
|
|
2114
2118
|
* middleware: [${s}()]
|
|
@@ -2140,7 +2144,7 @@ export interface ${R(t)}Options {
|
|
|
2140
2144
|
* Usage with @Middleware decorator:
|
|
2141
2145
|
* @Middleware(${s}())
|
|
2142
2146
|
*/
|
|
2143
|
-
export function ${s}(options: ${
|
|
2147
|
+
export function ${s}(options: ${L(t)}Options = {}) {
|
|
2144
2148
|
return (req: Request, res: Response, next: NextFunction) => {
|
|
2145
2149
|
// Implement your middleware logic here. \`options\` is captured by
|
|
2146
2150
|
// closure — log or read it anywhere in this handler body.
|
|
@@ -2148,7 +2152,7 @@ export function ${s}(options: ${R(t)}Options = {}) {
|
|
|
2148
2152
|
next()
|
|
2149
2153
|
}
|
|
2150
2154
|
}
|
|
2151
|
-
`),c.push(l),c}async function Zn(e){let{name:t,moduleName:n,modulesDir:r,pattern:i}=e,a=Yn({type:`guard`,outDir:e.outDir,moduleName:n,modulesDir:r,defaultDir:`src/guards`,pattern:i,shouldPluralize:e.pluralize??!0}),o=
|
|
2155
|
+
`),c.push(l),c}async function Zn(e){let{name:t,moduleName:n,modulesDir:r,pattern:i}=e,a=Yn({type:`guard`,outDir:e.outDir,moduleName:n,modulesDir:r,defaultDir:`src/guards`,pattern:i,shouldPluralize:e.pluralize??!0}),o=z(t),s=R(t),c=L(t),l=[],u=h(a,`${o}.guard.ts`);return await N(u,`import { Container, HttpException } from '@forinda/kickjs'
|
|
2152
2156
|
import type { RequestContext } from '@forinda/kickjs'
|
|
2153
2157
|
|
|
2154
2158
|
/**
|
|
@@ -2184,7 +2188,7 @@ export async function ${s}Guard(ctx: RequestContext, next: () => void): Promise<
|
|
|
2184
2188
|
ctx.res.status(401).json({ message: 'Invalid or expired token' })
|
|
2185
2189
|
}
|
|
2186
2190
|
}
|
|
2187
|
-
`),l.push(u),l}function Qn(e){return e?e.split(`,`).map(e=>e.trim()).filter(Boolean).map(e=>{let[t,n]=e.split(`:`).map(e=>e.trim());return{name:t,type:n||`string`}}).filter(e=>e.name.length>0):[]}function $n(e){switch(e){case`string`:return`''`;case`number`:return`0`;case`boolean`:return`false`;default:return null}}async function er(e){let{name:t,moduleName:n,modulesDir:r,pattern:i}=e,a=e.type??`http`,o=
|
|
2191
|
+
`),l.push(u),l}function Qn(e){return e?e.split(`,`).map(e=>e.trim()).filter(Boolean).map(e=>{let[t,n]=e.split(`:`).map(e=>e.trim());return{name:t,type:n||`string`}}).filter(e=>e.name.length>0):[]}function $n(e){switch(e){case`string`:return`''`;case`number`:return`0`;case`boolean`:return`false`;default:return null}}async function er(e){let{name:t,moduleName:n,modulesDir:r,pattern:i}=e,a=e.type??`http`,o=z(t),s=L(t),c=e.key??R(t),l=Array.isArray(e.params)?e.params:Qn(e.params),u=Yn({type:`contributor`,outDir:e.outDir,moduleName:n,modulesDir:r,defaultDir:`src/contributors`,pattern:i,shouldPluralize:e.pluralize??!0}),d=a===`http`?`defineHttpContextDecorator`:`defineContextDecorator`,f=a===`http`?`RequestContext`:`ExecutionContext`,p=l.length>0?`\nexport type ${s}Params = {\n${l.map(e=>` ${e.name}: ${e.type}`).join(`
|
|
2188
2192
|
`)}\n}\n`:``,m=l.length>0?`${d}.withParams<${s}Params>()({`:`${d}({`,g=l.map(e=>({name:e.name,def:$n(e.type)})).filter(e=>e.def!==null).map(e=>` ${e.name}: ${e.def},`),_=l.length>0?` paramDefaults: {\n${g.join(`
|
|
2189
2193
|
`)}\n },\n`:``,v=l.length>0?`(ctx, _deps, params)`:`(ctx)`,y=l.length>0?` // \`params\` is typed as ${s}Params (call-site overrides merged onto paramDefaults).`:` // \`ctx\` is a ${f} — read ctx.req / ctx.headers / ctx.params (http) or ctx.get (bare).`,b=`import { ${d} } from '@forinda/kickjs'
|
|
2190
2194
|
import type { ${f} } from '@forinda/kickjs'
|
|
@@ -2224,7 +2228,7 @@ ${y}
|
|
|
2224
2228
|
throw new Error("${s} contributor: resolve() not implemented")
|
|
2225
2229
|
},
|
|
2226
2230
|
})
|
|
2227
|
-
`,x=h(u,`${o}.contributor.ts`);return await
|
|
2231
|
+
`,x=h(u,`${o}.contributor.ts`);return await N(x,b),[x]}async function tr(e){let{name:t,moduleName:n,modulesDir:r,pattern:i}=e,a=Yn({type:`service`,outDir:e.outDir,moduleName:n,modulesDir:r,defaultDir:`src/services`,pattern:i,shouldPluralize:e.pluralize??!0}),o=z(t),s=L(t),c=[],l=h(a,`${o}.service.ts`);return await N(l,`import { Service } from '@forinda/kickjs'
|
|
2228
2232
|
|
|
2229
2233
|
@Service()
|
|
2230
2234
|
export class ${s}Service {
|
|
@@ -2233,7 +2237,7 @@ export class ${s}Service {
|
|
|
2233
2237
|
// @Inject(MY_REPO) private readonly repo: IMyRepository,
|
|
2234
2238
|
// ) {}
|
|
2235
2239
|
}
|
|
2236
|
-
`),c.push(l),c}async function nr(e){let{name:t,moduleName:n,modulesDir:r,pattern:i}=e,a=Yn({type:`controller`,outDir:e.outDir,moduleName:n,modulesDir:r,defaultDir:`src/controllers`,pattern:i,shouldPluralize:e.pluralize??!0}),o=
|
|
2240
|
+
`),c.push(l),c}async function nr(e){let{name:t,moduleName:n,modulesDir:r,pattern:i}=e,a=Yn({type:`controller`,outDir:e.outDir,moduleName:n,modulesDir:r,defaultDir:`src/controllers`,pattern:i,shouldPluralize:e.pluralize??!0}),o=z(t),s=L(t),c=[],l=h(a,`${o}.controller.ts`);return await N(l,`import { Controller, Get, Post, type Ctx } from '@forinda/kickjs'
|
|
2237
2241
|
|
|
2238
2242
|
// \`Ctx<KickRoutes.${s}Controller['<method>']>\` is generated by
|
|
2239
2243
|
// \`kick typegen\` (auto-run on \`kick dev\`). After the first run, your IDE
|
|
@@ -2254,7 +2258,7 @@ export class ${s}Controller {
|
|
|
2254
2258
|
ctx.created({ message: '${s} created', data: ctx.body })
|
|
2255
2259
|
}
|
|
2256
2260
|
}
|
|
2257
|
-
`),c.push(l),c}async function rr(e){let{name:t,moduleName:n,modulesDir:r,pattern:i}=e,a=Yn({type:`dto`,outDir:e.outDir,moduleName:n,modulesDir:r,defaultDir:`src/dtos`,pattern:i,shouldPluralize:e.pluralize??!0}),o=
|
|
2261
|
+
`),c.push(l),c}async function rr(e){let{name:t,moduleName:n,modulesDir:r,pattern:i}=e,a=Yn({type:`dto`,outDir:e.outDir,moduleName:n,modulesDir:r,defaultDir:`src/dtos`,pattern:i,shouldPluralize:e.pluralize??!0}),o=z(t),s=L(t),c=R(t),l=[],u=h(a,`${o}.dto.ts`);return await N(u,`import { z } from 'zod'
|
|
2258
2262
|
|
|
2259
2263
|
export const ${c}Schema = z.object({
|
|
2260
2264
|
// Define your schema fields here
|
|
@@ -2262,8 +2266,8 @@ export const ${c}Schema = z.object({
|
|
|
2262
2266
|
})
|
|
2263
2267
|
|
|
2264
2268
|
export type ${s}DTO = z.infer<typeof ${c}Schema>
|
|
2265
|
-
`),l.push(u),l}async function ir(e){let t=h(e.outDir,`kick.config.ts`),n=e.modulesDir??`src/modules`,i=e.defaultRepo??`inmemory`;return r(t)&&!e.force&&!await
|
|
2266
|
-
Skipped — existing kick.config.ts preserved.`),[]):(await
|
|
2269
|
+
`),l.push(u),l}async function ir(e){let t=h(e.outDir,`kick.config.ts`),n=e.modulesDir??`src/modules`,i=e.defaultRepo??`inmemory`;return r(t)&&!e.force&&!await F({message:`kick.config.ts already exists. Overwrite?`,initialValue:!1})?(console.log(`
|
|
2270
|
+
Skipped — existing kick.config.ts preserved.`),[]):(await N(t,`import { defineConfig } from '@forinda/kickjs-cli'
|
|
2267
2271
|
|
|
2268
2272
|
export default defineConfig({
|
|
2269
2273
|
modules: {
|
|
@@ -2300,8 +2304,8 @@ export default defineConfig({
|
|
|
2300
2304
|
},
|
|
2301
2305
|
],
|
|
2302
2306
|
})
|
|
2303
|
-
`),[t])}var ar=
|
|
2304
|
-
`).map(e=>{if(e.trim()===``)return e;let n=RegExp(`^ {0,${t}}`)
|
|
2307
|
+
`),[t])}var ar=k({generateAgentDocs:()=>dr});const or=`.agents`,sr=new Set([`rest`,`minimal`]);function cr(e,t){if(t)return t;try{let t=JSON.parse(a(h(e,`package.json`),`utf-8`));if(t.name)return t.name.replace(/^@[^/]+\//,``)}catch{}return e.split(`/`).findLast(Boolean)??`app`}function lr(e,t){if(t)return t;try{let t=JSON.parse(a(h(e,`package.json`),`utf-8`));if(t.packageManager)return t.packageManager.split(`@`)[0]}catch{}return`pnpm`}async function ur(e,t){if(t)return t;try{let t=(await j(e))?.pattern;if(t&&sr.has(t))return t}catch{}return`rest`}async function dr(e){let t=e.only??`all`,n=cr(e.outDir,e.name),i=lr(e.outDir,e.pm),a=await ur(e.outDir,e.template),o=t===`agents`||t===`both`||t===`all`,s=t===`claude`||t===`both`||t===`all`,c=t===`skills`||t===`all`,l=t===`gemini`||t===`all`,u=t===`copilot`||t===`all`,d=[];if(o&&d.push({file:h(e.outDir,or,`AGENTS.md`),render:()=>ht(n,a,i)}),s&&d.push({file:h(e.outDir,`CLAUDE.md`),render:()=>mt(n,a,i)}),c)for(let t of gt(n,a,i))d.push({file:h(e.outDir,or,`skills`,t.slug,`SKILL.md`),render:()=>t.content});l&&d.push({file:h(e.outDir,or,`GEMINI.md`),render:()=>_t(n,a,i)}),u&&d.push({file:h(e.outDir,or,`COPILOT.md`),render:()=>vt(n,a,i)});let f=[];for(let{file:t,render:n}of d){if(r(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 N(t,n()),f.push(t)}return f}function fr(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 pr(e,t){let n=t.exec(e);if(!n)return null;let r=n.index+n[0].length-1,i=fr(e,r);return i===-1?null:e.slice(r+1,i)}function mr(e,t,n){let r=` `.repeat(n);return e.split(`
|
|
2308
|
+
`).map(e=>{if(e.trim()===``)return e;let n=RegExp(`^ {0,${t}}`),i=e.replace(n,``);return r+i}).join(`
|
|
2305
2309
|
`)}function hr(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 gr(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 _r(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=fr(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=pr(o,/register\s*\(([^)]*)\)\s*:\s*void\s*\{/),u=pr(o,/contributors\s*\(\s*\)\s*:\s*ContributorRegistrations\s*\{/),d=pr(o,/routes\s*\(\s*\)\s*:\s*[A-Za-z|[\]\s]+\{/);if(!d)return{migrated:null,reason:`routes() method missing or signature unrecognized`};let f=hr(s),p=``;return l&&(p+=` register(container) {${mr(l,4,6)} },\n\n`),u&&(p+=` contributors() {${mr(u,4,6)} },\n\n`),p+=` routes() {${mr(d,4,6)} },`,{migrated:`${f}${`export const ${r} = defineModule({
|
|
2306
2310
|
name: '${r}',
|
|
2307
2311
|
build: () => ({
|
|
@@ -2311,7 +2315,7 @@ ${p}
|
|
|
2311
2315
|
`||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=fr(s,f);if(p===-1)return{migrated:null,reason:`unbalanced build() braces`};let m=s.slice(f+1,p),h=pr(m,/register\s*\(([^)]*)\)\s*\{/),g=pr(m,/contributors\s*\(\s*\)\s*\{/),_=pr(m,/routes\s*\(\s*\)\s*\{/);if(!_)return{migrated:null,reason:`routes() method missing inside build()`};let v=gr(c,{container:h!==null,appModule:!0,moduleRoutes:!0,contributorRegistrations:g!==null}),y=``;return h!==null&&(y+=` register(container: Container): void {${mr(h,6,4)} }\n\n`),g!==null&&(y+=` contributors(): ContributorRegistrations {${mr(g,6,4)} }\n\n`),y+=` routes(): ModuleRoutes {${mr(_,6,4)} }`,{migrated:`${v}${`export class ${r} implements AppModule {
|
|
2312
2316
|
${y}
|
|
2313
2317
|
}
|
|
2314
|
-
`}${u}`}}function yr(e,t){return t===`class`?vr(e):_r(e)}function br(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 xr(e){let t=[];return await n(v(e),0),t;async function n(e,r){let i;try{i=await
|
|
2318
|
+
`}${u}`}}function yr(e,t){return t===`class`?vr(e):_r(e)}function br(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 xr(e){let t=[];return await n(v(e),0),t;async function n(e,r){let i;try{i=await oe(e)}catch{return}for(let a of i){if(a===`node_modules`||a===`dist`||a===`.kickjs`)continue;let i=h(e,a),o;try{o=await ce(i)}catch{continue}o.isDirectory()?await n(i,r+1):(a.endsWith(`.module.ts`)||a===`index.ts`&&r===1)&&t.push(i)}}}async function Sr(e,t){let n=0;return await r(e,t),n;async function r(e,t){let i;try{i=await oe(e)}catch{return}await C(t,{recursive:!0});for(let a of i){if(a===`node_modules`||a===`dist`||a===`.kickjs`)continue;let i=h(e,a),o=h(t,a),s;try{s=await ce(i)}catch{continue}s.isDirectory()?await r(i,o):(await ae(i,o),n++)}}}function Cr(e){return h(e,`.kickjs`,`codemod-backups`,`${new Date().toISOString().replaceAll(/[:.]/g,`-`)}-modules`)}async function wr(e,t){let{dryRun:n=!1,cwd:r=process.cwd(),target:i}=t,a=t.backup??!n,o=await xr(e),s=await w(h(e,`index.ts`),`utf-8`).then(()=>!0,()=>!1),c=null;a&&(o.length>0||s)&&(c=Cr(r),await Sr(e,c));let l=[];for(let e of o){let t=yr(await w(e,`utf-8`),i);if(t.migrated==null){l.push({path:e,status:`skipped`,reason:t.reason});continue}n||await T(e,t.migrated,`utf-8`),l.push({path:e,status:`migrated`})}let u=h(e,`index.ts`),d=null;try{d=await w(u,`utf-8`)}catch{return{target:i,files:l,indexStatus:`not-found`,indexPath:u,backupDir:c}}let f=br(d,i);return f.migrated==null?{target:i,files:l,indexStatus:`skipped`,indexPath:u,indexReason:f.reason,backupDir:c}:(n||await T(u,f.migrated,`utf-8`),{target:i,files:l,indexStatus:`migrated`,indexPath:u,backupDir:c})}async function Tr(e,t){let n=await xr(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 w(e,`utf-8`);i.test(t)&&r.push(e)}return r}async function Er(e){let{name:t,outDir:n}=e,r=L(t),i=z(t),a=R(t),o=e.queue??`${i}-queue`,s=[];return await(async(e,t)=>{let r=h(n,e);await N(r,t),s.push(r)})(`${i}.job.ts`,`import { Inject } from '@forinda/kickjs'
|
|
2315
2319
|
import { Job, Process, QUEUE_MANAGER, type QueueService } from '@forinda/kickjs-queue'
|
|
2316
2320
|
|
|
2317
2321
|
/**
|
|
@@ -2344,7 +2348,7 @@ export class ${r}Job {
|
|
|
2344
2348
|
// Handle high-priority variant of this job
|
|
2345
2349
|
}
|
|
2346
2350
|
}
|
|
2347
|
-
`),s}const Dr={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 Or(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=Dr[a];if(!o){let e=[...Object.keys(Dr),`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 kr(e){let{name:t,fields:n,modulesDir:r,repo:i=`inmemory`,tokenScope:a=`app`,style:o=`define`}=e,s=e.pluralize!==!1,c=
|
|
2351
|
+
`),s}const Dr={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 Or(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=Dr[a];if(!o){let e=[...Object.keys(Dr),`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 kr(e){let{name:t,fields:n,modulesDir:r,repo:i=`inmemory`,tokenScope:a=`app`,style:o=`define`}=e,s=e.pluralize!==!1,c=z(t),l=L(t),u=s?B(c):c,d=s?en(l):l,f=h(r,u),p=[],m=async(e,t)=>{let n=h(f,e);await N(n,t),p.push(n)};await m(`${c}.module.ts`,Sn({pascal:l,kebab:c,plural:u,repo:i,style:o})),await m(`${c}.constants.ts`,Pn({pascal:l,kebab:c})),await m(`${c}.controller.ts`,wn({pascal:l,kebab:c,plural:u,pluralPascal:d})),await m(`${c}.service.ts`,Nn({pascal:l,kebab:c})),await m(`dtos/create-${c}.dto.ts`,Ar(l,n)),await m(`dtos/update-${c}.dto.ts`,jr(l,n)),await m(`dtos/${c}-response.dto.ts`,Mr(l,n)),await m(`${c}.repository.ts`,On({pascal:l,kebab:c,dtoPrefix:`./dtos`,tokenScope:a}));let g=i===`inmemory`,_=g?`in-memory-${c}`:`${z(i)}-${c}`,v=g?kn({pascal:l,kebab:c,repoPrefix:`.`,dtoPrefix:`./dtos`}):An({pascal:l,kebab:c,repoType:i,repoPrefix:`.`,dtoPrefix:`./dtos`});return await m(`${_}.repository.ts`,v),await zn(r,l,u,c,o),p}function Ar(e,t){return`import { z } from 'zod'
|
|
2348
2352
|
|
|
2349
2353
|
export const create${e}Schema = z.object({
|
|
2350
2354
|
${t.map(e=>{let t=e.zodType;return` ${e.name}: ${t}${e.optional?`.optional()`:``},`}).join(`
|
|
@@ -2367,7 +2371,7 @@ ${t.map(e=>` ${e.name}${e.optional?`?`:``}: ${e.tsType}`).join(`
|
|
|
2367
2371
|
createdAt: string
|
|
2368
2372
|
updatedAt: string
|
|
2369
2373
|
}
|
|
2370
|
-
`}async function Nr(e){let{name:t,moduleName:n,modulesDir:r}=e,i=e.pluralize??!0,a=
|
|
2374
|
+
`}async function Nr(e){let{name:t,moduleName:n,modulesDir:r}=e,i=e.pluralize??!0,a=z(t),o=L(t),s=[],c;if(e.outDir)c=v(e.outDir);else if(n){let e=z(n),t=i?B(e):e;c=v(h(r??`src/modules`,t,`__tests__`))}else c=v(`src/__tests__`);let l=h(c,`${a}.test.ts`);return await N(l,`import { describe, it, expect, beforeEach } from 'vitest'
|
|
2371
2375
|
import { Container } from '@forinda/kickjs'
|
|
2372
2376
|
|
|
2373
2377
|
describe('${o}', () => {
|
|
@@ -2390,18 +2394,19 @@ describe('${o}', () => {
|
|
|
2390
2394
|
expect(true).toBe(true)
|
|
2391
2395
|
})
|
|
2392
2396
|
})
|
|
2393
|
-
`),s.push(l),s}const Pr=[`classes`,`tokens`,`injects`,`pluginsAndAdapters`,`augmentations`,`contextKeys`,`routes`,`moduleMounts`,`globPatterns`];function Fr(e){if(!e||typeof e!=`object`)return!1;let t=e;return Pr.every(e=>Array.isArray(t[e]))}var Ir=class e{path;prev;next=new Map;nextSig=new Map;constructor(e,t){this.path=e,this.prev=t}static async load(t){let n=h(t,`scan.json`),r=new Map;try{let e=await T(n,`utf-8`),t=JSON.parse(e);if(t.version===2&&t.files)for(let[e,n]of Object.entries(t.files))n&&typeof n.sig==`string`&&Fr(n.extract)&&r.set(e,n)}catch{}return new e(n,r)}static async signature(e){try{let t=await se(e);return`${t.mtimeMs}:${t.size}`}catch{return null}}get(e,t){let n=this.prev.get(e);return n&&n.sig===t?n.extract:null}set(e,t,n){this.next.set(e,n),this.nextSig.set(e,t)}cachedFiles(){return[...this.prev.keys()]}peek(e){return this.prev.get(e)?.extract??null}carry(e){let t=this.prev.get(e);return t?(this.next.set(e,t.extract),this.nextSig.set(e,t.sig),!0):!1}async save(){let e={};for(let[t,n]of this.next){let r=this.nextSig.get(t);r&&(e[t]={sig:r,extract:n})}let t={version:2,files:e};try{await w(f(this.path),{recursive:!0}),await E(this.path,JSON.stringify(t),`utf-8`)}catch{}}};let Lr=null;function Rr(){return Lr??=new Set(ei),Lr}const zr=new Set([`Get`,`Post`,`Put`,`Delete`,`Patch`]);function H(e){return typeof e==`object`&&!!e&&typeof e.type==`string`}function U(e,t){if(Array.isArray(e)){for(let n of e)U(n,t);return}if(H(e)){t(e);for(let n of Object.keys(e)){if(n===`type`)continue;let r=e[n];typeof r==`object`&&r&&U(r,t)}}}function W(e){if(!H(e))return null;if(e.type===`Literal`&&typeof e.value==`string`)return e.value;if(e.type===`TemplateLiteral`){let t=e.quasis,n=e.expressions;if(t?.length===1&&(n?.length??0)===0){let e=t[0].value?.cooked;return typeof e==`string`?e:null}}return null}function G(e){return H(e)&&e.type===`Identifier`?e.name:null}function Br(e){return G(e.callee)}function K(e,t){if(!e||e.type!==`ObjectExpression`)return null;for(let n of e.properties??[]){if(n.type!==`Property`)continue;let e=n.key;if((G(e)??(e.type===`Literal`?String(e.value):W(e)))===t)return n.value}return null}function Vr(e){let t=e.arguments?.[0];return H(t)&&t.type===`ObjectExpression`?t:null}function Hr(e,t){let n=K(e,t);if(!H(n)||n.type!==`ArrayExpression`)return[];let r=[];for(let e of n.elements??[]){let t=W(e);t!==null&&r.push(t)}return r}function Ur(e,t){return _(t,e).split(y).join(`/`)}function Wr(e){return(e.match(/:([a-zA-Z_]\w*)/g)??[]).map(e=>e.slice(1))}function Gr(e,t){for(let n of e.implements??[]){let e=n.expression??n;if(G(e)===t)return!0;if(e.type===`TSQualifiedName`||e.type===`MemberExpression`){let n=e.right??e.property;if(n&&G(n)===t)return!0}}return!1}function Kr(e){return e.decorators??[]}function qr(e){let t=e.expression;if(!H(t)||t.type!==`CallExpression`)return null;let n=Br(t);return n?{name:n,call:t}:null}function Jr(e){let t=new Map,n=new Set;for(let r of e.body??[]){if(r.type===`ImportDeclaration`){let e=W(r.source)??``;for(let n of r.specifiers??[]){let r=G(n.local);r&&t.set(r,{source:e})}continue}let e=r.type===`VariableDeclaration`?r:r.type===`ExportNamedDeclaration`&&H(r.declaration)?r.declaration:null;if(H(e)&&e.type===`VariableDeclaration`)for(let t of e.declarations??[]){let e=G(t.id);e&&n.add(e)}}return{imports:t,topLevelConsts:n}}function Yr(e,t){let n=t.imports.get(e);return n?{identifier:e,source:n.source}:t.topLevelConsts.has(e)?{identifier:e,source:``}:{identifier:e,source:null}}function Xr(e,t,n){let r=G(K(e,t));return r?Yr(r,n):null}function Zr(e,t){for(let n of e){let e=qr(n);if(!e||e.name!==`ApiQueryParams`)continue;let r=e.call.arguments?.[0],i=null;if(H(r)&&r.type===`ObjectExpression`)i=r;else{let e=G(r);if(e){let n=t.get(e);n&&n.type===`ObjectExpression`&&(i=n)}}return{filterable:Hr(i,`filterable`),sortable:Hr(i,`sortable`),searchable:Hr(i,`searchable`)}}return null}function Qr(e,t,n){let r;try{let n=de(t,e);if(n.errors.length>0)return null;r=n.program}catch{return null}let i=Ur(t,n),a=Jr(r),o=[],s=[],c=[],l=[],u=[],d=[],f=[],p=[],m=[],h=new Set,g=new Set,_=new Set,v=new Map;for(let e of r.body??[]){let t=e.type===`VariableDeclaration`?e:e.type===`ExportNamedDeclaration`&&H(e.declaration)?e.declaration:null;if(H(t)&&t.type===`VariableDeclaration`)for(let e of t.declarations??[]){let t=G(e.id);t&&H(e.init)&&v.set(t,e.init)}}let y=[];for(let e of r.body??[])if(e.type===`ExportNamedDeclaration`&&H(e.declaration)){let t=e.declaration;t.type===`ClassDeclaration`&&y.push({cls:t,isDefault:!1})}else if(e.type===`ExportDefaultDeclaration`&&H(e.declaration)){let t=e.declaration;t.type===`ClassDeclaration`&&y.push({cls:t,isDefault:!0})}for(let{cls:e,isDefault:n}of y){let r=G(e.id);if(!r)continue;let a=null;for(let t of Kr(e)){let e=qr(t);if(e&&Rr().has(e.name)){a=e.name;break}}a?o.push({className:r,decorator:a,filePath:t,relativePath:i,isDefault:n}):Gr(e,`AppModule`)&&o.push({className:r,decorator:`Module`,filePath:t,relativePath:i,isDefault:n})}for(let e of r.body??[]){if(e.type!==`ExportNamedDeclaration`||!H(e.declaration))continue;let n=e.declaration;if(n.type===`VariableDeclaration`)for(let e of n.declarations??[]){let n=G(e.id),r=e.init;!n||!H(r)||r.type!==`CallExpression`||Br(r)===`defineModule`&&(o.some(e=>e.className===n)||o.push({className:n,decorator:`Module`,filePath:t,relativePath:i,isDefault:!1}))}}U(r,e=>{if(e.type===`VariableDeclarator`){let n=e.init;if(H(n)&&n.type===`CallExpression`&&Br(n)===`createToken`){let r=W(n.arguments?.[0]);r!==null&&(_.add(n),s.push({name:r,variable:G(e.id),filePath:t,relativePath:i}))}return}if(e.type!==`CallExpression`){if(e.type===`Decorator`){let n=qr(e);if(n?.name===`Inject`){let e=W(n.call.arguments?.[0]);e!==null&&c.push({name:e,filePath:t,relativePath:i})}}return}let n=e.callee,r=Br(e);if(r===`createToken`&&!_.has(e)){let n=W(e.arguments?.[0]);n!==null&&s.push({name:n,variable:null,filePath:t,relativePath:i});return}if(r===`defineAdapter`||r===`definePlugin`){let n=W(K(Vr(e),`name`));if(n!==null){let e=r===`definePlugin`?`plugin`:`adapter`,a=`${r}::${n}::${t}`;h.has(a)||(h.add(a),l.push({kind:e,name:n,filePath:t,relativePath:i}))}return}if(r===`defineAugmentation`){let n=e.arguments??[],r=W(n[0]);if(r!==null){let e=H(n[1])&&n[1].type===`ObjectExpression`?n[1]:null;u.push({name:r,description:W(K(e,`description`)),example:W(K(e,`example`)),filePath:t,relativePath:i})}return}if(r===`defineContextDecorator`||r===`defineHttpContextDecorator`){let n=W(K(Vr(e),`key`));n!==null&&!g.has(n)&&(g.add(n),d.push({key:n,filePath:t,relativePath:i}));return}if(H(n)&&n.type===`CallExpression`){let r=n.callee;if(H(r)&&r.type===`MemberExpression`&&G(r.property)===`withParams`){let n=G(r.object);if(n===`defineContextDecorator`||n===`defineHttpContextDecorator`){let n=W(K(Vr(e),`key`));n!==null&&!g.has(n)&&(g.add(n),d.push({key:n,filePath:t,relativePath:i}))}}return}if(H(n)&&n.type===`MemberExpression`&&G(n.property)===`glob`){let t=n.object;H(t)&&t.type===`MetaProperty`&&U(e.arguments,e=>{let t=W(e);t!==null&&m.push(t)})}});let b=[];U(r,e=>{if(e.type===`ClassDeclaration`||e.type===`ClassExpression`){let t=G(e.id);t&&b.push({cls:e,className:t})}});for(let{cls:e,className:n}of b){let r=o.find(e=>e.className===n),s=e.body?.body;if(Gr(e,`AppAdapter`))for(let e of s??[]){if(e.type!==`PropertyDefinition`||G(e.key)!==`name`)continue;let n=W(e.value);if(n===null)continue;let r=`class::${n}::${t}`;h.has(r)||(h.add(r),l.push({kind:`adapter`,name:n,filePath:t,relativePath:i}));break}for(let e of s??[]){if(e.type!==`MethodDefinition`)continue;let o=G(e.key);if(!o)continue;if(o===`routes`){$r(e.value,p);continue}if(!r)continue;let s=Kr(e),c=Zr(s,v);for(let e of s){let r=qr(e);if(!r||!zr.has(r.name))continue;let s=r.call.arguments??[],l=W(s[0]),u=l&&l.length>0?l:`/`,d=H(s[1])&&s[1].type===`ObjectExpression`?s[1]:null;f.push({controller:n,method:o,httpMethod:r.name.toUpperCase(),path:u,pathParams:Wr(u),queryFilterable:c?.filterable??null,querySortable:c?.sortable??null,querySearchable:c?.searchable??null,bodySchema:Xr(d,`body`,a),querySchema:Xr(d,`query`,a),paramsSchema:Xr(d,`params`,a),filePath:t,relativePath:i})}}}return U(r,e=>{if(e.type!==`Property`||G(e.key)!==`routes`)return;let t=e.value;H(t)&&(t.type===`FunctionExpression`||t.type===`ArrowFunctionExpression`)&&$r(t,p)}),{classes:o,tokens:s,injects:c,pluginsAndAdapters:l,augmentations:u,contextKeys:d,routes:f,moduleMounts:p,globPatterns:/\.module\.[mc]?[tj]sx?$/.test(t)?m:[]}}function $r(e,t){let n=[],r=[];U(e.body,e=>{if(e.type!==`Property`)return;let t=G(e.key);if(t===`path`){let t=W(e.value);t!==null&&n.push(t)}else if(t===`controller`){let t=G(e.value);t&&/^[A-Z]/.test(t)&&r.push(t)}});let i=Math.min(n.length,r.length);for(let e=0;e<i;e++)t.push({controller:r[e],mountPath:n[e]})}const ei=[`Service`,`Controller`,`Repository`,`Injectable`,`Component`,`Module`],ti=[`.ts`,`.tsx`,`.mts`,`.cts`],ni=[`node_modules`,`.kickjs`,`dist`,`build`,`.test.`,`.spec.`,`.d.ts`],ri=new RegExp(String.raw`@(${ei.join(`|`)})\s*\([^)]*\)`+String.raw`(?:\s*@[A-Z]\w*(?:\s*\([^)]*\))?)*`+String.raw`\s*export\s+(default\s+)?(?:abstract\s+)?class\s+(\w+)`,`g`),ii=new RegExp(String.raw`export\s+(default\s+)?(?:abstract\s+)?class\s+(\w+)`+String.raw`(?:\s+extends\s+\w+(?:<[^>]*>)?)?`+String.raw`\s+implements\s+[^{]*\bAppModule\b`,`g`),ai=/export\s+const\s+(\w+)\s*(?::\s*[^=]+)?=\s*defineModule\s*(?:<[^>]*>)?\s*\(/g,oi=/(?:export\s+)?const\s+(\w+)\s*(?::\s*[^=]+)?=\s*createToken\s*(?:<[^>]*>)?\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g,si=/createToken\s*(?:<[^>]*>)?\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g,ci=/@Inject\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g,li=/\b(defineAdapter|definePlugin)\s*(?:<[^>]*>)?\s*\(/g,ui=/\b(?:defineContextDecorator|defineHttpContextDecorator)\s*(?:\.withParams\s*<(?:[^<>]|<[^<>]*>)*>\s*\(\s*\))?\s*(?:<(?:[^<>]|<[^<>]*>)*>)?\s*\(/g,di=new RegExp(String.raw`export\s+(?:default\s+)?(?:abstract\s+)?class\s+(\w+)`+String.raw`(?:\s+extends\s+\w+(?:<[^>]*>)?)?`+String.raw`\s+implements\s+[^{]*\bAppAdapter\b`,`g`),fi=/\bname\s*(?::\s*[^=]+)?=\s*['"`]([^'"`]+)['"`]/,pi=/\bdefineAugmentation\s*\(\s*['"`]([^'"`]+)['"`]\s*(,\s*\{)?/g,mi=new RegExp(String.raw`@(${[`Get`,`Post`,`Put`,`Delete`,`Patch`].join(`|`)})\s*\(`,`g`);function hi(e,t){let n=1;for(let r=t+1;r<e.length;r++){let t=e[r];if(t===`(`)n++;else if(t===`)`&&(n--,n===0))return r}return-1}function gi(e,t){let n=t;for(;n<e.length;){for(;n<e.length&&/\s/.test(e[n]);)n++;if(e[n]!==`@`)break;let t=e.slice(n).match(/^@([A-Z]\w*)/);if(!t)break;for(n+=t[0].length;n<e.length&&/\s/.test(e[n]);)n++;if(e[n]===`(`){let t=hi(e,n);if(t<0)return null;n=t+1}}for(;n<e.length&&/\s/.test(e[n]);)n++;for(let t of[`public`,`private`,`protected`])if(e.slice(n,n+t.length)===t&&/\s/.test(e.charAt(n+t.length))){for(n+=t.length;n<e.length&&/\s/.test(e[n]);)n++;break}if(e.slice(n,n+5)===`async`&&/\s/.test(e.charAt(n+5)))for(n+=5;n<e.length&&/\s/.test(e[n]);)n++;let r=e.slice(n).match(/^([a-zA-Z_]\w*)\s*\(/);return r?{methodName:r[1],endPos:n+r[0].length}:null}function _i(e){return(e.match(/:([a-zA-Z_]\w*)/g)??[]).map(e=>e.slice(1))}function vi(e,t){let n=e.endsWith(`/`)?e.slice(0,-1):e;return!t||t===`/`?n||`/`:n+(t.startsWith(`/`)?t:`/`+t)||`/`}const yi=/\b(?:public\s+|private\s+|protected\s+)?routes\s*\([^)]*\)\s*(?::\s*[A-Za-z_][\w<>[\]\s,|]*\s*)?\{/g,bi=/\bpath\s*:\s*['"`]([^'"`]*)['"`]/g,xi=/\bcontroller\s*:\s*([A-Z]\w*)\b/g,Si=/\bimport\.meta\.glob\s*\(/g;function Ci(e){let t=[];for(Si.lastIndex=0;Si.exec(e)!==null;){let n=Si.lastIndex-1,r=hi(e,n);if(r<0)continue;let i=e.slice(n+1,r),a=/['"`]([^'"`]+)['"`]/g,o;for(;(o=a.exec(i))!==null;)t.push(o[1])}return t}function wi(e){let t=e.replace(/[.+^$()|[\]\\]/g,`\\$&`).replace(/\?/g,`.`).replace(/\*\*\//g,`___DOUBLESTAR_SLASH___`).replace(/\*\*/g,`___DOUBLESTAR___`).replace(/\*/g,`[^/]*`).replace(/___DOUBLESTAR_SLASH___/g,`(?:.+/)?`).replace(/___DOUBLESTAR___/g,`.*`);return RegExp(`^`+t+`$`)}function Ti(e,t){let n=e.startsWith(`./`)?e:`./`+e,r=!1;for(let e of t){let t=e.startsWith(`!`);wi(t?e.slice(1):e).test(n)&&(r=!t)}return r}function Ei(e){let t=[];yi.lastIndex=0;let n;for(;(n=yi.exec(e))!==null;){let r=e.indexOf(`{`,n.index+n[0].length-1);if(r<0)continue;let i=Ri(e,r);if(i<0)continue;let a=e.slice(r+1,i),o=[];bi.lastIndex=0;let s;for(;(s=bi.exec(a))!==null;)o.push(s[1]??``);let c=[];xi.lastIndex=0;let l;for(;(l=xi.exec(a))!==null;)c.push(l[1]);let u=Math.min(o.length,c.length);for(let e=0;e<u;e++)t.push({controller:c[e],mountPath:o[e]})}return t}function Di(e,t){let n=new RegExp(String.raw`\b${t}\s*:\s*([A-Za-z_$][\w$]*)`,`g`).exec(e);return n?n[1]:null}function Oi(e,t){let n=new RegExp(String.raw`import\s*(?:type\s+)?\{[^}]*\b${t}\b[^}]*\}\s*from\s*['"\`]([^'"\`]+)['"\`]`).exec(e);if(n)return n[1];let r=new RegExp(String.raw`import\s+(?:type\s+)?${t}\s+from\s*['"\`]([^'"\`]+)['"\`]`).exec(e);if(r)return r[1];let i=new RegExp(String.raw`import\s*\*\s*as\s+${t}\s+from\s*['"\`]([^'"\`]+)['"\`]`).exec(e);return i?i[1]:new RegExp(String.raw`(?:^|\n)\s*(?:export\s+)?const\s+${t}\b`).test(e)?``:null}function ki(e,t){let n=/@ApiQueryParams\s*\(\s*([\s\S]*?)\s*\)\s*$/.exec(e);if(!n){let n=/@ApiQueryParams\s*\(([\s\S]*?)\)/.exec(e);return n?Ai(n[1].trim(),t):null}return Ai(n[1].trim(),t)}function Ai(e,t){if(e.startsWith(`{`))return Mi(e);let n=/^([A-Za-z_]\w*)/.exec(e);if(n){let e=n[1],r=new RegExp(String.raw`const\s+${e}\s*(?::\s*[^=]+)?=\s*(\{[\s\S]*?\n\})`,`m`).exec(t);if(r)return Mi(r[1])}return{filterable:[],sortable:[],searchable:[]}}function ji(e,t){let n=new RegExp(String.raw`${t}\s*:\s*\[([\s\S]*?)\]`).exec(e);return n?Array.from(n[1].matchAll(/['"`]([^'"`]+)['"`]/g)).map(e=>e[1]):[]}function Mi(e){return{filterable:ji(e,`filterable`),sortable:ji(e,`sortable`),searchable:ji(e,`searchable`)}}async function Ni(e,t){let n=t.extensions??ti,r=t.exclude??ni,i=[],a;try{a=await ae(e,{withFileTypes:!0,encoding:`utf-8`})}catch{return i}for(let o of a){let a=h(e,o.name),s=_(t.cwd,a);r.some(e=>s.includes(e))||(o.isDirectory()?i.push(...await Ni(a,t)):o.isFile()&&n.some(e=>o.name.endsWith(e))&&i.push(a))}return i}function q(e,t){return _(t,e).split(y).join(`/`)}function Pi(e,t,n){let r=[],i=q(t,n);ri.lastIndex=0;let a;for(;(a=ri.exec(e))!==null;){let[,e,n,o]=a;r.push({className:o,decorator:e,filePath:t,relativePath:i,isDefault:!!n})}ii.lastIndex=0;let o;for(;(o=ii.exec(e))!==null;){let[,e,n]=o;r.some(e=>e.className===n&&e.filePath===t)||r.push({className:n,decorator:`Module`,filePath:t,relativePath:i,isDefault:!!e})}ai.lastIndex=0;let s;for(;(s=ai.exec(e))!==null;){let[,e]=s;r.some(n=>n.className===e&&n.filePath===t)||r.push({className:e,decorator:`Module`,filePath:t,relativePath:i,isDefault:!1})}return r}function Fi(e,t,n){let r=[],i=q(t,n),a=new Set;oi.lastIndex=0;let o;for(;(o=oi.exec(e))!==null;){let[e,n,s]=o;a.add(e),r.push({name:s,variable:n,filePath:t,relativePath:i})}for(si.lastIndex=0;(o=si.exec(e))!==null;)a.has(o[0])||r.push({name:o[1],variable:null,filePath:t,relativePath:i});return r}function Ii(e,t,n,r,i=new Map){let a=[];if(r.length===0)return a;let o=q(t,n),s=[];for(let t of r){let n=new RegExp(String.raw`class\s+${t.className}\b`).exec(e);n?.index!==void 0&&s.push({cls:t,start:n.index})}s.sort((e,t)=>e.start-t.start);for(let n=0;n<s.length;n++){let{cls:r,start:c}=s[n],l=n+1<s.length?s[n+1].start:e.length,u=e.slice(c,l);mi.lastIndex=0;let d;for(;(d=mi.exec(u))!==null;){let n=d[1],s=d.index,c=mi.lastIndex-1,l=hi(u,c);if(l<0)continue;let f=u.slice(c+1,l),p=f.match(/^\s*['"`]([^'"`]*)['"`]/),m=p&&p[1].length>0?p[1]:`/`,h=gi(u,l+1);if(!h)continue;let{methodName:g,endPos:_}=h;mi.lastIndex=_;let v=ki(u.slice(s,_),e),y=Di(f,`body`),b=Di(f,`query`),x=Di(f,`params`),S=i.get(r.className)??``,C=S?vi(S,m):m;a.push({controller:r.className,method:g,httpMethod:n.toUpperCase(),path:m,pathParams:_i(C),queryFilterable:v?.filterable??null,querySortable:v?.sortable??null,querySearchable:v?.searchable??null,bodySchema:y?{identifier:y,source:Oi(e,y)}:null,querySchema:b?{identifier:b,source:Oi(e,b)}:null,paramsSchema:x?{identifier:x,source:Oi(e,x)}:null,filePath:t,relativePath:o})}}return a}function Li(e,t,n){let r=[],i=q(t,n);ci.lastIndex=0;let a;for(;(a=ci.exec(e))!==null;)r.push({name:a[1],filePath:t,relativePath:i});return r}function Ri(e,t){let n=1;for(let r=t+1;r<e.length;r++){let t=e[r];if(t===`{`)n++;else if(t===`}`&&(n--,n===0))return r}return-1}function zi(e,t,n){let r=[],i=q(t,n),a=new Set;li.lastIndex=0;let o;for(;(o=li.exec(e))!==null;){let n=o[1],s=li.lastIndex-1,c=hi(e,s);if(c<0)continue;let l=e.slice(s+1,c),u=/\bname\s*:\s*['"`]([^'"`]+)['"`]/.exec(l);if(!u)continue;let d=u[1],f=`${n}::${d}::${t}`;a.has(f)||(a.add(f),r.push({kind:n===`definePlugin`?`plugin`:`adapter`,name:d,filePath:t,relativePath:i}))}di.lastIndex=0;let s;for(;(s=di.exec(e))!==null;){let n=s.index,o=e.indexOf(`{`,n);if(o<0)continue;let c=Ri(e,o);if(c<0)continue;let l=e.slice(o+1,c),u=fi.exec(l);if(!u)continue;let d=u[1],f=`class::${d}::${t}`;a.has(f)||(a.add(f),r.push({kind:`adapter`,name:d,filePath:t,relativePath:i}))}return r}function Bi(e,t,n){let r=[],i=q(t,n),a=new Set;for(ui.lastIndex=0;ui.exec(e)!==null;){let n=ui.lastIndex-1,o=hi(e,n);if(o<0)continue;let s=e.slice(n+1,o),c=/\bkey\s*:\s*['"`]([^'"`]+)['"`]/.exec(s);if(!c)continue;let l=c[1];a.has(l)||(a.add(l),r.push({key:l,filePath:t,relativePath:i}))}return r}function Vi(e,t,n){let r=[],i=q(t,n);pi.lastIndex=0;let a;for(;(a=pi.exec(e))!==null;){let n=a[1],o=null,s=null;if(a[2]){let t=e.indexOf(`{`,a.index+a[0].length-1);if(t>=0){let n=Ri(e,t);if(n>=0){let r=e.slice(t+1,n);o=Hi(r,`description`),s=Hi(r,`example`)}}}r.push({name:n,description:o,example:s,filePath:t,relativePath:i})}return r}function Hi(e,t){let n=RegExp(`\\b${t}\\s*:\\s*(['"\`])`,`g`).exec(e);if(!n)return null;let r=n[1],i=n.index+n[0].length,a=i,o=null;for(;a<e.length;){let t=e[a];if(t===`\\`){a+=2;continue}if(t===r){o=e.slice(i,a);break}a++}return o===null?null:o.replace(/\\(.)/g,(e,t)=>t===`n`?`
|
|
2394
|
-
`:t===`t`?` `:t===`r`?`\r`:t)}const Ui=[`src/config/index.ts`,`src/config/env.ts`,`src/config.ts`,`src/env.ts`];async function Wi(e,t){let n=t===`src/env.ts`?Ui:[t];for(let t of n){let n=v(e,t),r;try{r=await
|
|
2395
|
-
`)}function da(e,t){let n=_(f(t),e).split(y).join(`/`);return n=n.replace(/\.(ts|tsx|mts|cts)$/i,``),n.startsWith(`.`)||(n=`./`+n),n}function fa(e){let t=e.relativePath.replace(/^src\//,``).replace(/\.(ts|tsx|mts|cts)$/i,``).split(`/`);t.pop();let n=t.join(`/`);return n?`${n}/${e.className}`:e.className}function pa(e,t,n){let r=new Set,i=[];for(let a of e){if(!ca.has(a.decorator))continue;let e=n.has(a.className)?fa(a):a.className;if(r.has(e))continue;r.add(e);let o=da(a.filePath,t),s=a.isDefault?`import('${o}').default`:`import('${o}').${a.className}`;i.push(` '${e}': ${s}`)}
|
|
2397
|
+
`),s.push(l),s}const Pr=[`classes`,`tokens`,`injects`,`pluginsAndAdapters`,`augmentations`,`contextKeys`,`routes`,`moduleMounts`,`globPatterns`];function Fr(e){if(!e||typeof e!=`object`)return!1;let t=e;return Pr.every(e=>Array.isArray(t[e]))}var Ir=class e{path;prev;next=new Map;nextSig=new Map;constructor(e,t){this.path=e,this.prev=t}static async load(t){let n=h(t,`scan.json`),r=new Map;try{let e=await w(n,`utf-8`),t=JSON.parse(e);if(t.version===2&&t.files)for(let[e,n]of Object.entries(t.files))n&&typeof n.sig==`string`&&Fr(n.extract)&&r.set(e,n)}catch{}return new e(n,r)}static async signature(e){try{let t=await ce(e);return`${t.mtimeMs}:${t.size}`}catch{return null}}get(e,t){let n=this.prev.get(e);return n&&n.sig===t?n.extract:null}set(e,t,n){this.next.set(e,n),this.nextSig.set(e,t)}cachedFiles(){return[...this.prev.keys()]}peek(e){return this.prev.get(e)?.extract??null}carry(e){let t=this.prev.get(e);return t?(this.next.set(e,t.extract),this.nextSig.set(e,t.sig),!0):!1}async save(){let e={};for(let[t,n]of this.next){let r=this.nextSig.get(t);r&&(e[t]={sig:r,extract:n})}let t={version:2,files:e};try{await C(f(this.path),{recursive:!0}),await T(this.path,JSON.stringify(t),`utf-8`)}catch{}}};let Lr=null;function Rr(){return Lr??=new Set(ei),Lr}const zr=new Set([`Get`,`Post`,`Put`,`Delete`,`Patch`]);function H(e){return typeof e==`object`&&!!e&&typeof e.type==`string`}function U(e,t){if(Array.isArray(e)){for(let n of e)U(n,t);return}if(H(e)){t(e);for(let n of Object.keys(e)){if(n===`type`)continue;let r=e[n];typeof r==`object`&&r&&U(r,t)}}}function W(e){if(!H(e))return null;if(e.type===`Literal`&&typeof e.value==`string`)return e.value;if(e.type===`TemplateLiteral`){let t=e.quasis,n=e.expressions;if(t?.length===1&&(n?.length??0)===0){let e=t[0].value?.cooked;return typeof e==`string`?e:null}}return null}function G(e){return H(e)&&e.type===`Identifier`?e.name:null}function Br(e){return G(e.callee)}function K(e,t){if(!e||e.type!==`ObjectExpression`)return null;for(let n of e.properties??[]){if(n.type!==`Property`)continue;let e=n.key;if((G(e)??(e.type===`Literal`?String(e.value):W(e)))===t)return n.value}return null}function Vr(e){let t=e.arguments?.[0];return H(t)&&t.type===`ObjectExpression`?t:null}function Hr(e,t){let n=K(e,t);if(!H(n)||n.type!==`ArrayExpression`)return[];let r=[];for(let e of n.elements??[]){let t=W(e);t!==null&&r.push(t)}return r}function Ur(e,t){return _(t,e).split(y).join(`/`)}function Wr(e){return(e.match(/:([a-zA-Z_]\w*)/g)??[]).map(e=>e.slice(1))}function Gr(e,t){for(let n of e.implements??[]){let e=n.expression??n;if(G(e)===t)return!0;if(e.type===`TSQualifiedName`||e.type===`MemberExpression`){let n=e.right??e.property;if(n&&G(n)===t)return!0}}return!1}function Kr(e){return e.decorators??[]}function qr(e){let t=e.expression;if(!H(t)||t.type!==`CallExpression`)return null;let n=Br(t);return n?{name:n,call:t}:null}function Jr(e){let t=new Map,n=new Set;for(let r of e.body??[]){if(r.type===`ImportDeclaration`){let e=W(r.source)??``;for(let n of r.specifiers??[]){let r=G(n.local);r&&t.set(r,{source:e})}continue}let e=r.type===`VariableDeclaration`?r:r.type===`ExportNamedDeclaration`&&H(r.declaration)?r.declaration:null;if(H(e)&&e.type===`VariableDeclaration`)for(let t of e.declarations??[]){let e=G(t.id);e&&n.add(e)}}return{imports:t,topLevelConsts:n}}function Yr(e,t){let n=t.imports.get(e);return n?{identifier:e,source:n.source}:t.topLevelConsts.has(e)?{identifier:e,source:``}:{identifier:e,source:null}}function Xr(e,t,n){let r=G(K(e,t));return r?Yr(r,n):null}function Zr(e,t){for(let n of e){let e=qr(n);if(!e||e.name!==`ApiQueryParams`)continue;let r=e.call.arguments?.[0],i=null;if(H(r)&&r.type===`ObjectExpression`)i=r;else{let e=G(r);if(e){let n=t.get(e);n&&n.type===`ObjectExpression`&&(i=n)}}return{filterable:Hr(i,`filterable`),sortable:Hr(i,`sortable`),searchable:Hr(i,`searchable`)}}return null}function Qr(e,t,n){let r;try{let n=fe(t,e);if(n.errors.length>0)return null;r=n.program}catch{return null}let i=Ur(t,n),a=Jr(r),o=[],s=[],c=[],l=[],u=[],d=[],f=[],p=[],m=[],h=new Set,g=new Set,_=new Set,v=new Map;for(let e of r.body??[]){let t=e.type===`VariableDeclaration`?e:e.type===`ExportNamedDeclaration`&&H(e.declaration)?e.declaration:null;if(H(t)&&t.type===`VariableDeclaration`)for(let e of t.declarations??[]){let t=G(e.id);t&&H(e.init)&&v.set(t,e.init)}}let y=[];for(let e of r.body??[])if(e.type===`ExportNamedDeclaration`&&H(e.declaration)){let t=e.declaration;t.type===`ClassDeclaration`&&y.push({cls:t,isDefault:!1})}else if(e.type===`ExportDefaultDeclaration`&&H(e.declaration)){let t=e.declaration;t.type===`ClassDeclaration`&&y.push({cls:t,isDefault:!0})}for(let{cls:e,isDefault:n}of y){let r=G(e.id);if(!r)continue;let a=null;for(let t of Kr(e)){let e=qr(t);if(e&&Rr().has(e.name)){a=e.name;break}}a?o.push({className:r,decorator:a,filePath:t,relativePath:i,isDefault:n}):Gr(e,`AppModule`)&&o.push({className:r,decorator:`Module`,filePath:t,relativePath:i,isDefault:n})}for(let e of r.body??[]){if(e.type!==`ExportNamedDeclaration`||!H(e.declaration))continue;let n=e.declaration;if(n.type===`VariableDeclaration`)for(let e of n.declarations??[]){let n=G(e.id),r=e.init;!n||!H(r)||r.type!==`CallExpression`||Br(r)===`defineModule`&&(o.some(e=>e.className===n)||o.push({className:n,decorator:`Module`,filePath:t,relativePath:i,isDefault:!1}))}}U(r,e=>{if(e.type===`VariableDeclarator`){let n=e.init;if(H(n)&&n.type===`CallExpression`&&Br(n)===`createToken`){let r=W(n.arguments?.[0]);r!==null&&(_.add(n),s.push({name:r,variable:G(e.id),filePath:t,relativePath:i}))}return}if(e.type!==`CallExpression`){if(e.type===`Decorator`){let n=qr(e);if(n?.name===`Inject`){let e=W(n.call.arguments?.[0]);e!==null&&c.push({name:e,filePath:t,relativePath:i})}}return}let n=e.callee,r=Br(e);if(r===`createToken`&&!_.has(e)){let n=W(e.arguments?.[0]);n!==null&&s.push({name:n,variable:null,filePath:t,relativePath:i});return}if(r===`defineAdapter`||r===`definePlugin`){let n=W(K(Vr(e),`name`));if(n!==null){let e=r===`definePlugin`?`plugin`:`adapter`,a=`${r}::${n}::${t}`;h.has(a)||(h.add(a),l.push({kind:e,name:n,filePath:t,relativePath:i}))}return}if(r===`defineAugmentation`){let n=e.arguments??[],r=W(n[0]);if(r!==null){let e=H(n[1])&&n[1].type===`ObjectExpression`?n[1]:null;u.push({name:r,description:W(K(e,`description`)),example:W(K(e,`example`)),filePath:t,relativePath:i})}return}if(r===`defineContextDecorator`||r===`defineHttpContextDecorator`){let n=W(K(Vr(e),`key`));n!==null&&!g.has(n)&&(g.add(n),d.push({key:n,filePath:t,relativePath:i}));return}if(H(n)&&n.type===`CallExpression`){let r=n.callee;if(H(r)&&r.type===`MemberExpression`&&G(r.property)===`withParams`){let n=G(r.object);if(n===`defineContextDecorator`||n===`defineHttpContextDecorator`){let n=W(K(Vr(e),`key`));n!==null&&!g.has(n)&&(g.add(n),d.push({key:n,filePath:t,relativePath:i}))}}return}if(H(n)&&n.type===`MemberExpression`&&G(n.property)===`glob`){let t=n.object;H(t)&&t.type===`MetaProperty`&&U(e.arguments,e=>{let t=W(e);t!==null&&m.push(t)})}});let b=[];U(r,e=>{if(e.type===`ClassDeclaration`||e.type===`ClassExpression`){let t=G(e.id);t&&b.push({cls:e,className:t})}});for(let{cls:e,className:n}of b){let r=o.find(e=>e.className===n),s=e.body?.body;if(Gr(e,`AppAdapter`))for(let e of s??[]){if(e.type!==`PropertyDefinition`||G(e.key)!==`name`)continue;let n=W(e.value);if(n===null)continue;let r=`class::${n}::${t}`;h.has(r)||(h.add(r),l.push({kind:`adapter`,name:n,filePath:t,relativePath:i}));break}for(let e of s??[]){if(e.type!==`MethodDefinition`)continue;let o=G(e.key);if(!o)continue;if(o===`routes`){$r(e.value,p);continue}if(!r)continue;let s=Kr(e),c=Zr(s,v);for(let e of s){let s=qr(e);if(!s||!zr.has(s.name))continue;let l=s.call.arguments??[],u=W(l[0]),d=u&&u.length>0?u:`/`,p=H(l[1])&&l[1].type===`ObjectExpression`?l[1]:null;f.push({controller:n,method:o,httpMethod:s.name.toUpperCase(),path:d,pathParams:Wr(d),queryFilterable:c?.filterable??null,querySortable:c?.sortable??null,querySearchable:c?.searchable??null,bodySchema:Xr(p,`body`,a),querySchema:Xr(p,`query`,a),paramsSchema:Xr(p,`params`,a),filePath:t,relativePath:i,controllerIsDefaultExport:r.isDefault,mountedPath:d})}}}return U(r,e=>{if(e.type!==`Property`||G(e.key)!==`routes`)return;let t=e.value;H(t)&&(t.type===`FunctionExpression`||t.type===`ArrowFunctionExpression`)&&$r(t,p)}),{classes:o,tokens:s,injects:c,pluginsAndAdapters:l,augmentations:u,contextKeys:d,routes:f,moduleMounts:p,globPatterns:/\.module\.[mc]?[tj]sx?$/.test(t)?m:[]}}function $r(e,t){let n=[],r=[];U(e.body,e=>{if(e.type!==`Property`)return;let t=G(e.key);if(t===`path`){let t=W(e.value);t!==null&&n.push(t)}else if(t===`controller`){let t=G(e.value);t&&/^[A-Z]/.test(t)&&r.push(t)}});let i=Math.min(n.length,r.length);for(let e=0;e<i;e++)t.push({controller:r[e],mountPath:n[e]})}const ei=[`Service`,`Controller`,`Repository`,`Injectable`,`Component`,`Module`],ti=[`.ts`,`.tsx`,`.mts`,`.cts`],ni=[`node_modules`,`.kickjs`,`dist`,`build`,`.test.`,`.spec.`,`.d.ts`],ri=new RegExp(String.raw`@(${ei.join(`|`)})\s*\([^)]*\)`+String.raw`(?:\s*@[A-Z]\w*(?:\s*\([^)]*\))?)*`+String.raw`\s*export\s+(default\s+)?(?:abstract\s+)?class\s+(\w+)`,`g`),ii=new RegExp(String.raw`export\s+(default\s+)?(?:abstract\s+)?class\s+(\w+)`+String.raw`(?:\s+extends\s+\w+(?:<[^>]*>)?)?`+String.raw`\s+implements\s+[^{]*\bAppModule\b`,`g`),ai=/export\s+const\s+(\w+)\s*(?::\s*[^=]+)?=\s*defineModule\s*(?:<[^>]*>)?\s*\(/g,oi=/(?:export\s+)?const\s+(\w+)\s*(?::\s*[^=]+)?=\s*createToken\s*(?:<[^>]*>)?\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g,si=/createToken\s*(?:<[^>]*>)?\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g,ci=/@Inject\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g,li=/\b(defineAdapter|definePlugin)\s*(?:<[^>]*>)?\s*\(/g,ui=/\b(?:defineContextDecorator|defineHttpContextDecorator)\s*(?:\.withParams\s*<(?:[^<>]|<[^<>]*>)*>\s*\(\s*\))?\s*(?:<(?:[^<>]|<[^<>]*>)*>)?\s*\(/g,di=new RegExp(String.raw`export\s+(?:default\s+)?(?:abstract\s+)?class\s+(\w+)`+String.raw`(?:\s+extends\s+\w+(?:<[^>]*>)?)?`+String.raw`\s+implements\s+[^{]*\bAppAdapter\b`,`g`),fi=/\bname\s*(?::\s*[^=]+)?=\s*['"`]([^'"`]+)['"`]/,pi=/\bdefineAugmentation\s*\(\s*['"`]([^'"`]+)['"`]\s*(,\s*\{)?/g,mi=new RegExp(String.raw`@(${[`Get`,`Post`,`Put`,`Delete`,`Patch`].join(`|`)})\s*\(`,`g`);function hi(e,t){let n=1;for(let r=t+1;r<e.length;r++){let t=e[r];if(t===`(`)n++;else if(t===`)`&&(n--,n===0))return r}return-1}function gi(e,t){let n=t;for(;n<e.length;){for(;n<e.length&&/\s/.test(e[n]);)n++;if(e[n]!==`@`)break;let t=e.slice(n).match(/^@([A-Z]\w*)/);if(!t)break;for(n+=t[0].length;n<e.length&&/\s/.test(e[n]);)n++;if(e[n]===`(`){let t=hi(e,n);if(t<0)return null;n=t+1}}for(;n<e.length&&/\s/.test(e[n]);)n++;for(let t of[`public`,`private`,`protected`])if(e.slice(n,n+t.length)===t&&/\s/.test(e.charAt(n+t.length))){for(n+=t.length;n<e.length&&/\s/.test(e[n]);)n++;break}if(e.slice(n,n+5)===`async`&&/\s/.test(e.charAt(n+5)))for(n+=5;n<e.length&&/\s/.test(e[n]);)n++;let r=e.slice(n).match(/^([a-zA-Z_]\w*)\s*\(/);return r?{methodName:r[1],endPos:n+r[0].length}:null}function _i(e){return(e.match(/:([a-zA-Z_]\w*)/g)??[]).map(e=>e.slice(1))}function vi(e,t){let n=e.endsWith(`/`)?e.slice(0,-1):e;return!t||t===`/`?n||`/`:n+(t.startsWith(`/`)?t:`/`+t)||`/`}const yi=/\b(?:public\s+|private\s+|protected\s+)?routes\s*\([^)]*\)\s*(?::\s*[A-Za-z_][\w<>[\]\s,|]*\s*)?\{/g,bi=/\bpath\s*:\s*['"`]([^'"`]*)['"`]/g,xi=/\bcontroller\s*:\s*([A-Z]\w*)\b/g,Si=/\bimport\.meta\.glob\s*\(/g;function Ci(e){let t=[];for(Si.lastIndex=0;Si.exec(e)!==null;){let n=Si.lastIndex-1,r=hi(e,n);if(r<0)continue;let i=e.slice(n+1,r),a=/['"`]([^'"`]+)['"`]/g,o;for(;(o=a.exec(i))!==null;)t.push(o[1])}return t}function wi(e){let t=e.replace(/[.+^$()|[\]\\]/g,`\\$&`).replace(/\?/g,`.`).replace(/\*\*\//g,`___DOUBLESTAR_SLASH___`).replace(/\*\*/g,`___DOUBLESTAR___`).replace(/\*/g,`[^/]*`).replace(/___DOUBLESTAR_SLASH___/g,`(?:.+/)?`).replace(/___DOUBLESTAR___/g,`.*`);return RegExp(`^`+t+`$`)}function Ti(e,t){let n=e.startsWith(`./`)?e:`./`+e,r=!1;for(let e of t){let t=e.startsWith(`!`);wi(t?e.slice(1):e).test(n)&&(r=!t)}return r}function Ei(e){let t=[];yi.lastIndex=0;let n;for(;(n=yi.exec(e))!==null;){let r=e.indexOf(`{`,n.index+n[0].length-1);if(r<0)continue;let i=Ri(e,r);if(i<0)continue;let a=e.slice(r+1,i),o=[];bi.lastIndex=0;let s;for(;(s=bi.exec(a))!==null;)o.push(s[1]??``);let c=[];xi.lastIndex=0;let l;for(;(l=xi.exec(a))!==null;)c.push(l[1]);let u=Math.min(o.length,c.length);for(let e=0;e<u;e++)t.push({controller:c[e],mountPath:o[e]})}return t}function Di(e,t){let n=new RegExp(String.raw`\b${t}\s*:\s*([A-Za-z_$][\w$]*)`,`g`).exec(e);return n?n[1]:null}function Oi(e,t){let n=new RegExp(String.raw`import\s*(?:type\s+)?\{[^}]*\b${t}\b[^}]*\}\s*from\s*['"\`]([^'"\`]+)['"\`]`).exec(e);if(n)return n[1];let r=new RegExp(String.raw`import\s+(?:type\s+)?${t}\s+from\s*['"\`]([^'"\`]+)['"\`]`).exec(e);if(r)return r[1];let i=new RegExp(String.raw`import\s*\*\s*as\s+${t}\s+from\s*['"\`]([^'"\`]+)['"\`]`).exec(e);return i?i[1]:new RegExp(String.raw`(?:^|\n)\s*(?:export\s+)?const\s+${t}\b`).test(e)?``:null}function ki(e,t){let n=/@ApiQueryParams\s*\(\s*([\s\S]*?)\s*\)\s*$/.exec(e);if(!n){let n=/@ApiQueryParams\s*\(([\s\S]*?)\)/.exec(e);return n?Ai(n[1].trim(),t):null}return Ai(n[1].trim(),t)}function Ai(e,t){if(e.startsWith(`{`))return Mi(e);let n=/^([A-Za-z_]\w*)/.exec(e);if(n){let e=n[1],r=new RegExp(String.raw`const\s+${e}\s*(?::\s*[^=]+)?=\s*(\{[\s\S]*?\n\})`,`m`).exec(t);if(r)return Mi(r[1])}return{filterable:[],sortable:[],searchable:[]}}function ji(e,t){let n=new RegExp(String.raw`${t}\s*:\s*\[([\s\S]*?)\]`).exec(e);return n?Array.from(n[1].matchAll(/['"`]([^'"`]+)['"`]/g)).map(e=>e[1]):[]}function Mi(e){return{filterable:ji(e,`filterable`),sortable:ji(e,`sortable`),searchable:ji(e,`searchable`)}}async function Ni(e,t){let n=t.extensions??ti,r=t.exclude??ni,i=[],a;try{a=await oe(e,{withFileTypes:!0,encoding:`utf-8`})}catch{return i}for(let o of a){let a=h(e,o.name),s=_(t.cwd,a);r.some(e=>s.includes(e))||(o.isDirectory()?i.push(...await Ni(a,t)):o.isFile()&&n.some(e=>o.name.endsWith(e))&&i.push(a))}return i}function q(e,t){return _(t,e).split(y).join(`/`)}function Pi(e,t,n){let r=[],i=q(t,n);ri.lastIndex=0;let a;for(;(a=ri.exec(e))!==null;){let[,e,n,o]=a;r.push({className:o,decorator:e,filePath:t,relativePath:i,isDefault:!!n})}ii.lastIndex=0;let o;for(;(o=ii.exec(e))!==null;){let[,e,n]=o;r.some(e=>e.className===n&&e.filePath===t)||r.push({className:n,decorator:`Module`,filePath:t,relativePath:i,isDefault:!!e})}ai.lastIndex=0;let s;for(;(s=ai.exec(e))!==null;){let[,e]=s;r.some(n=>n.className===e&&n.filePath===t)||r.push({className:e,decorator:`Module`,filePath:t,relativePath:i,isDefault:!1})}return r}function Fi(e,t,n){let r=[],i=q(t,n),a=new Set;oi.lastIndex=0;let o;for(;(o=oi.exec(e))!==null;){let[e,n,s]=o;a.add(e),r.push({name:s,variable:n,filePath:t,relativePath:i})}for(si.lastIndex=0;(o=si.exec(e))!==null;)a.has(o[0])||r.push({name:o[1],variable:null,filePath:t,relativePath:i});return r}function Ii(e,t,n,r,i=new Map){let a=[];if(r.length===0)return a;let o=q(t,n),s=[];for(let t of r){let n=new RegExp(String.raw`class\s+${t.className}\b`).exec(e);n?.index!==void 0&&s.push({cls:t,start:n.index})}s.sort((e,t)=>e.start-t.start);for(let n=0;n<s.length;n++){let{cls:r,start:c}=s[n],l=n+1<s.length?s[n+1].start:e.length,u=e.slice(c,l);mi.lastIndex=0;let d;for(;(d=mi.exec(u))!==null;){let n=d[1],s=d.index,c=mi.lastIndex-1,l=hi(u,c);if(l<0)continue;let f=u.slice(c+1,l),p=f.match(/^\s*['"`]([^'"`]*)['"`]/),m=p&&p[1].length>0?p[1]:`/`,h=gi(u,l+1);if(!h)continue;let{methodName:g,endPos:_}=h;mi.lastIndex=_;let v=ki(u.slice(s,_),e),y=Di(f,`body`),b=Di(f,`query`),x=Di(f,`params`),ee=i.get(r.className)??``,S=ee?vi(ee,m):m;a.push({controller:r.className,method:g,httpMethod:n.toUpperCase(),path:m,pathParams:_i(S),queryFilterable:v?.filterable??null,querySortable:v?.sortable??null,querySearchable:v?.searchable??null,bodySchema:y?{identifier:y,source:Oi(e,y)}:null,querySchema:b?{identifier:b,source:Oi(e,b)}:null,paramsSchema:x?{identifier:x,source:Oi(e,x)}:null,filePath:t,relativePath:o,controllerIsDefaultExport:r.isDefault,mountedPath:S})}}return a}function Li(e,t,n){let r=[],i=q(t,n);ci.lastIndex=0;let a;for(;(a=ci.exec(e))!==null;)r.push({name:a[1],filePath:t,relativePath:i});return r}function Ri(e,t){let n=1;for(let r=t+1;r<e.length;r++){let t=e[r];if(t===`{`)n++;else if(t===`}`&&(n--,n===0))return r}return-1}function zi(e,t,n){let r=[],i=q(t,n),a=new Set;li.lastIndex=0;let o;for(;(o=li.exec(e))!==null;){let n=o[1],s=li.lastIndex-1,c=hi(e,s);if(c<0)continue;let l=e.slice(s+1,c),u=/\bname\s*:\s*['"`]([^'"`]+)['"`]/.exec(l);if(!u)continue;let d=u[1],f=`${n}::${d}::${t}`;a.has(f)||(a.add(f),r.push({kind:n===`definePlugin`?`plugin`:`adapter`,name:d,filePath:t,relativePath:i}))}di.lastIndex=0;let s;for(;(s=di.exec(e))!==null;){let n=s.index,o=e.indexOf(`{`,n);if(o<0)continue;let c=Ri(e,o);if(c<0)continue;let l=e.slice(o+1,c),u=fi.exec(l);if(!u)continue;let d=u[1],f=`class::${d}::${t}`;a.has(f)||(a.add(f),r.push({kind:`adapter`,name:d,filePath:t,relativePath:i}))}return r}function Bi(e,t,n){let r=[],i=q(t,n),a=new Set;for(ui.lastIndex=0;ui.exec(e)!==null;){let n=ui.lastIndex-1,o=hi(e,n);if(o<0)continue;let s=e.slice(n+1,o),c=/\bkey\s*:\s*['"`]([^'"`]+)['"`]/.exec(s);if(!c)continue;let l=c[1];a.has(l)||(a.add(l),r.push({key:l,filePath:t,relativePath:i}))}return r}function Vi(e,t,n){let r=[],i=q(t,n);pi.lastIndex=0;let a;for(;(a=pi.exec(e))!==null;){let n=a[1],o=null,s=null;if(a[2]){let t=e.indexOf(`{`,a.index+a[0].length-1);if(t>=0){let n=Ri(e,t);if(n>=0){let r=e.slice(t+1,n);o=Hi(r,`description`),s=Hi(r,`example`)}}}r.push({name:n,description:o,example:s,filePath:t,relativePath:i})}return r}function Hi(e,t){let n=RegExp(`\\b${t}\\s*:\\s*(['"\`])`,`g`).exec(e);if(!n)return null;let r=n[1],i=n.index+n[0].length,a=i,o=null;for(;a<e.length;){let t=e[a];if(t===`\\`){a+=2;continue}if(t===r){o=e.slice(i,a);break}a++}return o===null?null:o.replace(/\\(.)/g,(e,t)=>t===`n`?`
|
|
2398
|
+
`:t===`t`?` `:t===`r`?`\r`:t)}const Ui=[`src/config/index.ts`,`src/config/env.ts`,`src/config.ts`,`src/env.ts`];async function Wi(e,t){let n=t===`src/env.ts`?Ui:[t];for(let t of n){let n=v(e,t),r;try{r=await w(n,`utf-8`)}catch{continue}if(!(!/\bdefineEnv\s*\(/.test(r)&&!/\bfrom(Zod|Valibot|Yup)\s*\(/.test(r))&&/export\s+default\b/.test(r)&&!/export\s+default\s+loadEnvFromSchema\s*\(/.test(r))return{filePath:n,relativePath:q(n,e)}}return null}function Gi(e){let t=new Map;for(let n of e){let e=t.get(n.className)??[];e.push(n),t.set(n.className,e)}let n=[];for(let[e,r]of t)new Set(r.map(e=>e.filePath)).size>1&&n.push({className:e,classes:r});return n.sort((e,t)=>e.className.localeCompare(t.className)),n}function Ki(e,t,n){return Qr(e,t,n)||qi(e,t,n)}function qi(e,t,n){let r=Pi(e,t,n);return{classes:r,tokens:Fi(e,t,n),injects:Li(e,t,n),pluginsAndAdapters:zi(e,t,n),augmentations:Vi(e,t,n),contextKeys:Bi(e,t,n),routes:Ii(e,t,n,r,new Map),moduleMounts:Ei(e),globPatterns:/\.module\.[mc]?[tj]sx?$/.test(t)?Ci(e):[]}}async function Ji(e,t,n){let r=n?await Ir.signature(e):null;if(n&&r){let t=n.get(e,r);if(t)return n.set(e,r,t),t}let i;try{i=await w(e,`utf-8`)}catch{return null}let a=Ki(i,e,t);return n&&r&&n.set(e,r,a),a}async function Yi(e,t,n){let r=[],i=0,a=Array.from({length:Math.min(t,e.length)},async()=>{for(;;){let t=i++;if(t>=e.length)return;r[t]=await n(e[t],t)}});return await Promise.all(a),r}async function Xi(e){let t=(await Ni(v(e.root),e)).toSorted(),n=e.cacheDir?await Ir.load(e.cacheDir):null,r=$i(t,await Yi(t,16,t=>Ji(t,e.cwd,n))),i=await Wi(e.cwd,e.envFile??`src/env.ts`);return n&&await n.save(),{...r,env:i}}function Zi(e,t,n){let r=n.extensions??ti,i=n.exclude??ni;if(!e.startsWith(t+y)&&e!==t||!r.some(t=>e.endsWith(t)))return!1;let a=_(n.cwd,e);return!i.some(e=>a.includes(e))}async function Qi(e,t){if(!e.cacheDir)return Xi(e);let n=v(e.root),r=await Ir.load(e.cacheDir),i=r.cachedFiles();if(i.length===0)return Xi(e);let a=new Set(t.removed.map(t=>v(e.cwd,t))),o=t.changed.map(t=>v(e.cwd,t)).filter(t=>!a.has(t)&&Zi(t,n,e)),s=new Set(o),c=new Set(i);for(let e of s)c.add(e);for(let e of a)c.delete(e);let l=new Map;await Yi(o,16,async t=>{if(!c.has(t))return;let n=await Ir.signature(t),i;try{i=await w(t,`utf-8`)}catch{c.delete(t);return}let a=Ki(i,t,e.cwd);l.set(t,a),n&&r.set(t,n,a)});let u=[...c].toSorted(),d=$i(u,u.map(e=>l.get(e)||(r.carry(e),r.peek(e)))),f=await Wi(e.cwd,e.envFile??`src/env.ts`);return await r.save(),{...d,env:f}}function $i(e,t){let n=[],r=[],i=[],a=[],o=[],s=[],c=[],l=new Map;for(let e of t)if(e)for(let{controller:t,mountPath:n}of e.moduleMounts)l.has(t)||l.set(t,n);let u=new Map;for(let d=0;d<e.length;d++){let f=t[d];if(f){n.push(...f.classes),i.push(...f.tokens),a.push(...f.injects),o.push(...f.pluginsAndAdapters),s.push(...f.augmentations),c.push(...f.contextKeys),f.globPatterns.length>0&&u.set(e[d],f.globPatterns);for(let e of f.routes){let t=l.get(e.controller);if(t){let n=vi(t,e.path);r.push({...e,pathParams:_i(n),mountedPath:n})}else r.push({...e,mountedPath:e.mountedPath??e.path})}}}let d=[];for(let[e,t]of u){if(!/\.module\.[mc]?[tj]sx?$/.test(e)||t.length===0)continue;let r=e.replaceAll(y,`/`),i=r.slice(0,r.lastIndexOf(`/`));for(let a of n){if(a.decorator===`Module`)continue;let n=a.filePath.replaceAll(y,`/`);n.startsWith(i+`/`)&&n!==r&&(Ti(n.slice(i.length+1),t)||d.push({className:a.className,filePath:a.filePath,relativePath:a.relativePath,moduleFilePath:e,decorator:a.decorator}))}}n.sort((e,t)=>e.className===t.className?e.relativePath.localeCompare(t.relativePath):e.className.localeCompare(t.className)),i.sort((e,t)=>e.name.localeCompare(t.name)||e.relativePath.localeCompare(t.relativePath)),a.sort((e,t)=>e.name.localeCompare(t.name)||e.relativePath.localeCompare(t.relativePath)),r.sort((e,t)=>e.controller.localeCompare(t.controller)||e.method.localeCompare(t.method)),o.sort((e,t)=>e.name.localeCompare(t.name)||e.relativePath.localeCompare(t.relativePath)),s.sort((e,t)=>e.name.localeCompare(t.name)||e.relativePath.localeCompare(t.relativePath)),c.sort((e,t)=>e.key.localeCompare(t.key)||e.relativePath.localeCompare(t.relativePath));let f=Gi(n);return d.sort((e,t)=>e.relativePath.localeCompare(t.relativePath)||e.className.localeCompare(t.className)),{classes:n,routes:r,tokens:i,injects:a,collisions:f,pluginsAndAdapters:o,augmentations:s,contextKeys:c,orphanedClasses:d}}function ea(e){let t=e.lastIndexOf(`.`);return t<=0?{stem:e,ext:``}:{stem:e.slice(0,t),ext:e.slice(t+1)}}function ta(e){let t=e.replaceAll(`\\`,`/`),{stem:n,ext:r}=ea(t.slice(t.lastIndexOf(`/`)+1)),i=r||`ts`,a=n.lastIndexOf(`.`);return a>0?`./**/*.${n.slice(a+1)}.${i}`:`./**/*.${i}`}function na(e){let t=new Set;for(let n of e)t.add(ta(n.relativePath));return[...t].toSorted()}function ra(e,t){let n=0,r=null;for(let i=t;i<e.length;i++){let t=e[i];if(r){if(t===`\\`){i++;continue}t===r&&(r=null);continue}if(t===`'`||t===`"`||t==="`")r=t;else if(t===`(`)n++;else if(t===`)`&&(n--,n===0))return i}return-1}function ia(e,t,n,r){let i=null;for(let a=n;a<r;a++){let n=e[a];if(i){if(n===`\\`){a++;continue}n===i&&(i=null);continue}if(n===`'`||n===`"`||n==="`")i=n;else if(n===t)return a}return-1}function aa(e,t){let n=0,r=null;for(let i=t;i<e.length;i++){let t=e[i];if(r){if(t===`\\`){i++;continue}t===r&&(r=null);continue}if(t===`'`||t===`"`||t==="`")r=t;else if(t===`[`)n++;else if(t===`]`&&(n--,n===0))return i}return-1}function oa(e){let t=/\bimport\.meta\.glob\s*\(/g,n=[],r;for(;(r=t.exec(e))!==null;){let t=e.indexOf(`(`,r.index);if(t<0)continue;let i=ra(e,t);i<0||n.push({start:r.index,open:t,close:i})}return n}function sa(e,t){let n=oa(e);if(n.length===0)return null;let r=n.find(t=>/\beager\s*:\s*true\b/.test(e.slice(t.open,t.close+1)))??n[0],i=e.slice(r.start,r.close+1),a=new Set(Ci(i).map(e=>e.startsWith(`!`)?e.slice(1):e)),o=t.filter(e=>!a.has(e));if(o.length===0)return null;let s=o.map(e=>`'${e}'`).join(`, `),c=ia(e,`[`,r.open,r.close);if(c>=0){let t=aa(e,c);if(t<0||t>r.close)return null;let n=e.slice(0,t);return n+(/[[,]\s*$/.test(n)?``:`, `)+s+e.slice(t)}let l=/(['"`])((?:\\.|(?!\1).)*)\1/,u=e.slice(r.open+1,r.close),d=l.exec(u);if(!d)return null;let f=r.open+1+d.index,p=f+d[0].length;return e.slice(0,f)+`[${d[0]}, ${s}]`+e.slice(p)}const J="/* 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",ca=new Set([`Service`,`Repository`,`Injectable`,`Component`]);var la=class extends Error{collisions;constructor(e){super(ua(e)),this.name=`TokenCollisionError`,this.collisions=e}};function ua(e){let t=[`kick typegen: token collision detected`];for(let n of e){t.push(``),t.push(` ${n.classes.length} classes named '${n.className}':`);for(let e of n.classes)t.push(` - ${e.relativePath}`)}return t.push(``),t.push(`Resolutions:`),t.push(` (a) Rename one of the classes`),t.push(` (b) Use createToken<T>('namespaced/Name') and import the token explicitly — see @forinda/kickjs`),t.push(` (c) Pass --allow-duplicates to namespace the registry keys automatically`),t.push(` (e.g. 'modules/users/UserService' instead of 'UserService')`),t.join(`
|
|
2399
|
+
`)}function da(e,t){let n=_(f(t),e).split(y).join(`/`);return n=n.replace(/\.(ts|tsx|mts|cts)$/i,``),n.startsWith(`.`)||(n=`./`+n),n}function fa(e){let t=e.relativePath.replace(/^src\//,``).replace(/\.(ts|tsx|mts|cts)$/i,``).split(`/`);t.pop();let n=t.join(`/`);return n?`${n}/${e.className}`:e.className}function pa(e,t,n){let r=new Set,i=[];for(let a of e){if(!ca.has(a.decorator))continue;let e=n.has(a.className)?fa(a):a.className;if(r.has(e))continue;r.add(e);let o=da(a.filePath,t),s=a.isDefault?`import('${o}').default`:`import('${o}').${a.className}`;i.push(` '${e}': ${s}`)}let a=i.length?i.join(`
|
|
2400
|
+
`):" // (no services discovered yet — run `kick g service <name>` to add one)";return`${J}
|
|
2396
2401
|
declare module '@forinda/kickjs' {
|
|
2397
2402
|
interface KickJsRegistry {
|
|
2398
|
-
${
|
|
2399
|
-
`):" // (no services discovered yet — run `kick g service <name>` to add one)"}
|
|
2403
|
+
${a}
|
|
2400
2404
|
}
|
|
2401
2405
|
}
|
|
2402
2406
|
|
|
2403
2407
|
export {}
|
|
2404
|
-
`}function ma(e){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(e)}function ha(e){
|
|
2408
|
+
`}function ma(e){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(e)}function ha(e){let t=[...new Set(e.map(e=>e.key))].toSorted().map(e=>` ${ma(e)?e:JSON.stringify(e)}: true`).join(`
|
|
2409
|
+
`);return`${J}
|
|
2405
2410
|
declare module '@forinda/kickjs' {
|
|
2406
2411
|
/**
|
|
2407
2412
|
* Key-only registry of every context key produced by a
|
|
@@ -2410,20 +2415,20 @@ declare module '@forinda/kickjs' {
|
|
|
2410
2415
|
* \`ContextMeta\`; this only records that the key exists.
|
|
2411
2416
|
*/
|
|
2412
2417
|
interface ContextKeys {
|
|
2413
|
-
${
|
|
2414
|
-
`)}
|
|
2418
|
+
${t}
|
|
2415
2419
|
}
|
|
2416
2420
|
}
|
|
2417
2421
|
|
|
2418
2422
|
export {}
|
|
2419
|
-
`}function ga(e,t,n){
|
|
2423
|
+
`}function ga(e,t,n){if(t.length===0)return`${J}
|
|
2420
2424
|
// ${n}
|
|
2421
2425
|
export type ${e} = never
|
|
2422
|
-
|
|
2426
|
+
`;let r=[...new Set(t)].toSorted();return`${J}
|
|
2423
2427
|
export type ${e} =
|
|
2424
|
-
${
|
|
2428
|
+
${r.map(e=>` | '${e}'`).join(`
|
|
2425
2429
|
`)}
|
|
2426
|
-
`}function _a(e,t,n,r){return[...e.filter(e=>ca.has(e.decorator)).map(e=>r.has(e.className)?fa(e):e.className),...t.map(e=>e.name),...n.map(e=>e.name)]}function va(e){return e.filter(e=>e.decorator===`Module`).map(e=>e.className)}function ya(e){let t=new Map;for(let n of e)t.has(n.name)||t.set(n.name,n);
|
|
2430
|
+
`}function _a(e,t,n,r){return[...e.filter(e=>ca.has(e.decorator)).map(e=>r.has(e.className)?fa(e):e.className),...t.map(e=>e.name),...n.map(e=>e.name)]}function va(e){return e.filter(e=>e.decorator===`Module`).map(e=>e.className)}function ya(e){let t=new Map;for(let n of e)t.has(n.name)||t.set(n.name,n);let n=[...t.values()].toSorted((e,t)=>e.name.localeCompare(t.name)).map(e=>` '${e.name}': '${e.kind}'`).join(`
|
|
2431
|
+
`);return`${J}
|
|
2427
2432
|
declare module '@forinda/kickjs' {
|
|
2428
2433
|
/**
|
|
2429
2434
|
* Map of every plugin/adapter \`name\` discovered in the project. The
|
|
@@ -2432,8 +2437,7 @@ declare module '@forinda/kickjs' {
|
|
|
2432
2437
|
* become compile errors instead of boot-time \`MissingMountDepError\`.
|
|
2433
2438
|
*/
|
|
2434
2439
|
interface KickJsPluginRegistry {
|
|
2435
|
-
${
|
|
2436
|
-
`)||" // (no plugins/adapters discovered yet — `defineAdapter`/`definePlugin` calls feed this)"}
|
|
2440
|
+
${n||" // (no plugins/adapters discovered yet — `defineAdapter`/`definePlugin` calls feed this)"}
|
|
2437
2441
|
}
|
|
2438
2442
|
}
|
|
2439
2443
|
|
|
@@ -2462,7 +2466,7 @@ export {}
|
|
|
2462
2466
|
${n.join(`
|
|
2463
2467
|
|
|
2464
2468
|
`)}
|
|
2465
|
-
`}const xa=/^(kick\/)?([a-z][\w-]*\/[A-Z]\w*)(\/.+)?(:[a-z][\w-]+(:[a-z][\w-]+)*)?$/;function Sa(e){let t=[];for(let n of e){let e=n.name;e.startsWith(`kickjs.`)||xa.test(e)||t.push({token:e,variable:n.variable,filePath:n.relativePath,reason:"does not match `<scope>/<PascalKey>[/<suffix>][:<instance>]`",suggestion:Ca(e)})}return t}function Ca(e){if(/^[A-Z]\w*$/.test(e))return`'<scope>/${e}' (e.g. 'mycorp/${e}')`;if(e.includes(`.`))return`consider '<scope>/PascalKey' instead of dotted form`;let t=/^([a-z][\w-]*)\/([a-z]\w*)$/.exec(e);if(t){let[,e,n]=t;return`'${e}/${n.charAt(0).toUpperCase()}${n.slice(1)}'`}}function wa(e,t){if(!e)return{entries:[],count:0};let n=new Map;for(let[r,i]of Object.entries(e)){if(!i||typeof i.src!=`string`)continue;let e=v(t,i.src);if(!ka(e))continue;let a=
|
|
2469
|
+
`}const xa=/^(kick\/)?([a-z][\w-]*\/[A-Z]\w*)(\/.+)?(:[a-z][\w-]+(:[a-z][\w-]+)*)?$/;function Sa(e){let t=[];for(let n of e){let e=n.name;e.startsWith(`kickjs.`)||xa.test(e)||t.push({token:e,variable:n.variable,filePath:n.relativePath,reason:"does not match `<scope>/<PascalKey>[/<suffix>][:<instance>]`",suggestion:Ca(e)})}return t}function Ca(e){if(/^[A-Z]\w*$/.test(e))return`'<scope>/${e}' (e.g. 'mycorp/${e}')`;if(e.includes(`.`))return`consider '<scope>/PascalKey' instead of dotted form`;let t=/^([a-z][\w-]*)\/([a-z]\w*)$/.exec(e);if(t){let[,e,n]=t;return`'${e}/${n.charAt(0).toUpperCase()}${n.slice(1)}'`}}function wa(e,t){if(!e)return{entries:[],count:0};let n=new Map;for(let[r,i]of Object.entries(e)){if(!i||typeof i.src!=`string`)continue;let e=v(t,i.src);if(!ka(e))continue;let a=me(i.glob??`**/*`,{cwd:e,nodir:!0,dot:!1,posix:!0});a.sort();let{pairs:o}=he(r,a,{strategy:i.keys??`auto`});for(let{key:e}of o){let t=e.slice(r.length+1);n.set(e,{namespace:r,key:t})}}return{entries:[...n.values()],count:n.size}}function Ta(e){let t="/* eslint-disable */\n// AUTO-GENERATED by `kick typegen`. DO NOT EDIT.\n// Re-run with `kick typegen` or rely on `kick dev` to refresh.\n";if(e.entries.length===0)return`${t}
|
|
2466
2470
|
declare module '@forinda/kickjs' {
|
|
2467
2471
|
/**
|
|
2468
2472
|
* Map of every typed asset discovered in the project's assetMap.
|
|
@@ -2488,40 +2492,40 @@ ${Da(n,` `)}
|
|
|
2488
2492
|
|
|
2489
2493
|
export {}
|
|
2490
2494
|
`}const Ea=Symbol(`asset-leaf`);function Da(e,t){let n=Object.keys(e).toSorted(),r=[];for(let i of n){let n=e[i],a=Oa(i)?i:JSON.stringify(i);n===Ea?r.push(`${t}${a}: () => string`):(r.push(`${t}${a}: {`),r.push(Da(n,`${t} `)),r.push(`${t}}`))}return r.join(`
|
|
2491
|
-
`)}function Oa(e){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(e)}function ka(e){try{return c(e).isDirectory()}catch{return!1}}var Aa=
|
|
2495
|
+
`)}function Oa(e){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(e)}function ka(e){try{return c(e).isDirectory()}catch{return!1}}var Aa=k({runTypegen:()=>Ma,sweepStaleTypegen:()=>La,watchTypegen:()=>Ia,writeTypegenArtifacts:()=>Fa});function ja(e){let t=e.cwd??process.cwd();return{cwd:t,srcDir:v(t,e.srcDir??`src`),outDir:v(t,e.outDir??`.kickjs/types`),silent:e.silent??!1,allowDuplicates:e.allowDuplicates??!1,schemaValidator:e.schemaValidator??!1,envFile:e.envFile??`src/env.ts`}}async function Ma(e={}){let{cwd:t,srcDir:n,outDir:r,silent:i,allowDuplicates:a,envFile:o}=ja(e),s=Date.now(),c={root:n,cwd:t,cacheDir:e.noCache?void 0:v(t,`.kickjs`,`cache`),envFile:o===!1?void 0:o},l=e.changedFiles?await Qi(c,e.changedFiles):await Xi(c);if(l.collisions.length>0&&!a)throw new la(l.collisions);let u=wa(e.assetMap,t),d=[],f=[];if(e.runPlugins!==!1){try{let{runAllPluginTypegens:n}=await Promise.resolve().then(()=>Xa),{loadKickConfig:r}=await Promise.resolve().then(()=>we);d=await n({cwd:t,config:await r(t),silent:!0,changedFiles:e.changedFiles})}catch(e){if(!i){let t=e instanceof Error?e.message:String(e);console.warn(` kick typegen: plugin pipeline failed (${t}) — continuing`)}}f.push(...await Fa(r,d,i))}let p=Sa(l.tokens),m=Pa(l,u.count,f),h=Date.now()-s;if(!i){let e=r.replace(t+`/`,``),n=m.resolvedCollisions>0?`, ${m.resolvedCollisions} collisions namespaced`:``,i=m.envWritten?`, env typed`:``,a=m.pluginEntries>0?`, ${m.pluginEntries} plugins/adapters`:``,o=m.augmentationEntries>0?`, ${m.augmentationEntries} augmentations`:``,s=m.assetEntries>0?`, ${m.assetEntries} assets`:``;if(console.log(` kick typegen → ${m.serviceTokens} services, ${m.routeEntries} routes, ${m.moduleTokens} modules${a}${o}${s}${i}${n} → ${e} (${h}ms)`),p.length>0){console.warn(` kick typegen: ${p.length} token(s) don't match the §22.2 convention:`);for(let e of p){let t=e.variable?` [${e.variable}]`:``;console.warn(` '${e.token}' (${e.filePath})${t} — ${e.reason}`),e.suggestion&&console.warn(` → suggestion: ${e.suggestion}`)}}}return l.orphanedClasses.length>0&&await Na(l.orphanedClasses,{fix:e.fix??!1,silent:i}),{scan:l,result:m,tokenWarnings:p}}async function Na(e,{fix:t,silent:n}){let r=new Map;for(let t of e){let e=r.get(t.moduleFilePath)??[];e.push(t),r.set(t.moduleFilePath,e)}if(t){let e=0,t=[];for(let[i,a]of r){let r=na(a);try{let a=await w(i,`utf-8`),o=sa(a,r);o&&o!==a?(await T(i,o),e++,n||console.log(` kick typegen --fix: patched ${i}\n + ${r.join(`, `)}`)):t.push(i)}catch{t.push(i)}}if(!n&&(e>0&&console.log(` kick typegen --fix: updated ${e} module glob(s) — re-run typegen to pick up the now-loaded classes.`),t.length>0)){console.warn(` kick typegen --fix: could not auto-patch ${t.length} module(s) (no import.meta.glob() call found) — add the patterns by hand:`);for(let e of t){let t=r.get(e)??[];console.warn(` ${e}: ${na(t).join(`, `)}`)}}return}if(!n){console.warn(` kick typegen: ${e.length} decorated class(es) not matched by any module's import.meta.glob():`);for(let[e,t]of r){for(let e of t)console.warn(` @${e.decorator} ${e.className} (${e.relativePath})`);let n=na(t);console.warn(` → add to import.meta.glob([...]) in ${e}:`),console.warn(` ${n.map(e=>`'${e}'`).join(`, `)}`)}console.warn(" → or run `kick typegen --fix` to apply these automatically.")}}function Pa(e,t,n){let r=new Set(e.collisions.map(e=>e.className)),i=e.classes.filter(e=>ca.has(e.decorator)),a=_a(e.classes,e.tokens,e.injects,r);return{registryEntries:i.length,serviceTokens:new Set(a).size,moduleTokens:va(e.classes).length,routeEntries:e.routes.length,pluginEntries:new Set(e.pluginsAndAdapters.map(e=>e.name)).size,augmentationEntries:new Set(e.augmentations.map(e=>e.name)).size,assetEntries:t,envWritten:e.env!==null,written:n,resolvedCollisions:e.collisions.length}}async function Fa(e,t,n){await C(e,{recursive:!0}),await T(h(f(e),`.gitignore`),`# Auto-generated by kick typegen
|
|
2492
2496
|
*
|
|
2493
|
-
`,`utf-8`);let r=t.filter(e=>e.outFile).map(e=>e.outFile);return await La(e,r,t,n),r}async function Ia(e={}){let t=ja(e),{srcDir:n,silent:r,cwd:i}=t,a={...t,allowDuplicates:!0,runPlugins:!1,noCache:e.noCache},o=process.env.KICKJS_WATCH_POLLING===`1`||process.env.KICKJS_WATCH_POLLING===`true`,[{runAllPluginTypegens:s},{loadKickConfig:c}]=await Promise.all([Promise.resolve().then(()=>Xa),Promise.resolve().then(()=>
|
|
2497
|
+
`,`utf-8`);let r=t.filter(e=>e.outFile).map(e=>e.outFile);return await La(e,r,t,n),r}async function Ia(e={}){let t=ja(e),{srcDir:n,silent:r,cwd:i}=t,a={...t,allowDuplicates:!0,runPlugins:!1,noCache:e.noCache},o=process.env.KICKJS_WATCH_POLLING===`1`||process.env.KICKJS_WATCH_POLLING===`true`,[{runAllPluginTypegens:s},{loadKickConfig:c}]=await Promise.all([Promise.resolve().then(()=>Xa),Promise.resolve().then(()=>we)]),l=await c(i),u=async()=>{try{await Ma({...a})}catch(e){if(r)return;if(e instanceof la)console.error(`
|
|
2494
2498
|
`+e.message+`
|
|
2495
|
-
`);else{let t=e instanceof Error?e.message:String(e);console.error(` kick typegen failed: ${t}`)}}},d=async()=>{try{let e=await s({cwd:i,config:l,silent:!0});await Fa(t.outDir,e,!0)}catch{}};await u(),await d();let{watch:f}=await import(`node:fs`),p=null,m=e=>{e&&/\.(ts|tsx|mts|cts)$/.test(e)&&(e.includes(`.kickjs`)||e.endsWith(`.d.ts`)||(p&&clearTimeout(p),p=setTimeout(()=>{u().then(d)},100)))};if(o){r||console.log(` kick typegen: polling mode (KICKJS_WATCH_POLLING)`);let e=setInterval(()=>{u().then(d)},2e3);return()=>clearInterval(e)}let h;try{h=f(n,{recursive:!0},(e,t)=>{m(t)})}catch(e){r||console.warn(` kick typegen: watch mode unavailable (${e?.message??e}). Falling back to polling.`);let t=setInterval(()=>{u().then(d)},2e3);return()=>clearInterval(t)}return()=>{p&&clearTimeout(p),h.close()}}async function La(e,t,n,r){let i=new Set;for(let e of t)i.add(d(e));for(let e of n)e.outFile&&i.add(d(e.outFile));let a;try{a=await
|
|
2496
|
-
(dry run — no files were written)`),console.log()}async function Ba(e){if(!e)try{let e=await
|
|
2499
|
+
`);else{let t=e instanceof Error?e.message:String(e);console.error(` kick typegen failed: ${t}`)}}},d=async()=>{try{let e=await s({cwd:i,config:l,silent:!0});await Fa(t.outDir,e,!0)}catch{}};await u(),await d();let{watch:f}=await import(`node:fs`),p=null,m=e=>{e&&/\.(ts|tsx|mts|cts)$/.test(e)&&(e.includes(`.kickjs`)||e.endsWith(`.d.ts`)||(p&&clearTimeout(p),p=setTimeout(()=>{u().then(d)},100)))};if(o){r||console.log(` kick typegen: polling mode (KICKJS_WATCH_POLLING)`);let e=setInterval(()=>{u().then(d)},2e3);return()=>clearInterval(e)}let h;try{h=f(n,{recursive:!0},(e,t)=>{m(t)})}catch(e){r||console.warn(` kick typegen: watch mode unavailable (${e?.message??e}). Falling back to polling.`);let t=setInterval(()=>{u().then(d)},2e3);return()=>clearInterval(t)}return()=>{p&&clearTimeout(p),h.close()}}async function La(e,t,n,r){let i=new Set;for(let e of t)i.add(d(e));for(let e of n)e.outFile&&i.add(d(e.outFile));let a;try{a=await oe(e)}catch{return[]}let o=[];for(let t of a){if(!Ra.has(t)||i.has(t))continue;let n=v(e,t);try{if(!(await ce(n)).isFile())continue;await le(n),o.push(t)}catch{}}return o.length>0&&!r&&console.log(` kick typegen: swept ${o.length} stale file(s): ${o.join(`, `)}`),o}const Ra=new Set([`assets.d.ts`,`env.ts`,`routes.ts`,`registry.d.ts`,`services.d.ts`,`modules.d.ts`,`plugins.d.ts`,`augmentations.d.ts`,`index.d.ts`]),za=[`agents`,`claude`,`skills`,`gemini`,`copilot`,`both`,`all`];function Y(e){return e.parent?.opts()?.dryRun??!1}function X(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(`
|
|
2500
|
+
(dry run — no files were written)`),console.log()}async function Ba(e){if(!e)try{let e=await j(process.cwd());await Ma({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 Va=[{name:`module <name>`,description:`REST module (controller, service, DTOs, 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:`contributor <name>`,description:`Context contributor [--type http|bare] [--params a:string] [-m]`},{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`}],Ha=new Set(Va.map(e=>e.name.split(` `)[0]));async function Ua(){console.log(`
|
|
2497
2501
|
Built-in generators:
|
|
2498
|
-
`);let e=Math.max(...Va.map(e=>e.name.length));for(let t of Va)console.log(` kick g ${t.name.padEnd(e+2)} ${t.description}`);let t=await
|
|
2502
|
+
`);let e=Math.max(...Va.map(e=>e.name.length));for(let t of Va)console.log(` kick g ${t.name.padEnd(e+2)} ${t.description}`);let t=await j(process.cwd()),n=Ie(t?.plugins??[],t?.commands??[]),r=await hn(process.cwd(),n.generators);if(r.generators.length>0){console.log(`
|
|
2499
2503
|
Plugin generators:
|
|
2500
2504
|
`);let e=Math.max(...r.generators.map(e=>`${e.spec.name} <name>`.length));for(let{source:t,spec:n}of r.generators){let r=`${n.name} <name>`;console.log(` kick g ${r.padEnd(e+2)} ${n.description} [${t}]`)}}if(r.failed.length>0){console.log(`
|
|
2501
2505
|
Failed to load:
|
|
2502
|
-
`);for(let{source:e,reason:t}of r.failed)console.log(` ${e} — ${t}`)}console.log()}async function Wa(e,t,n){let r=await
|
|
2503
|
-
Use -m to scope it to a module: kick g middleware auth -m users`).option(`-o, --out <dir>`,`Output directory (overrides --module)`).option(`-m, --module <module>`,`Place inside a module folder`).action(async(e,t,n)=>{let r=Y(n);
|
|
2504
|
-
Use -m to scope it to a module: kick g guard admin -m users`).option(`-o, --out <dir>`,`Output directory (overrides --module)`).option(`-m, --module <module>`,`Place inside a module folder`).action(async(e,t,n)=>{let r=Y(n);
|
|
2506
|
+
`);for(let{source:e,reason:t}of r.failed)console.log(` ${e} — ${t}`)}console.log()}async function Wa(e,t,n){let r=await j(process.cwd()),i=A(r),a=t.modulesDir??i.dir??`src/modules`,o=t.repo??Ln(i.repo);t.repo&&Oe(t.repo);let s=t.pattern??r?.pattern??`rest`,c=t.pluralize===!1?!1:i.pluralize??!0,l=Ae(r,process.cwd()),u=i.style??`define`;if(!n&&u===`define`){let e=await Tr(v(a),`define`);if(e.length>0){console.error(`\n ${O.red(`Error:`)} ${e.length} module file(s) still use the legacy \`class … implements AppModule\` shape.\n ${O.dim(`Project setting:`)} modules.style: 'define' (default)\n\n ${O.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 ${O.bold(`Pick one:`)}\n 1. Migrate everything to defineModule:\n ${O.dim(`$`)} kick codemod modules --experimental --apply\n 2. Keep the class form — pin it in kick.config.ts:\n ${O.dim(`// kick.config.ts`)}\n ${O.dim(`export default defineConfig({ modules: { style: 'class' } })`)}\n`),process.exit(1)}}let d=[];for(let r of e){let e=await Rn({name:r,modulesDir:v(a),noEntity:t.entity===!1,noTests:t.tests===!1,repo:o,minimal:t.minimal,force:t.force,pattern:s,dryRun:n,pluralize:c,prismaClientPath:i.prismaClientPath,tokenScope:l,style:i.style});d.push(...e)}X(d,n),await Ba(n)}function Ga(e,t){let n=e.command(`generate [names...]`).alias(`g`).description("Generate code scaffolds — bare form `kick g <name>` is shorthand for `kick g module <name>`").option(`--list`,`List all available generators`).option(`--dry-run`,`Preview files that would be generated without writing them`).option(`--no-entity`,`Skip entity and value object generation (module shortcut)`).option(`--no-tests`,`Skip test file generation (module shortcut)`).option(`--repo <type>`,`Repository name: inmemory (default) or any DB name (e.g. postgres)`).option(`--pattern <pattern>`,`Override project pattern: rest | minimal`).option(`--minimal`,`Shorthand for --pattern minimal`).option(`--modules-dir <dir>`,`Modules directory`).option(`--no-pluralize`,`Use singular names (skip auto-pluralization)`).option(`-f, --force`,`Overwrite existing files without prompting`).action(async(e,r,i)=>{if(r.list){await Ua();return}if(!e||e.length===0){n.help();return}let a=Y(i);M(a);let[o,s,...c]=e;if(o){let e=await j(process.cwd()),n=Ie(e?.plugins??[],e?.commands??[]),i=await mn({generatorName:o,itemName:s??``,args:c,flags:r,cwd:process.cwd(),projectRoot:t?.projectRoot},n.generators);if(i){X(i.files,a);return}if(o!==`module`&&Ha.has(o)){console.error(`\n '${o}' is a generator, not a module name.`),console.error(` Did you mean: kick g ${o} ${s??`<name>`}`),console.error(` If that errors, your @forinda/kickjs-cli is older than the '${o}' generator — upgrade it.\n`),process.exitCode=1;return}}await Wa(e,r,a)});n.command(`module <names...>`).description(`Generate one or more modules (e.g. kick g module user task project)`).option(`--no-entity`,`Skip entity and value object generation`).option(`--no-tests`,`Skip test file generation`).option(`--repo <type>`,`Repository name: inmemory (default) or any DB name (e.g. postgres)`).option(`--pattern <pattern>`,`Override project pattern: rest | 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=Y(n);M(r),await Wa(e,{...n.optsWithGlobals(),...t},r)}),n.command(`adapter <name>`).description(`Generate an AppAdapter with lifecycle hooks and middleware support`).option(`-o, --out <dir>`,`Output directory`,`src/adapters`).action(async(e,t,n)=>{let r=Y(n);M(r),X(await Kn({name:e,outDir:v(t.out)}),r)}),n.command(`plugin <name>`).description(`Generate a KickPlugin with DI, modules, adapters, middleware, and lifecycle hooks`).option(`-o, --out <dir>`,`Output directory`,`src/plugins`).action(async(e,t,n)=>{let r=Y(n);M(r),X(await qn({name:e,outDir:v(t.out)}),r)}),n.command(`middleware <name>`).description(`Generate an Express middleware function
|
|
2507
|
+
Use -m to scope it to a module: kick g middleware auth -m users`).option(`-o, --out <dir>`,`Output directory (overrides --module)`).option(`-m, --module <module>`,`Place inside a module folder`).action(async(e,t,n)=>{let r=Y(n);M(r);let i=await j(process.cwd()),a=A(i),o=a.dir??`src/modules`;X(await Xn({name:e,outDir:t.out,moduleName:t.module,modulesDir:o,pattern:i?.pattern,pluralize:a.pluralize??!0}),r)}),n.command(`guard <name>`).description(`Generate a route guard (auth, roles, etc.)
|
|
2508
|
+
Use -m to scope it to a module: kick g guard admin -m users`).option(`-o, --out <dir>`,`Output directory (overrides --module)`).option(`-m, --module <module>`,`Place inside a module folder`).action(async(e,t,n)=>{let r=Y(n);M(r);let i=await j(process.cwd()),a=A(i),o=a.dir??`src/modules`;X(await Zn({name:e,outDir:t.out,moduleName:t.module,modulesDir:o,pattern:i?.pattern,pluralize:a.pluralize??!0}),r)}),n.command(`contributor <name>`).description(`Generate a Context Contributor (typed alternative to @Middleware for ctx.set)
|
|
2505
2509
|
--type http (default, RequestContext) | bare (ExecutionContext)
|
|
2506
2510
|
--params "source:string,region:number" → emits the withParams<T>() form
|
|
2507
|
-
Use -m to scope it to a module: kick g contributor tenant -m users`).option(`-o, --out <dir>`,`Output directory (overrides --module)`).option(`-m, --module <module>`,`Place inside a module folder`).option(`-t, --type <type>`,`Contributor flavour: http | bare`,`http`).option(`-k, --key <key>`,`Context key it writes (defaults to camelCase of name)`).option(`--params <fields>`,`Per-call params, e.g. "source:string,region:number"`).action(async(e,t,n)=>{let r=Y(n);
|
|
2508
|
-
Use -m to scope it to a module: kick g service payment -m orders`).option(`-o, --out <dir>`,`Output directory (overrides --module)`).option(`-m, --module <module>`,`Place inside a module folder`).action(async(e,t,n)=>{let r=Y(n);
|
|
2509
|
-
Use -m to scope it to a module: kick g controller auth -m users`).option(`-o, --out <dir>`,`Output directory (overrides --module)`).option(`-m, --module <module>`,`Place inside a module folder`).action(async(e,t,n)=>{let r=Y(n);
|
|
2510
|
-
Use -m to scope it to a module: kick g dto create-user -m users`).option(`-o, --out <dir>`,`Output directory (overrides --module)`).option(`-m, --module <module>`,`Place inside a module folder`).action(async(e,t,n)=>{let r=Y(n);
|
|
2511
|
-
Use -m to scope it to a module: kick g test user-service -m users`).option(`-o, --out <dir>`,`Output directory (overrides --module)`).option(`-m, --module <module>`,`Place inside a module's __tests__/ folder`).action(async(e,t,n)=>{let r=Y(n);
|
|
2511
|
+
Use -m to scope it to a module: kick g contributor tenant -m users`).option(`-o, --out <dir>`,`Output directory (overrides --module)`).option(`-m, --module <module>`,`Place inside a module folder`).option(`-t, --type <type>`,`Contributor flavour: http | bare`,`http`).option(`-k, --key <key>`,`Context key it writes (defaults to camelCase of name)`).option(`--params <fields>`,`Per-call params, e.g. "source:string,region:number"`).action(async(e,t,n)=>{let r=Y(n);M(r);let i=(t.type??`http`).toLowerCase();i!==`http`&&i!==`bare`&&(console.warn(` kick g contributor: unknown --type '${t.type}', using 'http'.`),i=`http`);let a=await j(process.cwd()),o=A(a),s=o.dir??`src/modules`;X(await er({name:e,type:i,key:t.key,params:t.params,outDir:t.out,moduleName:t.module,modulesDir:s,pattern:a?.pattern,pluralize:o.pluralize??!0}),r)}),n.command(`service <name>`).description(`Generate a @Service() class
|
|
2512
|
+
Use -m to scope it to a module: kick g service payment -m orders`).option(`-o, --out <dir>`,`Output directory (overrides --module)`).option(`-m, --module <module>`,`Place inside a module folder`).action(async(e,t,n)=>{let r=Y(n);M(r);let i=await j(process.cwd()),a=A(i),o=a.dir??`src/modules`;X(await tr({name:e,outDir:t.out,moduleName:t.module,modulesDir:o,pattern:i?.pattern,pluralize:a.pluralize??!0}),r)}),n.command(`controller <name>`).description(`Generate a @Controller() class with basic routes
|
|
2513
|
+
Use -m to scope it to a module: kick g controller auth -m users`).option(`-o, --out <dir>`,`Output directory (overrides --module)`).option(`-m, --module <module>`,`Place inside a module folder`).action(async(e,t,n)=>{let r=Y(n);M(r);let i=await j(process.cwd()),a=A(i),o=a.dir??`src/modules`;X(await nr({name:e,outDir:t.out,moduleName:t.module,modulesDir:o,pattern:i?.pattern,pluralize:a.pluralize??!0}),r),await Ba(r)}),n.command(`dto <name>`).description(`Generate a Zod DTO schema
|
|
2514
|
+
Use -m to scope it to a module: kick g dto create-user -m users`).option(`-o, --out <dir>`,`Output directory (overrides --module)`).option(`-m, --module <module>`,`Place inside a module folder`).action(async(e,t,n)=>{let r=Y(n);M(r);let i=await j(process.cwd()),a=A(i),o=a.dir??`src/modules`;X(await rr({name:e,outDir:t.out,moduleName:t.module,modulesDir:o,pattern:i?.pattern,pluralize:a.pluralize??!0}),r)}),n.command(`test <name>`).description(`Generate a Vitest test scaffold
|
|
2515
|
+
Use -m to scope it to a module: kick g test user-service -m users`).option(`-o, --out <dir>`,`Output directory (overrides --module)`).option(`-m, --module <module>`,`Place inside a module's __tests__/ folder`).action(async(e,t,n)=>{let r=Y(n);M(r);let i=A(await j(process.cwd())),a=i.dir??`src/modules`;X(await Nr({name:e,outDir:t.out,moduleName:t.module,modulesDir:a,pluralize:i.pluralize??!0}),r)}),n.command(`job <name>`).description(`Generate a @Job queue processor with @Process handlers`).option(`-o, --out <dir>`,`Output directory`,`src/jobs`).option(`-q, --queue <name>`,`Queue name (default: <name>-queue)`).action(async(e,t,n)=>{let r=Y(n);M(r),X(await Er({name:e,outDir:v(t.out),queue:t.queue}),r)}),n.command(`scaffold <name> [fields...]`).description(`Generate a full CRUD module from field definitions
|
|
2512
2516
|
Example: kick g scaffold Post title:string body:text:optional published:boolean:optional
|
|
2513
2517
|
Types: string, text, number, int, float, boolean, date, email, url, uuid, json, enum:a,b,c
|
|
2514
2518
|
Optional: append :optional (shell-safe): description:text:optional
|
|
2515
|
-
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,t,n,r)=>{let i=Y(r);
|
|
2519
|
+
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,t,n,r)=>{let i=Y(r);M(i),t.length===0&&(console.error(`
|
|
2516
2520
|
Error: At least one field is required.
|
|
2517
2521
|
Usage: kick g scaffold <name> <field:type> [field:type...]
|
|
2518
2522
|
Example: kick g scaffold Post title:string body:text:optional published:boolean:optional
|
|
2519
2523
|
Optional: append :optional (shell-safe, no quoting needed)
|
|
2520
|
-
`),process.exit(1));let a=await
|
|
2521
|
-
`,d=``;if(r(a)&&(d=await
|
|
2522
|
-
`,`utf-8`),s(` ✓ wrote manifest → ${_(n,p)} (${Object.keys(d).length} entries)`),{manifestPath:p,entries:u,manifest:f}}async function to(e,t,a,o){let s=v(a,t.src),c=t.dest?v(a,t.dest):h(o,e);if(io(c,a))return console.warn(` ⚠ assetMap.${e}.dest ('${t.dest}') resolves outside the project root — skipping copy`),{entrySummary:{namespace:e,src:t.src,dest:_(a,c),filesCopied:0},manifestSlice:{}};if(!r(s)||!ao(s))return{entrySummary:{namespace:e,src:t.src,dest:_(a,c),filesCopied:0},manifestSlice:{}};let l=await
|
|
2524
|
+
`),process.exit(1));let a=await j(process.cwd()),o=A(a),s=n.modulesDir??o.dir??`src/modules`,c=Or(t),l=Ae(a,process.cwd()),u=await kr({name:e,fields:c,modulesDir:v(s),noEntity:n.entity===!1,noTests:n.tests===!1,pluralize:n.pluralize===!1?!1:o.pluralize??!0,tokenScope:l,style:o.style});console.log(`\n Scaffolded ${e} with ${c.length} field(s):`);for(let e of c)console.log(` ${e.name}: ${e.type}${e.optional?` (optional)`:``}`);X(u,i),await Ba(i)}),n.command(`config`).description(`Generate a kick.config.ts at the project root`).option(`--modules-dir <dir>`,`Modules directory path`,`src/modules`).option(`--repo <type>`,`Repository name: inmemory (default) or any DB name`,`inmemory`).option(`-f, --force`,`Overwrite existing kick.config.ts without prompting`).action(async(e,t)=>{let n=Y(t);M(n),X(await ir({outDir:v(`.`),modulesDir:e.modulesDir,defaultRepo:e.repo,force:e.force}),n)}),n.command(`agents`).alias(`agent-docs`).alias(`ai-docs`).description(`Regenerate AGENTS.md + CLAUDE.md + kickjs-skills.md (sync after framework upgrades)`).option(`--only <which>`,`Limit scope: agents | claude | skills | both (agents+claude) | all (default: all)`,`all`).option(`--name <name>`,`Project name (defaults to package.json name)`).option(`--pm <pm>`,`Package manager (defaults to package.json packageManager)`).option(`--template <template>`,`Template: rest | minimal`).option(`-f, --force`,`Overwrite existing files without prompting`).action(async(e,t)=>{let n=Y(t);M(n);let r=e.only??`all`;if(!za.includes(r)){console.error(` Invalid --only value: ${r}. Expected: ${za.join(` | `)}`),process.exitCode=1;return}X(await dr({outDir:v(`.`),only:r,name:e.name,pm:e.pm,template:e.template,force:e.force}),n)});for(let e of t?.generators??[])Ka(n,e,t?.projectRoot)}function Ka(e,t,n){let{source:r,spec:i}=t,a=i.args?.[0],o=a?.name??`itemName`,s=a?.required?`<${o}>`:`[${o}]`,c=`${i.name} ${s} [extraArgs...]`,l=e.command(c).description(`${i.description} [${r}]`);for(let e of i.flags??[]){let t=e.takesValue?`--${e.name} <value>`:`--${e.name}`,n=e.alias?`-${e.alias}, ${t}`:t;l.option(n,e.description??``)}l.action(async(e,r,a,o)=>{let s=Y(o);M(s);let c=await mn({generatorName:i.name,itemName:e??``,args:r??[],flags:a,cwd:process.cwd(),projectRoot:n},[t]);c&&X(c.files,s)})}async function qa(e){let t=u.resolve(e.cwd,`.kickjs/types`);await C(t,{recursive:!0});let n=new Map,i=e.scan??Xi,a=u.resolve(e.cwd,`.kickjs`,`cache`),o=e.scan?void 0:e.changedFiles,s={cwd:e.cwd,config:e.config,async importTs(e){return await import(x(e).href)},async writeFile(t,n){let r=u.resolve(e.cwd,t);await C(u.dirname(r),{recursive:!0}),await T(r,n,`utf8`)},getScanResult:e=>{let t=Ja(e),r=n.get(t);if(!r){let s={cacheDir:a,...e};r=o?Qi(s,o):i(s),n.set(t,r)}return r},log:console},c=[];for(let n of e.plugins){let i=n.outExtension??`.d.ts`,a=u.join(t,`${n.id.replace(/\//g,`__`)}${i}`),o;try{o=await n.generate(s)}catch(e){let t=e instanceof Error?e.message:String(e);s.log.error(` ${n.id}: typegen failed (${t}) — keeping previous output`),c.push({id:n.id,status:`error`,outFile:a});continue}if(o===null){c.push({id:n.id,status:`skipped`});continue}let l=`/* AUTO-GENERATED by kick typegen — do not edit. Plugin: ${n.id} */\n\n`+o+`
|
|
2525
|
+
`,d=``;if(r(a)&&(d=await w(a,`utf8`)),d===l){c.push({id:n.id,status:`unchanged`,outFile:a});continue}if(e.check)throw Error(`kick typegen --check: drift detected for ${n.id} (${a})`);await T(a,l,`utf8`),c.push({id:n.id,status:`written`,outFile:a})}return c}function Ja(e){let t=(e.extensions??[]).slice().toSorted().join(`,`),n=(e.exclude??[]).slice().toSorted().join(`,`);return[`root=${e.root}`,`cwd=${e.cwd}`,`extensions=${t}`,`exclude=${n}`,`envFile=${e.envFile??``}`].join(`|`)}function Ya(e,t){let n=new Set(t),r=[],i=[],a=new Set;for(let t of e)n.has(t.id)?(i.push(t),a.add(t.id)):r.push(t);return{enabled:r,skipped:i,unknown:[...n].filter(e=>!a.has(e))}}var Xa=k({applyDisableFilter:()=>Ya,runAllPluginTypegens:()=>Qa});function Za(){let e=(process.env.LOG_LEVEL??process.env.KICKJS_LOG_LEVEL??``).toLowerCase();return e===`debug`||e===`trace`}async function Qa(e){let{enabled:t,skipped:n,unknown:r}=Ya(Ie([...Cc,...e.config?.plugins??[]],e.config?.commands??[]).typegens,e.config?.typegen?.disable??[]);if(!e.silent&&n.length>0)for(let e of n)console.log(` ${e.id}: disabled (typegen.disable)`);if(!e.silent&&r.length>0&&console.warn(` kick typegen: disable list references unknown id(s): ${r.map(e=>`'${e}'`).join(`, `)}. Run \`kick typegen --list\` to see registered ids.`),t.length===0)return[];try{let n=await qa({cwd:e.cwd,config:e.config??{},plugins:t,check:e.check,changedFiles:e.changedFiles});if(!e.silent&&Za())for(let e of n)console.log(` ${e.id}: ${e.status}`);return n}catch(t){if(!e.silent){let e=t instanceof Error?t.message:String(t);console.warn(` kick typegen plugins: skipped (${e})`)}return[]}}var $a=k({ASSET_MANIFEST_VERSION:()=>1,buildAssets:()=>eo});async function eo(e,t){let{cwd:n,silent:r=!1}=t,a=t.distDir??e?.build?.outDir??`dist`,o=e?.assetMap;if(!o||Object.keys(o).length===0)return null;let s=r?()=>{}:console.log,c=v(n,a);i(c,{recursive:!0});let u=[],d={};for(let[e,t]of Object.entries(o)){let r=await to(e,t,n,c);u.push(r.entrySummary),Object.assign(d,r.manifestSlice),s(` ✓ ${e}: ${r.entrySummary.filesCopied} file(s) → ${r.entrySummary.dest}`)}let f={version:1,entries:d},p=h(c,`.kickjs-assets.json`);return l(p,JSON.stringify(f,null,2)+`
|
|
2526
|
+
`,`utf-8`),s(` ✓ wrote manifest → ${_(n,p)} (${Object.keys(d).length} entries)`),{manifestPath:p,entries:u,manifest:f}}async function to(e,t,a,o){let s=v(a,t.src),c=t.dest?v(a,t.dest):h(o,e);if(io(c,a))return console.warn(` ⚠ assetMap.${e}.dest ('${t.dest}') resolves outside the project root — skipping copy`),{entrySummary:{namespace:e,src:t.src,dest:_(a,c),filesCopied:0},manifestSlice:{}};if(!r(s)||!ao(s))return{entrySummary:{namespace:e,src:t.src,dest:_(a,c),filesCopied:0},manifestSlice:{}};let l=await pe(t.glob??`**/*`,{cwd:s,nodir:!0,dot:!1,posix:!0});i(c,{recursive:!0});let u={},{pairs:d,collisionGroupsResolved:p}=he(e,[...l].toSorted(),{strategy:t.keys??`auto`}),m=0;for(let{rel:e,key:t}of d){let r=h(s,e),a=h(c,e);u[t]=ro(o,a),!no(r,a)&&(i(f(a),{recursive:!0}),n(r,a),m++)}return p>0&&console.log(` ℹ assetMap.${e}: auto-resolved ${p} basename collision(s) by keeping extensions (set 'keys: "strip"' to opt back into legacy last-write-wins behaviour, or 'keys: "with-extension"' to keep all keys verbose).`),{entrySummary:{namespace:e,src:t.src,dest:_(a,c),filesCopied:m},manifestSlice:u}}function no(e,t){if(!r(t))return!1;try{let n=c(e),r=c(t);return r.size===n.size&&r.mtimeMs>=n.mtimeMs}catch{return!1}}function ro(e,t){return _(e,t).split(/[\\/]/).filter(Boolean).join(`/`)}function io(e,t){let n=_(t,e);return n===``?!1:n.startsWith(`..`)||m(n)}function ao(e){try{return c(e).isDirectory()}catch{return!1}}function oo(e){let t=new Map;return{report(n,r){let i=r instanceof Error?r.message:String(r);t.get(n)!==i&&(t.set(n,i),e(` kick typegen: ${n} pass failed (${i}) — types in .kickjs/types may be stale`))},clear(e){t.delete(e)}}}function so(e){let{cwd:t,config:n}=e,r=e.debounceMs??100,i=e.pipeline??{runTypegen:async e=>(await Promise.resolve().then(()=>Aa)).runTypegen(e),runAllPluginTypegens:async e=>(await Promise.resolve().then(()=>Xa)).runAllPluginTypegens(e),writeTypegenArtifacts:async(e,t,n)=>(await Promise.resolve().then(()=>Aa)).writeTypegenArtifacts(e,t,n),buildAssets:async(e,t)=>(await Promise.resolve().then(()=>$a)).buildAssets(e,t)},a=n?.typegen?.schemaValidator??`zod`,o=n?.typegen?.envFile,s=u.resolve(t,n?.typegen?.outDir??`.kickjs/types`),c=n?.assetMap?Object.values(n.assetMap).map(e=>e?.src).filter(e=>typeof e==`string`&&e.length>0).map(e=>u.resolve(t,e)):[],l=!!n?.assetMap&&Object.keys(n.assetMap).length>0,d=e=>e.replaceAll(`\\`,`/`),f=c.map(d),p=e=>{let t=d(e);return f.some(e=>t===e||t.startsWith(`${e}/`))},m=oo(e.emitWarning),h=null,g=!1,_=new Set,v=new Set,y=!1,b=!1;function x(r,c){i.runTypegen({cwd:t,silent:!0,allowDuplicates:!0,schemaValidator:a,envFile:o,srcDir:n?.typegen?.srcDir,outDir:n?.typegen?.outDir,assetMap:n?.assetMap,changedFiles:r,runPlugins:!1}).then(()=>m.clear(`scan`)).catch(e=>m.report(`scan`,e)),i.runAllPluginTypegens({cwd:t,config:n,silent:!0,changedFiles:r}).then(e=>i.writeTypegenArtifacts(s,e,!0)).then(()=>m.clear(`plugins`)).catch(e=>m.report(`plugins`,e)).finally(()=>e.onPassComplete?.()),c&&n&&i.buildAssets(n,{cwd:t,silent:!0}).catch(()=>{})}function ee(){let e=y?void 0:{changed:[..._],removed:[...v]},t=b;_.clear(),v.clear(),y=!1,b=!1,x(e,t)}return{assetSrcRoots:c,handleWatchEvent(e,t){if(!g&&!d(t).includes(`/.kickjs/`)){if(e===`unlinkDir`)y=!0,l&&(b=!0);else{if(t.endsWith(`.d.ts`))return;let n=/\.(ts|tsx|mts|cts)$/.test(t),r=p(t);if(!n&&!r)return;r&&l&&(b=!0),n&&(e===`unlink`?(v.add(t),_.delete(t)):(_.add(t),v.delete(t)))}h&&clearTimeout(h),h=setTimeout(ee,r)}},runOnce(){g||x(void 0,l)},dispose(){g=!0,h&&clearTimeout(h),h=null}}}function co(e){let t=h(e,`node_modules`,`.bin`),n=process.platform===`win32`;for(let e of[`tsgo`,`tsc`]){let i=n?[`${e}.CMD`,`${e}.cmd`,`${e}.exe`]:[e];for(let a of i){let i=h(t,a);if(r(i))return{cmd:i,args:[`--noEmit`],shell:n,kind:e}}}return null}function lo(e){let t=e.spawnFn??ne,n=null,r=0,i=!1;return{schedule(){if(i)return;let a=++r;n&&=(n.kill(),null);let o=Date.now(),s=t(e.bin.cmd,e.bin.args,{cwd:e.cwd,shell:e.bin.shell,stdio:[`ignore`,`pipe`,`pipe`]});n=s;let c=``;s.stdout?.on(`data`,e=>{c+=e.toString()}),s.stderr?.on(`data`,e=>{c+=e.toString()}),s.on(`error`,()=>{a===r&&(n=null)}),s.on(`close`,t=>{i||a!==r||(n=null,e.onResult({ok:t===0,output:c,durationMs:Date.now()-o,kind:e.bin.kind}))})},dispose(){i=!0,n&&=(n.kill(),null)}}}function uo(e,t=12){let n=e.trim().split(/\r?\n/);return n.length<=t?n.join(`
|
|
2523
2527
|
`):`${n.slice(0,t).join(`
|
|
2524
|
-
`)}\n… ${n.length-t} more line(s)`}function fo(e){if(typeof e==`boolean`)return e;let t=process.env.KICKJS_WATCH_POLLING;return t===`1`||t===`true`}async function po(e,t,n={}){t&&(process.env.PORT=t);let r=fo(n.polling),i=process.cwd(),a=await
|
|
2528
|
+
`)}\n… ${n.length-t} more line(s)`}function fo(e){if(typeof e==`boolean`)return e;let t=process.env.KICKJS_WATCH_POLLING;return t===`1`||t===`true`}async function po(e,t,n={}){t&&(process.env.PORT=t);let r=fo(n.polling),i=process.cwd(),a=await j(i),o=a?.typegen?.schemaValidator??`zod`,s=a?.typegen?.envFile;try{await Ma({cwd:i,allowDuplicates:!0,schemaValidator:o,envFile:s,srcDir:a?.typegen?.srcDir,outDir:a?.typegen?.outDir,assetMap:a?.assetMap,runPlugins:!1})}catch(e){console.warn(` kick typegen: skipped (${e?.message??e})`)}let c=v(i,a?.typegen?.outDir??`.kickjs/types`);try{await Fa(c,await Qa({cwd:i,config:a}),!1)}catch(e){console.warn(` kick typegen: plugin pass skipped (${e?.message??e})`)}let{createRequire:l}=await import(`node:module`),{createServer:u}=await import(x(l(v(`package.json`)).resolve(`vite`)).href);globalThis.__kickjs_typegen_owner=`kick-dev`;let d=await u({configFile:v(`vite.config.ts`),server:{port:t?parseInt(t,10):void 0,...r?{watch:{usePolling:!0,interval:100}}:{}}}),f=n.typecheck??a?.dev?.typecheck??!1,p=null,m=!0;if(f){let e=co(i);e?p=lo({cwd:i,bin:e,onResult:e=>{d.hot.send({type:`custom`,event:`kickjs:typecheck`,data:{ok:e.ok,output:e.output,durationMs:e.durationMs}}),e.ok?m||(m=!0,console.log(` kick typecheck: clean again (${e.kind}, ${e.durationMs}ms)`)):(m=!1,console.warn(`\n kick typecheck (${e.kind}, ${e.durationMs}ms):`),console.warn(uo(e.output).replace(/^/gm,` `)))}}):console.warn(` kick dev: --typecheck requested but neither tsgo (@typescript/native-preview) nor typescript is installed in this project — skipping type checks.`)}let h=so({cwd:i,config:a,emitWarning:e=>{console.warn(e),d.hot.send({type:`custom`,event:`kickjs:typegen-error`,data:{message:e,timestamp:Date.now()}})},onPassComplete:()=>p?.schedule()});d.watcher.on(`add`,e=>h.handleWatchEvent(`add`,e)),d.watcher.on(`unlink`,e=>h.handleWatchEvent(`unlink`,e)),d.watcher.on(`change`,e=>h.handleWatchEvent(`change`,e)),d.watcher.on(`unlinkDir`,e=>h.handleWatchEvent(`unlinkDir`,e)),h.assetSrcRoots.length>0&&d.watcher.add([...h.assetSrcRoots]),await d.listen(),d.printUrls(),console.log(`
|
|
2525
2529
|
KickJS dev server running (Vite + @forinda/kickjs-vite)
|
|
2526
2530
|
`),p?.schedule();let g=!1,_=async()=>{if(!g){g=!0,h.dispose(),p?.dispose();try{await globalThis.__kickjs_app_shutdown?.()}catch(e){console.error(` app shutdown hook failed: ${e?.message??e}`)}await d.close(),process.exit(0)}};process.on(`SIGINT`,_),process.on(`SIGTERM`,_),process.on(`SIGBREAK`,_)}function mo(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)`).option(`--typecheck`,`Run the project TypeScript checker (tsgo/tsc --noEmit) after each change and report diagnostics`).action(async e=>{try{await po(e.entry,e.port,{polling:e.polling,typecheck:e.typecheck})}catch(e){e.code===`ERR_MODULE_NOT_FOUND`&&e.message?.includes(`vite`)?console.error(`
|
|
2527
2531
|
Error: vite is not installed.
|
|
@@ -2529,16 +2533,16 @@ export {}
|
|
|
2529
2533
|
`):console.error(`
|
|
2530
2534
|
Dev server failed:`,e.message??e),process.exit(1)}}),e.command(`build`).description(`Build for production via Vite`).action(async()=>{console.log(`
|
|
2531
2535
|
Building for production...
|
|
2532
|
-
`);let{createRequire:e}=await import(`node:module`),{build:t}=await import(x(e(v(`package.json`)).resolve(`vite`)).href);await t({configFile:v(`vite.config.ts`)});let a=await
|
|
2536
|
+
`);let{createRequire:e}=await import(`node:module`),{build:t}=await import(x(e(v(`package.json`)).resolve(`vite`)).href);await t({configFile:v(`vite.config.ts`)});let a=await j(process.cwd()),o=a?.copyDirs??[];if(o.length>0){console.log(`
|
|
2533
2537
|
Copying directories to dist...`);for(let e of o){let t=typeof e==`string`?e:e.src,a=typeof e==`string`?h(`dist`,e):e.dest??h(`dist`,t),o=v(t),s=v(a);if(!r(o)){console.log(` ⚠ Skipped ${t} (not found)`);continue}i(s,{recursive:!0}),n(o,s,{recursive:!0}),console.log(` ✓ ${t} → ${a}`)}}if(a?.assetMap&&Object.keys(a.assetMap).length>0){console.log(`
|
|
2534
2538
|
Building asset map...`);try{await eo(a,{cwd:process.cwd()})}catch(e){console.error(` ✗ asset build failed: ${e instanceof Error?e.message:String(e)}`),process.exit(1)}}console.log(`
|
|
2535
2539
|
Build complete.
|
|
2536
|
-
`)}),e.command(`build:assets`).description(`Rebuild the .kickjs-assets.json manifest under the configured outDir (no JS rebuild)`).action(async()=>{let e=await
|
|
2540
|
+
`)}),e.command(`build:assets`).description(`Rebuild the .kickjs-assets.json manifest under the configured outDir (no JS rebuild)`).action(async()=>{let e=await j(process.cwd());if(!e?.assetMap||Object.keys(e.assetMap).length===0){console.log(` No assetMap entries — nothing to build.`);return}console.log(`
|
|
2537
2541
|
Building asset map...`);try{await eo(e,{cwd:process.cwd()}),console.log(`
|
|
2538
2542
|
Asset build complete.
|
|
2539
|
-
`)}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)),
|
|
2540
|
-
Dev server (debug) failed:`,e.message??e),process.exit(1)}})}function ho(){try{let e=f(b(import.meta.url));return JSON.parse(a(h(e,`..`,`package.json`),`utf-8`)).version??`unknown`}catch{return`unknown`}}const go=new Set(Object.values(
|
|
2541
|
-
`))})}const{bold:Z,dim:Q,green:bo,red:xo,yellow:So,blue:Co}=
|
|
2543
|
+
`)}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)),xe(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 po(e.entry,e.port)}catch(e){console.error(`
|
|
2544
|
+
Dev server (debug) failed:`,e.message??e),process.exit(1)}})}function ho(){try{let e=f(b(import.meta.url));return JSON.parse(a(h(e,`..`,`package.json`),`utf-8`)).version??`unknown`}catch{return`unknown`}}const go=new Set(Object.values(yt).filter(e=>e.deprecated).map(e=>e.pkg));function _o(e){let t=h(e,`package.json`);if(!r(t))return[];let n;try{n=JSON.parse(a(t,`utf-8`))}catch{return[]}let i={...n.dependencies,...n.devDependencies};return Object.keys(i).filter(e=>e===`@forinda/kickjs`||e.startsWith(`@forinda/kickjs-`)).toSorted().map(t=>{let n=null,o=h(e,`node_modules`,...t.split(`/`),`package.json`);if(r(o))try{n=JSON.parse(a(o,`utf-8`)).version??null}catch{}return{name:t,installed:n,declared:i[t]??null,deprecated:go.has(t)}})}function vo(e){let t=e;for(;;){if(r(h(t,`package.json`)))return t;let e=f(t);if(e===t)return null;t=e}}function yo(e){e.command(`info`).description(`Print system and framework info`).action(()=>{let e=[``,` KickJS CLI v${ho()}`,``,` System:`,` OS: ${_e()} ${ve()} (${ge()})`,` Node: ${process.version}`],t=vo(process.cwd()),n=t?_o(t):[];if(!t)e.push(``,` Packages: (not inside a project — no package.json found)`);else if(n.length===0)e.push(``,` Packages: (no @forinda/kickjs* dependencies in ${t})`);else{e.push(``,` Packages:`);let t=Math.max(...n.map(e=>e.name.length));for(let r of n){let n=r.installed??`${r.declared??`?`} (declared — not installed)`,i=r.deprecated?" [DEPRECATED — see `kick add --list --all`]":``;e.push(` ${r.name.padEnd(t+2)} ${n}${i}`)}}e.push(``),console.log(e.join(`
|
|
2545
|
+
`))})}const{bold:Z,dim:Q,green:bo,red:xo,yellow:So,blue:Co}=O;function wo(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 To(e){let t=await fetch(e,{signal:AbortSignal.timeout(5e3)});if(!t.ok)throw Error(`${t.status} ${t.statusText}`);return t.json()}async function Eo(e,t){try{return await To(`${e}${t}`)}catch{return null}}async function Do(e){let[t,n,r,i,a]=await Promise.all([Eo(e,`/health`),Eo(e,`/metrics`),Eo(e,`/routes`),Eo(e,`/container`),Eo(e,`/ws`)]);return{health:t,metrics:n,routes:r,container:i,ws:a}}function Oo(e,t){let{health:n,metrics:r,routes:i,container:a,ws:o}=t,s=Q(`─`.repeat(60));if(console.log(),console.log(Z(` KickJS Inspector`)+Q(` → ${e}`)),console.log(s),n){let e=n.status===`healthy`?bo(`● healthy`):xo(`● `+n.status);console.log(` ${Z(`Health:`)} ${e}`)}else console.log(` ${Z(`Health:`)} ${xo(`● unreachable`)}`);if(r){let e=((r.errorRate??0)*100).toFixed(1),t=r.errorRate>.1?xo:r.errorRate>0?So:bo;console.log(` ${Z(`Uptime:`)} ${wo(r.uptimeSeconds)}`),console.log(` ${Z(`Requests:`)} ${r.requests}`),console.log(` ${Z(`Errors:`)} ${r.serverErrors} server, ${r.clientErrors??0} client ${Q(`(`)}${t(e+`%`)}${Q(`)`)}`)}if(a&&console.log(` ${Z(`DI:`)} ${a.count} bindings`),o&&o.enabled&&console.log(` ${Z(`WS:`)} ${o.connections??0} connections, ${o.namespaces??0} namespaces`),i?.routes?.length){console.log(),console.log(Z(` Routes`)),console.log(s),console.log(` ${Q(`METHOD`)} ${Q(`PATH`.padEnd(36))} ${Q(`CONTROLLER`)}`);for(let e of i.routes){let t=e.path.length>36?e.path.slice(0,33)+`...`:e.path.padEnd(36);console.log(` ${Wt(e.method)} ${t} ${Co(e.controller)}.${Q(e.handler)}`)}}console.log(s),console.log()}function ko(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 Do(r);t.json?console.log(JSON.stringify(e,null,2)):Oo(n,e)}catch(e){t.json?console.log(JSON.stringify({error:String(e)})):(console.error(xo(` ✖ Could not connect to ${n}`)),console.error(Q(` ${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 Ao(e,t){let n=e.toLowerCase();return t.every(e=>n.includes(e.toLowerCase()))}function $(e,t){let n=e.toLowerCase();return t.some(e=>n.includes(e.toLowerCase()))}const jo=[{match(e,t){let n=Ao(e,[`config`,`get`])&&$(e,[`undefined`,`null`]),r=e.includes(`@Value`)&&$(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
|
|
2542
2546
|
registers the env schema with kickjs at module-load time. Without it,
|
|
2543
2547
|
ConfigService falls back to the base schema (PORT/NODE_ENV/LOG_LEVEL only)
|
|
2544
2548
|
and every user-defined key reads as undefined. @Value() may *appear* to
|
|
@@ -2648,10 +2652,10 @@ Pass a message as a positional arg, --message flag, or pipe via stdin:
|
|
|
2648
2652
|
|
|
2649
2653
|
`)}function qo(e,t){return e.split(`
|
|
2650
2654
|
`).map(e=>`${t}${e}`).join(`
|
|
2651
|
-
`)}function Jo(e,t){return e.length<=t?e:e.slice(0,t-1)+`…`}function Yo(e){return e>=90?`high confidence`:e>=70?`good match`:e>=50?`medium confidence`:`low confidence — verify manually`}function Xo(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(Zo),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(Qo)}function Zo(e){let t=v(e.entry);r(t)||(process.stderr.write(`Error: entry file not found: ${t}\n\nBuild the app first with \`kick build\`, or pass a custom entry:\n kick mcp -e dist/server.js\n`),process.exit(1));let n=[...e.nodeArg??[],t],i=
|
|
2655
|
+
`)}function Jo(e,t){return e.length<=t?e:e.slice(0,t-1)+`…`}function Yo(e){return e>=90?`high confidence`:e>=70?`good match`:e>=50?`medium confidence`:`low confidence — verify manually`}function Xo(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(Zo),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(Qo)}function Zo(e){let t=v(e.entry);r(t)||(process.stderr.write(`Error: entry file not found: ${t}\n\nBuild the app first with \`kick build\`, or pass a custom entry:\n kick mcp -e dist/server.js\n`),process.exit(1));let n=[...e.nodeArg??[],t],i=ne(process.execPath,n,{stdio:`inherit`,env:{...process.env,KICK_MCP_STDIO:`1`,NODE_ENV:process.env.NODE_ENV??`production`}});i.on(`error`,e=>{process.stderr.write(`Failed to start MCP server: ${e.message}\n`),process.exit(1)}),i.on(`exit`,(e,t)=>{if(t){process.kill(process.pid,t);return}process.exit(e??0)});let a=e=>{i.killed||i.kill(e)};process.on(`SIGINT`,()=>a(`SIGINT`)),process.on(`SIGTERM`,()=>a(`SIGTERM`))}function Qo(e){let t=process.cwd(),n=$o(t)??d(t),i=e.name??n,o=e.global?v(process.env.HOME??`.`,`.mcp.json`):v(t,e.out),s={command:`kick`,args:[`mcp`],cwd:t},c={mcpServers:{}};if(r(o))try{let e=a(o,`utf8`),t=JSON.parse(e);t&&typeof t==`object`&&t.mcpServers&&(c={mcpServers:{...t.mcpServers}})}catch(e){let t=e instanceof Error?e.message:String(e);process.stderr.write(`Error: existing ${o} is not valid JSON (${t}).\nFix the file or pass --force to overwrite the entry.\n`),process.exit(1)}c.mcpServers[i]&&!e.force&&(process.stderr.write(`Error: an entry for "${i}" already exists in ${o}.\nPass --force to overwrite it, or use --name to pick a different key.\n`),process.exit(1)),c.mcpServers[i]=s,l(o,JSON.stringify(c,null,2)+`
|
|
2652
2656
|
`,`utf8`),process.stdout.write(`\n ✓ Wrote MCP server entry "${i}" to ${o}\n\n To activate it:\n 1. Build your app: kick build\n 2. Restart your MCP client (Claude Code, Cursor, Zed)\n 3. The server should appear in the client's tool picker\n\n`)}function $o(e){let t=v(e,`package.json`);if(!r(t))return null;try{let e=a(t,`utf8`),n=JSON.parse(e);return typeof n.name==`string`?n.name:null}catch{return null}}function es(e){e.command(`tinker`).description(`Interactive REPL with DI container and services loaded`).option(`-e, --entry <file>`,`Entry file to load`,`src/index.ts`).action(async e=>{let t=process.cwd(),n=v(t,e.entry);r(n)||(console.error(`\n Error: ${e.entry} not found.\n`),process.exit(1));let i=ns(t,`tsx`);i||(console.error(`
|
|
2653
2657
|
Error: tsx not found. Install it: pnpm add -D tsx
|
|
2654
|
-
`),process.exit(1));let a=ts(n,e.entry),o=h(t,`.kick-tinker.mjs`),{writeFileSync:s,unlinkSync:c}=await import(`node:fs`);s(o,a,`utf-8`);try{let e=
|
|
2658
|
+
`),process.exit(1));let a=ts(n,e.entry),o=h(t,`.kick-tinker.mjs`),{writeFileSync:s,unlinkSync:c}=await import(`node:fs`);s(o,a,`utf-8`);try{let e=te(o,[],{cwd:t,execPath:i,stdio:`inherit`});await new Promise(t=>{e.on(`exit`,()=>t())})}finally{try{c(o)}catch{}}})}function ts(e,t){return`
|
|
2655
2659
|
import 'reflect-metadata'
|
|
2656
2660
|
|
|
2657
2661
|
// Prevent bootstrap() from starting the HTTP server
|
|
@@ -2707,11 +2711,11 @@ server.on('exit', () => {
|
|
|
2707
2711
|
})
|
|
2708
2712
|
`}function ns(e,t){let n=e;for(;;){let e=h(n,`node_modules`,`.bin`,t);if(r(e))return e;let i=v(n,`..`);if(i===n)break;n=i}return null}function rs(e,t){let n=RegExp(`^\\s*${V(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]!==`
|
|
2709
2713
|
`;)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]===`
|
|
2710
|
-
`);)t--;a=a.slice(0,t)+a.slice(s+1),r=!0,i=t;continue}i=s+1}return{content:a,changed:r}}function is(e,t){let n=Vn(e);if(!n)return e;let r=n.rhsStart,i=n.rhsEnd+1,a=e.slice(r,i);return a=rs(a,t).content,a=a.replace(RegExp(`\\s*,?\\s*${V(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 as(e){let{name:t,modulesDir:n,force:r}=e,i=e.pluralize!==!1,a=
|
|
2714
|
+
`);)t--;a=a.slice(0,t)+a.slice(s+1),r=!0,i=t;continue}i=s+1}return{content:a,changed:r}}function is(e,t){let n=Vn(e);if(!n)return e;let r=n.rhsStart,i=n.rhsEnd+1,a=e.slice(r,i);return a=rs(a,t).content,a=a.replace(RegExp(`\\s*,?\\s*${V(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 as(e){let{name:t,modulesDir:n,force:r}=e,i=e.pluralize!==!1,a=z(t),o=L(t),s=i?B(a):a,c=h(n,s);if(!await Ge(c)){console.log(`\n Module not found: ${c}\n`);return}if(!r&&!await F({message:O.red(`Delete module '${s}' at ${c}? This cannot be undone.`),initialValue:!1})){console.log(`
|
|
2711
2715
|
Cancelled.
|
|
2712
|
-
`);return}await
|
|
2716
|
+
`);return}await se(c,{recursive:!0,force:!0}),console.log(` Deleted: ${c}`);let l=h(n,`index.ts`);if(await Ge(l)){let e=await w(l,`utf-8`),t=e,n=RegExp(`^import\\s*\\{\\s*${V(o)}Module\\s*\\}\\s*from\\s*['"][^'"]*${V(s)}(?:/[^'"]*)?['"].*\\n?`,`gm`);e=e.replace(n,``),e=is(e,o),e=e.replace(/\n{3,}/g,`
|
|
2713
2717
|
|
|
2714
|
-
`),e!==t&&(await
|
|
2718
|
+
`),e!==t&&(await T(l,e,`utf-8`),console.log(` Unregistered: ${o}Module from ${l}`))}console.log(`\n Module '${s}' removed.\n`)}function os(e){e.command(`remove`).alias(`rm`).description(`Remove generated code`).command(`module <names...>`).description(`Remove one or more modules (e.g. kick rm module user task)`).option(`--modules-dir <dir>`,`Modules directory`).option(`--no-pluralize`,`Use singular module name`).option(`-f, --force`,`Skip confirmation prompt`).action(async(e,t)=>{let n=A(await j(process.cwd())),r=t.modulesDir??n.dir??`src/modules`,i=t.pluralize===!1?!1:n.pluralize??!0;for(let n of e)await as({name:n,modulesDir:v(r),force:t.force,pluralize:i})})}function ss(e){if(e!==void 0){if(e===`false`||e===`off`||e===`none`)return!1;if(e===`zod`)return`zod`;if(e===`kickjs-schema`||e===`schema`)return`kickjs-schema`;console.warn(` kick typegen: unknown --schema-validator '${e}' (supported: 'zod', 'kickjs-schema', 'false'). Falling back to project config.`)}}function cs(e){if(e!==void 0)return e===`false`||e===`off`||e===`none`?!1:e}function ls(e){e.command(`typegen`).description(`Generate type-safe DI registry and module types into .kickjs/types/`).option(`-w, --watch`,`Watch source files and regenerate on change`).option(`-s, --src <dir>`,`Source directory to scan`,`src`).option(`-o, --out <dir>`,`Output directory`,`.kickjs/types`).option(`--silent`,`Suppress output`).option(`--allow-duplicates`,`Auto-namespace duplicate class names instead of failing (use with caution)`).option(`--schema-validator <name>`,`Schema validator for body/query/params typing (currently 'zod' or 'false')`).option(`--env-file <path>`,`Path to env schema file for KickEnv typing (default 'src/env.ts'; pass 'false' to disable)`).option(`--check`,`CI gate: fail on plugin-typegen drift instead of writing`).option(`--fix`,`Patch module import.meta.glob() calls to cover decorated classes that aren't loaded by any glob (orphans)`).option(`--list`,"List every registered typegen plugin id (use to populate `typegen.disable`)").option(`--no-cache`,`Disable the persistent scan cache; re-read + re-extract every file from cold`).action(async e=>{let t=rn(process.cwd()),n=await j(t);if(e.list){let{mergeCliPlugins:e}=await Promise.resolve().then(()=>Le),{builtinCliPlugins:t}=await Promise.resolve().then(()=>Sc),r=e([...t,...n?.plugins??[]],n?.commands??[]),i=new Set(n?.typegen?.disable??[]);if(r.typegens.length===0){console.log(` No typegen plugins registered.`);return}let a=Math.max(...r.typegens.map(e=>e.id.length));console.log(`
|
|
2715
2719
|
Registered typegen plugins:
|
|
2716
2720
|
`);for(let e of r.typegens){let t=i.has(e.id)?` (disabled)`:``;console.log(` ${e.id.padEnd(a+2)}inputs: ${e.inputs.join(`, `)||`(none)`}${t}`)}console.log();return}let r=ss(e.schemaValidator)??n?.typegen?.schemaValidator??`zod`,i=cs(e.envFile)??n?.typegen?.envFile,a={cwd:t,srcDir:e.src??n?.typegen?.srcDir,outDir:e.out??n?.typegen?.outDir,silent:e.silent,fix:e.fix,allowDuplicates:e.allowDuplicates,noCache:e.cache===!1,schemaValidator:r,envFile:i,assetMap:n?.assetMap,runPlugins:!1};try{if(e.watch){let t=await Ia(a);e.silent||console.log(` kick typegen: watching for changes (Ctrl-C to exit)`);let n=()=>{t(),process.exit(0)};process.on(`SIGINT`,n),process.on(`SIGTERM`,n),await new Promise(()=>{})}else{await Ma(a);let r=await Qa({cwd:t,config:n??null,silent:e.silent,check:e.check});e.check&&r.some(e=>e.status===`written`)&&process.exit(1),e.check||await Fa(v(t,e.out??n?.typegen?.outDir??`.kickjs/types`),r,e.silent??!1)}}catch(e){e instanceof la?console.error(`
|
|
2717
2721
|
`+e.message+`
|
|
@@ -2720,39 +2724,46 @@ server.on('exit', () => {
|
|
|
2720
2724
|
|
|
2721
2725
|
Available checks:
|
|
2722
2726
|
--deploy Audit for production readiness (security, config, best practices)
|
|
2723
|
-
`);return}let t=process.cwd();
|
|
2724
|
-
Install a supported version via nvm / fnm / volta.`}:{name:`Node version`,status:`pass`,message:e}}function Os(e){if(!e.pkg)return{name:`@forinda/kickjs installed`,status:`warn`,message:`no package.json`};let t={...e.pkg.dependencies,...e.pkg.peerDependencies};return t[`@forinda/kickjs`]?{name:`@forinda/kickjs installed`,status:`pass`,message:t[`@forinda/kickjs`]}:{name:`@forinda/kickjs installed`,status:`fail`,fix:"This directory does not look like a KickJS project — `@forinda/kickjs` is not in your package.json. Run `kick doctor` from the project root, or scaffold a fresh project with `kick new <name>`."}}function ks(e){if(!e.pkg)return null;let t={...e.pkg.dependencies,...e.pkg.peerDependencies};return t[`@forinda/kickjs`]&&!t.express?{name:`express installed`,status:`fail`,fix:"`@forinda/kickjs` declares `express` as a required peer dependency, but your package.json does not include it. Install: pnpm add express"}:t.express?{name:`express installed`,status:`pass`,message:t.express}:null}const As={express:[],fastify:[`fastify`,`@fastify/middie`],h3:[`h3`]};function js(e){if(!e.pkg||e.runtime===`express`)return null;let t={...e.pkg.dependencies,...e.pkg.peerDependencies,...e.pkg.devDependencies},n=As[e.runtime].filter(e=>!t[e]),r=`runtime engine (${e.runtime})`;return n.length>0?{name:r,status:`fail`,fix:`Resolved runtime '${e.runtime}' is missing engine peer(s): ${n.join(`, `)}.\nInstall: pnpm add ${n.join(` `)}`}:{name:r,status:`pass`}}function Ms(e){if(!e.pkg||!Ps(e.cwd))return null;let t=
|
|
2727
|
+
`);return}let t=process.cwd();Kt(`KickJS Deploy Check`);let n=Zt();n.start(`Scanning project...`);let r=bs(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(`${Gt(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?O.red(`${a} critical`):`${a} critical`,o>0?O.yellow(`${o} ${c}`):`${o} ${c}`,`${s} info`].join(`, `);a>0?(P(O.red(`${l} — fix critical issues before deploying`)),process.exit(1)):P(O.green(`${l} — looking good!`))})}function Ss(e){try{return JSON.parse(a(e,`utf-8`))}catch{return null}}function Cs(e){try{return a(e,`utf-8`)}catch{return null}}function ws(e){let t=Cs(h(e,`tsconfig.json`));if(!t)return null;let n=t.replace(/\/\*[\s\S]*?\*\//g,``).replace(/\/\/.*$/gm,``),r;try{r=JSON.parse(n)}catch{return null}if(typeof r?.extends==`string`){let t=Ts(e,r.extends);if(t){let e=Ss(t)??{};r.compilerOptions={...e.compilerOptions,...r.compilerOptions}}}return r}function Ts(e,t){if(t.startsWith(`.`)){let n=v(e,t);return r(n)?n:null}let n=h(e,`node_modules`,t);return r(n)?n:null}function Es(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function Ds(){let e=process.version,t=Number.parseInt(e.replace(/^v/,``).split(`.`)[0],10);return Number.isNaN(t)||t<20?{name:`Node version`,status:`fail`,message:e,fix:`KickJS requires Node 20 or newer.
|
|
2728
|
+
Install a supported version via nvm / fnm / volta.`}:{name:`Node version`,status:`pass`,message:e}}function Os(e){if(!e.pkg)return{name:`@forinda/kickjs installed`,status:`warn`,message:`no package.json`};let t={...e.pkg.dependencies,...e.pkg.peerDependencies};return t[`@forinda/kickjs`]?{name:`@forinda/kickjs installed`,status:`pass`,message:t[`@forinda/kickjs`]}:{name:`@forinda/kickjs installed`,status:`fail`,fix:"This directory does not look like a KickJS project — `@forinda/kickjs` is not in your package.json. Run `kick doctor` from the project root, or scaffold a fresh project with `kick new <name>`."}}function ks(e){if(!e.pkg)return null;let t={...e.pkg.dependencies,...e.pkg.peerDependencies};return t[`@forinda/kickjs`]&&!t.express?{name:`express installed`,status:`fail`,fix:"`@forinda/kickjs` declares `express` as a required peer dependency, but your package.json does not include it. Install: pnpm add express"}:t.express?{name:`express installed`,status:`pass`,message:t.express}:null}const As={express:[],fastify:[`fastify`,`@fastify/middie`],h3:[`h3`]};function js(e){if(!e.pkg||e.runtime===`express`)return null;let t={...e.pkg.dependencies,...e.pkg.peerDependencies,...e.pkg.devDependencies},n=As[e.runtime].filter(e=>!t[e]),r=`runtime engine (${e.runtime})`;return n.length>0?{name:r,status:`fail`,fix:`Resolved runtime '${e.runtime}' is missing engine peer(s): ${n.join(`, `)}.\nInstall: pnpm add ${n.join(` `)}`}:{name:r,status:`pass`}}function Ms(e){if(!e.pkg||!Ps(e.cwd))return null;let t=xt[e.runtime],n=`upload driver (${e.runtime})`;return t.prod?{...e.pkg.dependencies,...e.pkg.peerDependencies,...e.pkg.devDependencies}[t.prod]?{name:n,status:`pass`,message:t.prod}:{name:n,status:`fail`,fix:`This project uses file uploads on the '${e.runtime}' runtime, which needs '${t.prod}'.\nInstall it: kick add upload (or pnpm add ${t.prod})`}:{name:n,status:`pass`,message:`native multipart`}}const Ns=2e3;function Ps(e){let t=h(e,`src`);if(!r(t))return!1;let n=/@FileUpload\b|\bupload\.(single|array|none)\s*\(/,i=[t],a=0;for(;i.length>0&&a<Ns;){let e=i.pop(),t;try{t=o(e,{withFileTypes:!0})}catch{continue}for(let r of t){if(a>=Ns)break;let t=h(e,r.name);if(r.isDirectory()){r.name!==`node_modules`&&i.push(t);continue}if(/\.(ts|tsx|mts|cts)$/.test(r.name)&&(a++,n.test(Cs(t)??``)))return!0}}return!1}function Fs(e){if(!e.pkg)return{name:`reflect-metadata installed`,status:`warn`,message:`no package.json`};let t={...e.pkg.dependencies,...e.pkg.peerDependencies,...e.pkg.devDependencies};return t[`reflect-metadata`]?{name:`reflect-metadata installed`,status:`pass`,message:t[`reflect-metadata`]}:{name:`reflect-metadata installed`,status:`fail`,fix:`KickJS decorators require the reflect-metadata polyfill.
|
|
2725
2729
|
Install it: pnpm add reflect-metadata
|
|
2726
2730
|
Then import it at the top of src/index.ts:
|
|
2727
2731
|
|
|
2728
2732
|
import 'reflect-metadata'
|
|
2729
|
-
// ... rest of bootstrap`}}function Is(e){if(!e.tsconfig)return[{name:`tsconfig.json present`,status:`fail`,fix:"Create a tsconfig.json with `experimentalDecorators: true` and `emitDecoratorMetadata: true`. `kick new` scaffolds one automatically."}];let t=e.tsconfig.compilerOptions??{},n=[];return n.push(t.experimentalDecorators===!0?{name:`tsconfig: experimentalDecorators`,status:`pass`}:{name:`tsconfig: experimentalDecorators`,status:`fail`,fix:'Add `"experimentalDecorators": true` to compilerOptions in tsconfig.json. Without it, @Service / @Controller / @Get etc. don\'t register any metadata at compile time.'}),n.push(t.emitDecoratorMetadata===!0?{name:`tsconfig: emitDecoratorMetadata`,status:`pass`}:{name:`tsconfig: emitDecoratorMetadata`,status:`fail`,fix:'Add `"emitDecoratorMetadata": true` to compilerOptions in tsconfig.json. The DI container uses this metadata for constructor-parameter injection.'}),n}function Ls(e){let t=[`src/env.ts`,`src/env/index.ts`,`src/config/env.ts`,`src/config/index.ts`].map(t=>h(e.cwd,t)).filter(e=>r(e)).filter(e=>/\bloadEnv\s*\(/.test(Cs(e)??``));if(t.length===0)return null;let n=[`src/index.ts`,`src/main.ts`].map(t=>h(e.cwd,t)).find(e=>r(e));if(!n)return{name:`env wiring`,status:`warn`,message:`env-init file exists but no src/index.ts or src/main.ts found`};let i=Cs(n)??``,a=f(n),o=[];for(let e of t){let t=_(a,e).replace(/\\/g,`/`).replace(/\.ts$/,``),n=t.startsWith(`.`)?t:`./`+t,r=n.replace(/\/index$/,``);o.push(n,r);let i=e.replace(/\\/g,`/`).match(/\/src\/(.+?)(?:\.ts)?$/);if(i){let e=`@/`+i[1],t=e.replace(/\/index$/,``);o.push(e,t)}}let s=-1;for(let e of new Set(o)){let t=RegExp(`^import\\s+(?:.*?from\\s+)?['"]${Es(e)}['"]`,`m`),n=i.match(t);n&&n.index!==void 0&&(s===-1||n.index<s)&&(s=n.index)}let c=i.search(/\bbootstrap\s*\(/),l=t.map(t=>_(e.cwd,t).replace(/\\/g,`/`)).join(`, `);return s===-1?{name:`env wiring`,status:`fail`,message:l,fix:`An env-init file (${l}) calls \`loadEnv(...)\` but \`${_(e.cwd,n).replace(/\\/g,`/`)}\` doesn't import it.\nWithout this, ConfigService.get('X') returns undefined while @Value('X') works via process.env fallback — a half-broken config you won't notice until something is missing.\n\nFix: add a side-effect import at the top of ${_(e.cwd,n).replace(/\\/g,`/`)} (above bootstrap()), pointing at one of the detected files. For example:\n\n import './env'\n // or\n import './config'\n // or, with the @/ alias:\n import '@/config/env'`}:c!==-1&&s>c?{name:`env wiring`,status:`warn`,message:`env-init imported AFTER bootstrap() — should be before`,fix:`Move the env import above the bootstrap() call so the schema runs before any service reads from ConfigService.`}:{name:`env wiring`,status:`pass`}}function Rs(e,t=zs){let n=0,r=0,i=[e];for(;i.length>0&&r<t;){let e=i.pop(),a;try{a=o(e,{withFileTypes:!0})}catch{continue}for(let o of a){if(r>=t)break;r++;let a=h(e,o.name);if(o.isDirectory()){i.push(a);continue}try{let e=c(a).mtimeMs;e>n&&(n=e)}catch{}}}return n}const zs=2e3;function Bs(e){let t=h(e.cwd,`.kickjs`,`types`);if(!r(t))return null;let n=Rs(t);if(n===0)return null;let i=Date.now()-n,a=Math.floor(i/6e4);return a>60?{name:`typegen freshness`,status:`warn`,message:`last updated ${a} minutes ago`,fix:"Re-run `kick typegen` (or `kick dev`, which runs it on every reload) so generated types match the current code."}:{name:`typegen freshness`,status:`pass`,message:a===0?`just now`:`${a}m ago`}}const Vs=[()=>Ds(),Os,ks,js,Ms,Fs,Is,Ls,Bs];async function Hs(e,t={}){let n={cwd:e,pkg:Ss(h(e,`package.json`)),tsconfig:ws(e),runtime:t.runtime??`express`},r=[...Vs,...t.extraChecks??[]],i=[];for(let e of r){let t;try{t=await e(n)}catch(t){i.push({name:e.name||`doctor check`,status:`fail`,message:t instanceof Error?t.message:String(t)});continue}t!=null&&(Array.isArray(t)?i.push(...t):i.push(t))}return i}function Us(e){switch(e){case`pass`:return
|
|
2730
|
-
`).map(e=>` ${
|
|
2731
|
-
`)}function Ks(e){return e?.doctor?.checks??[]}function qs(e){e.command(`doctor`).description(`Pre-flight checks for your KickJS project (dev environment health)`).action(async()=>{let e=process.cwd(),t=Ks(await
|
|
2733
|
+
// ... rest of bootstrap`}}function Is(e){if(!e.tsconfig)return[{name:`tsconfig.json present`,status:`fail`,fix:"Create a tsconfig.json with `experimentalDecorators: true` and `emitDecoratorMetadata: true`. `kick new` scaffolds one automatically."}];let t=e.tsconfig.compilerOptions??{},n=[];return n.push(t.experimentalDecorators===!0?{name:`tsconfig: experimentalDecorators`,status:`pass`}:{name:`tsconfig: experimentalDecorators`,status:`fail`,fix:'Add `"experimentalDecorators": true` to compilerOptions in tsconfig.json. Without it, @Service / @Controller / @Get etc. don\'t register any metadata at compile time.'}),n.push(t.emitDecoratorMetadata===!0?{name:`tsconfig: emitDecoratorMetadata`,status:`pass`}:{name:`tsconfig: emitDecoratorMetadata`,status:`fail`,fix:'Add `"emitDecoratorMetadata": true` to compilerOptions in tsconfig.json. The DI container uses this metadata for constructor-parameter injection.'}),n}function Ls(e){let t=[`src/env.ts`,`src/env/index.ts`,`src/config/env.ts`,`src/config/index.ts`].map(t=>h(e.cwd,t)).filter(e=>r(e)).filter(e=>/\bloadEnv\s*\(/.test(Cs(e)??``));if(t.length===0)return null;let n=[`src/index.ts`,`src/main.ts`].map(t=>h(e.cwd,t)).find(e=>r(e));if(!n)return{name:`env wiring`,status:`warn`,message:`env-init file exists but no src/index.ts or src/main.ts found`};let i=Cs(n)??``,a=f(n),o=[];for(let e of t){let t=_(a,e).replace(/\\/g,`/`).replace(/\.ts$/,``),n=t.startsWith(`.`)?t:`./`+t,r=n.replace(/\/index$/,``);o.push(n,r);let i=e.replace(/\\/g,`/`).match(/\/src\/(.+?)(?:\.ts)?$/);if(i){let e=`@/`+i[1],t=e.replace(/\/index$/,``);o.push(e,t)}}let s=-1;for(let e of new Set(o)){let t=RegExp(`^import\\s+(?:.*?from\\s+)?['"]${Es(e)}['"]`,`m`),n=i.match(t);n&&n.index!==void 0&&(s===-1||n.index<s)&&(s=n.index)}let c=i.search(/\bbootstrap\s*\(/),l=t.map(t=>_(e.cwd,t).replace(/\\/g,`/`)).join(`, `);return s===-1?{name:`env wiring`,status:`fail`,message:l,fix:`An env-init file (${l}) calls \`loadEnv(...)\` but \`${_(e.cwd,n).replace(/\\/g,`/`)}\` doesn't import it.\nWithout this, ConfigService.get('X') returns undefined while @Value('X') works via process.env fallback — a half-broken config you won't notice until something is missing.\n\nFix: add a side-effect import at the top of ${_(e.cwd,n).replace(/\\/g,`/`)} (above bootstrap()), pointing at one of the detected files. For example:\n\n import './env'\n // or\n import './config'\n // or, with the @/ alias:\n import '@/config/env'`}:c!==-1&&s>c?{name:`env wiring`,status:`warn`,message:`env-init imported AFTER bootstrap() — should be before`,fix:`Move the env import above the bootstrap() call so the schema runs before any service reads from ConfigService.`}:{name:`env wiring`,status:`pass`}}function Rs(e,t=zs){let n=0,r=0,i=[e];for(;i.length>0&&r<t;){let e=i.pop(),a;try{a=o(e,{withFileTypes:!0})}catch{continue}for(let o of a){if(r>=t)break;r++;let a=h(e,o.name);if(o.isDirectory()){i.push(a);continue}try{let e=c(a).mtimeMs;e>n&&(n=e)}catch{}}}return n}const zs=2e3;function Bs(e){let t=h(e.cwd,`.kickjs`,`types`);if(!r(t))return null;let n=Rs(t);if(n===0)return null;let i=Date.now()-n,a=Math.floor(i/6e4);return a>60?{name:`typegen freshness`,status:`warn`,message:`last updated ${a} minutes ago`,fix:"Re-run `kick typegen` (or `kick dev`, which runs it on every reload) so generated types match the current code."}:{name:`typegen freshness`,status:`pass`,message:a===0?`just now`:`${a}m ago`}}const Vs=[()=>Ds(),Os,ks,js,Ms,Fs,Is,Ls,Bs];async function Hs(e,t={}){let n={cwd:e,pkg:Ss(h(e,`package.json`)),tsconfig:ws(e),runtime:t.runtime??`express`},r=[...Vs,...t.extraChecks??[]],i=[];for(let e of r){let t;try{t=await e(n)}catch(t){i.push({name:e.name||`doctor check`,status:`fail`,message:t instanceof Error?t.message:String(t)});continue}t!=null&&(Array.isArray(t)?i.push(...t):i.push(t))}return i}function Us(e){switch(e){case`pass`:return O.green(`✔`);case`warn`:return O.yellow(`⚠`);case`fail`:return O.red(`✖`)}}function Ws(e){let t=Us(e.status),n=e.message?` ${O.dim(`(${e.message})`)}`:``;return`${t} ${e.name}${n}`}function Gs(e){return e.split(`
|
|
2734
|
+
`).map(e=>` ${O.dim(`→`)} ${e}`).join(`
|
|
2735
|
+
`)}function Ks(e){return e?.doctor?.checks??[]}function qs(e){e.command(`doctor`).description(`Pre-flight checks for your KickJS project (dev environment health)`).action(async()=>{let e=process.cwd(),t=Ks(await j(e)),n=await St(e);Kt(`KickJS Doctor`);let r=await Hs(e,{extraChecks:t,runtime:n});for(let e of r)I.message(Ws(e)),e.fix&&e.status!==`pass`&&I.message(Gs(e.fix));let i=r.filter(e=>e.status===`pass`).length,a=r.filter(e=>e.status===`warn`).length,o=r.filter(e=>e.status===`fail`).length,s=[O.green(`${i} passed`),a>0?O.yellow(`${a} warning${a===1?``:`s`}`):`${a} warnings`,o>0?O.red(`${o} error${o===1?``:`s`}`):`${o} errors`].join(`, `);o>0?(P(`${s} — fix the errors above before running the app`),process.exit(1)):P(a>0?`${s} — review the warnings`:O.green(`${s} — your environment looks good`))})}function Js(e){return e.optsWithGlobals().dryRun??!1}function Ys(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.
|
|
2732
2736
|
Direction defaults to \`modules.style\` from kick.config (or "define").
|
|
2733
2737
|
--target define|class Override the migration direction.
|
|
2734
2738
|
--apply Apply the changes (default: dry-run preview).
|
|
2735
|
-
--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 n=Js(t)||!e.apply;
|
|
2736
|
-
`+
|
|
2739
|
+
--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 n=Js(t)||!e.apply;M(n),e.experimental||(console.error(`
|
|
2740
|
+
`+O.red(`Error:`)+` kick codemod modules is experimental — pass --experimental to acknowledge.
|
|
2737
2741
|
The regex-based rewrite handles the shapes our templates produce.
|
|
2738
2742
|
Hand-rolled modules with non-standard structures may be skipped.
|
|
2739
2743
|
Always commit before running with --apply.
|
|
2740
|
-
`),process.exit(1));let r=
|
|
2744
|
+
`),process.exit(1));let r=A(await j(process.cwd())),i=v(e.modulesDir??r.dir??`src/modules`),a;e.target===`define`||e.target===`class`?a=e.target:e.target===void 0?a=r.style??`define`:(console.error(`\n ${O.red(`Error:`)} --target must be 'define' or 'class' (got '${e.target}').\n`),process.exit(1));let o=O.dim(`→ ${a}`),s=n?O.dim(`(dry-run)`):O.bold(`(applying)`);console.log(`\n ${O.bold(`kick codemod modules`)} ${o} ${s}`),console.log(` modulesDir: ${O.dim(i)}\n`);let c=e.backup!==!1&&!n,l=await wr(i,{dryRun:n,target:a,backup:c});if(l.backupDir){let e=l.backupDir;console.log(` ${O.green(`✓`)} backup: ${O.dim(e)}\n ${O.dim(`(restore: rm -rf <modulesDir> && mv "<backup>" <modulesDir>)`)}\n`)}else!n&&e.backup===!1&&console.log(` ${O.dim(`(--no-backup — skipping snapshot)`)}\n`);let u=0,d=0;for(let e of l.files)if(e.status===`migrated`)u++,console.log(` ${O.green(`✓`)} ${e.path}`);else{d++;let t=O.dim(`(${e.reason??`skipped`})`);console.log(` ${O.dim(`-`)} ${e.path} ${t}`)}if(console.log(),l.indexStatus===`migrated`)console.log(` ${O.green(`✓`)} ${l.indexPath}`);else if(l.indexStatus===`skipped`){let e=O.dim(`(${l.indexReason??`skipped`})`);console.log(` ${O.dim(`-`)} ${l.indexPath} ${e}`)}else console.log(` ${O.dim(`-`)} ${l.indexPath} ${O.dim(`(not found)`)}`);let f=n?O.dim(` (dry-run — pass --apply to write)`):``;console.log(`\n ${O.bold(String(u))} migrated, ${O.bold(String(d))} skipped${f}\n`)})}const Xs=()=>({id:`kick/assets`,inputs:[`kick.config.ts`,`kick.config.js`,`kick.config.mjs`],async generate(e){if(!r(u.resolve(e.cwd,`kick.config.ts`)))return null;let t=await j(e.cwd);if(!t?.assetMap)return null;let n=wa(t.assetMap,e.cwd);return n.count===0?null:Ta(n)}}),Zs="/* 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 Qs(e,t,n,r={}){if(e.length===0)return`${Zs}
|
|
2741
2745
|
// (no routes discovered yet — annotate a controller method with
|
|
2742
2746
|
// @Get/@Post/@Put/@Delete/@Patch and re-run \`kick typegen\`)
|
|
2743
2747
|
declare global {
|
|
2744
2748
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
2745
|
-
namespace KickRoutes {
|
|
2749
|
+
namespace KickRoutes {
|
|
2750
|
+
// Always present so \`createClient<KickRoutes.Api>\` compiles before the
|
|
2751
|
+
// first route exists (fresh project / pre-controller typegen runs).
|
|
2752
|
+
interface Api {}
|
|
2753
|
+
}
|
|
2746
2754
|
}
|
|
2747
2755
|
|
|
2748
2756
|
export {}
|
|
2749
|
-
`;let i=new Map;for(let t of e){let e=i.get(t.controller)??[];e.push(t),i.set(t.controller,e)}let a=new Map,o=(e,i,o)=>{let s=tc(e,i.filePath,t,n,a);if(!s){if(e&&n!==!1){let t=o===`params`?`URL-pattern params`:o===`query`&&i.queryFilterable!==null?`the @ApiQueryParams-derived query shape`:`'unknown'`;r.onWarn?.(`route ${i.controller}.${i.method} (${i.httpMethod} ${i.path}): ${o} schema '${e.identifier}' could not be statically resolved — falling back to ${t}. Export the schema from the controller file or import it with a static specifier.`)}return null}return n===`kickjs-schema`?`import('@forinda/kickjs-schema').InferSchemaOutput<typeof ${s}>`:`import('zod').infer<typeof ${s}>`},
|
|
2750
|
-
`))}
|
|
2757
|
+
`;let i=new Map;for(let t of e){let e=i.get(t.controller)??[];e.push(t),i.set(t.controller,e)}let a=new Map,o=new Map,s=e=>{let t=`${e.filePath}::${e.controller}`,n=o.get(t);return n||(n=`_C${o.size}`,o.set(t,n)),n},c=(e,i,o)=>{let s=tc(e,i.filePath,t,n,a);if(!s){if(e&&n!==!1){let t=o===`params`?`URL-pattern params`:o===`query`&&i.queryFilterable!==null?`the @ApiQueryParams-derived query shape`:`'unknown'`;r.onWarn?.(`route ${i.controller}.${i.method} (${i.httpMethod} ${i.path}): ${o} schema '${e.identifier}' could not be statically resolved — falling back to ${t}. Export the schema from the controller file or import it with a static specifier.`)}return null}return n===`kickjs-schema`?`import('@forinda/kickjs-schema').InferSchemaOutput<typeof ${s}>`:`import('zod').infer<typeof ${s}>`},l=[];for(let[e,t]of i){let n=[` interface ${e} {`];for(let e of t){let t=e.pathParams.length>0?`{ ${e.pathParams.map(e=>`${e}: string`).join(`; `)} }`:`{}`,r=c(e.bodySchema,e,`body`),i=c(e.querySchema,e,`query`),a=c(e.paramsSchema,e,`params`)??t,o=r??`unknown`,l=i??$s(e),u=`import('@forinda/kickjs').InferHandlerResponse<${s(e)}['${e.method}']>`,d=ec(e);n.push(` /**`,` * ${e.httpMethod} ${e.path}`,...d.map(e=>` * ${e}`),` */`,` ${e.method}: {`,` params: ${a}`,` body: ${o}`,` query: ${l}`,` response: ${u}`,` }`)}n.push(` }`),l.push(n.join(`
|
|
2758
|
+
`))}let u=[],d=new Set;i.has(`Api`)&&r.onWarn?.(`controller class 'Api' collides with the reserved KickRoutes.Api client map — its interface declaration-merges into the flat route map. Rename the controller.`);for(let[e,t]of i)for(let n of t){let t=`${n.httpMethod} ${n.mountedPath??n.path}`;if(d.has(t)){r.onWarn?.(`duplicate route '${t}' (${e}.${n.method}) — two handlers claim the same verb+path at runtime. KickRoutes.Api keeps the first (scan order, which may not match runtime dispatch); resolve the conflict in the modules.`);continue}d.add(t),u.push(` '${t}': ${e}['${n.method}']`)}let f=[` interface Api {`,...u,` }`].join(`
|
|
2759
|
+
`);l.push(f);let p=[],m=new Map;for(let t of e)m.set(`${t.filePath}::${t.controller}`,t);for(let[e,n]of o){let r=m.get(e),i=rc(``,r.filePath,t),a=r.controllerIsDefaultExport?`default as ${n}`:`${r.controller} as ${n}`;p.push(`import type { ${a} } from '${i}'`)}let h=p.length>0?p.join(`
|
|
2760
|
+
`)+`
|
|
2761
|
+
`:``,g=nc(a)+h,_=l.join(`
|
|
2762
|
+
`);return`${Zs}${g}
|
|
2751
2763
|
declare global {
|
|
2752
2764
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
2753
2765
|
namespace KickRoutes {
|
|
2754
|
-
${
|
|
2755
|
-
`)}
|
|
2766
|
+
${_}
|
|
2756
2767
|
}
|
|
2757
2768
|
}
|
|
2758
2769
|
|
|
@@ -2798,4 +2809,4 @@ declare global {
|
|
|
2798
2809
|
|
|
2799
2810
|
export {}
|
|
2800
2811
|
`}const cc=()=>({id:`kick/env`,outExtension:`.ts`,inputs:[`src/env.ts`,`src/**/env.ts`,`src/**/*.env.ts`],async generate(e){let t=uc(e);if(t===!1)return null;let n=await e.getScanResult({root:lc(e),cwd:e.cwd,envFile:t});if(!n.env)return null;let r=e.config?.typegen?.schemaValidator??`zod`,i=u.resolve(e.cwd,`.kickjs/types/kick__env.ts`);return sc(n.env,i,r)}});function lc(e){return u.resolve(e.cwd,e.config?.typegen?.srcDir??`src`)}function uc(e){return e.config?.typegen?.envFile}function dc(e){return u.resolve(e.cwd,e.config?.typegen?.srcDir??`src`)}function fc(e){let t=e.config?.typegen?.envFile;if(t!==!1)return t}function pc(e){return{root:dc(e),cwd:e.cwd,envFile:fc(e)}}const mc=()=>({id:`kick/registry`,inputs:[`src/**/*.ts`],async generate(e){let t=await e.getScanResult(pc(e)),n=u.resolve(e.cwd,`.kickjs/types/kick__registry.d.ts`),r=new Set(t.collisions.map(e=>e.className));return pa(t.classes,n,r)}}),hc=()=>({id:`kick/services`,inputs:[`src/**/*.ts`],async generate(e){let t=await e.getScanResult(pc(e)),n=new Set(t.collisions.map(e=>e.className));return ga(`ServiceToken`,_a(t.classes,t.tokens,t.injects,n),"(no tokens discovered — declare with createToken<T>() or `kick g service <name>`)")}}),gc=()=>({id:`kick/modules`,inputs:[`src/**/*.ts`],async generate(e){return ga(`ModuleToken`,va((await e.getScanResult(pc(e))).classes),"(no @Module classes discovered — `kick g module <name>` to add one)")}}),_c=()=>({id:`kick/plugins`,inputs:[`src/**/*.ts`],async generate(e){return ya((await e.getScanResult(pc(e))).pluginsAndAdapters)}}),vc=()=>({id:`kick/augmentations`,inputs:[`src/**/*.ts`],async generate(e){return ba((await e.getScanResult(pc(e))).augmentations)}}),yc=()=>({id:`kick/context`,inputs:[`src/**/*.ts`],async generate(e){let t=await e.getScanResult(pc(e));return t.contextKeys.length===0?null:ha(t.contextKeys)}}),bc={fastify:{subpath:`@forinda/kickjs/fastify`,typeName:`FastifyRuntimeTypes`},h3:{subpath:`@forinda/kickjs/h3`,typeName:`H3RuntimeTypes`}},xc=()=>({id:`kick/runtime`,outExtension:`.ts`,inputs:[`kick.config.ts`,`kick.config.js`,`kick.config.mjs`,`kick.config.json`],async generate(e){let t=e.config?.runtime;if(t!==`fastify`&&t!==`h3`)return null;let{subpath:n,typeName:r}=bc[t];return[`// Runtime escape-hatch types for the '${t}' engine (kick.config runtime).`,`declare module '@forinda/kickjs' {`,` interface KickRuntimeRegister {`,` runtime: import('${n}').${r}`,` }`,`}`,``,`export {}`,``].join(`
|
|
2801
|
-
`)}});var Sc=
|
|
2812
|
+
`)}});var Sc=k({builtinCliPlugins:()=>Cc});const Cc=[E({name:`kick/init`,register:$t}),E({name:`kick/generate`,register:Ga}),E({name:`kick/run`,register:mo}),E({name:`kick/info`,register:yo}),E({name:`kick/inspect`,register:ko}),E({name:`kick/add`,register:Mt}),E({name:`kick/list`,register:jt}),E({name:`kick/explain`,register:zo}),E({name:`kick/mcp`,register:Xo}),E({name:`kick/tinker`,register:es}),E({name:`kick/remove`,register:os}),E({name:`kick/typegen`,register:ls}),E({name:`kick/check`,register:xs}),E({name:`kick/doctor`,register:qs}),E({name:`kick/codemod`,register:Ys}),E({name:`kick/registry`,typegens:[mc()]}),E({name:`kick/services`,typegens:[hc()]}),E({name:`kick/modules`,typegens:[gc()]}),E({name:`kick/plugins`,typegens:[_c()]}),E({name:`kick/augmentations`,typegens:[vc()]}),E({name:`kick/context`,typegens:[yc()]}),E({name:`kick/assets`,typegens:[Xs()]}),E({name:`kick/routes`,typegens:[ic()]}),E({name:`kick/env`,typegens:[cc()]}),E({name:`kick/runtime`,typegens:[xc()]})],wc=f(b(import.meta.url)),Tc=JSON.parse(a(h(wc,`..`,`package.json`),`utf-8`));async function Ec(){let e=new t;e.name(`kick`).description(`KickJS — A production-grade, decorator-driven Node.js framework`).version(Tc.version);let n=rn(process.cwd()),r=n,i=await j(r)??{},a=Ie([...Cc,...i.plugins??[]],i.commands??[]);await a.register(e,{cwd:r,projectRoot:n,config:i,log:e=>console.log(e)}),Se(e,{...i,commands:a.commands}),e.showHelpAfterError();let o=process.argv.map(e=>e===`-v`?`--version`:e);await e.parseAsync(o)}Ec().catch(e=>{console.error(e instanceof Error?e.message:e),process.exitCode=1});export{N as i,Ht as n,Lt as r,Aa as t};
|