kavoru 0.9.6 → 0.9.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -38,7 +38,7 @@ bunx kavoru@latest my-api
38
38
  | `--no-install` | Skip `bun install` |
39
39
  | `--repo owner/name` | Override template repo (default: `mertthesamael/Kavoru`) |
40
40
  | `--branch name` | Template branch (default: `master`) |
41
- | `--minimal` | Core only health, OpenAPI, response envelope |
41
+ | `--minimal` | Optional integrations off (Docker Compose + Project CLI always included) |
42
42
  | `--features list` | Comma-separated features to include |
43
43
  | `--no-features list`| Comma-separated features to exclude (default: all on) |
44
44
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kavoru",
3
- "version": "0.9.6",
3
+ "version": "0.9.8",
4
4
  "description": "Scaffold a new Kavoru (Elysia + Bun) backend from the official template",
5
5
  "type": "module",
6
6
  "bin": {
package/src/args.ts CHANGED
@@ -32,7 +32,7 @@ Options:
32
32
  --no-install Skip "bun install" after scaffolding
33
33
  --repo <owner/name> GitHub template repo (default: mertthesamael/Kavoru)
34
34
  --branch <name> Template branch (default: master)
35
- --minimal Core only (health, OpenAPI, response envelope)
35
+ --minimal Core optional integrations only (Docker + Project CLI always included)
36
36
  --features <list> Comma-separated features to include (default: all)
37
37
  --no-features <list> Comma-separated features to exclude
38
38
 
package/src/features.ts CHANGED
@@ -17,6 +17,19 @@ export type FeatureId =
17
17
  /** Always scaffolded — not a CLI toggle. */
18
18
  export const ALWAYS_INCLUDED = ["docker", "cli"] as const;
19
19
 
20
+ export const MANDATORY_FEATURE_DEFS = [
21
+ {
22
+ id: "docker",
23
+ label: "Docker Compose",
24
+ description: "docker-compose.yaml + app image",
25
+ },
26
+ {
27
+ id: "cli",
28
+ label: "Project CLI",
29
+ description: "kavoru module command, bin, shims",
30
+ },
31
+ ] as const;
32
+
20
33
  const FEATURE_ALIASES: Record<string, FeatureId> = {
21
34
  prisma: "postgres",
22
35
  };
@@ -288,9 +301,12 @@ export function parseFeatureExcludeList(
288
301
  }
289
302
 
290
303
  export function formatFeatureSelection(selection: FeatureSelection): string {
304
+ const mandatory = ALWAYS_INCLUDED.join(", ");
291
305
  const enabled = enabledFeatures(selection);
292
- if (enabled.length === 0) return "core only";
293
- return enabled.join(", ");
306
+ if (enabled.length === 0) {
307
+ return `${mandatory} · optional: none`;
308
+ }
309
+ return `${mandatory} · optional: ${enabled.join(", ")}`;
294
310
  }
295
311
 
296
312
  async function removePaths(projectDir: string, relativePaths: string[]) {
@@ -316,6 +332,31 @@ async function writeText(
316
332
  await Bun.write(path.join(projectDir, relativePath), content);
317
333
  }
318
334
 
335
+ export async function regenerateRouteRegistry(projectDir: string): Promise<void> {
336
+ const modulesDir = path.join(projectDir, "src/modules");
337
+ const glob = new Bun.Glob("*/routes.ts");
338
+ const files = [...glob.scanSync(modulesDir)]
339
+ .map((file) => file.replaceAll("\\", "/"))
340
+ .sort();
341
+
342
+ const imports = files
343
+ .map((file, index) => {
344
+ const modulePath = `./${file.replace(/\.ts$/, "")}`;
345
+ return `import * as route${index} from "${modulePath}";`;
346
+ })
347
+ .join("\n");
348
+
349
+ const registry = files.map((_, index) => `route${index}`).join(", ");
350
+
351
+ const content = `// Auto-generated by scripts/generate-route-registry.ts — do not edit
352
+ ${imports}
353
+
354
+ export const routeModules = [${registry}];
355
+ `;
356
+
357
+ await writeText(projectDir, "src/modules/routes.registry.ts", content);
358
+ }
359
+
319
360
  function removeImportLines(content: string, modules: string[]) {
320
361
  let next = content;
321
362
  for (const modulePath of modules) {
@@ -1010,6 +1051,8 @@ export async function applyFeatures(
1010
1051
  await removePaths(projectDir, FEATURE_PATHS[featureId]);
1011
1052
  }
1012
1053
 
1054
+ await regenerateRouteRegistry(projectDir);
1055
+
1013
1056
  await patchModulesIndex(projectDir, selection);
1014
1057
  await patchEntryIndex(projectDir, selection);
1015
1058
  await patchServerIndex(projectDir, selection);
package/src/prompts.ts CHANGED
@@ -2,6 +2,7 @@ import { stdin, stdout } from "node:process";
2
2
  import {
3
3
  ALL_FEATURES,
4
4
  FEATURES,
5
+ MANDATORY_FEATURE_DEFS,
5
6
  MINIMAL_FEATURES,
6
7
  normalizeFeatureSelection,
7
8
  type FeatureId,
@@ -84,10 +85,19 @@ function renderCheckboxMenu(
84
85
  ): number {
85
86
  const lines: string[] = [
86
87
  `${cyan}◆${reset} Select optional features ${dim}(↑↓ move · Space toggle · Enter confirm)${reset}`,
87
- `${dim} a = all · m = minimal${reset}`,
88
+ `${dim} a = all · m = minimal optional only${reset}`,
88
89
  "",
90
+ `${dim}Always included:${reset}`,
89
91
  ];
90
92
 
93
+ for (const feature of MANDATORY_FEATURE_DEFS) {
94
+ lines.push(
95
+ ` [x] ${feature.label.padEnd(22)} ${dim}${feature.description}${reset}`,
96
+ );
97
+ }
98
+
99
+ lines.push("", `${dim}Optional:${reset}`);
100
+
91
101
  FEATURES.forEach((feature, index) => {
92
102
  const isActive = index === activeIndex;
93
103
  const pointer = isActive ? `${cyan}❯${reset}` : " ";