Skip to main content

network

Read the network instead of the DOM. Snoop JSON API responses, wait for a request instead of sleeping, collect items while scrolling, record a QA flight trace (jsonl, HAR, screenshots), and intercept requests with routes.

Datos de origen

Repositorio
code-yeongyu/omowright
Última actividad en el origen
23 de septiembre de 2026 a las 05:10
Idioma detectado de SKILL.md
inglés
Estrellas
3
Forks
2

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
name
network
description
Read the network instead of the DOM. Snoop JSON API responses, wait for a request instead of sleeping, collect items while scrolling, record a QA flight trace (jsonl, HAR, screenshots), and intercept requests with routes.
# Network Every page session already has the `Network` domain on, so watching traffic costs nothing and pages can't see it. All four tools come from the package entrypoint: ```js const { createNetworkSnoop, collectWhileScrolling, createTrace, createRoutes } = await import("omowright"); ``` ## Snoop before you scrape When a page renders a list, a table, or search results, the data almost always arrived as JSON one request earlier. That JSON is complete, typed, and free of truncated labels. Snapshot to find and click; snoop to read. ```js const snoop = createNetworkSnoop(page, { match: { url: /\/api\//, mimeType: "json" } }); // strings match as substrings await page.goto("https://example.com/search?q=widgets"); const results = snoop.popJson(); // parsed bodies, buffer drained console.log(snoop.summary({ max: 20 })); // "GET 200 application/json 8123B https://..." snoop.dispose(); ``` Create the snoop before the navigation or click that produces the traffic. Entries land when the response finishes, so `match` may test `status` and `mimeType`. `pop()` gives raw entries; `peek()` copies without draining. ## Wait for the request, not the clock A fixed sleep either wastes time or fails on a slow day. Wait for the response you need instead: ```js const saved = snoop.waitFor({ url: "/api/cart", method: "POST" }, { timeoutMs: 10000 }); await page.locator("e7").click(); const entry = await saved; // { status, body, ... } if (entry.status !== 200) throw new Error(`cart save failed: ${entry.status} ${entry.statusText}`); ``` Start the wait first, then act; a response that finishes before `waitFor` is called goes to the buffer, not the waiter. ## Collect while scrolling Infinite lists load pages over XHR as you scroll. Drive the scroll and drain the snoop in one loop: ```js const snoop = createNetworkSnoop(page, { match: { url: /\/feed\?/ } }); const items = []; const gen = collectWhileScrolling(page, snoop, { minItems: 200, maxScrolls: 15, extract: json => json.items ?? [], scroll: "wheel", // "end" jumps to the bottom instead settleMs: 800, }); let step; while (!(step = await gen.next()).done) items.push(step.value); step.value; // { rounds, total, stoppedBecause } ``` `for await (const item of gen)` works too when you don't need the return value. The loop drains first, then scrolls, and stops on `minItems`, `maxScrolls`, or two consecutive rounds where the document height didn't grow (`noGrowth`). The default `extract` accepts bodies that are already arrays. ## Flight recorder for QA `createTrace` records what happened while you drove the page, so a failed run is a directory to read rather than a memory to reconstruct: ```js const trace = createTrace(page, { dir: "/tmp/checkout-trace" }); await trace.step("open cart", () => page.goto("https://example.com/cart")); await trace.step("apply coupon", async () => { await page.locator("e3").fill("SAVE10"); await page.locator("e4").click(); }); trace.mark("expected total", { total: "90.00" }); const summary = await trace.stop(); // { steps, events, network, startedAt, endedAt, url } ``` What lands in `dir`: - `trace.jsonl`: one JSON object per line, ordered by `seq`. `kind` is one of `step` (name, `durationMs`, `error`, screenshot paths), `network`, `console`, `dialog`, `navigation`, `download`, `mark`, `warning`. Grep it: `rg '"kind":"console"' trace.jsonl` or `jq -c 'select(.kind=="step")'`. - `trace.har`: HAR 1.2 of every finished request; open it in DevTools or any HAR viewer to see timings and bodies. - `summary.json`: the object `stop()` returned. - `screenshots/<seq>-<slug>-before.png` and `-after.png` for every step. Steps rethrow, so call `stop()` in a `finally` to keep the evidence from a failure. The recorder rides the existing network and console paths. ## Routes: intercept with care `createRoutes(page)` blocks, rewrites, or fakes requests: ```js const routes = createRoutes(page); await routes.route("*/analytics/*", ({ abort }) => abort("BlockedByClient")); await routes.route(/\/api\/flags$/, ({ fulfill }) => fulfill({ status: 200, contentType: "application/json", body: JSON.stringify({ beta: true }) })); await routes.route(({ method }) => method === "POST", ({ request, continue: go }) => go({ headers: { ...request.headers, "x-test-run": "1" } })); // ... drive the page ... await routes.dispose(); // Fetch.disable ``` Glob strings use `*` and `?`; a string without either is a substring match. A handler that throws or never settles lets the request continue, with a warning. Stealth caveat: `Fetch.enable` goes out on the first `route()`, and interception changes the timing and blocking patterns that bot defenses score. Leave routes off for WAF-protected targets and stealth profiles; use the snoop, which is passive, to read the same traffic.
Ver en GitHub