@nitpicker/crawler 0.15.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/lib/archive/archive.d.ts +52 -1
  2. package/lib/archive/archive.js +68 -0
  3. package/lib/archive/create-adjunct-tables.d.ts +3 -0
  4. package/lib/archive/create-adjunct-tables.js +43 -0
  5. package/lib/archive/create-entity-tables.js +10 -0
  6. package/lib/archive/database.d.ts +40 -1
  7. package/lib/archive/database.js +54 -0
  8. package/lib/archive/db-ops/config/get-config.js +1 -0
  9. package/lib/archive/db-ops/dedupe-cap/accumulate-dedupe-cap-rejected-count.d.ts +18 -0
  10. package/lib/archive/db-ops/dedupe-cap/accumulate-dedupe-cap-rejected-count.js +23 -0
  11. package/lib/archive/db-ops/dedupe-cap/finalize-dedupe-cap-event.d.ts +12 -0
  12. package/lib/archive/db-ops/dedupe-cap/finalize-dedupe-cap-event.js +15 -0
  13. package/lib/archive/db-ops/dedupe-cap/insert-dedupe-cap-event.d.ts +14 -0
  14. package/lib/archive/db-ops/dedupe-cap/insert-dedupe-cap-event.js +30 -0
  15. package/lib/archive/db-ops/dedupe-cap/list-dedupe-cap-shape-keys.d.ts +21 -0
  16. package/lib/archive/db-ops/dedupe-cap/list-dedupe-cap-shape-keys.js +27 -0
  17. package/lib/archive/db-ops/inventory/record-inventory-run.js +1 -0
  18. package/lib/archive/db-ops/lifecycle/init.d.ts +4 -2
  19. package/lib/archive/db-ops/lifecycle/init.js +12 -2
  20. package/lib/archive/db-ops/pages/write/insert-inventory-content-items.d.ts +38 -0
  21. package/lib/archive/db-ops/pages/write/insert-inventory-content-items.js +59 -0
  22. package/lib/archive/db-ops/pages/write/insert-inventory-seeds.d.ts +5 -6
  23. package/lib/archive/db-ops/pages/write/insert-inventory-seeds.js +17 -41
  24. package/lib/archive/db-ops/pages/write/insert-inventory-skipped-pages.d.ts +42 -0
  25. package/lib/archive/db-ops/pages/write/insert-inventory-skipped-pages.js +56 -0
  26. package/lib/archive/migrate-content-items-dedupe-cap-event-id.d.ts +41 -0
  27. package/lib/archive/migrate-content-items-dedupe-cap-event-id.js +51 -0
  28. package/lib/archive/migrate-entity-tables.d.ts +10 -0
  29. package/lib/archive/migrate-entity-tables.js +10 -0
  30. package/lib/archive/migrate-inventory-runs-exclude-skipped.d.ts +20 -0
  31. package/lib/archive/migrate-inventory-runs-exclude-skipped.js +33 -0
  32. package/lib/archive/populate-entity-tables/test-utils/setup-entities-db.d.ts +7 -0
  33. package/lib/archive/populate-entity-tables/test-utils/setup-entities-db.js +9 -0
  34. package/lib/archive/types.d.ts +16 -0
  35. package/lib/classify-error-kind.d.ts +1 -0
  36. package/lib/classify-error-kind.js +14 -0
  37. package/lib/crawler/assert-chrome-installed.d.ts +24 -0
  38. package/lib/crawler/assert-chrome-installed.js +43 -0
  39. package/lib/crawler/crawler.d.ts +12 -0
  40. package/lib/crawler/crawler.js +239 -29
  41. package/lib/crawler/decode-auth-credential.d.ts +29 -0
  42. package/lib/crawler/decode-auth-credential.js +39 -0
  43. package/lib/crawler/dedupe/compute-meta-signature.d.ts +30 -0
  44. package/lib/crawler/dedupe/compute-meta-signature.js +0 -0
  45. package/lib/crawler/dedupe/compute-shape-key.d.ts +37 -0
  46. package/lib/crawler/dedupe/compute-shape-key.js +56 -0
  47. package/lib/crawler/dedupe/dedupe-cap-tracker.d.ts +84 -0
  48. package/lib/crawler/dedupe/dedupe-cap-tracker.js +185 -0
  49. package/lib/crawler/dedupe/is-predicted-content-duplicate.d.ts +24 -0
  50. package/lib/crawler/dedupe/is-predicted-content-duplicate.js +26 -0
  51. package/lib/crawler/dedupe/is-shape-capped.d.ts +10 -0
  52. package/lib/crawler/dedupe/is-shape-capped.js +12 -0
  53. package/lib/crawler/dedupe/resolve-og-url-mismatch.d.ts +31 -0
  54. package/lib/crawler/dedupe/resolve-og-url-mismatch.js +40 -0
  55. package/lib/crawler/dedupe/types.d.ts +42 -0
  56. package/lib/crawler/dedupe/types.js +1 -0
  57. package/lib/crawler/fetch-destination.js +14 -2
  58. package/lib/crawler/generate-predicted-urls.d.ts +12 -0
  59. package/lib/crawler/generate-predicted-urls.js +33 -2
  60. package/lib/crawler/is-puppeteer-fallback-candidate.js +3 -0
  61. package/lib/crawler/types.d.ts +38 -0
  62. package/lib/crawler-orchestrator.d.ts +39 -10
  63. package/lib/crawler-orchestrator.js +187 -23
  64. package/lib/crawler.d.ts +2 -0
  65. package/lib/crawler.js +2 -0
  66. package/lib/permanent-error-kinds.d.ts +9 -4
  67. package/lib/permanent-error-kinds.js +10 -4
  68. package/lib/types.d.ts +4 -1
  69. package/package.json +3 -3
