@forinda/kickjs-cli 1.2.10 → 1.2.12

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/index.js CHANGED
@@ -1,88 +1,5 @@
1
- var __defProp = Object.defineProperty;
2
- var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
-
4
- // src/generators/module.ts
5
- import { join } from "path";
6
- import { createInterface } from "readline";
7
-
8
- // src/utils/fs.ts
9
- import { writeFile, mkdir, access, readFile } from "fs/promises";
10
- import { dirname } from "path";
11
- var _dryRun = false;
12
- async function writeFileSafe(filePath, content) {
13
- if (_dryRun) return;
14
- await mkdir(dirname(filePath), {
15
- recursive: true
16
- });
17
- await writeFile(filePath, content, "utf-8");
18
- }
19
- __name(writeFileSafe, "writeFileSafe");
20
- async function fileExists(filePath) {
21
- try {
22
- await access(filePath);
23
- return true;
24
- } catch {
25
- return false;
26
- }
27
- }
28
- __name(fileExists, "fileExists");
29
-
30
- // src/utils/naming.ts
31
- function toPascalCase(name) {
32
- return name.replace(/[-_\s]+(.)?/g, (_, c) => c ? c.toUpperCase() : "").replace(/^(.)/, (c) => c.toUpperCase());
33
- }
34
- __name(toPascalCase, "toPascalCase");
35
- function toCamelCase(name) {
36
- const pascal = toPascalCase(name);
37
- return pascal.charAt(0).toLowerCase() + pascal.slice(1);
38
- }
39
- __name(toCamelCase, "toCamelCase");
40
- function toKebabCase(name) {
41
- return name.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase();
42
- }
43
- __name(toKebabCase, "toKebabCase");
44
- function pluralize(name) {
45
- if (name.endsWith("s")) return name;
46
- if (name.endsWith("x") || name.endsWith("z")) return name + "es";
47
- if (name.endsWith("sh") || name.endsWith("ch")) return name + "es";
48
- if (name.endsWith("y") && !/[aeiou]y$/.test(name)) return name.slice(0, -1) + "ies";
49
- return name + "s";
50
- }
51
- __name(pluralize, "pluralize");
52
- function pluralizePascal(name) {
53
- if (name.endsWith("s")) return name;
54
- if (name.endsWith("x") || name.endsWith("z")) return name + "es";
55
- if (name.endsWith("sh") || name.endsWith("ch")) return name + "es";
56
- if (name.endsWith("y") && !/[aeiou]y$/i.test(name)) return name.slice(0, -1) + "ies";
57
- return name + "s";
58
- }
59
- __name(pluralizePascal, "pluralizePascal");
60
-
61
- // src/generators/module.ts
62
- import { readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
63
-
64
- // src/generators/templates/module-index.ts
65
- function repoMaps(pascal, kebab, repo) {
66
- const repoClassMap = {
67
- inmemory: `InMemory${pascal}Repository`,
68
- drizzle: `Drizzle${pascal}Repository`,
69
- prisma: `Prisma${pascal}Repository`
70
- };
71
- const repoFileMap = {
72
- inmemory: `in-memory-${kebab}`,
73
- drizzle: `drizzle-${kebab}`,
74
- prisma: `prisma-${kebab}`
75
- };
76
- return {
77
- repoClass: repoClassMap[repo] ?? repoClassMap.inmemory,
78
- repoFile: repoFileMap[repo] ?? repoFileMap.inmemory
79
- };
80
- }
81
- __name(repoMaps, "repoMaps");
82
- function generateModuleIndex(pascal, kebab, plural, repo) {
83
- const { repoClass, repoFile } = repoMaps(pascal, kebab, repo);
84
- return `/**
85
- * ${pascal} Module
1
+ var me=Object.defineProperty;var i=(e,t)=>me(e,"name",{value:t,configurable:!0});import{join as oe}from"path";import{createInterface as ge}from"readline";import{writeFile as ue,mkdir as le,access as fe,readFile as it}from"fs/promises";import{dirname as $e}from"path";var ye=!1;async function c(e,t){ye||(await le($e(e),{recursive:!0}),await ue(e,t,"utf-8"))}i(c,"writeFileSafe");async function F(e){try{return await fe(e),!0}catch{return!1}}i(F,"fileExists");function l(e){return e.replace(/[-_\s]+(.)?/g,(t,r)=>r?r.toUpperCase():"").replace(/^(.)/,t=>t.toUpperCase())}i(l,"toPascalCase");function C(e){let t=l(e);return t.charAt(0).toLowerCase()+t.slice(1)}i(C,"toCamelCase");function f(e){return e.replace(/([a-z])([A-Z])/g,"$1-$2").replace(/[\s_]+/g,"-").toLowerCase()}i(f,"toKebabCase");function x(e){return e.endsWith("s")?e:e.endsWith("x")||e.endsWith("z")||e.endsWith("sh")||e.endsWith("ch")?e+"es":e.endsWith("y")&&!/[aeiou]y$/.test(e)?e.slice(0,-1)+"ies":e+"s"}i(x,"pluralize");function ae(e){return e.endsWith("s")?e:e.endsWith("x")||e.endsWith("z")||e.endsWith("sh")||e.endsWith("ch")?e+"es":e.endsWith("y")&&!/[aeiou]y$/i.test(e)?e.slice(0,-1)+"ies":e+"s"}i(ae,"pluralizePascal");import{readFile as he,writeFile as we}from"fs/promises";function de(e,t,r){let o={inmemory:`InMemory${e}Repository`,drizzle:`Drizzle${e}Repository`,prisma:`Prisma${e}Repository`},n={inmemory:`in-memory-${t}`,drizzle:`drizzle-${t}`,prisma:`prisma-${t}`};return{repoClass:o[r]??o.inmemory,repoFile:n[r]??n.inmemory}}i(de,"repoMaps");function Q(e,t,r,o){let{repoClass:n,repoFile:s}=de(e,t,o);return`/**
2
+ * ${e} Module
86
3
  *
87
4
  * Self-contained feature module following Domain-Driven Design (DDD).
88
5
  * Registers dependencies in the DI container and declares HTTP routes.
@@ -95,9 +12,9 @@ function generateModuleIndex(pascal, kebab, plural, repo) {
95
12
  */
96
13
  import { Container, type AppModule, type ModuleRoutes } from '@forinda/kickjs-core'
97
14
  import { buildRoutes } from '@forinda/kickjs-http'
98
- import { ${pascal.toUpperCase()}_REPOSITORY } from './domain/repositories/${kebab}.repository'
99
- import { ${repoClass} } from './infrastructure/repositories/${repoFile}.repository'
100
- import { ${pascal}Controller } from './presentation/${kebab}.controller'
15
+ import { ${e.toUpperCase()}_REPOSITORY } from './domain/repositories/${t}.repository'
16
+ import { ${n} } from './infrastructure/repositories/${s}.repository'
17
+ import { ${e}Controller } from './presentation/${t}.controller'
101
18
 
102
19
  // Eagerly load decorated classes so @Service()/@Repository() decorators register in the DI container
103
20
  import.meta.glob(
@@ -105,402 +22,325 @@ import.meta.glob(
105
22
  { eager: true },
106
23
  )
107
24
 
108
- export class ${pascal}Module implements AppModule {
25
+ export class ${e}Module implements AppModule {
109
26
  /**
110
27
  * Register module dependencies in the DI container.
111
28
  * Bind repository interface tokens to their implementations here.
112
29
  * To swap implementations (e.g. in-memory -> Drizzle), change the factory target.
113
30
  */
114
31
  register(container: Container): void {
115
- container.registerFactory(${pascal.toUpperCase()}_REPOSITORY, () =>
116
- container.resolve(${repoClass}),
32
+ container.registerFactory(${e.toUpperCase()}_REPOSITORY, () =>
33
+ container.resolve(${n}),
117
34
  )
118
35
  }
119
36
 
120
37
  /**
121
38
  * Declare HTTP routes for this module.
122
- * The path is prefixed with the global apiPrefix and version (e.g. /api/v1/${plural}).
39
+ * The path is prefixed with the global apiPrefix and version (e.g. /api/v1/${r}).
123
40
  * Passing 'controller' enables automatic OpenAPI spec generation via SwaggerAdapter.
124
41
  */
125
42
  routes(): ModuleRoutes {
126
43
  return {
127
- path: '/${plural}',
128
- router: buildRoutes(${pascal}Controller),
129
- controller: ${pascal}Controller,
44
+ path: '/${r}',
45
+ router: buildRoutes(${e}Controller),
46
+ controller: ${e}Controller,
130
47
  }
131
48
  }
132
49
  }
133
- `;
134
- }
135
- __name(generateModuleIndex, "generateModuleIndex");
136
- function generateRestModuleIndex(pascal, kebab, plural, repo) {
137
- const { repoClass, repoFile } = repoMaps(pascal, kebab, repo);
138
- return `/**
139
- * ${pascal} Module
50
+ `}i(Q,"generateModuleIndex");function G(e,t,r,o){let{repoClass:n,repoFile:s}=de(e,t,o);return`/**
51
+ * ${e} Module
140
52
  *
141
53
  * REST module with a flat folder structure.
142
54
  * Controller delegates to service, service wraps the repository.
143
55
  *
144
56
  * Structure:
145
- * ${kebab}.controller.ts \u2014 HTTP routes (CRUD)
146
- * ${kebab}.service.ts \u2014 Business logic
147
- * ${kebab}.repository.ts \u2014 Repository interface
148
- * ${repoFile}.repository.ts \u2014 Repository implementation
57
+ * ${t}.controller.ts \u2014 HTTP routes (CRUD)
58
+ * ${t}.service.ts \u2014 Business logic
59
+ * ${t}.repository.ts \u2014 Repository interface
60
+ * ${s}.repository.ts \u2014 Repository implementation
149
61
  * dtos/ \u2014 Request/response schemas
150
62
  */
151
63
  import { Container, type AppModule, type ModuleRoutes } from '@forinda/kickjs-core'
152
64
  import { buildRoutes } from '@forinda/kickjs-http'
153
- import { ${pascal.toUpperCase()}_REPOSITORY } from './${kebab}.repository'
154
- import { ${repoClass} } from './${repoFile}.repository'
155
- import { ${pascal}Controller } from './${kebab}.controller'
65
+ import { ${e.toUpperCase()}_REPOSITORY } from './${t}.repository'
66
+ import { ${n} } from './${s}.repository'
67
+ import { ${e}Controller } from './${t}.controller'
156
68
 
157
69
  // Eagerly load decorated classes so @Service()/@Repository() decorators register in the DI container
158
70
  import.meta.glob(['./**/*.service.ts', './**/*.repository.ts', '!./**/*.test.ts'], { eager: true })
159
71
 
160
- export class ${pascal}Module implements AppModule {
72
+ export class ${e}Module implements AppModule {
161
73
  register(container: Container): void {
162
- container.registerFactory(${pascal.toUpperCase()}_REPOSITORY, () =>
163
- container.resolve(${repoClass}),
74
+ container.registerFactory(${e.toUpperCase()}_REPOSITORY, () =>
75
+ container.resolve(${n}),
164
76
  )
165
77
  }
166
78
 
167
79
  routes(): ModuleRoutes {
168
80
  return {
169
- path: '/${plural}',
170
- router: buildRoutes(${pascal}Controller),
171
- controller: ${pascal}Controller,
81
+ path: '/${r}',
82
+ router: buildRoutes(${e}Controller),
83
+ controller: ${e}Controller,
172
84
  }
173
85
  }
174
86
  }
175
- `;
176
- }
177
- __name(generateRestModuleIndex, "generateRestModuleIndex");
178
- function generateMinimalModuleIndex(pascal, kebab, plural) {
179
- return `import { type AppModule, type ModuleRoutes } from '@forinda/kickjs-core'
87
+ `}i(G,"generateRestModuleIndex");function N(e,t,r){return`import { type AppModule, type ModuleRoutes } from '@forinda/kickjs-core'
180
88
  import { buildRoutes } from '@forinda/kickjs-http'
181
- import { ${pascal}Controller } from './${kebab}.controller'
89
+ import { ${e}Controller } from './${t}.controller'
182
90
 
183
- export class ${pascal}Module implements AppModule {
91
+ export class ${e}Module implements AppModule {
184
92
  routes(): ModuleRoutes {
185
93
  return {
186
- path: '/${plural}',
187
- router: buildRoutes(${pascal}Controller),
188
- controller: ${pascal}Controller,
94
+ path: '/${r}',
95
+ router: buildRoutes(${e}Controller),
96
+ controller: ${e}Controller,
189
97
  }
190
98
  }
191
99
  }
192
- `;
193
- }
194
- __name(generateMinimalModuleIndex, "generateMinimalModuleIndex");
195
-
196
- // src/generators/templates/controller.ts
197
- function generateController(pascal, kebab, plural, pluralPascal) {
198
- return `import { Controller, Get, Post, Put, Delete, Autowired, ApiQueryParams } from '@forinda/kickjs-core'
100
+ `}i(N,"generateMinimalModuleIndex");function Y(e,t,r,o){return`import { Controller, Get, Post, Put, Delete, Autowired, ApiQueryParams } from '@forinda/kickjs-core'
199
101
  import type { RequestContext } from '@forinda/kickjs-http'
200
102
  import { ApiTags } from '@forinda/kickjs-swagger'
201
- import { Create${pascal}UseCase } from '../application/use-cases/create-${kebab}.use-case'
202
- import { Get${pascal}UseCase } from '../application/use-cases/get-${kebab}.use-case'
203
- import { List${pluralPascal}UseCase } from '../application/use-cases/list-${plural}.use-case'
204
- import { Update${pascal}UseCase } from '../application/use-cases/update-${kebab}.use-case'
205
- import { Delete${pascal}UseCase } from '../application/use-cases/delete-${kebab}.use-case'
206
- import { create${pascal}Schema } from '../application/dtos/create-${kebab}.dto'
207
- import { update${pascal}Schema } from '../application/dtos/update-${kebab}.dto'
208
- import { ${pascal.toUpperCase()}_QUERY_CONFIG } from '../constants'
103
+ import { Create${e}UseCase } from '../application/use-cases/create-${t}.use-case'
104
+ import { Get${e}UseCase } from '../application/use-cases/get-${t}.use-case'
105
+ import { List${o}UseCase } from '../application/use-cases/list-${r}.use-case'
106
+ import { Update${e}UseCase } from '../application/use-cases/update-${t}.use-case'
107
+ import { Delete${e}UseCase } from '../application/use-cases/delete-${t}.use-case'
108
+ import { create${e}Schema } from '../application/dtos/create-${t}.dto'
109
+ import { update${e}Schema } from '../application/dtos/update-${t}.dto'
110
+ import { ${e.toUpperCase()}_QUERY_CONFIG } from '../constants'
209
111
 
210
112
  @Controller()
211
- export class ${pascal}Controller {
212
- @Autowired() private create${pascal}UseCase!: Create${pascal}UseCase
213
- @Autowired() private get${pascal}UseCase!: Get${pascal}UseCase
214
- @Autowired() private list${pluralPascal}UseCase!: List${pluralPascal}UseCase
215
- @Autowired() private update${pascal}UseCase!: Update${pascal}UseCase
216
- @Autowired() private delete${pascal}UseCase!: Delete${pascal}UseCase
113
+ export class ${e}Controller {
114
+ @Autowired() private create${e}UseCase!: Create${e}UseCase
115
+ @Autowired() private get${e}UseCase!: Get${e}UseCase
116
+ @Autowired() private list${o}UseCase!: List${o}UseCase
117
+ @Autowired() private update${e}UseCase!: Update${e}UseCase
118
+ @Autowired() private delete${e}UseCase!: Delete${e}UseCase
217
119
 
218
120
  @Get('/')
219
- @ApiTags('${pascal}')
220
- @ApiQueryParams(${pascal.toUpperCase()}_QUERY_CONFIG)
121
+ @ApiTags('${e}')
122
+ @ApiQueryParams(${e.toUpperCase()}_QUERY_CONFIG)
221
123
  async list(ctx: RequestContext) {
222
124
  return ctx.paginate(
223
- (parsed) => this.list${pluralPascal}UseCase.execute(parsed),
224
- ${pascal.toUpperCase()}_QUERY_CONFIG,
125
+ (parsed) => this.list${o}UseCase.execute(parsed),
126
+ ${e.toUpperCase()}_QUERY_CONFIG,
225
127
  )
226
128
  }
227
129
 
228
130
  @Get('/:id')
229
- @ApiTags('${pascal}')
131
+ @ApiTags('${e}')
230
132
  async getById(ctx: RequestContext) {
231
- const result = await this.get${pascal}UseCase.execute(ctx.params.id)
232
- if (!result) return ctx.notFound('${pascal} not found')
133
+ const result = await this.get${e}UseCase.execute(ctx.params.id)
134
+ if (!result) return ctx.notFound('${e} not found')
233
135
  ctx.json(result)
234
136
  }
235
137
 
236
- @Post('/', { body: create${pascal}Schema, name: 'Create${pascal}' })
237
- @ApiTags('${pascal}')
138
+ @Post('/', { body: create${e}Schema, name: 'Create${e}' })
139
+ @ApiTags('${e}')
238
140
  async create(ctx: RequestContext) {
239
- const result = await this.create${pascal}UseCase.execute(ctx.body)
141
+ const result = await this.create${e}UseCase.execute(ctx.body)
240
142
  ctx.created(result)
241
143
  }
242
144
 
243
- @Put('/:id', { body: update${pascal}Schema, name: 'Update${pascal}' })
244
- @ApiTags('${pascal}')
145
+ @Put('/:id', { body: update${e}Schema, name: 'Update${e}' })
146
+ @ApiTags('${e}')
245
147
  async update(ctx: RequestContext) {
246
- const result = await this.update${pascal}UseCase.execute(ctx.params.id, ctx.body)
148
+ const result = await this.update${e}UseCase.execute(ctx.params.id, ctx.body)
247
149
  ctx.json(result)
248
150
  }
249
151
 
250
152
  @Delete('/:id')
251
- @ApiTags('${pascal}')
153
+ @ApiTags('${e}')
252
154
  async remove(ctx: RequestContext) {
253
- await this.delete${pascal}UseCase.execute(ctx.params.id)
155
+ await this.delete${e}UseCase.execute(ctx.params.id)
254
156
  ctx.noContent()
255
157
  }
256
158
  }
257
- `;
258
- }
259
- __name(generateController, "generateController");
260
- function generateRestController(pascal, kebab, plural, pluralPascal) {
261
- const camel = pascal.charAt(0).toLowerCase() + pascal.slice(1);
262
- return `import { Controller, Get, Post, Put, Delete, Autowired, ApiQueryParams } from '@forinda/kickjs-core'
159
+ `}i(Y,"generateController");function B(e,t,r,o){let n=e.charAt(0).toLowerCase()+e.slice(1);return`import { Controller, Get, Post, Put, Delete, Autowired, ApiQueryParams } from '@forinda/kickjs-core'
263
160
  import type { RequestContext } from '@forinda/kickjs-http'
264
161
  import { ApiTags } from '@forinda/kickjs-swagger'
265
- import { ${pascal}Service } from './${kebab}.service'
266
- import { create${pascal}Schema } from './dtos/create-${kebab}.dto'
267
- import { update${pascal}Schema } from './dtos/update-${kebab}.dto'
268
- import { ${pascal.toUpperCase()}_QUERY_CONFIG } from './${kebab}.constants'
162
+ import { ${e}Service } from './${t}.service'
163
+ import { create${e}Schema } from './dtos/create-${t}.dto'
164
+ import { update${e}Schema } from './dtos/update-${t}.dto'
165
+ import { ${e.toUpperCase()}_QUERY_CONFIG } from './${t}.constants'
269
166
 
270
167
  @Controller()
271
- export class ${pascal}Controller {
272
- @Autowired() private ${camel}Service!: ${pascal}Service
168
+ export class ${e}Controller {
169
+ @Autowired() private ${n}Service!: ${e}Service
273
170
 
274
171
  @Get('/')
275
- @ApiTags('${pascal}')
276
- @ApiQueryParams(${pascal.toUpperCase()}_QUERY_CONFIG)
172
+ @ApiTags('${e}')
173
+ @ApiQueryParams(${e.toUpperCase()}_QUERY_CONFIG)
277
174
  async list(ctx: RequestContext) {
278
175
  return ctx.paginate(
279
- (parsed) => this.${camel}Service.findPaginated(parsed),
280
- ${pascal.toUpperCase()}_QUERY_CONFIG,
176
+ (parsed) => this.${n}Service.findPaginated(parsed),
177
+ ${e.toUpperCase()}_QUERY_CONFIG,
281
178
  )
282
179
  }
283
180
 
284
181
  @Get('/:id')
285
- @ApiTags('${pascal}')
182
+ @ApiTags('${e}')
286
183
  async getById(ctx: RequestContext) {
287
- const result = await this.${camel}Service.findById(ctx.params.id)
288
- if (!result) return ctx.notFound('${pascal} not found')
184
+ const result = await this.${n}Service.findById(ctx.params.id)
185
+ if (!result) return ctx.notFound('${e} not found')
289
186
  ctx.json(result)
290
187
  }
291
188
 
292
- @Post('/', { body: create${pascal}Schema, name: 'Create${pascal}' })
293
- @ApiTags('${pascal}')
189
+ @Post('/', { body: create${e}Schema, name: 'Create${e}' })
190
+ @ApiTags('${e}')
294
191
  async create(ctx: RequestContext) {
295
- const result = await this.${camel}Service.create(ctx.body)
192
+ const result = await this.${n}Service.create(ctx.body)
296
193
  ctx.created(result)
297
194
  }
298
195
 
299
- @Put('/:id', { body: update${pascal}Schema, name: 'Update${pascal}' })
300
- @ApiTags('${pascal}')
196
+ @Put('/:id', { body: update${e}Schema, name: 'Update${e}' })
197
+ @ApiTags('${e}')
301
198
  async update(ctx: RequestContext) {
302
- const result = await this.${camel}Service.update(ctx.params.id, ctx.body)
199
+ const result = await this.${n}Service.update(ctx.params.id, ctx.body)
303
200
  ctx.json(result)
304
201
  }
305
202
 
306
203
  @Delete('/:id')
307
- @ApiTags('${pascal}')
204
+ @ApiTags('${e}')
308
205
  async remove(ctx: RequestContext) {
309
- await this.${camel}Service.delete(ctx.params.id)
206
+ await this.${n}Service.delete(ctx.params.id)
310
207
  ctx.noContent()
311
208
  }
312
209
  }
313
- `;
314
- }
315
- __name(generateRestController, "generateRestController");
316
-
317
- // src/generators/templates/constants.ts
318
- function generateConstants(pascal) {
319
- return `import type { QueryParamsConfig } from '@forinda/kickjs-core'
210
+ `}i(B,"generateRestController");function L(e){return`import type { QueryParamsConfig } from '@forinda/kickjs-core'
320
211
 
321
- export const ${pascal.toUpperCase()}_QUERY_CONFIG: QueryParamsConfig = {
212
+ export const ${e.toUpperCase()}_QUERY_CONFIG: QueryParamsConfig = {
322
213
  filterable: ['name'],
323
214
  sortable: ['name', 'createdAt'],
324
215
  searchable: ['name'],
325
216
  }
326
- `;
327
- }
328
- __name(generateConstants, "generateConstants");
329
- function generateDrizzleConstants(pascal, kebab) {
330
- return `import type { DrizzleQueryParamsConfig } from '@forinda/kickjs-drizzle'
217
+ `}i(L,"generateConstants");function W(e,t){return`import type { DrizzleQueryParamsConfig } from '@forinda/kickjs-drizzle'
331
218
  // TODO: Import your schema table and reference actual columns for type safety
332
- // import { ${kebab}s } from '@/db/schema'
219
+ // import { ${t}s } from '@/db/schema'
333
220
 
334
- export const ${pascal.toUpperCase()}_QUERY_CONFIG: DrizzleQueryParamsConfig = {
221
+ export const ${e.toUpperCase()}_QUERY_CONFIG: DrizzleQueryParamsConfig = {
335
222
  columns: {
336
223
  // Replace with actual Drizzle Column references for type-safe filtering:
337
- // name: ${kebab}s.name,
338
- // status: ${kebab}s.status,
224
+ // name: ${t}s.name,
225
+ // status: ${t}s.status,
339
226
  },
340
227
  sortable: {
341
- // name: ${kebab}s.name,
342
- // createdAt: ${kebab}s.createdAt,
228
+ // name: ${t}s.name,
229
+ // createdAt: ${t}s.createdAt,
343
230
  },
344
231
  searchColumns: [
345
- // ${kebab}s.name,
232
+ // ${t}s.name,
346
233
  ],
347
234
  }
348
- `;
349
- }
350
- __name(generateDrizzleConstants, "generateDrizzleConstants");
351
-
352
- // src/generators/templates/dtos.ts
353
- function generateCreateDTO(pascal, kebab) {
354
- return `import { z } from 'zod'
235
+ `}i(W,"generateDrizzleConstants");function R(e,t){return`import { z } from 'zod'
355
236
 
356
237
  /**
357
- * Create ${pascal} DTO \u2014 Zod schema for validating POST request bodies.
358
- * This schema is passed to @Post('/', { body: create${pascal}Schema }) for automatic validation.
238
+ * Create ${e} DTO \u2014 Zod schema for validating POST request bodies.
239
+ * This schema is passed to @Post('/', { body: create${e}Schema }) for automatic validation.
359
240
  * It also generates OpenAPI request body docs when SwaggerAdapter is used.
360
241
  *
361
242
  * Add more fields as needed. Supported Zod types:
362
243
  * z.string(), z.number(), z.boolean(), z.enum([...]),
363
244
  * z.array(), z.object(), .optional(), .default(), .transform()
364
245
  */
365
- export const create${pascal}Schema = z.object({
246
+ export const create${e}Schema = z.object({
366
247
  name: z.string().min(1, 'Name is required').max(200),
367
248
  })
368
249
 
369
- export type Create${pascal}DTO = z.infer<typeof create${pascal}Schema>
370
- `;
371
- }
372
- __name(generateCreateDTO, "generateCreateDTO");
373
- function generateUpdateDTO(pascal, kebab) {
374
- return `import { z } from 'zod'
250
+ export type Create${e}DTO = z.infer<typeof create${e}Schema>
251
+ `}i(R,"generateCreateDTO");function D(e,t){return`import { z } from 'zod'
375
252
 
376
- export const update${pascal}Schema = z.object({
253
+ export const update${e}Schema = z.object({
377
254
  name: z.string().min(1).max(200).optional(),
378
255
  })
379
256
 
380
- export type Update${pascal}DTO = z.infer<typeof update${pascal}Schema>
381
- `;
382
- }
383
- __name(generateUpdateDTO, "generateUpdateDTO");
384
- function generateResponseDTO(pascal, kebab) {
385
- return `export interface ${pascal}ResponseDTO {
257
+ export type Update${e}DTO = z.infer<typeof update${e}Schema>
258
+ `}i(D,"generateUpdateDTO");function O(e,t){return`export interface ${e}ResponseDTO {
386
259
  id: string
387
260
  name: string
388
261
  createdAt: string
389
262
  updatedAt: string
390
263
  }
391
- `;
392
- }
393
- __name(generateResponseDTO, "generateResponseDTO");
394
-
395
- // src/generators/templates/use-cases.ts
396
- function generateUseCases(pascal, kebab, plural, pluralPascal) {
397
- return [
398
- {
399
- file: `create-${kebab}.use-case.ts`,
400
- content: `/**
401
- * Create ${pascal} Use Case
264
+ `}i(O,"generateResponseDTO");function b(e,t,r,o){return[{file:`create-${t}.use-case.ts`,content:`/**
265
+ * Create ${e} Use Case
402
266
  *
403
267
  * Application layer \u2014 orchestrates a single business operation.
404
268
  * Use cases are thin: validate input (via DTO), call domain/repo, return response.
405
269
  * Keep business rules in the domain service, not here.
406
270
  */
407
271
  import { Service, Inject } from '@forinda/kickjs-core'
408
- import { ${pascal.toUpperCase()}_REPOSITORY, type I${pascal}Repository } from '../../domain/repositories/${kebab}.repository'
409
- import type { Create${pascal}DTO } from '../dtos/create-${kebab}.dto'
410
- import type { ${pascal}ResponseDTO } from '../dtos/${kebab}-response.dto'
272
+ import { ${e.toUpperCase()}_REPOSITORY, type I${e}Repository } from '../../domain/repositories/${t}.repository'
273
+ import type { Create${e}DTO } from '../dtos/create-${t}.dto'
274
+ import type { ${e}ResponseDTO } from '../dtos/${t}-response.dto'
411
275
 
412
276
  @Service()
413
- export class Create${pascal}UseCase {
277
+ export class Create${e}UseCase {
414
278
  constructor(
415
- @Inject(${pascal.toUpperCase()}_REPOSITORY) private readonly repo: I${pascal}Repository,
279
+ @Inject(${e.toUpperCase()}_REPOSITORY) private readonly repo: I${e}Repository,
416
280
  ) {}
417
281
 
418
- async execute(dto: Create${pascal}DTO): Promise<${pascal}ResponseDTO> {
282
+ async execute(dto: Create${e}DTO): Promise<${e}ResponseDTO> {
419
283
  return this.repo.create(dto)
420
284
  }
421
285
  }
422
- `
423
- },
424
- {
425
- file: `get-${kebab}.use-case.ts`,
426
- content: `import { Service, Inject } from '@forinda/kickjs-core'
427
- import { ${pascal.toUpperCase()}_REPOSITORY, type I${pascal}Repository } from '../../domain/repositories/${kebab}.repository'
428
- import type { ${pascal}ResponseDTO } from '../dtos/${kebab}-response.dto'
286
+ `},{file:`get-${t}.use-case.ts`,content:`import { Service, Inject } from '@forinda/kickjs-core'
287
+ import { ${e.toUpperCase()}_REPOSITORY, type I${e}Repository } from '../../domain/repositories/${t}.repository'
288
+ import type { ${e}ResponseDTO } from '../dtos/${t}-response.dto'
429
289
 
430
290
  @Service()
431
- export class Get${pascal}UseCase {
291
+ export class Get${e}UseCase {
432
292
  constructor(
433
- @Inject(${pascal.toUpperCase()}_REPOSITORY) private readonly repo: I${pascal}Repository,
293
+ @Inject(${e.toUpperCase()}_REPOSITORY) private readonly repo: I${e}Repository,
434
294
  ) {}
435
295
 
436
- async execute(id: string): Promise<${pascal}ResponseDTO | null> {
296
+ async execute(id: string): Promise<${e}ResponseDTO | null> {
437
297
  return this.repo.findById(id)
438
298
  }
439
299
  }
440
- `
441
- },
442
- {
443
- file: `list-${plural}.use-case.ts`,
444
- content: `import { Service, Inject } from '@forinda/kickjs-core'
445
- import { ${pascal.toUpperCase()}_REPOSITORY, type I${pascal}Repository } from '../../domain/repositories/${kebab}.repository'
300
+ `},{file:`list-${r}.use-case.ts`,content:`import { Service, Inject } from '@forinda/kickjs-core'
301
+ import { ${e.toUpperCase()}_REPOSITORY, type I${e}Repository } from '../../domain/repositories/${t}.repository'
446
302
  import type { ParsedQuery } from '@forinda/kickjs-http'
447
303
 
448
304
  @Service()
449
- export class List${pluralPascal}UseCase {
305
+ export class List${o}UseCase {
450
306
  constructor(
451
- @Inject(${pascal.toUpperCase()}_REPOSITORY) private readonly repo: I${pascal}Repository,
307
+ @Inject(${e.toUpperCase()}_REPOSITORY) private readonly repo: I${e}Repository,
452
308
  ) {}
453
309
 
454
310
  async execute(parsed: ParsedQuery) {
455
311
  return this.repo.findPaginated(parsed)
456
312
  }
457
313
  }
458
- `
459
- },
460
- {
461
- file: `update-${kebab}.use-case.ts`,
462
- content: `import { Service, Inject } from '@forinda/kickjs-core'
463
- import { ${pascal.toUpperCase()}_REPOSITORY, type I${pascal}Repository } from '../../domain/repositories/${kebab}.repository'
464
- import type { Update${pascal}DTO } from '../dtos/update-${kebab}.dto'
465
- import type { ${pascal}ResponseDTO } from '../dtos/${kebab}-response.dto'
314
+ `},{file:`update-${t}.use-case.ts`,content:`import { Service, Inject } from '@forinda/kickjs-core'
315
+ import { ${e.toUpperCase()}_REPOSITORY, type I${e}Repository } from '../../domain/repositories/${t}.repository'
316
+ import type { Update${e}DTO } from '../dtos/update-${t}.dto'
317
+ import type { ${e}ResponseDTO } from '../dtos/${t}-response.dto'
466
318
 
467
319
  @Service()
468
- export class Update${pascal}UseCase {
320
+ export class Update${e}UseCase {
469
321
  constructor(
470
- @Inject(${pascal.toUpperCase()}_REPOSITORY) private readonly repo: I${pascal}Repository,
322
+ @Inject(${e.toUpperCase()}_REPOSITORY) private readonly repo: I${e}Repository,
471
323
  ) {}
472
324
 
473
- async execute(id: string, dto: Update${pascal}DTO): Promise<${pascal}ResponseDTO> {
325
+ async execute(id: string, dto: Update${e}DTO): Promise<${e}ResponseDTO> {
474
326
  return this.repo.update(id, dto)
475
327
  }
476
328
  }
477
- `
478
- },
479
- {
480
- file: `delete-${kebab}.use-case.ts`,
481
- content: `import { Service, Inject } from '@forinda/kickjs-core'
482
- import { ${pascal.toUpperCase()}_REPOSITORY, type I${pascal}Repository } from '../../domain/repositories/${kebab}.repository'
329
+ `},{file:`delete-${t}.use-case.ts`,content:`import { Service, Inject } from '@forinda/kickjs-core'
330
+ import { ${e.toUpperCase()}_REPOSITORY, type I${e}Repository } from '../../domain/repositories/${t}.repository'
483
331
 
484
332
  @Service()
485
- export class Delete${pascal}UseCase {
333
+ export class Delete${e}UseCase {
486
334
  constructor(
487
- @Inject(${pascal.toUpperCase()}_REPOSITORY) private readonly repo: I${pascal}Repository,
335
+ @Inject(${e.toUpperCase()}_REPOSITORY) private readonly repo: I${e}Repository,
488
336
  ) {}
489
337
 
490
338
  async execute(id: string): Promise<void> {
491
339
  await this.repo.delete(id)
492
340
  }
493
341
  }
494
- `
495
- }
496
- ];
497
- }
498
- __name(generateUseCases, "generateUseCases");
499
-
500
- // src/generators/templates/repository.ts
501
- function generateRepositoryInterface(pascal, kebab, dtoPrefix = "../../application/dtos") {
502
- return `/**
503
- * ${pascal} Repository Interface
342
+ `}]}i(b,"generateUseCases");function k(e,t,r="../../application/dtos"){return`/**
343
+ * ${e} Repository Interface
504
344
  *
505
345
  * Defines the contract for data access.
506
346
  * The interface declares what operations are available;
@@ -508,27 +348,23 @@ function generateRepositoryInterface(pascal, kebab, dtoPrefix = "../../applicati
508
348
  *
509
349
  * To swap implementations, change the factory in the module's register() method.
510
350
  */
511
- import type { ${pascal}ResponseDTO } from '${dtoPrefix}/${kebab}-response.dto'
512
- import type { Create${pascal}DTO } from '${dtoPrefix}/create-${kebab}.dto'
513
- import type { Update${pascal}DTO } from '${dtoPrefix}/update-${kebab}.dto'
351
+ import type { ${e}ResponseDTO } from '${r}/${t}-response.dto'
352
+ import type { Create${e}DTO } from '${r}/create-${t}.dto'
353
+ import type { Update${e}DTO } from '${r}/update-${t}.dto'
514
354
  import type { ParsedQuery } from '@forinda/kickjs-http'
515
355
 
516
- export interface I${pascal}Repository {
517
- findById(id: string): Promise<${pascal}ResponseDTO | null>
518
- findAll(): Promise<${pascal}ResponseDTO[]>
519
- findPaginated(parsed: ParsedQuery): Promise<{ data: ${pascal}ResponseDTO[]; total: number }>
520
- create(dto: Create${pascal}DTO): Promise<${pascal}ResponseDTO>
521
- update(id: string, dto: Update${pascal}DTO): Promise<${pascal}ResponseDTO>
356
+ export interface I${e}Repository {
357
+ findById(id: string): Promise<${e}ResponseDTO | null>
358
+ findAll(): Promise<${e}ResponseDTO[]>
359
+ findPaginated(parsed: ParsedQuery): Promise<{ data: ${e}ResponseDTO[]; total: number }>
360
+ create(dto: Create${e}DTO): Promise<${e}ResponseDTO>
361
+ update(id: string, dto: Update${e}DTO): Promise<${e}ResponseDTO>
522
362
  delete(id: string): Promise<void>
523
363
  }
524
364
 
525
- export const ${pascal.toUpperCase()}_REPOSITORY = Symbol('I${pascal}Repository')
526
- `;
527
- }
528
- __name(generateRepositoryInterface, "generateRepositoryInterface");
529
- function generateInMemoryRepository(pascal, kebab, repoPrefix = "../../domain/repositories", dtoPrefix = "../../application/dtos") {
530
- return `/**
531
- * In-Memory ${pascal} Repository
365
+ export const ${e.toUpperCase()}_REPOSITORY = Symbol('I${e}Repository')
366
+ `}i(k,"generateRepositoryInterface");function I(e,t,r="../../domain/repositories",o="../../application/dtos"){return`/**
367
+ * In-Memory ${e} Repository
532
368
  *
533
369
  * Implements the repository interface using a Map.
534
370
  * Useful for prototyping and testing. Replace with a database implementation
@@ -539,32 +375,32 @@ function generateInMemoryRepository(pascal, kebab, repoPrefix = "../../domain/re
539
375
  import { randomUUID } from 'node:crypto'
540
376
  import { Repository, HttpException } from '@forinda/kickjs-core'
541
377
  import type { ParsedQuery } from '@forinda/kickjs-http'
542
- import type { I${pascal}Repository } from '${repoPrefix}/${kebab}.repository'
543
- import type { ${pascal}ResponseDTO } from '${dtoPrefix}/${kebab}-response.dto'
544
- import type { Create${pascal}DTO } from '${dtoPrefix}/create-${kebab}.dto'
545
- import type { Update${pascal}DTO } from '${dtoPrefix}/update-${kebab}.dto'
378
+ import type { I${e}Repository } from '${r}/${t}.repository'
379
+ import type { ${e}ResponseDTO } from '${o}/${t}-response.dto'
380
+ import type { Create${e}DTO } from '${o}/create-${t}.dto'
381
+ import type { Update${e}DTO } from '${o}/update-${t}.dto'
546
382
 
547
383
  @Repository()
548
- export class InMemory${pascal}Repository implements I${pascal}Repository {
549
- private store = new Map<string, ${pascal}ResponseDTO>()
384
+ export class InMemory${e}Repository implements I${e}Repository {
385
+ private store = new Map<string, ${e}ResponseDTO>()
550
386
 
551
- async findById(id: string): Promise<${pascal}ResponseDTO | null> {
387
+ async findById(id: string): Promise<${e}ResponseDTO | null> {
552
388
  return this.store.get(id) ?? null
553
389
  }
554
390
 
555
- async findAll(): Promise<${pascal}ResponseDTO[]> {
391
+ async findAll(): Promise<${e}ResponseDTO[]> {
556
392
  return Array.from(this.store.values())
557
393
  }
558
394
 
559
- async findPaginated(parsed: ParsedQuery): Promise<{ data: ${pascal}ResponseDTO[]; total: number }> {
395
+ async findPaginated(parsed: ParsedQuery): Promise<{ data: ${e}ResponseDTO[]; total: number }> {
560
396
  const all = Array.from(this.store.values())
561
397
  const data = all.slice(parsed.pagination.offset, parsed.pagination.offset + parsed.pagination.limit)
562
398
  return { data, total: all.length }
563
399
  }
564
400
 
565
- async create(dto: Create${pascal}DTO): Promise<${pascal}ResponseDTO> {
401
+ async create(dto: Create${e}DTO): Promise<${e}ResponseDTO> {
566
402
  const now = new Date().toISOString()
567
- const entity: ${pascal}ResponseDTO = {
403
+ const entity: ${e}ResponseDTO = {
568
404
  id: randomUUID(),
569
405
  name: dto.name,
570
406
  createdAt: now,
@@ -574,25 +410,21 @@ export class InMemory${pascal}Repository implements I${pascal}Repository {
574
410
  return entity
575
411
  }
576
412
 
577
- async update(id: string, dto: Update${pascal}DTO): Promise<${pascal}ResponseDTO> {
413
+ async update(id: string, dto: Update${e}DTO): Promise<${e}ResponseDTO> {
578
414
  const existing = this.store.get(id)
579
- if (!existing) throw HttpException.notFound('${pascal} not found')
415
+ if (!existing) throw HttpException.notFound('${e} not found')
580
416
  const updated = { ...existing, ...dto, updatedAt: new Date().toISOString() }
581
417
  this.store.set(id, updated)
582
418
  return updated
583
419
  }
584
420
 
585
421
  async delete(id: string): Promise<void> {
586
- if (!this.store.has(id)) throw HttpException.notFound('${pascal} not found')
422
+ if (!this.store.has(id)) throw HttpException.notFound('${e} not found')
587
423
  this.store.delete(id)
588
424
  }
589
425
  }
590
- `;
591
- }
592
- __name(generateInMemoryRepository, "generateInMemoryRepository");
593
- function generateDrizzleRepository(pascal, kebab, repoPrefix = "../../domain/repositories", dtoPrefix = "../../application/dtos") {
594
- return `/**
595
- * Drizzle ${pascal} Repository
426
+ `}i(I,"generateInMemoryRepository");function T(e,t,r="../../domain/repositories",o="../../application/dtos"){return`/**
427
+ * Drizzle ${e} Repository
596
428
  *
597
429
  * Implements the repository interface using Drizzle ORM.
598
430
  * Uses buildFromColumns() with Column objects for type-safe query building.
@@ -606,185 +438,170 @@ import { eq, ne, gt, gte, lt, lte, ilike, inArray, between, and, or, asc, desc,
606
438
  import { Repository, HttpException, Inject } from '@forinda/kickjs-core'
607
439
  import { DRIZZLE_DB, DrizzleQueryAdapter } from '@forinda/kickjs-drizzle'
608
440
  import type { ParsedQuery } from '@forinda/kickjs-http'
609
- import type { I${pascal}Repository } from '${repoPrefix}/${kebab}.repository'
610
- import type { ${pascal}ResponseDTO } from '${dtoPrefix}/${kebab}-response.dto'
611
- import type { Create${pascal}DTO } from '${dtoPrefix}/create-${kebab}.dto'
612
- import type { Update${pascal}DTO } from '${dtoPrefix}/update-${kebab}.dto'
613
- import { ${pascal.toUpperCase()}_QUERY_CONFIG } from '../../constants'
441
+ import type { I${e}Repository } from '${r}/${t}.repository'
442
+ import type { ${e}ResponseDTO } from '${o}/${t}-response.dto'
443
+ import type { Create${e}DTO } from '${o}/create-${t}.dto'
444
+ import type { Update${e}DTO } from '${o}/update-${t}.dto'
445
+ import { ${e.toUpperCase()}_QUERY_CONFIG } from '../../constants'
614
446
 
615
447
  // TODO: Import your Drizzle schema table \u2014 e.g.:
616
- // import { ${kebab}s } from '@/db/schema'
448
+ // import { ${t}s } from '@/db/schema'
617
449
 
618
450
  const queryAdapter = new DrizzleQueryAdapter({
619
451
  eq, ne, gt, gte, lt, lte, ilike, inArray, between, and, or, asc, desc,
620
452
  })
621
453
 
622
454
  @Repository()
623
- export class Drizzle${pascal}Repository implements I${pascal}Repository {
455
+ export class Drizzle${e}Repository implements I${e}Repository {
624
456
  constructor(@Inject(DRIZZLE_DB) private db: any) {}
625
457
 
626
- async findById(id: string): Promise<${pascal}ResponseDTO | null> {
458
+ async findById(id: string): Promise<${e}ResponseDTO | null> {
627
459
  // TODO: Implement with Drizzle
628
- // const row = this.db.select().from(${kebab}s).where(eq(${kebab}s.id, id)).get()
460
+ // const row = this.db.select().from(${t}s).where(eq(${t}s.id, id)).get()
629
461
  // return row ?? null
630
- throw new Error('Drizzle ${pascal} repository not yet implemented \u2014 update schema imports and queries')
462
+ throw new Error('Drizzle ${e} repository not yet implemented \u2014 update schema imports and queries')
631
463
  }
632
464
 
633
- async findAll(): Promise<${pascal}ResponseDTO[]> {
465
+ async findAll(): Promise<${e}ResponseDTO[]> {
634
466
  // TODO: Implement with Drizzle
635
- // return this.db.select().from(${kebab}s).all()
636
- throw new Error('Drizzle ${pascal} repository not yet implemented')
467
+ // return this.db.select().from(${t}s).all()
468
+ throw new Error('Drizzle ${e} repository not yet implemented')
637
469
  }
638
470
 
639
- async findPaginated(parsed: ParsedQuery): Promise<{ data: ${pascal}ResponseDTO[]; total: number }> {
471
+ async findPaginated(parsed: ParsedQuery): Promise<{ data: ${e}ResponseDTO[]; total: number }> {
640
472
  // TODO: Use buildFromColumns() with your query config for type-safe filtering
641
- // const query = queryAdapter.buildFromColumns(parsed, ${pascal.toUpperCase()}_QUERY_CONFIG)
473
+ // const query = queryAdapter.buildFromColumns(parsed, ${e.toUpperCase()}_QUERY_CONFIG)
642
474
  //
643
475
  // const data = this.db
644
- // .select().from(${kebab}s).$dynamic()
476
+ // .select().from(${t}s).$dynamic()
645
477
  // .where(query.where).orderBy(...query.orderBy)
646
478
  // .limit(query.limit).offset(query.offset).all()
647
479
  //
648
480
  // const totalResult = this.db
649
- // .select({ count: count() }).from(${kebab}s)
481
+ // .select({ count: count() }).from(${t}s)
650
482
  // .$dynamic().where(query.where).get()
651
483
  //
652
484
  // return { data, total: totalResult?.count ?? 0 }
653
- throw new Error('Drizzle ${pascal} repository not yet implemented')
485
+ throw new Error('Drizzle ${e} repository not yet implemented')
654
486
  }
655
487
 
656
- async create(dto: Create${pascal}DTO): Promise<${pascal}ResponseDTO> {
488
+ async create(dto: Create${e}DTO): Promise<${e}ResponseDTO> {
657
489
  // TODO: Implement with Drizzle
658
- // return this.db.insert(${kebab}s).values(dto).returning().get()
659
- throw new Error('Drizzle ${pascal} repository not yet implemented')
490
+ // return this.db.insert(${t}s).values(dto).returning().get()
491
+ throw new Error('Drizzle ${e} repository not yet implemented')
660
492
  }
661
493
 
662
- async update(id: string, dto: Update${pascal}DTO): Promise<${pascal}ResponseDTO> {
494
+ async update(id: string, dto: Update${e}DTO): Promise<${e}ResponseDTO> {
663
495
  // TODO: Implement with Drizzle
664
- // const row = this.db.update(${kebab}s).set(dto).where(eq(${kebab}s.id, id)).returning().get()
665
- // if (!row) throw HttpException.notFound('${pascal} not found')
496
+ // const row = this.db.update(${t}s).set(dto).where(eq(${t}s.id, id)).returning().get()
497
+ // if (!row) throw HttpException.notFound('${e} not found')
666
498
  // return row
667
- throw new Error('Drizzle ${pascal} repository not yet implemented')
499
+ throw new Error('Drizzle ${e} repository not yet implemented')
668
500
  }
669
501
 
670
502
  async delete(id: string): Promise<void> {
671
503
  // TODO: Implement with Drizzle
672
- // this.db.delete(${kebab}s).where(eq(${kebab}s.id, id)).run()
673
- throw new Error('Drizzle ${pascal} repository not yet implemented')
504
+ // this.db.delete(${t}s).where(eq(${t}s.id, id)).run()
505
+ throw new Error('Drizzle ${e} repository not yet implemented')
674
506
  }
675
507
  }
676
- `;
677
- }
678
- __name(generateDrizzleRepository, "generateDrizzleRepository");
679
- function generatePrismaRepository(pascal, kebab, repoPrefix = "../../domain/repositories", dtoPrefix = "../../application/dtos") {
680
- const camel = kebab.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
681
- return `/**
682
- * Prisma ${pascal} Repository
508
+ `}i(T,"generateDrizzleRepository");function P(e,t,r="../../domain/repositories",o="../../application/dtos"){let n=t.replace(/-([a-z])/g,(s,p)=>p.toUpperCase());return`/**
509
+ * Prisma ${e} Repository
683
510
  *
684
511
  * Implements the repository interface using Prisma Client.
685
512
  * Requires a PrismaClient instance injected via the DI container.
686
513
  *
687
- * TODO: Ensure your Prisma schema has a '${pascal}' model defined.
514
+ * TODO: Ensure your Prisma schema has a '${e}' model defined.
688
515
  * TODO: Replace 'PRISMA_CLIENT' with your actual Prisma injection token.
689
516
  *
690
517
  * @Repository() registers this class in the DI container as a singleton.
691
518
  */
692
519
  import { Repository, HttpException, Autowired } from '@forinda/kickjs-core'
693
520
  import type { ParsedQuery } from '@forinda/kickjs-http'
694
- import type { I${pascal}Repository } from '${repoPrefix}/${kebab}.repository'
695
- import type { ${pascal}ResponseDTO } from '${dtoPrefix}/${kebab}-response.dto'
696
- import type { Create${pascal}DTO } from '${dtoPrefix}/create-${kebab}.dto'
697
- import type { Update${pascal}DTO } from '${dtoPrefix}/update-${kebab}.dto'
521
+ import type { I${e}Repository } from '${r}/${t}.repository'
522
+ import type { ${e}ResponseDTO } from '${o}/${t}-response.dto'
523
+ import type { Create${e}DTO } from '${o}/create-${t}.dto'
524
+ import type { Update${e}DTO } from '${o}/update-${t}.dto'
698
525
 
699
526
  // TODO: Import your Prisma injection token \u2014 e.g.:
700
527
  // import { PRISMA_CLIENT } from '@/db/prisma.provider'
701
528
  // import type { PrismaClient } from '@prisma/client'
702
529
 
703
530
  @Repository()
704
- export class Prisma${pascal}Repository implements I${pascal}Repository {
531
+ export class Prisma${e}Repository implements I${e}Repository {
705
532
  // TODO: Uncomment and configure your Prisma injection:
706
533
  // @Autowired(PRISMA_CLIENT) private prisma!: PrismaClient
707
534
 
708
- async findById(id: string): Promise<${pascal}ResponseDTO | null> {
535
+ async findById(id: string): Promise<${e}ResponseDTO | null> {
709
536
  // TODO: Implement with Prisma
710
- // return this.prisma.${camel}.findUnique({ where: { id } })
711
- throw new Error('Prisma ${pascal} repository not yet implemented \u2014 update Prisma imports and queries')
537
+ // return this.prisma.${n}.findUnique({ where: { id } })
538
+ throw new Error('Prisma ${e} repository not yet implemented \u2014 update Prisma imports and queries')
712
539
  }
713
540
 
714
- async findAll(): Promise<${pascal}ResponseDTO[]> {
541
+ async findAll(): Promise<${e}ResponseDTO[]> {
715
542
  // TODO: Implement with Prisma
716
- // return this.prisma.${camel}.findMany()
717
- throw new Error('Prisma ${pascal} repository not yet implemented')
543
+ // return this.prisma.${n}.findMany()
544
+ throw new Error('Prisma ${e} repository not yet implemented')
718
545
  }
719
546
 
720
- async findPaginated(parsed: ParsedQuery): Promise<{ data: ${pascal}ResponseDTO[]; total: number }> {
547
+ async findPaginated(parsed: ParsedQuery): Promise<{ data: ${e}ResponseDTO[]; total: number }> {
721
548
  // TODO: Implement with Prisma
722
549
  // const [data, total] = await Promise.all([
723
- // this.prisma.${camel}.findMany({
550
+ // this.prisma.${n}.findMany({
724
551
  // skip: parsed.pagination.offset,
725
552
  // take: parsed.pagination.limit,
726
553
  // }),
727
- // this.prisma.${camel}.count(),
554
+ // this.prisma.${n}.count(),
728
555
  // ])
729
556
  // return { data, total }
730
- throw new Error('Prisma ${pascal} repository not yet implemented')
557
+ throw new Error('Prisma ${e} repository not yet implemented')
731
558
  }
732
559
 
733
- async create(dto: Create${pascal}DTO): Promise<${pascal}ResponseDTO> {
560
+ async create(dto: Create${e}DTO): Promise<${e}ResponseDTO> {
734
561
  // TODO: Implement with Prisma
735
- // return this.prisma.${camel}.create({ data: dto })
736
- throw new Error('Prisma ${pascal} repository not yet implemented')
562
+ // return this.prisma.${n}.create({ data: dto })
563
+ throw new Error('Prisma ${e} repository not yet implemented')
737
564
  }
738
565
 
739
- async update(id: string, dto: Update${pascal}DTO): Promise<${pascal}ResponseDTO> {
566
+ async update(id: string, dto: Update${e}DTO): Promise<${e}ResponseDTO> {
740
567
  // TODO: Implement with Prisma
741
- // const row = await this.prisma.${camel}.update({ where: { id }, data: dto })
742
- // if (!row) throw HttpException.notFound('${pascal} not found')
568
+ // const row = await this.prisma.${n}.update({ where: { id }, data: dto })
569
+ // if (!row) throw HttpException.notFound('${e} not found')
743
570
  // return row
744
- throw new Error('Prisma ${pascal} repository not yet implemented')
571
+ throw new Error('Prisma ${e} repository not yet implemented')
745
572
  }
746
573
 
747
574
  async delete(id: string): Promise<void> {
748
575
  // TODO: Implement with Prisma
749
- // await this.prisma.${camel}.delete({ where: { id } })
750
- throw new Error('Prisma ${pascal} repository not yet implemented')
576
+ // await this.prisma.${n}.delete({ where: { id } })
577
+ throw new Error('Prisma ${e} repository not yet implemented')
751
578
  }
752
579
  }
753
- `;
754
- }
755
- __name(generatePrismaRepository, "generatePrismaRepository");
756
-
757
- // src/generators/templates/domain.ts
758
- function generateDomainService(pascal, kebab) {
759
- return `/**
760
- * ${pascal} Domain Service
580
+ `}i(P,"generatePrismaRepository");function K(e,t){return`/**
581
+ * ${e} Domain Service
761
582
  *
762
583
  * Domain layer \u2014 contains business rules that don't belong to a single entity.
763
584
  * Use this for cross-entity logic, validation rules, and domain invariants.
764
585
  * Keep it free of HTTP/framework concerns.
765
586
  */
766
587
  import { Service, Inject, HttpException } from '@forinda/kickjs-core'
767
- import { ${pascal.toUpperCase()}_REPOSITORY, type I${pascal}Repository } from '../repositories/${kebab}.repository'
588
+ import { ${e.toUpperCase()}_REPOSITORY, type I${e}Repository } from '../repositories/${t}.repository'
768
589
 
769
590
  @Service()
770
- export class ${pascal}DomainService {
591
+ export class ${e}DomainService {
771
592
  constructor(
772
- @Inject(${pascal.toUpperCase()}_REPOSITORY) private readonly repo: I${pascal}Repository,
593
+ @Inject(${e.toUpperCase()}_REPOSITORY) private readonly repo: I${e}Repository,
773
594
  ) {}
774
595
 
775
596
  async ensureExists(id: string): Promise<void> {
776
597
  const entity = await this.repo.findById(id)
777
598
  if (!entity) {
778
- throw HttpException.notFound('${pascal} not found')
599
+ throw HttpException.notFound('${e} not found')
779
600
  }
780
601
  }
781
602
  }
782
- `;
783
- }
784
- __name(generateDomainService, "generateDomainService");
785
- function generateEntity(pascal, kebab) {
786
- return `/**
787
- * ${pascal} Entity
603
+ `}i(K,"generateDomainService");function H(e,t){return`/**
604
+ * ${e} Entity
788
605
  *
789
606
  * Domain layer \u2014 the core business object.
790
607
  * Uses a private constructor with static factory methods (create, reconstitute)
@@ -796,33 +613,33 @@ function generateEntity(pascal, kebab) {
796
613
  * - reconstitute(): factory for rebuilding from persistence (no side effects)
797
614
  * - changeName(): mutation method that enforces business rules
798
615
  */
799
- import { ${pascal}Id } from '../value-objects/${kebab}-id.vo'
616
+ import { ${e}Id } from '../value-objects/${t}-id.vo'
800
617
 
801
- interface ${pascal}Props {
802
- id: ${pascal}Id
618
+ interface ${e}Props {
619
+ id: ${e}Id
803
620
  name: string
804
621
  createdAt: Date
805
622
  updatedAt: Date
806
623
  }
807
624
 
808
- export class ${pascal} {
809
- private constructor(private props: ${pascal}Props) {}
625
+ export class ${e} {
626
+ private constructor(private props: ${e}Props) {}
810
627
 
811
- static create(params: { name: string }): ${pascal} {
628
+ static create(params: { name: string }): ${e} {
812
629
  const now = new Date()
813
- return new ${pascal}({
814
- id: ${pascal}Id.create(),
630
+ return new ${e}({
631
+ id: ${e}Id.create(),
815
632
  name: params.name,
816
633
  createdAt: now,
817
634
  updatedAt: now,
818
635
  })
819
636
  }
820
637
 
821
- static reconstitute(props: ${pascal}Props): ${pascal} {
822
- return new ${pascal}(props)
638
+ static reconstitute(props: ${e}Props): ${e} {
639
+ return new ${e}(props)
823
640
  }
824
641
 
825
- get id(): ${pascal}Id {
642
+ get id(): ${e}Id {
826
643
  return this.props.id
827
644
  }
828
645
  get name(): string {
@@ -852,54 +669,44 @@ export class ${pascal} {
852
669
  }
853
670
  }
854
671
  }
855
- `;
856
- }
857
- __name(generateEntity, "generateEntity");
858
- function generateValueObject(pascal, kebab) {
859
- return `/**
860
- * ${pascal} ID Value Object
672
+ `}i(H,"generateEntity");function V(e,t){return`/**
673
+ * ${e} ID Value Object
861
674
  *
862
675
  * Domain layer \u2014 wraps a primitive ID with type safety and validation.
863
676
  * Value objects are immutable and compared by value, not reference.
864
677
  *
865
- * ${pascal}Id.create() \u2014 generate a new UUID
866
- * ${pascal}Id.from(id) \u2014 wrap an existing ID string (validates non-empty)
678
+ * ${e}Id.create() \u2014 generate a new UUID
679
+ * ${e}Id.from(id) \u2014 wrap an existing ID string (validates non-empty)
867
680
  * id.equals(other) \u2014 compare two IDs by value
868
681
  */
869
682
  import { randomUUID } from 'node:crypto'
870
683
 
871
- export class ${pascal}Id {
684
+ export class ${e}Id {
872
685
  private constructor(private readonly value: string) {}
873
686
 
874
- static create(): ${pascal}Id {
875
- return new ${pascal}Id(randomUUID())
687
+ static create(): ${e}Id {
688
+ return new ${e}Id(randomUUID())
876
689
  }
877
690
 
878
- static from(id: string): ${pascal}Id {
691
+ static from(id: string): ${e}Id {
879
692
  if (!id || id.trim().length === 0) {
880
- throw new Error('${pascal}Id cannot be empty')
693
+ throw new Error('${e}Id cannot be empty')
881
694
  }
882
- return new ${pascal}Id(id)
695
+ return new ${e}Id(id)
883
696
  }
884
697
 
885
698
  toString(): string {
886
699
  return this.value
887
700
  }
888
701
 
889
- equals(other: ${pascal}Id): boolean {
702
+ equals(other: ${e}Id): boolean {
890
703
  return this.value === other.value
891
704
  }
892
705
  }
893
- `;
894
- }
895
- __name(generateValueObject, "generateValueObject");
896
-
897
- // src/generators/templates/tests.ts
898
- function generateControllerTest(pascal, kebab, plural) {
899
- return `import { describe, it, expect, beforeEach } from 'vitest'
706
+ `}i(V,"generateValueObject");function S(e,t,r){return`import { describe, it, expect, beforeEach } from 'vitest'
900
707
  import { Container } from '@forinda/kickjs-core'
901
708
 
902
- describe('${pascal}Controller', () => {
709
+ describe('${e}Controller', () => {
903
710
  beforeEach(() => {
904
711
  Container.reset()
905
712
  })
@@ -908,64 +715,60 @@ describe('${pascal}Controller', () => {
908
715
  expect(true).toBe(true)
909
716
  })
910
717
 
911
- describe('POST /${plural}', () => {
912
- it('should create a new ${kebab}', async () => {
718
+ describe('POST /${r}', () => {
719
+ it('should create a new ${t}', async () => {
913
720
  // TODO: Set up test module, call create endpoint, assert 201
914
721
  expect(true).toBe(true)
915
722
  })
916
723
  })
917
724
 
918
- describe('GET /${plural}', () => {
919
- it('should return paginated ${plural}', async () => {
725
+ describe('GET /${r}', () => {
726
+ it('should return paginated ${r}', async () => {
920
727
  // TODO: Set up test module, call list endpoint, assert { data, meta }
921
728
  expect(true).toBe(true)
922
729
  })
923
730
  })
924
731
 
925
- describe('GET /${plural}/:id', () => {
926
- it('should return a ${kebab} by id', async () => {
927
- // TODO: Create a ${kebab}, then fetch by id, assert match
732
+ describe('GET /${r}/:id', () => {
733
+ it('should return a ${t} by id', async () => {
734
+ // TODO: Create a ${t}, then fetch by id, assert match
928
735
  expect(true).toBe(true)
929
736
  })
930
737
 
931
- it('should return 404 for non-existent ${kebab}', async () => {
738
+ it('should return 404 for non-existent ${t}', async () => {
932
739
  // TODO: Fetch non-existent id, assert 404
933
740
  expect(true).toBe(true)
934
741
  })
935
742
  })
936
743
 
937
- describe('PUT /${plural}/:id', () => {
938
- it('should update an existing ${kebab}', async () => {
744
+ describe('PUT /${r}/:id', () => {
745
+ it('should update an existing ${t}', async () => {
939
746
  // TODO: Create, update, assert changes
940
747
  expect(true).toBe(true)
941
748
  })
942
749
  })
943
750
 
944
- describe('DELETE /${plural}/:id', () => {
945
- it('should delete a ${kebab}', async () => {
751
+ describe('DELETE /${r}/:id', () => {
752
+ it('should delete a ${t}', async () => {
946
753
  // TODO: Create, delete, assert gone
947
754
  expect(true).toBe(true)
948
755
  })
949
756
  })
950
757
  })
951
- `;
952
- }
953
- __name(generateControllerTest, "generateControllerTest");
954
- function generateRepositoryTest(pascal, kebab, plural, repoImport = `../infrastructure/repositories/in-memory-${kebab}.repository`) {
955
- return `import { describe, it, expect, beforeEach } from 'vitest'
956
- import { InMemory${pascal}Repository } from '${repoImport}'
758
+ `}i(S,"generateControllerTest");function j(e,t,r,o=`../infrastructure/repositories/in-memory-${t}.repository`){return`import { describe, it, expect, beforeEach } from 'vitest'
759
+ import { InMemory${e}Repository } from '${o}'
957
760
 
958
- describe('InMemory${pascal}Repository', () => {
959
- let repo: InMemory${pascal}Repository
761
+ describe('InMemory${e}Repository', () => {
762
+ let repo: InMemory${e}Repository
960
763
 
961
764
  beforeEach(() => {
962
- repo = new InMemory${pascal}Repository()
765
+ repo = new InMemory${e}Repository()
963
766
  })
964
767
 
965
- it('should create and retrieve a ${kebab}', async () => {
966
- const created = await repo.create({ name: 'Test ${pascal}' })
768
+ it('should create and retrieve a ${t}', async () => {
769
+ const created = await repo.create({ name: 'Test ${e}' })
967
770
  expect(created).toBeDefined()
968
- expect(created.name).toBe('Test ${pascal}')
771
+ expect(created.name).toBe('Test ${e}')
969
772
  expect(created.id).toBeDefined()
970
773
 
971
774
  const found = await repo.findById(created.id)
@@ -977,18 +780,18 @@ describe('InMemory${pascal}Repository', () => {
977
780
  expect(found).toBeNull()
978
781
  })
979
782
 
980
- it('should list all ${plural}', async () => {
981
- await repo.create({ name: '${pascal} 1' })
982
- await repo.create({ name: '${pascal} 2' })
783
+ it('should list all ${r}', async () => {
784
+ await repo.create({ name: '${e} 1' })
785
+ await repo.create({ name: '${e} 2' })
983
786
 
984
787
  const all = await repo.findAll()
985
788
  expect(all).toHaveLength(2)
986
789
  })
987
790
 
988
791
  it('should return paginated results', async () => {
989
- await repo.create({ name: '${pascal} 1' })
990
- await repo.create({ name: '${pascal} 2' })
991
- await repo.create({ name: '${pascal} 3' })
792
+ await repo.create({ name: '${e} 1' })
793
+ await repo.create({ name: '${e} 2' })
794
+ await repo.create({ name: '${e} 3' })
992
795
 
993
796
  const result = await repo.findPaginated({
994
797
  filters: [],
@@ -1001,43 +804,37 @@ describe('InMemory${pascal}Repository', () => {
1001
804
  expect(result.total).toBe(3)
1002
805
  })
1003
806
 
1004
- it('should update a ${kebab}', async () => {
807
+ it('should update a ${t}', async () => {
1005
808
  const created = await repo.create({ name: 'Original' })
1006
809
  const updated = await repo.update(created.id, { name: 'Updated' })
1007
810
  expect(updated.name).toBe('Updated')
1008
811
  })
1009
812
 
1010
- it('should delete a ${kebab}', async () => {
813
+ it('should delete a ${t}', async () => {
1011
814
  const created = await repo.create({ name: 'To Delete' })
1012
815
  await repo.delete(created.id)
1013
816
  const found = await repo.findById(created.id)
1014
817
  expect(found).toBeNull()
1015
818
  })
1016
819
  })
1017
- `;
1018
- }
1019
- __name(generateRepositoryTest, "generateRepositoryTest");
1020
-
1021
- // src/generators/templates/rest-service.ts
1022
- function generateRestService(pascal, kebab) {
1023
- return `import { Service, Inject, HttpException } from '@forinda/kickjs-core'
820
+ `}i(j,"generateRepositoryTest");function J(e,t){return`import { Service, Inject, HttpException } from '@forinda/kickjs-core'
1024
821
  import type { ParsedQuery } from '@forinda/kickjs-http'
1025
- import { ${pascal.toUpperCase()}_REPOSITORY, type I${pascal}Repository } from './${kebab}.repository'
1026
- import type { ${pascal}ResponseDTO } from './dtos/${kebab}-response.dto'
1027
- import type { Create${pascal}DTO } from './dtos/create-${kebab}.dto'
1028
- import type { Update${pascal}DTO } from './dtos/update-${kebab}.dto'
822
+ import { ${e.toUpperCase()}_REPOSITORY, type I${e}Repository } from './${t}.repository'
823
+ import type { ${e}ResponseDTO } from './dtos/${t}-response.dto'
824
+ import type { Create${e}DTO } from './dtos/create-${t}.dto'
825
+ import type { Update${e}DTO } from './dtos/update-${t}.dto'
1029
826
 
1030
827
  @Service()
1031
- export class ${pascal}Service {
828
+ export class ${e}Service {
1032
829
  constructor(
1033
- @Inject(${pascal.toUpperCase()}_REPOSITORY) private readonly repo: I${pascal}Repository,
830
+ @Inject(${e.toUpperCase()}_REPOSITORY) private readonly repo: I${e}Repository,
1034
831
  ) {}
1035
832
 
1036
- async findById(id: string): Promise<${pascal}ResponseDTO | null> {
833
+ async findById(id: string): Promise<${e}ResponseDTO | null> {
1037
834
  return this.repo.findById(id)
1038
835
  }
1039
836
 
1040
- async findAll(): Promise<${pascal}ResponseDTO[]> {
837
+ async findAll(): Promise<${e}ResponseDTO[]> {
1041
838
  return this.repo.findAll()
1042
839
  }
1043
840
 
@@ -1045,11 +842,11 @@ export class ${pascal}Service {
1045
842
  return this.repo.findPaginated(parsed)
1046
843
  }
1047
844
 
1048
- async create(dto: Create${pascal}DTO): Promise<${pascal}ResponseDTO> {
845
+ async create(dto: Create${e}DTO): Promise<${e}ResponseDTO> {
1049
846
  return this.repo.create(dto)
1050
847
  }
1051
848
 
1052
- async update(id: string, dto: Update${pascal}DTO): Promise<${pascal}ResponseDTO> {
849
+ async update(id: string, dto: Update${e}DTO): Promise<${e}ResponseDTO> {
1053
850
  return this.repo.update(id, dto)
1054
851
  }
1055
852
 
@@ -1057,37 +854,15 @@ export class ${pascal}Service {
1057
854
  await this.repo.delete(id)
1058
855
  }
1059
856
  }
1060
- `;
1061
- }
1062
- __name(generateRestService, "generateRestService");
1063
- function generateRestConstants(pascal) {
1064
- return `import type { QueryFieldConfig } from '@forinda/kickjs-http'
857
+ `}i(J,"generateRestService");function z(e){return`import type { QueryFieldConfig } from '@forinda/kickjs-http'
1065
858
 
1066
- export const ${pascal.toUpperCase()}_QUERY_CONFIG: QueryFieldConfig = {
859
+ export const ${e.toUpperCase()}_QUERY_CONFIG: QueryFieldConfig = {
1067
860
  filterable: ['name'],
1068
861
  sortable: ['name', 'createdAt'],
1069
862
  searchable: ['name'],
1070
863
  }
1071
- `;
1072
- }
1073
- __name(generateRestConstants, "generateRestConstants");
1074
-
1075
- // src/generators/templates/cqrs.ts
1076
- function generateCqrsModuleIndex(pascal, kebab, plural, repo) {
1077
- const repoClassMap = {
1078
- inmemory: `InMemory${pascal}Repository`,
1079
- drizzle: `Drizzle${pascal}Repository`,
1080
- prisma: `Prisma${pascal}Repository`
1081
- };
1082
- const repoFileMap = {
1083
- inmemory: `in-memory-${kebab}`,
1084
- drizzle: `drizzle-${kebab}`,
1085
- prisma: `prisma-${kebab}`
1086
- };
1087
- const repoClass = repoClassMap[repo] ?? repoClassMap.inmemory;
1088
- const repoFile = repoFileMap[repo] ?? repoFileMap.inmemory;
1089
- return `/**
1090
- * ${pascal} Module \u2014 CQRS Pattern
864
+ `}i(z,"generateRestConstants");function Z(e,t,r,o){let n={inmemory:`InMemory${e}Repository`,drizzle:`Drizzle${e}Repository`,prisma:`Prisma${e}Repository`},s={inmemory:`in-memory-${t}`,drizzle:`drizzle-${t}`,prisma:`prisma-${t}`},p=n[o]??n.inmemory,a=s[o]??s.inmemory;return`/**
865
+ * ${e} Module \u2014 CQRS Pattern
1091
866
  *
1092
867
  * Separates read (queries) and write (commands) operations.
1093
868
  * Events are emitted after state changes and can be handled via
@@ -1101,9 +876,9 @@ function generateCqrsModuleIndex(pascal, kebab, plural, repo) {
1101
876
  */
1102
877
  import { Container, type AppModule, type ModuleRoutes } from '@forinda/kickjs-core'
1103
878
  import { buildRoutes } from '@forinda/kickjs-http'
1104
- import { ${pascal.toUpperCase()}_REPOSITORY } from './${kebab}.repository'
1105
- import { ${repoClass} } from './${repoFile}.repository'
1106
- import { ${pascal}Controller } from './${kebab}.controller'
879
+ import { ${e.toUpperCase()}_REPOSITORY } from './${t}.repository'
880
+ import { ${p} } from './${a}.repository'
881
+ import { ${e}Controller } from './${t}.controller'
1107
882
 
1108
883
  // Eagerly load decorated classes
1109
884
  import.meta.glob(
@@ -1116,210 +891,168 @@ import.meta.glob(
1116
891
  { eager: true },
1117
892
  )
1118
893
 
1119
- export class ${pascal}Module implements AppModule {
894
+ export class ${e}Module implements AppModule {
1120
895
  register(container: Container): void {
1121
- container.registerFactory(${pascal.toUpperCase()}_REPOSITORY, () =>
1122
- container.resolve(${repoClass}),
896
+ container.registerFactory(${e.toUpperCase()}_REPOSITORY, () =>
897
+ container.resolve(${p}),
1123
898
  )
1124
899
  }
1125
900
 
1126
901
  routes(): ModuleRoutes {
1127
902
  return {
1128
- path: '/${plural}',
1129
- router: buildRoutes(${pascal}Controller),
1130
- controller: ${pascal}Controller,
903
+ path: '/${r}',
904
+ router: buildRoutes(${e}Controller),
905
+ controller: ${e}Controller,
1131
906
  }
1132
907
  }
1133
908
  }
1134
- `;
1135
- }
1136
- __name(generateCqrsModuleIndex, "generateCqrsModuleIndex");
1137
- function generateCqrsController(pascal, kebab, plural, pluralPascal) {
1138
- const camel = pascal.charAt(0).toLowerCase() + pascal.slice(1);
1139
- return `import { Controller, Get, Post, Put, Delete, Autowired, ApiQueryParams } from '@forinda/kickjs-core'
909
+ `}i(Z,"generateCqrsModuleIndex");function X(e,t,r,o){let n=e.charAt(0).toLowerCase()+e.slice(1);return`import { Controller, Get, Post, Put, Delete, Autowired, ApiQueryParams } from '@forinda/kickjs-core'
1140
910
  import type { RequestContext } from '@forinda/kickjs-http'
1141
911
  import { ApiTags } from '@forinda/kickjs-swagger'
1142
- import { Create${pascal}Command } from './commands/create-${kebab}.command'
1143
- import { Update${pascal}Command } from './commands/update-${kebab}.command'
1144
- import { Delete${pascal}Command } from './commands/delete-${kebab}.command'
1145
- import { Get${pascal}Query } from './queries/get-${kebab}.query'
1146
- import { List${pluralPascal}Query } from './queries/list-${plural}.query'
1147
- import { create${pascal}Schema } from './dtos/create-${kebab}.dto'
1148
- import { update${pascal}Schema } from './dtos/update-${kebab}.dto'
1149
- import { ${pascal.toUpperCase()}_QUERY_CONFIG } from './${kebab}.constants'
912
+ import { Create${e}Command } from './commands/create-${t}.command'
913
+ import { Update${e}Command } from './commands/update-${t}.command'
914
+ import { Delete${e}Command } from './commands/delete-${t}.command'
915
+ import { Get${e}Query } from './queries/get-${t}.query'
916
+ import { List${o}Query } from './queries/list-${r}.query'
917
+ import { create${e}Schema } from './dtos/create-${t}.dto'
918
+ import { update${e}Schema } from './dtos/update-${t}.dto'
919
+ import { ${e.toUpperCase()}_QUERY_CONFIG } from './${t}.constants'
1150
920
 
1151
921
  @Controller()
1152
- export class ${pascal}Controller {
1153
- @Autowired() private create${pascal}Command!: Create${pascal}Command
1154
- @Autowired() private update${pascal}Command!: Update${pascal}Command
1155
- @Autowired() private delete${pascal}Command!: Delete${pascal}Command
1156
- @Autowired() private get${pascal}Query!: Get${pascal}Query
1157
- @Autowired() private list${pluralPascal}Query!: List${pluralPascal}Query
922
+ export class ${e}Controller {
923
+ @Autowired() private create${e}Command!: Create${e}Command
924
+ @Autowired() private update${e}Command!: Update${e}Command
925
+ @Autowired() private delete${e}Command!: Delete${e}Command
926
+ @Autowired() private get${e}Query!: Get${e}Query
927
+ @Autowired() private list${o}Query!: List${o}Query
1158
928
 
1159
929
  @Get('/')
1160
- @ApiTags('${pascal}')
1161
- @ApiQueryParams(${pascal.toUpperCase()}_QUERY_CONFIG)
930
+ @ApiTags('${e}')
931
+ @ApiQueryParams(${e.toUpperCase()}_QUERY_CONFIG)
1162
932
  async list(ctx: RequestContext) {
1163
933
  return ctx.paginate(
1164
- (parsed) => this.list${pluralPascal}Query.execute(parsed),
1165
- ${pascal.toUpperCase()}_QUERY_CONFIG,
934
+ (parsed) => this.list${o}Query.execute(parsed),
935
+ ${e.toUpperCase()}_QUERY_CONFIG,
1166
936
  )
1167
937
  }
1168
938
 
1169
939
  @Get('/:id')
1170
- @ApiTags('${pascal}')
940
+ @ApiTags('${e}')
1171
941
  async getById(ctx: RequestContext) {
1172
- const result = await this.get${pascal}Query.execute(ctx.params.id)
1173
- if (!result) return ctx.notFound('${pascal} not found')
942
+ const result = await this.get${e}Query.execute(ctx.params.id)
943
+ if (!result) return ctx.notFound('${e} not found')
1174
944
  ctx.json(result)
1175
945
  }
1176
946
 
1177
- @Post('/', { body: create${pascal}Schema, name: 'Create${pascal}' })
1178
- @ApiTags('${pascal}')
947
+ @Post('/', { body: create${e}Schema, name: 'Create${e}' })
948
+ @ApiTags('${e}')
1179
949
  async create(ctx: RequestContext) {
1180
- const result = await this.create${pascal}Command.execute(ctx.body)
950
+ const result = await this.create${e}Command.execute(ctx.body)
1181
951
  ctx.created(result)
1182
952
  }
1183
953
 
1184
- @Put('/:id', { body: update${pascal}Schema, name: 'Update${pascal}' })
1185
- @ApiTags('${pascal}')
954
+ @Put('/:id', { body: update${e}Schema, name: 'Update${e}' })
955
+ @ApiTags('${e}')
1186
956
  async update(ctx: RequestContext) {
1187
- const result = await this.update${pascal}Command.execute(ctx.params.id, ctx.body)
957
+ const result = await this.update${e}Command.execute(ctx.params.id, ctx.body)
1188
958
  ctx.json(result)
1189
959
  }
1190
960
 
1191
961
  @Delete('/:id')
1192
- @ApiTags('${pascal}')
962
+ @ApiTags('${e}')
1193
963
  async remove(ctx: RequestContext) {
1194
- await this.delete${pascal}Command.execute(ctx.params.id)
964
+ await this.delete${e}Command.execute(ctx.params.id)
1195
965
  ctx.noContent()
1196
966
  }
1197
967
  }
1198
- `;
1199
- }
1200
- __name(generateCqrsController, "generateCqrsController");
1201
- function generateCqrsCommands(pascal, kebab) {
1202
- return [
1203
- {
1204
- file: `create-${kebab}.command.ts`,
1205
- content: `import { Service, Inject } from '@forinda/kickjs-core'
1206
- import { ${pascal.toUpperCase()}_REPOSITORY, type I${pascal}Repository } from '../${kebab}.repository'
1207
- import type { Create${pascal}DTO } from '../dtos/create-${kebab}.dto'
1208
- import type { ${pascal}ResponseDTO } from '../dtos/${kebab}-response.dto'
1209
- import { ${pascal}Events } from '../events/${kebab}.events'
968
+ `}i(X,"generateCqrsController");function ee(e,t){return[{file:`create-${t}.command.ts`,content:`import { Service, Inject } from '@forinda/kickjs-core'
969
+ import { ${e.toUpperCase()}_REPOSITORY, type I${e}Repository } from '../${t}.repository'
970
+ import type { Create${e}DTO } from '../dtos/create-${t}.dto'
971
+ import type { ${e}ResponseDTO } from '../dtos/${t}-response.dto'
972
+ import { ${e}Events } from '../events/${t}.events'
1210
973
 
1211
974
  @Service()
1212
- export class Create${pascal}Command {
975
+ export class Create${e}Command {
1213
976
  constructor(
1214
- @Inject(${pascal.toUpperCase()}_REPOSITORY) private readonly repo: I${pascal}Repository,
1215
- @Inject(${pascal}Events) private readonly events: ${pascal}Events,
977
+ @Inject(${e.toUpperCase()}_REPOSITORY) private readonly repo: I${e}Repository,
978
+ @Inject(${e}Events) private readonly events: ${e}Events,
1216
979
  ) {}
1217
980
 
1218
- async execute(dto: Create${pascal}DTO): Promise<${pascal}ResponseDTO> {
981
+ async execute(dto: Create${e}DTO): Promise<${e}ResponseDTO> {
1219
982
  const result = await this.repo.create(dto)
1220
- this.events.emit('${kebab}.created', result)
983
+ this.events.emit('${t}.created', result)
1221
984
  return result
1222
985
  }
1223
986
  }
1224
- `
1225
- },
1226
- {
1227
- file: `update-${kebab}.command.ts`,
1228
- content: `import { Service, Inject } from '@forinda/kickjs-core'
1229
- import { ${pascal.toUpperCase()}_REPOSITORY, type I${pascal}Repository } from '../${kebab}.repository'
1230
- import type { Update${pascal}DTO } from '../dtos/update-${kebab}.dto'
1231
- import type { ${pascal}ResponseDTO } from '../dtos/${kebab}-response.dto'
1232
- import { ${pascal}Events } from '../events/${kebab}.events'
987
+ `},{file:`update-${t}.command.ts`,content:`import { Service, Inject } from '@forinda/kickjs-core'
988
+ import { ${e.toUpperCase()}_REPOSITORY, type I${e}Repository } from '../${t}.repository'
989
+ import type { Update${e}DTO } from '../dtos/update-${t}.dto'
990
+ import type { ${e}ResponseDTO } from '../dtos/${t}-response.dto'
991
+ import { ${e}Events } from '../events/${t}.events'
1233
992
 
1234
993
  @Service()
1235
- export class Update${pascal}Command {
994
+ export class Update${e}Command {
1236
995
  constructor(
1237
- @Inject(${pascal.toUpperCase()}_REPOSITORY) private readonly repo: I${pascal}Repository,
1238
- @Inject(${pascal}Events) private readonly events: ${pascal}Events,
996
+ @Inject(${e.toUpperCase()}_REPOSITORY) private readonly repo: I${e}Repository,
997
+ @Inject(${e}Events) private readonly events: ${e}Events,
1239
998
  ) {}
1240
999
 
1241
- async execute(id: string, dto: Update${pascal}DTO): Promise<${pascal}ResponseDTO> {
1000
+ async execute(id: string, dto: Update${e}DTO): Promise<${e}ResponseDTO> {
1242
1001
  const result = await this.repo.update(id, dto)
1243
- this.events.emit('${kebab}.updated', result)
1002
+ this.events.emit('${t}.updated', result)
1244
1003
  return result
1245
1004
  }
1246
1005
  }
1247
- `
1248
- },
1249
- {
1250
- file: `delete-${kebab}.command.ts`,
1251
- content: `import { Service, Inject } from '@forinda/kickjs-core'
1252
- import { ${pascal.toUpperCase()}_REPOSITORY, type I${pascal}Repository } from '../${kebab}.repository'
1253
- import { ${pascal}Events } from '../events/${kebab}.events'
1006
+ `},{file:`delete-${t}.command.ts`,content:`import { Service, Inject } from '@forinda/kickjs-core'
1007
+ import { ${e.toUpperCase()}_REPOSITORY, type I${e}Repository } from '../${t}.repository'
1008
+ import { ${e}Events } from '../events/${t}.events'
1254
1009
 
1255
1010
  @Service()
1256
- export class Delete${pascal}Command {
1011
+ export class Delete${e}Command {
1257
1012
  constructor(
1258
- @Inject(${pascal.toUpperCase()}_REPOSITORY) private readonly repo: I${pascal}Repository,
1259
- @Inject(${pascal}Events) private readonly events: ${pascal}Events,
1013
+ @Inject(${e.toUpperCase()}_REPOSITORY) private readonly repo: I${e}Repository,
1014
+ @Inject(${e}Events) private readonly events: ${e}Events,
1260
1015
  ) {}
1261
1016
 
1262
1017
  async execute(id: string): Promise<void> {
1263
1018
  await this.repo.delete(id)
1264
- this.events.emit('${kebab}.deleted', { id })
1019
+ this.events.emit('${t}.deleted', { id })
1265
1020
  }
1266
1021
  }
1267
- `
1268
- }
1269
- ];
1270
- }
1271
- __name(generateCqrsCommands, "generateCqrsCommands");
1272
- function generateCqrsQueries(pascal, kebab, plural, pluralPascal) {
1273
- return [
1274
- {
1275
- file: `get-${kebab}.query.ts`,
1276
- content: `import { Service, Inject } from '@forinda/kickjs-core'
1277
- import { ${pascal.toUpperCase()}_REPOSITORY, type I${pascal}Repository } from '../${kebab}.repository'
1278
- import type { ${pascal}ResponseDTO } from '../dtos/${kebab}-response.dto'
1022
+ `}]}i(ee,"generateCqrsCommands");function te(e,t,r,o){return[{file:`get-${t}.query.ts`,content:`import { Service, Inject } from '@forinda/kickjs-core'
1023
+ import { ${e.toUpperCase()}_REPOSITORY, type I${e}Repository } from '../${t}.repository'
1024
+ import type { ${e}ResponseDTO } from '../dtos/${t}-response.dto'
1279
1025
 
1280
1026
  @Service()
1281
- export class Get${pascal}Query {
1027
+ export class Get${e}Query {
1282
1028
  constructor(
1283
- @Inject(${pascal.toUpperCase()}_REPOSITORY) private readonly repo: I${pascal}Repository,
1029
+ @Inject(${e.toUpperCase()}_REPOSITORY) private readonly repo: I${e}Repository,
1284
1030
  ) {}
1285
1031
 
1286
- async execute(id: string): Promise<${pascal}ResponseDTO | null> {
1032
+ async execute(id: string): Promise<${e}ResponseDTO | null> {
1287
1033
  return this.repo.findById(id)
1288
1034
  }
1289
1035
  }
1290
- `
1291
- },
1292
- {
1293
- file: `list-${plural}.query.ts`,
1294
- content: `import { Service, Inject } from '@forinda/kickjs-core'
1295
- import { ${pascal.toUpperCase()}_REPOSITORY, type I${pascal}Repository } from '../${kebab}.repository'
1036
+ `},{file:`list-${r}.query.ts`,content:`import { Service, Inject } from '@forinda/kickjs-core'
1037
+ import { ${e.toUpperCase()}_REPOSITORY, type I${e}Repository } from '../${t}.repository'
1296
1038
  import type { ParsedQuery } from '@forinda/kickjs-http'
1297
1039
 
1298
1040
  @Service()
1299
- export class List${pluralPascal}Query {
1041
+ export class List${o}Query {
1300
1042
  constructor(
1301
- @Inject(${pascal.toUpperCase()}_REPOSITORY) private readonly repo: I${pascal}Repository,
1043
+ @Inject(${e.toUpperCase()}_REPOSITORY) private readonly repo: I${e}Repository,
1302
1044
  ) {}
1303
1045
 
1304
1046
  async execute(parsed: ParsedQuery) {
1305
1047
  return this.repo.findPaginated(parsed)
1306
1048
  }
1307
1049
  }
1308
- `
1309
- }
1310
- ];
1311
- }
1312
- __name(generateCqrsQueries, "generateCqrsQueries");
1313
- function generateCqrsEvents(pascal, kebab) {
1314
- return [
1315
- {
1316
- file: `${kebab}.events.ts`,
1317
- content: `import { Service } from '@forinda/kickjs-core'
1050
+ `}]}i(te,"generateCqrsQueries");function re(e,t){return[{file:`${t}.events.ts`,content:`import { Service } from '@forinda/kickjs-core'
1318
1051
  import { EventEmitter } from 'node:events'
1319
- import type { ${pascal}ResponseDTO } from '../dtos/${kebab}-response.dto'
1052
+ import type { ${e}ResponseDTO } from '../dtos/${t}-response.dto'
1320
1053
 
1321
1054
  /**
1322
- * ${pascal} domain event types.
1055
+ * ${e} domain event types.
1323
1056
  *
1324
1057
  * These events are emitted by commands after state changes.
1325
1058
  * Subscribe to them in event handlers for side effects:
@@ -1328,346 +1061,118 @@ import type { ${pascal}ResponseDTO } from '../dtos/${kebab}-response.dto'
1328
1061
  * - Audit logging
1329
1062
  * - Cache invalidation
1330
1063
  */
1331
- export interface ${pascal}EventMap {
1332
- '${kebab}.created': ${pascal}ResponseDTO
1333
- '${kebab}.updated': ${pascal}ResponseDTO
1334
- '${kebab}.deleted': { id: string }
1064
+ export interface ${e}EventMap {
1065
+ '${t}.created': ${e}ResponseDTO
1066
+ '${t}.updated': ${e}ResponseDTO
1067
+ '${t}.deleted': { id: string }
1335
1068
  }
1336
1069
 
1337
1070
  @Service()
1338
- export class ${pascal}Events {
1071
+ export class ${e}Events {
1339
1072
  private emitter = new EventEmitter()
1340
1073
 
1341
- emit<K extends keyof ${pascal}EventMap>(event: K, data: ${pascal}EventMap[K]): void {
1074
+ emit<K extends keyof ${e}EventMap>(event: K, data: ${e}EventMap[K]): void {
1342
1075
  this.emitter.emit(event, data)
1343
1076
  }
1344
1077
 
1345
- on<K extends keyof ${pascal}EventMap>(event: K, handler: (data: ${pascal}EventMap[K]) => void): void {
1078
+ on<K extends keyof ${e}EventMap>(event: K, handler: (data: ${e}EventMap[K]) => void): void {
1346
1079
  this.emitter.on(event, handler)
1347
1080
  }
1348
1081
 
1349
- off<K extends keyof ${pascal}EventMap>(event: K, handler: (data: ${pascal}EventMap[K]) => void): void {
1082
+ off<K extends keyof ${e}EventMap>(event: K, handler: (data: ${e}EventMap[K]) => void): void {
1350
1083
  this.emitter.off(event, handler)
1351
1084
  }
1352
1085
  }
1353
- `
1354
- },
1355
- {
1356
- file: `on-${kebab}-change.handler.ts`,
1357
- content: `import { Service, Autowired } from '@forinda/kickjs-core'
1358
- import { ${pascal}Events } from './${kebab}.events'
1086
+ `},{file:`on-${t}-change.handler.ts`,content:`import { Service, Autowired } from '@forinda/kickjs-core'
1087
+ import { ${e}Events } from './${t}.events'
1359
1088
 
1360
1089
  /**
1361
- * ${pascal} Change Event Handler
1090
+ * ${e} Change Event Handler
1362
1091
  *
1363
1092
  * Reacts to domain events emitted by commands.
1364
1093
  * Wire up side effects here:
1365
1094
  *
1366
1095
  * 1. WebSocket broadcast \u2014 notify connected clients in real-time
1367
1096
  * import { WsGateway } from '@forinda/kickjs-ws'
1368
- * this.ws.broadcast('${kebab}-channel', { event, data })
1097
+ * this.ws.broadcast('${t}-channel', { event, data })
1369
1098
  *
1370
1099
  * 2. Queue dispatch \u2014 offload heavy processing to background workers
1371
1100
  * import { QueueService } from '@forinda/kickjs-queue'
1372
- * this.queue.add('${kebab}-etl', { action: event, payload: data })
1101
+ * this.queue.add('${t}-etl', { action: event, payload: data })
1373
1102
  *
1374
1103
  * 3. ETL pipeline \u2014 transform and load data to external systems
1375
1104
  * await this.etlPipeline.process(data)
1376
1105
  */
1377
1106
  @Service()
1378
- export class On${pascal}ChangeHandler {
1379
- @Autowired() private events!: ${pascal}Events
1107
+ export class On${e}ChangeHandler {
1108
+ @Autowired() private events!: ${e}Events
1380
1109
 
1381
1110
  // Uncomment to inject WebSocket and Queue services:
1382
1111
  // @Autowired() private ws!: WsGateway
1383
1112
  // @Autowired() private queue!: QueueService
1384
1113
 
1385
1114
  onInit(): void {
1386
- this.events.on('${kebab}.created', (data) => {
1387
- console.log('[${pascal}] Created:', data.id)
1115
+ this.events.on('${t}.created', (data) => {
1116
+ console.log('[${e}] Created:', data.id)
1388
1117
  // TODO: Broadcast via WebSocket
1389
- // this.ws.broadcast('${kebab}-channel', { event: '${kebab}.created', data })
1118
+ // this.ws.broadcast('${t}-channel', { event: '${t}.created', data })
1390
1119
  // TODO: Dispatch to queue for async processing / ETL
1391
- // this.queue.add('${kebab}-etl', { action: 'create', payload: data })
1120
+ // this.queue.add('${t}-etl', { action: 'create', payload: data })
1392
1121
  })
1393
1122
 
1394
- this.events.on('${kebab}.updated', (data) => {
1395
- console.log('[${pascal}] Updated:', data.id)
1123
+ this.events.on('${t}.updated', (data) => {
1124
+ console.log('[${e}] Updated:', data.id)
1396
1125
  // TODO: Broadcast via WebSocket
1397
- // this.ws.broadcast('${kebab}-channel', { event: '${kebab}.updated', data })
1126
+ // this.ws.broadcast('${t}-channel', { event: '${t}.updated', data })
1398
1127
  })
1399
1128
 
1400
- this.events.on('${kebab}.deleted', (data) => {
1401
- console.log('[${pascal}] Deleted:', data.id)
1129
+ this.events.on('${t}.deleted', (data) => {
1130
+ console.log('[${e}] Deleted:', data.id)
1402
1131
  // TODO: Broadcast via WebSocket
1403
- // this.ws.broadcast('${kebab}-channel', { event: '${kebab}.deleted', data })
1132
+ // this.ws.broadcast('${t}-channel', { event: '${t}.deleted', data })
1404
1133
  })
1405
1134
  }
1406
1135
  }
1407
- `
1408
- }
1409
- ];
1410
- }
1411
- __name(generateCqrsEvents, "generateCqrsEvents");
1412
-
1413
- // src/generators/module.ts
1414
- function promptUser(question) {
1415
- const rl = createInterface({
1416
- input: process.stdin,
1417
- output: process.stdout
1418
- });
1419
- return new Promise((resolve2) => {
1420
- rl.question(question, (answer) => {
1421
- rl.close();
1422
- resolve2(answer.trim().toLowerCase());
1423
- });
1424
- });
1425
- }
1426
- __name(promptUser, "promptUser");
1427
- async function generateModule(options) {
1428
- const { name, modulesDir, noEntity, noTests, repo = "inmemory", force, dryRun } = options;
1429
- let pattern = options.pattern ?? "ddd";
1430
- if (options.minimal) pattern = "minimal";
1431
- const kebab = toKebabCase(name);
1432
- const pascal = toPascalCase(name);
1433
- const plural = pluralize(kebab);
1434
- const pluralPascal = pluralizePascal(pascal);
1435
- const moduleDir = join(modulesDir, plural);
1436
- const files = [];
1437
- let overwriteAll = force ?? false;
1438
- const write = /* @__PURE__ */ __name(async (relativePath, content) => {
1439
- const fullPath = join(moduleDir, relativePath);
1440
- if (dryRun) {
1441
- files.push(fullPath);
1442
- return;
1443
- }
1444
- if (!overwriteAll && await fileExists(fullPath)) {
1445
- const answer = await promptUser(` File already exists: ${relativePath}
1446
- Overwrite? (y/n/a = yes/no/all) `);
1447
- if (answer === "a") {
1448
- overwriteAll = true;
1449
- } else if (answer !== "y") {
1450
- console.log(` Skipped: ${relativePath}`);
1451
- return;
1452
- }
1453
- }
1454
- await writeFileSafe(fullPath, content);
1455
- files.push(fullPath);
1456
- }, "write");
1457
- const ctx = {
1458
- kebab,
1459
- pascal,
1460
- plural,
1461
- pluralPascal,
1462
- moduleDir,
1463
- repo,
1464
- noEntity: noEntity ?? false,
1465
- noTests: noTests ?? false,
1466
- write,
1467
- files
1468
- };
1469
- switch (pattern) {
1470
- case "minimal":
1471
- await generateMinimalFiles(ctx);
1472
- break;
1473
- case "rest":
1474
- await generateRestFiles(ctx);
1475
- break;
1476
- case "cqrs":
1477
- await generateCqrsFiles(ctx);
1478
- break;
1479
- case "graphql":
1480
- case "ddd":
1481
- default:
1482
- await generateDddFiles(ctx);
1483
- break;
1484
- }
1485
- if (!dryRun) {
1486
- await autoRegisterModule(modulesDir, pascal, plural);
1487
- }
1488
- return files;
1489
- }
1490
- __name(generateModule, "generateModule");
1491
- async function generateMinimalFiles(ctx) {
1492
- const { pascal, kebab, plural, write } = ctx;
1493
- await write("index.ts", generateMinimalModuleIndex(pascal, kebab, plural));
1494
- await write(`${kebab}.controller.ts`, `import { Controller, Get } from '@forinda/kickjs-core'
1136
+ `}]}i(re,"generateCqrsEvents");function ve(e){let t=ge({input:process.stdin,output:process.stdout});return new Promise(r=>{t.question(e,o=>{t.close(),r(o.trim().toLowerCase())})})}i(ve,"promptUser");async function Ce(e){let{name:t,modulesDir:r,noEntity:o,noTests:n,repo:s="inmemory",force:p,dryRun:a}=e,d=e.pattern??"ddd";e.minimal&&(d="minimal");let m=f(t),u=l(t),y=x(m),v=ae(u),g=oe(r,y),E=[],ne=p??!1,A={kebab:m,pascal:u,plural:y,pluralPascal:v,moduleDir:g,repo:s,noEntity:o??!1,noTests:n??!1,write:i(async(M,ce)=>{let U=oe(g,M);if(a){E.push(U);return}if(!ne&&await F(U)){let se=await ve(` File already exists: ${M}
1137
+ Overwrite? (y/n/a = yes/no/all) `);if(se==="a")ne=!0;else if(se!=="y"){console.log(` Skipped: ${M}`);return}}await c(U,ce),E.push(U)},"write"),files:E};switch(d){case"minimal":await xe(A);break;case"rest":await Re(A);break;case"cqrs":await De(A);break;default:await Oe(A);break}return a||await ke(r,u,y),E}i(Ce,"generateModule");async function xe(e){let{pascal:t,kebab:r,plural:o,write:n}=e;await n("index.ts",N(t,r,o)),await n(`${r}.controller.ts`,`import { Controller, Get } from '@forinda/kickjs-core'
1495
1138
  import type { RequestContext } from '@forinda/kickjs-http'
1496
1139
 
1497
1140
  @Controller()
1498
- export class ${pascal}Controller {
1141
+ export class ${t}Controller {
1499
1142
  @Get('/')
1500
1143
  async list(ctx: RequestContext) {
1501
- ctx.json({ message: '${pascal} list' })
1502
- }
1503
- }
1504
- `);
1505
- }
1506
- __name(generateMinimalFiles, "generateMinimalFiles");
1507
- async function generateRestFiles(ctx) {
1508
- const { pascal, kebab, plural, pluralPascal, repo, noTests, write } = ctx;
1509
- await write("index.ts", generateRestModuleIndex(pascal, kebab, plural, repo));
1510
- await write(`${kebab}.constants.ts`, generateRestConstants(pascal));
1511
- await write(`${kebab}.controller.ts`, generateRestController(pascal, kebab, plural, pluralPascal));
1512
- await write(`${kebab}.service.ts`, generateRestService(pascal, kebab));
1513
- await write(`dtos/create-${kebab}.dto.ts`, generateCreateDTO(pascal, kebab));
1514
- await write(`dtos/update-${kebab}.dto.ts`, generateUpdateDTO(pascal, kebab));
1515
- await write(`dtos/${kebab}-response.dto.ts`, generateResponseDTO(pascal, kebab));
1516
- await write(`${kebab}.repository.ts`, generateRepositoryInterface(pascal, kebab, "./dtos"));
1517
- const repoFileMap = {
1518
- inmemory: `in-memory-${kebab}`,
1519
- drizzle: `drizzle-${kebab}`,
1520
- prisma: `prisma-${kebab}`
1521
- };
1522
- const repoGeneratorMap = {
1523
- inmemory: /* @__PURE__ */ __name(() => generateInMemoryRepository(pascal, kebab, ".", "./dtos"), "inmemory"),
1524
- drizzle: /* @__PURE__ */ __name(() => generateDrizzleRepository(pascal, kebab, ".", "./dtos"), "drizzle"),
1525
- prisma: /* @__PURE__ */ __name(() => generatePrismaRepository(pascal, kebab, ".", "./dtos"), "prisma")
1526
- };
1527
- await write(`${repoFileMap[repo]}.repository.ts`, repoGeneratorMap[repo]());
1528
- if (!noTests) {
1529
- await write(`__tests__/${kebab}.controller.test.ts`, generateControllerTest(pascal, kebab, plural));
1530
- await write(`__tests__/${kebab}.repository.test.ts`, generateRepositoryTest(pascal, kebab, plural, `../${repoFileMap.inmemory}.repository`));
1531
- }
1532
- }
1533
- __name(generateRestFiles, "generateRestFiles");
1534
- async function generateCqrsFiles(ctx) {
1535
- const { pascal, kebab, plural, pluralPascal, repo, noTests, write } = ctx;
1536
- await write("index.ts", generateCqrsModuleIndex(pascal, kebab, plural, repo));
1537
- await write(`${kebab}.constants.ts`, generateRestConstants(pascal));
1538
- await write(`${kebab}.controller.ts`, generateCqrsController(pascal, kebab, plural, pluralPascal));
1539
- await write(`dtos/create-${kebab}.dto.ts`, generateCreateDTO(pascal, kebab));
1540
- await write(`dtos/update-${kebab}.dto.ts`, generateUpdateDTO(pascal, kebab));
1541
- await write(`dtos/${kebab}-response.dto.ts`, generateResponseDTO(pascal, kebab));
1542
- const commands = generateCqrsCommands(pascal, kebab);
1543
- for (const cmd of commands) {
1544
- await write(`commands/${cmd.file}`, cmd.content);
1545
- }
1546
- const queries = generateCqrsQueries(pascal, kebab, plural, pluralPascal);
1547
- for (const q of queries) {
1548
- await write(`queries/${q.file}`, q.content);
1549
- }
1550
- const events = generateCqrsEvents(pascal, kebab);
1551
- for (const e of events) {
1552
- await write(`events/${e.file}`, e.content);
1553
- }
1554
- await write(`${kebab}.repository.ts`, generateRepositoryInterface(pascal, kebab, "./dtos"));
1555
- const repoFileMap = {
1556
- inmemory: `in-memory-${kebab}`,
1557
- drizzle: `drizzle-${kebab}`,
1558
- prisma: `prisma-${kebab}`
1559
- };
1560
- const repoGeneratorMap = {
1561
- inmemory: /* @__PURE__ */ __name(() => generateInMemoryRepository(pascal, kebab, ".", "./dtos"), "inmemory"),
1562
- drizzle: /* @__PURE__ */ __name(() => generateDrizzleRepository(pascal, kebab, ".", "./dtos"), "drizzle"),
1563
- prisma: /* @__PURE__ */ __name(() => generatePrismaRepository(pascal, kebab, ".", "./dtos"), "prisma")
1564
- };
1565
- await write(`${repoFileMap[repo]}.repository.ts`, repoGeneratorMap[repo]());
1566
- if (!noTests) {
1567
- await write(`__tests__/${kebab}.controller.test.ts`, generateControllerTest(pascal, kebab, plural));
1568
- await write(`__tests__/${kebab}.repository.test.ts`, generateRepositoryTest(pascal, kebab, plural, `../${repoFileMap.inmemory}.repository`));
1144
+ ctx.json({ message: '${t} list' })
1569
1145
  }
1570
1146
  }
1571
- __name(generateCqrsFiles, "generateCqrsFiles");
1572
- async function generateDddFiles(ctx) {
1573
- const { pascal, kebab, plural, pluralPascal, repo, noEntity, noTests, write } = ctx;
1574
- await write("index.ts", generateModuleIndex(pascal, kebab, plural, repo));
1575
- await write("constants.ts", repo === "drizzle" ? generateDrizzleConstants(pascal, kebab) : generateConstants(pascal));
1576
- await write(`presentation/${kebab}.controller.ts`, generateController(pascal, kebab, plural, pluralPascal));
1577
- await write(`application/dtos/create-${kebab}.dto.ts`, generateCreateDTO(pascal, kebab));
1578
- await write(`application/dtos/update-${kebab}.dto.ts`, generateUpdateDTO(pascal, kebab));
1579
- await write(`application/dtos/${kebab}-response.dto.ts`, generateResponseDTO(pascal, kebab));
1580
- const useCases = generateUseCases(pascal, kebab, plural, pluralPascal);
1581
- for (const uc of useCases) {
1582
- await write(`application/use-cases/${uc.file}`, uc.content);
1583
- }
1584
- await write(`domain/repositories/${kebab}.repository.ts`, generateRepositoryInterface(pascal, kebab));
1585
- await write(`domain/services/${kebab}-domain.service.ts`, generateDomainService(pascal, kebab));
1586
- const repoFileMap = {
1587
- inmemory: `in-memory-${kebab}`,
1588
- drizzle: `drizzle-${kebab}`,
1589
- prisma: `prisma-${kebab}`
1590
- };
1591
- const repoGeneratorMap = {
1592
- inmemory: /* @__PURE__ */ __name(() => generateInMemoryRepository(pascal, kebab), "inmemory"),
1593
- drizzle: /* @__PURE__ */ __name(() => generateDrizzleRepository(pascal, kebab), "drizzle"),
1594
- prisma: /* @__PURE__ */ __name(() => generatePrismaRepository(pascal, kebab), "prisma")
1595
- };
1596
- await write(`infrastructure/repositories/${repoFileMap[repo]}.repository.ts`, repoGeneratorMap[repo]());
1597
- if (!noEntity) {
1598
- await write(`domain/entities/${kebab}.entity.ts`, generateEntity(pascal, kebab));
1599
- await write(`domain/value-objects/${kebab}-id.vo.ts`, generateValueObject(pascal, kebab));
1600
- }
1601
- if (!noTests) {
1602
- await write(`__tests__/${kebab}.controller.test.ts`, generateControllerTest(pascal, kebab, plural));
1603
- await write(`__tests__/${kebab}.repository.test.ts`, generateRepositoryTest(pascal, kebab, plural));
1604
- }
1605
- }
1606
- __name(generateDddFiles, "generateDddFiles");
1607
- async function autoRegisterModule(modulesDir, pascal, plural) {
1608
- const indexPath = join(modulesDir, "index.ts");
1609
- const exists = await fileExists(indexPath);
1610
- if (!exists) {
1611
- await writeFileSafe(indexPath, `import type { AppModuleClass } from '@forinda/kickjs-core'
1612
- import { ${pascal}Module } from './${plural}'
1613
-
1614
- export const modules: AppModuleClass[] = [${pascal}Module]
1615
- `);
1616
- return;
1617
- }
1618
- let content = await readFile2(indexPath, "utf-8");
1619
- const importLine = `import { ${pascal}Module } from './${plural}'`;
1620
- if (!content.includes(`${pascal}Module`)) {
1621
- const lastImportIdx = content.lastIndexOf("import ");
1622
- if (lastImportIdx !== -1) {
1623
- const lineEnd = content.indexOf("\n", lastImportIdx);
1624
- content = content.slice(0, lineEnd + 1) + importLine + "\n" + content.slice(lineEnd + 1);
1625
- } else {
1626
- content = importLine + "\n" + content;
1627
- }
1628
- content = content.replace(/(=\s*\[)([\s\S]*?)(])/, (_match, open, existing, close) => {
1629
- const trimmed = existing.trim();
1630
- if (!trimmed) {
1631
- return `${open}${pascal}Module${close}`;
1632
- }
1633
- const needsComma = trimmed.endsWith(",") ? "" : ",";
1634
- return `${open}${existing.trimEnd()}${needsComma} ${pascal}Module${close}`;
1635
- });
1636
- }
1637
- await writeFile2(indexPath, content, "utf-8");
1638
- }
1639
- __name(autoRegisterModule, "autoRegisterModule");
1640
-
1641
- // src/generators/adapter.ts
1642
- import { join as join2 } from "path";
1643
- async function generateAdapter(options) {
1644
- const { name, outDir } = options;
1645
- const kebab = toKebabCase(name);
1646
- const pascal = toPascalCase(name);
1647
- const files = [];
1648
- const filePath = join2(outDir, `${kebab}.adapter.ts`);
1649
- await writeFileSafe(filePath, `import type { Express } from 'express'
1147
+ `)}i(xe,"generateMinimalFiles");async function Re(e){let{pascal:t,kebab:r,plural:o,pluralPascal:n,repo:s,noTests:p,write:a}=e;await a("index.ts",G(t,r,o,s)),await a(`${r}.constants.ts`,z(t)),await a(`${r}.controller.ts`,B(t,r,o,n)),await a(`${r}.service.ts`,J(t,r)),await a(`dtos/create-${r}.dto.ts`,R(t,r)),await a(`dtos/update-${r}.dto.ts`,D(t,r)),await a(`dtos/${r}-response.dto.ts`,O(t,r)),await a(`${r}.repository.ts`,k(t,r,"./dtos"));let d={inmemory:`in-memory-${r}`,drizzle:`drizzle-${r}`,prisma:`prisma-${r}`},m={inmemory:i(()=>I(t,r,".","./dtos"),"inmemory"),drizzle:i(()=>T(t,r,".","./dtos"),"drizzle"),prisma:i(()=>P(t,r,".","./dtos"),"prisma")};await a(`${d[s]}.repository.ts`,m[s]()),p||(await a(`__tests__/${r}.controller.test.ts`,S(t,r,o)),await a(`__tests__/${r}.repository.test.ts`,j(t,r,o,`../${d.inmemory}.repository`)))}i(Re,"generateRestFiles");async function De(e){let{pascal:t,kebab:r,plural:o,pluralPascal:n,repo:s,noTests:p,write:a}=e;await a("index.ts",Z(t,r,o,s)),await a(`${r}.constants.ts`,z(t)),await a(`${r}.controller.ts`,X(t,r,o,n)),await a(`dtos/create-${r}.dto.ts`,R(t,r)),await a(`dtos/update-${r}.dto.ts`,D(t,r)),await a(`dtos/${r}-response.dto.ts`,O(t,r));let d=ee(t,r);for(let g of d)await a(`commands/${g.file}`,g.content);let m=te(t,r,o,n);for(let g of m)await a(`queries/${g.file}`,g.content);let u=re(t,r);for(let g of u)await a(`events/${g.file}`,g.content);await a(`${r}.repository.ts`,k(t,r,"./dtos"));let y={inmemory:`in-memory-${r}`,drizzle:`drizzle-${r}`,prisma:`prisma-${r}`},v={inmemory:i(()=>I(t,r,".","./dtos"),"inmemory"),drizzle:i(()=>T(t,r,".","./dtos"),"drizzle"),prisma:i(()=>P(t,r,".","./dtos"),"prisma")};await a(`${y[s]}.repository.ts`,v[s]()),p||(await a(`__tests__/${r}.controller.test.ts`,S(t,r,o)),await a(`__tests__/${r}.repository.test.ts`,j(t,r,o,`../${y.inmemory}.repository`)))}i(De,"generateCqrsFiles");async function Oe(e){let{pascal:t,kebab:r,plural:o,pluralPascal:n,repo:s,noEntity:p,noTests:a,write:d}=e;await d("index.ts",Q(t,r,o,s)),await d("constants.ts",s==="drizzle"?W(t,r):L(t)),await d(`presentation/${r}.controller.ts`,Y(t,r,o,n)),await d(`application/dtos/create-${r}.dto.ts`,R(t,r)),await d(`application/dtos/update-${r}.dto.ts`,D(t,r)),await d(`application/dtos/${r}-response.dto.ts`,O(t,r));let m=b(t,r,o,n);for(let v of m)await d(`application/use-cases/${v.file}`,v.content);await d(`domain/repositories/${r}.repository.ts`,k(t,r)),await d(`domain/services/${r}-domain.service.ts`,K(t,r));let u={inmemory:`in-memory-${r}`,drizzle:`drizzle-${r}`,prisma:`prisma-${r}`},y={inmemory:i(()=>I(t,r),"inmemory"),drizzle:i(()=>T(t,r),"drizzle"),prisma:i(()=>P(t,r),"prisma")};await d(`infrastructure/repositories/${u[s]}.repository.ts`,y[s]()),p||(await d(`domain/entities/${r}.entity.ts`,H(t,r)),await d(`domain/value-objects/${r}-id.vo.ts`,V(t,r))),a||(await d(`__tests__/${r}.controller.test.ts`,S(t,r,o)),await d(`__tests__/${r}.repository.test.ts`,j(t,r,o)))}i(Oe,"generateDddFiles");async function ke(e,t,r){let o=oe(e,"index.ts");if(!await F(o)){await c(o,`import type { AppModuleClass } from '@forinda/kickjs-core'
1148
+ import { ${t}Module } from './${r}'
1149
+
1150
+ export const modules: AppModuleClass[] = [${t}Module]
1151
+ `);return}let s=await he(o,"utf-8"),p=`import { ${t}Module } from './${r}'`;if(!s.includes(`${t}Module`)){let a=s.lastIndexOf("import ");if(a!==-1){let d=s.indexOf(`
1152
+ `,a);s=s.slice(0,d+1)+p+`
1153
+ `+s.slice(d+1)}else s=p+`
1154
+ `+s;s=s.replace(/(=\s*\[)([\s\S]*?)(])/,(d,m,u,y)=>{let v=u.trim();if(!v)return`${m}${t}Module${y}`;let g=v.endsWith(",")?"":",";return`${m}${u.trimEnd()}${g} ${t}Module${y}`})}await we(o,s,"utf-8")}i(ke,"autoRegisterModule");import{join as Ie}from"path";async function Te(e){let{name:t,outDir:r}=e,o=f(t),n=l(t),s=[],p=Ie(r,`${o}.adapter.ts`);return await c(p,`import type { Express } from 'express'
1650
1155
  import type { AppAdapter, AdapterMiddleware, Container } from '@forinda/kickjs-core'
1651
1156
 
1652
- export interface ${pascal}AdapterOptions {
1157
+ export interface ${n}AdapterOptions {
1653
1158
  // Add your adapter configuration here
1654
1159
  }
1655
1160
 
1656
1161
  /**
1657
- * ${pascal} adapter.
1162
+ * ${n} adapter.
1658
1163
  *
1659
1164
  * Hooks into the Application lifecycle to add middleware, routes,
1660
1165
  * or external service connections.
1661
1166
  *
1662
1167
  * Usage:
1663
1168
  * bootstrap({
1664
- * adapters: [new ${pascal}Adapter({ ... })],
1169
+ * adapters: [new ${n}Adapter({ ... })],
1665
1170
  * })
1666
1171
  */
1667
- export class ${pascal}Adapter implements AppAdapter {
1668
- name = '${pascal}Adapter'
1172
+ export class ${n}Adapter implements AppAdapter {
1173
+ name = '${n}Adapter'
1669
1174
 
1670
- constructor(private options: ${pascal}AdapterOptions = {}) {}
1175
+ constructor(private options: ${n}AdapterOptions = {}) {}
1671
1176
 
1672
1177
  /**
1673
1178
  * Return middleware entries that the Application will mount.
@@ -1680,7 +1185,7 @@ export class ${pascal}Adapter implements AppAdapter {
1680
1185
  // {
1681
1186
  // phase: 'beforeGlobal',
1682
1187
  // handler: (_req: any, res: any, next: any) => {
1683
- // res.setHeader('X-${pascal}', 'true')
1188
+ // res.setHeader('X-${n}', 'true')
1684
1189
  // next()
1685
1190
  // },
1686
1191
  // },
@@ -1700,7 +1205,7 @@ export class ${pascal}Adapter implements AppAdapter {
1700
1205
  */
1701
1206
  beforeMount(app: Express, container: Container): void {
1702
1207
  // Example: mount a status route
1703
- // app.get('/${kebab}/status', (_req, res) => {
1208
+ // app.get('/${o}/status', (_req, res) => {
1704
1209
  // res.json({ status: 'ok' })
1705
1210
  // })
1706
1211
  }
@@ -1732,133 +1237,45 @@ export class ${pascal}Adapter implements AppAdapter {
1732
1237
  // await this.pool.end()
1733
1238
  }
1734
1239
  }
1735
- `);
1736
- files.push(filePath);
1737
- return files;
1738
- }
1739
- __name(generateAdapter, "generateAdapter");
1740
-
1741
- // src/generators/middleware.ts
1742
- import { join as join4 } from "path";
1743
-
1744
- // src/utils/resolve-out-dir.ts
1745
- import { resolve, join as join3 } from "path";
1746
- var DDD_FOLDER_MAP = {
1747
- controller: "presentation",
1748
- service: "domain/services",
1749
- dto: "application/dtos",
1750
- guard: "presentation/guards",
1751
- middleware: "middleware"
1752
- };
1753
- var FLAT_FOLDER_MAP = {
1754
- controller: "",
1755
- service: "",
1756
- dto: "dtos",
1757
- guard: "guards",
1758
- middleware: "middleware"
1759
- };
1760
- var CQRS_FOLDER_MAP = {
1761
- controller: "",
1762
- service: "",
1763
- dto: "dtos",
1764
- guard: "guards",
1765
- middleware: "middleware",
1766
- command: "commands",
1767
- query: "queries",
1768
- event: "events"
1769
- };
1770
- function resolveOutDir(options) {
1771
- const { type, outDir, moduleName, modulesDir = "src/modules", defaultDir, pattern = "ddd" } = options;
1772
- if (outDir) return resolve(outDir);
1773
- if (moduleName) {
1774
- const folderMap = pattern === "ddd" ? DDD_FOLDER_MAP : pattern === "cqrs" ? CQRS_FOLDER_MAP : FLAT_FOLDER_MAP;
1775
- const kebab = toKebabCase(moduleName);
1776
- const plural = pluralize(kebab);
1777
- const subfolder = folderMap[type] ?? "";
1778
- const base = join3(modulesDir, plural);
1779
- return resolve(subfolder ? join3(base, subfolder) : base);
1780
- }
1781
- return resolve(defaultDir);
1782
- }
1783
- __name(resolveOutDir, "resolveOutDir");
1784
-
1785
- // src/generators/middleware.ts
1786
- async function generateMiddleware(options) {
1787
- const { name, moduleName, modulesDir, pattern } = options;
1788
- const outDir = resolveOutDir({
1789
- type: "middleware",
1790
- outDir: options.outDir,
1791
- moduleName,
1792
- modulesDir,
1793
- defaultDir: "src/middleware",
1794
- pattern
1795
- });
1796
- const kebab = toKebabCase(name);
1797
- const camel = toCamelCase(name);
1798
- const files = [];
1799
- const filePath = join4(outDir, `${kebab}.middleware.ts`);
1800
- await writeFileSafe(filePath, `import type { Request, Response, NextFunction } from 'express'
1801
-
1802
- export interface ${toPascalCase(name)}Options {
1240
+ `),s.push(p),s}i(Te,"generateAdapter");import{join as Ee}from"path";import{resolve as ie,join as pe}from"path";var Pe={controller:"presentation",service:"domain/services",dto:"application/dtos",guard:"presentation/guards",middleware:"middleware"},Se={controller:"",service:"",dto:"dtos",guard:"guards",middleware:"middleware"},je={controller:"",service:"",dto:"dtos",guard:"guards",middleware:"middleware",command:"commands",query:"queries",event:"events"};function w(e){let{type:t,outDir:r,moduleName:o,modulesDir:n="src/modules",defaultDir:s,pattern:p="ddd"}=e;if(r)return ie(r);if(o){let a=p==="ddd"?Pe:p==="cqrs"?je:Se,d=f(o),m=x(d),u=a[t]??"",y=pe(n,m);return ie(u?pe(y,u):y)}return ie(s)}i(w,"resolveOutDir");async function Ae(e){let{name:t,moduleName:r,modulesDir:o,pattern:n}=e,s=w({type:"middleware",outDir:e.outDir,moduleName:r,modulesDir:o,defaultDir:"src/middleware",pattern:n}),p=f(t),a=C(t),d=[],m=Ee(s,`${p}.middleware.ts`);return await c(m,`import type { Request, Response, NextFunction } from 'express'
1241
+
1242
+ export interface ${l(t)}Options {
1803
1243
  // Add configuration options here
1804
1244
  }
1805
1245
 
1806
1246
  /**
1807
- * ${toPascalCase(name)} middleware.
1247
+ * ${l(t)} middleware.
1808
1248
  *
1809
1249
  * Usage in bootstrap:
1810
- * middleware: [${camel}()]
1250
+ * middleware: [${a}()]
1811
1251
  *
1812
1252
  * Usage with adapter:
1813
- * middleware() { return [{ handler: ${camel}(), phase: 'afterGlobal' }] }
1253
+ * middleware() { return [{ handler: ${a}(), phase: 'afterGlobal' }] }
1814
1254
  *
1815
1255
  * Usage with @Middleware decorator:
1816
- * @Middleware(${camel}())
1256
+ * @Middleware(${a}())
1817
1257
  */
1818
- export function ${camel}(options: ${toPascalCase(name)}Options = {}) {
1258
+ export function ${a}(options: ${l(t)}Options = {}) {
1819
1259
  return (req: Request, res: Response, next: NextFunction) => {
1820
1260
  // Implement your middleware logic here
1821
1261
  next()
1822
1262
  }
1823
1263
  }
1824
- `);
1825
- files.push(filePath);
1826
- return files;
1827
- }
1828
- __name(generateMiddleware, "generateMiddleware");
1829
-
1830
- // src/generators/guard.ts
1831
- import { join as join5 } from "path";
1832
- async function generateGuard(options) {
1833
- const { name, moduleName, modulesDir, pattern } = options;
1834
- const outDir = resolveOutDir({
1835
- type: "guard",
1836
- outDir: options.outDir,
1837
- moduleName,
1838
- modulesDir,
1839
- defaultDir: "src/guards",
1840
- pattern
1841
- });
1842
- const kebab = toKebabCase(name);
1843
- const camel = toCamelCase(name);
1844
- const pascal = toPascalCase(name);
1845
- const files = [];
1846
- const filePath = join5(outDir, `${kebab}.guard.ts`);
1847
- await writeFileSafe(filePath, `import { Container, HttpException } from '@forinda/kickjs-core'
1264
+ `),d.push(m),d}i(Ae,"generateMiddleware");import{join as Ue}from"path";async function ze(e){let{name:t,moduleName:r,modulesDir:o,pattern:n}=e,s=w({type:"guard",outDir:e.outDir,moduleName:r,modulesDir:o,defaultDir:"src/guards",pattern:n}),p=f(t),a=C(t),d=l(t),m=[],u=Ue(s,`${p}.guard.ts`);return await c(u,`import { Container, HttpException } from '@forinda/kickjs-core'
1848
1265
  import type { RequestContext } from '@forinda/kickjs-http'
1849
1266
 
1850
1267
  /**
1851
- * ${pascal} guard.
1268
+ * ${d} guard.
1852
1269
  *
1853
1270
  * Guards protect routes by checking conditions before the handler runs.
1854
1271
  * Return early with an error response to block access.
1855
1272
  *
1856
1273
  * Usage:
1857
- * @Middleware(${camel}Guard)
1274
+ * @Middleware(${a}Guard)
1858
1275
  * @Get('/protected')
1859
1276
  * async handler(ctx: RequestContext) { ... }
1860
1277
  */
1861
- export async function ${camel}Guard(ctx: RequestContext, next: () => void): Promise<void> {
1278
+ export async function ${a}Guard(ctx: RequestContext, next: () => void): Promise<void> {
1862
1279
  // Example: check for an authorization header
1863
1280
  const header = ctx.headers.authorization
1864
1281
  if (!header?.startsWith('Bearer ')) {
@@ -1880,183 +1297,43 @@ export async function ${camel}Guard(ctx: RequestContext, next: () => void): Prom
1880
1297
  ctx.res.status(401).json({ message: 'Invalid or expired token' })
1881
1298
  }
1882
1299
  }
1883
- `);
1884
- files.push(filePath);
1885
- return files;
1886
- }
1887
- __name(generateGuard, "generateGuard");
1888
-
1889
- // src/generators/service.ts
1890
- import { join as join6 } from "path";
1891
- async function generateService(options) {
1892
- const { name, moduleName, modulesDir, pattern } = options;
1893
- const outDir = resolveOutDir({
1894
- type: "service",
1895
- outDir: options.outDir,
1896
- moduleName,
1897
- modulesDir,
1898
- defaultDir: "src/services",
1899
- pattern
1900
- });
1901
- const kebab = toKebabCase(name);
1902
- const pascal = toPascalCase(name);
1903
- const files = [];
1904
- const filePath = join6(outDir, `${kebab}.service.ts`);
1905
- await writeFileSafe(filePath, `import { Service } from '@forinda/kickjs-core'
1300
+ `),m.push(u),m}i(ze,"generateGuard");import{join as _e}from"path";async function qe(e){let{name:t,moduleName:r,modulesDir:o,pattern:n}=e,s=w({type:"service",outDir:e.outDir,moduleName:r,modulesDir:o,defaultDir:"src/services",pattern:n}),p=f(t),a=l(t),d=[],m=_e(s,`${p}.service.ts`);return await c(m,`import { Service } from '@forinda/kickjs-core'
1906
1301
 
1907
1302
  @Service()
1908
- export class ${pascal}Service {
1303
+ export class ${a}Service {
1909
1304
  // Inject dependencies via constructor
1910
1305
  // constructor(
1911
1306
  // @Inject(MY_REPO) private readonly repo: IMyRepository,
1912
1307
  // ) {}
1913
1308
  }
1914
- `);
1915
- files.push(filePath);
1916
- return files;
1917
- }
1918
- __name(generateService, "generateService");
1919
-
1920
- // src/generators/controller.ts
1921
- import { join as join7 } from "path";
1922
- async function generateController2(options) {
1923
- const { name, moduleName, modulesDir, pattern } = options;
1924
- const outDir = resolveOutDir({
1925
- type: "controller",
1926
- outDir: options.outDir,
1927
- moduleName,
1928
- modulesDir,
1929
- defaultDir: "src/controllers",
1930
- pattern
1931
- });
1932
- const kebab = toKebabCase(name);
1933
- const pascal = toPascalCase(name);
1934
- const files = [];
1935
- const filePath = join7(outDir, `${kebab}.controller.ts`);
1936
- await writeFileSafe(filePath, `import { Controller, Get, Post, Autowired } from '@forinda/kickjs-core'
1309
+ `),d.push(m),d}i(qe,"generateService");import{join as Me}from"path";async function Fe(e){let{name:t,moduleName:r,modulesDir:o,pattern:n}=e,s=w({type:"controller",outDir:e.outDir,moduleName:r,modulesDir:o,defaultDir:"src/controllers",pattern:n}),p=f(t),a=l(t),d=[],m=Me(s,`${p}.controller.ts`);return await c(m,`import { Controller, Get, Post, Autowired } from '@forinda/kickjs-core'
1937
1310
  import type { RequestContext } from '@forinda/kickjs-http'
1938
1311
 
1939
1312
  @Controller()
1940
- export class ${pascal}Controller {
1313
+ export class ${a}Controller {
1941
1314
  // @Autowired() private myService!: MyService
1942
1315
 
1943
1316
  @Get('/')
1944
1317
  async list(ctx: RequestContext) {
1945
- ctx.json({ message: '${pascal} list' })
1318
+ ctx.json({ message: '${a} list' })
1946
1319
  }
1947
1320
 
1948
1321
  @Post('/')
1949
1322
  async create(ctx: RequestContext) {
1950
- ctx.created({ message: '${pascal} created', data: ctx.body })
1323
+ ctx.created({ message: '${a} created', data: ctx.body })
1951
1324
  }
1952
1325
  }
1953
- `);
1954
- files.push(filePath);
1955
- return files;
1956
- }
1957
- __name(generateController2, "generateController");
1958
-
1959
- // src/generators/dto.ts
1960
- import { join as join8 } from "path";
1961
- async function generateDto(options) {
1962
- const { name, moduleName, modulesDir, pattern } = options;
1963
- const outDir = resolveOutDir({
1964
- type: "dto",
1965
- outDir: options.outDir,
1966
- moduleName,
1967
- modulesDir,
1968
- defaultDir: "src/dtos",
1969
- pattern
1970
- });
1971
- const kebab = toKebabCase(name);
1972
- const pascal = toPascalCase(name);
1973
- const camel = toCamelCase(name);
1974
- const files = [];
1975
- const filePath = join8(outDir, `${kebab}.dto.ts`);
1976
- await writeFileSafe(filePath, `import { z } from 'zod'
1977
-
1978
- export const ${camel}Schema = z.object({
1326
+ `),d.push(m),d}i(Fe,"generateController");import{join as Qe}from"path";async function Ge(e){let{name:t,moduleName:r,modulesDir:o,pattern:n}=e,s=w({type:"dto",outDir:e.outDir,moduleName:r,modulesDir:o,defaultDir:"src/dtos",pattern:n}),p=f(t),a=l(t),d=C(t),m=[],u=Qe(s,`${p}.dto.ts`);return await c(u,`import { z } from 'zod'
1327
+
1328
+ export const ${d}Schema = z.object({
1979
1329
  // Define your schema fields here
1980
1330
  name: z.string().min(1).max(200),
1981
1331
  })
1982
1332
 
1983
- export type ${pascal}DTO = z.infer<typeof ${camel}Schema>
1984
- `);
1985
- files.push(filePath);
1986
- return files;
1987
- }
1988
- __name(generateDto, "generateDto");
1989
-
1990
- // src/generators/project.ts
1991
- import { join as join9, dirname as dirname2 } from "path";
1992
- import { execSync } from "child_process";
1993
- import { readFileSync } from "fs";
1994
- import { fileURLToPath } from "url";
1995
- var __dirname = dirname2(fileURLToPath(import.meta.url));
1996
- var cliPkg = JSON.parse(readFileSync(join9(__dirname, "..", "package.json"), "utf-8"));
1997
- var KICKJS_VERSION = `^${cliPkg.version}`;
1998
- async function initProject(options) {
1999
- const { name, directory, packageManager = "pnpm", template = "rest" } = options;
2000
- const dir = directory;
2001
- console.log(`
2002
- Creating KickJS project: ${name}
2003
- `);
2004
- const baseDeps = {
2005
- "@forinda/kickjs-core": KICKJS_VERSION,
2006
- "@forinda/kickjs-http": KICKJS_VERSION,
2007
- "@forinda/kickjs-config": KICKJS_VERSION,
2008
- express: "^5.1.0",
2009
- "reflect-metadata": "^0.2.2",
2010
- zod: "^4.3.6",
2011
- pino: "^10.3.1",
2012
- "pino-pretty": "^13.1.3"
2013
- };
2014
- if (template !== "minimal") {
2015
- baseDeps["@forinda/kickjs-swagger"] = KICKJS_VERSION;
2016
- baseDeps["@forinda/kickjs-devtools"] = KICKJS_VERSION;
2017
- }
2018
- if (template === "graphql") {
2019
- baseDeps["@forinda/kickjs-graphql"] = KICKJS_VERSION;
2020
- baseDeps["graphql"] = "^16.11.0";
2021
- }
2022
- if (template === "cqrs") {
2023
- baseDeps["@forinda/kickjs-queue"] = KICKJS_VERSION;
2024
- baseDeps["@forinda/kickjs-ws"] = KICKJS_VERSION;
2025
- baseDeps["@forinda/kickjs-otel"] = KICKJS_VERSION;
2026
- }
2027
- if (template === "ddd") {
2028
- baseDeps["@forinda/kickjs-swagger"] = KICKJS_VERSION;
2029
- }
2030
- await writeFileSafe(join9(dir, "package.json"), JSON.stringify({
2031
- name,
2032
- version: cliPkg.version,
2033
- type: "module",
2034
- scripts: {
2035
- dev: "kick dev",
2036
- "dev:debug": "kick dev:debug",
2037
- build: "kick build",
2038
- start: "kick start",
2039
- test: "vitest run",
2040
- "test:watch": "vitest",
2041
- typecheck: "tsc --noEmit",
2042
- lint: "eslint src/",
2043
- format: "prettier --write src/"
2044
- },
2045
- dependencies: baseDeps,
2046
- devDependencies: {
2047
- "@forinda/kickjs-cli": KICKJS_VERSION,
2048
- "@swc/core": "^1.7.28",
2049
- "@types/express": "^5.0.6",
2050
- "@types/node": "^24.5.2",
2051
- "unplugin-swc": "^1.5.9",
2052
- vite: "^7.3.1",
2053
- "vite-node": "^5.3.0",
2054
- vitest: "^3.2.4",
2055
- typescript: "^5.9.2",
2056
- prettier: "^3.8.1"
2057
- }
2058
- }, null, 2));
2059
- await writeFileSafe(join9(dir, "vite.config.ts"), `import { defineConfig } from 'vite'
1333
+ export type ${a}DTO = z.infer<typeof ${d}Schema>
1334
+ `),m.push(u),m}i(Ge,"generateDto");import{join as $,dirname as Ne}from"path";import{execSync as _}from"child_process";import{readFileSync as Ye}from"fs";import{fileURLToPath as Be}from"url";var Le=Ne(Be(import.meta.url)),q=JSON.parse(Ye($(Le,"..","package.json"),"utf-8")),h=`^${q.version}`;async function We(e){let{name:t,directory:r,packageManager:o="pnpm",template:n="rest"}=e,s=r;console.log(`
1335
+ Creating KickJS project: ${t}
1336
+ `);let p={"@forinda/kickjs-core":h,"@forinda/kickjs-http":h,"@forinda/kickjs-config":h,express:"^5.1.0","reflect-metadata":"^0.2.2",zod:"^4.3.6",pino:"^10.3.1","pino-pretty":"^13.1.3"};if(n!=="minimal"&&(p["@forinda/kickjs-swagger"]=h,p["@forinda/kickjs-devtools"]=h),n==="graphql"&&(p["@forinda/kickjs-graphql"]=h,p.graphql="^16.11.0"),n==="cqrs"&&(p["@forinda/kickjs-queue"]=h,p["@forinda/kickjs-ws"]=h,p["@forinda/kickjs-otel"]=h),n==="ddd"&&(p["@forinda/kickjs-swagger"]=h),await c($(s,"package.json"),JSON.stringify({name:t,version:q.version,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",lint:"eslint src/",format:"prettier --write src/"},dependencies:p,devDependencies:{"@forinda/kickjs-cli":h,"@swc/core":"^1.7.28","@types/express":"^5.0.6","@types/node":"^24.5.2","unplugin-swc":"^1.5.9",vite:"^7.3.1","vite-node":"^5.3.0",vitest:"^3.2.4",typescript:"^5.9.2",prettier:"^3.8.1"}},null,2)),await c($(s,"vite.config.ts"),`import { defineConfig } from 'vite'
2060
1337
  import { resolve } from 'path'
2061
1338
  import swc from 'unplugin-swc'
2062
1339
 
@@ -2082,46 +1359,7 @@ export default defineConfig({
2082
1359
  },
2083
1360
  },
2084
1361
  })
2085
- `);
2086
- await writeFileSafe(join9(dir, "tsconfig.json"), JSON.stringify({
2087
- compilerOptions: {
2088
- target: "ES2022",
2089
- module: "ESNext",
2090
- moduleResolution: "bundler",
2091
- lib: [
2092
- "ES2022"
2093
- ],
2094
- types: [
2095
- "node",
2096
- "vite/client"
2097
- ],
2098
- strict: true,
2099
- esModuleInterop: true,
2100
- skipLibCheck: true,
2101
- sourceMap: true,
2102
- declaration: true,
2103
- experimentalDecorators: true,
2104
- emitDecoratorMetadata: true,
2105
- outDir: "dist",
2106
- rootDir: "src",
2107
- paths: {
2108
- "@/*": [
2109
- "./src/*"
2110
- ]
2111
- }
2112
- },
2113
- include: [
2114
- "src"
2115
- ]
2116
- }, null, 2));
2117
- await writeFileSafe(join9(dir, ".prettierrc"), JSON.stringify({
2118
- semi: false,
2119
- singleQuote: true,
2120
- trailingComma: "all",
2121
- printWidth: 100,
2122
- tabWidth: 2
2123
- }, null, 2));
2124
- await writeFileSafe(join9(dir, ".editorconfig"), `# https://editorconfig.org
1362
+ `),await c($(s,"tsconfig.json"),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",rootDir:"src",paths:{"@/*":["./src/*"]}},include:["src"]},null,2)),await c($(s,".prettierrc"),JSON.stringify({semi:!1,singleQuote:!0,trailingComma:"all",printWidth:100,tabWidth:2},null,2)),await c($(s,".editorconfig"),`# https://editorconfig.org
2125
1363
  root = true
2126
1364
 
2127
1365
  [*]
@@ -2134,15 +1372,13 @@ insert_final_newline = true
2134
1372
 
2135
1373
  [*.md]
2136
1374
  trim_trailing_whitespace = false
2137
- `);
2138
- await writeFileSafe(join9(dir, ".gitignore"), `node_modules/
1375
+ `),await c($(s,".gitignore"),`node_modules/
2139
1376
  dist/
2140
1377
  .env
2141
1378
  coverage/
2142
1379
  .DS_Store
2143
1380
  *.tsbuildinfo
2144
- `);
2145
- await writeFileSafe(join9(dir, ".gitattributes"), `# Auto-detect text files and normalise line endings to LF
1381
+ `),await c($(s,".gitattributes"),`# Auto-detect text files and normalise line endings to LF
2146
1382
  * text=auto eol=lf
2147
1383
 
2148
1384
  # Explicitly mark generated / binary files
@@ -2160,25 +1396,17 @@ coverage/
2160
1396
  pnpm-lock.yaml -diff linguist-generated
2161
1397
  yarn.lock -diff linguist-generated
2162
1398
  package-lock.json -diff linguist-generated
2163
- `);
2164
- await writeFileSafe(join9(dir, ".env"), `PORT=3000
1399
+ `),await c($(s,".env"),`PORT=3000
2165
1400
  NODE_ENV=development
2166
- `);
2167
- await writeFileSafe(join9(dir, ".env.example"), `PORT=3000
1401
+ `),await c($(s,".env.example"),`PORT=3000
2168
1402
  NODE_ENV=development
2169
- `);
2170
- await writeFileSafe(join9(dir, "src/index.ts"), getEntryFile(name, template));
2171
- await writeFileSafe(join9(dir, "src/modules/index.ts"), `import type { AppModuleClass } from '@forinda/kickjs-core'
1403
+ `),await c($(s,"src/index.ts"),be(t,n)),await c($(s,"src/modules/index.ts"),`import type { AppModuleClass } from '@forinda/kickjs-core'
2172
1404
 
2173
1405
  export const modules: AppModuleClass[] = []
2174
- `);
2175
- if (template === "graphql") {
2176
- await writeFileSafe(join9(dir, "src/resolvers/.gitkeep"), "");
2177
- }
2178
- await writeFileSafe(join9(dir, "kick.config.ts"), `import { defineConfig } from '@forinda/kickjs-cli'
1406
+ `),n==="graphql"&&await c($(s,"src/resolvers/.gitkeep"),""),await c($(s,"kick.config.ts"),`import { defineConfig } from '@forinda/kickjs-cli'
2179
1407
 
2180
1408
  export default defineConfig({
2181
- pattern: '${template}',
1409
+ pattern: '${n}',
2182
1410
  modulesDir: 'src/modules',
2183
1411
  defaultRepo: 'inmemory',
2184
1412
 
@@ -2206,8 +1434,7 @@ export default defineConfig({
2206
1434
  },
2207
1435
  ],
2208
1436
  })
2209
- `);
2210
- await writeFileSafe(join9(dir, "vitest.config.ts"), `import { defineConfig } from 'vitest/config'
1437
+ `),await c($(s,"vitest.config.ts"),`import { defineConfig } from 'vitest/config'
2211
1438
  import swc from 'unplugin-swc'
2212
1439
 
2213
1440
  export default defineConfig({
@@ -2218,89 +1445,12 @@ export default defineConfig({
2218
1445
  include: ['src/**/*.test.ts'],
2219
1446
  },
2220
1447
  })
2221
- `);
2222
- await writeFileSafe(join9(dir, "README.md"), generateReadme(name, template, packageManager));
2223
- if (options.initGit) {
2224
- try {
2225
- execSync("git init", {
2226
- cwd: dir,
2227
- stdio: "pipe"
2228
- });
2229
- execSync("git add -A", {
2230
- cwd: dir,
2231
- stdio: "pipe"
2232
- });
2233
- execSync('git commit -m "chore: initial commit from kick new"', {
2234
- cwd: dir,
2235
- stdio: "pipe"
2236
- });
2237
- console.log(" Git repository initialized");
2238
- } catch {
2239
- console.log(" Warning: git init failed (git may not be installed)");
2240
- }
2241
- }
2242
- if (options.installDeps) {
2243
- console.log(`
2244
- Installing dependencies with ${packageManager}...
2245
- `);
2246
- try {
2247
- execSync(`${packageManager} install`, {
2248
- cwd: dir,
2249
- stdio: "inherit"
2250
- });
2251
- console.log("\n Dependencies installed successfully!");
2252
- } catch {
2253
- console.log(`
2254
- Warning: ${packageManager} install failed. Run it manually.`);
2255
- }
2256
- }
2257
- console.log("\n Project scaffolded successfully!");
2258
- console.log();
2259
- const needsCd = dir !== process.cwd();
2260
- console.log(" Next steps:");
2261
- if (needsCd) console.log(` cd ${name}`);
2262
- if (!options.installDeps) console.log(` ${packageManager} install`);
2263
- const genHint = {
2264
- rest: "kick g module user",
2265
- graphql: "kick g resolver user",
2266
- ddd: "kick g module user --repo drizzle",
2267
- cqrs: "kick g module user --pattern cqrs",
2268
- minimal: "# add your routes to src/index.ts"
2269
- };
2270
- console.log(` ${genHint[template] ?? genHint.rest}`);
2271
- console.log(" kick dev");
2272
- console.log();
2273
- console.log(" Commands:");
2274
- console.log(" kick dev Start dev server with Vite HMR");
2275
- console.log(" kick build Production build via Vite");
2276
- console.log(" kick start Run production build");
2277
- console.log();
2278
- console.log(" Generators:");
2279
- console.log(" kick g module <name> Full DDD module (controller, DTOs, use-cases, repo)");
2280
- console.log(" kick g scaffold <n> <f..> CRUD module from field definitions");
2281
- console.log(" kick g controller <name> Standalone controller");
2282
- console.log(" kick g service <name> @Service() class");
2283
- console.log(" kick g middleware <name> Express middleware");
2284
- console.log(" kick g guard <name> Route guard (auth, roles, etc.)");
2285
- console.log(" kick g adapter <name> AppAdapter with lifecycle hooks");
2286
- console.log(" kick g dto <name> Zod DTO schema");
2287
- if (template === "graphql") console.log(" kick g resolver <name> GraphQL resolver");
2288
- if (template === "cqrs") console.log(" kick g job <name> Queue job processor");
2289
- console.log(" kick g config Generate kick.config.ts");
2290
- console.log();
2291
- console.log(" Add packages:");
2292
- console.log(" kick add <pkg> Install a KickJS package + peers");
2293
- console.log(" kick add --list Show all available packages");
2294
- console.log();
2295
- console.log(" Available: auth, swagger, graphql, drizzle, prisma, ws,");
2296
- console.log(" cron, queue, mailer, otel, multi-tenant, notifications, testing");
2297
- console.log();
2298
- }
2299
- __name(initProject, "initProject");
2300
- function getEntryFile(name, template) {
2301
- switch (template) {
2302
- case "graphql":
2303
- return `import 'reflect-metadata'
1448
+ `),await c($(s,"README.md"),Ke(t,n,o)),e.initGit)try{_("git init",{cwd:s,stdio:"pipe"}),_("git add -A",{cwd:s,stdio:"pipe"}),_('git commit -m "chore: initial commit from kick new"',{cwd:s,stdio:"pipe"}),console.log(" Git repository initialized")}catch{console.log(" Warning: git init failed (git may not be installed)")}if(e.installDeps){console.log(`
1449
+ Installing dependencies with ${o}...
1450
+ `);try{_(`${o} install`,{cwd:s,stdio:"inherit"}),console.log(`
1451
+ Dependencies installed successfully!`)}catch{console.log(`
1452
+ Warning: ${o} install failed. Run it manually.`)}}console.log(`
1453
+ Project scaffolded successfully!`),console.log();let a=s!==process.cwd();console.log(" Next steps:"),a&&console.log(` cd ${t}`),e.installDeps||console.log(` ${o} install`);let d={rest:"kick g module user",graphql:"kick g resolver user",ddd:"kick g module user --repo drizzle",cqrs:"kick g module user --pattern cqrs",minimal:"# add your routes to src/index.ts"};console.log(` ${d[n]??d.rest}`),console.log(" kick dev"),console.log(),console.log(" Commands:"),console.log(" kick dev Start dev server with Vite HMR"),console.log(" kick build Production build via Vite"),console.log(" kick start Run production build"),console.log(),console.log(" Generators:"),console.log(" kick g module <name> Full DDD module (controller, DTOs, use-cases, repo)"),console.log(" kick g scaffold <n> <f..> CRUD module from field definitions"),console.log(" kick g controller <name> Standalone controller"),console.log(" kick g service <name> @Service() class"),console.log(" kick g middleware <name> Express middleware"),console.log(" kick g guard <name> Route guard (auth, roles, etc.)"),console.log(" kick g adapter <name> AppAdapter with lifecycle hooks"),console.log(" kick g dto <name> Zod DTO schema"),n==="graphql"&&console.log(" kick g resolver <name> GraphQL resolver"),n==="cqrs"&&console.log(" kick g job <name> Queue job processor"),console.log(" kick g config Generate kick.config.ts"),console.log(),console.log(" Add packages:"),console.log(" kick add <pkg> Install a KickJS package + peers"),console.log(" kick add --list Show all available packages"),console.log(),console.log(" Available: auth, swagger, graphql, drizzle, prisma, ws,"),console.log(" cron, queue, mailer, otel, multi-tenant, notifications, testing"),console.log()}i(We,"initProject");function be(e,t){switch(t){case"graphql":return`import 'reflect-metadata'
2304
1454
  import { bootstrap } from '@forinda/kickjs-http'
2305
1455
  import { DevToolsAdapter } from '@forinda/kickjs-devtools'
2306
1456
  import { GraphQLAdapter } from '@forinda/kickjs-graphql'
@@ -2320,9 +1470,7 @@ bootstrap({
2320
1470
  }),
2321
1471
  ],
2322
1472
  })
2323
- `;
2324
- case "cqrs":
2325
- return `import 'reflect-metadata'
1473
+ `;case"cqrs":return`import 'reflect-metadata'
2326
1474
  import { bootstrap } from '@forinda/kickjs-http'
2327
1475
  import { DevToolsAdapter } from '@forinda/kickjs-devtools'
2328
1476
  import { SwaggerAdapter } from '@forinda/kickjs-swagger'
@@ -2334,10 +1482,10 @@ import { modules } from './modules'
2334
1482
  bootstrap({
2335
1483
  modules,
2336
1484
  adapters: [
2337
- new OtelAdapter({ serviceName: '${name}' }),
1485
+ new OtelAdapter({ serviceName: '${e}' }),
2338
1486
  new DevToolsAdapter(),
2339
1487
  new SwaggerAdapter({
2340
- info: { title: '${name}', version: '${cliPkg.version}' },
1488
+ info: { title: '${e}', version: '${q.version}' },
2341
1489
  }),
2342
1490
  // Uncomment for WebSocket support:
2343
1491
  // new WsAdapter(),
@@ -2347,18 +1495,12 @@ bootstrap({
2347
1495
  // }),
2348
1496
  ],
2349
1497
  })
2350
- `;
2351
- case "minimal":
2352
- return `import 'reflect-metadata'
1498
+ `;case"minimal":return`import 'reflect-metadata'
2353
1499
  import { bootstrap } from '@forinda/kickjs-http'
2354
1500
  import { modules } from './modules'
2355
1501
 
2356
1502
  bootstrap({ modules })
2357
- `;
2358
- case "ddd":
2359
- case "rest":
2360
- default:
2361
- return `import 'reflect-metadata'
1503
+ `;default:return`import 'reflect-metadata'
2362
1504
  import { bootstrap } from '@forinda/kickjs-http'
2363
1505
  import { DevToolsAdapter } from '@forinda/kickjs-devtools'
2364
1506
  import { SwaggerAdapter } from '@forinda/kickjs-swagger'
@@ -2369,42 +1511,18 @@ bootstrap({
2369
1511
  adapters: [
2370
1512
  new DevToolsAdapter(),
2371
1513
  new SwaggerAdapter({
2372
- info: { title: '${name}', version: '${cliPkg.version}' },
1514
+ info: { title: '${e}', version: '${q.version}' },
2373
1515
  }),
2374
1516
  ],
2375
1517
  })
2376
- `;
2377
- }
2378
- }
2379
- __name(getEntryFile, "getEntryFile");
2380
- function generateReadme(name, template, pm) {
2381
- const templateLabels = {
2382
- rest: "REST API",
2383
- graphql: "GraphQL API",
2384
- ddd: "Domain-Driven Design",
2385
- cqrs: "CQRS + Event-Driven",
2386
- minimal: "Minimal"
2387
- };
2388
- const packages = [
2389
- "@forinda/kickjs-core",
2390
- "@forinda/kickjs-http",
2391
- "@forinda/kickjs-config"
2392
- ];
2393
- if (template !== "minimal") {
2394
- packages.push("@forinda/kickjs-swagger", "@forinda/kickjs-devtools");
2395
- }
2396
- if (template === "graphql") packages.push("@forinda/kickjs-graphql");
2397
- if (template === "cqrs") {
2398
- packages.push("@forinda/kickjs-queue", "@forinda/kickjs-ws", "@forinda/kickjs-otel");
2399
- }
2400
- return `# ${name}
2401
-
2402
- A **${templateLabels[template] ?? "REST API"}** built with [KickJS](https://forinda.github.io/kick-js/) \u2014 a decorator-driven Node.js framework on Express 5 and TypeScript.
1518
+ `}}i(be,"getEntryFile");function Ke(e,t,r){let o={rest:"REST API",graphql:"GraphQL API",ddd:"Domain-Driven Design",cqrs:"CQRS + Event-Driven",minimal:"Minimal"},n=["@forinda/kickjs-core","@forinda/kickjs-http","@forinda/kickjs-config"];return t!=="minimal"&&n.push("@forinda/kickjs-swagger","@forinda/kickjs-devtools"),t==="graphql"&&n.push("@forinda/kickjs-graphql"),t==="cqrs"&&n.push("@forinda/kickjs-queue","@forinda/kickjs-ws","@forinda/kickjs-otel"),`# ${e}
1519
+
1520
+ A **${o[t]??"REST API"}** built with [KickJS](https://forinda.github.io/kick-js/) \u2014 a decorator-driven Node.js framework on Express 5 and TypeScript.
2403
1521
 
2404
1522
  ## Getting Started
2405
1523
 
2406
1524
  \`\`\`bash
2407
- ${pm} install
1525
+ ${r} install
2408
1526
  kick dev
2409
1527
  \`\`\`
2410
1528
 
@@ -2415,7 +1533,7 @@ kick dev
2415
1533
  | \`kick dev\` | Start dev server with Vite HMR |
2416
1534
  | \`kick build\` | Production build |
2417
1535
  | \`kick start\` | Run production build |
2418
- | \`${pm} run test\` | Run tests with Vitest |
1536
+ | \`${r} run test\` | Run tests with Vitest |
2419
1537
  | \`kick g module <name>\` | Generate a DDD module |
2420
1538
  | \`kick g scaffold <name> <fields...>\` | Generate CRUD from field definitions |
2421
1539
  | \`kick add <package>\` | Add a KickJS package |
@@ -2432,7 +1550,8 @@ src/
2432
1550
 
2433
1551
  ## Packages
2434
1552
 
2435
- ${packages.map((p) => `- \`${p}\``).join("\n")}
1553
+ ${n.map(s=>`- \`${s}\``).join(`
1554
+ `)}
2436
1555
 
2437
1556
  ## Adding Features
2438
1557
 
@@ -2459,63 +1578,4 @@ Copy \`.env.example\` to \`.env\` and configure:
2459
1578
 
2460
1579
  - [KickJS Documentation](https://forinda.github.io/kick-js/)
2461
1580
  - [CLI Reference](https://forinda.github.io/kick-js/api/cli.html)
2462
- `;
2463
- }
2464
- __name(generateReadme, "generateReadme");
2465
-
2466
- // src/config.ts
2467
- import { readFile as readFile3, access as access2 } from "fs/promises";
2468
- import { join as join10 } from "path";
2469
- function defineConfig(config) {
2470
- return config;
2471
- }
2472
- __name(defineConfig, "defineConfig");
2473
- var CONFIG_FILES = [
2474
- "kick.config.ts",
2475
- "kick.config.js",
2476
- "kick.config.mjs",
2477
- "kick.config.json"
2478
- ];
2479
- async function loadKickConfig(cwd) {
2480
- for (const filename of CONFIG_FILES) {
2481
- const filepath = join10(cwd, filename);
2482
- try {
2483
- await access2(filepath);
2484
- } catch {
2485
- continue;
2486
- }
2487
- if (filename.endsWith(".json")) {
2488
- const content = await readFile3(filepath, "utf-8");
2489
- return JSON.parse(content);
2490
- }
2491
- try {
2492
- const { pathToFileURL } = await import("url");
2493
- const mod = await import(pathToFileURL(filepath).href);
2494
- return mod.default ?? mod;
2495
- } catch (err) {
2496
- if (filename.endsWith(".ts")) {
2497
- console.warn(`Warning: Failed to load ${filename}. TypeScript config files require a runtime loader (e.g. tsx, ts-node) or use kick.config.js/.mjs instead.`);
2498
- }
2499
- continue;
2500
- }
2501
- }
2502
- return null;
2503
- }
2504
- __name(loadKickConfig, "loadKickConfig");
2505
- export {
2506
- defineConfig,
2507
- generateAdapter,
2508
- generateController2 as generateController,
2509
- generateDto,
2510
- generateGuard,
2511
- generateMiddleware,
2512
- generateModule,
2513
- generateService,
2514
- initProject,
2515
- loadKickConfig,
2516
- pluralize,
2517
- toCamelCase,
2518
- toKebabCase,
2519
- toPascalCase
2520
- };
2521
- //# sourceMappingURL=index.js.map
1581
+ `}i(Ke,"generateReadme");import{readFile as He,access as Ve}from"fs/promises";import{join as Je}from"path";function Ze(e){return e}i(Ze,"defineConfig");var Xe=["kick.config.ts","kick.config.js","kick.config.mjs","kick.config.json"];async function et(e){for(let t of Xe){let r=Je(e,t);try{await Ve(r)}catch{continue}if(t.endsWith(".json")){let o=await He(r,"utf-8");return JSON.parse(o)}try{let{pathToFileURL:o}=await import("url"),n=await import(o(r).href);return n.default??n}catch{t.endsWith(".ts")&&console.warn(`Warning: Failed to load ${t}. TypeScript config files require a runtime loader (e.g. tsx, ts-node) or use kick.config.js/.mjs instead.`);continue}}return null}i(et,"loadKickConfig");export{Ze as defineConfig,Te as generateAdapter,Fe as generateController,Ge as generateDto,ze as generateGuard,Ae as generateMiddleware,Ce as generateModule,qe as generateService,We as initProject,et as loadKickConfig,x as pluralize,C as toCamelCase,f as toKebabCase,l as toPascalCase};