universal-parcel-scraper 0.11.0 → 0.13.0-main.337

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 (59) hide show
  1. package/README.md +4 -4
  2. package/data/catalog.json +6 -5
  3. package/data/coverage-summary.json +3 -3
  4. package/data/detection-golden.json +188 -0
  5. package/dist/browser/scraper.js +30 -26
  6. package/dist/carriers/cne/adapter.d.ts +12 -0
  7. package/dist/carriers/cne/adapter.js +43 -0
  8. package/dist/carriers/cne/carrier.json +17 -5
  9. package/dist/carriers/cne/numbers.json +28 -2
  10. package/dist/carriers/cne/parser.d.ts +3 -0
  11. package/dist/carriers/cne/parser.js +74 -0
  12. package/dist/carriers/cne/statuses.json +63 -1
  13. package/dist/carriers/dpd-uk/adapter.d.ts +11 -0
  14. package/dist/carriers/dpd-uk/adapter.js +58 -0
  15. package/dist/carriers/dpd-uk/carrier.json +18 -6
  16. package/dist/carriers/dpd-uk/numbers.json +30 -2
  17. package/dist/carriers/dpd-uk/parser.d.ts +9 -0
  18. package/dist/carriers/dpd-uk/parser.js +127 -0
  19. package/dist/carriers/evri-uk/adapter.d.ts +11 -0
  20. package/dist/carriers/evri-uk/adapter.js +80 -0
  21. package/dist/carriers/evri-uk/browser.d.ts +56 -0
  22. package/dist/carriers/evri-uk/browser.js +137 -0
  23. package/dist/carriers/evri-uk/carrier.json +21 -8
  24. package/dist/carriers/evri-uk/numbers.json +19 -2
  25. package/dist/carriers/evri-uk/parser.d.ts +5 -0
  26. package/dist/carriers/evri-uk/parser.js +89 -0
  27. package/dist/carriers/evri-uk/statuses.json +8 -1
  28. package/dist/carriers/intelcom/numbers.json +26 -0
  29. package/dist/carriers/intelcom/parser.js +9 -2
  30. package/dist/carriers/intelcom/statuses.json +9 -1
  31. package/dist/carriers/lbc-express/adapter.d.ts +13 -0
  32. package/dist/carriers/lbc-express/adapter.js +150 -0
  33. package/dist/carriers/lbc-express/carrier.json +20 -7
  34. package/dist/carriers/lbc-express/numbers.json +52 -0
  35. package/dist/carriers/lbc-express/parser.d.ts +3 -0
  36. package/dist/carriers/lbc-express/parser.js +68 -0
  37. package/dist/carriers/lbc-express/statuses.json +20 -1
  38. package/dist/carriers/nova-poshta/adapter.js +22 -5
  39. package/dist/carriers/nova-poshta/carrier.json +18 -6
  40. package/dist/carriers/nova-poshta/numbers.json +49 -0
  41. package/dist/carriers/nova-poshta/parser.d.ts +2 -0
  42. package/dist/carriers/nova-poshta/parser.js +98 -1
  43. package/dist/carriers/nova-poshta/statuses.json +93 -1
  44. package/dist/carriers/royal-mail/adapter.d.ts +3 -0
  45. package/dist/carriers/royal-mail/adapter.js +94 -47
  46. package/dist/carriers/royal-mail/numbers.json +13 -0
  47. package/dist/carriers/royal-mail/status.d.ts +1 -0
  48. package/dist/carriers/royal-mail/status.js +14 -0
  49. package/dist/carriers/royal-mail/statuses.json +151 -11
  50. package/dist/carriers/spx-ph/numbers.json +16 -0
  51. package/dist/carriers/spx-ph/parser.js +10 -4
  52. package/dist/carriers/spx-ph/statuses.json +56 -1
  53. package/dist/data/catalog.json +6 -5
  54. package/dist/generated/catalog.d.ts +6 -5
  55. package/dist/generated/catalog.js +6 -5
  56. package/dist/generated/registry.js +12 -4
  57. package/dist/providers/coverage.json +24 -20
  58. package/dist/server/openapi.json +1 -1
  59. 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 **94 dedicated adapters** and **5 universal fallbacks**
