@forinda/kickjs-cli 6.1.1 → 6.2.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -2
- package/dist/{agent-docs-GpRHHdWC.mjs → agent-docs-B65qHJup.mjs} +3 -3
- package/dist/{agent-docs-GpRHHdWC.mjs.map → agent-docs-B65qHJup.mjs.map} +1 -1
- package/dist/{build-D9X9QBkC.mjs → build-C8B6v3iF.mjs} +3 -3
- package/dist/{build-D9X9QBkC.mjs.map → build-C8B6v3iF.mjs.map} +1 -1
- package/dist/{builtins-DHcybuaw.mjs → builtins-D4DM7SWf.mjs} +2 -2
- package/dist/cli.mjs +156 -154
- package/dist/{config-DLy6JCCy.mjs → config-MpY5O0Uv.mjs} +3 -3
- package/dist/config-MpY5O0Uv.mjs.map +1 -0
- package/dist/{doctor-CcVNNzGj.mjs → doctor-Da_WPc4H.mjs} +71 -63
- package/dist/doctor-Da_WPc4H.mjs.map +1 -0
- package/dist/index.d.mts +28 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/{plugin-C6jhcq0N.mjs → plugin-1LpIVE1p.mjs} +3 -3
- package/dist/{plugin-C6jhcq0N.mjs.map → plugin-1LpIVE1p.mjs.map} +1 -1
- package/dist/{project-docs-CqOymvmb.mjs → project-docs-DdHhz2vw.mjs} +2 -2
- package/dist/{project-docs-CqOymvmb.mjs.map → project-docs-DdHhz2vw.mjs.map} +1 -1
- package/dist/{project-root-yLxS5CqO.mjs → project-root-DEufQPY3.mjs} +3 -3
- package/dist/{project-root-yLxS5CqO.mjs.map → project-root-DEufQPY3.mjs.map} +1 -1
- package/dist/{rolldown-runtime-BnMWUWuC.mjs → rolldown-runtime-DT7Ktfzg.mjs} +1 -1
- package/dist/{run-plugins-CubT9x_A.mjs → run-plugins-DtHMyrXU.mjs} +70 -76
- package/dist/run-plugins-DtHMyrXU.mjs.map +1 -0
- package/dist/{typegen-BJwy65-p.mjs → typegen-BaE5TxzH.mjs} +5 -5
- package/dist/{typegen-BJwy65-p.mjs.map → typegen-BaE5TxzH.mjs.map} +1 -1
- package/dist/{types-D7d_Y66D.mjs → types-Btg3O9XP.mjs} +1 -1
- package/package.json +4 -4
- package/dist/config-DLy6JCCy.mjs.map +0 -1
- package/dist/doctor-CcVNNzGj.mjs.map +0 -1
- package/dist/run-plugins-CubT9x_A.mjs.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @forinda/kickjs-cli v6.
|
|
2
|
+
* @forinda/kickjs-cli v6.2.0-alpha.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Felix Orinda
|
|
5
5
|
*
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
|
-
import{b as e,c as t,d as n,g as r,l as i,o as a,s as o,v as s}from"./project-docs-
|
|
11
|
+
import{b as e,c as t,d as n,g as r,l as i,o as a,s as o,v as s}from"./project-docs-DdHhz2vw.mjs";import{i as c,t as l}from"./config-MpY5O0Uv.mjs";import{t as u}from"./project-root-DEufQPY3.mjs";import{createRequire as d}from"node:module";import f,{dirname as p,join as m,relative as h,resolve as g}from"node:path";import{existsSync as _,readFileSync as v,readdirSync as y,statSync as b}from"node:fs";import{readFile as x,writeFile as S}from"node:fs/promises";import C from"pluralize";import{execFileSync as ee,execSync as w}from"node:child_process";import{fileURLToPath as te,pathToFileURL as ne}from"node:url";import{defineGenerator as re}from"@forinda/kickjs-cli-kit";function T(e){return e.replace(/[-_\s]+(.)?/g,(e,t)=>t?t.toUpperCase():``).replace(/^(.)/,e=>e.toUpperCase())}function E(e){let t=T(e);return t.charAt(0).toLowerCase()+t.slice(1)}function D(e){return e.replace(/([a-z])([A-Z])/g,`$1-$2`).replace(/[\s_]+/g,`-`).toLowerCase()}function O(e){return C.plural(e)}function k(e){return C.plural(e)}function A(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function ie(e){return e.charAt(0).toUpperCase()+e.slice(1).replace(/-([a-z])/g,(e,t)=>t.toUpperCase())}function ae(e){return e.replace(/([a-z])([A-Z])/g,`$1-$2`).toLowerCase()}function oe(e,t,n){let r={inmemory:`InMemory${e}Repository`,drizzle:`Drizzle${e}Repository`,prisma:`Prisma${e}Repository`},i={inmemory:`in-memory-${t}`,drizzle:`drizzle-${t}`,prisma:`prisma-${t}`};return{repoClass:r[n]??`${ie(n)}${e}Repository`,repoFile:i[n]??`${ae(n)}-${t}`}}function j(e){return e??`define`}function M(e){let{pascal:t,kebab:n,plural:r=``,repo:i,style:a}=e,{repoClass:o,repoFile:s}=oe(t,n,i),c=j(a),l=`/**
|
|
12
12
|
* ${t} Module
|
|
13
13
|
*
|
|
14
14
|
* REST module with a flat folder structure.
|
|
@@ -80,7 +80,7 @@ ${d}
|
|
|
80
80
|
},
|
|
81
81
|
}),
|
|
82
82
|
})
|
|
83
|
-
`}function
|
|
83
|
+
`}function se(e){let{pascal:t,kebab:n,plural:r=``,style:i}=e,a=j(i),o=` /**
|
|
84
84
|
* Declare HTTP routes. Return value shape:
|
|
85
85
|
*
|
|
86
86
|
* - \`path\` — URL prefix for this route set.
|
|
@@ -175,7 +175,7 @@ export class ${t}Controller {
|
|
|
175
175
|
ctx.noContent()
|
|
176
176
|
}
|
|
177
177
|
}
|
|
178
|
-
`}function
|
|
178
|
+
`}function ce(e){let{pascal:t}=e;return`import { z } from 'zod'
|
|
179
179
|
|
|
180
180
|
/**
|
|
181
181
|
* Create ${t} DTO — Zod schema for validating POST request bodies.
|
|
@@ -191,14 +191,14 @@ export const create${t}Schema = z.object({
|
|
|
191
191
|
})
|
|
192
192
|
|
|
193
193
|
export type Create${t}DTO = z.infer<typeof create${t}Schema>
|
|
194
|
-
`}function
|
|
194
|
+
`}function le(e){let{pascal:t}=e;return`import { z } from 'zod'
|
|
195
195
|
|
|
196
196
|
export const update${t}Schema = z.object({
|
|
197
197
|
name: z.string().min(1).max(200).optional(),
|
|
198
198
|
})
|
|
199
199
|
|
|
200
200
|
export type Update${t}DTO = z.infer<typeof update${t}Schema>
|
|
201
|
-
`}function
|
|
201
|
+
`}function ue(e){let{pascal:t}=e;return`export interface ${t}ResponseDTO {
|
|
202
202
|
id: string
|
|
203
203
|
name: string
|
|
204
204
|
createdAt: string
|
|
@@ -368,7 +368,7 @@ export class ${o}${t}Repository implements I${t}Repository {
|
|
|
368
368
|
this.store.delete(id)
|
|
369
369
|
}
|
|
370
370
|
}
|
|
371
|
-
`}function
|
|
371
|
+
`}function de(e){let{pascal:t,kebab:n,plural:r=``}=e;return`import { describe, it, expect, beforeEach } from 'vitest'
|
|
372
372
|
import { Container } from '@forinda/kickjs'
|
|
373
373
|
|
|
374
374
|
describe('${t}Controller', () => {
|
|
@@ -420,7 +420,7 @@ describe('${t}Controller', () => {
|
|
|
420
420
|
})
|
|
421
421
|
})
|
|
422
422
|
})
|
|
423
|
-
`}function
|
|
423
|
+
`}function fe(e){let{pascal:t,kebab:n,plural:r=``,repoPrefix:i=`../infrastructure/repositories/in-memory-${n}.repository`}=e;return`import { describe, it, expect, beforeEach } from 'vitest'
|
|
424
424
|
import { InMemory${t}Repository } from '${i}'
|
|
425
425
|
|
|
426
426
|
describe('InMemory${t}Repository', () => {
|
|
@@ -482,7 +482,7 @@ describe('InMemory${t}Repository', () => {
|
|
|
482
482
|
expect(found).toBeNull()
|
|
483
483
|
})
|
|
484
484
|
})
|
|
485
|
-
`}function
|
|
485
|
+
`}function pe(e){let{pascal:t,kebab:n}=e;return`import { Service, Inject, HttpException } from '@forinda/kickjs'
|
|
486
486
|
import type { ParsedQuery } from '@forinda/kickjs'
|
|
487
487
|
import { ${t.toUpperCase()}_REPOSITORY, type I${t}Repository } from './${n}.repository'
|
|
488
488
|
import type { ${t}ResponseDTO } from './dtos/${n}-response.dto'
|
|
@@ -519,65 +519,61 @@ export class ${t}Service {
|
|
|
519
519
|
await this.repo.delete(id)
|
|
520
520
|
}
|
|
521
521
|
}
|
|
522
|
-
`}function
|
|
522
|
+
`}function me(e){let{pascal:t}=e;return`import type { QueryFieldConfig } from '@forinda/kickjs'
|
|
523
523
|
|
|
524
524
|
export const ${t.toUpperCase()}_QUERY_CONFIG: QueryFieldConfig = {
|
|
525
525
|
filterable: ['name'],
|
|
526
526
|
sortable: ['name', 'createdAt'],
|
|
527
527
|
searchable: ['name'],
|
|
528
528
|
}
|
|
529
|
-
`}function
|
|
529
|
+
`}const he={express:{from:`@forinda/kickjs`,name:`expressRuntime`},fastify:{from:`@forinda/kickjs/fastify`,name:`fastifyRuntime`},h3:{from:`@forinda/kickjs/h3`,name:`h3Runtime`}};function ge(e,t,n,r=[],i=`express`){let a=he[i],o=i===`express`;switch(t){case`minimal`:{let t=[],i=[],s=o?`import { bootstrap, ${a.name} } from '@forinda/kickjs'`:`import { bootstrap } from '@forinda/kickjs'\nimport { ${a.name} } from '${a.from}'`;r.includes(`swagger`)&&(t.push(`import { SwaggerAdapter } from '@forinda/kickjs-swagger'`),i.push(` SwaggerAdapter({ info: { title: '${e}', version: '${n}' } }),`)),r.includes(`devtools`)&&(t.push(`import { DevToolsAdapter } from '@forinda/kickjs-devtools'`),i.push(` DevToolsAdapter(),`));let c=t.length?t.join(`
|
|
530
|
+
`)+`
|
|
531
|
+
`:``,l=i.length?`,\n adapters: [\n${i.join(`
|
|
532
|
+
`)}\n ]`:``;return`import 'reflect-metadata'
|
|
530
533
|
// Side-effect import — registers the extended env schema with kickjs
|
|
531
534
|
// **before** any controller / service / @Value gets resolved. Without
|
|
532
535
|
// this line ConfigService.get('YOUR_KEY') returns undefined because the
|
|
533
536
|
// cached schema would still be the base shape. See guide/configuration.
|
|
534
537
|
import './config'
|
|
535
|
-
|
|
536
|
-
${
|
|
537
|
-
`)+`
|
|
538
|
-
`:``}import { modules } from './modules'
|
|
538
|
+
${s}
|
|
539
|
+
${c}import { modules } from './modules'
|
|
539
540
|
|
|
540
541
|
// Export the app for the Vite plugin (dev mode)
|
|
541
|
-
export const app = await bootstrap({ modules
|
|
542
|
-
`)}\n
|
|
543
|
-
`
|
|
542
|
+
export const app = await bootstrap({ modules, runtime: ${a.name}()${l} })
|
|
543
|
+
`}default:{let t=[],i=[];r.includes(`devtools`)&&(t.push(`import { DevToolsAdapter } from '@forinda/kickjs-devtools'`),i.push(` DevToolsAdapter(),`)),r.includes(`swagger`)&&(t.push(`import { SwaggerAdapter } from '@forinda/kickjs-swagger'`),i.push(` SwaggerAdapter({\n info: { title: '${e}', version: '${n}' },\n }),`));let s=t.length?t.join(`
|
|
544
|
+
`)+`
|
|
545
|
+
`:``,c=i.length?`\n adapters: [\n${i.join(`
|
|
546
|
+
`)}\n ],`:``,l=[`bootstrap`,`requestId`,`requestLogger`,`helmet`,`cors`];o&&l.push(a.name);let u=o?`import express from 'express'\nimport {\n ${l.join(`,
|
|
547
|
+
`)},\n} from '@forinda/kickjs'`:`import {\n ${l.join(`,
|
|
548
|
+
`)},\n} from '@forinda/kickjs'\nimport { ${a.name} } from '${a.from}'`,d=o?`
|
|
549
|
+
express.json(),`:``;return`import 'reflect-metadata'
|
|
544
550
|
// Side-effect import — registers the extended env schema with kickjs
|
|
545
551
|
// **before** any controller / service / @Value gets resolved. Without
|
|
546
552
|
// this line ConfigService.get('YOUR_KEY') returns undefined because the
|
|
547
553
|
// cached schema would still be the base shape. See guide/configuration.
|
|
548
554
|
import './config'
|
|
549
|
-
|
|
550
|
-
import {
|
|
551
|
-
bootstrap,
|
|
552
|
-
requestId,
|
|
553
|
-
requestLogger,
|
|
554
|
-
helmet,
|
|
555
|
-
cors,
|
|
556
|
-
} from '@forinda/kickjs'
|
|
557
|
-
${t.length?t.join(`
|
|
558
|
-
`)+`
|
|
559
|
-
`:``}import { modules } from './modules'
|
|
555
|
+
${u}
|
|
556
|
+
${s}import { modules } from './modules'
|
|
560
557
|
|
|
561
558
|
// Export the app for the Vite plugin (dev mode)
|
|
562
559
|
export const app = await bootstrap({
|
|
563
|
-
modules
|
|
564
|
-
|
|
560
|
+
modules,
|
|
561
|
+
runtime: ${a.name}(),${c}
|
|
565
562
|
middleware: [
|
|
566
563
|
helmet(),
|
|
567
564
|
cors({ origin: '*' }),
|
|
568
565
|
requestId(),
|
|
569
|
-
requestLogger()
|
|
570
|
-
express.json(),
|
|
566
|
+
requestLogger(),${d}
|
|
571
567
|
],
|
|
572
568
|
})
|
|
573
|
-
`}}}function
|
|
569
|
+
`}}}function _e(){return`import { defineModules } from '@forinda/kickjs'
|
|
574
570
|
import { HelloModule } from './hello/hello.module'
|
|
575
571
|
|
|
576
572
|
// Remove HelloModule and run: kick g module <name>
|
|
577
573
|
// \`defineModules()\` returns a chainable list — \`kick g module\` appends
|
|
578
574
|
// \`.mount(NewModule())\` to the chain on every generation.
|
|
579
575
|
export const modules = defineModules().mount(HelloModule())
|
|
580
|
-
`}function
|
|
576
|
+
`}function ve(e=`zod`){return e===`valibot`?`import { loadEnvFromSchema } from '@forinda/kickjs/config'
|
|
581
577
|
import { fromValibot } from '@forinda/kickjs-schema/valibot'
|
|
582
578
|
import * as v from 'valibot'
|
|
583
579
|
|
|
@@ -705,7 +701,7 @@ const envSchema = fromZod(
|
|
|
705
701
|
export const env = loadEnvFromSchema(envSchema)
|
|
706
702
|
|
|
707
703
|
export default envSchema
|
|
708
|
-
`}function
|
|
704
|
+
`}function ye(){return`import { Service } from '@forinda/kickjs'
|
|
709
705
|
|
|
710
706
|
@Service()
|
|
711
707
|
export class HelloService {
|
|
@@ -717,7 +713,7 @@ export class HelloService {
|
|
|
717
713
|
return { status: 'ok', uptime: process.uptime() }
|
|
718
714
|
}
|
|
719
715
|
}
|
|
720
|
-
`}function
|
|
716
|
+
`}function be(){return`import { Controller, Get, Autowired, type Ctx } from '@forinda/kickjs'
|
|
721
717
|
import { HelloService } from './hello.service'
|
|
722
718
|
|
|
723
719
|
// \`Ctx<KickRoutes.HelloController['<method>']>\` is generated by
|
|
@@ -739,7 +735,7 @@ export class HelloController {
|
|
|
739
735
|
ctx.json(this.helloService.healthCheck())
|
|
740
736
|
}
|
|
741
737
|
}
|
|
742
|
-
`}function
|
|
738
|
+
`}function xe(){return`import { defineModule } from '@forinda/kickjs'
|
|
743
739
|
import { HelloController } from './hello.controller'
|
|
744
740
|
|
|
745
741
|
export const HelloModule = defineModule({
|
|
@@ -760,10 +756,15 @@ export const HelloModule = defineModule({
|
|
|
760
756
|
},
|
|
761
757
|
}),
|
|
762
758
|
})
|
|
763
|
-
`}function
|
|
759
|
+
`}function Se(e,t=`inmemory`,n=`pnpm`,r=`express`){return`import { defineConfig } from '@forinda/kickjs-cli'
|
|
764
760
|
|
|
765
761
|
export default defineConfig({
|
|
766
762
|
pattern: '${e}',
|
|
763
|
+
// The HTTP engine this app boots on (matches \`bootstrap({ runtime })\` in
|
|
764
|
+
// src/index.ts). Dep-aware commands read it: \`kick add upload\` installs the
|
|
765
|
+
// engine's multipart driver, \`kick doctor\` checks the engine peers, and
|
|
766
|
+
// \`kick typegen\` flips the runtime escape-hatch types to this engine.
|
|
767
|
+
runtime: '${r}',
|
|
767
768
|
// Pinned so \`kick add\` and other dep-installing commands always use the
|
|
768
769
|
// project's intended package manager, regardless of which lockfile exists.
|
|
769
770
|
packageManager: '${n}',
|
|
@@ -807,7 +808,7 @@ export default defineConfig({
|
|
|
807
808
|
},
|
|
808
809
|
],
|
|
809
810
|
})
|
|
810
|
-
`}async function
|
|
811
|
+
`}async function Ce(e){let{pascal:t,kebab:n,plural:r,style:i,write:a}=e;await a(`${n}.module.ts`,se({pascal:t,kebab:n,plural:r,style:i})),await a(`${n}.controller.ts`,`import { Controller, Get, type Ctx } from '@forinda/kickjs'
|
|
811
812
|
|
|
812
813
|
// \`Ctx<KickRoutes.${t}Controller['<method>']>\` is generated by
|
|
813
814
|
// \`kick typegen\` (auto-run on \`kick dev\`).
|
|
@@ -819,7 +820,7 @@ export class ${t}Controller {
|
|
|
819
820
|
ctx.json({ message: '${t} list' })
|
|
820
821
|
}
|
|
821
822
|
}
|
|
822
|
-
`)}async function
|
|
823
|
+
`)}async function we(e){let{pascal:t,kebab:n,plural:r,pluralPascal:i,repo:a,noTests:o,tokenScope:s,style:c,write:l}=e;await l(`${n}.module.ts`,M({pascal:t,kebab:n,plural:r,repo:a,style:c})),await l(`${n}.constants.ts`,me({pascal:t,kebab:n})),await l(`${n}.controller.ts`,N({pascal:t,kebab:n,plural:r,pluralPascal:i})),await l(`${n}.service.ts`,pe({pascal:t,kebab:n})),await l(`dtos/create-${n}.dto.ts`,ce({pascal:t,kebab:n})),await l(`dtos/update-${n}.dto.ts`,le({pascal:t,kebab:n})),await l(`dtos/${n}-response.dto.ts`,ue({pascal:t,kebab:n})),await l(`${n}.repository.ts`,P({pascal:t,kebab:n,dtoPrefix:`./dtos`,tokenScope:s}));let u=a===`inmemory`,d=u?`in-memory-${n}`:`${D(a)}-${n}`,f=u?F({pascal:t,kebab:n,repoPrefix:`.`,dtoPrefix:`./dtos`}):I({pascal:t,kebab:n,repoType:a,repoPrefix:`.`,dtoPrefix:`./dtos`});await l(`${d}.repository.ts`,f),o||(a!==`inmemory`&&await l(`in-memory-${n}.repository.ts`,F({pascal:t,kebab:n,repoPrefix:`.`,dtoPrefix:`./dtos`})),await l(`__tests__/${n}.controller.test.ts`,de({pascal:t,kebab:n,plural:r})),await l(`__tests__/${n}.repository.test.ts`,fe({pascal:t,kebab:n,plural:r,repoPrefix:`../in-memory-${n}.repository`})))}function Te(e){return e?typeof e==`string`?e:e.name:`inmemory`}async function Ee(t){let{name:n,modulesDir:a,noEntity:c,noTests:l,repo:u=`inmemory`,force:d,dryRun:f}=t,p=t.pluralize!==!1,h=t.pattern??`rest`;t.minimal&&(h=`minimal`);let g=D(n),_=T(n),v=p?O(g):g,y=p?k(_):_,b=m(a,v),x=[],S=d??!1,C={kebab:g,pascal:_,plural:v,pluralPascal:y,moduleDir:b,repo:u,noEntity:c??!1,noTests:l??!1,prismaClientPath:t.prismaClientPath??`@prisma/client`,tokenScope:t.tokenScope??`app`,style:t.style??`define`,write:async(t,n)=>{let a=m(b,t);if(f){x.push(a);return}if(!S&&await s(a)&&!await o({message:`File exists: ${r.dim(t)}. Overwrite?`,initialValue:!1})){i.warn(`Skipped: ${t}`);return}await e(a,n),x.push(a)},files:x};switch(h){case`minimal`:await Ce(C);break;default:await we(C);break}return f||await L(a,_,v,g,C.style),x}async function L(t,n,r,i,a=`define`){let o=m(t,`index.ts`),c=await s(o),l=`./${r}/${i}.module`,u=a===`class`?`${n}Module`:`${n}Module()`;if(!c){await e(o,a===`class`?`import type { AppModuleEntry } from '@forinda/kickjs'
|
|
823
824
|
import { ${n}Module } from '${l}'
|
|
824
825
|
|
|
825
826
|
export const modules: AppModuleEntry[] = [${u}]
|
|
@@ -827,11 +828,11 @@ export const modules: AppModuleEntry[] = [${u}]
|
|
|
827
828
|
import { ${n}Module } from '${l}'
|
|
828
829
|
|
|
829
830
|
export const modules = defineModules().mount(${u})
|
|
830
|
-
`);return}let d=await
|
|
831
|
+
`);return}let d=await x(o,`utf-8`),f=`import { ${n}Module } from '${l}'`,p=A(l);if(!RegExp(`^import\\s*\\{[^}]*\\b${A(n)}Module\\b[^}]*\\}\\s*from\\s*['"]${p}['"]`,`m`).test(d)){let e=d.lastIndexOf(`import `);if(e!==-1){let t=d.indexOf(`
|
|
831
832
|
`,e);d=d.slice(0,t+1)+f+`
|
|
832
833
|
`+d.slice(t+1)}else d=f+`
|
|
833
|
-
`+d}let h=
|
|
834
|
-
`;)t++;return t}if(n===`/*`){for(t+=2;t+1<e.length&&!(e[t]===`*`&&e[t+1]===`/`);)t++;return t+2}return t}function
|
|
834
|
+
`+d}let h=z(d);if(h){let e=d.slice(h.rhsStart,h.rhsEnd+1);RegExp(`\\b${A(n)}Module\\b`).test(e)||(d=R(d,u))}else d=R(d,u);await S(o,d,`utf-8`)}function R(e,t){let n=z(e);if(!n)return e;if(n.shape===`array`){let r=e.slice(n.rhsStart+1,n.rhsEnd),i=r.trim(),a;if(!i)a=`[${t}]`;else{let e=i.endsWith(`,`)?``:`,`;a=`[${r.trimEnd()}${e} ${t}]`}return e.slice(0,n.rhsStart)+a+e.slice(n.rhsEnd+1)}return`${e.slice(0,n.chainEnd)}\n .mount(${t})${e.slice(n.chainEnd)}`}function z(e){let t=/export\s+const\s+modules\b[^=]*=/.exec(e);if(!t)return null;let n=t.index+t[0].length;for(;n<e.length&&/\s/.test(e[n]??``);)n++;if(e[n]===`[`){let t=Oe(e,n);return t===-1?null:{shape:`array`,rhsStart:n,rhsEnd:t}}if(e.slice(n,n+13)===`defineModules`){let t=De(e,n);return t===-1?null:{shape:`chain`,rhsStart:n,rhsEnd:t-1,chainEnd:t}}return null}function De(e,t=0){let n=/defineModules\s*\(/g;n.lastIndex=t;let r=n.exec(e);if(!r)return-1;let i=r.index+r[0].length-1;if(e[i]!==`(`||(i=V(e,i),i===-1))return-1;for(i++;;){let t=i;for(;t<e.length&&/\s/.test(e[t]??``);)t++;if(e[t]!==`.`||e.slice(t,t+6)!==`.mount`)break;for(t+=6;t<e.length&&/\s/.test(e[t]??``);)t++;if(e[t]!==`(`)break;let n=V(e,t);if(n===-1)break;i=n+1}return i}function B(e,t){let n=e.slice(t,t+2);if(n===`//`){for(t+=2;t<e.length&&e[t]!==`
|
|
835
|
+
`;)t++;return t}if(n===`/*`){for(t+=2;t+1<e.length&&!(e[t]===`*`&&e[t+1]===`/`);)t++;return t+2}return t}function Oe(e,t){if(e[t]!==`[`)return-1;let n=1,r=t+1;for(;r<e.length;){let t=e.slice(r,r+2);if(t===`//`||t===`/*`){r=B(e,r);continue}let i=e[r]??``;if(i===`'`||i===`"`||i==="`"){let t=i;for(r++;r<e.length&&e[r]!==t;)e[r]===`\\`&&r++,r++;r<e.length&&r++;continue}if(i===`[`)n++;else if(i===`]`&&(n--,n===0))return r;r++}return-1}function V(e,t){if(e[t]!==`(`)return-1;let n=1,r=t+1;for(;r<e.length;){let t=e.slice(r,r+2);if(t===`//`||t===`/*`){r=B(e,r);continue}let i=e[r]??``;if(i===`'`||i===`"`||i==="`"){let t=i;for(r++;r<e.length&&e[r]!==t;)e[r]===`\\`&&r++,r++;r<e.length&&r++;continue}if(i===`(`)n++;else if(i===`)`&&(n--,n===0))return r;r++}return-1}async function ke(t){let{name:n,outDir:r}=t,i=D(n),a=T(n),o=[],s=m(r,`${i}.adapter.ts`);return await e(s,`import {
|
|
835
836
|
defineAdapter,
|
|
836
837
|
type AdapterContext,
|
|
837
838
|
type AdapterMiddleware,
|
|
@@ -1000,7 +1001,7 @@ export const ${a}Adapter = defineAdapter<${a}AdapterConfig>({
|
|
|
1000
1001
|
}
|
|
1001
1002
|
},
|
|
1002
1003
|
})
|
|
1003
|
-
`),o.push(s),o}const
|
|
1004
|
+
`),o.push(s),o}const Ae={controller:``,service:``,dto:`dtos`,guard:`guards`,middleware:`middleware`,contributor:`contributors`};function H(e){let{type:t,outDir:n,moduleName:r,modulesDir:i=`src/modules`,defaultDir:a,shouldPluralize:o=!0}=e;if(n)return g(n);if(r){let e=Ae,n=D(r),a=o?O(n):n,s=e[t]??``,c=m(i,a);return g(s?m(c,s):c)}return g(a)}async function je(t){let{name:n,moduleName:r,modulesDir:i,pattern:a}=t,o=H({type:`middleware`,outDir:t.outDir,moduleName:r,modulesDir:i,defaultDir:`src/middleware`,pattern:a,shouldPluralize:t.pluralize??!0}),s=D(n),c=E(n),l=[],u=m(o,`${s}.middleware.ts`);return await e(u,`import type { Request, Response, NextFunction } from 'express'
|
|
1004
1005
|
|
|
1005
1006
|
export interface ${T(n)}Options {
|
|
1006
1007
|
// Add configuration options here. The factory below closes over the
|
|
@@ -1050,7 +1051,7 @@ export function ${c}(options: ${T(n)}Options = {}) {
|
|
|
1050
1051
|
next()
|
|
1051
1052
|
}
|
|
1052
1053
|
}
|
|
1053
|
-
`),l.push(u),l}async function
|
|
1054
|
+
`),l.push(u),l}async function Me(t){let{name:n,moduleName:r,modulesDir:i,pattern:a}=t,o=H({type:`guard`,outDir:t.outDir,moduleName:r,modulesDir:i,defaultDir:`src/guards`,pattern:a,shouldPluralize:t.pluralize??!0}),s=D(n),c=E(n),l=T(n),u=[],d=m(o,`${s}.guard.ts`);return await e(d,`import { Container, HttpException } from '@forinda/kickjs'
|
|
1054
1055
|
import type { RequestContext } from '@forinda/kickjs'
|
|
1055
1056
|
|
|
1056
1057
|
/**
|
|
@@ -1086,7 +1087,7 @@ export async function ${c}Guard(ctx: RequestContext, next: () => void): Promise<
|
|
|
1086
1087
|
ctx.res.status(401).json({ message: 'Invalid or expired token' })
|
|
1087
1088
|
}
|
|
1088
1089
|
}
|
|
1089
|
-
`),u.push(d),u}async function
|
|
1090
|
+
`),u.push(d),u}async function Ne(t){let{name:n,moduleName:r,modulesDir:i,pattern:a}=t,o=H({type:`service`,outDir:t.outDir,moduleName:r,modulesDir:i,defaultDir:`src/services`,pattern:a,shouldPluralize:t.pluralize??!0}),s=D(n),c=T(n),l=[],u=m(o,`${s}.service.ts`);return await e(u,`import { Service } from '@forinda/kickjs'
|
|
1090
1091
|
|
|
1091
1092
|
@Service()
|
|
1092
1093
|
export class ${c}Service {
|
|
@@ -1095,7 +1096,7 @@ export class ${c}Service {
|
|
|
1095
1096
|
// @Inject(MY_REPO) private readonly repo: IMyRepository,
|
|
1096
1097
|
// ) {}
|
|
1097
1098
|
}
|
|
1098
|
-
`),l.push(u),l}async function
|
|
1099
|
+
`),l.push(u),l}async function Pe(t){let{name:n,moduleName:r,modulesDir:i,pattern:a}=t,o=H({type:`controller`,outDir:t.outDir,moduleName:r,modulesDir:i,defaultDir:`src/controllers`,pattern:a,shouldPluralize:t.pluralize??!0}),s=D(n),c=T(n),l=[],u=m(o,`${s}.controller.ts`);return await e(u,`import { Controller, Get, Post, type Ctx } from '@forinda/kickjs'
|
|
1099
1100
|
|
|
1100
1101
|
// \`Ctx<KickRoutes.${c}Controller['<method>']>\` is generated by
|
|
1101
1102
|
// \`kick typegen\` (auto-run on \`kick dev\`). After the first run, your IDE
|
|
@@ -1116,7 +1117,7 @@ export class ${c}Controller {
|
|
|
1116
1117
|
ctx.created({ message: '${c} created', data: ctx.body })
|
|
1117
1118
|
}
|
|
1118
1119
|
}
|
|
1119
|
-
`),l.push(u),l}async function
|
|
1120
|
+
`),l.push(u),l}async function Fe(t){let{name:n,moduleName:r,modulesDir:i,pattern:a}=t,o=H({type:`dto`,outDir:t.outDir,moduleName:r,modulesDir:i,defaultDir:`src/dtos`,pattern:a,shouldPluralize:t.pluralize??!0}),s=D(n),c=T(n),l=E(n),u=[],d=m(o,`${s}.dto.ts`);return await e(d,`import { z } from 'zod'
|
|
1120
1121
|
|
|
1121
1122
|
export const ${l}Schema = z.object({
|
|
1122
1123
|
// Define your schema fields here
|
|
@@ -1124,7 +1125,7 @@ export const ${l}Schema = z.object({
|
|
|
1124
1125
|
})
|
|
1125
1126
|
|
|
1126
1127
|
export type ${c}DTO = z.infer<typeof ${l}Schema>
|
|
1127
|
-
`),u.push(d),u}const
|
|
1128
|
+
`),u.push(d),u}const Ie={swagger:`@forinda/kickjs-swagger`,ws:`@forinda/kickjs-ws`,queue:`@forinda/kickjs-queue`,devtools:`@forinda/kickjs-devtools`},Le={zod:{name:`zod`,range:`^4.3.6`},valibot:{name:`valibot`,range:`^1.4.1`},yup:{name:`yup`,range:`^1.7.1`}};function U(e,t){let n=e[t];if(!n)throw Error(`generatePackageJson: missing resolved version for ${t}. Add it to SIBLING_PACKAGES in generators/project.ts.`);return n}function Re(e,t,n,r=[],i=`zod`,a=`express`){let o=Le[i],s={"@forinda/kickjs":U(n,`@forinda/kickjs`),"@forinda/kickjs-schema":U(n,`@forinda/kickjs-schema`),dotenv:`^17.3.1`,express:`^5.1.0`,"reflect-metadata":`^0.2.2`,[o.name]:o.range};a===`fastify`?(s.fastify=`^5.0.0`,s[`@fastify/middie`]=`^9.0.0`):a===`h3`&&(s.h3=`^1.0.0`);for(let e of r){let t=Ie[e];t&&!s[t]&&(s[t]=U(n,t))}return JSON.stringify({name:e,version:`0.0.0`,type:`module`,scripts:{dev:`kick dev`,"dev:debug":`kick dev:debug`,build:`kick build`,start:`kick start`,test:`vitest run`,"test:watch":`vitest`,typecheck:`tsc --noEmit`,typegen:`kick typegen`,lint:`eslint src/`,format:`prettier --write src/`},dependencies:s,devDependencies:{"@forinda/kickjs-cli":U(n,`@forinda/kickjs-cli`),"@forinda/kickjs-vite":U(n,`@forinda/kickjs-vite`),"@swc/core":`^1.15.21`,"@types/express":`^5.0.6`,"@types/node":`^25.0.0`,"unplugin-swc":`^1.5.9`,vite:`^8.0.3`,vitest:`^4.1.2`,typescript:`^6.0.3`,prettier:`^3.8.1`}},null,2)}function ze(){return`import { defineConfig } from 'vite'
|
|
1128
1129
|
import { resolve } from 'node:path'
|
|
1129
1130
|
import swc from 'unplugin-swc'
|
|
1130
1131
|
import { kickjsVitePlugin, envWatchPlugin } from '@forinda/kickjs-vite'
|
|
@@ -1154,7 +1155,7 @@ export default defineConfig({
|
|
|
1154
1155
|
},
|
|
1155
1156
|
},
|
|
1156
1157
|
})
|
|
1157
|
-
`}function
|
|
1158
|
+
`}function Be(){return JSON.stringify({compilerOptions:{target:`ES2022`,module:`ESNext`,moduleResolution:`bundler`,lib:[`ES2022`],types:[`node`,`vite/client`],strict:!0,esModuleInterop:!0,skipLibCheck:!0,sourceMap:!0,declaration:!0,experimentalDecorators:!0,emitDecoratorMetadata:!0,outDir:`dist`,paths:{"@/*":[`./src/*`]}},include:[`src`,`.kickjs/types/**/*.d.ts`,`.kickjs/types/**/*.ts`]},null,2)}function Ve(){return JSON.stringify({semi:!1,singleQuote:!0,trailingComma:`all`,printWidth:100,tabWidth:2},null,2)}function He(){return`# https://editorconfig.org
|
|
1158
1159
|
root = true
|
|
1159
1160
|
|
|
1160
1161
|
[*]
|
|
@@ -1167,14 +1168,14 @@ insert_final_newline = true
|
|
|
1167
1168
|
|
|
1168
1169
|
[*.md]
|
|
1169
1170
|
trim_trailing_whitespace = false
|
|
1170
|
-
`}function
|
|
1171
|
+
`}function Ue(){return`node_modules/
|
|
1171
1172
|
dist/
|
|
1172
1173
|
.env
|
|
1173
1174
|
coverage/
|
|
1174
1175
|
.DS_Store
|
|
1175
1176
|
*.tsbuildinfo
|
|
1176
1177
|
.kickjs/
|
|
1177
|
-
`}function
|
|
1178
|
+
`}function We(){return`# Auto-detect text files and normalise line endings to LF
|
|
1178
1179
|
* text=auto eol=lf
|
|
1179
1180
|
|
|
1180
1181
|
# Explicitly mark generated / binary files
|
|
@@ -1192,11 +1193,11 @@ coverage/
|
|
|
1192
1193
|
pnpm-lock.yaml -diff linguist-generated
|
|
1193
1194
|
yarn.lock -diff linguist-generated
|
|
1194
1195
|
package-lock.json -diff linguist-generated
|
|
1195
|
-
`}function
|
|
1196
|
+
`}function Ge(){return`PORT=3000
|
|
1196
1197
|
NODE_ENV=development
|
|
1197
|
-
`}function
|
|
1198
|
+
`}function Ke(){return`PORT=3000
|
|
1198
1199
|
NODE_ENV=development
|
|
1199
|
-
`}function
|
|
1200
|
+
`}function qe(){return`import { defineConfig } from 'vitest/config'
|
|
1200
1201
|
import swc from 'unplugin-swc'
|
|
1201
1202
|
|
|
1202
1203
|
export default defineConfig({
|
|
@@ -1207,15 +1208,22 @@ export default defineConfig({
|
|
|
1207
1208
|
include: ['src/**/*.test.ts'],
|
|
1208
1209
|
},
|
|
1209
1210
|
})
|
|
1210
|
-
`}const
|
|
1211
|
-
Dependencies installed successfully!`)}catch{console.log(`\n Warning: ${i} install failed. Run it manually.`)}}try{let{runTypegen:e}=await import(`./typegen-
|
|
1212
|
-
Project scaffolded successfully!`),console.log();let h=u!==process.cwd();d(`Next steps:`),h&&d(` cd ${n}`),t.installDeps||d(` ${i} install`);let g={rest:`kick g module user`,ddd:`kick g module user --repo drizzle`,cqrs:`kick g module user --pattern cqrs`,minimal:`# add your routes to src/index.ts`};d(` ${g[o]??g.rest}`),d(` kick dev`),d(``),d(`Commands:`),d(` kick dev Start dev server with Vite HMR`),d(` kick build Production build via Vite`),d(` kick start Run production build`),d(``),d(`Generators:`),d(` kick g module <name> Full DDD module (controller, DTOs, use-cases, repo)`),d(` kick g scaffold <n> <f..> CRUD module from field definitions`),d(` kick g controller <name> Standalone controller`),d(` kick g service <name> @Service() class`),d(` kick g middleware <name> Express middleware`),d(` kick g guard <name> Route guard (auth, roles, etc.)`),d(` kick g adapter <name> AppAdapter with lifecycle hooks`),d(` kick g dto <name> Zod DTO schema`),d(` kick g config Generate kick.config.ts`),d(``),d(`Add packages:`),d(` kick add <pkg> Install a KickJS package + peers`),d(` kick add --list Show all available packages`),d(``),d(`Available: auth, swagger, drizzle, prisma, ws, queue, devtools, mcp, testing`),d(``)}function Ye(e){let t=new Map;return{report(n,r){let i=r instanceof Error?r.message:String(r);t.get(n)!==i&&(t.set(n,i),e(` kick typegen: ${n} pass failed (${i}) — types in .kickjs/types may be stale`))},clear(e){t.delete(e)}}}const Xe=`__kickjs_typegen_owner`;function Ze(e){let{cwd:t,config:n}=e,r=e.debounceMs??100,i=e.pipeline??{runTypegen:async e=>(await import(`./typegen-BJwy65-p.mjs`).then(e=>e.n)).runTypegen(e),runAllPluginTypegens:async e=>(await import(`./run-plugins-CubT9x_A.mjs`)).runAllPluginTypegens(e),writeTypegenArtifacts:async(e,t,n)=>(await import(`./typegen-BJwy65-p.mjs`).then(e=>e.n)).writeTypegenArtifacts(e,t,n),buildAssets:async(e,t)=>(await import(`./build-D9X9QBkC.mjs`).then(e=>e.n)).buildAssets(e,t)},a=n?.typegen?.schemaValidator??`zod`,o=n?.typegen?.envFile,s=d.resolve(t,n?.typegen?.outDir??`.kickjs/types`),c=n?.assetMap?Object.values(n.assetMap).map(e=>e?.src).filter(e=>typeof e==`string`&&e.length>0).map(e=>d.resolve(t,e)):[],l=!!n?.assetMap&&Object.keys(n.assetMap).length>0,u=e=>e.replaceAll(`\\`,`/`),f=c.map(u),p=e=>{let t=u(e);return f.some(e=>t===e||t.startsWith(`${e}/`))},m=Ye(e.emitWarning),h=null,g=!1,_=new Set,v=new Set,y=!1,b=!1;function x(r,c){i.runTypegen({cwd:t,silent:!0,allowDuplicates:!0,schemaValidator:a,envFile:o,srcDir:n?.typegen?.srcDir,outDir:n?.typegen?.outDir,assetMap:n?.assetMap,changedFiles:r,runPlugins:!1}).then(()=>m.clear(`scan`)).catch(e=>m.report(`scan`,e)),i.runAllPluginTypegens({cwd:t,config:n,silent:!0,changedFiles:r}).then(e=>i.writeTypegenArtifacts(s,e,!0)).then(()=>m.clear(`plugins`)).catch(e=>m.report(`plugins`,e)).finally(()=>e.onPassComplete?.()),c&&n&&i.buildAssets(n,{cwd:t,silent:!0}).catch(()=>{})}function S(){let e=y?void 0:{changed:[..._],removed:[...v]},t=b;_.clear(),v.clear(),y=!1,b=!1,x(e,t)}return{assetSrcRoots:c,handleWatchEvent(e,t){if(!g&&!u(t).includes(`/.kickjs/`)){if(e===`unlinkDir`)y=!0,l&&(b=!0);else{if(t.endsWith(`.d.ts`))return;let n=/\.(ts|tsx|mts|cts)$/.test(t),r=p(t);if(!n&&!r)return;r&&l&&(b=!0),n&&(e===`unlink`?(v.add(t),_.delete(t)):(_.add(t),v.delete(t)))}h&&clearTimeout(h),h=setTimeout(S,r)}},runOnce(){g||x(void 0,l)},dispose(){g=!0,h&&clearTimeout(h),h=null}}}function Qe(e){return D(e).replace(/-/g,`_`)}function q(e){let t=e.cwd??process.cwd(),n=e.projectRoot??l(t),r=e.pluralize??!0,i=T(e.name),a=E(e.name),o=D(e.name),s=Qe(e.name),c={name:e.name,pascal:i,camel:a,kebab:o,snake:s,modulesDir:e.modulesDir??`src/modules`,cwd:t,projectRoot:n,args:e.args??[],flags:e.flags??{}};if(r){let e=O(o);c.pluralKebab=e,c.pluralPascal=T(e),c.pluralCamel=E(e)}return c}function $e(e,t){return h(e.cwd,t)}async function et(e){return import(te(e).href)}const J=new Map;async function Y(e){let t=J.get(e);if(t)return t;let n=tt(e);return J.set(e,n),n}async function tt(e){let t=h(e,`package.json`);if(!g(t))return{generators:[],loaded:[],failed:[]};let n=nt(JSON.parse(await b(t,`utf-8`))),r=u(h(e,`package.json`)),i=[],a=[],o=[];for(let e of n){let t;try{t=r.resolve(`${e}/package.json`)}catch{continue}let n;try{n=JSON.parse(await b(t,`utf-8`))}catch(t){o.push({source:e,reason:`failed to parse package.json: ${t}`});continue}if(!n.kickjs?.generators)continue;let s=n.kickjs.generators,c=h(f(t),s);if(!g(c)){o.push({source:e,reason:`kickjs.generators points to missing file: ${s}`});continue}let l;try{l=await et(c)}catch(t){o.push({source:e,reason:`failed to import manifest: ${t}`});continue}let u=l.default;if(!Array.isArray(u)){o.push({source:e,reason:`manifest's default export is not an array of GeneratorSpec`});continue}for(let t of u){if(!rt(t)){o.push({source:e,reason:`manifest entry is not a valid GeneratorSpec (missing name/files)`});continue}i.push({source:e,spec:t})}a.push(e)}return{generators:i,loaded:a,failed:o}}function nt(e){let t=new Set;for(let n of[e.dependencies,e.devDependencies,e.peerDependencies])if(n)for(let e of Object.keys(n))t.add(e);return Array.from(t)}function rt(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.name==`string`&&typeof t.files==`function`}async function it(e,t=[]){let n=e.cwd??process.cwd(),r=t.find(t=>t.spec.name===e.generatorName);if(r)return X(r.spec,r.source,e,n);let i=ot(await Y(n),e.generatorName);return i?X(i.spec,i.source,e,n):null}async function at(e,t=[]){let n=await Y(e),r=new Set(t.map(e=>e.spec.name)),i=n.generators.filter(e=>!r.has(e.spec.name));return{generators:[...t,...i],loaded:n.loaded,failed:n.failed}}function ot(e,t){return e.generators.find(e=>e.spec.name===t)}async function X(t,n,r,i){let a=q({name:r.itemName,args:r.args,flags:r.flags,modulesDir:r.modulesDir,pluralize:r.pluralize,cwd:i,projectRoot:r.projectRoot}),o=await t.files(a),s=[];for(let t of o){let n=$e(a,t.path);await e(n,t.content),s.push(n)}return{files:s,source:n}}function st(e){return e}function ct(e){return e}function Z(e){try{return JSON.parse(_(e,`utf-8`))}catch{return null}}function Q(e){try{return _(e,`utf-8`)}catch{return null}}function lt(e){let t=Q(p(e,`tsconfig.json`));if(!t)return null;let n=t.replace(/\/\*[\s\S]*?\*\//g,``).replace(/\/\/.*$/gm,``),r;try{r=JSON.parse(n)}catch{return null}if(typeof r?.extends==`string`){let t=ut(e,r.extends);if(t){let e=Z(t)??{};r.compilerOptions={...e.compilerOptions,...r.compilerOptions}}}return r}function ut(e,t){if(t.startsWith(`.`)){let n=h(e,t);return g(n)?n:null}let n=p(e,`node_modules`,t);return g(n)?n:null}function dt(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function ft(){let e=process.version,t=Number.parseInt(e.replace(/^v/,``).split(`.`)[0],10);return Number.isNaN(t)||t<20?{name:`Node version`,status:`fail`,message:e,fix:`KickJS requires Node 20 or newer.
|
|
1213
|
-
|
|
1211
|
+
`}const Je=p(te(import.meta.url)),W=JSON.parse(v(m(Je,`..`,`package.json`),`utf-8`)),Ye=`^${W.version}`,Xe=[`@forinda/kickjs`,`@forinda/kickjs-cli`,`@forinda/kickjs-schema`,`@forinda/kickjs-vite`,`@forinda/kickjs-swagger`,`@forinda/kickjs-ws`,`@forinda/kickjs-queue`,`@forinda/kickjs-devtools`,`@forinda/kickjs-testing`];async function Ze(){let e=await Promise.all(Xe.map(async e=>{try{let t=ee(`npm`,[`view`,e,`version`],{encoding:`utf-8`,timeout:5e3,stdio:[`ignore`,`pipe`,`ignore`]}).toString().trim();if(t&&/^\d+\.\d+\.\d+/.test(t))return[e,`^${t}`]}catch{}return[e,Ye]}));return Object.fromEntries(e)}async function Qe(t){let{name:n,directory:r,packageManager:i=`pnpm`,template:o=`rest`,defaultRepo:s=`inmemory`,packages:c=[],schemaLib:l=`zod`,runtime:u=`express`}=t,d=r,f=e=>console.log(` ${e}`);console.log(`\n Creating KickJS project: ${n}\n`),f(`Resolving package versions...`);let p=await Ze();await e(m(d,`package.json`),Re(n,o,p,c,l,u)),await e(m(d,`vite.config.ts`),ze()),await e(m(d,`tsconfig.json`),Be()),await e(m(d,`.prettierrc`),Ve()),await e(m(d,`.editorconfig`),He()),await e(m(d,`.gitignore`),Ue()),await e(m(d,`.gitattributes`),We()),await e(m(d,`.env`),Ge()),await e(m(d,`.env.example`),Ke()),await e(m(d,`src/config/index.ts`),ve(l)),await e(m(d,`src/index.ts`),ge(n,o,W.version,c,u)),await e(m(d,`src/modules/index.ts`),_e()),await e(m(d,`src/modules/hello/hello.service.ts`),ye()),await e(m(d,`src/modules/hello/hello.controller.ts`),be()),await e(m(d,`src/modules/hello/hello.module.ts`),xe()),await e(m(d,`kick.config.ts`),Se(o,s,i,u)),await e(m(d,`vitest.config.ts`),qe()),await e(m(d,`README.md`),a(n,o,i));let{generateAgentDocs:h}=await import(`./agent-docs-B65qHJup.mjs`).then(e=>e.t);if(await h({outDir:d,name:n,pm:i,template:o,only:`all`,force:!0}),t.installDeps){console.log(`\n Installing dependencies with ${i}...\n`);try{w(`${i} install`,{cwd:d,stdio:`inherit`}),console.log(`
|
|
1212
|
+
Dependencies installed successfully!`)}catch{console.log(`\n Warning: ${i} install failed. Run it manually.`)}}try{let{runTypegen:e}=await import(`./typegen-BaE5TxzH.mjs`).then(e=>e.n);await e({cwd:d,allowDuplicates:!0,silent:!0})}catch{}if(t.initGit)try{w(`git init`,{cwd:d,stdio:`pipe`}),w(`git branch -M main`,{cwd:d,stdio:`pipe`}),w(`git add -A`,{cwd:d,stdio:`pipe`}),w(`git commit -m "chore: initial commit from kick new"`,{cwd:d,stdio:`pipe`}),f(`Git repository initialized`)}catch{f(`Warning: git init failed (git may not be installed)`)}console.log(`
|
|
1213
|
+
Project scaffolded successfully!`),console.log();let g=d!==process.cwd();f(`Next steps:`),g&&f(` cd ${n}`),t.installDeps||f(` ${i} install`);let _={rest:`kick g module user`,ddd:`kick g module user --repo drizzle`,cqrs:`kick g module user --pattern cqrs`,minimal:`# add your routes to src/index.ts`};f(` ${_[o]??_.rest}`),f(` kick dev`),f(``),f(`Commands:`),f(` kick dev Start dev server with Vite HMR`),f(` kick build Production build via Vite`),f(` kick start Run production build`),f(``),f(`Generators:`),f(` kick g module <name> Full DDD module (controller, DTOs, use-cases, repo)`),f(` kick g scaffold <n> <f..> CRUD module from field definitions`),f(` kick g controller <name> Standalone controller`),f(` kick g service <name> @Service() class`),f(` kick g middleware <name> Express middleware`),f(` kick g guard <name> Route guard (auth, roles, etc.)`),f(` kick g adapter <name> AppAdapter with lifecycle hooks`),f(` kick g dto <name> Zod DTO schema`),f(` kick g config Generate kick.config.ts`),f(``),f(`Add packages:`),f(` kick add <pkg> Install a KickJS package + peers`),f(` kick add --list Show all available packages`),f(``),f(`Available: auth, swagger, drizzle, prisma, ws, queue, devtools, mcp, testing`),f(``)}function $e(e){let t=new Map;return{report(n,r){let i=r instanceof Error?r.message:String(r);t.get(n)!==i&&(t.set(n,i),e(` kick typegen: ${n} pass failed (${i}) — types in .kickjs/types may be stale`))},clear(e){t.delete(e)}}}const et=`__kickjs_typegen_owner`;function tt(e){let{cwd:t,config:n}=e,r=e.debounceMs??100,i=e.pipeline??{runTypegen:async e=>(await import(`./typegen-BaE5TxzH.mjs`).then(e=>e.n)).runTypegen(e),runAllPluginTypegens:async e=>(await import(`./run-plugins-DtHMyrXU.mjs`)).runAllPluginTypegens(e),writeTypegenArtifacts:async(e,t,n)=>(await import(`./typegen-BaE5TxzH.mjs`).then(e=>e.n)).writeTypegenArtifacts(e,t,n),buildAssets:async(e,t)=>(await import(`./build-C8B6v3iF.mjs`).then(e=>e.n)).buildAssets(e,t)},a=n?.typegen?.schemaValidator??`zod`,o=n?.typegen?.envFile,s=f.resolve(t,n?.typegen?.outDir??`.kickjs/types`),c=n?.assetMap?Object.values(n.assetMap).map(e=>e?.src).filter(e=>typeof e==`string`&&e.length>0).map(e=>f.resolve(t,e)):[],l=!!n?.assetMap&&Object.keys(n.assetMap).length>0,u=e=>e.replaceAll(`\\`,`/`),d=c.map(u),p=e=>{let t=u(e);return d.some(e=>t===e||t.startsWith(`${e}/`))},m=$e(e.emitWarning),h=null,g=!1,_=new Set,v=new Set,y=!1,b=!1;function x(r,c){i.runTypegen({cwd:t,silent:!0,allowDuplicates:!0,schemaValidator:a,envFile:o,srcDir:n?.typegen?.srcDir,outDir:n?.typegen?.outDir,assetMap:n?.assetMap,changedFiles:r,runPlugins:!1}).then(()=>m.clear(`scan`)).catch(e=>m.report(`scan`,e)),i.runAllPluginTypegens({cwd:t,config:n,silent:!0,changedFiles:r}).then(e=>i.writeTypegenArtifacts(s,e,!0)).then(()=>m.clear(`plugins`)).catch(e=>m.report(`plugins`,e)).finally(()=>e.onPassComplete?.()),c&&n&&i.buildAssets(n,{cwd:t,silent:!0}).catch(()=>{})}function S(){let e=y?void 0:{changed:[..._],removed:[...v]},t=b;_.clear(),v.clear(),y=!1,b=!1,x(e,t)}return{assetSrcRoots:c,handleWatchEvent(e,t){if(!g&&!u(t).includes(`/.kickjs/`)){if(e===`unlinkDir`)y=!0,l&&(b=!0);else{if(t.endsWith(`.d.ts`))return;let n=/\.(ts|tsx|mts|cts)$/.test(t),r=p(t);if(!n&&!r)return;r&&l&&(b=!0),n&&(e===`unlink`?(v.add(t),_.delete(t)):(_.add(t),v.delete(t)))}h&&clearTimeout(h),h=setTimeout(S,r)}},runOnce(){g||x(void 0,l)},dispose(){g=!0,h&&clearTimeout(h),h=null}}}function nt(e){return D(e).replace(/-/g,`_`)}function G(e){let t=e.cwd??process.cwd(),n=e.projectRoot??u(t),r=e.pluralize??!0,i=T(e.name),a=E(e.name),o=D(e.name),s=nt(e.name),c={name:e.name,pascal:i,camel:a,kebab:o,snake:s,modulesDir:e.modulesDir??`src/modules`,cwd:t,projectRoot:n,args:e.args??[],flags:e.flags??{}};if(r){let e=O(o);c.pluralKebab=e,c.pluralPascal=T(e),c.pluralCamel=E(e)}return c}function rt(e,t){return g(e.cwd,t)}async function it(e){return import(ne(e).href)}const K=new Map;async function q(e){let t=K.get(e);if(t)return t;let n=at(e);return K.set(e,n),n}async function at(e){let t=g(e,`package.json`);if(!_(t))return{generators:[],loaded:[],failed:[]};let n=ot(JSON.parse(await x(t,`utf-8`))),r=d(g(e,`package.json`)),i=[],a=[],o=[];for(let e of n){let t;try{t=r.resolve(`${e}/package.json`)}catch{continue}let n;try{n=JSON.parse(await x(t,`utf-8`))}catch(t){o.push({source:e,reason:`failed to parse package.json: ${t}`});continue}if(!n.kickjs?.generators)continue;let s=n.kickjs.generators,c=g(p(t),s);if(!_(c)){o.push({source:e,reason:`kickjs.generators points to missing file: ${s}`});continue}let l;try{l=await it(c)}catch(t){o.push({source:e,reason:`failed to import manifest: ${t}`});continue}let u=l.default;if(!Array.isArray(u)){o.push({source:e,reason:`manifest's default export is not an array of GeneratorSpec`});continue}for(let t of u){if(!st(t)){o.push({source:e,reason:`manifest entry is not a valid GeneratorSpec (missing name/files)`});continue}i.push({source:e,spec:t})}a.push(e)}return{generators:i,loaded:a,failed:o}}function ot(e){let t=new Set;for(let n of[e.dependencies,e.devDependencies,e.peerDependencies])if(n)for(let e of Object.keys(n))t.add(e);return Array.from(t)}function st(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.name==`string`&&typeof t.files==`function`}async function ct(e,t=[]){let n=e.cwd??process.cwd(),r=t.find(t=>t.spec.name===e.generatorName);if(r)return J(r.spec,r.source,e,n);let i=ut(await q(n),e.generatorName);return i?J(i.spec,i.source,e,n):null}async function lt(e,t=[]){let n=await q(e),r=new Set(t.map(e=>e.spec.name)),i=n.generators.filter(e=>!r.has(e.spec.name));return{generators:[...t,...i],loaded:n.loaded,failed:n.failed}}function ut(e,t){return e.generators.find(e=>e.spec.name===t)}async function J(t,n,r,i){let a=G({name:r.itemName,args:r.args,flags:r.flags,modulesDir:r.modulesDir,pluralize:r.pluralize,cwd:i,projectRoot:r.projectRoot}),o=await t.files(a),s=[];for(let t of o){let n=rt(a,t.path);await e(n,t.content),s.push(n)}return{files:s,source:n}}const Y={kickjs:{pkg:`@forinda/kickjs`,peers:[`express`],description:`Unified framework: DI, decorators, routing, middleware`,core:!0},vite:{pkg:`@forinda/kickjs-vite`,peers:[`vite`],description:`Vite plugin: dev server, HMR, module discovery`,dev:!0,core:!0},cli:{pkg:`@forinda/kickjs-cli`,peers:[],description:`CLI tool and code generators`,dev:!0,core:!0},zod:{pkg:`zod`,peers:[],description:`Zod schema validation (env, DTOs, OpenAPI) — wrap with fromZod()`},valibot:{pkg:`valibot`,peers:[],description:`Valibot schema validation — wrap with fromValibot()`},yup:{pkg:`yup`,peers:[],description:`Yup schema validation — wrap with fromYup()`},auth:{pkg:`@forinda/kickjs-auth`,peers:[`jsonwebtoken`],description:`JWT, API key, OAuth strategies, @Public, @Roles (+ optional argon2/bcryptjs)`,deprecated:`auth is moving to BYO — compose @LoadAuthUser/@RequireRole/@Public from defineContextDecorator (see the BYO Auth recipe in the docs)`},ai:{pkg:`@forinda/kickjs-ai`,peers:[`zod`],description:`AI toolkit — LLM providers, tool definitions from controllers`},swagger:{pkg:`@forinda/kickjs-swagger`,peers:[],description:`OpenAPI spec + Swagger UI + ReDoc`},db:{pkg:`@forinda/kickjs-db`,peers:[],description:`kick/db core — schema DSL, migrations, KickDbClient, customType`},pg:{pkg:`@forinda/kickjs-db`,peers:[`pg`],description:`kick/db + PostgreSQL driver (use @forinda/kickjs-db/pg)`},sqlite:{pkg:`@forinda/kickjs-db`,peers:[`better-sqlite3`],description:`kick/db + SQLite driver (use @forinda/kickjs-db/sqlite)`},mysql:{pkg:`@forinda/kickjs-db`,peers:[`mysql2`],description:`kick/db + MySQL driver (use @forinda/kickjs-db/mysql)`},drizzle:{pkg:`@forinda/kickjs-drizzle`,peers:[`drizzle-orm`],description:`Drizzle ORM adapter + query builder`,deprecated:"early-adoption adapter, no longer maintained — wire Drizzle directly (BYO), or use @forinda/kickjs-db, the built-in Kick ORM (`kick add db` / pg / sqlite / mysql)"},prisma:{pkg:`@forinda/kickjs-prisma`,peers:[`@prisma/client`],description:`Prisma adapter + query builder`,deprecated:"early-adoption adapter, no longer maintained — wire Prisma directly (BYO), or use @forinda/kickjs-db, the built-in Kick ORM (`kick add db` / pg / sqlite / mysql)"},ws:{pkg:`@forinda/kickjs-ws`,peers:[`ws`],description:`WebSocket with @WsController decorators`},devtools:{pkg:`@forinda/kickjs-devtools`,peers:[],description:`Development dashboard — routes, DI, metrics, health`,dev:!0},queue:{pkg:`@forinda/kickjs-queue`,peers:[],description:`Queue adapter (BullMQ/RabbitMQ/Kafka)`},"queue:bullmq":{pkg:`@forinda/kickjs-queue`,peers:[`bullmq`,`ioredis`],description:`Queue with BullMQ + Redis`},"queue:rabbitmq":{pkg:`@forinda/kickjs-queue`,peers:[`amqplib`],description:`Queue with RabbitMQ`},"queue:kafka":{pkg:`@forinda/kickjs-queue`,peers:[`kafkajs`],description:`Queue with Kafka`},"queue:redis-pubsub":{pkg:`@forinda/kickjs-queue`,peers:[`ioredis`],description:`Lightweight pub/sub via Redis (no persistence)`},mcp:{pkg:`@forinda/kickjs-mcp`,peers:[`@modelcontextprotocol/sdk`],description:`Model Context Protocol server — expose @Controller endpoints as AI tools`},testing:{pkg:`@forinda/kickjs-testing`,peers:[],description:`Test utilities and TestModule builder`,dev:!0}},X={express:{prod:`multer`,dev:`@types/multer`,note:`Express uploads use multer (memory/disk storage, ctx.file / ctx.files).`},fastify:{prod:`@fastify/multipart`,note:`Fastify uploads use @fastify/multipart (buffered into ctx.file / ctx.files).`},h3:{note:`h3 parses multipart natively (readMultipartFormData) — no driver to install.`}};async function Z(e=process.cwd()){let t=(await c(e))?.runtime;return t===`express`||t===`fastify`||t===`h3`?t:dt(e)}function dt(e=process.cwd()){let t=Q(`package.json`,e);if(t)try{let e=JSON.parse(v(g(t,`package.json`),`utf-8`)),n={...e.dependencies,...e.devDependencies};if(`fastify`in n)return`fastify`;if(`h3`in n)return`h3`}catch{}return`express`}function Q(e,t=process.cwd()){let n=t;for(;;){if(_(g(n,e)))return n;let t=p(n);if(t===n)return null;n=t}}function ft(){return Q(`pnpm-lock.yaml`)?`pnpm`:Q(`yarn.lock`)?`yarn`:Q(`bun.lockb`)||Q(`bun.lock`)?`bun`:Q(`package-lock.json`)?`npm`:null}function pt(){let e=process.cwd();for(;e;){let t=g(e,`package.json`);if(_(t))try{let e=JSON.parse(v(t,`utf-8`)).packageManager;if(typeof e==`string`){let t=e.split(`@`)[0];if(l.includes(t))return t}}catch{}let n=p(e);if(n===e)return null;e=n}return null}async function mt(e){if(e&&l.includes(e))return{pm:e,source:`flag`};let t=await c(process.cwd());if(t?.packageManager&&l.includes(t.packageManager))return{pm:t.packageManager,source:`config`};let n=pt();if(n)return{pm:n,source:`package.json`};let r=ft();return r?{pm:r,source:`lockfile`}:{pm:`npm`,source:`default`}}async function ht(e){let{pm:t}=await mt(e);return t}function gt(e=!1){let t=Object.entries(Y),n=Math.max(...t.map(([e])=>e.length)),r=t.filter(([,e])=>e.core),i=t.filter(([,e])=>!e.core),a=([e,t])=>{let r=e.padEnd(n+2),i=t.peers.length?` (+ ${t.peers.join(`, `)})`:``,a=t.deprecated?` [DEPRECATED — ${t.deprecated}]`:``;return` ${r} ${t.description}${i}${a}`};console.log(`
|
|
1214
|
+
Core packages (always installed by \`kick new\`):
|
|
1215
|
+
`);for(let e of r)console.log(a(e));if(e){console.log(`
|
|
1216
|
+
Optional packages (add as needed):
|
|
1217
|
+
`);for(let e of i)console.log(a(e))}else console.log(`\n Plus ${i.length} optional packages (auth, swagger, db, queue, …).`),console.log(" Run `kick add --list --all` for the full catalog.");console.log(`
|
|
1218
|
+
Usage: kick add ai db swagger`),console.log(` kick add queue:bullmq`),console.log(` kick add upload # installs the multipart driver for your runtime`),console.log()}function _t(e,t,n=`express`){let r=new Set,i=new Set,a=[],o=[],s=[];for(let c of e){if(c===`upload`){let e=X[n];s.push(`upload (${n}): ${e.note}`),e.prod&&(t?i:r).add(e.prod),e.dev&&i.add(e.dev);continue}let e=Y[c];if(!e){a.push(c);continue}e.deprecated&&o.push(`'${c}' (${e.pkg}) is deprecated — ${e.deprecated}`);let l=t||e.dev?i:r;l.add(e.pkg);for(let t of e.peers)l.add(t)}return{prodDeps:[...r],devDeps:[...i],unknown:a,warnings:o,notices:s}}function vt(e){e.command(`list`).alias(`ls`).description(`List KickJS packages (core only; pair with --all for the full catalog)`).option(`--all`,`Include the full optional catalog`).action(e=>{gt(!!e.all)})}function yt(e){e.command(`add [packages...]`).description(`Add KickJS packages with their required dependencies`).option(`--pm <manager>`,`Package manager override`).option(`-D, --dev`,`Install as dev dependency`).option(`--list`,`List packages (core only by default; pair with --all)`).option(`--all`,`When listing, include the full optional catalog`).action(async(e,t)=>{if(t.list||e.length===0){gt(!!t.all);return}let{pm:n,source:r}=await mt(t.pm);console.log(`\n Using ${n} (resolved from ${r})`);let i=await Z(process.cwd()),{prodDeps:a,devDeps:o,unknown:s,warnings:c,notices:l}=_t(e,!!t.dev,i);for(let e of c)console.warn(`\n WARNING: ${e}`);for(let e of l)console.log(`\n ${e}`);if(!(s.length>0&&(console.log(`\n Unknown packages: ${s.join(`, `)}`),console.log(` Run "kick add --list" to see available packages.
|
|
1219
|
+
`),a.length===0&&o.length===0))){if(a.length>0){let e=a,t=`${n} add ${e.join(` `)}`;console.log(`\n Installing ${e.length} dependency(ies):`);for(let t of e)console.log(` + ${t}`);console.log();try{w(t,{stdio:`inherit`})}catch{console.log(`\n Installation failed. Run manually:\n ${t}\n`)}}if(o.length>0){let e=o,t=`${n} add -D ${e.join(` `)}`;console.log(`\n Installing ${e.length} dev dependency(ies):`);for(let t of e)console.log(` + ${t} (dev)`);console.log();try{w(t,{stdio:`inherit`})}catch{console.log(`\n Installation failed. Run manually:\n ${t}\n`)}}console.log(` Done!
|
|
1220
|
+
`)}})}function bt(e){return e}function xt(e){return e}function St(e){try{return JSON.parse(v(e,`utf-8`))}catch{return null}}function $(e){try{return v(e,`utf-8`)}catch{return null}}function Ct(e){let t=$(m(e,`tsconfig.json`));if(!t)return null;let n=t.replace(/\/\*[\s\S]*?\*\//g,``).replace(/\/\/.*$/gm,``),r;try{r=JSON.parse(n)}catch{return null}if(typeof r?.extends==`string`){let t=wt(e,r.extends);if(t){let e=St(t)??{};r.compilerOptions={...e.compilerOptions,...r.compilerOptions}}}return r}function wt(e,t){if(t.startsWith(`.`)){let n=g(e,t);return _(n)?n:null}let n=m(e,`node_modules`,t);return _(n)?n:null}function Tt(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function Et(){let e=process.version,t=Number.parseInt(e.replace(/^v/,``).split(`.`)[0],10);return Number.isNaN(t)||t<20?{name:`Node version`,status:`fail`,message:e,fix:`KickJS requires Node 20 or newer.
|
|
1221
|
+
Install a supported version via nvm / fnm / volta.`}:{name:`Node version`,status:`pass`,message:e}}function Dt(e){if(!e.pkg)return{name:`@forinda/kickjs installed`,status:`warn`,message:`no package.json`};let t={...e.pkg.dependencies,...e.pkg.peerDependencies};return t[`@forinda/kickjs`]?{name:`@forinda/kickjs installed`,status:`pass`,message:t[`@forinda/kickjs`]}:{name:`@forinda/kickjs installed`,status:`fail`,fix:"This directory does not look like a KickJS project — `@forinda/kickjs` is not in your package.json. Run `kick doctor` from the project root, or scaffold a fresh project with `kick new <name>`."}}function Ot(e){if(!e.pkg)return null;let t={...e.pkg.dependencies,...e.pkg.peerDependencies};return t[`@forinda/kickjs`]&&!t.express?{name:`express installed`,status:`fail`,fix:"`@forinda/kickjs` declares `express` as a required peer dependency, but your package.json does not include it. Install: pnpm add express"}:t.express?{name:`express installed`,status:`pass`,message:t.express}:null}const kt={express:[],fastify:[`fastify`,`@fastify/middie`],h3:[`h3`]};function At(e){if(!e.pkg||e.runtime===`express`)return null;let t={...e.pkg.dependencies,...e.pkg.peerDependencies,...e.pkg.devDependencies},n=kt[e.runtime].filter(e=>!t[e]),r=`runtime engine (${e.runtime})`;return n.length>0?{name:r,status:`fail`,fix:`Resolved runtime '${e.runtime}' is missing engine peer(s): ${n.join(`, `)}.\nInstall: pnpm add ${n.join(` `)}`}:{name:r,status:`pass`}}function jt(e){if(!e.pkg||!Nt(e.cwd))return null;let t=X[e.runtime],n=`upload driver (${e.runtime})`;return t.prod?{...e.pkg.dependencies,...e.pkg.peerDependencies,...e.pkg.devDependencies}[t.prod]?{name:n,status:`pass`,message:t.prod}:{name:n,status:`fail`,fix:`This project uses file uploads on the '${e.runtime}' runtime, which needs '${t.prod}'.\nInstall it: kick add upload (or pnpm add ${t.prod})`}:{name:n,status:`pass`,message:`native multipart`}}const Mt=2e3;function Nt(e){let t=m(e,`src`);if(!_(t))return!1;let n=/@FileUpload\b|\bupload\.(single|array|none)\s*\(/,r=[t],i=0;for(;r.length>0&&i<Mt;){let e=r.pop(),t;try{t=y(e,{withFileTypes:!0})}catch{continue}for(let a of t){if(i>=Mt)break;let t=m(e,a.name);if(a.isDirectory()){a.name!==`node_modules`&&r.push(t);continue}if(/\.(ts|tsx|mts|cts)$/.test(a.name)&&(i++,n.test($(t)??``)))return!0}}return!1}function Pt(e){if(!e.pkg)return{name:`reflect-metadata installed`,status:`warn`,message:`no package.json`};let t={...e.pkg.dependencies,...e.pkg.peerDependencies,...e.pkg.devDependencies};return t[`reflect-metadata`]?{name:`reflect-metadata installed`,status:`pass`,message:t[`reflect-metadata`]}:{name:`reflect-metadata installed`,status:`fail`,fix:`KickJS decorators require the reflect-metadata polyfill.
|
|
1214
1222
|
Install it: pnpm add reflect-metadata
|
|
1215
1223
|
Then import it at the top of src/index.ts:
|
|
1216
1224
|
|
|
1217
1225
|
import 'reflect-metadata'
|
|
1218
|
-
// ... rest of bootstrap`}}function
|
|
1226
|
+
// ... rest of bootstrap`}}function Ft(e){if(!e.tsconfig)return[{name:`tsconfig.json present`,status:`fail`,fix:"Create a tsconfig.json with `experimentalDecorators: true` and `emitDecoratorMetadata: true`. `kick new` scaffolds one automatically."}];let t=e.tsconfig.compilerOptions??{},n=[];return n.push(t.experimentalDecorators===!0?{name:`tsconfig: experimentalDecorators`,status:`pass`}:{name:`tsconfig: experimentalDecorators`,status:`fail`,fix:'Add `"experimentalDecorators": true` to compilerOptions in tsconfig.json. Without it, @Service / @Controller / @Get etc. don\'t register any metadata at compile time.'}),n.push(t.emitDecoratorMetadata===!0?{name:`tsconfig: emitDecoratorMetadata`,status:`pass`}:{name:`tsconfig: emitDecoratorMetadata`,status:`fail`,fix:'Add `"emitDecoratorMetadata": true` to compilerOptions in tsconfig.json. The DI container uses this metadata for constructor-parameter injection.'}),n}function It(e){let t=[`src/env.ts`,`src/env/index.ts`,`src/config/env.ts`,`src/config/index.ts`].map(t=>m(e.cwd,t)).filter(e=>_(e)).filter(e=>/\bloadEnv\s*\(/.test($(e)??``));if(t.length===0)return null;let n=[`src/index.ts`,`src/main.ts`].map(t=>m(e.cwd,t)).find(e=>_(e));if(!n)return{name:`env wiring`,status:`warn`,message:`env-init file exists but no src/index.ts or src/main.ts found`};let r=$(n)??``,i=p(n),a=[];for(let e of t){let t=h(i,e).replace(/\\/g,`/`).replace(/\.ts$/,``),n=t.startsWith(`.`)?t:`./`+t,r=n.replace(/\/index$/,``);a.push(n,r);let o=e.replace(/\\/g,`/`).match(/\/src\/(.+?)(?:\.ts)?$/);if(o){let e=`@/`+o[1],t=e.replace(/\/index$/,``);a.push(e,t)}}let o=-1;for(let e of new Set(a)){let t=RegExp(`^import\\s+(?:.*?from\\s+)?['"]${Tt(e)}['"]`,`m`),n=r.match(t);n&&n.index!==void 0&&(o===-1||n.index<o)&&(o=n.index)}let s=r.search(/\bbootstrap\s*\(/),c=t.map(t=>h(e.cwd,t).replace(/\\/g,`/`)).join(`, `);return o===-1?{name:`env wiring`,status:`fail`,message:c,fix:`An env-init file (${c}) calls \`loadEnv(...)\` but \`${h(e.cwd,n).replace(/\\/g,`/`)}\` doesn't import it.\nWithout this, ConfigService.get('X') returns undefined while @Value('X') works via process.env fallback — a half-broken config you won't notice until something is missing.\n\nFix: add a side-effect import at the top of ${h(e.cwd,n).replace(/\\/g,`/`)} (above bootstrap()), pointing at one of the detected files. For example:\n\n import './env'\n // or\n import './config'\n // or, with the @/ alias:\n import '@/config/env'`}:s!==-1&&o>s?{name:`env wiring`,status:`warn`,message:`env-init imported AFTER bootstrap() — should be before`,fix:`Move the env import above the bootstrap() call so the schema runs before any service reads from ConfigService.`}:{name:`env wiring`,status:`pass`}}function Lt(e,t=Rt){let n=0,r=0,i=[e];for(;i.length>0&&r<t;){let e=i.pop(),a;try{a=y(e,{withFileTypes:!0})}catch{continue}for(let o of a){if(r>=t)break;r++;let a=m(e,o.name);if(o.isDirectory()){i.push(a);continue}try{let e=b(a).mtimeMs;e>n&&(n=e)}catch{}}}return n}const Rt=2e3;function zt(e){let t=m(e.cwd,`.kickjs`,`types`);if(!_(t))return null;let n=Lt(t);if(n===0)return null;let r=Date.now()-n,i=Math.floor(r/6e4);return i>60?{name:`typegen freshness`,status:`warn`,message:`last updated ${i} minutes ago`,fix:"Re-run `kick typegen` (or `kick dev`, which runs it on every reload) so generated types match the current code."}:{name:`typegen freshness`,status:`pass`,message:i===0?`just now`:`${i}m ago`}}const Bt=[()=>Et(),Dt,Ot,At,jt,Pt,Ft,It,zt];async function Vt(e,t={}){let n={cwd:e,pkg:St(m(e,`package.json`)),tsconfig:Ct(e),runtime:t.runtime??`express`},r=[...Bt,...t.extraChecks??[]],i=[];for(let e of r){let t;try{t=await e(n)}catch(t){i.push({name:e.name||`doctor check`,status:`fail`,message:t instanceof Error?t.message:String(t)});continue}t!=null&&(Array.isArray(t)?i.push(...t):i.push(t))}return i}function Ht(e){switch(e){case`pass`:return r.green(`✔`);case`warn`:return r.yellow(`⚠`);case`fail`:return r.red(`✖`)}}function Ut(e){let t=Ht(e.status),n=e.message?` ${r.dim(`(${e.message})`)}`:``;return`${t} ${e.name}${n}`}function Wt(e){return e.split(`
|
|
1219
1227
|
`).map(e=>` ${r.dim(`→`)} ${e}`).join(`
|
|
1220
|
-
`)}function
|
|
1221
|
-
//# sourceMappingURL=doctor-
|
|
1228
|
+
`)}function Gt(e){return e?.doctor?.checks??[]}function Kt(e){e.command(`doctor`).description(`Pre-flight checks for your KickJS project (dev environment health)`).action(async()=>{let e=process.cwd(),a=Gt(await c(e)),o=await Z(e);t(`KickJS Doctor`);let s=await Vt(e,{extraChecks:a,runtime:o});for(let e of s)i.message(Ut(e)),e.fix&&e.status!==`pass`&&i.message(Wt(e.fix));let l=s.filter(e=>e.status===`pass`).length,u=s.filter(e=>e.status===`warn`).length,d=s.filter(e=>e.status===`fail`).length,f=[r.green(`${l} passed`),u>0?r.yellow(`${u} warning${u===1?``:`s`}`):`${u} warnings`,d>0?r.red(`${d} error${d===1?``:`s`}`):`${d} errors`].join(`, `);d>0?(n(`${f} — fix the errors above before running the app`),process.exit(1)):n(u>0?`${f} — review the warnings`:r.green(`${f} — your environment looks good`))})}export{P as A,z as C,pe as D,me as E,k as F,E as I,D as L,M,A as N,I as O,O as P,T as R,L as S,Te as T,Ne as _,yt as a,H as b,lt as c,re as d,et as f,Pe as g,Fe as h,Y as i,N as j,F as k,ct as l,Qe as m,bt as n,vt as o,tt as p,Kt as r,ht as s,xt as t,G as u,Me as v,Ee as w,ke as x,je as y};
|
|
1229
|
+
//# sourceMappingURL=doctor-Da_WPc4H.mjs.map
|