@pagepocket/lib 0.7.1 → 0.8.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.
Files changed (261) hide show
  1. package/README.md +7 -6
  2. package/dist/build-snapshot-from-bundle.d.ts +23 -0
  3. package/dist/build-snapshot-from-bundle.js +68 -0
  4. package/dist/builtin-blacklist.js +3 -6
  5. package/dist/bundle/from-network-store.d.ts +10 -0
  6. package/dist/bundle/from-network-store.js +26 -0
  7. package/dist/bundle/types.d.ts +32 -0
  8. package/dist/bundle/types.js +2 -0
  9. package/dist/capture/index.d.ts +14 -0
  10. package/dist/capture/index.js +86 -0
  11. package/dist/capture/memory-content-store.d.ts +4 -0
  12. package/dist/capture/memory-content-store.js +42 -0
  13. package/dist/capture/types.d.ts +61 -0
  14. package/dist/capture/types.js +2 -0
  15. package/dist/content-store.js +3 -8
  16. package/dist/content-type.d.ts +1 -1
  17. package/dist/content-type.js +2 -28
  18. package/dist/core/_impl/completion.d.ts +4 -0
  19. package/dist/core/_impl/completion.js +29 -0
  20. package/dist/core/_impl/content-store.d.ts +21 -0
  21. package/dist/core/_impl/content-store.js +91 -0
  22. package/dist/core/_impl/debug.d.ts +1 -0
  23. package/dist/core/_impl/debug.js +16 -0
  24. package/dist/core/_impl/inflight-tracker.d.ts +19 -0
  25. package/dist/core/_impl/inflight-tracker.js +48 -0
  26. package/dist/core/_impl/pagepocket.d.ts +27 -0
  27. package/dist/core/_impl/pagepocket.js +155 -0
  28. package/dist/core/capture/_impl/memory-content-store.d.ts +4 -0
  29. package/dist/core/capture/_impl/memory-content-store.js +42 -0
  30. package/dist/core/capture/_impl/types.d.ts +61 -0
  31. package/dist/core/capture/_impl/types.js +2 -0
  32. package/dist/core/capture/internal/memory-content-store.d.ts +4 -0
  33. package/dist/core/capture/internal/memory-content-store.js +42 -0
  34. package/dist/core/capture/internal/types.d.ts +61 -0
  35. package/dist/core/capture/internal/types.js +2 -0
  36. package/dist/core/capture/memory-content-store.d.ts +4 -0
  37. package/dist/core/capture/memory-content-store.js +38 -0
  38. package/dist/core/capture/types.d.ts +61 -0
  39. package/dist/core/capture/types.js +1 -0
  40. package/dist/core/completion.d.ts +4 -0
  41. package/dist/core/completion.js +23 -0
  42. package/dist/core/content-store.d.ts +21 -0
  43. package/dist/core/content-store.js +54 -0
  44. package/dist/core/debug.d.ts +1 -0
  45. package/dist/core/debug.js +12 -0
  46. package/dist/core/file-tree-merge.d.ts +2 -0
  47. package/dist/core/file-tree-merge.js +27 -0
  48. package/dist/core/file-tree.d.ts +36 -0
  49. package/dist/core/file-tree.js +1 -0
  50. package/dist/core/inflight-tracker.d.ts +19 -0
  51. package/dist/core/inflight-tracker.js +44 -0
  52. package/dist/core/internal/completion.d.ts +4 -0
  53. package/dist/core/internal/completion.js +29 -0
  54. package/dist/core/internal/content-store.d.ts +21 -0
  55. package/dist/core/internal/content-store.js +91 -0
  56. package/dist/core/internal/debug.d.ts +1 -0
  57. package/dist/core/internal/debug.js +16 -0
  58. package/dist/core/internal/inflight-tracker.d.ts +19 -0
  59. package/dist/core/internal/inflight-tracker.js +48 -0
  60. package/dist/core/internal/pagepocket.d.ts +27 -0
  61. package/dist/core/internal/pagepocket.js +155 -0
  62. package/dist/core/pagepocket.d.ts +38 -0
  63. package/dist/core/pagepocket.js +57 -0
  64. package/dist/core/plugin/_impl/context.d.ts +47 -0
  65. package/dist/core/plugin/_impl/context.js +142 -0
  66. package/dist/core/plugin/_impl/runner.d.ts +12 -0
  67. package/dist/core/plugin/_impl/runner.js +232 -0
  68. package/dist/core/plugin/_impl/types.d.ts +108 -0
  69. package/dist/core/plugin/_impl/types.js +2 -0
  70. package/dist/core/plugin/context.d.ts +47 -0
  71. package/dist/core/plugin/context.js +205 -0
  72. package/dist/core/plugin/internal/context.d.ts +47 -0
  73. package/dist/core/plugin/internal/context.js +142 -0
  74. package/dist/core/plugin/internal/runner.d.ts +12 -0
  75. package/dist/core/plugin/internal/runner.js +232 -0
  76. package/dist/core/plugin/internal/types.d.ts +108 -0
  77. package/dist/core/plugin/internal/types.js +2 -0
  78. package/dist/core/plugin/runner-utils.d.ts +9 -0
  79. package/dist/core/plugin/runner-utils.js +29 -0
  80. package/dist/core/plugin/runner.d.ts +12 -0
  81. package/dist/core/plugin/runner.js +118 -0
  82. package/dist/core/plugin/types.d.ts +117 -0
  83. package/dist/core/plugin/types.js +1 -0
  84. package/dist/core/runtime/types.d.ts +14 -0
  85. package/dist/core/runtime/types.js +2 -0
  86. package/dist/css-rewrite.js +1 -5
  87. package/dist/debug.d.ts +0 -1
  88. package/dist/debug.js +3 -5
  89. package/dist/files/types.d.ts +41 -0
  90. package/dist/files/types.js +2 -0
  91. package/dist/hack-html.js +20 -13
  92. package/dist/hackers/index.d.ts +1 -1
  93. package/dist/hackers/index.js +24 -27
  94. package/dist/hackers/preload-fetch.d.ts +1 -1
  95. package/dist/hackers/preload-fetch.js +1 -4
  96. package/dist/hackers/preload-xhr.d.ts +1 -1
  97. package/dist/hackers/preload-xhr.js +1 -4
  98. package/dist/hackers/replay-beacon.d.ts +1 -1
  99. package/dist/hackers/replay-beacon.js +1 -4
  100. package/dist/hackers/replay-block-text-fragment.d.ts +1 -1
  101. package/dist/hackers/replay-block-text-fragment.js +1 -4
  102. package/dist/hackers/replay-css-proxy.d.ts +1 -1
  103. package/dist/hackers/replay-css-proxy.js +9 -12
  104. package/dist/hackers/replay-dom-rewrite.d.ts +1 -1
  105. package/dist/hackers/replay-dom-rewrite.js +165 -154
  106. package/dist/hackers/replay-eventsource.d.ts +1 -1
  107. package/dist/hackers/replay-eventsource.js +1 -4
  108. package/dist/hackers/replay-fetch.d.ts +1 -1
  109. package/dist/hackers/replay-fetch.js +1 -4
  110. package/dist/hackers/replay-history-path.d.ts +1 -1
  111. package/dist/hackers/replay-history-path.js +1 -4
  112. package/dist/hackers/replay-svg-image.d.ts +1 -1
  113. package/dist/hackers/replay-svg-image.js +1 -4
  114. package/dist/hackers/replay-websocket.d.ts +1 -1
  115. package/dist/hackers/replay-websocket.js +1 -4
  116. package/dist/hackers/replay-xhr.d.ts +1 -1
  117. package/dist/hackers/replay-xhr.js +1 -4
  118. package/dist/hackers/types.js +1 -2
  119. package/dist/index.d.ts +29 -13
  120. package/dist/index.js +23 -44
  121. package/dist/kind-map.d.ts +68 -0
  122. package/dist/kind-map.js +58 -0
  123. package/dist/network-store.js +12 -1
  124. package/dist/pagepocket.d.ts +19 -4
  125. package/dist/pagepocket.js +36 -102
  126. package/dist/path-resolver.d.ts +1 -2
  127. package/dist/path-resolver.js +9 -16
  128. package/dist/plugin/builtins/build-snapshot-plugin.d.ts +5 -0
  129. package/dist/plugin/builtins/build-snapshot-plugin.js +84 -0
  130. package/dist/plugin/builtins/replace-elements-plugin.d.ts +8 -0
  131. package/dist/plugin/builtins/replace-elements-plugin.js +13 -0
  132. package/dist/plugin/builtins/to-directory-plugin.d.ts +7 -0
  133. package/dist/plugin/builtins/to-directory-plugin.js +20 -0
  134. package/dist/plugin/builtins/to-zip-plugin.d.ts +5 -0
  135. package/dist/plugin/builtins/to-zip-plugin.js +19 -0
  136. package/dist/plugin/context.d.ts +47 -0
  137. package/dist/plugin/context.js +142 -0
  138. package/dist/plugin/runner.d.ts +12 -0
  139. package/dist/plugin/runner.js +232 -0
  140. package/dist/plugin/types.d.ts +108 -0
  141. package/dist/plugin/types.js +2 -0
  142. package/dist/plugins/build-files-from-capture.d.ts +5 -0
  143. package/dist/plugins/build-files-from-capture.js +85 -0
  144. package/dist/plugins/build-warc.d.ts +5 -0
  145. package/dist/plugins/build-warc.js +225 -0
  146. package/dist/plugins/builtins/manifest.d.ts +2 -0
  147. package/dist/plugins/builtins/manifest.js +42 -0
  148. package/dist/plugins/builtins/snapshot-directory.d.ts +2 -0
  149. package/dist/plugins/builtins/snapshot-directory.js +24 -0
  150. package/dist/plugins/builtins/snapshot-zip.d.ts +2 -0
  151. package/dist/plugins/builtins/snapshot-zip.js +25 -0
  152. package/dist/plugins/capture-http-lighterceptor.d.ts +5 -0
  153. package/dist/plugins/capture-http-lighterceptor.js +85 -0
  154. package/dist/plugins/capture-http-puppeteer.d.ts +5 -0
  155. package/dist/plugins/capture-http-puppeteer.js +85 -0
  156. package/dist/plugins/host.d.ts +37 -0
  157. package/dist/plugins/host.js +105 -0
  158. package/dist/plugins/index.d.ts +6 -0
  159. package/dist/plugins/index.js +11 -0
  160. package/dist/plugins/ordering.d.ts +2 -0
  161. package/dist/plugins/ordering.js +19 -0
  162. package/dist/plugins/types.d.ts +51 -0
  163. package/dist/plugins/types.js +2 -0
  164. package/dist/preload.js +3 -7
  165. package/dist/replace-elements/actions.d.ts +5 -0
  166. package/dist/replace-elements/actions.js +86 -0
  167. package/dist/replace-elements/match.d.ts +5 -0
  168. package/dist/replace-elements/match.js +46 -0
  169. package/dist/replace-elements/normalize.d.ts +21 -0
  170. package/dist/replace-elements/normalize.js +50 -0
  171. package/dist/replace-elements.d.ts +1 -1
  172. package/dist/replace-elements.js +5 -185
  173. package/dist/replay/match-api.d.ts +10 -0
  174. package/dist/replay/match-api.js +162 -0
  175. package/dist/replay/templates/match-api-source.d.ts +1 -0
  176. package/dist/replay/templates/match-api-source.js +137 -0
  177. package/dist/replay/templates/replay-script-template.d.ts +5 -0
  178. package/dist/replay/templates/replay-script-template.js +337 -0
  179. package/dist/replay/templates/resource-proxy-script.d.ts +1 -0
  180. package/dist/replay/templates/resource-proxy-script.js +274 -0
  181. package/dist/replay-script.d.ts +3 -10
  182. package/dist/replay-script.js +11 -625
  183. package/dist/resource-filter.d.ts +1 -1
  184. package/dist/resource-filter.js +1 -5
  185. package/dist/resource-proxy/escape-percent.d.ts +1 -0
  186. package/dist/resource-proxy/escape-percent.js +12 -0
  187. package/dist/resource-proxy/multimap.d.ts +3 -0
  188. package/dist/resource-proxy/multimap.js +18 -0
  189. package/dist/resource-proxy/pathname-variants.d.ts +3 -0
  190. package/dist/resource-proxy/pathname-variants.js +54 -0
  191. package/dist/resource-proxy.d.ts +4 -2
  192. package/dist/resource-proxy.js +48 -117
  193. package/dist/resources.js +4 -42
  194. package/dist/rewrite-links/js-imports.d.ts +3 -0
  195. package/dist/rewrite-links/js-imports.js +56 -0
  196. package/dist/rewrite-links/link-rel.d.ts +2 -0
  197. package/dist/rewrite-links/link-rel.js +10 -0
  198. package/dist/rewrite-links/meta-refresh.d.ts +3 -0
  199. package/dist/rewrite-links/meta-refresh.js +22 -0
  200. package/dist/rewrite-links/skip.d.ts +1 -0
  201. package/dist/rewrite-links/skip.js +10 -0
  202. package/dist/rewrite-links/srcset.d.ts +3 -0
  203. package/dist/rewrite-links/srcset.js +63 -0
  204. package/dist/rewrite-links/url-resolve.d.ts +3 -0
  205. package/dist/rewrite-links/url-resolve.js +13 -0
  206. package/dist/rewrite-links.d.ts +3 -3
  207. package/dist/rewrite-links.js +31 -240
  208. package/dist/snapshot-builder/api.d.ts +3 -0
  209. package/dist/snapshot-builder/api.js +6 -0
  210. package/dist/snapshot-builder/build-snapshot.d.ts +3 -0
  211. package/dist/snapshot-builder/build-snapshot.js +138 -0
  212. package/dist/snapshot-builder/capture-index/index-capture.d.ts +13 -0
  213. package/dist/snapshot-builder/capture-index/index-capture.js +168 -0
  214. package/dist/snapshot-builder/capture-index/index.d.ts +2 -0
  215. package/dist/snapshot-builder/capture-index/index.js +1 -0
  216. package/dist/snapshot-builder/capture-index/types.d.ts +12 -0
  217. package/dist/snapshot-builder/capture-index/types.js +1 -0
  218. package/dist/snapshot-builder/capture-index.d.ts +12 -0
  219. package/dist/snapshot-builder/capture-index.js +173 -0
  220. package/dist/snapshot-builder/emit-document.d.ts +24 -0
  221. package/dist/snapshot-builder/emit-document.js +50 -0
  222. package/dist/snapshot-builder/grouping.d.ts +8 -0
  223. package/dist/snapshot-builder/grouping.js +87 -0
  224. package/dist/snapshot-builder/http.d.ts +6 -0
  225. package/dist/snapshot-builder/http.js +28 -0
  226. package/dist/snapshot-builder/index.d.ts +4 -0
  227. package/dist/snapshot-builder/index.js +2 -0
  228. package/dist/snapshot-builder/path-map.d.ts +3 -0
  229. package/dist/snapshot-builder/path-map.js +35 -0
  230. package/dist/snapshot-builder/resources-path.d.ts +23 -0
  231. package/dist/snapshot-builder/resources-path.js +47 -0
  232. package/dist/snapshot-builder/rewrite-resource.d.ts +18 -0
  233. package/dist/snapshot-builder/rewrite-resource.js +52 -0
  234. package/dist/snapshot-builder/types.d.ts +37 -0
  235. package/dist/snapshot-builder/types.js +2 -0
  236. package/dist/snapshot-builder.d.ts +12 -8
  237. package/dist/snapshot-builder.js +252 -27
  238. package/dist/types.d.ts +122 -78
  239. package/dist/types.js +4 -2
  240. package/dist/units/contracts-bridge.d.ts +76 -0
  241. package/dist/units/contracts-bridge.js +6 -0
  242. package/dist/units/index.d.ts +4 -0
  243. package/dist/units/index.js +2 -0
  244. package/dist/units/runner.d.ts +11 -0
  245. package/dist/units/runner.js +270 -0
  246. package/dist/units/types.d.ts +39 -0
  247. package/dist/units/types.js +1 -0
  248. package/dist/utils/streams.d.ts +2 -0
  249. package/dist/utils/streams.js +29 -0
  250. package/dist/utils.d.ts +35 -1
  251. package/dist/utils.js +107 -29
  252. package/dist/v3/contracts-bridge.d.ts +69 -0
  253. package/dist/v3/contracts-bridge.js +5 -0
  254. package/dist/v3/index.d.ts +4 -0
  255. package/dist/v3/index.js +2 -0
  256. package/dist/v3/runner.d.ts +20 -0
  257. package/dist/v3/runner.js +245 -0
  258. package/dist/v3/types.d.ts +39 -0
  259. package/dist/v3/types.js +1 -0
  260. package/dist/writers.js +3 -1
  261. package/package.json +11 -3
