@forinda/kickjs-cli 8.13.0 → 8.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/{agent-docs-DD0hT2pE.mjs → agent-docs-BxuvlGy4.mjs} +3 -3
  2. package/dist/{agent-docs-DD0hT2pE.mjs.map → agent-docs-BxuvlGy4.mjs.map} +1 -1
  3. package/dist/{agent-docs-D0qgHBA8.mjs → agent-docs-Dq_azKfQ.mjs} +2 -2
  4. package/dist/{build-DEdLI54B.mjs → build-eFEdQsTj.mjs} +3 -3
  5. package/dist/{build-DEdLI54B.mjs.map → build-eFEdQsTj.mjs.map} +1 -1
  6. package/dist/{build-C1ZgYqj7.mjs → build-t8pGkT7W.mjs} +2 -2
  7. package/dist/{builtins-DZ-kQSyt.mjs → builtins-DCvidf69.mjs} +4 -4
  8. package/dist/{builtins-BWtf5CEP.mjs → builtins-ubUekPfw.mjs} +2 -2
  9. package/dist/cli.mjs +2 -2
  10. package/dist/{config-CQGH0FTE.mjs → config-BIlu1hs0.mjs} +2 -2
  11. package/dist/{config-CHRM7WLZ.mjs → config-D0zuz3Fx.mjs} +3 -3
  12. package/dist/{config-CHRM7WLZ.mjs.map → config-D0zuz3Fx.mjs.map} +1 -1
  13. package/dist/{doctor-D0uazKD7.mjs → doctor-BDlJqXWX.mjs} +4 -4
  14. package/dist/{doctor-D0uazKD7.mjs.map → doctor-BDlJqXWX.mjs.map} +1 -1
  15. package/dist/{fullstack-Cr5tath7.mjs → fullstack-BWdQFw3R.mjs} +4 -4
  16. package/dist/{fullstack-Cr5tath7.mjs.map → fullstack-BWdQFw3R.mjs.map} +1 -1
  17. package/dist/{fullstack-C8k03oM8.mjs → fullstack-C6hCr30Z.mjs} +3 -3
  18. package/dist/index.mjs +2 -2
  19. package/dist/{package-manager-mqxVziQ9.mjs → package-manager-CSsqVTZ-.mjs} +3 -3
  20. package/dist/{package-manager-mqxVziQ9.mjs.map → package-manager-CSsqVTZ-.mjs.map} +1 -1
  21. package/dist/{package-manager-B-BW1RBj.mjs → package-manager-D5grCG_d.mjs} +2 -2
  22. package/dist/{plugin-DSgKyJSD.mjs → plugin-BXckYw0A.mjs} +2 -2
  23. package/dist/{plugin-MPu_4sWN.mjs → plugin-CGlWHBFX.mjs} +2 -2
  24. package/dist/{project--T8NPgfc.mjs → project-BE7J8TpW.mjs} +5 -5
  25. package/dist/{project-w-OcvS26.mjs → project-B_yEOLE4.mjs} +6 -6
  26. package/dist/project-B_yEOLE4.mjs.map +1 -0
  27. package/dist/{project-root-BsIxM6Gj.mjs → project-root-B1zLyHn6.mjs} +2 -2
  28. package/dist/{project-root-C4lAZePJ.mjs → project-root-DYJU7ROd.mjs} +3 -3
  29. package/dist/{project-root-C4lAZePJ.mjs.map → project-root-DYJU7ROd.mjs.map} +1 -1
  30. package/dist/{rolldown-runtime-BVrPnwAV.mjs → rolldown-runtime-Bn82Wzut.mjs} +1 -1
  31. package/dist/{run-plugins-cqNounm7.mjs → run-plugins-B8vUgyD4.mjs} +4 -4
  32. package/dist/{run-plugins-cqNounm7.mjs.map → run-plugins-B8vUgyD4.mjs.map} +1 -1
  33. package/dist/{typegen-Ctafx65M.mjs → typegen-B3mw3F07.mjs} +5 -5
  34. package/dist/{typegen-Ctafx65M.mjs.map → typegen-B3mw3F07.mjs.map} +1 -1
  35. package/dist/{typegen-BfFiyGeh.mjs → typegen-CAni3mL3.mjs} +4 -4
  36. package/dist/{types-CH5itn9u.mjs → types-DJMtN7wo.mjs} +1 -1
  37. package/package.json +2 -2
  38. package/templates/feature-devtools/feature.json +1 -1
  39. package/dist/project-w-OcvS26.mjs.map +0 -1
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs-cli v8.13.0
2
+ * @forinda/kickjs-cli v8.13.1
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,6 +8,6 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import{t as e}from"./rolldown-runtime-BVrPnwAV.mjs";import{dirname as t,isAbsolute as n,join as r,relative as i,resolve as a}from"node:path";import{cpSync as o,existsSync as s,mkdirSync as c,statSync as l,writeFileSync as u}from"node:fs";import{glob as d}from"glob";import{groupAssetKeys as f}from"@forinda/kickjs";var p=/* @__PURE__ */ e({ASSET_MANIFEST_VERSION:()=>1,buildAssets:()=>m});async function m(e,t){let{cwd:n,silent:o=!1}=t,s=t.distDir??e?.build?.outDir??`dist`,l=e?.assetMap;if(!l||Object.keys(l).length===0)return null;let d=o?()=>{}:console.log,f=a(n,s);c(f,{recursive:!0});let p=[],m={};for(let[e,t]of Object.entries(l)){let r=await h(e,t,n,f);p.push(r.entrySummary),Object.assign(m,r.manifestSlice),d(` ✓ ${e}: ${r.entrySummary.filesCopied} file(s) → ${r.entrySummary.dest}`)}let g={version:1,entries:m},_=r(f,`.kickjs-assets.json`);return u(_,JSON.stringify(g,null,2)+`
11
+ import{t as e}from"./rolldown-runtime-Bn82Wzut.mjs";import{dirname as t,isAbsolute as n,join as r,relative as i,resolve as a}from"node:path";import{cpSync as o,existsSync as s,mkdirSync as c,statSync as l,writeFileSync as u}from"node:fs";import{glob as d}from"glob";import{groupAssetKeys as f}from"@forinda/kickjs";var p=/* @__PURE__ */ e({ASSET_MANIFEST_VERSION:()=>1,buildAssets:()=>m});async function m(e,t){let{cwd:n,silent:o=!1}=t,s=t.distDir??e?.build?.outDir??`dist`,l=e?.assetMap;if(!l||Object.keys(l).length===0)return null;let d=o?()=>{}:console.log,f=a(n,s);c(f,{recursive:!0});let p=[],m={};for(let[e,t]of Object.entries(l)){let r=await h(e,t,n,f);p.push(r.entrySummary),Object.assign(m,r.manifestSlice),d(` ✓ ${e}: ${r.entrySummary.filesCopied} file(s) → ${r.entrySummary.dest}`)}let g={version:1,entries:m},_=r(f,`.kickjs-assets.json`);return u(_,JSON.stringify(g,null,2)+`
12
12
  `,`utf-8`),d(` ✓ wrote manifest → ${i(n,_)} (${Object.keys(m).length} entries)`),{manifestPath:_,entries:p,manifest:g}}async function h(e,n,l,u){let p=a(l,n.src),m=n.dest?a(l,n.dest):r(u,e);if(v(m,l))return console.warn(` ⚠ assetMap.${e}.dest ('${n.dest}') resolves outside the project root — skipping copy`),{entrySummary:{namespace:e,src:n.src,dest:i(l,m),filesCopied:0},manifestSlice:{}};if(!s(p)||!y(p))return{entrySummary:{namespace:e,src:n.src,dest:i(l,m),filesCopied:0},manifestSlice:{}};let h=n.glob??`**/*`,b=await d(h,{cwd:p,nodir:!0,dot:!1,posix:!0});c(m,{recursive:!0});let x={},S=[...b].toSorted(),{pairs:C,collisionGroupsResolved:w}=f(e,S,{strategy:n.keys??`auto`}),T=0;for(let{rel:e,key:n}of C){let i=r(p,e),a=r(m,e);x[n]=_(u,a),!g(i,a)&&(c(t(a),{recursive:!0}),o(i,a),T++)}return w>0&&console.log(` ℹ assetMap.${e}: auto-resolved ${w} basename collision(s) by keeping extensions (set 'keys: "strip"' to opt back into legacy last-write-wins behaviour, or 'keys: "with-extension"' to keep all keys verbose).`),{entrySummary:{namespace:e,src:n.src,dest:i(l,m),filesCopied:T},manifestSlice:x}}function g(e,t){if(!s(t))return!1;try{let n=l(e),r=l(t);return r.size===n.size&&r.mtimeMs>=n.mtimeMs}catch{return!1}}function _(e,t){return i(e,t).split(/[\\/]/).filter(Boolean).join(`/`)}function v(e,t){let r=i(t,e);return r===``?!1:r.startsWith(`..`)||n(r)}function y(e){try{return l(e).isDirectory()}catch{return!1}}export{p as n,m as t};
13
- //# sourceMappingURL=build-DEdLI54B.mjs.map
13
+ //# sourceMappingURL=build-eFEdQsTj.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"build-DEdLI54B.mjs","names":["__exportAll","build_exports","buildAssets","opts","distDir","config","map","log","silent","distAbs","resolve","cwd","mkdirSync","summary","manifestEntries","namespace","entry","result","processEntry","manifest","manifestPath","join","writeFileSync","relative","srcAbs","destAbs","escapesRoot","existsSync","isDirectorySync","pattern","matches","glob","manifestSlice","sorted","groupAssetKeys","filesCopied","relPath","pairs","srcFile","destFile","key","toManifestRelative","dirname","cpSync","collisionGroupsResolved","isUpToDate","s","statSync","d","manifestDir","rel","root","path","isAbsolute"],"sources":["../src/asset-manager/build.ts"],"sourcesContent":["/**\n * Build pipeline for `assetMap` entries (asset-manager PR 2).\n *\n * For each entry, walks `src/<...>` matching the configured `glob`,\n * copies matches into `dest` (default `dist/<name>/`), then emits a\n * `dist/.kickjs-assets.json` manifest mapping logical\n * `<namespace>/<key>` keys to repo-relative paths inside `dist/`.\n *\n * Pure function on top of `node:fs` + `glob` — no shell, no side\n * effects beyond the configured directory writes. The build entry-\n * point in `commands/run.ts` calls `buildAssets` after the existing\n * `copyDirs` step.\n *\n * @module @forinda/kickjs-cli/asset-manager/build\n */\n\nimport { cpSync, existsSync, mkdirSync, statSync, writeFileSync } from 'node:fs'\nimport { dirname, isAbsolute, join, relative, resolve } from 'node:path'\nimport { glob } from 'glob'\nimport { groupAssetKeys } from '@forinda/kickjs'\nimport type { AssetMapEntry, KickConfig } from '../config'\n\n/** Wire-format version for `dist/.kickjs-assets.json`. Bump on shape change. */\nexport const ASSET_MANIFEST_VERSION = 1 as const\n\n/** On-disk manifest format (`dist/.kickjs-assets.json`). */\nexport interface AssetManifest {\n version: typeof ASSET_MANIFEST_VERSION\n /**\n * Logical key → manifest-relative path. Logical key is\n * `<namespace>/<key>` where `<key>` is the file path under `src`\n * with the extension stripped + path separators normalised.\n *\n * Path values are relative to the manifest file's directory so the\n * runtime can resolve them with a single `path.resolve(manifestDir,\n * entry)` regardless of where dist/ lives.\n */\n entries: Record<string, string>\n}\n\nexport interface BuildAssetsOptions {\n /** Project root — resolved for every relative path in the entry. */\n cwd: string\n /**\n * Output dir for the manifest + per-namespace asset copies. When\n * omitted, falls back to `config.build?.outDir` (resolved against\n * `cwd`), then to `dist/` under cwd. Adopters with a custom Vite\n * `build.outDir` should set `kick.config.ts.build.outDir` to match.\n */\n distDir?: string\n /** Suppress per-entry log lines. Default: false. */\n silent?: boolean\n}\n\n/** One entry in the per-build summary returned by `buildAssets`. */\nexport interface BuildAssetsEntryResult {\n namespace: string\n src: string\n dest: string\n /**\n * Number of files actually written this run. On an incremental\n * rebuild where nothing changed this is 0 even though the manifest\n * still lists every matched file.\n */\n filesCopied: number\n}\n\n/** Aggregated outcome of `buildAssets`. */\nexport interface BuildAssetsResult {\n manifestPath: string\n entries: BuildAssetsEntryResult[]\n /** `entries` merged into a single record — useful for tests + tooling. */\n manifest: AssetManifest\n}\n\n/**\n * Run the full asset build for a loaded config:\n *\n * 1. For each `assetMap` entry, glob → copy → manifest stub.\n * 2. Write `dist/.kickjs-assets.json`.\n *\n * Returns a summary including the manifest contents. No-op (and no\n * manifest written) when `assetMap` is empty / missing — the build\n * pipeline shouldn't litter `dist/` with empty manifests for\n * adopters who don't use the feature.\n */\nexport async function buildAssets(\n config: KickConfig | null,\n opts: BuildAssetsOptions,\n): Promise<BuildAssetsResult | null> {\n const { cwd, silent = false } = opts\n // Resolution order: explicit opts.distDir → config.build.outDir → 'dist'.\n // The CLI build command passes nothing explicit, so adopters control\n // the output via kick.config.ts.build.outDir alone.\n const distDir = opts.distDir ?? config?.build?.outDir ?? 'dist'\n const map = config?.assetMap\n if (!map || Object.keys(map).length === 0) return null\n\n const log = silent ? () => {} : console.log\n\n const distAbs = resolve(cwd, distDir)\n mkdirSync(distAbs, { recursive: true })\n\n const summary: BuildAssetsEntryResult[] = []\n const manifestEntries: Record<string, string> = {}\n\n for (const [namespace, entry] of Object.entries(map)) {\n const result = await processEntry(namespace, entry, cwd, distAbs)\n summary.push(result.entrySummary)\n Object.assign(manifestEntries, result.manifestSlice)\n log(\n ` ✓ ${namespace}: ${result.entrySummary.filesCopied} file(s) → ${result.entrySummary.dest}`,\n )\n }\n\n const manifest: AssetManifest = {\n version: ASSET_MANIFEST_VERSION,\n entries: manifestEntries,\n }\n const manifestPath = join(distAbs, '.kickjs-assets.json')\n writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\\n', 'utf-8')\n log(\n ` ✓ wrote manifest → ${relative(cwd, manifestPath)} (${Object.keys(manifestEntries).length} entries)`,\n )\n\n return { manifestPath, entries: summary, manifest }\n}\n\n/** Per-entry inner pipeline — extracted for unit-test reuse. */\nasync function processEntry(\n namespace: string,\n entry: AssetMapEntry,\n cwd: string,\n distAbs: string,\n): Promise<{\n entrySummary: BuildAssetsEntryResult\n manifestSlice: Record<string, string>\n}> {\n const srcAbs = resolve(cwd, entry.src)\n const destAbs = entry.dest ? resolve(cwd, entry.dest) : join(distAbs, namespace)\n\n // Defensive: refuse to write outside the project root (cwd) even\n // though validateAssetMap warned about it at config-load time. The\n // build step shouldn't trust upstream warnings — a typo like\n // `dest: '../../'` would otherwise sprinkle files outside the\n // workspace despite the warning being printed.\n if (escapesRoot(destAbs, cwd)) {\n console.warn(\n ` ⚠ assetMap.${namespace}.dest ('${entry.dest}') resolves outside the project root — skipping copy`,\n )\n return {\n entrySummary: { namespace, src: entry.src, dest: relative(cwd, destAbs), filesCopied: 0 },\n manifestSlice: {},\n }\n }\n\n // Treat src-not-a-directory the same as src-missing — `glob` would\n // throw if pointed at a file, surfacing as a generic build failure\n // instead of a clean 0-files entry. Matches the validator's warning\n // shape (already emitted at config-load time for the missing case).\n if (!existsSync(srcAbs) || !isDirectorySync(srcAbs)) {\n return {\n entrySummary: { namespace, src: entry.src, dest: relative(cwd, destAbs), filesCopied: 0 },\n manifestSlice: {},\n }\n }\n\n const pattern = entry.glob ?? '**/*'\n // `glob` returns paths relative to `cwd` when `cwd` is set —\n // exactly the slugs we want for the manifest keys.\n const matches = await glob(pattern, {\n cwd: srcAbs,\n nodir: true,\n dot: false,\n posix: true,\n })\n\n mkdirSync(destAbs, { recursive: true })\n\n const manifestSlice: Record<string, string> = {}\n // Sort the walk so the manifest is byte-stable across platforms.\n // The `groupAssetKeys` helper preserves input order, so a stable\n // sort here makes the resulting manifest stable too.\n const sorted = [...matches].toSorted()\n const { pairs, collisionGroupsResolved } = groupAssetKeys(namespace, sorted, {\n strategy: entry.keys ?? 'auto',\n })\n\n // Copy the files and write the keyed manifest slice. Both come from\n // the same `pairs` order so the on-disk layout matches the\n // manifest's iteration order — easier to grep in cold-start\n // debugging.\n //\n // Incremental: skip the copy when the destination is already\n // up-to-date (exists, same size, mtime ≥ source). `cpSync` stamps the\n // copy with the current time, so an unchanged source always satisfies\n // `dest.mtime ≥ src.mtime` on the next run — turning a re-build into a\n // pure stat sweep instead of re-copying every asset. The manifest\n // slice is written unconditionally so the manifest stays complete.\n let filesCopied = 0\n for (const { rel: relPath, key } of pairs) {\n const srcFile = join(srcAbs, relPath)\n const destFile = join(destAbs, relPath)\n manifestSlice[key] = toManifestRelative(distAbs, destFile)\n if (isUpToDate(srcFile, destFile)) continue\n mkdirSync(dirname(destFile), { recursive: true })\n cpSync(srcFile, destFile)\n filesCopied++\n }\n\n if (collisionGroupsResolved > 0) {\n console.log(\n ` ℹ assetMap.${namespace}: auto-resolved ${collisionGroupsResolved} basename collision(s) by keeping extensions ` +\n `(set 'keys: \"strip\"' to opt back into legacy last-write-wins behaviour, or 'keys: \"with-extension\"' to keep all keys verbose).`,\n )\n }\n\n return {\n entrySummary: {\n namespace,\n src: entry.src,\n dest: relative(cwd, destAbs),\n filesCopied,\n },\n manifestSlice,\n }\n}\n\n/**\n * Is `destFile` already a current copy of `srcFile`? True when the\n * destination exists with the same byte size and an mtime no older than\n * the source. Used to skip redundant copies on an incremental rebuild.\n */\nfunction isUpToDate(srcFile: string, destFile: string): boolean {\n if (!existsSync(destFile)) return false\n try {\n const s = statSync(srcFile)\n const d = statSync(destFile)\n return d.size === s.size && d.mtimeMs >= s.mtimeMs\n } catch {\n return false\n }\n}\n\n/**\n * Make `destFile` relative to the manifest's directory + force POSIX\n * separators so the manifest is byte-stable across platforms.\n */\nfunction toManifestRelative(manifestDir: string, destFile: string): string {\n const rel = relative(manifestDir, destFile)\n // path.relative returns OS-native separators; the manifest is JSON\n // and the runtime uses path.resolve which handles either, but a\n // forward-slash manifest is grep-friendly + diff-stable.\n return rel.split(/[\\\\/]/).filter(Boolean).join('/')\n}\n\n/**\n * Pure manifest writer — handy for tests that want to assert against\n * a hand-crafted manifest without exercising the full pipeline.\n */\nexport function writeAssetManifest(distDir: string, manifest: AssetManifest): string {\n const path = join(distDir, '.kickjs-assets.json')\n mkdirSync(distDir, { recursive: true })\n writeFileSync(path, JSON.stringify(manifest, null, 2) + '\\n', 'utf-8')\n return path\n}\n\n/**\n * Read + parse a manifest from disk. Returns `null` on missing or\n * malformed file rather than throwing — the runtime resolver wants\n * to fall through to dev-mode lookup in that case.\n */\nexport function readAssetManifest(distDir: string): AssetManifest | null {\n const path = join(distDir, '.kickjs-assets.json')\n if (!existsSync(path)) return null\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const fs = require('node:fs') as typeof import('node:fs')\n const raw = fs.readFileSync(path, 'utf-8')\n const parsed = JSON.parse(raw) as Partial<AssetManifest>\n if (parsed.version !== ASSET_MANIFEST_VERSION) return null\n if (!parsed.entries || typeof parsed.entries !== 'object') return null\n return parsed as AssetManifest\n } catch {\n return null\n }\n}\n\n/**\n * Project-root escape check that's safe across symlinks + drive letters.\n * `path.relative` returns `..` segments when the target sits above root,\n * and an absolute path when the two live on different roots (Windows).\n * `startsWith(root)` would miss both cases.\n */\nfunction escapesRoot(path: string, root: string): boolean {\n const rel = relative(root, path)\n if (rel === '') return false\n return rel.startsWith('..') || isAbsolute(rel)\n}\n\n/** Pure helper — `false` for missing, non-dir, or unreadable paths. */\nfunction isDirectorySync(path: string): boolean {\n try {\n return statSync(path).isDirectory()\n } catch {\n return false\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"build-eFEdQsTj.mjs","names":["__exportAll","build_exports","buildAssets","opts","distDir","config","map","log","silent","distAbs","resolve","cwd","mkdirSync","summary","manifestEntries","namespace","entry","result","processEntry","manifest","manifestPath","join","writeFileSync","relative","srcAbs","destAbs","escapesRoot","existsSync","isDirectorySync","pattern","matches","glob","manifestSlice","sorted","groupAssetKeys","filesCopied","relPath","pairs","srcFile","destFile","key","toManifestRelative","dirname","cpSync","collisionGroupsResolved","isUpToDate","s","statSync","d","manifestDir","rel","root","path","isAbsolute"],"sources":["../src/asset-manager/build.ts"],"sourcesContent":["/**\n * Build pipeline for `assetMap` entries (asset-manager PR 2).\n *\n * For each entry, walks `src/<...>` matching the configured `glob`,\n * copies matches into `dest` (default `dist/<name>/`), then emits a\n * `dist/.kickjs-assets.json` manifest mapping logical\n * `<namespace>/<key>` keys to repo-relative paths inside `dist/`.\n *\n * Pure function on top of `node:fs` + `glob` — no shell, no side\n * effects beyond the configured directory writes. The build entry-\n * point in `commands/run.ts` calls `buildAssets` after the existing\n * `copyDirs` step.\n *\n * @module @forinda/kickjs-cli/asset-manager/build\n */\n\nimport { cpSync, existsSync, mkdirSync, statSync, writeFileSync } from 'node:fs'\nimport { dirname, isAbsolute, join, relative, resolve } from 'node:path'\nimport { glob } from 'glob'\nimport { groupAssetKeys } from '@forinda/kickjs'\nimport type { AssetMapEntry, KickConfig } from '../config'\n\n/** Wire-format version for `dist/.kickjs-assets.json`. Bump on shape change. */\nexport const ASSET_MANIFEST_VERSION = 1 as const\n\n/** On-disk manifest format (`dist/.kickjs-assets.json`). */\nexport interface AssetManifest {\n version: typeof ASSET_MANIFEST_VERSION\n /**\n * Logical key → manifest-relative path. Logical key is\n * `<namespace>/<key>` where `<key>` is the file path under `src`\n * with the extension stripped + path separators normalised.\n *\n * Path values are relative to the manifest file's directory so the\n * runtime can resolve them with a single `path.resolve(manifestDir,\n * entry)` regardless of where dist/ lives.\n */\n entries: Record<string, string>\n}\n\nexport interface BuildAssetsOptions {\n /** Project root — resolved for every relative path in the entry. */\n cwd: string\n /**\n * Output dir for the manifest + per-namespace asset copies. When\n * omitted, falls back to `config.build?.outDir` (resolved against\n * `cwd`), then to `dist/` under cwd. Adopters with a custom Vite\n * `build.outDir` should set `kick.config.ts.build.outDir` to match.\n */\n distDir?: string\n /** Suppress per-entry log lines. Default: false. */\n silent?: boolean\n}\n\n/** One entry in the per-build summary returned by `buildAssets`. */\nexport interface BuildAssetsEntryResult {\n namespace: string\n src: string\n dest: string\n /**\n * Number of files actually written this run. On an incremental\n * rebuild where nothing changed this is 0 even though the manifest\n * still lists every matched file.\n */\n filesCopied: number\n}\n\n/** Aggregated outcome of `buildAssets`. */\nexport interface BuildAssetsResult {\n manifestPath: string\n entries: BuildAssetsEntryResult[]\n /** `entries` merged into a single record — useful for tests + tooling. */\n manifest: AssetManifest\n}\n\n/**\n * Run the full asset build for a loaded config:\n *\n * 1. For each `assetMap` entry, glob → copy → manifest stub.\n * 2. Write `dist/.kickjs-assets.json`.\n *\n * Returns a summary including the manifest contents. No-op (and no\n * manifest written) when `assetMap` is empty / missing — the build\n * pipeline shouldn't litter `dist/` with empty manifests for\n * adopters who don't use the feature.\n */\nexport async function buildAssets(\n config: KickConfig | null,\n opts: BuildAssetsOptions,\n): Promise<BuildAssetsResult | null> {\n const { cwd, silent = false } = opts\n // Resolution order: explicit opts.distDir → config.build.outDir → 'dist'.\n // The CLI build command passes nothing explicit, so adopters control\n // the output via kick.config.ts.build.outDir alone.\n const distDir = opts.distDir ?? config?.build?.outDir ?? 'dist'\n const map = config?.assetMap\n if (!map || Object.keys(map).length === 0) return null\n\n const log = silent ? () => {} : console.log\n\n const distAbs = resolve(cwd, distDir)\n mkdirSync(distAbs, { recursive: true })\n\n const summary: BuildAssetsEntryResult[] = []\n const manifestEntries: Record<string, string> = {}\n\n for (const [namespace, entry] of Object.entries(map)) {\n const result = await processEntry(namespace, entry, cwd, distAbs)\n summary.push(result.entrySummary)\n Object.assign(manifestEntries, result.manifestSlice)\n log(\n ` ✓ ${namespace}: ${result.entrySummary.filesCopied} file(s) → ${result.entrySummary.dest}`,\n )\n }\n\n const manifest: AssetManifest = {\n version: ASSET_MANIFEST_VERSION,\n entries: manifestEntries,\n }\n const manifestPath = join(distAbs, '.kickjs-assets.json')\n writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\\n', 'utf-8')\n log(\n ` ✓ wrote manifest → ${relative(cwd, manifestPath)} (${Object.keys(manifestEntries).length} entries)`,\n )\n\n return { manifestPath, entries: summary, manifest }\n}\n\n/** Per-entry inner pipeline — extracted for unit-test reuse. */\nasync function processEntry(\n namespace: string,\n entry: AssetMapEntry,\n cwd: string,\n distAbs: string,\n): Promise<{\n entrySummary: BuildAssetsEntryResult\n manifestSlice: Record<string, string>\n}> {\n const srcAbs = resolve(cwd, entry.src)\n const destAbs = entry.dest ? resolve(cwd, entry.dest) : join(distAbs, namespace)\n\n // Defensive: refuse to write outside the project root (cwd) even\n // though validateAssetMap warned about it at config-load time. The\n // build step shouldn't trust upstream warnings — a typo like\n // `dest: '../../'` would otherwise sprinkle files outside the\n // workspace despite the warning being printed.\n if (escapesRoot(destAbs, cwd)) {\n console.warn(\n ` ⚠ assetMap.${namespace}.dest ('${entry.dest}') resolves outside the project root — skipping copy`,\n )\n return {\n entrySummary: { namespace, src: entry.src, dest: relative(cwd, destAbs), filesCopied: 0 },\n manifestSlice: {},\n }\n }\n\n // Treat src-not-a-directory the same as src-missing — `glob` would\n // throw if pointed at a file, surfacing as a generic build failure\n // instead of a clean 0-files entry. Matches the validator's warning\n // shape (already emitted at config-load time for the missing case).\n if (!existsSync(srcAbs) || !isDirectorySync(srcAbs)) {\n return {\n entrySummary: { namespace, src: entry.src, dest: relative(cwd, destAbs), filesCopied: 0 },\n manifestSlice: {},\n }\n }\n\n const pattern = entry.glob ?? '**/*'\n // `glob` returns paths relative to `cwd` when `cwd` is set —\n // exactly the slugs we want for the manifest keys.\n const matches = await glob(pattern, {\n cwd: srcAbs,\n nodir: true,\n dot: false,\n posix: true,\n })\n\n mkdirSync(destAbs, { recursive: true })\n\n const manifestSlice: Record<string, string> = {}\n // Sort the walk so the manifest is byte-stable across platforms.\n // The `groupAssetKeys` helper preserves input order, so a stable\n // sort here makes the resulting manifest stable too.\n const sorted = [...matches].toSorted()\n const { pairs, collisionGroupsResolved } = groupAssetKeys(namespace, sorted, {\n strategy: entry.keys ?? 'auto',\n })\n\n // Copy the files and write the keyed manifest slice. Both come from\n // the same `pairs` order so the on-disk layout matches the\n // manifest's iteration order — easier to grep in cold-start\n // debugging.\n //\n // Incremental: skip the copy when the destination is already\n // up-to-date (exists, same size, mtime ≥ source). `cpSync` stamps the\n // copy with the current time, so an unchanged source always satisfies\n // `dest.mtime ≥ src.mtime` on the next run — turning a re-build into a\n // pure stat sweep instead of re-copying every asset. The manifest\n // slice is written unconditionally so the manifest stays complete.\n let filesCopied = 0\n for (const { rel: relPath, key } of pairs) {\n const srcFile = join(srcAbs, relPath)\n const destFile = join(destAbs, relPath)\n manifestSlice[key] = toManifestRelative(distAbs, destFile)\n if (isUpToDate(srcFile, destFile)) continue\n mkdirSync(dirname(destFile), { recursive: true })\n cpSync(srcFile, destFile)\n filesCopied++\n }\n\n if (collisionGroupsResolved > 0) {\n console.log(\n ` ℹ assetMap.${namespace}: auto-resolved ${collisionGroupsResolved} basename collision(s) by keeping extensions ` +\n `(set 'keys: \"strip\"' to opt back into legacy last-write-wins behaviour, or 'keys: \"with-extension\"' to keep all keys verbose).`,\n )\n }\n\n return {\n entrySummary: {\n namespace,\n src: entry.src,\n dest: relative(cwd, destAbs),\n filesCopied,\n },\n manifestSlice,\n }\n}\n\n/**\n * Is `destFile` already a current copy of `srcFile`? True when the\n * destination exists with the same byte size and an mtime no older than\n * the source. Used to skip redundant copies on an incremental rebuild.\n */\nfunction isUpToDate(srcFile: string, destFile: string): boolean {\n if (!existsSync(destFile)) return false\n try {\n const s = statSync(srcFile)\n const d = statSync(destFile)\n return d.size === s.size && d.mtimeMs >= s.mtimeMs\n } catch {\n return false\n }\n}\n\n/**\n * Make `destFile` relative to the manifest's directory + force POSIX\n * separators so the manifest is byte-stable across platforms.\n */\nfunction toManifestRelative(manifestDir: string, destFile: string): string {\n const rel = relative(manifestDir, destFile)\n // path.relative returns OS-native separators; the manifest is JSON\n // and the runtime uses path.resolve which handles either, but a\n // forward-slash manifest is grep-friendly + diff-stable.\n return rel.split(/[\\\\/]/).filter(Boolean).join('/')\n}\n\n/**\n * Pure manifest writer — handy for tests that want to assert against\n * a hand-crafted manifest without exercising the full pipeline.\n */\nexport function writeAssetManifest(distDir: string, manifest: AssetManifest): string {\n const path = join(distDir, '.kickjs-assets.json')\n mkdirSync(distDir, { recursive: true })\n writeFileSync(path, JSON.stringify(manifest, null, 2) + '\\n', 'utf-8')\n return path\n}\n\n/**\n * Read + parse a manifest from disk. Returns `null` on missing or\n * malformed file rather than throwing — the runtime resolver wants\n * to fall through to dev-mode lookup in that case.\n */\nexport function readAssetManifest(distDir: string): AssetManifest | null {\n const path = join(distDir, '.kickjs-assets.json')\n if (!existsSync(path)) return null\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const fs = require('node:fs') as typeof import('node:fs')\n const raw = fs.readFileSync(path, 'utf-8')\n const parsed = JSON.parse(raw) as Partial<AssetManifest>\n if (parsed.version !== ASSET_MANIFEST_VERSION) return null\n if (!parsed.entries || typeof parsed.entries !== 'object') return null\n return parsed as AssetManifest\n } catch {\n return null\n }\n}\n\n/**\n * Project-root escape check that's safe across symlinks + drive letters.\n * `path.relative` returns `..` segments when the target sits above root,\n * and an absolute path when the two live on different roots (Windows).\n * `startsWith(root)` would miss both cases.\n */\nfunction escapesRoot(path: string, root: string): boolean {\n const rel = relative(root, path)\n if (rel === '') return false\n return rel.startsWith('..') || isAbsolute(rel)\n}\n\n/** Pure helper — `false` for missing, non-dir, or unreadable paths. */\nfunction isDirectorySync(path: string): boolean {\n try {\n return statSync(path).isDirectory()\n } catch {\n return false\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs-cli v8.13.0
2
+ * @forinda/kickjs-cli v8.13.1
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,5 +8,5 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import{t as e}from"./rolldown-runtime-BVrPnwAV.mjs";import{cpSync as t,existsSync as n,mkdirSync as r,statSync as i,writeFileSync as a}from"node:fs";import{dirname as o,isAbsolute as s,join as c,relative as l,resolve as u}from"node:path";import{glob as d}from"glob";import{groupAssetKeys as f}from"@forinda/kickjs";var p=/* @__PURE__ */ e({ASSET_MANIFEST_VERSION:()=>1,buildAssets:()=>m});async function m(e,t){let{cwd:n,silent:i=!1}=t,o=t.distDir??e?.build?.outDir??`dist`,s=e?.assetMap;if(!s||Object.keys(s).length===0)return null;let d=i?()=>{}:console.log,f=u(n,o);r(f,{recursive:!0});let p=[],m={};for(let[e,t]of Object.entries(s)){let r=await h(e,t,n,f);p.push(r.entrySummary),Object.assign(m,r.manifestSlice),d(` ✓ ${e}: ${r.entrySummary.filesCopied} file(s) → ${r.entrySummary.dest}`)}let g={version:1,entries:m},_=c(f,`.kickjs-assets.json`);return a(_,JSON.stringify(g,null,2)+`
11
+ import{t as e}from"./rolldown-runtime-Bn82Wzut.mjs";import{cpSync as t,existsSync as n,mkdirSync as r,statSync as i,writeFileSync as a}from"node:fs";import{dirname as o,isAbsolute as s,join as c,relative as l,resolve as u}from"node:path";import{glob as d}from"glob";import{groupAssetKeys as f}from"@forinda/kickjs";var p=/* @__PURE__ */ e({ASSET_MANIFEST_VERSION:()=>1,buildAssets:()=>m});async function m(e,t){let{cwd:n,silent:i=!1}=t,o=t.distDir??e?.build?.outDir??`dist`,s=e?.assetMap;if(!s||Object.keys(s).length===0)return null;let d=i?()=>{}:console.log,f=u(n,o);r(f,{recursive:!0});let p=[],m={};for(let[e,t]of Object.entries(s)){let r=await h(e,t,n,f);p.push(r.entrySummary),Object.assign(m,r.manifestSlice),d(` ✓ ${e}: ${r.entrySummary.filesCopied} file(s) → ${r.entrySummary.dest}`)}let g={version:1,entries:m},_=c(f,`.kickjs-assets.json`);return a(_,JSON.stringify(g,null,2)+`
12
12
  `,`utf-8`),d(` ✓ wrote manifest → ${l(n,_)} (${Object.keys(m).length} entries)`),{manifestPath:_,entries:p,manifest:g}}async function h(e,i,a,s){let p=u(a,i.src),m=i.dest?u(a,i.dest):c(s,e);if(v(m,a))return console.warn(` ⚠ assetMap.${e}.dest ('${i.dest}') resolves outside the project root — skipping copy`),{entrySummary:{namespace:e,src:i.src,dest:l(a,m),filesCopied:0},manifestSlice:{}};if(!n(p)||!y(p))return{entrySummary:{namespace:e,src:i.src,dest:l(a,m),filesCopied:0},manifestSlice:{}};let h=i.glob??`**/*`,b=await d(h,{cwd:p,nodir:!0,dot:!1,posix:!0});r(m,{recursive:!0});let x={},S=[...b].toSorted(),{pairs:C,collisionGroupsResolved:w}=f(e,S,{strategy:i.keys??`auto`}),T=0;for(let{rel:e,key:n}of C){let i=c(p,e),a=c(m,e);x[n]=_(s,a),!g(i,a)&&(r(o(a),{recursive:!0}),t(i,a),T++)}return w>0&&console.log(` ℹ assetMap.${e}: auto-resolved ${w} basename collision(s) by keeping extensions (set 'keys: "strip"' to opt back into legacy last-write-wins behaviour, or 'keys: "with-extension"' to keep all keys verbose).`),{entrySummary:{namespace:e,src:i.src,dest:l(a,m),filesCopied:T},manifestSlice:x}}function g(e,t){if(!n(t))return!1;try{let n=i(e),r=i(t);return r.size===n.size&&r.mtimeMs>=n.mtimeMs}catch{return!1}}function _(e,t){return l(e,t).split(/[\\/]/).filter(Boolean).join(`/`)}function v(e,t){let n=l(t,e);return n===``?!1:n.startsWith(`..`)||s(n)}function y(e){try{return i(e).isDirectory()}catch{return!1}}export{p as n,m as t};
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs-cli v8.13.0
2
+ * @forinda/kickjs-cli v8.13.1
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,7 +8,7 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import{t as e}from"./rolldown-runtime-BVrPnwAV.mjs";import{c as t,g as n,i as r,l as i,o as a,r as o,s,t as c,u as l}from"./project--T8NPgfc.mjs";import{a as u,c as d,d as f,f as p,i as m,l as h,m as g,o as _,p as v,s as y,u as b}from"./config-CQGH0FTE.mjs";import{n as x,r as S}from"./plugin-MPu_4sWN.mjs";import{_ as C,a as ee,c as w,d as te,f as ne,g as T,h as re,i as ie,l as ae,m as oe,n as se,o as E,p as D,s as ce,t as O,u as le}from"./package-manager-B-BW1RBj.mjs";import{t as k}from"./project-root-BsIxM6Gj.mjs";import{n as ue}from"./agent-docs-D0qgHBA8.mjs";import{C as de,S as fe,_ as pe,a as me,b as he,c as ge,d as _e,f as ve,g as ye,h as be,i as xe,l as Se,m as Ce,o as we,p as Te,r as Ee,s as De,t as Oe,u as ke,v as Ae,w as je,x as A,y as Me}from"./typegen-BfFiyGeh.mjs";import{t as Ne}from"./build-C1ZgYqj7.mjs";import{createRequire as Pe}from"node:module";import{cpSync as Fe,existsSync as j,mkdirSync as Ie,readFileSync as M,readdirSync as N,rmSync as Le,statSync as Re,writeFileSync as P}from"node:fs";import F,{basename as ze,dirname as I,join as L,relative as R,resolve as z,sep as B}from"node:path";import{fileURLToPath as Be,pathToFileURL as V}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 H,readdir as Ke,rm as qe,stat as Je,writeFile as Ye}from"node:fs/promises";import"@forinda/kickjs-cli-kit";import{createHash as Xe}from"node:crypto";import{parseSync as Ze}from"oxc-parser";import Qe from"pluralize";import{arch as $e,platform as et,release as tt}from"node:os";const nt=[{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`},{value:`storage`,label:`Storage`,hint:`disk, S3 / R2 / MinIO`}];function rt(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 | inertia`).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(`--deploy <targets>`,`Comma-separated deploy targets to write files for: netlify, vercel, docker (later: kick g deploy)`).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)=>{ee(`KickJS — Create a new project`);let n=[];try{n=t.deploy?l(t.deploy):[]}catch(e){E.error(e.message),w(`Aborted.`),process.exitCode=1;return}let r=!!(t.yes||t.nonInteractive);e||=r?`my-api`:await te({message:`Project name`,placeholder:`my-api`,defaultValue:`my-api`});let i;if(e===`.`?(i=z(`.`),e=ze(i)):i=z(t.directory||e),j(i)){let n=N(i);if(n.length>0){if(t.force)E.warn(`Clearing existing files in ${i}`);else if(r){E.warn(`Directory "${e}" is not empty. Pass --force to clear it.`),w(`Aborted.`);return}else{E.warn(`Directory "${e}" is not empty:`);let t=n.slice(0,5);for(let e of t)E.message(` - ${e}`);if(n.length>5&&E.message(` ... and ${n.length-5} more`),!await ie({message:D.red(`Remove all existing files and proceed?`),initialValue:!1})){w(`Aborted.`);return}}for(let e of n)Le(z(i,e),{recursive:!0,force:!0})}}let a=t.template;a||=r?`minimal`:await ae({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`},{value:`inertia`,label:`Inertia`,hint:`server-driven React pages, one app, SSR`}]});let o=t.runtime;o||=r?`express`:await ae({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||=r?await se(void 0):await ae({message:`Package manager`,options:[{value:`pnpm`,label:`pnpm`},{value:`npm`,label:`npm`},{value:`yarn`,label:`yarn`},{value:`bun`,label:`bun`}]});let u=t.repo;u||=r?`inmemory`:await te({message:`Repository name`,placeholder:`inmemory (or a DB name, e.g. postgres)`,defaultValue:`inmemory`}),g(u);let d=t.schema;a===`inertia`&&(d&&d!==`zod`&&E.warn(`The inertia template uses zod — ignoring --schema ${d}.`),d=`zod`),d||=r?`zod`:await ae({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(d)||(E.warn(`Unknown --schema "${d}", falling back to zod.`),d=`zod`);let f;if(t.packages!==void 0){let e=t.packages.trim().toLowerCase();f=e===``||e===`none`||e===`false`?[]:t.packages.split(`,`).map(e=>e.trim()).filter(Boolean)}else f=r?[]:await ce({message:`Select packages to include`,options:[...nt],required:!1});let m;m=t.git===void 0?r?!0:await ie({message:`Initialize git repository?`,initialValue:!0}):t.git;let h;if(h=t.install===void 0?r?!0:await ie({message:`Install dependencies?`,initialValue:!0}):t.install,t.frontend!==void 0&&t.frontend!==`kick`&&t.frontend!==`vite`){E.error(`Unknown --frontend '${String(t.frontend)}'. Use 'kick' (wired React app) or 'vite' (create-vite).`),w(`Aborted.`);return}let{VITE_TEMPLATES:_,DEFAULT_VITE_TEMPLATE:v}=await import(`./fullstack-C8k03oM8.mjs`);if(t.viteTemplate!==void 0&&!_.some(e=>e.value===t.viteTemplate)){E.error(`Unknown --vite-template '${String(t.viteTemplate)}'. TypeScript templates only: ${_.map(e=>e.value).join(`, `)}.`),w(`Aborted.`);return}let y=t.frontend===`vite`?`vite`:`kick`,b=t.viteTemplate??v;if(a===`fullstack`&&!t.frontend&&!r&&(y=await ae({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)`}]})),y===`vite`&&!t.viteTemplate&&!r&&(b=await ae({message:`create-vite template`,options:_.map(e=>({value:e.value,label:e.label})),initialValue:v})),a===`fullstack`){let{initFullstackProject:t}=await import(`./fullstack-C8k03oM8.mjs`);await t({name:e,directory:i,packageManager:s,initGit:m,installDeps:h,schemaLib:d,runtime:o,packages:f,frontend:y,viteTemplate:b,deploy:n}),w(`Done! Next steps: ${D.cyan(`cd ${e} && ${s}${s===`pnpm`?` dev`:` run dev:server`}`)}`)}else await c({name:e,directory:i,packageManager:s,initGit:m,installDeps:h,template:a,defaultRepo:u,packages:f,schemaLib:d,runtime:o,deploy:n}),w(`Done! Next steps: ${D.cyan(`cd ${e} && ${p(s,`dev`)}`)}`)})}Qe.addUncountableRule(`auth`);function U(e){return e.replace(/[-_\s]+(.)?/g,(e,t)=>t?t.toUpperCase():``).replace(/^(.)/,e=>e.toUpperCase())}function it(e){let t=U(e);return t.charAt(0).toLowerCase()+t.slice(1)}function W(e){return e.replace(/([a-z])([A-Z])/g,`$1-$2`).replace(/[\s_]+/g,`-`).toLowerCase()}function G(e){return Qe.plural(e)}function at(e){return Qe.plural(e)}function ot(e){return W(e).replace(/-/g,`_`)}function st(e){let t=e.cwd??process.cwd(),n=e.projectRoot??k(t),r=e.pluralize??!1,i=U(e.name),a=it(e.name),o=W(e.name),s=ot(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=G(o);c.pluralKebab=e,c.pluralPascal=U(e),c.pluralCamel=it(e)}return c}function ct(e,t){return z(e.cwd,t)}async function lt(e){return import(V(e).href)}const ut=/* @__PURE__ */ new Map;async function dt(e){let t=ut.get(e);if(t)return t;let n=ft(e);return ut.set(e,n),n}async function ft(e){let t=z(e,`package.json`);if(!j(t))return{generators:[],loaded:[],failed:[]};let n=pt(JSON.parse(await H(t,`utf-8`))),r=Pe(z(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 H(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=z(I(t),s);if(!j(c)){o.push({source:e,reason:`kickjs.generators points to missing file: ${s}`});continue}let l;try{l=await lt(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`});else{for(let t of u)mt(t)?i.push({source:e,spec:t}):o.push({source:e,reason:`manifest entry is not a valid GeneratorSpec (missing name/files)`});a.push(e)}}return{generators:i,loaded:a,failed:o}}function pt(e){let t=/* @__PURE__ */ 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 mt(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.name==`string`&&typeof t.files==`function`}async function ht(e,t=[]){let n=e.cwd??process.cwd(),r=t.find(t=>t.spec.name===e.generatorName);if(r)return vt(r.spec,r.source,e,n);let i=_t(await dt(n),e.generatorName);return i?vt(i.spec,i.source,e,n):null}async function gt(e,t=[]){let n=await dt(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 _t(e,t){return e.generators.find(e=>e.spec.name===t)}async function vt(e,t,n,r){let i=st({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=ct(i,e.path);await C(t,e.content),o.push(t)}return{files:o,source:t}}function K(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}const yt={inmemory:`in-memory`,drizzle:`Drizzle`,prisma:`Prisma`};function bt(e){return e.charAt(0).toUpperCase()+e.slice(1).replace(/-([a-z])/g,(e,t)=>t.toUpperCase())}function xt(e){return yt[e]??bt(e)}function St(e){return`create${e}Repository`}function Ct(e){return e??`define`}function wt(e){let{pascal:t,kebab:n,plural:r=``,repo:i,style:a}=e,o=e.routePath??r,s=St(t),c=Ct(a),l=`/**
11
+ import{t as e}from"./rolldown-runtime-Bn82Wzut.mjs";import{c as t,g as n,i as r,l as i,o as a,r as o,s,t as c,u as l}from"./project-BE7J8TpW.mjs";import{a as u,c as d,d as f,f as p,i as m,l as h,m as g,o as _,p as v,s as y,u as b}from"./config-BIlu1hs0.mjs";import{n as x,r as S}from"./plugin-CGlWHBFX.mjs";import{_ as C,a as ee,c as w,d as te,f as ne,g as T,h as re,i as ie,l as ae,m as oe,n as se,o as E,p as D,s as ce,t as O,u as le}from"./package-manager-D5grCG_d.mjs";import{t as k}from"./project-root-B1zLyHn6.mjs";import{n as ue}from"./agent-docs-Dq_azKfQ.mjs";import{C as de,S as fe,_ as pe,a as me,b as he,c as ge,d as _e,f as ve,g as ye,h as be,i as xe,l as Se,m as Ce,o as we,p as Te,r as Ee,s as De,t as Oe,u as ke,v as Ae,w as je,x as A,y as Me}from"./typegen-CAni3mL3.mjs";import{t as Ne}from"./build-t8pGkT7W.mjs";import{createRequire as Pe}from"node:module";import{cpSync as Fe,existsSync as j,mkdirSync as Ie,readFileSync as M,readdirSync as N,rmSync as Le,statSync as Re,writeFileSync as P}from"node:fs";import F,{basename as ze,dirname as I,join as L,relative as R,resolve as z,sep as B}from"node:path";import{fileURLToPath as Be,pathToFileURL as V}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 H,readdir as Ke,rm as qe,stat as Je,writeFile as Ye}from"node:fs/promises";import"@forinda/kickjs-cli-kit";import{createHash as Xe}from"node:crypto";import{parseSync as Ze}from"oxc-parser";import Qe from"pluralize";import{arch as $e,platform as et,release as tt}from"node:os";const nt=[{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`},{value:`storage`,label:`Storage`,hint:`disk, S3 / R2 / MinIO`}];function rt(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 | inertia`).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(`--deploy <targets>`,`Comma-separated deploy targets to write files for: netlify, vercel, docker (later: kick g deploy)`).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)=>{ee(`KickJS — Create a new project`);let n=[];try{n=t.deploy?l(t.deploy):[]}catch(e){E.error(e.message),w(`Aborted.`),process.exitCode=1;return}let r=!!(t.yes||t.nonInteractive);e||=r?`my-api`:await te({message:`Project name`,placeholder:`my-api`,defaultValue:`my-api`});let i;if(e===`.`?(i=z(`.`),e=ze(i)):i=z(t.directory||e),j(i)){let n=N(i);if(n.length>0){if(t.force)E.warn(`Clearing existing files in ${i}`);else if(r){E.warn(`Directory "${e}" is not empty. Pass --force to clear it.`),w(`Aborted.`);return}else{E.warn(`Directory "${e}" is not empty:`);let t=n.slice(0,5);for(let e of t)E.message(` - ${e}`);if(n.length>5&&E.message(` ... and ${n.length-5} more`),!await ie({message:D.red(`Remove all existing files and proceed?`),initialValue:!1})){w(`Aborted.`);return}}for(let e of n)Le(z(i,e),{recursive:!0,force:!0})}}let a=t.template;a||=r?`minimal`:await ae({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`},{value:`inertia`,label:`Inertia`,hint:`server-driven React pages, one app, SSR`}]});let o=t.runtime;o||=r?`express`:await ae({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||=r?await se(void 0):await ae({message:`Package manager`,options:[{value:`pnpm`,label:`pnpm`},{value:`npm`,label:`npm`},{value:`yarn`,label:`yarn`},{value:`bun`,label:`bun`}]});let u=t.repo;u||=r?`inmemory`:await te({message:`Repository name`,placeholder:`inmemory (or a DB name, e.g. postgres)`,defaultValue:`inmemory`}),g(u);let d=t.schema;a===`inertia`&&(d&&d!==`zod`&&E.warn(`The inertia template uses zod — ignoring --schema ${d}.`),d=`zod`),d||=r?`zod`:await ae({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(d)||(E.warn(`Unknown --schema "${d}", falling back to zod.`),d=`zod`);let f;if(t.packages!==void 0){let e=t.packages.trim().toLowerCase();f=e===``||e===`none`||e===`false`?[]:t.packages.split(`,`).map(e=>e.trim()).filter(Boolean)}else f=r?[]:await ce({message:`Select packages to include`,options:[...nt],required:!1});let m;m=t.git===void 0?r?!0:await ie({message:`Initialize git repository?`,initialValue:!0}):t.git;let h;if(h=t.install===void 0?r?!0:await ie({message:`Install dependencies?`,initialValue:!0}):t.install,t.frontend!==void 0&&t.frontend!==`kick`&&t.frontend!==`vite`){E.error(`Unknown --frontend '${String(t.frontend)}'. Use 'kick' (wired React app) or 'vite' (create-vite).`),w(`Aborted.`);return}let{VITE_TEMPLATES:_,DEFAULT_VITE_TEMPLATE:v}=await import(`./fullstack-C6hCr30Z.mjs`);if(t.viteTemplate!==void 0&&!_.some(e=>e.value===t.viteTemplate)){E.error(`Unknown --vite-template '${String(t.viteTemplate)}'. TypeScript templates only: ${_.map(e=>e.value).join(`, `)}.`),w(`Aborted.`);return}let y=t.frontend===`vite`?`vite`:`kick`,b=t.viteTemplate??v;if(a===`fullstack`&&!t.frontend&&!r&&(y=await ae({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)`}]})),y===`vite`&&!t.viteTemplate&&!r&&(b=await ae({message:`create-vite template`,options:_.map(e=>({value:e.value,label:e.label})),initialValue:v})),a===`fullstack`){let{initFullstackProject:t}=await import(`./fullstack-C6hCr30Z.mjs`);await t({name:e,directory:i,packageManager:s,initGit:m,installDeps:h,schemaLib:d,runtime:o,packages:f,frontend:y,viteTemplate:b,deploy:n}),w(`Done! Next steps: ${D.cyan(`cd ${e} && ${s}${s===`pnpm`?` dev`:` run dev:server`}`)}`)}else await c({name:e,directory:i,packageManager:s,initGit:m,installDeps:h,template:a,defaultRepo:u,packages:f,schemaLib:d,runtime:o,deploy:n}),w(`Done! Next steps: ${D.cyan(`cd ${e} && ${p(s,`dev`)}`)}`)})}Qe.addUncountableRule(`auth`);function U(e){return e.replace(/[-_\s]+(.)?/g,(e,t)=>t?t.toUpperCase():``).replace(/^(.)/,e=>e.toUpperCase())}function it(e){let t=U(e);return t.charAt(0).toLowerCase()+t.slice(1)}function W(e){return e.replace(/([a-z])([A-Z])/g,`$1-$2`).replace(/[\s_]+/g,`-`).toLowerCase()}function G(e){return Qe.plural(e)}function at(e){return Qe.plural(e)}function ot(e){return W(e).replace(/-/g,`_`)}function st(e){let t=e.cwd??process.cwd(),n=e.projectRoot??k(t),r=e.pluralize??!1,i=U(e.name),a=it(e.name),o=W(e.name),s=ot(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=G(o);c.pluralKebab=e,c.pluralPascal=U(e),c.pluralCamel=it(e)}return c}function ct(e,t){return z(e.cwd,t)}async function lt(e){return import(V(e).href)}const ut=/* @__PURE__ */ new Map;async function dt(e){let t=ut.get(e);if(t)return t;let n=ft(e);return ut.set(e,n),n}async function ft(e){let t=z(e,`package.json`);if(!j(t))return{generators:[],loaded:[],failed:[]};let n=pt(JSON.parse(await H(t,`utf-8`))),r=Pe(z(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 H(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=z(I(t),s);if(!j(c)){o.push({source:e,reason:`kickjs.generators points to missing file: ${s}`});continue}let l;try{l=await lt(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`});else{for(let t of u)mt(t)?i.push({source:e,spec:t}):o.push({source:e,reason:`manifest entry is not a valid GeneratorSpec (missing name/files)`});a.push(e)}}return{generators:i,loaded:a,failed:o}}function pt(e){let t=/* @__PURE__ */ 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 mt(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.name==`string`&&typeof t.files==`function`}async function ht(e,t=[]){let n=e.cwd??process.cwd(),r=t.find(t=>t.spec.name===e.generatorName);if(r)return vt(r.spec,r.source,e,n);let i=_t(await dt(n),e.generatorName);return i?vt(i.spec,i.source,e,n):null}async function gt(e,t=[]){let n=await dt(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 _t(e,t){return e.generators.find(e=>e.spec.name===t)}async function vt(e,t,n,r){let i=st({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=ct(i,e.path);await C(t,e.content),o.push(t)}return{files:o,source:t}}function K(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}const yt={inmemory:`in-memory`,drizzle:`Drizzle`,prisma:`Prisma`};function bt(e){return e.charAt(0).toUpperCase()+e.slice(1).replace(/-([a-z])/g,(e,t)=>t.toUpperCase())}function xt(e){return yt[e]??bt(e)}function St(e){return`create${e}Repository`}function Ct(e){return e??`define`}function wt(e){let{pascal:t,kebab:n,plural:r=``,repo:i,style:a}=e,o=e.routePath??r,s=St(t),c=Ct(a),l=`/**
12
12
  * ${t} Module
13
13
  *
14
14
  * REST module with a flat folder structure.
@@ -1515,7 +1515,7 @@ describe('${s}', () => {
1515
1515
  Example: kick g scaffold Post title:string body:text:optional published:boolean:optional
1516
1516
  Optional: append :optional (shell-safe, no quoting needed)
1517
1517
  `),process.exit(1));let o=await _(process.cwd()),s=y(o),c=i.modulesDir??s.dir??`src/modules`,l=Tn(t),p=f(o,process.cwd()),m=u(k()),g=await En({name:e,fields:l,modulesDir:z(c),noEntity:i.entity===!1,noTests:i.tests===!1,pluralize:d(i.pluralize,s),pluralizeRoutes:h(i.pluralizeRoutes,s),tokenScope:p,swagger:m,style:s.style});console.log(`\n Scaffolded ${e} with ${l.length} field(s):`);for(let e of l)console.log(` ${e.name}: ${e.type}${e.optional?` (optional)`:``}`);J(g,a),await Pn(a)}),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=q(t);T(n),J(await ln({outDir:z(`.`),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 (default: detected from kick.config, packageManager, or the lockfile)`).option(`--template <template>`,`Template: rest | minimal | fullstack | inertia`).option(`-f, --force`,`Overwrite existing files without prompting`).action(async(e,t)=>{let n=q(t);T(n);let r=e.only??`all`;Nn.includes(r)?J(await ue({outDir:z(`.`),only:r,name:e.name,pm:e.pm,template:e.template,force:e.force}),n):(console.error(` Invalid --only value: ${r}. Expected: ${Nn.join(` | `)}`),process.exitCode=1)}),n.command(`deploy <targets...>`).description(`Add deploy files: netlify | vercel | docker (config, serverless entry, build script)`).option(`--pm <pm>`,`Package manager (default: detected)`).option(`-f, --force`,`Overwrite existing files without prompting`).action(async(e,t,n)=>{let r=q(n);T(r);let a;try{a=l(e.flatMap(e=>e.split(`,`))),J(await i({dir:z(`.`),targets:a,pm:t.pm,force:t.force}),r)}catch(e){console.error(` ${e.message}`),process.exitCode=1}});for(let e of t?.generators??[])Hn(n,e,t?.projectRoot)}function Hn(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=q(o);T(s);let c=await ht({generatorName:i.name,itemName:e??``,args:r??[],flags:a,cwd:process.cwd(),projectRoot:n},[t]);c&&J(c.files,s)})}const Un=`/* AUTO-GENERATED by kick typegen — do not edit. Plugin: `;async function Wn(e){let t=F.resolve(e.cwd,`.kickjs/types`);e.check||await Ge(t,{recursive:!0});let n=/* @__PURE__ */ new Map,r=e.scan??be,i=F.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(V(e).href)},async writeFile(t,n){let r=F.resolve(e.cwd,t);await Ge(F.dirname(r),{recursive:!0}),await Ye(r,n,`utf8`)},getScanResult:e=>{let t=Gn(e),o=n.get(t);if(!o){let s={cacheDir:i,...e};o=a?ye(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=F.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=`${Un}${n.id} */\n\n`+a+`
1518
- `,u=``;j(i)&&(u=await H(i,`utf8`)),u===l?s.push({id:n.id,status:`unchanged`,outFile:i}):e.check?(c.push({id:n.id,outFile:i}),s.push({id:n.id,status:`drifted`,outFile:i})):(await Ye(i,l,`utf8`),s.push({id:n.id,status:`written`,outFile:i}))}if(c.length>0)throw new Mn(c);return s}function Gn(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 Kn(e,t){let n=new Set(t),r=[],i=[],a=/* @__PURE__ */ 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 qn=/* @__PURE__ */ e({applyDisableFilter:()=>Kn,runAllPluginTypegens:()=>Jn});async function Jn(e){let t=[...Vo,...e.config?.plugins??[]],{enabled:n,skipped:r,unknown:i}=Kn(x(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 Wn({cwd:e.cwd,config:e.config??{},plugins:n,watch:e.watch,check:e.check,changedFiles:e.changedFiles});if(!e.silent&&jn())for(let e of t)console.log(` ${e.id}: ${e.status}`);return t}catch(t){if(t instanceof Mn||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 Yn(e){let t=/* @__PURE__ */ new Map;return{report(n,r){let i=r instanceof Error?r.message:String(r);t.get(n)!==i&&(t.set(n,i),e(` kick typegen: ${n} pass failed (${i}) — types in .kickjs/types may be stale`))},clear(e){t.delete(e)}}}const Xn=`__kickjs_typegen_owner`;function Zn(e){let{cwd:t,config:n}=e,r=e.debounceMs??100,i=e.pipeline??{runTypegen:async e=>(await import(`./typegen-BfFiyGeh.mjs`).then(e=>e.n)).runTypegen(e),runAllPluginTypegens:async e=>(await Promise.resolve().then(()=>qn)).runAllPluginTypegens(e),writeTypegenArtifacts:async(e,t,n)=>(await import(`./typegen-BfFiyGeh.mjs`).then(e=>e.n)).writeTypegenArtifacts(e,t,n),buildAssets:async(e,t)=>(await import(`./build-C1ZgYqj7.mjs`).then(e=>e.n)).buildAssets(e,t)},a=n?.typegen?.schemaValidator??`zod`,o=n?.typegen?.envFile,s=F.resolve(t,n?.typegen?.outDir??`.kickjs/types`),c=n?.assetMap?Object.values(n.assetMap).map(e=>e?.src).filter(e=>typeof e==`string`&&e.length>0).map(e=>F.resolve(t,e)):[],l=!!n?.assetMap&&Object.keys(n.assetMap).length>0,u=e=>e.replaceAll(`\\`,`/`),d=c.map(u),f=e=>{let t=u(e);return d.some(e=>t===e||t.startsWith(`${e}/`))},p=Yn(e.emitWarning),m=null,h=!1,g=/* @__PURE__ */ new Set,_=/* @__PURE__ */ 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 Qn(e){let t=process.platform===`win32`;for(let n of $n(e))for(let e of[`vue-tsc`,`tsgo`,`tsc`]){let r=t?[`${e}.CMD`,`${e}.cmd`,`${e}.exe`]:[e];for(let i of r){let r=L(n,i);if(j(r))return{cmd:r,args:[`--noEmit`],shell:t,kind:e}}}return null}function $n(e){let t=z(e),n=er(t);return(n?[t,n]:[t]).map(e=>L(e,`node_modules`,`.bin`))}function er(e){for(let t=I(e);t!==I(t);t=I(t)){let n=L(t,`pnpm-workspace.yaml`),r=L(t,`package.json`);if(j(n)||j(r))return tr(n,r).some(n=>nr(n,R(t,e)))?t:void 0}}function tr(e,t){try{if(j(e)){let t=M(e,`utf-8`).split(/^packages:\s*$/m)[1]??``,n=[];for(let e of t.split(`
1518
+ `,u=``;j(i)&&(u=await H(i,`utf8`)),u===l?s.push({id:n.id,status:`unchanged`,outFile:i}):e.check?(c.push({id:n.id,outFile:i}),s.push({id:n.id,status:`drifted`,outFile:i})):(await Ye(i,l,`utf8`),s.push({id:n.id,status:`written`,outFile:i}))}if(c.length>0)throw new Mn(c);return s}function Gn(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 Kn(e,t){let n=new Set(t),r=[],i=[],a=/* @__PURE__ */ 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 qn=/* @__PURE__ */ e({applyDisableFilter:()=>Kn,runAllPluginTypegens:()=>Jn});async function Jn(e){let t=[...Vo,...e.config?.plugins??[]],{enabled:n,skipped:r,unknown:i}=Kn(x(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 Wn({cwd:e.cwd,config:e.config??{},plugins:n,watch:e.watch,check:e.check,changedFiles:e.changedFiles});if(!e.silent&&jn())for(let e of t)console.log(` ${e.id}: ${e.status}`);return t}catch(t){if(t instanceof Mn||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 Yn(e){let t=/* @__PURE__ */ new Map;return{report(n,r){let i=r instanceof Error?r.message:String(r);t.get(n)!==i&&(t.set(n,i),e(` kick typegen: ${n} pass failed (${i}) — types in .kickjs/types may be stale`))},clear(e){t.delete(e)}}}const Xn=`__kickjs_typegen_owner`;function Zn(e){let{cwd:t,config:n}=e,r=e.debounceMs??100,i=e.pipeline??{runTypegen:async e=>(await import(`./typegen-CAni3mL3.mjs`).then(e=>e.n)).runTypegen(e),runAllPluginTypegens:async e=>(await Promise.resolve().then(()=>qn)).runAllPluginTypegens(e),writeTypegenArtifacts:async(e,t,n)=>(await import(`./typegen-CAni3mL3.mjs`).then(e=>e.n)).writeTypegenArtifacts(e,t,n),buildAssets:async(e,t)=>(await import(`./build-t8pGkT7W.mjs`).then(e=>e.n)).buildAssets(e,t)},a=n?.typegen?.schemaValidator??`zod`,o=n?.typegen?.envFile,s=F.resolve(t,n?.typegen?.outDir??`.kickjs/types`),c=n?.assetMap?Object.values(n.assetMap).map(e=>e?.src).filter(e=>typeof e==`string`&&e.length>0).map(e=>F.resolve(t,e)):[],l=!!n?.assetMap&&Object.keys(n.assetMap).length>0,u=e=>e.replaceAll(`\\`,`/`),d=c.map(u),f=e=>{let t=u(e);return d.some(e=>t===e||t.startsWith(`${e}/`))},p=Yn(e.emitWarning),m=null,h=!1,g=/* @__PURE__ */ new Set,_=/* @__PURE__ */ 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 Qn(e){let t=process.platform===`win32`;for(let n of $n(e))for(let e of[`vue-tsc`,`tsgo`,`tsc`]){let r=t?[`${e}.CMD`,`${e}.cmd`,`${e}.exe`]:[e];for(let i of r){let r=L(n,i);if(j(r))return{cmd:r,args:[`--noEmit`],shell:t,kind:e}}}return null}function $n(e){let t=z(e),n=er(t);return(n?[t,n]:[t]).map(e=>L(e,`node_modules`,`.bin`))}function er(e){for(let t=I(e);t!==I(t);t=I(t)){let n=L(t,`pnpm-workspace.yaml`),r=L(t,`package.json`);if(j(n)||j(r))return tr(n,r).some(n=>nr(n,R(t,e)))?t:void 0}}function tr(e,t){try{if(j(e)){let t=M(e,`utf-8`).split(/^packages:\s*$/m)[1]??``,n=[];for(let e of t.split(`
1519
1519
  `)){if(!e.trim()||e.trim().startsWith(`#`))continue;let t=/^\s+-\s*['"]?([^'"#]+?)['"]?\s*$/.exec(e);if(!t)break;n.push(t[1])}return n}let{workspaces:n}=JSON.parse(M(t,`utf-8`)),r=Array.isArray(n)?n:n?.packages;return Array.isArray(r)?r.filter(e=>typeof e==`string`):[]}catch{return[]}}function nr(e,t){let n=e.replace(/^\.\//,``).replace(/\/+$/,``).split(`/`).map(e=>e===`**`?`.*`:e.replace(/[.+^${}()|[\]\\]/g,`\\$&`).replace(/\*/g,`[^/]*`)).join(`/`);return RegExp(`^${n}$`).test(t.split(B).join(`/`))}function rr(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 ir(e,t=12){let n=e.trim().split(/\r?\n/);return n.length<=t?n.join(`
1520
1520
  `):`${n.slice(0,t).join(`
1521
1521
  `)}\n… ${n.length-t} more line(s)`}function ar(e){if(typeof e==`boolean`)return e;let t=process.env.KICKJS_WATCH_POLLING;return t===`1`||t===`true`}async function or(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 sr(e,t,n={}){t&&(process.env.PORT=t);let r=ar(n.polling),i=process.cwd(),a=await _(i),o=a?.typegen?.schemaValidator??`zod`,s=a?.typegen?.envFile;try{await Oe({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=z(i,a?.typegen?.outDir??`.kickjs/types`);try{let e=await Jn({cwd:i,config:a});await xe(c,e,!1)}catch(e){console.warn(` kick typegen: plugin pass skipped (${e?.message??e})`)}let{createRequire:l}=await import(`node:module`),u=l(z(`package.json`)).resolve(`vite`),{createServer:d}=await import(V(u).href);globalThis[Xn]=`kick-dev`;let f=await d({configFile:z(`vite.config.ts`),server:{port:t?parseInt(t,10):void 0,...r?{watch:{usePolling:!0,interval:100}}:{}}}),p=n.typecheck??a?.dev?.typecheck??!1,m=null,h=!0;if(p){let e=Qn(i);e?m=rr({cwd:i,bin:e,onResult:e=>{f.hot.send({type:`custom`,event:`kickjs:typecheck`,data:{ok:e.ok,output:e.output,durationMs:e.durationMs}}),e.ok?h||(h=!0,console.log(` kick typecheck: clean again (${e.kind}, ${e.durationMs}ms)`)):(h=!1,console.warn(`\n kick typecheck (${e.kind}, ${e.durationMs}ms):`),console.warn(ir(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 g=Zn({cwd:i,config:a,emitWarning:e=>{console.warn(e),f.hot.send({type:`custom`,event:`kickjs:typegen-error`,data:{message:e,timestamp:Date.now()}})},onPassComplete:()=>m?.schedule()});f.watcher.on(`add`,e=>g.handleWatchEvent(`add`,e)),f.watcher.on(`unlink`,e=>g.handleWatchEvent(`unlink`,e)),f.watcher.on(`change`,e=>g.handleWatchEvent(`change`,e)),f.watcher.on(`unlinkDir`,e=>g.handleWatchEvent(`unlinkDir`,e)),g.assetSrcRoots.length>0&&f.watcher.add([...g.assetSrcRoots]),await f.listen(),f.printUrls(),console.log(`
@@ -1839,7 +1839,7 @@ server.on('exit', () => {
1839
1839
  Cancelled.
1840
1840
  `);return}await qe(c,{recursive:!0,force:!0}),console.log(` Deleted: ${c}`);let l=L(n,`index.ts`);if(await re(l)){let e=await H(l,`utf-8`),t=e,n=RegExp(`^import\\s*\\{\\s*${K(o)}Module\\s*\\}\\s*from\\s*['"][^'"]*${K(s)}(?:/[^'"]*)?['"].*\\n?`,`gm`);e=e.replace(n,``),e=Qr(e,o),e=e.replace(/\n{3,}/g,`
1841
1841
 
1842
- `),e!==t&&(await C(l,e),console.log(` Unregistered: ${o}Module from ${l}`))}console.log(`\n Module '${s}' removed.\n`)}function ei(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(`--pluralize`,`The module folder is pluralized (users/ for user)`).option(`--no-pluralize`,`The module folder is the name as typed (the default)`).option(`-f, --force`,`Skip confirmation prompt`).action(async(e,t)=>{let n=await _(process.cwd()),r=y(n),i=t.modulesDir??r.dir??`src/modules`,a=d(t.pluralize,r);for(let n of e)await $r({name:n,modulesDir:z(i),force:t.force,pluralize:a})})}function ti(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 ni(e){if(e!==void 0)return e===`false`||e===`off`||e===`none`?!1:e}function ri(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=k(process.cwd()),n=await _(t);if(e.list){let{mergeCliPlugins:e}=await import(`./plugin-MPu_4sWN.mjs`).then(e=>e.t),{builtinCliPlugins:t}=await Promise.resolve().then(()=>Bo),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(`
1842
+ `),e!==t&&(await C(l,e),console.log(` Unregistered: ${o}Module from ${l}`))}console.log(`\n Module '${s}' removed.\n`)}function ei(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(`--pluralize`,`The module folder is pluralized (users/ for user)`).option(`--no-pluralize`,`The module folder is the name as typed (the default)`).option(`-f, --force`,`Skip confirmation prompt`).action(async(e,t)=>{let n=await _(process.cwd()),r=y(n),i=t.modulesDir??r.dir??`src/modules`,a=d(t.pluralize,r);for(let n of e)await $r({name:n,modulesDir:z(i),force:t.force,pluralize:a})})}function ti(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 ni(e){if(e!==void 0)return e===`false`||e===`off`||e===`none`?!1:e}function ri(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=k(process.cwd()),n=await _(t);if(e.list){let{mergeCliPlugins:e}=await import(`./plugin-CGlWHBFX.mjs`).then(e=>e.t),{builtinCliPlugins:t}=await Promise.resolve().then(()=>Bo),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(`
1843
1843
  Registered typegen plugins:
1844
1844
  `);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(`
1845
1845
  Disable one in kick.config.ts:
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs-cli v8.13.0
2
+ * @forinda/kickjs-cli v8.13.1
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,4 +8,4 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- export{t as builtinCliPlugins}from"./run-plugins-cqNounm7.mjs";
11
+ export{t as builtinCliPlugins}from"./run-plugins-B8vUgyD4.mjs";
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs-cli v8.13.0
2
+ * @forinda/kickjs-cli v8.13.1
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,4 +8,4 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import{_ as e}from"./project--T8NPgfc.mjs";import{o as t}from"./config-CQGH0FTE.mjs";import{n}from"./plugin-MPu_4sWN.mjs";import{t as r}from"./builtins-DZ-kQSyt.mjs";import{t as i}from"./project-root-BsIxM6Gj.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)n.has(r.name)?console.warn(` Warning: custom command '${r.name}' skipped — conflicts with a built-in command`):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{};
11
+ import{_ as e}from"./project-BE7J8TpW.mjs";import{o as t}from"./config-BIlu1hs0.mjs";import{n}from"./plugin-CGlWHBFX.mjs";import{t as r}from"./builtins-DCvidf69.mjs";import{t as i}from"./project-root-B1zLyHn6.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)n.has(r.name)?console.warn(` Warning: custom command '${r.name}' skipped — conflicts with a built-in command`):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{};
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs-cli v8.13.0
2
+ * @forinda/kickjs-cli v8.13.1
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,5 +8,5 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import{t as e}from"./rolldown-runtime-BVrPnwAV.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=/* @__PURE__ */ e({BUILTIN_REPO_TYPES:()=>_,DEPRECATED_REPO_TYPES:()=>v,PACKAGE_MANAGERS:()=>m,PLURALIZE_DEFAULT:()=>!1,defineConfig:()=>b,execBin:()=>g,hasDependency:()=>x,hasSwagger:()=>C,loadKickConfig:()=>M,resolveModuleConfig:()=>k,resolvePluralize:()=>D,resolvePluralizeRoutes:()=>O,resolveSchemaLib:()=>w,resolveTokenScope:()=>T,runScript:()=>h,testImportSource:()=>S,validateAssetMap:()=>P,warnIfDeprecatedRepo:()=>y,writeAssetConfigSnapshot:()=>N});const m=[`pnpm`,`npm`,`yarn`,`bun`];function h(e,t){return e===`npm`||e===`bun`?`${e} run ${t}`:`${e} ${t}`}function g(e,t){return{npm:`npx ${t}`,pnpm:`pnpm exec ${t}`,yarn:`yarn ${t}`,bun:`bunx ${t}`}[e]}const _=[`inmemory`],v=[`prisma`,`drizzle`];function y(e){return v.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 b(e){return e}function x(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 S(e){return x(e,`vite-plus`,`any`)&&!x(e,`vitest`,`any`)?`vite-plus/test`:`vitest`}function C(e){return x(e,`@forinda/kickjs-swagger`,`runtime`)}function w(e){return x(e,`valibot`,`runtime`)?`valibot`:x(e,`yup`,`runtime`)?`yup`:`zod`}function T(e,n){if(e?.tokenScope&&typeof e.tokenScope==`string`&&e.tokenScope.length>0){let t=E(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=E(e?e[1]:t.name);if(n.length>0)return n}}}catch{}return`app`}function E(e){return e.toLowerCase().replace(/[^a-z0-9-]/g,`-`).replace(/^-+|-+$/g,``).replace(/-{2,}/g,`-`)}function D(e,t){return e??t?.pluralize??!1}function O(e,t){return e??t?.pluralizeRoutes??!0}function k(e){if(!e)return{};let t={dir:e.modules?.dir,repo:e.modules?.repo,schemaDir:e.modules?.schemaDir,pluralize:e.modules?.pluralize,pluralizeRoutes:e.modules?.pluralizeRoutes,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`&&!_.includes(t.repo)&&(y(t.repo)||console.warn(` Warning: modules.repo '${t.repo}' is not a built-in type (${_.join(`, `)}). It will generate a stub repository. Use { name: '${t.repo}' } to silence this warning.`)),t}const A=[`kick.config.ts`,`kick.config.js`,`kick.config.mjs`,`kick.config.json`];function j(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 M(e){let{findProjectRoot:t}=await import(`./project-root-BsIxM6Gj.mjs`).then(e=>e.n),n=t(e);for(let e of A){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. Install jiti as a dev dependency, 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:j(n),tsconfigPaths:!0}).import(t,{default:!0}),i=P(e,n);for(let e of i)console.warn(` Warning: ${e}`);return N(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=P(i,n);for(let e of a)console.warn(` Warning: ${e}`);return N(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 N(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)+`
11
+ import{t as e}from"./rolldown-runtime-Bn82Wzut.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=/* @__PURE__ */ e({BUILTIN_REPO_TYPES:()=>_,DEPRECATED_REPO_TYPES:()=>v,PACKAGE_MANAGERS:()=>m,PLURALIZE_DEFAULT:()=>!1,defineConfig:()=>b,execBin:()=>g,hasDependency:()=>x,hasSwagger:()=>C,loadKickConfig:()=>M,resolveModuleConfig:()=>k,resolvePluralize:()=>D,resolvePluralizeRoutes:()=>O,resolveSchemaLib:()=>w,resolveTokenScope:()=>T,runScript:()=>h,testImportSource:()=>S,validateAssetMap:()=>P,warnIfDeprecatedRepo:()=>y,writeAssetConfigSnapshot:()=>N});const m=[`pnpm`,`npm`,`yarn`,`bun`];function h(e,t){return e===`npm`||e===`bun`?`${e} run ${t}`:`${e} ${t}`}function g(e,t){return{npm:`npx ${t}`,pnpm:`pnpm exec ${t}`,yarn:`yarn ${t}`,bun:`bunx ${t}`}[e]}const _=[`inmemory`],v=[`prisma`,`drizzle`];function y(e){return v.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 b(e){return e}function x(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 S(e){return x(e,`vite-plus`,`any`)&&!x(e,`vitest`,`any`)?`vite-plus/test`:`vitest`}function C(e){return x(e,`@forinda/kickjs-swagger`,`runtime`)}function w(e){return x(e,`valibot`,`runtime`)?`valibot`:x(e,`yup`,`runtime`)?`yup`:`zod`}function T(e,n){if(e?.tokenScope&&typeof e.tokenScope==`string`&&e.tokenScope.length>0){let t=E(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=E(e?e[1]:t.name);if(n.length>0)return n}}}catch{}return`app`}function E(e){return e.toLowerCase().replace(/[^a-z0-9-]/g,`-`).replace(/^-+|-+$/g,``).replace(/-{2,}/g,`-`)}function D(e,t){return e??t?.pluralize??!1}function O(e,t){return e??t?.pluralizeRoutes??!0}function k(e){if(!e)return{};let t={dir:e.modules?.dir,repo:e.modules?.repo,schemaDir:e.modules?.schemaDir,pluralize:e.modules?.pluralize,pluralizeRoutes:e.modules?.pluralizeRoutes,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`&&!_.includes(t.repo)&&(y(t.repo)||console.warn(` Warning: modules.repo '${t.repo}' is not a built-in type (${_.join(`, `)}). It will generate a stub repository. Use { name: '${t.repo}' } to silence this warning.`)),t}const A=[`kick.config.ts`,`kick.config.js`,`kick.config.mjs`,`kick.config.json`];function j(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 M(e){let{findProjectRoot:t}=await import(`./project-root-B1zLyHn6.mjs`).then(e=>e.n),n=t(e);for(let e of A){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. Install jiti as a dev dependency, 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:j(n),tsconfigPaths:!0}).import(t,{default:!0}),i=P(e,n);for(let e of i)console.warn(` Warning: ${e}`);return N(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=P(i,n);for(let e of a)console.warn(` Warning: ${e}`);return N(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 N(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
12
  `,`utf-8`)}catch{}}function P(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&&F(l(n,o.dest),i)&&r.push(`assetMap.${a}.dest ('${o.dest}') resolves outside the project root — refusing to copy`)}return r}function F(e,t){let n=c(t,e);return n===``?!1:n.startsWith(`..`)||o(n)}export{C as a,D as c,T as d,h as f,x as i,O as l,y as m,p as n,M as o,S as p,g as r,k as s,m as t,w as u};
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs-cli v8.13.0
2
+ * @forinda/kickjs-cli v8.13.1
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,6 +8,6 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import{t as e}from"./rolldown-runtime-BVrPnwAV.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=/* @__PURE__ */ e({BUILTIN_REPO_TYPES:()=>_,DEPRECATED_REPO_TYPES:()=>v,PACKAGE_MANAGERS:()=>m,PLURALIZE_DEFAULT:()=>!1,defineConfig:()=>b,execBin:()=>g,hasDependency:()=>x,hasSwagger:()=>C,loadKickConfig:()=>M,resolveModuleConfig:()=>k,resolvePluralize:()=>D,resolvePluralizeRoutes:()=>O,resolveSchemaLib:()=>w,resolveTokenScope:()=>T,runScript:()=>h,testImportSource:()=>S,validateAssetMap:()=>P,warnIfDeprecatedRepo:()=>y,writeAssetConfigSnapshot:()=>N});const m=[`pnpm`,`npm`,`yarn`,`bun`];function h(e,t){return e===`npm`||e===`bun`?`${e} run ${t}`:`${e} ${t}`}function g(e,t){return{npm:`npx ${t}`,pnpm:`pnpm exec ${t}`,yarn:`yarn ${t}`,bun:`bunx ${t}`}[e]}const _=[`inmemory`],v=[`prisma`,`drizzle`];function y(e){return v.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 b(e){return e}function x(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 S(e){return x(e,`vite-plus`,`any`)&&!x(e,`vitest`,`any`)?`vite-plus/test`:`vitest`}function C(e){return x(e,`@forinda/kickjs-swagger`,`runtime`)}function w(e){return x(e,`valibot`,`runtime`)?`valibot`:x(e,`yup`,`runtime`)?`yup`:`zod`}function T(e,t){if(e?.tokenScope&&typeof e.tokenScope==`string`&&e.tokenScope.length>0){let t=E(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=E(e?e[1]:t.name);if(n.length>0)return n}}}catch{}return`app`}function E(e){return e.toLowerCase().replace(/[^a-z0-9-]/g,`-`).replace(/^-+|-+$/g,``).replace(/-{2,}/g,`-`)}function D(e,t){return e??t?.pluralize??!1}function O(e,t){return e??t?.pluralizeRoutes??!0}function k(e){if(!e)return{};let t={dir:e.modules?.dir,repo:e.modules?.repo,schemaDir:e.modules?.schemaDir,pluralize:e.modules?.pluralize,pluralizeRoutes:e.modules?.pluralizeRoutes,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`&&!_.includes(t.repo)&&(y(t.repo)||console.warn(` Warning: modules.repo '${t.repo}' is not a built-in type (${_.join(`, `)}). It will generate a stub repository. Use { name: '${t.repo}' } to silence this warning.`)),t}const A=[`kick.config.ts`,`kick.config.js`,`kick.config.mjs`,`kick.config.json`];function j(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 M(e){let{findProjectRoot:t}=await import(`./project-root-C4lAZePJ.mjs`).then(e=>e.n),n=t(e);for(let e of A){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. Install jiti as a dev dependency, 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:j(n),tsconfigPaths:!0}).import(t,{default:!0}),i=P(e,n);for(let e of i)console.warn(` Warning: ${e}`);return N(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=P(i,n);for(let e of a)console.warn(` Warning: ${e}`);return N(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 N(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)+`
11
+ import{t as e}from"./rolldown-runtime-Bn82Wzut.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=/* @__PURE__ */ e({BUILTIN_REPO_TYPES:()=>_,DEPRECATED_REPO_TYPES:()=>v,PACKAGE_MANAGERS:()=>m,PLURALIZE_DEFAULT:()=>!1,defineConfig:()=>b,execBin:()=>g,hasDependency:()=>x,hasSwagger:()=>C,loadKickConfig:()=>M,resolveModuleConfig:()=>k,resolvePluralize:()=>D,resolvePluralizeRoutes:()=>O,resolveSchemaLib:()=>w,resolveTokenScope:()=>T,runScript:()=>h,testImportSource:()=>S,validateAssetMap:()=>P,warnIfDeprecatedRepo:()=>y,writeAssetConfigSnapshot:()=>N});const m=[`pnpm`,`npm`,`yarn`,`bun`];function h(e,t){return e===`npm`||e===`bun`?`${e} run ${t}`:`${e} ${t}`}function g(e,t){return{npm:`npx ${t}`,pnpm:`pnpm exec ${t}`,yarn:`yarn ${t}`,bun:`bunx ${t}`}[e]}const _=[`inmemory`],v=[`prisma`,`drizzle`];function y(e){return v.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 b(e){return e}function x(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 S(e){return x(e,`vite-plus`,`any`)&&!x(e,`vitest`,`any`)?`vite-plus/test`:`vitest`}function C(e){return x(e,`@forinda/kickjs-swagger`,`runtime`)}function w(e){return x(e,`valibot`,`runtime`)?`valibot`:x(e,`yup`,`runtime`)?`yup`:`zod`}function T(e,t){if(e?.tokenScope&&typeof e.tokenScope==`string`&&e.tokenScope.length>0){let t=E(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=E(e?e[1]:t.name);if(n.length>0)return n}}}catch{}return`app`}function E(e){return e.toLowerCase().replace(/[^a-z0-9-]/g,`-`).replace(/^-+|-+$/g,``).replace(/-{2,}/g,`-`)}function D(e,t){return e??t?.pluralize??!1}function O(e,t){return e??t?.pluralizeRoutes??!0}function k(e){if(!e)return{};let t={dir:e.modules?.dir,repo:e.modules?.repo,schemaDir:e.modules?.schemaDir,pluralize:e.modules?.pluralize,pluralizeRoutes:e.modules?.pluralizeRoutes,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`&&!_.includes(t.repo)&&(y(t.repo)||console.warn(` Warning: modules.repo '${t.repo}' is not a built-in type (${_.join(`, `)}). It will generate a stub repository. Use { name: '${t.repo}' } to silence this warning.`)),t}const A=[`kick.config.ts`,`kick.config.js`,`kick.config.mjs`,`kick.config.json`];function j(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 M(e){let{findProjectRoot:t}=await import(`./project-root-DYJU7ROd.mjs`).then(e=>e.n),n=t(e);for(let e of A){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. Install jiti as a dev dependency, 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:j(n),tsconfigPaths:!0}).import(t,{default:!0}),i=P(e,n);for(let e of i)console.warn(` Warning: ${e}`);return N(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=P(i,n);for(let e of a)console.warn(` Warning: ${e}`);return N(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 N(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
12
  `,`utf-8`)}catch{}}function P(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&&F(a(t,s.dest),r)&&n.push(`assetMap.${i}.dest ('${s.dest}') resolves outside the project root — refusing to copy`)}return n}function F(e,t){let r=i(t,e);return r===``?!1:r.startsWith(`..`)||n(r)}export{x as a,k as c,w as d,T as f,y as h,g as i,D as l,S as m,p as n,C as o,h as p,b as r,M as s,m as t,O as u};
13
- //# sourceMappingURL=config-CHRM7WLZ.mjs.map
13
+ //# sourceMappingURL=config-D0zuz3Fx.mjs.map