muddle/scripts/forgejo-modules.ts

113 lines
2.6 KiB
TypeScript

#!/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<Response> {
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<void> {
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<void> {
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}`,
);
}