package/dist/index.js CHANGED
@@ -1,44 +1,23 @@
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.applyReplaceElements = exports.toZip = exports.writeToFS = exports.rewriteCssText = exports.rewriteJsText = exports.rewriteEntryHtml = exports.buildPreloadScript = exports.buildReplayScript = exports.timeout = exports.networkIdle = exports.createDefaultResourceFilter = exports.withPrefixPathResolver = exports.createDefaultPathResolver = exports.HybridContentStore = exports.PagePocket = void 0;
18
- var pagepocket_1 = require("./pagepocket");
19
- Object.defineProperty(exports, "PagePocket", { enumerable: true, get: function () { return pagepocket_1.PagePocket; } });
20
- var content_store_1 = require("./content-store");
21
- Object.defineProperty(exports, "HybridContentStore", { enumerable: true, get: function () { return content_store_1.HybridContentStore; } });
22
- var path_resolver_1 = require("./path-resolver");
23
- Object.defineProperty(exports, "createDefaultPathResolver", { enumerable: true, get: function () { return path_resolver_1.createDefaultPathResolver; } });
24
- Object.defineProperty(exports, "withPrefixPathResolver", { enumerable: true, get: function () { return path_resolver_1.withPrefixPathResolver; } });
25
- var resource_filter_1 = require("./resource-filter");
26
- Object.defineProperty(exports, "createDefaultResourceFilter", { enumerable: true, get: function () { return resource_filter_1.createDefaultResourceFilter; } });
27
- __exportStar(require("./builtin-blacklist"), exports);
28
- var completion_1 = require("./completion");
29
- Object.defineProperty(exports, "networkIdle", { enumerable: true, get: function () { return completion_1.networkIdle; } });
30
- Object.defineProperty(exports, "timeout", { enumerable: true, get: function () { return completion_1.timeout; } });
31
- var replay_script_1 = require("./replay-script");
32
- Object.defineProperty(exports, "buildReplayScript", { enumerable: true, get: function () { return replay_script_1.buildReplayScript; } });
33
- var preload_1 = require("./preload");
34
- Object.defineProperty(exports, "buildPreloadScript", { enumerable: true, get: function () { return preload_1.buildPreloadScript; } });
35
- var rewrite_links_1 = require("./rewrite-links");
36
- Object.defineProperty(exports, "rewriteEntryHtml", { enumerable: true, get: function () { return rewrite_links_1.rewriteEntryHtml; } });
37
- Object.defineProperty(exports, "rewriteJsText", { enumerable: true, get: function () { return rewrite_links_1.rewriteJsText; } });
38
- var css_rewrite_1 = require("./css-rewrite");
39
- Object.defineProperty(exports, "rewriteCssText", { enumerable: true, get: function () { return css_rewrite_1.rewriteCssText; } });
40
- var writers_1 = require("./writers");
41
- Object.defineProperty(exports, "writeToFS", { enumerable: true, get: function () { return writers_1.writeToFS; } });
42
- Object.defineProperty(exports, "toZip", { enumerable: true, get: function () { return writers_1.toZip; } });
43
- var replace_elements_1 = require("./replace-elements");
44
- Object.defineProperty(exports, "applyReplaceElements", { enumerable: true, get: function () { return replace_elements_1.applyReplaceElements; } });
1
+ export { PagePocket } from "./core/pagepocket.js";
2
+ // New Units/Plugins API (break change).
3
+ export * from "./units/index.js";
4
+ export { TERMINAL_RESULT_KEY } from "./units/contracts-bridge.js";
5
+ export { TriggerActionValues } from "./types.js";
6
+ export { HybridContentStore } from "./core/content-store.js";
7
+ export { createDefaultPathResolver, withPrefixPathResolver } from "./path-resolver.js";
8
+ export { createDefaultResourceFilter } from "./resource-filter.js";
9
+ export { buildSnapshot } from "./snapshot-builder/index.js";
10
+ export * from "./builtin-blacklist.js";
11
+ export { networkIdle, timeout } from "./core/completion.js";
12
+ export { normalizeCompletion } from "./core/completion.js";
13
+ export { debugLog } from "./core/debug.js";
14
+ export { InflightTracker } from "./core/inflight-tracker.js";
15
+ export { mergeFileTrees } from "./core/file-tree-merge.js";
16
+ export { createMemoryContentStore } from "./core/capture/memory-content-store.js";
17
+ export { buildReplayScript } from "./replay-script.js";
18
+ export { buildPreloadScript } from "./preload.js";
19
+ export { rewriteEntryHtml, rewriteJsText } from "./rewrite-links.js";
20
+ export { rewriteCssText } from "./css-rewrite.js";
21
+ export { applyReplaceElements } from "./replace-elements.js";
22
+ export { streamToUint8Array, streamFromUint8Array } from "./utils/streams.js";
23
+ export { mapKind, requiredEntryKindError, throwRequiredEntryKind, throwUnsupportedEntryKind, unsupportedEntryKindError } from "./kind-map.js";
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Partial mapping from a discriminated union member to a result.
3
+ *
4
+ * Keys are the union's `kind` values; each value is a lazy builder function.
5
+ */
6
+ export type KindBuilders<Entry extends {
7
+ kind: string;
8
+ }, Result> = Partial<{
9
+ [K in Entry["kind"]]: (entry: Extract<Entry, {
10
+ kind: K;
11
+ }>) => Result;
12
+ }>;
13
+ type BuilderReturn<F> = F extends (...args: any[]) => infer R ? R : never;
14
+ type BuildersResult<Builders> = BuilderReturn<NonNullable<Builders[keyof Builders]>>;
15
+ /**
16
+ * Generic helper for mapping discriminated unions by `kind`.
17
+ *
18
+ * This is useful when you want an object-based alternative to a switch statement.
19
+ * It preserves runtime safety by delegating unsupported kinds to a handler.
20
+ *
21
+ * Notes:
22
+ * - The builder map is intentionally partial: unsupported kinds are handled via
23
+ * `onUnsupportedKind` (typically: throw).
24
+ * - The values should be functions (lazy) to avoid reading fields that do not
25
+ * exist on other union members.
26
+ */
27
+ export declare const mapKind: <Entry extends {
28
+ kind: string;
29
+ }, Builders extends KindBuilders<Entry, unknown>>(entry: Entry, builders: Builders, options: {
30
+ /**
31
+ * Called when `entry.kind` is not present in `builders`.
32
+ * Should throw.
33
+ */
34
+ onUnsupportedKind: (kind: Entry["kind"], entry: Entry) => never;
35
+ }) => BuildersResult<Builders>;
36
+ /**
37
+ * Standard error for capture units that build an InterceptTarget from runtime entry.
38
+ *
39
+ * Format matches existing unit errors:
40
+ * "<UnitName> does not support entry kind: <kind>"
41
+ */
42
+ export declare const unsupportedEntryKindError: (unitName: string, entry: {
43
+ kind: unknown;
44
+ }) => Error;
45
+ /**
46
+ * Standard error for capture units that *require* a specific entry kind.
47
+ *
48
+ * Format matches existing unit errors:
49
+ * "<UnitName> requires entry kind \"<required>\" (got <kind>)"
50
+ */
51
+ export declare const requiredEntryKindError: (unitName: string, requiredKind: string, entry: {
52
+ kind: unknown;
53
+ }) => Error;
54
+ /**
55
+ * Convenience handler for `mapKind` that throws a standardized
56
+ * "does not support entry kind" error.
57
+ */
58
+ export declare const throwUnsupportedEntryKind: (unitName: string) => (_kind: string, entry: {
59
+ kind: unknown;
60
+ }) => never;
61
+ /**
62
+ * Convenience handler for `mapKind` that throws a standardized
63
+ * "requires entry kind" error.
64
+ */
65
+ export declare const throwRequiredEntryKind: (unitName: string, requiredKind: string) => (_kind: string, entry: {
66
+ kind: unknown;
67
+ }) => never;
68
+ export {};
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Generic helper for mapping discriminated unions by `kind`.
3
+ *
4
+ * This is useful when you want an object-based alternative to a switch statement.
5
+ * It preserves runtime safety by delegating unsupported kinds to a handler.
6
+ *
7
+ * Notes:
8
+ * - The builder map is intentionally partial: unsupported kinds are handled via
9
+ * `onUnsupportedKind` (typically: throw).
10
+ * - The values should be functions (lazy) to avoid reading fields that do not
11
+ * exist on other union members.
12
+ */
13
+ export const mapKind = (entry, builders, options) => {
14
+ const hasBuilder = Object.prototype.hasOwnProperty.call(builders, entry.kind);
15
+ const builder = hasBuilder ? builders[entry.kind] : undefined;
16
+ if (!builder) {
17
+ return options.onUnsupportedKind(entry.kind, entry);
18
+ }
19
+ return builder(entry);
20
+ };
21
+ /**
22
+ * Standard error for capture units that build an InterceptTarget from runtime entry.
23
+ *
24
+ * Format matches existing unit errors:
25
+ * "<UnitName> does not support entry kind: <kind>"
26
+ */
27
+ export const unsupportedEntryKindError = (unitName, entry) => {
28
+ const kind = entry.kind;
29
+ return new Error(`${unitName} does not support entry kind: ${String(kind)}`);
30
+ };
31
+ /**
32
+ * Standard error for capture units that *require* a specific entry kind.
33
+ *
34
+ * Format matches existing unit errors:
35
+ * "<UnitName> requires entry kind \"<required>\" (got <kind>)"
36
+ */
37
+ export const requiredEntryKindError = (unitName, requiredKind, entry) => {
38
+ const kind = entry.kind;
39
+ return new Error(`${unitName} requires entry kind "${requiredKind}" (got ${String(kind)})`);
40
+ };
41
+ /**
42
+ * Convenience handler for `mapKind` that throws a standardized
43
+ * "does not support entry kind" error.
44
+ */
45
+ export const throwUnsupportedEntryKind = (unitName) => {
46
+ return (_kind, entry) => {
47
+ throw unsupportedEntryKindError(unitName, entry);
48
+ };
49
+ };
50
+ /**
51
+ * Convenience handler for `mapKind` that throws a standardized
52
+ * "requires entry kind" error.
53
+ */
54
+ export const throwRequiredEntryKind = (unitName, requiredKind) => {
55
+ return (_kind, entry) => {
56
+ throw requiredEntryKindError(unitName, requiredKind, entry);
57
+ };
58
+ };
@@ -15,6 +15,17 @@ const getHeaderValue = (headers, name) => {
15
15
  }
