universal-parcel-scraper 0.894.0-main.4792 → 0.895.1-main.4797

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 (48) hide show
  1. package/README.md +2 -2
  2. package/data/catalog.json +17 -8
  3. package/data/coverage-summary.json +1 -1
  4. package/dist/browser/scraper.js +17 -8
  5. package/dist/carriers/ait-worldwide/adapter.d.ts +2 -0
  6. package/dist/carriers/ait-worldwide/adapter.js +10 -6
  7. package/dist/carriers/ait-worldwide/carrier.json +4 -2
  8. package/dist/carriers/celeritas/adapter.d.ts +2 -0
  9. package/dist/carriers/celeritas/adapter.js +10 -6
  10. package/dist/carriers/celeritas/carrier.json +4 -2
  11. package/dist/carriers/delnext/adapter.d.ts +2 -0
  12. package/dist/carriers/delnext/adapter.js +10 -6
  13. package/dist/carriers/delnext/carrier.json +4 -2
  14. package/dist/carriers/four-px/status.js +4 -0
  15. package/dist/carriers/four-px/statuses.json +26 -0
  16. package/dist/carriers/hitch/adapter.d.ts +2 -0
  17. package/dist/carriers/hitch/adapter.js +10 -6
  18. package/dist/carriers/hitch/carrier.json +4 -2
  19. package/dist/carriers/mrl-global/adapter.d.ts +2 -0
  20. package/dist/carriers/mrl-global/adapter.js +8 -5
  21. package/dist/carriers/mrl-global/carrier.json +4 -2
  22. package/dist/carriers/pbt/adapter.d.ts +2 -0
  23. package/dist/carriers/pbt/adapter.js +10 -6
  24. package/dist/carriers/pbt/carrier.json +4 -2
  25. package/dist/carriers/pro-carrier/adapter.d.ts +2 -0
  26. package/dist/carriers/pro-carrier/adapter.js +10 -6
  27. package/dist/carriers/pro-carrier/carrier.json +4 -2
  28. package/dist/carriers/swiss-post/adapter.js +8 -0
  29. package/dist/carriers/trendyol-express/adapter.d.ts +13 -0
  30. package/dist/carriers/trendyol-express/adapter.js +26 -0
  31. package/dist/carriers/trendyol-express/carrier.json +33 -7
  32. package/dist/carriers/trendyol-express/parser.d.ts +7 -0
  33. package/dist/carriers/trendyol-express/parser.js +92 -0
  34. package/dist/carriers/trendyol-express/status.d.ts +4 -0
  35. package/dist/carriers/trendyol-express/status.js +13 -0
  36. package/dist/carriers/wanbexpress/status.d.ts +2 -2
  37. package/dist/carriers/wanbexpress/status.js +11 -2
  38. package/dist/carriers/wanbexpress/statuses.json +14 -0
  39. package/dist/core/catalog/statusMaps.js +2 -1
  40. package/dist/core/transport/trawl.d.ts +2 -0
  41. package/dist/core/transport/trawlPage.d.ts +12 -0
  42. package/dist/core/transport/trawlPage.js +30 -0
  43. package/dist/data/catalog.json +17 -8
  44. package/dist/generated/catalog.d.ts +10 -1
  45. package/dist/generated/catalog.js +17 -8
  46. package/dist/generated/registry.js +3 -1
  47. package/dist/server/openapi.json +1 -1
  48. package/package.json +1 -1
package/README.md CHANGED
@@ -13,7 +13,7 @@ The engine behind [Peek](https://peektracker.com) ([GitHub](https://github.com/p
13
13
  [![License: Apache-2.0](https://img.shields.io/badge/core-Apache--2.0-blue.svg)](LICENSE)
14
14
 
15
15
  <!-- GENERATED:summary -->
16
- **3,500+ carriers** through **671 dedicated adapters** and **5 universal fallbacks**
16
+ **3,500+ carriers** through **672 dedicated adapters** and **5 universal fallbacks**
17
17
 
18
18
  <sub>1201 catalog entries · 154 countries represented</sub>
19
19
  <!-- /GENERATED:summary -->
@@ -163,7 +163,7 @@ the command line's `track --source ParcelsApp` does the same.
163
163
  <!-- GENERATED:stages -->
164
164
  <img src="docs/assets/stages.svg" alt="DHL: Die Sendung wurde in das Zustellfahrzeug geladen.; Mondial Relay: En cours de livraison; Correios Brazil: Objeto saiu para entrega ao destinatário; Correos Express: EN REPARTO; Yamato Transport: 配達中; La Poste / Colissimo: DISTOU. All are filed under out_for_delivery." width="760">
165
165
 
166
- The carrier folders record 18,036 such statuses, each filed under one stage.
166
+ The carrier folders record 18,041 such statuses, each filed under one stage.
167
167
  <!-- /GENERATED:stages -->
168
168
 
169
169
  Wording nobody recorded yet goes through a classifier that reads seven European languages.
package/data/catalog.json CHANGED
@@ -6815,7 +6815,8 @@
6815
6815
  "mode": "automatic",
6816
6816
  "adapter": "ait-worldwide",
6817
6817
  "recognitionRank": 625,
6818
- "localClocks": true
6818
+ "localClocks": true,
6819
+ "browser": true
6819
6820
  },
6820
6821
  "canaryUrl": "https://fastrak.aitworldwide.com/",
6821
6822
  "trackingUrlTemplate": "https://fastrak.aitworldwide.com/?trackingnumber={trackingNumber}",
@@ -11098,7 +11099,8 @@
11098
11099
  "mode": "automatic",
11099
11100
  "adapter": "celeritas",
11100
11101
  "recognitionRank": 996,
11101
- "localClocks": true
11102
+ "localClocks": true,
11103
+ "browser": true
11102
11104
  },
11103
11105
  "canaryUrl": "https://celeritastransporte.com/seguimiento-paquete-pedidos/",
11104
11106
  "trackingUrlTemplate": "https://celeritastransporte.com/seguimiento-paquete-pedidos/?refer={trackingNumber}&lang=es",
@@ -14336,7 +14338,8 @@
14336
14338
  "mode": "automatic",
14337
14339
  "adapter": "delnext",
14338
14340
  "recognitionRank": 889,
14339
- "localClocks": true
14341
+ "localClocks": true,
14342
+ "browser": true
14340
14343
  },
