@plurnk/plurnk-schemes-http 1.4.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/Browser.js DELETED
@@ -1,295 +0,0 @@
1
- // Headless-Chromium render foundation {§render-lifecycle}, derived from
2
- // @possumtech/rummy.web's MIT WebFetcher by the same author. It is a standalone
3
- // package surface whose initialization and shutdown follow {§handler-lifecycle}.
4
- //
5
- // Scope here is render-ONLY: navigate, let JS run + hydration settle, serialize
6
- // the final DOM. It returns the true rendered page; it never cleans, strips,
7
- // or extracts — projection (markdown/symbols/deepXml) is the mimetype layer's
8
- // job, off the faithful body we hand over.
9
- //
10
- // Driver is Playwright, lazy-imported so only the render path pays for it (the
11
- // raw-byte fetch path stays Node-builtin-only). The engine is reached through
12
- // a minimal structural seam (`ChromiumEngine`) so it can be injected — fakes
13
- // in unit tests, and a remote CDP endpoint (Lightpanda/browserless/shared
14
- // chromium) swapped in via env with zero code change.
15
- // Mobile device emulation (a Pixel-5-class profile) is the configured default;
16
- // PLURNK_SCHEMES_HTTP_MOBILE=0 selects a desktop context {§http-config}.
17
- // The ONE browser identity both acquisition paths present (render context AND
18
- // the byte-path fetch) — ordinary Chrome traffic, never an automated-client or
19
- // plurnk fingerprint. Model-supplied {User-Agent: …} target blocks override it.
20
- export const BROWSER_UA = "Mozilla/5.0 (Linux; Android 13; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36";
21
- const MOBILE_CONTEXT = Object.freeze({
22
- userAgent: BROWSER_UA,
23
- viewport: { width: 393, height: 851 },
24
- deviceScaleFactor: 2.75,
25
- isMobile: true,
26
- hasTouch: true,
27
- });
28
- // Required floor-set knob; unset is a configuration failure {§http-config}.
29
- const mobileEmulation = () => {
30
- const raw = process.env.PLURNK_SCHEMES_HTTP_MOBILE;
31
- if (raw === undefined)
32
- throw new Error("Browser: required env PLURNK_SCHEMES_HTTP_MOBILE is unset — see .env.defaults");
33
- return raw === "0" ? undefined : MOBILE_CONTEXT;
34
- };
35
- // Required numeric lookup. `.env.defaults` owns values; call sites own when a
36
- // value becomes necessary, and no in-code fallback hides its absence
37
- // {§http-config}.
38
- export const requireNumEnv = (key) => {
39
- const raw = process.env[key];
40
- if (raw === undefined)
41
- throw new Error(`Browser: required env ${key} is unset — see .env.defaults`);
42
- const n = Number(raw);
43
- if (Number.isNaN(n))
44
- throw new Error(`Browser: ${key}=${raw} is not a number`);
45
- return n;
46
- };
47
- // Default factory: lazy-import the real chromium. The cast bridges Playwright's
48
- // full type to our structural view at the single trusted library boundary.
49
- const defaultFactory = async () => (await import("playwright")).chromium;
50
- const requireBoolEnv = (key) => {
51
- const raw = process.env[key];
52
- if (raw !== "0" && raw !== "1")
53
- throw new Error(`Browser: required env ${key} must be 0 or 1 — see .env.defaults`);
54
- return raw === "1";
55
- };
56
- const browserConfig = () => {
57
- const raw = process.env.PLURNK_SCHEMES_HTTP_PLAYWRIGHT_METHOD;
58
- if (raw === undefined)
59
- throw new Error("Browser: required env PLURNK_SCHEMES_HTTP_PLAYWRIGHT_METHOD is unset — see .env.defaults");
60
- if (!["launch", "connect", "connectOverCDP", "disabled"].includes(raw)) {
61
- throw new Error(`Browser: PLURNK_SCHEMES_HTTP_PLAYWRIGHT_METHOD=${raw} must be launch, connect, connectOverCDP, or disabled`);
62
- }
63
- const method = raw;
64
- const endpoint = process.env.PLURNK_SCHEMES_HTTP_PLAYWRIGHT_ENDPOINT;
65
- const channel = process.env.PLURNK_SCHEMES_HTTP_PLAYWRIGHT_CHANNEL;
66
- const executablePath = process.env.PLURNK_SCHEMES_HTTP_PLAYWRIGHT_EXECUTABLE_PATH;
67
- if ((method === "connect" || method === "connectOverCDP") && !endpoint) {
68
- throw new Error(`Browser: ${method} requires PLURNK_SCHEMES_HTTP_PLAYWRIGHT_ENDPOINT`);
69
- }
70
- if (method !== "connect" && method !== "connectOverCDP" && endpoint) {
71
- throw new Error(`Browser: PLURNK_SCHEMES_HTTP_PLAYWRIGHT_ENDPOINT is incompatible with ${method}`);
72
- }
73
- if (method !== "launch" && (channel || executablePath)) {
74
- throw new Error(`Browser: Playwright channel and executable path are incompatible with ${method}`);
75
- }
76
- if (channel && executablePath) {
77
- throw new Error("Browser: PLURNK_SCHEMES_HTTP_PLAYWRIGHT_CHANNEL and PLURNK_SCHEMES_HTTP_PLAYWRIGHT_EXECUTABLE_PATH are mutually exclusive");
78
- }
79
- if (method === "disabled")
80
- return { method };
81
- const timeout = requireNumEnv("PLURNK_SCHEMES_HTTP_PLAYWRIGHT_TIMEOUT");
82
- if (method === "connect" || method === "connectOverCDP") {
83
- return { method, endpoint: endpoint, options: { timeout } };
84
- }
85
- const args = [];
86
- const heapMb = process.env.PLURNK_SCHEMES_HTTP_CHROMIUM_HEAP_MB;
87
- if (heapMb)
88
- args.push(`--js-flags=--max-old-space-size=${heapMb}`);
89
- return {
90
- method,
91
- options: {
92
- headless: requireBoolEnv("PLURNK_SCHEMES_HTTP_PLAYWRIGHT_HEADLESS"),
93
- chromiumSandbox: requireBoolEnv("PLURNK_SCHEMES_HTTP_PLAYWRIGHT_CHROMIUM_SANDBOX"),
94
- timeout,
95
- args,
96
- ...(channel ? { channel } : {}),
97
- ...(executablePath ? { executablePath } : {}),
98
- },
99
- };
100
- };
101
- export default class Browser {
102
- #factory;
103
- #browser = null;
104
- #launching = null;
105
- // One atomically acquired BrowserContext per worker — cookies / cache /
106
- // storage scoped to the worker that opened it, no cross-worker bleed.
107
- // Promises make overlapping first renders share the same acquisition.
108
- #contexts = new Map();
109
- #idleTimer = null;
110
- // Inject a factory in tests; production lazy-imports playwright.
111
- constructor(factory = defaultFactory) {
112
- this.#factory = factory;
113
- }
114
- async ready() {
115
- const { method } = browserConfig();
116
- if (method !== "disabled")
117
- await this.#getBrowser();
118
- return method;
119
- }
120
- // Render a URL to its final serialized DOM. Opens a page in the worker's
121
- // context, navigates with the settle+salvage strategy, serializes, closes
122
- // the page. Throws on navigation failure (the caller maps it to a status).
123
- async render(url, { workerId, signal, headers, timeout = requireNumEnv("PLURNK_SCHEMES_HTTP_FETCH_TIMEOUT") }) {
124
- const context = await this.#getContext(workerId);
125
- const page = await context.newPage();
126
- let closeFailure;
127
- let closePromise;
128
- // {§render-lifecycle} Abort and final settlement share one immediately
129
- // observed close promise, so neither a duplicate call nor an unhandled
130
- // rejection can escape the render boundary.
131
- const closePage = () => {
132
- closePromise ??= Promise.resolve()
133
- .then(() => page.close())
134
- .catch((cause) => { closeFailure = { cause }; });
135
- return closePromise;
136
- };
137
- const onAbort = () => { void closePage(); };
138
- signal?.addEventListener("abort", onAbort, { once: true });
139
- let outcome;
140
- try {
141
- if (signal?.aborted) {
142
- onAbort();
143
- signal.throwIfAborted();
144
- }
145
- // Playwright's page header API is single-valued; byte acquisition preserves duplicates.
146
- if (headers && headers.length > 0)
147
- await page.setExtraHTTPHeaders(Object.fromEntries(headers));
148
- const response = await this.#safeGoto(page, url, timeout);
149
- const html = await page.content();
150
- outcome = {
151
- result: {
152
- status: response?.status() ?? 200,
153
- statusText: response?.statusText() ?? "",
154
- headers: response ? Object.entries(response.headers()) : [],
155
- html,
156
- },
157
- };
158
- }
159
- catch (cause) {
160
- outcome = { cause };
161
- }
162
- finally {
163
- signal?.removeEventListener("abort", onAbort);
164
- await closePage();
165
- }
166
- if (outcome === undefined)
167
- throw new Error("Browser render settled without an outcome");
168
- if ("cause" in outcome) {
169
- if (closeFailure !== undefined) {
170
- throw new AggregateError([outcome.cause, closeFailure.cause], "Browser render and page close failed");
171
- }
172
- throw outcome.cause;
173
- }
174
- if (closeFailure !== undefined)
175
- throw closeFailure.cause;
176
- return outcome.result;
177
- }
178
- // page.goto with the salvage path. networkidle timing out while the DOM has
179
- // already rendered substantive body text is the chatty-page case: the
180
- // content is there even though the network never settled. readyState is
181
- // unreliable (a never-ending stream stays `loading` forever); the load-
182
- // bearing signal is the body's innerText length — below the salvage
183
- // threshold we discard (too little to be sure the DOM rendered the article
184
- // rather than a skeleton). Returns the Response on normal completion, null
185
- // on salvage, and re-throws every other error.
186
- async #safeGoto(page, url, timeout) {
187
- try {
188
- return await page.goto(url, { waitUntil: "networkidle", timeout });
189
- }
190
- catch (err) {
191
- if (!(err instanceof Error) || err.name !== "TimeoutError")
192
- throw err;
193
- const bodyLen = await page
194
- .evaluate(() => document?.body?.innerText?.length ?? 0)
195
- .catch(() => 0);
196
- if (bodyLen < requireNumEnv("PLURNK_SCHEMES_HTTP_SALVAGE_MIN_BODY_CHARS"))
197
- throw err;
198
- return null;
199
- }
200
- }
201
- // Get-or-launch the warm chromium under the one explicitly selected mode.
202
- // Single browser across all workers;
203
- // per-worker isolation is at the context layer. Relaunches if chromium dies
204
- // (OOM/segfault/WS teardown) leaves the handle stale.
205
- async #getBrowser() {
206
- this.#touchIdle();
207
- if (this.#browser)
208
- return this.#browser;
209
- this.#launching ??= (async () => {
210
- const config = browserConfig();
211
- if (config.method === "disabled")
212
- throw new Error("Browser: HTML rendering is disabled by PLURNK_SCHEMES_HTTP_PLAYWRIGHT_METHOD=disabled");
213
- const chromium = await this.#factory();
214
- if (config.method === "connect")
215
- return chromium.connect(config.endpoint, config.options);
216
- if (config.method === "connectOverCDP")
217
- return chromium.connectOverCDP(config.endpoint, config.options);
218
- return chromium.launch(config.options);
219
- })();
220
- const browser = await this.#launching;
221
- this.#launching = null;
222
- browser.on("disconnected", () => {
223
- if (this.#browser === browser) {
224
- this.#browser = null;
225
- this.#contexts.clear();
226
- }
227
- });
228
- this.#browser = browser;
229
- return browser;
230
- }
231
- // Get-or-create the worker's BrowserContext. Mobile-emulated by default (a
232
- // lighter responsive layout is the better generation hint); desktop when
233
- // PLURNK_SCHEMES_HTTP_MOBILE=0.
234
- async #getContext(workerId) {
235
- this.#touchIdle();
236
- let context = this.#contexts.get(workerId);
237
- if (context === undefined) {
238
- context = (async () => {
239
- const browser = await this.#getBrowser();
240
- return browser.newContext(mobileEmulation());
241
- })();
242
- this.#contexts.set(workerId, context);
243
- }
244
- try {
245
- return await context;
246
- }
247
- catch (error) {
248
- if (this.#contexts.get(workerId) === context)
249
- this.#contexts.delete(workerId);
250
- throw error;
251
- }
252
- }
253
- // Drop the worker's context (run end or abort). Closing it cascades to any
254
- // in-flight page in that context.
255
- async closeContext(workerId) {
256
- const context = this.#contexts.get(workerId);
257
- if (!context)
258
- return;
259
- this.#contexts.delete(workerId);
260
- await (await context).close();
261
- }
262
- #touchIdle() {
263
- if (this.#idleTimer)
264
- clearTimeout(this.#idleTimer);
265
- this.#idleTimer = setTimeout(() => {
266
- void this.close().catch((error) => {
267
- console.error("Browser idle cleanup failed", { error });
268
- });
269
- }, requireNumEnv("PLURNK_SCHEMES_HTTP_IDLE_TIMEOUT"));
270
- this.#idleTimer.unref?.();
271
- }
272
- // Tear everything down: per-worker contexts then the browser. In CDP mode
273
- // close() disconnects the local handle without shutting the remote down.
274
- async close() {
275
- if (this.#idleTimer) {
276
- clearTimeout(this.#idleTimer);
277
- this.#idleTimer = null;
278
- }
279
- const contexts = [...this.#contexts.values()];
280
- this.#contexts.clear();
281
- const contextResults = await Promise.allSettled(contexts.map(async (context) => (await context).close()));
282
- const browser = this.#browser;
283
- this.#browser = null;
284
- this.#launching = null;
285
- const browserResults = browser === null ? [] : await Promise.allSettled([browser.close()]);
286
- const errors = [...contextResults, ...browserResults]
287
- .filter((result) => result.status === "rejected")
288
- .flatMap((result) => result.reason instanceof AggregateError
289
- ? [...result.reason.errors]
290
- : [result.reason]);
291
- if (errors.length > 0)
292
- throw new AggregateError(errors, "Browser shutdown failed");
293
- }
294
- }
295
- //# sourceMappingURL=Browser.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Browser.js","sourceRoot":"","sources":["../src/Browser.ts"],"names":[],"mappings":"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"}