#!/usr/bin/env node // E2E fake wrangler (release 18). The deploy stage spawns `wranglerBin(paths)` // — WRANGLER_BIN when set, which playwright.config.ts points here — with // // pages deploy --project-name --branch // // (common/lib/pagesDeploy.ts pagesDeployArgs). The suite must never reach // Cloudflare, so this deploys nothing. What it does: // // - records every invocation in an argv sidecar, `.fake-wrangler.json`, // BESIDE the bundle (the directory holding ): `{ invocations: [{ // argv, cwd, project, branch, outDir, files }] }`, appended, so a spec reads // what was "deployed", from where, to which branch; // - prints wrangler 4's success lines, ending on "Take a peek over at // https://..pages.dev" — the line deploymentUrlIn reads; // - in AUTH-FAIL mode, prints wrangler's own refusal for a token Cloudflare // does not accept ("Authentication error [code: 10000]") and exits 1, // without writing the sidecar — the deploy stage must turn that into // "[deploy] REFUSED by Cloudflare — the API token was not accepted" and // leave deployed.json untouched. The mode is a MODE SIDECAR a spec writes // and removes, `/.fake-wrangler-mode.json` `{"authFail": // true}` (the editor's actions pass the stage no env of a spec's, so an // env var cannot reach one test; fake-ytdlp.mjs's sidecar pattern), or // E2E_FAKE_WRANGLER_AUTH_FAIL=1 as the fallback; // - answers `--version` like the pinned binary. // // A missing fails as wrangler does. Anything else is a usage error. import { existsSync, readdirSync, readFileSync, statSync, writeFileSync } from "node:fs"; import path from "node:path"; import { installFixtureWatchdog } from "./_watchdog.mjs"; // Never outlive the run that spawned us — see _watchdog.mjs. installFixtureWatchdog(); const VERSION = "4.147.0"; const argv = process.argv.slice(2); if (argv[0] === "--version" || argv[0] === "-v") { process.stdout.write(`${VERSION}\n`); process.exit(0); } const opt = (flag) => { const i = argv.indexOf(flag); return i < 0 ? undefined : argv[i + 1]; }; if (argv[0] !== "pages" || argv[1] !== "deploy" || !argv[2] || argv[2].startsWith("--")) { process.stderr.write(`[fake-wrangler] unsupported invocation: ${argv.join(" ")}\n`); process.exit(2); } const outDir = path.resolve(argv[2]); const project = opt("--project-name"); const branch = opt("--branch") ?? "main"; process.stdout.write(`\n ⛅️ wrangler ${VERSION} (fake)\n───────────────────\n`); // The mode sidecar: in EXPORT_BUILDS_DIR when set, else beside the editor's // export-public dir (paths.ts exportBuildsDir), else two levels above the // bundle (//out). function modeSidecar() { const dirs = [ process.env.EXPORT_BUILDS_DIR, process.env.EXPORT_PUBLIC_DIR && path.join(path.dirname(process.env.EXPORT_PUBLIC_DIR), ".export-builds"), path.dirname(path.dirname(outDir)), ].filter(Boolean); for (const d of dirs) { try { return JSON.parse(readFileSync(path.join(d, ".fake-wrangler-mode.json"), "utf8")); } catch { // absent or unreadable: the next place } } return {}; } const mode = modeSidecar(); if (mode.authFail === true || process.env.E2E_FAKE_WRANGLER_AUTH_FAIL === "1") { process.stderr.write( `\n✘ [ERROR] A request to the Cloudflare API (/accounts/0000/pages/projects/${project ?? "?"}) failed.\n\n` + " Authentication error [code: 10000]\n\n" + " 📎 It looks like you are authenticating Wrangler via a custom API token set in an environment variable.\n" + " Please ensure it has the correct permissions for this operation.\n\n", ); process.exit(1); } if (!existsSync(outDir) || !statSync(outDir).isDirectory()) { process.stderr.write(`\n✘ [ERROR] The directory specified ("${argv[2]}") does not exist.\n`); process.exit(1); } if (!project) { process.stderr.write("\n✘ [ERROR] Must specify a project name.\n"); process.exit(1); } let files = 0; const walk = (d) => { for (const e of readdirSync(d, { withFileTypes: true })) { if (e.isDirectory()) walk(path.join(d, e.name)); else files++; } }; walk(outDir); const sidecar = path.join(path.dirname(outDir), ".fake-wrangler.json"); let record = { invocations: [] }; try { record = JSON.parse(readFileSync(sidecar, "utf8")); if (!Array.isArray(record.invocations)) record = { invocations: [] }; } catch { // first invocation } record.invocations.push({ argv, cwd: process.cwd(), project, branch, outDir, files }); writeFileSync(sidecar, `${JSON.stringify(record, null, 2)}\n`); process.stdout.write(`Uploading... (${files}/${files})\n`); process.stdout.write(`✨ Success! Uploaded ${files} files (0 already uploaded) (0.01 sec)\n\n`); process.stdout.write("🌎 Deploying...\n"); process.stdout.write(`✨ Deployment complete! Take a peek over at https://${branch}.${project}.pages.dev\n`);