14341
14344
  "canaryUrl": "https://www.delnext.com/PT/track_your_parcel",
14342
14345
  "trackingUrlTemplate": "https://www.delnext.com/PT/track_your_parcel?tracking_code={trackingNumber}",
@@ -22459,7 +22462,8 @@
22459
22462
  "mode": "automatic",
22460
22463
  "adapter": "hitch",
22461
22464
  "recognitionRank": 117,
22462
- "localClocks": true
22465
+ "localClocks": true,
22466
+ "browser": true
22463
22467
  },
22464
22468
  "canaryUrl": "https://hitch.com.ph/",
22465
22469
  "trackingUrlTemplate": "https://hitch.com.ph/tracking?no={trackingNumber}",
@@ -29407,7 +29411,8 @@
29407
29411
  "tracking": {
29408
29412
  "mode": "automatic",
29409
29413
  "adapter": "mrl-global",
29410
- "localClocks": true
29414
+ "localClocks": true,
29415
+ "browser": true
29411
29416
  },
29412
29417
  "canaryUrl": "https://www.mrlglobal.com/tracking/",
29413
29418
  "trackingUrlTemplate": "https://www.mrlglobal.com/tracking/?connoteno={trackingNumber}",
@@ -32442,7 +32447,8 @@
32442
32447
  "mode": "automatic",
32443
32448
  "adapter": "pbt",
32444
32449
  "recognitionRank": 623,
32445
- "localClocks": true
32450
+ "localClocks": true,
32451
+ "browser": true
32446
32452
  },
32447
32453
  "canaryUrl": "https://www.pbt.nz/",
32448
32454
  "trackingUrlTemplate": "https://www.pbt.nz/tracking-result/?consignmentNumber={trackingNumber}",
@@ -34487,7 +34493,8 @@
34487
34493
  "mode": "automatic",
34488
34494
  "adapter": "pro-carrier",
34489
34495
  "recognitionRank": 843,
34490
- "localClocks": true
34496
+ "localClocks": true,
34497
+ "browser": true
34491
34498
  },
34492
34499
  "canaryUrl": "https://tracking.weareprocarrier.com/",
34493
34500
  "trackingUrlTemplate": "https://tracking.weareprocarrier.com/?tn={trackingNumber}",
@@ -42369,7 +42376,9 @@
42369
42376
  "timezone": "Europe/Istanbul",
42370
42377
  "tracking": {
42371
42378
  "mode": "automatic",
42372
- "adapter": "universal"
42379
+ "adapter": "trendyol-express",
42380
+ "localClocks": true,
42381
+ "browser": true
42373
42382
  },
42374
42383
  "canaryUrl": "https://trendyolexpress.com/",
42375
42384
  "trackingUrlTemplate": "https://kargotakip.trendyol.com/?orderNumber={trackingNumber}",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "catalog": 1201,
3
- "activeAdapters": 671,
3
+ "activeAdapters": 672,
4
4
  "countries": 154,
5
5
  "referenceCarriers": 100,
