@pagepocket/lib 0.5.1 → 0.6.1

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/README.md CHANGED
@@ -17,7 +17,7 @@ import { PagePocket } from "@pagepocket/lib";
17
17
  import { CdpAdapter } from "@pagepocket/cdp-adapter";
18
18
 
19
19
  const interceptor = new CdpAdapter();
20
- const snapshot = await PagePocket.fromURL("https://example.com").capture({
20
+ const snapshot = await PagePocket.fromTarget({ kind: "cdp-tab", tabId: 123 }).capture({
21
21
  interceptor
22
22
  });
23
23
 
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { PagePocket } from "./pagepocket";
2
- export type { ApiRecord, ApiSnapshot, CaptureOptions, CompletionContext, CompletionStrategy, ContentRef, ContentStore, ContentStoreHandle, InterceptOptions, InterceptSession, InterceptTarget, NetworkEvent, NetworkEventHandlers, NetworkInterceptorAdapter, NetworkRequestEvent, NetworkRequestFailedEvent, NetworkResponseEvent, PagePocketOptions, PageSnapshot, PathResolver, ResourceFilter, ResourceType, SnapshotFile, WriteFSOptions, WriteResult, ZipOptions } from "./types";
2
+ export type { ApiRecord, ApiSnapshot, CaptureOptions, CompletionContext, CompletionStrategy, ContentRef, ContentStore, ContentStoreHandle, NetworkRequestEvent, NetworkRequestFailedEvent, NetworkResponseEvent, PagePocketOptions, PageSnapshot, PathResolver, ResourceFilter, SnapshotFile, WriteFSOptions, WriteResult, ZipOptions } from "./types";
3
3
  export { HybridContentStore } from "./content-store";
4
4
  export { createDefaultPathResolver, withPrefixPathResolver } from "./path-resolver";
5
5
  export { createDefaultResourceFilter } from "./resource-filter";
@@ -1,4 +1,5 @@
1
- import type { ApiRecord, ContentRef, ContentStore, NetworkEvent, NetworkRequestEvent, NetworkRequestFailedEvent, NetworkResponseEvent, ResourceFilter } from "./types";
1
+ import type { NetworkEvent, NetworkRequestEvent, NetworkRequestFailedEvent, NetworkResponseEvent } from "@pagepocket/interceptor";
2
+ import type { ApiRecord, ContentRef, ContentStore, ResourceFilter } from "./types";
2
3
  type Limits = {
3
4
  maxTotalBytes?: number;
4
5
  maxSingleResourceBytes?: number;
@@ -1,4 +1,5 @@
1
- import type { CaptureOptions, InterceptTarget, PagePocketOptions, PageSnapshot } from "./types";
1
+ import type { InterceptTarget } from "@pagepocket/interceptor";
2
+ import type { CaptureOptions, PagePocketOptions, PageSnapshot } from "./types";
2
3
  export declare class PagePocket {
3
4
  private target;
4
5
  private options;
@@ -1,12 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PagePocket = void 0;
4
- const content_store_1 = require("./content-store");
5
4
  const completion_1 = require("./completion");
5
+ const content_store_1 = require("./content-store");
6
+ const network_store_1 = require("./network-store");
6
7
  const path_resolver_1 = require("./path-resolver");
7
8
  const resource_filter_1 = require("./resource-filter");
8
9
  const snapshot_builder_1 = require("./snapshot-builder");
9
- const network_store_1 = require("./network-store");
10
10
  class PagePocket {
11
11
  constructor(target, options) {
12
12
  this.target = target;
@@ -29,9 +29,7 @@ class PagePocket {
29
29
  const rewriteCSS = options?.rewriteCSS ?? true;
30
30
  const limits = options?.limits;
31
31
  const completionStrategies = (0, completion_1.normalizeCompletion)(options?.completion);
32
- const completion = completionStrategies.length > 0
33
- ? completionStrategies
34
- : [(0, completion_1.networkIdle)(1000), (0, completion_1.timeout)(5000)];
32
+ const completion = completionStrategies.length > 0 ? completionStrategies : [(0, completion_1.networkIdle)(1000), (0, completion_1.timeout)(5000)];
35
33
  const store = new network_store_1.NetworkStore({
36
34
  contentStore,
37
35
  filter,
@@ -1,4 +1,5 @@
1
- import type { PathResolver, ResourceType } from "./types";
1
+ import type { ResourceType } from "@pagepocket/interceptor";
2
+ import type { PathResolver } from "./types";
2
3
  export declare const createDefaultPathResolver: () => PathResolver;
3
4
  export declare const resolveCrossOrigin: (url: string, entryUrl: string) => boolean;
4
5
  export declare const withPrefixPathResolver: (resolver: PathResolver, prefix: string) => PathResolver;
@@ -43,9 +43,7 @@ const createDefaultPathResolver = () => {
43
43
  const pathname = normalizePathname(parsed?.pathname || "/");
44
44
  const queryHash = `${parsed?.search || ""}${parsed?.hash || ""}`;
45
45
  const suffix = queryHash ? `__ppq_${(0, utils_1.hashString)(queryHash)}` : "";
46
- const basePath = input.isCrossOrigin
47
- ? `/external_resources${pathname}`
48
- : `${pathname}`;
46
+ const basePath = input.isCrossOrigin ? `/external_resources${pathname}` : `${pathname}`;
49
47
  let resolvedPath = suffix ? withSuffix(basePath, suffix) : basePath;
50
48
  const collisionKey = resolvedPath;
51
49
  const existingUrl = usedPaths.get(collisionKey);
@@ -1,14 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createDefaultResourceFilter = void 0;
4
- const DEFAULT_ALLOWED = new Set([
5
- "document",
6
- "stylesheet",
7
- "script",
8
- "image",
9
- "font",
10
- "media"
11
- ]);
4
+ const DEFAULT_ALLOWED = new Set(["document", "stylesheet", "script", "image", "font", "media"]);
12
5
  const isSkippableUrl = (url) => url.startsWith("data:") ||
13
6
  url.startsWith("blob:") ||
14
7
  url.startsWith("mailto:") ||
@@ -1,5 +1,5 @@
1
- import type { ContentStore, PageSnapshot, PathResolver } from "./types";
2
1
  import type { ApiEntry, StoredResource } from "./network-store";
2
+ import type { ContentStore, PageSnapshot, PathResolver } from "./types";
3
3
  type BuildOptions = {
4
4
  entryUrl: string;
5
5
  createdAt: number;
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.buildSnapshot = void 0;
4
- const path_resolver_1 = require("./path-resolver");
5
- const snapshot_1 = require("./snapshot");
6
4
  const css_rewrite_1 = require("./css-rewrite");
5
+ const path_resolver_1 = require("./path-resolver");
7
6
  const rewrite_links_1 = require("./rewrite-links");
7
+ const snapshot_1 = require("./snapshot");
8
8
  const utils_1 = require("./utils");
9
9
  const streamToUint8Array = async (stream) => {
10
10
  const reader = stream.getReader();
@@ -80,7 +80,7 @@ const groupResources = (input) => {
80
80
  });
81
81
  }
82
82
  const primaryGroup = primaryDoc
83
- ? groups.get(primaryDoc.request.frameId ?? primaryDoc.request.requestId) ?? null
83
+ ? (groups.get(primaryDoc.request.frameId ?? primaryDoc.request.requestId) ?? null)
84
84
  : null;
85
85
  const groupByUrl = new Map();
86
86
  for (const group of groups.values()) {
@@ -92,7 +92,9 @@ const groupResources = (input) => {
92
92
  }
93
93
  const frameId = resource.request.frameId;
94
94
  const byFrame = frameId ? groups.get(frameId) : undefined;
95
- const byInitiator = resource.request.initiator?.url ? groupByUrl.get(resource.request.initiator.url) : undefined;
95
+ const byInitiator = resource.request.initiator?.url
96
+ ? groupByUrl.get(resource.request.initiator.url)
97
+ : undefined;
96
98
  const target = byFrame ?? byInitiator ?? primaryGroup ?? Array.from(groups.values())[0];
97
99
  if (target) {
98
100
  target.resources.push(resource);
@@ -101,7 +103,9 @@ const groupResources = (input) => {
101
103
  for (const entry of input.apiEntries) {
102
104
  const frameId = entry.request.frameId;
103
105
  const byFrame = frameId ? groups.get(frameId) : undefined;
104
- const byInitiator = entry.request.initiator?.url ? groupByUrl.get(entry.request.initiator.url) : undefined;
106
+ const byInitiator = entry.request.initiator?.url
107
+ ? groupByUrl.get(entry.request.initiator.url)
108
+ : undefined;
105
109
  const target = byFrame ?? byInitiator ?? primaryGroup ?? Array.from(groups.values())[0];
106
110
  if (target) {
107
111
  target.apiEntries.push(entry);
package/dist/types.d.ts CHANGED
@@ -1,84 +1,5 @@
1
- export type ResourceType = "document" | "stylesheet" | "script" | "image" | "font" | "media" | "xhr" | "fetch" | "other" | (string & {});
2
- export type BodySource = {
3
- kind: "buffer";
4
- data: Uint8Array;
5
- } | {
6
- kind: "stream";
7
- stream: ReadableStream<Uint8Array>;
8
- } | {
9
- kind: "late";
10
- read: () => Promise<Uint8Array>;
11
- };
12
- export interface NetworkRequestEvent {
13
- type: "request";
14
- requestId: string;
15
- url: string;
16
- method: string;
17
- headers: Record<string, string>;
18
- frameId?: string;
19
- resourceType?: ResourceType;
20
- initiator?: {
21
- type?: string;
22
- url?: string;
23
- };
24
- timestamp: number;
25
- }
26
- export interface NetworkResponseEvent {
27
- type: "response";
28
- requestId: string;
29
- url: string;
30
- status: number;
31
- statusText?: string;
32
- headers: Record<string, string>;
33
- mimeType?: string;
34
- fromDiskCache?: boolean;
35
- fromServiceWorker?: boolean;
36
- timestamp: number;
37
- body?: BodySource;
38
- }
39
- export interface NetworkRequestFailedEvent {
40
- type: "failed";
41
- requestId: string;
42
- url: string;
43
- errorText: string;
44
- timestamp: number;
45
- }
46
- export type NetworkEvent = NetworkRequestEvent | NetworkResponseEvent | NetworkRequestFailedEvent;
47
- export interface NetworkEventHandlers {
48
- onEvent(event: NetworkEvent): void;
49
- onError?(error: Error): void;
50
- onLog?(msg: string, meta?: unknown): void;
51
- }
52
- export interface InterceptorCapabilities {
53
- canGetResponseBody: boolean;
54
- canStreamResponseBody: boolean;
55
- canGetRequestBody: boolean;
56
- providesResourceType: boolean;
57
- }
58
- export type InterceptTarget = {
59
- kind: "url";
60
- url: string;
61
- } | {
62
- kind: "puppeteer-page";
63
- page: unknown;
64
- } | {
65
- kind: "cdp-tab";
66
- tabId: number;
67
- } | {
68
- kind: "cdp-session";
69
- session: unknown;
70
- };
71
- export type InterceptOptions = Record<string, unknown>;
72
- export type NavigateOptions = Record<string, unknown>;
73
- export interface InterceptSession {
74
- navigate?(url: string, options?: NavigateOptions): Promise<void>;
75
- stop(): Promise<void>;
76
- }
77
- export interface NetworkInterceptorAdapter {
78
- readonly name: string;
79
- readonly capabilities: InterceptorCapabilities;
80
- start(target: InterceptTarget, handlers: NetworkEventHandlers, options?: InterceptOptions): Promise<InterceptSession>;
81
- }
1
+ import type { BodySource, NetworkInterceptorAdapter, NetworkRequestEvent, NetworkResponseEvent, ResourceType } from "@pagepocket/interceptor";
2
+ export type { BodySource, InterceptOptions, InterceptSession, InterceptTarget, InterceptorActions, InterceptorCapabilities, NavigateOptions, NetworkEvent, NetworkEventHandlers, NetworkInterceptorAdapter, NetworkRequestEvent, NetworkRequestFailedEvent, NetworkResponseEvent, ResourceType, TriggerAction } from "@pagepocket/interceptor";
82
3
  export interface PathResolver {
83
4
  resolve(input: {
84
5
  url: string;
package/dist/utils.js CHANGED
@@ -17,7 +17,7 @@ const hashString = (value) => {
17
17
  exports.hashString = hashString;
18
18
  const stripLeadingSlash = (value) => value.replace(/^\/+/, "");
19
19
  exports.stripLeadingSlash = stripLeadingSlash;
20
- const ensureLeadingSlash = (value) => value.startsWith("/") ? value : `/${value}`;
20
+ const ensureLeadingSlash = (value) => (value.startsWith("/") ? value : `/${value}`);
21
21
  exports.ensureLeadingSlash = ensureLeadingSlash;
22
22
  const sanitizePosixPath = (value) => {
23
23
  const parts = value.split("/").filter(Boolean);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pagepocket/lib",
3
- "version": "0.5.1",
3
+ "version": "0.6.1",
4
4
  "description": "Library for rewriting HTML snapshots and inlining local resources.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -12,10 +12,13 @@
12
12
  "license": "ISC",
13
13
  "dependencies": {
14
14
  "cheerio": "^1.0.0-rc.12",
15
- "@pagepocket/uni-fs": "0.5.1"
15
+ "@pagepocket/interceptor": "0.6.1",
16
+ "@pagepocket/uni-fs": "0.6.1"
16
17
  },
17
18
  "devDependencies": {
19
+ "@playwright/test": "^1.50.1",
18
20
  "@types/node": "^20.11.30",
21
+ "esbuild": "^0.25.1",
19
22
  "prettier": "^3.7.4",
20
23
  "tsx": "^4.19.3",
21
24
  "typescript": "^5.4.5"
@@ -24,6 +27,7 @@
24
27
  "build": "tsc",
25
28
  "format": "prettier --write .",
26
29
  "format:check": "prettier --check .",
27
- "test": "tsx --test specs/**/*.test.ts"
30
+ "test": "tsx --test specs/*.spec.ts",
31
+ "test:e2e": "playwright test -c e2e/playwright.config.ts"
28
32
  }
29
33
  }
@@ -1,25 +0,0 @@
1
- import { type ResourceReference, type SrcsetReference } from "./resources";
2
- import type { SnapshotData } from "./types";
3
- export type DownloadedResource = {
4
- url: string;
5
- filename: string;
6
- extension: string;
7
- localPath: string;
8
- contentType?: string | null;
9
- size?: number;
10
- };
11
- type DownloadResourcesInput = {
12
- baseUrl: string;
13
- assetsDirName: string;
14
- resourceUrls: ResourceReference[];
15
- srcsetItems: SrcsetReference[];
16
- referer?: string;
17
- };
18
- type DownloadResourcesResult = {
19
- resourceMap: Map<string, DownloadedResource>;
20
- resourceMeta: SnapshotData["resources"];
21
- downloadedCount: number;
22
- failedCount: number;
23
- };
24
- export declare const downloadResources: (input: DownloadResourcesInput) => Promise<DownloadResourcesResult>;
25
- export {};
@@ -1,160 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.downloadResources = void 0;
37
- const content_type_1 = require("./content-type");
38
- const resources_1 = require("./resources");
39
- const FNV_OFFSET = 0x811c9dc5;
40
- const FNV_PRIME = 0x01000193;
41
- const shouldSkipUrl = (value) => {
42
- const trimmed = value.trim();
43
- return (!trimmed ||
44
- trimmed.startsWith("data:") ||
45
- trimmed.startsWith("blob:") ||
46
- trimmed.startsWith("mailto:") ||
47
- trimmed.startsWith("tel:") ||
48
- trimmed.startsWith("javascript:") ||
49
- trimmed.startsWith("#"));
50
- };
51
- const hashUrl = (value) => {
52
- let hash = FNV_OFFSET;
53
- for (let i = 0; i < value.length; i += 1) {
54
- hash ^= value.charCodeAt(i);
55
- hash = (hash * FNV_PRIME) >>> 0;
56
- }
57
- return hash.toString(16).padStart(8, "0");
58
- };
59
- const extensionFromUrl = (url) => {
60
- try {
61
- const pathname = new URL(url).pathname;
62
- const lastDot = pathname.lastIndexOf(".");
63
- if (lastDot === -1) {
64
- return "";
65
- }
66
- return pathname.slice(lastDot);
67
- }
68
- catch {
69
- return "";
70
- }
71
- };
72
- const normalizeExtension = (extension) => {
73
- if (!extension) {
74
- return "";
75
- }
76
- return extension.startsWith(".") ? extension.slice(1) : extension;
77
- };
78
- const buildLocalPath = (assetsDirName, filename, extension) => {
79
- const normalizedExtension = normalizeExtension(extension);
80
- if (!normalizedExtension) {
81
- return `${assetsDirName}/${filename}`;
82
- }
83
- return `${assetsDirName}/${filename}.${normalizedExtension}`;
84
- };
85
- const collectSrcsetUrls = (items, baseUrl) => {
86
- const urls = [];
87
- for (const item of items) {
88
- const parts = item.value.split(",").map((part) => part.trim());
89
- for (const part of parts) {
90
- const [rawUrl] = part.split(/\s+/, 2);
91
- if (!rawUrl) {
92
- continue;
93
- }
94
- const absolute = (0, resources_1.toAbsoluteUrl)(baseUrl, rawUrl);
95
- urls.push(absolute);
96
- }
97
- }
98
- return urls;
99
- };
100
- const downloadResources = async (input) => {
101
- const { write, exists } = await Promise.resolve().then(() => __importStar(require("@pagepocket/uni-fs")));
102
- const resourceMap = new Map();
103
- const resourceMeta = [];
104
- let downloadedCount = 0;
105
- let failedCount = 0;
106
- const srcsetUrls = collectSrcsetUrls(input.srcsetItems, input.baseUrl);
107
- const candidateUrls = [...input.resourceUrls.map((resource) => resource.url), ...srcsetUrls];
108
- for (const candidate of candidateUrls) {
109
- if (shouldSkipUrl(candidate)) {
110
- continue;
111
- }
112
- const url = (0, resources_1.toAbsoluteUrl)(input.baseUrl, candidate);
113
- if (!url || resourceMap.has(url)) {
114
- continue;
115
- }
116
- try {
117
- const headers = {};
118
- if (input.referer) {
119
- headers.referer = input.referer;
120
- }
121
- const response = await fetch(url, { redirect: "follow", headers });
122
- const contentType = response.headers.get("content-type");
123
- const buffer = new Uint8Array(await response.arrayBuffer());
124
- const extFromUrl = extensionFromUrl(url);
125
- const extFromType = (0, content_type_1.extensionFromContentType)(contentType);
126
- const extension = normalizeExtension(extFromUrl || extFromType);
127
- const filename = hashUrl(url);
128
- const localPath = buildLocalPath(input.assetsDirName, filename, extension);
129
- if (!(await exists(input.assetsDirName + "/" + filename, extension))) {
130
- await write(input.assetsDirName + "/" + filename, extension, buffer);
131
- }
132
- const entry = {
133
- url,
134
- filename,
135
- extension,
136
- localPath,
137
- contentType,
138
- size: buffer.byteLength
139
- };
140
- resourceMap.set(url, entry);
141
- resourceMeta.push({
142
- url,
143
- localPath,
144
- contentType,
145
- size: buffer.byteLength
146
- });
147
- downloadedCount += 1;
148
- }
149
- catch {
150
- failedCount += 1;
151
- }
152
- }
153
- return {
154
- resourceMap,
155
- resourceMeta,
156
- downloadedCount,
157
- failedCount
158
- };
159
- };
160
- exports.downloadResources = downloadResources;
@@ -1,4 +0,0 @@
1
- import type { CapturedNetworkRecord, NetworkRecord } from "./types";
2
- export declare const toDataUrlFromRecord: (record: NetworkRecord) => string | null;
3
- export declare const findFaviconDataUrl: (records: NetworkRecord[]) => string | null;
4
- export declare const mapCapturedNetworkRecords: (records: CapturedNetworkRecord[] | undefined) => NetworkRecord[];
@@ -1,83 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.mapCapturedNetworkRecords = exports.findFaviconDataUrl = exports.toDataUrlFromRecord = void 0;
4
- const getHeaderValue = (headers, name) => {
5
- for (const key in headers) {
6
- if (key.toLowerCase() === name.toLowerCase()) {
7
- return headers[key];
8
- }
9
- }
10
- return undefined;
11
- };
12
- const toBase64 = (value) => {
13
- const bufferConstructor = globalThis.Buffer;
14
- if (bufferConstructor) {
15
- return bufferConstructor.from(value, "utf-8").toString("base64");
16
- }
17
- if (typeof btoa === "function") {
18
- return btoa(value);
19
- }
20
- return "";
21
- };
22
- const toDataUrlFromRecord = (record) => {
23
- if (!record)
24
- return null;
25
- const headers = record.responseHeaders || {};
26
- const contentType = getHeaderValue(headers, "content-type") || "application/octet-stream";
27
- if (record.responseEncoding === "base64" && record.responseBodyBase64) {
28
- return `data:${contentType};base64,${record.responseBodyBase64}`;
29
- }
30
- if (record.responseBody) {
31
- const encoded = toBase64(record.responseBody);
32
- if (!encoded) {
33
- return null;
34
- }
35
- return `data:${contentType};base64,${encoded}`;
36
- }
37
- return null;
38
- };
39
- exports.toDataUrlFromRecord = toDataUrlFromRecord;
40
- const findFaviconDataUrl = (records) => {
41
- for (const record of records) {
42
- if (!record || !record.url)
43
- continue;
44
- const headers = record.responseHeaders || {};
45
- const contentType = (getHeaderValue(headers, "content-type") || "").toLowerCase();
46
- const pathname = (() => {
47
- try {
48
- return new URL(record.url).pathname;
49
- }
50
- catch {
51
- return record.url;
52
- }
53
- })();
54
- const looksLikeFavicon = contentType.includes("icon") || /favicon(\.[a-z0-9]+)?$/i.test(pathname || "");
55
- if (!looksLikeFavicon)
56
- continue;
57
- const dataUrl = (0, exports.toDataUrlFromRecord)(record);
58
- if (dataUrl)
59
- return dataUrl;
60
- }
61
- return null;
62
- };
63
- exports.findFaviconDataUrl = findFaviconDataUrl;
64
- const mapCapturedNetworkRecords = (records) => {
65
- if (!records)
66
- return [];
67
- return records.map((record) => {
68
- const response = record.response;
69
- return {
70
- url: record.url,
71
- method: record.method,
72
- status: response?.status,
73
- statusText: response?.statusText,
74
- responseHeaders: response?.headers,
75
- responseBody: response?.bodyEncoding === "text" ? response.body : undefined,
76
- responseBodyBase64: response?.bodyEncoding === "base64" ? response.body : undefined,
77
- responseEncoding: response?.bodyEncoding,
78
- error: record.error,
79
- timestamp: record.timestamp
80
- };
81
- });
82
- };
83
- exports.mapCapturedNetworkRecords = mapCapturedNetworkRecords;