@@ -6,11 +6,12 @@
6
6
  * Used by `resetFailedPages` to exclude pages whose latest recorded error
7
7
  * falls in this set, so `--retry-failed` actually converges: without the
8
8
  * exclusion, NXDOMAIN / TLS mismatch / `ERR_BLOCKED_BY_CLIENT` /
9
- * `ECONNREFUSED` / HTTP parse-error pages would be reset to pending on every
10
- * iteration, the crawler would re-attempt them, they would fail again the
11
- * same way, and the retry-target count would stay constant forever.
9
+ * `ECONNREFUSED` / HTTP parse-error / redirect-loop pages would be reset to
10
+ * pending on every iteration, the crawler would re-attempt them, they would
11
+ * fail again the same way, and the retry-target count would stay constant
12
+ * forever.
12
13
  *
13
- * Why these five and not others:
14
+ * Why these six and not others:
14
15
  * - **dns** — `ENOTFOUND` / `ERR_NAME_NOT_RESOLVED` are authoritative DNS
15
16
  * answers; the host is gone (or never existed). EAI_AGAIN is split out as
16
17
  * `dns-transient` precisely so it is NOT in this set.
@@ -27,6 +28,10 @@
27
28
  * the listener; either no process is listening on the port or its accept
28
29
  * queue rejected the connection. Either way the answer is final until the
29
30
  * server operator intervenes.
31
+ * - **redirect-loop** — `Maximum number of redirects exceeded` /
32
+ * `ERR_TOO_MANY_REDIRECTS` means the site's own redirect chain never
33
+ * terminates; the exact same chain is served on every future fetch until
34
+ * the site operator fixes it.
30
35
  *
31
36
  * Notably absent (intentionally retryable):
32
37
  * - `connection-reset` / `connection-timeout` — could be middlebox or
@@ -45,4 +50,5 @@ export const PERMANENT_ERROR_KINDS = new Set([
45
50
  'client-blocked',
46
51
  'parse-error',
47
52
  'connection-refused',
53
+ 'redirect-loop',
48
54
  ]);