6
6
  "comparison": {
@@ -5713,7 +5713,8 @@ var at = {
5713
5713
  mode: "automatic",
5714
5714
  adapter: "ait-worldwide",
5715
5715
  recognitionRank: 625,
5716
- localClocks: !0
5716
+ localClocks: !0,
5717
+ browser: !0
5717
5718
  },
5718
5719
  canaryUrl: "https://fastrak.aitworldwide.com/",
5719
5720
  trackingUrlTemplate: "https://fastrak.aitworldwide.com/?trackingnumber={trackingNumber}",
@@ -8889,7 +8890,8 @@ var at = {
8889
8890
  mode: "automatic",
8890
8891
  adapter: "celeritas",
8891
8892
  recognitionRank: 996,
8892
- localClocks: !0
8893
+ localClocks: !0,
8894
+ browser: !0
8893
8895
  },
8894
8896
  canaryUrl: "https://celeritastransporte.com/seguimiento-paquete-pedidos/",
8895
8897
  trackingUrlTemplate: "https://celeritastransporte.com/seguimiento-paquete-pedidos/?refer={trackingNumber}&lang=es",
@@ -11321,7 +11323,8 @@ var at = {
11321
11323
  mode: "automatic",
11322
11324
  adapter: "delnext",
11323
11325
  recognitionRank: 889,
11324
- localClocks: !0
11326
+ localClocks: !0,
11327
+ browser: !0
11325
11328
  },
11326
11329
  canaryUrl: "https://www.delnext.com/PT/track_your_parcel",
11327
11330
  trackingUrlTemplate: "https://www.delnext.com/PT/track_your_parcel?tracking_code={trackingNumber}",
@@ -17395,7 +17398,8 @@ var at = {
17395
17398
  mode: "automatic",
17396
17399
  adapter: "hitch",
17397
17400
  recognitionRank: 117,
17398
- localClocks: !0
17401
+ localClocks: !0,
17402
+ browser: !0
17399
17403
  },
17400
17404
  canaryUrl: "https://hitch.com.ph/",
17401
17405
  trackingUrlTemplate: "https://hitch.com.ph/tracking?no={trackingNumber}",
@@ -22652,7 +22656,8 @@ var at = {
22652
22656
  tracking: {
22653
22657
  mode: "automatic",
22654
22658
  adapter: "mrl-global",
22655
- localClocks: !0
22659
+ localClocks: !0,
22660
+ browser: !0
22656
22661
  },
22657
22662
  canaryUrl: "https://www.mrlglobal.com/tracking/",
22658
22663
  trackingUrlTemplate: "https://www.mrlglobal.com/tracking/?connoteno={trackingNumber}",
@@ -24943,7 +24948,8 @@ var at = {
24943
24948
  mode: "automatic",
24944
24949
  adapter: "pbt",
24945
24950
  recognitionRank: 623,
24946
- localClocks: !0
24951
+ localClocks: !0,
24952
+ browser: !0
24947
24953
  },
24948
24954
  canaryUrl: "https://www.pbt.nz/",
24949
24955
  trackingUrlTemplate: "https://www.pbt.nz/tracking-result/?consignmentNumber={trackingNumber}",
@@ -26460,7 +26466,8 @@ var at = {
26460
26466
  mode: "automatic",
26461
26467
  adapter: "pro-carrier",
26462
26468
  recognitionRank: 843,
26463
- localClocks: !0
26469
+ localClocks: !0,
26470
+ browser: !0
26464
26471
  },
26465
26472
  canaryUrl: "https://tracking.weareprocarrier.com/",
26466
26473
  trackingUrlTemplate: "https://tracking.weareprocarrier.com/?tn={trackingNumber}",
@@ -32346,7 +32353,9 @@ var at = {
32346
32353
  timezone: "Europe/Istanbul",
32347
32354
  tracking: {
32348
32355
  mode: "automatic",
32349
- adapter: "universal"
32356
+ adapter: "trendyol-express",
32357
+ localClocks: !0,
32358
+ browser: !0
32350
32359
  },
32351
32360
  canaryUrl: "https://trendyolexpress.com/",
32352
32361
  trackingUrlTemplate: "https://kargotakip.trendyol.com/?orderNumber={trackingNumber}",
@@ -1,6 +1,7 @@
1
1
  import { type AdapterFactory, type TrackingContext } from '../../core/adapter/index.js';
2
2
  import type { CarrierResult } from '../../core/result/index.js';
3
3
  import { type StepRecorder } from '../../core/telemetry/index.js';
4
+ import type { TrawlClient } from '../../core/transport/trawl.js';
4
5
  export { FASTRAK } from './parser.js';
5
6
  /** FasTrak's address for one whole bill number, as AIT's tracking box opens it. */
6
7
  export declare function aitLookupUrl(number: string): string;
@@ -10,6 +11,7 @@ export declare class AitTracker {
10
11
  fetcher?: typeof fetch;
11
12
  recorder?: StepRecorder;
12
13
  userAgent?: string;
14
+ trawl?: TrawlClient | null;
13
15
  });
14
16
  fetch(raw: string, context?: TrackingContext): Promise<CarrierResult>;
15
17
  }
@@ -4,6 +4,7 @@ import { runSteps } from '../../core/runner/index.js';
4
4
  import { firstAttemptMs, networkRetryStep } from '../../core/runner/networkRetry.js';
5
5
  import { NOOP_RECORDER } from '../../core/telemetry/index.js';
6
6
  import { decodeText, fetchBounded, userAgentOf } from '../../core/transport/index.js';
7
+ import { trawlPageStep } from '../../core/transport/trawlPage.js';
7
8
  import { AIT_MAX_BYTES, FASTRAK, normalizeAitNumber, parseAit, PROVIDER } from './parser.js';
8
9
  export { FASTRAK } from './parser.js';
9
10
  const REDIRECTS = [301, 302, 303, 307, 308];
@@ -32,18 +33,21 @@ export class AitTracker {
32
33
  };
33
34
  // A request that fails to reach FasTrak, or hangs, gets one more try: the
34
35
  // first gets half of the budget, so the retry fits in the rest.
35
- return runSteps({ carrier: 'ait-worldwide', budgetMs: context.budgetMs ?? 15_000, signal: context.signal,
36
+ return runSteps({ carrier: 'ait-worldwide', budgetMs: context.budgetMs ?? (this.options.trawl ? 60_000 : 15_000), signal: context.signal,
36
37
  recorder: this.options.recorder ?? NOOP_RECORDER }, [
37
- { id: 'direct', run: ({ signal, remainingMs }) => read(signal, firstAttemptMs(remainingMs)) },
38
- networkRetryStep(({ signal, remainingMs }) => read(signal, remainingMs)),
38
+ { id: 'direct', run: ({ signal, remainingMs }) => read(signal, firstAttemptMs(this.options.trawl ? Math.min(15_000, remainingMs) : remainingMs)) },
39
+ networkRetryStep(({ signal, remainingMs }) => read(signal, this.options.trawl ? Math.min(7_500, remainingMs) : remainingMs)),
40
+ trawlPageStep({ ...this.options, provider: PROVIDER, url: aitLookupUrl(number), maxBytes: AIT_MAX_BYTES,
41
+ parse: html => parseAit(html, number) }),
39
42
  ]);
40
43
  }
41
44
  }
42
45
  export const adapter = (environment) => {
43
- const tracker = new AitTracker({ fetcher: environment.fetcher, recorder: environment.recorder, userAgent: environment.userAgent });
46
+ const tracker = new AitTracker({ fetcher: environment.fetcher, recorder: environment.recorder, userAgent: environment.userAgent, trawl: environment.trawl });
47
+ const http = new AitTracker({ fetcher: environment.fetcher, recorder: environment.recorder, userAgent: environment.userAgent });
44
48
  return {
45
- id: 'ait-worldwide', recordsSteps: true, steps: ['direct', 'retry'],
49
+ id: 'ait-worldwide', recordsSteps: true, steps: ['direct', 'retry', 'trawl'],
46
50
  track: (input, context) => tracker.fetch(input.number, context),
47
- recognize: (number, context) => recognizeFromLookup(() => tracker.fetch(number, context), () => accepted(() => normalizeAitNumber(number))),
51
+ recognize: (number, context) => recognizeFromLookup(() => http.fetch(number, context), () => accepted(() => normalizeAitNumber(number))),
48
52
  };
49
53
  };
@@ -20,12 +20,14 @@
20
20
  "adapter": "ait-worldwide",
21
21
  "steps": [
22
22
  "direct",
23
- "retry"
23
+ "retry",
24
+ "trawl"
24
25
  ],
25
26
  "recognition": {
26
27
  "rank": 625
27
28
  },
28
- "localClocks": true
29
+ "localClocks": true,
30
+ "browser": true
29
31
  },
