@arcote.tech/arc-cli 0.7.5 → 0.7.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/dist/index.js +1614 -165
- package/package.json +22 -9
- package/src/builder/dependency-collector.ts +34 -1
- package/src/commands/platform-deploy.ts +16 -0
- package/src/deploy/bootstrap.ts +94 -2
- package/src/deploy/caddyfile.ts +45 -2
- package/src/deploy/compose.ts +147 -2
- package/src/deploy/config.ts +55 -0
- package/src/deploy/env-file.ts +14 -8
- package/src/deploy/htpasswd.ts +20 -0
- package/src/deploy/observability-configs.ts +958 -0
- package/src/platform/server.ts +65 -4
package/src/platform/server.ts
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
import { existsSync, mkdirSync } from "fs";
|
|
12
12
|
import { join } from "path";
|
|
13
13
|
import { readTranslationsConfig } from "../i18n";
|
|
14
|
-
import type
|
|
14
|
+
import { err, ok, type BuildManifest, type WorkspaceInfo } from "./shared";
|
|
15
15
|
import type { BuildManifestGroup, ModuleAccess } from "@arcote.tech/platform";
|
|
16
16
|
|
|
17
17
|
// ---------------------------------------------------------------------------
|
|
@@ -97,6 +97,21 @@ export function generateShellHtml(
|
|
|
97
97
|
initial?: { file: string; hash: string },
|
|
98
98
|
stylesHash?: string,
|
|
99
99
|
): string {
|
|
100
|
+
// OpenTelemetry config — injected as a global so the browser SDK chunk
|
|
101
|
+
// (lazy-loaded by start-app.ts) can pick it up without a fetch. Endpoint
|
|
102
|
+
// is same-origin so Caddy can apply CORS + auth uniformly.
|
|
103
|
+
const otelConfig = process.env.ARC_OTEL_ENABLED === "true"
|
|
104
|
+
? {
|
|
105
|
+
enabled: true,
|
|
106
|
+
endpoint: "/otel",
|
|
107
|
+
serviceName: process.env.OTEL_SERVICE_NAME ?? `${appName}-browser`,
|
|
108
|
+
environment: process.env.NODE_ENV === "production" ? "production" : "development",
|
|
109
|
+
sampleRate: Number(process.env.ARC_OTEL_BROWSER_SAMPLE_RATE ?? "0.1"),
|
|
110
|
+
}
|
|
111
|
+
: null;
|
|
112
|
+
const otelTag = otelConfig
|
|
113
|
+
? `\n <script>window.__ARC_OTEL_CONFIG=${JSON.stringify(otelConfig)};</script>`
|
|
114
|
+
: "";
|
|
100
115
|
// Initial bundle carries framework, public modules, and PlatformApp re-export.
|
|
101
116
|
// No importmap — single Bun.build with splitting:true inlines + dedups everything
|
|
102
117
|
// across initial and per-token group bundles via auto-emitted chunk-<hash>.js.
|
|
@@ -117,7 +132,7 @@ export function generateShellHtml(
|
|
|
117
132
|
<title>${manifest?.title ?? appName}</title>${manifest?.favicon ? `\n <link rel="icon" href="${manifest.favicon}">` : ""}${manifest ? `\n <link rel="manifest" href="/manifest.json">` : ""}
|
|
118
133
|
<link rel="stylesheet" href="/styles.css${stylesQs}" />
|
|
119
134
|
<link rel="stylesheet" href="/theme.css${stylesQs}" />
|
|
120
|
-
<link rel="modulepreload" href="${initialUrl}"
|
|
135
|
+
<link rel="modulepreload" href="${initialUrl}" />${otelTag}
|
|
121
136
|
</head>
|
|
122
137
|
<body>
|
|
123
138
|
<div id="root"></div>
|
|
@@ -480,6 +495,30 @@ export async function startPlatformServer(
|
|
|
480
495
|
): Promise<PlatformServer> {
|
|
481
496
|
const { ws, port, devMode, context } = opts;
|
|
482
497
|
ensureModuleSigSecret(ws, !!devMode);
|
|
498
|
+
|
|
499
|
+
// OpenTelemetry — only when explicitly enabled (deploy injects the env
|
|
500
|
+
// when `observability.enabled` is set in deploy.arc.json). Dynamic import
|
|
501
|
+
// keeps the OTel SDK out of bundles that don't use it.
|
|
502
|
+
let telemetry: import("@arcote.tech/arc-otel").ArcTelemetry | undefined;
|
|
503
|
+
let telemetryShutdown: (() => Promise<void>) | undefined;
|
|
504
|
+
if (process.env.ARC_OTEL_ENABLED === "true") {
|
|
505
|
+
try {
|
|
506
|
+
const { initServerTelemetry } = await import("@arcote.tech/arc-otel/server");
|
|
507
|
+
const init = initServerTelemetry({
|
|
508
|
+
serviceName: process.env.OTEL_SERVICE_NAME ?? ws.appName,
|
|
509
|
+
environment: "server",
|
|
510
|
+
endpoint: process.env.OTEL_EXPORTER_OTLP_ENDPOINT,
|
|
511
|
+
mode: devMode ? "development" : "production",
|
|
512
|
+
sampleRate: devMode ? 1.0 : 1.0, // head-based 100%, collector tail-samples
|
|
513
|
+
});
|
|
514
|
+
telemetry = init.telemetry;
|
|
515
|
+
telemetryShutdown = init.shutdown;
|
|
516
|
+
ok("Telemetry enabled — exporting to " + process.env.OTEL_EXPORTER_OTLP_ENDPOINT);
|
|
517
|
+
} catch (e) {
|
|
518
|
+
err(`Failed to init telemetry: ${(e as Error).message}`);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
483
522
|
const moduleAccessMap = opts.moduleAccess ?? new Map();
|
|
484
523
|
let manifest = opts.manifest;
|
|
485
524
|
const getManifest = () => manifest;
|
|
@@ -561,7 +600,25 @@ export async function startPlatformServer(
|
|
|
561
600
|
// Context available — use createArcServer with platform handlers on top.
|
|
562
601
|
// `resolveDbAdapterFactory` picks SQLite or Postgres based on DATABASE_URL.
|
|
563
602
|
const dbPath = opts.dbPath || join(ws.arcDir, "data", "arc.db");
|
|
564
|
-
const
|
|
603
|
+
const baseDbFactory = await resolveDbAdapterFactory(dbPath);
|
|
604
|
+
|
|
605
|
+
// Wrap the DB adapter for per-transaction spans when telemetry is on.
|
|
606
|
+
// Done here (not in arc-host) so arc-host stays free of arc-otel runtime
|
|
607
|
+
// imports — duplicate @opentelemetry/api copies silently drop spans.
|
|
608
|
+
let dbAdapterFactory = baseDbFactory;
|
|
609
|
+
if (telemetry) {
|
|
610
|
+
// Pull wrapDbAdapter from `/server` (not the root export) so Bun
|
|
611
|
+
// doesn't double-bundle arc-otel for the CLI bundle. Both /server
|
|
612
|
+
// and / share telemetry.ts but split bundling otherwise.
|
|
613
|
+
const { wrapDbAdapter } = await import("@arcote.tech/arc-otel/server");
|
|
614
|
+
const dbSystem: "postgresql" | "sqlite" = process.env.DATABASE_URL
|
|
615
|
+
? "postgresql"
|
|
616
|
+
: "sqlite";
|
|
617
|
+
dbAdapterFactory = async (ctx: any) => {
|
|
618
|
+
const a = await baseDbFactory(ctx);
|
|
619
|
+
return wrapDbAdapter(a, telemetry, dbSystem);
|
|
620
|
+
};
|
|
621
|
+
}
|
|
565
622
|
|
|
566
623
|
const arcServer = await createArcServer({
|
|
567
624
|
context,
|
|
@@ -575,6 +632,7 @@ export async function startPlatformServer(
|
|
|
575
632
|
spaFallbackHandler(getShellHtml),
|
|
576
633
|
],
|
|
577
634
|
onWsClose: (clientId) => cleanupClientSubs(clientId),
|
|
635
|
+
telemetry,
|
|
578
636
|
});
|
|
579
637
|
|
|
580
638
|
return {
|
|
@@ -583,6 +641,9 @@ export async function startPlatformServer(
|
|
|
583
641
|
connectionManager: arcServer.connectionManager,
|
|
584
642
|
setManifest,
|
|
585
643
|
notifyReload,
|
|
586
|
-
stop: () =>
|
|
644
|
+
stop: () => {
|
|
645
|
+
arcServer.stop();
|
|
646
|
+
void telemetryShutdown?.();
|
|
647
|
+
},
|
|
587
648
|
};
|
|
588
649
|
}
|