@pagepocket/lighterceptor
v0.8.6
Published
Capture outbound requests from HTML/JS/CSS in a jsdom environment.
Readme
@pagepocket/lighterceptor
Capture outbound requests an HTML/JS/CSS payload would trigger in a jsdom environment, without hitting the network.
Install
pnpm add @pagepocket/lighterceptorQuick Start
import { Lighterceptor } from "@pagepocket/lighterceptor";
const html = `
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="https://cdn.example.com/site.css" />
</head>
<body>
<img src="https://cdn.example.com/logo.png" />
<script>
fetch("https://api.example.com/search?q=lighterceptor");
</script>
</body>
</html>
`;
const result = await new Lighterceptor(html).run();
console.log(result.requests);Recursion (Dependency Graph)
Enable recursion to keep walking JS/CSS/HTML dependencies. This is useful when HTML loads CSS/JS, and those assets load more assets.
import { Lighterceptor } from "@pagepocket/lighterceptor";
const html = `
<!doctype html>
<link rel="stylesheet" href="https://example.com/site.css" />
<script src="https://example.com/app.js"></script>
`;
const result = await new Lighterceptor(html, { recursion: true }).run();
console.log(result.requests.map((item) => item.url));Recursion uses the global fetch to load discovered resources. In tests or
offline usage, stub fetch to return deterministic content.
API
Lighterceptor
type LighterceptorOptions = {
settleTimeMs?: number;
recursion?: boolean;
requestOnly?: boolean;
baseUrl?: string;
};
type RequestRecord = {
url: string;
source: "resource" | "img" | "css" | "fetch" | "xhr" | "unknown";
timestamp: number;
};
type ResponseRecord = {
status: number;
statusText: string;
headers: Record<string, string>;
body: string;
bodyEncoding: "text" | "base64";
};
type NetworkRecord = {
url: string;
source: "resource" | "img" | "css" | "fetch" | "xhr" | "unknown";
method: string;
timestamp: number;
response?: ResponseRecord;
error?: string;
};
type LighterceptorResult = {
title?: string;
capturedAt: string;
requests: RequestRecord[];
networkRecords?: NetworkRecord[];
};settleTimeMs: wait time before the run finishes, so script-driven requests can be captured.recursion: when true, fetches JS/CSS/HTML resources and applies the same interception logic to their dependencies.requestOnly: when true, skips response capture and only records request metadata.baseUrl: absolute URL used to resolve/pathURLs and other relative references.
createJSDOMWithInterceptor
Use this when you need low-level access to jsdom.
import { createJSDOMWithInterceptor } from "@pagepocket/lighterceptor";
const dom = createJSDOMWithInterceptor({
html: "<img src='https://example.com/logo.png'>",
domOptions: {
pretendToBeVisual: true,
runScripts: "dangerously"
},
interceptor: (url, options) => {
console.log("Intercepted", url, options.source);
return "";
}
});Examples
See the examples/ directory for more:
examples/basic-lighterceptor.tsexamples/custom-interceptor.tsexamples/aggregate-requests.tsexamples/recursive-crawl.tsexamples/real-world-moon.ts