30
32
  "capabilities": [
31
33
  "history",
@@ -1,6 +1,7 @@
1
1
  import { type AdapterFactory, type TrackingContext } from '../../core/adapter/index.js';
2
2
  import type { CarrierResult } from '../../core/result/index.js';
3
3
  import { type StepRecorder } from '../../core/telemetry/index.js';
4
+ import type { TrawlClient } from '../../core/transport/trawl.js';
4
5
  export declare const CELERITAS_ENDPOINT = "https://celeritastransporte.com/seguimiento-paquete-pedidos/";
5
6
  export declare class CeleritasTracker {
6
7
  private readonly options;
@@ -8,6 +9,7 @@ export declare class CeleritasTracker {
8
9
  fetcher?: typeof fetch;
9
10
  recorder?: StepRecorder;
10
11
  userAgent?: string;
12
+ trawl?: TrawlClient | null;
11
13
  });
12
14
  fetch(raw: string, context?: TrackingContext): Promise<CarrierResult>;
13
15
  }
@@ -4,6 +4,7 @@ import { runSteps } from '../../core/runner/index.js';
4
4
  import { firstAttemptMs, networkRetryStep } from '../../core/runner/networkRetry.js';
5
5
  import { NOOP_RECORDER } from '../../core/telemetry/index.js';
6
6
  import { decodeText, fetchBounded, userAgentOf } from '../../core/transport/index.js';
7
+ import { trawlPageStep } from '../../core/transport/trawlPage.js';
7
8
  import { CELERITAS_MAX_BYTES, CELERITAS_ORIGIN, normalizeCeleritasNumber, parseCeleritas, PROVIDER } from './parser.js';
8
9
  // The tracking page, which renders a shipment for the reference in `refer`:
9
10
  // the address Celeritas's own notifications link to. The form on the page
