@forinda/kickjs-cli 8.4.0 → 8.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{project-docs-Ck3uzaEG.mjs → agent-docs-BFOgLbXq.mjs} +81 -71
- package/dist/agent-docs-BFOgLbXq.mjs.map +1 -0
- package/dist/{project-docs-8d5GNDIw.mjs → agent-docs-BU1rORKA.mjs} +75 -67
- package/dist/{build-Bw_SFnBG.mjs → build-CdIpRyfy.mjs} +3 -3
- package/dist/{build-Bw_SFnBG.mjs.map → build-CdIpRyfy.mjs.map} +1 -1
- package/dist/{build-BrNa6gYZ.mjs → build-DlfIkjcw.mjs} +2 -2
- package/dist/{builtins-DHjV84lv.mjs → builtins-CfAXBoIM.mjs} +2 -2
- package/dist/{builtins-CNZ4QP-z.mjs → builtins-CmuUgcIq.mjs} +36 -31
- package/dist/cli.mjs +2 -2
- package/dist/config-SvlcF3Ls.mjs +12 -0
- package/dist/config-ndsVdO8u.mjs +13 -0
- package/dist/config-ndsVdO8u.mjs.map +1 -0
- package/dist/{doctor-DzqvC6jF.mjs → doctor-D3RMXkxE.mjs} +6 -6
- package/dist/{doctor-DzqvC6jF.mjs.map → doctor-D3RMXkxE.mjs.map} +1 -1
- package/dist/fs-DdNMcW_P.mjs +12 -0
- package/dist/fs-DdNMcW_P.mjs.map +1 -0
- package/dist/fs-v57MCgpH.mjs +11 -0
- package/dist/fullstack-DOufUeMv.mjs +95 -0
- package/dist/fullstack-LJwhodT-.mjs +96 -0
- package/dist/fullstack-LJwhodT-.mjs.map +1 -0
- package/dist/index.d.mts +15 -24
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/{plugin-C11bSFtE.mjs → plugin-Dighdqh-.mjs} +2 -2
- package/dist/{plugin-BdN4scZR.mjs → plugin-Dn67elEZ.mjs} +2 -2
- package/dist/project-AXCA1hD9.mjs +45 -0
- package/dist/project-Cb_NLUWI.mjs +46 -0
- package/dist/project-Cb_NLUWI.mjs.map +1 -0
- package/dist/{project-root-DORRVmte.mjs → project-root-C7TrLJlZ.mjs} +3 -3
- package/dist/{project-root-DORRVmte.mjs.map → project-root-C7TrLJlZ.mjs.map} +1 -1
- package/dist/{project-root-D_rrQbpy.mjs → project-root-Dgvy5kYG.mjs} +2 -2
- package/dist/{prompts-DHHDYxLL.mjs → prompts-CSATvwXw.mjs} +2 -2
- package/dist/{prompts-DHHDYxLL.mjs.map → prompts-CSATvwXw.mjs.map} +1 -1
- package/dist/{rolldown-runtime-LCdccCoI.mjs → rolldown-runtime-BhxEEqxa.mjs} +1 -1
- package/dist/{run-plugins-DSYGn4AC.mjs → run-plugins-Cf_6BgGZ.mjs} +34 -29
- package/dist/run-plugins-Cf_6BgGZ.mjs.map +1 -0
- package/dist/{typegen-Bv9EzadE.mjs → typegen-97E_RYNp.mjs} +4 -4
- package/dist/typegen-CYhFNfIu.mjs +132 -0
- package/dist/{typegen-COTKpuqW.mjs.map → typegen-CYhFNfIu.mjs.map} +1 -1
- package/dist/{types-CW4qiwB1.mjs → types-lHwt_SNI.mjs} +1 -1
- package/package.json +10 -9
- package/templates/base/feature.json +18 -0
- package/templates/base/files/README.md +61 -0
- package/templates/base/files/_dot_editorconfig +13 -0
- package/templates/base/files/_dot_env +2 -0
- package/templates/base/files/_dot_env.example +2 -0
- package/templates/base/files/_dot_env.test +9 -0
- package/templates/base/files/_dot_env.test.example +11 -0
- package/templates/base/files/_dot_gitattributes +18 -0
- package/templates/base/files/_dot_gitignore +14 -0
- package/templates/base/files/_dot_oxfmtrc.json +9 -0
- package/templates/base/files/kick.config.ts +58 -0
- package/templates/base/files/src/modules/hello/hello.controller.ts +26 -0
- package/templates/base/files/src/modules/hello/hello.module.ts +21 -0
- package/templates/base/files/src/modules/hello/hello.service.ts +12 -0
- package/templates/base/files/src/modules/index.ts +7 -0
- package/templates/base/files/tsconfig.json +21 -0
- package/templates/base/files/vite.config.ts +31 -0
- package/templates/base/files/vitest.config.ts +18 -0
- package/templates/feature-devtools/feature.json +13 -0
- package/templates/feature-queue/feature.json +16 -0
- package/templates/feature-queue/files/_dot_env.append +2 -0
- package/templates/feature-queue/files/_dot_env.example.append +2 -0
- package/templates/feature-swagger/feature.json +16 -0
- package/templates/feature-ws/feature.json +13 -0
- package/templates/fullstack-root/files/_dot_gitignore +8 -0
- package/templates/fullstack-root/files/netlify.toml +13 -0
- package/templates/fullstack-root/files/vercel.json +5 -0
- package/templates/host-config/files/netlify.toml +6 -0
- package/templates/host-config/files/vercel.json +5 -0
- package/templates/runtime-express/feature.json +22 -0
- package/templates/runtime-fastify/feature.json +13 -0
- package/templates/runtime-h3/feature.json +13 -0
- package/templates/schema-valibot/feature.json +3 -0
- package/templates/schema-valibot/files/src/config/index.ts +41 -0
- package/templates/schema-yup/feature.json +3 -0
- package/templates/schema-yup/files/src/config/index.ts +43 -0
- package/templates/schema-zod/feature.json +3 -0
- package/templates/schema-zod/files/src/config/index.ts +41 -0
- package/templates/server-fullstack/feature.json +13 -0
- package/templates/template-minimal/feature.json +10 -0
- package/templates/template-minimal/files/src/index.ts +17 -0
- package/templates/template-rest/feature.json +10 -0
- package/templates/template-rest/files/src/index.ts +28 -0
- package/templates/web-kick/files/web/index.html +12 -0
- package/templates/web-kick/files/web/src/App.tsx +45 -0
- package/templates/web-kick/files/web/src/api.ts +14 -0
- package/templates/web-kick/files/web/src/main.tsx +9 -0
- package/templates/web-kick/files/web/tsconfig.json +15 -0
- package/templates/web-kick/files/web/vite.config.ts +13 -0
- package/dist/agent-docs-BIYv2Od-.mjs +0 -11
- package/dist/agent-docs-DWRW_0cn.mjs +0 -12
- package/dist/agent-docs-DWRW_0cn.mjs.map +0 -1
- package/dist/config-B6LRxtE1.mjs +0 -13
- package/dist/config-B6LRxtE1.mjs.map +0 -1
- package/dist/config-DIH8bQUO.mjs +0 -12
- package/dist/fullstack-BwdcyVD3.mjs +0 -195
- package/dist/fullstack-BwdcyVD3.mjs.map +0 -1
- package/dist/fullstack-CkAO5DhE.mjs +0 -194
- package/dist/project--WiWkarb.mjs +0 -450
- package/dist/project-JoccwqS2.mjs +0 -451
- package/dist/project-JoccwqS2.mjs.map +0 -1
- package/dist/project-docs-8d5GNDIw.mjs.map +0 -1
- package/dist/run-plugins-DSYGn4AC.mjs.map +0 -1
- package/dist/typegen-COTKpuqW.mjs +0 -132
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @forinda/kickjs-cli v8.
|
|
2
|
+
* @forinda/kickjs-cli v8.6.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Felix Orinda
|
|
5
5
|
*
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
|
-
import{t as e}from"./rolldown-runtime-LCdccCoI.mjs";import{a as t,c as n,l as r,m as i,r as a,s as o,t as s,u as c}from"./project--WiWkarb.mjs";import{a as l,c as u,i as d,l as f,o as p,r as m,s as h}from"./config-DIH8bQUO.mjs";import{n as g,r as _}from"./plugin-BdN4scZR.mjs";import{c as v,l as y,s as b}from"./project-docs-Ck3uzaEG.mjs";import{a as x,c as S,d as ee,f as C,i as te,l as ne,n as re,o as ie,p as ae,r as w,s as T,u as oe}from"./agent-docs-BIYv2Od-.mjs";import{t as E}from"./project-root-D_rrQbpy.mjs";import{C as se,S as D,T as ce,_ as le,a as ue,b as de,c as fe,d as pe,f as me,g as he,h as ge,i as _e,l as ve,m as ye,o as be,p as xe,r as Se,s as Ce,t as we,u as Te,v as Ee,w as De,x as Oe,y as ke}from"./typegen-Bv9EzadE.mjs";import{t as Ae}from"./build-BrNa6gYZ.mjs";import{createRequire as je}from"node:module";import{cpSync as Me,existsSync as O,mkdirSync as Ne,readFileSync as k,readdirSync as Pe,rmSync as Fe,statSync as Ie,writeFileSync as Le}from"node:fs";import A,{basename as Re,dirname as j,join as M,relative as N,resolve as P,sep as ze}from"node:path";import{fileURLToPath as Be,pathToFileURL as F}from"node:url";import{fork as Ve,spawn as He,spawnSync as Ue}from"node:child_process";import{copyFile as We,mkdir as Ge,readFile as I,readdir as Ke,rm as qe,stat as Je,writeFile as L}from"node:fs/promises";import"@forinda/kickjs-cli-kit";import Ye from"pluralize";import{parseSync as Xe}from"oxc-parser";import{arch as Ze,platform as Qe,release as $e}from"node:os";import{createHash as et}from"node:crypto";const tt=[{value:`swagger`,label:`Swagger`,hint:`OpenAPI docs`},{value:`ws`,label:`WebSocket`,hint:`rooms, heartbeat`},{value:`queue`,label:`Queue`,hint:`BullMQ/RabbitMQ/Kafka`},{value:`devtools`,label:`DevTools`,hint:`debug dashboard`}];function nt(e){e.command(`new [name]`).alias(`init`).description(`Create a new KickJS project (use "." for current directory)`).option(`-d, --directory <dir>`,`Target directory (defaults to project name)`).option(`--pm <manager>`,`Package manager: pnpm | npm | yarn | bun`).option(`--git`,`Initialize git repository`).option(`--no-git`,`Skip git initialization`).option(`--install`,`Install dependencies after scaffolding`).option(`--no-install`,`Skip dependency installation`).option(`-f, --force`,`Remove existing files without prompting`).option(`-t, --template <type>`,`Project template: rest | minimal | fullstack`).option(`--runtime <engine>`,`HTTP runtime: express | fastify | h3`).option(`-r, --repo <type>`,`Repository name (inmemory, or any DB name e.g. postgres)`).option(`-s, --schema <lib>`,`Schema library for env / DTOs: zod | valibot | yup (default: zod)`).option(`--frontend <kind>`,`Fullstack web/ scaffold: 'kick' (wired React app) or 'vite' (create-vite, unwired)`).option(`--vite-template <name>`,`create-vite TypeScript template for --frontend vite (default 'react-ts')`).option(`--packages <packages>`,`Comma-separated packages to include (e.g. swagger,ws,queue,devtools)`).option(`-y, --yes`,`Pick safe defaults for every prompt (template=minimal, repo=inmemory, no extras, git+install on)`).option(`--non-interactive`,`alias for --yes`).action(async(e,t)=>{te(`KickJS — Create a new project`);let n=!!(t.yes||t.nonInteractive);e||=n?`my-api`:await oe({message:`Project name`,placeholder:`my-api`,defaultValue:`my-api`});let r;if(e===`.`?(r=P(`.`),e=Re(r)):r=P(t.directory||e),O(r)){let i=Pe(r);if(i.length>0){if(t.force)x.warn(`Clearing existing files in ${r}`);else if(n){x.warn(`Directory "${e}" is not empty. Pass --force to clear it.`),T(`Aborted.`);return}else{x.warn(`Directory "${e}" is not empty:`);let t=i.slice(0,5);for(let e of t)x.message(` - ${e}`);if(i.length>5&&x.message(` ... and ${i.length-5} more`),!await w({message:C.red(`Remove all existing files and proceed?`),initialValue:!1})){T(`Aborted.`);return}}for(let e of i)Fe(P(r,e),{recursive:!0,force:!0})}}let i=t.template;i||=n?`minimal`:await S({message:`Project template`,options:[{value:`rest`,label:`REST API`,hint:`Express + Swagger`},{value:`minimal`,label:`Minimal`,hint:`bare Express`},{value:`fullstack`,label:`Fullstack`,hint:`server + Vite React web, typed client`}]});let a=t.runtime;a||=n?`express`:await S({message:`HTTP runtime`,options:[{value:`express`,label:`Express`,hint:`default, zero-config`},{value:`fastify`,label:`Fastify`,hint:`fastify + @fastify/middie`},{value:`h3`,label:`h3`,hint:`Nitro / Nuxt engine`}]});let o=t.pm;o||=n?await c(void 0):await S({message:`Package manager`,options:[{value:`pnpm`,label:`pnpm`},{value:`npm`,label:`npm`},{value:`yarn`,label:`yarn`},{value:`bun`,label:`bun`}]});let l=t.repo;l||=n?`inmemory`:await oe({message:`Repository name`,placeholder:`inmemory (or a DB name, e.g. postgres)`,defaultValue:`inmemory`}),f(l);let u=t.schema;u||=n?`zod`:await S({message:`Schema library (env + DTO validation)`,options:[{value:`zod`,label:`Zod`,hint:`default — broad ecosystem`},{value:`valibot`,label:`Valibot`,hint:`smaller bundle`},{value:`yup`,label:`Yup`,hint:`classic API`}]}),[`zod`,`valibot`,`yup`].includes(u)||(x.warn(`Unknown --schema "${u}", falling back to zod.`),u=`zod`);let d;if(t.packages!==void 0){let e=t.packages.trim().toLowerCase();d=e===``||e===`none`||e===`false`?[]:t.packages.split(`,`).map(e=>e.trim()).filter(Boolean)}else d=n?[]:await ie({message:`Select packages to include`,options:[...tt],required:!1});let p;p=t.git===void 0?n?!0:await w({message:`Initialize git repository?`,initialValue:!0}):t.git;let m;if(m=t.install===void 0?n?!0:await w({message:`Install dependencies?`,initialValue:!0}):t.install,t.frontend!==void 0&&t.frontend!==`kick`&&t.frontend!==`vite`){x.error(`Unknown --frontend '${String(t.frontend)}'. Use 'kick' (wired React app) or 'vite' (create-vite).`),T(`Aborted.`);return}let{VITE_TEMPLATES:h,DEFAULT_VITE_TEMPLATE:g}=await import(`./fullstack-CkAO5DhE.mjs`);if(t.viteTemplate!==void 0&&!h.some(e=>e.value===t.viteTemplate)){x.error(`Unknown --vite-template '${String(t.viteTemplate)}'. TypeScript templates only: ${h.map(e=>e.value).join(`, `)}.`),T(`Aborted.`);return}let _=t.frontend===`vite`?`vite`:`kick`,v=t.viteTemplate??g;if(i===`fullstack`&&!t.frontend&&!n&&(_=await S({message:`Frontend for web/`,options:[{value:`kick`,label:`KickJS React app`,hint:`typed client, /api proxy, route types — wired`},{value:`vite`,label:`Delegate to create-vite`,hint:`pick any framework; wiring is manual (guide printed after)`}]})),_===`vite`&&!t.viteTemplate&&!n&&(v=await S({message:`create-vite template`,options:h.map(e=>({value:e.value,label:e.label})),initialValue:g})),i===`fullstack`){let{initFullstackProject:t}=await import(`./fullstack-CkAO5DhE.mjs`);await t({name:e,directory:r,packageManager:o,initGit:p,installDeps:m,schemaLib:u,runtime:a,frontend:_,viteTemplate:v}),T(`Done! Next steps: ${C.cyan(`cd ${e} && ${o}${o===`pnpm`?` dev`:` run dev:server`}`)}`);return}await s({name:e,directory:r,packageManager:o,initGit:p,installDeps:m,template:i,defaultRepo:l,packages:d,schemaLib:u,runtime:a}),T(`Done! Next steps: ${C.cyan(`cd ${e} && ${o} dev`)}`)})}function R(e){return e.replace(/[-_\s]+(.)?/g,(e,t)=>t?t.toUpperCase():``).replace(/^(.)/,e=>e.toUpperCase())}function z(e){let t=R(e);return t.charAt(0).toLowerCase()+t.slice(1)}function B(e){return e.replace(/([a-z])([A-Z])/g,`$1-$2`).replace(/[\s_]+/g,`-`).toLowerCase()}function V(e){return Ye.plural(e)}function rt(e){return Ye.plural(e)}function it(e){return B(e).replace(/-/g,`_`)}function at(e){let t=e.cwd??process.cwd(),n=e.projectRoot??E(t),r=e.pluralize??!0,i=R(e.name),a=z(e.name),o=B(e.name),s=it(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=V(o);c.pluralKebab=e,c.pluralPascal=R(e),c.pluralCamel=z(e)}return c}function ot(e,t){return P(e.cwd,t)}async function st(e){return import(F(e).href)}const ct=new Map;async function lt(e){let t=ct.get(e);if(t)return t;let n=ut(e);return ct.set(e,n),n}async function ut(e){let t=P(e,`package.json`);if(!O(t))return{generators:[],loaded:[],failed:[]};let n=dt(JSON.parse(await I(t,`utf-8`))),r=je(P(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 I(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=P(j(t),s);if(!O(c)){o.push({source:e,reason:`kickjs.generators points to missing file: ${s}`});continue}let l;try{l=await st(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(!ft(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 dt(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 ft(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.name==`string`&&typeof t.files==`function`}async function pt(e,t=[]){let n=e.cwd??process.cwd(),r=t.find(t=>t.spec.name===e.generatorName);if(r)return gt(r.spec,r.source,e,n);let i=ht(await lt(n),e.generatorName);return i?gt(i.spec,i.source,e,n):null}async function mt(e,t=[]){let n=await lt(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 ht(e,t){return e.generators.find(e=>e.spec.name===t)}async function gt(e,t,n,r){let i=at({name:n.itemName,args:n.args,flags:n.flags,modulesDir:n.modulesDir,pluralize:n.pluralize,cwd:r,projectRoot:n.projectRoot}),a=await e.files(i),o=[];for(let e of a){let t=ot(i,e.path);await y(t,e.content),o.push(t)}return{files:o,source:t}}function H(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}const _t={inmemory:`in-memory`,drizzle:`Drizzle`,prisma:`Prisma`};function vt(e){return e.charAt(0).toUpperCase()+e.slice(1).replace(/-([a-z])/g,(e,t)=>t.toUpperCase())}function yt(e){return _t[e]??vt(e)}function bt(e){return`create${e}Repository`}function xt(e){return e??`define`}function St(e){let{pascal:t,kebab:n,plural:r=``,repo:i,style:a}=e,o=bt(t),s=xt(a),c=`/**
|
|
11
|
+
import{t as e}from"./rolldown-runtime-BhxEEqxa.mjs";import{c as t,i as n,l as r,o as i,p as a,r as o,s,t as c}from"./project-AXCA1hD9.mjs";import{a as l,c as u,i as d,l as f,o as p,r as m,s as h}from"./config-SvlcF3Ls.mjs";import{n as g,r as _}from"./plugin-Dn67elEZ.mjs";import{n as v,r as y,t as b}from"./fs-v57MCgpH.mjs";import{a as x,c as S,d as ee,f as C,i as te,l as ne,n as re,o as ie,p as ae,r as w,s as T,u as oe}from"./agent-docs-BU1rORKA.mjs";import{t as E}from"./project-root-Dgvy5kYG.mjs";import{C as se,S as D,T as ce,_ as le,a as ue,b as de,c as fe,d as pe,f as me,g as he,h as ge,i as _e,l as ve,m as ye,o as be,p as xe,r as Se,s as Ce,t as we,u as Te,v as Ee,w as De,x as Oe,y as ke}from"./typegen-97E_RYNp.mjs";import{t as Ae}from"./build-DlfIkjcw.mjs";import{createRequire as je}from"node:module";import{cpSync as Me,existsSync as O,mkdirSync as Ne,readFileSync as k,readdirSync as Pe,rmSync as Fe,statSync as Ie,writeFileSync as Le}from"node:fs";import A,{basename as Re,dirname as j,join as M,relative as N,resolve as P,sep as ze}from"node:path";import{fileURLToPath as Be,pathToFileURL as F}from"node:url";import{fork as Ve,spawn as He,spawnSync as Ue}from"node:child_process";import{copyFile as We,mkdir as Ge,readFile as I,readdir as Ke,rm as qe,stat as Je,writeFile as L}from"node:fs/promises";import"@forinda/kickjs-cli-kit";import{parseSync as Ye}from"oxc-parser";import Xe from"pluralize";import{arch as Ze,platform as Qe,release as $e}from"node:os";import{createHash as et}from"node:crypto";const tt=[{value:`swagger`,label:`Swagger`,hint:`OpenAPI docs`},{value:`ws`,label:`WebSocket`,hint:`rooms, heartbeat`},{value:`queue`,label:`Queue`,hint:`BullMQ/RabbitMQ/Kafka`},{value:`devtools`,label:`DevTools`,hint:`debug dashboard`}];function nt(e){e.command(`new [name]`).alias(`init`).description(`Create a new KickJS project (use "." for current directory)`).option(`-d, --directory <dir>`,`Target directory (defaults to project name)`).option(`--pm <manager>`,`Package manager: pnpm | npm | yarn | bun`).option(`--git`,`Initialize git repository`).option(`--no-git`,`Skip git initialization`).option(`--install`,`Install dependencies after scaffolding`).option(`--no-install`,`Skip dependency installation`).option(`-f, --force`,`Remove existing files without prompting`).option(`-t, --template <type>`,`Project template: rest | minimal | fullstack`).option(`--runtime <engine>`,`HTTP runtime: express | fastify | h3`).option(`-r, --repo <type>`,`Repository name (inmemory, or any DB name e.g. postgres)`).option(`-s, --schema <lib>`,`Schema library for env / DTOs: zod | valibot | yup (default: zod)`).option(`--frontend <kind>`,`Fullstack web/ scaffold: 'kick' (wired React app) or 'vite' (create-vite, unwired)`).option(`--vite-template <name>`,`create-vite TypeScript template for --frontend vite (default 'react-ts')`).option(`--packages <packages>`,`Comma-separated packages to include (e.g. swagger,ws,queue,devtools)`).option(`-y, --yes`,`Pick safe defaults for every prompt (template=minimal, repo=inmemory, no extras, git+install on)`).option(`--non-interactive`,`alias for --yes`).action(async(e,t)=>{te(`KickJS — Create a new project`);let n=!!(t.yes||t.nonInteractive);e||=n?`my-api`:await oe({message:`Project name`,placeholder:`my-api`,defaultValue:`my-api`});let i;if(e===`.`?(i=P(`.`),e=Re(i)):i=P(t.directory||e),O(i)){let r=Pe(i);if(r.length>0){if(t.force)x.warn(`Clearing existing files in ${i}`);else if(n){x.warn(`Directory "${e}" is not empty. Pass --force to clear it.`),T(`Aborted.`);return}else{x.warn(`Directory "${e}" is not empty:`);let t=r.slice(0,5);for(let e of t)x.message(` - ${e}`);if(r.length>5&&x.message(` ... and ${r.length-5} more`),!await w({message:C.red(`Remove all existing files and proceed?`),initialValue:!1})){T(`Aborted.`);return}}for(let e of r)Fe(P(i,e),{recursive:!0,force:!0})}}let a=t.template;a||=n?`minimal`:await S({message:`Project template`,options:[{value:`rest`,label:`REST API`,hint:`Express + Swagger`},{value:`minimal`,label:`Minimal`,hint:`bare Express`},{value:`fullstack`,label:`Fullstack`,hint:`server + Vite React web, typed client`}]});let o=t.runtime;o||=n?`express`:await S({message:`HTTP runtime`,options:[{value:`express`,label:`Express`,hint:`default, zero-config`},{value:`fastify`,label:`Fastify`,hint:`fastify + @fastify/middie`},{value:`h3`,label:`h3`,hint:`Nitro / Nuxt engine`}]});let s=t.pm;s||=n?await r(void 0):await S({message:`Package manager`,options:[{value:`pnpm`,label:`pnpm`},{value:`npm`,label:`npm`},{value:`yarn`,label:`yarn`},{value:`bun`,label:`bun`}]});let l=t.repo;l||=n?`inmemory`:await oe({message:`Repository name`,placeholder:`inmemory (or a DB name, e.g. postgres)`,defaultValue:`inmemory`}),f(l);let u=t.schema;u||=n?`zod`:await S({message:`Schema library (env + DTO validation)`,options:[{value:`zod`,label:`Zod`,hint:`default — broad ecosystem`},{value:`valibot`,label:`Valibot`,hint:`smaller bundle`},{value:`yup`,label:`Yup`,hint:`classic API`}]}),[`zod`,`valibot`,`yup`].includes(u)||(x.warn(`Unknown --schema "${u}", falling back to zod.`),u=`zod`);let d;if(t.packages!==void 0){let e=t.packages.trim().toLowerCase();d=e===``||e===`none`||e===`false`?[]:t.packages.split(`,`).map(e=>e.trim()).filter(Boolean)}else d=n?[]:await ie({message:`Select packages to include`,options:[...tt],required:!1});let p;p=t.git===void 0?n?!0:await w({message:`Initialize git repository?`,initialValue:!0}):t.git;let m;if(m=t.install===void 0?n?!0:await w({message:`Install dependencies?`,initialValue:!0}):t.install,t.frontend!==void 0&&t.frontend!==`kick`&&t.frontend!==`vite`){x.error(`Unknown --frontend '${String(t.frontend)}'. Use 'kick' (wired React app) or 'vite' (create-vite).`),T(`Aborted.`);return}let{VITE_TEMPLATES:h,DEFAULT_VITE_TEMPLATE:g}=await import(`./fullstack-DOufUeMv.mjs`);if(t.viteTemplate!==void 0&&!h.some(e=>e.value===t.viteTemplate)){x.error(`Unknown --vite-template '${String(t.viteTemplate)}'. TypeScript templates only: ${h.map(e=>e.value).join(`, `)}.`),T(`Aborted.`);return}let _=t.frontend===`vite`?`vite`:`kick`,v=t.viteTemplate??g;if(a===`fullstack`&&!t.frontend&&!n&&(_=await S({message:`Frontend for web/`,options:[{value:`kick`,label:`KickJS React app`,hint:`typed client, /api proxy, route types — wired`},{value:`vite`,label:`Delegate to create-vite`,hint:`pick any framework; wiring is manual (guide printed after)`}]})),_===`vite`&&!t.viteTemplate&&!n&&(v=await S({message:`create-vite template`,options:h.map(e=>({value:e.value,label:e.label})),initialValue:g})),a===`fullstack`){let{initFullstackProject:t}=await import(`./fullstack-DOufUeMv.mjs`);await t({name:e,directory:i,packageManager:s,initGit:p,installDeps:m,schemaLib:u,runtime:o,packages:d,frontend:_,viteTemplate:v}),T(`Done! Next steps: ${C.cyan(`cd ${e} && ${s}${s===`pnpm`?` dev`:` run dev:server`}`)}`);return}await c({name:e,directory:i,packageManager:s,initGit:p,installDeps:m,template:a,defaultRepo:l,packages:d,schemaLib:u,runtime:o}),T(`Done! Next steps: ${C.cyan(`cd ${e} && ${s} dev`)}`)})}function R(e){return e.replace(/[-_\s]+(.)?/g,(e,t)=>t?t.toUpperCase():``).replace(/^(.)/,e=>e.toUpperCase())}function z(e){let t=R(e);return t.charAt(0).toLowerCase()+t.slice(1)}function B(e){return e.replace(/([a-z])([A-Z])/g,`$1-$2`).replace(/[\s_]+/g,`-`).toLowerCase()}function V(e){return Xe.plural(e)}function rt(e){return Xe.plural(e)}function it(e){return B(e).replace(/-/g,`_`)}function at(e){let t=e.cwd??process.cwd(),n=e.projectRoot??E(t),r=e.pluralize??!0,i=R(e.name),a=z(e.name),o=B(e.name),s=it(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=V(o);c.pluralKebab=e,c.pluralPascal=R(e),c.pluralCamel=z(e)}return c}function ot(e,t){return P(e.cwd,t)}async function st(e){return import(F(e).href)}const ct=new Map;async function lt(e){let t=ct.get(e);if(t)return t;let n=ut(e);return ct.set(e,n),n}async function ut(e){let t=P(e,`package.json`);if(!O(t))return{generators:[],loaded:[],failed:[]};let n=dt(JSON.parse(await I(t,`utf-8`))),r=je(P(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 I(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=P(j(t),s);if(!O(c)){o.push({source:e,reason:`kickjs.generators points to missing file: ${s}`});continue}let l;try{l=await st(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(!ft(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 dt(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 ft(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.name==`string`&&typeof t.files==`function`}async function pt(e,t=[]){let n=e.cwd??process.cwd(),r=t.find(t=>t.spec.name===e.generatorName);if(r)return gt(r.spec,r.source,e,n);let i=ht(await lt(n),e.generatorName);return i?gt(i.spec,i.source,e,n):null}async function mt(e,t=[]){let n=await lt(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 ht(e,t){return e.generators.find(e=>e.spec.name===t)}async function gt(e,t,n,r){let i=at({name:n.itemName,args:n.args,flags:n.flags,modulesDir:n.modulesDir,pluralize:n.pluralize,cwd:r,projectRoot:n.projectRoot}),a=await e.files(i),o=[];for(let e of a){let t=ot(i,e.path);await y(t,e.content),o.push(t)}return{files:o,source:t}}function H(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}const _t={inmemory:`in-memory`,drizzle:`Drizzle`,prisma:`Prisma`};function vt(e){return e.charAt(0).toUpperCase()+e.slice(1).replace(/-([a-z])/g,(e,t)=>t.toUpperCase())}function yt(e){return _t[e]??vt(e)}function bt(e){return`create${e}Repository`}function xt(e){return e??`define`}function St(e){let{pascal:t,kebab:n,plural:r=``,repo:i,style:a}=e,o=bt(t),s=xt(a),c=`/**
|
|
12
12
|
* ${t} Module
|
|
13
13
|
*
|
|
14
14
|
* REST module with a flat folder structure.
|
|
@@ -1290,7 +1290,7 @@ describe('${o}', () => {
|
|
|
1290
1290
|
Example: kick g scaffold Post title:string body:text:optional published:boolean:optional
|
|
1291
1291
|
Optional: append :optional (shell-safe, no quoting needed)
|
|
1292
1292
|
`),process.exit(1));let a=await l(process.cwd()),o=p(a),s=n.modulesDir??o.dir??`src/modules`,c=_n(t),f=u(a,process.cwd()),m=d(E()),h=await vn({name:e,fields:c,modulesDir:P(s),noEntity:n.entity===!1,noTests:n.tests===!1,pluralize:n.pluralize===!1?!1:o.pluralize??!0,tokenScope:f,swagger:m,style:o.style});console.log(`\n Scaffolded ${e} with ${c.length} field(s):`);for(let e of c)console.log(` ${e.name}: ${e.type}${e.optional?` (optional)`:``}`);q(h,i),await En(i)}),n.command(`config`).description(`Generate a kick.config.ts at the project root`).option(`--modules-dir <dir>`,`Modules directory path`,`src/modules`).option(`--repo <type>`,`Repository name: inmemory (default) or any DB name`,`inmemory`).option(`-f, --force`,`Overwrite existing kick.config.ts without prompting`).action(async(e,t)=>{let n=K(t);v(n),q(await nn({outDir:P(`.`),modulesDir:e.modulesDir,defaultRepo:e.repo,force:e.force}),n)}),n.command(`agents`).alias(`agent-docs`).alias(`ai-docs`).description(`Regenerate .agents/* + root CLAUDE.md (sync after framework upgrades)`).option(`--only <which>`,`Limit scope: agents | claude | skills | gemini | copilot | both (agents+claude) | all (default: all)`,`all`).option(`--name <name>`,`Project name (defaults to package.json name)`).option(`--pm <pm>`,`Package manager (defaults to package.json packageManager)`).option(`--template <template>`,`Template: rest | minimal | fullstack`).option(`-f, --force`,`Overwrite existing files without prompting`).action(async(e,t)=>{let n=K(t);v(n);let r=e.only??`all`;if(!Tn.includes(r)){console.error(` Invalid --only value: ${r}. Expected: ${Tn.join(` | `)}`),process.exitCode=1;return}q(await re({outDir:P(`.`),only:r,name:e.name,pm:e.pm,template:e.template,force:e.force}),n)});for(let e of t?.generators??[])Nn(n,e,t?.projectRoot)}function Nn(e,t,n){let{source:r,spec:i}=t,a=i.args?.[0],o=a?.name??`itemName`,s=a?.required?`<${o}>`:`[${o}]`,c=`${i.name} ${s} [extraArgs...]`,l=e.command(c).description(`${i.description} [${r}]`);for(let e of i.flags??[]){let t=e.takesValue?`--${e.name} <value>`:`--${e.name}`,n=e.alias?`-${e.alias}, ${t}`:t;l.option(n,e.description??``)}l.action(async(e,r,a,o)=>{let s=K(o);v(s);let c=await pt({generatorName:i.name,itemName:e??``,args:r??[],flags:a,cwd:process.cwd(),projectRoot:n},[t]);c&&q(c.files,s)})}const Pn=`/* AUTO-GENERATED by kick typegen — do not edit. Plugin: `;async function Fn(e){let t=A.resolve(e.cwd,`.kickjs/types`);e.check||await Ge(t,{recursive:!0});let n=new Map,r=e.scan??he,i=A.resolve(e.cwd,`.kickjs`,`cache`),a=e.scan?void 0:e.changedFiles,o={cwd:e.cwd,config:e.config,async importTs(e){return await import(F(e).href)},async writeFile(t,n){let r=A.resolve(e.cwd,t);await Ge(A.dirname(r),{recursive:!0}),await L(r,n,`utf8`)},getScanResult:e=>{let t=In(e),o=n.get(t);if(!o){let s={cacheDir:i,...e};o=a?le(s,a):r(s),n.set(t,o)}return o},log:console,watch:e.watch,check:e.check},s=[],c=[];for(let n of e.plugins){let r=n.outExtension??`.d.ts`,i=A.join(t,`${n.id.replace(/\//g,`__`)}${r}`),a;try{a=await n.generate(o)}catch(t){let r=t instanceof Error?t.message:String(t);if(e.check)throw Error(`kick typegen --check: ${n.id} failed to generate (${r})`,{cause:t});o.log.error(` ${n.id}: typegen failed (${r}) — keeping previous output`),s.push({id:n.id,status:`error`,outFile:i});continue}if(a===null){s.push({id:n.id,status:`skipped`});continue}let l=`${Pn}${n.id} */\n\n`+a+`
|
|
1293
|
-
`,u=``;if(O(i)&&(u=await I(i,`utf8`)),u===l){s.push({id:n.id,status:`unchanged`,outFile:i});continue}if(e.check){c.push({id:n.id,outFile:i}),s.push({id:n.id,status:`drifted`,outFile:i});continue}await L(i,l,`utf8`),s.push({id:n.id,status:`written`,outFile:i})}if(c.length>0)throw new wn(c);return s}function In(e){let t=(e.extensions??[]).slice().toSorted().join(`,`),n=(e.exclude??[]).slice().toSorted().join(`,`);return[`root=${e.root}`,`cwd=${e.cwd}`,`extensions=${t}`,`exclude=${n}`,`envFile=${e.envFile??``}`].join(`|`)}function Ln(e,t){let n=new Set(t),r=[],i=[],a=new Set;for(let t of e)n.has(t.id)?(i.push(t),a.add(t.id)):r.push(t);return{enabled:r,skipped:i,unknown:[...n].filter(e=>!a.has(e))}}var Rn=e({applyDisableFilter:()=>Ln,runAllPluginTypegens:()=>zn});async function zn(e){let t=[...
|
|
1293
|
+
`,u=``;if(O(i)&&(u=await I(i,`utf8`)),u===l){s.push({id:n.id,status:`unchanged`,outFile:i});continue}if(e.check){c.push({id:n.id,outFile:i}),s.push({id:n.id,status:`drifted`,outFile:i});continue}await L(i,l,`utf8`),s.push({id:n.id,status:`written`,outFile:i})}if(c.length>0)throw new wn(c);return s}function In(e){let t=(e.extensions??[]).slice().toSorted().join(`,`),n=(e.exclude??[]).slice().toSorted().join(`,`);return[`root=${e.root}`,`cwd=${e.cwd}`,`extensions=${t}`,`exclude=${n}`,`envFile=${e.envFile??``}`].join(`|`)}function Ln(e,t){let n=new Set(t),r=[],i=[],a=new Set;for(let t of e)n.has(t.id)?(i.push(t),a.add(t.id)):r.push(t);return{enabled:r,skipped:i,unknown:[...n].filter(e=>!a.has(e))}}var Rn=e({applyDisableFilter:()=>Ln,runAllPluginTypegens:()=>zn});async function zn(e){let t=[...fo,...e.config?.plugins??[]],{enabled:n,skipped:r,unknown:i}=Ln(g(t,e.config?.commands??[]).typegens,e.config?.typegen?.disable??[]);if(!e.silent&&r.length>0)for(let e of r)console.log(` ${e.id}: disabled (typegen.disable)`);if(!e.silent&&i.length>0&&console.warn(` kick typegen: disable list references unknown id(s): ${i.map(e=>`'${e}'`).join(`, `)}. Run \`kick typegen --list\` to see registered ids.`),n.length===0)return[];try{let t=await Fn({cwd:e.cwd,config:e.config??{},plugins:n,watch:e.watch,check:e.check,changedFiles:e.changedFiles});if(!e.silent&&Cn())for(let e of t)console.log(` ${e.id}: ${e.status}`);return t}catch(t){if(t instanceof wn||e.check)throw t;if(!e.silent){let e=t instanceof Error?t.message:String(t);console.warn(` kick typegen plugins: skipped (${e})`)}return[]}}function Bn(e){let t=new Map;return{report(n,r){let i=r instanceof Error?r.message:String(r);t.get(n)!==i&&(t.set(n,i),e(` kick typegen: ${n} pass failed (${i}) — types in .kickjs/types may be stale`))},clear(e){t.delete(e)}}}function Vn(e){let{cwd:t,config:n}=e,r=e.debounceMs??100,i=e.pipeline??{runTypegen:async e=>(await import(`./typegen-97E_RYNp.mjs`).then(e=>e.n)).runTypegen(e),runAllPluginTypegens:async e=>(await Promise.resolve().then(()=>Rn)).runAllPluginTypegens(e),writeTypegenArtifacts:async(e,t,n)=>(await import(`./typegen-97E_RYNp.mjs`).then(e=>e.n)).writeTypegenArtifacts(e,t,n),buildAssets:async(e,t)=>(await import(`./build-DlfIkjcw.mjs`).then(e=>e.n)).buildAssets(e,t)},a=n?.typegen?.schemaValidator??`zod`,o=n?.typegen?.envFile,s=A.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=>A.resolve(t,e)):[],l=!!n?.assetMap&&Object.keys(n.assetMap).length>0,u=e=>e.replaceAll(`\\`,`/`),d=c.map(u),f=e=>{let t=u(e);return d.some(e=>t===e||t.startsWith(`${e}/`))},p=Bn(e.emitWarning),m=null,h=!1,g=new Set,_=new Set,v=!1,y=!1;function b(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(()=>p.clear(`scan`)).catch(e=>p.report(`scan`,e)),i.runAllPluginTypegens({cwd:t,config:n,silent:!0,changedFiles:r,watch:!0}).then(e=>i.writeTypegenArtifacts(s,e,!0)).then(()=>p.clear(`plugins`)).catch(e=>p.report(`plugins`,e)).finally(()=>e.onPassComplete?.()),c&&n&&i.buildAssets(n,{cwd:t,silent:!0}).catch(()=>{})}function x(){let e=v?void 0:{changed:[...g],removed:[..._]},t=y;g.clear(),_.clear(),v=!1,y=!1,b(e,t)}return{assetSrcRoots:c,handleWatchEvent(e,t){if(!h&&!u(t).includes(`/.kickjs/`)){if(e===`unlinkDir`)v=!0,l&&(y=!0);else{if(t.endsWith(`.d.ts`))return;let n=/\.(ts|tsx|mts|cts)$/.test(t),r=f(t);if(!n&&!r)return;r&&l&&(y=!0),n&&(e===`unlink`?(_.add(t),g.delete(t)):(g.add(t),_.delete(t)))}m&&clearTimeout(m),m=setTimeout(x,r)}},runOnce(){h||b(void 0,l)},dispose(){h=!0,m&&clearTimeout(m),m=null}}}function Hn(e){let t=M(e,`node_modules`,`.bin`),n=process.platform===`win32`;for(let e of[`vue-tsc`,`tsgo`,`tsc`]){let r=n?[`${e}.CMD`,`${e}.cmd`,`${e}.exe`]:[e];for(let i of r){let r=M(t,i);if(O(r))return{cmd:r,args:[`--noEmit`],shell:n,kind:e}}}return null}function Un(e){let t=e.spawnFn??He,n=null,r=0,i=!1;return{schedule(){if(i)return;let a=++r;n&&=(n.kill(),null);let o=Date.now(),s=t(e.bin.cmd,e.bin.args,{cwd:e.cwd,shell:e.bin.shell,stdio:[`ignore`,`pipe`,`pipe`]});n=s;let c=``;s.stdout?.on(`data`,e=>{c+=e.toString()}),s.stderr?.on(`data`,e=>{c+=e.toString()}),s.on(`error`,()=>{a===r&&(n=null)}),s.on(`close`,t=>{i||a!==r||(n=null,e.onResult({ok:t===0,output:c,durationMs:Date.now()-o,kind:e.bin.kind}))})},dispose(){i=!0,n&&=(n.kill(),null)}}}function Wn(e,t=12){let n=e.trim().split(/\r?\n/);return n.length<=t?n.join(`
|
|
1294
1294
|
`):`${n.slice(0,t).join(`
|
|
1295
1295
|
`)}\n… ${n.length-t} more line(s)`}function Gn(e){if(typeof e==`boolean`)return e;let t=process.env.KICKJS_WATCH_POLLING;return t===`1`||t===`true`}async function Kn(e,t=`127.0.0.1`){let n=await import(`node:inspector`);n.open(e,t,!1);let r=n.url();if(!r)throw Error(`inspector.open() reported no URL`);return r}async function qn(e,t,n={}){t&&(process.env.PORT=t);let r=Gn(n.polling),i=process.cwd(),a=await l(i),o=a?.typegen?.schemaValidator??`zod`,s=a?.typegen?.envFile;try{await we({cwd:i,allowDuplicates:!0,schemaValidator:o,envFile:s,srcDir:a?.typegen?.srcDir,outDir:a?.typegen?.outDir,assetMap:a?.assetMap,runPlugins:!1})}catch(e){console.warn(` kick typegen: skipped (${e?.message??e})`)}let c=P(i,a?.typegen?.outDir??`.kickjs/types`);try{let e=await zn({cwd:i,config:a});await _e(c,e,!1)}catch(e){console.warn(` kick typegen: plugin pass skipped (${e?.message??e})`)}let{createRequire:u}=await import(`node:module`),d=u(P(`package.json`)).resolve(`vite`),{createServer:f}=await import(F(d).href);globalThis.__kickjs_typegen_owner=`kick-dev`;let p=await f({configFile:P(`vite.config.ts`),server:{port:t?parseInt(t,10):void 0,...r?{watch:{usePolling:!0,interval:100}}:{}}}),m=n.typecheck??a?.dev?.typecheck??!1,h=null,g=!0;if(m){let e=Hn(i);e?h=Un({cwd:i,bin:e,onResult:e=>{p.hot.send({type:`custom`,event:`kickjs:typecheck`,data:{ok:e.ok,output:e.output,durationMs:e.durationMs}}),e.ok?g||(g=!0,console.log(` kick typecheck: clean again (${e.kind}, ${e.durationMs}ms)`)):(g=!1,console.warn(`\n kick typecheck (${e.kind}, ${e.durationMs}ms):`),console.warn(Wn(e.output).replace(/^/gm,` `)))}}):console.warn(` kick dev: --typecheck requested but neither tsgo (@typescript/native-preview) nor typescript is installed in this project — skipping type checks.`)}let _=Vn({cwd:i,config:a,emitWarning:e=>{console.warn(e),p.hot.send({type:`custom`,event:`kickjs:typegen-error`,data:{message:e,timestamp:Date.now()}})},onPassComplete:()=>h?.schedule()});p.watcher.on(`add`,e=>_.handleWatchEvent(`add`,e)),p.watcher.on(`unlink`,e=>_.handleWatchEvent(`unlink`,e)),p.watcher.on(`change`,e=>_.handleWatchEvent(`change`,e)),p.watcher.on(`unlinkDir`,e=>_.handleWatchEvent(`unlinkDir`,e)),_.assetSrcRoots.length>0&&p.watcher.add([..._.assetSrcRoots]),await p.listen(),p.printUrls(),console.log(`
|
|
1296
1296
|
KickJS dev server running (Vite + @forinda/kickjs-vite)
|
|
@@ -1307,12 +1307,12 @@ describe('${o}', () => {
|
|
|
1307
1307
|
`)}),e.command(`build:assets`).description(`Rebuild the .kickjs-assets.json manifest under the configured outDir (no JS rebuild)`).action(async()=>{let e=await l(process.cwd());if(!e?.assetMap||Object.keys(e.assetMap).length===0){console.log(` No assetMap entries — nothing to build.`);return}console.log(`
|
|
1308
1308
|
Building asset map...`);try{await Ae(e,{cwd:process.cwd()}),console.log(`
|
|
1309
1309
|
Asset build complete.
|
|
1310
|
-
`)}catch(e){console.error(` ✗ ${e instanceof Error?e.message:String(e)}`),process.exit(1)}}),e.command(`start`).description(`Start production server`).option(`-e, --entry <file>`,`Entry file`,`dist/index.js`).option(`-p, --port <port>`,`Port number`).action(e=>{let t={NODE_ENV:`production`};e.port&&(t.PORT=String(e.port)),
|
|
1310
|
+
`)}catch(e){console.error(` ✗ ${e instanceof Error?e.message:String(e)}`),process.exit(1)}}),e.command(`start`).description(`Start production server`).option(`-e, --entry <file>`,`Entry file`,`dist/index.js`).option(`-p, --port <port>`,`Port number`).action(e=>{let t={NODE_ENV:`production`};e.port&&(t.PORT=String(e.port)),a(e.entry,t)}),e.command(`typecheck`).description(`Type-check the project with its own tsgo/tsc`).option(`--cwd <dir>`,`Directory to type-check`,`.`).option(`--no-typegen`,`Skip refreshing .kickjs/types first`).action(async e=>{let t=P(process.cwd(),e.cwd??`.`);e.typegen!==!1&&await Jn(t);let n=Hn(t);if(!n){console.error(`
|
|
1311
1311
|
No type-checker found. Install one in this project:
|
|
1312
1312
|
pnpm add -D typescript (tsc)
|
|
1313
1313
|
pnpm add -D @typescript/native-preview (tsgo, faster)
|
|
1314
1314
|
`),process.exit(1);return}let r=Ue(n.cmd,n.args,{stdio:`inherit`,shell:n.shell,cwd:t});process.exit(r.status??1)}),e.command(`dev:debug`).description(`Start dev server with Node.js inspector attached`).option(`-e, --entry <file>`,`Entry file`,`src/index.ts`).option(`-p, --port <port>`,`Port number`).option(`--inspect-port <port>`,`Inspector port`,`9229`).option(`--inspect-host <host>`,`Inspector bind address (use 0.0.0.0 to reach it from outside a container)`,`127.0.0.1`).action(async e=>{let t=Number(e.inspectPort??`9229`),n=e.inspectHost??`127.0.0.1`;[`127.0.0.1`,`localhost`,`::1`].includes(n)||console.warn(` WARNING: the debugger is bound to ${n}, not loopback. Anyone who can\n reach port ${t} can run code in this process. Use it on a trusted\n network only, and prefer publishing the port from your container instead.`);let r;try{r=await Kn(t,n)}catch(e){console.error(`\n Could not open the inspector on ${t}: ${e.message??e}\n Another process may already hold it — try --inspect-port <port>.`),process.exit(1);return}console.log(` Debugger: ${r}`);try{await qn(e.entry,e.port)}catch(e){console.error(`
|
|
1315
|
-
Dev server (debug) failed:`,e.message??e),process.exit(1)}})}function Xn(){try{let e=j(Be(import.meta.url));return JSON.parse(k(M(e,`..`,`package.json`),`utf-8`)).version??`unknown`}catch{return`unknown`}}const Zn=new Set(Object.values(
|
|
1315
|
+
Dev server (debug) failed:`,e.message??e),process.exit(1)}})}function Xn(){try{let e=j(Be(import.meta.url));return JSON.parse(k(M(e,`..`,`package.json`),`utf-8`)).version??`unknown`}catch{return`unknown`}}const Zn=new Set(Object.values(o).filter(e=>e.deprecated).map(e=>e.pkg));function Qn(e){let t=M(e,`package.json`);if(!O(t))return[];let n;try{n=JSON.parse(k(t,`utf-8`))}catch{return[]}let r={...n.dependencies,...n.devDependencies};return Object.keys(r).filter(e=>e===`@forinda/kickjs`||e.startsWith(`@forinda/kickjs-`)).toSorted().map(t=>{let n=null,i=M(e,`node_modules`,...t.split(`/`),`package.json`);if(O(i))try{n=JSON.parse(k(i,`utf-8`)).version??null}catch{}return{name:t,installed:n,declared:r[t]??null,deprecated:Zn.has(t)}})}function $n(e){let t=e;for(;;){if(O(M(t,`package.json`)))return t;let e=j(t);if(e===t)return null;t=e}}function er(e){e.command(`info`).description(`Print system and framework info`).action(()=>{let e=[``,` KickJS CLI v${Xn()}`,``,` System:`,` OS: ${Qe()} ${$e()} (${Ze()})`,` Node: ${process.version}`],t=$n(process.cwd()),n=t?Qn(t):[];if(!t)e.push(``,` Packages: (not inside a project — no package.json found)`);else if(n.length===0)e.push(``,` Packages: (no @forinda/kickjs* dependencies in ${t})`);else{e.push(``,` Packages:`);let t=Math.max(...n.map(e=>e.name.length));for(let r of n){let n=r.installed??`${r.declared??`?`} (declared — not installed)`,i=r.deprecated?" [DEPRECATED — see `kick add --list --all`]":``;e.push(` ${r.name.padEnd(t+2)} ${n}${i}`)}}e.push(``),console.log(e.join(`
|
|
1316
1316
|
`))})}const{bold:J,dim:Y,green:tr,red:nr,yellow:rr,blue:ir}=C;function ar(e){let t=Math.floor(e/86400),n=Math.floor(e%86400/3600),r=Math.floor(e%3600/60),i=e%60,a=[];return t&&a.push(`${t}d`),n&&a.push(`${n}h`),r&&a.push(`${r}m`),a.push(`${i}s`),a.join(` `)}async function or(e){let t=await fetch(e,{signal:AbortSignal.timeout(5e3)});if(!t.ok)throw Error(`${t.status} ${t.statusText}`);return t.json()}async function sr(e,t){try{return await or(`${e}${t}`)}catch{return null}}async function cr(e){let[t,n,r,i,a]=await Promise.all([sr(e,`/health`),sr(e,`/metrics`),sr(e,`/routes`),sr(e,`/container`),sr(e,`/ws`)]);return{health:t,metrics:n,routes:r,container:i,ws:a}}function lr(e,t){let{health:n,metrics:r,routes:i,container:a,ws:o}=t,s=Y(`─`.repeat(60));if(console.log(),console.log(J(` KickJS Inspector`)+Y(` → ${e}`)),console.log(s),n){let e=n.status===`healthy`?tr(`● healthy`):nr(`● `+n.status);console.log(` ${J(`Health:`)} ${e}`)}else console.log(` ${J(`Health:`)} ${nr(`● unreachable`)}`);if(r){let e=((r.errorRate??0)*100).toFixed(1),t=r.errorRate>.1?nr:r.errorRate>0?rr:tr;console.log(` ${J(`Uptime:`)} ${ar(r.uptimeSeconds)}`),console.log(` ${J(`Requests:`)} ${r.requests}`),console.log(` ${J(`Errors:`)} ${r.serverErrors} server, ${r.clientErrors??0} client ${Y(`(`)}${t(e+`%`)}${Y(`)`)}`)}if(a&&console.log(` ${J(`DI:`)} ${a.count} bindings`),o&&o.enabled&&console.log(` ${J(`WS:`)} ${o.connections??0} connections, ${o.namespaces??0} namespaces`),i?.routes?.length){console.log(),console.log(J(` Routes`)),console.log(s),console.log(` ${Y(`METHOD`)} ${Y(`PATH`.padEnd(36))} ${Y(`CONTROLLER`)}`);for(let e of i.routes){let t=e.path.length>36?e.path.slice(0,33)+`...`:e.path.padEnd(36);console.log(` ${ee(e.method)} ${t} ${ir(e.controller)}.${Y(e.handler)}`)}}console.log(s),console.log()}function ur(e){e.command(`inspect [url]`).description(`Connect to a running KickJS app and display debug info`).option(`-p, --port <port>`,`Override port`).option(`-w, --watch`,`Poll every 5 seconds`).option(`-j, --json`,`Output raw JSON`).action(async(e,t)=>{let n=e??`http://localhost:3000`;if(t.port)try{let e=new URL(n);e.port=t.port,n=e.origin}catch{n=`http://localhost:${t.port}`}let r=`${n.replace(/\/$/,``)}/_debug`,i=async()=>{try{let e=await cr(r);t.json?console.log(JSON.stringify(e,null,2)):lr(n,e)}catch(e){t.json?console.log(JSON.stringify({error:String(e)})):(console.error(nr(` ✖ Could not connect to ${n}`)),console.error(Y(` ${e instanceof Error?e.message:String(e)}`))),t.watch||(process.exitCode=1)}};if(t.watch){let e=async()=>{process.stdout.write(`\x1B[2J\x1B[H`),await i()};await e(),setInterval(e,5e3)}else await i()})}function X(e,t){let n=e.toLowerCase();return t.every(e=>n.includes(e.toLowerCase()))}function Z(e,t){let n=e.toLowerCase();return t.some(e=>n.includes(e.toLowerCase()))}const dr=[{match(e,t){let n=X(e,[`config`,`get`])&&Z(e,[`undefined`,`null`]),r=e.includes(`@Value`)&&Z(e,[`undefined`,`is not defined`]);return!n&&!r?null:Z(e,[`vitest`,`createTestApp`,`__tests__`,`.test.`,`.spec.`])?{confidence:85,diagnosis:{id:`env-schema-not-registered-in-test`,title:`ConfigService.get() returns undefined inside a test`,explanation:`The env schema is registered by a module-load side effect in
|
|
1317
1317
|
src/config/index.ts, and src/index.ts imports it before bootstrap().
|
|
1318
1318
|
Tests never load src/index.ts — \`createTestApp\` builds the app
|
|
@@ -1622,7 +1622,7 @@ server.on('exit', () => {
|
|
|
1622
1622
|
Cancelled.
|
|
1623
1623
|
`);return}await qe(c,{recursive:!0,force:!0}),console.log(` Deleted: ${c}`);let l=M(n,`index.ts`);if(await b(l)){let e=await I(l,`utf-8`),t=e,n=RegExp(`^import\\s*\\{\\s*${H(o)}Module\\s*\\}\\s*from\\s*['"][^'"]*${H(s)}(?:/[^'"]*)?['"].*\\n?`,`gm`);e=e.replace(n,``),e=Rr(e,o),e=e.replace(/\n{3,}/g,`
|
|
1624
1624
|
|
|
1625
|
-
`),e!==t&&(await L(l,e,`utf-8`),console.log(` Unregistered: ${o}Module from ${l}`))}console.log(`\n Module '${s}' removed.\n`)}function Br(e){e.command(`remove`).alias(`rm`).description(`Remove generated code`).command(`module <names...>`).description(`Remove one or more modules (e.g. kick rm module user task)`).option(`--modules-dir <dir>`,`Modules directory`).option(`--no-pluralize`,`Use singular module name`).option(`-f, --force`,`Skip confirmation prompt`).action(async(e,t)=>{let n=await l(process.cwd()),r=p(n),i=t.modulesDir??r.dir??`src/modules`,a=t.pluralize===!1?!1:r.pluralize??!0;for(let n of e)await zr({name:n,modulesDir:P(i),force:t.force,pluralize:a})})}function Vr(e){if(e!==void 0){if(e===`false`||e===`off`||e===`none`)return!1;if(e===`zod`)return`zod`;if(e===`kickjs-schema`||e===`schema`)return`kickjs-schema`;console.warn(` kick typegen: unknown --schema-validator '${e}' (supported: 'zod', 'kickjs-schema', 'false'). Falling back to project config.`)}}function Hr(e){if(e!==void 0)return e===`false`||e===`off`||e===`none`?!1:e}function Ur(e){e.command(`typegen`).description(`Generate type-safe DI registry and module types into .kickjs/types/`).option(`-w, --watch`,`Watch source files and regenerate on change`).option(`-s, --src <dir>`,`Source directory to scan`,`src`).option(`-o, --out <dir>`,`Output directory`,`.kickjs/types`).option(`--silent`,`Suppress output`).option(`--allow-duplicates`,`Auto-namespace duplicate class names instead of failing (use with caution)`).option(`--schema-validator <name>`,`Schema validator for body/query/params typing (currently 'zod' or 'false')`).option(`--env-file <path>`,`Path to env schema file for KickEnv typing (default 'src/env.ts'; pass 'false' to disable)`).option(`--check`,`CI gate: exit non-zero if any generated file in .kickjs/types/ is out of date (routes, env, db, assets, adopter plugins) instead of writing it`).option(`--fix`,`Patch module import.meta.glob() calls to cover decorated classes that aren't loaded by any glob (orphans)`).option(`--list`,"List every registered typegen plugin id (use to populate `typegen.disable`)").option(`--no-cache`,`Disable the persistent scan cache; re-read + re-extract every file from cold`).action(async e=>{let t=E(process.cwd()),n=await l(t);if(e.list){let{mergeCliPlugins:e}=await import(`./plugin-
|
|
1625
|
+
`),e!==t&&(await L(l,e,`utf-8`),console.log(` Unregistered: ${o}Module from ${l}`))}console.log(`\n Module '${s}' removed.\n`)}function Br(e){e.command(`remove`).alias(`rm`).description(`Remove generated code`).command(`module <names...>`).description(`Remove one or more modules (e.g. kick rm module user task)`).option(`--modules-dir <dir>`,`Modules directory`).option(`--no-pluralize`,`Use singular module name`).option(`-f, --force`,`Skip confirmation prompt`).action(async(e,t)=>{let n=await l(process.cwd()),r=p(n),i=t.modulesDir??r.dir??`src/modules`,a=t.pluralize===!1?!1:r.pluralize??!0;for(let n of e)await zr({name:n,modulesDir:P(i),force:t.force,pluralize:a})})}function Vr(e){if(e!==void 0){if(e===`false`||e===`off`||e===`none`)return!1;if(e===`zod`)return`zod`;if(e===`kickjs-schema`||e===`schema`)return`kickjs-schema`;console.warn(` kick typegen: unknown --schema-validator '${e}' (supported: 'zod', 'kickjs-schema', 'false'). Falling back to project config.`)}}function Hr(e){if(e!==void 0)return e===`false`||e===`off`||e===`none`?!1:e}function Ur(e){e.command(`typegen`).description(`Generate type-safe DI registry and module types into .kickjs/types/`).option(`-w, --watch`,`Watch source files and regenerate on change`).option(`-s, --src <dir>`,`Source directory to scan`,`src`).option(`-o, --out <dir>`,`Output directory`,`.kickjs/types`).option(`--silent`,`Suppress output`).option(`--allow-duplicates`,`Auto-namespace duplicate class names instead of failing (use with caution)`).option(`--schema-validator <name>`,`Schema validator for body/query/params typing (currently 'zod' or 'false')`).option(`--env-file <path>`,`Path to env schema file for KickEnv typing (default 'src/env.ts'; pass 'false' to disable)`).option(`--check`,`CI gate: exit non-zero if any generated file in .kickjs/types/ is out of date (routes, env, db, assets, adopter plugins) instead of writing it`).option(`--fix`,`Patch module import.meta.glob() calls to cover decorated classes that aren't loaded by any glob (orphans)`).option(`--list`,"List every registered typegen plugin id (use to populate `typegen.disable`)").option(`--no-cache`,`Disable the persistent scan cache; re-read + re-extract every file from cold`).action(async e=>{let t=E(process.cwd()),n=await l(t);if(e.list){let{mergeCliPlugins:e}=await import(`./plugin-Dn67elEZ.mjs`).then(e=>e.t),{builtinCliPlugins:t}=await Promise.resolve().then(()=>uo),r=e([...t,...n?.plugins??[]],n?.commands??[]),i=new Set(n?.typegen?.disable??[]);if(r.typegens.length===0){console.log(` No typegen plugins registered.`);return}let a=Math.max(...r.typegens.map(e=>e.id.length));console.log(`
|
|
1626
1626
|
Registered typegen plugins:
|
|
1627
1627
|
`);for(let e of r.typegens){let t=i.has(e.id)?` (disabled)`:``,n=`${e.id.replace(/\//g,`__`)}${e.outExtension??`.d.ts`}`;console.log(` ${e.id.padEnd(a+2)}→ .kickjs/types/${n}${t}`),console.log(` ${` `.repeat(a+2)} watches: ${e.inputs.join(`, `)||`(none)`}`)}console.log(`
|
|
1628
1628
|
Disable one in kick.config.ts:
|
|
@@ -1632,14 +1632,14 @@ server.on('exit', () => {
|
|
|
1632
1632
|
`):e instanceof wn?console.error(`
|
|
1633
1633
|
`+e.message+`
|
|
1634
1634
|
`):e instanceof Error?console.error(`\n kick typegen failed: ${e.message}`):console.error(`\n kick typegen failed: ${JSON.stringify(e)}`),process.exit(1)}})}const Wr=new Set([`Service`,`Injectable`,`Component`,`Repository`]);function Gr(e,t){return typeof t==`number`?e.slice(0,t).split(`
|
|
1635
|
-
`).length:1}function Kr(e){let t=De(e);if(t===`singleton`||t===`transient`||t===`request`)return t;if(se(e)&&e.type===`MemberExpression`&&D(e.object)===`Scope`){let t=D(e.property);if(t===`SINGLETON`)return`singleton`;if(t===`TRANSIENT`)return`transient`;if(t===`REQUEST`)return`request`}return`unknown`}function qr(e){let t=D(e);if(t)return{key:`id:${t}`,label:t};let n=De(e);return n===null?null:{key:`lit:${n}`,label:`'${n}'`}}function Jr(e,t){let n=(e.body?.body??[]).find(e=>e.type===`MethodDefinition`&&e.kind===`constructor`)?.value?.params??[],r=[];for(let e of n){let n=e.type===`TSParameterProperty`?e.parameter:e,i=ke(e).map(Ee).find(e=>e?.name===`Inject`),a=null;if(i)a=qr(i.call.arguments?.[0]);else{let e=n?.typeAnnotation?.typeAnnotation??null;e?.type===`TSTypeReference`&&(a=qr(e.typeName))}a&&r.push({...a,line:Gr(t,e.start)})}return r}function Yr(e){let t=new Map,n=new Map,r=[],i=(e,n)=>{t.has(e)||t.set(e,new Set),t.get(e).add(n)},a=(e,t)=>{e&&(n.has(e)||n.set(e,new Set),n.get(e).add(t))};for(let{path:t,source:n}of e){let e;try{let r=
|
|
1635
|
+
`).length:1}function Kr(e){let t=De(e);if(t===`singleton`||t===`transient`||t===`request`)return t;if(se(e)&&e.type===`MemberExpression`&&D(e.object)===`Scope`){let t=D(e.property);if(t===`SINGLETON`)return`singleton`;if(t===`TRANSIENT`)return`transient`;if(t===`REQUEST`)return`request`}return`unknown`}function qr(e){let t=D(e);if(t)return{key:`id:${t}`,label:t};let n=De(e);return n===null?null:{key:`lit:${n}`,label:`'${n}'`}}function Jr(e,t){let n=(e.body?.body??[]).find(e=>e.type===`MethodDefinition`&&e.kind===`constructor`)?.value?.params??[],r=[];for(let e of n){let n=e.type===`TSParameterProperty`?e.parameter:e,i=ke(e).map(Ee).find(e=>e?.name===`Inject`),a=null;if(i)a=qr(i.call.arguments?.[0]);else{let e=n?.typeAnnotation?.typeAnnotation??null;e?.type===`TSTypeReference`&&(a=qr(e.typeName))}a&&r.push({...a,line:Gr(t,e.start)})}return r}function Yr(e){let t=new Map,n=new Map,r=[],i=(e,n)=>{t.has(e)||t.set(e,new Set),t.get(e).add(n)},a=(e,t)=>{e&&(n.has(e)||n.set(e,new Set),n.get(e).add(t))};for(let{path:t,source:n}of e){let e;try{let r=Ye(t,n);if(r.errors.length>0)continue;e=r.program}catch{continue}for(let n of e.body??[]){let e=(n.type===`ExportNamedDeclaration`||n.type===`ExportDefaultDeclaration`)&&se(n.declaration)?n.declaration:n;if(e.type===`ClassDeclaration`&&a(D(e.id),t),e.type===`VariableDeclaration`)for(let n of e.declarations??[])a(D(n.id),t)}ce(e,e=>{if(e.type===`ClassDeclaration`){let a=D(e.id);if(!a)return;for(let o of ke(e)){let s=Ee(o);if(s){if(s.name===`Controller`){i(`id:${a}`,`singleton`),r.push({name:a,kind:`controller`,file:t,params:Jr(e,n)});return}if(Wr.has(s.name)){let o=Oe(de(s.call),`scope`),c=o?Kr(o):`singleton`;i(`id:${a}`,c),r.push({name:a,kind:`other`,file:t,params:Jr(e,n)});return}}}return}if(e.type!==`CallExpression`)return;let a=e.callee;if(!se(a)||a.type!==`MemberExpression`)return;let o=D(a.property);if(o!==`register`&&o!==`registerFactory`)return;let s=e.arguments??[];if(s.length<2)return;let c=qr(s[0]);c&&i(c.key,s.length>=3?Kr(s[2]):`singleton`)})}let o=e=>(n.get(e)?.size??0)<=1,s=(e,n)=>{let r=t.get(e);return r?.size===1&&r.has(n)},c=[];for(let e of r)if(o(e.name)&&s(`id:${e.name}`,`singleton`))for(let t of e.params){if(t.key.startsWith(`id:`)&&!o(t.label)||!s(t.key,`request`))continue;let n=e.kind===`controller`?`@Controller() is always SINGLETON, so inject ${t.label} with @Autowired() instead of the constructor.`:`Give ${e.name} TRANSIENT or REQUEST scope, or inject ${t.label} with @Autowired() instead of the constructor.`;c.push({file:e.file,line:t.line,parent:e.name,dependency:t.label,message:`${e.name} (SINGLETON) injects REQUEST-scoped ${t.label} through its constructor — the first request that resolves it answers 500. ${n}`})}return c}function Xr(e){let t=[];if(!O(e))return t;let n=Pe(e,{withFileTypes:!0});for(let r of n){let n=M(e,r.name);if(r.isDirectory()){if([`node_modules`,`dist`,`.kickjs`,`.git`].includes(r.name))continue;t.push(...Xr(n))}else r.isFile()&&/\.tsx?$/.test(r.name)&&!r.name.endsWith(`.d.ts`)&&t.push(n)}return t}function Zr(e){try{return k(e,`utf-8`)}catch{return``}}const Qr=new Set([`secret`,`changeme`,`password`,`test`,`default`,``]);function $r(e,t){let n=Zr(M(e,`.env`));if(n){let e=n.match(/^JWT_SECRET\s*=\s*['"]?([^'"\n]*)['"]?/m);if(e){let t=e[1].trim();if(Qr.has(t.toLowerCase())||t.length<32)return{severity:`CRITICAL`,message:`JWT_SECRET appears to be a default value or too short (< 32 chars) — change it`}}}for(let e of t)for(let t of[/JWT_SECRET['"]?\s*[:=]\s*['"]?(secret|changeme|password|test|default)['"]?/i,/secret\s*[:=]\s*['"]?(secret|changeme|password|test|default)['"]?/i])if(t.test(e))return{severity:`CRITICAL`,message:`JWT_SECRET appears to be a default value in source code — use an environment variable`};return null}function ei(e){for(let t of e)if(/cors\s*\(/.test(t)&&/origin\s*:\s*['"]\*['"]/.test(t))return{severity:`CRITICAL`,message:`CORS origin is '*' — restrict to your domains`};return null}function ti(e){for(let t of e)if(/rateLimit/i.test(t)||/@RateLimit/i.test(t))return null;return{severity:`WARNING`,message:`No rate limiting detected — add rateLimit() middleware or @RateLimit decorator`}}function ni(){return process.env.NODE_ENV===`production`?null:{severity:`WARNING`,message:`NODE_ENV is '${process.env.NODE_ENV??`undefined`}', not 'production'`}}function ri(e){let t=!1,n=!1;for(let r of e)/tokenStore/i.test(r)&&(t=!0),/MemoryTokenStore/i.test(r)&&(n=!0);return n?{severity:`WARNING`,message:`MemoryTokenStore detected — use a persistent store (Redis, DB) for production deployments`}:t?null:{severity:`WARNING`,message:`No token revocation store detected — consider adding one for auth token management`}}function ii(e){for(let t of e)if(/helmet\s*\(/.test(t))return/security\s*\.\s*helmet\s*.*false/.test(t)?{severity:`WARNING`,message:`Helmet security headers are disabled — enable them for production`}:{severity:`INFO`,message:`Helmet security headers active`};return{severity:`WARNING`,message:`Helmet not detected — add helmet() middleware for security headers`}}function ai(e){for(let t of e)if(/AuthAdapter/i.test(t))return{severity:`INFO`,message:`AuthAdapter configured`};return{severity:`INFO`,message:`No AuthAdapter detected — add one if your app requires authentication`}}function oi(e){let t=Xr(M(e,`src`)).map(e=>Zr(e)),n=[],r=$r(e,t);r&&n.push(r);let i=ei(t);i&&n.push(i);let a=ti(t);a&&n.push(a);let o=ni();o&&n.push(o);let s=ri(t);return s&&n.push(s),n.push(ii(t)),n.push(ai(t)),n}function si(e){let t=Yr(Xr(M(e,`src`)).filter(e=>!/\.(test|spec)\.tsx?$/.test(e)).map(t=>({path:N(e,t).split(`\\`).join(`/`),source:Zr(t)})));return t.length===0?[{severity:`INFO`,message:`No REQUEST-scoped dependency injected into a singleton`}]:t.map(e=>({severity:`CRITICAL`,message:`${e.file}:${e.line} ${e.message}`}))}function ci(e){e.command(`check`).description(`Audit project for common issues`).option(`--deploy`,`Run production readiness checks`).option(`--di`,`Find REQUEST-scoped dependencies injected into singletons`).action(e=>{if(!e.deploy&&!e.di){console.log(`
|
|
1636
1636
|
Usage: kick check [--deploy] [--di]
|
|
1637
1637
|
|
|
1638
1638
|
Available checks:
|
|
1639
1639
|
--deploy Audit for production readiness (security, config, best practices)
|
|
1640
1640
|
--di Find REQUEST-scoped dependencies injected into singleton constructors
|
|
1641
1641
|
`);return}let t=process.cwd();te(e.deploy?`KickJS Deploy Check`:`KickJS DI Check`);let n=ne();n.start(`Scanning project...`);let r=[...e.deploy?oi(t):[],...e.di?si(t):[]];n.stop(`Scan complete`);let i={CRITICAL:0,WARNING:1,INFO:2};r.sort((e,t)=>i[e.severity]-i[t.severity]);for(let e of r)x.message(`${ae(e.severity)} ${e.message}`);let a=r.filter(e=>e.severity===`CRITICAL`).length,o=r.filter(e=>e.severity===`WARNING`).length,s=r.filter(e=>e.severity===`INFO`).length,c=o===1?`warning`:`warnings`,l=[a>0?C.red(`${a} critical`):`${a} critical`,o>0?C.yellow(`${o} ${c}`):`${o} ${c}`,`${s} info`].join(`, `);a>0?(T(C.red(`${l} — fix critical issues before deploying`)),process.exit(1)):T(C.green(`${l} — looking good!`))})}function li(e){try{return JSON.parse(k(e,`utf-8`))}catch{return null}}function ui(e){try{return k(e,`utf-8`)}catch{return null}}function di(e){let t=e.replace(/\/\*[\s\S]*?\*\//g,``).replace(/(^|[^:"'\\])\/\/.*$/gm,`$1`).replace(/,(\s*[}\]])/g,`$1`);try{return JSON.parse(t)}catch{return null}}function fi(e){let t=M(e,`tsconfig.json`);if(O(t))return pi(t,new Set)}function pi(e,t){if(t.has(e)||t.size>=16)return null;t.add(e);let n=ui(e);if(n===null)return null;let r=di(n);if(typeof r!=`object`||!r)return null;let i=Array.isArray(r.extends)?r.extends:typeof r.extends==`string`?[r.extends]:[],a={};for(let n of i){if(typeof n!=`string`)continue;let r=mi(j(e),n);if(!r)continue;let i=pi(r,t);i&&Object.assign(a,i.compilerOptions)}return r.compilerOptions={...a,...r.compilerOptions},r}function mi(e,t){if(t.startsWith(`.`)||t.startsWith(`/`))return hi(P(e,t));let n=e;for(;;){let e=hi(M(n,`node_modules`,t));if(e)return e;let r=j(n);if(r===n)break;n=r}return null}function hi(e){if(O(e)){try{if(Ie(e).isDirectory()){let t=M(e,`tsconfig.json`);return O(t)?t:null}}catch{return null}return e}let t=`${e}.json`;return O(t)?t:null}function gi(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function _i(){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.
|
|
1642
|
-
Install a supported version via nvm / fnm / volta.`}:{name:`Node version`,status:`pass`,message:e}}function vi(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 yi(e){if(!e.pkg)return null;let t={...e.pkg.dependencies,...e.pkg.peerDependencies};return t[`@forinda/kickjs`]&&!t.express?{name:`express installed`,status:`fail`,fix:"`@forinda/kickjs` declares `express` as a required peer dependency, but your package.json does not include it. Install: pnpm add express"}:t.express?{name:`express installed`,status:`pass`,message:t.express}:null}const bi={express:[],fastify:[`fastify`,`@fastify/middie`],h3:[`h3`]};function xi(e){if(!e.pkg||e.runtime===`express`)return null;let t={...e.pkg.dependencies,...e.pkg.peerDependencies,...e.pkg.devDependencies},n=bi[e.runtime].filter(e=>!t[e]),r=`runtime engine (${e.runtime})`;return n.length>0?{name:r,status:`fail`,fix:`Resolved runtime '${e.runtime}' is missing engine peer(s): ${n.join(`, `)}.\nInstall: pnpm add ${n.join(` `)}`}:{name:r,status:`pass`}}function Si(e){if(!e.pkg||!wi(e.cwd))return null;let n
|
|
1642
|
+
Install a supported version via nvm / fnm / volta.`}:{name:`Node version`,status:`pass`,message:e}}function vi(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 yi(e){if(!e.pkg)return null;let t={...e.pkg.dependencies,...e.pkg.peerDependencies};return t[`@forinda/kickjs`]&&!t.express?{name:`express installed`,status:`fail`,fix:"`@forinda/kickjs` declares `express` as a required peer dependency, but your package.json does not include it. Install: pnpm add express"}:t.express?{name:`express installed`,status:`pass`,message:t.express}:null}const bi={express:[],fastify:[`fastify`,`@fastify/middie`],h3:[`h3`]};function xi(e){if(!e.pkg||e.runtime===`express`)return null;let t={...e.pkg.dependencies,...e.pkg.peerDependencies,...e.pkg.devDependencies},n=bi[e.runtime].filter(e=>!t[e]),r=`runtime engine (${e.runtime})`;return n.length>0?{name:r,status:`fail`,fix:`Resolved runtime '${e.runtime}' is missing engine peer(s): ${n.join(`, `)}.\nInstall: pnpm add ${n.join(` `)}`}:{name:r,status:`pass`}}function Si(e){if(!e.pkg||!wi(e.cwd))return null;let t=n[e.runtime],r=`upload driver (${e.runtime})`;return t.prod?{...e.pkg.dependencies,...e.pkg.peerDependencies,...e.pkg.devDependencies}[t.prod]?{name:r,status:`pass`,message:t.prod}:{name:r,status:`fail`,fix:`This project uses file uploads on the '${e.runtime}' runtime, which needs '${t.prod}'.\nInstall it: kick add upload (or pnpm add ${t.prod})`}:{name:r,status:`pass`,message:`native multipart`}}const Ci=2e3;function wi(e){let t=M(e,`src`);if(!O(t))return!1;let n=/@FileUpload\b|\bupload\.(single|array|none)\s*\(/,r=[t],i=0;for(;r.length>0&&i<Ci;){let e=r.pop(),t;try{t=Pe(e,{withFileTypes:!0})}catch{continue}for(let a of t){if(i>=Ci)break;let t=M(e,a.name);if(a.isDirectory()){a.name!==`node_modules`&&r.push(t);continue}if(/\.(ts|tsx|mts|cts)$/.test(a.name)&&(i++,n.test(ui(t)??``)))return!0}}return!1}function Ti(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.
|
|
1643
1643
|
Install it: pnpm add reflect-metadata
|
|
1644
1644
|
Then import it at the top of src/index.ts:
|
|
1645
1645
|
|
|
@@ -1653,7 +1653,7 @@ holding the whole environment the suite should run against
|
|
|
1653
1653
|
(a var you leave out is then missing, not inherited), or set KICKJS_ENV_FILE=off
|
|
1654
1654
|
and supply env from the test runner.`}}const Ii=[()=>_i(),vi,yi,xi,Si,Ti,Ei,Di,Fi,Ai];async function Li(e,t={}){let n={cwd:e,pkg:li(M(e,`package.json`)),tsconfig:fi(e),runtime:t.runtime??`express`},r=[...Ii,...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 Ri(e){switch(e){case`pass`:return C.green(`✔`);case`warn`:return C.yellow(`⚠`);case`fail`:return C.red(`✖`)}}function zi(e){let t=Ri(e.status),n=e.message?` ${C.dim(`(${e.message})`)}`:``;return`${t} ${e.name}${n}`}function Bi(e){return e.split(`
|
|
1655
1655
|
`).map(e=>` ${C.dim(`→`)} ${e}`).join(`
|
|
1656
|
-
`)}function Vi(e){return e?.doctor?.checks??[]}function Hi(e){e.command(`doctor`).description(`Pre-flight checks for your KickJS project (dev environment health)`).action(async()=>{let e=process.cwd(),
|
|
1656
|
+
`)}function Vi(e){return e?.doctor?.checks??[]}function Hi(e){e.command(`doctor`).description(`Pre-flight checks for your KickJS project (dev environment health)`).action(async()=>{let e=process.cwd(),n=Vi(await l(e)),r=await t(e);te(`KickJS Doctor`);let i=await Li(e,{extraChecks:n,runtime:r});for(let e of i)x.message(zi(e)),e.fix&&e.status!==`pass`&&x.message(Bi(e.fix));let a=i.filter(e=>e.status===`pass`).length,o=i.filter(e=>e.status===`warn`).length,s=i.filter(e=>e.status===`fail`).length,c=[C.green(`${a} passed`),o>0?C.yellow(`${o} warning${o===1?``:`s`}`):`${o} warnings`,s>0?C.red(`${s} error${s===1?``:`s`}`):`${s} errors`].join(`, `);s>0?(T(`${c} — fix the errors above before running the app`),process.exit(1)):T(o>0?`${c} — review the warnings`:C.green(`${c} — your environment looks good`))})}function Ui(e){return e.optsWithGlobals().dryRun??!1}function Wi(e){e.command(`codemod`).description(`Codebase migration commands (AST-style rewrites — distinct from db migrate)`).command(`modules`).description(`Rewrite module declarations between class form and the defineModule factory.
|
|
1657
1657
|
Direction defaults to \`modules.style\` from kick.config (or "define").
|
|
1658
1658
|
--target define|class Override the migration direction.
|
|
1659
1659
|
--apply Apply the changes (default: dry-run preview).
|
|
@@ -1664,14 +1664,19 @@ and supply env from the test runner.`}}const Ii=[()=>_i(),vi,yi,xi,Si,Ti,Ei,Di,F
|
|
|
1664
1664
|
Always commit before running with --apply.
|
|
1665
1665
|
`),process.exit(1));let r=await l(process.cwd()),i=p(r),a=P(e.modulesDir??i.dir??`src/modules`),o;e.target===`define`||e.target===`class`?o=e.target:e.target===void 0?o=i.style??`define`:(console.error(`\n ${C.red(`Error:`)} --target must be 'define' or 'class' (got '${e.target}').\n`),process.exit(1));let s=C.dim(`→ ${o}`),c=n?C.dim(`(dry-run)`):C.bold(`(applying)`);console.log(`\n ${C.bold(`kick codemod modules`)} ${s} ${c}`),console.log(` modulesDir: ${C.dim(a)}\n`);let u=e.backup!==!1&&!n,d=await mn(a,{dryRun:n,target:o,backup:u});if(d.backupDir){let e=d.backupDir;console.log(` ${C.green(`✓`)} backup: ${C.dim(e)}\n ${C.dim(`(restore: rm -rf <modulesDir> && mv "<backup>" <modulesDir>)`)}\n`)}else!n&&e.backup===!1&&console.log(` ${C.dim(`(--no-backup — skipping snapshot)`)}\n`);let f=0,m=0;for(let e of d.files)if(e.status===`migrated`)f++,console.log(` ${C.green(`✓`)} ${e.path}`);else{m++;let t=C.dim(`(${e.reason??`skipped`})`);console.log(` ${C.dim(`-`)} ${e.path} ${t}`)}if(console.log(),d.indexStatus===`migrated`)console.log(` ${C.green(`✓`)} ${d.indexPath}`);else if(d.indexStatus===`skipped`){let e=C.dim(`(${d.indexReason??`skipped`})`);console.log(` ${C.dim(`-`)} ${d.indexPath} ${e}`)}else console.log(` ${C.dim(`-`)} ${d.indexPath} ${C.dim(`(not found)`)}`);let h=n?C.dim(` (dry-run — pass --apply to write)`):``;console.log(`\n ${C.bold(String(f))} migrated, ${C.bold(String(m))} skipped${h}\n`)})}function Gi(e,t=O){let n=j(e);return(t(P(n,`pnpm-workspace.yaml`))||t(P(n,`package.json`)))&&t(P(n,`web`,`package.json`))?{staticDir:`../web/dist`,siteRoot:`..`,apiPath:`/api`}:{siteRoot:`.`,apiPath:``}}function Ki(e,t,n){let r=Gi(t,n),i=e?.staticDir===!1?void 0:e?.staticDir??r.staticDir;return{entry:e?.entry??`src/serverless.ts`,outDir:e?.outDir??`dist/serverless`,staticDir:i,siteRoot:e?.siteRoot??r.siteRoot,publishDir:e?.publishDir??`dist/public`,apiPath:e?.apiPath??r.apiPath,external:e?.external??[`valibot`,`yup`],vercelRuntime:e?.vercelRuntime??`nodejs22.x`}}function qi(e,t){return`import { handler } from '${e}'
|
|
1666
1666
|
|
|
1667
|
-
|
|
1667
|
+
// Netlify's context carries waitUntil, so ctx.waitUntil() work finishes after the response.
|
|
1668
|
+
export default (request, context) => handler.fetch(request, context)
|
|
1668
1669
|
|
|
1669
1670
|
export const config = {
|
|
1670
1671
|
path: '${t}/*',
|
|
1671
1672
|
}
|
|
1672
|
-
`}function Ji(
|
|
1673
|
-
|
|
1674
|
-
|
|
1673
|
+
`}function Ji(){return`import { handler } from './server.mjs'
|
|
1674
|
+
|
|
1675
|
+
const requestContext = () => globalThis[Symbol.for('@vercel/request-context')]?.get?.()
|
|
1676
|
+
|
|
1677
|
+
export default (req, res) => handler.node(req, res, requestContext())
|
|
1678
|
+
`}function Yi(e){return/^\s*publish\s*=\s*["']([^"']+)["']/m.exec(e)?.[1]?.replace(/^\.\//,``).replace(/\/+$/,``)}function Xi(e,t,n=!1){let r=[{handle:`filesystem`},{src:`^${e}/(.*)$`,dest:`/api`}];return n&&e!==``&&r.push({src:`^/_kick/(.*)$`,dest:`/api`}),t&&r.push({src:`^/(.*)$`,dest:`/index.html`}),r}function Zi(e,t){let n;try{n=Ye(t,e).program}catch{return[]}let r=[],i=t=>e.slice(0,t).split(`
|
|
1679
|
+
`).length,a=e=>{if(!e||typeof e!=`object`)return;if(Array.isArray(e))return e.forEach(a);let n=e,o=n.expression;if(n.type===`Decorator`&&o?.type===`CallExpression`&&o.callee?.type===`Identifier`&&o.callee.name===`Cron`){let[e,a]=o.arguments??[],s=e?.type===`Literal`&&typeof e.value==`string`?e.value:e?.type===`TemplateLiteral`&&e.expressions.length===0?e.quasis[0]?.value?.cooked:void 0;r.push({file:t,line:i(n.start??0),expression:s,timezone:a?.type===`ObjectExpression`&&a.properties.some(e=>(e.key?.name??e.key?.value)===`timezone`)})}for(let e in n)e!==`parent`&&a(n[e])};return a(n),r}function Qi(e){let t=P(e,`src`);return O(t)?Pe(t,{recursive:!0,encoding:`utf-8`}).filter(e=>/\.m?ts$/.test(e)&&!/\.(test|spec|d)\.m?ts$/.test(e)).flatMap(e=>{let n=k(P(t,e),`utf-8`);return n.includes(`@Cron`)?Zi(n,`src/${e}`):[]}):[]}function $i(e){let t=2166136261;for(let n of e.trim().replace(/\s+/g,` `))t^=n.codePointAt(0),t=Math.imul(t,16777619)>>>0;return t.toString(36)}function ea(e){let t=[],n=new Map;for(let r of e){let e=`${r.file}:${r.line}`;if(r.expression===void 0){t.push(`${e}: @Cron expression is not a string literal, so it has no Vercel cron entry`);continue}r.timezone&&t.push(`${e}: Vercel crons run in UTC — the timezone option is ignored there`);let i=r.expression.trim().replace(/\s+/g,` `);if(i.split(` `).length!==5){t.push(`${e}: Vercel crons need a five-field expression, so it has no Vercel cron entry`);continue}n.set($i(i),i)}return{crons:[...n].map(([e,t])=>({path:`/_kick/cron/${e}`,schedule:t})),warnings:t}}function ta(e){let t=e=>{if(typeof e==`string`)return e;if(!e||typeof e!=`object`)return;let n=e;for(let e of[`import`,`module`,`node`,`default`]){let r=t(n[e]);if(r)return r}},n=e.exports;return t(typeof n==`string`||Array.isArray(n)?n:n?.[`.`]??n)??e.module??e.main}async function na(e,t){let{createRequire:n}=await import(`node:module`),r=n(P(e,`package.json`)),i;try{i=r.resolve(`${t}/package.json`)}catch{i=P(e,`node_modules`,t,`package.json`)}if(!O(i))throw Error(`${t} is not installed in this project. Run: pnpm add -D vite unplugin-swc @forinda/kickjs-vite`);let a=ta(JSON.parse(k(i,`utf-8`)));if(!a)throw Error(`${t} has no importable entry point`);return import(F(P(j(i),a)).href)}async function ra(e,t,n){let r=P(e,t.entry);if(!O(r))throw Error(`${t.entry} not found. The serverless entry exports \`handler = createHandler({ modules })\` — see the Serverless guide.`);let{build:i}=await na(e,`vite`),{default:a}=await na(e,`unplugin-swc`),{devtoolsFlagPlugin:o,devtoolsStripPlugin:s}=await na(e,`@forinda/kickjs-vite`);await i({configFile:!1,root:e,logLevel:`warn`,oxc:!1,plugins:[a.vite(),o(),s()],resolve:{alias:{"@":P(e,`src`)}},ssr:{noExternal:!0,target:`node`},build:{ssr:!0,target:`node20`,outDir:P(e,t.outDir),emptyOutDir:!0,minify:!1,rollupOptions:{input:r,external:t.external.filter(t=>!O(P(e,`node_modules`,t))),output:{format:`esm`,entryFileNames:`server.mjs`,codeSplitting:!1}}}});let c=P(e,t.outDir,`server.mjs`);return n(`bundled ${N(process.cwd(),c)}`),c}function ia(e,t){let n=t.projectRoot,r=()=>Ki(t.config?.deploy,n);e.command(`build:netlify`).description(`Bundle the serverless entry and write the Netlify function`).action(async()=>{let e=r(),i=await ra(n,e,t.log),a=P(n,e.siteRoot),o=Qi(n);o.length>0&&t.log(`warning: ${o.length} @Cron job(s) found — Netlify has no cron trigger for them, so they will not run. Use Netlify scheduled functions, or deploy to Vercel or Workers.`);let s=P(a,`.netlify/v1/functions`);Ne(s,{recursive:!0});let c=N(s,i).split(ze).join(`/`);Le(P(s,`api.mjs`),qi(c,e.apiPath)),t.log(`wrote ${N(process.cwd(),P(s,`api.mjs`))}`);let l=e.staticDir??e.publishDir;e.staticDir||(Ne(P(n,l),{recursive:!0}),t.log(`publish directory ready at ${N(process.cwd(),P(n,l))}`));let u=P(a,`netlify.toml`);if(O(u)){let e=Yi(k(u,`utf-8`)),r=N(a,P(n,l)).split(ze).join(`/`);e!==void 0&&e!==r&&t.log(`warning: netlify.toml publishes "${e}", but this build fills "${r}". Update netlify.toml, or set \`deploy.publishDir\` / \`deploy.staticDir\` to match.`)}}),e.command(`build:vercel`).description(`Bundle the serverless entry and write .vercel/output (Build Output API v3)`).action(async()=>{let e=r(),i=await ra(n,e,t.log),a=P(n,e.siteRoot),o=e.staticDir?P(n,e.staticDir):void 0,s=P(a,`.vercel/output`),c=P(s,`functions/api.func`);if(Fe(s,{recursive:!0,force:!0}),Ne(c,{recursive:!0}),Me(i,P(c,`server.mjs`)),Le(P(c,`index.mjs`),Ji()),Le(P(c,`.vc-config.json`),`${JSON.stringify({runtime:e.vercelRuntime,handler:`index.mjs`,launcherType:`Nodejs`,supportsResponseStreaming:!0},null,2)}\n`),o){if(!O(o))throw Error(`build:vercel: ${e.staticDir} does not exist — build the frontend first`);Me(o,P(s,`static`),{recursive:!0})}let{crons:l,warnings:u}=ea(Qi(n));for(let e of u)t.log(`warning: ${e}`);let d={version:3,routes:Xi(e.apiPath,!!o,l.length>0),...l.length>0?{crons:l}:{}};Le(P(s,`config.json`),`${JSON.stringify(d,null,2)}\n`),t.log(`wrote ${N(process.cwd(),s)}`),l.length>0&&t.log(`${l.length} cron schedule(s) written. Set CRON_SECRET in the Vercel project — the trigger is not mounted without it.`)})}const aa=()=>({id:`kick/assets`,inputs:[`kick.config.ts`,`kick.config.js`,`kick.config.mjs`],async generate(e){let t=A.resolve(e.cwd,`kick.config.ts`);if(!O(t))return null;let n=await l(e.cwd);if(!n?.assetMap)return null;let r=ue(n.assetMap,e.cwd);return r.count===0?null:be(r)}}),oa="/* eslint-disable */\n// AUTO-GENERATED by `kick typegen`. DO NOT EDIT.\n// Re-run with `kick typegen` or rely on `kick dev` to refresh.\n";function sa(e,t,n,r={}){if(e.length===0)return`${oa}
|
|
1675
1680
|
// (no routes discovered yet — annotate a controller method with
|
|
1676
1681
|
// @Get/@Post/@Put/@Delete/@Patch and re-run \`kick typegen\`)
|
|
1677
1682
|
declare global {
|
|
@@ -1688,14 +1693,14 @@ declare global {
|
|
|
1688
1693
|
|
|
1689
1694
|
/** Empty until the first route exists — see kick typegen. */
|
|
1690
1695
|
export const kickRpc = {} as const
|
|
1691
|
-
`;let i=new Map;for(let t of e){let e=i.get(t.controller)??[];e.push(t),i.set(t.controller,e)}let a=new Map,o=new Map,s=e=>{let t=`${e.filePath}::${e.controller}`,n=o.get(t);return n||(n=`_C${o.size}`,o.set(t,n)),n},c=(e,i,o)=>{let s=
|
|
1696
|
+
`;let i=new Map;for(let t of e){let e=i.get(t.controller)??[];e.push(t),i.set(t.controller,e)}let a=new Map,o=new Map,s=e=>{let t=`${e.filePath}::${e.controller}`,n=o.get(t);return n||(n=`_C${o.size}`,o.set(t,n)),n},c=(e,i,o)=>{let s=da(e,i.filePath,t,n,a);if(!s){if(e&&n!==!1){let t=o===`params`?`URL-pattern params`:o===`query`&&i.queryFilterable!==null?`the @ApiQueryParams-derived query shape`:`'unknown'`;r.onWarn?.(`route ${i.controller}.${i.method} (${i.httpMethod} ${i.path}): ${o} schema '${e.identifier}' could not be statically resolved — falling back to ${t}. Export the schema from the controller file or import it with a static specifier.`)}return null}return n===`kickjs-schema`?`import('@forinda/kickjs-schema').InferSchemaOutput<typeof ${s}>`:`import('zod').infer<typeof ${s}>`},l=[];for(let[e,t]of i){let n=[` interface ${e} {`];for(let e of t){let t=e.pathParams.length>0?`{ ${e.pathParams.map(e=>`${e}: string`).join(`; `)} }`:`{}`,r=c(e.bodySchema,e,`body`),i=c(e.querySchema,e,`query`),a=c(e.paramsSchema,e,`params`)??t,o=r??`unknown`,l=i??la(e),u=c(e.responseSchema??null,e,`response`),d=s(e),f=u??`import('@forinda/kickjs').InferHandlerResponse<${d}['${e.method}']>`,p=ua(e);n.push(` /**`,` * ${e.httpMethod} ${e.path}`,...p.map(e=>` * ${e}`),` */`,` ${e.method}: {`,` params: ${a}`,` body: ${o}`,` query: ${l}`,` response: ${f}`,` contextKeys: ${ca(e)}`,` }`)}n.push(` }`),l.push(n.join(`
|
|
1692
1697
|
`))}let u=[],d=new Set,f=new Set;i.has(`Api`)&&r.onWarn?.(`controller class 'Api' collides with the reserved KickRoutes.Api client map — its interface declaration-merges into the flat route map. Rename the controller.`);for(let[e,t]of i)for(let n of t){let t=`${n.httpMethod} ${n.mountedPath??n.path}`;if(d.has(t)){r.onWarn?.(`duplicate route '${t}' (${e}.${n.method}) — two handlers claim the same verb+path at runtime. KickRoutes.Api keeps the first (scan order, which may not match runtime dispatch); resolve the conflict in the modules.`);continue}d.add(t),f.add(`${e}.${n.method}`),u.push(` '${t}': ${e}['${n.method}']`)}let p=[` interface Api {`,...u,` }`].join(`
|
|
1693
|
-
`);l.push(p);let m=[],h=new Set;for(let[e,t]of i){let n=
|
|
1698
|
+
`);l.push(p);let m=[],h=new Set;for(let[e,t]of i){let n=ma(e);if(h.has(n)){r.onWarn?.(`RPC manifest: controller key '${n}' (from ${e}) collides with another controller — keeping the first; rename one class for distinct RPC namespaces.`);continue}h.add(n);let i=[];for(let n of t){if(!f.has(`${e}.${n.method}`))continue;let t=`${n.httpMethod} ${n.mountedPath??n.path}`;i.push(` ${n.method}: '${t}',`)}i.length>0&&m.push(` ${n}: {\n${i.join(`
|
|
1694
1699
|
`)}\n },`)}let g=[`/**`,` * Runtime route manifest for the tRPC-style sugar:`," * `createRpc(api, kickRpc)` from @forinda/kickjs-client.",` */`,`export const kickRpc = {`,...m,`} as const`].join(`
|
|
1695
|
-
`),_=[],v=new Map;for(let t of e)v.set(`${t.filePath}::${t.controller}`,t);for(let[e,n]of o){let r=v.get(e),i=
|
|
1700
|
+
`),_=[],v=new Map;for(let t of e)v.set(`${t.filePath}::${t.controller}`,t);for(let[e,n]of o){let r=v.get(e),i=pa(``,r.filePath,t),a=r.controllerIsDefaultExport?`default as ${n}`:`${r.controller} as ${n}`;_.push(`import type { ${a} } from '${i}'`)}let y=_.length>0?_.join(`
|
|
1696
1701
|
`)+`
|
|
1697
|
-
`:``,b=
|
|
1698
|
-
`);return`${
|
|
1702
|
+
`:``,b=fa(a)+y,x=l.join(`
|
|
1703
|
+
`);return`${oa}${b}
|
|
1699
1704
|
declare global {
|
|
1700
1705
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
1701
1706
|
namespace KickRoutes {
|
|
@@ -1707,18 +1712,18 @@ ${x}
|
|
|
1707
1712
|
}
|
|
1708
1713
|
|
|
1709
1714
|
${g}
|
|
1710
|
-
`}function
|
|
1715
|
+
`}function ca(e){let t=e.contextKeys;return t==null?`string`:t.length===0?`never`:t.map(e=>JSON.stringify(e)).join(` | `)}function la(e){if(e.queryFilterable===null)return`unknown`;let t=e.querySortable??[];return`{ filter?: string | string[]; sort?: ${t.length>0?t.flatMap(e=>[`'${e}'`,`'-${e}'`]).join(` | `):`string`}; q?: string; page?: string; limit?: string }`}function ua(e){let t=[];return e.queryFilterable&&e.queryFilterable.length>0&&t.push(`Filterable: ${e.queryFilterable.join(`, `)}`),e.querySortable&&e.querySortable.length>0&&t.push(`Sortable: ${e.querySortable.join(`, `)}`),e.querySearchable&&e.querySearchable.length>0&&t.push(`Searchable: ${e.querySearchable.join(`, `)}`),t}function da(e,t,n,r,i){if(!e||r===!1||e.source===null)return null;let a=pa(e.source,t,n);if(a===`unknown`)return null;let o=`${a}::${e.identifier}`,s=i.get(o)?.specifier;return s?s=i.get(o).specifier:(s=`_S${i.size}`,i.set(o,{identifier:e.identifier,specifier:s})),s}function fa(e){if(e.size===0)return``;let t=[];for(let[n,r]of e){let[e]=n.split(`::`);t.push(`import type { ${r.identifier} as ${r.specifier} } from '${e}'`)}return t.join(`
|
|
1711
1716
|
`)+`
|
|
1712
|
-
`}function
|
|
1713
|
-
TypeScript 7 does not ship a compiler API, so the compatibility package is required.\n ${t}`):Error(`kick typegen: the client route map needs a TypeScript compiler API, and neither 'typescript' nor '${
|
|
1717
|
+
`}function pa(e,t,n){if(e===null)return`unknown`;let r=j(n);if(e===``){let e=N(r,t).split(ze).join(`/`);return e=e.replace(/\.(ts|tsx|mts|cts)$/i,``),e.startsWith(`.`)||(e=`./`+e),e}if(!e.startsWith(`.`)&&!e.startsWith(`/`))return e;let i=j(t),a=P(i,e),o=N(r,a).split(ze).join(`/`);return o=o.replace(/\.(ts|tsx|mts|cts)$/i,``),o.startsWith(`.`)||(o=`./`+o),o}function ma(e){let t=e.endsWith(`Controller`)?e.slice(0,-10):e,n=t.length>0?t:e;return n.charAt(0).toLowerCase()+n.slice(1)}const ha=()=>({id:`kick/routes`,outExtension:`.ts`,inputs:[`src/**/*.controller.ts`,`src/**/*.module.ts`],async generate(e){let t=await e.getScanResult({root:ga(e),cwd:e.cwd,envFile:_a(e)}),n=e.config?.typegen?.schemaValidator??`zod`,r=A.resolve(e.cwd,`.kickjs/types/kick__routes.ts`);return sa(t.routes,r,n,{onWarn:t=>e.log.warn(t)})}});function ga(e){return A.resolve(e.cwd,e.config?.typegen?.srcDir??`src`)}function _a(e){let t=e.config?.typegen?.envFile;if(t!==!1)return t}const va=`@typescript/typescript6`;function ya(e){return typeof e?.createProgram==`function`}function ba(e){if(ya(e.typescript))return{api:e.typescript,source:`typescript`};if(ya(e.ts6))return{api:e.ts6,source:va};let t=`Install it in the project:\n pnpm add -D ${va}`;throw e.typescript?Error(`kick typegen: the client route map needs a TypeScript compiler API.
|
|
1718
|
+
TypeScript 7 does not ship a compiler API, so the compatibility package is required.\n ${t}`):Error(`kick typegen: the client route map needs a TypeScript compiler API, and neither 'typescript' nor '${va}' resolved from this project.\n ${t}`)}async function xa(e){let t=je(M(e,`package.json`)),n=async e=>{try{return await import(F(t.resolve(e)).href)}catch{return null}},[r,i]=await Promise.all([n(`typescript`),n(va)]);return ba({typescript:Sa(r),ts6:Sa(i)}).api}function Sa(e){let t=e;return t?.default&&typeof t.default==`object`?t.default:e}const Ca=Symbol(`kick/client: expansion budget exhausted`);var wa=class{ts;checker;program;opts;get printFlags(){return this.ts.TypeFormatFlags.NoTruncation}hoistedByType=new Map;inProgress=new Map;jsonInProgress=new Set;nextName=0;blocks=[];maxDepth;truncations=0;budget;constructor(e,t,n,r={}){this.ts=e,this.checker=t,this.program=n,this.opts=r,this.maxDepth=r.maxDepth??12,this.budget=r.truncationBudget??1e3}hoisted(){return this.blocks}expand(e){this.truncations=0;try{return this.render(e,0)}catch(e){if(e!==Ca)throw e;return this.opts.onWarn?.(`expansion abandoned after ${this.budget} truncations — emitting 'unknown'. This usually means a recursive type. Declare a response schema on the route for an exact type.`),`unknown`}}render(e,t){let n=this.ts.TypeFlags;if(t>this.maxDepth){if(++this.truncations>this.budget)throw Ca;return this.opts.onWarn?.(`type nesting exceeded ${this.maxDepth} levels — emitting 'unknown'. Declare a response schema on the route for an exact type.`),`unknown`}if(e.flags&(n.String|n.Number|n.Boolean|n.BigInt|n.ESSymbol)||e.flags&(n.Any|n.Unknown|n.Never|n.Void|n.Undefined|n.Null)||e.isLiteral()||e.flags&n.BooleanLiteral)return this.checker.typeToString(e,void 0,this.printFlags);if(e.isUnion()){let n=e.types.filter(e=>!this.isCallable(e));return(n.length>0?n:e.types).map(e=>this.render(e,t+1)).join(` | `)}if(e.isIntersection())return e.types.map(e=>this.render(e,t+1)).join(` & `);if(this.isTuple(e))return this.renderTuple(e,t);let r=this.arrayElement(e);if(r){let e=this.render(r.element,t+1),n=/[|&]/.test(e)?`(${e})[]`:`${e}[]`;return r.readonly?`readonly ${n}`:n}let i=this.toJsonType(e);if(i){if(this.jsonInProgress.has(e))return this.opts.onWarn?.(`'${this.checker.typeToString(e,void 0,this.printFlags)}' has a cyclic toJSON() — emitting 'unknown', since it has no serializable form.`),`unknown`;this.jsonInProgress.add(e);try{return this.render(i,t)}finally{this.jsonInProgress.delete(e)}}return this.isLibType(e)?this.renderLibType(e,t):e.flags&n.Object?this.renderObject(e,t):(this.opts.onWarn?.(`could not expand type '${this.checker.typeToString(e)}' — emitting 'unknown'`),`unknown`)}renderObject(e,t){let n=this.hoistedByType.get(e);if(n)return n;if(this.isNamed(e)){let t=this.allocName();this.hoistedByType.set(e,t);let n=this.blocks.length;return this.blocks.push(``),this.blocks[n]=`interface ${t} {\n${this.members(e,0,` `)}\n}`,t}let r=this.inProgress.get(e);if(r)return r.name??=this.allocName();let i={name:null};this.inProgress.set(e,i);let a;try{a=this.members(e,t,``,`; `)}finally{this.inProgress.delete(e)}if(i.name){this.hoistedByType.set(e,i.name);let t=this.blocks.length;return this.blocks.push(``),this.blocks[t]=`interface ${i.name} {\n${this.members(e,0,` `)}\n}`,i.name}return a.length>0?`{ ${a} }`:`{}`}allocName(){return`__T${this.nextName++}`}members(e,t,n,r=`
|
|
1714
1719
|
`){let i=[];for(let r of this.checker.getIndexInfosOfType(e)){let e=this.checker.typeToString(r.keyType,void 0,this.printFlags);i.push(`${n}[key: ${e}]: ${this.render(r.type,t+1)}`)}for(let r of this.checker.getPropertiesOfType(e)){let e=this.typeOfProperty(r);if(this.isCallable(e)||r.getName().startsWith(`__@`))continue;let a=(r.flags&this.ts.SymbolFlags.Optional)!==0,o=this.renderPropertyType(e,a,r,t+1),s=this.isReadonlyProp(r)?`readonly `:``;i.push(`${n}${s}${this.propName(r.getName())}${a?`?`:``}: ${o}`)}return i.join(r===`
|
|
1715
1720
|
`?`
|
|
1716
|
-
`:r)}typeOfProperty(e){let t=this.checker;if(typeof t.getTypeOfSymbol==`function`)return t.getTypeOfSymbol(e);let n=e.valueDeclaration??e.declarations?.[0];return n?this.checker.getTypeOfSymbolAtLocation(e,n):this.checker.getDeclaredTypeOfSymbol(e)}renderPropertyType(e,t,n,r){if(!t||!e.isUnion()||this.declaresUndefined(n))return this.render(e,r);let i=e.types.filter(e=>!(e.flags&this.ts.TypeFlags.Undefined));return i.length===0?`undefined`:i.map(e=>this.render(e,r)).join(` | `)}isReadonlyProp(e){let t=e.valueDeclaration??e.declarations?.[0];return t?(this.ts.getCombinedModifierFlags(t)&this.ts.ModifierFlags.Readonly)!==0:!1}declaresUndefined(e){let t=e.valueDeclaration??e.declarations?.[0];if(!t||!(this.ts.isPropertySignature(t)||this.ts.isPropertyDeclaration(t))||!t.type)return!1;let n=this.checker.getTypeFromTypeNode(t.type);return(n.isUnion()?n.types:[n]).some(e=>(e.flags&this.ts.TypeFlags.Undefined)!==0)}renderTuple(e,t){let n=this.ts.ElementFlags,r=this.checker.getTypeArguments(e),i=e.target,a=i.elementFlags??[],o=r.map((e,r)=>{let i=a[r]??n.Required;return i&n.Optional?`${(e.isUnion()?e.types.filter(e=>!(e.flags&this.ts.TypeFlags.Undefined)):[e]).map(e=>this.render(e,t+1)).join(` | `)}?`:i&n.Rest?`...${this.render(e,t+1)}[]`:i&n.Variadic?`...${this.render(e,t+1)}`:this.render(e,t+1)});return`${i.readonly?`readonly `:``}[${o.join(`, `)}]`}propName(e){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(e)?e:JSON.stringify(e)}isLibType(e){let t=e.aliasSymbol?.declarations??e.getSymbol()?.declarations;return!t||t.length===0?!1:t.every(e=>this.program.isSourceFileDefaultLibrary(e.getSourceFile()))}renderLibType(e,t){let n=(e.aliasSymbol??e.getSymbol())?.getName(),r=e.aliasTypeArguments??this.typeArguments(e);return!n||r.length===0?this.checker.typeToString(e,void 0,this.printFlags):`${n}<${r.map(e=>this.render(e,t+1)).join(`, `)}>`}typeArguments(e){return!(e.flags&this.ts.TypeFlags.Object)||!(e.objectFlags&this.ts.ObjectFlags.Reference)?[]:this.checker.getTypeArguments(e)}toJsonType(e){if(!(e.flags&this.ts.TypeFlags.Object))return null;let t=this.checker.getPropertyOfType(e,`toJSON`);if(!t)return null;let[n]=this.checker.getSignaturesOfType(this.typeOfProperty(t),this.ts.SignatureKind.Call);if(!n)return null;let r=this.checker.getReturnTypeOfSignature(n);return r===e?null:r}isCallable(e){if(e.isUnion()){let t=e.types.filter(e=>!(e.flags&(this.ts.TypeFlags.Undefined|this.ts.TypeFlags.Null)));return t.length>0&&t.every(e=>this.isCallable(e))}return this.checker.getSignaturesOfType(e,this.ts.SignatureKind.Call).length>0||this.checker.getSignaturesOfType(e,this.ts.SignatureKind.Construct).length>0}isNamed(e){let t=e.getSymbol();if(!t)return!1;let n=t.getName();return n!==`__type`&&n!==`__object`&&n.length>0}isTuple(e){let t=this.ts.ObjectFlags;if(!(e.flags&this.ts.TypeFlags.Object)||!(e.objectFlags&t.Reference))return!1;let n=e.target;return!!(n&&n.objectFlags&t.Tuple)}arrayElement(e){let t=e.getSymbol()?.getName();if(t!==`Array`&&t!==`ReadonlyArray`)return null;let n=this.checker.getTypeArguments(e);return n.length===1?{element:n[0],readonly:t===`ReadonlyArray`}:null}};const
|
|
1717
|
-
`));for(let n of
|
|
1718
|
-
`);throw Error(`${n} has ${i.length} type error(s), so its route types cannot be resolved — every entry would come out as 'any'.\n${a}\n Usually this means dependencies are not installed or the server does not type-check.`)}function
|
|
1721
|
+
`:r)}typeOfProperty(e){let t=this.checker;if(typeof t.getTypeOfSymbol==`function`)return t.getTypeOfSymbol(e);let n=e.valueDeclaration??e.declarations?.[0];return n?this.checker.getTypeOfSymbolAtLocation(e,n):this.checker.getDeclaredTypeOfSymbol(e)}renderPropertyType(e,t,n,r){if(!t||!e.isUnion()||this.declaresUndefined(n))return this.render(e,r);let i=e.types.filter(e=>!(e.flags&this.ts.TypeFlags.Undefined));return i.length===0?`undefined`:i.map(e=>this.render(e,r)).join(` | `)}isReadonlyProp(e){let t=e.valueDeclaration??e.declarations?.[0];return t?(this.ts.getCombinedModifierFlags(t)&this.ts.ModifierFlags.Readonly)!==0:!1}declaresUndefined(e){let t=e.valueDeclaration??e.declarations?.[0];if(!t||!(this.ts.isPropertySignature(t)||this.ts.isPropertyDeclaration(t))||!t.type)return!1;let n=this.checker.getTypeFromTypeNode(t.type);return(n.isUnion()?n.types:[n]).some(e=>(e.flags&this.ts.TypeFlags.Undefined)!==0)}renderTuple(e,t){let n=this.ts.ElementFlags,r=this.checker.getTypeArguments(e),i=e.target,a=i.elementFlags??[],o=r.map((e,r)=>{let i=a[r]??n.Required;return i&n.Optional?`${(e.isUnion()?e.types.filter(e=>!(e.flags&this.ts.TypeFlags.Undefined)):[e]).map(e=>this.render(e,t+1)).join(` | `)}?`:i&n.Rest?`...${this.render(e,t+1)}[]`:i&n.Variadic?`...${this.render(e,t+1)}`:this.render(e,t+1)});return`${i.readonly?`readonly `:``}[${o.join(`, `)}]`}propName(e){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(e)?e:JSON.stringify(e)}isLibType(e){let t=e.aliasSymbol?.declarations??e.getSymbol()?.declarations;return!t||t.length===0?!1:t.every(e=>this.program.isSourceFileDefaultLibrary(e.getSourceFile()))}renderLibType(e,t){let n=(e.aliasSymbol??e.getSymbol())?.getName(),r=e.aliasTypeArguments??this.typeArguments(e);return!n||r.length===0?this.checker.typeToString(e,void 0,this.printFlags):`${n}<${r.map(e=>this.render(e,t+1)).join(`, `)}>`}typeArguments(e){return!(e.flags&this.ts.TypeFlags.Object)||!(e.objectFlags&this.ts.ObjectFlags.Reference)?[]:this.checker.getTypeArguments(e)}toJsonType(e){if(!(e.flags&this.ts.TypeFlags.Object))return null;let t=this.checker.getPropertyOfType(e,`toJSON`);if(!t)return null;let[n]=this.checker.getSignaturesOfType(this.typeOfProperty(t),this.ts.SignatureKind.Call);if(!n)return null;let r=this.checker.getReturnTypeOfSignature(n);return r===e?null:r}isCallable(e){if(e.isUnion()){let t=e.types.filter(e=>!(e.flags&(this.ts.TypeFlags.Undefined|this.ts.TypeFlags.Null)));return t.length>0&&t.every(e=>this.isCallable(e))}return this.checker.getSignaturesOfType(e,this.ts.SignatureKind.Call).length>0||this.checker.getSignaturesOfType(e,this.ts.SignatureKind.Construct).length>0}isNamed(e){let t=e.getSymbol();if(!t)return!1;let n=t.getName();return n!==`__type`&&n!==`__object`&&n.length>0}isTuple(e){let t=this.ts.ObjectFlags;if(!(e.flags&this.ts.TypeFlags.Object)||!(e.objectFlags&t.Reference))return!1;let n=e.target;return!!(n&&n.objectFlags&t.Tuple)}arrayElement(e){let t=e.getSymbol()?.getName();if(t!==`Array`&&t!==`ReadonlyArray`)return null;let n=this.checker.getTypeArguments(e);return n.length===1?{element:n[0],readonly:t===`ReadonlyArray`}:null}};const Ta=[`pnpm-lock.yaml`,`package-lock.json`,`yarn.lock`,`bun.lock`,`bun.lockb`],Ea=/(?:^|[\\/])(?:node_modules|\.kickjs)(?:[\\/]|$)/;function Da(e){return et(`sha1`).update(e).digest(`hex`)}function Oa(e){let t=et(`sha1`);t.update(e.cliVersion),t.update(JSON.stringify(e.options??{})),t.update(e.keys.join(`
|
|
1722
|
+
`));for(let n of Ta){let r=M(e.projectDir,n);if(O(r))try{t.update(k(r))}catch(e){throw Error(`kick/client: cannot read lockfile ${r}`,{cause:e})}}for(let n of e.fileNames.toSorted())if(!Ea.test(n)){t.update(n);try{t.update(k(n))}catch(e){throw Error(`kick/client: cannot read project file ${n}`,{cause:e})}}return t.digest(`hex`)}async function ka(e){try{let t=await xa(e.compilerFrom??e.projectDir),n={...t.sys,onUnRecoverableConfigFileDiagnostic:()=>{}},r=t.getParsedCommandLineOfConfigFile(M(e.projectDir,`tsconfig.json`),{},n);return r?Oa({projectDir:e.projectDir,fileNames:r.fileNames,keys:e.keys,options:{...r.options,__kickMaxDepth:e.maxDepth??null},cliVersion:e.cliVersion}):null}catch{return null}}async function Aa(e){let t=await xa(e.compilerFrom??e.projectDir),n=M(j(e.routesFile),`__kick_client_probe__.ts`),r=Na(e.routesFile,e.keys),i=Ia(t,e.projectDir,n,r),a=i.getTypeChecker(),o=i.getSourceFile(n);if(!o)throw Error(`kick/client: could not add the resolution probe to the program. Check that ${e.routesFile} exists — run \`kick typegen\` first.`);ja(t,i,e.routesFile);let s=Pa(t,i,o,e.keys),c=null,l=new wa(t,a,i,{maxDepth:e.maxDepth,onWarn:t=>e.onWarn?.(c?`route '${c}': ${t}`:t)}),u=new Map;for(let[n,r]of e.keys.entries()){if(s.has(r)){e.onWarn?.(`route '${r}' is not present in KickRoutes.Api — skipped. Re-run \`kick typegen\` so the two maps agree.`);continue}let i=o.statements.find(e=>t.isTypeAliasDeclaration(e)&&e.name.text===Ma(n));if(!i){e.onWarn?.(`route '${r}' could not be resolved — skipped.`);continue}let d=a.getTypeAtLocation(i.type);if(d.flags&t.TypeFlags.Any){e.onWarn?.(`route '${r}' resolved to 'any' — skipped rather than emitted, since an 'any' entry silently accepts every call. Check that the server type-checks.`);continue}c=r,u.set(r,l.expand(d)),c=null}return{entries:u,hoisted:l.hoisted()}}function ja(e,t,n){let r=t.getSourceFile(n);if(!r)throw Error(`kick/client: ${n} is not in the TypeScript program. Run \`kick typegen\` first, and check that tsconfig.json includes .kickjs.`);let i=t.getSemanticDiagnostics(r);if(i.length===0)return;let a=i.slice(0,3).map(t=>` ${e.flattenDiagnosticMessageText(t.messageText,` `)}`).join(`
|
|
1723
|
+
`);throw Error(`${n} has ${i.length} type error(s), so its route types cannot be resolved — every entry would come out as 'any'.\n${a}\n Usually this means dependencies are not installed or the server does not type-check.`)}function Ma(e){return`_K${e}`}function Na(e,t){let n=`./`+Re(e).replace(/\.tsx?$/,``),r=t.map((e,t)=>`type ${Ma(t)} = KickRoutes.Api[${JSON.stringify(e)}]`);return[`import ${JSON.stringify(n)}`,...r].join(`
|
|
1719
1724
|
`)+`
|
|
1720
|
-
`}function
|
|
1721
|
-
`))}},o=e.getParsedCommandLineOfConfigFile(i,{},a);if(!o)throw Error(`kick/client: could not read ${i}`);let s=e.createCompilerHost(o.options,!0),c=s.readFile.bind(s),l=s.getSourceFile.bind(s),u=s.fileExists.bind(s);return s.readFile=e=>e===n?r:c(e),s.fileExists=e=>e===n||u(e),s.getSourceFile=(t,i,a,o)=>t===n?e.createSourceFile(t,r,i,!0):l(t,i,a,o),e.createProgram({rootNames:[...
|
|
1725
|
+
`}function Pa(e,t,n,r){let i=new Set,a=new Map;for(let t of n.statements)e.isTypeAliasDeclaration(t)&&a.set(t.name.text,t);for(let e of t.getSemanticDiagnostics(n))if(e.start!==void 0)for(let[t,o]of r.entries()){let r=a.get(Ma(t));r&&e.start>=r.getStart(n)&&e.start<r.getEnd()&&i.add(o)}return i}function Fa(e,t){let n=e.filter(e=>/\.d\.(ts|mts|cts)$/.test(e)),r=[];try{r=Pe(t).filter(e=>e.endsWith(`.ts`)).map(e=>M(t,e))}catch{}return[...new Set([...n,...r])]}function Ia(e,t,n,r){let i=M(t,`tsconfig.json`),a={...e.sys,onUnRecoverableConfigFileDiagnostic:t=>{throw Error(e.flattenDiagnosticMessageText(t.messageText,`
|
|
1726
|
+
`))}},o=e.getParsedCommandLineOfConfigFile(i,{},a);if(!o)throw Error(`kick/client: could not read ${i}`);let s=e.createCompilerHost(o.options,!0),c=s.readFile.bind(s),l=s.getSourceFile.bind(s),u=s.fileExists.bind(s);return s.readFile=e=>e===n?r:c(e),s.fileExists=e=>e===n||u(e),s.getSourceFile=(t,i,a,o)=>t===n?e.createSourceFile(t,r,i,!0):l(t,i,a,o),e.createProgram({rootNames:[...Fa(o.fileNames,j(n)),n],options:o.options,host:s})}const La=`/* eslint-disable */
|
|
1722
1727
|
// AUTO-GENERATED by \`kick typegen\`. DO NOT EDIT.
|
|
1723
1728
|
//
|
|
1724
1729
|
// Self-contained: this file has no imports, so a frontend consumes it without
|
|
@@ -1732,7 +1737,7 @@ ${g}
|
|
|
1732
1737
|
//
|
|
1733
1738
|
// Not refreshed by \`kick dev\` — resolving these types builds a full
|
|
1734
1739
|
// TypeScript program over the server. Re-run \`kick typegen\`.
|
|
1735
|
-
`;function
|
|
1740
|
+
`;function Ra(e,t){let n=t.filter(t=>e.entries.has(t));if(n.length===0)return`${La}
|
|
1736
1741
|
// (no routes discovered yet — annotate a controller method with
|
|
1737
1742
|
// @Get/@Post/@Put/@Delete/@Patch and re-run \`kick typegen\`)
|
|
1738
1743
|
interface Api {}
|
|
@@ -1749,7 +1754,7 @@ export type { Api }
|
|
|
1749
1754
|
|
|
1750
1755
|
`)+`
|
|
1751
1756
|
|
|
1752
|
-
`:``,i=n.map(t=>` ${JSON.stringify(t)}: ${e.entries.get(t)}`);return`${
|
|
1757
|
+
`:``,i=n.map(t=>` ${JSON.stringify(t)}: ${e.entries.get(t)}`);return`${La}
|
|
1753
1758
|
${r}interface Api {
|
|
1754
1759
|
${i.join(`
|
|
1755
1760
|
`)}
|
|
@@ -1763,7 +1768,7 @@ declare global {
|
|
|
1763
1768
|
}
|
|
1764
1769
|
|
|
1765
1770
|
export type { Api }
|
|
1766
|
-
`}const
|
|
1771
|
+
`}const za=`kick/client`,Q=`.kickjs/types/kick__client.d.ts`,Ba=`.kickjs/cache/client-map.sha1`,Va=(()=>{try{return je(import.meta.url)(`../../../package.json`).version??`0.0.0`}catch{return`0.0.0`}})();function Ha(e){try{if(!O(e))return null;let[t,n]=k(e,`utf-8`).trim().split(/\s+/);return t&&n?{inputs:t,output:n}:null}catch{return null}}function Ua(e){return`${Pn}${za} */\n\n${e}\n`}function Wa(e){try{return O(e)?k(e,`utf-8`):null}catch{return null}}async function Ga(e){let t=A.resolve(e.cwd,Q);if(!O(t))return!1;try{await qe(t,{force:!0})}catch(t){return e.log.warn(` kick/client: could not remove the stale ${Q} — treat it as out of date (${t instanceof Error?t.message:String(t)})`),!0}return e.log.warn(` kick/client: removed the previously generated ${Q} rather than leave a stale one — re-run \`kick typegen\` once the cause above is fixed.`),!0}function Ka(e){let t=e?.typegen?.client;return typeof t==`object`?t.maxDepth:void 0}function qa(e){let t=e.config?.typegen?.client;return typeof t==`boolean`?t:t&&typeof t==`object`?t.enabled!==!1:(O(A.resolve(e.cwd,Q))&&e.log.warn(` kick/client: ${Q} exists but typegen.client is not set, so it is NOT being refreshed.\n Add \`typegen: { client: true }\` to kick.config.ts to keep it current, or delete the file if nothing reads it.`),!1)}const Ja=()=>({id:za,outExtension:`.d.ts`,inputs:[`src/**/*.controller.ts`,`src/**/*.module.ts`],async generate(e){if(!qa(e))return null;if(e.watch)return e.log.info?.(" kick/client: skipped under watch (builds a full TypeScript program). Run `kick typegen` to refresh the client route map."),null;let t=await e.getScanResult({root:A.resolve(e.cwd,e.config?.typegen?.srcDir??`src`),cwd:e.cwd}),n=[],r=new Set;for(let e of t.routes){let t=`${e.httpMethod} ${e.mountedPath??e.path}`;r.has(t)||(r.add(t),n.push(t))}let i=Ka(e.config),a=await ka({projectDir:e.cwd,keys:n,maxDepth:i,cliVersion:Va}),o=Ha(A.resolve(e.cwd,Ba)),s=Wa(A.resolve(e.cwd,Q));if(a&&o&&s!==null&&o.inputs===a&&o.output===Da(s))return Cn()&&e.log.info?.(` kick/client: unchanged, keeping ${Q}`),null;try{let t=Ra(await Aa({projectDir:e.cwd,routesFile:A.resolve(e.cwd,`.kickjs/types/kick__routes.ts`),keys:n,maxDepth:i,onWarn:t=>e.log.warn(t)}),n);return a&&!e.check&&await e.writeFile(Ba,`${a} ${Da(Ua(t))}`),t}catch(t){let n=O(A.resolve(e.cwd,Q)),r=` kick/client: skipped — ${t instanceof Error?t.message:String(t)}`;return n?e.log.warn(r):Cn()&&e.log.info?.(r),n&&await Ga(e),null}}});function Ya(e,t,n=`zod`){if(!e)return null;let r=j(t),i=N(r,e.filePath).split(ze).join(`/`);return i=i.replace(/\.(ts|tsx|mts|cts)$/i,``),i.startsWith(`.`)||(i=`./`+i),`/* eslint-disable */
|
|
1767
1772
|
// AUTO-GENERATED by \`kick typegen\`. DO NOT EDIT.
|
|
1768
1773
|
// Re-run with \`kick typegen\` or rely on \`kick dev\` to refresh.
|
|
1769
1774
|
|
|
@@ -1801,5 +1806,5 @@ declare global {
|
|
|
1801
1806
|
}
|
|
1802
1807
|
|
|
1803
1808
|
export {}
|
|
1804
|
-
`}const
|
|
1805
|
-
`)}});var
|
|
1809
|
+
`}const Xa=()=>({id:`kick/env`,outExtension:`.ts`,inputs:[`src/env.ts`,`src/**/env.ts`,`src/**/*.env.ts`],async generate(e){let t=Qa(e);if(t===!1)return null;let n=await e.getScanResult({root:Za(e),cwd:e.cwd,envFile:t});if(!n.env)return null;let r=e.config?.typegen?.schemaValidator??`zod`,i=A.resolve(e.cwd,`.kickjs/types/kick__env.ts`);return Ya(n.env,i,r)}});function Za(e){return A.resolve(e.cwd,e.config?.typegen?.srcDir??`src`)}function Qa(e){return e.config?.typegen?.envFile}function $a(e){return A.resolve(e.cwd,e.config?.typegen?.srcDir??`src`)}function eo(e){let t=e.config?.typegen?.envFile;if(t!==!1)return t}function $(e){return{root:$a(e),cwd:e.cwd,envFile:eo(e)}}const to=()=>({id:`kick/registry`,inputs:[`src/**/*.ts`],async generate(e){let t=await e.getScanResult($(e)),n=A.resolve(e.cwd,`.kickjs/types/kick__registry.d.ts`),r=new Set(t.collisions.map(e=>e.className));return xe(t.classes,n,r)}}),no=()=>({id:`kick/services`,inputs:[`src/**/*.ts`],async generate(e){let t=await e.getScanResult($(e)),n=new Set(t.collisions.map(e=>e.className)),r=ve(t.classes,t.tokens,t.injects,n);return ge(`ServiceToken`,r,"(no tokens discovered — declare with createToken<T>() or `kick g service <name>`)")}}),ro=()=>({id:`kick/modules`,inputs:[`src/**/*.ts`],async generate(e){let t=await e.getScanResult($(e));return ge(`ModuleToken`,fe(t.classes),"(no @Module classes discovered — `kick g module <name>` to add one)")}}),io=()=>({id:`kick/plugins`,inputs:[`src/**/*.ts`],async generate(e){let t=await e.getScanResult($(e));return me(t.pluginsAndAdapters)}}),ao=()=>({id:`kick/augmentations`,inputs:[`src/**/*.ts`],async generate(e){let t=await e.getScanResult($(e));return Te(t.augmentations)}}),oo=()=>({id:`kick/context`,inputs:[`src/**/*.ts`],async generate(e){let t=await e.getScanResult($(e));return t.contextKeys.length===0?null:pe(t.contextKeys)}}),so=()=>({id:`kick/route-flags`,inputs:[`src/**/*.ts`],async generate(e){let t=await e.getScanResult($(e));return ye(t.routeFlags)}}),co={fastify:{subpath:`@forinda/kickjs/fastify`,typeName:`FastifyRuntimeTypes`},h3:{subpath:`@forinda/kickjs/h3`,typeName:`H3RuntimeTypes`}},lo=()=>({id:`kick/runtime`,outExtension:`.ts`,inputs:[`kick.config.ts`,`kick.config.js`,`kick.config.mjs`,`kick.config.json`],async generate(e){let t=e.config?.runtime;if(t!==`fastify`&&t!==`h3`)return null;let{subpath:n,typeName:r}=co[t];return[`// Runtime escape-hatch types for the '${t}' engine (kick.config runtime).`,`declare module '@forinda/kickjs' {`,` interface KickRuntimeRegister {`,` runtime: import('${n}').${r}`,` }`,`}`,``,`export {}`,``].join(`
|
|
1810
|
+
`)}});var uo=e({builtinCliPlugins:()=>fo});const fo=[_({name:`kick/init`,register:nt}),_({name:`kick/generate`,register:Mn}),_({name:`kick/run`,register:Yn}),_({name:`kick/info`,register:er}),_({name:`kick/inspect`,register:ur}),_({name:`kick/add`,register:i}),_({name:`kick/list`,register:s}),_({name:`kick/explain`,register:yr}),_({name:`kick/mcp`,register:Ar}),_({name:`kick/tinker`,register:Pr}),_({name:`kick/remove`,register:Br}),_({name:`kick/typegen`,register:Ur}),_({name:`kick/check`,register:ci}),_({name:`kick/doctor`,register:Hi}),_({name:`kick/codemod`,register:Wi}),_({name:`kick/deploy`,register:ia}),_({name:`kick/registry`,typegens:[to()]}),_({name:`kick/services`,typegens:[no()]}),_({name:`kick/modules`,typegens:[ro()]}),_({name:`kick/plugins`,typegens:[io()]}),_({name:`kick/augmentations`,typegens:[ao()]}),_({name:`kick/context`,typegens:[oo()]}),_({name:`kick/route-flags`,typegens:[so()]}),_({name:`kick/assets`,typegens:[aa()]}),_({name:`kick/routes`,typegens:[ha()]}),_({name:`kick/client`,typegens:[Ja()]}),_({name:`kick/env`,typegens:[Xa()]}),_({name:`kick/runtime`,typegens:[lo()]})];export{Rn as n,fo as t};
|
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @forinda/kickjs-cli v8.
|
|
2
|
+
* @forinda/kickjs-cli v8.6.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Felix Orinda
|
|
5
5
|
*
|
|
@@ -8,4 +8,4 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
|
-
import{
|
|
11
|
+
import{m as e}from"./project-AXCA1hD9.mjs";import{a as t}from"./config-SvlcF3Ls.mjs";import{n}from"./plugin-Dn67elEZ.mjs";import{t as r}from"./builtins-CmuUgcIq.mjs";import{t as i}from"./project-root-Dgvy5kYG.mjs";import{Command as a}from"commander";import{readFileSync as o}from"node:fs";import{delimiter as s,dirname as c,join as l}from"node:path";import{fileURLToPath as u}from"node:url";function d(e,t){if(!t?.commands?.length)return;let n=new Set(e.commands.map(e=>e.name()));for(let r of t.commands){if(n.has(r.name)){console.warn(` Warning: custom command '${r.name}' skipped — conflicts with a built-in command`);continue}f(e,r)}}function f(t,n){let r=t.command(n.name).description(n.description);if(n.aliases)for(let e of n.aliases)r.alias(e);r.allowUnknownOption(!0),r.argument(`[args...]`,`Additional arguments passed to the command`);function i(){return{PATH:`${l(process.cwd(),`node_modules`,`.bin`)}${s}${process.env.PATH??``}`}}r.action(t=>{let r=t.join(` `),a=Array.isArray(n.steps)?n.steps:[n.steps];for(let t of a){let a=r?`${t} ${r}`:t;console.log(` $ ${a}`);try{e(a,void 0,i())}catch{console.error(` Command failed: ${n.name}`),process.exitCode=1;return}}})}const p=c(u(import.meta.url)),m=JSON.parse(o(l(p,`..`,`package.json`),`utf-8`));async function h(){let e=new a;e.name(`kick`).description(`KickJS — A production-grade, decorator-driven Node.js framework`).version(m.version);let o=i(process.cwd()),s=o,c=await t(s)??{},l=[...r,...c.plugins??[]],u=n(l,c.commands??[]);await u.register(e,{cwd:s,projectRoot:o,config:c,log:e=>console.log(e)}),d(e,{...c,commands:u.commands}),e.showHelpAfterError();let f=process.argv.map(e=>e===`-v`?`--version`:e);await e.parseAsync(f)}h().catch(e=>{console.error(e instanceof Error?e.message:e),process.exitCode=1});export{};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @forinda/kickjs-cli v8.6.0
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) Felix Orinda
|
|
5
|
+
*
|
|
6
|
+
* This source code is licensed under the MIT license found in the
|
|
7
|
+
* LICENSE file in the root directory of this source tree.
|
|
8
|
+
*
|
|
9
|
+
* @license MIT
|
|
10
|
+
*/
|
|
11
|
+
import{t as e}from"./rolldown-runtime-BhxEEqxa.mjs";import{existsSync as t,mkdirSync as n,readFileSync as r,writeFileSync as i}from"node:fs";import{dirname as a,isAbsolute as o,join as s,relative as c,resolve as l}from"node:path";import{fileURLToPath as u}from"node:url";import{access as d,readFile as f}from"node:fs/promises";var p=e({BUILTIN_REPO_TYPES:()=>h,DEPRECATED_REPO_TYPES:()=>g,PACKAGE_MANAGERS:()=>m,defineConfig:()=>v,hasDependency:()=>y,hasSwagger:()=>b,loadKickConfig:()=>D,resolveModuleConfig:()=>w,resolveSchemaLib:()=>x,resolveTokenScope:()=>S,validateAssetMap:()=>k,warnIfDeprecatedRepo:()=>_,writeAssetConfigSnapshot:()=>O});const m=[`pnpm`,`npm`,`yarn`,`bun`],h=[`inmemory`],g=[`prisma`,`drizzle`];function _(e){return g.includes(e)?(console.warn(` Note: '${e}' is no longer a built-in repository preset — a repository shaped to it is that library's interface, not KickJS's.\n Scaffolding a generic custom-repository stub instead; wire it to ${e} yourself.`),!0):!1}function v(e){return e}function y(e,n,i=`runtime`){try{let a=s(e,`package.json`);if(!t(a))return!1;let o=JSON.parse(r(a,`utf-8`));return o.dependencies?.[n]?!0:i===`any`&&!!o.devDependencies?.[n]}catch{return!1}}function b(e){return y(e,`@forinda/kickjs-swagger`,`runtime`)}function x(e){return y(e,`valibot`,`runtime`)?`valibot`:y(e,`yup`,`runtime`)?`yup`:`zod`}function S(e,n){if(e?.tokenScope&&typeof e.tokenScope==`string`&&e.tokenScope.length>0){let t=C(e.tokenScope);if(t.length>0)return t}try{let e=s(n,`package.json`);if(t(e)){let t=JSON.parse(r(e,`utf-8`));if(typeof t.name==`string`&&t.name.length>0){let e=t.name.match(/^@([^/]+)\//),n=C(e?e[1]:t.name);if(n.length>0)return n}}}catch{}return`app`}function C(e){return e.toLowerCase().replace(/[^a-z0-9-]/g,`-`).replace(/^-+|-+$/g,``).replace(/-{2,}/g,`-`)}function w(e){if(!e)return{};let t={dir:e.modules?.dir,repo:e.modules?.repo,schemaDir:e.modules?.schemaDir,pluralize:e.modules?.pluralize,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`&&!h.includes(t.repo)&&(_(t.repo)||console.warn(` Warning: modules.repo '${t.repo}' is not a built-in type (${h.join(`, `)}). It will generate a stub repository. Use { name: '${t.repo}' } to silence this warning.`)),t}const T=[`kick.config.ts`,`kick.config.js`,`kick.config.mjs`,`kick.config.json`];function E(e){for(let n=e;;n=a(n)){if(t(s(n,`node_modules`,`@forinda`,`kickjs-cli`,`package.json`)))return{};if(a(n)===n)break}let n=s(a(u(import.meta.url)),`..`),r=[s(n,`dist`,`index.mjs`),s(n,`src`,`index.ts`)].find(t);return r?{"@forinda/kickjs-cli":r}:{}}async function D(e){let{findProjectRoot:t}=await import(`./project-root-Dgvy5kYG.mjs`).then(e=>e.n),n=t(e);for(let e of T){let t=s(n,e);try{await d(t)}catch{continue}if(e.endsWith(`.json`)){let e=await f(t,`utf-8`);return JSON.parse(e)}if(e.endsWith(`.ts`)){let r;try{r=await import(`jiti`)}catch(t){let n=t instanceof Error?t.message:String(t);n.includes(`Cannot find package 'jiti'`)||n.includes(`ERR_MODULE_NOT_FOUND`)?console.warn(`Warning: Failed to load ${e} — 'jiti' is required for TypeScript configs. Run \`pnpm add -D jiti\` (or your package manager's equivalent), or rename the file to kick.config.js / kick.config.mjs / kick.config.json.`):console.warn(`Warning: Failed to initialize jiti for ${e}: ${n}`);continue}try{let e=await r.createJiti(n,{interopDefault:!0,fsCache:!1,alias:E(n)}).import(t,{default:!0}),i=k(e,n);for(let e of i)console.warn(` Warning: ${e}`);return O(n,e),e}catch(t){let n=t instanceof Error?t.message:String(t);console.warn(`Warning: Failed to load ${e}: ${n}`);continue}}try{let{pathToFileURL:e}=await import(`node:url`),r=await import(e(t).href),i=r.default??r,a=k(i,n);for(let e of a)console.warn(` Warning: ${e}`);return O(n,i),i}catch(t){let n=t instanceof Error?t.message:String(t);console.warn(`Warning: Failed to load ${e}: ${n}`);continue}}return null}function O(e,t){if(t?.assetMap&&Object.keys(t.assetMap).length!==0)try{let r=s(e,`.kickjs`);n(r,{recursive:!0});let a={version:1,assetMap:t.assetMap,...t.build?.outDir?{build:{outDir:t.build.outDir}}:{}};i(s(r,`kick.config.json`),JSON.stringify(a,null,2)+`
|
|
12
|
+
`,`utf-8`)}catch{}}function k(e,n){let r=[];if(!e?.assetMap)return r;let i=l(n);for(let[a,o]of Object.entries(e.assetMap)){if(!a||a.includes(`/`)){r.push(`assetMap key '${a}' is invalid — must be a non-empty string without '/'`);continue}if(typeof o?.src!=`string`||o.src.length===0){r.push(`assetMap.${a} is missing a non-empty 'src' field`);continue}let e=l(n,o.src);t(e)||r.push(`assetMap.${a}.src ('${o.src}') does not exist — typegen + build will fail`),o.dest&&A(l(n,o.dest),i)&&r.push(`assetMap.${a}.dest ('${o.dest}') resolves outside the project root — refusing to copy`)}return r}function A(e,t){let n=c(t,e);return n===``?!1:n.startsWith(`..`)||o(n)}export{D as a,S as c,b as i,_ as l,p as n,w as o,y as r,x as s,m as t};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @forinda/kickjs-cli v8.6.0
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) Felix Orinda
|
|
5
|
+
*
|
|
6
|
+
* This source code is licensed under the MIT license found in the
|
|
7
|
+
* LICENSE file in the root directory of this source tree.
|
|
8
|
+
*
|
|
9
|
+
* @license MIT
|
|
10
|
+
*/
|
|
11
|
+
import{t as e}from"./rolldown-runtime-BhxEEqxa.mjs";import{dirname as t,isAbsolute as n,join as r,relative as i,resolve as a}from"node:path";import{existsSync as o,mkdirSync as s,readFileSync as c,writeFileSync as l}from"node:fs";import{access as u,readFile as d}from"node:fs/promises";import{fileURLToPath as f}from"node:url";var p=e({BUILTIN_REPO_TYPES:()=>h,DEPRECATED_REPO_TYPES:()=>g,PACKAGE_MANAGERS:()=>m,defineConfig:()=>v,hasDependency:()=>y,hasSwagger:()=>b,loadKickConfig:()=>D,resolveModuleConfig:()=>w,resolveSchemaLib:()=>x,resolveTokenScope:()=>S,validateAssetMap:()=>k,warnIfDeprecatedRepo:()=>_,writeAssetConfigSnapshot:()=>O});const m=[`pnpm`,`npm`,`yarn`,`bun`],h=[`inmemory`],g=[`prisma`,`drizzle`];function _(e){return g.includes(e)?(console.warn(` Note: '${e}' is no longer a built-in repository preset — a repository shaped to it is that library's interface, not KickJS's.\n Scaffolding a generic custom-repository stub instead; wire it to ${e} yourself.`),!0):!1}function v(e){return e}function y(e,t,n=`runtime`){try{let i=r(e,`package.json`);if(!o(i))return!1;let a=JSON.parse(c(i,`utf-8`));return a.dependencies?.[t]?!0:n===`any`&&!!a.devDependencies?.[t]}catch{return!1}}function b(e){return y(e,`@forinda/kickjs-swagger`,`runtime`)}function x(e){return y(e,`valibot`,`runtime`)?`valibot`:y(e,`yup`,`runtime`)?`yup`:`zod`}function S(e,t){if(e?.tokenScope&&typeof e.tokenScope==`string`&&e.tokenScope.length>0){let t=C(e.tokenScope);if(t.length>0)return t}try{let e=r(t,`package.json`);if(o(e)){let t=JSON.parse(c(e,`utf-8`));if(typeof t.name==`string`&&t.name.length>0){let e=t.name.match(/^@([^/]+)\//),n=C(e?e[1]:t.name);if(n.length>0)return n}}}catch{}return`app`}function C(e){return e.toLowerCase().replace(/[^a-z0-9-]/g,`-`).replace(/^-+|-+$/g,``).replace(/-{2,}/g,`-`)}function w(e){if(!e)return{};let t={dir:e.modules?.dir,repo:e.modules?.repo,schemaDir:e.modules?.schemaDir,pluralize:e.modules?.pluralize,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`&&!h.includes(t.repo)&&(_(t.repo)||console.warn(` Warning: modules.repo '${t.repo}' is not a built-in type (${h.join(`, `)}). It will generate a stub repository. Use { name: '${t.repo}' } to silence this warning.`)),t}const T=[`kick.config.ts`,`kick.config.js`,`kick.config.mjs`,`kick.config.json`];function E(e){for(let n=e;;n=t(n)){if(o(r(n,`node_modules`,`@forinda`,`kickjs-cli`,`package.json`)))return{};if(t(n)===n)break}let n=r(t(f(import.meta.url)),`..`),i=[r(n,`dist`,`index.mjs`),r(n,`src`,`index.ts`)].find(o);return i?{"@forinda/kickjs-cli":i}:{}}async function D(e){let{findProjectRoot:t}=await import(`./project-root-C7TrLJlZ.mjs`).then(e=>e.n),n=t(e);for(let e of T){let t=r(n,e);try{await u(t)}catch{continue}if(e.endsWith(`.json`)){let e=await d(t,`utf-8`);return JSON.parse(e)}if(e.endsWith(`.ts`)){let r;try{r=await import(`jiti`)}catch(t){let n=t instanceof Error?t.message:String(t);n.includes(`Cannot find package 'jiti'`)||n.includes(`ERR_MODULE_NOT_FOUND`)?console.warn(`Warning: Failed to load ${e} — 'jiti' is required for TypeScript configs. Run \`pnpm add -D jiti\` (or your package manager's equivalent), or rename the file to kick.config.js / kick.config.mjs / kick.config.json.`):console.warn(`Warning: Failed to initialize jiti for ${e}: ${n}`);continue}try{let e=await r.createJiti(n,{interopDefault:!0,fsCache:!1,alias:E(n)}).import(t,{default:!0}),i=k(e,n);for(let e of i)console.warn(` Warning: ${e}`);return O(n,e),e}catch(t){let n=t instanceof Error?t.message:String(t);console.warn(`Warning: Failed to load ${e}: ${n}`);continue}}try{let{pathToFileURL:e}=await import(`node:url`),r=await import(e(t).href),i=r.default??r,a=k(i,n);for(let e of a)console.warn(` Warning: ${e}`);return O(n,i),i}catch(t){let n=t instanceof Error?t.message:String(t);console.warn(`Warning: Failed to load ${e}: ${n}`);continue}}return null}function O(e,t){if(t?.assetMap&&Object.keys(t.assetMap).length!==0)try{let n=r(e,`.kickjs`);s(n,{recursive:!0});let i={version:1,assetMap:t.assetMap,...t.build?.outDir?{build:{outDir:t.build.outDir}}:{}};l(r(n,`kick.config.json`),JSON.stringify(i,null,2)+`
|
|
12
|
+
`,`utf-8`)}catch{}}function k(e,t){let n=[];if(!e?.assetMap)return n;let r=a(t);for(let[i,s]of Object.entries(e.assetMap)){if(!i||i.includes(`/`)){n.push(`assetMap key '${i}' is invalid — must be a non-empty string without '/'`);continue}if(typeof s?.src!=`string`||s.src.length===0){n.push(`assetMap.${i} is missing a non-empty 'src' field`);continue}let e=a(t,s.src);o(e)||n.push(`assetMap.${i}.src ('${s.src}') does not exist — typegen + build will fail`),s.dest&&A(a(t,s.dest),r)&&n.push(`assetMap.${i}.dest ('${s.dest}') resolves outside the project root — refusing to copy`)}return n}function A(e,t){let r=i(t,e);return r===``?!1:r.startsWith(`..`)||n(r)}export{b as a,x as c,y as i,S as l,p as n,D as o,v as r,w as s,m as t,_ as u};
|
|
13
|
+
//# sourceMappingURL=config-ndsVdO8u.mjs.map
|