universal-parcel-scraper 0.131.0-main.1107 → 0.133.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/README.md +2 -2
  2. package/data/catalog.json +52 -10
  3. package/data/coverage-summary.json +1 -1
  4. package/data/detection-golden.json +14 -7
  5. package/dist/browser/scraper.js +108 -58
  6. package/dist/carriers/asendia/adapter.d.ts +10 -7
  7. package/dist/carriers/asendia/adapter.js +98 -3
  8. package/dist/carriers/asendia/carrier.json +2 -1
  9. package/dist/carriers/asendia/status.d.ts +11 -3
  10. package/dist/carriers/asendia/status.js +39 -0
  11. package/dist/carriers/asendia/statuses.json +168 -0
  12. package/dist/carriers/asendia/uk.d.ts +20 -0
  13. package/dist/carriers/asendia/uk.js +222 -0
  14. package/dist/carriers/day-ross/adapter.d.ts +8 -0
  15. package/dist/carriers/day-ross/adapter.js +86 -0
  16. package/dist/carriers/day-ross/carrier.json +42 -8
  17. package/dist/carriers/day-ross/parser.d.ts +8 -0
  18. package/dist/carriers/day-ross/parser.js +85 -0
  19. package/dist/carriers/day-ross/status.d.ts +2 -0
  20. package/dist/carriers/day-ross/status.js +6 -0
  21. package/dist/carriers/day-ross/statuses.json +97 -1
  22. package/dist/carriers/instabox/adapter.d.ts +8 -0
  23. package/dist/carriers/instabox/adapter.js +77 -0
  24. package/dist/carriers/instabox/carrier.json +49 -8
  25. package/dist/carriers/instabox/parser.d.ts +7 -0
  26. package/dist/carriers/instabox/parser.js +127 -0
  27. package/dist/carriers/instabox/status.d.ts +2 -0
  28. package/dist/carriers/instabox/status.js +14 -0
  29. package/dist/carriers/instabox/statuses.json +44 -1
  30. package/dist/carriers/parcelforce/carrier.json +3 -1
  31. package/dist/carriers/saia/adapter.d.ts +23 -0
  32. package/dist/carriers/saia/adapter.js +151 -0
  33. package/dist/carriers/saia/carrier.json +72 -8
  34. package/dist/carriers/saia/parser.d.ts +26 -0
  35. package/dist/carriers/saia/parser.js +190 -0
  36. package/dist/carriers/saia/status.d.ts +12 -0
  37. package/dist/carriers/saia/status.js +72 -0
  38. package/dist/carriers/saia/statuses.json +20 -1
  39. package/dist/carriers/wanbexpress/adapter.d.ts +11 -0
  40. package/dist/carriers/wanbexpress/adapter.js +84 -0
  41. package/dist/carriers/wanbexpress/carrier.json +43 -7
  42. package/dist/carriers/wanbexpress/parser.d.ts +7 -0
  43. package/dist/carriers/wanbexpress/parser.js +71 -0
  44. package/dist/carriers/wanbexpress/status.d.ts +2 -0
  45. package/dist/carriers/wanbexpress/status.js +10 -0
  46. package/dist/carriers/wanbexpress/statuses.json +96 -1
  47. package/dist/carriers/xpo-ltl/adapter.d.ts +2 -0
  48. package/dist/carriers/xpo-ltl/adapter.js +21 -7
  49. package/dist/carriers/xpo-ltl/browser.d.ts +5 -0
  50. package/dist/carriers/xpo-ltl/browser.js +119 -0
  51. package/dist/carriers/xpo-ltl/carrier.json +10 -5
  52. package/dist/core/catalog/inputs.js +4 -0
  53. package/dist/core/catalog/statusMaps.js +8 -4
  54. package/dist/core/catalog/types.d.ts +1 -1
  55. package/dist/core/catalog/urls.d.ts +2 -0
  56. package/dist/core/catalog/urls.js +31 -0
  57. package/dist/data/catalog.json +52 -10
  58. package/dist/generated/catalog.d.ts +38 -9
  59. package/dist/generated/catalog.js +52 -10
  60. package/dist/generated/recognition.js +3 -0
  61. package/dist/generated/registry.js +12 -4
  62. package/dist/index.d.ts +1 -1
  63. package/dist/index.js +1 -1
  64. package/dist/providers/coverage.json +1 -1
  65. package/dist/server/openapi.json +1 -1
  66. 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 **193 dedicated adapters** and **5 universal fallbacks**
16
+ **3,500+ carriers** through **197 dedicated adapters** and **5 universal fallbacks**
17
17
 
18
18
  <sub>210 catalog entries · 66 countries represented</sub>
19
19
  <!-- /GENERATED:summary -->