@@ -39,18 +40,21 @@ export class CeleritasTracker {
39
40
  // A request that fails to reach Celeritas, or hangs, gets one more try: the
40
41
  // first gets half of the budget, so the retry fits in the rest. An HTTP
41
42
  // status, a rate limit included, is never sent again.
42
- return runSteps({ carrier: 'celeritas', budgetMs: context.budgetMs ?? 15_000, signal: context.signal,
43
+ return runSteps({ carrier: 'celeritas', budgetMs: context.budgetMs ?? (this.options.trawl ? 60_000 : 15_000), signal: context.signal,
43
44
  recorder: this.options.recorder ?? NOOP_RECORDER }, [
44
- { id: 'direct', run: ({ signal, remainingMs }) => read(signal, firstAttemptMs(remainingMs)) },
45
- networkRetryStep(({ signal, remainingMs }) => read(signal, remainingMs)),
45
+ { id: 'direct', run: ({ signal, remainingMs }) => read(signal, firstAttemptMs(this.options.trawl ? Math.min(15_000, remainingMs) : remainingMs)) },
46
+ networkRetryStep(({ signal, remainingMs }) => read(signal, this.options.trawl ? Math.min(7_500, remainingMs) : remainingMs)),
47
+ trawlPageStep({ ...this.options, provider: PROVIDER, url, maxBytes: CELERITAS_MAX_BYTES,
48
+ parse: html => parseCeleritas(html, number) }),
46
49
  ]);
47
50
  }
48
51
  }
49
52
  export const adapter = (environment) => {
50
- const tracker = new CeleritasTracker({ fetcher: environment.fetcher, recorder: environment.recorder, userAgent: environment.userAgent });
53
+ const tracker = new CeleritasTracker({ fetcher: environment.fetcher, recorder: environment.recorder, userAgent: environment.userAgent, trawl: environment.trawl });
54
+ const http = new CeleritasTracker({ fetcher: environment.fetcher, recorder: environment.recorder, userAgent: environment.userAgent });
51
55
  return {
52
- id: 'celeritas', recordsSteps: true, steps: ['direct', 'retry'],
56
+ id: 'celeritas', recordsSteps: true, steps: ['direct', 'retry', 'trawl'],
53
57
  track: (input, context) => tracker.fetch(input.number, context),
54
- recognize: (number, context) => recognizeFromLookup(() => tracker.fetch(number, context), () => accepted(() => normalizeCeleritasNumber(number))),
58
+ recognize: (number, context) => recognizeFromLookup(() => http.fetch(number, context), () => accepted(() => normalizeCeleritasNumber(number))),
55
59
  };
56
60
  };
@@ -22,12 +22,14 @@
22
22
  "adapter": "celeritas",
23
23
  "steps": [
24
24
  "direct",
25
- "retry"
25
+ "retry",
26
+ "trawl"
26
27
  ],
27
28
  "recognition": {
28
29
  "rank": 996
29
30
  },
30
- "localClocks": true
31
+ "localClocks": true,
32
+ "browser": true
31
33
  },
