@forinda/kickjs-cli 5.1.0 → 5.2.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 (27) hide show
  1. package/dist/{builtins-caRjFvKz.mjs → builtins-B0dptoXq.mjs} +626 -241
  2. package/dist/builtins-B0dptoXq.mjs.map +1 -0
  3. package/dist/{builtins-Cb_d-b1S.mjs → builtins-N3mDa6bM.mjs} +695 -273
  4. package/dist/cli.mjs +9 -9
  5. package/dist/{config-8bAt-mLl.mjs → config-Bc6ERRTE.mjs} +35 -5
  6. package/dist/{config-C_LQNClP.mjs → config-CRi3zCxk.mjs} +36 -6
  7. package/dist/config-CRi3zCxk.mjs.map +1 -0
  8. package/dist/{generator-extension-CYY-RI21.mjs → generator-extension-C-HwKvFf.mjs} +76 -39
  9. package/dist/generator-extension-C-HwKvFf.mjs.map +1 -0
  10. package/dist/index.d.mts +282 -1
  11. package/dist/index.d.mts.map +1 -1
  12. package/dist/index.mjs +4 -4
  13. package/dist/{plugin-D8K5fG-O.mjs → plugin-DfomEcef.mjs} +4 -4
  14. package/dist/{plugin-D8K5fG-O.mjs.map → plugin-DfomEcef.mjs.map} +1 -1
  15. package/dist/{plugin-Bgfg7qMk.mjs → plugin-b7ig7Uxv.mjs} +2 -2
  16. package/dist/{rolldown-runtime-BM29JyaJ.mjs → rolldown-runtime-CV_zlh2d.mjs} +1 -1
  17. package/dist/{run-plugins-BXvMFPhJ.mjs → run-plugins-D9abb5Nx.mjs} +2 -2
  18. package/dist/{typegen-BNz_RQTb.mjs → typegen-B9S81bOx.mjs} +48 -225
  19. package/dist/typegen-B9S81bOx.mjs.map +1 -0
  20. package/dist/{typegen-8ZeA1B-X.mjs → typegen-BKUAdp_3.mjs} +47 -228
  21. package/dist/{types-BBUo1vXh.mjs → types-CU89yUxU.mjs} +2 -2
  22. package/dist/{types-BBUo1vXh.mjs.map → types-CU89yUxU.mjs.map} +1 -1
  23. package/package.json +6 -4
  24. package/dist/builtins-caRjFvKz.mjs.map +0 -1
  25. package/dist/config-C_LQNClP.mjs.map +0 -1
  26. package/dist/generator-extension-CYY-RI21.mjs.map +0 -1
  27. package/dist/typegen-8ZeA1B-X.mjs.map +0 -1
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs-cli v5.1.0
2
+ * @forinda/kickjs-cli v5.2.1
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,9 +8,9 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import { i as runShellCommand, t as builtinCliPlugins } from "./builtins-Cb_d-b1S.mjs";
12
- import { r as loadKickConfig } from "./config-8bAt-mLl.mjs";
13
- import { n as mergeCliPlugins } from "./plugin-Bgfg7qMk.mjs";
11
+ import { i as runShellCommand, t as builtinCliPlugins } from "./builtins-N3mDa6bM.mjs";
12
+ import { r as loadKickConfig } from "./config-Bc6ERRTE.mjs";
13
+ import { n as mergeCliPlugins } from "./plugin-b7ig7Uxv.mjs";
14
14
  import { Command } from "commander";
15
15
  import { readFileSync } from "node:fs";
16
16
  import { dirname, join } from "node:path";
