kavoru 0.7.0 → 0.8.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.
- package/package.json +1 -1
- package/src/features.ts +57 -32
package/package.json
CHANGED
package/src/features.ts
CHANGED
|
@@ -108,7 +108,7 @@ const FEATURE_PATHS: Record<FeatureId, string[]> = {
|
|
|
108
108
|
],
|
|
109
109
|
resend: ["src/infra/resend"],
|
|
110
110
|
cron: ["src/schedules"],
|
|
111
|
-
docker: ["
|
|
111
|
+
docker: ["docker-compose.yaml", "docker"],
|
|
112
112
|
};
|
|
113
113
|
|
|
114
114
|
const FEATURE_DEPENDENCIES: Partial<
|
|
@@ -276,11 +276,14 @@ async function patchModulesIndex(
|
|
|
276
276
|
await writeText(projectDir, relativePath, content);
|
|
277
277
|
}
|
|
278
278
|
|
|
279
|
-
|
|
279
|
+
export function buildEntryIndex(selection: FeatureSelection): string {
|
|
280
280
|
const imports = [
|
|
281
281
|
selection.sentry
|
|
282
282
|
? 'import { initSentry, flushSentry } from "./infra/sentry";'
|
|
283
283
|
: null,
|
|
284
|
+
selection.otel
|
|
285
|
+
? 'import {\n bootstrapOpenTelemetry,\n shutdownOpenTelemetry,\n} from "./infra/telemetry";'
|
|
286
|
+
: null,
|
|
284
287
|
selection.kafka
|
|
285
288
|
? 'import { startKafka, stopKafka } from "./infra/kafka";'
|
|
286
289
|
: null,
|
|
@@ -291,8 +294,11 @@ async function patchEntryIndex(projectDir: string, selection: FeatureSelection)
|
|
|
291
294
|
|
|
292
295
|
const body: string[] = [];
|
|
293
296
|
|
|
297
|
+
if (selection.otel) {
|
|
298
|
+
body.push("", "bootstrapOpenTelemetry();");
|
|
299
|
+
}
|
|
294
300
|
if (selection.sentry) {
|
|
295
|
-
body.push("
|
|
301
|
+
body.push("initSentry();");
|
|
296
302
|
}
|
|
297
303
|
|
|
298
304
|
body.push("", "const server = new HttpServer();", "");
|
|
@@ -326,6 +332,9 @@ async function patchEntryIndex(projectDir: string, selection: FeatureSelection)
|
|
|
326
332
|
if (selection.sentry) {
|
|
327
333
|
body.push(" await flushSentry();");
|
|
328
334
|
}
|
|
335
|
+
if (selection.otel) {
|
|
336
|
+
body.push(" await shutdownOpenTelemetry();");
|
|
337
|
+
}
|
|
329
338
|
|
|
330
339
|
body.push(
|
|
331
340
|
" process.exit(0);",
|
|
@@ -337,7 +346,11 @@ async function patchEntryIndex(projectDir: string, selection: FeatureSelection)
|
|
|
337
346
|
"",
|
|
338
347
|
);
|
|
339
348
|
|
|
340
|
-
|
|
349
|
+
return [...imports, ...body].join("\n");
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
async function patchEntryIndex(projectDir: string, selection: FeatureSelection) {
|
|
353
|
+
await writeText(projectDir, "src/index.ts", buildEntryIndex(selection));
|
|
341
354
|
}
|
|
342
355
|
|
|
343
356
|
async function patchServerIndex(projectDir: string, selection: FeatureSelection) {
|
|
@@ -497,7 +510,7 @@ async function patchEnvExample(
|
|
|
497
510
|
async function patchDockerfile(projectDir: string, selection: FeatureSelection) {
|
|
498
511
|
if (!selection.docker) return;
|
|
499
512
|
|
|
500
|
-
const relativePath = "Dockerfile";
|
|
513
|
+
const relativePath = "docker/app/Dockerfile";
|
|
501
514
|
const current = await readText(projectDir, relativePath);
|
|
502
515
|
if (!current) return;
|
|
503
516
|
|
|
@@ -517,19 +530,21 @@ async function patchDockerfile(projectDir: string, selection: FeatureSelection)
|
|
|
517
530
|
await writeText(projectDir, relativePath, content);
|
|
518
531
|
}
|
|
519
532
|
|
|
520
|
-
function
|
|
521
|
-
const lines = [
|
|
533
|
+
function buildDockerAppEnv(selection: FeatureSelection): string {
|
|
534
|
+
const lines = [
|
|
535
|
+
"# Docker-only overrides (loaded after root .env)",
|
|
536
|
+
"NODE_ENV=production",
|
|
537
|
+
];
|
|
522
538
|
if (selection.kafka) {
|
|
523
|
-
lines.push("
|
|
539
|
+
lines.push("KAFKA_BROKERS=kafka:9092");
|
|
524
540
|
}
|
|
525
541
|
if (selection.otel) {
|
|
526
|
-
lines.push("
|
|
527
|
-
lines.push(" OTEL_SERVICE_NAME: ${OTEL_SERVICE_NAME:-kavoru}");
|
|
542
|
+
lines.push("OTEL_EXPORTER_OTLP_ENDPOINT=http://otel:4318/v1/traces");
|
|
528
543
|
}
|
|
529
544
|
if (selection.sentry) {
|
|
530
|
-
lines.push("
|
|
545
|
+
lines.push("SENTRY_SPOTLIGHT=http://spotlight:8969/stream");
|
|
531
546
|
}
|
|
532
|
-
return
|
|
547
|
+
return `${lines.join("\n")}\n`;
|
|
533
548
|
}
|
|
534
549
|
|
|
535
550
|
function generateDockerCompose(selection: FeatureSelection): string {
|
|
@@ -539,29 +554,17 @@ function generateDockerCompose(selection: FeatureSelection): string {
|
|
|
539
554
|
condition: service_started
|
|
540
555
|
`
|
|
541
556
|
: "";
|
|
542
|
-
const appEnvironment = buildAppEnvironment(selection);
|
|
543
557
|
|
|
544
558
|
const kafkaService = selection.kafka
|
|
545
559
|
? `
|
|
546
560
|
kafka:
|
|
547
|
-
|
|
561
|
+
build:
|
|
562
|
+
context: docker/kafka
|
|
548
563
|
hostname: kafka
|
|
549
564
|
ports:
|
|
550
565
|
- "9094:9094"
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
KAFKA_NODE_ID: "0"
|
|
554
|
-
KAFKA_PROCESS_ROLES: broker,controller
|
|
555
|
-
KAFKA_LISTENERS: PLAINTEXT://:9092,CONTROLLER://:9093,EXTERNAL://:9094
|
|
556
|
-
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,EXTERNAL://localhost:9094
|
|
557
|
-
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,EXTERNAL:PLAINTEXT
|
|
558
|
-
KAFKA_CONTROLLER_QUORUM_VOTERS: 0@kafka:9093
|
|
559
|
-
KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
|
|
560
|
-
KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
|
|
561
|
-
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
|
|
562
|
-
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
|
|
563
|
-
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
|
|
564
|
-
KAFKA_LOG_DIRS: /tmp/kraft-combined-logs
|
|
566
|
+
env_file:
|
|
567
|
+
- docker/kafka/.env
|
|
565
568
|
networks:
|
|
566
569
|
- app_network
|
|
567
570
|
restart: unless-stopped
|
|
@@ -572,10 +575,11 @@ function generateDockerCompose(selection: FeatureSelection): string {
|
|
|
572
575
|
? `
|
|
573
576
|
otel:
|
|
574
577
|
build:
|
|
575
|
-
context:
|
|
576
|
-
dockerfile: docker/otel.Dockerfile
|
|
578
|
+
context: docker/otel
|
|
577
579
|
ports:
|
|
578
580
|
- "4318:4318"
|
|
581
|
+
env_file:
|
|
582
|
+
- docker/otel/.env
|
|
579
583
|
networks:
|
|
580
584
|
- app_network
|
|
581
585
|
restart: unless-stopped
|
|
@@ -585,9 +589,12 @@ function generateDockerCompose(selection: FeatureSelection): string {
|
|
|
585
589
|
const spotlightService = selection.sentry
|
|
586
590
|
? `
|
|
587
591
|
spotlight:
|
|
588
|
-
|
|
592
|
+
build:
|
|
593
|
+
context: docker/spotlight
|
|
589
594
|
ports:
|
|
590
595
|
- "8969:8969"
|
|
596
|
+
env_file:
|
|
597
|
+
- docker/spotlight/.env
|
|
591
598
|
networks:
|
|
592
599
|
- app_network
|
|
593
600
|
restart: unless-stopped
|
|
@@ -598,6 +605,7 @@ function generateDockerCompose(selection: FeatureSelection): string {
|
|
|
598
605
|
app:
|
|
599
606
|
build:
|
|
600
607
|
context: .
|
|
608
|
+
dockerfile: docker/app/Dockerfile
|
|
601
609
|
target: build
|
|
602
610
|
args:
|
|
603
611
|
PORT: \${PORT:-3131}
|
|
@@ -615,7 +623,8 @@ function generateDockerCompose(selection: FeatureSelection): string {
|
|
|
615
623
|
restart: unless-stopped
|
|
616
624
|
env_file:
|
|
617
625
|
- .env
|
|
618
|
-
|
|
626
|
+
- docker/app/.env
|
|
627
|
+
${appDependsOn} healthcheck:
|
|
619
628
|
test: ["CMD", "curl", "-f", "http://localhost:\${PORT}/healthz"]
|
|
620
629
|
interval: 600s
|
|
621
630
|
timeout: 300s
|
|
@@ -633,6 +642,22 @@ async function patchDockerCompose(
|
|
|
633
642
|
selection: FeatureSelection,
|
|
634
643
|
) {
|
|
635
644
|
if (!selection.docker) return;
|
|
645
|
+
|
|
646
|
+
if (!selection.kafka) {
|
|
647
|
+
await removePaths(projectDir, ["docker/kafka"]);
|
|
648
|
+
}
|
|
649
|
+
if (!selection.otel) {
|
|
650
|
+
await removePaths(projectDir, ["docker/otel"]);
|
|
651
|
+
}
|
|
652
|
+
if (!selection.sentry) {
|
|
653
|
+
await removePaths(projectDir, ["docker/spotlight"]);
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
await writeText(
|
|
657
|
+
projectDir,
|
|
658
|
+
"docker/app/.env",
|
|
659
|
+
buildDockerAppEnv(selection),
|
|
660
|
+
);
|
|
636
661
|
await writeText(projectDir, "docker-compose.yaml", generateDockerCompose(selection));
|
|
637
662
|
}
|
|
638
663
|
|