#!/usr/bin/env bun import { existsSync } from "node:fs"; import { mkdir, readFile, writeFile } from "node:fs/promises"; import { join, resolve } from "node:path"; const moduleNames = [ "amezing", "analysis", "astro", "database", "latex", "mdx", "optimize", "prettier-plugin", "shadcn", "tailwind", ] as const; const root = resolve(import.meta.dir, ".."); const api = (process.env.MUDDLE_FORGEJO_URL ?? "https://git.crit.rip").replace( /\/$/, "", ); const owner = process.env.MUDDLE_FORGEJO_OWNER ?? "mdl"; const dryRun = process.argv.includes("--dry-run"); const token = process.env.MUDDLE_FORGEJO_TOKEN; if (!dryRun && !token) { throw new Error("Set MUDDLE_FORGEJO_TOKEN or use --dry-run."); } async function forgejo( path: string, init: RequestInit = {}, ): Promise { if (dryRun) return new Response(null, { status: 204 }); return fetch(`${api}/api/v1${path}`, { ...init, headers: { Authorization: `token ${token}`, Accept: "application/json", "Content-Type": "application/json", ...init.headers, }, }); } async function ensureWorkspaceModule(name: string): Promise { const dir = join(root, "modules", name); await mkdir(dir, { recursive: true }); const manifest = join(dir, "package.json"); if (!existsSync(manifest)) { await writeFile( manifest, `${JSON.stringify( { name: `@muddle/${name}`, version: "0.1.0", type: "module", exports: "./index.ts", peerDependencies: { muddle: "*" }, }, null, 2, )}\n`, ); await writeFile(join(dir, "index.ts"), "export {};\n"); } const parsed = JSON.parse(await readFile(manifest, "utf8")) as { name?: string; }; if (parsed.name !== `@muddle/${name}`) { throw new Error(`${manifest} must declare @muddle/${name}`); } } async function ensureRemoteRepository(name: string): Promise { const response = await forgejo(`/repos/${owner}/${name}`); if (response.status === 200 || response.status === 204) return; if (response.status !== 404) { throw new Error( `Unable to inspect ${owner}/${name}, Forgejo returned ${response.status}`, ); } const created = await forgejo(`/orgs/${owner}/repos`, { method: "POST", body: JSON.stringify({ name, private: false, description: `@muddle/${name} integration module`, }), }); if (!created.ok) { throw new Error( `Unable to create ${owner}/${name}, Forgejo returned ${created.status}`, ); } } for (const name of moduleNames) { await ensureWorkspaceModule(name); await ensureRemoteRepository(name); console.log( `${ dryRun ? "would provision" : "provisioned" } @muddle/${name} at ${api}/${owner}/${name}`, ); }