@nitpicker/crawler 0.12.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.
- package/README.md +6 -4
- package/lib/archive/archive-accessor.d.ts +2 -2
- package/lib/archive/archive-accessor.js +2 -2
- package/lib/archive/archive-lock.d.ts +7 -0
- package/lib/archive/archive-lock.js +7 -0
- package/lib/archive/archive.d.ts +63 -16
- package/lib/archive/archive.js +56 -17
- package/lib/archive/create-adjunct-tables.d.ts +43 -0
- package/lib/archive/create-adjunct-tables.js +213 -0
- package/lib/archive/create-entity-tables.d.ts +173 -0
- package/lib/archive/create-entity-tables.js +318 -0
- package/lib/archive/create-progress-reporter.d.ts +30 -0
- package/lib/archive/create-progress-reporter.js +38 -0
- package/lib/archive/create-ref-tables.d.ts +35 -0
- package/lib/archive/create-ref-tables.js +188 -0
- package/lib/archive/database.d.ts +92 -345
- package/lib/archive/database.js +168 -1942
- package/lib/archive/db-ops/_shared/clear-write-ref-caches.d.ts +27 -0
- package/lib/archive/db-ops/_shared/clear-write-ref-caches.js +34 -0
- package/lib/archive/db-ops/_shared/create-write-ref-caches.d.ts +17 -0
- package/lib/archive/db-ops/_shared/create-write-ref-caches.js +26 -0
- package/lib/archive/db-ops/_shared/decode-json-ref.d.ts +17 -0
- package/lib/archive/db-ops/_shared/decode-json-ref.js +31 -0
- package/lib/archive/db-ops/_shared/load-response-headers-by-set-ids.d.ts +20 -0
- package/lib/archive/db-ops/_shared/load-response-headers-by-set-ids.js +53 -0
- package/lib/archive/db-ops/_shared/resolve-content-item-id.d.ts +61 -0
- package/lib/archive/db-ops/_shared/resolve-content-item-id.js +111 -0
- package/lib/archive/db-ops/_shared/resolve-url-or-blob.d.ts +23 -0
- package/lib/archive/db-ops/_shared/resolve-url-or-blob.js +29 -0
- package/lib/archive/db-ops/_shared/retry-setting.d.ts +16 -0
- package/lib/archive/db-ops/_shared/retry-setting.js +18 -0
- package/lib/archive/db-ops/_shared/safe-parse-json.d.ts +11 -0
- package/lib/archive/db-ops/_shared/safe-parse-json.js +18 -0
- package/lib/archive/db-ops/_shared/types.d.ts +53 -0
- package/lib/archive/db-ops/_shared/types.js +1 -0
- package/lib/archive/db-ops/_shared/upsert-blob-ref.d.ts +25 -0
- package/lib/archive/db-ops/_shared/upsert-blob-ref.js +48 -0
- package/lib/archive/db-ops/_shared/upsert-content-type-ref.d.ts +30 -0
- package/lib/archive/db-ops/_shared/upsert-content-type-ref.js +45 -0
- package/lib/archive/db-ops/_shared/upsert-json-ref.d.ts +22 -0
- package/lib/archive/db-ops/_shared/upsert-json-ref.js +41 -0
- package/lib/archive/db-ops/_shared/upsert-response-headers.d.ts +35 -0
- package/lib/archive/db-ops/_shared/upsert-response-headers.js +49 -0
- package/lib/archive/db-ops/_shared/upsert-url-ref.d.ts +39 -0
- package/lib/archive/db-ops/_shared/upsert-url-ref.js +62 -0
- package/lib/archive/db-ops/analysis/replace-analysis-violations.d.ts +28 -0
- package/lib/archive/db-ops/analysis/replace-analysis-violations.js +152 -0
- package/lib/archive/db-ops/anchors/get-anchors-on-page.d.ts +10 -0
- package/lib/archive/db-ops/anchors/get-anchors-on-page.js +21 -0
- package/lib/archive/db-ops/config/get-base-url.d.ts +8 -0
- package/lib/archive/db-ops/config/get-base-url.js +14 -0
- package/lib/archive/db-ops/config/get-config.d.ts +10 -0
- package/lib/archive/db-ops/config/get-config.js +27 -0
- package/lib/archive/db-ops/config/get-name.d.ts +8 -0
- package/lib/archive/db-ops/config/get-name.js +14 -0
- package/lib/archive/db-ops/config/info-column-allowlist.d.ts +7 -0
- package/lib/archive/db-ops/config/info-column-allowlist.js +26 -0
- package/lib/archive/db-ops/config/info-json-columns.d.ts +5 -0
- package/lib/archive/db-ops/config/info-json-columns.js +10 -0
- package/lib/archive/db-ops/config/set-config.d.ts +12 -0
- package/lib/archive/db-ops/config/set-config.js +21 -0
- package/lib/archive/db-ops/config/update-config.d.ts +17 -0
- package/lib/archive/db-ops/config/update-config.js +36 -0
- package/lib/archive/db-ops/errors/insert-crawl-error.d.ts +15 -0
- package/lib/archive/db-ops/errors/insert-crawl-error.js +21 -0
- package/lib/archive/db-ops/errors/insert-page-error.d.ts +21 -0
- package/lib/archive/db-ops/errors/insert-page-error.js +28 -0
- package/lib/archive/db-ops/errors/list-dns-burned-host-candidates.d.ts +22 -0
- package/lib/archive/db-ops/errors/list-dns-burned-host-candidates.js +141 -0
- package/lib/archive/db-ops/html/get-html-of-page-by-id.d.ts +18 -0
- package/lib/archive/db-ops/html/get-html-of-page-by-id.js +29 -0
- package/lib/archive/db-ops/inventory/record-inventory-run.d.ts +21 -0
- package/lib/archive/db-ops/inventory/record-inventory-run.js +38 -0
- package/lib/archive/db-ops/lifecycle/checkpoint.d.ts +8 -0
- package/lib/archive/db-ops/lifecycle/checkpoint.js +9 -0
- package/lib/archive/db-ops/lifecycle/destroy.d.ts +6 -0
- package/lib/archive/db-ops/lifecycle/destroy.js +7 -0
- package/lib/archive/db-ops/lifecycle/init.d.ts +22 -0
- package/lib/archive/db-ops/lifecycle/init.js +42 -0
- package/lib/archive/db-ops/meta/get-jsonld-of-page.d.ts +13 -0
- package/lib/archive/db-ops/meta/get-jsonld-of-page.js +27 -0
- package/lib/archive/db-ops/meta/get-tags-of-page.d.ts +12 -0
- package/lib/archive/db-ops/meta/get-tags-of-page.js +28 -0
- package/lib/archive/db-ops/pages/order/set-url-order.d.ts +8 -0
- package/lib/archive/db-ops/pages/order/set-url-order.js +32 -0
- package/lib/archive/db-ops/pages/read/build-page-query.d.ts +18 -0
- package/lib/archive/db-ops/pages/read/build-page-query.js +40 -0
- package/lib/archive/db-ops/pages/read/get-crawling-state.d.ts +70 -0
- package/lib/archive/db-ops/pages/read/get-crawling-state.js +98 -0
- package/lib/archive/db-ops/pages/read/get-existing-page-urls.d.ts +15 -0
- package/lib/archive/db-ops/pages/read/get-existing-page-urls.js +30 -0
- package/lib/archive/db-ops/pages/read/get-page-count.d.ts +12 -0
- package/lib/archive/db-ops/pages/read/get-page-count.js +21 -0
- package/lib/archive/db-ops/pages/read/get-page-source-by-url.d.ts +24 -0
- package/lib/archive/db-ops/pages/read/get-page-source-by-url.js +28 -0
- package/lib/archive/db-ops/pages/read/get-pages-with-rels.d.ts +38 -0
- package/lib/archive/db-ops/pages/read/get-pages-with-rels.js +107 -0
- package/lib/archive/db-ops/pages/read/get-pages.d.ts +11 -0
- package/lib/archive/db-ops/pages/read/get-pages.js +51 -0
- package/lib/archive/db-ops/pages/read/get-scraped-html-page-count.d.ts +18 -0
- package/lib/archive/db-ops/pages/read/get-scraped-html-page-count.js +25 -0
- package/lib/archive/db-ops/pages/read/reconstruct-page-rows.d.ts +31 -0
- package/lib/archive/db-ops/pages/read/reconstruct-page-rows.js +32 -0
- package/lib/archive/db-ops/pages/reset/repromote-external-pages.d.ts +24 -0
- package/lib/archive/db-ops/pages/reset/repromote-external-pages.js +93 -0
- package/lib/archive/db-ops/pages/reset/reset-failed-pages.d.ts +47 -0
- package/lib/archive/db-ops/pages/reset/reset-failed-pages.js +124 -0
- package/lib/archive/db-ops/pages/write/insert-inventory-seeds.d.ts +37 -0
- package/lib/archive/db-ops/pages/write/insert-inventory-seeds.js +72 -0
- package/lib/archive/db-ops/pages/write/insert-jsonld.d.ts +17 -0
- package/lib/archive/db-ops/pages/write/insert-jsonld.js +49 -0
- package/lib/archive/db-ops/pages/write/insert-page.d.ts +36 -0
- package/lib/archive/db-ops/pages/write/insert-page.js +208 -0
- package/lib/archive/db-ops/pages/write/insert-tags.d.ts +16 -0
- package/lib/archive/db-ops/pages/write/insert-tags.js +34 -0
- package/lib/archive/db-ops/pages/write/link-redirect-sources.d.ts +36 -0
- package/lib/archive/db-ops/pages/write/link-redirect-sources.js +93 -0
- package/lib/archive/db-ops/pages/write/record-redirect.d.ts +35 -0
- package/lib/archive/db-ops/pages/write/record-redirect.js +100 -0
- package/lib/archive/db-ops/pages/write/set-skipped-page.d.ts +13 -0
- package/lib/archive/db-ops/pages/write/set-skipped-page.js +22 -0
- package/lib/archive/db-ops/pages/write/update-page.d.ts +29 -0
- package/lib/archive/db-ops/pages/write/update-page.js +334 -0
- package/lib/archive/db-ops/pages/write/write-page-html-blob.d.ts +19 -0
- package/lib/archive/db-ops/pages/write/write-page-html-blob.js +41 -0
- package/lib/archive/db-ops/referrers/get-redirects-for-pages.d.ts +9 -0
- package/lib/archive/db-ops/referrers/get-redirects-for-pages.js +15 -0
- package/lib/archive/db-ops/referrers/get-referrers-of-page.d.ts +17 -0
- package/lib/archive/db-ops/referrers/get-referrers-of-page.js +32 -0
- package/lib/archive/db-ops/referrers/get-referrers-of-resource.d.ts +8 -0
- package/lib/archive/db-ops/referrers/get-referrers-of-resource.js +15 -0
- package/lib/archive/db-ops/resources/build-resource-query.d.ts +25 -0
- package/lib/archive/db-ops/resources/build-resource-query.js +29 -0
- package/lib/archive/db-ops/resources/get-existing-resource-urls.d.ts +9 -0
- package/lib/archive/db-ops/resources/get-existing-resource-urls.js +24 -0
- package/lib/archive/db-ops/resources/get-resource-by-url.d.ts +13 -0
- package/lib/archive/db-ops/resources/get-resource-by-url.js +22 -0
- package/lib/archive/db-ops/resources/get-resource-url-list.d.ts +9 -0
- package/lib/archive/db-ops/resources/get-resource-url-list.js +13 -0
- package/lib/archive/db-ops/resources/get-resources.d.ts +8 -0
- package/lib/archive/db-ops/resources/get-resources.js +11 -0
- package/lib/archive/db-ops/resources/insert-inventory-resources.d.ts +24 -0
- package/lib/archive/db-ops/resources/insert-inventory-resources.js +64 -0
- package/lib/archive/db-ops/resources/insert-resource-referrers.d.ts +15 -0
- package/lib/archive/db-ops/resources/insert-resource-referrers.js +54 -0
- package/lib/archive/db-ops/resources/insert-resource.d.ts +34 -0
- package/lib/archive/db-ops/resources/insert-resource.js +73 -0
- package/lib/archive/db-ops/resources/reconstruct-resource-rows.d.ts +26 -0
- package/lib/archive/db-ops/resources/reconstruct-resource-rows.js +30 -0
- package/lib/archive/decode-html-blob.d.ts +18 -0
- package/lib/archive/decode-html-blob.js +31 -0
- package/lib/archive/derive-lineage-from-parent.d.ts +1 -1
- package/lib/archive/derive-lineage-from-parent.js +1 -1
- package/lib/archive/drop-legacy-tables.d.ts +45 -0
- package/lib/archive/drop-legacy-tables.js +56 -0
- package/lib/archive/filesystem/rename.js +1 -1
- package/lib/archive/get-failed-page-messages.d.ts +5 -4
- package/lib/archive/get-failed-page-messages.js +5 -4
- package/lib/archive/init-schema.d.ts +35 -39
- package/lib/archive/init-schema.js +99 -460
- package/lib/archive/limited-page-ids.d.ts +2 -1
- package/lib/archive/limited-page-ids.js +5 -4
- package/lib/archive/meta/assert-compatible-version.d.ts +24 -3
- package/lib/archive/meta/assert-compatible-version.js +24 -3
- package/lib/archive/meta/types.d.ts +87 -1
- package/lib/archive/meta/types.js +34 -2
- package/lib/archive/migrate-entity-tables.d.ts +45 -0
- package/lib/archive/migrate-entity-tables.js +56 -0
- package/lib/archive/migrate-ref-tables.d.ts +25 -0
- package/lib/archive/migrate-ref-tables.js +38 -0
- package/lib/archive/page-meta-column-maps.d.ts +32 -0
- package/lib/archive/page-meta-column-maps.js +43 -0
- package/lib/archive/page.d.ts +6 -6
- package/lib/archive/page.js +5 -5
- package/lib/archive/peek-archive-lock.d.ts +2 -2
- package/lib/archive/peek-archive-lock.js +2 -2
- package/lib/archive/populate-entity-tables/collapse-anchor-rows.d.ts +41 -0
- package/lib/archive/populate-entity-tables/collapse-anchor-rows.js +87 -0
- package/lib/archive/populate-entity-tables/derive-dom-path.d.ts +35 -0
- package/lib/archive/populate-entity-tables/derive-dom-path.js +72 -0
- package/lib/archive/populate-entity-tables/is-blob-ref-value.d.ts +16 -0
- package/lib/archive/populate-entity-tables/is-blob-ref-value.js +19 -0
- package/lib/archive/populate-entity-tables/match-images-to-dom-paths.d.ts +66 -0
- package/lib/archive/populate-entity-tables/match-images-to-dom-paths.js +96 -0
- package/lib/archive/populate-entity-tables/populate-anchor-edges.d.ts +33 -0
- package/lib/archive/populate-entity-tables/populate-anchor-edges.js +153 -0
- package/lib/archive/populate-entity-tables/populate-content-items.d.ts +40 -0
- package/lib/archive/populate-entity-tables/populate-content-items.js +141 -0
- package/lib/archive/populate-entity-tables/populate-entities.d.ts +81 -0
- package/lib/archive/populate-entity-tables/populate-entities.js +111 -0
- package/lib/archive/populate-entity-tables/populate-image-items.d.ts +91 -0
- package/lib/archive/populate-entity-tables/populate-image-items.js +223 -0
- package/lib/archive/populate-entity-tables/populate-page-meta.d.ts +33 -0
- package/lib/archive/populate-entity-tables/populate-page-meta.js +267 -0
- package/lib/archive/populate-entity-tables/populate-resource-items.d.ts +22 -0
- package/lib/archive/populate-entity-tables/populate-resource-items.js +114 -0
- package/lib/archive/populate-entity-tables/populate-resource-ref-edges.d.ts +31 -0
- package/lib/archive/populate-entity-tables/populate-resource-ref-edges.js +33 -0
- package/lib/archive/populate-entity-tables/resolve-blob-refs.d.ts +31 -0
- package/lib/archive/populate-entity-tables/resolve-blob-refs.js +100 -0
- package/lib/archive/populate-entity-tables/resolve-content-type-refs.d.ts +22 -0
- package/lib/archive/populate-entity-tables/resolve-content-type-refs.js +27 -0
- package/lib/archive/populate-entity-tables/resolve-header-sets.d.ts +49 -0
- package/lib/archive/populate-entity-tables/resolve-header-sets.js +122 -0
- package/lib/archive/populate-entity-tables/resolve-json-refs.d.ts +25 -0
- package/lib/archive/populate-entity-tables/resolve-json-refs.js +67 -0
- package/lib/archive/populate-entity-tables/resolve-text-refs.d.ts +30 -0
- package/lib/archive/populate-entity-tables/resolve-text-refs.js +61 -0
- package/lib/archive/populate-entity-tables/resolve-url-or-blob-from-maps.d.ts +21 -0
- package/lib/archive/populate-entity-tables/resolve-url-or-blob-from-maps.js +27 -0
- package/lib/archive/populate-entity-tables/resolve-url-refs.d.ts +33 -0
- package/lib/archive/populate-entity-tables/resolve-url-refs.js +60 -0
- package/lib/archive/populate-entity-tables/test-utils/count-rows.d.ts +17 -0
- package/lib/archive/populate-entity-tables/test-utils/count-rows.js +20 -0
- package/lib/archive/populate-entity-tables/test-utils/seed-content-items.d.ts +25 -0
- package/lib/archive/populate-entity-tables/test-utils/seed-content-items.js +42 -0
- package/lib/archive/populate-entity-tables/test-utils/setup-entities-db.d.ts +23 -0
- package/lib/archive/populate-entity-tables/test-utils/setup-entities-db.js +178 -0
- package/lib/archive/populate-entity-tables/types.d.ts +157 -0
- package/lib/archive/populate-entity-tables/types.js +12 -0
- package/lib/archive/populate-entity-tables/upsert-text-refs.d.ts +38 -0
- package/lib/archive/populate-entity-tables/upsert-text-refs.js +78 -0
- package/lib/archive/populate-ref-tables/classify-content-type.d.ts +16 -0
- package/lib/archive/populate-ref-tables/classify-content-type.js +52 -0
- package/lib/archive/populate-ref-tables/compute-content-hash.d.ts +22 -0
- package/lib/archive/populate-ref-tables/compute-content-hash.js +26 -0
- package/lib/archive/populate-ref-tables/compute-header-flags.d.ts +16 -0
- package/lib/archive/populate-ref-tables/compute-header-flags.js +70 -0
- package/lib/archive/populate-ref-tables/content-type-rules.d.ts +38 -0
- package/lib/archive/populate-ref-tables/content-type-rules.js +133 -0
- package/lib/archive/populate-ref-tables/create-header-table-caches.d.ts +25 -0
- package/lib/archive/populate-ref-tables/create-header-table-caches.js +49 -0
- package/lib/archive/populate-ref-tables/data-uri-url-refs-limit.d.ts +15 -0
- package/lib/archive/populate-ref-tables/data-uri-url-refs-limit.js +15 -0
- package/lib/archive/populate-ref-tables/decode-data-uri.d.ts +21 -0
- package/lib/archive/populate-ref-tables/decode-data-uri.js +126 -0
- package/lib/archive/populate-ref-tables/decompose-header-set.d.ts +29 -0
- package/lib/archive/populate-ref-tables/decompose-header-set.js +157 -0
- package/lib/archive/populate-ref-tables/decompose-url.d.ts +25 -0
- package/lib/archive/populate-ref-tables/decompose-url.js +70 -0
- package/lib/archive/populate-ref-tables/header-stability.d.ts +19 -0
- package/lib/archive/populate-ref-tables/header-stability.js +22 -0
- package/lib/archive/populate-ref-tables/header-value-cache-key.d.ts +17 -0
- package/lib/archive/populate-ref-tables/header-value-cache-key.js +19 -0
- package/lib/archive/populate-ref-tables/normalize-mime.d.ts +24 -0
- package/lib/archive/populate-ref-tables/normalize-mime.js +36 -0
- package/lib/archive/populate-ref-tables/populate-blob-refs.d.ts +38 -0
- package/lib/archive/populate-ref-tables/populate-blob-refs.js +134 -0
- package/lib/archive/populate-ref-tables/populate-content-type-refs.d.ts +27 -0
- package/lib/archive/populate-ref-tables/populate-content-type-refs.js +70 -0
- package/lib/archive/populate-ref-tables/populate-header-tables.d.ts +35 -0
- package/lib/archive/populate-ref-tables/populate-header-tables.js +80 -0
- package/lib/archive/populate-ref-tables/populate-json-refs.d.ts +29 -0
- package/lib/archive/populate-ref-tables/populate-json-refs.js +101 -0
- package/lib/archive/populate-ref-tables/populate-refs.d.ts +51 -0
- package/lib/archive/populate-ref-tables/populate-refs.js +62 -0
- package/lib/archive/populate-ref-tables/populate-text-refs.d.ts +32 -0
- package/lib/archive/populate-ref-tables/populate-text-refs.js +133 -0
- package/lib/archive/populate-ref-tables/populate-url-refs.d.ts +28 -0
- package/lib/archive/populate-ref-tables/populate-url-refs.js +148 -0
- package/lib/archive/populate-ref-tables/test-utils/count-rows.d.ts +15 -0
- package/lib/archive/populate-ref-tables/test-utils/count-rows.js +17 -0
- package/lib/archive/populate-ref-tables/types.d.ts +197 -0
- package/lib/archive/populate-ref-tables/types.js +7 -0
- package/lib/archive/populate-ref-tables/upsert-one-header-set.d.ts +34 -0
- package/lib/archive/populate-ref-tables/upsert-one-header-set.js +208 -0
- package/lib/archive/populate-ref-tables/volatile-header-names.d.ts +20 -0
- package/lib/archive/populate-ref-tables/volatile-header-names.js +33 -0
- package/lib/archive/redirect-table.d.ts +4 -2
- package/lib/archive/redirect-table.js +15 -10
- package/lib/archive/resolve-redirect-chain.d.ts +3 -3
- package/lib/archive/resolve-redirect-chain.js +2 -2
- package/lib/archive/resource.d.ts +1 -1
- package/lib/archive/retarget-legacy-fk-tables.d.ts +47 -0
- package/lib/archive/retarget-legacy-fk-tables.js +107 -0
- package/lib/archive/test-utils/fk-parent-tables.d.ts +15 -0
- package/lib/archive/test-utils/fk-parent-tables.js +19 -0
- package/lib/archive/test-utils/seed-content-item.d.ts +35 -0
- package/lib/archive/test-utils/seed-content-item.js +42 -0
- package/lib/archive/test-utils/setup-legacy-fk-db.d.ts +33 -0
- package/lib/archive/test-utils/setup-legacy-fk-db.js +270 -0
- package/lib/archive/types.d.ts +127 -24
- package/lib/archive/verify-migration/capture-rejection.d.ts +24 -0
- package/lib/archive/verify-migration/capture-rejection.js +31 -0
- package/lib/archive/verify-migration/check-anchor-edges-count.d.ts +34 -0
- package/lib/archive/verify-migration/check-anchor-edges-count.js +72 -0
- package/lib/archive/verify-migration/check-anchor-edges-sum.d.ts +13 -0
- package/lib/archive/verify-migration/check-anchor-edges-sum.js +27 -0
- package/lib/archive/verify-migration/check-content-items-count.d.ts +16 -0
- package/lib/archive/verify-migration/check-content-items-count.js +30 -0
- package/lib/archive/verify-migration/check-content-type-preservation.d.ts +22 -0
- package/lib/archive/verify-migration/check-content-type-preservation.js +40 -0
- package/lib/archive/verify-migration/check-foreign-key-integrity.d.ts +31 -0
- package/lib/archive/verify-migration/check-foreign-key-integrity.js +47 -0
- package/lib/archive/verify-migration/check-image-items-count.d.ts +12 -0
- package/lib/archive/verify-migration/check-image-items-count.js +26 -0
- package/lib/archive/verify-migration/check-page-meta-count.d.ts +15 -0
- package/lib/archive/verify-migration/check-page-meta-count.js +31 -0
- package/lib/archive/verify-migration/check-reader-parity.d.ts +23 -0
- package/lib/archive/verify-migration/check-reader-parity.js +211 -0
- package/lib/archive/verify-migration/check-resource-items-count.d.ts +17 -0
- package/lib/archive/verify-migration/check-resource-items-count.js +33 -0
- package/lib/archive/verify-migration/check-url-round-trip.d.ts +43 -0
- package/lib/archive/verify-migration/check-url-round-trip.js +112 -0
- package/lib/archive/verify-migration/types.d.ts +70 -0
- package/lib/archive/verify-migration/types.js +63 -0
- package/lib/archive/verify-migration/verify-migration.d.ts +41 -0
- package/lib/archive/verify-migration/verify-migration.js +120 -0
- package/lib/crawler/build-redirect-event.d.ts +1 -1
- package/lib/crawler/build-redirect-event.js +1 -1
- package/lib/crawler/capture-image-dom-paths.d.ts +33 -0
- package/lib/crawler/capture-image-dom-paths.js +39 -0
- package/lib/crawler/clear-dns-burned-host-cache.d.ts +1 -1
- package/lib/crawler/clear-dns-burned-host-cache.js +1 -1
- package/lib/crawler/collect-image-dom-paths.d.ts +23 -0
- package/lib/crawler/collect-image-dom-paths.js +64 -0
- package/lib/crawler/crawler.d.ts +19 -0
- package/lib/crawler/crawler.js +40 -26
- package/lib/crawler/dns-burned-host-cache.d.ts +3 -3
- package/lib/crawler/dns-burned-host-cache.js +3 -3
- package/lib/crawler/dns-burned-host-short-circuit-counter.d.ts +2 -2
- package/lib/crawler/dns-burned-host-short-circuit-counter.js +2 -2
- package/lib/crawler/inject-scope-auth.d.ts +1 -1
- package/lib/crawler/inject-scope-auth.js +1 -1
- package/lib/crawler/normalize-content-type.d.ts +1 -1
- package/lib/crawler/normalize-content-type.js +1 -1
- package/lib/crawler/types.d.ts +3 -3
- package/lib/crawler-orchestrator.d.ts +9 -0
- package/lib/crawler-orchestrator.js +44 -28
- package/lib/crawler.d.ts +12 -0
- package/lib/crawler.js +21 -0
- package/lib/permanent-error-kinds.d.ts +1 -1
- package/lib/permanent-error-kinds.js +1 -1
- package/lib/types.d.ts +1 -1
- package/lib/utils/compute-file-sha256.d.ts +5 -4
- package/lib/utils/compute-file-sha256.js +5 -4
- package/lib/utils/error/emit-error-with-retry.d.ts +1 -1
- package/lib/utils/error/emit-error-with-retry.js +1 -1
- package/package.json +10 -10
- package/lib/archive/migrate-crawl-errors.d.ts +0 -20
- package/lib/archive/migrate-crawl-errors.js +0 -38
- package/lib/archive/migrate-html-blob-tables.d.ts +0 -24
- package/lib/archive/migrate-html-blob-tables.js +0 -53
- package/lib/archive/migrate-inventory-runs.d.ts +0 -29
- package/lib/archive/migrate-inventory-runs.js +0 -52
- package/lib/archive/migrate-page-errors.d.ts +0 -16
- package/lib/archive/migrate-page-errors.js +0 -35
- package/lib/archive/migrate-pages-resources-source.d.ts +0 -16
- package/lib/archive/migrate-pages-resources-source.js +0 -46
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { JsonLdRow, TagRow } from './meta/types.js';
|
|
2
|
-
import type { Config, DatabaseOption,
|
|
2
|
+
import type { Config, DatabaseOption, DB_Redirect, DB_Resource, DatabaseEvent, InventoryRunMeta, PageFilter, PageSource } from './types.js';
|
|
3
3
|
import type { PageData, Resource } from '../utils/types/types.js';
|
|
4
4
|
import type { ExURL, ParseURLOptions } from '@d-zero/shared/parse-url';
|
|
5
5
|
import type { Knex } from 'knex';
|
|
@@ -7,12 +7,14 @@ import { TypedAwaitEventEmitter as EventEmitter } from '@d-zero/shared/typed-awa
|
|
|
7
7
|
/**
|
|
8
8
|
* Low-level database abstraction layer for the archive's SQLite database.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
10
|
+
* Every method is a thin dispatcher: the SQL itself lives in a dedicated
|
|
11
|
+
* single-export op module under `./db-ops/` (one file per operation), and
|
|
12
|
+
* the class contributes only the connection (`this.#instance`) plus the
|
|
13
|
+
* error/retry wrapper. Public methods that perform database queries use the
|
|
14
|
+
* `emitErrorAndRetry` HOF for automatic retry on transient failures combined
|
|
15
|
+
* with error-event propagation, or `emitError` when retry is not appropriate.
|
|
16
|
+
* The set of tables this layer manages is defined by `init-schema.ts` (the
|
|
17
|
+
* source of truth — query that file for the canonical list).
|
|
16
18
|
*
|
|
17
19
|
* **Label sync caveat**: each `emitError` / `emitErrorAndRetry` call passes
|
|
18
20
|
* the method name as a string literal (e.g. `'Database.getAnchorsOnPage'`).
|
|
@@ -28,103 +30,40 @@ export declare class Database extends EventEmitter<DatabaseEvent> {
|
|
|
28
30
|
#private;
|
|
29
31
|
private constructor();
|
|
30
32
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* @deprecated Since v0.1.x. The column is now created during table initialization.
|
|
34
|
-
* @returns The result of the schema alteration, or void if the column already exists.
|
|
35
|
-
*/
|
|
36
|
-
addOrderField(): Promise<void>;
|
|
37
|
-
/**
|
|
38
|
-
* Forces a WAL checkpoint, writing all pending WAL data back to the main database file.
|
|
39
|
-
* Uses TRUNCATE mode to reset the WAL file to zero bytes after checkpointing.
|
|
40
|
-
* This ensures the database is fully self-contained in `db.sqlite` before archiving.
|
|
33
|
+
* Forces a WAL checkpoint, writing all pending WAL data back to the main
|
|
34
|
+
* database file. Delegates to {@link checkpointOp}.
|
|
41
35
|
*/
|
|
42
36
|
checkpoint(): Promise<void>;
|
|
43
37
|
/**
|
|
44
38
|
* Destroys the database connection, releasing all pooled resources.
|
|
39
|
+
* Delegates to {@link destroyOp}.
|
|
45
40
|
*/
|
|
46
41
|
destroy(): Promise<void>;
|
|
47
42
|
/**
|
|
48
43
|
* Retrieves all anchors (outgoing links) on a specific page.
|
|
49
|
-
*
|
|
44
|
+
* Delegates to {@link getAnchorsOnPageOp}.
|
|
50
45
|
* @param pageId - The database ID of the page whose anchors to retrieve.
|
|
51
46
|
* @returns An array of anchor records with resolved URL, title, status, and content type.
|
|
52
47
|
*/
|
|
53
48
|
getAnchorsOnPage(pageId: number): Promise<any[]>;
|
|
54
49
|
/**
|
|
55
50
|
* Retrieves the base URL of the crawl session from the `info` table.
|
|
51
|
+
* Delegates to {@link getBaseUrlOp}.
|
|
56
52
|
* @returns The base URL string.
|
|
57
53
|
* @throws {Error} If no base URL is found in the database.
|
|
58
54
|
*/
|
|
59
|
-
getBaseUrl(): Promise<
|
|
55
|
+
getBaseUrl(): Promise<string>;
|
|
60
56
|
/**
|
|
61
57
|
* Retrieves the full crawl configuration from the `info` table.
|
|
62
|
-
*
|
|
58
|
+
* Delegates to {@link getConfigOp}.
|
|
63
59
|
* @returns The parsed {@link Config} object.
|
|
64
60
|
* @throws {Error} If no configuration is found in the database.
|
|
65
61
|
*/
|
|
66
62
|
getConfig(): Promise<Config>;
|
|
67
63
|
/**
|
|
68
64
|
* Retrieves the current crawling state by listing scraped and pending URLs.
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
* — that is, every URL the crawl reached a terminal state on, including
|
|
72
|
-
* setSkippedPage / setExternalPage / outright setPage success or failure.
|
|
73
|
-
*
|
|
74
|
-
* `pending` is intentionally STRICT — not "every `scraped = 0` row".
|
|
75
|
-
* Three filters apply:
|
|
76
|
-
*
|
|
77
|
-
* 1. `scraped = 0` — work still incomplete.
|
|
78
|
-
* 2. `isExternal = 0` — only in-scope work. External URLs go through a
|
|
79
|
-
* HEAD-only path that always lands on `scraped = 1` (either setPage or
|
|
80
|
-
* setExternalPage). A row with `isExternal = 1 AND scraped = 0` is
|
|
81
|
-
* therefore a data anomaly, and resume / inventory / append have no
|
|
82
|
-
* business retrying it on the next session.
|
|
83
|
-
* 3. `EXISTS (anchor with hrefId = pages.id) OR source != 'crawled'` —
|
|
84
|
-
* the row was either discovered as an anchor destination during a
|
|
85
|
-
* previous scrape OR was explicitly tagged with a non-default
|
|
86
|
-
* source label (`'inventory-seed'`, `'inventory-discovered'`, …).
|
|
87
|
-
* Both halves of the OR represent "deliberately enqueued, expected
|
|
88
|
-
* to be processed", which is exactly what `resume` should pick up.
|
|
89
|
-
*
|
|
90
|
-
* The orphan filter targets the **predicted-discard leak** in
|
|
91
|
-
* `crawler.ts` where `shouldDiscardPredicted` returns true but no
|
|
92
|
-
* `emit('skip')` follows. Such placeholders are inserted with the
|
|
93
|
-
* DB DEFAULT `source = 'crawled'` (no caller explicitly labels
|
|
94
|
-
* them) AND have no anchor referrer (predicted URLs are
|
|
95
|
-
* synthesised from pagination patterns, never anchored from a
|
|
96
|
-
* rendered page) — both halves of the OR are therefore false and
|
|
97
|
-
* the leak is excluded.
|
|
98
|
-
*
|
|
99
|
-
* The `source != 'crawled'` clause specifically saves the
|
|
100
|
-
* `--inventory` × `--retry-failed` interaction: an inventory-seed
|
|
101
|
-
* URL came from the operator's URL list (no anchor referrer) and
|
|
102
|
-
* `resetFailedPages` puts it back at `scraped = 0`. Without this
|
|
103
|
-
* clause those legitimate retries would be dropped on resume.
|
|
104
|
-
*
|
|
105
|
-
* The defensive shape is on purpose: the data source can drift into
|
|
106
|
-
* anomalous states under interruption, but the reader must never throw
|
|
107
|
-
* or feed garbage back into the dealer. A real in-scope URL that was
|
|
108
|
-
* truly interrupted mid-crawl will always have at least one anchor
|
|
109
|
-
* referrer (otherwise the dealer would not have queued it), so the
|
|
110
|
-
* strict filter loses no legitimate pending work.
|
|
111
|
-
*
|
|
112
|
-
* Seeds passed directly to `Crawler.start()` are NOT in the strict
|
|
113
|
-
* pending set when they were never picked by the dealer — they have no
|
|
114
|
-
* DB row at all in that case (`linkList.add` is purely in-memory until
|
|
115
|
-
* `setPage` runs). A Ctrl-C between dealer pick and `setPage` likewise
|
|
116
|
-
* leaves no row to recover. Recovery of un-picked seeds is the
|
|
117
|
-
* responsibility of the caller (e.g. re-running `--inventory ./list.txt`
|
|
118
|
-
* with the same URL list).
|
|
119
|
-
*
|
|
120
|
-
* The query uses an explicit `p` alias on the `pages` table so the
|
|
121
|
-
* correlated `EXISTS` subquery can join via `whereRaw('anchors.hrefId =
|
|
122
|
-
* p.id')`. A future refactor that renames the alias must update both
|
|
123
|
-
* sites — the raw string in the subquery cannot be grep-resolved
|
|
124
|
-
* automatically. Read-only / stub viewer connections never call this
|
|
125
|
-
* method (they do not need to know about pending state), so the EXISTS
|
|
126
|
-
* shape is safe to use without the `migrate*` guards that other writer
|
|
127
|
-
* methods carry.
|
|
65
|
+
* Delegates to {@link getCrawlingStateOp} — see the op for the strict
|
|
66
|
+
* pending-set rationale.
|
|
128
67
|
* @returns An object with `scraped` (completed URLs) and `pending` (the
|
|
129
68
|
* strict set of in-scope, anchor-referenced, unfinished URLs).
|
|
130
69
|
*/
|
|
@@ -134,47 +73,28 @@ export declare class Database extends EventEmitter<DatabaseEvent> {
|
|
|
134
73
|
}>;
|
|
135
74
|
/**
|
|
136
75
|
* Return the subset of `urls` that already exist in the `pages` table.
|
|
137
|
-
*
|
|
138
|
-
* (`SQLITE_MAX_VARIABLE_NUMBER`, default 999) cannot be hit even when the
|
|
139
|
-
* inventory list contains tens of thousands of URLs.
|
|
140
|
-
*
|
|
141
|
-
* Read-only — no transaction, no lock contention with the crawler write
|
|
142
|
-
* pipeline (callers run this BEFORE the `<archive>.bak` is taken and the
|
|
143
|
-
* crawl is started).
|
|
76
|
+
* Delegates to {@link getExistingPageUrlsOp}.
|
|
144
77
|
* @param urls - URL strings to probe (already in `withoutHashAndAuth` form).
|
|
145
78
|
* @returns URLs found in `pages`. Order is not preserved.
|
|
146
79
|
*/
|
|
147
80
|
getExistingPageUrls(urls: readonly string[]): Promise<string[]>;
|
|
148
81
|
/**
|
|
149
82
|
* Return the subset of `urls` that already exist in the `resources` table.
|
|
150
|
-
*
|
|
83
|
+
* Delegates to {@link getExistingResourceUrlsOp}.
|
|
151
84
|
* @param urls - URL strings to probe.
|
|
152
85
|
* @returns URLs found in `resources`.
|
|
153
86
|
*/
|
|
154
87
|
getExistingResourceUrls(urls: readonly string[]): Promise<string[]>;
|
|
155
88
|
/**
|
|
156
89
|
* Reads the HTML snapshot stored as a zstd-compressed BLOB for the given page.
|
|
157
|
-
*
|
|
158
|
-
* Joins `page_html_ref` → `page_html_blobs` and decompresses inline. Returns
|
|
159
|
-
* `null` when the page has no stored body (a non-HTML resource, a redirect
|
|
160
|
-
* source, a degraded render). Read works identically on read-only / stub
|
|
161
|
-
* connections — the special-cased "do we have a loose dir vs zip?" branching
|
|
162
|
-
* the previous file-backed layout required is gone.
|
|
163
|
-
*
|
|
164
|
-
* Tables `page_html_ref` and `page_html_blobs` are created by `initSchema`.
|
|
165
|
-
* Older `.nitpicker` archives that predate this migration must be passed
|
|
166
|
-
* through `scripts/migrate-to-0.10.mjs` before they can be read.
|
|
90
|
+
* Delegates to {@link getHtmlOfPageByIdOp}.
|
|
167
91
|
* @param pageId - The database ID of the page.
|
|
168
92
|
* @returns The decompressed HTML string, or `null` if no snapshot is stored.
|
|
169
93
|
*/
|
|
170
94
|
getHtmlOfPageById(pageId: number): Promise<string | null>;
|
|
171
95
|
/**
|
|
172
96
|
* Retrieves all `page_jsonld` rows for the given page id, parsed back into
|
|
173
|
-
* {@link JsonLdRow} shape
|
|
174
|
-
*
|
|
175
|
-
* Read-side counterpart to `#insertJsonLd`. Returns rows in insertion order
|
|
176
|
-
* by `id` so the order observed by `get-page-jsonld` matches the order the
|
|
177
|
-
* scraper saw them.
|
|
97
|
+
* {@link JsonLdRow} shape. Delegates to {@link getJsonLdOfPageOp}.
|
|
178
98
|
* @param pageId
|
|
179
99
|
*/
|
|
180
100
|
getJsonLdOfPage(pageId: number): Promise<JsonLdRow[]>;
|
|
@@ -187,90 +107,72 @@ export declare class Database extends EventEmitter<DatabaseEvent> {
|
|
|
187
107
|
getKnex(): Knex;
|
|
188
108
|
/**
|
|
189
109
|
* Retrieves the crawl session name from the `info` table.
|
|
110
|
+
* Delegates to {@link getNameOp}.
|
|
190
111
|
* @returns The name string.
|
|
191
112
|
* @throws {Error} If no name is found in the database.
|
|
192
113
|
*/
|
|
193
|
-
getName(): Promise<
|
|
114
|
+
getName(): Promise<string>;
|
|
194
115
|
/**
|
|
195
116
|
* Counts the total number of pages in the database.
|
|
117
|
+
* Delegates to {@link getPageCountOp}.
|
|
196
118
|
* @returns The total page count.
|
|
197
119
|
* @throws {Error} If the count query fails.
|
|
198
120
|
*/
|
|
199
121
|
getPageCount(): Promise<number>;
|
|
200
122
|
/**
|
|
201
|
-
* Retrieves pages from the database with optional filtering, pagination via
|
|
123
|
+
* Retrieves pages from the database with optional filtering, pagination via
|
|
124
|
+
* offset and limit. Delegates to {@link getPagesOp}.
|
|
202
125
|
* @param filter - An optional {@link PageFilter} to narrow results by content type and origin.
|
|
203
126
|
* @param offset - The number of rows to skip. Defaults to `0`.
|
|
204
127
|
* @param limit - The maximum number of rows to return. Defaults to `100000`.
|
|
205
|
-
* @returns An array of raw
|
|
128
|
+
* @returns An array of raw `DB_Page` rows.
|
|
206
129
|
*/
|
|
207
|
-
getPages(filter?: PageFilter, offset?: number, limit?: number): Promise<DB_Page[]>;
|
|
130
|
+
getPages(filter?: PageFilter, offset?: number, limit?: number): Promise<import("./types.js").DB_Page[]>;
|
|
208
131
|
/**
|
|
209
|
-
* Look up the `source` column of a single page by its URL key.
|
|
210
|
-
*
|
|
211
|
-
* resolve a parent page's lineage on `--resume` / `--retry-failed`
|
|
212
|
-
* sessions, where the in-memory `inventoryMode` is no longer
|
|
213
|
-
* available but the DB still remembers what label was last persisted.
|
|
214
|
-
*
|
|
215
|
-
* Returns `undefined` when the URL has no `pages` row (e.g. a brand-new
|
|
216
|
-
* URL that has not been seen yet) so the caller can fall through to
|
|
217
|
-
* its default behaviour without distinguishing "row absent" from "row
|
|
218
|
-
* present with NULL source" — the schema's `NOT NULL DEFAULT 'crawled'`
|
|
219
|
-
* makes a NULL value impossible in practice.
|
|
220
|
-
*
|
|
221
|
-
* Read-only — no transaction, single PK-equivalent lookup on
|
|
222
|
-
* `pages.url` (a UNIQUE column), so the cost is constant per call. The
|
|
223
|
-
* Crawler calls this at most once per page render, NOT per
|
|
224
|
-
* sub-resource, so the N+1 risk does not apply.
|
|
132
|
+
* Look up the `source` column of a single page by its URL key.
|
|
133
|
+
* Delegates to {@link getPageSourceByUrlOp}.
|
|
225
134
|
* @param url - URL key in `url.withoutHashAndAuth` form.
|
|
226
135
|
* @returns The recorded `source`, or `undefined` when no row exists.
|
|
227
136
|
*/
|
|
228
137
|
getPageSourceByUrl(url: string): Promise<PageSource | undefined>;
|
|
229
138
|
/**
|
|
230
139
|
* Retrieves pages along with their related redirect, anchor, and referrer data.
|
|
231
|
-
* Results are ordered by the natural URL sort order. Only non-redirected pages
|
|
140
|
+
* Results are ordered by the natural URL sort order. Only non-redirected pages
|
|
141
|
+
* are returned. Delegates to {@link getPagesWithRelsOp}.
|
|
232
142
|
* @param offset - The number of rows to skip.
|
|
233
143
|
* @param limit - The maximum number of pages to return.
|
|
234
144
|
* @returns An object containing `pages`, `redirects`, `anchors`, and `referrers` arrays.
|
|
235
145
|
*/
|
|
236
146
|
getPagesWithRels(offset: number, limit: number): Promise<{
|
|
237
|
-
pages: DB_Page[];
|
|
147
|
+
pages: import("./types.js").DB_Page[];
|
|
238
148
|
redirects: DB_Redirect[];
|
|
239
|
-
anchors: DB_Anchor[];
|
|
240
|
-
referrers: DB_Referrer[];
|
|
149
|
+
anchors: import("./types.js").DB_Anchor[];
|
|
150
|
+
referrers: import("./types.js").DB_Referrer[];
|
|
241
151
|
}>;
|
|
242
152
|
/**
|
|
243
153
|
* Retrieves redirect sources for the given page IDs in bulk.
|
|
154
|
+
* Delegates to {@link getRedirectsForPagesOp}.
|
|
244
155
|
* @param pageIds - The database IDs of the destination pages.
|
|
245
156
|
* @returns An array of {@link DB_Redirect} records mapping destination pages to their redirect sources.
|
|
246
157
|
*/
|
|
247
158
|
getRedirectsForPages(pageIds: number[]): Promise<DB_Redirect[]>;
|
|
248
159
|
/**
|
|
249
|
-
* Retrieves pages that link to a specific page (incoming links / referrers)
|
|
250
|
-
*
|
|
251
|
-
* Incoming links are resolved **through redirects**: an anchor pointing at a
|
|
252
|
-
* redirect source (e.g. `http://x` that 301s to `https://x`) counts as a
|
|
253
|
-
* referrer of the redirect's final destination, not of the source. This keeps
|
|
254
|
-
* backlinks merged on the canonical page instead of splitting them across the
|
|
255
|
-
* `http`/`https` (or any redirect source/dest) pair. The resolution mirrors
|
|
256
|
-
* `redirectTable()` — `redirectDestId` is pre-flattened to the final
|
|
257
|
-
* destination, so `COALESCE(target.redirectDestId, target.id)` is a single hop.
|
|
160
|
+
* Retrieves pages that link to a specific page (incoming links / referrers),
|
|
161
|
+
* resolved through redirects. Delegates to {@link getReferrersOfPageOp}.
|
|
258
162
|
* @param pageId - The database ID of the target page.
|
|
259
163
|
* @returns An array of referrer records with URL, hash, and text content.
|
|
260
164
|
*/
|
|
261
165
|
getReferrersOfPage(pageId: number): Promise<any[]>;
|
|
262
166
|
/**
|
|
263
167
|
* Retrieves the page URLs that reference a specific resource.
|
|
168
|
+
* Delegates to {@link getReferrersOfResourceOp}.
|
|
264
169
|
* @param id - The database ID of the resource.
|
|
265
170
|
* @returns An array of page URL strings that reference the resource.
|
|
266
171
|
*/
|
|
267
172
|
getReferrersOfResource(id: number): Promise<string[]>;
|
|
268
173
|
/**
|
|
269
174
|
* Retrieves a single sub-resource from the `resources` table by its URL.
|
|
270
|
-
*
|
|
271
|
-
* Accepts multiple URL candidates because the stored key is the resource's
|
|
272
|
-
* `href` while callers may only know the hash-stripped form; the first match
|
|
273
|
-
* wins.
|
|
175
|
+
* Delegates to {@link getResourceByUrlOp}.
|
|
274
176
|
*
|
|
275
177
|
* Deliberately NOT wrapped with `emitError`/`emitErrorAndRetry`: the only caller (the
|
|
276
178
|
* crawler's resource-reuse hook) has a full fallback (the HEAD pre-flight),
|
|
@@ -283,115 +185,53 @@ export declare class Database extends EventEmitter<DatabaseEvent> {
|
|
|
283
185
|
getResourceByUrl(urls: readonly string[]): Promise<DB_Resource | null>;
|
|
284
186
|
/**
|
|
285
187
|
* Retrieves all sub-resources from the `resources` table.
|
|
188
|
+
* Delegates to {@link getResourcesOp}.
|
|
286
189
|
* @returns An array of raw {@link DB_Resource} rows.
|
|
287
190
|
*/
|
|
288
191
|
getResources(): Promise<DB_Resource[]>;
|
|
289
192
|
/**
|
|
290
193
|
* Retrieves a flat list of all resource URLs from the `resources` table.
|
|
194
|
+
* Delegates to {@link getResourceUrlListOp}.
|
|
291
195
|
* @returns An array of resource URL strings.
|
|
292
196
|
*/
|
|
293
|
-
getResourceUrlList(): Promise<
|
|
197
|
+
getResourceUrlList(): Promise<string[]>;
|
|
294
198
|
/**
|
|
295
199
|
* Counts pages that were scraped as crawl targets (full HTML render).
|
|
296
|
-
*
|
|
297
|
-
* Used by the crawler to seed its `pagesScraped` counter on resume so the
|
|
298
|
-
* progress display reflects all browser-rendered HTML pages across sessions,
|
|
299
|
-
* not just the current one.
|
|
300
|
-
*
|
|
301
|
-
* "HTML page" is guaranteed by `contentType = 'text/html'`, NOT by `isTarget`
|
|
302
|
-
* alone: `isTarget` means "in-scope crawl target" and is set for in-scope
|
|
303
|
-
* non-HTML resources too (e.g. a PDF reached via the HEAD pre-flight is
|
|
304
|
-
* `isTarget = 1`). Counting those would over-report the HTML page total, so
|
|
305
|
-
* page-ness is asserted at the read layer here rather than by trusting
|
|
306
|
-
* `isTarget`.
|
|
200
|
+
* Delegates to {@link getScrapedHtmlPageCountOp}.
|
|
307
201
|
* @returns The number of `text/html` rows with `isTarget = 1` and `scraped = 1`.
|
|
308
202
|
*/
|
|
309
203
|
getScrapedHtmlPageCount(): Promise<number>;
|
|
310
204
|
/**
|
|
311
205
|
* Retrieves all `page_tags` rows for the given page id, parsed back into
|
|
312
|
-
* {@link TagRow} shape
|
|
313
|
-
* deserialised).
|
|
314
|
-
*
|
|
315
|
-
* Read-side counterpart to `#insertTags`.
|
|
206
|
+
* {@link TagRow} shape. Delegates to {@link getTagsOfPageOp}.
|
|
316
207
|
* @param pageId
|
|
317
208
|
*/
|
|
318
209
|
getTagsOfPage(pageId: number): Promise<TagRow[]>;
|
|
319
210
|
/**
|
|
320
211
|
* Records a crawler-level (`error` channel) failure into `crawl_errors`.
|
|
321
|
-
*
|
|
322
|
-
* Unlike {@link insertPageError} this is not tied to a scraped page: `url`
|
|
323
|
-
* may be an external link that never became a page row, or `null` for a
|
|
324
|
-
* process-level error. The cause is intentionally not stored — it is derived
|
|
325
|
-
* on read so that older archives (which only have `error.log`) and freshly
|
|
326
|
-
* captured rows classify identically.
|
|
212
|
+
* Delegates to {@link insertCrawlErrorOp}.
|
|
327
213
|
* @param url - The URL the error is about, or `null` for a process-level error.
|
|
328
214
|
* @param message - The error message (one line is enough for classification).
|
|
329
215
|
* @param isExternal - Whether the URL is external to the crawl scope.
|
|
330
216
|
*/
|
|
331
217
|
insertCrawlError(url: string | null, message: string, isExternal?: boolean): Promise<void>;
|
|
332
218
|
/**
|
|
333
|
-
* Pre-insert inventory non-HTML URLs into `resources` as placeholder rows
|
|
334
|
-
*
|
|
335
|
-
* non-HTML counterpart of {@link Database.insertInventorySeeds}. Used by
|
|
336
|
-
* `CrawlerOrchestrator.inventory` so the ingestion phase commits all of
|
|
337
|
-
* its non-HTML URLs in one chunked round-trip per 500 instead of N
|
|
338
|
-
* sequential `insertResource` awaits. On a 50k-URL inventory list the
|
|
339
|
-
* old per-URL loop spent minutes inside the `.bak`-protected window;
|
|
340
|
-
* the bulk path finishes in seconds.
|
|
341
|
-
*
|
|
342
|
-
* Idempotent: `onConflict('url').ignore()` leaves existing rows untouched
|
|
343
|
-
* (the orchestrator's `getExistingResourceUrls` filter is what keeps a
|
|
344
|
-
* crawled-lineage `resources` row from being downgraded to the
|
|
345
|
-
* inventory label here).
|
|
346
|
-
*
|
|
347
|
-
* Chunked at 500 to stay well under SQLite's `SQLITE_MAX_VARIABLE_NUMBER`
|
|
348
|
-
* (default 999) — every row binds the URL plus the `responseHeaders`
|
|
349
|
-
* JSON null, so the per-chunk bound budget is well within limits.
|
|
219
|
+
* Pre-insert inventory non-HTML URLs into `resources` as placeholder rows.
|
|
220
|
+
* Delegates to {@link insertInventoryResourcesOp}.
|
|
350
221
|
* @param urls - URL strings (already in `withoutHashAndAuth` form).
|
|
351
222
|
*/
|
|
352
223
|
insertInventoryResources(urls: readonly string[]): Promise<void>;
|
|
353
224
|
/**
|
|
354
225
|
* Pre-insert inventory HTML seeds into `pages` as `scraped = 0`,
|
|
355
|
-
* `source = 'inventory-seed'` placeholders
|
|
356
|
-
*
|
|
357
|
-
*
|
|
358
|
-
* Why this is the linchpin of `--inventory` Ctrl+C tolerance: HTML seeds
|
|
359
|
-
* used to live only in the Crawler's in-memory `LinkList` until the
|
|
360
|
-
* dealer eventually called `setPage`. A Ctrl+C / crash before that point
|
|
361
|
-
* lost the seed without trace, and `--resume` could not recover it
|
|
362
|
-
* because `getCrawlingState`'s strict pending set requires a `pages` row.
|
|
363
|
-
* Pre-inserting fills exactly that gap: the strict pending set picks
|
|
364
|
-
* these rows up via its `OR p.source != 'crawled'` clause, so
|
|
365
|
-
* `--resume` after an interrupted inventory pass picks every seed back
|
|
366
|
-
* up. See {@link Database.getCrawlingState} for the strict-set rationale.
|
|
367
|
-
*
|
|
368
|
-
* Idempotent: `onConflict('url').ignore()` keeps existing rows intact.
|
|
369
|
-
* The {@link Database.#getIdByUrl} crawled-wins downgrade still fires
|
|
370
|
-
* later when a crawled-lineage anchor reaches one of these seeds —
|
|
371
|
-
* that's the right behaviour (a seed that turned out to be reachable
|
|
372
|
-
* is not an orphan and should not retain the inventory label).
|
|
373
|
-
*
|
|
374
|
-
* Chunked into 500-URL batches so SQLite's bound-parameter limit
|
|
375
|
-
* (`SQLITE_MAX_VARIABLE_NUMBER`, default 999) cannot be hit even on a
|
|
376
|
-
* tens-of-thousands inventory list.
|
|
377
|
-
*
|
|
378
|
-
* Called by {@link CrawlerOrchestrator.inventory} during the
|
|
379
|
-
* `.bak`-protected ingestion phase, so any failure here aborts the run
|
|
380
|
-
* and restores from backup — the operator reruns from scratch.
|
|
226
|
+
* `source = 'inventory-seed'` placeholders. Delegates to
|
|
227
|
+
* {@link insertInventorySeedsOp} — see the op for the Ctrl+C tolerance
|
|
228
|
+
* rationale.
|
|
381
229
|
* @param urls - URL strings already in `withoutHashAndAuth` form.
|
|
382
230
|
*/
|
|
383
231
|
insertInventorySeeds(urls: readonly string[]): Promise<void>;
|
|
384
232
|
/**
|
|
385
233
|
* Records a partial scrape failure against the page identified by `url`.
|
|
386
|
-
*
|
|
387
|
-
* The page row is resolved (or inserted as a stub) via
|
|
388
|
-
* {@link Database.#getIdByUrl} so the error can be recorded even before
|
|
389
|
-
* `setPage` has run — useful when the failure fires during scraping
|
|
390
|
-
* (e.g. mid-`scrapeStart`) and the orchestrator enqueues this write
|
|
391
|
-
* before the success write for the same URL.
|
|
392
|
-
*
|
|
393
|
-
* A single page can have multiple `page_errors` rows (e.g. both
|
|
394
|
-
* `desktop-compact` and `mobile-small` viewports failing).
|
|
234
|
+
* Delegates to {@link insertPageErrorOp}.
|
|
395
235
|
* @param url - URL of the page being scraped.
|
|
396
236
|
* @param phase - Scrape phase name (typically `'retryExhausted'`).
|
|
397
237
|
* @param message - Human-readable failure message.
|
|
@@ -400,162 +240,83 @@ export declare class Database extends EventEmitter<DatabaseEvent> {
|
|
|
400
240
|
insertPageError(url: string, phase: string, message: string, isExternal?: boolean): Promise<void>;
|
|
401
241
|
/**
|
|
402
242
|
* Inserts a sub-resource into the `resources` table.
|
|
403
|
-
*
|
|
404
|
-
*
|
|
405
|
-
* The `source` provenance label is written ONLY on insert; an
|
|
406
|
-
* `ON CONFLICT IGNORE` collision leaves an existing row's source untouched
|
|
407
|
-
* (this is what makes a second `crawl --inventory` non-destructive — see
|
|
408
|
-
* the inventory plan).
|
|
243
|
+
* Delegates to {@link insertResourceOp}.
|
|
409
244
|
* @param resource - The resource data to insert.
|
|
410
245
|
* @param source - Provenance label for new rows. `undefined` leaves the DB DEFAULT (`'crawled'`).
|
|
411
246
|
*/
|
|
412
247
|
insertResource(resource: Resource, source?: PageSource): Promise<void>;
|
|
413
248
|
/**
|
|
414
249
|
* Inserts a referrer relationship between a resource and a page into the
|
|
415
|
-
* `resources-referrers` table.
|
|
250
|
+
* `resources-referrers` table. Delegates to {@link insertResourceReferrersOp}.
|
|
416
251
|
* @param src - The URL of the resource.
|
|
417
252
|
* @param pageUrl - The URL of the page that references the resource.
|
|
418
253
|
*/
|
|
419
254
|
insertResourceReferrers(src: string, pageUrl: string): Promise<void>;
|
|
420
255
|
/**
|
|
421
256
|
* Hostnames whose `crawl_errors` history is consistently DNS failures and
|
|
422
|
-
* for which no recent 2xx-3xx page or resource is recorded
|
|
423
|
-
*
|
|
424
|
-
* form. Used by `CrawlerOrchestrator.#preloadDnsBurnedHostCache` so the
|
|
425
|
-
* next session short-circuits HEAD pre-flight on these hosts.
|
|
426
|
-
*
|
|
427
|
-
* Implementation: a coarse `LIKE` filter over `crawl_errors.message`
|
|
428
|
-
* narrows the row set, then `classifyErrorKind` confirms `'dns'` in JS
|
|
429
|
-
* (the regex is the single truth source — DB-side filters never narrow
|
|
430
|
-
* it). Exclusion bags are built from a single `pages` and a single
|
|
431
|
-
* `resources` scan: any host with a 2xx-3xx page, a 2xx-3xx resource, or
|
|
432
|
-
* a `pages.lastCrawledAt` newer than its latest DNS error is dropped
|
|
433
|
-
* (the host probably recovered between the failure and the last crawl).
|
|
434
|
-
*
|
|
435
|
-
* Returns `[]` on legacy archives that pre-date the `crawl_errors`
|
|
436
|
-
* table — the `hasTable` guard keeps the call non-destructive.
|
|
257
|
+
* for which no recent 2xx-3xx page or resource is recorded.
|
|
258
|
+
* Delegates to {@link listDnsBurnedHostCandidatesOp}.
|
|
437
259
|
* @returns Lower-cased hostnames safe to short-circuit.
|
|
438
260
|
*/
|
|
439
261
|
listDnsBurnedHostCandidates(): Promise<string[]>;
|
|
440
262
|
/**
|
|
441
263
|
* Appends one row to the `inventory_runs` audit log.
|
|
442
|
-
*
|
|
443
|
-
* Called by {@link CrawlerOrchestrator.inventory} on every successful
|
|
444
|
-
* `--inventory <list>` invocation so the archive carries a durable
|
|
445
|
-
* record of which deploy list was applied when and at what scale —
|
|
446
|
-
* the operational question "did we apply last month's list" the
|
|
447
|
-
* archive itself can answer without consulting external bookkeeping.
|
|
448
|
-
*
|
|
449
|
-
* Append-only at Phase 1. There is intentionally no UPDATE path and
|
|
450
|
-
* no UNIQUE constraint on `source_file_sha256`; two applies of the
|
|
451
|
-
* same list each get their own row, and `Phase 3 --refresh` is where
|
|
452
|
-
* dedupe / pre-flight against the hash will land. Field-level NULL
|
|
453
|
-
* semantics live on {@link InventoryRunMeta}.
|
|
264
|
+
* Delegates to {@link recordInventoryRunOp}.
|
|
454
265
|
* @param meta - The run metadata to record. Only `ran_at` is required.
|
|
455
266
|
* @returns The autoincremented `id` of the newly-inserted row.
|
|
456
267
|
*/
|
|
457
268
|
recordInventoryRun(meta: InventoryRunMeta): Promise<number>;
|
|
458
269
|
/**
|
|
459
270
|
* Records a redirect edge (source → destination) **without** re-storing the
|
|
460
|
-
* destination's content.
|
|
461
|
-
*
|
|
462
|
-
* The crawler renders a many-to-one redirect destination exactly once. For
|
|
463
|
-
* every subsequent source URL that redirects to that already-rendered
|
|
464
|
-
* destination, it calls this instead of {@link updatePage} (#73). Routing a
|
|
465
|
-
* content-less HEAD result through `updatePage` would funnel it into
|
|
466
|
-
* `#insertPage` and overwrite the destination's good title / meta with empty
|
|
467
|
-
* values, so the dedicated edge-only path is required.
|
|
468
|
-
*
|
|
469
|
-
* The destination row is resolved (created on demand if a concurrent in-flight
|
|
470
|
-
* render has not committed it yet) so the edge always points at a valid id;
|
|
471
|
-
* the single render fills in the destination's content under that same id.
|
|
472
|
-
* The destination's existing anchors / images are never touched here.
|
|
271
|
+
* destination's content. Delegates to {@link recordRedirectOp}.
|
|
473
272
|
* @param page - HEAD-resolved page data carrying the redirect chain. Its
|
|
474
273
|
* `anchorList` / `imageList` are ignored (a redirect source owns no content).
|
|
475
|
-
* @param source - Inventory provenance forwarded by the orchestrator
|
|
476
|
-
*
|
|
477
|
-
*
|
|
478
|
-
* the archive (`#73` convergence on first sight, js-redirect rescue
|
|
479
|
-
* before any prior write). When the originating row already exists
|
|
480
|
-
* (e.g. anchor-lineage INSERT from a prior pass), its stored `source`
|
|
481
|
-
* takes precedence so transitive lineage is preserved across resume /
|
|
482
|
-
* retry-failed sessions. `undefined` keeps the DB DEFAULT `'crawled'`
|
|
483
|
-
* on a brand-new destination row.
|
|
274
|
+
* @param source - Inventory provenance forwarded by the orchestrator for
|
|
275
|
+
* the redirect-edge fast path. `undefined` keeps the DB DEFAULT
|
|
276
|
+
* `'crawled'` on a brand-new destination row.
|
|
484
277
|
*/
|
|
485
278
|
recordRedirect(page: PageData, source?: PageSource): Promise<void>;
|
|
486
279
|
/**
|
|
487
|
-
*
|
|
488
|
-
*
|
|
489
|
-
*
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
280
|
+
* Replaces the stored analysis violations with a freshly generated set.
|
|
281
|
+
* Delegates to {@link replaceAnalysisViolationsOp}.
|
|
282
|
+
* @param violations - Flat violation list from the analyze phase.
|
|
283
|
+
*/
|
|
284
|
+
replaceAnalysisViolations(violations: readonly {
|
|
285
|
+
validator: string;
|
|
286
|
+
severity: string;
|
|
287
|
+
rule: string;
|
|
288
|
+
code?: string | null;
|
|
289
|
+
message: string;
|
|
290
|
+
url: string;
|
|
291
|
+
line?: number | null;
|
|
292
|
+
col?: number | null;
|
|
293
|
+
}[]): Promise<void>;
|
|
294
|
+
/**
|
|
295
|
+
* Promote previously-external pages whose URL falls under any of the new
|
|
296
|
+
* scope entries back to a "needs scraping" state.
|
|
297
|
+
* Delegates to {@link repromoteExternalPagesOp}.
|
|
500
298
|
* @param scopes - The hostname-indexed scope map after the new roots are merged.
|
|
501
|
-
* @param options - URL parsing options forwarded to
|
|
299
|
+
* @param options - URL parsing options forwarded to the scope matcher.
|
|
502
300
|
* @returns The URLs of the pages that were promoted.
|
|
503
301
|
*/
|
|
504
302
|
repromoteExternalPages(scopes: ReadonlyMap<string, readonly ExURL[]>, options?: ParseURLOptions): Promise<string[]>;
|
|
505
303
|
/**
|
|
506
304
|
* Reset previously-attempted pages that ended in a recoverable failure so a
|
|
507
|
-
* follow-up crawl can re-fetch them from scratch.
|
|
508
|
-
*
|
|
509
|
-
*
|
|
510
|
-
* (`scraped = 1`), is not a redirect source (`redirectDestId IS NULL`), was
|
|
511
|
-
* not intentionally skipped (`isSkipped` is not `1`), and one of the
|
|
512
|
-
* following holds:
|
|
513
|
-
*
|
|
514
|
-
* - `status = -1` — the sentinel a hard scrape failure (network error,
|
|
515
|
-
* timeout, browser crash) is recorded with (see `handle-scrape-error.ts`);
|
|
516
|
-
* - `status IS NULL` — no status was ever stored for the row;
|
|
517
|
-
* - `contentType IS NULL` — the content type could not be determined;
|
|
518
|
-
* - `status` is in the `5xx` range — a (frequently transient) server error.
|
|
519
|
-
*
|
|
520
|
-
* Definitive `4xx` responses are intentionally excluded: re-fetching a 404
|
|
521
|
-
* almost always yields the same answer.
|
|
522
|
-
*
|
|
523
|
-
* A second exclusion runs in JS after the SQL candidate scan: any page whose
|
|
524
|
-
* latest recorded `page_errors` / `crawl_errors` message classifies into a
|
|
525
|
-
* permanent {@link PERMANENT_ERROR_KINDS} kind (dns / tls / client-blocked /
|
|
526
|
-
* parse-error / connection-refused) is left as-is rather than reset to
|
|
527
|
-
* pending. Without this filter, `--retry-failed` never converges: NXDOMAIN
|
|
528
|
-
* hosts, expired-cert hosts, and `ERR_BLOCKED_BY_CLIENT` ad pixels would be
|
|
529
|
-
* reset every iteration, re-attempted, fail identically, and rejoin the
|
|
530
|
-
* candidate pool for the next iteration. The exclusion keeps the retry
|
|
531
|
-
* target shrinking across `--retry-failed` passes by leaving deterministic
|
|
532
|
-
* dead-ends alone.
|
|
533
|
-
*
|
|
534
|
-
* Matching rows — internal and external alike — are demoted back to pending
|
|
535
|
-
* (`scraped = 0`) and have their stale scrape metadata cleared. The page row
|
|
536
|
-
* itself is kept (id preserved) so existing `anchors.hrefId` referrers stay
|
|
537
|
-
* valid, and `isExternal` is left untouched so the next pass re-classifies
|
|
538
|
-
* each page from the crawl scope. Related `anchors`, `images`,
|
|
539
|
-
* `resources-referrers`, and `page_errors` rows are deleted so the re-scrape
|
|
540
|
-
* can re-insert fresh data without duplicates.
|
|
541
|
-
*
|
|
542
|
-
* SELECT and UPDATE/DELETE statements are chunked to stay below SQLite's
|
|
543
|
-
* `SQLITE_LIMIT_VARIABLE_NUMBER`.
|
|
305
|
+
* follow-up crawl can re-fetch them from scratch. Delegates to
|
|
306
|
+
* {@link resetFailedPagesOp} — see the op for the permanent-failure
|
|
307
|
+
* exclusion rationale.
|
|
544
308
|
* @returns The URLs of the pages that were reset to pending.
|
|
545
309
|
*/
|
|
546
310
|
resetFailedPages(): Promise<string[]>;
|
|
547
311
|
/**
|
|
548
312
|
* Stores the crawl configuration in the `info` table.
|
|
549
|
-
*
|
|
550
|
-
* runtime-only field on the input is silently dropped so callers can splat
|
|
551
|
-
* a wider config object without producing SQL errors. JSON-array fields
|
|
552
|
-
* are serialized via `JSON.stringify`.
|
|
313
|
+
* Delegates to {@link setConfigOp}.
|
|
553
314
|
* @param config - The {@link Config} object to store.
|
|
554
315
|
*/
|
|
555
316
|
setConfig(config: Config): Promise<number[]>;
|
|
556
317
|
/**
|
|
557
318
|
* Marks a page as skipped in the database with the given reason.
|
|
558
|
-
*
|
|
319
|
+
* Delegates to {@link setSkippedPageOp}.
|
|
559
320
|
* @param url - The URL of the skipped page.
|
|
560
321
|
* @param reason - The reason the page was skipped.
|
|
561
322
|
* @param isExternal - Whether the page is on an external domain. Defaults to `false`.
|
|
@@ -563,31 +324,19 @@ export declare class Database extends EventEmitter<DatabaseEvent> {
|
|
|
563
324
|
setSkippedPage(url: string, reason: string, isExternal?: boolean): Promise<void>;
|
|
564
325
|
/**
|
|
565
326
|
* Assigns natural URL sort order values to all internal pages.
|
|
566
|
-
*
|
|
327
|
+
* Delegates to {@link setUrlOrderOp}.
|
|
567
328
|
*/
|
|
568
329
|
setUrlOrder(): Promise<void>;
|
|
569
330
|
/**
|
|
570
331
|
* Update the single row in the `info` table with a partial config patch.
|
|
571
|
-
*
|
|
572
|
-
* Used by the append flow to extend `roots` (and any other tweakable
|
|
573
|
-
* field) without replacing the entire row. JSON-array fields are serialized on
|
|
574
|
-
* the fly; primitive fields are written verbatim. Unspecified fields stay as-is.
|
|
575
|
-
*
|
|
576
|
-
* Unknown keys (anything outside the allow-list of `info`-table columns) are
|
|
577
|
-
* silently dropped instead of being passed to SQL, so callers that splat a
|
|
578
|
-
* wider runtime config (e.g. `CrawlConfig` with `cwd` / `executablePath`)
|
|
579
|
-
* cannot accidentally trigger a "no such column" SQL error.
|
|
332
|
+
* Delegates to {@link updateConfigOp}.
|
|
580
333
|
* @param patch - Partial {@link Config} fields to overwrite. `undefined` values are skipped.
|
|
581
334
|
*/
|
|
582
335
|
updateConfig(patch: Partial<Config>): Promise<void>;
|
|
583
336
|
/**
|
|
584
|
-
* Inserts or updates a crawled page in the database, including its redirect
|
|
585
|
-
* anchors, images, and (when `writeHtml`) its compressed HTML
|
|
586
|
-
*
|
|
587
|
-
* Self-redirects (where the source URL equals the destination URL after normalization)
|
|
588
|
-
* are skipped to avoid marking a page as redirected to itself — a situation caused by
|
|
589
|
-
* authentication challenges (e.g. Basic Auth 302) that would otherwise exclude the page
|
|
590
|
-
* from reports via the `whereNull('redirectDestId')` filter.
|
|
337
|
+
* Inserts or updates a crawled page in the database, including its redirect
|
|
338
|
+
* chain, anchors, images, and (when `writeHtml`) its compressed HTML
|
|
339
|
+
* snapshot BLOB. Delegates to {@link updatePageOp}.
|
|
591
340
|
* @param page - The page data to store.
|
|
592
341
|
* @param writeHtml - When `true`, this call is allowed to insert (or clear)
|
|
593
342
|
* the page's HTML blob. `setExternalPage` passes `false` because external
|
|
@@ -595,9 +344,7 @@ export declare class Database extends EventEmitter<DatabaseEvent> {
|
|
|
595
344
|
* stored body.
|
|
596
345
|
* @param isTarget - Whether this page is a crawl target.
|
|
597
346
|
* @param source - Provenance label written ONLY when the row is freshly
|
|
598
|
-
* inserted. Existing rows keep their original `source
|
|
599
|
-
* second `crawl --inventory` does not "demote" an `'inventory-seed'` row
|
|
600
|
-
* that was discovered earlier).
|
|
347
|
+
* inserted. Existing rows keep their original `source`.
|
|
601
348
|
* @returns The database `pageId` of the inserted/updated row.
|
|
602
349
|
*/
|
|
603
350
|
updatePage(page: PageData, writeHtml: boolean, isTarget: boolean, source?: PageSource): Promise<number>;
|