package/lib/types.d.ts CHANGED
@@ -18,6 +18,8 @@ export interface InventoryRunAggregates {
18
18
  nonHtmlCount: number;
19
19
  /** URLs dropped because they fell outside the archived scope. Stored as `scope_skipped`. */
20
20
  outOfScope: number;
21
+ /** Novel in-scope URLs recorded as terminal skipped pages (`is_skipped=1`, `skip_reason='excluded'`) instead of being imported, because they matched the effective `excludes` / `excludeUrls` config — the same inputs the scrape phase's fetch-time `shouldSkipUrl` gate uses. Stored as `exclude_skipped`. */
22
+ excludeSkipped: number;
21
23
  /**
22
24
  * SHA-256 hex digest of the source `.txt`, **pre-computed by the caller**
23
25
  * (typically the CLI's `inventoryCrawl`). Stored verbatim as
@@ -66,6 +68,7 @@ export interface InventoryRunAggregates {
66
68
  * | `local-network` | **yes** | no | local machine's network is unreachable / changed (WiFi, sleep, ICMP-unreachable, …) |
67
69
  * | `parse-error` | mostly persistent | no | HTTP response could not be parsed (proxy, garbage, MITM) |
68
70
  * | `client-blocked` | persistent (per browser) | no | Chromium-side `ERR_BLOCKED_BY_*` family — the browser actively refused the request (ad/tracker heuristics, CSP, CORP, administrator block list, …) |
71
+ * | `redirect-loop` | no | no | the redirect chain exceeded `follow-redirects`' `maxRedirects` limit — the site's own redirect configuration never converges |
69
72
  * | `protocol` | yes | no | puppeteer protocol layer (frame detached, target closed, …) |
70
73
  * | `timeout` | yes | no | puppeteer navigation timeout or HEAD pre-flight race timeout (`Timeout: <url>`) |
71
74
  * | `unknown` | unknown | no | catch-all for messages no matcher recognised |
@@ -90,7 +93,7 @@ export interface InventoryRunAggregates {
90
93
  * entry), or a recoverable URL never reaching the puppeteer fallback (no
91
94
  * PUPPETEER_FALLBACK entry).
92
95
  */
93
- export type ErrorKind = 'dns' | 'dns-transient' | 'connection-refused' | 'connection-reset' | 'connection-timeout' | 'tls' | 'local-network' | 'parse-error' | 'client-blocked' | 'timeout' | 'protocol' | 'unknown';
96
+ export type ErrorKind = 'dns' | 'dns-transient' | 'connection-refused' | 'connection-reset' | 'connection-timeout' | 'tls' | 'local-network' | 'parse-error' | 'client-blocked' | 'redirect-loop' | 'timeout' | 'protocol' | 'unknown';
94
97
  /**
95
98
  * Event map for the `CrawlerOrchestrator` class.
96
99
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nitpicker/crawler",
3
- "version": "0.15.0",
3
+ "version": "0.17.0",
4
4
  "description": "Web crawler engine with headless browser rendering and archive storage",
5
5
  "author": "D-ZERO",
6
6
  "license": "Apache-2.0",
@@ -39,7 +39,7 @@
39
39
  "libsql": "0.5.29",
40
40
  "puppeteer": "25.3.0",
41
41
  "robots-parser": "3.0.1",
42
- "tar": "7.5.20"
42
+ "tar": "7.5.21"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@types/debug": "4.1.13",
@@ -48,5 +48,5 @@
48
48
  "@types/tar": "7.0.87",
49
49
  "@types/unzipper": "0.10.11"
50
50
  },
51
- "gitHead": "d1485df6e43375c6a44edfe07a0293fd39d7810d"
51
+ "gitHead": "2cdef7cbb4da489270e0f1c9ec2e8166b3d84e91"
52
52
  }