/** * Patch: fix store-github HTTP methods for Gitea's Contents API. * * GitHub API: PUT /contents/{path} = create-or-update (sha optional) * Gitea API: POST /contents/{path} = create (no sha) * PUT /contents/{path} = update (sha required → 422 without it) * * Two changes: * 1. createFile: use POST instead of PUT. * 2. updateFile: when sha is undefined (file didn't exist), bail out to * createFile() instead of falling through to PUT-without-SHA which 422s. * Also restores plain `sha` in the PUT body (no longer need the spread * guard from patch-store-github-update-fallback since we bail early). */ import { readFile, writeFile, access } from "node:fs/promises"; const TARGET = "node_modules/@indiekit/store-github/index.js"; const MARKER = "// [patch] store-github-gitea-methods"; // ── Change 1: createFile uses POST ────────────────────────────────────────── const OLD_CREATE_PUT = ` createResponse = await this.#client(filePath, "PUT", {`; const NEW_CREATE_POST = ` createResponse = await this.#client(filePath, "POST", { ${MARKER}`; // ── Change 2: updateFile bails to createFile when sha is undefined ─────────── // Targets the block that starts after sha is resolved (by patch-store-github-update-fallback). // Replaces the spread-sha guard with an early-return to createFile. const OLD_UPDATE_SPREAD = ` const updateFilePath = newPath || filePath; let updateResponse; try { debug(\`Try updating file \${filePath} in repo \${repo}, branch \${branch}\`); updateResponse = await this.#client(updateFilePath, "PUT", { branch, content: Buffer.from(content).toString("base64"), message, ...(sha ? { sha } : {}), // [patch] store-github-update-fallback`; const NEW_UPDATE_SPREAD = ` if (!sha) { ${MARKER} // File didn't exist — create it via POST instead of PUT-without-SHA (422 on Gitea) return this.createFile(filePath, content, { message }); } const updateFilePath = newPath || filePath; let updateResponse; try { debug(\`Try updating file \${filePath} in repo \${repo}, branch \${branch}\`); updateResponse = await this.#client(updateFilePath, "PUT", { branch, content: Buffer.from(content).toString("base64"), message, sha, ${MARKER}`; async function exists(p) { try { await access(p); return true; } catch { return false; } } if (!(await exists(TARGET))) { console.log(`[postinstall] store-github-gitea-methods: target not found, skipping`); process.exit(0); } const source = await readFile(TARGET, "utf8"); if (source.includes(MARKER)) { console.log("[postinstall] store-github-gitea-methods: already patched"); process.exit(0); } let updated = source; let patched = 0; if (!updated.includes(OLD_CREATE_PUT)) { console.warn("[postinstall] store-github-gitea-methods: createFile PUT snippet not found — skipping change 1"); } else { updated = updated.replace(OLD_CREATE_PUT, NEW_CREATE_POST); patched++; } if (!updated.includes(OLD_UPDATE_SPREAD)) { console.warn("[postinstall] store-github-gitea-methods: updateFile spread snippet not found — skipping change 2"); } else { updated = updated.replace(OLD_UPDATE_SPREAD, NEW_UPDATE_SPREAD); patched++; } if (patched === 0) { console.warn("[postinstall] store-github-gitea-methods: no changes applied"); process.exit(0); } await writeFile(TARGET, updated, "utf8"); console.log(`[postinstall] store-github-gitea-methods: patched ${patched}/2 change(s) in ${TARGET}`);