@nitpicker/crawler 0.11.0 → 0.13.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 (387) hide show
  1. package/README.md +6 -4
  2. package/lib/archive/archive-accessor.d.ts +2 -2
  3. package/lib/archive/archive-accessor.js +2 -2
  4. package/lib/archive/archive-lock.d.ts +7 -0
  5. package/lib/archive/archive-lock.js +7 -0
  6. package/lib/archive/archive.d.ts +175 -13
  7. package/lib/archive/archive.js +198 -14
  8. package/lib/archive/cache/compute-archive-cache-key.d.ts +39 -0
  9. package/lib/archive/cache/compute-archive-cache-key.js +95 -0
  10. package/lib/archive/cache/extract-archive-to-cache.d.ts +43 -0
  11. package/lib/archive/cache/extract-archive-to-cache.js +309 -0
  12. package/lib/archive/cache/get-archive-cache-root.d.ts +20 -0
  13. package/lib/archive/cache/get-archive-cache-root.js +53 -0
  14. package/lib/archive/cache/is-archive-cache-disabled.d.ts +24 -0
  15. package/lib/archive/cache/is-archive-cache-disabled.js +34 -0
  16. package/lib/archive/cache/resolve-archive-cache-dir.d.ts +26 -0
  17. package/lib/archive/cache/resolve-archive-cache-dir.js +32 -0
  18. package/lib/archive/create-adjunct-tables.d.ts +43 -0
  19. package/lib/archive/create-adjunct-tables.js +213 -0
  20. package/lib/archive/create-entity-tables.d.ts +173 -0
  21. package/lib/archive/create-entity-tables.js +318 -0
  22. package/lib/archive/create-progress-reporter.d.ts +30 -0
  23. package/lib/archive/create-progress-reporter.js +38 -0
  24. package/lib/archive/create-ref-tables.d.ts +35 -0
  25. package/lib/archive/create-ref-tables.js +188 -0
  26. package/lib/archive/database.d.ts +130 -182
  27. package/lib/archive/database.js +524 -1777
  28. package/lib/archive/db-ops/_shared/clear-write-ref-caches.d.ts +27 -0
  29. package/lib/archive/db-ops/_shared/clear-write-ref-caches.js +34 -0
  30. package/lib/archive/db-ops/_shared/create-write-ref-caches.d.ts +17 -0
  31. package/lib/archive/db-ops/_shared/create-write-ref-caches.js +26 -0
  32. package/lib/archive/db-ops/_shared/decode-json-ref.d.ts +17 -0
  33. package/lib/archive/db-ops/_shared/decode-json-ref.js +31 -0
  34. package/lib/archive/db-ops/_shared/load-response-headers-by-set-ids.d.ts +20 -0
  35. package/lib/archive/db-ops/_shared/load-response-headers-by-set-ids.js +53 -0
  36. package/lib/archive/db-ops/_shared/resolve-content-item-id.d.ts +61 -0
  37. package/lib/archive/db-ops/_shared/resolve-content-item-id.js +111 -0
  38. package/lib/archive/db-ops/_shared/resolve-url-or-blob.d.ts +23 -0
  39. package/lib/archive/db-ops/_shared/resolve-url-or-blob.js +29 -0
  40. package/lib/archive/db-ops/_shared/retry-setting.d.ts +16 -0
  41. package/lib/archive/db-ops/_shared/retry-setting.js +18 -0
  42. package/lib/archive/db-ops/_shared/safe-parse-json.d.ts +11 -0
  43. package/lib/archive/db-ops/_shared/safe-parse-json.js +18 -0
  44. package/lib/archive/db-ops/_shared/types.d.ts +53 -0
  45. package/lib/archive/db-ops/_shared/types.js +1 -0
  46. package/lib/archive/db-ops/_shared/upsert-blob-ref.d.ts +25 -0
  47. package/lib/archive/db-ops/_shared/upsert-blob-ref.js +48 -0
  48. package/lib/archive/db-ops/_shared/upsert-content-type-ref.d.ts +30 -0
  49. package/lib/archive/db-ops/_shared/upsert-content-type-ref.js +45 -0
  50. package/lib/archive/db-ops/_shared/upsert-json-ref.d.ts +22 -0
  51. package/lib/archive/db-ops/_shared/upsert-json-ref.js +41 -0
  52. package/lib/archive/db-ops/_shared/upsert-response-headers.d.ts +35 -0
  53. package/lib/archive/db-ops/_shared/upsert-response-headers.js +49 -0
  54. package/lib/archive/db-ops/_shared/upsert-url-ref.d.ts +39 -0
  55. package/lib/archive/db-ops/_shared/upsert-url-ref.js +62 -0
  56. package/lib/archive/db-ops/analysis/replace-analysis-violations.d.ts +28 -0
  57. package/lib/archive/db-ops/analysis/replace-analysis-violations.js +152 -0
  58. package/lib/archive/db-ops/anchors/get-anchors-on-page.d.ts +10 -0
  59. package/lib/archive/db-ops/anchors/get-anchors-on-page.js +21 -0
  60. package/lib/archive/db-ops/config/get-base-url.d.ts +8 -0
  61. package/lib/archive/db-ops/config/get-base-url.js +14 -0
  62. package/lib/archive/db-ops/config/get-config.d.ts +10 -0
  63. package/lib/archive/db-ops/config/get-config.js +27 -0
  64. package/lib/archive/db-ops/config/get-name.d.ts +8 -0
  65. package/lib/archive/db-ops/config/get-name.js +14 -0
  66. package/lib/archive/db-ops/config/info-column-allowlist.d.ts +7 -0
  67. package/lib/archive/db-ops/config/info-column-allowlist.js +26 -0
  68. package/lib/archive/db-ops/config/info-json-columns.d.ts +5 -0
  69. package/lib/archive/db-ops/config/info-json-columns.js +10 -0
  70. package/lib/archive/db-ops/config/set-config.d.ts +12 -0
  71. package/lib/archive/db-ops/config/set-config.js +21 -0
  72. package/lib/archive/db-ops/config/update-config.d.ts +17 -0
  73. package/lib/archive/db-ops/config/update-config.js +36 -0
  74. package/lib/archive/db-ops/errors/insert-crawl-error.d.ts +15 -0
  75. package/lib/archive/db-ops/errors/insert-crawl-error.js +21 -0
  76. package/lib/archive/db-ops/errors/insert-page-error.d.ts +21 -0
  77. package/lib/archive/db-ops/errors/insert-page-error.js +28 -0
  78. package/lib/archive/db-ops/errors/list-dns-burned-host-candidates.d.ts +22 -0
  79. package/lib/archive/db-ops/errors/list-dns-burned-host-candidates.js +141 -0
  80. package/lib/archive/db-ops/html/get-html-of-page-by-id.d.ts +18 -0
  81. package/lib/archive/db-ops/html/get-html-of-page-by-id.js +29 -0
  82. package/lib/archive/db-ops/inventory/record-inventory-run.d.ts +21 -0
  83. package/lib/archive/db-ops/inventory/record-inventory-run.js +38 -0
  84. package/lib/archive/db-ops/lifecycle/checkpoint.d.ts +8 -0
  85. package/lib/archive/db-ops/lifecycle/checkpoint.js +9 -0
  86. package/lib/archive/db-ops/lifecycle/destroy.d.ts +6 -0
  87. package/lib/archive/db-ops/lifecycle/destroy.js +7 -0
  88. package/lib/archive/db-ops/lifecycle/init.d.ts +22 -0
  89. package/lib/archive/db-ops/lifecycle/init.js +42 -0
  90. package/lib/archive/db-ops/meta/get-jsonld-of-page.d.ts +13 -0
  91. package/lib/archive/db-ops/meta/get-jsonld-of-page.js +27 -0
  92. package/lib/archive/db-ops/meta/get-tags-of-page.d.ts +12 -0
  93. package/lib/archive/db-ops/meta/get-tags-of-page.js +28 -0
  94. package/lib/archive/db-ops/pages/order/set-url-order.d.ts +8 -0
  95. package/lib/archive/db-ops/pages/order/set-url-order.js +32 -0
  96. package/lib/archive/db-ops/pages/read/build-page-query.d.ts +18 -0
  97. package/lib/archive/db-ops/pages/read/build-page-query.js +40 -0
  98. package/lib/archive/db-ops/pages/read/get-crawling-state.d.ts +70 -0
  99. package/lib/archive/db-ops/pages/read/get-crawling-state.js +98 -0
  100. package/lib/archive/db-ops/pages/read/get-existing-page-urls.d.ts +15 -0
  101. package/lib/archive/db-ops/pages/read/get-existing-page-urls.js +30 -0
  102. package/lib/archive/db-ops/pages/read/get-page-count.d.ts +12 -0
  103. package/lib/archive/db-ops/pages/read/get-page-count.js +21 -0
  104. package/lib/archive/db-ops/pages/read/get-page-source-by-url.d.ts +24 -0
  105. package/lib/archive/db-ops/pages/read/get-page-source-by-url.js +28 -0
  106. package/lib/archive/db-ops/pages/read/get-pages-with-rels.d.ts +38 -0
  107. package/lib/archive/db-ops/pages/read/get-pages-with-rels.js +107 -0
  108. package/lib/archive/db-ops/pages/read/get-pages.d.ts +11 -0
  109. package/lib/archive/db-ops/pages/read/get-pages.js +51 -0
  110. package/lib/archive/db-ops/pages/read/get-scraped-html-page-count.d.ts +18 -0
  111. package/lib/archive/db-ops/pages/read/get-scraped-html-page-count.js +25 -0
  112. package/lib/archive/db-ops/pages/read/reconstruct-page-rows.d.ts +31 -0
  113. package/lib/archive/db-ops/pages/read/reconstruct-page-rows.js +32 -0
  114. package/lib/archive/db-ops/pages/reset/repromote-external-pages.d.ts +24 -0
  115. package/lib/archive/db-ops/pages/reset/repromote-external-pages.js +93 -0
  116. package/lib/archive/db-ops/pages/reset/reset-failed-pages.d.ts +47 -0
  117. package/lib/archive/db-ops/pages/reset/reset-failed-pages.js +124 -0
  118. package/lib/archive/db-ops/pages/write/insert-inventory-seeds.d.ts +37 -0
  119. package/lib/archive/db-ops/pages/write/insert-inventory-seeds.js +72 -0
  120. package/lib/archive/db-ops/pages/write/insert-jsonld.d.ts +17 -0
  121. package/lib/archive/db-ops/pages/write/insert-jsonld.js +49 -0
  122. package/lib/archive/db-ops/pages/write/insert-page.d.ts +36 -0
  123. package/lib/archive/db-ops/pages/write/insert-page.js +208 -0
  124. package/lib/archive/db-ops/pages/write/insert-tags.d.ts +16 -0
  125. package/lib/archive/db-ops/pages/write/insert-tags.js +34 -0
  126. package/lib/archive/db-ops/pages/write/link-redirect-sources.d.ts +36 -0
  127. package/lib/archive/db-ops/pages/write/link-redirect-sources.js +93 -0
  128. package/lib/archive/db-ops/pages/write/record-redirect.d.ts +35 -0
  129. package/lib/archive/db-ops/pages/write/record-redirect.js +100 -0
  130. package/lib/archive/db-ops/pages/write/set-skipped-page.d.ts +13 -0
  131. package/lib/archive/db-ops/pages/write/set-skipped-page.js +22 -0
  132. package/lib/archive/db-ops/pages/write/update-page.d.ts +29 -0
  133. package/lib/archive/db-ops/pages/write/update-page.js +334 -0
  134. package/lib/archive/db-ops/pages/write/write-page-html-blob.d.ts +19 -0
  135. package/lib/archive/db-ops/pages/write/write-page-html-blob.js +41 -0
  136. package/lib/archive/db-ops/referrers/get-redirects-for-pages.d.ts +9 -0
  137. package/lib/archive/db-ops/referrers/get-redirects-for-pages.js +15 -0
  138. package/lib/archive/db-ops/referrers/get-referrers-of-page.d.ts +17 -0
  139. package/lib/archive/db-ops/referrers/get-referrers-of-page.js +32 -0
  140. package/lib/archive/db-ops/referrers/get-referrers-of-resource.d.ts +8 -0
  141. package/lib/archive/db-ops/referrers/get-referrers-of-resource.js +15 -0
  142. package/lib/archive/db-ops/resources/build-resource-query.d.ts +25 -0
  143. package/lib/archive/db-ops/resources/build-resource-query.js +29 -0
  144. package/lib/archive/db-ops/resources/get-existing-resource-urls.d.ts +9 -0
  145. package/lib/archive/db-ops/resources/get-existing-resource-urls.js +24 -0
  146. package/lib/archive/db-ops/resources/get-resource-by-url.d.ts +13 -0
  147. package/lib/archive/db-ops/resources/get-resource-by-url.js +22 -0
  148. package/lib/archive/db-ops/resources/get-resource-url-list.d.ts +9 -0
  149. package/lib/archive/db-ops/resources/get-resource-url-list.js +13 -0
  150. package/lib/archive/db-ops/resources/get-resources.d.ts +8 -0
  151. package/lib/archive/db-ops/resources/get-resources.js +11 -0
  152. package/lib/archive/db-ops/resources/insert-inventory-resources.d.ts +24 -0
  153. package/lib/archive/db-ops/resources/insert-inventory-resources.js +64 -0
  154. package/lib/archive/db-ops/resources/insert-resource-referrers.d.ts +15 -0
  155. package/lib/archive/db-ops/resources/insert-resource-referrers.js +54 -0
  156. package/lib/archive/db-ops/resources/insert-resource.d.ts +34 -0
  157. package/lib/archive/db-ops/resources/insert-resource.js +73 -0
  158. package/lib/archive/db-ops/resources/reconstruct-resource-rows.d.ts +26 -0
  159. package/lib/archive/db-ops/resources/reconstruct-resource-rows.js +30 -0
  160. package/lib/archive/decode-html-blob.d.ts +18 -0
  161. package/lib/archive/decode-html-blob.js +31 -0
  162. package/lib/archive/derive-lineage-from-parent.d.ts +37 -0
  163. package/lib/archive/derive-lineage-from-parent.js +42 -0
  164. package/lib/archive/drop-legacy-tables.d.ts +45 -0
  165. package/lib/archive/drop-legacy-tables.js +56 -0
  166. package/lib/archive/filesystem/rename.js +1 -1
  167. package/lib/archive/get-failed-page-messages.d.ts +44 -0
  168. package/lib/archive/get-failed-page-messages.js +132 -0
  169. package/lib/archive/init-schema.d.ts +35 -39
  170. package/lib/archive/init-schema.js +111 -320
  171. package/lib/archive/is-inventory-source.d.ts +21 -0
  172. package/lib/archive/is-inventory-source.js +22 -0
  173. package/lib/archive/limited-page-ids.d.ts +2 -1
  174. package/lib/archive/limited-page-ids.js +5 -4
  175. package/lib/archive/meta/assert-compatible-version.d.ts +24 -3
  176. package/lib/archive/meta/assert-compatible-version.js +24 -3
  177. package/lib/archive/meta/types.d.ts +87 -1
  178. package/lib/archive/meta/types.js +34 -2
  179. package/lib/archive/migrate-entity-tables.d.ts +45 -0
  180. package/lib/archive/migrate-entity-tables.js +56 -0
  181. package/lib/archive/migrate-ref-tables.d.ts +25 -0
  182. package/lib/archive/migrate-ref-tables.js +38 -0
  183. package/lib/archive/page-meta-column-maps.d.ts +32 -0
  184. package/lib/archive/page-meta-column-maps.js +43 -0
  185. package/lib/archive/page.d.ts +6 -6
  186. package/lib/archive/page.js +5 -5
  187. package/lib/archive/peek-archive-lock.d.ts +2 -2
  188. package/lib/archive/peek-archive-lock.js +2 -2
  189. package/lib/archive/populate-entity-tables/collapse-anchor-rows.d.ts +41 -0
  190. package/lib/archive/populate-entity-tables/collapse-anchor-rows.js +87 -0
  191. package/lib/archive/populate-entity-tables/derive-dom-path.d.ts +35 -0
  192. package/lib/archive/populate-entity-tables/derive-dom-path.js +72 -0
  193. package/lib/archive/populate-entity-tables/is-blob-ref-value.d.ts +16 -0
  194. package/lib/archive/populate-entity-tables/is-blob-ref-value.js +19 -0
  195. package/lib/archive/populate-entity-tables/match-images-to-dom-paths.d.ts +66 -0
  196. package/lib/archive/populate-entity-tables/match-images-to-dom-paths.js +96 -0
  197. package/lib/archive/populate-entity-tables/populate-anchor-edges.d.ts +33 -0
  198. package/lib/archive/populate-entity-tables/populate-anchor-edges.js +153 -0
  199. package/lib/archive/populate-entity-tables/populate-content-items.d.ts +40 -0
  200. package/lib/archive/populate-entity-tables/populate-content-items.js +141 -0
  201. package/lib/archive/populate-entity-tables/populate-entities.d.ts +81 -0
  202. package/lib/archive/populate-entity-tables/populate-entities.js +111 -0
  203. package/lib/archive/populate-entity-tables/populate-image-items.d.ts +91 -0
  204. package/lib/archive/populate-entity-tables/populate-image-items.js +223 -0
  205. package/lib/archive/populate-entity-tables/populate-page-meta.d.ts +33 -0
  206. package/lib/archive/populate-entity-tables/populate-page-meta.js +267 -0
  207. package/lib/archive/populate-entity-tables/populate-resource-items.d.ts +22 -0
  208. package/lib/archive/populate-entity-tables/populate-resource-items.js +114 -0
  209. package/lib/archive/populate-entity-tables/populate-resource-ref-edges.d.ts +31 -0
  210. package/lib/archive/populate-entity-tables/populate-resource-ref-edges.js +33 -0
  211. package/lib/archive/populate-entity-tables/resolve-blob-refs.d.ts +31 -0
  212. package/lib/archive/populate-entity-tables/resolve-blob-refs.js +100 -0
  213. package/lib/archive/populate-entity-tables/resolve-content-type-refs.d.ts +22 -0
  214. package/lib/archive/populate-entity-tables/resolve-content-type-refs.js +27 -0
  215. package/lib/archive/populate-entity-tables/resolve-header-sets.d.ts +49 -0
  216. package/lib/archive/populate-entity-tables/resolve-header-sets.js +122 -0
  217. package/lib/archive/populate-entity-tables/resolve-json-refs.d.ts +25 -0
  218. package/lib/archive/populate-entity-tables/resolve-json-refs.js +67 -0
  219. package/lib/archive/populate-entity-tables/resolve-text-refs.d.ts +30 -0
  220. package/lib/archive/populate-entity-tables/resolve-text-refs.js +61 -0
  221. package/lib/archive/populate-entity-tables/resolve-url-or-blob-from-maps.d.ts +21 -0
  222. package/lib/archive/populate-entity-tables/resolve-url-or-blob-from-maps.js +27 -0
  223. package/lib/archive/populate-entity-tables/resolve-url-refs.d.ts +33 -0
  224. package/lib/archive/populate-entity-tables/resolve-url-refs.js +60 -0
  225. package/lib/archive/populate-entity-tables/test-utils/count-rows.d.ts +17 -0
  226. package/lib/archive/populate-entity-tables/test-utils/count-rows.js +20 -0
  227. package/lib/archive/populate-entity-tables/test-utils/seed-content-items.d.ts +25 -0
  228. package/lib/archive/populate-entity-tables/test-utils/seed-content-items.js +42 -0
  229. package/lib/archive/populate-entity-tables/test-utils/setup-entities-db.d.ts +23 -0
  230. package/lib/archive/populate-entity-tables/test-utils/setup-entities-db.js +178 -0
  231. package/lib/archive/populate-entity-tables/types.d.ts +157 -0
  232. package/lib/archive/populate-entity-tables/types.js +12 -0
  233. package/lib/archive/populate-entity-tables/upsert-text-refs.d.ts +38 -0
  234. package/lib/archive/populate-entity-tables/upsert-text-refs.js +78 -0
  235. package/lib/archive/populate-ref-tables/classify-content-type.d.ts +16 -0
  236. package/lib/archive/populate-ref-tables/classify-content-type.js +52 -0
  237. package/lib/archive/populate-ref-tables/compute-content-hash.d.ts +22 -0
  238. package/lib/archive/populate-ref-tables/compute-content-hash.js +26 -0
  239. package/lib/archive/populate-ref-tables/compute-header-flags.d.ts +16 -0
  240. package/lib/archive/populate-ref-tables/compute-header-flags.js +70 -0
  241. package/lib/archive/populate-ref-tables/content-type-rules.d.ts +38 -0
  242. package/lib/archive/populate-ref-tables/content-type-rules.js +133 -0
  243. package/lib/archive/populate-ref-tables/create-header-table-caches.d.ts +25 -0
  244. package/lib/archive/populate-ref-tables/create-header-table-caches.js +49 -0
  245. package/lib/archive/populate-ref-tables/data-uri-url-refs-limit.d.ts +15 -0
  246. package/lib/archive/populate-ref-tables/data-uri-url-refs-limit.js +15 -0
  247. package/lib/archive/populate-ref-tables/decode-data-uri.d.ts +21 -0
  248. package/lib/archive/populate-ref-tables/decode-data-uri.js +126 -0
  249. package/lib/archive/populate-ref-tables/decompose-header-set.d.ts +29 -0
  250. package/lib/archive/populate-ref-tables/decompose-header-set.js +157 -0
  251. package/lib/archive/populate-ref-tables/decompose-url.d.ts +25 -0
  252. package/lib/archive/populate-ref-tables/decompose-url.js +70 -0
  253. package/lib/archive/populate-ref-tables/header-stability.d.ts +19 -0
  254. package/lib/archive/populate-ref-tables/header-stability.js +22 -0
  255. package/lib/archive/populate-ref-tables/header-value-cache-key.d.ts +17 -0
  256. package/lib/archive/populate-ref-tables/header-value-cache-key.js +19 -0
  257. package/lib/archive/populate-ref-tables/normalize-mime.d.ts +24 -0
  258. package/lib/archive/populate-ref-tables/normalize-mime.js +36 -0
  259. package/lib/archive/populate-ref-tables/populate-blob-refs.d.ts +38 -0
  260. package/lib/archive/populate-ref-tables/populate-blob-refs.js +134 -0
  261. package/lib/archive/populate-ref-tables/populate-content-type-refs.d.ts +27 -0
  262. package/lib/archive/populate-ref-tables/populate-content-type-refs.js +70 -0
  263. package/lib/archive/populate-ref-tables/populate-header-tables.d.ts +35 -0
  264. package/lib/archive/populate-ref-tables/populate-header-tables.js +80 -0
  265. package/lib/archive/populate-ref-tables/populate-json-refs.d.ts +29 -0
  266. package/lib/archive/populate-ref-tables/populate-json-refs.js +101 -0
  267. package/lib/archive/populate-ref-tables/populate-refs.d.ts +51 -0
  268. package/lib/archive/populate-ref-tables/populate-refs.js +62 -0
  269. package/lib/archive/populate-ref-tables/populate-text-refs.d.ts +32 -0
  270. package/lib/archive/populate-ref-tables/populate-text-refs.js +133 -0
  271. package/lib/archive/populate-ref-tables/populate-url-refs.d.ts +28 -0
  272. package/lib/archive/populate-ref-tables/populate-url-refs.js +148 -0
  273. package/lib/archive/populate-ref-tables/test-utils/count-rows.d.ts +15 -0
  274. package/lib/archive/populate-ref-tables/test-utils/count-rows.js +17 -0
  275. package/lib/archive/populate-ref-tables/types.d.ts +197 -0
  276. package/lib/archive/populate-ref-tables/types.js +7 -0
  277. package/lib/archive/populate-ref-tables/upsert-one-header-set.d.ts +34 -0
  278. package/lib/archive/populate-ref-tables/upsert-one-header-set.js +208 -0
  279. package/lib/archive/populate-ref-tables/volatile-header-names.d.ts +20 -0
  280. package/lib/archive/populate-ref-tables/volatile-header-names.js +33 -0
  281. package/lib/archive/redirect-table.d.ts +4 -2
  282. package/lib/archive/redirect-table.js +15 -10
  283. package/lib/archive/resolve-redirect-chain.d.ts +3 -3
  284. package/lib/archive/resolve-redirect-chain.js +2 -2
  285. package/lib/archive/resource.d.ts +1 -1
  286. package/lib/archive/retarget-legacy-fk-tables.d.ts +47 -0
  287. package/lib/archive/retarget-legacy-fk-tables.js +107 -0
  288. package/lib/archive/test-utils/fk-parent-tables.d.ts +15 -0
  289. package/lib/archive/test-utils/fk-parent-tables.js +19 -0
  290. package/lib/archive/test-utils/seed-content-item.d.ts +35 -0
  291. package/lib/archive/test-utils/seed-content-item.js +42 -0
  292. package/lib/archive/test-utils/setup-legacy-fk-db.d.ts +33 -0
  293. package/lib/archive/test-utils/setup-legacy-fk-db.js +270 -0
  294. package/lib/archive/types.d.ts +151 -15
  295. package/lib/archive/verify-migration/capture-rejection.d.ts +24 -0
  296. package/lib/archive/verify-migration/capture-rejection.js +31 -0
  297. package/lib/archive/verify-migration/check-anchor-edges-count.d.ts +34 -0
  298. package/lib/archive/verify-migration/check-anchor-edges-count.js +72 -0
  299. package/lib/archive/verify-migration/check-anchor-edges-sum.d.ts +13 -0
  300. package/lib/archive/verify-migration/check-anchor-edges-sum.js +27 -0
  301. package/lib/archive/verify-migration/check-content-items-count.d.ts +16 -0
  302. package/lib/archive/verify-migration/check-content-items-count.js +30 -0
  303. package/lib/archive/verify-migration/check-content-type-preservation.d.ts +22 -0
  304. package/lib/archive/verify-migration/check-content-type-preservation.js +40 -0
  305. package/lib/archive/verify-migration/check-foreign-key-integrity.d.ts +31 -0
  306. package/lib/archive/verify-migration/check-foreign-key-integrity.js +47 -0
  307. package/lib/archive/verify-migration/check-image-items-count.d.ts +12 -0
  308. package/lib/archive/verify-migration/check-image-items-count.js +26 -0
  309. package/lib/archive/verify-migration/check-page-meta-count.d.ts +15 -0
  310. package/lib/archive/verify-migration/check-page-meta-count.js +31 -0
  311. package/lib/archive/verify-migration/check-reader-parity.d.ts +23 -0
  312. package/lib/archive/verify-migration/check-reader-parity.js +211 -0
  313. package/lib/archive/verify-migration/check-resource-items-count.d.ts +17 -0
  314. package/lib/archive/verify-migration/check-resource-items-count.js +33 -0
  315. package/lib/archive/verify-migration/check-url-round-trip.d.ts +43 -0
  316. package/lib/archive/verify-migration/check-url-round-trip.js +112 -0
  317. package/lib/archive/verify-migration/types.d.ts +70 -0
  318. package/lib/archive/verify-migration/types.js +63 -0
  319. package/lib/archive/verify-migration/verify-migration.d.ts +41 -0
  320. package/lib/archive/verify-migration/verify-migration.js +120 -0
  321. package/lib/classify-error-kind.d.ts +19 -0
  322. package/lib/classify-error-kind.js +122 -0
  323. package/lib/crawler/build-js-redirect-edge.d.ts +68 -0
  324. package/lib/crawler/build-js-redirect-edge.js +57 -0
  325. package/lib/crawler/build-redirect-event.d.ts +24 -0
  326. package/lib/crawler/build-redirect-event.js +28 -0
  327. package/lib/crawler/capture-image-dom-paths.d.ts +33 -0
  328. package/lib/crawler/capture-image-dom-paths.js +39 -0
  329. package/lib/crawler/clear-dns-burned-host-cache.d.ts +6 -0
  330. package/lib/crawler/clear-dns-burned-host-cache.js +11 -0
  331. package/lib/crawler/collect-image-dom-paths.d.ts +23 -0
  332. package/lib/crawler/collect-image-dom-paths.js +64 -0
  333. package/lib/crawler/crawler.d.ts +22 -1
  334. package/lib/crawler/crawler.js +679 -117
  335. package/lib/crawler/derive-js-redirect-target.d.ts +68 -0
  336. package/lib/crawler/derive-js-redirect-target.js +129 -0
  337. package/lib/crawler/derive-resource-source.d.ts +25 -15
  338. package/lib/crawler/derive-resource-source.js +28 -17
  339. package/lib/crawler/dns-burned-host-cache.d.ts +26 -0
  340. package/lib/crawler/dns-burned-host-cache.js +25 -0
  341. package/lib/crawler/dns-burned-host-short-circuit-counter.d.ts +13 -0
  342. package/lib/crawler/dns-burned-host-short-circuit-counter.js +11 -0
  343. package/lib/crawler/fetch-destination.d.ts +12 -4
  344. package/lib/crawler/fetch-destination.js +94 -16
  345. package/lib/crawler/inject-scope-auth.d.ts +1 -1
  346. package/lib/crawler/inject-scope-auth.js +1 -1
  347. package/lib/crawler/is-js-redirect-error-shape.d.ts +40 -0
  348. package/lib/crawler/is-js-redirect-error-shape.js +53 -0
  349. package/lib/crawler/is-puppeteer-fallback-candidate.d.ts +16 -0
  350. package/lib/crawler/is-puppeteer-fallback-candidate.js +63 -0
  351. package/lib/crawler/link-list.d.ts +21 -1
  352. package/lib/crawler/link-list.js +23 -3
  353. package/lib/crawler/normalize-content-type.d.ts +1 -1
  354. package/lib/crawler/normalize-content-type.js +1 -1
  355. package/lib/crawler/plan-sub-resource-emits.d.ts +63 -0
  356. package/lib/crawler/plan-sub-resource-emits.js +44 -0
  357. package/lib/crawler/preload-short-circuit-error.d.ts +22 -0
  358. package/lib/crawler/preload-short-circuit-error.js +25 -0
  359. package/lib/crawler/should-burn-host.d.ts +78 -0
  360. package/lib/crawler/should-burn-host.js +61 -0
  361. package/lib/crawler/should-get-fallback-on-head-failure.d.ts +38 -0
  362. package/lib/crawler/should-get-fallback-on-head-failure.js +46 -0
  363. package/lib/crawler/types.d.ts +108 -1
  364. package/lib/crawler-orchestrator.d.ts +22 -3
  365. package/lib/crawler-orchestrator.js +312 -73
  366. package/lib/crawler.d.ts +15 -2
  367. package/lib/crawler.js +24 -1
  368. package/lib/permanent-error-kinds.d.ts +43 -0
  369. package/lib/permanent-error-kinds.js +48 -0
  370. package/lib/types.d.ts +84 -0
  371. package/lib/utils/compute-file-sha256.d.ts +24 -0
  372. package/lib/utils/compute-file-sha256.js +56 -0
  373. package/lib/utils/error/emit-error-with-retry.d.ts +40 -0
  374. package/lib/utils/error/emit-error-with-retry.js +44 -0
  375. package/lib/utils/error/emit-error.d.ts +39 -0
  376. package/lib/utils/error/emit-error.js +41 -0
  377. package/package.json +12 -12
  378. package/lib/archive/migrate-crawl-errors.d.ts +0 -20
  379. package/lib/archive/migrate-crawl-errors.js +0 -38
  380. package/lib/archive/migrate-html-blob-tables.d.ts +0 -24
  381. package/lib/archive/migrate-html-blob-tables.js +0 -53
  382. package/lib/archive/migrate-page-errors.d.ts +0 -16
  383. package/lib/archive/migrate-page-errors.js +0 -35
  384. package/lib/archive/migrate-pages-resources-source.d.ts +0 -16
  385. package/lib/archive/migrate-pages-resources-source.js +0 -46
  386. package/lib/utils/error/error-emitter.d.ts +0 -18
  387. package/lib/utils/error/error-emitter.js +0 -29
