@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,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Computes the {@link HeaderFlagsRow} for one decomposed header set.
|
|
3
|
+
*
|
|
4
|
+
* Each `has_*` boolean is a straight "is this name present" check on the
|
|
5
|
+
* decomposed entries — semantically equivalent to `checkHeaders` /
|
|
6
|
+
* `headerPresenceExpression` in `@nitpicker/query`, but expressed in JS
|
|
7
|
+
* over the already-normalized `HeaderEntry.name` (lower-cased) so no
|
|
8
|
+
* `LIKE` pattern is needed. This drops the JSON-key-shape false-positive
|
|
9
|
+
* risk that `headerPresenceExpression`'s SQL guard against (a value that
|
|
10
|
+
* happens to mention another header's name won't fire here because names
|
|
11
|
+
* come from the parsed JSON's KEYS, not from a substring scan).
|
|
12
|
+
* @param entries - Every decomposed entry for one `header_sets` row.
|
|
13
|
+
* @returns The row-shaped flags to insert into `header_flags`.
|
|
14
|
+
*/
|
|
15
|
+
export function computeHeaderFlags(entries) {
|
|
16
|
+
const cachePolicies = [];
|
|
17
|
+
let hasCsp = false;
|
|
18
|
+
let hasXFrameOptions = false;
|
|
19
|
+
let hasXContentTypeOptions = false;
|
|
20
|
+
let hasHsts = false;
|
|
21
|
+
let hasReferrerPolicy = false;
|
|
22
|
+
let hasPermissionsPolicy = false;
|
|
23
|
+
let hasSetCookie = false;
|
|
24
|
+
for (const entry of entries) {
|
|
25
|
+
switch (entry.name) {
|
|
26
|
+
case 'content-security-policy': {
|
|
27
|
+
hasCsp = true;
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
case 'x-frame-options': {
|
|
31
|
+
hasXFrameOptions = true;
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
case 'x-content-type-options': {
|
|
35
|
+
hasXContentTypeOptions = true;
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
case 'strict-transport-security': {
|
|
39
|
+
hasHsts = true;
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
case 'referrer-policy': {
|
|
43
|
+
hasReferrerPolicy = true;
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
case 'permissions-policy': {
|
|
47
|
+
hasPermissionsPolicy = true;
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
case 'set-cookie': {
|
|
51
|
+
hasSetCookie = true;
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
case 'cache-control': {
|
|
55
|
+
cachePolicies.push(entry.value);
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
has_csp: hasCsp ? 1 : 0,
|
|
62
|
+
has_x_frame_options: hasXFrameOptions ? 1 : 0,
|
|
63
|
+
has_x_content_type_options: hasXContentTypeOptions ? 1 : 0,
|
|
64
|
+
has_hsts: hasHsts ? 1 : 0,
|
|
65
|
+
has_referrer_policy: hasReferrerPolicy ? 1 : 0,
|
|
66
|
+
has_permissions_policy: hasPermissionsPolicy ? 1 : 0,
|
|
67
|
+
has_set_cookie: hasSetCookie ? 1 : 0,
|
|
68
|
+
cache_policy: cachePolicies.length === 0 ? null : cachePolicies.join(', '),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ContentTypeCategory } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Single matcher slot for a Content-Type rule. See `@nitpicker/query`'s
|
|
4
|
+
* `content-type-rules.ts` for the wider design discussion — this file only
|
|
5
|
+
* carries the subset required for JS-side classification (no SQL builders,
|
|
6
|
+
* which live in `@nitpicker/query`).
|
|
7
|
+
*/
|
|
8
|
+
type Matcher = {
|
|
9
|
+
readonly kind: 'exact';
|
|
10
|
+
readonly value: string;
|
|
11
|
+
} | {
|
|
12
|
+
readonly kind: 'prefix';
|
|
13
|
+
readonly value: string;
|
|
14
|
+
} | {
|
|
15
|
+
readonly kind: 'suffix';
|
|
16
|
+
readonly value: string;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* One row of the classification table: attach a category to a set of
|
|
20
|
+
* matchers, all of which OR together.
|
|
21
|
+
*/
|
|
22
|
+
interface Rule {
|
|
23
|
+
readonly category: Exclude<ContentTypeCategory, 'other' | 'unknown'>;
|
|
24
|
+
readonly matchers: readonly Matcher[];
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Content-Type classification rules, evaluated in array order — first match
|
|
28
|
+
* wins. Kept in lock-step with the source-of-truth table in
|
|
29
|
+
* `packages/@nitpicker/query/src/content-type-rules.ts`. Do not reorder
|
|
30
|
+
* without also editing the query-side copy (a drift would misroute
|
|
31
|
+
* `image/svg+xml` between `image` and `xml`, etc.).
|
|
32
|
+
*
|
|
33
|
+
* A future cleanup can lift the rule table into `@d-zero/shared` so both
|
|
34
|
+
* `@nitpicker/crawler` and `@nitpicker/query` import a single source of
|
|
35
|
+
* truth; that migration is out of 0.13's scope.
|
|
36
|
+
*/
|
|
37
|
+
export declare const CONTENT_TYPE_RULES: readonly Rule[];
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content-Type classification rules, evaluated in array order — first match
|
|
3
|
+
* wins. Kept in lock-step with the source-of-truth table in
|
|
4
|
+
* `packages/@nitpicker/query/src/content-type-rules.ts`. Do not reorder
|
|
5
|
+
* without also editing the query-side copy (a drift would misroute
|
|
6
|
+
* `image/svg+xml` between `image` and `xml`, etc.).
|
|
7
|
+
*
|
|
8
|
+
* A future cleanup can lift the rule table into `@d-zero/shared` so both
|
|
9
|
+
* `@nitpicker/crawler` and `@nitpicker/query` import a single source of
|
|
10
|
+
* truth; that migration is out of 0.13's scope.
|
|
11
|
+
*/
|
|
12
|
+
export const CONTENT_TYPE_RULES = [
|
|
13
|
+
{
|
|
14
|
+
category: 'html',
|
|
15
|
+
matchers: [
|
|
16
|
+
{ kind: 'exact', value: 'text/html' },
|
|
17
|
+
{ kind: 'exact', value: 'application/xhtml+xml' },
|
|
18
|
+
],
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
category: 'pdf',
|
|
22
|
+
matchers: [{ kind: 'exact', value: 'application/pdf' }],
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
category: 'csv',
|
|
26
|
+
matchers: [
|
|
27
|
+
{ kind: 'exact', value: 'text/csv' },
|
|
28
|
+
{ kind: 'exact', value: 'application/csv' },
|
|
29
|
+
{ kind: 'exact', value: 'application/x-csv' },
|
|
30
|
+
{ kind: 'exact', value: 'text/tab-separated-values' },
|
|
31
|
+
{ kind: 'exact', value: 'text/tsv' },
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
category: 'word',
|
|
36
|
+
matchers: [
|
|
37
|
+
{ kind: 'exact', value: 'application/msword' },
|
|
38
|
+
{
|
|
39
|
+
kind: 'exact',
|
|
40
|
+
value: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
category: 'excel',
|
|
46
|
+
matchers: [
|
|
47
|
+
{ kind: 'exact', value: 'application/vnd.ms-excel' },
|
|
48
|
+
{
|
|
49
|
+
kind: 'exact',
|
|
50
|
+
value: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
category: 'powerpoint',
|
|
56
|
+
matchers: [
|
|
57
|
+
{ kind: 'exact', value: 'application/vnd.ms-powerpoint' },
|
|
58
|
+
{
|
|
59
|
+
kind: 'exact',
|
|
60
|
+
value: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
category: 'image',
|
|
66
|
+
matchers: [{ kind: 'prefix', value: 'image/' }],
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
category: 'audio',
|
|
70
|
+
matchers: [{ kind: 'prefix', value: 'audio/' }],
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
category: 'video',
|
|
74
|
+
matchers: [{ kind: 'prefix', value: 'video/' }],
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
category: 'font',
|
|
78
|
+
matchers: [
|
|
79
|
+
{ kind: 'prefix', value: 'font/' },
|
|
80
|
+
{ kind: 'prefix', value: 'application/font-' },
|
|
81
|
+
{ kind: 'exact', value: 'application/vnd.ms-fontobject' },
|
|
82
|
+
],
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
category: 'css',
|
|
86
|
+
matchers: [{ kind: 'exact', value: 'text/css' }],
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
category: 'javascript',
|
|
90
|
+
matchers: [
|
|
91
|
+
{ kind: 'exact', value: 'text/javascript' },
|
|
92
|
+
{ kind: 'exact', value: 'application/javascript' },
|
|
93
|
+
{ kind: 'exact', value: 'application/x-javascript' },
|
|
94
|
+
{ kind: 'exact', value: 'application/ecmascript' },
|
|
95
|
+
],
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
category: 'json',
|
|
99
|
+
matchers: [
|
|
100
|
+
{ kind: 'exact', value: 'application/json' },
|
|
101
|
+
{ kind: 'exact', value: 'application/yaml' },
|
|
102
|
+
{ kind: 'exact', value: 'application/x-yaml' },
|
|
103
|
+
{ kind: 'exact', value: 'text/yaml' },
|
|
104
|
+
{ kind: 'exact', value: 'text/x-yaml' },
|
|
105
|
+
{ kind: 'suffix', value: '+json' },
|
|
106
|
+
{ kind: 'suffix', value: '+yaml' },
|
|
107
|
+
],
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
category: 'xml',
|
|
111
|
+
matchers: [
|
|
112
|
+
{ kind: 'exact', value: 'application/xml' },
|
|
113
|
+
{ kind: 'exact', value: 'text/xml' },
|
|
114
|
+
{ kind: 'suffix', value: '+xml' },
|
|
115
|
+
],
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
category: 'archive',
|
|
119
|
+
matchers: [
|
|
120
|
+
{ kind: 'exact', value: 'application/zip' },
|
|
121
|
+
{ kind: 'exact', value: 'application/gzip' },
|
|
122
|
+
{ kind: 'exact', value: 'application/x-gzip' },
|
|
123
|
+
{ kind: 'exact', value: 'application/x-tar' },
|
|
124
|
+
{ kind: 'exact', value: 'application/x-7z-compressed' },
|
|
125
|
+
{ kind: 'exact', value: 'application/x-rar-compressed' },
|
|
126
|
+
{ kind: 'exact', value: 'application/octet-stream' },
|
|
127
|
+
],
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
category: 'text',
|
|
131
|
+
matchers: [{ kind: 'prefix', value: 'text/' }],
|
|
132
|
+
},
|
|
133
|
+
];
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { HeaderTableCaches } from './types.js';
|
|
2
|
+
import type { Knex } from 'knex';
|
|
3
|
+
/**
|
|
4
|
+
* Creates a {@link HeaderTableCaches} bundle warmed from the DB's current
|
|
5
|
+
* `header_name_refs` / `header_value_refs` / `header_sets` rows.
|
|
6
|
+
*
|
|
7
|
+
* Warming lets idempotent re-runs (and resumed / appended crawls against
|
|
8
|
+
* an archive that already holds header rows) reuse existing ids instead
|
|
9
|
+
* of re-issuing an upsert per entry. On a fresh archive all three tables
|
|
10
|
+
* are empty and the warm-up is three cheap SELECTs.
|
|
11
|
+
*
|
|
12
|
+
* The bundle is only valid for the connection (or transaction lineage)
|
|
13
|
+
* it was warmed against — ids observed here are stable because the
|
|
14
|
+
* header dictionaries are append-only, but a cache warmed on connection
|
|
15
|
+
* A does not see rows a concurrent writer B added. The crawler holds a
|
|
16
|
+
* single writer connection per archive, so this cannot occur in
|
|
17
|
+
* practice.
|
|
18
|
+
* @param trx - Knex instance or transaction connected to the archive DB.
|
|
19
|
+
* @returns Warmed cache bundle ready for
|
|
20
|
+
* {@link ./upsert-one-header-set.ts}.
|
|
21
|
+
* @example
|
|
22
|
+
* const caches = await createHeaderTableCaches(knex);
|
|
23
|
+
* const setId = await upsertOneHeaderSet(knex, decomposed, caches);
|
|
24
|
+
*/
|
|
25
|
+
export declare function createHeaderTableCaches(trx: Knex): Promise<HeaderTableCaches>;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { headerValueCacheKey } from './header-value-cache-key.js';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a {@link HeaderTableCaches} bundle warmed from the DB's current
|
|
4
|
+
* `header_name_refs` / `header_value_refs` / `header_sets` rows.
|
|
5
|
+
*
|
|
6
|
+
* Warming lets idempotent re-runs (and resumed / appended crawls against
|
|
7
|
+
* an archive that already holds header rows) reuse existing ids instead
|
|
8
|
+
* of re-issuing an upsert per entry. On a fresh archive all three tables
|
|
9
|
+
* are empty and the warm-up is three cheap SELECTs.
|
|
10
|
+
*
|
|
11
|
+
* The bundle is only valid for the connection (or transaction lineage)
|
|
12
|
+
* it was warmed against — ids observed here are stable because the
|
|
13
|
+
* header dictionaries are append-only, but a cache warmed on connection
|
|
14
|
+
* A does not see rows a concurrent writer B added. The crawler holds a
|
|
15
|
+
* single writer connection per archive, so this cannot occur in
|
|
16
|
+
* practice.
|
|
17
|
+
* @param trx - Knex instance or transaction connected to the archive DB.
|
|
18
|
+
* @returns Warmed cache bundle ready for
|
|
19
|
+
* {@link ./upsert-one-header-set.ts}.
|
|
20
|
+
* @example
|
|
21
|
+
* const caches = await createHeaderTableCaches(knex);
|
|
22
|
+
* const setId = await upsertOneHeaderSet(knex, decomposed, caches);
|
|
23
|
+
*/
|
|
24
|
+
export async function createHeaderTableCaches(trx) {
|
|
25
|
+
const nameIdCache = new Map();
|
|
26
|
+
const nameRows = await trx('header_name_refs').select();
|
|
27
|
+
for (const row of nameRows) {
|
|
28
|
+
nameIdCache.set(row.name, row.id);
|
|
29
|
+
}
|
|
30
|
+
const valueIdCache = new Map();
|
|
31
|
+
const valueRows = await trx('header_value_refs').select();
|
|
32
|
+
for (const row of valueRows) {
|
|
33
|
+
valueIdCache.set(headerValueCacheKey(Buffer.from(row.hash), row.value), row.id);
|
|
34
|
+
}
|
|
35
|
+
const setIdByRawJsonHash = new Map();
|
|
36
|
+
const setIdByRawHash = new Map();
|
|
37
|
+
const setRows = await trx('header_sets').select('id', 'raw_json_hash', 'raw_hash');
|
|
38
|
+
for (const row of setRows) {
|
|
39
|
+
setIdByRawJsonHash.set(Buffer.from(row.raw_json_hash).toString('hex'), row.id);
|
|
40
|
+
setIdByRawHash.set(Buffer.from(row.raw_hash).toString('hex'), row.id);
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
nameIdCache,
|
|
44
|
+
valueIdCache,
|
|
45
|
+
setIdByRawJsonHash,
|
|
46
|
+
setIdByRawHash,
|
|
47
|
+
setIdsProcessedThisRun: new Set(),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Threshold above which a `data:` URI is treated as a `blob_refs` payload
|
|
3
|
+
* rather than a `url_refs` URL. Shared between {@link ./populate-url-refs.ts}
|
|
4
|
+
* (which excludes `> LIMIT` data URIs from `url_refs`) and
|
|
5
|
+
* {@link ./populate-blob-refs.ts} (which routes them to `blob_refs`).
|
|
6
|
+
*
|
|
7
|
+
* The two populators MUST agree on this constant — a mismatch creates a
|
|
8
|
+
* routing hole where URIs of the disputed length land in neither table.
|
|
9
|
+
* Keeping the value here as a single-file export makes drift impossible.
|
|
10
|
+
*
|
|
11
|
+
* 512 was chosen because well-formed http(s) URLs virtually never exceed
|
|
12
|
+
* 512 characters in practice, while the smallest observed data URIs are
|
|
13
|
+
* ~600 bytes.
|
|
14
|
+
*/
|
|
15
|
+
export declare const DATA_URI_URL_REFS_LIMIT = 512;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Threshold above which a `data:` URI is treated as a `blob_refs` payload
|
|
3
|
+
* rather than a `url_refs` URL. Shared between {@link ./populate-url-refs.ts}
|
|
4
|
+
* (which excludes `> LIMIT` data URIs from `url_refs`) and
|
|
5
|
+
* {@link ./populate-blob-refs.ts} (which routes them to `blob_refs`).
|
|
6
|
+
*
|
|
7
|
+
* The two populators MUST agree on this constant — a mismatch creates a
|
|
8
|
+
* routing hole where URIs of the disputed length land in neither table.
|
|
9
|
+
* Keeping the value here as a single-file export makes drift impossible.
|
|
10
|
+
*
|
|
11
|
+
* 512 was chosen because well-formed http(s) URLs virtually never exceed
|
|
12
|
+
* 512 characters in practice, while the smallest observed data URIs are
|
|
13
|
+
* ~600 bytes.
|
|
14
|
+
*/
|
|
15
|
+
export const DATA_URI_URL_REFS_LIMIT = 512;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { DecodedDataUri } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Attempts to decode a `data:...` URI into its raw payload bytes.
|
|
4
|
+
*
|
|
5
|
+
* Supports the two encoding forms in RFC 2397:
|
|
6
|
+
*
|
|
7
|
+
* - `data:<mime>;base64,<base64-bytes>` — the base64 tail is decoded via
|
|
8
|
+
* `Buffer.from(..., 'base64')`.
|
|
9
|
+
* - `data:<mime>,<percent-encoded-bytes>` — the tail is percent-decoded
|
|
10
|
+
* via `decodeURIComponent(...)`, then re-encoded as UTF-8. This form is
|
|
11
|
+
* commonly used for SVG data URIs.
|
|
12
|
+
*
|
|
13
|
+
* Returns `null` on any parse / decode failure so the caller can skip the
|
|
14
|
+
* value without aborting the whole `blob_refs` population step. A single
|
|
15
|
+
* malformed data URI in a 470 K-row archive should not halt the migration
|
|
16
|
+
* — the raw `url` string is still preserved in the source `images` row.
|
|
17
|
+
* @param value - Raw column value; may or may not start with `data:`.
|
|
18
|
+
* @returns Decoded bytes, or `null` when the value isn't a data URI or
|
|
19
|
+
* can't be decoded.
|
|
20
|
+
*/
|
|
21
|
+
export declare function decodeDataUri(value: string): DecodedDataUri | null;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Attempts to decode a `data:...` URI into its raw payload bytes.
|
|
3
|
+
*
|
|
4
|
+
* Supports the two encoding forms in RFC 2397:
|
|
5
|
+
*
|
|
6
|
+
* - `data:<mime>;base64,<base64-bytes>` — the base64 tail is decoded via
|
|
7
|
+
* `Buffer.from(..., 'base64')`.
|
|
8
|
+
* - `data:<mime>,<percent-encoded-bytes>` — the tail is percent-decoded
|
|
9
|
+
* via `decodeURIComponent(...)`, then re-encoded as UTF-8. This form is
|
|
10
|
+
* commonly used for SVG data URIs.
|
|
11
|
+
*
|
|
12
|
+
* Returns `null` on any parse / decode failure so the caller can skip the
|
|
13
|
+
* value without aborting the whole `blob_refs` population step. A single
|
|
14
|
+
* malformed data URI in a 470 K-row archive should not halt the migration
|
|
15
|
+
* — the raw `url` string is still preserved in the source `images` row.
|
|
16
|
+
* @param value - Raw column value; may or may not start with `data:`.
|
|
17
|
+
* @returns Decoded bytes, or `null` when the value isn't a data URI or
|
|
18
|
+
* can't be decoded.
|
|
19
|
+
*/
|
|
20
|
+
export function decodeDataUri(value) {
|
|
21
|
+
if (!value.startsWith('data:')) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
const commaIndex = value.indexOf(',');
|
|
25
|
+
if (commaIndex === -1) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
const header = value.slice(5, commaIndex);
|
|
29
|
+
const payload = value.slice(commaIndex + 1);
|
|
30
|
+
try {
|
|
31
|
+
if (/;\s*base64$/i.test(header)) {
|
|
32
|
+
// `Buffer.from(..., 'base64')` silently strips characters outside
|
|
33
|
+
// the base64 alphabet — a malformed payload decodes to garbage
|
|
34
|
+
// instead of throwing. Validate the alphabet + padding shape
|
|
35
|
+
// first so callers can distinguish "successfully decoded" from
|
|
36
|
+
// "silently corrupted" and get the promised `null` on malformed
|
|
37
|
+
// input.
|
|
38
|
+
if (!isValidBase64(payload)) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
const bytes = Buffer.from(payload, 'base64');
|
|
42
|
+
return { bytes };
|
|
43
|
+
}
|
|
44
|
+
return { bytes: percentDecodeToBytes(payload) };
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Standard base64 alphabet + padding, plus one common URL-safe variant
|
|
52
|
+
* that occasionally appears in `data:` URIs even though RFC 2397 says
|
|
53
|
+
* only the standard alphabet. `-` / `_` are the URL-safe substitutes
|
|
54
|
+
* for `+` / `/`.
|
|
55
|
+
*/
|
|
56
|
+
const BASE64_ALPHABET_RE = /^[\w+/-]*={0,2}$/;
|
|
57
|
+
/**
|
|
58
|
+
* Validates whether a base64 payload is well-formed enough that
|
|
59
|
+
* `Buffer.from(payload, 'base64')` won't need to silently strip
|
|
60
|
+
* characters. Whitespace-tolerant (RFC 2045 permits internal
|
|
61
|
+
* whitespace in base64 line-wrapped output).
|
|
62
|
+
* @param payload - Base64 payload (everything after `,` in the data URI).
|
|
63
|
+
* @returns `true` when the payload contains only valid base64 characters
|
|
64
|
+
* + optional trailing padding.
|
|
65
|
+
*/
|
|
66
|
+
function isValidBase64(payload) {
|
|
67
|
+
const stripped = payload.replaceAll(/\s+/g, '');
|
|
68
|
+
if (stripped === '') {
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
if (!BASE64_ALPHABET_RE.test(stripped)) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
// base64 chunks group by 4 characters — a well-formed payload has
|
|
75
|
+
// length ≡ 0 (mod 4) once padding is applied. Padding-less trailing
|
|
76
|
+
// chunks of length 2 or 3 are also accepted (Node's decoder tolerates
|
|
77
|
+
// missing `=`), but length 1 or a padding-only chunk is malformed.
|
|
78
|
+
const remainder = stripped.length % 4;
|
|
79
|
+
if (remainder === 1) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Percent-decodes a data-URI payload byte-by-byte, avoiding the round
|
|
86
|
+
* through `decodeURIComponent` → UTF-8 re-encode that mangles arbitrary
|
|
87
|
+
* binary payloads (e.g. a `%FF` byte becomes a JS string of code
|
|
88
|
+
* point U+00FF, then re-encodes to `[0xC3, 0xBF]` — the byte value
|
|
89
|
+
* changes). RFC 2397's non-base64 form treats the payload as octets,
|
|
90
|
+
* not as a UTF-8 string, so an octet-preserving decode is the correct
|
|
91
|
+
* inverse.
|
|
92
|
+
* @param payload - Raw payload text (everything after the `,`).
|
|
93
|
+
* @returns Payload bytes.
|
|
94
|
+
* @throws {URIError} If a `%` escape is truncated or not two hex
|
|
95
|
+
* digits; the caller's try/catch maps this to a `null` return.
|
|
96
|
+
*/
|
|
97
|
+
function percentDecodeToBytes(payload) {
|
|
98
|
+
const chunks = [];
|
|
99
|
+
let i = 0;
|
|
100
|
+
while (i < payload.length) {
|
|
101
|
+
const ch = payload.codePointAt(i);
|
|
102
|
+
if (ch === 0x25 /* % */) {
|
|
103
|
+
if (i + 2 >= payload.length) {
|
|
104
|
+
throw new URIError('truncated % escape');
|
|
105
|
+
}
|
|
106
|
+
const hex = payload.slice(i + 1, i + 3);
|
|
107
|
+
if (!/^[\da-f]{2}$/i.test(hex)) {
|
|
108
|
+
throw new URIError('invalid % escape');
|
|
109
|
+
}
|
|
110
|
+
chunks.push(Buffer.from(hex, 'hex'));
|
|
111
|
+
i += 3;
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
if (ch > 127 /* 0x7F, ASCII high-bit boundary */) {
|
|
115
|
+
// A non-ASCII code point in a percent-encoded payload is
|
|
116
|
+
// unusual (browsers percent-encode outbound), but WHATWG
|
|
117
|
+
// tolerates it — encode as UTF-8 to preserve the character.
|
|
118
|
+
chunks.push(Buffer.from(payload[i], 'utf8'));
|
|
119
|
+
i += 1;
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
chunks.push(Buffer.from([ch]));
|
|
123
|
+
i += 1;
|
|
124
|
+
}
|
|
125
|
+
return Buffer.concat(chunks);
|
|
126
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { DecomposedHeaderSet } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Parses one raw `responseHeaders` JSON string and produces the derived
|
|
4
|
+
* data shape required to insert into `header_sets`, `header_set_entries`,
|
|
5
|
+
* and `header_flags`.
|
|
6
|
+
*
|
|
7
|
+
* Behaviour:
|
|
8
|
+
*
|
|
9
|
+
* - `null` / `""` / `"null"` / `"{}"` / non-object JSON → returns `null`.
|
|
10
|
+
* The caller sets `header_set_id = null` on the referring row.
|
|
11
|
+
* - Multiple values per header name (JSON arrays, e.g.
|
|
12
|
+
* `{ "set-cookie": ["a=1", "b=2"] }`) become multiple
|
|
13
|
+
* {@link HeaderEntry} rows with `occurrence` ordinals 1, 2, ... The
|
|
14
|
+
* composite PK on `header_set_entries` `(header_set_id, name_id,
|
|
15
|
+
* occurrence)` guarantees no truncation.
|
|
16
|
+
* - Names are lower-cased. Values are trimmed of whitespace only in the
|
|
17
|
+
* sorted-hash construction; the raw value is preserved verbatim in
|
|
18
|
+
* the emitted `HeaderEntry.value` (and hence in `header_value_refs`).
|
|
19
|
+
* Trimming inside hash construction lets `content-type: text/html`
|
|
20
|
+
* and `content-type: text/html ` dedup to one stable set.
|
|
21
|
+
* - Sort order for hashing is `(name, occurrence)` in binary form —
|
|
22
|
+
* deterministic regardless of the input JSON's insertion order or
|
|
23
|
+
* how the JSON serializer arranged keys.
|
|
24
|
+
* @param rawJson - The raw JSON string exactly as stored in
|
|
25
|
+
* `pages.responseHeaders` / `resources.responseHeaders`.
|
|
26
|
+
* @returns Decomposed shape, or `null` when the row has no meaningful
|
|
27
|
+
* header set.
|
|
28
|
+
*/
|
|
29
|
+
export declare function decomposeHeaderSet(rawJson: string | null): DecomposedHeaderSet | null;
|