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.
- package/README.md +2 -2
- package/data/catalog.json +17 -8
- package/data/coverage-summary.json +1 -1
- package/dist/browser/scraper.js +17 -8
- package/dist/carriers/ait-worldwide/adapter.d.ts +2 -0
- package/dist/carriers/ait-worldwide/adapter.js +10 -6
- package/dist/carriers/ait-worldwide/carrier.json +4 -2
- package/dist/carriers/celeritas/adapter.d.ts +2 -0
- package/dist/carriers/celeritas/adapter.js +10 -6
- package/dist/carriers/celeritas/carrier.json +4 -2
- package/dist/carriers/delnext/adapter.d.ts +2 -0
- package/dist/carriers/delnext/adapter.js +10 -6
- package/dist/carriers/delnext/carrier.json +4 -2
- package/dist/carriers/four-px/status.js +4 -0
- package/dist/carriers/four-px/statuses.json +26 -0
- package/dist/carriers/hitch/adapter.d.ts +2 -0
- package/dist/carriers/hitch/adapter.js +10 -6
- package/dist/carriers/hitch/carrier.json +4 -2
- package/dist/carriers/mrl-global/adapter.d.ts +2 -0
- package/dist/carriers/mrl-global/adapter.js +8 -5
- package/dist/carriers/mrl-global/carrier.json +4 -2
- package/dist/carriers/pbt/adapter.d.ts +2 -0
- package/dist/carriers/pbt/adapter.js +10 -6
- package/dist/carriers/pbt/carrier.json +4 -2
- package/dist/carriers/pro-carrier/adapter.d.ts +2 -0
- package/dist/carriers/pro-carrier/adapter.js +10 -6
- package/dist/carriers/pro-carrier/carrier.json +4 -2
- package/dist/carriers/swiss-post/adapter.js +8 -0
- package/dist/carriers/trendyol-express/adapter.d.ts +13 -0
- package/dist/carriers/trendyol-express/adapter.js +26 -0
- package/dist/carriers/trendyol-express/carrier.json +33 -7
- package/dist/carriers/trendyol-express/parser.d.ts +7 -0
- package/dist/carriers/trendyol-express/parser.js +92 -0
- package/dist/carriers/trendyol-express/status.d.ts +4 -0
- package/dist/carriers/trendyol-express/status.js +13 -0
- package/dist/carriers/wanbexpress/status.d.ts +2 -2
- package/dist/carriers/wanbexpress/status.js +11 -2
- package/dist/carriers/wanbexpress/statuses.json +14 -0
- package/dist/core/catalog/statusMaps.js +2 -1
- package/dist/core/transport/trawl.d.ts +2 -0
- package/dist/core/transport/trawlPage.d.ts +12 -0
- package/dist/core/transport/trawlPage.js +30 -0
- package/dist/data/catalog.json +17 -8
- package/dist/generated/catalog.d.ts +10 -1
- package/dist/generated/catalog.js +17 -8
- package/dist/generated/registry.js +3 -1
- package/dist/server/openapi.json +1 -1
- 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)
|
|
14
14
|
|
|
15
15
|
<!-- GENERATED:summary -->
|
|
16
|
-
**3,500+ carriers** through **
|
|
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,
|
|
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": "
|
|
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}",
|
package/dist/browser/scraper.js
CHANGED
|
@@ -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: "
|
|
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(() =>
|
|
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(() =>
|
|
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(() =>
|
|
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(() =>
|
|
51
|
+
recognize: (number, context) => recognizeFromLookup(() => http.fetch(number, context), () => accepted(() => normalizeHitchNumber(number))),
|
|
48
52
|
};
|
|
49
53
|
};
|
|
@@ -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
|
};
|
|
@@ -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
|
}
|