@forinda/kickjs-cli 8.7.9 → 8.8.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/bin.js +2 -2
- package/dist/{agent-docs-BLBI7YID.mjs → agent-docs-BsXKM5QH.mjs} +16 -12
- package/dist/agent-docs-BsXKM5QH.mjs.map +1 -0
- package/dist/{agent-docs-Ep7kO8om.mjs → agent-docs-DQksWOe5.mjs} +15 -11
- package/dist/{build-DQGyJjPJ.mjs → build-Bnd_mk4h.mjs} +3 -3
- package/dist/build-Bnd_mk4h.mjs.map +1 -0
- package/dist/{build-NKAoV4wt.mjs → build-DPUojF2G.mjs} +2 -2
- package/dist/{builtins-CAznAas6.mjs → builtins-BEBO5upe.mjs} +2 -2
- package/dist/{builtins-DrRpYzbB.mjs → builtins-CJTP3xQj.mjs} +52 -52
- package/dist/cli.mjs +2 -2
- package/dist/config-F9g6CNDA.mjs +13 -0
- package/dist/config-F9g6CNDA.mjs.map +1 -0
- package/dist/config-ty1Nc3PN.mjs +12 -0
- package/dist/{doctor-CYVZFw9C.mjs → doctor-C8TAKn1d.mjs} +10 -10
- package/dist/doctor-C8TAKn1d.mjs.map +1 -0
- package/dist/fs-BB3QxPj8.mjs +12 -0
- package/dist/fs-BB3QxPj8.mjs.map +1 -0
- package/dist/fs-BGHl3dHm.mjs +11 -0
- package/dist/{fullstack-s_aMeFzj.mjs → fullstack-D25STbVk.mjs} +5 -5
- package/dist/{fullstack-uCHI9HHB.mjs → fullstack-DWcfo-zl.mjs} +6 -6
- package/dist/fullstack-DWcfo-zl.mjs.map +1 -0
- package/dist/index.d.mts +10 -14
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/plugin-C4Dl_s4-.mjs +11 -0
- package/dist/{plugin-Dx_Z_-gx.mjs → plugin-Y7BoYk1K.mjs} +2 -2
- package/dist/project-3LsfnPLE.mjs +47 -0
- package/dist/project-3LsfnPLE.mjs.map +1 -0
- package/dist/project-BIq7_Fzk.mjs +46 -0
- package/dist/project-root-BDRPMlb9.mjs +11 -0
- package/dist/project-root-CFrn6ftT.mjs +12 -0
- package/dist/project-root-CFrn6ftT.mjs.map +1 -0
- package/dist/{prompts-QNb3FEUG.mjs → prompts-BJTp1w0l.mjs} +2 -2
- package/dist/prompts-BJTp1w0l.mjs.map +1 -0
- package/dist/{rolldown-runtime-D4R0ptAp.mjs → rolldown-runtime-OACgOwtl.mjs} +1 -1
- package/dist/{run-plugins-DFoIjByI.mjs → run-plugins-2DJy76gx.mjs} +33 -33
- package/dist/run-plugins-2DJy76gx.mjs.map +1 -0
- package/dist/typegen-BBzX2LDz.mjs +107 -0
- package/dist/typegen-BBzX2LDz.mjs.map +1 -0
- package/dist/typegen-COAIhZZ4.mjs +106 -0
- package/dist/{types-CsiChRIU.mjs → types-gy6PkRFW.mjs} +2 -2
- package/package.json +7 -7
- package/templates/template-inertia/feature.json +29 -0
- package/templates/template-inertia/files/_dot_env.append +2 -0
- package/templates/template-inertia/files/_dot_env.example.append +2 -0
- package/templates/template-inertia/files/_dot_env.test.append +1 -0
- package/templates/template-inertia/files/_dot_env.test.example.append +1 -0
- package/templates/template-inertia/files/public/favicon.svg +1 -0
- package/templates/template-inertia/files/public/robots.txt +4 -0
- package/templates/template-inertia/files/src/client/Layout.tsx +20 -0
- package/templates/template-inertia/files/src/client/app.css +8 -0
- package/templates/template-inertia/files/src/client/main.tsx +14 -0
- package/templates/template-inertia/files/src/client/pages/Error.tsx +14 -0
- package/templates/template-inertia/files/src/client/pages/Home.tsx +13 -0
- package/templates/template-inertia/files/src/client/pages/Posts/Index.tsx +38 -0
- package/templates/template-inertia/files/src/client/ssr.tsx +17 -0
- package/templates/template-inertia/files/src/index.ts +46 -0
- package/templates/template-inertia/files/src/modules/index.ts +7 -0
- package/templates/template-inertia/files/src/modules/pages/pages.controller.ts +37 -0
- package/templates/template-inertia/files/src/modules/pages/pages.module.ts +12 -0
- package/templates/template-inertia/files/tsconfig.json +22 -0
- package/templates/template-inertia/files/vite.client.config.ts +19 -0
- package/templates/template-inertia/files/vite.config.ts +40 -0
- package/templates/web-kick/files/web/src/api.ts +5 -2
- package/templates/web-kick/files/web/tsconfig.json +1 -1
- package/dist/agent-docs-BLBI7YID.mjs.map +0 -1
- package/dist/build-DQGyJjPJ.mjs.map +0 -1
- package/dist/config-BELa-bQp.mjs +0 -13
- package/dist/config-BELa-bQp.mjs.map +0 -1
- package/dist/config-kVPKaftt.mjs +0 -12
- package/dist/doctor-CYVZFw9C.mjs.map +0 -1
- package/dist/fs-DeTT9ZK-.mjs +0 -11
- package/dist/fs-nag0OfKW.mjs +0 -12
- package/dist/fs-nag0OfKW.mjs.map +0 -1
- package/dist/fullstack-uCHI9HHB.mjs.map +0 -1
- package/dist/plugin-C77kofvz.mjs +0 -11
- package/dist/project-6r0RJYMr.mjs +0 -46
- package/dist/project-DzjSBUTp.mjs +0 -47
- package/dist/project-DzjSBUTp.mjs.map +0 -1
- package/dist/project-root-BRTvnJkL.mjs +0 -12
- package/dist/project-root-BRTvnJkL.mjs.map +0 -1
- package/dist/project-root-Cw17cNBj.mjs +0 -11
- package/dist/prompts-QNb3FEUG.mjs.map +0 -1
- package/dist/run-plugins-DFoIjByI.mjs.map +0 -1
- package/dist/typegen-8MO7N1hc.mjs +0 -107
- package/dist/typegen-8MO7N1hc.mjs.map +0 -1
- package/dist/typegen-vfWafXuR.mjs +0 -106
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @forinda/kickjs-cli v8.8.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-OACgOwtl.mjs";import{statSync as t}from"node:fs";import{basename as n,dirname as r,join as i,relative as a,resolve as o,sep as s}from"node:path";import{mkdir as c,readFile as l,readdir as u,stat as d,unlink as f,writeFile as p}from"node:fs/promises";import{parseSync as m}from"oxc-parser";import{globSync as h}from"glob";import{groupAssetKeys as g}from"@forinda/kickjs";const _=[`classes`,`tokens`,`injects`,`pluginsAndAdapters`,`contextKeys`,`routeFlags`,`routes`,`moduleMounts`,`globPatterns`];function v(e){if(!e||typeof e!=`object`)return!1;let t=e;return _.every(e=>Array.isArray(t[e]))}var y=class e{path;prev;next=/* @__PURE__ */ new Map;nextSig=/* @__PURE__ */ new Map;constructor(e,t){this.path=e,this.prev=t}static async load(t){let n=i(t,`scan.json`),r=/* @__PURE__ */ new Map;try{let e=await l(n,`utf-8`),t=JSON.parse(e);if(t.version===3&&t.files)for(let[e,n]of Object.entries(t.files))n&&typeof n.sig==`string`&&v(n.extract)&&r.set(e,n)}catch{}return new e(n,r)}static async signature(e){try{let t=await d(e);return`${t.mtimeMs}:${t.size}`}catch{return null}}get(e,t){let n=this.prev.get(e);return n&&n.sig===t?n.extract:null}set(e,t,n){this.next.set(e,n),this.nextSig.set(e,t)}cachedFiles(){return[...this.prev.keys()]}peek(e){return this.prev.get(e)?.extract??null}carry(e){let t=this.prev.get(e);return t?(this.next.set(e,t.extract),this.nextSig.set(e,t.sig),!0):!1}async save(){let e={};for(let[t,n]of this.next){let r=this.nextSig.get(t);r&&(e[t]={sig:r,extract:n})}let t={version:3,files:e};try{await c(r(this.path),{recursive:!0}),await p(this.path,JSON.stringify(t),`utf-8`)}catch{}}};let b=null;function x(){return b??=new Set(ue),b}const S=/* @__PURE__ */ new Set([`Get`,`Post`,`Put`,`Delete`,`Patch`]);function C(e){return typeof e==`object`&&!!e&&typeof e.type==`string`}function w(e,t){if(Array.isArray(e))for(let n of e)w(n,t);else if(C(e)){t(e);for(let n of Object.keys(e)){if(n===`type`)continue;let r=e[n];typeof r==`object`&&r&&w(r,t)}}}function T(e){if(!C(e))return null;if(e.type===`Literal`&&typeof e.value==`string`)return e.value;if(e.type===`TemplateLiteral`){let t=e.quasis,n=e.expressions;if(t?.length===1&&(n?.length??0)===0){let e=t[0].value?.cooked;return typeof e==`string`?e:null}}return null}function E(e){return C(e)&&e.type===`Identifier`?e.name:null}function D(e){return E(e.callee)}function O(e,t){if(!e||e.type!==`ObjectExpression`)return null;for(let n of e.properties??[]){if(n.type!==`Property`)continue;let e=n.key;if((E(e)??(e.type===`Literal`?String(e.value):T(e)))===t)return n.value}return null}function k(e){let t=e.arguments?.[0];return C(t)&&t.type===`ObjectExpression`?t:null}function A(e,t){let n=O(e,t);if(!C(n)||n.type!==`ArrayExpression`)return[];let r=[];for(let e of n.elements??[]){let t=T(e);t!==null&&r.push(t)}return r}function ee(e,t){return a(t,e).split(s).join(`/`)}function te(e){return(e.match(/:([a-zA-Z_]\w*)/g)??[]).map(e=>e.slice(1))}function ne(e,t){for(let n of e.implements??[]){let e=n.expression??n;if(E(e)===t)return!0;if(e.type===`TSQualifiedName`||e.type===`MemberExpression`){let n=e.right??e.property;if(n&&E(n)===t)return!0}}return!1}function j(e){return e.decorators??[]}function M(e){let t=e.expression;if(!C(t)||t.type!==`CallExpression`)return null;let n=D(t);return n?{name:n,call:t}:null}function re(e){let t=/* @__PURE__ */ new Map,n=/* @__PURE__ */ new Set;for(let r of e.body??[]){if(r.type===`ImportDeclaration`){let e=T(r.source)??``;for(let n of r.specifiers??[]){let r=E(n.local);r&&t.set(r,{source:e})}continue}let e=r.type===`VariableDeclaration`?r:r.type===`ExportNamedDeclaration`&&C(r.declaration)?r.declaration:null;if(C(e)&&e.type===`VariableDeclaration`)for(let t of e.declarations??[]){let e=E(t.id);e&&n.add(e)}}return{imports:t,topLevelConsts:n}}function N(e,t){let n=t.imports.get(e);return n?{identifier:e,source:n.source}:t.topLevelConsts.has(e)?{identifier:e,source:``}:{identifier:e,source:null}}function ie(e,t){let n=[];for(let r of e){let e=M(r),i=e?e.name:E(r.expression);if(!i||S.has(i))continue;let a=t.imports.get(i);n.push({identifier:i,source:a?a.source:t.topLevelConsts.has(i)?``:null})}return n}const P=/* @__PURE__ */ new Set([`bootstrap`,`createWebApp`,`Application`]);function ae(e,t){if(!P.has(e))return!1;let n=t.imports.get(e)?.source;return n===`@forinda/kickjs`||(n?.startsWith(`@forinda/kickjs/`)??!1)}function oe(e,t){let n={refs:[],resolved:!1},r=F(e);if(!r||r.type!==`ArrayExpression`)return n;let i=[];for(let e of r.elements??[]){if(!C(e)||e.type!==`MemberExpression`||E(e.property)!==`registration`)return n;let r=e.object,a=E(r);if(!a&&C(r)&&r.type===`CallExpression`){let e=r.callee;C(e)&&e.type===`MemberExpression`&&E(e.property)===`with`&&(a=E(e.object))}if(!a)return n;let o=t.imports.get(a);i.push({identifier:a,source:o?o.source:t.topLevelConsts.has(a)?``:null})}return{refs:i,resolved:!0}}function F(e){let t=e.value??e;if(!C(t))return null;if(t.type===`ArrayExpression`)return t;let n=t.body;if(!C(n))return null;if(n.type!==`BlockStatement`)return n;let r=(n.body??[]).filter(e=>e.type===`ReturnStatement`);if(r.length!==1)return null;let i=r[0].argument;return C(i)?i:null}function I(e,t,n){let r=E(O(e,t));return r?N(r,n):null}function se(e,t){for(let n of e){let e=M(n);if(!e||e.name!==`ApiQueryParams`)continue;let r=e.call.arguments?.[0],i=null;if(C(r)&&r.type===`ObjectExpression`)i=r;else{let e=E(r);if(e){let n=t.get(e);n&&n.type===`ObjectExpression`&&(i=n)}}return{filterable:A(i,`filterable`),sortable:A(i,`sortable`),searchable:A(i,`searchable`)}}return null}function ce(e,t,n){let r;try{let n=m(t,e);if(n.errors.length>0)return null;r=n.program}catch{return null}let i=ee(t,n),a=re(r),o=[],s=[],c=[],l=[],u=[],d=[],f=/* @__PURE__ */ new Set,p=[],h=[],g=[],_=/* @__PURE__ */ new Set,v=/* @__PURE__ */ new Set,y=/* @__PURE__ */ new Map;w(r,e=>{if(e.type!==`VariableDeclarator`)return;let t=E(e.id),n=e.init;t&&C(n)&&y.set(n,t)});let b=/* @__PURE__ */ new Set,A=/* @__PURE__ */ new Map;for(let e of r.body??[]){let t=e.type===`VariableDeclaration`?e:e.type===`ExportNamedDeclaration`&&C(e.declaration)?e.declaration:null;if(C(t)&&t.type===`VariableDeclaration`)for(let e of t.declarations??[]){let t=E(e.id);t&&C(e.init)&&A.set(t,e.init)}}let N=[];for(let e of r.body??[])if(e.type===`ExportNamedDeclaration`&&C(e.declaration)){let t=e.declaration;t.type===`ClassDeclaration`&&N.push({cls:t,isDefault:!1})}else if(e.type===`ExportDefaultDeclaration`&&C(e.declaration)){let t=e.declaration;t.type===`ClassDeclaration`&&N.push({cls:t,isDefault:!0})}for(let{cls:e,isDefault:n}of N){let r=E(e.id);if(!r)continue;let a=null;for(let t of j(e)){let e=M(t);if(e&&x().has(e.name)){a=e.name;break}}a?o.push({className:r,decorator:a,filePath:t,relativePath:i,isDefault:n}):ne(e,`AppModule`)&&o.push({className:r,decorator:`Module`,filePath:t,relativePath:i,isDefault:n})}for(let e of r.body??[]){if(e.type!==`ExportNamedDeclaration`||!C(e.declaration))continue;let n=e.declaration;if(n.type===`VariableDeclaration`)for(let e of n.declarations??[]){let n=E(e.id),r=e.init;n&&C(r)&&r.type===`CallExpression`&&D(r)===`defineModule`&&(o.some(e=>e.className===n)||o.push({className:n,decorator:`Module`,filePath:t,relativePath:i,isDefault:!1}))}}w(r,n=>{if(n.type===`VariableDeclarator`){let e=n.init;if(C(e)&&e.type===`CallExpression`&&D(e)===`createToken`){let r=T(e.arguments?.[0]);r!==null&&(b.add(e),s.push({name:r,variable:E(n.id),filePath:t,relativePath:i}))}return}if(n.type!==`CallExpression`){if(n.type===`Decorator`){let e=M(n);if(e?.name===`Inject`){let n=T(e.call.arguments?.[0]);n!==null&&c.push({name:n,filePath:t,relativePath:i})}}return}let r=n.callee,a=D(n);if(a===`createToken`&&!b.has(n)){let e=T(n.arguments?.[0]);e!==null&&s.push({name:e,variable:null,filePath:t,relativePath:i})}else if(a===`defineAdapter`||a===`definePlugin`){let e=T(O(k(n),`name`));if(e!==null){let n=a===`definePlugin`?`plugin`:`adapter`,r=`${a}::${e}::${t}`;_.has(r)||(_.add(r),l.push({kind:n,name:e,filePath:t,relativePath:i}))}}else if(a===`defineRouteFlag`){let r=T(n.arguments?.[0]);if(r!==null&&!f.has(r)){f.add(r);let a=n.typeArguments,o=a?e.slice(a.start,a.end):null;d.push({name:r,valueType:o?o.slice(1,-1).trim():null,filePath:t,relativePath:i})}}else if(a===`defineContextDecorator`||a===`defineHttpContextDecorator`){let e=T(O(k(n),`key`));e!==null&&!v.has(e)&&(v.add(e),u.push({key:e,exportName:y.get(n)??null,filePath:t,relativePath:i}))}else if(C(r)&&r.type===`CallExpression`){let e=r.callee;if(C(e)&&e.type===`MemberExpression`&&E(e.property)===`withParams`){let r=E(e.object);if(r===`defineContextDecorator`||r===`defineHttpContextDecorator`){let e=T(O(k(n),`key`));e!==null&&!v.has(e)&&(v.add(e),u.push({key:e,exportName:y.get(n)??null,filePath:t,relativePath:i}))}}}else if(C(r)&&r.type===`MemberExpression`&&E(r.property)===`glob`){let e=r.object;C(e)&&e.type===`MetaProperty`&&w(n.arguments,e=>{let t=T(e);t!==null&&g.push(t)})}});let P=[];w(r,e=>{if(e.type===`ClassDeclaration`||e.type===`ClassExpression`){let t=E(e.id);t&&P.push({cls:e,className:t})}});for(let{cls:e,className:n}of P){let r=o.find(e=>e.className===n),s=e.body?.body;if(ne(e,`AppAdapter`))for(let e of s??[]){if(e.type!==`PropertyDefinition`||E(e.key)!==`name`)continue;let n=T(e.value);if(n===null)continue;let r=`class::${n}::${t}`;_.has(r)||(_.add(r),l.push({kind:`adapter`,name:n,filePath:t,relativePath:i}));break}for(let o of s??[]){if(o.type!==`MethodDefinition`)continue;let s=E(o.key);if(!s)continue;if(s===`routes`){le(o.value,h);continue}if(!r)continue;let c=j(o),l=se(c,A),u=[...ie(j(e),a),...ie(c,a)];for(let e of c){let o=M(e);if(!o||!S.has(o.name))continue;let c=o.call.arguments??[],d=T(c[0]),f=d&&d.length>0?d:`/`,m=C(c[1])&&c[1].type===`ObjectExpression`?c[1]:null;p.push({controller:n,method:s,httpMethod:o.name.toUpperCase(),path:f,pathParams:te(f),queryFilterable:l?.filterable??null,querySortable:l?.sortable??null,querySearchable:l?.searchable??null,bodySchema:I(m,`body`,a),querySchema:I(m,`query`,a),paramsSchema:I(m,`params`,a),responseSchema:I(m,`response`,a),filePath:t,relativePath:i,controllerIsDefaultExport:r.isDefault,appliedDecorators:u,mountedPath:f})}}}w(r,e=>{if(e.type!==`Property`||E(e.key)!==`routes`)return;let t=e.value;C(t)&&(t.type===`FunctionExpression`||t.type===`ArrowFunctionExpression`)&&le(t,h)});let F=/* @__PURE__ */ new Set,ce=/* @__PURE__ */ new Set;w(r,e=>{let t=e.type===`Property`&&E(e.key)===`contributors`,n=e.type===`MethodDefinition`&&E(e.key)===`contributors`;(t||n)&&ce.add(e)});let ue=e=>e.properties??e.body?.body??[];w(r,e=>{if(e.type!==`ObjectExpression`&&e.type!==`ClassDeclaration`)return;let t=ue(e);if(t.map(e=>E(e.key)).includes(`routes`))for(let e of t)E(e.key)===`contributors`&&F.add(e)});let L=/* @__PURE__ */ new Set;w(r,e=>{let t=e.type===`CallExpression`?D(e):e.type===`NewExpression`?E(e.callee):null;if(t===null||!ae(t,a))return;let n=k(e);if(n)for(let e of n.properties??[])e.type===`Property`&&E(e.key)===`contributors`&&L.add(e)});let R=e=>{if(e.size===0)return null;let n=[],r=!0;for(let t of e){let e=oe(t,a);e.resolved||(r=!1),n.push(...e.refs)}return{refs:n,resolved:r,filePath:t}},z=R(F),B=R(L);return{classes:o,tokens:s,injects:c,pluginsAndAdapters:l,contextKeys:u,routeFlags:d,routes:p,moduleMounts:h,globPatterns:/\.module\.[mc]?[tj]sx?$/.test(t)?g:[],moduleContributors:z,appContributors:B,hasNonDecoratorContributors:ce.size>F.size+L.size}}function le(e,t){let n=[],r=[];w(e.body,e=>{if(e.type!==`Property`)return;let t=E(e.key);if(t===`path`){let t=T(e.value);t!==null&&n.push(t)}else if(t===`controller`){let t=E(e.value);t&&/^[A-Z]/.test(t)&&r.push(t)}});let i=Math.min(n.length,r.length);for(let e=0;e<i;e++)t.push({controller:r[e],mountPath:n[e]})}const ue=[`Service`,`Controller`,`Repository`,`Injectable`,`Component`,`Module`],L=[`.ts`,`.tsx`,`.mts`,`.cts`],R=[`node_modules`,`.kickjs`,`dist`,`build`,`.test.`,`.spec.`,`.d.ts`],z=new RegExp(String.raw`@(${ue.join(`|`)})\s*\([^)]*\)`+String.raw`(?:\s*@[A-Z]\w*(?:\s*\([^)]*\))?)*`+String.raw`\s*export\s+(default\s+)?(?:abstract\s+)?class\s+(\w+)`,`g`),B=new RegExp(String.raw`export\s+(default\s+)?(?:abstract\s+)?class\s+(\w+)`+String.raw`(?:\s+extends\s+\w+(?:<[^>]*>)?)?`+String.raw`\s+implements\s+[^{]*\bAppModule\b`,`g`),de=/export\s+const\s+(\w+)\s*(?::\s*[^=]+)?=\s*defineModule\s*(?:<[^>]*>)?\s*\(/g,fe=/(?:export\s+)?const\s+(\w+)\s*(?::\s*[^=]+)?=\s*createToken\s*(?:<[^>]*>)?\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g,pe=/createToken\s*(?:<[^>]*>)?\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g,me=/@Inject\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g,V=/\b(defineAdapter|definePlugin)\s*(?:<[^>]*>)?\s*\(/g,H=/(?:(?:export\s+)?(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*(?::[^=]+)?=\s*)?\b(?:defineContextDecorator|defineHttpContextDecorator)\s*(?:\.withParams\s*<(?:[^<>]|<[^<>]*>)*>\s*\(\s*\))?\s*(?:<(?:[^<>]|<[^<>]*>)*>)?\s*\(/g,he=new RegExp(String.raw`export\s+(?:default\s+)?(?:abstract\s+)?class\s+(\w+)`+String.raw`(?:\s+extends\s+\w+(?:<[^>]*>)?)?`+String.raw`\s+implements\s+[^{]*\bAppAdapter\b`,`g`),ge=/\bname\s*(?::\s*[^=]+)?=\s*['"`]([^'"`]+)['"`]/,U=new RegExp(String.raw`@(${[`Get`,`Post`,`Put`,`Delete`,`Patch`].join(`|`)})\s*\(`,`g`);function W(e,t){let n=1;for(let r=t+1;r<e.length;r++){let t=e[r];if(t===`(`)n++;else if(t===`)`&&(n--,n===0))return r}return-1}function _e(e,t){let n=t;for(;n<e.length;){for(;n<e.length&&/\s/.test(e[n]);)n++;if(e[n]!==`@`)break;let t=e.slice(n).match(/^@([A-Z]\w*)/);if(!t)break;for(n+=t[0].length;n<e.length&&/\s/.test(e[n]);)n++;if(e[n]===`(`){let t=W(e,n);if(t<0)return null;n=t+1}}for(;n<e.length&&/\s/.test(e[n]);)n++;for(let t of[`public`,`private`,`protected`])if(e.slice(n,n+t.length)===t&&/\s/.test(e.charAt(n+t.length))){for(n+=t.length;n<e.length&&/\s/.test(e[n]);)n++;break}if(e.slice(n,n+5)===`async`&&/\s/.test(e.charAt(n+5)))for(n+=5;n<e.length&&/\s/.test(e[n]);)n++;let r=e.slice(n).match(/^([a-zA-Z_]\w*)\s*\(/);return r?{methodName:r[1],endPos:n+r[0].length}:null}function ve(e){return(e.match(/:([a-zA-Z_]\w*)/g)??[]).map(e=>e.slice(1))}function ye(e,t){let n=e.endsWith(`/`)?e.slice(0,-1):e;return!t||t===`/`?n||`/`:n+(t.startsWith(`/`)?t:`/`+t)||`/`}const be=/\b(?:public\s+|private\s+|protected\s+)?routes\s*\([^)]*\)\s*(?::\s*[A-Za-z_][\w<>[\]\s,|]*\s*)?\{/g,xe=/\bpath\s*:\s*['"`]([^'"`]*)['"`]/g,Se=/\bcontroller\s*:\s*([A-Z]\w*)\b/g,G=/\bimport\.meta\.glob\s*\(/g;function Ce(e){let t=[];for(G.lastIndex=0;G.exec(e)!==null;){let n=G.lastIndex-1,r=W(e,n);if(r<0)continue;let i=e.slice(n+1,r),a=/['"`]([^'"`]+)['"`]/g,o;for(;(o=a.exec(i))!==null;)t.push(o[1])}return t}function we(e){let t=e.replace(/[.+^$()|[\]\\]/g,`\\$&`).replace(/\?/g,`.`).replace(/\*\*\//g,`___DOUBLESTAR_SLASH___`).replace(/\*\*/g,`___DOUBLESTAR___`).replace(/\*/g,`[^/]*`).replace(/___DOUBLESTAR_SLASH___/g,`(?:.+/)?`).replace(/___DOUBLESTAR___/g,`.*`);return RegExp(`^`+t+`$`)}function Te(e,t){let n=e.startsWith(`./`)?e:`./`+e,r=!1;for(let e of t){let t=e.startsWith(`!`);we(t?e.slice(1):e).test(n)&&(r=!t)}return r}function Ee(e){let t=[];be.lastIndex=0;let n;for(;(n=be.exec(e))!==null;){let r=e.indexOf(`{`,n.index+n[0].length-1);if(r<0)continue;let i=Fe(e,r);if(i<0)continue;let a=e.slice(r+1,i),o=[];xe.lastIndex=0;let s;for(;(s=xe.exec(a))!==null;)o.push(s[1]??``);let c=[];Se.lastIndex=0;let l;for(;(l=Se.exec(a))!==null;)c.push(l[1]);let u=Math.min(o.length,c.length);for(let e=0;e<u;e++)t.push({controller:c[e],mountPath:o[e]})}return t}function K(e,t){let n=new RegExp(String.raw`\b${t}\s*:\s*([A-Za-z_$][\w$]*)`,`g`).exec(e);return n?n[1]:null}function q(e,t){let n=new RegExp(String.raw`import\s*(?:type\s+)?\{[^}]*\b${t}\b[^}]*\}\s*from\s*['"\`]([^'"\`]+)['"\`]`).exec(e);if(n)return n[1];let r=new RegExp(String.raw`import\s+(?:type\s+)?${t}\s+from\s*['"\`]([^'"\`]+)['"\`]`).exec(e);if(r)return r[1];let i=new RegExp(String.raw`import\s*\*\s*as\s+${t}\s+from\s*['"\`]([^'"\`]+)['"\`]`).exec(e);return i?i[1]:new RegExp(String.raw`(?:^|\n)\s*(?:export\s+)?const\s+${t}\b`).test(e)?``:null}function De(e,t){let n=/@ApiQueryParams\s*\(\s*([\s\S]*?)\s*\)\s*$/.exec(e);if(!n){let n=/@ApiQueryParams\s*\(([\s\S]*?)\)/.exec(e);return n?Oe(n[1].trim(),t):null}return Oe(n[1].trim(),t)}function Oe(e,t){if(e.startsWith(`{`))return ke(e);let n=/^([A-Za-z_]\w*)/.exec(e);if(n){let e=n[1],r=new RegExp(String.raw`const\s+${e}\s*(?::\s*[^=]+)?=\s*(\{[\s\S]*?\n\})`,`m`).exec(t);if(r)return ke(r[1])}return{filterable:[],sortable:[],searchable:[]}}function J(e,t){let n=new RegExp(String.raw`${t}\s*:\s*\[([\s\S]*?)\]`).exec(e);return n?Array.from(n[1].matchAll(/['"`]([^'"`]+)['"`]/g)).map(e=>e[1]):[]}function ke(e){return{filterable:J(e,`filterable`),sortable:J(e,`sortable`),searchable:J(e,`searchable`)}}async function Ae(e,t){let n=t.extensions??L,r=t.exclude??R,o=[],s;try{s=await u(e,{withFileTypes:!0,encoding:`utf-8`})}catch{return o}for(let c of s){let s=i(e,c.name),l=a(t.cwd,s);r.some(e=>l.includes(e))||(c.isDirectory()?o.push(...await Ae(s,t)):c.isFile()&&n.some(e=>c.name.endsWith(e))&&o.push(s))}return o}function Y(e,t){return a(t,e).split(s).join(`/`)}function je(e,t,n){let r=[],i=Y(t,n);z.lastIndex=0;let a;for(;(a=z.exec(e))!==null;){let[,e,n,o]=a;r.push({className:o,decorator:e,filePath:t,relativePath:i,isDefault:!!n})}B.lastIndex=0;let o;for(;(o=B.exec(e))!==null;){let[,e,n]=o;r.some(e=>e.className===n&&e.filePath===t)||r.push({className:n,decorator:`Module`,filePath:t,relativePath:i,isDefault:!!e})}de.lastIndex=0;let s;for(;(s=de.exec(e))!==null;){let[,e]=s;r.some(n=>n.className===e&&n.filePath===t)||r.push({className:e,decorator:`Module`,filePath:t,relativePath:i,isDefault:!1})}return r}function Me(e,t,n){let r=[],i=Y(t,n),a=/* @__PURE__ */ new Set;fe.lastIndex=0;let o;for(;(o=fe.exec(e))!==null;){let[e,n,s]=o;a.add(e),r.push({name:s,variable:n,filePath:t,relativePath:i})}for(pe.lastIndex=0;(o=pe.exec(e))!==null;)a.has(o[0])||r.push({name:o[1],variable:null,filePath:t,relativePath:i});return r}function Ne(e,t,n,r,i=/* @__PURE__ */ new Map){let a=[];if(r.length===0)return a;let o=Y(t,n),s=[];for(let t of r){let n=new RegExp(String.raw`class\s+${t.className}\b`).exec(e);n?.index!==void 0&&s.push({cls:t,start:n.index})}s.sort((e,t)=>e.start-t.start);for(let n=0;n<s.length;n++){let{cls:r,start:c}=s[n],l=n+1<s.length?s[n+1].start:e.length,u=e.slice(c,l);U.lastIndex=0;let d;for(;(d=U.exec(u))!==null;){let n=d[1],s=d.index,c=U.lastIndex-1,l=W(u,c);if(l<0)continue;let f=u.slice(c+1,l),p=f.match(/^\s*['"`]([^'"`]*)['"`]/),m=p&&p[1].length>0?p[1]:`/`,h=_e(u,l+1);if(!h)continue;let{methodName:g,endPos:_}=h;U.lastIndex=_;let v=De(u.slice(s,_),e),y=K(f,`body`),b=K(f,`query`),x=K(f,`params`),S=K(f,`response`),C=i.get(r.className)??``,w=C?ye(C,m):m;a.push({controller:r.className,method:g,httpMethod:n.toUpperCase(),path:m,pathParams:ve(w),queryFilterable:v?.filterable??null,querySortable:v?.sortable??null,querySearchable:v?.searchable??null,bodySchema:y?{identifier:y,source:q(e,y)}:null,querySchema:b?{identifier:b,source:q(e,b)}:null,paramsSchema:x?{identifier:x,source:q(e,x)}:null,responseSchema:S?{identifier:S,source:q(e,S)}:null,filePath:t,relativePath:o,controllerIsDefaultExport:r.isDefault,mountedPath:w})}}return a}function Pe(e,t,n){let r=[],i=Y(t,n);me.lastIndex=0;let a;for(;(a=me.exec(e))!==null;)r.push({name:a[1],filePath:t,relativePath:i});return r}function Fe(e,t){let n=1;for(let r=t+1;r<e.length;r++){let t=e[r];if(t===`{`)n++;else if(t===`}`&&(n--,n===0))return r}return-1}function Ie(e,t,n){let r=[],i=Y(t,n),a=/* @__PURE__ */ new Set;V.lastIndex=0;let o;for(;(o=V.exec(e))!==null;){let n=o[1],s=V.lastIndex-1,c=W(e,s);if(c<0)continue;let l=e.slice(s+1,c),u=/\bname\s*:\s*['"`]([^'"`]+)['"`]/.exec(l);if(!u)continue;let d=u[1],f=`${n}::${d}::${t}`;a.has(f)||(a.add(f),r.push({kind:n===`definePlugin`?`plugin`:`adapter`,name:d,filePath:t,relativePath:i}))}he.lastIndex=0;let s;for(;(s=he.exec(e))!==null;){let n=s.index,o=e.indexOf(`{`,n);if(o<0)continue;let c=Fe(e,o);if(c<0)continue;let l=e.slice(o+1,c),u=ge.exec(l);if(!u)continue;let d=u[1],f=`class::${d}::${t}`;a.has(f)||(a.add(f),r.push({kind:`adapter`,name:d,filePath:t,relativePath:i}))}return r}function Le(e,t,n){let r=[],i=Y(t,n),a=/* @__PURE__ */ new Set;H.lastIndex=0;let o;for(;(o=H.exec(e))!==null;){let n=H.lastIndex-1,s=W(e,n);if(s<0)continue;let c=e.slice(n+1,s),l=/\bkey\s*:\s*['"`]([^'"`]+)['"`]/.exec(c);if(!l)continue;let u=l[1];a.has(u)||(a.add(u),r.push({key:u,exportName:o[1]??null,filePath:t,relativePath:i}))}return r}const Re=[`src/config/index.ts`,`src/config/env.ts`,`src/config.ts`,`src/env.ts`];async function ze(e,t){let n=t===`src/env.ts`?Re:[t];for(let t of n){let n=o(e,t),r;try{r=await l(n,`utf-8`)}catch{continue}if((/\bdefineEnv\s*\(/.test(r)||/\bfrom(Zod|Valibot|Yup)\s*\(/.test(r))&&/export\s+default\b/.test(r)&&!/export\s+default\s+loadEnvFromSchema\s*\(/.test(r))return{filePath:n,relativePath:Y(n,e)}}return null}function Be(e){let t=/* @__PURE__ */ new Map;for(let n of e){let e=t.get(n.className)??[];e.push(n),t.set(n.className,e)}let n=[];for(let[e,r]of t)new Set(r.map(e=>e.filePath)).size>1&&n.push({className:e,classes:r});return n.sort((e,t)=>e.className.localeCompare(t.className)),n}const Ve=/* @__PURE__ */ new Set([`Controller`,`Service`,`Repository`,`Injectable`,`Component`,`Module`,`Middleware`,`ApiQueryParams`,`Public`,`Roles`,`Cron`,`Cacheable`,`CacheEvict`,`FileUpload`,`Asset`,`Builder`,`PostConstruct`,`PreDestroy`,`Value`,`Inject`,`Autowired`]);function X(e){return e.split(s).join(`/`).replace(/\.[mc]?[tj]sx?$/,``)}function He(e,t,n){let i=X(n);if(t===``)return i===X(e);if(t.startsWith(`.`)){let n=X(o(r(e),t));return i===n||i===`${n}/index`}let a=t.replace(/^[@~#]\//,``);if(a===t&&t.startsWith(`@`))return!1;let s=X(a);return i===s||i.endsWith(`/${s}`)}function Ue(e){let t=/* @__PURE__ */ new Map,n=/* @__PURE__ */ new Map;for(let t of e)if(t)for(let{controller:e}of t.moduleMounts)n.set(e,(n.get(e)??0)+1);for(let r of e)if(r?.moduleContributors)for(let{controller:e}of r.moduleMounts){if((n.get(e)??0)>1){t.set(e,`ambiguous`);continue}let i=t.get(e);t.set(e,i===void 0?r.moduleContributors:`ambiguous`)}return t}function We(e,t,n,r=/* @__PURE__ */ new Map,i=[]){if(n){for(let t of e)t.contextKeys=null;return}let a=/* @__PURE__ */ new Map;for(let e of t){if(!e.exportName)continue;let t=a.get(e.exportName);t?t.push(e):a.set(e.exportName,[e])}for(let t of e){let e=t.appliedDecorators;if(!e){t.contextKeys=null;continue}let n=/* @__PURE__ */ new Set,o=!0,s=(e,t)=>{if(t.source===null)return null;let n=(a.get(t.identifier)??[]).filter(n=>He(e,t.source,n.filePath));return n.length===1?n[0].key:null};for(let r of e){if(Ve.has(r.identifier))continue;let e=s(t.filePath,r);if(e===null){o=!1;break}n.add(e)}if(o)for(let e of i){if(!e.resolved){o=!1;break}for(let t of e.refs){let r=s(e.filePath,t);if(r===null){o=!1;break}n.add(r)}if(!o)break}if(o){let e=r.get(t.controller);if(e===`ambiguous`)o=!1;else if(e){if(!e.resolved)o=!1;else for(let t of e.refs){let r=s(e.filePath,t);if(r===null){o=!1;break}n.add(r)}}}t.contextKeys=o?[...n].toSorted():null}}const Ge=/\bcontributors\s*(?::|\()/;function Ke(e,t,n){return ce(e,t,n)||{...qe(e,t,n),hasNonDecoratorContributors:Ge.test(e)}}function qe(e,t,n){let r=je(e,t,n);return{classes:r,tokens:Me(e,t,n),injects:Pe(e,t,n),pluginsAndAdapters:Ie(e,t,n),routeFlags:[],contextKeys:Le(e,t,n),routes:Ne(e,t,n,r,/* @__PURE__ */ new Map),moduleMounts:Ee(e),globPatterns:/\.module\.[mc]?[tj]sx?$/.test(t)?Ce(e):[],hasNonDecoratorContributors:!1}}async function Je(e,t,n){let r=n?await y.signature(e):null;if(n&&r){let t=n.get(e,r);if(t)return n.set(e,r,t),t}let i;try{i=await l(e,`utf-8`)}catch{return null}let a=Ke(i,e,t);return n&&r&&n.set(e,r,a),a}async function Ye(e,t,n){let r=[],i=0,a=Array.from({length:Math.min(t,e.length)},async()=>{for(;;){let t=i++;if(t>=e.length)return;r[t]=await n(e[t],t)}});return await Promise.all(a),r}async function Z(e){let t=(await Ae(o(e.root),e)).toSorted(),n=e.cacheDir?await y.load(e.cacheDir):null,r=Qe(t,await Ye(t,16,t=>Je(t,e.cwd,n))),i=await ze(e.cwd,e.envFile??`src/env.ts`);return n&&await n.save(),{...r,env:i}}function Xe(e,t,n){let r=n.extensions??L,i=n.exclude??R;if(!e.startsWith(t+s)&&e!==t||!r.some(t=>e.endsWith(t)))return!1;let o=a(n.cwd,e);return!i.some(e=>o.includes(e))}async function Ze(e,t){if(!e.cacheDir)return Z(e);let n=o(e.root),r=await y.load(e.cacheDir),i=r.cachedFiles();if(i.length===0)return Z(e);let a=new Set(t.removed.map(t=>o(e.cwd,t))),s=t.changed.map(t=>o(e.cwd,t)).filter(t=>!a.has(t)&&Xe(t,n,e)),c=new Set(s),u=new Set(i);for(let e of c)u.add(e);for(let e of a)u.delete(e);let d=/* @__PURE__ */ new Map;await Ye(s,16,async t=>{if(!u.has(t))return;let n=await y.signature(t),i;try{i=await l(t,`utf-8`)}catch{u.delete(t);return}let a=Ke(i,t,e.cwd);d.set(t,a),n&&r.set(t,n,a)});let f=[...u].toSorted(),p=Qe(f,f.map(e=>d.get(e)||(r.carry(e),r.peek(e)))),m=await ze(e.cwd,e.envFile??`src/env.ts`);return await r.save(),{...p,env:m}}function Qe(e,t){let n=[],r=[],i=[],a=[],o=[],c=[],l=[],u=/* @__PURE__ */ new Map;for(let e of t)if(e)for(let{controller:t,mountPath:n}of e.moduleMounts)u.has(t)||u.set(t,n);let d=/* @__PURE__ */ new Map;for(let s=0;s<e.length;s++){let f=t[s];if(f){n.push(...f.classes),i.push(...f.tokens),a.push(...f.injects),o.push(...f.pluginsAndAdapters),c.push(...f.contextKeys),l.push(...f.routeFlags),f.globPatterns.length>0&&d.set(e[s],f.globPatterns);for(let e of f.routes){let t=u.get(e.controller);if(t){let n=ye(t,e.path);r.push({...e,pathParams:ve(n),mountedPath:n})}else r.push({...e,mountedPath:e.mountedPath??e.path})}}}We(r,c,t.some(e=>e?.hasNonDecoratorContributors===!0),Ue(t),t.flatMap(e=>e?.appContributors?[e.appContributors]:[]));let f=[];for(let[e,t]of d){if(!/\.module\.[mc]?[tj]sx?$/.test(e)||t.length===0)continue;let r=e.replaceAll(s,`/`),i=r.slice(0,r.lastIndexOf(`/`));for(let a of n){if(a.decorator===`Module`)continue;let n=a.filePath.replaceAll(s,`/`);n.startsWith(i+`/`)&&n!==r&&(Te(n.slice(i.length+1),t)||f.push({className:a.className,filePath:a.filePath,relativePath:a.relativePath,moduleFilePath:e,decorator:a.decorator}))}}n.sort((e,t)=>e.className===t.className?e.relativePath.localeCompare(t.relativePath):e.className.localeCompare(t.className)),i.sort((e,t)=>e.name.localeCompare(t.name)||e.relativePath.localeCompare(t.relativePath)),a.sort((e,t)=>e.name.localeCompare(t.name)||e.relativePath.localeCompare(t.relativePath)),r.sort((e,t)=>e.controller.localeCompare(t.controller)||e.method.localeCompare(t.method)),o.sort((e,t)=>e.name.localeCompare(t.name)||e.relativePath.localeCompare(t.relativePath)),c.sort((e,t)=>e.key.localeCompare(t.key)||e.relativePath.localeCompare(t.relativePath));let p=Be(n);return f.sort((e,t)=>e.relativePath.localeCompare(t.relativePath)||e.className.localeCompare(t.className)),{classes:n,routes:r,tokens:i,injects:a,collisions:p,pluginsAndAdapters:o,contextKeys:c,routeFlags:l,orphanedClasses:f}}function $e(e){let t=e.lastIndexOf(`.`);return t<=0?{stem:e,ext:``}:{stem:e.slice(0,t),ext:e.slice(t+1)}}function et(e){let t=e.replaceAll(`\\`,`/`),{stem:n,ext:r}=$e(t.slice(t.lastIndexOf(`/`)+1)),i=r||`ts`,a=n.lastIndexOf(`.`);return a>0?`./**/*.${n.slice(a+1)}.${i}`:`./**/*.${i}`}function tt(e){let t=/* @__PURE__ */ new Set;for(let n of e)t.add(et(n.relativePath));return[...t].toSorted()}function nt(e,t){let n=0,r=null;for(let i=t;i<e.length;i++){let t=e[i];if(r){if(t===`\\`){i++;continue}t===r&&(r=null)}else if(t===`'`||t===`"`||t==="`")r=t;else if(t===`(`)n++;else if(t===`)`&&(n--,n===0))return i}return-1}function rt(e,t,n,r){let i=null;for(let a=n;a<r;a++){let n=e[a];if(i){if(n===`\\`){a++;continue}n===i&&(i=null)}else if(n===`'`||n===`"`||n==="`")i=n;else if(n===t)return a}return-1}function it(e,t){let n=0,r=null;for(let i=t;i<e.length;i++){let t=e[i];if(r){if(t===`\\`){i++;continue}t===r&&(r=null)}else if(t===`'`||t===`"`||t==="`")r=t;else if(t===`[`)n++;else if(t===`]`&&(n--,n===0))return i}return-1}function at(e){let t=/\bimport\.meta\.glob\s*\(/g,n=[],r;for(;(r=t.exec(e))!==null;){let t=e.indexOf(`(`,r.index);if(t<0)continue;let i=nt(e,t);i<0||n.push({start:r.index,open:t,close:i})}return n}function ot(e,t){let n=at(e);if(n.length===0)return null;let r=n.find(t=>/\beager\s*:\s*true\b/.test(e.slice(t.open,t.close+1)))??n[0],i=e.slice(r.start,r.close+1),a=new Set(Ce(i).map(e=>e.startsWith(`!`)?e.slice(1):e)),o=t.filter(e=>!a.has(e));if(o.length===0)return null;let s=o.map(e=>`'${e}'`).join(`, `),c=rt(e,`[`,r.open,r.close);if(c>=0){let t=it(e,c);if(t<0||t>r.close)return null;let n=e.slice(0,t);return n+(/[[,]\s*$/.test(n)?``:`, `)+s+e.slice(t)}let l=/(['"`])((?:\\.|(?!\1).)*)\1/,u=e.slice(r.open+1,r.close),d=l.exec(u);if(!d)return null;let f=r.open+1+d.index,p=f+d[0].length;return e.slice(0,f)+`[${d[0]}, ${s}]`+e.slice(p)}const Q="/* 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",st=/* @__PURE__ */ new Set([`Service`,`Repository`,`Injectable`,`Component`]);var ct=class extends Error{collisions;constructor(e){super(lt(e)),this.name=`TokenCollisionError`,this.collisions=e}};function lt(e){let t=[`kick typegen: token collision detected`];for(let n of e){t.push(``),t.push(` ${n.classes.length} classes named '${n.className}':`);for(let e of n.classes)t.push(` - ${e.relativePath}`)}return t.push(``),t.push(`Resolutions:`),t.push(` (a) Rename one of the classes`),t.push(` (b) Use createToken<T>('namespaced/Name') and import the token explicitly — see @forinda/kickjs`),t.push(` (c) Pass --allow-duplicates to namespace the registry keys automatically`),t.push(` (e.g. 'modules/users/UserService' instead of 'UserService')`),t.join(`
|
|
12
|
+
`)}function ut(e,t){let n=r(t),i=a(n,e).split(s).join(`/`);return i=i.replace(/\.(ts|tsx|mts|cts)$/i,``),i.startsWith(`.`)||(i=`./`+i),i}function dt(e){let t=e.relativePath.replace(/^src\//,``).replace(/\.(ts|tsx|mts|cts)$/i,``).split(`/`);t.pop();let n=t.join(`/`);return n?`${n}/${e.className}`:e.className}function ft(e,t,n){let r=/* @__PURE__ */ new Set,i=[];for(let a of e){if(!st.has(a.decorator))continue;let e=n.has(a.className)?dt(a):a.className;if(r.has(e))continue;r.add(e);let o=ut(a.filePath,t),s=a.isDefault?`import('${o}').default`:`import('${o}').${a.className}`;i.push(` '${e}': ${s}`)}let a=i.length?i.join(`
|
|
13
|
+
`):" // (no services discovered yet — run `kick g service <name>` to add one)";return`${Q}
|
|
14
|
+
declare module '@forinda/kickjs' {
|
|
15
|
+
interface KickJsRegistry {
|
|
16
|
+
${a}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export {}
|
|
21
|
+
`}function pt(e){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(e)}function mt(e){let t=[...new Set(e.map(e=>e.key))].toSorted().map(e=>` ${pt(e)?e:JSON.stringify(e)}: true`).join(`
|
|
22
|
+
`);return`${Q}
|
|
23
|
+
declare module '@forinda/kickjs' {
|
|
24
|
+
/**
|
|
25
|
+
* Key-only registry of every context key produced by a
|
|
26
|
+
* \`defineContextDecorator\` / \`defineHttpContextDecorator\` in the
|
|
27
|
+
* project. Feeds \`dependsOn\` typo-checking. Value types live in
|
|
28
|
+
* \`ContextMeta\`; this only records that the key exists.
|
|
29
|
+
*/
|
|
30
|
+
interface ContextKeys {
|
|
31
|
+
${t}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export {}
|
|
36
|
+
`}function ht(e,t,n){if(t.length===0)return`${Q}
|
|
37
|
+
// ${n}
|
|
38
|
+
export type ${e} = never
|
|
39
|
+
`;let r=[...new Set(t)].toSorted();return`${Q}
|
|
40
|
+
export type ${e} =
|
|
41
|
+
${r.map(e=>` | '${e}'`).join(`
|
|
42
|
+
`)}
|
|
43
|
+
`}function gt(e,t,n,r){return[...e.filter(e=>st.has(e.decorator)).map(e=>r.has(e.className)?dt(e):e.className),...t.map(e=>e.name),...n.map(e=>e.name)]}function _t(e){return e.filter(e=>e.decorator===`Module`).map(e=>e.className)}const vt=/* @__PURE__ */ new Set(/* @__PURE__ */ `string.number.boolean.bigint.symbol.object.unknown.any.never.void.null.undefined.true.false.Array.ReadonlyArray.Record.Partial.Required.Readonly.Pick.Omit.Date.RegExp.Map.Set.ReadonlyMap.ReadonlySet.Promise.Error.URL.Uint8Array.ArrayBuffer`.split(`.`));function yt(e){return(e.replace(/'[^']*'|"[^"]*"|`[^`]*`/g,``).replace(/[A-Za-z_$][A-Za-z0-9_$]*\s*\??\s*:/g,`:`).match(/[A-Za-z_$][A-Za-z0-9_$]*/g)??[]).every(e=>vt.has(e))}const bt=e=>{let t=e??`true`,n=[];return t.replace(/'[^']*'|"[^"]*"|`[^`]*`/g,e=>(n.push(e),`@@kicklit${n.length-1}@@`)).replace(/\s+/g,``).replace(/@@kicklit(\d+)@@/g,(e,t)=>n[Number(t)])};function xt(e){let t=/* @__PURE__ */ new Map;for(let n of e){let e=t.get(n.name);if(!e)t.set(n.name,n);else if(bt(e.valueType)!==bt(n.valueType))throw Error(`Route flag '${n.name}' is declared with two different value types:\n ${e.relativePath}: ${e.valueType??`true`}\n ${n.relativePath}: ${n.valueType??`true`}\nDeclare the flag once and import it, or give the two flags different names.`)}let n=[...t.values()].toSorted((e,t)=>e.name.localeCompare(t.name)).map(e=>{let t=JSON.stringify(e.name);return e.valueType===null?` ${t}: true`:yt(e.valueType)?` ${t}: ${e.valueType}`:` // '${e.valueType.replace(/\s+/g,` `).trim()}' is declared in ${e.relativePath}, not in scope here.\n // Inline the type at the defineRouteFlag call, or declare this flag by hand.\n ${t}: unknown`}).join(`
|
|
44
|
+
`);return`${Q}
|
|
45
|
+
declare module '@forinda/kickjs' {
|
|
46
|
+
/**
|
|
47
|
+
* Every route flag declared in this project, from its \`defineRouteFlag\`
|
|
48
|
+
* call site. A bare flag carries \`true\`; one declared with an explicit
|
|
49
|
+
* value type carries that type.
|
|
50
|
+
*
|
|
51
|
+
* The \`keyof\` narrows every flag name in the codebase — \`skipWhen\`,
|
|
52
|
+
* \`onlyWhen\`, \`exemptWhen\`, \`flags.has()\` — so a typo is a compile
|
|
53
|
+
* error rather than a flag that silently never matches.
|
|
54
|
+
*/
|
|
55
|
+
interface KickRouteFlags {
|
|
56
|
+
${n||" // (no route flags discovered yet — `defineRouteFlag(...)` calls feed this)"}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export {}
|
|
61
|
+
`}function St(e){let t=/* @__PURE__ */ new Map;for(let n of e)t.has(n.name)||t.set(n.name,n);let n=[...t.values()].toSorted((e,t)=>e.name.localeCompare(t.name)).map(e=>` '${e.name}': '${e.kind}'`).join(`
|
|
62
|
+
`);return`${Q}
|
|
63
|
+
declare module '@forinda/kickjs' {
|
|
64
|
+
/**
|
|
65
|
+
* Map of every plugin/adapter \`name\` discovered in the project. The
|
|
66
|
+
* value type is the kind tag (\`'plugin'\` or \`'adapter'\`); the
|
|
67
|
+
* \`keyof\` of this interface narrows \`dependsOn\` so misspelled deps
|
|
68
|
+
* become compile errors instead of boot-time \`MissingMountDepError\`.
|
|
69
|
+
*/
|
|
70
|
+
interface KickJsPluginRegistry {
|
|
71
|
+
${n||" // (no plugins/adapters discovered yet — `defineAdapter`/`definePlugin` calls feed this)"}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export {}
|
|
76
|
+
`}const Ct=/^(kick\/)?([a-z][\w-]*\/[A-Z]\w*)(\/.+)?(:[a-z][\w-]+(:[a-z][\w-]+)*)?$/;function wt(e){let t=[];for(let n of e){let e=n.name;e.startsWith(`kickjs.`)||Ct.test(e)||t.push({token:e,variable:n.variable,filePath:n.relativePath,reason:"does not match `<scope>/<PascalKey>[/<suffix>][:<instance>]`",suggestion:Tt(e)})}return t}function Tt(e){if(/^[A-Z]\w*$/.test(e))return`'<scope>/${e}' (e.g. 'mycorp/${e}')`;if(e.includes(`.`))return`consider '<scope>/PascalKey' instead of dotted form`;let t=/^([a-z][\w-]*)\/([a-z]\w*)$/.exec(e);if(t){let[,e,n]=t;return`'${e}/${n.charAt(0).toUpperCase()}${n.slice(1)}'`}}function Et(e,t){if(!e)return{entries:[],count:0};let n=/* @__PURE__ */ new Map;for(let[r,i]of Object.entries(e)){if(!i||typeof i.src!=`string`)continue;let e=o(t,i.src);if(!jt(e))continue;let a=h(i.glob??`**/*`,{cwd:e,nodir:!0,dot:!1,posix:!0});a.sort();let{pairs:s}=g(r,a,{strategy:i.keys??`auto`});for(let{key:e}of s){let t=e.slice(r.length+1);n.set(e,{namespace:r,key:t})}}return{entries:[...n.values()],count:n.size}}function Dt(e){let t="/* 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";if(e.entries.length===0)return`${t}
|
|
77
|
+
declare module '@forinda/kickjs' {
|
|
78
|
+
/**
|
|
79
|
+
* Map of every typed asset discovered in the project's assetMap.
|
|
80
|
+
* (No assetMap entries discovered yet — declare with
|
|
81
|
+
* \`assetMap: { name: { src: 'src/...' } }\` in kick.config.ts.)
|
|
82
|
+
*/
|
|
83
|
+
interface KickAssets {}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export {}
|
|
87
|
+
`;let n={};for(let t of e.entries){let e=`${t.namespace}/${t.key}`.split(`/`),r=n;for(let t=0;t<e.length-1;t++){let n=e[t],i=r[n];if(i===Ot){let e={};r[n]=e,r=e}else i||(r[n]={}),r=r[n]}let i=e[e.length-1];typeof r[i]!=`object`&&(r[i]=Ot)}return`${t}
|
|
88
|
+
declare module '@forinda/kickjs' {
|
|
89
|
+
/**
|
|
90
|
+
* Map of every typed asset discovered in the project's assetMap.
|
|
91
|
+
* Each leaf is a \`() => string\` thunk that returns the resolved
|
|
92
|
+
* absolute path for the file in the current run mode (dev → src,
|
|
93
|
+
* prod → dist).
|
|
94
|
+
*/
|
|
95
|
+
interface KickAssets {
|
|
96
|
+
${kt(n,` `)}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export {}
|
|
101
|
+
`}const Ot=Symbol(`asset-leaf`);function kt(e,t){let n=Object.keys(e).toSorted(),r=[];for(let i of n){let n=e[i],a=At(i)?i:JSON.stringify(i);n===Ot?r.push(`${t}${a}: () => string`):(r.push(`${t}${a}: {`),r.push(kt(n,`${t} `)),r.push(`${t}}`))}return r.join(`
|
|
102
|
+
`)}function At(e){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(e)}function jt(e){try{return t(e).isDirectory()}catch{return!1}}var Mt=/* @__PURE__ */ e({runTypegen:()=>Pt,sweepStaleTypegen:()=>Rt,watchTypegen:()=>Lt,writeTypegenArtifacts:()=>$});function Nt(e){let t=e.cwd??process.cwd();return{cwd:t,srcDir:o(t,e.srcDir??`src`),outDir:o(t,e.outDir??`.kickjs/types`),silent:e.silent??!1,allowDuplicates:e.allowDuplicates??!1,schemaValidator:e.schemaValidator??!1,envFile:e.envFile??`src/env.ts`}}async function Pt(e={}){let{cwd:t,srcDir:n,outDir:r,silent:i,allowDuplicates:a,envFile:s}=Nt(e),c=Date.now(),l={root:n,cwd:t,cacheDir:e.noCache?void 0:o(t,`.kickjs`,`cache`),envFile:s===!1?void 0:s},u=e.changedFiles?await Ze(l,e.changedFiles):await Z(l);if(u.collisions.length>0&&!a)throw new ct(u.collisions);let d=Et(e.assetMap,t),f=[],p=[];if(e.runPlugins!==!1){try{let{runAllPluginTypegens:n}=await import(`./builtins-CJTP3xQj.mjs`).then(e=>e.n),{loadKickConfig:r}=await import(`./config-ty1Nc3PN.mjs`).then(e=>e.n);f=await n({cwd:t,config:await r(t),silent:!0,changedFiles:e.changedFiles})}catch(e){if(!i){let t=e instanceof Error?e.message:String(e);console.warn(` kick typegen: plugin pipeline failed (${t}) — continuing`)}}p.push(...await $(r,f,i))}let m=wt(u.tokens),h=It(u,d.count,p),g=Date.now()-c;if(!i){let e=r.replace(t+`/`,``),n=h.resolvedCollisions>0?`, ${h.resolvedCollisions} collisions namespaced`:``,i=h.envWritten?`, env typed`:``,a=h.pluginEntries>0?`, ${h.pluginEntries} plugins/adapters`:``,o=h.assetEntries>0?`, ${h.assetEntries} assets`:``;if(console.log(` kick typegen → ${h.serviceTokens} services, ${h.routeEntries} routes, ${h.moduleTokens} modules${a}${o}${i}${n} → ${e} (${g}ms)`),m.length>0){console.warn(` kick typegen: ${m.length} token(s) don't match the §22.2 convention:`);for(let e of m){let t=e.variable?` [${e.variable}]`:``;console.warn(` '${e.token}' (${e.filePath})${t} — ${e.reason}`),e.suggestion&&console.warn(` → suggestion: ${e.suggestion}`)}}}return u.orphanedClasses.length>0&&await Ft(u.orphanedClasses,{fix:e.fix??!1,silent:i}),{scan:u,result:h,tokenWarnings:m}}async function Ft(e,{fix:t,silent:n}){let r=/* @__PURE__ */ new Map;for(let t of e){let e=r.get(t.moduleFilePath)??[];e.push(t),r.set(t.moduleFilePath,e)}if(t){let e=0,t=[];for(let[i,a]of r){let r=tt(a);try{let a=await l(i,`utf-8`),o=ot(a,r);o&&o!==a?(await p(i,o),e++,n||console.log(` kick typegen --fix: patched ${i}\n + ${r.join(`, `)}`)):t.push(i)}catch{t.push(i)}}if(!n&&(e>0&&console.log(` kick typegen --fix: updated ${e} module glob(s) — re-run typegen to pick up the now-loaded classes.`),t.length>0)){console.warn(` kick typegen --fix: could not auto-patch ${t.length} module(s) (no import.meta.glob() call found) — add the patterns by hand:`);for(let e of t){let t=r.get(e)??[];console.warn(` ${e}: ${tt(t).join(`, `)}`)}}}else if(!n){console.warn(` kick typegen: ${e.length} decorated class(es) not matched by any module's import.meta.glob():`);for(let[e,t]of r){for(let e of t)console.warn(` @${e.decorator} ${e.className} (${e.relativePath})`);let n=tt(t);console.warn(` → add to import.meta.glob([...]) in ${e}:`),console.warn(` ${n.map(e=>`'${e}'`).join(`, `)}`)}console.warn(" → or run `kick typegen --fix` to apply these automatically.")}}function It(e,t,n){let r=new Set(e.collisions.map(e=>e.className)),i=e.classes.filter(e=>st.has(e.decorator)),a=gt(e.classes,e.tokens,e.injects,r);return{registryEntries:i.length,serviceTokens:new Set(a).size,moduleTokens:_t(e.classes).length,routeEntries:e.routes.length,pluginEntries:new Set(e.pluginsAndAdapters.map(e=>e.name)).size,assetEntries:t,envWritten:e.env!==null,written:n,resolvedCollisions:e.collisions.length}}async function $(e,t,n){await c(e,{recursive:!0}),await p(i(r(e),`.gitignore`),`# Auto-generated by kick typegen
|
|
103
|
+
*
|
|
104
|
+
`,`utf-8`);let a=t.filter(e=>e.outFile).map(e=>e.outFile);return await Rt(e,a,t,n),a}async function Lt(e={}){let t=Nt(e),{srcDir:n,silent:r,cwd:i}=t,a={...t,allowDuplicates:!0,runPlugins:!1,noCache:e.noCache},o=process.env.KICKJS_WATCH_POLLING===`1`||process.env.KICKJS_WATCH_POLLING===`true`,[{runAllPluginTypegens:s},{loadKickConfig:c}]=await Promise.all([import(`./builtins-CJTP3xQj.mjs`).then(e=>e.n),import(`./config-ty1Nc3PN.mjs`).then(e=>e.n)]),l=await c(i),u=async()=>{try{await Pt({...a})}catch(e){if(r)return;if(e instanceof ct)console.error(`
|
|
105
|
+
`+e.message+`
|
|
106
|
+
`);else{let t=e instanceof Error?e.message:String(e);console.error(` kick typegen failed: ${t}`)}}},d=async()=>{try{let e=await s({cwd:i,config:l,silent:!0,watch:!0});await $(t.outDir,e,!0)}catch{}};await u(),await d();let{watch:f}=await import(`node:fs`),p=null,m=e=>{e&&/\.(ts|tsx|mts|cts)$/.test(e)&&(e.includes(`.kickjs`)||e.endsWith(`.d.ts`)||(p&&clearTimeout(p),p=setTimeout(()=>{u().then(d)},100)))};if(o){r||console.log(` kick typegen: polling mode (KICKJS_WATCH_POLLING)`);let e=setInterval(()=>{u().then(d)},2e3);return()=>clearInterval(e)}let h;try{h=f(n,{recursive:!0},(e,t)=>{m(t)})}catch(e){r||console.warn(` kick typegen: watch mode unavailable (${e?.message??e}). Falling back to polling.`);let t=setInterval(()=>{u().then(d)},2e3);return()=>clearInterval(t)}return()=>{p&&clearTimeout(p),h.close()}}async function Rt(e,t,r,i){let a=/* @__PURE__ */ new Set;for(let e of t)a.add(n(e));for(let e of r)e.outFile&&a.add(n(e.outFile));let s;try{s=await u(e)}catch{return[]}let c=[];for(let t of s){if(!zt.has(t)||a.has(t))continue;let n=o(e,t);try{if(!(await d(n)).isFile())continue;await f(n),c.push(t)}catch{}}return c.length>0&&!i&&console.log(` kick typegen: swept ${c.length} stale file(s): ${c.join(`, `)}`),c}const zt=/* @__PURE__ */ new Set([`assets.d.ts`,`env.ts`,`routes.ts`,`registry.d.ts`,`services.d.ts`,`modules.d.ts`,`plugins.d.ts`,`augmentations.d.ts`,`index.d.ts`,`kick__augmentations.d.ts`]);export{T as C,C as S,M as _,Et as a,O as b,_t as c,St as d,ft as f,Ze as g,Z as h,$ as i,gt as l,ht as m,Mt as n,Dt as o,xt as p,Lt as r,ct as s,Pt as t,mt as u,j as v,w,E as x,k as y};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @forinda/kickjs-cli v8.
|
|
2
|
+
* @forinda/kickjs-cli v8.8.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Felix Orinda
|
|
5
5
|
*
|
|
@@ -8,4 +8,4 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
|
-
|
|
11
|
+
export{defineCliPlugin as n,KickPluginConflictError as t}from"@forinda/kickjs-cli-kit";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forinda/kickjs-cli",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.8.0",
|
|
4
4
|
"description": "CLI for KickJS — project scaffolding, DDD module generation, dev/build/start",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"kickjs",
|
|
@@ -41,21 +41,21 @@
|
|
|
41
41
|
"oxfmt": "^0.71.0",
|
|
42
42
|
"picocolors": "^1.1.1",
|
|
43
43
|
"pluralize": "^8.0.0",
|
|
44
|
-
"@forinda/kickjs": "
|
|
45
|
-
"@forinda/kickjs-
|
|
46
|
-
"@forinda/kickjs-
|
|
44
|
+
"@forinda/kickjs": "10.0.0",
|
|
45
|
+
"@forinda/kickjs-cli-kit": "0.1.3",
|
|
46
|
+
"@forinda/kickjs-db": "8.6.0"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@swc/core": "^1.16.13",
|
|
50
|
-
"@types/node": "^26.6.
|
|
50
|
+
"@types/node": "^26.6.5",
|
|
51
51
|
"@types/pg": "^8.23.1",
|
|
52
52
|
"@types/pluralize": "^0.0.33",
|
|
53
53
|
"@typescript/typescript6": "^6.0.2",
|
|
54
54
|
"pg": "^8.23.1",
|
|
55
55
|
"typescript": "^7.0.2",
|
|
56
|
-
"vite": "^8.3.
|
|
56
|
+
"vite": "^8.3.4",
|
|
57
57
|
"vitest": "^5.0.3",
|
|
58
|
-
"@forinda/kickjs-ai": "8.3.
|
|
58
|
+
"@forinda/kickjs-ai": "8.3.1"
|
|
59
59
|
},
|
|
60
60
|
"publishConfig": {
|
|
61
61
|
"access": "public"
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"dependencies": [
|
|
3
|
+
"@forinda/kickjs-inertia",
|
|
4
|
+
"@inertiajs/core",
|
|
5
|
+
"@inertiajs/react",
|
|
6
|
+
"react",
|
|
7
|
+
"react-dom"
|
|
8
|
+
],
|
|
9
|
+
"devDependencies": ["@vitejs/plugin-react", "@types/react", "@types/react-dom"],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "kick build && vite build --config vite.client.config.ts && vite build --config vite.client.config.ts --ssr src/client/ssr.tsx",
|
|
12
|
+
"build:netlify": "kick build && vite build --config vite.client.config.ts && vite build --config vite.client.config.ts --ssr src/client/ssr.tsx && kick build:netlify",
|
|
13
|
+
"build:vercel": "kick build && vite build --config vite.client.config.ts && vite build --config vite.client.config.ts --ssr src/client/ssr.tsx && kick build:vercel"
|
|
14
|
+
},
|
|
15
|
+
"integrations": [
|
|
16
|
+
{
|
|
17
|
+
"import": {
|
|
18
|
+
"from": "@forinda/kickjs",
|
|
19
|
+
"names": ["bootstrap", "requestId", "session"]
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"import": {
|
|
24
|
+
"from": "@forinda/kickjs-inertia",
|
|
25
|
+
"names": ["InertiaAdapter", "inertiaErrorHandler", "inertiaNotFound"]
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
SESSION_SECRET=test-session-secret-not-for-production
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
SESSION_SECRET=test-session-secret-not-for-production
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><rect width="32" height="32" rx="6" fill="#4f46e5"/></svg>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Link, usePage } from '@inertiajs/react'
|
|
2
|
+
import type { ReactNode } from 'react'
|
|
3
|
+
|
|
4
|
+
export function Layout({ children }: { children: ReactNode }) {
|
|
5
|
+
const page = usePage<{ appName: string }>()
|
|
6
|
+
const flash = page.flash as { success?: string }
|
|
7
|
+
return (
|
|
8
|
+
<main
|
|
9
|
+
style={{ fontFamily: 'system-ui', maxWidth: 640, margin: '2rem auto', padding: '0 1rem' }}
|
|
10
|
+
>
|
|
11
|
+
<nav style={{ display: 'flex', gap: 12 }}>
|
|
12
|
+
<strong>{page.props.appName}</strong>
|
|
13
|
+
<Link href="/">Home</Link>
|
|
14
|
+
<Link href="/posts">Posts</Link>
|
|
15
|
+
</nav>
|
|
16
|
+
{flash.success && <p style={{ color: 'green' }}>{flash.success}</p>}
|
|
17
|
+
{children}
|
|
18
|
+
</main>
|
|
19
|
+
)
|
|
20
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/* Global styles, imported by main.tsx (browser) and ssr.tsx (server).
|
|
2
|
+
* Tailwind: pnpm add -D tailwindcss @tailwindcss/vite, add tailwindcss() to
|
|
3
|
+
* the plugins in vite.config.ts and vite.client.config.ts, then replace this
|
|
4
|
+
* file's contents with: @import "tailwindcss";
|
|
5
|
+
*/
|
|
6
|
+
body {
|
|
7
|
+
margin: 0;
|
|
8
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import './app.css'
|
|
2
|
+
import { createInertiaApp } from '@inertiajs/react'
|
|
3
|
+
import { createRoot, hydrateRoot } from 'react-dom/client'
|
|
4
|
+
|
|
5
|
+
const pages = import.meta.glob('./pages/**/*.tsx', { eager: true })
|
|
6
|
+
|
|
7
|
+
createInertiaApp({
|
|
8
|
+
resolve: (name) => pages[`./pages/${name}.tsx`] as never,
|
|
9
|
+
setup({ el, App, props }) {
|
|
10
|
+
// Server-rendered pages are hydrated; the rest render from scratch.
|
|
11
|
+
if (el.hasAttribute('data-server-rendered')) hydrateRoot(el, <App {...props} />)
|
|
12
|
+
else createRoot(el).render(<App {...props} />)
|
|
13
|
+
},
|
|
14
|
+
})
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Link } from '@inertiajs/react'
|
|
2
|
+
import { Layout } from '~/Layout'
|
|
3
|
+
|
|
4
|
+
// Rendered for unknown URLs (404) and errors thrown while handling a page.
|
|
5
|
+
// In production a 5xx message is replaced with a generic one.
|
|
6
|
+
export default function ErrorPage({ status, message }: { status: number; message: string }) {
|
|
7
|
+
return (
|
|
8
|
+
<Layout>
|
|
9
|
+
<h1>{status}</h1>
|
|
10
|
+
<p>{message}</p>
|
|
11
|
+
<Link href="/">Back home</Link>
|
|
12
|
+
</Layout>
|
|
13
|
+
)
|
|
14
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Layout } from '~/Layout'
|
|
2
|
+
|
|
3
|
+
export default function Home({ greeting }: { greeting: string }) {
|
|
4
|
+
return (
|
|
5
|
+
<Layout>
|
|
6
|
+
<h1>{greeting}</h1>
|
|
7
|
+
<p>
|
|
8
|
+
Pages are React components in <code>src/client/pages</code>; their props come from the
|
|
9
|
+
controller in <code>src/modules/pages</code>.
|
|
10
|
+
</p>
|
|
11
|
+
</Layout>
|
|
12
|
+
)
|
|
13
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Deferred, useForm } from '@inertiajs/react'
|
|
2
|
+
import { Layout } from '~/Layout'
|
|
3
|
+
|
|
4
|
+
interface Post {
|
|
5
|
+
id: number
|
|
6
|
+
title: string
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export default function PostsIndex({ posts, stats }: { posts: Post[]; stats?: { total: number } }) {
|
|
10
|
+
const form = useForm({ title: '' })
|
|
11
|
+
return (
|
|
12
|
+
<Layout>
|
|
13
|
+
<h1>Posts</h1>
|
|
14
|
+
<Deferred data="stats" fallback={<p>Loading stats…</p>}>
|
|
15
|
+
<p>Total: {stats?.total}</p>
|
|
16
|
+
</Deferred>
|
|
17
|
+
<ul>
|
|
18
|
+
{posts.map((post) => (
|
|
19
|
+
<li key={post.id}>{post.title}</li>
|
|
20
|
+
))}
|
|
21
|
+
</ul>
|
|
22
|
+
<form
|
|
23
|
+
onSubmit={(event) => {
|
|
24
|
+
event.preventDefault()
|
|
25
|
+
form.post('/posts', { onSuccess: () => form.reset() })
|
|
26
|
+
}}
|
|
27
|
+
>
|
|
28
|
+
<input
|
|
29
|
+
aria-label="Title"
|
|
30
|
+
value={form.data.title}
|
|
31
|
+
onChange={(event) => form.setData('title', event.target.value)}
|
|
32
|
+
/>
|
|
33
|
+
<button disabled={form.processing}>Add</button>
|
|
34
|
+
{form.errors.title && <p style={{ color: 'crimson' }}>{form.errors.title}</p>}
|
|
35
|
+
</form>
|
|
36
|
+
</Layout>
|
|
37
|
+
)
|
|
38
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Also imported here, so the dev server can link it in server-rendered HTML.
|
|
2
|
+
import './app.css'
|
|
3
|
+
import { createInertiaApp } from '@inertiajs/react'
|
|
4
|
+
import type { Page } from '@inertiajs/core'
|
|
5
|
+
import { renderToString } from 'react-dom/server'
|
|
6
|
+
|
|
7
|
+
const pages = import.meta.glob('./pages/**/*.tsx', { eager: true })
|
|
8
|
+
|
|
9
|
+
// Called by InertiaAdapter to render a page on the server: the page object
|
|
10
|
+
// in, `{ head, body }` out.
|
|
11
|
+
export default (page: Page) =>
|
|
12
|
+
createInertiaApp({
|
|
13
|
+
page,
|
|
14
|
+
render: renderToString,
|
|
15
|
+
resolve: (name) => pages[`./pages/${name}.tsx`] as never,
|
|
16
|
+
setup: ({ App, props }) => <App {...props} />,
|
|
17
|
+
})
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import 'reflect-metadata'
|
|
2
|
+
// Side-effect import — registers the extended env schema with kickjs
|
|
3
|
+
// **before** any controller / service / @Value gets resolved. Without
|
|
4
|
+
// this line ConfigService.get('YOUR_KEY') returns undefined because the
|
|
5
|
+
// cached schema would still be the base shape. See guide/configuration.
|
|
6
|
+
import './config'
|
|
7
|
+
// @kick:imports
|
|
8
|
+
import { modules } from './modules'
|
|
9
|
+
|
|
10
|
+
const sessionSecret = process.env.SESSION_SECRET
|
|
11
|
+
if (!sessionSecret) throw new Error('SESSION_SECRET is not set — see .env.example')
|
|
12
|
+
|
|
13
|
+
// Export the app for the Vite plugin (dev mode)
|
|
14
|
+
export const app = await bootstrap({
|
|
15
|
+
modules,
|
|
16
|
+
// @kick:runtime
|
|
17
|
+
middlewares: [
|
|
18
|
+
requestId(),
|
|
19
|
+
// @kick:middleware
|
|
20
|
+
// Carries validation errors and flash messages to the next page.
|
|
21
|
+
session({ secret: sessionSecret }),
|
|
22
|
+
],
|
|
23
|
+
adapters: [
|
|
24
|
+
InertiaAdapter({
|
|
25
|
+
title: '{{name}}',
|
|
26
|
+
entry: 'src/client/main.tsx',
|
|
27
|
+
// On every page. Per-page titles and meta: Inertia's <Head> component.
|
|
28
|
+
head: '<link rel="icon" href="/favicon.svg" type="image/svg+xml" />',
|
|
29
|
+
// Props every page receives.
|
|
30
|
+
share: () => ({ appName: '{{name}}' }),
|
|
31
|
+
ssr: { entry: 'src/client/ssr.tsx' },
|
|
32
|
+
// Unknown URLs and thrown errors render src/client/pages/Error.tsx
|
|
33
|
+
// (through inertiaNotFound / inertiaErrorHandler below).
|
|
34
|
+
errorPage: 'Error',
|
|
35
|
+
}),
|
|
36
|
+
// @kick:adapter
|
|
37
|
+
],
|
|
38
|
+
// A failed validation on an Inertia visit goes back to the form with
|
|
39
|
+
// `props.errors` instead of answering 422.
|
|
40
|
+
onError: inertiaErrorHandler(),
|
|
41
|
+
// Unknown URLs: the Error page for browsers, the usual 404 / 405 for API calls.
|
|
42
|
+
onNotFound: inertiaNotFound(),
|
|
43
|
+
// Answer unknown URLs here in dev too — not by handing them back to Vite —
|
|
44
|
+
// so `kick dev` shows the same Error page as production on every runtime.
|
|
45
|
+
notFoundFallthrough: false,
|
|
46
|
+
})
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { defineModules } from '@forinda/kickjs'
|
|
2
|
+
import { HelloModule } from './hello/hello.module'
|
|
3
|
+
import { PagesModule } from './pages/pages.module'
|
|
4
|
+
|
|
5
|
+
// Every module the app mounts. `kick g module <name>` appends a `.mount(...)`
|
|
6
|
+
// line here; `kick rm module <name>` takes one out.
|
|
7
|
+
export const modules = defineModules().mount(HelloModule()).mount(PagesModule())
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Controller, Get, Post, type RequestContext } from '@forinda/kickjs'
|
|
2
|
+
import { defer, flash, inertia, redirect } from '@forinda/kickjs-inertia'
|
|
3
|
+
import { z } from 'zod'
|
|
4
|
+
|
|
5
|
+
// In memory for the example — swap in your repository.
|
|
6
|
+
const posts = [{ id: 1, title: 'Hello from KickJS' }]
|
|
7
|
+
|
|
8
|
+
export const createPostSchema = z.object({
|
|
9
|
+
title: z.string().trim().min(3, { error: 'Title needs at least 3 characters' }),
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
@Controller()
|
|
13
|
+
export class PagesController {
|
|
14
|
+
@Get('/')
|
|
15
|
+
home() {
|
|
16
|
+
// Renders src/client/pages/Home.tsx with these props.
|
|
17
|
+
return inertia('Home', { greeting: 'Welcome to {{name}}' })
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@Get('/posts')
|
|
21
|
+
index() {
|
|
22
|
+
return inertia('Posts/Index', {
|
|
23
|
+
posts,
|
|
24
|
+
// Loaded right after the page renders, in a second request.
|
|
25
|
+
stats: defer(() => ({ total: posts.length })),
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// A failed schema check redirects back with props.errors (see
|
|
30
|
+
// inertiaErrorHandler in src/index.ts).
|
|
31
|
+
@Post('/posts', { body: createPostSchema })
|
|
32
|
+
create(ctx: RequestContext) {
|
|
33
|
+
posts.push({ id: posts.length + 1, title: ctx.body.title })
|
|
34
|
+
flash(ctx, { success: 'Post created' })
|
|
35
|
+
return redirect('/posts')
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { defineModule } from '@forinda/kickjs'
|
|
2
|
+
import { PagesController } from './pages.controller'
|
|
3
|
+
|
|
4
|
+
export const PagesModule = defineModule({
|
|
5
|
+
name: 'PagesModule',
|
|
6
|
+
build: () => ({
|
|
7
|
+
routes() {
|
|
8
|
+
// Pages live at the site root, outside the /api/v1 prefix.
|
|
9
|
+
return { path: '/', prefix: false, version: false, controller: PagesController }
|
|
10
|
+
},
|
|
11
|
+
}),
|
|
12
|
+
})
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
7
|
+
"jsx": "react-jsx",
|
|
8
|
+
"types": ["node", "vite/client"],
|
|
9
|
+
"strict": true,
|
|
10
|
+
"esModuleInterop": true,
|
|
11
|
+
"skipLibCheck": true,
|
|
12
|
+
"sourceMap": true,
|
|
13
|
+
"experimentalDecorators": true,
|
|
14
|
+
"emitDecoratorMetadata": true,
|
|
15
|
+
"outDir": "dist",
|
|
16
|
+
"paths": {
|
|
17
|
+
"@/*": ["./src/*"],
|
|
18
|
+
"~/*": ["./src/client/*"]
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"include": ["src", "db", ".kickjs/types/**/*.d.ts", ".kickjs/types/**/*.ts"]
|
|
22
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { defineConfig } from 'vite'
|
|
2
|
+
import react from '@vitejs/plugin-react'
|
|
3
|
+
|
|
4
|
+
// Production builds of the pages (`pnpm build` runs both):
|
|
5
|
+
// vite build --config vite.client.config.ts → dist/client
|
|
6
|
+
// vite build --config vite.client.config.ts --ssr src/client/ssr.tsx → dist/ssr/ssr.js
|
|
7
|
+
// InertiaAdapter reads dist/client/.vite/manifest.json for the script tags
|
|
8
|
+
// and renders pages with dist/ssr/ssr.js.
|
|
9
|
+
export default defineConfig(({ isSsrBuild }) => ({
|
|
10
|
+
// The server's .env sets NODE_ENV=development, which would make these
|
|
11
|
+
// development builds. The browser bundle needs nothing from it.
|
|
12
|
+
envDir: false,
|
|
13
|
+
plugins: [react()],
|
|
14
|
+
// Same aliases as the dev server: tsconfig.json `paths`.
|
|
15
|
+
resolve: { tsconfigPaths: true },
|
|
16
|
+
build: isSsrBuild
|
|
17
|
+
? { outDir: 'dist/ssr' }
|
|
18
|
+
: { outDir: 'dist/client', manifest: true, rollupOptions: { input: 'src/client/main.tsx' } },
|
|
19
|
+
}))
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { defineConfig } from 'vite'
|
|
2
|
+
import { fileURLToPath } from 'node:url'
|
|
3
|
+
import swc from 'unplugin-swc'
|
|
4
|
+
import react from '@vitejs/plugin-react'
|
|
5
|
+
import { kickjsVitePlugin, envWatchPlugin } from '@forinda/kickjs-vite'
|
|
6
|
+
|
|
7
|
+
// Dev server for the API and the pages. swc compiles both sides —
|
|
8
|
+
// decorators on the server, JSX (tsconfig "jsx": "react-jsx") in
|
|
9
|
+
// src/client — and react() adds Fast Refresh.
|
|
10
|
+
export default defineConfig({
|
|
11
|
+
oxc: false,
|
|
12
|
+
plugins: [
|
|
13
|
+
swc.vite(),
|
|
14
|
+
react(),
|
|
15
|
+
kickjsVitePlugin({ entry: 'src/index.ts' }),
|
|
16
|
+
// Watches .env files and triggers a full reload on change so the
|
|
17
|
+
// dev server picks up env tweaks without a manual restart.
|
|
18
|
+
envWatchPlugin(),
|
|
19
|
+
],
|
|
20
|
+
// The server renders the HTML, so Vite has no index.html to scan for the
|
|
21
|
+
// browser's dependencies — name the entry and the CommonJS ones.
|
|
22
|
+
optimizeDeps: {
|
|
23
|
+
entries: ['src/client/main.tsx'],
|
|
24
|
+
include: ['react', 'react-dom/client', 'react/jsx-runtime', 'react/jsx-dev-runtime'],
|
|
25
|
+
},
|
|
26
|
+
// @kick:vite-option
|
|
27
|
+
// Aliases come from tsconfig.json `paths` — one list for the server,
|
|
28
|
+
// the pages and the editor.
|
|
29
|
+
resolve: { tsconfigPaths: true },
|
|
30
|
+
build: {
|
|
31
|
+
target: 'node20',
|
|
32
|
+
ssr: true,
|
|
33
|
+
outDir: 'dist',
|
|
34
|
+
sourcemap: true,
|
|
35
|
+
rollupOptions: {
|
|
36
|
+
input: fileURLToPath(new URL('./src/index.ts', import.meta.url)),
|
|
37
|
+
output: { format: 'esm' },
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
})
|