@@ -155,7 +155,7 @@ createTracker({ providers: ['ParcelsApp', 'Ship24', '17TRACK', 'Postal Ninja', '
155
155
  <!-- GENERATED:stages -->
156
156
  <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">
157
157
 
158
- The carrier folders record 5,782 such statuses, each filed under one stage.
158
+ The carrier folders record 5,854 such statuses, each filed under one stage.
159
159
  <!-- /GENERATED:stages -->
160
160
 
161
161
  Wording nobody recorded yet goes through a classifier that reads seven European languages.
package/data/catalog.json CHANGED
@@ -1651,7 +1651,8 @@
1651
1651
  "timezone": "UTC",
1652
1652
  "tracking": {
1653
1653
  "mode": "automatic",
1654
- "adapter": "asendia"
1654
+ "adapter": "asendia",
1655
+ "localClocks": true
1655
1656
  },
1656
1657
  "canaryUrl": "https://a1.asendiausa.com/tracking/",
1657
1658
  "trackingUrlTemplate": "https://track.asendia.com/track/{trackingNumber}",
@@ -2023,6 +2024,9 @@
2023
2024
  "parcelforce": {
2024
2025
  "displayName": "Parcelforce Worldwide",
2025
2026
  "color": "#9d0f11",
2027
+ "aliases": [
2028
+ "Parcelforce"
2029
+ ],
2026
2030
  "countries": [
2027
2031
  "GB"
2028
2032
  ],
@@ -5464,9 +5468,12 @@
5464
5468
  "timezone": "America/Moncton",
5465
5469
  "tracking": {
5466
5470
  "mode": "automatic",
5467
- "adapter": "universal"
5471
+ "adapter": "day-ross",
5472
+ "recognitionRank": 38,
5473
+ "localClocks": true
5468
5474
  },
5469
- "canaryUrl": "https://dayross.com/",
5475
+ "canaryUrl": "https://dayross.com/track-shipments",
5476
+ "trackingSearchUrl": "https://dayross.com/track-shipments",
5470
5477
  "linkRules": [],
5471
5478
  "detectionRules": [
5472
5479
  {
@@ -6987,11 +6994,31 @@
6987
6994
  "timezone": "Europe/Stockholm",
6988
6995
  "tracking": {
6989
6996
  "mode": "automatic",
6990
- "adapter": "universal"
6997
+ "adapter": "instabox",
6998
+ "requirements": [
6999
+ {
7000
+ "field": "trackingUrl",
7001
+ "validator": "instaboxCapabilityUrl",
7002
+ "optional": true,
7003
+ "label": "Instabox notification URL",
7004
+ "type": "url",
7005
+ "placeholder": "https://track.instabox.com/…",
7006
+ "help": "The complete notification link opens your parcel history. Without it, other sources are asked."
7007
+ }
7008
+ ]
6991
7009
  },
6992
- "canaryUrl": "https://track.instabox.com/en",
7010
+ "canaryUrl": "https://track.instabox.com/",
6993
7011
  "trackingSearchUrl": "https://track.instabox.com/en",
6994
- "linkRules": [],
7012
+ "linkRules": [
7013
+ {
7014
+ "domains": [
7015
+ "track.instabox.com"
7016
+ ],
7017
+ "pathPattern": "^/[a-z]{2}(?:-[A-Z]{2})?/[A-Za-z0-9]{4,40}(?:/locker-to-locker-recipient)?/?$",
7018
+ "path": "^/[a-z]{2}(?:-[A-Z]{2})?/([A-Za-z0-9]{4,40})(?:/locker-to-locker-recipient)?/?$",
7019
+ "keepsCapabilityUrl": true
7020
+ }
7021
+ ],
6995
7022
  "detectionRules": []
6996
7023
  },
6997
7024
  "intelcom": {
@@ -8242,10 +8269,12 @@
8242
8269
  "timezone": "America/New_York",
8243
8270
  "tracking": {
8244
8271
  "mode": "automatic",
8245
- "adapter": "universal"
8272
+ "adapter": "saia",
8273
+ "recognitionRank": 12,
8274
+ "localClocks": true
8246
8275
  },
8247
8276
  "canaryUrl": "https://www.saia.com/track",
8248
- "trackingUrlTemplate": "https://www.saia.com/track?pro={trackingNumber}",
8277
+ "trackingUrlTemplate": "https://www.saia.com/track/details;pro={trackingNumber}",
8249
8278
  "trackingSearchUrl": "https://www.saia.com/track",
8250
8279
  "linkRules": [
8251
8280
  {
@@ -8256,6 +8285,16 @@
8256
8285
  "params": [
8257
8286
  "pro"
8258
8287
  ]
8288
+ },
8289
+ {
8290
+ "domains": [
8291
+ "saia.com"
8292
+ ],
8293
+ "pathPattern": "^/track/details(?:/|;|$)",
8294
+ "path": "^/track/details;pro=(\\d+)",
8295
+ "params": [
8296
+ "pro"
8297
+ ]
8259
8298
  }
8260
8299
  ],
8261
8300
  "detectionRules": []
@@ -8727,9 +8766,11 @@
8727
8766
  "timezone": "Asia/Shanghai",
8728
8767
  "tracking": {
8729
8768
  "mode": "automatic",
8730
- "adapter": "universal"
8769
+ "adapter": "wanbexpress",
8770
+ "recognitionRank": 33,
8771
+ "browserRecognitionRank": 33
8731
8772
  },
8732
- "canaryUrl": "https://www.wanbexpress.com/",
8773
+ "canaryUrl": "https://tracking.wanbexpress.com/",
8733
8774
  "linkRules": [],
8734
8775
  "detectionRules": [
8735
8776
  {
@@ -8855,6 +8896,7 @@
8855
8896
  "mode": "automatic",
8856
8897
  "adapter": "xpo-ltl",
8857
8898
  "recognitionRank": 25,
8899
+ "browserRecognitionRank": 25,
8858
8900
  "localClocks": true
8859
8901
  },
8860
8902
  "canaryUrl": "https://www.xpo.com/",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "catalog": 210,
3
- "activeAdapters": 193,
3
+ "activeAdapters": 197,
4
4
  "countries": 66,
5
5
  "referenceCarriers": 100,
6
6
  "comparison": {
@@ -33006,7 +33006,8 @@
33006
33006
  "day-ross"
33007
33007
  ],
33008
33008
  "asked": [
33009
- "australia-post"
33009
+ "australia-post",
33010
+ "day-ross"
33010
33011
  ]
33011
33012
  },
33012
33013
  {
@@ -33037,7 +33038,8 @@
33037
33038
  "day-ross"
33038
33039
  ],
33039
33040
  "asked": [
33040
- "australia-post"
33041
+ "australia-post",
33042
+ "day-ross"
33041
33043
  ]
33042
33044
  },
33043
33045
  {
@@ -35872,7 +35874,8 @@
35872
35874
  "day-ross"
35873
35875
  ],
35874
35876
  "asked": [
35875
- "australia-post"
35877
+ "australia-post",
35878
+ "day-ross"
35876
35879
  ]
35877
35880
  },
35878
35881
  {
@@ -35884,7 +35887,8 @@
35884
35887
  "day-ross"
35885
35888
  ],
35886
35889
  "asked": [
35887
- "australia-post"
35890
+ "australia-post",
35891
+ "day-ross"
35888
35892
  ]
35889
35893
  },
35890
35894
  {
@@ -35896,7 +35900,8 @@
35896
35900
  "day-ross"
35897
35901
  ],
35898
35902
  "asked": [
35899
- "australia-post"
35903
+ "australia-post",
35904
+ "day-ross"
35900
35905
  ]
35901
35906
  },
35902
35907
  {
@@ -37615,7 +37620,8 @@
37615
37620
  "day-ross"
37616
37621
  ],
37617
37622
  "asked": [
37618
- "australia-post"
37623
+ "australia-post",
37624
+ "day-ross"
37619
37625
  ]
37620
37626
  },
37621
37627
  {
@@ -37627,7 +37633,8 @@
37627
37633
  "day-ross"
37628
37634
  ],
37629
37635
  "asked": [
37630
- "australia-post"
37636
+ "australia-post",
37637
+ "day-ross"
37631
37638
  ]
37632
37639
  },
