@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.
- 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 +175 -13
- package/lib/archive/archive.js +198 -14
- package/lib/archive/cache/compute-archive-cache-key.d.ts +39 -0
- package/lib/archive/cache/compute-archive-cache-key.js +95 -0
- package/lib/archive/cache/extract-archive-to-cache.d.ts +43 -0
- package/lib/archive/cache/extract-archive-to-cache.js +309 -0
- package/lib/archive/cache/get-archive-cache-root.d.ts +20 -0
- package/lib/archive/cache/get-archive-cache-root.js +53 -0
- package/lib/archive/cache/is-archive-cache-disabled.d.ts +24 -0
- package/lib/archive/cache/is-archive-cache-disabled.js +34 -0
- package/lib/archive/cache/resolve-archive-cache-dir.d.ts +26 -0
- package/lib/archive/cache/resolve-archive-cache-dir.js +32 -0
- 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 +130 -182
- package/lib/archive/database.js +524 -1777
- 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 +37 -0
- package/lib/archive/derive-lineage-from-parent.js +42 -0
- 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 +44 -0
- package/lib/archive/get-failed-page-messages.js +132 -0
- package/lib/archive/init-schema.d.ts +35 -39
- package/lib/archive/init-schema.js +111 -320
- package/lib/archive/is-inventory-source.d.ts +21 -0
- package/lib/archive/is-inventory-source.js +22 -0
- 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 +151 -15
- 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/classify-error-kind.d.ts +19 -0
- package/lib/classify-error-kind.js +122 -0
- package/lib/crawler/build-js-redirect-edge.d.ts +68 -0
- package/lib/crawler/build-js-redirect-edge.js +57 -0
- package/lib/crawler/build-redirect-event.d.ts +24 -0
- package/lib/crawler/build-redirect-event.js +28 -0
- 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 +6 -0
- package/lib/crawler/clear-dns-burned-host-cache.js +11 -0
- 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 +22 -1
- package/lib/crawler/crawler.js +679 -117
- package/lib/crawler/derive-js-redirect-target.d.ts +68 -0
- package/lib/crawler/derive-js-redirect-target.js +129 -0
- package/lib/crawler/derive-resource-source.d.ts +25 -15
- package/lib/crawler/derive-resource-source.js +28 -17
- package/lib/crawler/dns-burned-host-cache.d.ts +26 -0
- package/lib/crawler/dns-burned-host-cache.js +25 -0
- package/lib/crawler/dns-burned-host-short-circuit-counter.d.ts +13 -0
- package/lib/crawler/dns-burned-host-short-circuit-counter.js +11 -0
- package/lib/crawler/fetch-destination.d.ts +12 -4
- package/lib/crawler/fetch-destination.js +94 -16
- package/lib/crawler/inject-scope-auth.d.ts +1 -1
- package/lib/crawler/inject-scope-auth.js +1 -1
- package/lib/crawler/is-js-redirect-error-shape.d.ts +40 -0
- package/lib/crawler/is-js-redirect-error-shape.js +53 -0
- package/lib/crawler/is-puppeteer-fallback-candidate.d.ts +16 -0
- package/lib/crawler/is-puppeteer-fallback-candidate.js +63 -0
- package/lib/crawler/link-list.d.ts +21 -1
- package/lib/crawler/link-list.js +23 -3
- package/lib/crawler/normalize-content-type.d.ts +1 -1
- package/lib/crawler/normalize-content-type.js +1 -1
- package/lib/crawler/plan-sub-resource-emits.d.ts +63 -0
- package/lib/crawler/plan-sub-resource-emits.js +44 -0
- package/lib/crawler/preload-short-circuit-error.d.ts +22 -0
- package/lib/crawler/preload-short-circuit-error.js +25 -0
- package/lib/crawler/should-burn-host.d.ts +78 -0
- package/lib/crawler/should-burn-host.js +61 -0
- package/lib/crawler/should-get-fallback-on-head-failure.d.ts +38 -0
- package/lib/crawler/should-get-fallback-on-head-failure.js +46 -0
- package/lib/crawler/types.d.ts +108 -1
- package/lib/crawler-orchestrator.d.ts +22 -3
- package/lib/crawler-orchestrator.js +312 -73
- package/lib/crawler.d.ts +15 -2
- package/lib/crawler.js +24 -1
- package/lib/permanent-error-kinds.d.ts +43 -0
- package/lib/permanent-error-kinds.js +48 -0
- package/lib/types.d.ts +84 -0
- package/lib/utils/compute-file-sha256.d.ts +24 -0
- package/lib/utils/compute-file-sha256.js +56 -0
- package/lib/utils/error/emit-error-with-retry.d.ts +40 -0
- package/lib/utils/error/emit-error-with-retry.js +44 -0
- package/lib/utils/error/emit-error.d.ts +39 -0
- package/lib/utils/error/emit-error.js +41 -0
- package/package.json +12 -12
- 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-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
- package/lib/utils/error/error-emitter.d.ts +0 -18
- package/lib/utils/error/error-emitter.js +0 -29
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provisions the pre-0.13 legacy table shape on a test database:
|
|
3
|
+
* the five legacy write-model tables (`pages` / `anchors` / `images` /
|
|
4
|
+
* `resources` / `resources-referrers`) plus the five adjunct tables in
|
|
5
|
+
* their old form whose FK columns still point at `pages(id)`
|
|
6
|
+
* (`page_html_ref` / `page_tags` / `page_jsonld` / `page_errors` /
|
|
7
|
+
* `analysis_violations`, with their companion tables `page_html_blobs` /
|
|
8
|
+
* `analysis_text_refs`).
|
|
9
|
+
*
|
|
10
|
+
* `initSchema` no longer creates any of these shapes — fresh archives get
|
|
11
|
+
* neither the legacy write-model tables nor `pages(id)`-referencing
|
|
12
|
+
* adjunct tables — so specs that exercise the migration input format
|
|
13
|
+
* (`scripts/migrate-to-0.13.mjs` integration, `retargetLegacyFkTables`,
|
|
14
|
+
* `dropLegacyTables`) build it through this helper instead. The DDL is a
|
|
15
|
+
* verbatim copy of what pre-0.13 archives actually contain: the legacy
|
|
16
|
+
* write-model tables match the pre-0.13 `initSchema`, and the adjunct
|
|
17
|
+
* tables match the `scripts/migrate-to-0.10.mjs` / lazy-runtime-migration
|
|
18
|
+
* output of that era.
|
|
19
|
+
*
|
|
20
|
+
* Any current-form adjunct tables already present (e.g. created by
|
|
21
|
+
* `Archive.create()` on the current schema) are dropped first so the
|
|
22
|
+
* old-FK versions can take their place — callers get a deterministic
|
|
23
|
+
* "genuine pre-0.13 archive" shape regardless of how the underlying DB
|
|
24
|
+
* was provisioned.
|
|
25
|
+
* @param db - Knex connected to the test DB (or a transaction).
|
|
26
|
+
* @example
|
|
27
|
+
* await createRefTables(db);
|
|
28
|
+
* await createEntityTables(db);
|
|
29
|
+
* await setupLegacyFkDb(db);
|
|
30
|
+
* await db('pages').insert({ url: 'https://example.com/', scraped: 1, isTarget: 1 });
|
|
31
|
+
*/
|
|
32
|
+
export async function setupLegacyFkDb(db) {
|
|
33
|
+
// Children before parents so the drops never trip FK enforcement
|
|
34
|
+
// when the caller has `PRAGMA foreign_keys = ON`.
|
|
35
|
+
await db.raw('DROP TABLE IF EXISTS "page_html_ref"');
|
|
36
|
+
await db.raw('DROP TABLE IF EXISTS "page_html_blobs"');
|
|
37
|
+
await db.raw('DROP TABLE IF EXISTS "analysis_violations"');
|
|
38
|
+
await db.raw('DROP TABLE IF EXISTS "analysis_text_refs"');
|
|
39
|
+
await db.raw('DROP TABLE IF EXISTS "page_tags"');
|
|
40
|
+
await db.raw('DROP TABLE IF EXISTS "page_jsonld"');
|
|
41
|
+
await db.raw('DROP TABLE IF EXISTS "page_errors"');
|
|
42
|
+
await db.schema
|
|
43
|
+
.createTable('pages', (t) => {
|
|
44
|
+
t.increments('id');
|
|
45
|
+
t.string('url', 8190).notNullable().unique();
|
|
46
|
+
t.integer('redirectDestId').unsigned().references('pages.id').defaultTo(null);
|
|
47
|
+
t.boolean('scraped').notNullable();
|
|
48
|
+
t.boolean('isTarget').notNullable();
|
|
49
|
+
t.boolean('isExternal');
|
|
50
|
+
t.integer('status');
|
|
51
|
+
t.string('statusText');
|
|
52
|
+
t.string('contentType').nullable();
|
|
53
|
+
t.integer('contentLength').unsigned().nullable();
|
|
54
|
+
t.json('responseHeaders').nullable();
|
|
55
|
+
// Document basics
|
|
56
|
+
t.string('lang');
|
|
57
|
+
t.string('dir');
|
|
58
|
+
t.string('charset');
|
|
59
|
+
t.string('baseHref');
|
|
60
|
+
t.text('viewport_raw');
|
|
61
|
+
t.string('themeColor');
|
|
62
|
+
t.string('applicationName');
|
|
63
|
+
t.string('author');
|
|
64
|
+
t.string('generator');
|
|
65
|
+
t.string('publisher');
|
|
66
|
+
// Title / description / keywords (top-level Meta fields)
|
|
67
|
+
t.string('title');
|
|
68
|
+
t.text('description');
|
|
69
|
+
t.text('keywords');
|
|
70
|
+
// Robots
|
|
71
|
+
t.text('robots_raw');
|
|
72
|
+
t.integer('robots_noindex');
|
|
73
|
+
t.integer('robots_nofollow');
|
|
74
|
+
t.integer('robots_noarchive');
|
|
75
|
+
t.integer('robots_noimageindex');
|
|
76
|
+
t.string('googlebot');
|
|
77
|
+
// Link (1:1 only — array shapes live in meta_extras)
|
|
78
|
+
t.string('canonical', 8190);
|
|
79
|
+
t.string('amphtml', 8190);
|
|
80
|
+
t.string('manifest', 8190);
|
|
81
|
+
t.string('icon_href', 8190);
|
|
82
|
+
t.string('appleTouchIcon_href', 8190);
|
|
83
|
+
// Open Graph
|
|
84
|
+
t.string('og_type');
|
|
85
|
+
t.string('og_title');
|
|
86
|
+
t.string('og_url', 8190);
|
|
87
|
+
t.string('og_site_name');
|
|
88
|
+
t.text('og_description');
|
|
89
|
+
t.string('og_image', 8190);
|
|
90
|
+
t.string('og_image_alt');
|
|
91
|
+
t.string('og_image_width');
|
|
92
|
+
t.string('og_image_height');
|
|
93
|
+
t.string('og_locale');
|
|
94
|
+
t.string('og_article_published_time');
|
|
95
|
+
t.string('og_article_modified_time');
|
|
96
|
+
// Twitter
|
|
97
|
+
t.string('twitter_card');
|
|
98
|
+
t.string('twitter_site');
|
|
99
|
+
t.string('twitter_creator');
|
|
100
|
+
t.string('twitter_title');
|
|
101
|
+
t.text('twitter_description');
|
|
102
|
+
t.string('twitter_image', 8190);
|
|
103
|
+
// One-offs
|
|
104
|
+
t.string('fb_app_id');
|
|
105
|
+
t.string('verification_google');
|
|
106
|
+
t.integer('formatDetection_telephone');
|
|
107
|
+
// Within-archive observation timestamps (UNIX ms)
|
|
108
|
+
t.integer('firstCrawledAt');
|
|
109
|
+
t.integer('lastCrawledAt');
|
|
110
|
+
// Denormalised aggregates
|
|
111
|
+
t.integer('tag_count');
|
|
112
|
+
t.integer('jsonld_count');
|
|
113
|
+
t.text('tags_providers_csv');
|
|
114
|
+
// Catch-all JSON for nested Meta sub-objects not flattened above
|
|
115
|
+
t.json('meta_extras');
|
|
116
|
+
// Crawl lifecycle
|
|
117
|
+
t.boolean('isSkipped');
|
|
118
|
+
t.string('skipReason');
|
|
119
|
+
t.integer('order').unsigned().nullable();
|
|
120
|
+
t.string('source').notNullable().defaultTo('crawled');
|
|
121
|
+
t.index('isExternal');
|
|
122
|
+
t.index('contentType');
|
|
123
|
+
t.index('scraped');
|
|
124
|
+
t.index('redirectDestId');
|
|
125
|
+
t.index('order');
|
|
126
|
+
t.index('robots_noindex');
|
|
127
|
+
t.index('og_type');
|
|
128
|
+
t.index('source');
|
|
129
|
+
})
|
|
130
|
+
.createTable('anchors', (t) => {
|
|
131
|
+
t.increments('id');
|
|
132
|
+
t.integer('pageId').notNullable().unsigned().references('pages.id');
|
|
133
|
+
t.integer('hrefId').notNullable().unsigned().references('pages.id');
|
|
134
|
+
t.string('hash');
|
|
135
|
+
t.string('textContent').nullable();
|
|
136
|
+
t.index('pageId');
|
|
137
|
+
t.index('hrefId');
|
|
138
|
+
})
|
|
139
|
+
.createTable('images', (t) => {
|
|
140
|
+
t.increments('id');
|
|
141
|
+
t.integer('pageId').notNullable().unsigned().references('pages.id');
|
|
142
|
+
t.string('src', 8190);
|
|
143
|
+
t.string('currentSrc', 8190);
|
|
144
|
+
t.string('alt');
|
|
145
|
+
t.float('width').unsigned().notNullable();
|
|
146
|
+
t.float('height').unsigned().notNullable();
|
|
147
|
+
t.integer('naturalWidth').unsigned().notNullable();
|
|
148
|
+
t.integer('naturalHeight').unsigned().notNullable();
|
|
149
|
+
t.boolean('isLazy');
|
|
150
|
+
t.integer('viewportWidth').unsigned().notNullable();
|
|
151
|
+
t.string('sourceCode');
|
|
152
|
+
t.index('pageId');
|
|
153
|
+
})
|
|
154
|
+
.createTable('resources', (t) => {
|
|
155
|
+
t.increments('id');
|
|
156
|
+
t.string('url', 8190).notNullable().unique();
|
|
157
|
+
t.boolean('isExternal');
|
|
158
|
+
t.integer('status');
|
|
159
|
+
t.string('statusText');
|
|
160
|
+
t.string('contentType').nullable();
|
|
161
|
+
t.integer('contentLength').unsigned().nullable();
|
|
162
|
+
t.string('compress').nullable();
|
|
163
|
+
t.string('cdn').nullable();
|
|
164
|
+
t.json('responseHeaders').nullable();
|
|
165
|
+
t.string('source').notNullable().defaultTo('crawled');
|
|
166
|
+
t.index('source');
|
|
167
|
+
})
|
|
168
|
+
.createTable('resources-referrers', (t) => {
|
|
169
|
+
t.increments('id');
|
|
170
|
+
t.integer('resourceId').notNullable().unsigned().references('resources.id');
|
|
171
|
+
t.integer('pageId').notNullable().unsigned().references('pages.id');
|
|
172
|
+
t.unique(['resourceId', 'pageId']);
|
|
173
|
+
t.index('resourceId');
|
|
174
|
+
t.index('pageId');
|
|
175
|
+
});
|
|
176
|
+
// Adjunct tables in their pre-0.13 shape: FK columns point at
|
|
177
|
+
// `pages(id)` — the exact declarations that
|
|
178
|
+
// `scripts/migrate-to-0.10.mjs` and the runtime lazy migrations of
|
|
179
|
+
// that era produced.
|
|
180
|
+
await db.schema.createTable('page_errors', (t) => {
|
|
181
|
+
t.increments('id');
|
|
182
|
+
t.integer('pageId').notNullable().unsigned().references('pages.id');
|
|
183
|
+
t.string('phase').notNullable();
|
|
184
|
+
t.text('message').notNullable();
|
|
185
|
+
t.integer('createdAt').notNullable();
|
|
186
|
+
t.index('pageId');
|
|
187
|
+
});
|
|
188
|
+
await db.schema.createTable('page_tags', (t) => {
|
|
189
|
+
t.increments('id');
|
|
190
|
+
t.integer('pageId')
|
|
191
|
+
.notNullable()
|
|
192
|
+
.unsigned()
|
|
193
|
+
.references('pages.id')
|
|
194
|
+
.onDelete('CASCADE');
|
|
195
|
+
t.string('provider').notNullable();
|
|
196
|
+
t.string('category');
|
|
197
|
+
t.string('externalId');
|
|
198
|
+
t.string('version');
|
|
199
|
+
t.integer('confidence');
|
|
200
|
+
t.json('categories');
|
|
201
|
+
t.json('sources');
|
|
202
|
+
t.index('pageId');
|
|
203
|
+
t.index('provider');
|
|
204
|
+
t.index('externalId');
|
|
205
|
+
});
|
|
206
|
+
await db.raw('CREATE INDEX page_tags_provider_extId ON page_tags(provider, externalId)');
|
|
207
|
+
await db.raw('CREATE INDEX page_tags_provider_pageId ON page_tags(provider, pageId)');
|
|
208
|
+
await db.schema.createTable('page_jsonld', (t) => {
|
|
209
|
+
t.increments('id');
|
|
210
|
+
t.integer('pageId')
|
|
211
|
+
.notNullable()
|
|
212
|
+
.unsigned()
|
|
213
|
+
.references('pages.id')
|
|
214
|
+
.onDelete('CASCADE');
|
|
215
|
+
t.string('kind').notNullable();
|
|
216
|
+
t.string('type');
|
|
217
|
+
t.text('raw').notNullable();
|
|
218
|
+
t.json('parsed');
|
|
219
|
+
t.text('parseError');
|
|
220
|
+
t.index('pageId');
|
|
221
|
+
t.index('type');
|
|
222
|
+
});
|
|
223
|
+
await db.raw('CREATE INDEX page_jsonld_type_pageId ON page_jsonld(type, pageId)');
|
|
224
|
+
await db.raw(`
|
|
225
|
+
CREATE TABLE analysis_text_refs (
|
|
226
|
+
id integer primary key,
|
|
227
|
+
text text not null,
|
|
228
|
+
sha256 text not null,
|
|
229
|
+
unique(sha256, text)
|
|
230
|
+
)
|
|
231
|
+
`);
|
|
232
|
+
await db.raw(`
|
|
233
|
+
CREATE TABLE analysis_violations (
|
|
234
|
+
id integer primary key,
|
|
235
|
+
page_id integer not null references pages(id),
|
|
236
|
+
validator text not null,
|
|
237
|
+
severity text not null,
|
|
238
|
+
rule text not null,
|
|
239
|
+
message_text_id integer not null references analysis_text_refs(id),
|
|
240
|
+
code_text_id integer references analysis_text_refs(id),
|
|
241
|
+
page_url_sort_key text not null,
|
|
242
|
+
message_sort_key text not null,
|
|
243
|
+
code_sort_key text not null
|
|
244
|
+
)
|
|
245
|
+
`);
|
|
246
|
+
await db.raw('CREATE INDEX av_url_order ON analysis_violations(page_url_sort_key, id)');
|
|
247
|
+
await db.raw('CREATE INDEX av_filter_url ON analysis_violations(validator, severity, rule, page_url_sort_key, id)');
|
|
248
|
+
await db.raw('CREATE INDEX av_validator_url ON analysis_violations(validator, page_url_sort_key, id)');
|
|
249
|
+
await db.raw('CREATE INDEX av_severity_url ON analysis_violations(severity, page_url_sort_key, id)');
|
|
250
|
+
await db.raw('CREATE INDEX av_rule_url ON analysis_violations(rule, page_url_sort_key, id)');
|
|
251
|
+
await db.raw('CREATE INDEX av_message_order ON analysis_violations(message_sort_key, id)');
|
|
252
|
+
await db.raw('CREATE INDEX av_code_order ON analysis_violations(code_sort_key, id)');
|
|
253
|
+
await db.raw('CREATE INDEX av_page ON analysis_violations(page_id, id)');
|
|
254
|
+
await db.raw(`
|
|
255
|
+
CREATE TABLE page_html_blobs (
|
|
256
|
+
hash BLOB PRIMARY KEY,
|
|
257
|
+
body BLOB NOT NULL,
|
|
258
|
+
codec TEXT NOT NULL CHECK(codec IN ('zstd', 'none')),
|
|
259
|
+
size_raw INTEGER NOT NULL,
|
|
260
|
+
size_stored INTEGER NOT NULL
|
|
261
|
+
) WITHOUT ROWID
|
|
262
|
+
`);
|
|
263
|
+
await db.raw(`
|
|
264
|
+
CREATE TABLE page_html_ref (
|
|
265
|
+
page_id INTEGER PRIMARY KEY REFERENCES pages(id) ON DELETE CASCADE,
|
|
266
|
+
hash BLOB NOT NULL REFERENCES page_html_blobs(hash)
|
|
267
|
+
) WITHOUT ROWID
|
|
268
|
+
`);
|
|
269
|
+
await db.raw('CREATE INDEX idx_page_html_ref_hash ON page_html_ref(hash)');
|
|
270
|
+
}
|
package/lib/archive/types.d.ts
CHANGED
|
@@ -1,6 +1,25 @@
|
|
|
1
|
+
import type { DomPathCandidate } from './populate-entity-tables/types.js';
|
|
2
|
+
import type { PageData } from '../utils/types/types.js';
|
|
1
3
|
import type { ParseURLOptions } from '@d-zero/shared/parse-url';
|
|
4
|
+
/**
|
|
5
|
+
* A scraped page payload optionally enriched with the in-browser
|
|
6
|
+
* dom-path capture (`crawler/capture-image-dom-paths.ts`): every `<img>`
|
|
7
|
+
* of the rendered document as `{ outerHTML, path }` pairs in document
|
|
8
|
+
* order. The write path matches these against `imageList[].sourceCode`
|
|
9
|
+
* to resolve `image_items.dom_path_text_id`; when absent (capture
|
|
10
|
+
* failed, metadata-only scrape, or a caller that never renders), every
|
|
11
|
+
* image falls back to the synthetic `unknown/<n>` marker.
|
|
12
|
+
*/
|
|
13
|
+
export type PageDataWithDomPaths = PageData & {
|
|
14
|
+
/** In-browser dom-path capture for the rendered document's images. */
|
|
15
|
+
imageDomPaths?: readonly DomPathCandidate[];
|
|
16
|
+
};
|
|
2
17
|
/**
|
|
3
18
|
* Event map for database-related events emitted by the Database and ArchiveAccessor classes.
|
|
19
|
+
* @example
|
|
20
|
+
* archive.on('error', (error) => {
|
|
21
|
+
* console.error('database failure:', error.message);
|
|
22
|
+
* });
|
|
4
23
|
*/
|
|
5
24
|
export interface DatabaseEvent {
|
|
6
25
|
/** An error that occurred during a database operation. */
|
|
@@ -9,6 +28,9 @@ export interface DatabaseEvent {
|
|
|
9
28
|
/**
|
|
10
29
|
* Configuration stored in the archive database's `info` table.
|
|
11
30
|
* Represents all crawling options that were used for the crawl session.
|
|
31
|
+
* @example
|
|
32
|
+
* const config = await archive.getConfig();
|
|
33
|
+
* console.log(config.roots, config.userAgent, config.parallels);
|
|
12
34
|
*/
|
|
13
35
|
export interface Config extends Required<Pick<ParseURLOptions, 'disableQueries'>> {
|
|
14
36
|
/** The starting URL for the crawl. Stored as a denormalised mirror of `roots[0]` so summary consumers can read a single URL without parsing the array. */
|
|
@@ -48,12 +70,11 @@ export interface Config extends Required<Pick<ParseURLOptions, 'disableQueries'>
|
|
|
48
70
|
}
|
|
49
71
|
/**
|
|
50
72
|
* Provenance of a page or resource row — which crawler channel originally
|
|
51
|
-
* inserted it. Stored as `
|
|
52
|
-
* SQLite schema (NOT NULL DEFAULT `'crawled'`).
|
|
73
|
+
* inserted it. Stored as `content_items.source` / `resource_items.source`
|
|
74
|
+
* in the SQLite schema (NOT NULL DEFAULT `'crawled'`).
|
|
53
75
|
*
|
|
54
76
|
* - `'crawled'` — discovered via the recursive crawl rooted at `info.roots`.
|
|
55
|
-
* Default for
|
|
56
|
-
* `migratePagesResourcesSource` runtime migration.
|
|
77
|
+
* Default for rows that predate the `--inventory` feature.
|
|
57
78
|
* - `'inventory-seed'` — supplied directly by a `crawl --inventory` URL
|
|
58
79
|
* list. For pages this is the HTML URL that was rendered; for resources
|
|
59
80
|
* this is a non-HTML URL handed in by the list (HEAD-fetched without
|
|
@@ -66,8 +87,55 @@ export interface Config extends Required<Pick<ParseURLOptions, 'disableQueries'>
|
|
|
66
87
|
* Isolation queries (`listIsolatedPages` / `listUnusedResources`) judge
|
|
67
88
|
* orphans by `referrer = 0`, NOT by this value — `source` only labels
|
|
68
89
|
* the row.
|
|
90
|
+
* @example
|
|
91
|
+
* if (page.source !== 'crawled') {
|
|
92
|
+
* // Row was introduced by a `crawl --inventory` pass.
|
|
93
|
+
* }
|
|
69
94
|
*/
|
|
70
95
|
export type PageSource = 'crawled' | 'inventory-seed' | 'inventory-discovered';
|
|
96
|
+
/**
|
|
97
|
+
* One row written to the `inventory_runs` audit table on each successful
|
|
98
|
+
* `--inventory <list>` invocation.
|
|
99
|
+
*
|
|
100
|
+
* Schema-mirror interface: every column on `inventory_runs` is represented
|
|
101
|
+
* here. Only `ran_at` is required — every other field is nullable so a
|
|
102
|
+
* raw-SQL backfill (a one-off `sqlite3 INSERT` recording an inventory
|
|
103
|
+
* pass that predates this table) can omit summary
|
|
104
|
+
* stats it cannot reconstruct.
|
|
105
|
+
*
|
|
106
|
+
* The audit log is append-only: there is intentionally no UPDATE path,
|
|
107
|
+
* no UNIQUE constraint on `source_file_sha256`, and no FK to pages /
|
|
108
|
+
* resources — re-applying the same list yields a second row. Duplicate
|
|
109
|
+
* detection is a read-side concern; `source_file_sha256` is recorded as
|
|
110
|
+
* the content-identity key it would use.
|
|
111
|
+
* @example
|
|
112
|
+
* await archive.recordInventoryRun({
|
|
113
|
+
* ran_at: new Date().toISOString(),
|
|
114
|
+
* list_label: 'prod-2026-06',
|
|
115
|
+
* total_lines: 113_268,
|
|
116
|
+
* new_pages: 1234,
|
|
117
|
+
* new_resources: 56,
|
|
118
|
+
* scope_skipped: 7,
|
|
119
|
+
* });
|
|
120
|
+
*/
|
|
121
|
+
export interface InventoryRunMeta {
|
|
122
|
+
/** ISO 8601 timestamp at which the run completed (e.g. `'2026-06-21T11:30:00+09:00'`). */
|
|
123
|
+
ran_at: string;
|
|
124
|
+
/** Human-readable identifier (e.g. `'prod-2026-06-21'`). `null` when the caller did not supply one. */
|
|
125
|
+
list_label?: string | null;
|
|
126
|
+
/** SHA-256 hex digest of the source file. `null` if hashing failed (e.g. file vanished mid-run). */
|
|
127
|
+
source_file_sha256?: string | null;
|
|
128
|
+
/** Number of non-empty lines in the input list (= URL count before scope filtering). */
|
|
129
|
+
total_lines?: number | null;
|
|
130
|
+
/** Number of new HTML seeds inserted as `content_items` rows by this run. */
|
|
131
|
+
new_pages?: number | null;
|
|
132
|
+
/** Number of new non-HTML URLs inserted as `resource_items` rows by this run. */
|
|
133
|
+
new_resources?: number | null;
|
|
134
|
+
/** Number of input URLs dropped because they fell outside the archived scope. */
|
|
135
|
+
scope_skipped?: number | null;
|
|
136
|
+
/** Free-form text for backfill annotations or operator notes. */
|
|
137
|
+
notes?: string | null;
|
|
138
|
+
}
|
|
71
139
|
/**
|
|
72
140
|
* Filter type for querying pages from the database.
|
|
73
141
|
*
|
|
@@ -78,16 +146,28 @@ export type PageSource = 'crawled' | 'inventory-seed' | 'inventory-discovered';
|
|
|
78
146
|
* - `'no-page'` - Non-HTML resources (e.g., images, PDFs)
|
|
79
147
|
* - `'external-no-page'` - External non-HTML resources
|
|
80
148
|
* - `'internal-no-page'` - Internal non-HTML resources
|
|
149
|
+
* @example
|
|
150
|
+
* const internalHtmlPages = await accessor.getPages('internal-page');
|
|
81
151
|
*/
|
|
82
152
|
export type PageFilter = 'page' | 'page-included-no-target' | 'external-page' | 'internal-page' | 'no-page' | 'external-no-page' | 'internal-no-page';
|
|
83
153
|
/**
|
|
84
|
-
*
|
|
154
|
+
* Flat page-row shape.
|
|
85
155
|
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
156
|
+
* Serves two roles: (1) the read shape that
|
|
157
|
+
* `db-ops/pages/read/reconstruct-page-rows.ts` rebuilds by joining the
|
|
158
|
+
* entity / ref tables (`content_items` / `page_meta` / `url_refs` …), and
|
|
159
|
+
* (2) the raw row shape of the pre-0.13 legacy `pages` table, which only
|
|
160
|
+
* exists inside pre-0.13 input archives and is read by the 0.13 migration
|
|
161
|
+
* populate code. Most meta fields are derived from beholder 3.0.0's nested
|
|
162
|
+
* {@link import('@d-zero/beholder').Meta} via
|
|
163
|
+
* `archive/meta/derive-flat-from-meta.ts` and are stored as plain scalars
|
|
164
|
+
* for SQL-level filter / projection. The catch-all `meta_extras` JSON
|
|
165
|
+
* column preserves nested sub-objects not flattened above.
|
|
166
|
+
* @example
|
|
167
|
+
* const pages = await accessor.getPages('page');
|
|
168
|
+
* for (const page of pages) {
|
|
169
|
+
* console.log(page.url, page.status, page.title);
|
|
170
|
+
* }
|
|
91
171
|
*/
|
|
92
172
|
export interface DB_Page {
|
|
93
173
|
/** Auto-incremented primary key. */
|
|
@@ -228,6 +308,12 @@ export interface DB_Page {
|
|
|
228
308
|
/**
|
|
229
309
|
* Raw database row representing a redirect relationship.
|
|
230
310
|
* Maps a source page to its redirect destination.
|
|
311
|
+
* @example
|
|
312
|
+
* const redirect: DB_Redirect = {
|
|
313
|
+
* pageId: 9, // destination page id
|
|
314
|
+
* from: 'http://example.com/old',
|
|
315
|
+
* fromId: 3,
|
|
316
|
+
* };
|
|
231
317
|
*/
|
|
232
318
|
export interface DB_Redirect {
|
|
233
319
|
/** The ID of the destination page after redirect. */
|
|
@@ -238,8 +324,12 @@ export interface DB_Redirect {
|
|
|
238
324
|
fromId: number;
|
|
239
325
|
}
|
|
240
326
|
/**
|
|
241
|
-
*
|
|
242
|
-
*
|
|
327
|
+
* Flat anchor-row shape reconstructed by joining `anchor_edges` with the
|
|
328
|
+
* destination's `content_items` row and the ref tables. Also mirrors the
|
|
329
|
+
* pre-0.13 legacy `anchors` join shape read by the migration populate code.
|
|
330
|
+
* @example
|
|
331
|
+
* const anchors = await accessor.getAnchorsOnPage(pageId);
|
|
332
|
+
* const brokenLinks = anchors.filter((a) => a.status === 404);
|
|
243
333
|
*/
|
|
244
334
|
export interface DB_Anchor {
|
|
245
335
|
/** The ID of the page that contains this anchor. */
|
|
@@ -266,6 +356,10 @@ export interface DB_Anchor {
|
|
|
266
356
|
/**
|
|
267
357
|
* Raw database row representing a referrer relationship.
|
|
268
358
|
* Indicates which page links to which other page, potentially through redirects.
|
|
359
|
+
* @example
|
|
360
|
+
* const referrers = await accessor.getReferrersOfPage(pageId);
|
|
361
|
+
* // `through` differs from the destination URL when the link passed
|
|
362
|
+
* // through a redirect source.
|
|
269
363
|
*/
|
|
270
364
|
export interface DB_Referrer {
|
|
271
365
|
/** The ID of the page being referred to. */
|
|
@@ -282,7 +376,15 @@ export interface DB_Referrer {
|
|
|
282
376
|
textContent: string | null;
|
|
283
377
|
}
|
|
284
378
|
/**
|
|
285
|
-
* Raw database row
|
|
379
|
+
* Raw database row of the pre-0.13 legacy `images` table. The table only
|
|
380
|
+
* exists inside pre-0.13 input archives; current archives store images in
|
|
381
|
+
* `image_items`. This type is read exclusively by the 0.13 migration
|
|
382
|
+
* populate code (`populate-image-items.ts`), which converts these rows
|
|
383
|
+
* into `image_items` before the legacy table is dropped.
|
|
384
|
+
* @example
|
|
385
|
+
* // Inside migration populate code reading a pre-0.13 input archive:
|
|
386
|
+
* const images: DB_Image[] = await trx('images').where('pageId', pageId);
|
|
387
|
+
* const missingAlt = images.filter((img) => img.alt === null);
|
|
286
388
|
*/
|
|
287
389
|
export interface DB_Image {
|
|
288
390
|
/** Auto-incremented primary key. */
|
|
@@ -312,6 +414,14 @@ export interface DB_Image {
|
|
|
312
414
|
}
|
|
313
415
|
/**
|
|
314
416
|
* Represents a page that links to another page (an incoming link).
|
|
417
|
+
* @example
|
|
418
|
+
* const referrer: Referrer = {
|
|
419
|
+
* url: 'https://example.com/from',
|
|
420
|
+
* through: 'https://example.com/old',
|
|
421
|
+
* throughId: 3,
|
|
422
|
+
* hash: null,
|
|
423
|
+
* textContent: 'Link text',
|
|
424
|
+
* };
|
|
315
425
|
*/
|
|
316
426
|
export interface Referrer {
|
|
317
427
|
/** The URL of the referring page. */
|
|
@@ -327,6 +437,18 @@ export interface Referrer {
|
|
|
327
437
|
}
|
|
328
438
|
/**
|
|
329
439
|
* Represents an outgoing link (anchor element) found on a page.
|
|
440
|
+
* @example
|
|
441
|
+
* const anchor: Anchor = {
|
|
442
|
+
* url: 'https://example.com/about',
|
|
443
|
+
* href: '/about',
|
|
444
|
+
* isExternal: false,
|
|
445
|
+
* title: null,
|
|
446
|
+
* status: 200,
|
|
447
|
+
* statusText: 'OK',
|
|
448
|
+
* contentType: 'text/html',
|
|
449
|
+
* hash: null,
|
|
450
|
+
* textContent: 'About us',
|
|
451
|
+
* };
|
|
330
452
|
*/
|
|
331
453
|
export interface Anchor {
|
|
332
454
|
/** The resolved destination URL of the anchor. */
|
|
@@ -350,6 +472,8 @@ export interface Anchor {
|
|
|
350
472
|
}
|
|
351
473
|
/**
|
|
352
474
|
* Represents a page that redirects to this page.
|
|
475
|
+
* @example
|
|
476
|
+
* const redirect: Redirect = { url: 'http://example.com/old', pageId: 3 };
|
|
353
477
|
*/
|
|
354
478
|
export interface Redirect {
|
|
355
479
|
/** The URL of the redirect source page. */
|
|
@@ -359,12 +483,19 @@ export interface Redirect {
|
|
|
359
483
|
}
|
|
360
484
|
/**
|
|
361
485
|
* Raw database row representing a sub-resource (CSS, JS, image, etc.) in the `resources` table.
|
|
486
|
+
* @example
|
|
487
|
+
* const resources = await accessor.getResources();
|
|
488
|
+
* const notFound = resources.filter((r) => r.status === 404);
|
|
362
489
|
*/
|
|
363
490
|
export interface DB_Resource {
|
|
364
491
|
/** Auto-incremented primary key. */
|
|
365
492
|
id: number;
|
|
366
|
-
/**
|
|
367
|
-
|
|
493
|
+
/**
|
|
494
|
+
* The URL of the resource, or `null` when its identity URL is a large
|
|
495
|
+
* `data:` URI routed to `blob_refs` instead of `url_refs` (mirrors
|
|
496
|
+
* `image_items`' src/blob convention — see `build-resource-query.ts`).
|
|
497
|
+
*/
|
|
498
|
+
url: string | null;
|
|
368
499
|
/** Whether the resource is hosted on an external domain (1) or internal (0). */
|
|
369
500
|
isExternal: 0 | 1;
|
|
370
501
|
/** HTTP response status code, or null if not yet fetched. */
|
|
@@ -386,6 +517,11 @@ export interface DB_Resource {
|
|
|
386
517
|
}
|
|
387
518
|
/**
|
|
388
519
|
* Connection options for the archive's libsql-backed database.
|
|
520
|
+
* @example
|
|
521
|
+
* const db = await Database.connect({
|
|
522
|
+
* filename: '/path/to/._nitpicker-site/db.sqlite',
|
|
523
|
+
* readOnly: true,
|
|
524
|
+
* });
|
|
389
525
|
*/
|
|
390
526
|
export interface DatabaseOption {
|
|
391
527
|
/** The absolute file path to the SQLite database file. */
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Awaits a rejecting promise and returns the thrown value. Fails the caller
|
|
3
|
+
* with a descriptive error if the promise resolves. Lets assertions treat
|
|
4
|
+
* the caught value as a normal object without needing a try/catch in the
|
|
5
|
+
* test body — the qa-engineer rule bans `if` / `switch` / try-catch inside
|
|
6
|
+
* test code because control flow inside a test hides which assertion is
|
|
7
|
+
* actually running when a check fails.
|
|
8
|
+
*
|
|
9
|
+
* The sentinel is a fresh `Symbol` per invocation so a genuine rejection
|
|
10
|
+
* whose reason is `undefined` is still correctly distinguished from a
|
|
11
|
+
* resolution to `undefined`.
|
|
12
|
+
*
|
|
13
|
+
* Shared by `check-reader-parity.spec.ts` and `verify-migration.spec.ts`
|
|
14
|
+
* (and any future verify-migration spec that needs to inspect a rejection
|
|
15
|
+
* reason). Not exported from the package — this is a test-only utility
|
|
16
|
+
* kept next to its callers.
|
|
17
|
+
* @param promise - The promise expected to reject.
|
|
18
|
+
* @returns The rejection reason.
|
|
19
|
+
* @example
|
|
20
|
+
* const error = await captureRejection(verifyMigration(db));
|
|
21
|
+
* expect(error).toBeInstanceOf(MigrationVerificationError);
|
|
22
|
+
* expect((error as MigrationVerificationError).details.check).toContain('#1');
|
|
23
|
+
*/
|
|
24
|
+
export declare function captureRejection(promise: Promise<unknown>): Promise<unknown>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Awaits a rejecting promise and returns the thrown value. Fails the caller
|
|
3
|
+
* with a descriptive error if the promise resolves. Lets assertions treat
|
|
4
|
+
* the caught value as a normal object without needing a try/catch in the
|
|
5
|
+
* test body — the qa-engineer rule bans `if` / `switch` / try-catch inside
|
|
6
|
+
* test code because control flow inside a test hides which assertion is
|
|
7
|
+
* actually running when a check fails.
|
|
8
|
+
*
|
|
9
|
+
* The sentinel is a fresh `Symbol` per invocation so a genuine rejection
|
|
10
|
+
* whose reason is `undefined` is still correctly distinguished from a
|
|
11
|
+
* resolution to `undefined`.
|
|
12
|
+
*
|
|
13
|
+
* Shared by `check-reader-parity.spec.ts` and `verify-migration.spec.ts`
|
|
14
|
+
* (and any future verify-migration spec that needs to inspect a rejection
|
|
15
|
+
* reason). Not exported from the package — this is a test-only utility
|
|
16
|
+
* kept next to its callers.
|
|
17
|
+
* @param promise - The promise expected to reject.
|
|
18
|
+
* @returns The rejection reason.
|
|
19
|
+
* @example
|
|
20
|
+
* const error = await captureRejection(verifyMigration(db));
|
|
21
|
+
* expect(error).toBeInstanceOf(MigrationVerificationError);
|
|
22
|
+
* expect((error as MigrationVerificationError).details.check).toContain('#1');
|
|
23
|
+
*/
|
|
24
|
+
export async function captureRejection(promise) {
|
|
25
|
+
const sentinel = Symbol('did-not-throw');
|
|
26
|
+
const value = await promise.then(() => sentinel, (error) => error);
|
|
27
|
+
if (value === sentinel) {
|
|
28
|
+
throw new Error('captureRejection: promise resolved but was expected to reject — the code path under test is silently succeeding');
|
|
29
|
+
}
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Knex } from 'knex';
|
|
2
|
+
/**
|
|
3
|
+
* Verifies 0.13 invariant #3: the `anchor_edges` dedup does not
|
|
4
|
+
* eliminate rows and does not create phantom rows.
|
|
5
|
+
*
|
|
6
|
+
* `populateAnchorEdges` collapses N `anchors` rows per `(pageId, hrefId)`
|
|
7
|
+
* pair into a single `anchor_edges` row with `count = N`. Two ways it
|
|
8
|
+
* could go wrong:
|
|
9
|
+
*
|
|
10
|
+
* - `count(anchor_edges) == 0 && count(anchors) > 0` — dedup annihilated
|
|
11
|
+
* the graph. A populate bug or a group-by mis-key would trip this.
|
|
12
|
+
* - `count(anchor_edges) > count(anchors)` — dedup produced more rows than
|
|
13
|
+
* inputs. Impossible under a correct `GROUP BY` but a phantom-insert bug
|
|
14
|
+
* in the populate loop would trip this.
|
|
15
|
+
*
|
|
16
|
+
* `count(anchor_edges) == count(anchors)` is **not** a failure. Issue #194
|
|
17
|
+
* spelled the upper bound as `< count(anchors)` (strict), but a legitimate
|
|
18
|
+
* small crawl where every `(pageId, hrefId)` pair is unique produces one
|
|
19
|
+
* edge per anchor (count=1) and satisfies the identity naturally. Enforcing
|
|
20
|
+
* strict `<` would refuse to migrate such archives even though every other
|
|
21
|
+
* invariant holds; the true invariant is "no rows added or dropped by
|
|
22
|
+
* dedup" (`anchor_edges <= anchors`), so the code enforces the weaker,
|
|
23
|
+
* correct clause. Check #4 (`SUM(count) == count(anchors)`) already
|
|
24
|
+
* establishes that no rows were silently discarded when the counts happen
|
|
25
|
+
* to match.
|
|
26
|
+
*
|
|
27
|
+
* A trivial archive with zero `anchors` legitimately produces zero
|
|
28
|
+
* `anchor_edges`, so both counts being zero passes; a non-zero `anchor_edges`
|
|
29
|
+
* with a zero `anchors` still throws — that would mean rows appeared from
|
|
30
|
+
* nowhere.
|
|
31
|
+
* @param trx - Knex instance or transaction connected to the populated archive.
|
|
32
|
+
* @throws {MigrationVerificationError} when the invariant is violated.
|
|
33
|
+
*/
|
|
34
|
+
export declare function checkAnchorEdgesCount(trx: Knex): Promise<void>;
|