/** * What is POLYFILL-SPECIFIC in these suites' setup: the harness page and the wallet this * repository's runs use. * * Everything generic — the wallet lifecycle, the broker crossing, profiles, bounds, the report * shape, the recognition of the known failure modes — lives in `ng-e2e-helpers`, which knows * nothing about this package and must keep knowing nothing about it: the polyfill is designed * to DISAPPEAR at migration, and that machinery talks about NextGraph itself, so it outlives * it. What is left here is the two things that genuinely belong to the polyfill: the page that * exposes its surface to a browser (`polyfill-entry.ts`), and the name of the wallet its runs * mint. */ import { execSync } from "node:child_process"; import * as fs from "node:fs"; import * as path from "node:path"; import { fileURLToPath } from "node:url"; import { mintWalletProfile, serveOnEphemeralPort, type RunProfile, type WalletCredentials, } from "ng-e2e-helpers"; const __dirname = path.dirname(fileURLToPath(import.meta.url)); /** * The throwaway credentials every suite in this package mints its own run's wallet with. * * A NAME, not an identity that survives: each run gets a profile of its own and mints this * wallet into it, so two runs sharing the name share nothing else. See `ng-e2e-helpers`' * `profiles.ts` for why one physical user per run is the rule, and why it is now a property of * the directory rather than something a lock had to enforce. * * Which is also why the password can sit in a source file in the clear: it opens a wallet that * exists for the length of one run and is deleted with the profile that holds it. A wallet * meant to LAST — the one a deployment serves — must never be minted with these; it gets its * own, chosen by whoever provisions it (`ng-e2e-helpers`' `bin/mint-wallet.ts`). */ export const WALLET: WalletCredentials = { name: "ng-eventually-e2e", password: "ng-eventually-e2e", }; /** * This run's physical user, in a profile of its own. * * The credentials are a PARAMETER defaulting to this package's throwaway pair, not a constant * baked into the call: minting is the same work whoever wants it, and a caller that needs its * own — anyone provisioning a wallet that outlives a run — must not have to reach for a * different function to get it. */ export function mintBatchWallet( suite: string, credentials: WalletCredentials = WALLET, ): Promise { return mintWalletProfile(suite, credentials); } /** `bun build` is a local bundle; a minute is already ten times what it takes. */ const BUILD_MS = 60_000; const ENTRY = path.resolve(__dirname, "polyfill-entry.ts"); const BUNDLE_OUT = path.resolve(__dirname, ".dist", "polyfill-entry.js"); export function buildBundle(): void { fs.mkdirSync(path.dirname(BUNDLE_OUT), { recursive: true }); execSync(`bun build ${ENTRY} --outfile ${BUNDLE_OUT} --bundle --format=esm`, { stdio: "pipe", cwd: path.resolve(__dirname, ".."), timeout: BUILD_MS, }); } /** Serve the harness page — the polyfill's surface, reachable from Playwright as `window.__sdk`. */ export function serveHarness(): Promise<{ url: string; close: () => void }> { const bundle = fs.readFileSync(BUNDLE_OUT, "utf-8"); const html = `ng-eventually polyfill e2e
`; return serveOnEphemeralPort((req, res) => { if (req.url === "/polyfill-entry.js") { res.writeHead(200, { "Content-Type": "application/javascript; charset=utf-8" }); res.end(bundle); } else { res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" }); res.end(html); } }); }