16
+ **3,500+ carriers** through **98 dedicated adapters** and **5 universal fallbacks**
17
17
 
18
18
  <sub>119 catalog entries · 58 countries represented</sub>
19
19
  <!-- /GENERATED:summary -->
@@ -33,9 +33,9 @@ its own as a command, a Node library or an HTTP server.
33
33
  ## Benchmark
34
34
 
35
35
  <!-- GENERATED:coverage -->
36
- In a curated benchmark of 113 carriers, dedicated adapters return tracking history for **66**, rising to **79** with all fallbacks enabled. The best single aggregator returns 53.
36
+ In a curated benchmark of 113 carriers, dedicated adapters return tracking history for **71**, rising to **84** with all fallbacks enabled. The best single aggregator returns 53.
37
37
 
38
- <img src="docs/assets/coverage.svg" alt="Carriers with tracking history: This project, all fallbacks enabled 79, This project, dedicated adapters alone 66, ParcelsApp 53, Postal Ninja 43, 17TRACK 40, Ship24 42, UPU 12." width="760">
38
+ <img src="docs/assets/coverage.svg" alt="Carriers with tracking history: This project, all fallbacks enabled 84, This project, dedicated adapters alone 71, ParcelsApp 53, Postal Ninja 43, 17TRACK 40, Ship24 42, UPU 12." width="760">
39
39
  <!-- /GENERATED:coverage -->
40
40
 
41
41
  [Method and results per carrier](providers/COVERAGE.md)
