@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
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ProgressCallback } from '../create-progress-reporter.js';
|
|
2
|
+
import type { Knex } from 'knex';
|
|
3
|
+
/**
|
|
4
|
+
* Populates the five header decomposition tables (`header_name_refs`,
|
|
5
|
+
* `header_value_refs`, `header_sets`, `header_set_entries`,
|
|
6
|
+
* `header_flags`) from every `pages.responseHeaders` and
|
|
7
|
+
* `resources.responseHeaders` JSON blob (issue #191).
|
|
8
|
+
*
|
|
9
|
+
* Strategy:
|
|
10
|
+
*
|
|
11
|
+
* 1. **Warm caches** via {@link ./create-header-table-caches.ts} — load
|
|
12
|
+
* existing `header_name_refs`, `header_value_refs`, and `header_sets`
|
|
13
|
+
* rows into id maps. Idempotent re-runs then reuse ids instead of
|
|
14
|
+
* re-issuing an upsert per entry, and new ids are appended as they
|
|
15
|
+
* are inserted.
|
|
16
|
+
* 2. **Stream `pages.responseHeaders` + `resources.responseHeaders`** in
|
|
17
|
+
* id-keyset chunks. Each non-null value is decomposed via
|
|
18
|
+
* {@link decomposeHeaderSet} and written via
|
|
19
|
+
* {@link ./upsert-one-header-set.ts} — the same per-set primitive the
|
|
20
|
+
* crawler's live write path uses, so migrated and live-crawled
|
|
21
|
+
* archives produce identical header rows.
|
|
22
|
+
*
|
|
23
|
+
* Every write is bulk-batched so the migration stays O(chunks × per-
|
|
24
|
+
* chunk-distinct-decomposed-sets) round-trips against the DB. Idempotency
|
|
25
|
+
* across full re-runs is guaranteed by the `INSERT OR IGNORE`s and the
|
|
26
|
+
* `setIdsProcessedThisRun` guard inside the per-set upsert.
|
|
27
|
+
* @param trx - Knex instance or transaction connected to the archive DB.
|
|
28
|
+
* @param onProgress - Optional sink for periodic progress lines (one per
|
|
29
|
+
* ~5% of each source table scanned); see {@link ../create-progress-reporter.ts}.
|
|
30
|
+
* @example
|
|
31
|
+
* await knex.transaction(async (trx) => {
|
|
32
|
+
* await populateHeaderTables(trx);
|
|
33
|
+
* });
|
|
34
|
+
*/
|
|
35
|
+
export declare function populateHeaderTables(trx: Knex, onProgress?: ProgressCallback): Promise<void>;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { createProgressReporter } from '../create-progress-reporter.js';
|
|
2
|
+
import { createHeaderTableCaches } from './create-header-table-caches.js';
|
|
3
|
+
import { decomposeHeaderSet } from './decompose-header-set.js';
|
|
4
|
+
import { upsertOneHeaderSet } from './upsert-one-header-set.js';
|
|
5
|
+
/**
|
|
6
|
+
* Rows scanned per SELECT chunk against `pages.responseHeaders` /
|
|
7
|
+
* `resources.responseHeaders`. Keyset-paginated on `id` to avoid loading
|
|
8
|
+
* a 470k-row `responseHeaders` column into a single query result.
|
|
9
|
+
*/
|
|
10
|
+
const READ_CHUNK_SIZE = 500;
|
|
11
|
+
/**
|
|
12
|
+
* Populates the five header decomposition tables (`header_name_refs`,
|
|
13
|
+
* `header_value_refs`, `header_sets`, `header_set_entries`,
|
|
14
|
+
* `header_flags`) from every `pages.responseHeaders` and
|
|
15
|
+
* `resources.responseHeaders` JSON blob (issue #191).
|
|
16
|
+
*
|
|
17
|
+
* Strategy:
|
|
18
|
+
*
|
|
19
|
+
* 1. **Warm caches** via {@link ./create-header-table-caches.ts} — load
|
|
20
|
+
* existing `header_name_refs`, `header_value_refs`, and `header_sets`
|
|
21
|
+
* rows into id maps. Idempotent re-runs then reuse ids instead of
|
|
22
|
+
* re-issuing an upsert per entry, and new ids are appended as they
|
|
23
|
+
* are inserted.
|
|
24
|
+
* 2. **Stream `pages.responseHeaders` + `resources.responseHeaders`** in
|
|
25
|
+
* id-keyset chunks. Each non-null value is decomposed via
|
|
26
|
+
* {@link decomposeHeaderSet} and written via
|
|
27
|
+
* {@link ./upsert-one-header-set.ts} — the same per-set primitive the
|
|
28
|
+
* crawler's live write path uses, so migrated and live-crawled
|
|
29
|
+
* archives produce identical header rows.
|
|
30
|
+
*
|
|
31
|
+
* Every write is bulk-batched so the migration stays O(chunks × per-
|
|
32
|
+
* chunk-distinct-decomposed-sets) round-trips against the DB. Idempotency
|
|
33
|
+
* across full re-runs is guaranteed by the `INSERT OR IGNORE`s and the
|
|
34
|
+
* `setIdsProcessedThisRun` guard inside the per-set upsert.
|
|
35
|
+
* @param trx - Knex instance or transaction connected to the archive DB.
|
|
36
|
+
* @param onProgress - Optional sink for periodic progress lines (one per
|
|
37
|
+
* ~5% of each source table scanned); see {@link ../create-progress-reporter.ts}.
|
|
38
|
+
* @example
|
|
39
|
+
* await knex.transaction(async (trx) => {
|
|
40
|
+
* await populateHeaderTables(trx);
|
|
41
|
+
* });
|
|
42
|
+
*/
|
|
43
|
+
export async function populateHeaderTables(trx, onProgress) {
|
|
44
|
+
const caches = await createHeaderTableCaches(trx);
|
|
45
|
+
for (const table of ['pages', 'resources']) {
|
|
46
|
+
const hasTable = await trx.schema.hasTable(table);
|
|
47
|
+
if (!hasTable) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const hasColumn = await trx.schema.hasColumn(table, 'responseHeaders');
|
|
51
|
+
if (!hasColumn) {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
const countRows = await trx(table).count({ n: '*' });
|
|
55
|
+
const total = Number(countRows[0]?.n ?? 0);
|
|
56
|
+
const report = createProgressReporter(`header_tables (${table})`, total, onProgress);
|
|
57
|
+
let processed = 0;
|
|
58
|
+
let cursor = 0;
|
|
59
|
+
while (true) {
|
|
60
|
+
const rows = await trx(table)
|
|
61
|
+
.select('id', 'responseHeaders')
|
|
62
|
+
.where('id', '>', cursor)
|
|
63
|
+
.orderBy('id', 'asc')
|
|
64
|
+
.limit(READ_CHUNK_SIZE);
|
|
65
|
+
if (rows.length === 0) {
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
cursor = rows.at(-1).id;
|
|
69
|
+
processed += rows.length;
|
|
70
|
+
report(processed);
|
|
71
|
+
for (const row of rows) {
|
|
72
|
+
const decomposed = decomposeHeaderSet(row.responseHeaders);
|
|
73
|
+
if (decomposed === null) {
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
await upsertOneHeaderSet(trx, decomposed, caches);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ProgressCallback } from '../create-progress-reporter.js';
|
|
2
|
+
import type { Knex } from 'knex';
|
|
3
|
+
/**
|
|
4
|
+
* Populates `json_refs` from every non-null `pages.meta_extras` value
|
|
5
|
+
* (issue #191).
|
|
6
|
+
*
|
|
7
|
+
* Each value is:
|
|
8
|
+
*
|
|
9
|
+
* 1. Hashed with {@link computeContentHash} (32-byte SHA-256; see that
|
|
10
|
+
* function's docs for the algorithm-choice rationale).
|
|
11
|
+
* 2. Compressed with `zstdCompressSync` (`codec='zstd'`) — same encoder
|
|
12
|
+
* used by `page_html_blobs`.
|
|
13
|
+
* 3. Deduplicated by hash — identical raw JSON strings produce one row.
|
|
14
|
+
*
|
|
15
|
+
* `size_raw` records the uncompressed byte length (UTF-8) and
|
|
16
|
+
* `size_stored` records the compressed byte length; consumers can
|
|
17
|
+
* estimate compression savings without decompressing.
|
|
18
|
+
*
|
|
19
|
+
* `INSERT OR IGNORE` on `hash` makes the step idempotent across partial-
|
|
20
|
+
* failure restarts.
|
|
21
|
+
* @param trx - Knex instance or transaction connected to the archive DB.
|
|
22
|
+
* @param onProgress - Optional sink for periodic progress lines (one per
|
|
23
|
+
* ~5% of `pages` scanned); see {@link ../create-progress-reporter.ts}.
|
|
24
|
+
* @example
|
|
25
|
+
* await knex.transaction(async (trx) => {
|
|
26
|
+
* await populateJsonRefs(trx);
|
|
27
|
+
* });
|
|
28
|
+
*/
|
|
29
|
+
export declare function populateJsonRefs(trx: Knex, onProgress?: ProgressCallback): Promise<void>;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { zstdCompressSync } from 'node:zlib';
|
|
2
|
+
import { createProgressReporter } from '../create-progress-reporter.js';
|
|
3
|
+
import { computeContentHash } from './compute-content-hash.js';
|
|
4
|
+
/**
|
|
5
|
+
* Number of `json_refs` rows sent per INSERT. Each row binds 5 params
|
|
6
|
+
* (hash + json_text + codec + size_raw + size_stored). 200 rows = 1000
|
|
7
|
+
* params — comfortable margin under SQLite's default variable limit and
|
|
8
|
+
* bounds any one INSERT's compressed-blob payload total to a size that
|
|
9
|
+
* fits in one WAL frame.
|
|
10
|
+
*/
|
|
11
|
+
const INSERT_CHUNK_SIZE = 200;
|
|
12
|
+
/**
|
|
13
|
+
* Rows scanned per source query. Same rationale as the other populators:
|
|
14
|
+
* streaming with keyset pagination on `id` avoids loading a 470k-row
|
|
15
|
+
* `meta_extras` column into a single result set.
|
|
16
|
+
*/
|
|
17
|
+
const READ_CHUNK_SIZE = 1000;
|
|
18
|
+
/**
|
|
19
|
+
* Populates `json_refs` from every non-null `pages.meta_extras` value
|
|
20
|
+
* (issue #191).
|
|
21
|
+
*
|
|
22
|
+
* Each value is:
|
|
23
|
+
*
|
|
24
|
+
* 1. Hashed with {@link computeContentHash} (32-byte SHA-256; see that
|
|
25
|
+
* function's docs for the algorithm-choice rationale).
|
|
26
|
+
* 2. Compressed with `zstdCompressSync` (`codec='zstd'`) — same encoder
|
|
27
|
+
* used by `page_html_blobs`.
|
|
28
|
+
* 3. Deduplicated by hash — identical raw JSON strings produce one row.
|
|
29
|
+
*
|
|
30
|
+
* `size_raw` records the uncompressed byte length (UTF-8) and
|
|
31
|
+
* `size_stored` records the compressed byte length; consumers can
|
|
32
|
+
* estimate compression savings without decompressing.
|
|
33
|
+
*
|
|
34
|
+
* `INSERT OR IGNORE` on `hash` makes the step idempotent across partial-
|
|
35
|
+
* failure restarts.
|
|
36
|
+
* @param trx - Knex instance or transaction connected to the archive DB.
|
|
37
|
+
* @param onProgress - Optional sink for periodic progress lines (one per
|
|
38
|
+
* ~5% of `pages` scanned); see {@link ../create-progress-reporter.ts}.
|
|
39
|
+
* @example
|
|
40
|
+
* await knex.transaction(async (trx) => {
|
|
41
|
+
* await populateJsonRefs(trx);
|
|
42
|
+
* });
|
|
43
|
+
*/
|
|
44
|
+
export async function populateJsonRefs(trx, onProgress) {
|
|
45
|
+
const hasPages = await trx.schema.hasTable('pages');
|
|
46
|
+
if (!hasPages) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const hasMetaExtras = await trx.schema.hasColumn('pages', 'meta_extras');
|
|
50
|
+
if (!hasMetaExtras) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const seen = new Set();
|
|
54
|
+
const pending = [];
|
|
55
|
+
const countRows = await trx('pages').count({ n: '*' });
|
|
56
|
+
const total = Number(countRows[0]?.n ?? 0);
|
|
57
|
+
const report = createProgressReporter('json_refs (pages)', total, onProgress);
|
|
58
|
+
let processed = 0;
|
|
59
|
+
let cursor = 0;
|
|
60
|
+
while (true) {
|
|
61
|
+
const rows = await trx('pages')
|
|
62
|
+
.select('id', 'meta_extras as value')
|
|
63
|
+
.where('id', '>', cursor)
|
|
64
|
+
.orderBy('id', 'asc')
|
|
65
|
+
.limit(READ_CHUNK_SIZE);
|
|
66
|
+
if (rows.length === 0) {
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
cursor = rows.at(-1).id;
|
|
70
|
+
processed += rows.length;
|
|
71
|
+
report(processed);
|
|
72
|
+
for (const row of rows) {
|
|
73
|
+
const raw = row.value;
|
|
74
|
+
if (raw == null || raw === '') {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const rawBytes = Buffer.from(raw, 'utf8');
|
|
78
|
+
const hash = computeContentHash(rawBytes);
|
|
79
|
+
const hex = hash.toString('hex');
|
|
80
|
+
if (seen.has(hex)) {
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
seen.add(hex);
|
|
84
|
+
const compressed = zstdCompressSync(rawBytes);
|
|
85
|
+
pending.push({
|
|
86
|
+
hash,
|
|
87
|
+
json_text: compressed,
|
|
88
|
+
codec: 'zstd',
|
|
89
|
+
size_raw: rawBytes.byteLength,
|
|
90
|
+
size_stored: compressed.byteLength,
|
|
91
|
+
});
|
|
92
|
+
if (pending.length >= INSERT_CHUNK_SIZE) {
|
|
93
|
+
await trx('json_refs').insert(pending).onConflict('hash').ignore();
|
|
94
|
+
pending.length = 0;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (pending.length > 0) {
|
|
99
|
+
await trx('json_refs').insert(pending).onConflict('hash').ignore();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { ProgressCallback } from '../create-progress-reporter.js';
|
|
2
|
+
import type { Knex } from 'knex';
|
|
3
|
+
/**
|
|
4
|
+
* Runs the six 0.13 ref-table populates (issue #191) in this fixed
|
|
5
|
+
* order against an already-connected archive:
|
|
6
|
+
*
|
|
7
|
+
* 1. `content_type_refs`
|
|
8
|
+
* 2. `url_refs`
|
|
9
|
+
* 3. `text_refs`
|
|
10
|
+
* 4. `json_refs`
|
|
11
|
+
* 5. `blob_refs`
|
|
12
|
+
* 6. Header tables (name / value / set / entries / flags).
|
|
13
|
+
*
|
|
14
|
+
* The order is an execution-order invariant, not arbitrary: the entity
|
|
15
|
+
* populates that run afterwards (`populateEntityTables`) JOIN against
|
|
16
|
+
* `content_type_refs` when filling `content_items` / `resource_items`,
|
|
17
|
+
* and look up `url_refs.id` for every URL column, so both dictionaries
|
|
18
|
+
* must be complete first. Within this function the ordering is:
|
|
19
|
+
* dictionary tables (1–5) first, header tables (6) last — the header
|
|
20
|
+
* tables' entries reference name / value refs, but those are inserted
|
|
21
|
+
* by `populateHeaderTables` itself, so no barrier between sub-populates
|
|
22
|
+
* is required.
|
|
23
|
+
*
|
|
24
|
+
* Every sub-populate is independently idempotent via `INSERT OR IGNORE`
|
|
25
|
+
* on its natural key. Running this orchestrator twice on the same archive
|
|
26
|
+
* produces the same rows — no phase marker table is used. This function
|
|
27
|
+
* does not open its own transaction so the caller controls the boundary;
|
|
28
|
+
* the whole invocation is expected to run inside one writer transaction
|
|
29
|
+
* with `.bak` protection at the caller level.
|
|
30
|
+
*
|
|
31
|
+
* `scripts/migrate-to-0.13.mjs` does NOT call this orchestrator directly
|
|
32
|
+
* — it calls the same six sub-populates itself, each in its own
|
|
33
|
+
* transaction, so a killed multi-hour migration only re-does the one
|
|
34
|
+
* table in flight on resume rather than the whole six-table batch. Use
|
|
35
|
+
* this function directly when that per-table checkpointing is not
|
|
36
|
+
* needed and a single all-or-nothing transaction is preferred.
|
|
37
|
+
* @param trx - Knex instance or transaction connected to the archive DB.
|
|
38
|
+
* @param onProgress - Optional sink threaded to every sub-populate for
|
|
39
|
+
* periodic progress lines; see {@link ../create-progress-reporter.ts}.
|
|
40
|
+
* @example
|
|
41
|
+
* // Single-transaction use: connect via Archive, wrap in a
|
|
42
|
+
* // transaction, run every sub-step, then rely on the caller's `.bak`
|
|
43
|
+
* // safety net if any step throws.
|
|
44
|
+
* const archive = await Archive.open(archivePath);
|
|
45
|
+
* const knex = archive.getKnex();
|
|
46
|
+
* await knex.transaction(async (trx) => {
|
|
47
|
+
* await populateRefTables(trx);
|
|
48
|
+
* });
|
|
49
|
+
* await archive.write();
|
|
50
|
+
*/
|
|
51
|
+
export declare function populateRefTables(trx: Knex, onProgress?: ProgressCallback): Promise<void>;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { populateBlobRefs } from './populate-blob-refs.js';
|
|
2
|
+
import { populateContentTypeRefs } from './populate-content-type-refs.js';
|
|
3
|
+
import { populateHeaderTables } from './populate-header-tables.js';
|
|
4
|
+
import { populateJsonRefs } from './populate-json-refs.js';
|
|
5
|
+
import { populateTextRefs } from './populate-text-refs.js';
|
|
6
|
+
import { populateUrlRefs } from './populate-url-refs.js';
|
|
7
|
+
/**
|
|
8
|
+
* Runs the six 0.13 ref-table populates (issue #191) in this fixed
|
|
9
|
+
* order against an already-connected archive:
|
|
10
|
+
*
|
|
11
|
+
* 1. `content_type_refs`
|
|
12
|
+
* 2. `url_refs`
|
|
13
|
+
* 3. `text_refs`
|
|
14
|
+
* 4. `json_refs`
|
|
15
|
+
* 5. `blob_refs`
|
|
16
|
+
* 6. Header tables (name / value / set / entries / flags).
|
|
17
|
+
*
|
|
18
|
+
* The order is an execution-order invariant, not arbitrary: the entity
|
|
19
|
+
* populates that run afterwards (`populateEntityTables`) JOIN against
|
|
20
|
+
* `content_type_refs` when filling `content_items` / `resource_items`,
|
|
21
|
+
* and look up `url_refs.id` for every URL column, so both dictionaries
|
|
22
|
+
* must be complete first. Within this function the ordering is:
|
|
23
|
+
* dictionary tables (1–5) first, header tables (6) last — the header
|
|
24
|
+
* tables' entries reference name / value refs, but those are inserted
|
|
25
|
+
* by `populateHeaderTables` itself, so no barrier between sub-populates
|
|
26
|
+
* is required.
|
|
27
|
+
*
|
|
28
|
+
* Every sub-populate is independently idempotent via `INSERT OR IGNORE`
|
|
29
|
+
* on its natural key. Running this orchestrator twice on the same archive
|
|
30
|
+
* produces the same rows — no phase marker table is used. This function
|
|
31
|
+
* does not open its own transaction so the caller controls the boundary;
|
|
32
|
+
* the whole invocation is expected to run inside one writer transaction
|
|
33
|
+
* with `.bak` protection at the caller level.
|
|
34
|
+
*
|
|
35
|
+
* `scripts/migrate-to-0.13.mjs` does NOT call this orchestrator directly
|
|
36
|
+
* — it calls the same six sub-populates itself, each in its own
|
|
37
|
+
* transaction, so a killed multi-hour migration only re-does the one
|
|
38
|
+
* table in flight on resume rather than the whole six-table batch. Use
|
|
39
|
+
* this function directly when that per-table checkpointing is not
|
|
40
|
+
* needed and a single all-or-nothing transaction is preferred.
|
|
41
|
+
* @param trx - Knex instance or transaction connected to the archive DB.
|
|
42
|
+
* @param onProgress - Optional sink threaded to every sub-populate for
|
|
43
|
+
* periodic progress lines; see {@link ../create-progress-reporter.ts}.
|
|
44
|
+
* @example
|
|
45
|
+
* // Single-transaction use: connect via Archive, wrap in a
|
|
46
|
+
* // transaction, run every sub-step, then rely on the caller's `.bak`
|
|
47
|
+
* // safety net if any step throws.
|
|
48
|
+
* const archive = await Archive.open(archivePath);
|
|
49
|
+
* const knex = archive.getKnex();
|
|
50
|
+
* await knex.transaction(async (trx) => {
|
|
51
|
+
* await populateRefTables(trx);
|
|
52
|
+
* });
|
|
53
|
+
* await archive.write();
|
|
54
|
+
*/
|
|
55
|
+
export async function populateRefTables(trx, onProgress) {
|
|
56
|
+
await populateContentTypeRefs(trx);
|
|
57
|
+
await populateUrlRefs(trx, onProgress);
|
|
58
|
+
await populateTextRefs(trx, onProgress);
|
|
59
|
+
await populateJsonRefs(trx, onProgress);
|
|
60
|
+
await populateBlobRefs(trx, onProgress);
|
|
61
|
+
await populateHeaderTables(trx, onProgress);
|
|
62
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ProgressCallback } from '../create-progress-reporter.js';
|
|
2
|
+
import type { Knex } from 'knex';
|
|
3
|
+
/**
|
|
4
|
+
* Populates `text_refs` from every text-shaped column across `anchors`,
|
|
5
|
+
* `images`, and `pages` (issue #191).
|
|
6
|
+
*
|
|
7
|
+
* Rules:
|
|
8
|
+
*
|
|
9
|
+
* - **Content-hash dedup contract**: identical text produces one row. The
|
|
10
|
+
* hash is derived by {@link computeContentHash} (currently SHA-256,
|
|
11
|
+
* matching `page_html_blobs.hash`; see that function's docs for the
|
|
12
|
+
* algorithm-choice rationale).
|
|
13
|
+
* - **Empty and null are skipped** — an empty `<a>` tag adds no text to
|
|
14
|
+
* the dictionary. Anchors with no text still get an `anchor_edges` row
|
|
15
|
+
* in 0.13, just with `first_text_id = NULL`.
|
|
16
|
+
* - **INSERT OR IGNORE on (hash, text)** — the composite UNIQUE from the
|
|
17
|
+
* 0.13 DDL — makes the step idempotent across partial-failure
|
|
18
|
+
* restarts.
|
|
19
|
+
*
|
|
20
|
+
* Peak memory is bounded by the count of distinct texts (all texts are
|
|
21
|
+
* held in a Map before insert). On the reference archive this Map is
|
|
22
|
+
* about 5 MB of anchor textContent + a few MB of page meta text — well
|
|
23
|
+
* within the migration process budget.
|
|
24
|
+
* @param trx - Knex instance or transaction connected to the archive DB.
|
|
25
|
+
* @param onProgress - Optional sink for periodic progress lines (one per
|
|
26
|
+
* ~5% of each source table scanned); see {@link ../create-progress-reporter.ts}.
|
|
27
|
+
* @example
|
|
28
|
+
* await knex.transaction(async (trx) => {
|
|
29
|
+
* await populateTextRefs(trx);
|
|
30
|
+
* });
|
|
31
|
+
*/
|
|
32
|
+
export declare function populateTextRefs(trx: Knex, onProgress?: ProgressCallback): Promise<void>;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { createProgressReporter } from '../create-progress-reporter.js';
|
|
2
|
+
import { computeContentHash } from './compute-content-hash.js';
|
|
3
|
+
/**
|
|
4
|
+
* Number of `text_refs` rows sent per `INSERT ... VALUES (...)` statement.
|
|
5
|
+
* Each row binds 2 params (hash + text), so 500 rows = 1000 params — well
|
|
6
|
+
* under SQLite's default `SQLITE_MAX_VARIABLE_NUMBER`.
|
|
7
|
+
*/
|
|
8
|
+
const INSERT_CHUNK_SIZE = 500;
|
|
9
|
+
/**
|
|
10
|
+
* Rows scanned per keyset-paginated `SELECT` chunk. One SELECT reads all
|
|
11
|
+
* text columns for the source table's chunk simultaneously so the pages
|
|
12
|
+
* table is scanned exactly once per populate call, not N-times-once-per-
|
|
13
|
+
* text-column.
|
|
14
|
+
*/
|
|
15
|
+
const READ_CHUNK_SIZE = 5000;
|
|
16
|
+
/**
|
|
17
|
+
* Source table + its text-shaped columns. Groups by table so each table
|
|
18
|
+
* is scanned exactly once with a single SELECT that covers every
|
|
19
|
+
* relevant column — a per-column scan would run 8 separate `pages`
|
|
20
|
+
* scans and multiply migration wall-clock accordingly.
|
|
21
|
+
*
|
|
22
|
+
* `dom_path` is intentionally absent: dom_path strings are derived from
|
|
23
|
+
* the stored HTML blob, not from any column of the current write-model,
|
|
24
|
+
* so this scan has nothing to read. Upserting dom_path strings into
|
|
25
|
+
* `text_refs` is the job of the image-items populate
|
|
26
|
+
* (`populate-entity-tables/populate-image-items.ts`), not this pass.
|
|
27
|
+
*/
|
|
28
|
+
const TEXT_SOURCES = [
|
|
29
|
+
{ table: 'anchors', columns: ['textContent'] },
|
|
30
|
+
{ table: 'images', columns: ['alt'] },
|
|
31
|
+
{
|
|
32
|
+
table: 'pages',
|
|
33
|
+
columns: [
|
|
34
|
+
'title',
|
|
35
|
+
'description',
|
|
36
|
+
'keywords',
|
|
37
|
+
'robots_raw',
|
|
38
|
+
'og_title',
|
|
39
|
+
'og_description',
|
|
40
|
+
'twitter_title',
|
|
41
|
+
'twitter_description',
|
|
42
|
+
],
|
|
43
|
+
},
|
|
44
|
+
];
|
|
45
|
+
/**
|
|
46
|
+
* Populates `text_refs` from every text-shaped column across `anchors`,
|
|
47
|
+
* `images`, and `pages` (issue #191).
|
|
48
|
+
*
|
|
49
|
+
* Rules:
|
|
50
|
+
*
|
|
51
|
+
* - **Content-hash dedup contract**: identical text produces one row. The
|
|
52
|
+
* hash is derived by {@link computeContentHash} (currently SHA-256,
|
|
53
|
+
* matching `page_html_blobs.hash`; see that function's docs for the
|
|
54
|
+
* algorithm-choice rationale).
|
|
55
|
+
* - **Empty and null are skipped** — an empty `<a>` tag adds no text to
|
|
56
|
+
* the dictionary. Anchors with no text still get an `anchor_edges` row
|
|
57
|
+
* in 0.13, just with `first_text_id = NULL`.
|
|
58
|
+
* - **INSERT OR IGNORE on (hash, text)** — the composite UNIQUE from the
|
|
59
|
+
* 0.13 DDL — makes the step idempotent across partial-failure
|
|
60
|
+
* restarts.
|
|
61
|
+
*
|
|
62
|
+
* Peak memory is bounded by the count of distinct texts (all texts are
|
|
63
|
+
* held in a Map before insert). On the reference archive this Map is
|
|
64
|
+
* about 5 MB of anchor textContent + a few MB of page meta text — well
|
|
65
|
+
* within the migration process budget.
|
|
66
|
+
* @param trx - Knex instance or transaction connected to the archive DB.
|
|
67
|
+
* @param onProgress - Optional sink for periodic progress lines (one per
|
|
68
|
+
* ~5% of each source table scanned); see {@link ../create-progress-reporter.ts}.
|
|
69
|
+
* @example
|
|
70
|
+
* await knex.transaction(async (trx) => {
|
|
71
|
+
* await populateTextRefs(trx);
|
|
72
|
+
* });
|
|
73
|
+
*/
|
|
74
|
+
export async function populateTextRefs(trx, onProgress) {
|
|
75
|
+
const seen = new Map();
|
|
76
|
+
for (const source of TEXT_SOURCES) {
|
|
77
|
+
const hasTable = await trx.schema.hasTable(source.table);
|
|
78
|
+
if (!hasTable) {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
const presentColumns = [];
|
|
82
|
+
for (const column of source.columns) {
|
|
83
|
+
if (await trx.schema.hasColumn(source.table, column)) {
|
|
84
|
+
presentColumns.push(column);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (presentColumns.length === 0) {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
const countRows = await trx(source.table).count({ n: '*' });
|
|
91
|
+
const total = Number(countRows[0]?.n ?? 0);
|
|
92
|
+
const report = createProgressReporter(`text_refs (${source.table})`, total, onProgress);
|
|
93
|
+
let processed = 0;
|
|
94
|
+
let cursor = 0;
|
|
95
|
+
while (true) {
|
|
96
|
+
const rows = await trx(source.table)
|
|
97
|
+
.select('id', ...presentColumns)
|
|
98
|
+
.where('id', '>', cursor)
|
|
99
|
+
.orderBy('id', 'asc')
|
|
100
|
+
.limit(READ_CHUNK_SIZE);
|
|
101
|
+
if (rows.length === 0) {
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
cursor = rows.at(-1).id;
|
|
105
|
+
processed += rows.length;
|
|
106
|
+
report(processed);
|
|
107
|
+
for (const row of rows) {
|
|
108
|
+
for (const column of presentColumns) {
|
|
109
|
+
const value = row[column];
|
|
110
|
+
if (typeof value !== 'string' || value === '') {
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
const hash = computeContentHash(value);
|
|
114
|
+
const key = hash.toString('hex');
|
|
115
|
+
if (!seen.has(key)) {
|
|
116
|
+
seen.set(key, value);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (seen.size === 0) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const inserts = [];
|
|
126
|
+
for (const [hex, text] of seen) {
|
|
127
|
+
inserts.push({ hash: Buffer.from(hex, 'hex'), text });
|
|
128
|
+
}
|
|
129
|
+
for (let index = 0; index < inserts.length; index += INSERT_CHUNK_SIZE) {
|
|
130
|
+
const chunk = inserts.slice(index, index + INSERT_CHUNK_SIZE);
|
|
131
|
+
await trx('text_refs').insert(chunk).onConflict(['hash', 'text']).ignore();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ProgressCallback } from '../create-progress-reporter.js';
|
|
2
|
+
import type { Knex } from 'knex';
|
|
3
|
+
/**
|
|
4
|
+
* Populates `url_refs` from every URL-shaped column across `pages`,
|
|
5
|
+
* `resources`, and `images` (issue #191).
|
|
6
|
+
*
|
|
7
|
+
* Runs two passes per source table:
|
|
8
|
+
*
|
|
9
|
+
* 1. **Collect distinct URLs** into an in-process `Set<string>`, streaming
|
|
10
|
+
* rows from each source table by keyset pagination on `id`. All the
|
|
11
|
+
* table's URL columns are read in a single SELECT so the pages scan
|
|
12
|
+
* is O(rows), not O(rows × columns). Peak memory is bounded by the
|
|
13
|
+
* count of distinct URLs, not the row count.
|
|
14
|
+
* 2. **Bulk-insert** into `url_refs` in chunks of {@link INSERT_CHUNK_SIZE},
|
|
15
|
+
* with the decomposed columns (`scheme` / `host` / `port` / `path` /
|
|
16
|
+
* `query_hash` / `fragment`) derived in JS by {@link decomposeUrl}.
|
|
17
|
+
*
|
|
18
|
+
* `INSERT OR IGNORE` on `url_refs.url` makes the step idempotent —
|
|
19
|
+
* repeated invocations after partial failure only add new URLs.
|
|
20
|
+
* @param trx - Knex instance or transaction connected to the archive DB.
|
|
21
|
+
* @param onProgress - Optional sink for periodic progress lines (one per
|
|
22
|
+
* ~5% of each source table scanned); see {@link ../create-progress-reporter.ts}.
|
|
23
|
+
* @example
|
|
24
|
+
* await knex.transaction(async (trx) => {
|
|
25
|
+
* await populateUrlRefs(trx);
|
|
26
|
+
* });
|
|
27
|
+
*/
|
|
28
|
+
export declare function populateUrlRefs(trx: Knex, onProgress?: ProgressCallback): Promise<void>;
|