@forinda/kickjs-cli 5.3.2 → 5.4.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/{builtins-CnQ6lxcV.mjs → builtins-DBzZkJey.mjs} +151 -90
- package/dist/builtins-DBzZkJey.mjs.map +1 -0
- package/dist/{builtins-BxGfcEP6.mjs → builtins-K-nRJcJG.mjs} +409 -214
- package/dist/cli.mjs +2 -2
- package/dist/config-CCNnXhar.mjs +11 -0
- package/dist/config-CQZ6Hppr.mjs +12 -0
- package/dist/config-CQZ6Hppr.mjs.map +1 -0
- package/dist/{generator-extension-BNgcYlom.mjs → generator-extension-Bn2aH7kY.mjs} +228 -94
- package/dist/generator-extension-Bn2aH7kY.mjs.map +1 -0
- package/dist/index.d.mts +45 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/{plugin-B56zClEX.mjs → plugin-D0C4ISZA.mjs} +2 -2
- package/dist/{plugin-Ccvf-gn6.mjs → plugin-DasN_2Zr.mjs} +3 -3
- package/dist/{plugin-Ccvf-gn6.mjs.map → plugin-DasN_2Zr.mjs.map} +1 -1
- package/dist/{rolldown-runtime-CP9PNXAB.mjs → rolldown-runtime-BTpMa50s.mjs} +1 -1
- package/dist/{run-plugins-sjeIm8hS.mjs → run-plugins-Dk7KBKON.mjs} +2 -2
- package/dist/{typegen-CYA1y8NJ.mjs → typegen-Bl9kUVNL.mjs} +4 -4
- package/dist/{typegen-CYA1y8NJ.mjs.map → typegen-Bl9kUVNL.mjs.map} +1 -1
- package/dist/{typegen-CFW1vIgv.mjs → typegen-DDQJNnUl.mjs} +3 -3
- package/dist/{types-2ICiQzlQ.mjs → types-kAfWJgh0.mjs} +2 -2
- package/dist/{types-2ICiQzlQ.mjs.map → types-kAfWJgh0.mjs.map} +1 -1
- package/package.json +2 -2
- package/dist/builtins-CnQ6lxcV.mjs.map +0 -1
- package/dist/config-B5g_GsV2.mjs +0 -12
- package/dist/config-B5g_GsV2.mjs.map +0 -1
- package/dist/config-DE9Vo6LN.mjs +0 -11
- package/dist/generator-extension-BNgcYlom.mjs.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @forinda/kickjs-cli v5.
|
|
2
|
+
* @forinda/kickjs-cli v5.4.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Felix Orinda
|
|
5
5
|
*
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
|
-
import{createRequire as e}from"node:module";import{dirname as t,extname as n,join as r,resolve as i}from"node:path";import{existsSync as a,readFileSync as o}from"node:fs";import{access as s,mkdir as c,readFile as l,writeFile as u}from"node:fs/promises";import*as d from"@clack/prompts";import f from"picocolors";import p from"pluralize";import{execSync as m}from"node:child_process";import{fileURLToPath as h,pathToFileURL as g}from"node:url";let _=!1;function v(e){_=e}const y=new Set([`.ts`,`.tsx`,`.js`,`.jsx`,`.mjs`,`.cjs`,`.json`,`.md`]);async function b(e,r){_||(await c(t(e),{recursive:!0}),await u(e,r,`utf-8`),y.has(n(e))&&await te(e,r).catch(()=>{}))}let x;async function ee(t){if(x!==void 0)return x;try{x=await import(e(r(t,`package.json`)).resolve(`oxfmt`))}catch{x=null}return x}async function te(e,t){let n=await ee(process.cwd());if(!n)return;let r=await ne(e);if(r===null)return;let i=await n.format(e,t,r);i.code!==t&&await u(e,i.code,`utf-8`)}const S=new Map;async function ne(e){let n=t(e),i=n;if(S.has(i))return S.get(i);for(;;){let e=r(n,`.oxfmtrc.json`);if(a(e))try{let t=await l(e,`utf-8`),n=JSON.parse(t);return delete n.$schema,delete n.ignorePatterns,S.set(i,n),n}catch{return S.set(i,null),null}let o=t(n);if(o===n)return S.set(i,null),null;n=o}}async function C(e){try{return await s(e),!0}catch{return!1}}const re={GET:f.green,POST:f.cyan,PUT:f.yellow,PATCH:f.magenta,DELETE:f.red};function ie(e){return(re[e]??f.dim)(e.padEnd(7))}function ae(e){let t=`[${e}]`.padEnd(10);switch(e){case`CRITICAL`:return f.red(t);case`WARNING`:return f.yellow(t);case`INFO`:return f.blue(f.dim(t));default:return t}}f.green(`✓`),f.red(`✖`),f.yellow(`⚠`),f.blue(`ℹ`);function oe(e){d.intro(f.bgCyan(f.black(` ${e} `)))}function se(e){d.outro(e)}function w(e){d.isCancel(e)&&(d.cancel(`Operation cancelled.`),process.exit(0))}async function ce(e){let t=await d.text(e);return w(t),t}async function le(e){let t=await d.select(e);return w(t),t}async function ue(e){let t=await d.multiselect(e);return w(t),t}async function T(e){let t=await d.confirm(e);return w(t),t}function de(){return d.spinner()}const E=d.log;function D(e){return e.replace(/[-_\s]+(.)?/g,(e,t)=>t?t.toUpperCase():``).replace(/^(.)/,e=>e.toUpperCase())}function O(e){let t=D(e);return t.charAt(0).toLowerCase()+t.slice(1)}function k(e){return e.replace(/([a-z])([A-Z])/g,`$1-$2`).replace(/[\s_]+/g,`-`).toLowerCase()}function A(e){return p.plural(e)}function j(e){return p.plural(e)}const fe={inmemory:`in-memory`,drizzle:`Drizzle`,prisma:`Prisma`};function M(e){return e.charAt(0).toUpperCase()+e.slice(1).replace(/-([a-z])/g,(e,t)=>t.toUpperCase())}function pe(e){return e.replace(/([a-z])([A-Z])/g,`$1-$2`).toLowerCase()}function N(e){return fe[e]??M(e)}function P(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]??`${M(n)}${e}Repository`,repoFile:i[n]??`${pe(n)}-${t}`}}function me(e){let{pascal:t,kebab:n,plural:r=``,repo:i}=e,{repoClass:
|
|
11
|
+
import{createRequire as e}from"node:module";import{dirname as t,extname as n,join as r,resolve as i}from"node:path";import{existsSync as a,readFileSync as o}from"node:fs";import{access as s,mkdir as c,readFile as l,writeFile as u}from"node:fs/promises";import*as d from"@clack/prompts";import f from"picocolors";import p from"pluralize";import{execSync as m}from"node:child_process";import{fileURLToPath as h,pathToFileURL as g}from"node:url";let _=!1;function v(e){_=e}const y=new Set([`.ts`,`.tsx`,`.js`,`.jsx`,`.mjs`,`.cjs`,`.json`,`.md`]);async function b(e,r){_||(await c(t(e),{recursive:!0}),await u(e,r,`utf-8`),y.has(n(e))&&await te(e,r).catch(()=>{}))}let x;async function ee(t){if(x!==void 0)return x;try{x=await import(e(r(t,`package.json`)).resolve(`oxfmt`))}catch{x=null}return x}async function te(e,t){let n=await ee(process.cwd());if(!n)return;let r=await ne(e);if(r===null)return;let i=await n.format(e,t,r);i.code!==t&&await u(e,i.code,`utf-8`)}const S=new Map;async function ne(e){let n=t(e),i=n;if(S.has(i))return S.get(i);for(;;){let e=r(n,`.oxfmtrc.json`);if(a(e))try{let t=await l(e,`utf-8`),n=JSON.parse(t);return delete n.$schema,delete n.ignorePatterns,S.set(i,n),n}catch{return S.set(i,null),null}let o=t(n);if(o===n)return S.set(i,null),null;n=o}}async function C(e){try{return await s(e),!0}catch{return!1}}const re={GET:f.green,POST:f.cyan,PUT:f.yellow,PATCH:f.magenta,DELETE:f.red};function ie(e){return(re[e]??f.dim)(e.padEnd(7))}function ae(e){let t=`[${e}]`.padEnd(10);switch(e){case`CRITICAL`:return f.red(t);case`WARNING`:return f.yellow(t);case`INFO`:return f.blue(f.dim(t));default:return t}}f.green(`✓`),f.red(`✖`),f.yellow(`⚠`),f.blue(`ℹ`);function oe(e){d.intro(f.bgCyan(f.black(` ${e} `)))}function se(e){d.outro(e)}function w(e){d.isCancel(e)&&(d.cancel(`Operation cancelled.`),process.exit(0))}async function ce(e){let t=await d.text(e);return w(t),t}async function le(e){let t=await d.select(e);return w(t),t}async function ue(e){let t=await d.multiselect(e);return w(t),t}async function T(e){let t=await d.confirm(e);return w(t),t}function de(){return d.spinner()}const E=d.log;function D(e){return e.replace(/[-_\s]+(.)?/g,(e,t)=>t?t.toUpperCase():``).replace(/^(.)/,e=>e.toUpperCase())}function O(e){let t=D(e);return t.charAt(0).toLowerCase()+t.slice(1)}function k(e){return e.replace(/([a-z])([A-Z])/g,`$1-$2`).replace(/[\s_]+/g,`-`).toLowerCase()}function A(e){return p.plural(e)}function j(e){return p.plural(e)}const fe={inmemory:`in-memory`,drizzle:`Drizzle`,prisma:`Prisma`};function M(e){return e.charAt(0).toUpperCase()+e.slice(1).replace(/-([a-z])/g,(e,t)=>t.toUpperCase())}function pe(e){return e.replace(/([a-z])([A-Z])/g,`$1-$2`).toLowerCase()}function N(e){return fe[e]??M(e)}function P(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]??`${M(n)}${e}Repository`,repoFile:i[n]??`${pe(n)}-${t}`}}function F(e){return e??`define`}function me(e){let{pascal:t,kebab:n,plural:r=``,repo:i,style:a}=e,{repoClass:o,repoFile:s}=P(t,n,i),c=F(a),l=`/**
|
|
12
12
|
* ${t} Module
|
|
13
13
|
*
|
|
14
14
|
* Self-contained feature module following Domain-Driven Design (DDD).
|
|
@@ -19,18 +19,34 @@ import{createRequire as e}from"node:module";import{dirname as t,extname as n,joi
|
|
|
19
19
|
* application/ — Use cases (orchestration) and DTOs (validation)
|
|
20
20
|
* domain/ — Entities, value objects, repository interfaces, domain services
|
|
21
21
|
* infrastructure/ — Repository implementations (currently ${N(i)})
|
|
22
|
-
|
|
23
|
-
import {
|
|
24
|
-
import { buildRoutes } from '@forinda/kickjs'
|
|
25
|
-
import { ${t.toUpperCase()}_REPOSITORY } from './domain/repositories/${n}.repository'
|
|
26
|
-
import { ${a} } from './infrastructure/repositories/${o}.repository'
|
|
22
|
+
*/`,u=`import { ${t.toUpperCase()}_REPOSITORY } from './domain/repositories/${n}.repository'
|
|
23
|
+
import { ${o} } from './infrastructure/repositories/${s}.repository'
|
|
27
24
|
import { ${t}Controller } from './presentation/${n}.controller'
|
|
28
25
|
|
|
29
26
|
// Eagerly load decorated classes so @Service()/@Repository() decorators register in the DI container
|
|
30
27
|
import.meta.glob(
|
|
31
28
|
['./domain/services/**/*.ts', './application/use-cases/**/*.ts', '!./**/*.test.ts'],
|
|
32
29
|
{ eager: true },
|
|
33
|
-
)
|
|
30
|
+
)`,d=` /**
|
|
31
|
+
* Declare HTTP routes for this module.
|
|
32
|
+
*
|
|
33
|
+
* The path is prefixed with the global apiPrefix and version
|
|
34
|
+
* (e.g. /api/v1/${r}). The framework derives the Express
|
|
35
|
+
* Router from the controller via \`buildRoutes()\` and uses the
|
|
36
|
+
* same controller for OpenAPI spec generation via SwaggerAdapter.
|
|
37
|
+
*
|
|
38
|
+
* Return an **array** to mount multiple route sets under the
|
|
39
|
+
* same module (e.g. side-by-side v1 + v2 controllers). Each
|
|
40
|
+
* entry can override the API version with a \`version\` field —
|
|
41
|
+
* the mount path becomes \`/{apiPrefix}/v{version}{path}\`:
|
|
42
|
+
*
|
|
43
|
+
* return [
|
|
44
|
+
* { path: '/${r}', version: 1, controller: ${t}V1Controller },
|
|
45
|
+
* { path: '/${r}', version: 2, controller: ${t}V2Controller },
|
|
46
|
+
* ]
|
|
47
|
+
*/`;return c===`class`?`${l}
|
|
48
|
+
import { Container, type AppModule, type ModuleRoutes } from '@forinda/kickjs'
|
|
49
|
+
${u}
|
|
34
50
|
|
|
35
51
|
export class ${t}Module implements AppModule {
|
|
36
52
|
/**
|
|
@@ -40,24 +56,46 @@ export class ${t}Module implements AppModule {
|
|
|
40
56
|
*/
|
|
41
57
|
register(container: Container): void {
|
|
42
58
|
container.registerFactory(${t.toUpperCase()}_REPOSITORY, () =>
|
|
43
|
-
container.resolve(${
|
|
59
|
+
container.resolve(${o}),
|
|
44
60
|
)
|
|
45
61
|
}
|
|
46
62
|
|
|
47
|
-
|
|
48
|
-
* Declare HTTP routes for this module.
|
|
49
|
-
* The path is prefixed with the global apiPrefix and version (e.g. /api/v1/${r}).
|
|
50
|
-
* Passing 'controller' enables automatic OpenAPI spec generation via SwaggerAdapter.
|
|
51
|
-
*/
|
|
63
|
+
${d.replace(/^ {4}/gm,` `).replace(/^ {6}/gm,` `)}
|
|
52
64
|
routes(): ModuleRoutes {
|
|
53
65
|
return {
|
|
54
66
|
path: '/${r}',
|
|
55
|
-
router: buildRoutes(${t}Controller),
|
|
56
67
|
controller: ${t}Controller,
|
|
57
68
|
}
|
|
58
69
|
}
|
|
59
70
|
}
|
|
60
|
-
|
|
71
|
+
`:`${l}
|
|
72
|
+
import { defineModule } from '@forinda/kickjs'
|
|
73
|
+
${u}
|
|
74
|
+
|
|
75
|
+
export const ${t}Module = defineModule({
|
|
76
|
+
name: '${t}Module',
|
|
77
|
+
build: () => ({
|
|
78
|
+
/**
|
|
79
|
+
* Register module dependencies in the DI container.
|
|
80
|
+
* Bind repository interface tokens to their implementations here.
|
|
81
|
+
* Currently wired to ${N(i)}. To swap implementations, change the factory target.
|
|
82
|
+
*/
|
|
83
|
+
register(container) {
|
|
84
|
+
container.registerFactory(${t.toUpperCase()}_REPOSITORY, () =>
|
|
85
|
+
container.resolve(${o}),
|
|
86
|
+
)
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
${d}
|
|
90
|
+
routes() {
|
|
91
|
+
return {
|
|
92
|
+
path: '/${r}',
|
|
93
|
+
controller: ${t}Controller,
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
}),
|
|
97
|
+
})
|
|
98
|
+
`}function he(e){let{pascal:t,kebab:n,plural:r=``,repo:i,style:a}=e,{repoClass:o,repoFile:s}=P(t,n,i),c=F(a),l=`/**
|
|
61
99
|
* ${t} Module
|
|
62
100
|
*
|
|
63
101
|
* REST module with a flat folder structure.
|
|
@@ -67,46 +105,106 @@ export class ${t}Module implements AppModule {
|
|
|
67
105
|
* ${n}.controller.ts — HTTP routes (CRUD)
|
|
68
106
|
* ${n}.service.ts — Business logic
|
|
69
107
|
* ${n}.repository.ts — Repository interface
|
|
70
|
-
* ${
|
|
108
|
+
* ${s}.repository.ts — Repository implementation
|
|
71
109
|
* dtos/ — Request/response schemas
|
|
72
|
-
|
|
73
|
-
import {
|
|
74
|
-
import { buildRoutes } from '@forinda/kickjs'
|
|
75
|
-
import { ${t.toUpperCase()}_REPOSITORY } from './${n}.repository'
|
|
76
|
-
import { ${a} } from './${o}.repository'
|
|
110
|
+
*/`,u=`import { ${t.toUpperCase()}_REPOSITORY } from './${n}.repository'
|
|
111
|
+
import { ${o} } from './${s}.repository'
|
|
77
112
|
import { ${t}Controller } from './${n}.controller'
|
|
78
113
|
|
|
79
114
|
// Eagerly load decorated classes so @Service()/@Repository() decorators register in the DI container
|
|
80
|
-
import.meta.glob(['./**/*.service.ts', './**/*.repository.ts', '!./**/*.test.ts'], { eager: true })
|
|
115
|
+
import.meta.glob(['./**/*.service.ts', './**/*.repository.ts', '!./**/*.test.ts'], { eager: true })`,d=` /**
|
|
116
|
+
* Declare HTTP routes for this module.
|
|
117
|
+
*
|
|
118
|
+
* Pass \`controller\` and the framework derives the Express
|
|
119
|
+
* Router via \`buildRoutes()\` and uses the same controller for
|
|
120
|
+
* OpenAPI spec generation through SwaggerAdapter.
|
|
121
|
+
*
|
|
122
|
+
* Return an **array** to mount multiple route sets under the
|
|
123
|
+
* same module (side-by-side v1 + v2 controllers, admin surfaces).
|
|
124
|
+
* Each entry can override the API version with a \`version\` field:
|
|
125
|
+
*
|
|
126
|
+
* return [
|
|
127
|
+
* { path: '/${r}', version: 1, controller: ${t}V1Controller },
|
|
128
|
+
* { path: '/${r}', version: 2, controller: ${t}V2Controller },
|
|
129
|
+
* ]
|
|
130
|
+
*/`;return c===`class`?`${l}
|
|
131
|
+
import { Container, type AppModule, type ModuleRoutes } from '@forinda/kickjs'
|
|
132
|
+
${u}
|
|
81
133
|
|
|
82
134
|
export class ${t}Module implements AppModule {
|
|
83
135
|
register(container: Container): void {
|
|
84
136
|
container.registerFactory(${t.toUpperCase()}_REPOSITORY, () =>
|
|
85
|
-
container.resolve(${
|
|
137
|
+
container.resolve(${o}),
|
|
86
138
|
)
|
|
87
139
|
}
|
|
88
140
|
|
|
141
|
+
${d.replace(/^ {4}/gm,` `).replace(/^ {6}/gm,` `)}
|
|
89
142
|
routes(): ModuleRoutes {
|
|
90
143
|
return {
|
|
91
144
|
path: '/${r}',
|
|
92
|
-
router: buildRoutes(${t}Controller),
|
|
93
145
|
controller: ${t}Controller,
|
|
94
146
|
}
|
|
95
147
|
}
|
|
96
148
|
}
|
|
97
|
-
|
|
98
|
-
import {
|
|
149
|
+
`:`${l}
|
|
150
|
+
import { defineModule } from '@forinda/kickjs'
|
|
151
|
+
${u}
|
|
152
|
+
|
|
153
|
+
export const ${t}Module = defineModule({
|
|
154
|
+
name: '${t}Module',
|
|
155
|
+
build: () => ({
|
|
156
|
+
register(container) {
|
|
157
|
+
container.registerFactory(${t.toUpperCase()}_REPOSITORY, () =>
|
|
158
|
+
container.resolve(${o}),
|
|
159
|
+
)
|
|
160
|
+
},
|
|
161
|
+
|
|
162
|
+
${d}
|
|
163
|
+
routes() {
|
|
164
|
+
return {
|
|
165
|
+
path: '/${r}',
|
|
166
|
+
controller: ${t}Controller,
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
}),
|
|
170
|
+
})
|
|
171
|
+
`}function ge(e){let{pascal:t,kebab:n,plural:r=``,style:i}=e,a=F(i),o=` /**
|
|
172
|
+
* Pass \`controller\` and the framework derives the Express
|
|
173
|
+
* Router via \`buildRoutes()\`. Return an array to mount multiple
|
|
174
|
+
* route sets — each entry can override the API version with a
|
|
175
|
+
* \`version\` field:
|
|
176
|
+
*
|
|
177
|
+
* return [
|
|
178
|
+
* { path: '/${r}', version: 1, controller: ${t}V1Controller },
|
|
179
|
+
* { path: '/${r}', version: 2, controller: ${t}V2Controller },
|
|
180
|
+
* ]
|
|
181
|
+
*/`;return a===`class`?`import { type AppModule, type ModuleRoutes } from '@forinda/kickjs'
|
|
99
182
|
import { ${t}Controller } from './${n}.controller'
|
|
100
183
|
|
|
101
184
|
export class ${t}Module implements AppModule {
|
|
185
|
+
${o.replace(/^ {4}/gm,` `).replace(/^ {6}/gm,` `)}
|
|
102
186
|
routes(): ModuleRoutes {
|
|
103
187
|
return {
|
|
104
188
|
path: '/${r}',
|
|
105
|
-
router: buildRoutes(${t}Controller),
|
|
106
189
|
controller: ${t}Controller,
|
|
107
190
|
}
|
|
108
191
|
}
|
|
109
192
|
}
|
|
193
|
+
`:`import { defineModule } from '@forinda/kickjs'
|
|
194
|
+
import { ${t}Controller } from './${n}.controller'
|
|
195
|
+
|
|
196
|
+
export const ${t}Module = defineModule({
|
|
197
|
+
name: '${t}Module',
|
|
198
|
+
build: () => ({
|
|
199
|
+
${o}
|
|
200
|
+
routes() {
|
|
201
|
+
return {
|
|
202
|
+
path: '/${r}',
|
|
203
|
+
controller: ${t}Controller,
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
}),
|
|
207
|
+
})
|
|
110
208
|
`}function _e(e){let{pascal:t,kebab:n,plural:r=``,pluralPascal:i=``}=e;return`import { Controller, Get, Post, Put, Delete, Autowired, ApiQueryParams, type Ctx } from '@forinda/kickjs'
|
|
111
209
|
import { ApiTags } from '@forinda/kickjs-swagger'
|
|
112
210
|
import { Create${t}UseCase } from '../application/use-cases/create-${n}.use-case'
|
|
@@ -232,7 +330,7 @@ export const ${t.toUpperCase()}_QUERY_CONFIG: QueryParamsConfig = {
|
|
|
232
330
|
sortable: ['name', 'createdAt'],
|
|
233
331
|
searchable: ['name'],
|
|
234
332
|
}
|
|
235
|
-
`}function
|
|
333
|
+
`}function I(e){let{pascal:t}=e;return`import { z } from 'zod'
|
|
236
334
|
|
|
237
335
|
/**
|
|
238
336
|
* Create ${t} DTO — Zod schema for validating POST request bodies.
|
|
@@ -248,14 +346,14 @@ export const create${t}Schema = z.object({
|
|
|
248
346
|
})
|
|
249
347
|
|
|
250
348
|
export type Create${t}DTO = z.infer<typeof create${t}Schema>
|
|
251
|
-
`}function
|
|
349
|
+
`}function L(e){let{pascal:t}=e;return`import { z } from 'zod'
|
|
252
350
|
|
|
253
351
|
export const update${t}Schema = z.object({
|
|
254
352
|
name: z.string().min(1).max(200).optional(),
|
|
255
353
|
})
|
|
256
354
|
|
|
257
355
|
export type Update${t}DTO = z.infer<typeof update${t}Schema>
|
|
258
|
-
`}function
|
|
356
|
+
`}function R(e){let{pascal:t}=e;return`export interface ${t}ResponseDTO {
|
|
259
357
|
id: string
|
|
260
358
|
name: string
|
|
261
359
|
createdAt: string
|
|
@@ -339,7 +437,7 @@ export class Delete${t}UseCase {
|
|
|
339
437
|
await this.repo.delete(id)
|
|
340
438
|
}
|
|
341
439
|
}
|
|
342
|
-
`}]}function
|
|
440
|
+
`}]}function z(e){let{pascal:t,kebab:n,dtoPrefix:r=`../../application/dtos`,tokenScope:i=`app`}=e;return`/**
|
|
343
441
|
* ${t} Repository Interface
|
|
344
442
|
*
|
|
345
443
|
* Defines the contract for data access.
|
|
@@ -374,7 +472,7 @@ export interface I${t}Repository {
|
|
|
374
472
|
* adopters must NOT use the reserved \`'kick/'\` namespace.
|
|
375
473
|
*/
|
|
376
474
|
export const ${t.toUpperCase()}_REPOSITORY = createToken<I${t}Repository>('${i}/${t}/repository')
|
|
377
|
-
`}function
|
|
475
|
+
`}function B(e){let{pascal:t,kebab:n,repoPrefix:r=`../../domain/repositories`,dtoPrefix:i=`../../application/dtos`}=e;return`/**
|
|
378
476
|
* In-Memory ${t} Repository
|
|
379
477
|
*
|
|
380
478
|
* Implements the repository interface using a Map.
|
|
@@ -434,7 +532,7 @@ export class InMemory${t}Repository implements I${t}Repository {
|
|
|
434
532
|
this.store.delete(id)
|
|
435
533
|
}
|
|
436
534
|
}
|
|
437
|
-
`}function
|
|
535
|
+
`}function V(e){let{pascal:t,kebab:n,repoType:r=``,repoPrefix:i=`../../domain/repositories`,dtoPrefix:a=`../../application/dtos`}=e,o=r.charAt(0).toUpperCase()+r.slice(1).replace(/-([a-z])/g,(e,t)=>t.toUpperCase());return`/**
|
|
438
536
|
* ${o} ${t} Repository
|
|
439
537
|
*
|
|
440
538
|
* Stub implementation for a custom '${r}' repository.
|
|
@@ -629,7 +727,7 @@ export class ${t}Id {
|
|
|
629
727
|
return this.value === other.value
|
|
630
728
|
}
|
|
631
729
|
}
|
|
632
|
-
`}function
|
|
730
|
+
`}function H(e){let{pascal:t,kebab:n,plural:r=``}=e;return`import { describe, it, expect, beforeEach } from 'vitest'
|
|
633
731
|
import { Container } from '@forinda/kickjs'
|
|
634
732
|
|
|
635
733
|
describe('${t}Controller', () => {
|
|
@@ -681,7 +779,7 @@ describe('${t}Controller', () => {
|
|
|
681
779
|
})
|
|
682
780
|
})
|
|
683
781
|
})
|
|
684
|
-
`}function
|
|
782
|
+
`}function U(e){let{pascal:t,kebab:n,plural:r=``,repoPrefix:i=`../infrastructure/repositories/in-memory-${n}.repository`}=e;return`import { describe, it, expect, beforeEach } from 'vitest'
|
|
685
783
|
import { InMemory${t}Repository } from '${i}'
|
|
686
784
|
|
|
687
785
|
describe('InMemory${t}Repository', () => {
|
|
@@ -780,14 +878,14 @@ export class ${t}Service {
|
|
|
780
878
|
await this.repo.delete(id)
|
|
781
879
|
}
|
|
782
880
|
}
|
|
783
|
-
`}function
|
|
881
|
+
`}function W(e){let{pascal:t}=e;return`import type { QueryFieldConfig } from '@forinda/kickjs'
|
|
784
882
|
|
|
785
883
|
export const ${t.toUpperCase()}_QUERY_CONFIG: QueryFieldConfig = {
|
|
786
884
|
filterable: ['name'],
|
|
787
885
|
sortable: ['name', 'createdAt'],
|
|
788
886
|
searchable: ['name'],
|
|
789
887
|
}
|
|
790
|
-
`}function Te(e){let{pascal:t,kebab:n,plural:r=``,repo:i}=e,
|
|
888
|
+
`}function Te(e){let{pascal:t,kebab:n,plural:r=``,repo:i,style:a}=e,o={inmemory:`InMemory${t}Repository`,drizzle:`Drizzle${t}Repository`,prisma:`Prisma${t}Repository`},s={inmemory:`in-memory-${n}`,drizzle:`drizzle-${n}`,prisma:`prisma-${n}`},c=o[i]??o.inmemory,l=s[i]??s.inmemory,u=a??`define`,d=`/**
|
|
791
889
|
* ${t} Module — CQRS Pattern
|
|
792
890
|
*
|
|
793
891
|
* Separates read (queries) and write (commands) operations.
|
|
@@ -799,11 +897,8 @@ export const ${t.toUpperCase()}_QUERY_CONFIG: QueryFieldConfig = {
|
|
|
799
897
|
* queries/ — Read operations (get, list)
|
|
800
898
|
* events/ — Domain events + handlers (WS broadcast, queue dispatch)
|
|
801
899
|
* dtos/ — Request/response schemas
|
|
802
|
-
|
|
803
|
-
import {
|
|
804
|
-
import { buildRoutes } from '@forinda/kickjs'
|
|
805
|
-
import { ${t.toUpperCase()}_REPOSITORY } from './${n}.repository'
|
|
806
|
-
import { ${s} } from './${c}.repository'
|
|
900
|
+
*/`,f=`import { ${t.toUpperCase()}_REPOSITORY } from './${n}.repository'
|
|
901
|
+
import { ${c} } from './${l}.repository'
|
|
807
902
|
import { ${t}Controller } from './${n}.controller'
|
|
808
903
|
|
|
809
904
|
// Eagerly load decorated classes
|
|
@@ -815,23 +910,58 @@ import.meta.glob(
|
|
|
815
910
|
'!./**/*.test.ts',
|
|
816
911
|
],
|
|
817
912
|
{ eager: true },
|
|
818
|
-
)
|
|
913
|
+
)`,p=` /**
|
|
914
|
+
* Declare HTTP routes. Pass \`controller\` and the framework
|
|
915
|
+
* derives the Express Router via \`buildRoutes()\` and uses the
|
|
916
|
+
* same controller for OpenAPI spec generation. Return an array
|
|
917
|
+
* to mount multiple route sets — each entry can override the API
|
|
918
|
+
* version with a \`version\` field:
|
|
919
|
+
*
|
|
920
|
+
* return [
|
|
921
|
+
* { path: '/${r}', version: 1, controller: ${t}V1Controller },
|
|
922
|
+
* { path: '/${r}', version: 2, controller: ${t}V2Controller },
|
|
923
|
+
* ]
|
|
924
|
+
*/`;return u===`class`?`${d}
|
|
925
|
+
import { Container, type AppModule, type ModuleRoutes } from '@forinda/kickjs'
|
|
926
|
+
${f}
|
|
819
927
|
|
|
820
928
|
export class ${t}Module implements AppModule {
|
|
821
929
|
register(container: Container): void {
|
|
822
930
|
container.registerFactory(${t.toUpperCase()}_REPOSITORY, () =>
|
|
823
|
-
container.resolve(${
|
|
931
|
+
container.resolve(${c}),
|
|
824
932
|
)
|
|
825
933
|
}
|
|
826
934
|
|
|
935
|
+
${p.replace(/^ {4}/gm,` `).replace(/^ {6}/gm,` `)}
|
|
827
936
|
routes(): ModuleRoutes {
|
|
828
937
|
return {
|
|
829
938
|
path: '/${r}',
|
|
830
|
-
router: buildRoutes(${t}Controller),
|
|
831
939
|
controller: ${t}Controller,
|
|
832
940
|
}
|
|
833
941
|
}
|
|
834
942
|
}
|
|
943
|
+
`:`${d}
|
|
944
|
+
import { defineModule } from '@forinda/kickjs'
|
|
945
|
+
${f}
|
|
946
|
+
|
|
947
|
+
export const ${t}Module = defineModule({
|
|
948
|
+
name: '${t}Module',
|
|
949
|
+
build: () => ({
|
|
950
|
+
register(container) {
|
|
951
|
+
container.registerFactory(${t.toUpperCase()}_REPOSITORY, () =>
|
|
952
|
+
container.resolve(${c}),
|
|
953
|
+
)
|
|
954
|
+
},
|
|
955
|
+
|
|
956
|
+
${p}
|
|
957
|
+
routes() {
|
|
958
|
+
return {
|
|
959
|
+
path: '/${r}',
|
|
960
|
+
controller: ${t}Controller,
|
|
961
|
+
}
|
|
962
|
+
},
|
|
963
|
+
}),
|
|
964
|
+
})
|
|
835
965
|
`}function Ee(e){let{pascal:t,kebab:n,plural:r=``,pluralPascal:i=``}=e;return`import { Controller, Get, Post, Put, Delete, Autowired, ApiQueryParams, type Ctx } from '@forinda/kickjs'
|
|
836
966
|
import { ApiTags } from '@forinda/kickjs-swagger'
|
|
837
967
|
import { Create${t}Command } from './commands/create-${n}.command'
|
|
@@ -1063,7 +1193,7 @@ export class On${t}ChangeHandler {
|
|
|
1063
1193
|
})
|
|
1064
1194
|
}
|
|
1065
1195
|
}
|
|
1066
|
-
`}]}function
|
|
1196
|
+
`}]}function G(e){let{pascal:t,kebab:n,repoPrefix:r=`../../domain/repositories`,dtoPrefix:i=`../../application/dtos`}=e;return`/**
|
|
1067
1197
|
* Drizzle ${t} Repository
|
|
1068
1198
|
*
|
|
1069
1199
|
* Implements the repository interface using Drizzle ORM.
|
|
@@ -1163,7 +1293,7 @@ export const ${t.toUpperCase()}_QUERY_CONFIG: DrizzleQueryParamsConfig = {
|
|
|
1163
1293
|
// ${n}s.name,
|
|
1164
1294
|
],
|
|
1165
1295
|
}
|
|
1166
|
-
`}function
|
|
1296
|
+
`}function K(e){let{pascal:t,kebab:n,repoPrefix:r=`../../domain/repositories`,dtoPrefix:i=`../../application/dtos`}=e,a=n.replace(/-([a-z])/g,(e,t)=>t.toUpperCase());return`/**
|
|
1167
1297
|
* Prisma ${t} Repository
|
|
1168
1298
|
*
|
|
1169
1299
|
* Implements the repository interface using Prisma Client.
|
|
@@ -1291,11 +1421,13 @@ export const app = await bootstrap({
|
|
|
1291
1421
|
express.json(),
|
|
1292
1422
|
],
|
|
1293
1423
|
})
|
|
1294
|
-
`}}}function Me(){return`import type {
|
|
1424
|
+
`}}}function Me(){return`import type { AppModuleEntry } from '@forinda/kickjs'
|
|
1295
1425
|
import { HelloModule } from './hello/hello.module'
|
|
1296
1426
|
|
|
1297
1427
|
// Remove HelloModule and run: kick g module <name>
|
|
1298
|
-
|
|
1428
|
+
// Modules built with \`defineModule\` are called as factories — the
|
|
1429
|
+
// invocation produces the AppModule instance bootstrap registers.
|
|
1430
|
+
export const modules: AppModuleEntry[] = [HelloModule()]
|
|
1299
1431
|
`}function Ne(){return`import { defineEnv, loadEnv } from '@forinda/kickjs/config'
|
|
1300
1432
|
import { z } from 'zod'
|
|
1301
1433
|
|
|
@@ -1365,25 +1497,27 @@ export class HelloController {
|
|
|
1365
1497
|
ctx.json(this.helloService.healthCheck())
|
|
1366
1498
|
}
|
|
1367
1499
|
}
|
|
1368
|
-
`}function Ie(){return`import {
|
|
1500
|
+
`}function Ie(){return`import { defineModule } from '@forinda/kickjs'
|
|
1369
1501
|
import { HelloController } from './hello.controller'
|
|
1370
1502
|
|
|
1371
|
-
export
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
}
|
|
1503
|
+
export const HelloModule = defineModule({
|
|
1504
|
+
name: 'HelloModule',
|
|
1505
|
+
build: () => ({
|
|
1506
|
+
// \`register(container)\` is optional — only implement it when you need
|
|
1507
|
+
// to bind a token to a concrete implementation, e.g.
|
|
1508
|
+
// register(container) {
|
|
1509
|
+
// container.registerFactory(USER_REPOSITORY, () => container.resolve(InMemoryUserRepository))
|
|
1510
|
+
// }
|
|
1511
|
+
// The HelloService uses @Service() so the decorator handles registration.
|
|
1512
|
+
|
|
1513
|
+
routes() {
|
|
1514
|
+
return {
|
|
1515
|
+
path: '/hello',
|
|
1516
|
+
controller: HelloController,
|
|
1517
|
+
}
|
|
1518
|
+
},
|
|
1519
|
+
}),
|
|
1520
|
+
})
|
|
1387
1521
|
`}function Le(e,t=`inmemory`,n=`pnpm`){return`import { defineConfig } from '@forinda/kickjs-cli'
|
|
1388
1522
|
|
|
1389
1523
|
export default defineConfig({
|
|
@@ -1428,7 +1562,7 @@ export default defineConfig({
|
|
|
1428
1562
|
},
|
|
1429
1563
|
],
|
|
1430
1564
|
})
|
|
1431
|
-
`}async function Re(e){let{pascal:t,kebab:n,plural:r,write:
|
|
1565
|
+
`}async function Re(e){let{pascal:t,kebab:n,plural:r,style:i,write:a}=e;await a(`${n}.module.ts`,ge({pascal:t,kebab:n,plural:r,style:i})),await a(`${n}.controller.ts`,`import { Controller, Get, type Ctx } from '@forinda/kickjs'
|
|
1432
1566
|
|
|
1433
1567
|
// \`Ctx<KickRoutes.${t}Controller['<method>']>\` is generated by
|
|
1434
1568
|
// \`kick typegen\` (auto-run on \`kick dev\`).
|
|
@@ -1440,14 +1574,14 @@ export class ${t}Controller {
|
|
|
1440
1574
|
ctx.json({ message: '${t} list' })
|
|
1441
1575
|
}
|
|
1442
1576
|
}
|
|
1443
|
-
`)}async function ze(e){let{pascal:t,kebab:n,plural:r,pluralPascal:i,repo:a,noTests:o,prismaClientPath:s,tokenScope:c,write:
|
|
1444
|
-
import { ${t}Module } from '${
|
|
1445
|
-
|
|
1446
|
-
export const modules:
|
|
1447
|
-
`);return}let
|
|
1448
|
-
`,e);
|
|
1449
|
-
`+
|
|
1450
|
-
`+
|
|
1577
|
+
`)}async function ze(e){let{pascal:t,kebab:n,plural:r,pluralPascal:i,repo:a,noTests:o,prismaClientPath:s,tokenScope:c,style:l,write:u}=e;await u(`${n}.module.ts`,he({pascal:t,kebab:n,plural:r,repo:a,style:l})),await u(`${n}.constants.ts`,W({pascal:t,kebab:n})),await u(`${n}.controller.ts`,ve({pascal:t,kebab:n,plural:r,pluralPascal:i})),await u(`${n}.service.ts`,we({pascal:t,kebab:n})),await u(`dtos/create-${n}.dto.ts`,I({pascal:t,kebab:n})),await u(`dtos/update-${n}.dto.ts`,L({pascal:t,kebab:n})),await u(`dtos/${n}-response.dto.ts`,R({pascal:t,kebab:n})),await u(`${n}.repository.ts`,z({pascal:t,kebab:n,dtoPrefix:`./dtos`,tokenScope:c}));let d={inmemory:`in-memory-${n}`,drizzle:`drizzle-${n}`,prisma:`prisma-${n}`},f={inmemory:()=>B({pascal:t,kebab:n,repoPrefix:`.`,dtoPrefix:`./dtos`}),drizzle:()=>G({pascal:t,kebab:n,repoPrefix:`.`,dtoPrefix:`./dtos`}),prisma:()=>K({pascal:t,kebab:n,repoPrefix:`.`,dtoPrefix:`./dtos`,prismaClientPath:s})},p=d[a]??`${k(a)}-${n}`,m=f[a]??(()=>V({pascal:t,kebab:n,repoType:a,repoPrefix:`.`,dtoPrefix:`./dtos`}));await u(`${p}.repository.ts`,m()),o||(a!==`inmemory`&&await u(`in-memory-${n}.repository.ts`,B({pascal:t,kebab:n,repoPrefix:`.`,dtoPrefix:`./dtos`})),await u(`__tests__/${n}.controller.test.ts`,H({pascal:t,kebab:n,plural:r})),await u(`__tests__/${n}.repository.test.ts`,U({pascal:t,kebab:n,plural:r,repoPrefix:`../${d.inmemory??`in-memory-${n}`}.repository`})))}async function Be(e){let{pascal:t,kebab:n,plural:r,pluralPascal:i,repo:a,noTests:o,prismaClientPath:s,tokenScope:c,style:l,write:u}=e;await u(`${n}.module.ts`,Te({pascal:t,kebab:n,plural:r,repo:a,style:l})),await u(`${n}.constants.ts`,W({pascal:t,kebab:n})),await u(`${n}.controller.ts`,Ee({pascal:t,kebab:n,plural:r,pluralPascal:i})),await u(`dtos/create-${n}.dto.ts`,I({pascal:t,kebab:n})),await u(`dtos/update-${n}.dto.ts`,L({pascal:t,kebab:n})),await u(`dtos/${n}-response.dto.ts`,R({pascal:t,kebab:n}));let d=De({pascal:t,kebab:n});for(let e of d)await u(`commands/${e.file}`,e.content);let f=Oe({pascal:t,kebab:n,plural:r,pluralPascal:i});for(let e of f)await u(`queries/${e.file}`,e.content);let p=ke({pascal:t,kebab:n});for(let e of p)await u(`events/${e.file}`,e.content);await u(`${n}.repository.ts`,z({pascal:t,kebab:n,dtoPrefix:`./dtos`,tokenScope:c}));let m={inmemory:`in-memory-${n}`,drizzle:`drizzle-${n}`,prisma:`prisma-${n}`},h={inmemory:()=>B({pascal:t,kebab:n,repoPrefix:`.`,dtoPrefix:`./dtos`}),drizzle:()=>G({pascal:t,kebab:n,repoPrefix:`.`,dtoPrefix:`./dtos`}),prisma:()=>K({pascal:t,kebab:n,repoPrefix:`.`,dtoPrefix:`./dtos`,prismaClientPath:s})},g=m[a]??`${k(a)}-${n}`,_=h[a]??(()=>V({pascal:t,kebab:n,repoType:a,repoPrefix:`.`,dtoPrefix:`./dtos`}));await u(`${g}.repository.ts`,_()),o||(a!==`inmemory`&&await u(`in-memory-${n}.repository.ts`,B({pascal:t,kebab:n,repoPrefix:`.`,dtoPrefix:`./dtos`})),await u(`__tests__/${n}.controller.test.ts`,H({pascal:t,kebab:n,plural:r})),await u(`__tests__/${n}.repository.test.ts`,U({pascal:t,kebab:n,plural:r,repoPrefix:`../${m.inmemory??`in-memory-${n}`}.repository`})))}async function Ve(e){let{pascal:t,kebab:n,plural:r,pluralPascal:i,repo:a,noEntity:o,noTests:s,prismaClientPath:c,tokenScope:l,style:u,write:d}=e;await d(`${n}.module.ts`,me({pascal:t,kebab:n,plural:r,repo:a,style:u})),await d(`constants.ts`,a===`drizzle`?Ae({pascal:t,kebab:n}):ye({pascal:t,kebab:n})),await d(`presentation/${n}.controller.ts`,_e({pascal:t,kebab:n,plural:r,pluralPascal:i})),await d(`application/dtos/create-${n}.dto.ts`,I({pascal:t,kebab:n})),await d(`application/dtos/update-${n}.dto.ts`,L({pascal:t,kebab:n})),await d(`application/dtos/${n}-response.dto.ts`,R({pascal:t,kebab:n}));let f=be({pascal:t,kebab:n,plural:r,pluralPascal:i});for(let e of f)await d(`application/use-cases/${e.file}`,e.content);await d(`domain/repositories/${n}.repository.ts`,z({pascal:t,kebab:n,tokenScope:l})),await d(`domain/services/${n}-domain.service.ts`,xe({pascal:t,kebab:n}));let p={inmemory:`in-memory-${n}`,drizzle:`drizzle-${n}`,prisma:`prisma-${n}`},m={inmemory:()=>B({pascal:t,kebab:n}),drizzle:()=>G({pascal:t,kebab:n}),prisma:()=>K({pascal:t,kebab:n,prismaClientPath:c})},h=p[a]??`${k(a)}-${n}`,g=m[a]??(()=>V({pascal:t,kebab:n,repoType:a}));await d(`infrastructure/repositories/${h}.repository.ts`,g()),o||(await d(`domain/entities/${n}.entity.ts`,Se({pascal:t,kebab:n})),await d(`domain/value-objects/${n}-id.vo.ts`,Ce({pascal:t,kebab:n}))),s||(a!==`inmemory`&&await d(`infrastructure/repositories/in-memory-${n}.repository.ts`,B({pascal:t,kebab:n})),await d(`__tests__/${n}.controller.test.ts`,H({pascal:t,kebab:n,plural:r})),await d(`__tests__/${n}.repository.test.ts`,U({pascal:t,kebab:n,plural:r})))}function He(e){return e?typeof e==`string`?e:e.name:`inmemory`}async function Ue(e){let{name:t,modulesDir:n,noEntity:i,noTests:a,repo:o=`inmemory`,force:s,dryRun:c}=e,l=e.pluralize!==!1,u=e.pattern??`ddd`;e.minimal&&(u=`minimal`);let d=k(t),p=D(t),m=l?A(d):d,h=l?j(p):p,g=r(n,m),_=[],v=s??!1,y={kebab:d,pascal:p,plural:m,pluralPascal:h,moduleDir:g,repo:o,noEntity:i??!1,noTests:a??!1,prismaClientPath:e.prismaClientPath??`@prisma/client`,tokenScope:e.tokenScope??`app`,style:e.style??`define`,write:async(e,t)=>{let n=r(g,e);if(c){_.push(n);return}if(!v&&await C(n)&&!await T({message:`File exists: ${f.dim(e)}. Overwrite?`,initialValue:!1})){E.warn(`Skipped: ${e}`);return}await b(n,t),_.push(n)},files:_};switch(u){case`minimal`:await Re(y);break;case`rest`:await ze(y);break;case`cqrs`:await Be(y);break;default:await Ve(y);break}return c||await We(n,p,m,d,y.style),_}async function We(e,t,n,i,a=`define`){let o=r(e,`index.ts`),s=await C(o),c=`./${n}/${i}.module`,d=a===`class`?`${t}Module`:`${t}Module()`;if(!s){await b(o,`import type { AppModuleEntry } from '@forinda/kickjs'
|
|
1578
|
+
import { ${t}Module } from '${c}'
|
|
1579
|
+
|
|
1580
|
+
export const modules: AppModuleEntry[] = [${d}]
|
|
1581
|
+
`);return}let f=await l(o,`utf-8`),p=`import { ${t}Module } from '${c}'`;if(!f.includes(`${t}Module`)){let e=f.lastIndexOf(`import `);if(e!==-1){let t=f.indexOf(`
|
|
1582
|
+
`,e);f=f.slice(0,t+1)+p+`
|
|
1583
|
+
`+f.slice(t+1)}else f=p+`
|
|
1584
|
+
`+f;f=f.replace(/(=\s*\[)([\s\S]*?)(])/,(e,t,n,r)=>{let i=n.trim();if(!i)return`${t}${d}${r}`;let a=i.endsWith(`,`)?``:`,`;return`${t}${n.trimEnd()}${a} ${d}${r}`})}await u(o,f,`utf-8`)}async function Ge(e){let{name:t,outDir:n}=e,i=k(t),a=D(t),o=[],s=r(n,`${i}.adapter.ts`);return await b(s,`import {
|
|
1451
1585
|
defineAdapter,
|
|
1452
1586
|
type AdapterContext,
|
|
1453
1587
|
type AdapterMiddleware,
|
|
@@ -1616,7 +1750,7 @@ export const ${a}Adapter = defineAdapter<${a}AdapterConfig>({
|
|
|
1616
1750
|
}
|
|
1617
1751
|
},
|
|
1618
1752
|
})
|
|
1619
|
-
`),o.push(s),o}const Ke={controller:`presentation`,service:`domain/services`,dto:`application/dtos`,guard:`presentation/guards`,middleware:`middleware`},qe={controller:``,service:``,dto:`dtos`,guard:`guards`,middleware:`middleware`},Je={controller:``,service:``,dto:`dtos`,guard:`guards`,middleware:`middleware`,command:`commands`,query:`queries`,event:`events`};function
|
|
1753
|
+
`),o.push(s),o}const Ke={controller:`presentation`,service:`domain/services`,dto:`application/dtos`,guard:`presentation/guards`,middleware:`middleware`},qe={controller:``,service:``,dto:`dtos`,guard:`guards`,middleware:`middleware`},Je={controller:``,service:``,dto:`dtos`,guard:`guards`,middleware:`middleware`,command:`commands`,query:`queries`,event:`events`};function q(e){let{type:t,outDir:n,moduleName:a,modulesDir:o=`src/modules`,defaultDir:s,pattern:c=`ddd`,shouldPluralize:l=!0}=e;if(n)return i(n);if(a){let e=c===`ddd`?Ke:c===`cqrs`?Je:qe,n=k(a),s=l?A(n):n,u=e[t]??``,d=r(o,s);return i(u?r(d,u):d)}return i(s)}async function Ye(e){let{name:t,moduleName:n,modulesDir:i,pattern:a}=e,o=q({type:`middleware`,outDir:e.outDir,moduleName:n,modulesDir:i,defaultDir:`src/middleware`,pattern:a,shouldPluralize:e.pluralize??!0}),s=k(t),c=O(t),l=[],u=r(o,`${s}.middleware.ts`);return await b(u,`import type { Request, Response, NextFunction } from 'express'
|
|
1620
1754
|
|
|
1621
1755
|
export interface ${D(t)}Options {
|
|
1622
1756
|
// Add configuration options here
|
|
@@ -1640,7 +1774,7 @@ export function ${c}(options: ${D(t)}Options = {}) {
|
|
|
1640
1774
|
next()
|
|
1641
1775
|
}
|
|
1642
1776
|
}
|
|
1643
|
-
`),l.push(u),l}async function Xe(e){let{name:t,moduleName:n,modulesDir:i,pattern:a}=e,o=
|
|
1777
|
+
`),l.push(u),l}async function Xe(e){let{name:t,moduleName:n,modulesDir:i,pattern:a}=e,o=q({type:`guard`,outDir:e.outDir,moduleName:n,modulesDir:i,defaultDir:`src/guards`,pattern:a,shouldPluralize:e.pluralize??!0}),s=k(t),c=O(t),l=D(t),u=[],d=r(o,`${s}.guard.ts`);return await b(d,`import { Container, HttpException } from '@forinda/kickjs'
|
|
1644
1778
|
import type { RequestContext } from '@forinda/kickjs'
|
|
1645
1779
|
|
|
1646
1780
|
/**
|
|
@@ -1676,7 +1810,7 @@ export async function ${c}Guard(ctx: RequestContext, next: () => void): Promise<
|
|
|
1676
1810
|
ctx.res.status(401).json({ message: 'Invalid or expired token' })
|
|
1677
1811
|
}
|
|
1678
1812
|
}
|
|
1679
|
-
`),u.push(d),u}async function Ze(e){let{name:t,moduleName:n,modulesDir:i,pattern:a}=e,o=
|
|
1813
|
+
`),u.push(d),u}async function Ze(e){let{name:t,moduleName:n,modulesDir:i,pattern:a}=e,o=q({type:`service`,outDir:e.outDir,moduleName:n,modulesDir:i,defaultDir:`src/services`,pattern:a,shouldPluralize:e.pluralize??!0}),s=k(t),c=D(t),l=[],u=r(o,`${s}.service.ts`);return await b(u,`import { Service } from '@forinda/kickjs'
|
|
1680
1814
|
|
|
1681
1815
|
@Service()
|
|
1682
1816
|
export class ${c}Service {
|
|
@@ -1685,7 +1819,7 @@ export class ${c}Service {
|
|
|
1685
1819
|
// @Inject(MY_REPO) private readonly repo: IMyRepository,
|
|
1686
1820
|
// ) {}
|
|
1687
1821
|
}
|
|
1688
|
-
`),l.push(u),l}async function Qe(e){let{name:t,moduleName:n,modulesDir:i,pattern:a}=e,o=
|
|
1822
|
+
`),l.push(u),l}async function Qe(e){let{name:t,moduleName:n,modulesDir:i,pattern:a}=e,o=q({type:`controller`,outDir:e.outDir,moduleName:n,modulesDir:i,defaultDir:`src/controllers`,pattern:a,shouldPluralize:e.pluralize??!0}),s=k(t),c=D(t),l=[],u=r(o,`${s}.controller.ts`);return await b(u,`import { Controller, Get, Post, type Ctx } from '@forinda/kickjs'
|
|
1689
1823
|
|
|
1690
1824
|
// \`Ctx<KickRoutes.${c}Controller['<method>']>\` is generated by
|
|
1691
1825
|
// \`kick typegen\` (auto-run on \`kick dev\`). After the first run, your IDE
|
|
@@ -1706,7 +1840,7 @@ export class ${c}Controller {
|
|
|
1706
1840
|
ctx.created({ message: '${c} created', data: ctx.body })
|
|
1707
1841
|
}
|
|
1708
1842
|
}
|
|
1709
|
-
`),l.push(u),l}async function $e(e){let{name:t,moduleName:n,modulesDir:i,pattern:a}=e,o=
|
|
1843
|
+
`),l.push(u),l}async function $e(e){let{name:t,moduleName:n,modulesDir:i,pattern:a}=e,o=q({type:`dto`,outDir:e.outDir,moduleName:n,modulesDir:i,defaultDir:`src/dtos`,pattern:a,shouldPluralize:e.pluralize??!0}),s=k(t),c=D(t),l=O(t),u=[],d=r(o,`${s}.dto.ts`);return await b(d,`import { z } from 'zod'
|
|
1710
1844
|
|
|
1711
1845
|
export const ${l}Schema = z.object({
|
|
1712
1846
|
// Define your schema fields here
|
|
@@ -1865,7 +1999,7 @@ Copy \`.env.example\` to \`.env\` and configure:
|
|
|
1865
1999
|
|
|
1866
2000
|
- [KickJS Documentation](https://forinda.github.io/kick-js/)
|
|
1867
2001
|
- [CLI Reference](https://forinda.github.io/kick-js/api/cli.html)
|
|
1868
|
-
`}function
|
|
2002
|
+
`}function J(e,t,n){return`# CLAUDE.md — ${e}
|
|
1869
2003
|
|
|
1870
2004
|
**Read \`./AGENTS.md\` first.** It is the canonical, multi-agent
|
|
1871
2005
|
reference for this project (Claude, Copilot, Codex, Gemini, etc.) —
|
|
@@ -1931,7 +2065,7 @@ When generating or modifying code in this project, stay aligned with the v4 conv
|
|
|
1931
2065
|
- **Refresh these files**: \`kick g agents -f\` regenerates \`AGENTS.md\` + \`CLAUDE.md\` from the latest CLI templates. Hand-edited content is overwritten — keep customisation in \`AGENTS.local.md\`.
|
|
1932
2066
|
|
|
1933
2067
|
For everything else (controllers, services, modules, RequestContext API, generators, CLI commands, package additions, env wiring, troubleshooting) → \`AGENTS.md\`.
|
|
1934
|
-
`}function
|
|
2068
|
+
`}function Y(e,t,n){return`# AGENTS.md — AI Agent Guide for ${e}
|
|
1935
2069
|
|
|
1936
2070
|
This guide is the **canonical, multi-agent reference** for this KickJS
|
|
1937
2071
|
application — Claude, Copilot, Codex, Gemini, etc. all read it first.
|
|
@@ -2036,7 +2170,7 @@ mistakes:
|
|
|
2036
2170
|
|
|
2037
2171
|
\`\`\`ts
|
|
2038
2172
|
// src/modules/index.ts
|
|
2039
|
-
export const modules:
|
|
2173
|
+
export const modules: AppModuleEntry[] = [HelloModule(), UsersModule(), ...]
|
|
2040
2174
|
|
|
2041
2175
|
// src/middleware/index.ts
|
|
2042
2176
|
export const middleware = [helmet(), cors(), requestId(), ...]
|
|
@@ -2100,7 +2234,7 @@ ${t===`ddd`?`\`\`\`
|
|
|
2100
2234
|
├── <name>.repository.ts # Data access (@Repository)
|
|
2101
2235
|
├── <name>.dto.ts # Request/response schemas (Zod)
|
|
2102
2236
|
├── <name>.entity.ts # Domain entity (optional)
|
|
2103
|
-
└── <name>.module.ts # Module definition (
|
|
2237
|
+
└── <name>.module.ts # Module definition (defineModule factory)
|
|
2104
2238
|
\`\`\`
|
|
2105
2239
|
`:t===`cqrs`?`\`\`\`
|
|
2106
2240
|
<name>/
|
|
@@ -2114,14 +2248,14 @@ ${t===`ddd`?`\`\`\`
|
|
|
2114
2248
|
│ └── <name>-created.event.ts
|
|
2115
2249
|
├── <name>.controller.ts # HTTP routes
|
|
2116
2250
|
├── <name>.repository.ts # Data access
|
|
2117
|
-
└── <name>.module.ts # Module definition (
|
|
2251
|
+
└── <name>.module.ts # Module definition (defineModule factory)
|
|
2118
2252
|
\`\`\`
|
|
2119
2253
|
`:t===`rest`?`\`\`\`
|
|
2120
2254
|
<name>/
|
|
2121
2255
|
├── <name>.controller.ts # HTTP routes (@Controller)
|
|
2122
2256
|
├── <name>.service.ts # Business logic (@Service)
|
|
2123
2257
|
├── <name>.dto.ts # Request/response schemas (Zod)
|
|
2124
|
-
└── <name>.module.ts # Module definition (
|
|
2258
|
+
└── <name>.module.ts # Module definition (defineModule factory)
|
|
2125
2259
|
\`\`\`
|
|
2126
2260
|
`:"```\nsrc/\n├── index.ts # Add routes here\n└── ... # Custom structure\n```\n"}
|
|
2127
2261
|
|
|
@@ -2152,8 +2286,8 @@ If not using generators:
|
|
|
2152
2286
|
- [ ] Create \`src/modules/<name>/<name>.controller.ts\`
|
|
2153
2287
|
- [ ] Add \`@Controller()\` decorator
|
|
2154
2288
|
- [ ] Add route handlers with \`@Get()\`, \`@Post()\`, etc.
|
|
2155
|
-
- [ ] Create module file
|
|
2156
|
-
- [ ] Register module in \`src/modules/index.ts\` (\`
|
|
2289
|
+
- [ ] Create module file with \`defineModule({ name, build: () => ({ routes() { return { path, controller } } }) })\` (the framework derives the Express router from the controller)
|
|
2290
|
+
- [ ] Register module in \`src/modules/index.ts\` (\`AppModuleEntry[]\` array — call the factory at the registration site: \`[MyModule()]\`)
|
|
2157
2291
|
- [ ] Test with \`kick dev\`
|
|
2158
2292
|
|
|
2159
2293
|
### Manual Service
|
|
@@ -2434,7 +2568,7 @@ ${t===`cqrs`?`### Background Jobs
|
|
|
2434
2568
|
- [Decorators Guide](https://forinda.github.io/kick-js/guide/decorators.html)
|
|
2435
2569
|
- [DI System](https://forinda.github.io/kick-js/guide/dependency-injection.html)
|
|
2436
2570
|
- [Testing](https://forinda.github.io/kick-js/api/testing.html)
|
|
2437
|
-
`}function
|
|
2571
|
+
`}function X(e,t,n){return`# kickjs-skills.md — Task Skills for AI Agents (${e})
|
|
2438
2572
|
|
|
2439
2573
|
This file is the agent-facing **skills index** for KickJS work in this
|
|
2440
2574
|
repo. Each block below is a short, rigid workflow keyed to a specific
|
|
@@ -2681,7 +2815,7 @@ description: Patterns to refuse outright when the user asks for them — they br
|
|
|
2681
2815
|
- [Decorators](https://forinda.github.io/kick-js/guide/decorators.html)
|
|
2682
2816
|
- [Context Decorators](https://forinda.github.io/kick-js/guide/context-decorators.html)
|
|
2683
2817
|
- [Testing](https://forinda.github.io/kick-js/api/testing.html)
|
|
2684
|
-
`}const ft=t(h(import.meta.url)),
|
|
2685
|
-
Dependencies installed successfully!`)}catch{console.log(`\n Warning: ${i} install failed. Run it manually.`)}}try{let{runTypegen:e}=await import(`./typegen-
|
|
2686
|
-
Project scaffolded successfully!`),console.log();let u=c!==process.cwd();l(`Next steps:`),u&&l(` cd ${t}`),e.installDeps||l(` ${i} install`);let d={rest:`kick g module user`,ddd:`kick g module user --repo drizzle`,cqrs:`kick g module user --pattern cqrs`,minimal:`# add your routes to src/index.ts`};l(` ${d[a]??d.rest}`),l(` kick dev`),l(``),l(`Commands:`),l(` kick dev Start dev server with Vite HMR`),l(` kick build Production build via Vite`),l(` kick start Run production build`),l(``),l(`Generators:`),l(` kick g module <name> Full DDD module (controller, DTOs, use-cases, repo)`),l(` kick g scaffold <n> <f..> CRUD module from field definitions`),l(` kick g controller <name> Standalone controller`),l(` kick g service <name> @Service() class`),l(` kick g middleware <name> Express middleware`),l(` kick g guard <name> Route guard (auth, roles, etc.)`),l(` kick g adapter <name> AppAdapter with lifecycle hooks`),l(` kick g dto <name> Zod DTO schema`),a===`cqrs`&&l(` kick g job <name> Queue job processor`),l(` kick g config Generate kick.config.ts`),l(``),l(`Add packages:`),l(` kick add <pkg> Install a KickJS package + peers`),l(` kick add --list Show all available packages`),l(``),l(`Available: auth, swagger, drizzle, prisma, ws, queue, devtools, mcp, testing`),l(``)}function ht(e){return e}function gt(e){return k(e).replace(/-/g,`_`)}function
|
|
2687
|
-
//# sourceMappingURL=generator-extension-
|
|
2818
|
+
`}const ft=t(h(import.meta.url)),Z=JSON.parse(o(r(ft,`..`,`package.json`),`utf-8`)),pt=`^${Z.version}`;async function mt(e){let{name:t,directory:n,packageManager:i=`pnpm`,template:a=`rest`,defaultRepo:o=`inmemory`,packages:s=[]}=e,c=n,l=e=>console.log(` ${e}`);if(console.log(`\n Creating KickJS project: ${t}\n`),await b(r(c,`package.json`),tt(t,a,pt,s)),await b(r(c,`vite.config.ts`),nt()),await b(r(c,`tsconfig.json`),rt()),await b(r(c,`.prettierrc`),it()),await b(r(c,`.editorconfig`),at()),await b(r(c,`.gitignore`),ot()),await b(r(c,`.gitattributes`),st()),await b(r(c,`.env`),ct()),await b(r(c,`.env.example`),lt()),await b(r(c,`src/config/index.ts`),Ne()),await b(r(c,`src/index.ts`),je(t,a,Z.version,s)),await b(r(c,`src/modules/index.ts`),Me()),await b(r(c,`src/modules/hello/hello.service.ts`),Pe()),await b(r(c,`src/modules/hello/hello.controller.ts`),Fe()),await b(r(c,`src/modules/hello/hello.module.ts`),Ie()),await b(r(c,`kick.config.ts`),Le(a,o,i)),await b(r(c,`vitest.config.ts`),ut()),await b(r(c,`README.md`),dt(t,a,i)),await b(r(c,`CLAUDE.md`),J(t,a,i)),await b(r(c,`AGENTS.md`),Y(t,a,i)),await b(r(c,`kickjs-skills.md`),X(t,a,i)),e.installDeps){console.log(`\n Installing dependencies with ${i}...\n`);try{m(`${i} install`,{cwd:c,stdio:`inherit`}),console.log(`
|
|
2819
|
+
Dependencies installed successfully!`)}catch{console.log(`\n Warning: ${i} install failed. Run it manually.`)}}try{let{runTypegen:e}=await import(`./typegen-Bl9kUVNL.mjs`).then(e=>e.n);await e({cwd:c,allowDuplicates:!0,silent:!0})}catch{}if(e.initGit)try{m(`git init`,{cwd:c,stdio:`pipe`}),m(`git branch -M main`,{cwd:c,stdio:`pipe`}),m(`git add -A`,{cwd:c,stdio:`pipe`}),m(`git commit -m "chore: initial commit from kick new"`,{cwd:c,stdio:`pipe`}),l(`Git repository initialized`)}catch{l(`Warning: git init failed (git may not be installed)`)}console.log(`
|
|
2820
|
+
Project scaffolded successfully!`),console.log();let u=c!==process.cwd();l(`Next steps:`),u&&l(` cd ${t}`),e.installDeps||l(` ${i} install`);let d={rest:`kick g module user`,ddd:`kick g module user --repo drizzle`,cqrs:`kick g module user --pattern cqrs`,minimal:`# add your routes to src/index.ts`};l(` ${d[a]??d.rest}`),l(` kick dev`),l(``),l(`Commands:`),l(` kick dev Start dev server with Vite HMR`),l(` kick build Production build via Vite`),l(` kick start Run production build`),l(``),l(`Generators:`),l(` kick g module <name> Full DDD module (controller, DTOs, use-cases, repo)`),l(` kick g scaffold <n> <f..> CRUD module from field definitions`),l(` kick g controller <name> Standalone controller`),l(` kick g service <name> @Service() class`),l(` kick g middleware <name> Express middleware`),l(` kick g guard <name> Route guard (auth, roles, etc.)`),l(` kick g adapter <name> AppAdapter with lifecycle hooks`),l(` kick g dto <name> Zod DTO schema`),a===`cqrs`&&l(` kick g job <name> Queue job processor`),l(` kick g config Generate kick.config.ts`),l(``),l(`Add packages:`),l(` kick add <pkg> Install a KickJS package + peers`),l(` kick add --list Show all available packages`),l(``),l(`Available: auth, swagger, drizzle, prisma, ws, queue, devtools, mcp, testing`),l(``)}function ht(e){return e}function gt(e){return k(e).replace(/-/g,`_`)}function Q(e){let t=e.cwd??process.cwd(),n=e.pluralize??!0,r=D(e.name),i=O(e.name),a=k(e.name),o=gt(e.name),s={name:e.name,pascal:r,camel:i,kebab:a,snake:o,modulesDir:e.modulesDir??`src/modules`,cwd:t,args:e.args??[],flags:e.flags??{}};if(n){let e=A(a);s.pluralKebab=e,s.pluralPascal=D(e),s.pluralCamel=O(e)}return s}function _t(e,t){return i(e.cwd,t)}async function vt(e){return import(g(e).href)}const $=new Map;async function yt(e){let t=$.get(e);if(t)return t;let n=bt(e);return $.set(e,n),n}async function bt(n){let r=i(n,`package.json`);if(!a(r))return{generators:[],loaded:[],failed:[]};let o=xt(JSON.parse(await l(r,`utf-8`))),s=e(i(n,`package.json`)),c=[],u=[],d=[];for(let e of o){let n;try{n=s.resolve(`${e}/package.json`)}catch{continue}let r;try{r=JSON.parse(await l(n,`utf-8`))}catch(t){d.push({source:e,reason:`failed to parse package.json: ${t}`});continue}if(!r.kickjs?.generators)continue;let o=r.kickjs.generators,f=i(t(n),o);if(!a(f)){d.push({source:e,reason:`kickjs.generators points to missing file: ${o}`});continue}let p;try{p=await vt(f)}catch(t){d.push({source:e,reason:`failed to import manifest: ${t}`});continue}let m=p.default;if(!Array.isArray(m)){d.push({source:e,reason:`manifest's default export is not an array of GeneratorSpec`});continue}for(let t of m){if(!St(t)){d.push({source:e,reason:`manifest entry is not a valid GeneratorSpec (missing name/files)`});continue}c.push({source:e,spec:t})}u.push(e)}return{generators:c,loaded:u,failed:d}}function xt(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 St(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.name==`string`&&typeof t.files==`function`}async function Ct(e,t=[]){let n=e.cwd??process.cwd(),r=t.find(t=>t.spec.name===e.generatorName);if(r)return Et(r.spec,r.source,e,n);let i=Tt(await yt(n),e.generatorName);return i?Et(i.spec,i.source,e,n):null}async function wt(e,t=[]){let n=await yt(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 Tt(e,t){return e.generators.find(e=>e.spec.name===t)}async function Et(e,t,n,r){let i=Q({name:n.itemName,args:n.args,flags:n.flags,modulesDir:n.modulesDir,pluralize:n.pluralize,cwd:r}),a=await e.files(i),o=[];for(let e of a){let t=_t(i,e.path);await b(t,e.content),o.push(t)}return{files:o,source:t}}export{ie as A,oe as C,le as D,se as E,b as F,ae as M,C as N,de as O,v as P,T as S,ue as T,A as _,mt as a,k as b,X as c,Ze as d,Xe as f,He as g,Ue as h,ht as i,f as j,ce as k,$e as l,Ge as m,Ct as n,Y as o,Ye as p,Q as r,J as s,wt as t,Qe as u,j as v,E as w,D as x,O as y};
|
|
2821
|
+
//# sourceMappingURL=generator-extension-Bn2aH7kY.mjs.map
|