@@ -149,7 +149,7 @@ createTracker({ providers: ['ParcelsApp', 'Ship24', '17TRACK', 'Postal Ninja', '
149
149
  <!-- GENERATED:stages -->
150
150
  <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">
151
151
 
152
- The carrier folders record 1,730 such statuses, each filed under one stage.
152
+ The carrier folders record 1,785 such statuses, each filed under one stage.
153
153
  <!-- /GENERATED:stages -->
154
154
 
155
155
  Wording nobody recorded yet goes through a classifier that reads seven European languages.
package/data/catalog.json CHANGED
@@ -4054,7 +4054,7 @@
4054
4054
  "timezone": "UTC",
4055
4055
  "tracking": {
4056
4056
  "mode": "automatic",
4057
- "adapter": "universal"
4057
+ "adapter": "cne"
4058
4058
  },
4059
4059
  "canaryUrl": "https://www.cne.com/track",
4060
4060
  "trackingUrlTemplate": "https://www.cne.com/en/track?no={trackingNumber}",
@@ -4172,7 +4172,8 @@
4172
4172
  "timezone": "Europe/London",
4173
4173
  "tracking": {
4174
4174
  "mode": "automatic",
4175
- "adapter": "universal"
4175
+ "adapter": "dpd-uk",
4176
+ "localClocks": true
4176
4177
  },
4177
4178
  "canaryUrl": "https://track.dpd.co.uk/",
4178
4179
  "trackingUrlTemplate": "https://track.dpd.co.uk/?reference={trackingNumber}",
@@ -4242,7 +4243,7 @@
4242
4243
  "timezone": "Europe/London",
4243
4244
  "tracking": {
4244
4245
  "mode": "automatic",
4245
- "adapter": "universal"
4246
+ "adapter": "evri-uk"
4246
4247
  },
4247
4248
  "canaryUrl": "https://www.evri.com/track-a-parcel",
4248
4249
  "trackingUrlTemplate": "https://www.evri.com/track/parcel/{trackingNumber}/details",
@@ -4316,10 +4317,10 @@
4316
4317
  "timezone": "Asia/Manila",
4317
4318
  "tracking": {
4318
4319
  "mode": "automatic",
4319
- "adapter": "universal"
4320
+ "adapter": "lbc-express",
4321
+ "localClocks": true
4320
4322
  },
4321
4323
  "canaryUrl": "https://www.lbcexpress.com/track/",
4322
- "trackingUrlTemplate": "https://www.lbcexpress.com/track/?tracking_no={trackingNumber}",
4323
4324
  "linkRules": [
4324
4325
  {
4325
4326
  "domains": [
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "catalog": 119,
3
- "activeAdapters": 94,
3
+ "activeAdapters": 98,
4
4
  "countries": 58,
5
5
  "referenceCarriers": 113,
6
6
  "comparison": {
7
- "combined": 79,
8
- "direct": 66,
7
+ "combined": 84,
8
+ "direct": 71,
9
9
  "providers": {
10
10
  "ParcelsApp": 53,
11
11
  "Postal Ninja": 43,
@@ -837,6 +837,28 @@
837
837
  "ciblex"
838
838
  ]
839
839
  },
840
+ {
841
+ "input": "100000000001",
842
+ "carrier": "unknown",
843
+ "confidence": "low",
844
+ "candidates": [
845
+ "fedex",
846
+ "dpd-fr",
847
+ "mondial-relay",
848
+ "colis-prive",
849
+ "mrw",
850
+ "purolator",
851
+ "sf-express",
852
+ "sto",
853
+ "zto",
854
+ "yamato",
855
+ "j-and-t",
856
+ "lbc-express"
857
+ ],
858
+ "asked": [
859
+ "colis-prive"
860
+ ]
861
+ },
840
862
  {
841
863
  "input": "1000478495775",
842
864
  "carrier": "unknown",
@@ -1336,6 +1358,76 @@
1336
1358
  "colis-prive"
1337
1359
  ]
1338
1360
  },
1361
+ {
1362
+ "input": "142062960271",
1363
+ "carrier": "unknown",
1364
+ "confidence": "low",
1365
+ "candidates": [
1366
+ "fedex",
1367
+ "dpd-fr",
1368
+ "mondial-relay",
1369
+ "colis-prive",
1370
+ "mrw",
1371
+ "purolator",
1372
+ "sf-express",
1373
+ "sto",
1374
+ "zto",
1375
+ "yamato",
1376
+ "j-and-t",
1377
+ "lbc-express"
1378
+ ],
1379
+ "asked": [
1380
+ "colis-prive"
1381
+ ]
1382
+ },
1383
+ {
1384
+ "input": "15504366056765",
1385
+ "carrier": "unknown",
1386
+ "confidence": "low",
1387
+ "candidates": [
1388
+ "dpd",
1389
+ "dpd-fr",
1390
+ "relais-colis",
1391
+ "ciblex",
1392
+ "seur",
1393
+ "brt",
1394
+ "delhivery",
1395
+ "dpd-de",
1396
+ "dpd-uk",
1397
+ "xpressbees"
1398
+ ],
1399
+ "asked": [
1400
+ "dpd",
1401
+ "seur",
1402
+ "brt",
1403
+ "relais-colis",
1404
+ "ciblex"
1405
+ ]
1406
+ },
1407
+ {
1408
+ "input": "15504366057635",
1409
+ "carrier": "unknown",
1410
+ "confidence": "low",
1411
+ "candidates": [
1412
+ "dpd",
1413
+ "dpd-fr",
1414
+ "relais-colis",
1415
+ "ciblex",
1416
+ "seur",
1417
+ "brt",
1418
+ "delhivery",
1419
+ "dpd-de",
1420
+ "dpd-uk",
1421
+ "xpressbees"
1422
+ ],
1423
+ "asked": [
1424
+ "dpd",
1425
+ "seur",
1426
+ "brt",
1427
+ "relais-colis",
1428
+ "ciblex"
1429
+ ]
1430
+ },
1339
1431
  {
1340
1432
  "input": "1595193512495",
1341
1433
  "carrier": "unknown",
@@ -1743,6 +1835,30 @@
1743
1835
  "postlogistics"
1744
1836
  ]
1745
1837
  },
1838
+ {
1839
+ "input": "20710517491331",
1840
+ "carrier": "unknown",
1841
+ "confidence": "low",
1842
+ "candidates": [
1843
+ "dpd",
1844
+ "relais-colis",
1845
+ "ciblex",
1846
+ "hermes-de",
1847
+ "seur",
1848
+ "brt",
1849
+ "delhivery",
1850
+ "dpd-de",
1851
+ "dpd-uk",
1852
+ "nova-poshta"
1853
+ ],
1854
+ "asked": [
1855
+ "dpd",
1856
+ "seur",
1857
+ "brt",
1858
+ "hermes-de",
1859
+ "relais-colis"
1860
+ ]
1861
+ },
1746
1862
  {
1747
1863
  "input": "2103/11207088",
1748
1864
  "carrier": "nacex",
@@ -2333,6 +2449,18 @@
2333
2449
  "relais-colis"
2334
2450
  ]
2335
2451
  },
2452
+ {
2453
+ "input": "3A5V609829713",
2454
+ "carrier": "unknown",
2455
+ "confidence": "none",
2456
+ "candidates": []
2457
+ },
2458
+ {
2459
+ "input": "3A5V721250488",
2460
+ "carrier": "unknown",
2461
+ "confidence": "none",
2462
+ "candidates": []
2463
+ },
2336
2464
  {
2337
2465
  "input": "3SA5210528875",
2338
2466
  "carrier": "spring-gds",
@@ -2941,6 +3069,29 @@
2941
3069
  "ciblex"
2942
3070
  ]
2943
3071
  },
3072
+ {
3073
+ "input": "59001766134310",
3074
+ "carrier": "unknown",
3075
+ "confidence": "low",
3076
+ "candidates": [
3077
+ "dpd",
3078
+ "relais-colis",
3079
+ "ciblex",
3080
+ "seur",
3081
+ "brt",
3082
+ "delhivery",
3083
+ "dpd-de",
3084
+ "dpd-uk",
3085
+ "nova-poshta"
3086
+ ],
3087
+ "asked": [
3088
+ "dpd",
3089
+ "seur",
3090
+ "brt",
3091
+ "relais-colis",
3092
+ "ciblex"
3093
+ ]
3094
+ },
2944
3095
  {
2945
3096
  "input": "5N30053962734",
2946
3097
  "carrier": "la-poste",
@@ -4536,6 +4687,18 @@
4536
4687
  "dhl"
4537
4688
  ]
4538
4689
  },
4690
+ {
4691
+ "input": "CRIN26062320118472",
4692
+ "carrier": "unknown",
4693
+ "confidence": "none",
4694
+ "candidates": []
4695
+ },
4696
+ {
4697
+ "input": "CRIN26082718020483",
4698
+ "carrier": "unknown",
4699
+ "confidence": "none",
4700
+ "candidates": []
4701
+ },
4539
4702
  {
4540
4703
  "input": "CV000562646ES",
4541
4704
  "carrier": "unknown",
@@ -5013,6 +5176,15 @@
5013
5176
  "hermes-de"
5014
5177
  ]
5015
5178
  },
