Diffinery

codician/diffinerypublic

Open-source, agent-first GitHub and GitHub Actions alternative that runs on your own Cloudflare account: git hosting, pull requests, code review and drop-in GitHub Actions YAML on Workers, Durable Objects, R2 and Containers.

55 lines · 2.7 KB · executableRaw History
1#!/usr/bin/env node
2// Render apps/diffinery/wrangler.deploy.jsonc from wrangler.jsonc plus values
3// discovered by scripts/bootstrap.sh (real D1 id, Access team domain and AUD).
4//
5// node scripts/render-config.mjs --d1 <uuid> [--team <x.cloudflareaccess.com>] [--aud <tag>]
6// [--public-url https://git.example.com] [--zone example.com] [--mail-from notifications@example.com]
7//
8// --public-url also points the Worker's route at that host (in --zone, by default
9// the host's last two labels) and sends email from notifications@<host>.
10import { readFileSync, writeFileSync } from "node:fs";
11import { dirname, join } from "node:path";
12import { fileURLToPath } from "node:url";
13import { parseArgs } from "node:util";
14
15const { values } = parseArgs({ options: { d1: { type: "string" }, team: { type: "string" }, aud: { type: "string" }, "public-url": { type: "string" }, zone: { type: "string" }, "mail-from": { type: "string" } } });
16if (!values.d1) throw new Error("--d1 <database id> is required");
17
18/** Strip // and /* *\/ comments and trailing commas from JSONC, leaving strings intact. */
19export function parseJsonc(text) {
20 let out = "";
21 for (let i = 0; i < text.length; i++) {
22 const ch = text[i];
23 if (ch === '"') {
24 let j = i + 1;
25 while (j < text.length && text[j] !== '"') j += text[j] === "\\" ? 2 : 1;
26 out += text.slice(i, j + 1);
27 i = j;
28 } else if (ch === "/" && text[i + 1] === "/") {
29 while (i < text.length && text[i] !== "\n") i++;
30 out += "\n";
31 } else if (ch === "/" && text[i + 1] === "*") {
32 i = text.indexOf("*/", i + 2) + 1;
33 } else out += ch;
34 }
35 return JSON.parse(out.replace(/,(\s*[}\]])/g, "$1"));
36}
37
38const appDir = join(dirname(fileURLToPath(import.meta.url)), "..", "apps", "diffinery");
39const cfg = parseJsonc(readFileSync(join(appDir, "wrangler.jsonc"), "utf8"));
40delete cfg.env;
41delete cfg.$schema;
42cfg.d1_databases[0].database_id = values.d1;
43if (values.team) cfg.vars.ACCESS_TEAM_DOMAIN = values.team;
44if (values.aud) cfg.vars.ACCESS_AUD = values.aud;
45if (values["public-url"]) {
46 const url = new URL(values["public-url"]);
47 if (url.protocol !== "https:" || url.pathname !== "/") throw new Error("--public-url must be an https origin, like https://git.example.com");
48 cfg.vars.PUBLIC_URL = url.origin;
49 const zone = values.zone ?? url.hostname.split(".").slice(-2).join(".");
50 cfg.routes = [{ pattern: `${url.hostname}/*`, zone_name: zone }];
51 cfg.vars.MAIL_FROM = `notifications@${url.hostname}`;
52}
53if (values["mail-from"]) cfg.vars.MAIL_FROM = values["mail-from"];
54writeFileSync(join(appDir, "wrangler.deploy.jsonc"), `// Generated by scripts/render-config.mjs; do not edit.\n${JSON.stringify(cfg, null, 2)}\n`);
55console.log(`wrote ${join(appDir, "wrangler.deploy.jsonc")}`);