37633
37640
  {
@@ -1470,7 +1470,8 @@ var De = {
1470
1470
  timezone: "UTC",
1471
1471
  tracking: {
1472
1472
  mode: "automatic",
1473
- adapter: "asendia"
1473
+ adapter: "asendia",
1474
+ localClocks: !0
1474
1475
  },
1475
1476
  canaryUrl: "https://a1.asendiausa.com/tracking/",
1476
1477
  trackingUrlTemplate: "https://track.asendia.com/track/{trackingNumber}",
@@ -1770,6 +1771,7 @@ var De = {
1770
1771
  parcelforce: {
1771
1772
  displayName: "Parcelforce Worldwide",
1772
1773
  color: "#9d0f11",
1774
+ aliases: ["Parcelforce"],
1773
1775
  countries: ["GB"],
1774
1776
  selectable: !0,
1775
1777
  timezone: "UTC",
@@ -4436,9 +4438,12 @@ var De = {
4436
4438
  timezone: "America/Moncton",
4437
4439
  tracking: {
4438
4440
  mode: "automatic",
4439
- adapter: "universal"
4441
+ adapter: "day-ross",
4442
+ recognitionRank: 38,
4443
+ localClocks: !0
4440
4444
  },
4441
- canaryUrl: "https://dayross.com/",
4445
+ canaryUrl: "https://dayross.com/track-shipments",
4446
+ trackingSearchUrl: "https://dayross.com/track-shipments",
4442
4447
  linkRules: [],
4443
4448
  detectionRules: [{
4444
4449
  pattern: "^(?:MRO|MTN|SMI|SML|XTO)\\d{7}$",
@@ -5564,11 +5569,25 @@ var De = {
5564
5569
  timezone: "Europe/Stockholm",
5565
5570
  tracking: {
5566
5571
  mode: "automatic",
5567
- adapter: "universal"
5572
+ adapter: "instabox",
5573
+ requirements: [{
5574
+ field: "trackingUrl",
5575
+ validator: "instaboxCapabilityUrl",
5576
+ optional: !0,
5577
+ label: "Instabox notification URL",
5578
+ type: "url",
5579
+ placeholder: "https://track.instabox.com/…",
5580
+ help: "The complete notification link opens your parcel history. Without it, other sources are asked."
5581
+ }]
5568
5582
  },
5569
- canaryUrl: "https://track.instabox.com/en",
5583
+ canaryUrl: "https://track.instabox.com/",
5570
5584
  trackingSearchUrl: "https://track.instabox.com/en",
5571
- linkRules: [],
5585
+ linkRules: [{
5586
+ domains: ["track.instabox.com"],
5587
+ pathPattern: "^/[a-z]{2}(?:-[A-Z]{2})?/[A-Za-z0-9]{4,40}(?:/locker-to-locker-recipient)?/?$",
5588
+ path: "^/[a-z]{2}(?:-[A-Z]{2})?/([A-Za-z0-9]{4,40})(?:/locker-to-locker-recipient)?/?$",
5589
+ keepsCapabilityUrl: !0
5590
+ }],
5572
5591
  detectionRules: []
5573
5592
  },
5574
5593
  intelcom: {
@@ -6507,15 +6526,22 @@ var De = {
6507
6526
  timezone: "America/New_York",
6508
6527
  tracking: {
6509
6528
  mode: "automatic",
6510
- adapter: "universal"
6529
+ adapter: "saia",
6530
+ recognitionRank: 12,
6531
+ localClocks: !0
6511
6532
  },
6512
6533
  canaryUrl: "https://www.saia.com/track",
6513
- trackingUrlTemplate: "https://www.saia.com/track?pro={trackingNumber}",
6534
+ trackingUrlTemplate: "https://www.saia.com/track/details;pro={trackingNumber}",
6514
6535
  trackingSearchUrl: "https://www.saia.com/track",
6515
6536
  linkRules: [{
6516
6537
  domains: ["saia.com"],
6517
6538
  pathPattern: "^/track/?$",
6518
6539
  params: ["pro"]
6540
+ }, {
6541
+ domains: ["saia.com"],
6542
+ pathPattern: "^/track/details(?:/|;|$)",
6543
+ path: "^/track/details;pro=(\\d+)",
6544
+ params: ["pro"]
6519
6545
  }],
6520
6546
  detectionRules: []
6521
6547
  },
@@ -6858,9 +6884,11 @@ var De = {
6858
6884
  timezone: "Asia/Shanghai",
6859
6885
  tracking: {
6860
6886
  mode: "automatic",
6861
- adapter: "universal"
6887
+ adapter: "wanbexpress",
6888
+ recognitionRank: 33,
6889
+ browserRecognitionRank: 33
6862
6890
  },
6863
- canaryUrl: "https://www.wanbexpress.com/",
6891
+ canaryUrl: "https://tracking.wanbexpress.com/",
6864
6892
  linkRules: [],
6865
6893
  detectionRules: [{
6866
6894
  pattern: "^WNB[A-Z]{2}\\d{10}YQ$",
@@ -6956,6 +6984,7 @@ var De = {
6956
6984
  mode: "automatic",
6957
6985
  adapter: "xpo-ltl",
6958
6986
  recognitionRank: 25,
6987
+ browserRecognitionRank: 25,
6959
6988
  localClocks: !0
6960
6989
  },
6961
6990
  canaryUrl: "https://www.xpo.com/",
@@ -12474,6 +12503,7 @@ var Qc = {
12474
12503
  "cyprus-post": 60,
12475
12504
  "dai-post": 62,
12476
12505
  dao: 515,
12506
+ "day-ross": 38,
12477
12507
  delhivery: 600,
12478
12508
  "dhl-ecommerce": 670,
12479
12509
  "dhl-ecommerce-es": 630,
@@ -12546,6 +12576,7 @@ var Qc = {
12546
12576
  redpack: 15,
12547
12577
  "relais-colis": 690,
12548
12578
  "rl-carriers": 5,
12579
+ saia: 12,
12549
12580
  sameday: 370,
12550
12581
  seur: 870,
12551
12582
  "slovak-parcel-service": 180,
@@ -12562,6 +12593,7 @@ var Qc = {
12562
12593
  uniuni: 770,
12563
12594
  venipak: 240,
12564
12595
  "vinted-go": 410,
12596
+ wanbexpress: 33,
12565
12597
  whistl: 320,
12566
12598
  "xpo-ltl": 25,
12567
12599
  "yurtici-kargo": 430,
@@ -12688,7 +12720,7 @@ function cl(e, t = /* @__PURE__ */ new Date()) {
12688
12720
  }
12689
12721
  //#endregion
12690
12722
  //#region core/catalog/urls.ts
12691
- var ll = "trackandtrace.planzergroup.com", ul = /^\/shared\/sendungen\/([^/]+)\/?$/, dl = /^[A-Za-z0-9_-]{32,256}$/, fl = "customeriberia.dachser.com", pl = "/customerarea/utilidades/seguimiento-publico/detalle", ml = /^[A-Za-z0-9_-]{4,256}$/, hl = /[\x00-\x1f\x7f]/, gl = /* @__PURE__ */ new Set([
12723
+ var ll = "trackandtrace.planzergroup.com", ul = /^\/shared\/sendungen\/([^/]+)\/?$/, dl = /^[A-Za-z0-9_-]{32,256}$/, fl = "customeriberia.dachser.com", pl = "/customerarea/utilidades/seguimiento-publico/detalle", ml = /^\/[a-z]{2}(?:-[A-Z]{2})?\/([A-Z0-9]{4,40})(?:\/locker-to-locker-recipient)?\/?$/i, hl = /^[A-Za-z0-9_-]{4,256}$/, gl = /[\x00-\x1f\x7f]/, _l = /* @__PURE__ */ new Set([
12692
12724
  "hash",
12693
12725
  "cliente",
12694
12726
  "numeroUnico",
@@ -12703,7 +12735,22 @@ var ll = "trackandtrace.planzergroup.com", ul = /^\/shared\/sendungen\/([^/]+)\/
12703
12735
  "origen",
12704
12736
  "usuario"
12705
12737
  ]);
12706
- function _l(e, n) {
12738
+ function vl(e, n) {
12739
+ let r;
12740
+ try {
12741
+ r = new URL(e.trim());
12742
+ } catch {
12743
+ throw TypeError("Paste the complete Instabox notification URL");
12744
+ }
12745
+ if (e.length > 4096 || r.protocol !== "https:" || r.hostname !== "track.instabox.com" || r.username || r.password || r.port && r.port !== "443" || r.hash) throw TypeError("Instabox notification links must use https://track.instabox.com");
12746
+ let i = ml.exec(r.pathname);
12747
+ if (!i || i[1].toUpperCase() !== t(n)) throw TypeError("The Instabox URL must name this complete parcel identifier");
12748
+ let a = [...r.searchParams].filter(([e]) => e === "authCode" || e === "c");
12749
+ if (a.length !== 1 || !/^[A-Za-z0-9_-]{16,160}$/.test(a[0][1])) throw TypeError("The Instabox notification URL must include its verification code");
12750
+ for (let [e, t] of r.searchParams) if (!["authCode", "c"].includes(e) && (!/^utm_(?:source|medium|campaign|content|term)$/.test(e) || t.length > 256)) throw TypeError("The Instabox URL contains an unsupported parameter");
12751
+ return r.pathname = r.pathname.replace(i[1], t(n)), r.search = new URLSearchParams([a[0]]).toString(), r.toString();
12752
+ }
12753
+ function yl(e, n) {
12707
12754
  let r = e.trim();
12708
12755
  if (r.length < 1 || r.length > 4096) throw TypeError("Paste the complete Planzer tracking URL");
12709
12756
  let i;
@@ -12726,7 +12773,7 @@ function _l(e, n) {
12726
12773
  if (s.length !== 1 || !dl.test(s[0])) throw TypeError("The Planzer URL must include its accessKey");
12727
12774
  return i.toString();
12728
12775
  }
12729
- function vl(e, n) {
12776
+ function bl(e, n) {
12730
12777
  let r = e.trim();
12731
12778
  if (r.length < 1 || r.length > 4096) throw TypeError("Paste the complete Dachser tracking URL");
12732
12779
  let i;
@@ -12745,25 +12792,25 @@ function vl(e, n) {
12745
12792
  if (a !== pl && a !== `${pl}/`) throw TypeError("Paste a Dachser public shipment detail URL");
12746
12793
  let o = /* @__PURE__ */ new Map();
12747
12794
  for (let [e, t] of i.searchParams) {
12748
- if (!gl.has(e)) throw TypeError("The Dachser URL contains an unsupported parameter");
12795
+ if (!_l.has(e)) throw TypeError("The Dachser URL contains an unsupported parameter");
12749
12796
  if (o.has(e)) throw TypeError("The Dachser URL contains a duplicate parameter");
12750
- if (!t || t.length > 256 || hl.test(t)) throw TypeError("The Dachser URL contains an invalid parameter");
12797
+ if (!t || t.length > 256 || gl.test(t)) throw TypeError("The Dachser URL contains an invalid parameter");
12751
12798
  o.set(e, t);
12752
12799
  }
12753
12800
  let s = o.get("numeroUnico");
12754
12801
  if (!s) throw TypeError("The Dachser URL must include its shipment number");
12755
12802
  if (t(s) !== t(n)) throw TypeError("The Dachser URL belongs to a different tracking number");
12756
- let c = o.get("hash"), l = o.get("clave"), u = o.get("fecha"), d = !!(c && ml.test(c)), f = !!(l && u && ml.test(l) && /^\d{8}$/.test(u));
12803
+ let c = o.get("hash"), l = o.get("clave"), u = o.get("fecha"), d = !!(c && hl.test(c)), f = !!(l && u && hl.test(l) && /^\d{8}$/.test(u));
12757
12804
  if (!d && !f) throw TypeError("The Dachser URL must include its access parameters");
12758
12805
  return i.protocol = "https:", i.hostname = fl, i.port = "", i.toString();
12759
12806
  }
12760
12807
  //#endregion
12761
12808
  //#region core/catalog/postcode.ts
12762
- var yl = /^(?=.{3,12}$)(?=.*\d)[A-Z0-9]+(?:[ -][A-Z0-9]+)*$/;
12763
- function bl(e) {
12809
+ var xl = /^(?=.{3,12}$)(?=.*\d)[A-Z0-9]+(?:[ -][A-Z0-9]+)*$/;
12810
+ function Sl(e) {
12764
12811
  return e.trim().toUpperCase().replace(/\s+/g, " ");
12765
12812
  }
12766
- function xl(e) {
12813
+ function Cl(e) {
12767
12814
  let t = e.toUpperCase().replace(/\s+/g, "");
12768
12815
  if (/^(?:0[1-9]|[1-8]\d|9[0-5]|97|98)\d{3}$/.test(t)) return t;
12769
12816
  let n = /^(?:(BE?|LU?)-?)?([1-9]\d{3})$/.exec(t);
@@ -12771,17 +12818,17 @@ function xl(e) {
12771
12818
  }
12772
12819
  //#endregion
12773
12820
  //#region core/catalog/inputs.ts
12774
- function Sl(e, t) {
12821
+ function wl(e, t) {
12775
12822
  return e === "mondial-relay" && /^(?:\d{10}|\d{12}|\d{26})$/.test(t);
12776
12823
  }
12777
- function Cl(e, t, n, r) {
12824
+ function Tl(e, t, n, r) {
12778
12825
  let i = {
12779
12826
  trackingUrl: n.trim() || null,
12780
12827
  postcode: r.trim() || null
12781
12828
  };
12782
12829
  if (e === "mondial-relay" && /^\d{26}$/.test(t) && !we(t)) throw TypeError("Invalid Mondial Relay barcode");
12783
12830
  let a = new Map(Be(e, t).map((e) => [e.field, e]));
12784
- Sl(e, t) && i.postcode && a.set("postcode", {
12831
+ wl(e, t) && i.postcode && a.set("postcode", {
12785
12832
  field: "postcode",
12786
12833
  validator: "internationalPostcode"
12787
12834
  });
@@ -12794,9 +12841,12 @@ function Cl(e, t, n, r) {
12794
12841
  }
12795
12842
  switch (r.validator) {
12796
12843
  case "planzerSharedUrl":
12797
- i[n] = _l(a, t);
12844
+ i[n] = yl(a, t);
12798
12845
  break;
12799
12846
  case "dachserCapabilityUrl":
12847
+ i[n] = bl(a, t);
12848
+ break;
12849
+ case "instaboxCapabilityUrl":
12800
12850
  i[n] = vl(a, t);
12801
12851
  break;
12802
12852
  case "swissPostcode":
@@ -12810,8 +12860,8 @@ function Cl(e, t, n, r) {
12810
12860
  if (!/^\d{4,5}$/.test(a)) throw TypeError(`${g(e).displayName} requires a four- or five-digit delivery postcode`);
12811
12861
  break;
12812
12862
  case "internationalPostcode":
12813
- if (!yl.test(bl(a))) throw TypeError(`${g(e).displayName} requires a valid delivery postcode`);
12814
- i[n] = bl(a);
12863
+ if (!xl.test(Sl(a))) throw TypeError(`${g(e).displayName} requires a valid delivery postcode`);
12864
+ i[n] = Sl(a);
12815
12865
  break;
12816
12866
  case "paackPostcode": {
12817
12867
  let e = a.toLocaleUpperCase("en-US");
@@ -12820,7 +12870,7 @@ function Cl(e, t, n, r) {
12820
12870
  break;
12821
12871
  }
12822
12872
  case "colisPrivePostcode": {
12823
- let t = xl(a);
12873
+ let t = Cl(a);
12824
12874
  if (!t) throw TypeError(`${g(e).displayName} requires a French, Belgian or Luxembourg delivery postcode`);
12825
12875
  i[n] = t;
12826
12876
  break;
@@ -12830,12 +12880,12 @@ function Cl(e, t, n, r) {
12830
12880
  }
12831
12881
  return i;
12832
12882
  }
12833
- function wl(e) {
12834
- let t = bl(e);
12835
- if (!yl.test(t)) throw TypeError("A valid delivery postcode is required");
12883
+ function El(e) {
12884
+ let t = Sl(e);
12885
+ if (!xl.test(t)) throw TypeError("A valid delivery postcode is required");
12836
12886
  return t;
12837
12887
  }
12838
- var Tl = { carriers: [
12888
+ var Dl = { carriers: [
12839
12889
  {
12840
12890
  carrier: "dhl",
12841
12891
  direct: "Yes",
@@ -15586,7 +15636,7 @@ var Tl = { carriers: [
15586
15636
  },
15587
15637
  {
15588
15638
  carrier: "asendia",
15589
- direct: "Yes (Asendia USA)",
15639
+ direct: "Yes (Asendia USA and UK)",
15590
15640
  sample: "✓ 5",
15591
15641
  references: [
15592
15642
  { results: {
@@ -16811,80 +16861,80 @@ var Tl = { carriers: [
16811
16861
  }
16812
16862
  }]
16813
16863
  }
16814
- ] }, El = [
16864
+ ] }, Ol = [
16815
16865
  "Ship24",
16816
16866
  "ParcelsApp",
16817
16867
  "17TRACK",
16818
16868
  "Postal Ninja",
16819
16869
  "UPU"
16820
- ], Dl = /* @__PURE__ */ new Set([
16870
+ ], kl = /* @__PURE__ */ new Set([
16821
16871
  "no_history",
16822
16872
  "summary_only",
16823
16873
  "undated",
16824
16874
  "sign_in",
16825
16875
  "postcode_prompt"
16826
- ]), Ol = Tl.carriers, kl = new Map(Ol.map((e) => [e.carrier, e]));
16827
- function Al(e) {
16876
+ ]), Al = Dl.carriers, jl = new Map(Al.map((e) => [e.carrier, e]));
16877
+ function Ml(e) {
16828
16878
  return typeof e == "number" || e === "history" || typeof e == "object" && !!e;
16829
16879
  }
16830
- function jl(e, t) {
16831
- let n = t.filter((t) => t.results[e] !== void 0), r = n.some((t) => !t.stale && (Dl.has(t.results[e]) || t.results[e] === "wrong_carrier") && Object.entries(t.results).some(([t, n]) => t !== e && t !== "UPU" && Al(n)));
16832
- return n.some((t) => Al(t.results[e])) ? n.some((t) => typeof t.results[e] == "object") || r ? "partial" : "full" : n.some((t) => ["wrong_carrier", "refused"].includes(t.results[e])) ? "excluded" : n.some((t) => !t.stale && Dl.has(t.results[e])) ? "empty" : "unknown";
16880
+ function Nl(e, t) {
16881
+ let n = t.filter((t) => t.results[e] !== void 0), r = n.some((t) => !t.stale && (kl.has(t.results[e]) || t.results[e] === "wrong_carrier") && Object.entries(t.results).some(([t, n]) => t !== e && t !== "UPU" && Ml(n)));
16882
+ return n.some((t) => Ml(t.results[e])) ? n.some((t) => typeof t.results[e] == "object") || r ? "partial" : "full" : n.some((t) => ["wrong_carrier", "refused"].includes(t.results[e])) ? "excluded" : n.some((t) => !t.stale && kl.has(t.results[e])) ? "empty" : "unknown";
16833
16883
  }
16834
- function Ml(e) {
16835
- let t = e ? kl.get(e) : void 0;
16836
- return t ? Object.fromEntries(El.map((e) => [e, jl(e, t.references)])) : null;
16884
+ function Pl(e) {
16885
+ let t = e ? jl.get(e) : void 0;
16886
+ return t ? Object.fromEntries(Ol.map((e) => [e, Nl(e, t.references)])) : null;
16837
16887
  }
16838
16888
  //#endregion
16839
16889
  //#region providers/plan.ts
16840
- var Nl = [
16890
+ var Fl = [
16841
16891
  "ParcelsApp",
16842
16892
  "Ship24",
16843
16893
  "17TRACK",
16844
16894
  "UPU"
16845
- ], Pl = /* @__PURE__ */ new Set(["17TRACK", "Postal Ninja"]);
16846
- function Fl(e) {
16895
+ ], Il = /* @__PURE__ */ new Set(["17TRACK", "Postal Ninja"]);
16896
+ function Ll(e) {
16847
16897
  return e === "ParcelsApp" ? 45e3 : e === "UPU" ? 8e3 : 3e4;
16848
16898
  }
16849
- function Il(e) {
16899
+ function Rl(e) {
16850
16900
  return e && /^\d{10}$/.test(t(e)) ? "Ship24" : e && /^[CL][A-Z]\d{9}CN$/.test(t(e)) && v(e) ? "17TRACK" : void 0;
16851
16901
  }
16852
- var Ll = {
16902
+ var zl = {
16853
16903
  full: 0,
16854
16904
  partial: 1,
16855
16905
  unknown: 2,
16856
16906
  empty: 3,
16857
16907
  excluded: 4
16858
16908
  };
16859
- function Rl(e, t) {
16860
- let n = Ll[e?.[t] ?? "unknown"];
16861
- return t === "UPU" ? Ll.unknown : t === "Postal Ninja" ? Math.max(n, Ll.empty) : n;
16862
- }
16863
- var zl = (e) => e === "UPU" ? 2 : +(e === "Postal Ninja");
16864
16909
  function Bl(e, t) {
16910
+ let n = zl[e?.[t] ?? "unknown"];
16911
+ return t === "UPU" ? zl.unknown : t === "Postal Ninja" ? Math.max(n, zl.empty) : n;
16912
+ }
16913
+ var Vl = (e) => e === "UPU" ? 2 : +(e === "Postal Ninja");
16914
+ function Hl(e, t) {
16865
16915
  let n = (e) => e !== "UPU" && t?.[e] === "excluded";
16866
- return (e.some((e) => e !== "UPU" && !n(e)) ? e.filter((e) => !n(e)) : [...e]).sort((n, r) => zl(n) - zl(r) || Rl(t, n) - Rl(t, r) || Number(Pl.has(n)) - Number(Pl.has(r)) || e.indexOf(n) - e.indexOf(r));
16916
+ return (e.some((e) => e !== "UPU" && !n(e)) ? e.filter((e) => !n(e)) : [...e]).sort((n, r) => Vl(n) - Vl(r) || Bl(t, n) - Bl(t, r) || Number(Il.has(n)) - Number(Il.has(r)) || e.indexOf(n) - e.indexOf(r));
16867
16917
  }
16868
- function Vl(e = {}) {
16918
+ function Ul(e = {}) {
16869
16919
  let { trackingNumber: t, enablePostalNinja: n = !1 } = e, r = (n ? [
16870
16920
  "ParcelsApp",
16871
16921
  "Ship24",
16872
16922
  "17TRACK",
16873
16923
  "Postal Ninja",
16874
16924
  "UPU"
16875
- ] : [...Nl]).filter((e) => e !== "UPU" || t === void 0 || v(t)), i = (e.carriers ?? []).find((e) => Ml(e)) ?? null, a = Ml(i), o = Bl(r, a), s = Il(t);
16925
+ ] : [...Fl]).filter((e) => e !== "UPU" || t === void 0 || v(t)), i = (e.carriers ?? []).find((e) => Pl(e)) ?? null, a = Pl(i), o = Hl(r, a), s = Rl(t);
16876
16926
  return {
16877
16927
  sources: s ? [s, ...o.filter((e) => e !== s)] : o,
16878
16928
  carrier: i,
16879
16929
  tier: (e) => a?.[e] ?? "unknown",
16880
- rank: (e) => Rl(a, e)
16930
+ rank: (e) => Bl(a, e)
16881
16931
  };
16882
16932
  }
16883
- function Hl(e = !1, t) {
16884
- return Vl({
16933
+ function Wl(e = !1, t) {
16934
+ return Ul({
16885
16935
  trackingNumber: t,
16886
16936
  enablePostalNinja: e
16887
16937
  }).sources;
16888
16938
  }
16889
16939
  //#endregion
16890
- export { je as AMAZON_NUMBER_PATTERN, He as AUTOMATIC_CARRIER_IDS, Pl as BROWSER_SOURCES, te as BudgetExceededError, _ as CARRIERS, De as CARRIER_CATALOG, h as CARRIER_DEFINITIONS, Oe as CARRIER_IDS, Ue as CARRIER_NAMES, a as CarrierError, l as ChallengeError, Ho as EXPLICIT_OFFSET_PATTERN, s as IndeterminateError, p as InputRequiredError, m as InvalidInputError, $c as MAX_RECOGNITIONS, d as MaintenanceError, c as NoHistoryError, o as NotFoundError, u as RateLimitedError, Ze as SELECTABLE_CARRIERS, Ae as STAGES, f as SchemaError, zt as TRACKING_CANDIDATE_PATTERNS, We as TRACKING_LINK_RULES, ee as TransportError, Nl as UNIVERSAL_SOURCES, re as UpstreamHttpError, ie as UpstreamNetworkError, Be as activeRequirements, Pe as amazonMarketplace, Fe as amazonOrdersUrl, Ie as amazonShippingOrigin, Le as amazonShippingUrl, gs as calendarDay, us as canadaProvinceTimeZone, ze as carrierAdapter, g as carrierDefinition, oe as carrierErrorKind, Xe as carrierInfo, Ge as carrierLinkRules, Qe as carrierRequirements, Re as carrierTimezone, Pt as checksumRejections, mc as classifyStage, lc as classifyWording, is as countryCode, as as countryTimeZone, Mc as deliveryHandoff, Ft as detectCarrier, y as detectCarrierMatch, ms as epochMillisTime, hs as epochSecondsTime, ce as errorTypeOf, Es as eventPoint, Wo as explicitOffsetTime, Zc as failureHint, Xc as failureKind, Yc as fillPartialAnswer, Q as firstOccurrence, r as formatTrackingNumber, jc as hasDirectHandoffAdapter, hc as inferStage, Me as isAmazonTrackingNumber, Jc as isPartialAnswer, n as isPlanzerSharedTrackingNumber, it as isValidCorreosSpainCheckLetter, me as isValidDhlExpressWaybill, st as isValidDpdParcelNumber, gt as isValidGlsParcelNumber, _t as isValidHermesParcelNumber, we as isValidMondialRelayBarcode, Se as isValidPocztaPolskaBarcode, v as isValidS10TrackingNumber, Ce as isValidSscc, ge as isValidTntConsignmentNumber, Dt as isValidUspsPackageBarcode, Ko as isoTime, Ut as keywordNumberInText, cc as languageStageStatus, tt as localizedCarrierUrl, Ke as matchesDomain, Jo as mislabeledLocalTime, Yo as mislabeledWallTime, Cl as normalizeCarrierInputs, Ds as normalizeCarrierResult, wl as normalizeDeliveryPostcode, t as normalizeTrackingNumber, Bl as orderUniversalSources, Xt as parseTrackingInput, Il as priorityUniversalSource, nl as recognitionCandidates, el as recognitionNumberShape, il as recognizeAll, Bt as recognizedNumberInText, ps as regionHasTown, Ve as requiredRequirements, $e as requirementSatisfied, Ne as requiresAmazonAccount, _c as resolveResult, pc as resultHasUpdate, fc as resultStage, se as retryAfterMsOf, Qo as settleGuessedClocks, cl as settleRecognition, Xo as sharedClockZone, gc as stageSource, xt as supportsSwissPostHandoff, os as timeZoneCountry, ds as townKey, sc as trackingLanguageStage, Je as trackingLink, qe as trackingNumberForLink, et as tracksAutomatically, Vl as universalPlan, Fl as universalSourceBudget, Hl as universalSources, cs as usStateTimeZone, Et as uspsPackageIdentifier, Lt as validTrackingNumber, vl as validateDachserTrackingUrl, _l as validatePlanzerSharedUrl, uc as wordingStage, Go as zonedTime };
16940
+ export { je as AMAZON_NUMBER_PATTERN, He as AUTOMATIC_CARRIER_IDS, Il as BROWSER_SOURCES, te as BudgetExceededError, _ as CARRIERS, De as CARRIER_CATALOG, h as CARRIER_DEFINITIONS, Oe as CARRIER_IDS, Ue as CARRIER_NAMES, a as CarrierError, l as ChallengeError, Ho as EXPLICIT_OFFSET_PATTERN, s as IndeterminateError, p as InputRequiredError, m as InvalidInputError, $c as MAX_RECOGNITIONS, d as MaintenanceError, c as NoHistoryError, o as NotFoundError, u as RateLimitedError, Ze as SELECTABLE_CARRIERS, Ae as STAGES, f as SchemaError, zt as TRACKING_CANDIDATE_PATTERNS, We as TRACKING_LINK_RULES, ee as TransportError, Fl as UNIVERSAL_SOURCES, re as UpstreamHttpError, ie as UpstreamNetworkError, Be as activeRequirements, Pe as amazonMarketplace, Fe as amazonOrdersUrl, Ie as amazonShippingOrigin, Le as amazonShippingUrl, gs as calendarDay, us as canadaProvinceTimeZone, ze as carrierAdapter, g as carrierDefinition, oe as carrierErrorKind, Xe as carrierInfo, Ge as carrierLinkRules, Qe as carrierRequirements, Re as carrierTimezone, Pt as checksumRejections, mc as classifyStage, lc as classifyWording, is as countryCode, as as countryTimeZone, Mc as deliveryHandoff, Ft as detectCarrier, y as detectCarrierMatch, ms as epochMillisTime, hs as epochSecondsTime, ce as errorTypeOf, Es as eventPoint, Wo as explicitOffsetTime, Zc as failureHint, Xc as failureKind, Yc as fillPartialAnswer, Q as firstOccurrence, r as formatTrackingNumber, jc as hasDirectHandoffAdapter, hc as inferStage, Me as isAmazonTrackingNumber, Jc as isPartialAnswer, n as isPlanzerSharedTrackingNumber, it as isValidCorreosSpainCheckLetter, me as isValidDhlExpressWaybill, st as isValidDpdParcelNumber, gt as isValidGlsParcelNumber, _t as isValidHermesParcelNumber, we as isValidMondialRelayBarcode, Se as isValidPocztaPolskaBarcode, v as isValidS10TrackingNumber, Ce as isValidSscc, ge as isValidTntConsignmentNumber, Dt as isValidUspsPackageBarcode, Ko as isoTime, Ut as keywordNumberInText, cc as languageStageStatus, tt as localizedCarrierUrl, Ke as matchesDomain, Jo as mislabeledLocalTime, Yo as mislabeledWallTime, Tl as normalizeCarrierInputs, Ds as normalizeCarrierResult, El as normalizeDeliveryPostcode, t as normalizeTrackingNumber, Hl as orderUniversalSources, Xt as parseTrackingInput, Rl as priorityUniversalSource, nl as recognitionCandidates, el as recognitionNumberShape, il as recognizeAll, Bt as recognizedNumberInText, ps as regionHasTown, Ve as requiredRequirements, $e as requirementSatisfied, Ne as requiresAmazonAccount, _c as resolveResult, pc as resultHasUpdate, fc as resultStage, se as retryAfterMsOf, Qo as settleGuessedClocks, cl as settleRecognition, Xo as sharedClockZone, gc as stageSource, xt as supportsSwissPostHandoff, os as timeZoneCountry, ds as townKey, sc as trackingLanguageStage, Je as trackingLink, qe as trackingNumberForLink, et as tracksAutomatically, Ul as universalPlan, Ll as universalSourceBudget, Wl as universalSources, cs as usStateTimeZone, Et as uspsPackageIdentifier, Lt as validTrackingNumber, bl as validateDachserTrackingUrl, vl as validateInstaboxTrackingUrl, yl as validatePlanzerSharedUrl, uc as wordingStage, Go as zonedTime };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Asendia tracking through Asendia USA's A1 platform.
2
+ * Asendia tracking through Asendia USA's A1 platform, then Asendia UK's tracker.
3
3
  *
4
4
  * Protocol provenance (inspected 2026-09-22):
5
5
  * - The official public page https://a1.asendiausa.com/tracking/ (the same
@@ -24,18 +24,21 @@
24
24
  * backend/src/sources/implementations/asendia.ts) and deingithub/beanstalk
25
25
  * (beanstalk/parcel.py).
26
26
  *
27
- * Coverage: parcels on the A1 platform only. Asendia's global portal
28
- * track.asendia.com, which serves the other subsidiaries, needs a Cloudflare
29
- * Turnstile token for every search and is not used here (see probe.ts). A
30
- * number A1 does not know is a not-found for this adapter only; routing then
31
- * tries the universal providers in the same check.
27
+ * Coverage: A1 answers for parcels on Asendia USA's platform. The adapter
28
+ * then asks Asendia UK's tracker (uk.ts), which serves parcels Asendia UK
29
+ * carries, when A1 does not know the number, fails, or holds its registration
30
+ * alone. Asendia's global portal track.asendia.com, which serves the
31
+ * other subsidiaries, needs a Cloudflare Turnstile token for every search and
32
+ * is not used here (see probe.ts). A number neither tracker knows is a
33
+ * not-found for this adapter only; routing then tries the universal providers
34
+ * in the same check.
32
35
  *
33
36
  * Privacy: events keep their time, wording, code and city, province and
34
37
  * country. Address lines and postal codes in `eventLocationDetails` are never
35
38
  * read, and nothing else from the summary is copied except the destination
36
39
  * country, weight and the declared last-mile reference.
37
40
  */
38
- import type { AdapterFactory, TrackingContext } from '../../core/adapter/index.js';
41
+ import { type AdapterFactory, type TrackingContext } from '../../core/adapter/index.js';
39
42
  import type { CarrierResult } from '../../core/result/index.js';
40
43
  export interface AsendiaA1PublicConfig {
41
44
  /** The API origin, e.g. https://a1reportapi.asendiaprod.com. */