16
16
  return undefined;
17
17
  };
18
+ const parseContentLength = (headers) => {
19
+ const raw = getHeaderValue(headers, "content-length");
20
+ if (!raw) {
21
+ return undefined;
22
+ }
23
+ const parsed = Number(raw);
24
+ if (!Number.isFinite(parsed) || parsed <= 0) {
25
+ return undefined;
26
+ }
27
+ return parsed;
28
+ };
18
29
  const responseMimeType = (response) => response.mimeType || getHeaderValue(response.headers || {}, "content-type");
19
30
  class NetworkStore {
20
31
  constructor(options) {
@@ -107,7 +118,7 @@ class NetworkStore {
107
118
  request,
108
119
  response,
109
120
  contentRef,
110
- size: bodyBytes.byteLength,
121
+ size: parseContentLength(response.headers || {}) ?? bodyBytes.byteLength,
111
122
  mimeType: responseMimeType(response)
112
123
  };
113
124
  this.storedResources.push(stored);
@@ -1,12 +1,27 @@
1
- import type { InterceptTarget } from "@pagepocket/interceptor";
2
- import type { CaptureOptions, NetworkEventStream, PagePocketOptions, PageSnapshot } from "./types";
1
+ import type { NetworkEvent } from "@pagepocket/interceptor";
2
+ import type { NetworkEventStream, PagePocketOptions } from "./types";
3
+ import type { CaptureWithPluginsOptions, PagePocketCaptureResult } from "./plugin/types";
3
4
  export declare class PagePocket {
4
5
  private target;
5
6
  private options;
6
7
  private eventStream;
7
8
  private constructor();
8
9
  static fromURL(url: string, options?: PagePocketOptions): PagePocket;
9
- static fromTarget(target: InterceptTarget, options?: PagePocketOptions): PagePocket;
10
+ static fromPuppeteerPage(page: unknown, options?: PagePocketOptions): PagePocket;
11
+ static fromCDPTab(tabId: number, options?: PagePocketOptions): PagePocket;
12
+ static fromHTMLString(htmlString: string, options: {
13
+ baseUrl: string;
14
+ url?: string;
15
+ } & PagePocketOptions): PagePocket;
10
16
  interceptedRequestEvents(): NetworkEventStream;
11
- capture(options?: CaptureOptions): Promise<PageSnapshot>;
17
+ /** @internal */
18
+ _emitNetworkEvent(event: NetworkEvent): void;
19
+ /** @internal */
20
+ _closeNetworkEventStream(): void;
21
+ static fromDocument(doc: unknown, options: {
22
+ baseUrl: string;
23
+ url?: string;
24
+ serialize?: (doc: unknown) => string;
25
+ } & PagePocketOptions): PagePocket;
26
+ capture(options: CaptureWithPluginsOptions): Promise<PagePocketCaptureResult>;
12
27
  }
@@ -1,14 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PagePocket = void 0;
4
- const completion_1 = require("./completion");
5
- const content_store_1 = require("./content-store");
6
- const debug_1 = require("./debug");
7
- const inflight_tracker_1 = require("./inflight-tracker");
8
- const network_store_1 = require("./network-store");
9
- const path_resolver_1 = require("./path-resolver");
10
- const resource_filter_1 = require("./resource-filter");
11
- const snapshot_builder_1 = require("./snapshot-builder");
4
+ const runner_1 = require("./plugin/runner");
12
5
  class AsyncEventQueue {
13
6
  constructor() {
14
7
  this.values = [];
@@ -114,107 +107,48 @@ class PagePocket {
114
107
  static fromURL(url, options) {
115
108
  return new PagePocket({ kind: "url", url }, options);
116
109
  }
117
- static fromTarget(target, options) {
118
- return new PagePocket(target, options);
110
+ static fromPuppeteerPage(page, options) {
111
+ return new PagePocket({ kind: "puppeteer-page", page }, options);
112
+ }
113
+ static fromCDPTab(tabId, options) {
114
+ return new PagePocket({ kind: "cdp-tab", tabId }, options);
115
+ }
116
+ static fromHTMLString(htmlString, options) {
117
+ const { baseUrl, url, ...rest } = options;
118
+ return new PagePocket({ kind: "html", htmlString, baseUrl, ...(url ? { url } : {}) }, rest);
119
119
  }
120
120
  interceptedRequestEvents() {
121
121
  return this.eventStream.subscribe();
122
122
  }
123
- async capture(options) {
124
- if (!options?.interceptor) {
125
- throw new Error("CaptureOptions.interceptor is required.");
126
- }
127
- const contentStore = options?.contentStore ?? new content_store_1.HybridContentStore();
128
- const baseFilter = options?.filter ?? (0, resource_filter_1.createDefaultResourceFilter)();
129
- const blacklist = options?.blacklist ?? [];
130
- const isBlacklisted = (url) => typeof url === "string" && blacklist.some((pattern) => pattern.test(url));
131
- const filter = blacklist.length === 0
132
- ? baseFilter
133
- : {
134
- shouldSave(req, res) {
135
- if (isBlacklisted(req.url)) {
136
- (0, debug_1.debug_log)("[pagepocket] blacklist match (skip save)", req.url);
137
- return false;
123
+ /** @internal */
124
+ _emitNetworkEvent(event) {
125
+ this.eventStream.emit(event);
126
+ }
127
+ /** @internal */
128
+ _closeNetworkEventStream() {
129
+ this.eventStream.close();
130
+ }
131
+ static fromDocument(doc, options) {
132
+ const serialize = options.serialize ??
133
+ ((value) => {
134
+ if (value && typeof value === "object" && "documentElement" in value) {
135
+ const el = value.documentElement;
136
+ if (el && typeof el.outerHTML === "string") {
137
+ return el.outerHTML;
138
138
  }
139
- return baseFilter.shouldSave(req, res);
140
- }
141
- };
142
- const pathResolver = options?.pathResolver ?? (0, path_resolver_1.createDefaultPathResolver)();
143
- const rewriteEntry = options?.rewriteEntry ?? true;
144
- const rewriteCSS = options?.rewriteCSS ?? true;
145
- const replaceElements = options?.replaceElements;
146
- const limits = options?.limits;
147
- const completionStrategies = (0, completion_1.normalizeCompletion)(options?.completion);
148
- const idleMs = options?.timeoutMs ?? 5000;
149
- const maxDurationMs = options?.maxDurationMs;
150
- const completion = completionStrategies.length > 0
151
- ? completionStrategies
152
- : [(0, completion_1.networkIdle)(idleMs), ...(maxDurationMs !== undefined ? [(0, completion_1.timeout)(maxDurationMs)] : [])];
153
- const store = new network_store_1.NetworkStore({
154
- contentStore,
155
- filter,
156
- limits
157
- });
158
- const inflightTracker = new inflight_tracker_1.InflightTracker({
159
- shouldIgnore: (event) => {
160
- if (!isBlacklisted(event.url)) {
161
- return false;
162
139
  }
163
- (0, debug_1.debug_log)("[pagepocket] blacklist match (ignore inflight)", event.url);
164
- return true;
165
- }
166
- });
167
- const getStats = () => {
168
- const stats = inflightTracker.getStats();
169
- (0, debug_1.debug_log)("[pagepocket] stats", stats);
170
- return stats;
171
- };
172
- const pendingEvents = new Set();
173
- const onEvent = (event) => {
174
- this.eventStream.emit(event);
175
- const stats = inflightTracker.handleEvent(event);
176
- (0, debug_1.debug_log)("[pagepocket] inflight", stats.inflightRequests, "event", event.type, event.requestId, event.url);
177
- const task = store.handleEvent(event);
178
- pendingEvents.add(task);
179
- task.finally(() => pendingEvents.delete(task));
180
- };
181
- (0, debug_1.debug_log)("[pagepocket] session start");
182
- const session = await options.interceptor.start(this.target, { onEvent }, { timeoutMs: options?.timeoutMs, maxDurationMs: options?.maxDurationMs });
183
- (0, debug_1.debug_log)("[pagepocket] session started");
184
- if (this.target.kind === "url" && session?.navigate) {
185
- (0, debug_1.debug_log)("[pagepocket] navigate", this.target.url);
186
- await session.navigate(this.target.url);
187
- (0, debug_1.debug_log)("[pagepocket] navigated");
188
- }
189
- if (completion.length === 1) {
190
- await completion[0].wait({
191
- now: () => Date.now(),
192
- getStats
140
+ throw new Error("fromDocument requires options.serialize(doc) or doc.documentElement.outerHTML");
193
141
  });
194
- }
195
- else if (completion.length > 1) {
196
- await Promise.race(completion.map((strategy) => strategy.wait({
197
- now: () => Date.now(),
198
- getStats
199
- })));
200
- }
201
- (0, debug_1.debug_log)("[pagepocket] session stop");
202
- await session.stop();
203
- (0, debug_1.debug_log)("[pagepocket] session stopped");
204
- await Promise.all(pendingEvents);
205
- this.eventStream.close();
206
- const entryUrl = this.target.kind === "url" ? this.target.url : "";
207
- return (0, snapshot_builder_1.buildSnapshot)({
208
- entryUrl,
209
- createdAt: Date.now(),
210
- resources: store.getResources(),
211
- apiEntries: store.getApiEntries(),
212
- contentStore,
213
- pathResolver,
214
- rewriteEntry,
215
- rewriteCSS,
216
- replaceElements,
217
- warnings: store.getWarnings()
142
+ const htmlString = serialize(doc);
143
+ const { baseUrl, url, serialize: _serialize, ...rest } = options;
144
+ return new PagePocket({ kind: "html", htmlString, baseUrl, ...(url ? { url } : {}) }, rest);
145
+ }
146
+ async capture(options) {
147
+ return (0, runner_1.captureWithPlugins)({
148
+ pocket: this,
149
+ pocketOptions: this.options,
150
+ target: this.target,
151
+ options
218
152
  });
219
153
  }
220
154
  }
@@ -1,5 +1,4 @@
1
- import type { ResourceType } from "@pagepocket/interceptor";
2
- import type { PathResolver } from "./types";
1
+ import type { PathResolver, ResourceType } from "./types.js";
3
2
  export declare const createDefaultPathResolver: () => PathResolver;
4
3
  export declare const resolveCrossOrigin: (url: string, entryUrl: string) => boolean;
5
4
  export declare const withPrefixPathResolver: (resolver: PathResolver, prefix: string) => PathResolver;
@@ -1,11 +1,8 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isDocumentType = exports.withPrefixPathResolver = exports.resolveCrossOrigin = exports.createDefaultPathResolver = void 0;
4
- const utils_1 = require("./utils");
1
+ import { hashString, sanitizePosixPath } from "./utils.js";
5
2
  const normalizePathname = (pathname) => {
6
3
  const normalized = pathname || "/";
7
4
  const hasTrailingSlash = normalized.endsWith("/");
8
- const clean = (0, utils_1.sanitizePosixPath)(normalized);
5
+ const clean = sanitizePosixPath(normalized);
9
6
  const parts = clean.split("/").filter(Boolean);
10
7
  if (hasTrailingSlash) {
11
8
  parts.push("index");
@@ -30,7 +27,7 @@ const withSuffix = (path, suffix) => {
30
27
  return `${path}${suffix}`;
31
28
  };
32
29
  const sameDomain = (left, right) => left.hostname === right.hostname;
33
- const createDefaultPathResolver = () => {
30
+ export const createDefaultPathResolver = () => {
34
31
  const resolvedByUrl = new Map();
35
32
  const usedPaths = new Map();
36
33
  return {
@@ -52,13 +49,13 @@ const createDefaultPathResolver = () => {
52
49
  }
53
50
  const pathname = normalizePathname(parsed?.pathname || "/");
54
51
  const queryHash = `${parsed?.search || ""}${parsed?.hash || ""}`;
55
- const suffix = queryHash ? `__ppq_${(0, utils_1.hashString)(queryHash)}` : "";
52
+ const suffix = queryHash ? `__ppq_${hashString(queryHash)}` : "";
56
53
  const basePath = input.isCrossOrigin ? `/external_resources${pathname}` : `${pathname}`;
57
54
  let resolvedPath = suffix ? withSuffix(basePath, suffix) : basePath;
58
55
  const collisionKey = resolvedPath;
59
56
  const existingUrl = usedPaths.get(collisionKey);
60
57
  if (existingUrl && existingUrl !== input.url) {
61
- const collisionSuffix = `__ppc_${(0, utils_1.hashString)(input.url)}`;
58
+ const collisionSuffix = `__ppc_${hashString(input.url)}`;
62
59
  resolvedPath = withSuffix(resolvedPath, collisionSuffix);
63
60
  }
64
61
  usedPaths.set(resolvedPath, input.url);
@@ -67,8 +64,7 @@ const createDefaultPathResolver = () => {
67
64
  }
68
65
  };
69
66
  };
70
- exports.createDefaultPathResolver = createDefaultPathResolver;
71
- const resolveCrossOrigin = (url, entryUrl) => {
67
+ export const resolveCrossOrigin = (url, entryUrl) => {
72
68
  try {
73
69
  const parsed = new URL(url);
74
70
  const entry = new URL(entryUrl);
@@ -78,9 +74,8 @@ const resolveCrossOrigin = (url, entryUrl) => {
78
74
  return false;
79
75
  }
80
76
  };
81
- exports.resolveCrossOrigin = resolveCrossOrigin;
82
- const withPrefixPathResolver = (resolver, prefix) => {
83
- const normalizedPrefix = (0, utils_1.sanitizePosixPath)(prefix);
77
+ export const withPrefixPathResolver = (resolver, prefix) => {
78
+ const normalizedPrefix = sanitizePosixPath(prefix);
84
79
  if (!normalizedPrefix) {
85
80
  return resolver;
86
81
  }
@@ -95,6 +90,4 @@ const withPrefixPathResolver = (resolver, prefix) => {
95
90
  }
96
91
  };
97
92
  };
98
- exports.withPrefixPathResolver = withPrefixPathResolver;
99
- const isDocumentType = (resourceType) => resourceType === "document";
100
- exports.isDocumentType = isDocumentType;
93
+ export const isDocumentType = (resourceType) => resourceType === "document";
@@ -0,0 +1,5 @@
1
+ import type { PagePocketContext, PagePocketPlugin } from "../types";
2
+ export declare class BuildSnapshotPlugin implements PagePocketPlugin {
3
+ readonly name = "built-in:build-snapshot";
4
+ apply(ctx: PagePocketContext): void;
5
+ }
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BuildSnapshotPlugin = void 0;
4
+ const content_store_1 = require("../../content-store");
5
+ const debug_1 = require("../../debug");
6
+ const inflight_tracker_1 = require("../../inflight-tracker");
7
+ const network_store_1 = require("../../network-store");
8
+ const path_resolver_1 = require("../../path-resolver");
9
+ const resource_filter_1 = require("../../resource-filter");
10
+ const snapshot_builder_1 = require("../../snapshot-builder");
11
+ class BuildSnapshotPlugin {
12
+ constructor() {
13
+ this.name = "built-in:build-snapshot";
14
+ }
15
+ apply(ctx) {
16
+ const ctxInternal = ctx;
17
+ const contentStore = ctx.options.contentStore ?? new content_store_1.HybridContentStore();
18
+ const baseFilter = ctx.options.filter ?? (0, resource_filter_1.createDefaultResourceFilter)();
19
+ const blacklist = ctx.options.blacklist ?? [];
20
+ const isBlacklisted = (url) => typeof url === "string" && blacklist.some((pattern) => pattern.test(url));
21
+ const filter = blacklist.length === 0
22
+ ? baseFilter
23
+ : {
24
+ shouldSave(req, res) {
25
+ if (isBlacklisted(req.url)) {
26
+ (0, debug_1.debug_log)("[pagepocket] blacklist match (skip save)", req.url);
27
+ return false;
28
+ }
29
+ return baseFilter.shouldSave(req, res);
30
+ }
31
+ };
32
+ const pathResolver = ctx.options.pathResolver ?? (0, path_resolver_1.createDefaultPathResolver)();
33
+ const rewriteEntry = ctx.options.rewriteEntry ?? true;
34
+ const rewriteCSS = ctx.options.rewriteCSS ?? true;
35
+ const limits = ctx.options.limits;
36
+ const store = new network_store_1.NetworkStore({
37
+ contentStore,
38
+ filter,
39
+ limits
40
+ });
41
+ const inflightTracker = new inflight_tracker_1.InflightTracker({
42
+ shouldIgnore: (event) => {
43
+ if (!isBlacklisted(event.url)) {
44
+ return false;
45
+ }
46
+ (0, debug_1.debug_log)("[pagepocket] blacklist match (ignore inflight)", event.url);
47
+ return true;
48
+ }
49
+ });
50
+ ctx.onNetworkEvent(async (event) => {
51
+ inflightTracker.handleEvent(event);
52
+ await store.handleEvent(event);
53
+ });
54
+ ctx.onFinalize(async () => {
55
+ if (ctx.snapshot) {
56
+ return;
57
+ }
58
+ const entryUrl = ctx.entry.kind === "url"
59
+ ? ctx.entry.url
60
+ : ctx.entry.kind === "html-string"
61
+ ? (ctx.entry.url ?? ctx.entry.baseUrl)
62
+ : "";
63
+ const replaceElements = ctxInternal._replaceElements.length > 0 ? ctxInternal._replaceElements : undefined;
64
+ const replaceElementsMerged = replaceElements
65
+ ? replaceElements.flat()
66
+ : undefined;
67
+ const snapshot = await (0, snapshot_builder_1.buildSnapshot)({
68
+ entryUrl,
69
+ createdAt: Date.now(),
70
+ resources: store.getResources(),
71
+ apiEntries: store.getApiEntries(),
72
+ contentStore,
73
+ pathResolver,
74
+ rewriteEntry,
75
+ rewriteCSS,
76
+ replaceElements: replaceElementsMerged,
77
+ warnings: []
78
+ });
79
+ ctx.snapshot = snapshot;
80
+ return { kind: "snapshot", snapshot };
81
+ });
82
+ }
83
+ }
84
+ exports.BuildSnapshotPlugin = BuildSnapshotPlugin;
@@ -0,0 +1,8 @@
1
+ import type { ReplaceElementsConfig } from "../../types";
2
+ import type { PagePocketPlugin } from "../types";
3
+ export declare class ReplaceElementsPlugin implements PagePocketPlugin {
4
+ readonly name = "built-in:replace-elements";
5
+ private rules;
6
+ constructor(rules: ReplaceElementsConfig);
7
+ apply(ctx: import("../types").PagePocketContext): void;
8
+ }
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ReplaceElementsPlugin = void 0;
4
+ class ReplaceElementsPlugin {
5
+ constructor(rules) {
6
+ this.name = "built-in:replace-elements";
7
+ this.rules = rules;
8
+ }
9
+ apply(ctx) {
10
+ ctx.addReplaceElements(this.rules);
11
+ }
12
+ }
13
+ exports.ReplaceElementsPlugin = ReplaceElementsPlugin;
@@ -0,0 +1,7 @@
1
+ import type { PagePocketContext, PagePocketPlugin } from "../types";
2
+ export declare class ToDirectoryPlugin implements PagePocketPlugin {
3
+ readonly name = "built-in:to-directory";
4
+ private outputDir;
5
+ constructor(outputDir: string);
6
+ apply(ctx: PagePocketContext): void;
7
+ }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ToDirectoryPlugin = void 0;
4
+ const writers_1 = require("../../writers");
5
+ class ToDirectoryPlugin {
6
+ constructor(outputDir) {
7
+ this.name = "built-in:to-directory";
8
+ this.outputDir = outputDir;
9
+ }
10
+ apply(ctx) {
11
+ ctx.onFinalize(async () => {
12
+ if (!ctx.snapshot) {
13
+ throw new Error("ToDirectoryPlugin requires ctx.snapshot");
14
+ }
15
+ await (0, writers_1.writeToFS)(ctx.snapshot, this.outputDir);
16
+ return { kind: "directory", outputDir: this.outputDir };
17
+ });
18
+ }
19
+ }
20
+ exports.ToDirectoryPlugin = ToDirectoryPlugin;
@@ -0,0 +1,5 @@
1
+ import type { PagePocketContext, PagePocketPlugin } from "../types";
2
+ export declare class ToZipPlugin implements PagePocketPlugin {
3
+ readonly name = "built-in:to-zip";
4
+ apply(ctx: PagePocketContext): void;
5
+ }