32
34
  "capabilities": [
33
35
  "history",
@@ -1,6 +1,7 @@
1
1
  import { type AdapterFactory, type TrackingContext } from '../../core/adapter/index.js';
2
2
  import type { CarrierResult } from '../../core/result/index.js';
3
3
  import { type StepRecorder } from '../../core/telemetry/index.js';
4
+ import type { TrawlClient } from '../../core/transport/trawl.js';
4
5
  /** Delnext's tracker; its search form sends the browser to this address with the code. */
5
6
  export declare const DELNEXT_TRACKER = "https://www.delnext.com/PT/track_your_parcel";
6
7
  /**
@@ -14,6 +15,7 @@ export declare class DelnextTracker {
14
15
  fetcher?: typeof fetch;
15
16
  recorder?: StepRecorder;
16
17
  userAgent?: string;
18
+ trawl?: TrawlClient | null;
17
19
  });
18
20
  fetch(raw: string, context?: TrackingContext): Promise<CarrierResult>;
19
21
  }
@@ -4,6 +4,7 @@ import { runSteps } from '../../core/runner/index.js';
4
4
  import { firstAttemptMs, networkRetryStep } from '../../core/runner/networkRetry.js';
5
5
  import { NOOP_RECORDER } from '../../core/telemetry/index.js';
6
6
  import { decodeText, fetchBounded, userAgentOf } from '../../core/transport/index.js';
7
+ import { trawlPageStep } from '../../core/transport/trawlPage.js';
7
8
  import { DELNEXT_MAX_BYTES, normalizeDelnextNumber, parseDelnext, PROVIDER } from './parser.js';
8
9
  /** Delnext's tracker; its search form sends the browser to this address with the code. */
9
10
  export const DELNEXT_TRACKER = 'https://www.delnext.com/PT/track_your_parcel';
@@ -37,18 +38,21 @@ export class DelnextTracker {
37
38
  };
38
39
  // A lookup that fails to reach the tracker, or hangs, gets one more try:
39
40
  // the first gets half of the budget, so the retry fits in the rest.
40
- return runSteps({ carrier: 'delnext', budgetMs: context.budgetMs ?? 15_000, signal: context.signal,
41
+ return runSteps({ carrier: 'delnext', budgetMs: context.budgetMs ?? (this.options.trawl ? 60_000 : 15_000), signal: context.signal,
41
42
  recorder: this.options.recorder ?? NOOP_RECORDER }, [
42
- { id: 'direct', run: ({ signal, remainingMs }) => read(signal, firstAttemptMs(remainingMs)) },
43
- networkRetryStep(({ signal, remainingMs }) => read(signal, remainingMs)),
43
+ { id: 'direct', run: ({ signal, remainingMs }) => read(signal, firstAttemptMs(this.options.trawl ? Math.min(15_000, remainingMs) : remainingMs)) },
44
+ networkRetryStep(({ signal, remainingMs }) => read(signal, this.options.trawl ? Math.min(7_500, remainingMs) : remainingMs)),
45
+ trawlPageStep({ ...this.options, provider: PROVIDER, url: delnextLookupUrl(number), maxBytes: DELNEXT_MAX_BYTES,
46
+ parse: html => parseDelnext(html, number) }),
44
47
  ]);
45
48
  }
46
49
  }
47
50
  export const adapter = (environment) => {
48
- const tracker = new DelnextTracker({ fetcher: environment.fetcher, recorder: environment.recorder, userAgent: environment.userAgent });
51
+ const tracker = new DelnextTracker({ fetcher: environment.fetcher, recorder: environment.recorder, userAgent: environment.userAgent, trawl: environment.trawl });
52
+ const http = new DelnextTracker({ fetcher: environment.fetcher, recorder: environment.recorder, userAgent: environment.userAgent });
49
53
  return {
50
- id: 'delnext', recordsSteps: true, steps: ['direct', 'retry'],
54
+ id: 'delnext', recordsSteps: true, steps: ['direct', 'retry', 'trawl'],
51
55
  track: (input, context) => tracker.fetch(input.number, context),
52
- recognize: (number, context) => recognizeFromLookup(() => tracker.fetch(number, context), () => accepted(() => normalizeDelnextNumber(number))),
56
+ recognize: (number, context) => recognizeFromLookup(() => http.fetch(number, context), () => accepted(() => normalizeDelnextNumber(number))),
53
57
  };
54
58
  };
@@ -18,12 +18,14 @@
18
18
  "adapter": "delnext",
19
19
  "steps": [
20
20
  "direct",
21
- "retry"
21
+ "retry",
22
+ "trawl"
22
23
  ],
23
24
  "recognition": {
24
25
  "rank": 889
25
26
  },
26
- "localClocks": true
27
+ "localClocks": true,
28
+ "browser": true
27
29
  },
