kavoru 0.9.5 → 0.9.7
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 +2 -3
- package/package.json +1 -1
- package/src/args.ts +3 -3
- package/src/cli.ts +6 -10
- package/src/features.ts +41 -46
- package/src/module-cli.ts +1 -1
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ docker compose up --build
|
|
|
14
14
|
|
|
15
15
|
Always use `@latest` so you get the newest published CLI. Equivalent to `bunx --bun kavoru@latest`.
|
|
16
16
|
|
|
17
|
-
Every scaffold includes **Docker Compose** (`docker-compose.yaml` + `docker/app/`). Infra services (Postgres, Kafka, Redis, OTEL, Spotlight) are added when you select those features — the app service is always present.
|
|
17
|
+
Every scaffold includes **Docker Compose** (`docker-compose.yaml` + `docker/app/`) and the **Project CLI** (`kavoru module`, bin, root shims). Infra services (Postgres, Kafka, Redis, Llama, OTEL, Spotlight) are added when you select those features — the app service is always present.
|
|
18
18
|
|
|
19
19
|
**Stale CLI after a new publish?** Bun caches `bunx` installs under `%TEMP%\bunx-*-kavoru@latest` and does not auto-refresh. Clear the cache, then run `@latest` again:
|
|
20
20
|
|
|
@@ -44,7 +44,7 @@ bunx kavoru@latest my-api
|
|
|
44
44
|
|
|
45
45
|
### Optional features
|
|
46
46
|
|
|
47
|
-
During setup you can pick which integrations to scaffold. **Docker Compose
|
|
47
|
+
During setup you can pick which integrations to scaffold. **Docker Compose** and **Project CLI** are always included. Core is always included: health routes, OpenAPI at `/help`, CORS, and the JSON response envelope.
|
|
48
48
|
|
|
49
49
|
| ID | Feature |
|
|
50
50
|
| ----------- | ---------------------- |
|
|
@@ -57,7 +57,6 @@ During setup you can pick which integrations to scaffold. **Docker Compose is al
|
|
|
57
57
|
| `websocket` | WebSocket realtime |
|
|
58
58
|
| `resend` | Resend email |
|
|
59
59
|
| `cron` | Cron jobs |
|
|
60
|
-
| `cli` | Project CLI (`kavoru module`, bin, root shims) |
|
|
61
60
|
|
|
62
61
|
Interactive mode (TTY) shows a checkbox menu (↑↓ move, Space toggle, Enter confirm). Non-interactive runs use the full stack unless you pass flags.
|
|
63
62
|
|
package/package.json
CHANGED
package/src/args.ts
CHANGED
|
@@ -37,9 +37,9 @@ Options:
|
|
|
37
37
|
--no-features <list> Comma-separated features to exclude
|
|
38
38
|
|
|
39
39
|
Features:
|
|
40
|
-
auth, postgres, otel, sentry, kafka, redis, llama, websocket, resend, cron
|
|
41
|
-
(prisma is accepted as an alias for postgres
|
|
42
|
-
Docker Compose
|
|
40
|
+
auth, postgres, otel, sentry, kafka, redis, llama, websocket, resend, cron
|
|
41
|
+
(prisma is accepted as an alias for postgres)
|
|
42
|
+
Docker Compose and Project CLI are always included — not toggles.
|
|
43
43
|
|
|
44
44
|
Examples:
|
|
45
45
|
bunx kavoru@latest my-api
|
package/src/cli.ts
CHANGED
|
@@ -137,9 +137,7 @@ export async function runCli(options: CliOptions): Promise<void> {
|
|
|
137
137
|
|
|
138
138
|
if (options.install) {
|
|
139
139
|
await installDependencies(targetDir);
|
|
140
|
-
|
|
141
|
-
await linkProjectCli(targetDir);
|
|
142
|
-
}
|
|
140
|
+
await linkProjectCli(targetDir);
|
|
143
141
|
}
|
|
144
142
|
} finally {
|
|
145
143
|
await rm(tempDir, { recursive: true, force: true }).catch(() => undefined);
|
|
@@ -154,14 +152,12 @@ export async function runCli(options: CliOptions): Promise<void> {
|
|
|
154
152
|
if (!options.install) {
|
|
155
153
|
console.log(" bun install");
|
|
156
154
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
console.log(" bun run link-cli # bare kavoru on PATH (~/.bun/bin)");
|
|
162
|
-
}
|
|
163
|
-
console.log(" bunx kavoru@latest module <name> # works without PATH setup");
|
|
155
|
+
console.log(" ./kavoru module <name> # Git Bash / macOS / Linux");
|
|
156
|
+
console.log(" .\\kavoru.cmd module <name> # Windows cmd / PowerShell");
|
|
157
|
+
if (!options.install) {
|
|
158
|
+
console.log(" bun run link-cli # bare kavoru on PATH (~/.bun/bin)");
|
|
164
159
|
}
|
|
160
|
+
console.log(" bunx kavoru@latest module <name> # works without PATH setup");
|
|
165
161
|
console.log(" bunx kavoru@latest <dir> # scaffold another project");
|
|
166
162
|
console.log(" bun run dev");
|
|
167
163
|
console.log();
|
package/src/features.ts
CHANGED
|
@@ -12,15 +12,13 @@ export type FeatureId =
|
|
|
12
12
|
| "llama"
|
|
13
13
|
| "websocket"
|
|
14
14
|
| "resend"
|
|
15
|
-
| "cron"
|
|
16
|
-
| "cli";
|
|
15
|
+
| "cron";
|
|
17
16
|
|
|
18
17
|
/** Always scaffolded — not a CLI toggle. */
|
|
19
|
-
export const ALWAYS_INCLUDED = ["docker"] as const;
|
|
18
|
+
export const ALWAYS_INCLUDED = ["docker", "cli"] as const;
|
|
20
19
|
|
|
21
20
|
const FEATURE_ALIASES: Record<string, FeatureId> = {
|
|
22
21
|
prisma: "postgres",
|
|
23
|
-
"kavoru-cli": "cli",
|
|
24
22
|
};
|
|
25
23
|
|
|
26
24
|
export type FeatureSelection = Record<FeatureId, boolean>;
|
|
@@ -82,11 +80,6 @@ export const FEATURES: FeatureDef[] = [
|
|
|
82
80
|
label: "Cron Jobs",
|
|
83
81
|
description: "Scheduled tasks via @elysiajs/cron",
|
|
84
82
|
},
|
|
85
|
-
{
|
|
86
|
-
id: "cli",
|
|
87
|
-
label: "Project CLI",
|
|
88
|
-
description: "kavoru module command, bin, and module scaffolds",
|
|
89
|
-
},
|
|
90
83
|
];
|
|
91
84
|
|
|
92
85
|
export const FEATURE_IDS = FEATURES.map((feature) => feature.id);
|
|
@@ -140,19 +133,6 @@ const FEATURE_PATHS: Record<FeatureId, string[]> = {
|
|
|
140
133
|
],
|
|
141
134
|
resend: ["src/infra/resend"],
|
|
142
135
|
cron: ["src/schedules"],
|
|
143
|
-
cli: [
|
|
144
|
-
"bin/kavoru.js",
|
|
145
|
-
"kavoru",
|
|
146
|
-
"kavoru.cmd",
|
|
147
|
-
"scripts/kavoru-cli.ts",
|
|
148
|
-
"scripts/generate-module.ts",
|
|
149
|
-
"scripts/generate-repository.ts",
|
|
150
|
-
"scripts/link-cli.ts",
|
|
151
|
-
"__tests__/generate-module.test.ts",
|
|
152
|
-
"__tests__/generate-repository.test.ts",
|
|
153
|
-
"__tests__/kavoru-cli.test.ts",
|
|
154
|
-
"__tests__/link-cli.test.ts",
|
|
155
|
-
],
|
|
156
136
|
};
|
|
157
137
|
|
|
158
138
|
const FEATURE_DEPENDENCIES: Partial<
|
|
@@ -182,7 +162,6 @@ const FEATURE_SCRIPTS: Partial<Record<FeatureId, string[]>> = {
|
|
|
182
162
|
otel: ["otel:view", "otel:tui"],
|
|
183
163
|
sentry: ["sentry:spotlight"],
|
|
184
164
|
postgres: ["seed"],
|
|
185
|
-
cli: ["link-cli"],
|
|
186
165
|
};
|
|
187
166
|
|
|
188
167
|
function resolveFeatureId(raw: string): FeatureId | null {
|
|
@@ -222,15 +201,20 @@ export function normalizeFeatureSelection(
|
|
|
222
201
|
return { ...selection };
|
|
223
202
|
}
|
|
224
203
|
|
|
225
|
-
function
|
|
226
|
-
const
|
|
227
|
-
|
|
204
|
+
function isAlwaysIncludedFeature(raw: string): boolean {
|
|
205
|
+
const normalized = raw === "kavoru-cli" ? "cli" : raw;
|
|
206
|
+
return ALWAYS_INCLUDED.includes(
|
|
207
|
+
normalized as (typeof ALWAYS_INCLUDED)[number],
|
|
228
208
|
);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function rejectReservedFeatureToggle(parts: string[], action: "include" | "exclude") {
|
|
212
|
+
const reserved = parts.filter((part) => isAlwaysIncludedFeature(part));
|
|
229
213
|
if (reserved.length === 0) return;
|
|
230
214
|
|
|
231
215
|
const verb = action === "exclude" ? "disable" : "toggle";
|
|
232
216
|
throw new Error(
|
|
233
|
-
`Docker
|
|
217
|
+
`Docker and Project CLI are always included and cannot be ${verb}. Omit "docker", "cli", or "kavoru-cli" from --features / --no-features.`,
|
|
234
218
|
);
|
|
235
219
|
}
|
|
236
220
|
|
|
@@ -332,6 +316,31 @@ async function writeText(
|
|
|
332
316
|
await Bun.write(path.join(projectDir, relativePath), content);
|
|
333
317
|
}
|
|
334
318
|
|
|
319
|
+
export async function regenerateRouteRegistry(projectDir: string): Promise<void> {
|
|
320
|
+
const modulesDir = path.join(projectDir, "src/modules");
|
|
321
|
+
const glob = new Bun.Glob("*/routes.ts");
|
|
322
|
+
const files = [...glob.scanSync(modulesDir)]
|
|
323
|
+
.map((file) => file.replaceAll("\\", "/"))
|
|
324
|
+
.sort();
|
|
325
|
+
|
|
326
|
+
const imports = files
|
|
327
|
+
.map((file, index) => {
|
|
328
|
+
const modulePath = `./${file.replace(/\.ts$/, "")}`;
|
|
329
|
+
return `import * as route${index} from "${modulePath}";`;
|
|
330
|
+
})
|
|
331
|
+
.join("\n");
|
|
332
|
+
|
|
333
|
+
const registry = files.map((_, index) => `route${index}`).join(", ");
|
|
334
|
+
|
|
335
|
+
const content = `// Auto-generated by scripts/generate-route-registry.ts — do not edit
|
|
336
|
+
${imports}
|
|
337
|
+
|
|
338
|
+
export const routeModules = [${registry}];
|
|
339
|
+
`;
|
|
340
|
+
|
|
341
|
+
await writeText(projectDir, "src/modules/routes.registry.ts", content);
|
|
342
|
+
}
|
|
343
|
+
|
|
335
344
|
function removeImportLines(content: string, modules: string[]) {
|
|
336
345
|
let next = content;
|
|
337
346
|
for (const modulePath of modules) {
|
|
@@ -547,16 +556,9 @@ async function patchPackageJson(
|
|
|
547
556
|
pkg.scripts.start = "bun run src/index.ts";
|
|
548
557
|
}
|
|
549
558
|
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
delete pkg.scripts.postinstall;
|
|
554
|
-
}
|
|
555
|
-
} else {
|
|
556
|
-
pkg.bin = { kavoru: "./bin/kavoru.js" };
|
|
557
|
-
pkg.scripts ??= {};
|
|
558
|
-
pkg.scripts.postinstall = "bun scripts/link-cli.ts";
|
|
559
|
-
}
|
|
559
|
+
pkg.bin = { kavoru: "./bin/kavoru.js" };
|
|
560
|
+
pkg.scripts ??= {};
|
|
561
|
+
pkg.scripts.postinstall = "bun scripts/link-cli.ts";
|
|
560
562
|
|
|
561
563
|
await Bun.write(pkgPath, `${JSON.stringify(pkg, null, 2)}\n`);
|
|
562
564
|
}
|
|
@@ -692,15 +694,6 @@ async function patchDockerfile(
|
|
|
692
694
|
);
|
|
693
695
|
}
|
|
694
696
|
|
|
695
|
-
if (!selection.cli) {
|
|
696
|
-
content = content.replace(/^COPY bin \.\/bin\n/m, "");
|
|
697
|
-
content = content.replace(
|
|
698
|
-
/^COPY scripts\/link-cli\.ts \.\/scripts\/link-cli\.ts\n/m,
|
|
699
|
-
"",
|
|
700
|
-
);
|
|
701
|
-
content = content.replace(/^ENV PATH="\/root\/\.bun\/bin:\$\{PATH\}"\n/m, "");
|
|
702
|
-
}
|
|
703
|
-
|
|
704
697
|
await writeText(projectDir, relativePath, content);
|
|
705
698
|
}
|
|
706
699
|
|
|
@@ -1042,6 +1035,8 @@ export async function applyFeatures(
|
|
|
1042
1035
|
await removePaths(projectDir, FEATURE_PATHS[featureId]);
|
|
1043
1036
|
}
|
|
1044
1037
|
|
|
1038
|
+
await regenerateRouteRegistry(projectDir);
|
|
1039
|
+
|
|
1045
1040
|
await patchModulesIndex(projectDir, selection);
|
|
1046
1041
|
await patchEntryIndex(projectDir, selection);
|
|
1047
1042
|
await patchServerIndex(projectDir, selection);
|
package/src/module-cli.ts
CHANGED
|
@@ -30,7 +30,7 @@ function findProjectRoot(cwd: string): string {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
throw new Error(
|
|
33
|
-
"Could not find a Kavoru project
|
|
33
|
+
"Could not find a Kavoru project. Run from a scaffolded project root that includes scripts/kavoru-cli.ts.",
|
|
34
34
|
);
|
|
35
35
|
}
|
|
36
36
|
|