/** * Patch: make store-github updateFile fall back to create when the file doesn't exist. * * Problem: when a post was created in MongoDB but the Gitea write failed (e.g. due to a * previous 401), IndieKit sees the post as existing and calls updateFile() on re-publish. * updateFile() reads the file first to get its SHA, gets a 404, and throws instead of * creating the file. * * Fix: if the read step returns "Not Found", proceed without a SHA. The Gitea Contents API * (same as GitHub API) creates a new file when PUT is called without a sha field. * Also fixes sha: false being sent (invalid) — now only sent when we actually have a SHA. */ import { readFile, writeFile, access } from "node:fs/promises"; const TARGET = "node_modules/@indiekit/store-github/index.js"; const MARKER = "// [patch] store-github-update-fallback"; const OLD_READ = ` let readResponse; try { debug(\`Try reading file \${filePath} in repo \${repo}, branch \${branch}\`); readResponse = await this.#client(\`\${filePath}?ref=\${branch}\`); } catch (error) { const message = crudErrorMessage({ error, operation: "read", filePath, repo, branch, }); debug(message); throw new Error(message); } const { sha } = await readResponse.json();`; const NEW_READ = ` let sha; ${MARKER} try { debug(\`Try reading file \${filePath} in repo \${repo}, branch \${branch}\`); const readResponse = await this.#client(\`\${filePath}?ref=\${branch}\`); const readJson = await readResponse.json(); sha = readJson.sha; } catch (error) { if (error.message && error.message.includes("Not Found")) { // File doesn't exist yet — will create it via PUT without sha debug(\`File \${filePath} not found in repo \${repo} — will create instead of update\`); sha = undefined; } else { const message = crudErrorMessage({ error, operation: "read", filePath, repo, branch, }); debug(message); throw new Error(message); } }`; const OLD_SHA = ` sha: sha || false,`; const NEW_SHA = ` ...(sha ? { sha } : {}), ${MARKER}`; async function exists(p) { try { await access(p); return true; } catch { return false; } } if (!(await exists(TARGET))) { console.log(`[postinstall] store-github-update-fallback: target not found, skipping`); process.exit(0); } const source = await readFile(TARGET, "utf8"); if (source.includes(MARKER)) { console.log("[postinstall] store-github-update-fallback: already patched"); process.exit(0); } if (!source.includes(OLD_READ)) { console.warn("[postinstall] store-github-update-fallback: read snippet not found — skipping"); process.exit(0); } if (!source.includes(OLD_SHA)) { console.warn("[postinstall] store-github-update-fallback: sha snippet not found — skipping"); process.exit(0); } const updated = source .replace(OLD_READ, NEW_READ) .replace(OLD_SHA, NEW_SHA); await writeFile(TARGET, updated, "utf8"); console.log(`[postinstall] store-github-update-fallback: patched ${TARGET}`);