summaryrefslogtreecommitdiffhomepage
path: root/packages
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-06-21 20:26:39 +0900
committerAdam Malczewski <[email protected]>2026-06-21 20:26:39 +0900
commit4434fbf951d06a721597e805094069477851178e (patch)
tree4d3103ccb0512ff77d9d472d7b4178c11c8b73b3 /packages
parentac69e5f8bea9377887a6f89ff362c6be0db1c874 (diff)
downloaddispatch-4434fbf951d06a721597e805094069477851178e.tar.gz
dispatch-4434fbf951d06a721597e805094069477851178e.zip
feat: standalone build + systemd install (Arch Linux)
bin/build: compiles standalone binaries (dispatch-server + dispatch CLI) via bun build --compile, builds the frontend static bundle with VITE_HTTP_PORT=24991 + VITE_WS_PORT=24990, copies to dist/web/. bin/install: installs binaries to /usr/bin/, frontend to /usr/share/dispatch/web/, systemd service to /etc/systemd/system/, config to /etc/dispatch/env, data dirs to /var/lib/dispatch/ + /var/log/dispatch/. Enables + starts the dispatch systemd service. Supports --uninstall and --no-build flags. systemd/dispatch.service: Type=simple, reads /etc/dispatch/env, restarts on failure, logs to journald. systemd/dispatch.env: template config (ports 24991 HTTP + 24990 WS, DISPATCH_WEB_DIR, API key, data paths). transport-http: optional webDir static file serving — unmatched GET requests fall through to Bun.file() serving with SPA index.html fallback. Gated on DISPATCH_WEB_DIR env var (backward compatible).
Diffstat (limited to 'packages')
-rw-r--r--packages/transport-http/src/app.ts27
-rw-r--r--packages/transport-http/src/extension.ts3
2 files changed, 30 insertions, 0 deletions
diff --git a/packages/transport-http/src/app.ts b/packages/transport-http/src/app.ts
index 86bac0d..9e4fc8a 100644
--- a/packages/transport-http/src/app.ts
+++ b/packages/transport-http/src/app.ts
@@ -64,6 +64,12 @@ export interface CreateServerOptions {
* that endpoint responds `500 { error: "not available" }`.
*/
readonly emit?: HostAPI["emit"];
+ /**
+ * Directory containing built frontend static files. When set, unmatched GET
+ * requests fall through to static file serving (SPA fallback to index.html).
+ * When absent, no static serving (API-only — backward compatible).
+ */
+ readonly webDir?: string;
}
const noopLogger: Logger = {
@@ -669,5 +675,26 @@ export function createApp(opts: CreateServerOptions): Hono {
}
});
+ // ─── Static frontend serving (catch-all, API routes take precedence) ──────
+ if (opts.webDir !== undefined) {
+ const webDir = opts.webDir;
+ app.get("*", async (c) => {
+ const urlPath = new URL(c.req.url).pathname;
+ const filePath = `${webDir}${urlPath}`;
+ const file = Bun.file(filePath);
+ if (await file.exists()) {
+ return new Response(file);
+ }
+ // SPA fallback: serve index.html for client-side routing
+ const indexFile = Bun.file(`${webDir}/index.html`);
+ if (await indexFile.exists()) {
+ return new Response(indexFile, {
+ headers: { "Content-Type": "text/html; charset=utf-8" },
+ });
+ }
+ return c.json({ error: "Not found" }, 404);
+ });
+ }
+
return app;
}
diff --git a/packages/transport-http/src/extension.ts b/packages/transport-http/src/extension.ts
index e402213..3555f8e 100644
--- a/packages/transport-http/src/extension.ts
+++ b/packages/transport-http/src/extension.ts
@@ -73,6 +73,9 @@ export function createTransportHttpExtension(): Extension & {
lspService,
logger,
emit: host.emit.bind(host),
+ ...(process.env.DISPATCH_WEB_DIR !== undefined
+ ? { webDir: process.env.DISPATCH_WEB_DIR }
+ : {}),
});
const port = host.config.get<number>("httpPort") ?? 24203;