@@ -0,0 +1,68 @@
1
+ import type { RedirectEdgeResult } from './types.js';
2
+ import type { PageData } from '@d-zero/beholder';
3
+ import type { ExURL } from '@d-zero/shared/parse-url';
4
+ /**
5
+ * Parameters for {@link buildJsRedirectEdge}.
6
+ */
7
+ export interface BuildJsRedirectEdgeParams {
8
+ /** Source URL puppeteer was asked to navigate to. */
9
+ url: ExURL;
10
+ /**
11
+ * Whether `url` is external to the crawl scope. Propagated onto the
12
+ * synthesised `PageData` so downstream `linkList.done` classifies the
13
+ * source the same way the original scrape would have.
14
+ */
15
+ isExternal: boolean;
16
+ /**
17
+ * Raw error message from `BrowserScrapeResult.error`. The rescue only
18
+ * fires when this matches the narrow `Page.goto returned null` sentinel
19
+ * (see {@link isJsRedirectErrorShape}) — anything else falls through
20
+ * so genuine browser failures surface unchanged.
21
+ */
22
+ errorMessage: string | null | undefined;
23
+ /**
24
+ * Value of `BrowserScrapeResult.postNavigationUrl` — the URL puppeteer's
25
+ * `page.url()` reported after the throw. Passed to
26
+ * {@link deriveJsRedirectTarget} for canonicalisation, credential strip,
27
+ * and scheme filtering.
28
+ */
29
+ postNavigationUrl: string | null | undefined;
30
+ /**
31
+ * When present, the rescue builds the redirect-edge `PageData` by
32
+ * spreading this HEAD-pre-flight result and overriding `redirectPaths`.
33
+ * Use this on the HEAD-success-then-puppeteer-fail path so the source row
34
+ * carries the real HTTP-level status / content-type from HEAD. When
35
+ * omitted, the rescue builds a synthetic placeholder via
36
+ * {@link linkToPageData} with `status = -1` / `statusText = errorMessage`
37
+ * — used on the HEAD-fail-then-puppeteer-fallback path where there is
38
+ * no HEAD response to draw from.
39
+ */
40
+ headCheckResult?: PageData;
41
+ }
42
+ /**
43
+ * Build a JS-redirect `RedirectEdgeResult` when the browser-scrape error
44
+ * looks like puppeteer's `page.goto() === null` shape AND `page.url()`
45
+ * resolved to a meaningfully-different URL.
46
+ *
47
+ * **Why this helper exists** — both rescue call sites in
48
+ * `Crawler.#scrapePage` (the HEAD-success-then-puppeteer-fail tail and the
49
+ * HEAD-fail-then-puppeteer-fallback branch inside `#sendHeadRequest`) run
50
+ * the same three-step recipe: classify the error shape → derive a JS target
51
+ * from `page.url()` → synthesise a redirect-edge result. Inlining the recipe
52
+ * twice means a future change to `deriveJsRedirectTarget`'s contract or the
53
+ * sentinel string has to be applied to both copies in sync; collapsing into
54
+ * a single helper keeps the rescue's invariants in one place. The
55
+ * intentional difference between the two call sites (whether to fold a
56
+ * HEAD result into the synthesised PageData or to start from a
57
+ * `linkToPageData` placeholder) is reduced to a single optional parameter
58
+ * (`headCheckResult`), preserving both shapes without behavioural drift.
59
+ *
60
+ * The helper logs at `crawlerLog` whenever it fires so operators tailing
61
+ * `DEBUG=Nitpicker:Crawler` see exactly which URL got rescued and to which
62
+ * destination — without this trail the rescue is invisible to anyone
63
+ * debugging "why did this 200-OK source row land in the archive as a 301?".
64
+ * @param params - Inputs gathered at the call site.
65
+ * @returns A `RedirectEdgeResult` when the rescue applies, otherwise
66
+ * `null` (the caller should fall through to the existing error path).
67
+ */
68
+ export declare function buildJsRedirectEdge(params: BuildJsRedirectEdgeParams): RedirectEdgeResult | null;
@@ -0,0 +1,57 @@
1
+ import { crawlerLog } from '../debug.js';
2
+ import { deriveJsRedirectTarget } from './derive-js-redirect-target.js';
3
+ import { isJsRedirectErrorShape } from './is-js-redirect-error-shape.js';
4
+ import { linkToPageData } from './link-to-page-data.js';
5
+ /**
6
+ * Build a JS-redirect `RedirectEdgeResult` when the browser-scrape error
7
+ * looks like puppeteer's `page.goto() === null` shape AND `page.url()`
8
+ * resolved to a meaningfully-different URL.
9
+ *
10
+ * **Why this helper exists** — both rescue call sites in
11
+ * `Crawler.#scrapePage` (the HEAD-success-then-puppeteer-fail tail and the
12
+ * HEAD-fail-then-puppeteer-fallback branch inside `#sendHeadRequest`) run
13
+ * the same three-step recipe: classify the error shape → derive a JS target
14
+ * from `page.url()` → synthesise a redirect-edge result. Inlining the recipe
15
+ * twice means a future change to `deriveJsRedirectTarget`'s contract or the
16
+ * sentinel string has to be applied to both copies in sync; collapsing into
17
+ * a single helper keeps the rescue's invariants in one place. The
18
+ * intentional difference between the two call sites (whether to fold a
19
+ * HEAD result into the synthesised PageData or to start from a
20
+ * `linkToPageData` placeholder) is reduced to a single optional parameter
21
+ * (`headCheckResult`), preserving both shapes without behavioural drift.
22
+ *
23
+ * The helper logs at `crawlerLog` whenever it fires so operators tailing
24
+ * `DEBUG=Nitpicker:Crawler` see exactly which URL got rescued and to which
25
+ * destination — without this trail the rescue is invisible to anyone
26
+ * debugging "why did this 200-OK source row land in the archive as a 301?".
27
+ * @param params - Inputs gathered at the call site.
28
+ * @returns A `RedirectEdgeResult` when the rescue applies, otherwise
29
+ * `null` (the caller should fall through to the existing error path).
30
+ */
31
+ export function buildJsRedirectEdge(params) {
32
+ if (!isJsRedirectErrorShape(params.errorMessage)) {
33
+ return null;
34
+ }
35
+ const jsRedirectTarget = deriveJsRedirectTarget(params.url.withoutHashAndAuth, params.postNavigationUrl);
36
+ if (jsRedirectTarget === null) {
37
+ return null;
38
+ }
39
+ const pageData = params.headCheckResult
40
+ ? { ...params.headCheckResult, redirectPaths: [jsRedirectTarget] }
41
+ : linkToPageData({
42
+ url: params.url,
43
+ isExternal: params.isExternal,
44
+ isLowerLayer: false,
45
+ dest: {
46
+ redirectPaths: [jsRedirectTarget],
47
+ status: -1,
48
+ statusText: typeof params.errorMessage === 'string' ? params.errorMessage : '',
49
+ contentType: null,
50
+ contentLength: null,
51
+ responseHeaders: null,
52
+ title: '',
53
+ },
54
+ });
55
+ crawlerLog('JS-redirect rescue fired for %s → %s (HEAD %s)', params.url.href, jsRedirectTarget, params.headCheckResult ? 'available' : 'absent');
56
+ return { type: 'redirect-edge', source: 'js-redirect', pageData };
57
+ }
@@ -0,0 +1,24 @@
1
+ import type { CrawlerEventTypes, InventoryMode } from './types.js';
2
+ import type { PageData } from '../utils/types/types.js';
3
+ /**
4
+ * Build the payload for the {@link CrawlerEventTypes.redirect} event so the
5
+ * `{ result, source }` shape is constructed in one place. Pure function —
6
+ * no I/O, no side effects, just the wiring that connects
7
+ * {@link derivePageSource} to the emit call.
8
+ *
9
+ * Exists so a unit test can pin the wiring directly. Before extraction
10
+ * the assembly lived inline in `Crawler.#scrape`, which meant the only
11
+ * way to catch "someone deletes the `source` field" or "someone passes
12
+ * `inventoryMode` where it should pass `derivePageSource(...)`" was the
13
+ * inventory E2E. Now a single-purpose spec exercises the construction.
14
+ *
15
+ * The originating URL passed in `pageUrlWithoutHashAndAuth` must be the
16
+ * URL the redirect chain STARTS from (the page being scraped), not the
17
+ * destination — see `Database.recordRedirect` JSDoc for why
18
+ * lineage propagates from origin, not from the destination.
19
+ * @param pageData - HEAD-resolved page data carrying the redirect chain.
20
+ * @param inventoryMode - Inventory-mode config from `CrawlerOptions.inventoryMode`, or `null` outside `--inventory`.
21
+ * @param pageUrlWithoutHashAndAuth - The originating page URL keyed by `withoutHashAndAuth`.
22
+ * @returns The exact event payload to feed `emit('redirect', ...)`.
23
+ */
24
+ export declare function buildRedirectEvent(pageData: PageData, inventoryMode: InventoryMode | null, pageUrlWithoutHashAndAuth: string): CrawlerEventTypes['redirect'];
@@ -0,0 +1,28 @@
1
+ import { derivePageSource } from './derive-page-source.js';
2
+ /**
3
+ * Build the payload for the {@link CrawlerEventTypes.redirect} event so the
4
+ * `{ result, source }` shape is constructed in one place. Pure function —
5
+ * no I/O, no side effects, just the wiring that connects
6
+ * {@link derivePageSource} to the emit call.
7
+ *
8
+ * Exists so a unit test can pin the wiring directly. Before extraction
9
+ * the assembly lived inline in `Crawler.#scrape`, which meant the only
10
+ * way to catch "someone deletes the `source` field" or "someone passes
11
+ * `inventoryMode` where it should pass `derivePageSource(...)`" was the
12
+ * inventory E2E. Now a single-purpose spec exercises the construction.
13
+ *
14
+ * The originating URL passed in `pageUrlWithoutHashAndAuth` must be the
15
+ * URL the redirect chain STARTS from (the page being scraped), not the
16
+ * destination — see `Database.recordRedirect` JSDoc for why
17
+ * lineage propagates from origin, not from the destination.
18
+ * @param pageData - HEAD-resolved page data carrying the redirect chain.
19
+ * @param inventoryMode - Inventory-mode config from `CrawlerOptions.inventoryMode`, or `null` outside `--inventory`.
20
+ * @param pageUrlWithoutHashAndAuth - The originating page URL keyed by `withoutHashAndAuth`.
21
+ * @returns The exact event payload to feed `emit('redirect', ...)`.
22
+ */
23
+ export function buildRedirectEvent(pageData, inventoryMode, pageUrlWithoutHashAndAuth) {
24
+ return {
25
+ result: pageData,
26
+ source: derivePageSource(inventoryMode, pageUrlWithoutHashAndAuth),
27
+ };
28
+ }
@@ -0,0 +1,33 @@
1
+ import type { DomPathCandidate } from '../archive/populate-entity-tables/types.js';
2
+ import type { Page as PuppeteerPage } from 'puppeteer';
3
+ /**
4
+ * Captures every `<img>` in the rendered document — its `outerHTML` and
5
+ * its `dom_path` string — in document order, for `image_items.dom_path_text_id`
6
+ * resolution at write time.
7
+ *
8
+ * `@d-zero/beholder`'s image metadata carries the element's `outerHTML`
9
+ * (`sourceCode`) but no positional information, so the crawler runs this
10
+ * one extra `page.evaluate` after `scrapeStart` returns, while the page
11
+ * is still alive. The in-browser walk is
12
+ * {@link ./collect-image-dom-paths.ts} — a self-contained function whose
13
+ * source puppeteer serialises into the page, and whose spec pins its
14
+ * output against the Node-side
15
+ * {@link ../archive/populate-entity-tables/derive-dom-path.ts} so a
16
+ * live-crawled archive and one whose dom paths were reconstructed from
17
+ * HTML snapshots by the migration script produce identical strings for
18
+ * identical DOM shapes.
19
+ *
20
+ * Returns `undefined` on any evaluation failure (page context died,
21
+ * navigation raced the call) — dom paths are best-effort enrichment and
22
+ * a capture failure must not fail the scrape. Callers fall back to the
23
+ * `unknown/<id>` synthetic marker per image via
24
+ * {@link ../archive/populate-entity-tables/match-images-to-dom-paths.ts}.
25
+ * @param page - The live puppeteer page, after the scrape completed and
26
+ * before the browser closes.
27
+ * @returns Candidates in document order, or `undefined` when the page
28
+ * could not be evaluated.
29
+ * @example
30
+ * const result = await scraper.scrapeStart(page, url, options);
31
+ * const imageDomPaths = await captureImageDomPaths(page);
32
+ */
33
+ export declare function captureImageDomPaths(page: PuppeteerPage): Promise<DomPathCandidate[] | undefined>;
@@ -0,0 +1,39 @@
1
+ import { collectImageDomPaths } from './collect-image-dom-paths.js';
2
+ /**
3
+ * Captures every `<img>` in the rendered document — its `outerHTML` and
4
+ * its `dom_path` string — in document order, for `image_items.dom_path_text_id`
5
+ * resolution at write time.
6
+ *
7
+ * `@d-zero/beholder`'s image metadata carries the element's `outerHTML`
8
+ * (`sourceCode`) but no positional information, so the crawler runs this
9
+ * one extra `page.evaluate` after `scrapeStart` returns, while the page
10
+ * is still alive. The in-browser walk is
11
+ * {@link ./collect-image-dom-paths.ts} — a self-contained function whose
12
+ * source puppeteer serialises into the page, and whose spec pins its
13
+ * output against the Node-side
14
+ * {@link ../archive/populate-entity-tables/derive-dom-path.ts} so a
15
+ * live-crawled archive and one whose dom paths were reconstructed from
16
+ * HTML snapshots by the migration script produce identical strings for
17
+ * identical DOM shapes.
18
+ *
19
+ * Returns `undefined` on any evaluation failure (page context died,
20
+ * navigation raced the call) — dom paths are best-effort enrichment and
21
+ * a capture failure must not fail the scrape. Callers fall back to the
22
+ * `unknown/<id>` synthetic marker per image via
23
+ * {@link ../archive/populate-entity-tables/match-images-to-dom-paths.ts}.
24
+ * @param page - The live puppeteer page, after the scrape completed and
25
+ * before the browser closes.
26
+ * @returns Candidates in document order, or `undefined` when the page
27
+ * could not be evaluated.
28
+ * @example
29
+ * const result = await scraper.scrapeStart(page, url, options);
30
+ * const imageDomPaths = await captureImageDomPaths(page);
31
+ */
32
+ export async function captureImageDomPaths(page) {
33
+ try {
34
+ return await page.evaluate(collectImageDomPaths);
35
+ }
36
+ catch {
37
+ return undefined;
38
+ }
39
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Clears the DNS-burned host cache and resets the short-circuit counter.
3
+ * Called between crawl sessions, alongside `clearDestinationCache`, to
4
+ * avoid leaking state from a previous session into a fresh one.
5
+ */
6
+ export declare function clearDnsBurnedHostCache(): void;
@@ -0,0 +1,11 @@
1
+ import { dnsBurnedHostCache } from './dns-burned-host-cache.js';
2
+ import { dnsBurnedHostShortCircuitCounter } from './dns-burned-host-short-circuit-counter.js';
3
+ /**
4
+ * Clears the DNS-burned host cache and resets the short-circuit counter.
5
+ * Called between crawl sessions, alongside `clearDestinationCache`, to
6
+ * avoid leaking state from a previous session into a fresh one.
7
+ */
8
+ export function clearDnsBurnedHostCache() {
9
+ dnsBurnedHostCache.clear();
10
+ dnsBurnedHostShortCircuitCounter.count = 0;
11
+ }
@@ -0,0 +1,23 @@
1
+ import type { DomPathCandidate } from '../archive/populate-entity-tables/types.js';
2
+ /**
3
+ * Collects every `<img>` in a document — its `outerHTML` and its
4
+ * `dom_path` string — in document order.
5
+ *
6
+ * **Self-contained by contract.** This function is passed verbatim to
7
+ * puppeteer's `page.evaluate`, which serialises the function source and
8
+ * executes it inside the browser: it must not reference imports,
9
+ * module-scope bindings, or any closure state. That constraint is also
10
+ * what makes single-sourcing possible — the exact same function body
11
+ * runs in the browser during a live crawl AND in Node (against a jsdom
12
+ * document) in its spec, so the dom-path derivation cannot drift between
13
+ * the two runtimes. The spec additionally pins its output against
14
+ * {@link ../archive/populate-entity-tables/derive-dom-path.ts} (the
15
+ * Node-side derivation the migration script uses) element-for-element.
16
+ * @param doc - The document to walk. Defaults to the global `document`,
17
+ * which is how the in-browser `page.evaluate(collectImageDomPaths)`
18
+ * call resolves it; Node callers (specs) pass a jsdom document.
19
+ * @returns Candidates in document order.
20
+ * @example
21
+ * const candidates = await page.evaluate(collectImageDomPaths);
22
+ */
23
+ export declare function collectImageDomPaths(doc?: Document): DomPathCandidate[];
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Collects every `<img>` in a document — its `outerHTML` and its
3
+ * `dom_path` string — in document order.
4
+ *
5
+ * **Self-contained by contract.** This function is passed verbatim to
6
+ * puppeteer's `page.evaluate`, which serialises the function source and
7
+ * executes it inside the browser: it must not reference imports,
8
+ * module-scope bindings, or any closure state. That constraint is also
9
+ * what makes single-sourcing possible — the exact same function body
10
+ * runs in the browser during a live crawl AND in Node (against a jsdom
11
+ * document) in its spec, so the dom-path derivation cannot drift between
12
+ * the two runtimes. The spec additionally pins its output against
13
+ * {@link ../archive/populate-entity-tables/derive-dom-path.ts} (the
14
+ * Node-side derivation the migration script uses) element-for-element.
15
+ * @param doc - The document to walk. Defaults to the global `document`,
16
+ * which is how the in-browser `page.evaluate(collectImageDomPaths)`
17
+ * call resolves it; Node callers (specs) pass a jsdom document.
18
+ * @returns Candidates in document order.
19
+ * @example
20
+ * const candidates = await page.evaluate(collectImageDomPaths);
21
+ */
22
+ export function collectImageDomPaths(doc) {
23
+ const target = doc ?? document;
24
+ /**
25
+ * Counts earlier same-tag siblings, returning the 1-based ordinal.
26
+ * @param element - The element whose ordinal is being computed.
27
+ * @param tag - The element's lower-cased tag name.
28
+ * @returns 1-based ordinal among same-tag siblings.
29
+ */
30
+ function computeSiblingOrdinal(element, tag) {
31
+ let count = 1;
32
+ let sibling = element.previousElementSibling;
33
+ while (sibling !== null) {
34
+ if (sibling.tagName.toLowerCase() === tag) {
35
+ count += 1;
36
+ }
37
+ sibling = sibling.previousElementSibling;
38
+ }
39
+ return count;
40
+ }
41
+ /**
42
+ * Derives the slash-joined dom_path for one element.
43
+ * @param element - The element to derive the path for.
44
+ * @returns The dom_path string.
45
+ */
46
+ function deriveDomPath(element) {
47
+ const segments = [];
48
+ let current = element;
49
+ while (current !== null) {
50
+ const tag = current.tagName.toLowerCase();
51
+ if (tag === 'html') {
52
+ segments.unshift('html');
53
+ break;
54
+ }
55
+ segments.unshift(`${tag}[${computeSiblingOrdinal(current, tag)}]`);
56
+ current = current.parentElement;
57
+ }
58
+ return segments.join('/');
59
+ }
60
+ return Array.from(target.querySelectorAll('img'), (img) => ({
61
+ outerHTML: img.outerHTML,
62
+ path: deriveDomPath(img),
63
+ }));
64
+ }
@@ -71,7 +71,8 @@ export default class Crawler extends EventEmitter<CrawlerEventTypes> {
71
71
  * before reaching the dealer so a URL that exists in both sources — which
72
72
  * is common in append-mode when a new root coincides with a repromoted
73
73
  * previously-external page — does not race on two parallel slots.
74
- * @param urls - The list of root URLs to begin crawling from. Must be non-empty.
74
+ * @param urls - The list of root URLs to begin crawling from. May be empty
75
+ * when resumed pending URLs already exist (for example `--retry-failed`).
75
76
  * @param opts - Optional overrides; currently only `recursive` is honoured.
76
77
  * @param opts.recursive - When `false`, disables recursive discovery and forces list-mode.
77
78
  * Defaults to the constructor option's `recursive` value.
@@ -80,6 +81,26 @@ export default class Crawler extends EventEmitter<CrawlerEventTypes> {
80
81
  start(urls: ExURL[], opts?: {
81
82
  recursive?: boolean;
82
83
  }): void;
84
+ /**
85
+ * Launches a fresh Puppeteer browser, runs the beholder scraper, and cleans up.
86
+ *
87
+ * WHY per-URL browser: Each URL gets its own browser instance to ensure
88
+ * complete isolation (cookies, cache, service workers). The browser is always
89
+ * closed in the `finally` block, even on error.
90
+ *
91
+ * The cascade-guard contract for the puppeteer-fallback success / skipped
92
+ * branches can be exercised via `vi.spyOn(Crawler.prototype,
93
+ * '_launchBrowserAndScrape')` in unit tests. There is no production
94
+ * consumer outside this class.
95
+ * @internal
96
+ * @param url - Target URL to scrape
97
+ * @param update - Callback for progress messages
98
+ * @param isExternal - Whether the URL is external to the crawl scope
99
+ * @param metadataOnly - When true, only extract title metadata
100
+ * @param headCheckResult - Optional HEAD result to pass to the scraper, avoiding a redundant request
101
+ * @returns The scrape result from beholder
102
+ */
103
+ private _launchBrowserAndScrape;
83
104
  /**
84
105
  * The default maximum number of concurrent scraping processes.
85
106
  *