b50591f5bd
Trois appelants veulent la même chose — un portefeuille neuf, ses octets et son mot de passe : la suite du polyfill à son démarrage, la suite d'une application au sien, et un humain une fois pour provisionner un déploiement. Rien ne produisait ce fichier ; il fallait aller le chercher à la main sur nextgraph.eu. Mêmes entrées, mêmes sorties, mais des appelants de nature différente : une suite ne va pas lancer un sous-processus et analyser sa sortie, et un humain ne va pas écrire un fichier jetable pour appeler une fonction. Donc une fonction, et un script mince par-dessus. mintWalletBytes(password, name) rend les OCTETS, pas un chemin. C'est une correction de ce qui existait : exportWalletFile imposait le disque à tout le monde, et la suite applicative écrivait un fichier temporaire pour le relire aussitôt en mémoire, puis devait le nettoyer. Elle ne le fait plus — serveApp prend les octets. Qui veut un fichier l'écrit ; personne n'y est forcé. Le script exige --password et refuse d'en inventer un, et refuse d'écraser un .ngw existant sans --force, vérifié AVANT de fabriquer quoi que ce soit. Exécuté pour de vrai : 800 octets, et le mot de passe imprimé est celui passé en entrée. C'est le seul des trois cas qu'aucune suite n'exerce, donc le seul qui pouvait être livré cassé sans que rien ne le dise. Ce qui ne change pas : les suites fabriquent un portefeuille par exécution et n'en héritent jamais ; le provisionnement veut l'inverse, durable et conservé. Ils partagent la fabrication et l'export, ils divergent sur la durée de vie. Les identifiants en dur deviennent un paramètre — les suites passent toujours les leurs, le script prend ceux qu'on lui donne, et il n'existe aucun mot de passe par défaut.
89 lines
3.7 KiB
TypeScript
89 lines
3.7 KiB
TypeScript
/**
|
|
* 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<RunProfile> {
|
|
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 = `<!DOCTYPE html><html><head><meta charset="utf-8"><title>ng-eventually polyfill e2e</title></head><body><div id="root"></div><script type="module" src="/polyfill-entry.js"></script></body></html>`;
|
|
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);
|
|
}
|
|
});
|
|
}
|