Pre-launch — Gluecron is in final validation. Public signups and git hosting for non-owner users open after launch review.
CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
Blame · Line-by-line history

install.ts

Each line is annotated with the commit that last touched it. Click any SHA to jump to that commit and see the surrounding change.

install.tsBlame59 lines · 1 contributor
46d6165Claude1/**
2 * Block L2 — one-command install.
3 *
4 * GET /install -> the bash installer (scripts/install.sh).
5 *
6 * Curl-able: `curl -sSL https://gluecron.com/install | bash`.
7 *
8 * The script is read from disk once at module load and cached in memory; we
9 * also serve it with `Cache-Control: public, max-age=300` so any CDN in front
10 * of us can absorb the load. Mirrors the static-string pattern used by
11 * `src/routes/pwa.ts`.
12 */
13
14import { Hono } from "hono";
15import { readFileSync } from "fs";
16import { join } from "path";
17
18const install = new Hono();
19
20// Resolve at module-load time. We try the on-disk script first; if anything
21// goes sideways (missing file in a stripped container image, weird CWD, etc.)
22// we fall back to a stub that points the user at the canonical URL so the
23// endpoint always returns *something* shell-safe.
24const FALLBACK_SCRIPT = `#!/usr/bin/env bash
25echo "Gluecron install script unavailable on this host." >&2
26echo "Fetch it directly from https://gluecron.com/install" >&2
27exit 1
28`;
29
30function loadScript(): string {
31 // Walk a few candidate locations so this works in dev, tests, and the
32 // fly.io container where CWD may be /app.
33 const candidates = [
34 join(process.cwd(), "scripts", "install.sh"),
35 join(import.meta.dir, "..", "..", "scripts", "install.sh"),
36 ];
37 for (const p of candidates) {
38 try {
39 const buf = readFileSync(p, "utf8");
40 if (buf && buf.length > 0) return buf;
41 } catch {
42 // try the next candidate
43 }
44 }
45 return FALLBACK_SCRIPT;
46}
47
48export const INSTALL_SCRIPT_SRC = loadScript();
49
50install.get("/install", (c) => {
51 c.header("content-type", "text/x-shellscript; charset=utf-8");
52 c.header("cache-control", "public, max-age=300");
53 // Make `curl https://gluecron.com/install -o install.sh` give a sensible
54 // default filename without forcing it for piped installs.
55 c.header("content-disposition", 'inline; filename="install.sh"');
56 return c.body(INSTALL_SCRIPT_SRC);
57});
58
59export default install;