28
30
  "capabilities": [
29
31
  "history",
@@ -7,6 +7,10 @@ const CODES = new Map([
7
7
  ['FPX_D_SASPS', { status: 'out_for_delivery', stage: 'ready_for_pickup' }],
8
8
  ['FPX_D_FD', { status: 'exception', stage: 'failed_attempt' }],
9
9
  ['FPX_D_DDRH', { status: 'exception', stage: 'failed_attempt' }], // The recipient was not in; a notice was left.
10
+ // The partner could not deliver to the address given and is checking it, before 4PX's "Delivery failed".
11
+ ['FPX_D_FDIA', { status: 'exception', stage: 'failed_attempt' }],
12
+ // The partner's decision to send the parcel back for that address: the return is under way, not yet with the sender.
13
+ ['FPX_M_PRTS', { status: 'exception', stage: 'exception' }],
10
14
  ['FPX_L_RPIF', { status: 'pending', stage: 'registered' }],
11
15
  ['FPX_L_SC', { status: 'in_transit', stage: 'accepted' }],
12
16
  ['FPX_C_SPLS', { status: 'in_transit', stage: 'accepted' }],
@@ -153,6 +153,32 @@
153
153
  "confirmedBy": "live",
154
154
  "firstSeen": "2026-10-08"
155
155
  },
156
+ {
157
+ "code": "FPX_D_FD",
158
+ "wording": "Delivery failed",
159
+ "language": "en",
160
+ "stage": "failed_attempt",
161
+ "confirmedBy": "live",
162
+ "firstSeen": "2026-10-30"
163
+ },
164
+ {
165
+ "code": "FPX_D_FDIA",
166
+ "wording": "Delivery attempt (incorrect address)",
167
+ "language": "en",
168
+ "stage": "failed_attempt",
169
+ "confirmedBy": "live",
170
+ "firstSeen": "2026-10-30",
171
+ "note": "The partner found the address incomplete or incorrect and is checking it; La Poste's own scan of that instant is a missed delivery."
172
+ },
173
+ {
174
+ "code": "FPX_M_PRTS",
175
+ "wording": "Returned (incorrect address)",
176
+ "language": "en",
177
+ "stage": "exception",
178
+ "confirmedBy": "live",
179
+ "firstSeen": "2026-10-30",
180
+ "note": "The decision to send the parcel back to its sender for that address, at the instant La Poste says it will be returned; the parcel is not back yet."
181
+ },
156
182
  {
157
183
  "code": "FPX_F_ST",
158
184
  "wording": "Shipment in transit",
@@ -1,6 +1,7 @@
1
1
  import { type AdapterFactory, type TrackingContext } from '../../core/adapter/index.js';
2
2
  import type { CarrierResult } from '../../core/result/index.js';
3
3
  import { type StepRecorder } from '../../core/telemetry/index.js';
4
+ import type { TrawlClient } from '../../core/transport/trawl.js';
4
5
  /** The tracker's page, which its search form opens with the number. */
5
6
  export declare const HITCH_TRACKING = "https://hitch.com.ph/tracking";
6
7
  /** The tracker's address for one number. */
@@ -11,6 +12,7 @@ export declare class HitchTracker {
11
12
  fetcher?: typeof fetch;
12
13
  recorder?: StepRecorder;
13
14
  userAgent?: string;
15
+ trawl?: TrawlClient | null;
14
16
  });
15
17
  private read;
16
18
  fetch(raw: string, context?: TrackingContext): Promise<CarrierResult>;
@@ -4,6 +4,7 @@ import { runSteps } from '../../core/runner/index.js';
4
4
  import { firstAttemptMs, networkRetryStep } from '../../core/runner/networkRetry.js';
5
5
  import { NOOP_RECORDER } from '../../core/telemetry/index.js';
6
6
  import { decodeText, fetchBounded, userAgentOf } from '../../core/transport/index.js';
7
+ import { trawlPageStep } from '../../core/transport/trawlPage.js';
7
8
  import { CARRIER, HITCH_MAX_BYTES, normalizeHitchNumber, parseHitch, PROVIDER } from './parser.js';
8
9
  /** The tracker's page, which its search form opens with the number. */
9
10
  export const HITCH_TRACKING = 'https://hitch.com.ph/tracking';
@@ -32,18 +33,21 @@ export class HitchTracker {
32
33
  const number = normalizeHitchNumber(raw);
33
34
  // A read that fails to reach the tracker, or hangs, is sent once more: the
34
35
  // first try gets half of the budget.
35
- return runSteps({ carrier: CARRIER, budgetMs: context.budgetMs ?? DEFAULT_BUDGET_MS, signal: context.signal,
36
+ return runSteps({ carrier: CARRIER, budgetMs: context.budgetMs ?? (this.options.trawl ? 60_000 : DEFAULT_BUDGET_MS), signal: context.signal,
36
37
  recorder: this.options.recorder ?? NOOP_RECORDER }, [
37
- { id: 'direct', run: ({ signal, remainingMs }) => this.read(number, signal, firstAttemptMs(remainingMs)) },
38
- networkRetryStep(({ signal, remainingMs }) => this.read(number, signal, remainingMs)),
38
+ { id: 'direct', run: ({ signal, remainingMs }) => this.read(number, signal, firstAttemptMs(this.options.trawl ? Math.min(15_000, remainingMs) : remainingMs)) },
39
+ networkRetryStep(({ signal, remainingMs }) => this.read(number, signal, this.options.trawl ? Math.min(7_500, remainingMs) : remainingMs)),
40
+ trawlPageStep({ ...this.options, provider: PROVIDER, url: hitchTrackingUrl(number), maxBytes: HITCH_MAX_BYTES,
41
+ parse: html => parseHitch(html, number) }),
39
42
  ]);
40
43
  }
41
44
  }
42
45
  export const adapter = (environment) => {
43
- const tracker = new HitchTracker({ fetcher: environment.fetcher, recorder: environment.recorder, userAgent: environment.userAgent });
46
+ const tracker = new HitchTracker({ fetcher: environment.fetcher, recorder: environment.recorder, userAgent: environment.userAgent, trawl: environment.trawl });
47
+ const http = new HitchTracker({ fetcher: environment.fetcher, recorder: environment.recorder, userAgent: environment.userAgent });
44
48
  return {
45
- id: CARRIER, recordsSteps: true, steps: ['direct', 'retry'],
49
+ id: CARRIER, recordsSteps: true, steps: ['direct', 'retry', 'trawl'],
46
50
  track: (input, context) => tracker.fetch(input.number, context),
47
- recognize: (number, context) => recognizeFromLookup(() => tracker.fetch(number, context), () => accepted(() => normalizeHitchNumber(number))),
51
+ recognize: (number, context) => recognizeFromLookup(() => http.fetch(number, context), () => accepted(() => normalizeHitchNumber(number))),
48
52
  };
49
53
  };
@@ -24,12 +24,14 @@
24
24
  "adapter": "hitch",
25
25
  "steps": [
26
26
  "direct",
27
- "retry"
27
+ "retry",
28
+ "trawl"
28
29
  ],
29
30
  "recognition": {
30
31
  "rank": 117
31
32
  },
32
- "localClocks": true
33
+ "localClocks": true,
34
+ "browser": true
33
35
  },
34
36
  "capabilities": [
35
37
  "history",
@@ -1,6 +1,7 @@
1
1
  import type { AdapterFactory, TrackingContext } from '../../core/adapter/index.js';
2
2
  import type { CarrierResult } from '../../core/result/index.js';
3
3
  import { type StepRecorder } from '../../core/telemetry/index.js';
4
+ import type { TrawlClient } from '../../core/transport/trawl.js';
4
5
  export { MRL_TRACKING } from './parser.js';
5
6
  /** The tracking page's address for one consignment, as its search form opens it. */
6
7
  export declare function mrlTrackingUrl(number: string): string;
@@ -10,6 +11,7 @@ export declare class MrlTracker {
10
11
  fetcher?: typeof fetch;
11
12
  recorder?: StepRecorder;
12
13
  userAgent?: string;
14
+ trawl?: TrawlClient | null;
13
15
  });
14
16
  private read;
15
17
  fetch(raw: string, context?: TrackingContext): Promise<CarrierResult>;
@@ -3,6 +3,7 @@ import { runSteps } from '../../core/runner/index.js';
3
3
  import { firstAttemptMs, networkRetryStep } from '../../core/runner/networkRetry.js';
4
4
  import { NOOP_RECORDER } from '../../core/telemetry/index.js';
5
5
  import { decodeText, fetchBounded, userAgentOf } from '../../core/transport/index.js';
6
+ import { trawlPageStep } from '../../core/transport/trawlPage.js';
6
7
  import { MRL_MAX_BYTES, MRL_TRACKING, normalizeMrlNumber, parseMrl, PROVIDER } from './parser.js';
7
8
  export { MRL_TRACKING } from './parser.js';
8
9
  const REDIRECTS = [301, 302, 303, 307, 308];
@@ -32,17 +33,19 @@ export class MrlTracker {
32
33
  const number = normalizeMrlNumber(raw);
33
34
  // A lookup that fails to reach MRL Global, or hangs, is asked once more:
34
35
  // the first try gets half of the budget. An HTTP status is never sent again.
35
- return runSteps({ carrier: 'mrl-global', budgetMs: context.budgetMs ?? DEFAULT_BUDGET_MS, signal: context.signal,
36
+ return runSteps({ carrier: 'mrl-global', budgetMs: context.budgetMs ?? (this.options.trawl ? 60_000 : DEFAULT_BUDGET_MS), signal: context.signal,
36
37
  recorder: this.options.recorder ?? NOOP_RECORDER }, [
37
- { id: 'direct', run: ({ signal, remainingMs }) => this.read(number, signal, firstAttemptMs(remainingMs)) },
38
- networkRetryStep(({ signal, remainingMs }) => this.read(number, signal, remainingMs)),
38
+ { id: 'direct', run: ({ signal, remainingMs }) => this.read(number, signal, firstAttemptMs(this.options.trawl ? Math.min(15_000, remainingMs) : remainingMs)) },
39
+ networkRetryStep(({ signal, remainingMs }) => this.read(number, signal, this.options.trawl ? Math.min(7_500, remainingMs) : remainingMs)),
40
+ trawlPageStep({ ...this.options, provider: PROVIDER, url: mrlTrackingUrl(number), maxBytes: MRL_MAX_BYTES,
41
+ parse: html => parseMrl(html, number) }),
39
42
  ]);
40
43
  }
41
44
  }
42
45
  export const adapter = (environment) => {
43
- const tracker = new MrlTracker({ fetcher: environment.fetcher, recorder: environment.recorder, userAgent: environment.userAgent });
46
+ const tracker = new MrlTracker({ fetcher: environment.fetcher, recorder: environment.recorder, userAgent: environment.userAgent, trawl: environment.trawl });
44
47
  return {
45
- id: 'mrl-global', recordsSteps: true, steps: ['direct', 'retry'],
48
+ id: 'mrl-global', recordsSteps: true, steps: ['direct', 'retry', 'trawl'],
46
49
  track: (input, context) => tracker.fetch(input.number, context),
47
50
  };
48
51
  };
@@ -20,9 +20,11 @@
20
20
  "adapter": "mrl-global",
21
21
  "steps": [
22
22
  "direct",
23
- "retry"
23
+ "retry",
24
+ "trawl"
24
25
  ],
25
- "localClocks": true
26
+ "localClocks": true,
27
+ "browser": true
26
28
  },
27
29
  "capabilities": [
28
30
  "history"
@@ -1,6 +1,7 @@
1
1
  import { type AdapterFactory, type TrackingContext } from '../../core/adapter/index.js';
2
2
  import type { CarrierResult } from '../../core/result/index.js';
3
3
  import { type StepRecorder } from '../../core/telemetry/index.js';
4
+ import type { TrawlClient } from '../../core/transport/trawl.js';
4
5
  export { PBT_RESULT } from './parser.js';
5
6
  /** The tracking page's address for one whole number, as the tracking form opens it. */
6
7
  export declare function pbtResultUrl(number: string): string;
@@ -10,6 +11,7 @@ export declare class PbtTracker {
10
11
  fetcher?: typeof fetch;
11
12
  recorder?: StepRecorder;
12
13
  userAgent?: string;
14
+ trawl?: TrawlClient | null;
13
15
  });
14
16
  fetch(raw: string, context?: TrackingContext): Promise<CarrierResult>;
15
17
  }