@@ -92,7 +92,7 @@ function registerSingleCommand(program, def) {
92
92
  console.log(` $ ${finalCmd}`);
93
93
  try {
94
94
  runShellCommand(finalCmd);
95
- } catch (err) {
95
+ } catch {
96
96
  console.error(` Command failed: ${def.name}`);
97
97
  process.exitCode = 1;
98
98
  return;
@@ -107,15 +107,15 @@ const pkg = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf-
107
107
  async function main() {
108
108
  const program = new Command();
109
109
  program.name("kick").description("KickJS — A production-grade, decorator-driven Node.js framework").version(pkg.version);
110
- const config = await loadKickConfig(process.cwd());
111
- const merged = mergeCliPlugins([...builtinCliPlugins, ...config?.plugins ?? []], config?.commands ?? []);
110
+ const config = await loadKickConfig(process.cwd()) ?? {};
111
+ const merged = mergeCliPlugins([...builtinCliPlugins, ...config.plugins ?? []], config.commands ?? []);
112
112
  await merged.register(program, {
113
113
  cwd: process.cwd(),
114
- config: config ?? null,
114
+ config,
115
115
  log: (msg) => console.log(msg)
116
116
  });
117
117
  registerCustomCommands(program, {
118
- ...config ?? {},
118
+ ...config,
119
119
  commands: merged.commands
120
120
  });
121
121
  program.showHelpAfterError();
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs-cli v5.1.0
2
+ * @forinda/kickjs-cli v5.2.1
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,8 +8,8 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import { t as __exportAll } from "./rolldown-runtime-BM29JyaJ.mjs";
12
- import { existsSync } from "node:fs";
11
+ import { t as __exportAll } from "./rolldown-runtime-CV_zlh2d.mjs";
12
+ import { existsSync, readFileSync } from "node:fs";
13
13
  import { isAbsolute, join, relative, resolve } from "node:path";
14
14
  import { access, readFile } from "node:fs/promises";
15
15
  //#region src/config.ts
@@ -19,6 +19,7 @@ var config_exports = /* @__PURE__ */ __exportAll({
19
19
  defineConfig: () => defineConfig,
20
20
  loadKickConfig: () => loadKickConfig,
21
21
  resolveModuleConfig: () => resolveModuleConfig,
22
+ resolveTokenScope: () => resolveTokenScope,
22
23
  validateAssetMap: () => validateAssetMap
23
24
  });
24
25
  const PACKAGE_MANAGERS = [
@@ -37,6 +38,35 @@ function defineConfig(config) {
37
38
  return config;
38
39
  }
39
40
  /** Resolve module config from `modules.*` block. */
41
+ /**
42
+ * Resolve the project's DI token scope for code generators.
43
+ * Falls back through kick.config.ts → package.json → `'app'`.
44
+ *
45
+ * @param config Loaded `kick.config.ts` (null when not present)
46
+ * @param cwd Project root — used to read package.json
47
+ */
48
+ function resolveTokenScope(config, cwd) {
49
+ if (config?.tokenScope && typeof config.tokenScope === "string" && config.tokenScope.length > 0) {
50
+ const sanitised = sanitizeScope(config.tokenScope);
51
+ if (sanitised.length > 0) return sanitised;
52
+ }
53
+ try {
54
+ const pkgPath = join(cwd, "package.json");
55
+ if (existsSync(pkgPath)) {
56
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
57
+ if (typeof pkg.name === "string" && pkg.name.length > 0) {
58
+ const scoped = pkg.name.match(/^@([^/]+)\//);
59
+ const candidate = scoped ? sanitizeScope(scoped[1]) : sanitizeScope(pkg.name);
60
+ if (candidate.length > 0) return candidate;
61
+ }
62
+ }
63
+ } catch {}
64
+ return "app";
65
+ }
66
+ /** Lowercase + strip characters that would break a token literal. */
67
+ function sanitizeScope(raw) {
68
+ return raw.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/^-+|-+$/g, "").replace(/-{2,}/g, "-");
69
+ }
40
70
  function resolveModuleConfig(config) {
41
71
  if (!config) return {};
42
72
  const mc = {
@@ -75,7 +105,7 @@ async function loadKickConfig(cwd) {
75
105
  const warnings = validateAssetMap(config, cwd);
76
106
  for (const warning of warnings) console.warn(` Warning: ${warning}`);
77
107
  return config;
78
- } catch (err) {
108
+ } catch {
79
109
  if (filename.endsWith(".ts")) console.warn(`Warning: Failed to load ${filename}. TypeScript config files require a runtime loader (e.g. tsx, ts-node) or use kick.config.js/.mjs instead.`);
80
110
  continue;
81
111
  }
@@ -136,4 +166,4 @@ function escapesRoot(path, root) {
136
166
  return rel === "" ? false : rel.startsWith("..") || isAbsolute(rel);
137
167
  }
138
168
  //#endregion
139
- export { resolveModuleConfig as i, config_exports as n, loadKickConfig as r, PACKAGE_MANAGERS as t };
169
+ export { resolveTokenScope as a, resolveModuleConfig as i, config_exports as n, loadKickConfig as r, PACKAGE_MANAGERS as t };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs-cli v5.1.0
2
+ * @forinda/kickjs-cli v5.2.1
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -8,10 +8,10 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- import { t as __exportAll } from "./rolldown-runtime-BM29JyaJ.mjs";
11
+ import { t as __exportAll } from "./rolldown-runtime-CV_zlh2d.mjs";
12
12
  import { isAbsolute, join, relative, resolve } from "node:path";
13
+ import { existsSync, readFileSync } from "node:fs";
13
14
  import { access, readFile } from "node:fs/promises";
14
- import { existsSync } from "node:fs";
15
15
  //#region src/config.ts
16
16
  var config_exports = /* @__PURE__ */ __exportAll({
17
17
  BUILTIN_REPO_TYPES: () => BUILTIN_REPO_TYPES,
@@ -19,6 +19,7 @@ var config_exports = /* @__PURE__ */ __exportAll({
19
19
  defineConfig: () => defineConfig,
20
20
  loadKickConfig: () => loadKickConfig,
21
21
  resolveModuleConfig: () => resolveModuleConfig,
22
+ resolveTokenScope: () => resolveTokenScope,
22
23
  validateAssetMap: () => validateAssetMap
23
24
  });
24
25
  const PACKAGE_MANAGERS = [
@@ -37,6 +38,35 @@ function defineConfig(config) {
37
38
  return config;
38
39
  }
39
40
  /** Resolve module config from `modules.*` block. */
41
+ /**
42
+ * Resolve the project's DI token scope for code generators.
43
+ * Falls back through kick.config.ts → package.json → `'app'`.
44
+ *
45
+ * @param config Loaded `kick.config.ts` (null when not present)
46
+ * @param cwd Project root — used to read package.json
47
+ */
48
+ function resolveTokenScope(config, cwd) {
49
+ if (config?.tokenScope && typeof config.tokenScope === "string" && config.tokenScope.length > 0) {
50
+ const sanitised = sanitizeScope(config.tokenScope);
51
+ if (sanitised.length > 0) return sanitised;
52
+ }
53
+ try {
54
+ const pkgPath = join(cwd, "package.json");
55
+ if (existsSync(pkgPath)) {
56
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
57
+ if (typeof pkg.name === "string" && pkg.name.length > 0) {
58
+ const scoped = pkg.name.match(/^@([^/]+)\//);
59
+ const candidate = scoped ? sanitizeScope(scoped[1]) : sanitizeScope(pkg.name);
60
+ if (candidate.length > 0) return candidate;
61
+ }
62
+ }
63
+ } catch {}
64
+ return "app";
65
+ }
66
+ /** Lowercase + strip characters that would break a token literal. */
67
+ function sanitizeScope(raw) {
68
+ return raw.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/^-+|-+$/g, "").replace(/-{2,}/g, "-");
69
+ }
40
70
  function resolveModuleConfig(config) {
41
71
  if (!config) return {};
42
72
  const mc = {
@@ -75,7 +105,7 @@ async function loadKickConfig(cwd) {
75
105
  const warnings = validateAssetMap(config, cwd);
76
106
  for (const warning of warnings) console.warn(` Warning: ${warning}`);
77
107
  return config;
78
- } catch (err) {
108
+ } catch {
79
109
  if (filename.endsWith(".ts")) console.warn(`Warning: Failed to load ${filename}. TypeScript config files require a runtime loader (e.g. tsx, ts-node) or use kick.config.js/.mjs instead.`);
80
110
  continue;
81
111
  }
@@ -136,6 +166,6 @@ function escapesRoot(path, root) {
136
166
  return rel === "" ? false : rel.startsWith("..") || isAbsolute(rel);
137
167
  }
138
168
  //#endregion
139
- export { resolveModuleConfig as a, loadKickConfig as i, config_exports as n, defineConfig as r, PACKAGE_MANAGERS as t };
169
+ export { resolveModuleConfig as a, loadKickConfig as i, config_exports as n, resolveTokenScope as o, defineConfig as r, PACKAGE_MANAGERS as t };
140
170
 
141
- //# sourceMappingURL=config-C_LQNClP.mjs.map
171
+ //# sourceMappingURL=config-CRi3zCxk.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-CRi3zCxk.mjs","names":[],"sources":["../src/config.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs'\nimport { readFile, access } from 'node:fs/promises'\nimport { isAbsolute, join, relative, resolve } from 'node:path'\n\nimport type { KickCliPlugin } from './plugin/types'\n\n/** A custom command that developers can register via kick.config.ts */\nexport interface KickCommandDefinition {\n /** The command name (e.g. 'db:migrate', 'seed', 'proto:gen') */\n name: string\n /** Description shown in --help */\n description: string\n /**\n * Shell command(s) to run. Can be a single string or an array of\n * sequential steps. Use {args} as a placeholder for CLI arguments.\n *\n * @example\n * 'npx drizzle-kit migrate'\n * ['npx drizzle-kit generate', 'npx drizzle-kit migrate']\n */\n steps: string | string[]\n /** Optional aliases (e.g. ['migrate'] for 'db:migrate') */\n aliases?: string[]\n}\n\n/** Project pattern — controls what generators produce and which deps are installed */\nexport type ProjectPattern = 'rest' | 'ddd' | 'cqrs' | 'minimal'\n\n/** Package manager used for `kick add` and other dep-installing commands */\nexport type PackageManager = 'pnpm' | 'npm' | 'yarn' | 'bun'\n\nexport const PACKAGE_MANAGERS: readonly PackageManager[] = ['pnpm', 'npm', 'yarn', 'bun']\n\n/** Built-in repository types with first-class code generation support */\nexport type BuiltinRepoType = 'drizzle' | 'inmemory' | 'prisma'\n\nexport const BUILTIN_REPO_TYPES: readonly string[] = ['drizzle', 'inmemory', 'prisma']\n\n/** Custom repository type — generates a stub with TODO markers */\nexport interface CustomRepoType {\n name: string\n}\n\n/** Repository type — built-in string or custom object */\nexport type RepoTypeConfig = BuiltinRepoType | CustomRepoType\n\n/**\n * Supported schema validators for `kick typegen` body/query/params\n * type extraction. Only `'zod'` ships built-in for now; other libraries\n * (Joi, Yup, JSON Schema) will be added later as the adapter system\n * grows. Set to `false` (or omit) to disable schema-driven body typing\n * entirely (the route entries will keep `body: unknown`).\n */\nexport type SchemaValidator = 'zod' | false\n\n/**\n * One entry in the typed `assetMap` config record (`assets-plan.md`).\n * Each entry names a source directory whose files become addressable\n * via the `assets.<name>.*` typed accessor at runtime.\n */\nexport interface AssetMapEntry {\n /**\n * Source directory, relative to project root. Required. The directory\n * must exist when `kick build` runs — `loadKickConfig` warns when an\n * entry points at a missing directory but doesn't fail the load\n * (the typegen + build steps surface the error in context instead).\n */\n src: string\n /**\n * Destination directory inside `dist/`. Defaults to `dist/<name>/`\n * where `<name>` is the assetMap key. Override when the consumer of\n * the assets expects a non-standard layout (e.g. an existing\n * downstream tool reads from `dist/templates/...`).\n */\n dest?: string\n /**\n * Glob pattern for which files to include. Defaults to `**\\/*` (all\n * files). Files that don't match are NOT copied — `assetMap` is\n * selective by design (unlike `copyDirs` which copies everything).\n */\n glob?: string\n /**\n * How file extensions feed into manifest keys. Default `'auto'`.\n *\n * - `'strip'` — drop the extension. `pages/index.pug` →\n * `'pages/index'`. Two siblings with the same basename collide;\n * last-walk-order wins, others are silently dropped. Opt-in\n * only — kept for backward compatibility with projects that\n * relied on this contract.\n * - `'with-extension'` — keep every extension on every key. Best\n * when the namespace holds extension siblings (`index.pug` +\n * `index.html` + `index.css` in `src/pages/`); every file\n * reaches the manifest under its full path.\n * - `'auto'` — strip when basenames are unique, keep extensions\n * on collision groups. Singleton files keep their short key;\n * `pages/index.{pug,html,css}` becomes\n * `pages/index.pug` / `pages/index.html` / `pages/index.css`.\n * No data loss; non-colliding namespaces stay on the short\n * keys they had before.\n *\n * @default 'auto'\n */\n keys?: 'auto' | 'strip' | 'with-extension'\n}\n\n/** Typegen settings — controls .kickjs/types/* generation */\nexport interface TypegenConfig {\n /**\n * Source directory to scan for controllers and decorators.\n * Defaults to `'src'`.\n */\n srcDir?: string\n /**\n * Output directory for generated `.d.ts` files.\n * Defaults to `'.kickjs/types'`.\n */\n outDir?: string\n /**\n * Schema validator used to derive `body` types from route metadata.\n *\n * - `'zod'` — emit `z.infer<typeof <importedSchema>>` for any schema\n * referenced as a named identifier in `@Get/@Post/...({ body, query, params })`.\n * - `false` — disable schema-driven body typing.\n *\n * Future: `'joi' | 'yup' | 'json-schema'` plus a `{ name; module }`\n * escape hatch for custom adapters.\n *\n * @default 'zod'\n */\n schemaValidator?: SchemaValidator\n /**\n * Path to the project's env schema file (relative to project root).\n * Must default-export a `defineEnv(...)` schema for typegen to emit\n * the typed `KickEnv` global registry.\n *\n * Set to `false` to disable env typing entirely.\n *\n * @default 'src/env.ts'\n */\n envFile?: string | false\n /**\n * Built-in or user typegen plugin ids to skip during `kick typegen`,\n * `kick dev`, and `kick typegen --watch`.\n *\n * The plugin still loads and merge-time conflict detection still\n * runs — only the `generate()` invocation is skipped — so adopters\n * who want to hand-write `KickDbRegister` (manual typeof-schema\n * augmentation) can disable `'kick/db'` and keep the rest:\n *\n * @example\n * typegen: {\n * disable: ['kick/db'], // hand-written register.ts owns the type\n * }\n *\n * Unrecognised ids are ignored — the list is treated as a wishlist,\n * not a strict registry.\n */\n disable?: string[]\n}\n\n/** Module generation settings — controls how `kick g module` produces code */\nexport interface ModuleConfig {\n /** Where modules live (default: 'src/modules') */\n dir?: string\n /**\n * Default repository implementation for generators.\n *\n * Built-in types (string): `'drizzle'`, `'inmemory'`, `'prisma'`\n * — generate fully working repository code.\n *\n * Custom types (object): `{ name: 'typeorm' }`\n * — generate a stub repository with TODO markers.\n *\n * @example\n * repo: 'prisma' // built-in\n * repo: { name: 'typeorm' } // custom\n */\n repo?: RepoTypeConfig\n /** Schema output directory (e.g. 'src/db/schema' for Drizzle, 'prisma/' for Prisma) */\n schemaDir?: string\n /**\n * Whether to pluralize module names in generated code.\n * When true (default), `kick g module user` creates `src/modules/users/`.\n * When false, it creates `src/modules/user/` and uses singular names throughout.\n */\n pluralize?: boolean\n /**\n * Import path for the Prisma generated client in `--repo prisma` templates.\n * Must resolve within `src/` for path alias compatibility.\n *\n * @default '@prisma/client' (Prisma 5/6)\n * @example\n * prismaClientPath: '@/generated/prisma/client' // Prisma 7+\n * prismaClientPath: './generated/prisma/client' // relative\n */\n prismaClientPath?: string\n}\n\n/** Configuration for the kick.config.ts file */\nexport interface KickConfig {\n /**\n * Project pattern — controls default generator behavior.\n * - 'rest' — Express + Swagger (default)\n * - 'ddd' — Full DDD modules with use cases, entities, value objects\n * - 'cqrs' — CQRS with commands, queries, events, WebSocket + queue\n * - 'minimal' — Bare Express with no scaffolding\n */\n pattern?: ProjectPattern\n /**\n * Module generation settings — directory, repo type, pluralization, schema dir.\n *\n * @example\n * modules: {\n * dir: 'src/modules',\n * repo: 'prisma',\n * pluralize: false,\n * schemaDir: 'prisma/',\n * }\n */\n modules?: ModuleConfig\n /**\n * Package manager used by `kick add` (and any future dep-installing command)\n * to install dependencies. When set, overrides lockfile auto-detection so\n * commands always use the project's intended package manager.\n *\n * Priority (highest first):\n * 1. `--pm` flag on the CLI\n * 2. `packageManager` in kick.config\n * 3. `packageManager` field in package.json (corepack convention)\n * 4. Lockfile detection (pnpm-lock.yaml → pnpm, yarn.lock → yarn)\n * 5. `'npm'`\n *\n * @example\n * packageManager: 'pnpm'\n */\n packageManager?: PackageManager\n\n /**\n * DI token scope prefix used by code generators. Every scaffolded\n * `createToken<T>('<scope>/<area>/<key>')` substitutes this string\n * for `<scope>`. Generators emit org-scoped tokens out of the box\n * so adopter projects pass `kick-lint`'s `token-reserved-prefix`\n * rule (which forbids the reserved `kick/` prefix on third-party\n * code) without manual rename.\n *\n * Resolution order (highest first):\n * 1. This field, when set\n * 2. `package.json` `name` field — `@scope/pkg` → `'scope'`,\n * bare `pkg` → `'pkg'`\n * 3. Fallback `'app'`\n *\n * @example\n * tokenScope: 'mycorp'\n * // → createToken<...>('mycorp/users/repository')\n */\n tokenScope?: string\n\n /**\n * Directories to copy to dist/ after build.\n * Useful for EJS templates, email templates, static assets, etc.\n *\n * @example\n * ```ts\n * copyDirs: [\n * 'src/views', // copies to dist/src/views\n * { src: 'src/views', dest: 'dist/views' }, // custom dest\n * 'src/emails',\n * ]\n * ```\n */\n copyDirs?: Array<string | { src: string; dest?: string }>\n /**\n * Build output settings. The asset manager + `kick build`'s copy\n * steps honour these — adopters who use Vite's `build.outDir =\n * 'out'` (or any non-default) should mirror the value here so\n * `assets.x.y()` paths line up with where Vite actually wrote.\n *\n * @example\n * ```ts\n * build: { outDir: 'out' }\n * ```\n */\n build?: {\n /**\n * Output directory, relative to project root. Defaults to\n * `'dist'`. The asset manager emits its manifest + copies\n * assetMap entries into this directory (under a per-namespace\n * subdirectory by default; override per-entry via `dest`).\n */\n outDir?: string\n }\n /**\n * Typed, addressable assets — see `assets-plan.md`. Each entry maps\n * a logical namespace name to a source directory. The build pipeline\n * auto-derives the necessary copy step + emits a manifest at\n * `dist/.kickjs-assets.json`; the runtime exposes\n * `import { assets } from '@forinda/kickjs'` so adopters can resolve\n * paths without dev/prod branching.\n *\n * `copyDirs` is unchanged — `assetMap` is a separate, opt-in surface.\n * Adopters who want raw directory copies keep using `copyDirs`; those\n * who want typed addressable assets add `assetMap` entries.\n *\n * @example\n * ```ts\n * assetMap: {\n * mails: { src: 'src/templates/mails' },\n * reports: { src: 'src/templates/reports', glob: '**\\/*.{ejs,html}' },\n * schemas: { src: 'src/schemas', glob: '**\\/*.json' },\n * }\n * ```\n */\n assetMap?: Record<string, AssetMapEntry>\n /**\n * Typegen settings — controls `.kickjs/types/*` generation including\n * the schema validator used for body type extraction.\n *\n * @example\n * ```ts\n * typegen: {\n * schemaValidator: 'zod',\n * }\n * ```\n */\n typegen?: TypegenConfig\n /** Custom commands that extend the CLI */\n commands?: KickCommandDefinition[]\n /**\n * CLI plugins — bundled commands + typegens contributed by external\n * packages (e.g. `@forinda/kickjs-cli-drizzle`). Plugin commands\n * appear first; adopter `commands` overrides plugin commands of the\n * same name. Duplicate commands or typegen ids across two plugins\n * fail-fast at CLI startup.\n *\n * @example\n * import { drizzlePlugin } from '@forinda/kickjs-cli-drizzle'\n * export default defineConfig({\n * plugins: [drizzlePlugin({ schemaPath: 'src/db/schema' })],\n * })\n */\n plugins?: KickCliPlugin[]\n /** Code style overrides (auto-detected from prettier when possible) */\n style?: {\n semicolons?: boolean\n quotes?: 'single' | 'double'\n trailingComma?: 'all' | 'es5' | 'none'\n indent?: number\n }\n}\n\n/** Helper to define a type-safe kick.config.ts */\nexport function defineConfig(config: KickConfig): KickConfig {\n return config\n}\n\n/** Resolve module config from `modules.*` block. */\n/**\n * Resolve the project's DI token scope for code generators.\n * Falls back through kick.config.ts → package.json → `'app'`.\n *\n * @param config Loaded `kick.config.ts` (null when not present)\n * @param cwd Project root — used to read package.json\n */\nexport function resolveTokenScope(config: KickConfig | null, cwd: string): string {\n if (config?.tokenScope && typeof config.tokenScope === 'string' && config.tokenScope.length > 0) {\n const sanitised = sanitizeScope(config.tokenScope)\n // Configured tokenScope can sanitise down to an empty string (e.g.\n // '___' or '!!') — falling through to the package.json chain is\n // safer than emitting an invalid `'/users/repository'` token.\n if (sanitised.length > 0) return sanitised\n }\n\n // Read package.json synchronously — this runs once per generator\n // invocation, so a sync read is cheaper than the async dance + lets\n // the call sites (template builders) stay synchronous.\n try {\n const pkgPath = join(cwd, 'package.json')\n if (existsSync(pkgPath)) {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8')) as { name?: unknown }\n if (typeof pkg.name === 'string' && pkg.name.length > 0) {\n const scoped = pkg.name.match(/^@([^/]+)\\//)\n const candidate = scoped ? sanitizeScope(scoped[1]) : sanitizeScope(pkg.name)\n if (candidate.length > 0) return candidate\n // Same empty-after-sanitize guard.\n }\n }\n } catch {\n // package.json missing or malformed — fall through to default\n }\n\n return 'app'\n}\n\n/** Lowercase + strip characters that would break a token literal. */\nfunction sanitizeScope(raw: string): string {\n return raw\n .toLowerCase()\n .replace(/[^a-z0-9-]/g, '-') // collapse anything weird to a hyphen\n .replace(/^-+|-+$/g, '') // trim leading/trailing hyphens\n .replace(/-{2,}/g, '-') // collapse runs of hyphens\n}\n\nexport function resolveModuleConfig(config: KickConfig | null): ModuleConfig {\n if (!config) return {}\n const mc: ModuleConfig = {\n dir: config.modules?.dir,\n repo: config.modules?.repo,\n schemaDir: config.modules?.schemaDir,\n pluralize: config.modules?.pluralize,\n prismaClientPath: config.modules?.prismaClientPath,\n }\n\n // Warn if a string repo value isn't a known built-in\n if (mc.repo && typeof mc.repo === 'string' && !BUILTIN_REPO_TYPES.includes(mc.repo)) {\n console.warn(\n ` Warning: modules.repo '${mc.repo}' is not a built-in type (${BUILTIN_REPO_TYPES.join(', ')}).` +\n ` It will generate a stub repository. Use { name: '${mc.repo}' } to silence this warning.`,\n )\n }\n\n return mc\n}\n\nconst CONFIG_FILES = ['kick.config.ts', 'kick.config.js', 'kick.config.mjs', 'kick.config.json']\n\n/** Load kick.config.* from the project root */\nexport async function loadKickConfig(cwd: string): Promise<KickConfig | null> {\n for (const filename of CONFIG_FILES) {\n const filepath = join(cwd, filename)\n try {\n await access(filepath)\n } catch {\n continue\n }\n\n if (filename.endsWith('.json')) {\n const content = await readFile(filepath, 'utf-8')\n return JSON.parse(content)\n }\n\n // For .ts/.js/.mjs — dynamic import (use file URL for cross-platform compat)\n try {\n const { pathToFileURL } = await import('node:url')\n const mod = await import(pathToFileURL(filepath).href)\n const config = (mod.default ?? mod) as KickConfig\n // Surface assetMap mistakes at config-load time so they aren't\n // hidden inside the build pipeline. Warnings only — a typo\n // shouldn't block `kick g`, `kick typegen`, etc.\n const warnings = validateAssetMap(config, cwd)\n for (const warning of warnings) console.warn(` Warning: ${warning}`)\n return config\n } catch {\n if (filename.endsWith('.ts')) {\n console.warn(\n `Warning: Failed to load ${filename}. TypeScript config files require ` +\n 'a runtime loader (e.g. tsx, ts-node) or use kick.config.js/.mjs instead.',\n )\n }\n continue\n }\n }\n return null\n}\n\n/**\n * Validate `assetMap` entries on a loaded config. Returns a list of\n * human-readable warnings; the caller decides how to surface them\n * (typically `console.warn`). Never throws — `kick g` and other\n * unrelated commands should keep working even when the assetMap is\n * misconfigured.\n *\n * Checks:\n *\n * - Each entry's `src` is a non-empty string.\n * - The `src` directory exists on disk (otherwise the typegen + build\n * steps will fail later with cryptic errors).\n * - `dest` doesn't escape the project root (defensive — a `dest:\n * '../../etc'` typo could write files outside the workspace).\n * - The namespace key is a non-empty string and doesn't include a\n * `/` (would conflict with the `<namespace>/<key>` manifest format).\n */\nexport function validateAssetMap(config: KickConfig | null, cwd: string): string[] {\n const warnings: string[] = []\n if (!config?.assetMap) return warnings\n\n const root = resolve(cwd)\n for (const [namespace, entry] of Object.entries(config.assetMap)) {\n if (!namespace || namespace.includes('/')) {\n warnings.push(\n `assetMap key '${namespace}' is invalid — must be a non-empty string without '/'`,\n )\n continue\n }\n if (typeof entry?.src !== 'string' || entry.src.length === 0) {\n warnings.push(`assetMap.${namespace} is missing a non-empty 'src' field`)\n continue\n }\n const srcAbs = resolve(cwd, entry.src)\n if (!existsSync(srcAbs)) {\n warnings.push(\n `assetMap.${namespace}.src ('${entry.src}') does not exist — typegen + build will fail`,\n )\n }\n if (entry.dest) {\n const destAbs = resolve(cwd, entry.dest)\n // path.relative is the right primitive for \"is X inside Y?\" —\n // a raw startsWith() prefix match has two failure modes the\n // earlier version hit: (a) `/app` is a prefix of `/app2/...`\n // even though they're different directories, and (b) it's\n // case-sensitive on filesystems that aren't (macOS default,\n // Windows). path.relative handles both correctly + accounts\n // for `..` traversal in the destination.\n if (escapesRoot(destAbs, root)) {\n warnings.push(\n `assetMap.${namespace}.dest ('${entry.dest}') resolves outside the project root — refusing to copy`,\n )\n }\n }\n }\n return warnings\n}\n\n/**\n * Returns true when `path` (absolute) resolves outside of `root`\n * (also absolute). Uses `path.relative` for accuracy:\n *\n * - The result is empty when paths are identical (inside).\n * - It starts with `..` when the path traverses outside the root.\n * - It's absolute (Windows: cross-drive) when there's no relative\n * path between them.\n *\n * Avoids the prefix-match pitfalls of `startsWith` (e.g. `/app`\n * matching `/app2/...`, or case-mismatches on macOS / Windows).\n */\nfunction escapesRoot(path: string, root: string): boolean {\n const rel = relative(root, path)\n return rel === '' ? false : rel.startsWith('..') || isAbsolute(rel)\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs-cli v5.1.0
2
+ * @forinda/kickjs-cli v5.2.1
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
@@ -10,12 +10,12 @@
10
10
  */
11
11
  import { createRequire } from "node:module";
12
12
  import { dirname, extname, join, resolve } from "node:path";
13
+ import { existsSync, readFileSync } from "node:fs";
13
14
  import { access, mkdir, readFile, writeFile } from "node:fs/promises";
14
15
  import * as clack from "@clack/prompts";
15
16
  import pc from "picocolors";
16
17
  import pkg from "pluralize";
17
18
  import { execSync } from "node:child_process";
18
- import { existsSync, readFileSync } from "node:fs";
19
19
  import { fileURLToPath, pathToFileURL } from "node:url";
20
20
  //#region src/utils/fs.ts
21
21
  let _dryRun = false;
@@ -23,7 +23,7 @@ let _dryRun = false;
23
23
  function setDryRun(enabled) {
24
24
  _dryRun = enabled;
25
25
  }
26
- /** Extensions prettier can format. Anything else is written verbatim. */
26
+ /** Extensions oxfmt can format. Anything else is written verbatim. */
27
27
  const FORMATTABLE = new Set([
28
28
  ".ts",
29
29
  ".tsx",
@@ -37,15 +37,14 @@ const FORMATTABLE = new Set([
37
37
  /**
38
38
  * Write a file, creating parent directories if needed.
39
39
  *
40
- * After write, runs prettier against the file when:
40
+ * After write, runs oxfmt against the file when:
41
41
  * - format-on-write is enabled (default)
42
42
  * - the extension is in {@link FORMATTABLE}
43
- * - prettier resolves from the user's project (or our own cwd)
43
+ * - oxfmt resolves from the user's project (or our own cwd)
44
44
  *
45
- * Failures (missing prettier, unparseable source, prettier crash) are
45
+ * Failures (missing oxfmt, unparseable source, formatter crash) are
46
46
  * swallowed silently — formatting is a polish step, not a correctness
47
- * gate. The pre-existing pre-commit hook still catches anything we
48
- * couldn't format.
47
+ * gate. The pre-commit hook still catches anything we couldn't format.
49
48
  *
50
49
  * Skips writing entirely in dry run mode.
51
50
  */
@@ -55,28 +54,58 @@ async function writeFileSafe(filePath, content) {
55
54
  await writeFile(filePath, content, "utf-8");
56
55
  if (FORMATTABLE.has(extname(filePath))) await formatFile(filePath, content).catch(() => {});
57
56
  }
58
- let _prettier = void 0;
59
- /** Resolve prettier from the user's project; cache the result (or null) for the process. */
60
- function resolvePrettier(cwd) {
61
- if (_prettier !== void 0) return _prettier;
57
+ let _oxfmt = void 0;
58
+ /** Resolve oxfmt from the user's project; cache the result (or null) for the process. */
59
+ async function resolveOxfmt(cwd) {
60
+ if (_oxfmt !== void 0) return _oxfmt;
62
61
  try {
63
- _prettier = createRequire(join(cwd, "package.json"))("prettier");
62
+ _oxfmt = await import(createRequire(join(cwd, "package.json")).resolve("oxfmt"));
64
63
  } catch {
65
- _prettier = null;
64
+ _oxfmt = null;
66
65
  }
67
- return _prettier;
66
+ return _oxfmt;
68
67
  }
69
68
  async function formatFile(filePath, content) {
70
- const prettier = resolvePrettier(process.cwd());
71
- if (!prettier) return;
72
- if ((await prettier.getFileInfo(filePath, { resolveConfig: true })).ignored) return;
73
- const config = await prettier.resolveConfig(filePath) ?? {};
74
- const formatted = await prettier.format(content, {
75
- ...config,
76
- filepath: filePath
77
- });
78
- if (formatted === content) return;
79
- await writeFile(filePath, formatted, "utf-8");
69
+ const oxfmt = await resolveOxfmt(process.cwd());
70
+ if (!oxfmt) return;
71
+ const options = await loadOxfmtConfig(filePath);
72
+ if (options === null) return;
73
+ const result = await oxfmt.format(filePath, content, options);
74
+ if (result.code === content) return;
75
+ await writeFile(filePath, result.code, "utf-8");
76
+ }
77
+ const _oxfmtConfigCache = /* @__PURE__ */ new Map();
78
+ /**
79
+ * Walk up from `filePath`'s directory looking for `.oxfmtrc.json`.
80
+ * Returns `null` when no config is found anywhere on the path —
81
+ * generators then leave the raw template alone (which already
82
+ * follows project conventions). Cached per starting directory so
83
+ * the walk is one-shot per generator run.
84
+ */
85
+ async function loadOxfmtConfig(filePath) {
86
+ let dir = dirname(filePath);
87
+ const startDir = dir;
88
+ if (_oxfmtConfigCache.has(startDir)) return _oxfmtConfigCache.get(startDir);
89
+ while (true) {
90
+ const configPath = join(dir, ".oxfmtrc.json");
91
+ if (existsSync(configPath)) try {
92
+ const raw = await readFile(configPath, "utf-8");
93
+ const parsed = JSON.parse(raw);
94
+ delete parsed["$schema"];
95
+ delete parsed.ignorePatterns;
96
+ _oxfmtConfigCache.set(startDir, parsed);
97
+ return parsed;
98
+ } catch {
99
+ _oxfmtConfigCache.set(startDir, null);
100
+ return null;
101
+ }
102
+ const parent = dirname(dir);
103
+ if (parent === dir) {
104
+ _oxfmtConfigCache.set(startDir, null);
105
+ return null;
106
+ }
107
+ dir = parent;
108
+ }
80
109
  }
81
110
  /** Check if a file exists */
82
111
  async function fileExists(filePath) {
@@ -481,7 +510,7 @@ export const ${pascal.toUpperCase()}_QUERY_CONFIG: QueryParamsConfig = {
481
510
  //#endregion
482
511
  //#region src/generators/templates/dtos.ts
483
512
  function generateCreateDTO(ctx) {
484
- const { pascal, kebab } = ctx;
513
+ const { pascal } = ctx;
485
514
  return `import { z } from 'zod'
486
515
 
487
516
  /**
@@ -501,7 +530,7 @@ export type Create${pascal}DTO = z.infer<typeof create${pascal}Schema>
501
530
  `;
502
531
  }
503
532
  function generateUpdateDTO(ctx) {
504
- const { pascal, kebab } = ctx;
533
+ const { pascal } = ctx;
505
534
  return `import { z } from 'zod'
506
535
 
507
536
  export const update${pascal}Schema = z.object({
@@ -512,7 +541,7 @@ export type Update${pascal}DTO = z.infer<typeof update${pascal}Schema>
512
541
  `;
513
542
  }
514
543
  function generateResponseDTO(ctx) {
515
- const { pascal, kebab } = ctx;
544
+ const { pascal } = ctx;
516
545
  return `export interface ${pascal}ResponseDTO {
517
546
  id: string
518
547
  name: string
@@ -629,7 +658,7 @@ export class Delete${pascal}UseCase {
629
658
  //#endregion
630
659
  //#region src/generators/templates/repository.ts
631
660
  function generateRepositoryInterface(ctx) {
632
- const { pascal, kebab, dtoPrefix = "../../application/dtos" } = ctx;
661
+ const { pascal, kebab, dtoPrefix = "../../application/dtos", tokenScope = "app" } = ctx;
633
662
  return `/**
634
663
  * ${pascal} Repository Interface
635
664
  *
@@ -659,8 +688,12 @@ export interface I${pascal}Repository {
659
688
  * \`container.resolve(${pascal.toUpperCase()}_REPOSITORY)\` and
660
689
  * \`@Inject(${pascal.toUpperCase()}_REPOSITORY)\` both return the typed
661
690
  * interface — no manual generic, no \`any\` cast.
691
+ *
692
+ * The \`'${tokenScope}/'\` prefix matches the project scope so
693
+ * \`kick-lint\`'s \`token-reserved-prefix\` rule never fires —
694
+ * adopters must NOT use the reserved \`'kick/'\` namespace.
662
695
  */
663
- export const ${pascal.toUpperCase()}_REPOSITORY = createToken<I${pascal}Repository>('app/${kebab}/repository')
696
+ export const ${pascal.toUpperCase()}_REPOSITORY = createToken<I${pascal}Repository>('${tokenScope}/${kebab}/repository')
664
697
  `;
665
698
  }
666
699
  function generateInMemoryRepository(ctx) {
@@ -904,7 +937,7 @@ export class ${pascal} {
904
937
  `;
905
938
  }
906
939
  function generateValueObject(ctx) {
907
- const { pascal, kebab } = ctx;
940
+ const { pascal } = ctx;
908
941
  return `/**
909
942
  * ${pascal} ID Value Object
910
943
  *
@@ -1949,7 +1982,7 @@ export class ${pascal}Controller {
1949
1982
  //#endregion
1950
1983
  //#region src/generators/patterns/rest.ts
1951
1984
  async function generateRestFiles(ctx) {
1952
- const { pascal, kebab, plural, pluralPascal, repo, noTests, prismaClientPath, write } = ctx;
1985
+ const { pascal, kebab, plural, pluralPascal, repo, noTests, prismaClientPath, tokenScope, write } = ctx;
1953
1986
  await write(`${kebab}.module.ts`, generateRestModuleIndex({
1954
1987
  pascal,
1955
1988
  kebab,
@@ -1985,7 +2018,8 @@ async function generateRestFiles(ctx) {
1985
2018
  await write(`${kebab}.repository.ts`, generateRepositoryInterface({
1986
2019
  pascal,
1987
2020
  kebab,
1988
- dtoPrefix: "./dtos"
2021
+ dtoPrefix: "./dtos",
2022
+ tokenScope
1989
2023
  }));
1990
2024
  const builtinRepoFileMap = {
1991
2025
  inmemory: `in-memory-${kebab}`,
@@ -2045,7 +2079,7 @@ async function generateRestFiles(ctx) {
2045
2079
  //#endregion
2046
2080
  //#region src/generators/patterns/cqrs.ts
2047
2081
  async function generateCqrsFiles(ctx) {
2048
- const { pascal, kebab, plural, pluralPascal, repo, noTests, prismaClientPath, write } = ctx;
2082
+ const { pascal, kebab, plural, pluralPascal, repo, noTests, prismaClientPath, tokenScope, write } = ctx;
2049
2083
  await write(`${kebab}.module.ts`, generateCqrsModuleIndex({
2050
2084
  pascal,
2051
2085
  kebab,
@@ -2094,7 +2128,8 @@ async function generateCqrsFiles(ctx) {
2094
2128
  await write(`${kebab}.repository.ts`, generateRepositoryInterface({
2095
2129
  pascal,
2096
2130
  kebab,
2097
- dtoPrefix: "./dtos"
2131
+ dtoPrefix: "./dtos",
2132
+ tokenScope
2098
2133
  }));
2099
2134
  const builtinRepoFileMap = {
2100
2135
  inmemory: `in-memory-${kebab}`,
@@ -2154,7 +2189,7 @@ async function generateCqrsFiles(ctx) {
2154
2189
  //#endregion
2155
2190
  //#region src/generators/patterns/ddd.ts
2156
2191
  async function generateDddFiles(ctx) {
2157
- const { pascal, kebab, plural, pluralPascal, repo, noEntity, noTests, prismaClientPath, write } = ctx;
2192
+ const { pascal, kebab, plural, pluralPascal, repo, noEntity, noTests, prismaClientPath, tokenScope, write } = ctx;
2158
2193
  await write(`${kebab}.module.ts`, generateModuleIndex({
2159
2194
  pascal,
2160
2195
  kebab,
@@ -2195,7 +2230,8 @@ async function generateDddFiles(ctx) {
2195
2230
  for (const uc of useCases) await write(`application/use-cases/${uc.file}`, uc.content);
2196
2231
  await write(`domain/repositories/${kebab}.repository.ts`, generateRepositoryInterface({
2197
2232
  pascal,
2198
- kebab
2233
+ kebab,
2234
+ tokenScope
2199
2235
  }));
2200
2236
  await write(`domain/services/${kebab}-domain.service.ts`, generateDomainService({
2201
2237
  pascal,
@@ -2312,6 +2348,7 @@ async function generateModule(options) {
2312
2348
  noEntity: noEntity ?? false,
2313
2349
  noTests: noTests ?? false,
2314
2350
  prismaClientPath: options.prismaClientPath ?? "@prisma/client",
2351
+ tokenScope: options.tokenScope ?? "app",
2315
2352
  write,
2316
2353
  files
2317
2354
  };
@@ -4002,7 +4039,7 @@ async function initProject(options) {
4002
4039
  }
4003
4040
  }
4004
4041
  try {
4005
- const { runTypegen } = await import("./typegen-8ZeA1B-X.mjs").then((n) => n.n);
4042
+ const { runTypegen } = await import("./typegen-B9S81bOx.mjs").then((n) => n.n);
4006
4043
  await runTypegen({
4007
4044
  cwd: dir,
4008
4045
  allowDuplicates: true,
@@ -4340,4 +4377,4 @@ async function runGenerator(spec, source, input, cwd) {
4340
4377
  //#endregion
4341
4378
  export { httpMethodColor as A, intro as C, select as D, outro as E, writeFileSafe as F, severityColor as M, fileExists as N, spinner as O, setDryRun as P, confirm as S, multiSelect as T, pluralize as _, initProject as a, toKebabCase as b, generateKickJsSkills as c, generateService as d, generateGuard as f, resolveRepoType as g, generateModule as h, defineGenerator as i, pc as j, text as k, generateDto as l, generateAdapter as m, tryDispatchPluginGenerator as n, generateAgents as o, generateMiddleware as p, buildGeneratorContext as r, generateClaude as s, listPluginGenerators as t, generateController as u, pluralizePascal as v, log as w, toPascalCase as x, toCamelCase as y };
4342
4379
 
4343
- //# sourceMappingURL=generator-extension-CYY-RI21.mjs.map
4380
+ //# sourceMappingURL=generator-extension-C-HwKvFf.mjs.map