5179
+ {
5180
+ "input": "H00RVA0538924343",
5181
+ "carrier": "unknown",
5182
+ "confidence": "low",
5183
+ "candidates": [
5184
+ "evri",
5185
+ "evri-uk"
5186
+ ]
5187
+ },
5016
5188
  {
5017
5189
  "input": "H0595C0000314450",
5018
5190
  "carrier": "unknown",
@@ -5772,6 +5944,14 @@
5772
5944
  "spx-ph"
5773
5945
  ]
5774
5946
  },
5947
+ {
5948
+ "input": "PH2542959127193",
5949
+ "carrier": "unknown",
5950
+ "confidence": "low",
5951
+ "candidates": [
5952
+ "spx-ph"
5953
+ ]
5954
+ },
5775
5955
  {
5776
5956
  "input": "PHAS9C0419962810128017D",
5777
5957
  "carrier": "correos-spain",
@@ -6663,6 +6843,14 @@
6663
6843
  "yunexpress"
6664
6844
  ]
6665
6845
  },
6846
+ {
6847
+ "input": "YT660296803GB",
6848
+ "carrier": "royal-mail",
6849
+ "confidence": "high",
6850
+ "candidates": [
6851
+ "royal-mail"
6852
+ ]
6853
+ },
6666
6854
  {
6667
6855
  "input": "YT8879092508074",
6668
6856
  "carrier": "yto",
@@ -3131,7 +3131,7 @@ var ce = {
3131
3131
  timezone: "UTC",
3132
3132
  tracking: {
3133
3133
  mode: "automatic",
3134
- adapter: "universal"
3134
+ adapter: "cne"
3135
3135
  },
3136
3136
  canaryUrl: "https://www.cne.com/track",
3137
3137
  trackingUrlTemplate: "https://www.cne.com/en/track?no={trackingNumber}",
@@ -3213,7 +3213,8 @@ var ce = {
3213
3213
  timezone: "Europe/London",
3214
3214
  tracking: {
3215
3215
  mode: "automatic",
3216
- adapter: "universal"
3216
+ adapter: "dpd-uk",
3217
+ localClocks: !0
3217
3218
  },
3218
3219
  canaryUrl: "https://track.dpd.co.uk/",
3219
3220
  trackingUrlTemplate: "https://track.dpd.co.uk/?reference={trackingNumber}",
@@ -3261,7 +3262,7 @@ var ce = {
3261
3262
  timezone: "Europe/London",
3262
3263
  tracking: {
3263
3264
  mode: "automatic",
3264
- adapter: "universal"
3265
+ adapter: "evri-uk"
3265
3266
  },
3266
3267
  canaryUrl: "https://www.evri.com/track-a-parcel",
3267
3268
  trackingUrlTemplate: "https://www.evri.com/track/parcel/{trackingNumber}/details",
@@ -3312,10 +3313,10 @@ var ce = {
3312
3313
  timezone: "Asia/Manila",
3313
3314
  tracking: {
3314
3315
  mode: "automatic",
3315
- adapter: "universal"
3316
+ adapter: "lbc-express",
3317
+ localClocks: !0
3316
3318
  },
3317
3319
  canaryUrl: "https://www.lbcexpress.com/track/",
3318
- trackingUrlTemplate: "https://www.lbcexpress.com/track/?tracking_no={trackingNumber}",
3319
3320
  linkRules: [{
3320
3321
  domains: ["lbcexpress.com"],
3321
3322
  params: ["tracking_no"]
@@ -8288,7 +8289,10 @@ var gs = { carriers: [
8288
8289
  "17TRACK": "no_history",
8289
8290
  "Postal Ninja": 4,
8290
8291
  UPU: "no_history"
8291
- } }]
8292
+ } }, {
8293
+ note: "Alternate public reference returned eight identity-bound full-history scans in an interactive official session. Fresh automated Chromium obtained the matching microsummary, but its separate events request failed; automated full history remains unverified: https://www.reddit.com/r/royalmail/comments/1wh27pw/cant_track_my_shipment/",
8294
+ results: {}
8295
+ }]
8292
8296
  },
8293
8297
  {
8294
8298
  carrier: "swiss-post",
@@ -9710,10 +9714,10 @@ var gs = { carriers: [
9710
9714
  },
9711
9715
  {
9712
9716
  carrier: "dpd-uk",
9713
- direct: "No adapter",
9714
- sample: "Blocked",
9717
+ direct: "Yes (UK parcel numbers)",
9718
+ sample: "✓ 7",
9715
9719
  references: [{
9716
- note: "UK reference-plus-postcode flow requires a challenge and session before retrieval.",
9720
+ note: "Public UK parcel references returned seven and eight history scans through the current anonymous empty-postcode lookup; unqualified scan clocks remain local: https://uk.trustpilot.com/review/primepaint.co.uk?page=3. Order and collection references behind the postcode form are outside the adapter scope.",
9717
9721
  results: {
9718
9722
  Ship24: "unverified",
9719
9723
  ParcelsApp: "unverified",
@@ -9725,10 +9729,10 @@ var gs = { carriers: [
9725
9729
  },
9726
9730
  {
9727
9731
  carrier: "evri-uk",
9728
- direct: "No adapter",
9729
- sample: "Blocked",
9732
+ direct: "Yes (local Chromium)",
9733
+ sample: "✓ 6",
9730
9734
  references: [{
9731
- note: "Domestic UK bootstrap requires a challenge; Evri International is a separate adapter.",
9735
+ note: "Public domestic reference returned six identity-bound, offset-dated history scans in fresh automated local Chromium. The current anonymous flow obtains rotating keys in the browser and requires no postcode: https://www.trustpilot.com/review/printerval.co.uk",
9732
9736
  results: {
9733
9737
  Ship24: "unverified",
9734
9738
  ParcelsApp: "unverified",
@@ -9756,9 +9760,9 @@ var gs = { carriers: [
9756
9760
  {
9757
9761
  carrier: "intelcom",
9758
9762
  direct: "Yes (Canada)",
9759
- sample: "Not found",
9763
+ sample: "Not found; alternate ✓ 6",
9760
9764
  references: [{
9761
- note: "Public Intelcom reference returned not_found; successful live history is unverified: https://www.justanswer.com/software/vud02-intelcom-package-not-delivered-address-dispute.html",
9765
+ note: "Comparison reference returned not_found: https://www.justanswer.com/software/vud02-intelcom-package-not-delivered-address-dispute.html. An alternate public reference returned six scans: https://intelcom.ca/en/track-your-package/?tracking-id=CRIN26082718020483",
9762
9766
  results: {
9763
9767
  Ship24: "unverified",
9764
9768
  ParcelsApp: "unverified",
@@ -9800,10 +9804,10 @@ var gs = { carriers: [
9800
9804
  },
9801
9805
  {
9802
9806
  carrier: "lbc-express",
9803
- direct: "No adapter",
9804
- sample: "Blocked",
9807
+ direct: "Yes (local Chromium)",
9808
+ sample: "Unverified; alternate ✓ 6",
9805
9809
  references: [{
9806
- note: "Public LBC reference: https://www.trustpilot.com/review/www.lbcexpress.com. Official anonymous retrieval is blocked.",
9810
+ note: "Original comparison reference has not been retried through the implemented browser flow: https://www.trustpilot.com/review/www.lbcexpress.com. An alternate public reference returned six unique date-only scans in a fresh automated browser: https://uk.trustpilot.com/review/www.lbcexpress.com",
9807
9811
  results: {
9808
9812
  Ship24: "unverified",
9809
9813
  ParcelsApp: "unverified",
@@ -9815,10 +9819,10 @@ var gs = { carriers: [
9815
9819
  },
9816
9820
  {
9817
9821
  carrier: "nova-poshta",
9818
- direct: "Yes (Ukraine; summary)",
9819
- sample: "Unverified",
9822
+ direct: "Yes (Ukraine)",
9823
+ sample: "✓ 10",
9820
9824
  references: [{
9821
- note: "Anonymous summary schema and explicit not-found response are established; successful live retrieval is unverified.",
9825
+ note: "Public Ukrainian waybill returned ten identity-bound movement scans: https://www.vidhuk.ua/uk/novaya-pochta-nova-poshta/review-2377100. A redirected import waybill returned twenty-two scans: https://www.vidhuk.ua/uk/novaya-pochta-nova-poshta/review-2376836",
9822
9826
  results: {
9823
9827
  Ship24: "unverified",
9824
9828
  ParcelsApp: "unverified",
@@ -9831,9 +9835,9 @@ var gs = { carriers: [
9831
9835
  {
9832
9836
  carrier: "spx-ph",
9833
9837
  direct: "Yes (Philippines)",
9834
- sample: "Unverified",
9838
+ sample: "✓ 10",
9835
9839
  references: [{
9836
- note: "Anonymous single-parcel schema is established; successful live history is unverified.",
9840
+ note: "Public marketplace reference returned ten visible identity-bound scans: https://www.reddit.com/r/ShopeePH/comments/1i67ifq/",
9837
9841
  results: {
9838
9842
  Ship24: "unverified",
9839
9843
  ParcelsApp: "unverified",
@@ -9845,10 +9849,10 @@ var gs = { carriers: [
9845
9849
  },
9846
9850
  {
9847
9851
  carrier: "cne",
9848
- direct: "No adapter",
9849
- sample: "Blocked",
9852
+ direct: "Yes",
9853
+ sample: "✓ 9",
9850
9854
  references: [{
9851
- note: "Official tracking requires a generated signature and challenges anonymous retrieval.",
9855
+ note: "Public CNE reference returned nine movement scans with unresolved unqualified clocks: https://nz.trustpilot.com/review/oriental-secrets.com. A second public reference returned a registration scan: https://ca.trustpilot.com/review/firalli.com?page=8",
9852
9856
  results: {
9853
9857
  Ship24: "unverified",
9854
9858
  ParcelsApp: "unverified",
@@ -9863,7 +9867,7 @@ var gs = { carriers: [
9863
9867
  direct: "No adapter",
9864
9868
  sample: "Blocked",
9865
9869
  references: [{
9866
- note: "Official tracking front door blocks anonymous retrieval.",
9870
+ note: "Sagawa has suspended public shipment inquiry and its carrier inquiry API; fresh anonymous history retrieval is unavailable: https://www2.sagawa-exp.co.jp/information/detail/425/",
9867
9871
  results: {
9868
9872
  Ship24: "unverified",
9869
9873
  ParcelsApp: "unverified",
@@ -0,0 +1,12 @@
1
+ import type { AdapterFactory, TrackingContext } from '../../core/adapter/index.js';
2
+ import { type StepRecorder } from '../../core/telemetry/index.js';
3
+ export declare class CneTracker {
4
+ private readonly options;
5
+ constructor(options?: {
6
+ fetcher?: typeof fetch;
7
+ recorder?: StepRecorder;
8
+ userAgent?: string;
9
+ });
10
+ fetch(raw: string, context?: TrackingContext): Promise<import("../../index.js").CarrierResult>;
11
+ }
12
+ export declare const adapter: AdapterFactory;
@@ -0,0 +1,43 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { TransportError, UpstreamHttpError } from '../../core/errors/index.js';
3
+ import { runSteps } from '../../core/runner/index.js';
4
+ import { NOOP_RECORDER } from '../../core/telemetry/index.js';
5
+ import { fetchBounded, parseJsonBytes, userAgentOf } from '../../core/transport/index.js';
6
+ import { normalizeCneNumber, parseCne } from './parser.js';
7
+ const ENDPOINT = 'https://wapi.cne.com/tracking/officialWebsite';
8
+ // The anonymous website's public WASM client prefixes inputs before MD5:
9
+ // https://www.cne.com/assets/wasm/wasm_md5_bg-074da2d9.wasm
10
+ // This is a form-protocol constant, not an account credential. Keep its space.
11
+ const PUBLIC_FORM_PREFIX = '01979c0bfa33772dbb3f5c07bd651b21 ';
12
+ const sign = (input) => createHash('md5').update(PUBLIC_FORM_PREFIX + input).digest('hex');
13
+ export class CneTracker {
14
+ options;
15
+ constructor(options = {}) {
16
+ this.options = options;
17
+ }
18
+ async fetch(raw, context = {}) {
19
+ const number = normalizeCneNumber(raw);
20
+ return runSteps({ carrier: 'cne', signal: context.signal, budgetMs: context.budgetMs ?? 15_000,
21
+ recorder: this.options.recorder ?? NOOP_RECORDER }, [{ id: 'direct', run: async ({ signal, remainingMs }) => {
22
+ const timestamp = Date.now().toString();
23
+ try {
24
+ const { bytes } = await fetchBounded(`${ENDPOINT}?t=${timestamp}`, { method: 'POST', signal,
25
+ headers: { 'Content-Type': 'application/json', Accept: 'application/json, text/plain, */*',
26
+ Origin: 'https://www.cne.com', Referer: 'https://www.cne.com/', 'User-Agent': userAgentOf(this.options.userAgent),
27
+ signature: sign(timestamp.substring(0, 12) + number) },
28
+ body: JSON.stringify({ lan: 'en', logisticsNo: number, md5: sign(number + 'Track') }),
29
+ }, { provider: 'CNE Express', timeoutMs: Math.max(1, Math.floor(remainingMs)), maxBytes: 1_000_000, fetcher: this.options.fetcher });
30
+ return parseCne(parseJsonBytes(bytes, 'CNE Express'), number);
31
+ }
32
+ catch (error) {
33
+ if (error instanceof UpstreamHttpError && [404, 410].includes(error.status))
34
+ throw new TransportError('CNE Express', 'CNE tracking endpoint is unavailable', { cause: error });
35
+ throw error;
36
+ }
37
+ } }]);
38
+ }
39
+ }
40
+ export const adapter = environment => {
41
+ const tracker = new CneTracker({ fetcher: environment.fetcher, recorder: environment.recorder, userAgent: environment.userAgent });
42
+ return { id: 'cne', recordsSteps: true, steps: ['direct'], track: (input, context) => tracker.fetch(input.number, context) };
43
+ };
@@ -17,10 +17,15 @@
17
17
  "timezone": "UTC",
18
18
  "tracking": {
19
19
  "mode": "automatic",
20
- "adapter": "universal",
21
- "steps": []
20
+ "adapter": "cne",
21
+ "steps": [
22
+ "direct"
23
+ ]
22
24
  },
23
- "capabilities": [],
25
+ "capabilities": [
26
+ "history",
27
+ "location"
28
+ ],
24
29
  "portal": {
25
30
  "url": "https://www.cne.com/en/track?no={trackingNumber}",
26
31
  "canaryUrl": "https://www.cne.com/track",
@@ -30,8 +35,15 @@
30
35
  "location",
31
36
  "delivery_partner"
32
37
  ],
33
- "scraped": [],
34
- "discarded": [],
38
+ "scraped": [
39
+ "status",
40
+ "history",
41
+ "location"
42
+ ],
43
+ "discarded": [
44
+ "transfer_reference",
45
+ "merchant_reference"
46
+ ],
35
47
  "unavailable": [
36
48
  "eta",
37
49
  "weight"
@@ -1,5 +1,31 @@
1
1
  {
2
2
  "carrier": "cne",
3
- "gap": "no public sample found yet",
4
- "records": []
3
+ "records": [
4
+ {
5
+ "number": "3A5V721250488",
6
+ "role": "shipment",
7
+ "evidence": "public_shipment_report",
8
+ "source": {
9
+ "url": "https://ca.trustpilot.com/review/firalli.com?page=8"
10
+ },
11
+ "expect": {
12
+ "carrier": "unknown",
13
+ "confidence": "none"
14
+ },
15
+ "note": "Customer report explicitly attributes the number to CNE. Requires explicit carrier selection."
16
+ },
17
+ {
18
+ "number": "3A5V609829713",
19
+ "role": "shipment",
20
+ "evidence": "public_shipment_report",
21
+ "source": {
22
+ "url": "https://nz.trustpilot.com/review/oriental-secrets.com"
23
+ },
24
+ "expect": {
25
+ "carrier": "unknown",
26
+ "confidence": "none"
27
+ },
28
+ "note": "Customer report explicitly attributes the number to CNE and describes a return."
29
+ }
30
+ ]
5
31
  }
@@ -0,0 +1,3 @@
1
+ import type { CarrierResult } from '../../core/result/index.js';
2
+ export declare function normalizeCneNumber(raw: string): string;
3
+ export declare function parseCne(payload: unknown, raw: string): CarrierResult;