@forinda/kickjs-cli 6.0.1 → 6.1.1

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.
Files changed (33) hide show
  1. package/README.md +1 -1
  2. package/dist/{agent-docs-hbOXsAAh.mjs → agent-docs-GpRHHdWC.mjs} +3 -3
  3. package/dist/{agent-docs-hbOXsAAh.mjs.map → agent-docs-GpRHHdWC.mjs.map} +1 -1
  4. package/dist/build-D9X9QBkC.mjs +13 -0
  5. package/dist/build-D9X9QBkC.mjs.map +1 -0
  6. package/dist/{builtins-Dyk9a-mv.mjs → builtins-DHcybuaw.mjs} +2 -2
  7. package/dist/cli.mjs +143 -151
  8. package/dist/{config-DSpcRefL.mjs → config-DLy6JCCy.mjs} +3 -3
  9. package/dist/config-DLy6JCCy.mjs.map +1 -0
  10. package/dist/{doctor-559QZlHi.mjs → doctor-CcVNNzGj.mjs} +41 -41
  11. package/dist/doctor-CcVNNzGj.mjs.map +1 -0
  12. package/dist/index.d.mts +287 -1
  13. package/dist/index.d.mts.map +1 -1
  14. package/dist/index.mjs +2 -2
  15. package/dist/index.mjs.map +1 -1
  16. package/dist/{plugin-DK01q7wy.mjs → plugin-C6jhcq0N.mjs} +3 -3
  17. package/dist/{plugin-DK01q7wy.mjs.map → plugin-C6jhcq0N.mjs.map} +1 -1
  18. package/dist/{project-docs-CrfNQIZA.mjs → project-docs-CqOymvmb.mjs} +2 -2
  19. package/dist/{project-docs-CrfNQIZA.mjs.map → project-docs-CqOymvmb.mjs.map} +1 -1
  20. package/dist/{project-root-BdTe6EpE.mjs → project-root-yLxS5CqO.mjs} +3 -3
  21. package/dist/{project-root-BdTe6EpE.mjs.map → project-root-yLxS5CqO.mjs.map} +1 -1
  22. package/dist/{rolldown-runtime-CoN4EDcd.mjs → rolldown-runtime-BnMWUWuC.mjs} +1 -1
  23. package/dist/{run-plugins-BAYoDnFI.mjs → run-plugins-CubT9x_A.mjs} +73 -82
  24. package/dist/run-plugins-CubT9x_A.mjs.map +1 -0
  25. package/dist/typegen-BJwy65-p.mjs +114 -0
  26. package/dist/typegen-BJwy65-p.mjs.map +1 -0
  27. package/dist/{types-BKKzf_bU.mjs → types-D7d_Y66D.mjs} +1 -1
  28. package/package.json +8 -8
  29. package/dist/config-DSpcRefL.mjs.map +0 -1
  30. package/dist/doctor-559QZlHi.mjs.map +0 -1
  31. package/dist/run-plugins-BAYoDnFI.mjs.map +0 -1
  32. package/dist/typegen-CwtvFZ0t.mjs +0 -114
  33. package/dist/typegen-CwtvFZ0t.mjs.map +0 -1
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs-cli v6.0.1
2
+ * @forinda/kickjs-cli v6.1.1
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,6 +8,6 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import{t as e}from"./rolldown-runtime-CoN4EDcd.mjs";import{isAbsolute as t,join as n,relative as r,resolve as i}from"node:path";import{existsSync as a,mkdirSync as o,readFileSync as s,writeFileSync as c}from"node:fs";import{access as l,readFile as u}from"node:fs/promises";var d=e({BUILTIN_REPO_TYPES:()=>p,DEPRECATED_REPO_TYPES:()=>m,PACKAGE_MANAGERS:()=>f,defineConfig:()=>g,loadKickConfig:()=>x,resolveModuleConfig:()=>y,resolveTokenScope:()=>_,validateAssetMap:()=>C,warnIfDeprecatedRepo:()=>h,writeAssetConfigSnapshot:()=>S});const f=[`pnpm`,`npm`,`yarn`,`bun`],p=[`inmemory`],m=[`prisma`,`drizzle`];function h(e){return m.includes(e)?(console.warn(` Note: the '${e}' repository preset is deprecated. Generating a generic custom repository named '${e}' instead — wire it to your DB by hand. Pass any name via \`--repo <name>\` or \`modules.repo: { name: '<name>' }\`.`),!0):!1}function g(e){return e}function _(e,t){if(e?.tokenScope&&typeof e.tokenScope==`string`&&e.tokenScope.length>0){let t=v(e.tokenScope);if(t.length>0)return t}try{let e=n(t,`package.json`);if(a(e)){let t=JSON.parse(s(e,`utf-8`));if(typeof t.name==`string`&&t.name.length>0){let e=t.name.match(/^@([^/]+)\//),n=v(e?e[1]:t.name);if(n.length>0)return n}}}catch{}return`app`}function v(e){return e.toLowerCase().replace(/[^a-z0-9-]/g,`-`).replace(/^-+|-+$/g,``).replace(/-{2,}/g,`-`)}function y(e){if(!e)return{};let t={dir:e.modules?.dir,repo:e.modules?.repo,schemaDir:e.modules?.schemaDir,pluralize:e.modules?.pluralize,prismaClientPath:e.modules?.prismaClientPath,style:e.modules?.style};return t.style!==void 0&&t.style!==`define`&&t.style!==`class`&&(console.warn(` Warning: modules.style '${t.style}' is not a valid value (expected 'define' or 'class'). Falling back to 'define'.`),t.style=`define`),t.repo&&typeof t.repo==`string`&&!p.includes(t.repo)&&(h(t.repo)||console.warn(` Warning: modules.repo '${t.repo}' is not a built-in type (${p.join(`, `)}). It will generate a stub repository. Use { name: '${t.repo}' } to silence this warning.`)),t}const b=[`kick.config.ts`,`kick.config.js`,`kick.config.mjs`,`kick.config.json`];async function x(e){let{findProjectRoot:t}=await import(`./project-root-BdTe6EpE.mjs`).then(e=>e.n),r=t(e);for(let e of b){let t=n(r,e);try{await l(t)}catch{continue}if(e.endsWith(`.json`)){let e=await u(t,`utf-8`);return JSON.parse(e)}if(e.endsWith(`.ts`)){let n;try{n=await import(`jiti`)}catch(t){let n=t instanceof Error?t.message:String(t);n.includes(`Cannot find package 'jiti'`)||n.includes(`ERR_MODULE_NOT_FOUND`)?console.warn(`Warning: Failed to load ${e} — 'jiti' is required for TypeScript configs. Run \`pnpm add -D jiti\` (or your package manager's equivalent), or rename the file to kick.config.js / kick.config.mjs / kick.config.json.`):console.warn(`Warning: Failed to initialize jiti for ${e}: ${n}`);continue}try{let e=await n.createJiti(r,{interopDefault:!0,fsCache:!1}).import(t,{default:!0}),i=C(e,r);for(let e of i)console.warn(` Warning: ${e}`);return S(r,e),e}catch(t){let n=t instanceof Error?t.message:String(t);console.warn(`Warning: Failed to load ${e}: ${n}`);continue}}try{let{pathToFileURL:e}=await import(`node:url`),n=await import(e(t).href),i=n.default??n,a=C(i,r);for(let e of a)console.warn(` Warning: ${e}`);return S(r,i),i}catch(t){let n=t instanceof Error?t.message:String(t);console.warn(`Warning: Failed to load ${e}: ${n}`);continue}}return null}function S(e,t){if(!(!t?.assetMap||Object.keys(t.assetMap).length===0))try{let r=n(e,`.kickjs`);o(r,{recursive:!0});let i={version:1,assetMap:t.assetMap,...t.build?.outDir?{build:{outDir:t.build.outDir}}:{}};c(n(r,`kick.config.json`),JSON.stringify(i,null,2)+`
11
+ import{t as e}from"./rolldown-runtime-BnMWUWuC.mjs";import{isAbsolute as t,join as n,relative as r,resolve as i}from"node:path";import{existsSync as a,mkdirSync as o,readFileSync as s,writeFileSync as c}from"node:fs";import{access as l,readFile as u}from"node:fs/promises";var d=e({BUILTIN_REPO_TYPES:()=>p,DEPRECATED_REPO_TYPES:()=>m,PACKAGE_MANAGERS:()=>f,defineConfig:()=>g,loadKickConfig:()=>x,resolveModuleConfig:()=>y,resolveTokenScope:()=>_,validateAssetMap:()=>C,warnIfDeprecatedRepo:()=>h,writeAssetConfigSnapshot:()=>S});const f=[`pnpm`,`npm`,`yarn`,`bun`],p=[`inmemory`],m=[`prisma`,`drizzle`];function h(e){return m.includes(e)?(console.warn(` Note: the '${e}' repository preset is deprecated. Generating a generic custom repository named '${e}' instead — wire it to your DB by hand. Pass any name via \`--repo <name>\` or \`modules.repo: { name: '<name>' }\`.`),!0):!1}function g(e){return e}function _(e,t){if(e?.tokenScope&&typeof e.tokenScope==`string`&&e.tokenScope.length>0){let t=v(e.tokenScope);if(t.length>0)return t}try{let e=n(t,`package.json`);if(a(e)){let t=JSON.parse(s(e,`utf-8`));if(typeof t.name==`string`&&t.name.length>0){let e=t.name.match(/^@([^/]+)\//),n=v(e?e[1]:t.name);if(n.length>0)return n}}}catch{}return`app`}function v(e){return e.toLowerCase().replace(/[^a-z0-9-]/g,`-`).replace(/^-+|-+$/g,``).replace(/-{2,}/g,`-`)}function y(e){if(!e)return{};let t={dir:e.modules?.dir,repo:e.modules?.repo,schemaDir:e.modules?.schemaDir,pluralize:e.modules?.pluralize,prismaClientPath:e.modules?.prismaClientPath,style:e.modules?.style};return t.style!==void 0&&t.style!==`define`&&t.style!==`class`&&(console.warn(` Warning: modules.style '${t.style}' is not a valid value (expected 'define' or 'class'). Falling back to 'define'.`),t.style=`define`),t.repo&&typeof t.repo==`string`&&!p.includes(t.repo)&&(h(t.repo)||console.warn(` Warning: modules.repo '${t.repo}' is not a built-in type (${p.join(`, `)}). It will generate a stub repository. Use { name: '${t.repo}' } to silence this warning.`)),t}const b=[`kick.config.ts`,`kick.config.js`,`kick.config.mjs`,`kick.config.json`];async function x(e){let{findProjectRoot:t}=await import(`./project-root-yLxS5CqO.mjs`).then(e=>e.n),r=t(e);for(let e of b){let t=n(r,e);try{await l(t)}catch{continue}if(e.endsWith(`.json`)){let e=await u(t,`utf-8`);return JSON.parse(e)}if(e.endsWith(`.ts`)){let n;try{n=await import(`jiti`)}catch(t){let n=t instanceof Error?t.message:String(t);n.includes(`Cannot find package 'jiti'`)||n.includes(`ERR_MODULE_NOT_FOUND`)?console.warn(`Warning: Failed to load ${e} — 'jiti' is required for TypeScript configs. Run \`pnpm add -D jiti\` (or your package manager's equivalent), or rename the file to kick.config.js / kick.config.mjs / kick.config.json.`):console.warn(`Warning: Failed to initialize jiti for ${e}: ${n}`);continue}try{let e=await n.createJiti(r,{interopDefault:!0,fsCache:!1}).import(t,{default:!0}),i=C(e,r);for(let e of i)console.warn(` Warning: ${e}`);return S(r,e),e}catch(t){let n=t instanceof Error?t.message:String(t);console.warn(`Warning: Failed to load ${e}: ${n}`);continue}}try{let{pathToFileURL:e}=await import(`node:url`),n=await import(e(t).href),i=n.default??n,a=C(i,r);for(let e of a)console.warn(` Warning: ${e}`);return S(r,i),i}catch(t){let n=t instanceof Error?t.message:String(t);console.warn(`Warning: Failed to load ${e}: ${n}`);continue}}return null}function S(e,t){if(!(!t?.assetMap||Object.keys(t.assetMap).length===0))try{let r=n(e,`.kickjs`);o(r,{recursive:!0});let i={version:1,assetMap:t.assetMap,...t.build?.outDir?{build:{outDir:t.build.outDir}}:{}};c(n(r,`kick.config.json`),JSON.stringify(i,null,2)+`
12
12
  `,`utf-8`)}catch{}}function C(e,t){let n=[];if(!e?.assetMap)return n;let r=i(t);for(let[o,s]of Object.entries(e.assetMap)){if(!o||o.includes(`/`)){n.push(`assetMap key '${o}' is invalid — must be a non-empty string without '/'`);continue}if(typeof s?.src!=`string`||s.src.length===0){n.push(`assetMap.${o} is missing a non-empty 'src' field`);continue}a(i(t,s.src))||n.push(`assetMap.${o}.src ('${s.src}') does not exist — typegen + build will fail`),s.dest&&w(i(t,s.dest),r)&&n.push(`assetMap.${o}.dest ('${s.dest}') resolves outside the project root — refusing to copy`)}return n}function w(e,n){let i=r(n,e);return i===``?!1:i.startsWith(`..`)||t(i)}export{y as a,x as i,d as n,_ as o,g as r,h as s,f as t};
13
- //# sourceMappingURL=config-DSpcRefL.mjs.map
13
+ //# sourceMappingURL=config-DLy6JCCy.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-DLy6JCCy.mjs","names":[],"sources":["../src/config.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { readFile, access } from 'node:fs/promises'\nimport { isAbsolute, join, relative, resolve } from 'node:path'\n\nimport type { KickCliPlugin } from './plugin/types'\n\n/** A custom command that developers can register via kick.config.ts */\nexport interface KickCommandDefinition {\n /** The command name (e.g. 'db:migrate', 'seed', 'proto:gen') */\n name: string\n /** Description shown in --help */\n description: string\n /**\n * Shell command(s) to run. Can be a single string or an array of\n * sequential steps. Use {args} as a placeholder for CLI arguments.\n *\n * @example\n * 'npx drizzle-kit migrate'\n * ['npx drizzle-kit generate', 'npx drizzle-kit migrate']\n */\n steps: string | string[]\n /** Optional aliases (e.g. ['migrate'] for 'db:migrate') */\n aliases?: string[]\n}\n\n/** Project pattern — controls what generators produce and which deps are installed */\nexport type ProjectPattern = 'rest' | 'minimal'\n\n/** Package manager used for `kick add` and other dep-installing commands */\nexport type PackageManager = 'pnpm' | 'npm' | 'yarn' | 'bun'\n\nexport const PACKAGE_MANAGERS: readonly PackageManager[] = ['pnpm', 'npm', 'yarn', 'bun']\n\n/**\n * Built-in repository type with first-class code generation support.\n *\n * Only `inmemory` remains built-in (zero-dep, framework-owned). The\n * `prisma` and `drizzle` ORM presets are **deprecated** — they now\n * scaffold a generic custom-repository stub like any other name (see\n * {@link DEPRECATED_REPO_TYPES}). Bring your own DB by passing a name:\n * `repo: { name: 'postgres' }`.\n */\nexport type BuiltinRepoType = 'inmemory'\n\nexport const BUILTIN_REPO_TYPES: readonly string[] = ['inmemory']\n\n/**\n * Repo names that used to have dedicated ORM generators. They still\n * work — they just produce the same generic stub every other custom\n * name does — but the CLI prints a one-line deprecation note.\n */\nexport const DEPRECATED_REPO_TYPES: readonly string[] = ['prisma', 'drizzle']\n\n/**\n * Print a deprecation note when a generator is asked for a\n * `prisma`/`drizzle` repo. No-op for every other name. Returns whether\n * a note was printed (handy for tests).\n */\nexport function warnIfDeprecatedRepo(repo: string): boolean {\n if (!DEPRECATED_REPO_TYPES.includes(repo)) return false\n console.warn(\n ` Note: the '${repo}' repository preset is deprecated. Generating a generic ` +\n `custom repository named '${repo}' instead — wire it to your DB by hand. ` +\n `Pass any name via \\`--repo <name>\\` or \\`modules.repo: { name: '<name>' }\\`.`,\n )\n return true\n}\n\n/** Custom repository type — generates a stub with TODO markers */\nexport interface CustomRepoType {\n name: string\n}\n\n/** Repository type — built-in string or custom object */\nexport type RepoTypeConfig = BuiltinRepoType | CustomRepoType\n\n/**\n * Supported schema validators for `kick typegen` body/query/params\n * type extraction.\n *\n * - `'zod'` — emits `import('zod').infer<typeof schema>` (default)\n * - `'kickjs-schema'` — emits `InferSchemaOutput<typeof schema>` from\n * `@forinda/kickjs-schema`, works with Zod, Valibot, Yup, and any\n * Standard Schema v1 or KickSchema adapter\n * - `false` — disables schema-driven body typing (fields stay `unknown`)\n */\nexport type SchemaValidator = 'zod' | 'kickjs-schema' | false\n\n/**\n * One entry in the typed `assetMap` config record (`assets-plan.md`).\n * Each entry names a source directory whose files become addressable\n * via the `assets.<name>.*` typed accessor at runtime.\n */\nexport interface AssetMapEntry {\n /**\n * Source directory, relative to project root. Required. The directory\n * must exist when `kick build` runs — `loadKickConfig` warns when an\n * entry points at a missing directory but doesn't fail the load\n * (the typegen + build steps surface the error in context instead).\n */\n src: string\n /**\n * Destination directory inside `dist/`. Defaults to `dist/<name>/`\n * where `<name>` is the assetMap key. Override when the consumer of\n * the assets expects a non-standard layout (e.g. an existing\n * downstream tool reads from `dist/templates/...`).\n */\n dest?: string\n /**\n * Glob pattern for which files to include. Defaults to `**\\/*` (all\n * files). Files that don't match are NOT copied — `assetMap` is\n * selective by design (unlike `copyDirs` which copies everything).\n */\n glob?: string\n /**\n * How file extensions feed into manifest keys. Default `'auto'`.\n *\n * - `'strip'` — drop the extension. `pages/index.pug` →\n * `'pages/index'`. Two siblings with the same basename collide;\n * last-walk-order wins, others are silently dropped. Opt-in\n * only — kept for backward compatibility with projects that\n * relied on this contract.\n * - `'with-extension'` — keep every extension on every key. Best\n * when the namespace holds extension siblings (`index.pug` +\n * `index.html` + `index.css` in `src/pages/`); every file\n * reaches the manifest under its full path.\n * - `'auto'` — strip when basenames are unique, keep extensions\n * on collision groups. Singleton files keep their short key;\n * `pages/index.{pug,html,css}` becomes\n * `pages/index.pug` / `pages/index.html` / `pages/index.css`.\n * No data loss; non-colliding namespaces stay on the short\n * keys they had before.\n *\n * @default 'auto'\n */\n keys?: 'auto' | 'strip' | 'with-extension'\n}\n\n/**\n * Database settings consumed by `kick db generate`, `kick db migrate`,\n * and the M4.C composite-type detection gate. Mirrors the runtime\n * `DbConfig` shape from `@forinda/kickjs-db` — duplicated here so\n * adopters who only install `@forinda/kickjs-cli` can set the block\n * without pulling `@forinda/kickjs-db` types into their kick.config.ts\n * resolution. The CLI loads kick.config.ts through `loadKickConfig`,\n * then `resolveDbConfig` re-reads this block from the same module and\n * normalises defaults (`schemaPath` / `migrationsDir` / `dialect`).\n *\n * @example\n * ```ts\n * defineConfig({\n * db: {\n * schemaPath: 'src/db/schema.ts',\n * migrationsDir: 'db/migrations',\n * dialect: 'postgres',\n * connectionString: process.env.DATABASE_URL,\n * },\n * })\n * ```\n */\nexport interface KickDbConfigBlock {\n /**\n * Path to the schema module (`pgEnum` / `table` declarations).\n * Defaults to `'src/db/schema.ts'`.\n */\n schemaPath?: string\n /**\n * Where `kick db generate` writes migration directories. Defaults\n * to `'db/migrations'`.\n */\n migrationsDir?: string\n /** SQL dialect. Defaults to `'postgres'`. */\n dialect?: 'postgres' | 'sqlite' | 'mysql'\n /**\n * Postgres connection string for the built-in pgAdapter path. Read\n * from the `DATABASE_URL` env var when omitted. Used by\n * `kick db migrate*` and the M4.C composite-type gate at\n * `kick db generate`.\n */\n connectionString?: string\n /**\n * Escape hatch: a factory returning a fully-constructed\n * MigrationAdapter (typed loosely here so the CLI types don't pull\n * `@forinda/kickjs-db` into adopter projects that don't import it).\n * Takes precedence over `connectionString` when both are set.\n */\n adapter?: () => unknown | Promise<unknown>\n}\n\n/** Typegen settings — controls .kickjs/types/* generation */\nexport interface TypegenConfig {\n /**\n * Source directory to scan for controllers and decorators.\n * Defaults to `'src'`.\n */\n srcDir?: string\n /**\n * Output directory for generated `.d.ts` files.\n * Defaults to `'.kickjs/types'`.\n */\n outDir?: string\n /**\n * Schema validator used to derive `body` types from route metadata.\n *\n * - `'zod'` — emit `z.infer<typeof <importedSchema>>` for any schema\n * referenced as a named identifier in `@Get/@Post/...({ body, query, params })`.\n * - `false` — disable schema-driven body typing.\n *\n * Future: `'joi' | 'yup' | 'json-schema'` plus a `{ name; module }`\n * escape hatch for custom adapters.\n *\n * @default 'zod'\n */\n schemaValidator?: SchemaValidator\n /**\n * Path to the project's env schema file (relative to project root).\n * Must default-export a `defineEnv(...)` schema for typegen to emit\n * the typed `KickEnv` global registry.\n *\n * Set to `false` to disable env typing entirely.\n *\n * @default 'src/env.ts'\n */\n envFile?: string | false\n /**\n * Built-in or user typegen plugin ids to skip during `kick typegen`,\n * `kick dev`, and `kick typegen --watch`.\n *\n * The plugin still loads and merge-time conflict detection still\n * runs — only the `generate()` invocation is skipped — so adopters\n * who want to hand-write `KickDbRegister` (manual typeof-schema\n * augmentation) can disable `'kick/db'` and keep the rest:\n *\n * @example\n * typegen: {\n * disable: ['kick/db'], // hand-written register.ts owns the type\n * }\n *\n * Unrecognised ids are ignored — the list is treated as a wishlist,\n * not a strict registry.\n */\n disable?: string[]\n}\n\n/** Module generation settings — controls how `kick g module` produces code */\nexport interface ModuleConfig {\n /** Where modules live (default: 'src/modules') */\n dir?: string\n /**\n * Default repository implementation for generators.\n *\n * Built-in types (string): `'drizzle'`, `'inmemory'`, `'prisma'`\n * — generate fully working repository code.\n *\n * Custom types (object): `{ name: 'typeorm' }`\n * — generate a stub repository with TODO markers.\n *\n * @example\n * repo: 'prisma' // built-in\n * repo: { name: 'typeorm' } // custom\n */\n repo?: RepoTypeConfig\n /** Schema output directory (e.g. 'src/db/schema' for Drizzle, 'prisma/' for Prisma) */\n schemaDir?: string\n /**\n * Whether to pluralize module names in generated code.\n * When true (default), `kick g module user` creates `src/modules/users/`.\n * When false, it creates `src/modules/user/` and uses singular names throughout.\n */\n pluralize?: boolean\n /**\n * Import path for the Prisma generated client in `--repo prisma` templates.\n * Must resolve within `src/` for path alias compatibility.\n *\n * @default '@prisma/client' (Prisma 5/6)\n * @example\n * prismaClientPath: '@/generated/prisma/client' // Prisma 7+\n * prismaClientPath: './generated/prisma/client' // relative\n */\n prismaClientPath?: string\n /**\n * Module declaration style emitted by `kick g module` and the\n * project scaffold.\n *\n * - `'define'` (default) — `defineModule({ name, build: () => ({...}) })`\n * factory form. Mirrors `defineAdapter` / `definePlugin` /\n * `defineContextDecorator`.\n * - `'class'` — legacy `class FooModule implements AppModule { ... }`\n * form. Still fully supported by the framework loader; pin to this\n * value for projects that prefer the class shape (existing-codebase\n * consistency, class-decorator setups, etc).\n *\n * The framework runtime accepts both shapes regardless of this\n * setting — the flag controls codegen output only. `kick g module`\n * inserts the matching call form into `src/modules/index.ts`\n * (`Module()` vs `Module`); `kick rm module` matches both.\n *\n * @default 'define'\n */\n style?: 'define' | 'class'\n}\n\n/** Configuration for the kick.config.ts file */\nexport interface KickConfig {\n /**\n * Project pattern — controls default generator behavior.\n * - 'rest' — Express + Swagger (default)\n * - 'ddd' — Full DDD modules with use cases, entities, value objects\n * - 'cqrs' — CQRS with commands, queries, events, WebSocket + queue\n * - 'minimal' — Bare Express with no scaffolding\n */\n pattern?: ProjectPattern\n /**\n * Module generation settings — directory, repo type, pluralization, schema dir.\n *\n * @example\n * modules: {\n * dir: 'src/modules',\n * repo: 'prisma',\n * pluralize: false,\n * schemaDir: 'prisma/',\n * }\n */\n modules?: ModuleConfig\n /**\n * Package manager used by `kick add` (and any future dep-installing command)\n * to install dependencies. When set, overrides lockfile auto-detection so\n * commands always use the project's intended package manager.\n *\n * Priority (highest first):\n * 1. `--pm` flag on the CLI\n * 2. `packageManager` in kick.config\n * 3. `packageManager` field in package.json (corepack convention)\n * 4. Lockfile detection (pnpm-lock.yaml → pnpm, yarn.lock → yarn)\n * 5. `'npm'`\n *\n * @example\n * packageManager: 'pnpm'\n */\n packageManager?: PackageManager\n\n /**\n * DI token scope prefix used by code generators. Every scaffolded\n * `createToken<T>('<scope>/<area>/<key>')` substitutes this string\n * for `<scope>`. Generators emit org-scoped tokens out of the box\n * so adopter projects pass `kick-lint`'s `token-reserved-prefix`\n * rule (which forbids the reserved `kick/` prefix on third-party\n * code) without manual rename.\n *\n * Resolution order (highest first):\n * 1. This field, when set\n * 2. `package.json` `name` field — `@scope/pkg` → `'scope'`,\n * bare `pkg` → `'pkg'`\n * 3. Fallback `'app'`\n *\n * @example\n * tokenScope: 'mycorp'\n * // → createToken<...>('mycorp/users/repository')\n */\n tokenScope?: string\n\n /**\n * Directories to copy to dist/ after build.\n * Useful for EJS templates, email templates, static assets, etc.\n *\n * @example\n * ```ts\n * copyDirs: [\n * 'src/views', // copies to dist/src/views\n * { src: 'src/views', dest: 'dist/views' }, // custom dest\n * 'src/emails',\n * ]\n * ```\n */\n copyDirs?: Array<string | { src: string; dest?: string }>\n /**\n * Build output settings. The asset manager + `kick build`'s copy\n * steps honour these — adopters who use Vite's `build.outDir =\n * 'out'` (or any non-default) should mirror the value here so\n * `assets.x.y()` paths line up with where Vite actually wrote.\n *\n * @example\n * ```ts\n * build: { outDir: 'out' }\n * ```\n */\n build?: {\n /**\n * Output directory, relative to project root. Defaults to\n * `'dist'`. The asset manager emits its manifest + copies\n * assetMap entries into this directory (under a per-namespace\n * subdirectory by default; override per-entry via `dest`).\n */\n outDir?: string\n }\n /**\n * Typed, addressable assets — see `assets-plan.md`. Each entry maps\n * a logical namespace name to a source directory. The build pipeline\n * auto-derives the necessary copy step + emits a manifest at\n * `dist/.kickjs-assets.json`; the runtime exposes\n * `import { assets } from '@forinda/kickjs'` so adopters can resolve\n * paths without dev/prod branching.\n *\n * `copyDirs` is unchanged — `assetMap` is a separate, opt-in surface.\n * Adopters who want raw directory copies keep using `copyDirs`; those\n * who want typed addressable assets add `assetMap` entries.\n *\n * @example\n * ```ts\n * assetMap: {\n * mails: { src: 'src/templates/mails' },\n * reports: { src: 'src/templates/reports', glob: '**\\/*.{ejs,html}' },\n * schemas: { src: 'src/schemas', glob: '**\\/*.json' },\n * }\n * ```\n */\n assetMap?: Record<string, AssetMapEntry>\n /**\n * Typegen settings — controls `.kickjs/types/*` generation including\n * the schema validator used for body type extraction.\n *\n * @example\n * ```ts\n * typegen: {\n * schemaValidator: 'zod',\n * }\n * ```\n */\n typegen?: TypegenConfig\n /**\n * Dev-server (`kick dev`) settings.\n */\n dev?: {\n /**\n * Run the project's TypeScript checker (`tsgo --noEmit`, falling\n * back to `tsc --noEmit`) after each debounced change and surface\n * diagnostics in the dev console + a `kickjs:typecheck` HMR event.\n * Equivalent to the `kick dev --typecheck` flag.\n *\n * @default false\n */\n typecheck?: boolean\n }\n /**\n * Database settings — schema path, migrations dir, dialect,\n * connection string, optional adapter factory. Consumed by\n * `kick db generate` / `kick db migrate*`. See {@link KickDbConfigBlock}.\n */\n db?: KickDbConfigBlock\n /** Custom commands that extend the CLI */\n commands?: KickCommandDefinition[]\n /**\n * CLI plugins — bundled commands + typegens contributed by external\n * packages (e.g. `@forinda/kickjs-cli-drizzle`). Plugin commands\n * appear first; adopter `commands` overrides plugin commands of the\n * same name. Duplicate commands or typegen ids across two plugins\n * fail-fast at CLI startup.\n *\n * @example\n * import { drizzlePlugin } from '@forinda/kickjs-cli-drizzle'\n * export default defineConfig({\n * plugins: [drizzlePlugin({ schemaPath: 'src/db/schema' })],\n * })\n */\n plugins?: KickCliPlugin[]\n /** Code style overrides (auto-detected from prettier when possible) */\n style?: {\n semicolons?: boolean\n quotes?: 'single' | 'double'\n trailingComma?: 'all' | 'es5' | 'none'\n indent?: number\n }\n\n /**\n * Extensibility hook for `kick doctor`. Adopters add their own\n * environment / project-shape checks here; each function receives\n * the same context the built-in checks see and returns a result (or\n * `null` to skip).\n *\n * The framework stays ORM- and stack-agnostic — Prisma-specific,\n * Drizzle-specific, deploy-target-specific checks belong in adopter\n * config (or in adapter packages that ship doctor extensions),\n * never in core.\n *\n * @example\n * ```ts\n * import { existsSync } from 'node:fs'\n * import { join } from 'node:path'\n * import { defineConfig } from '@forinda/kickjs-cli'\n *\n * export default defineConfig({\n * doctor: {\n * checks: [\n * (ctx) => {\n * if (!existsSync(join(ctx.cwd, 'prisma/schema.prisma'))) return null\n * const generated = join(ctx.cwd, 'node_modules/@prisma/client/default.js')\n * return existsSync(generated)\n * ? { name: 'Prisma client generated', status: 'pass' }\n * : {\n * name: 'Prisma client generated',\n * status: 'fail',\n * fix: 'Run: pnpm exec prisma generate',\n * }\n * },\n * ],\n * },\n * })\n * ```\n */\n doctor?: import('./commands/doctor').DoctorExtension\n}\n\n/** Helper to define a type-safe kick.config.ts */\nexport function defineConfig(config: KickConfig): KickConfig {\n return config\n}\n\n/** Resolve module config from `modules.*` block. */\n/**\n * Resolve the project's DI token scope for code generators.\n * Falls back through kick.config.ts → package.json → `'app'`.\n *\n * @param config Loaded `kick.config.ts` (null when not present)\n * @param cwd Project root — used to read package.json\n */\nexport function resolveTokenScope(config: KickConfig | null, cwd: string): string {\n if (config?.tokenScope && typeof config.tokenScope === 'string' && config.tokenScope.length > 0) {\n const sanitised = sanitizeScope(config.tokenScope)\n // Configured tokenScope can sanitise down to an empty string (e.g.\n // '___' or '!!') — falling through to the package.json chain is\n // safer than emitting an invalid `'/users/repository'` token.\n if (sanitised.length > 0) return sanitised\n }\n\n // Read package.json synchronously — this runs once per generator\n // invocation, so a sync read is cheaper than the async dance + lets\n // the call sites (template builders) stay synchronous.\n try {\n const pkgPath = join(cwd, 'package.json')\n if (existsSync(pkgPath)) {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8')) as { name?: unknown }\n if (typeof pkg.name === 'string' && pkg.name.length > 0) {\n const scoped = pkg.name.match(/^@([^/]+)\\//)\n const candidate = scoped ? sanitizeScope(scoped[1]) : sanitizeScope(pkg.name)\n if (candidate.length > 0) return candidate\n // Same empty-after-sanitize guard.\n }\n }\n } catch {\n // package.json missing or malformed — fall through to default\n }\n\n return 'app'\n}\n\n/** Lowercase + strip characters that would break a token literal. */\nfunction sanitizeScope(raw: string): string {\n return raw\n .toLowerCase()\n .replace(/[^a-z0-9-]/g, '-') // collapse anything weird to a hyphen\n .replace(/^-+|-+$/g, '') // trim leading/trailing hyphens\n .replace(/-{2,}/g, '-') // collapse runs of hyphens\n}\n\nexport function resolveModuleConfig(config: KickConfig | null): ModuleConfig {\n if (!config) return {}\n const mc: ModuleConfig = {\n dir: config.modules?.dir,\n repo: config.modules?.repo,\n schemaDir: config.modules?.schemaDir,\n pluralize: config.modules?.pluralize,\n prismaClientPath: config.modules?.prismaClientPath,\n style: config.modules?.style,\n }\n // Validate `style` — silently coerce unknown values to the default.\n // The CLI surface only documents 'define' and 'class'; anything else\n // is a typo (e.g. 'defineModule') we'd rather see than silently\n // emit class form.\n if (mc.style !== undefined && mc.style !== 'define' && mc.style !== 'class') {\n console.warn(\n ` Warning: modules.style '${mc.style as string}' is not a valid value ` +\n `(expected 'define' or 'class'). Falling back to 'define'.`,\n )\n mc.style = 'define'\n }\n\n // Warn if a string repo value isn't a known built-in. Deprecated ORM\n // presets get their own note; any other bare string suggests the\n // `{ name }` form to silence the stub-repo warning.\n if (mc.repo && typeof mc.repo === 'string' && !BUILTIN_REPO_TYPES.includes(mc.repo)) {\n if (!warnIfDeprecatedRepo(mc.repo)) {\n console.warn(\n ` Warning: modules.repo '${mc.repo}' is not a built-in type (${BUILTIN_REPO_TYPES.join(', ')}).` +\n ` It will generate a stub repository. Use { name: '${mc.repo}' } to silence this warning.`,\n )\n }\n }\n\n return mc\n}\n\nconst CONFIG_FILES = ['kick.config.ts', 'kick.config.js', 'kick.config.mjs', 'kick.config.json']\n\n/**\n * Load `kick.config.*` starting from `startDir` and walking up toward\n * the filesystem root until a config file is found. Returns `null`\n * when no config exists anywhere on the way up.\n *\n * Walking up means adopters can run `kick <cmd>` from any subdirectory\n * (e.g. `src/modules/users/`) and still pick up the project's config —\n * before this change a nested-cwd invocation silently saw `null` and\n * fell back to framework defaults.\n *\n * TypeScript configs (`.ts`) are loaded via `jiti` when available;\n * `.js` / `.mjs` use native `import()`; `.json` uses `JSON.parse`. The\n * jiti import is dynamic + best-effort: if the dep is missing we\n * surface a warning telling the adopter how to install it, instead of\n * silently dropping the config (which is what the previous bare-catch\n * did).\n */\nexport async function loadKickConfig(startDir: string): Promise<KickConfig | null> {\n const { findProjectRoot } = await import('./utils/project-root')\n const root = findProjectRoot(startDir)\n\n for (const filename of CONFIG_FILES) {\n const filepath = join(root, filename)\n try {\n await access(filepath)\n } catch {\n continue\n }\n\n if (filename.endsWith('.json')) {\n const content = await readFile(filepath, 'utf-8')\n return JSON.parse(content)\n }\n\n const isTs = filename.endsWith('.ts')\n\n if (isTs) {\n // Split the import-jiti step from the load-user-config step so the\n // diagnostic blames the right thing. Both surface as Node module-\n // resolution errors with similar shapes (`Cannot find package …`,\n // `ERR_MODULE_NOT_FOUND`), but the remedies differ:\n //\n // - Missing jiti → adopter needs to install jiti.\n // - Missing dep referenced from kick.config.ts → adopter needs to\n // install THAT package; telling them to install jiti would send\n // them to the wrong fix and bury the real missing module.\n let jitiModule: typeof import('jiti')\n try {\n jitiModule = await import('jiti')\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n if (msg.includes(\"Cannot find package 'jiti'\") || msg.includes('ERR_MODULE_NOT_FOUND')) {\n console.warn(\n `Warning: Failed to load ${filename} — 'jiti' is required for TypeScript configs. ` +\n \"Run `pnpm add -D jiti` (or your package manager's equivalent), or rename the file \" +\n 'to kick.config.js / kick.config.mjs / kick.config.json.',\n )\n } else {\n console.warn(`Warning: Failed to initialize jiti for ${filename}: ${msg}`)\n }\n continue\n }\n\n try {\n const jiti = jitiModule.createJiti(root, { interopDefault: true, fsCache: false })\n const config = (await jiti.import(filepath, { default: true })) as KickConfig\n const warnings = validateAssetMap(config, root)\n for (const warning of warnings) console.warn(` Warning: ${warning}`)\n writeAssetConfigSnapshot(root, config)\n return config\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n console.warn(`Warning: Failed to load ${filename}: ${msg}`)\n continue\n }\n }\n\n try {\n const { pathToFileURL } = await import('node:url')\n const mod = await import(pathToFileURL(filepath).href)\n const config = (mod.default ?? mod) as KickConfig\n const warnings = validateAssetMap(config, root)\n for (const warning of warnings) console.warn(` Warning: ${warning}`)\n writeAssetConfigSnapshot(root, config)\n return config\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n console.warn(`Warning: Failed to load ${filename}: ${msg}`)\n continue\n }\n }\n return null\n}\n\n/**\n * Mirror the JSON-serialisable slice of a TS/JS `kick.config` that the\n * runtime asset resolver needs (`assetMap` + `build.outDir`) into\n * `.kickjs/kick.config.json`.\n *\n * Why: the runtime resolver in `@forinda/kickjs` reads its config\n * *synchronously* (it sits on the hot path of `assets.x.y()` /\n * `resolveAsset()`), so it can only parse `kick.config.{json,js,cjs}` —\n * it deliberately can't transpile `kick.config.ts`. For a `.ts`-config\n * project in dev (no built `dist/.kickjs-assets.json` yet), that left\n * the resolver with no config to synthesise a manifest from, so\n * `assets.x.y()` threw `UnknownAssetError` until the first build.\n *\n * The CLI already transpiles the `.ts` config here, so it drops this\n * tiny snapshot the runtime can read with a plain `JSON.parse`. Best\n * effort: any failure (read-only fs, etc.) is swallowed — a missing\n * snapshot just falls back to the previous behaviour.\n */\nexport function writeAssetConfigSnapshot(root: string, config: KickConfig | null): void {\n // Only meaningful for asset-manager users — don't litter `.kickjs/`\n // for projects that never declare an assetMap.\n if (!config?.assetMap || Object.keys(config.assetMap).length === 0) return\n try {\n const dir = join(root, '.kickjs')\n mkdirSync(dir, { recursive: true })\n const snapshot = {\n // Marker so a future shape change can be detected/migrated.\n version: 1 as const,\n assetMap: config.assetMap,\n ...(config.build?.outDir ? { build: { outDir: config.build.outDir } } : {}),\n }\n writeFileSync(join(dir, 'kick.config.json'), JSON.stringify(snapshot, null, 2) + '\\n', 'utf-8')\n } catch {\n // Best effort — snapshot is an optimisation, not a correctness\n // requirement. Production reads the real dist manifest.\n }\n}\n\n/**\n * Validate `assetMap` entries on a loaded config. Returns a list of\n * human-readable warnings; the caller decides how to surface them\n * (typically `console.warn`). Never throws — `kick g` and other\n * unrelated commands should keep working even when the assetMap is\n * misconfigured.\n *\n * Checks:\n *\n * - Each entry's `src` is a non-empty string.\n * - The `src` directory exists on disk (otherwise the typegen + build\n * steps will fail later with cryptic errors).\n * - `dest` doesn't escape the project root (defensive — a `dest:\n * '../../etc'` typo could write files outside the workspace).\n * - The namespace key is a non-empty string and doesn't include a\n * `/` (would conflict with the `<namespace>/<key>` manifest format).\n */\nexport function validateAssetMap(config: KickConfig | null, cwd: string): string[] {\n const warnings: string[] = []\n if (!config?.assetMap) return warnings\n\n const root = resolve(cwd)\n for (const [namespace, entry] of Object.entries(config.assetMap)) {\n if (!namespace || namespace.includes('/')) {\n warnings.push(\n `assetMap key '${namespace}' is invalid — must be a non-empty string without '/'`,\n )\n continue\n }\n if (typeof entry?.src !== 'string' || entry.src.length === 0) {\n warnings.push(`assetMap.${namespace} is missing a non-empty 'src' field`)\n continue\n }\n const srcAbs = resolve(cwd, entry.src)\n if (!existsSync(srcAbs)) {\n warnings.push(\n `assetMap.${namespace}.src ('${entry.src}') does not exist — typegen + build will fail`,\n )\n }\n if (entry.dest) {\n const destAbs = resolve(cwd, entry.dest)\n // path.relative is the right primitive for \"is X inside Y?\" —\n // a raw startsWith() prefix match has two failure modes the\n // earlier version hit: (a) `/app` is a prefix of `/app2/...`\n // even though they're different directories, and (b) it's\n // case-sensitive on filesystems that aren't (macOS default,\n // Windows). path.relative handles both correctly + accounts\n // for `..` traversal in the destination.\n if (escapesRoot(destAbs, root)) {\n warnings.push(\n `assetMap.${namespace}.dest ('${entry.dest}') resolves outside the project root — refusing to copy`,\n )\n }\n }\n }\n return warnings\n}\n\n/**\n * Returns true when `path` (absolute) resolves outside of `root`\n * (also absolute). Uses `path.relative` for accuracy:\n *\n * - The result is empty when paths are identical (inside).\n * - It starts with `..` when the path traverses outside the root.\n * - It's absolute (Windows: cross-drive) when there's no relative\n * path between them.\n *\n * Avoids the prefix-match pitfalls of `startsWith` (e.g. `/app`\n * matching `/app2/...`, or case-mismatches on macOS / Windows).\n */\nfunction escapesRoot(path: string, root: string): boolean {\n const rel = relative(root, path)\n return rel === '' ? false : rel.startsWith('..') || isAbsolute(rel)\n}\n"],"mappings":";;;;;;;;;;mhBA+BA,MAAa,EAA8C,CAAC,OAAQ,MAAO,OAAQ,KAAK,EAa3E,EAAwC,CAAC,UAAU,EAOnD,EAA2C,CAAC,SAAU,SAAS,EAO5E,SAAgB,EAAqB,EAAuB,CAO1D,OANK,EAAsB,SAAS,CAAI,GACxC,QAAQ,KACN,gBAAgB,EAAK,mFACS,EAAK,qHAErC,EACO,IAN2C,EAOpD,CA+bA,SAAgB,EAAa,EAAgC,CAC3D,OAAO,CACT,CAUA,SAAgB,EAAkB,EAA2B,EAAqB,CAChF,GAAI,GAAQ,YAAc,OAAO,EAAO,YAAe,UAAY,EAAO,WAAW,OAAS,EAAG,CAC/F,IAAM,EAAY,EAAc,EAAO,UAAU,EAIjD,GAAI,EAAU,OAAS,EAAG,OAAO,CACnC,CAKA,GAAI,CACF,IAAM,EAAU,EAAK,EAAK,cAAc,EACxC,GAAI,EAAW,CAAO,EAAG,CACvB,IAAM,EAAM,KAAK,MAAM,EAAa,EAAS,OAAO,CAAC,EACrD,GAAI,OAAO,EAAI,MAAS,UAAY,EAAI,KAAK,OAAS,EAAG,CACvD,IAAM,EAAS,EAAI,KAAK,MAAM,aAAa,EACrC,EAAqB,EAAT,EAAuB,EAAO,GAAoB,EAAI,IAAI,EAC5E,GAAI,EAAU,OAAS,EAAG,OAAO,CAEnC,CACF,CACF,MAAQ,CAER,CAEA,MAAO,KACT,CAGA,SAAS,EAAc,EAAqB,CAC1C,OAAO,EACJ,YAAY,CAAC,CACb,QAAQ,cAAe,GAAG,CAAC,CAC3B,QAAQ,WAAY,EAAE,CAAC,CACvB,QAAQ,SAAU,GAAG,CAC1B,CAEA,SAAgB,EAAoB,EAAyC,CAC3E,GAAI,CAAC,EAAQ,MAAO,CAAC,EACrB,IAAM,EAAmB,CACvB,IAAK,EAAO,SAAS,IACrB,KAAM,EAAO,SAAS,KACtB,UAAW,EAAO,SAAS,UAC3B,UAAW,EAAO,SAAS,UAC3B,iBAAkB,EAAO,SAAS,iBAClC,MAAO,EAAO,SAAS,KACzB,EAyBA,OApBI,EAAG,QAAU,IAAA,IAAa,EAAG,QAAU,UAAY,EAAG,QAAU,UAClE,QAAQ,KACN,6BAA6B,EAAG,MAAgB,iFAElD,EACA,EAAG,MAAQ,UAMT,EAAG,MAAQ,OAAO,EAAG,MAAS,UAAY,CAAC,EAAmB,SAAS,EAAG,IAAI,IAC3E,EAAqB,EAAG,IAAI,GAC/B,QAAQ,KACN,4BAA4B,EAAG,KAAK,4BAA4B,EAAmB,KAAK,IAAI,EAAE,sDACvC,EAAG,KAAK,6BACjE,GAIG,CACT,CAEA,MAAM,EAAe,CAAC,iBAAkB,iBAAkB,kBAAmB,kBAAkB,EAmB/F,eAAsB,EAAe,EAA8C,CACjF,GAAM,CAAE,mBAAoB,MAAM,OAAO,8BAAuB,CAAA,KAAA,GAAA,EAAA,CAAA,EAC1D,EAAO,EAAgB,CAAQ,EAErC,IAAK,IAAM,KAAY,EAAc,CACnC,IAAM,EAAW,EAAK,EAAM,CAAQ,EACpC,GAAI,CACF,MAAM,EAAO,CAAQ,CACvB,MAAQ,CACN,QACF,CAEA,GAAI,EAAS,SAAS,OAAO,EAAG,CAC9B,IAAM,EAAU,MAAM,EAAS,EAAU,OAAO,EAChD,OAAO,KAAK,MAAM,CAAO,CAC3B,CAIA,GAFa,EAAS,SAAS,KAExB,EAAG,CAUR,IAAI,EACJ,GAAI,CACF,EAAa,MAAM,OAAO,OAC5B,OAAS,EAAK,CACZ,IAAM,EAAM,aAAe,MAAQ,EAAI,QAAU,OAAO,CAAG,EACvD,EAAI,SAAS,4BAA4B,GAAK,EAAI,SAAS,sBAAsB,EACnF,QAAQ,KACN,2BAA2B,EAAS,0LAGtC,EAEA,QAAQ,KAAK,0CAA0C,EAAS,IAAI,GAAK,EAE3E,QACF,CAEA,GAAI,CAEF,IAAM,EAAU,MADH,EAAW,WAAW,EAAM,CAAE,eAAgB,GAAM,QAAS,EAAM,CACvD,CAAC,CAAC,OAAO,EAAU,CAAE,QAAS,EAAK,CAAC,EACvD,EAAW,EAAiB,EAAQ,CAAI,EAC9C,IAAK,IAAM,KAAW,EAAU,QAAQ,KAAK,cAAc,GAAS,EAEpE,OADA,EAAyB,EAAM,CAAM,EAC9B,CACT,OAAS,EAAK,CACZ,IAAM,EAAM,aAAe,MAAQ,EAAI,QAAU,OAAO,CAAG,EAC3D,QAAQ,KAAK,2BAA2B,EAAS,IAAI,GAAK,EAC1D,QACF,CACF,CAEA,GAAI,CACF,GAAM,CAAE,iBAAkB,MAAM,OAAO,YACjC,EAAM,MAAM,OAAO,EAAc,CAAQ,CAAC,CAAC,MAC3C,EAAU,EAAI,SAAW,EACzB,EAAW,EAAiB,EAAQ,CAAI,EAC9C,IAAK,IAAM,KAAW,EAAU,QAAQ,KAAK,cAAc,GAAS,EAEpE,OADA,EAAyB,EAAM,CAAM,EAC9B,CACT,OAAS,EAAK,CACZ,IAAM,EAAM,aAAe,MAAQ,EAAI,QAAU,OAAO,CAAG,EAC3D,QAAQ,KAAK,2BAA2B,EAAS,IAAI,GAAK,EAC1D,QACF,CACF,CACA,OAAO,IACT,CAoBA,SAAgB,EAAyB,EAAc,EAAiC,CAGlF,MAAC,GAAQ,UAAY,OAAO,KAAK,EAAO,QAAQ,CAAC,CAAC,SAAW,GACjE,GAAI,CACF,IAAM,EAAM,EAAK,EAAM,SAAS,EAChC,EAAU,EAAK,CAAE,UAAW,EAAK,CAAC,EAClC,IAAM,EAAW,CAEf,QAAS,EACT,SAAU,EAAO,SACjB,GAAI,EAAO,OAAO,OAAS,CAAE,MAAO,CAAE,OAAQ,EAAO,MAAM,MAAO,CAAE,EAAI,CAAC,CAC3E,EACA,EAAc,EAAK,EAAK,kBAAkB,EAAG,KAAK,UAAU,EAAU,KAAM,CAAC,EAAI;EAAM,OAAO,CAChG,MAAQ,CAGR,CACF,CAmBA,SAAgB,EAAiB,EAA2B,EAAuB,CACjF,IAAM,EAAqB,CAAC,EAC5B,GAAI,CAAC,GAAQ,SAAU,OAAO,EAE9B,IAAM,EAAO,EAAQ,CAAG,EACxB,IAAK,GAAM,CAAC,EAAW,KAAU,OAAO,QAAQ,EAAO,QAAQ,EAAG,CAChE,GAAI,CAAC,GAAa,EAAU,SAAS,GAAG,EAAG,CACzC,EAAS,KACP,iBAAiB,EAAU,sDAC7B,EACA,QACF,CACA,GAAI,OAAO,GAAO,KAAQ,UAAY,EAAM,IAAI,SAAW,EAAG,CAC5D,EAAS,KAAK,YAAY,EAAU,oCAAoC,EACxE,QACF,CAEK,EADU,EAAQ,EAAK,EAAM,GACb,CAAC,GACpB,EAAS,KACP,YAAY,EAAU,SAAS,EAAM,IAAI,8CAC3C,EAEE,EAAM,MASJ,EARY,EAAQ,EAAK,EAAM,IAQb,EAAG,CAAI,GAC3B,EAAS,KACP,YAAY,EAAU,UAAU,EAAM,KAAK,wDAC7C,CAGN,CACA,OAAO,CACT,CAcA,SAAS,EAAY,EAAc,EAAuB,CACxD,IAAM,EAAM,EAAS,EAAM,CAAI,EAC/B,OAAO,IAAQ,GAAK,GAAQ,EAAI,WAAW,IAAI,GAAK,EAAW,CAAG,CACpE"}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs-cli v6.0.1
2
+ * @forinda/kickjs-cli v6.1.1
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-CrfNQIZA.mjs";import{i as c}from"./config-DSpcRefL.mjs";import{t as l}from"./project-root-BdTe6EpE.mjs";import{createRequire as u}from"node:module";import{dirname as d,join as f,relative as p,resolve as m}from"node:path";import{existsSync as h,readFileSync as g,readdirSync as _,statSync as v}from"node:fs";import{readFile as y,writeFile as b}from"node:fs/promises";import x from"pluralize";import{execFileSync as S,execSync as C}from"node:child_process";import{fileURLToPath as ee,pathToFileURL as te}from"node:url";import{defineGenerator as ne}from"@forinda/kickjs-cli-kit";function w(e){return e.replace(/[-_\s]+(.)?/g,(e,t)=>t?t.toUpperCase():``).replace(/^(.)/,e=>e.toUpperCase())}function T(e){let t=w(e);return t.charAt(0).toLowerCase()+t.slice(1)}function E(e){return e.replace(/([a-z])([A-Z])/g,`$1-$2`).replace(/[\s_]+/g,`-`).toLowerCase()}function D(e){return x.plural(e)}function O(e){return x.plural(e)}function k(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function re(e){return e.charAt(0).toUpperCase()+e.slice(1).replace(/-([a-z])/g,(e,t)=>t.toUpperCase())}function ie(e){return e.replace(/([a-z])([A-Z])/g,`$1-$2`).toLowerCase()}function ae(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]??`${re(n)}${e}Repository`,repoFile:i[n]??`${ie(n)}-${t}`}}function A(e){return e??`define`}function j(e){let{pascal:t,kebab:n,plural:r=``,repo:i,style:a}=e,{repoClass:o,repoFile:s}=ae(t,n,i),c=A(a),l=`/**
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-CqOymvmb.mjs";import{i as c}from"./config-DLy6JCCy.mjs";import{t as l}from"./project-root-yLxS5CqO.mjs";import{createRequire as u}from"node:module";import d,{dirname as f,join as p,relative as m,resolve as h}from"node:path";import{existsSync as g,readFileSync as _,readdirSync as v,statSync as y}from"node:fs";import{readFile as b,writeFile as x}from"node:fs/promises";import S from"pluralize";import{execFileSync as C,execSync as w}from"node:child_process";import{fileURLToPath as ee,pathToFileURL as te}from"node:url";import{defineGenerator as ne}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 S.plural(e)}function k(e){return S.plural(e)}function A(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function re(e){return e.charAt(0).toUpperCase()+e.slice(1).replace(/-([a-z])/g,(e,t)=>t.toUpperCase())}function ie(e){return e.replace(/([a-z])([A-Z])/g,`$1-$2`).toLowerCase()}function ae(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]??`${re(n)}${e}Repository`,repoFile:i[n]??`${ie(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}=ae(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 oe(e){let{pascal:t,kebab:n,plural:r=``,style:i}=e,a=A(i),o=` /**
83
+ `}function oe(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.
@@ -120,7 +120,7 @@ ${o}
120
120
  },
121
121
  }),
122
122
  })
123
- `}function M(e){let{pascal:t,kebab:n}=e,r=t.charAt(0).toLowerCase()+t.slice(1);return`import { Controller, Get, Post, Put, Delete, Autowired, ApiQueryParams, type Ctx } from '@forinda/kickjs'
123
+ `}function N(e){let{pascal:t,kebab:n}=e,r=t.charAt(0).toLowerCase()+t.slice(1);return`import { Controller, Get, Post, Put, Delete, Autowired, ApiQueryParams, type Ctx } from '@forinda/kickjs'
124
124
  import { ApiTags } from '@forinda/kickjs-swagger'
125
125
  import { ${t}Service } from './${n}.service'
126
126
  import { create${t}Schema } from './dtos/create-${n}.dto'
@@ -204,7 +204,7 @@ export type Update${t}DTO = z.infer<typeof update${t}Schema>
204
204
  createdAt: string
205
205
  updatedAt: string
206
206
  }
207
- `}function N(e){let{pascal:t,kebab:n,dtoPrefix:r=`../../application/dtos`,tokenScope:i=`app`}=e;return`/**
207
+ `}function P(e){let{pascal:t,kebab:n,dtoPrefix:r=`../../application/dtos`,tokenScope:i=`app`}=e;return`/**
208
208
  * ${t} Repository Interface
209
209
  *
210
210
  * Defines the contract for data access.
@@ -239,7 +239,7 @@ export interface I${t}Repository {
239
239
  * adopters must NOT use the reserved \`'kick/'\` namespace.
240
240
  */
241
241
  export const ${t.toUpperCase()}_REPOSITORY = createToken<I${t}Repository>('${i}/${t}/repository')
242
- `}function P(e){let{pascal:t,kebab:n,repoPrefix:r=`../../domain/repositories`,dtoPrefix:i=`../../application/dtos`}=e;return`/**
242
+ `}function F(e){let{pascal:t,kebab:n,repoPrefix:r=`../../domain/repositories`,dtoPrefix:i=`../../application/dtos`}=e;return`/**
243
243
  * In-Memory ${t} Repository
244
244
  *
245
245
  * Implements the repository interface using a Map.
@@ -299,7 +299,7 @@ export class InMemory${t}Repository implements I${t}Repository {
299
299
  this.store.delete(id)
300
300
  }
301
301
  }
302
- `}function F(e){let{pascal:t,kebab:n,repoType:r=``,repoPrefix:i=`../../domain/repositories`,dtoPrefix:a=`../../application/dtos`}=e,o=r.charAt(0).toUpperCase()+r.slice(1).replace(/-([a-z])/g,(e,t)=>t.toUpperCase());return`/**
302
+ `}function I(e){let{pascal:t,kebab:n,repoType:r=``,repoPrefix:i=`../../domain/repositories`,dtoPrefix:a=`../../application/dtos`}=e,o=r.charAt(0).toUpperCase()+r.slice(1).replace(/-([a-z])/g,(e,t)=>t.toUpperCase());return`/**
303
303
  * ${o} ${t} Repository
304
304
  *
305
305
  * Stub implementation for a custom '${r}' repository.
@@ -482,7 +482,7 @@ describe('InMemory${t}Repository', () => {
482
482
  expect(found).toBeNull()
483
483
  })
484
484
  })
485
- `}function I(e){let{pascal:t,kebab:n}=e;return`import { Service, Inject, HttpException } from '@forinda/kickjs'
485
+ `}function L(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,7 +519,7 @@ export class ${t}Service {
519
519
  await this.repo.delete(id)
520
520
  }
521
521
  }
522
- `}function L(e){let{pascal:t}=e;return`import type { QueryFieldConfig } from '@forinda/kickjs'
522
+ `}function R(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'],
@@ -717,7 +717,7 @@ export class HelloService {
717
717
  return { status: 'ok', uptime: process.uptime() }
718
718
  }
719
719
  }
720
- `}function R(){return`import { Controller, Get, Autowired, type Ctx } from '@forinda/kickjs'
720
+ `}function ge(){return`import { Controller, Get, Autowired, type Ctx } from '@forinda/kickjs'
721
721
  import { HelloService } from './hello.service'
722
722
 
723
723
  // \`Ctx<KickRoutes.HelloController['<method>']>\` is generated by
@@ -739,7 +739,7 @@ export class HelloController {
739
739
  ctx.json(this.helloService.healthCheck())
740
740
  }
741
741
  }
742
- `}function ge(){return`import { defineModule } from '@forinda/kickjs'
742
+ `}function _e(){return`import { defineModule } from '@forinda/kickjs'
743
743
  import { HelloController } from './hello.controller'
744
744
 
745
745
  export const HelloModule = defineModule({
@@ -760,7 +760,7 @@ export const HelloModule = defineModule({
760
760
  },
761
761
  }),
762
762
  })
763
- `}function _e(e,t=`inmemory`,n=`pnpm`){return`import { defineConfig } from '@forinda/kickjs-cli'
763
+ `}function ve(e,t=`inmemory`,n=`pnpm`){return`import { defineConfig } from '@forinda/kickjs-cli'
764
764
 
765
765
  export default defineConfig({
766
766
  pattern: '${e}',
@@ -807,7 +807,7 @@ export default defineConfig({
807
807
  },
808
808
  ],
809
809
  })
810
- `}async function ve(e){let{pascal:t,kebab:n,plural:r,style:i,write:a}=e;await a(`${n}.module.ts`,oe({pascal:t,kebab:n,plural:r,style:i})),await a(`${n}.controller.ts`,`import { Controller, Get, type Ctx } from '@forinda/kickjs'
810
+ `}async function ye(e){let{pascal:t,kebab:n,plural:r,style:i,write:a}=e;await a(`${n}.module.ts`,oe({pascal:t,kebab:n,plural:r,style:i})),await a(`${n}.controller.ts`,`import { Controller, Get, type Ctx } from '@forinda/kickjs'
811
811
 
812
812
  // \`Ctx<KickRoutes.${t}Controller['<method>']>\` is generated by
813
813
  // \`kick typegen\` (auto-run on \`kick dev\`).
@@ -819,7 +819,7 @@ export class ${t}Controller {
819
819
  ctx.json({ message: '${t} list' })
820
820
  }
821
821
  }
822
- `)}async function ye(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`,j({pascal:t,kebab:n,plural:r,repo:a,style:c})),await l(`${n}.constants.ts`,L({pascal:t,kebab:n})),await l(`${n}.controller.ts`,M({pascal:t,kebab:n,plural:r,pluralPascal:i})),await l(`${n}.service.ts`,I({pascal:t,kebab:n})),await l(`dtos/create-${n}.dto.ts`,se({pascal:t,kebab:n})),await l(`dtos/update-${n}.dto.ts`,ce({pascal:t,kebab:n})),await l(`dtos/${n}-response.dto.ts`,le({pascal:t,kebab:n})),await l(`${n}.repository.ts`,N({pascal:t,kebab:n,dtoPrefix:`./dtos`,tokenScope:s}));let u=a===`inmemory`,d=u?`in-memory-${n}`:`${E(a)}-${n}`,f=u?P({pascal:t,kebab:n,repoPrefix:`.`,dtoPrefix:`./dtos`}):F({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`,P({pascal:t,kebab:n,repoPrefix:`.`,dtoPrefix:`./dtos`})),await l(`__tests__/${n}.controller.test.ts`,ue({pascal:t,kebab:n,plural:r})),await l(`__tests__/${n}.repository.test.ts`,de({pascal:t,kebab:n,plural:r,repoPrefix:`../in-memory-${n}.repository`})))}function be(e){return e?typeof e==`string`?e:e.name:`inmemory`}async function xe(t){let{name:n,modulesDir:a,noEntity:c,noTests:l,repo:u=`inmemory`,force:d,dryRun:p}=t,m=t.pluralize!==!1,h=t.pattern??`rest`;t.minimal&&(h=`minimal`);let g=E(n),_=w(n),v=m?D(g):g,y=m?O(_):_,b=f(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=f(b,t);if(p){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 ve(C);break;default:await ye(C);break}return p||await z(a,_,v,g,C.style),x}async function z(t,n,r,i,a=`define`){let o=f(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'
822
+ `)}async function be(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`,R({pascal:t,kebab:n})),await l(`${n}.controller.ts`,N({pascal:t,kebab:n,plural:r,pluralPascal:i})),await l(`${n}.service.ts`,L({pascal:t,kebab:n})),await l(`dtos/create-${n}.dto.ts`,se({pascal:t,kebab:n})),await l(`dtos/update-${n}.dto.ts`,ce({pascal:t,kebab:n})),await l(`dtos/${n}-response.dto.ts`,le({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`,ue({pascal:t,kebab:n,plural:r})),await l(`__tests__/${n}.repository.test.ts`,de({pascal:t,kebab:n,plural:r,repoPrefix:`../in-memory-${n}.repository`})))}function xe(e){return e?typeof e==`string`?e:e.name:`inmemory`}async function Se(t){let{name:n,modulesDir:a,noEntity:c,noTests:l,repo:u=`inmemory`,force:d,dryRun:f}=t,m=t.pluralize!==!1,h=t.pattern??`rest`;t.minimal&&(h=`minimal`);let g=D(n),_=T(n),v=m?O(g):g,y=m?k(_):_,b=p(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=p(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 ye(C);break;default:await be(C);break}return f||await z(a,_,v,g,C.style),x}async function z(t,n,r,i,a=`define`){let o=p(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
823
  import { ${n}Module } from '${l}'
824
824
 
825
825
  export const modules: AppModuleEntry[] = [${u}]
@@ -827,11 +827,11 @@ export const modules: AppModuleEntry[] = [${u}]
827
827
  import { ${n}Module } from '${l}'
828
828
 
829
829
  export const modules = defineModules().mount(${u})
830
- `);return}let d=await y(o,`utf-8`),p=`import { ${n}Module } from '${l}'`,m=k(l);if(!RegExp(`^import\\s*\\{[^}]*\\b${k(n)}Module\\b[^}]*\\}\\s*from\\s*['"]${m}['"]`,`m`).test(d)){let e=d.lastIndexOf(`import `);if(e!==-1){let t=d.indexOf(`
831
- `,e);d=d.slice(0,t+1)+p+`
832
- `+d.slice(t+1)}else d=p+`
833
- `+d}let h=V(d);if(h){let e=d.slice(h.rhsStart,h.rhsEnd+1);RegExp(`\\b${k(n)}Module\\b`).test(e)||(d=B(d,u))}else d=B(d,u);await b(o,d,`utf-8`)}function B(e,t){let n=V(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 V(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=Ce(e,n);return t===-1?null:{shape:`array`,rhsStart:n,rhsEnd:t}}if(e.slice(n,n+13)===`defineModules`){let t=Se(e,n);return t===-1?null:{shape:`chain`,rhsStart:n,rhsEnd:t-1,chainEnd:t}}return null}function Se(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=U(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=U(e,t);if(n===-1)break;i=n+1}return i}function H(e,t){let n=e.slice(t,t+2);if(n===`//`){for(t+=2;t<e.length&&e[t]!==`
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 Ce(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=H(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 U(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=H(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 we(t){let{name:n,outDir:r}=t,i=E(n),a=w(n),o=[],s=f(r,`${i}.adapter.ts`);return await e(s,`import {
830
+ `);return}let d=await b(o,`utf-8`),f=`import { ${n}Module } from '${l}'`,m=A(l);if(!RegExp(`^import\\s*\\{[^}]*\\b${A(n)}Module\\b[^}]*\\}\\s*from\\s*['"]${m}['"]`,`m`).test(d)){let e=d.lastIndexOf(`import `);if(e!==-1){let t=d.indexOf(`
831
+ `,e);d=d.slice(0,t+1)+f+`
832
+ `+d.slice(t+1)}else d=f+`
833
+ `+d}let h=V(d);if(h){let e=d.slice(h.rhsStart,h.rhsEnd+1);RegExp(`\\b${A(n)}Module\\b`).test(e)||(d=B(d,u))}else d=B(d,u);await x(o,d,`utf-8`)}function B(e,t){let n=V(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 V(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=we(e,n);return t===-1?null:{shape:`array`,rhsStart:n,rhsEnd:t}}if(e.slice(n,n+13)===`defineModules`){let t=Ce(e,n);return t===-1?null:{shape:`chain`,rhsStart:n,rhsEnd:t-1,chainEnd:t}}return null}function Ce(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=U(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=U(e,t);if(n===-1)break;i=n+1}return i}function H(e,t){let n=e.slice(t,t+2);if(n===`//`){for(t+=2;t<e.length&&e[t]!==`
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 we(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=H(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 U(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=H(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 Te(t){let{name:n,outDir:r}=t,i=D(n),a=T(n),o=[],s=p(r,`${i}.adapter.ts`);return await e(s,`import {
835
835
  defineAdapter,
836
836
  type AdapterContext,
837
837
  type AdapterMiddleware,
@@ -1000,9 +1000,9 @@ export const ${a}Adapter = defineAdapter<${a}AdapterConfig>({
1000
1000
  }
1001
1001
  },
1002
1002
  })
1003
- `),o.push(s),o}const Te={controller:``,service:``,dto:`dtos`,guard:`guards`,middleware:`middleware`,contributor:`contributors`};function W(e){let{type:t,outDir:n,moduleName:r,modulesDir:i=`src/modules`,defaultDir:a,shouldPluralize:o=!0}=e;if(n)return m(n);if(r){let e=Te,n=E(r),a=o?D(n):n,s=e[t]??``,c=f(i,a);return m(s?f(c,s):c)}return m(a)}async function Ee(t){let{name:n,moduleName:r,modulesDir:i,pattern:a}=t,o=W({type:`middleware`,outDir:t.outDir,moduleName:r,modulesDir:i,defaultDir:`src/middleware`,pattern:a,shouldPluralize:t.pluralize??!0}),s=E(n),c=T(n),l=[],u=f(o,`${s}.middleware.ts`);return await e(u,`import type { Request, Response, NextFunction } from 'express'
1003
+ `),o.push(s),o}const Ee={controller:``,service:``,dto:`dtos`,guard:`guards`,middleware:`middleware`,contributor:`contributors`};function W(e){let{type:t,outDir:n,moduleName:r,modulesDir:i=`src/modules`,defaultDir:a,shouldPluralize:o=!0}=e;if(n)return h(n);if(r){let e=Ee,n=D(r),a=o?O(n):n,s=e[t]??``,c=p(i,a);return h(s?p(c,s):c)}return h(a)}async function De(t){let{name:n,moduleName:r,modulesDir:i,pattern:a}=t,o=W({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=p(o,`${s}.middleware.ts`);return await e(u,`import type { Request, Response, NextFunction } from 'express'
1004
1004
 
1005
- export interface ${w(n)}Options {
1005
+ export interface ${T(n)}Options {
1006
1006
  // Add configuration options here. The factory below closes over the
1007
1007
  // resolved options object; pass them at the call site —
1008
1008
  // \`${c}({ foo: 'bar' })\` — and the closure preserves them across
@@ -1010,7 +1010,7 @@ export interface ${w(n)}Options {
1010
1010
  }
1011
1011
 
1012
1012
  /**
1013
- * ${w(n)} middleware.
1013
+ * ${T(n)} middleware.
1014
1014
  *
1015
1015
  * Usage in bootstrap (fires on every request):
1016
1016
  * middleware: [${c}()]
@@ -1042,7 +1042,7 @@ export interface ${w(n)}Options {
1042
1042
  * Usage with @Middleware decorator:
1043
1043
  * @Middleware(${c}())
1044
1044
  */
1045
- export function ${c}(options: ${w(n)}Options = {}) {
1045
+ export function ${c}(options: ${T(n)}Options = {}) {
1046
1046
  return (req: Request, res: Response, next: NextFunction) => {
1047
1047
  // Implement your middleware logic here. \`options\` is captured by
1048
1048
  // closure — log or read it anywhere in this handler body.
@@ -1050,7 +1050,7 @@ export function ${c}(options: ${w(n)}Options = {}) {
1050
1050
  next()
1051
1051
  }
1052
1052
  }
1053
- `),l.push(u),l}async function De(t){let{name:n,moduleName:r,modulesDir:i,pattern:a}=t,o=W({type:`guard`,outDir:t.outDir,moduleName:r,modulesDir:i,defaultDir:`src/guards`,pattern:a,shouldPluralize:t.pluralize??!0}),s=E(n),c=T(n),l=w(n),u=[],d=f(o,`${s}.guard.ts`);return await e(d,`import { Container, HttpException } from '@forinda/kickjs'
1053
+ `),l.push(u),l}async function Oe(t){let{name:n,moduleName:r,modulesDir:i,pattern:a}=t,o=W({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=p(o,`${s}.guard.ts`);return await e(d,`import { Container, HttpException } from '@forinda/kickjs'
1054
1054
  import type { RequestContext } from '@forinda/kickjs'
1055
1055
 
1056
1056
  /**
@@ -1086,7 +1086,7 @@ export async function ${c}Guard(ctx: RequestContext, next: () => void): Promise<
1086
1086
  ctx.res.status(401).json({ message: 'Invalid or expired token' })
1087
1087
  }
1088
1088
  }
1089
- `),u.push(d),u}async function Oe(t){let{name:n,moduleName:r,modulesDir:i,pattern:a}=t,o=W({type:`service`,outDir:t.outDir,moduleName:r,modulesDir:i,defaultDir:`src/services`,pattern:a,shouldPluralize:t.pluralize??!0}),s=E(n),c=w(n),l=[],u=f(o,`${s}.service.ts`);return await e(u,`import { Service } from '@forinda/kickjs'
1089
+ `),u.push(d),u}async function ke(t){let{name:n,moduleName:r,modulesDir:i,pattern:a}=t,o=W({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=p(o,`${s}.service.ts`);return await e(u,`import { Service } from '@forinda/kickjs'
1090
1090
 
1091
1091
  @Service()
1092
1092
  export class ${c}Service {
@@ -1095,7 +1095,7 @@ export class ${c}Service {
1095
1095
  // @Inject(MY_REPO) private readonly repo: IMyRepository,
1096
1096
  // ) {}
1097
1097
  }
1098
- `),l.push(u),l}async function ke(t){let{name:n,moduleName:r,modulesDir:i,pattern:a}=t,o=W({type:`controller`,outDir:t.outDir,moduleName:r,modulesDir:i,defaultDir:`src/controllers`,pattern:a,shouldPluralize:t.pluralize??!0}),s=E(n),c=w(n),l=[],u=f(o,`${s}.controller.ts`);return await e(u,`import { Controller, Get, Post, type Ctx } from '@forinda/kickjs'
1098
+ `),l.push(u),l}async function Ae(t){let{name:n,moduleName:r,modulesDir:i,pattern:a}=t,o=W({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=p(o,`${s}.controller.ts`);return await e(u,`import { Controller, Get, Post, type Ctx } from '@forinda/kickjs'
1099
1099
 
1100
1100
  // \`Ctx<KickRoutes.${c}Controller['<method>']>\` is generated by
1101
1101
  // \`kick typegen\` (auto-run on \`kick dev\`). After the first run, your IDE
@@ -1116,7 +1116,7 @@ export class ${c}Controller {
1116
1116
  ctx.created({ message: '${c} created', data: ctx.body })
1117
1117
  }
1118
1118
  }
1119
- `),l.push(u),l}async function Ae(t){let{name:n,moduleName:r,modulesDir:i,pattern:a}=t,o=W({type:`dto`,outDir:t.outDir,moduleName:r,modulesDir:i,defaultDir:`src/dtos`,pattern:a,shouldPluralize:t.pluralize??!0}),s=E(n),c=w(n),l=T(n),u=[],d=f(o,`${s}.dto.ts`);return await e(d,`import { z } from 'zod'
1119
+ `),l.push(u),l}async function je(t){let{name:n,moduleName:r,modulesDir:i,pattern:a}=t,o=W({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=p(o,`${s}.dto.ts`);return await e(d,`import { z } from 'zod'
1120
1120
 
1121
1121
  export const ${l}Schema = z.object({
1122
1122
  // Define your schema fields here
@@ -1124,7 +1124,7 @@ export const ${l}Schema = z.object({
1124
1124
  })
1125
1125
 
1126
1126
  export type ${c}DTO = z.infer<typeof ${l}Schema>
1127
- `),u.push(d),u}const je={swagger:`@forinda/kickjs-swagger`,ws:`@forinda/kickjs-ws`,queue:`@forinda/kickjs-queue`,devtools:`@forinda/kickjs-devtools`},Me={zod:{name:`zod`,range:`^4.3.6`},valibot:{name:`valibot`,range:`^1.4.1`},yup:{name:`yup`,range:`^1.7.1`}};function G(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 Ne(e,t,n,r=[],i=`zod`){let a=Me[i],o={"@forinda/kickjs":G(n,`@forinda/kickjs`),"@forinda/kickjs-schema":G(n,`@forinda/kickjs-schema`),dotenv:`^17.3.1`,express:`^5.1.0`,"reflect-metadata":`^0.2.2`,[a.name]:a.range};for(let e of r){let t=je[e];t&&!o[t]&&(o[t]=G(n,t))}return JSON.stringify({name:e,version:`0.0.0`,type:`module`,scripts:{dev:`vite`,"dev:debug":`kick dev:debug`,build:`kick build`,start:`kick start`,test:`vitest run`,"test:watch":`vitest`,typecheck:`tsc --noEmit`,typegen:`kick typegen`,lint:`eslint src/`,format:`prettier --write src/`},dependencies:o,devDependencies:{"@forinda/kickjs-cli":G(n,`@forinda/kickjs-cli`),"@forinda/kickjs-vite":G(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 Pe(){return`import { defineConfig } from 'vite'
1127
+ `),u.push(d),u}const Me={swagger:`@forinda/kickjs-swagger`,ws:`@forinda/kickjs-ws`,queue:`@forinda/kickjs-queue`,devtools:`@forinda/kickjs-devtools`},Ne={zod:{name:`zod`,range:`^4.3.6`},valibot:{name:`valibot`,range:`^1.4.1`},yup:{name:`yup`,range:`^1.7.1`}};function G(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 Pe(e,t,n,r=[],i=`zod`){let a=Ne[i],o={"@forinda/kickjs":G(n,`@forinda/kickjs`),"@forinda/kickjs-schema":G(n,`@forinda/kickjs-schema`),dotenv:`^17.3.1`,express:`^5.1.0`,"reflect-metadata":`^0.2.2`,[a.name]:a.range};for(let e of r){let t=Me[e];t&&!o[t]&&(o[t]=G(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:o,devDependencies:{"@forinda/kickjs-cli":G(n,`@forinda/kickjs-cli`),"@forinda/kickjs-vite":G(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 Fe(){return`import { defineConfig } from 'vite'
1128
1128
  import { resolve } from 'node:path'
1129
1129
  import swc from 'unplugin-swc'
1130
1130
  import { kickjsVitePlugin, envWatchPlugin } from '@forinda/kickjs-vite'
@@ -1154,7 +1154,7 @@ export default defineConfig({
1154
1154
  },
1155
1155
  },
1156
1156
  })
1157
- `}function Fe(){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 Ie(){return JSON.stringify({semi:!1,singleQuote:!0,trailingComma:`all`,printWidth:100,tabWidth:2},null,2)}function Le(){return`# https://editorconfig.org
1157
+ `}function Ie(){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 Le(){return JSON.stringify({semi:!1,singleQuote:!0,trailingComma:`all`,printWidth:100,tabWidth:2},null,2)}function Re(){return`# https://editorconfig.org
1158
1158
  root = true
1159
1159
 
1160
1160
  [*]
@@ -1167,14 +1167,14 @@ insert_final_newline = true
1167
1167
 
1168
1168
  [*.md]
1169
1169
  trim_trailing_whitespace = false
1170
- `}function Re(){return`node_modules/
1170
+ `}function ze(){return`node_modules/
1171
1171
  dist/
1172
1172
  .env
1173
1173
  coverage/
1174
1174
  .DS_Store
1175
1175
  *.tsbuildinfo
1176
1176
  .kickjs/
1177
- `}function ze(){return`# Auto-detect text files and normalise line endings to LF
1177
+ `}function Be(){return`# Auto-detect text files and normalise line endings to LF
1178
1178
  * text=auto eol=lf
1179
1179
 
1180
1180
  # Explicitly mark generated / binary files
@@ -1192,11 +1192,11 @@ coverage/
1192
1192
  pnpm-lock.yaml -diff linguist-generated
1193
1193
  yarn.lock -diff linguist-generated
1194
1194
  package-lock.json -diff linguist-generated
1195
- `}function Be(){return`PORT=3000
1196
- NODE_ENV=development
1197
1195
  `}function Ve(){return`PORT=3000
1198
1196
  NODE_ENV=development
1199
- `}function He(){return`import { defineConfig } from 'vitest/config'
1197
+ `}function He(){return`PORT=3000
1198
+ NODE_ENV=development
1199
+ `}function Ue(){return`import { defineConfig } from 'vitest/config'
1200
1200
  import swc from 'unplugin-swc'
1201
1201
 
1202
1202
  export default defineConfig({
@@ -1207,15 +1207,15 @@ export default defineConfig({
1207
1207
  include: ['src/**/*.test.ts'],
1208
1208
  },
1209
1209
  })
1210
- `}const Ue=d(ee(import.meta.url)),K=JSON.parse(g(f(Ue,`..`,`package.json`),`utf-8`)),We=`^${K.version}`,Ge=[`@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 Ke(){let e=await Promise.all(Ge.map(async e=>{try{let t=S(`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,We]}));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`}=t,u=r,d=e=>console.log(` ${e}`);console.log(`\n Creating KickJS project: ${n}\n`),d(`Resolving package versions...`);let p=await Ke();await e(f(u,`package.json`),Ne(n,o,p,c,l)),await e(f(u,`vite.config.ts`),Pe()),await e(f(u,`tsconfig.json`),Fe()),await e(f(u,`.prettierrc`),Ie()),await e(f(u,`.editorconfig`),Le()),await e(f(u,`.gitignore`),Re()),await e(f(u,`.gitattributes`),ze()),await e(f(u,`.env`),Be()),await e(f(u,`.env.example`),Ve()),await e(f(u,`src/config/index.ts`),me(l)),await e(f(u,`src/index.ts`),fe(n,o,K.version,c)),await e(f(u,`src/modules/index.ts`),pe()),await e(f(u,`src/modules/hello/hello.service.ts`),he()),await e(f(u,`src/modules/hello/hello.controller.ts`),R()),await e(f(u,`src/modules/hello/hello.module.ts`),ge()),await e(f(u,`kick.config.ts`),_e(o,s,i)),await e(f(u,`vitest.config.ts`),He()),await e(f(u,`README.md`),a(n,o,i));let{generateAgentDocs:m}=await import(`./agent-docs-hbOXsAAh.mjs`).then(e=>e.t);if(await m({outDir:u,name:n,pm:i,template:o,only:`all`,force:!0}),t.installDeps){console.log(`\n Installing dependencies with ${i}...\n`);try{C(`${i} install`,{cwd:u,stdio:`inherit`}),console.log(`
1211
- Dependencies installed successfully!`)}catch{console.log(`\n Warning: ${i} install failed. Run it manually.`)}}try{let{runTypegen:e}=await import(`./typegen-CwtvFZ0t.mjs`).then(e=>e.n);await e({cwd:u,allowDuplicates:!0,silent:!0})}catch{}if(t.initGit)try{C(`git init`,{cwd:u,stdio:`pipe`}),C(`git branch -M main`,{cwd:u,stdio:`pipe`}),C(`git add -A`,{cwd:u,stdio:`pipe`}),C(`git commit -m "chore: initial commit from kick new"`,{cwd:u,stdio:`pipe`}),d(`Git repository initialized`)}catch{d(`Warning: git init failed (git may not be installed)`)}console.log(`
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 Je(e){return E(e).replace(/-/g,`_`)}function q(e){let t=e.cwd??process.cwd(),n=e.projectRoot??l(t),r=e.pluralize??!0,i=w(e.name),a=T(e.name),o=E(e.name),s=Je(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=D(o);c.pluralKebab=e,c.pluralPascal=w(e),c.pluralCamel=T(e)}return c}function Ye(e,t){return m(e.cwd,t)}async function Xe(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=Ze(e);return J.set(e,n),n}async function Ze(e){let t=m(e,`package.json`);if(!h(t))return{generators:[],loaded:[],failed:[]};let n=Qe(JSON.parse(await y(t,`utf-8`))),r=u(m(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 y(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=m(d(t),s);if(!h(c)){o.push({source:e,reason:`kickjs.generators points to missing file: ${s}`});continue}let l;try{l=await Xe(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(!$e(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 Qe(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 $e(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.name==`string`&&typeof t.files==`function`}async function et(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=nt(await Y(n),e.generatorName);return i?X(i.spec,i.source,e,n):null}async function tt(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 nt(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=Ye(a,t.path);await e(n,t.content),s.push(n)}return{files:s,source:n}}function rt(e){return e}function it(e){return e}function Z(e){try{return JSON.parse(g(e,`utf-8`))}catch{return null}}function Q(e){try{return g(e,`utf-8`)}catch{return null}}function at(e){let t=Q(f(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=ot(e,r.extends);if(t){let e=Z(t)??{};r.compilerOptions={...e.compilerOptions,...r.compilerOptions}}}return r}function ot(e,t){if(t.startsWith(`.`)){let n=m(e,t);return h(n)?n:null}let n=f(e,`node_modules`,t);return h(n)?n:null}function st(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function ct(){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
- Install a supported version via nvm / fnm / volta.`}:{name:`Node version`,status:`pass`,message:e}}function lt(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 ut(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}function dt(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.
1210
+ `}const We=f(ee(import.meta.url)),K=JSON.parse(_(p(We,`..`,`package.json`),`utf-8`)),Ge=`^${K.version}`,Ke=[`@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 qe(){let e=await Promise.all(Ke.map(async e=>{try{let t=C(`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,Ge]}));return Object.fromEntries(e)}async function Je(t){let{name:n,directory:r,packageManager:i=`pnpm`,template:o=`rest`,defaultRepo:s=`inmemory`,packages:c=[],schemaLib:l=`zod`}=t,u=r,d=e=>console.log(` ${e}`);console.log(`\n Creating KickJS project: ${n}\n`),d(`Resolving package versions...`);let f=await qe();await e(p(u,`package.json`),Pe(n,o,f,c,l)),await e(p(u,`vite.config.ts`),Fe()),await e(p(u,`tsconfig.json`),Ie()),await e(p(u,`.prettierrc`),Le()),await e(p(u,`.editorconfig`),Re()),await e(p(u,`.gitignore`),ze()),await e(p(u,`.gitattributes`),Be()),await e(p(u,`.env`),Ve()),await e(p(u,`.env.example`),He()),await e(p(u,`src/config/index.ts`),me(l)),await e(p(u,`src/index.ts`),fe(n,o,K.version,c)),await e(p(u,`src/modules/index.ts`),pe()),await e(p(u,`src/modules/hello/hello.service.ts`),he()),await e(p(u,`src/modules/hello/hello.controller.ts`),ge()),await e(p(u,`src/modules/hello/hello.module.ts`),_e()),await e(p(u,`kick.config.ts`),ve(o,s,i)),await e(p(u,`vitest.config.ts`),Ue()),await e(p(u,`README.md`),a(n,o,i));let{generateAgentDocs:m}=await import(`./agent-docs-GpRHHdWC.mjs`).then(e=>e.t);if(await m({outDir:u,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:u,stdio:`inherit`}),console.log(`
1211
+ Dependencies installed successfully!`)}catch{console.log(`\n Warning: ${i} install failed. Run it manually.`)}}try{let{runTypegen:e}=await import(`./typegen-BJwy65-p.mjs`).then(e=>e.n);await e({cwd:u,allowDuplicates:!0,silent:!0})}catch{}if(t.initGit)try{w(`git init`,{cwd:u,stdio:`pipe`}),w(`git branch -M main`,{cwd:u,stdio:`pipe`}),w(`git add -A`,{cwd:u,stdio:`pipe`}),w(`git commit -m "chore: initial commit from kick new"`,{cwd:u,stdio:`pipe`}),d(`Git repository initialized`)}catch{d(`Warning: git init failed (git may not be installed)`)}console.log(`
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
+ Install a supported version via nvm / fnm / volta.`}:{name:`Node version`,status:`pass`,message:e}}function $(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 pt(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}function mt(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
1214
  Install it: pnpm add reflect-metadata
1215
1215
  Then import it at the top of src/index.ts:
1216
1216
 
1217
1217
  import 'reflect-metadata'
1218
- // ... 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 $(e){let t=[`src/env.ts`,`src/env/index.ts`,`src/config/env.ts`,`src/config/index.ts`].map(t=>f(e.cwd,t)).filter(e=>h(e)).filter(e=>/\bloadEnv\s*\(/.test(Q(e)??``));if(t.length===0)return null;let n=[`src/index.ts`,`src/main.ts`].map(t=>f(e.cwd,t)).find(e=>h(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=Q(n)??``,i=d(n),a=[];for(let e of t){let t=p(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+)?['"]${st(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=>p(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 \`${p(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 ${p(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 pt(e,t=mt){let n=0,r=0,i=[e];for(;i.length>0&&r<t;){let e=i.pop(),a;try{a=_(e,{withFileTypes:!0})}catch{continue}for(let o of a){if(r>=t)break;r++;let a=f(e,o.name);if(o.isDirectory()){i.push(a);continue}try{let e=v(a).mtimeMs;e>n&&(n=e)}catch{}}}return n}const mt=2e3;function ht(e){let t=f(e.cwd,`.kickjs`,`types`);if(!h(t))return null;let n=pt(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 gt=[()=>ct(),lt,ut,dt,ft,$,ht];async function _t(e,t={}){let n={cwd:e,pkg:Z(f(e,`package.json`)),tsconfig:at(e)},r=[...gt,...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 vt(e){switch(e){case`pass`:return r.green(`✔`);case`warn`:return r.yellow(`⚠`);case`fail`:return r.red(`✖`)}}function yt(e){let t=vt(e.status),n=e.message?` ${r.dim(`(${e.message})`)}`:``;return`${t} ${e.name}${n}`}function bt(e){return e.split(`
1218
+ // ... rest of bootstrap`}}function ht(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 gt(e){let t=[`src/env.ts`,`src/env/index.ts`,`src/config/env.ts`,`src/config/index.ts`].map(t=>p(e.cwd,t)).filter(e=>g(e)).filter(e=>/\bloadEnv\s*\(/.test(Q(e)??``));if(t.length===0)return null;let n=[`src/index.ts`,`src/main.ts`].map(t=>p(e.cwd,t)).find(e=>g(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=Q(n)??``,i=f(n),a=[];for(let e of t){let t=m(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+)?['"]${dt(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=>m(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 \`${m(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 ${m(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 _t(e,t=vt){let n=0,r=0,i=[e];for(;i.length>0&&r<t;){let e=i.pop(),a;try{a=v(e,{withFileTypes:!0})}catch{continue}for(let o of a){if(r>=t)break;r++;let a=p(e,o.name);if(o.isDirectory()){i.push(a);continue}try{let e=y(a).mtimeMs;e>n&&(n=e)}catch{}}}return n}const vt=2e3;function yt(e){let t=p(e.cwd,`.kickjs`,`types`);if(!g(t))return null;let n=_t(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=[()=>ft(),$,pt,mt,ht,gt,yt];async function xt(e,t={}){let n={cwd:e,pkg:Z(p(e,`package.json`)),tsconfig:lt(e)},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 St(e){switch(e){case`pass`:return r.green(`✔`);case`warn`:return r.yellow(`⚠`);case`fail`:return r.red(`✖`)}}function Ct(e){let t=St(e.status),n=e.message?` ${r.dim(`(${e.message})`)}`:``;return`${t} ${e.name}${n}`}function wt(e){return e.split(`
1219
1219
  `).map(e=>` ${r.dim(`→`)} ${e}`).join(`
1220
- `)}function xt(e){return e?.doctor?.checks??[]}function St(e){e.command(`doctor`).description(`Pre-flight checks for your KickJS project (dev environment health)`).action(async()=>{let e=process.cwd(),a=xt(await c(e));t(`KickJS Doctor`);let o=await _t(e,{extraChecks:a});for(let e of o)i.message(yt(e)),e.fix&&e.status!==`pass`&&i.message(bt(e.fix));let s=o.filter(e=>e.status===`pass`).length,l=o.filter(e=>e.status===`warn`).length,u=o.filter(e=>e.status===`fail`).length,d=[r.green(`${s} passed`),l>0?r.yellow(`${l} warning${l===1?``:`s`}`):`${l} warnings`,u>0?r.red(`${u} error${u===1?``:`s`}`):`${u} errors`].join(`, `);u>0?(n(`${d} — fix the errors above before running the app`),process.exit(1)):n(l>0?`${d} — review the warnings`:r.green(`${d} — your environment looks good`))})}export{T as A,P as C,k as D,j as E,w as M,D as O,F as S,M as T,V as _,et as a,L as b,qe as c,Oe as d,De as f,z as g,we as h,tt as i,E as j,O as k,Ae as l,W as m,rt as n,q as o,Ee as p,St as r,ne as s,it as t,ke as u,xe as v,N as w,I as x,be as y};
1221
- //# sourceMappingURL=doctor-559QZlHi.mjs.map
1220
+ `)}function Tt(e){return e?.doctor?.checks??[]}function Et(e){e.command(`doctor`).description(`Pre-flight checks for your KickJS project (dev environment health)`).action(async()=>{let e=process.cwd(),a=Tt(await c(e));t(`KickJS Doctor`);let o=await xt(e,{extraChecks:a});for(let e of o)i.message(Ct(e)),e.fix&&e.status!==`pass`&&i.message(wt(e.fix));let s=o.filter(e=>e.status===`pass`).length,l=o.filter(e=>e.status===`warn`).length,u=o.filter(e=>e.status===`fail`).length,d=[r.green(`${s} passed`),l>0?r.yellow(`${l} warning${l===1?``:`s`}`):`${l} warnings`,u>0?r.red(`${u} error${u===1?``:`s`}`):`${u} errors`].join(`, `);u>0?(n(`${d} — fix the errors above before running the app`),process.exit(1)):n(l>0?`${d} — review the warnings`:r.green(`${d} — your environment looks good`))})}export{O as A,L as C,N as D,P as E,E as M,D as N,M as O,T as P,R as S,F as T,Te as _,it as a,Se as b,Xe as c,je as d,Ae as f,W as g,De as h,at as i,k as j,A as k,Ze as l,Oe as m,st as n,q as o,ke as p,Et as r,ne as s,ct as t,Je as u,z as v,I as w,xe as x,V as y};
1221
+ //# sourceMappingURL=doctor-CcVNNzGj.mjs.map