mirror of
https://github.com/saltbo/agent-kanban.git
synced 2026-09-19 09:01:47 +08:00
7ed77d2295
* fix: harden v2 service boundaries * fix(sessions): validate observation configuration first --------- Co-authored-by: jarvis <jarvis@agents.realmroot.dev>
61 lines
2.6 KiB
TypeScript
61 lines
2.6 KiB
TypeScript
// @vitest-environment node
|
|
|
|
import { readFileSync } from "node:fs";
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
const config = readFileSync(new URL("../wrangler.toml", import.meta.url), "utf8");
|
|
|
|
function tableBody(header: string): string {
|
|
const start = config.indexOf(header);
|
|
if (start === -1) throw new Error(`Missing wrangler table ${header}`);
|
|
const bodyStart = start + header.length;
|
|
const rest = config.slice(bodyStart);
|
|
const nextTable = rest.search(/^\s*\[/m);
|
|
return nextTable === -1 ? rest : rest.slice(0, nextTable);
|
|
}
|
|
|
|
function stringValue(body: string, key: string): string | null {
|
|
return body.match(new RegExp(`^${key}\\s*=\\s*"([^"]+)"`, "m"))?.[1] ?? null;
|
|
}
|
|
|
|
function stringArrayValue(body: string, key: string): string[] | null {
|
|
const raw = body.match(new RegExp(`^${key}\\s*=\\s*\\[([^\\]]*)\\]`, "m"))?.[1];
|
|
return raw === undefined ? null : [...raw.matchAll(/"([^"]+)"/g)].map((match) => match[1]);
|
|
}
|
|
|
|
describe("production wrangler configuration", () => {
|
|
it("routes the canonical API resource and its descendants to the Worker before SPA assets", () => {
|
|
const workerFirst = stringArrayValue(tableBody("[assets]"), "run_worker_first");
|
|
|
|
expect(workerFirst).toEqual(expect.arrayContaining(["/api", "/api/*"]));
|
|
expect(workerFirst?.filter((pattern) => pattern === "/api")).toHaveLength(1);
|
|
});
|
|
|
|
it("deploys only the canonical route without cron", () => {
|
|
const productionConfig = config.split("[env.staging]", 1)[0];
|
|
const routes = [...productionConfig.matchAll(/^\[\[routes\]\]\s*\n([\s\S]*?)(?=^\s*\[|(?![\s\S]))/gm)].map((match) => ({
|
|
pattern: stringValue(match[1], "pattern"),
|
|
zoneName: stringValue(match[1], "zone_name"),
|
|
customDomain: match[1].match(/^custom_domain\s*=\s*(true|false)/m)?.[1] === "true",
|
|
}));
|
|
|
|
expect(routes).toEqual([{ pattern: "agent-kanban.dev", zoneName: null, customDomain: true }]);
|
|
expect(productionConfig).not.toContain("ak.tftt.cc");
|
|
expect(stringArrayValue(tableBody("[triggers]"), "crons")).toEqual([]);
|
|
});
|
|
|
|
it("keeps staging routes explicitly empty", () => {
|
|
const staging = tableBody("[env.staging]");
|
|
|
|
expect(stringArrayValue(staging, "routes")).toEqual([]);
|
|
expect(staging).not.toContain("ak.tftt.cc");
|
|
expect(staging).not.toContain("agent-kanban.dev");
|
|
});
|
|
|
|
it("deletes the legacy TunnelRelay Durable Object without retaining a binding", () => {
|
|
expect(config).not.toContain("[[durable_objects.bindings]]");
|
|
expect(config).not.toMatch(/^binding\s*=\s*"TUNNEL_RELAY"$/m);
|
|
expect(tableBody('[[migrations]]\ntag = "v2"')).toContain('deleted_classes = ["TunnelRelay"]');
|
|
});
|
|
});
|