universal-parcel-scraper 0.580.0-main.2721 → 0.581.0-main.2728

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 (36) hide show
  1. package/README.md +3 -3
  2. package/data/catalog.json +30 -0
  3. package/data/coverage-summary.json +2 -2
  4. package/data/detection-golden.json +24 -0
  5. package/dist/browser/scraper.js +28 -1
  6. package/dist/carriers/dhl-express/adapter.js +5 -2
  7. package/dist/carriers/dhl-express/mobile.d.ts +2 -0
  8. package/dist/carriers/dhl-express/mobile.js +6 -2
  9. package/dist/carriers/dhlink/status.js +1 -0
  10. package/dist/carriers/dhlink/statuses.json +1 -0
  11. package/dist/carriers/globalpost/status.d.ts +1 -1
  12. package/dist/carriers/globalpost/status.js +7 -2
  13. package/dist/carriers/globalpost/statuses.json +2 -0
  14. package/dist/carriers/gzyl/hualei.d.ts +18 -0
  15. package/dist/carriers/gzyl/hualei.js +9 -4
  16. package/dist/carriers/imile/status.js +1 -0
  17. package/dist/carriers/imile/statuses.json +1 -0
  18. package/dist/carriers/kun-express/adapter.d.ts +6 -0
  19. package/dist/carriers/kun-express/adapter.js +9 -0
  20. package/dist/carriers/kun-express/carrier.json +97 -0
  21. package/dist/carriers/kun-express/numbers.json +62 -0
  22. package/dist/carriers/kun-express/parser.d.ts +31 -0
  23. package/dist/carriers/kun-express/parser.js +44 -0
  24. package/dist/carriers/kun-express/status.d.ts +8 -0
  25. package/dist/carriers/kun-express/status.js +11 -0
  26. package/dist/carriers/kun-express/statuses.json +18 -0
  27. package/dist/carriers/mayiyinfu/statuses.json +3 -1
  28. package/dist/core/catalog/statusMaps.js +2 -1
  29. package/dist/data/catalog.json +30 -0
  30. package/dist/generated/catalog.d.ts +20 -1
  31. package/dist/generated/catalog.js +32 -0
  32. package/dist/generated/registry.js +3 -0
  33. package/dist/providers/parcelsapp/adapter.js +10 -3
  34. package/dist/providers/shared/result.js +4 -2
  35. package/dist/server/openapi.json +1 -1
  36. package/package.json +1 -1
package/README.md CHANGED
@@ -13,9 +13,9 @@ 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 **604 dedicated adapters** and **5 universal fallbacks**
16
+ **3,500+ carriers** through **605 dedicated adapters** and **5 universal fallbacks**
17
17
 
18
- <sub>777 catalog entries · 134 countries represented</sub>
18
+ <sub>778 catalog entries · 134 countries represented</sub>
19
19
  <!-- /GENERATED:summary -->
20
20
 
21
21
  [Try it](#try-it) · [Ways to run it](#ways-to-run-it) · [Benchmark](#benchmark) · [Carriers](carriers/) · [Add a carrier](CONTRIBUTING.md)
@@ -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 16,189 such statuses, each filed under one stage.
158
+ The carrier folders record 16,208 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
@@ -18417,6 +18417,36 @@
18417
18417
  }
18418
18418
  ]
18419
18419
  },
18420
+ "kun-express": {
18421
+ "displayName": "Kun Express",
18422
+ "color": "#0761ff",
18423
+ "aliases": [
18424
+ "KUN",
18425
+ "KUNEXPRESS",
18426
+ "KunExpress",
18427
+ "鲲辰",
18428
+ "鯤辰",
18429
+ "杭州鲲辰跨境供应链管理有限公司"
18430
+ ],
18431
+ "countries": [
18432
+ "CN"
18433
+ ],
18434
+ "selectable": true,
18435
+ "timezone": "Asia/Shanghai",
18436
+ "tracking": {
18437
+ "mode": "automatic",
18438
+ "adapter": "kun-express",
18439
+ "localClocks": true
18440
+ },
18441
+ "canaryUrl": "https://t.17track.net/",
18442
+ "linkRules": [],
18443
+ "detectionRules": [
18444
+ {
18445
+ "pattern": "^KUN\\d{10}$",
18446
+ "confidence": "high"
18447
+ }
18448
+ ]
18449
+ },
18420
18450
  "kunyoung": {
18421
18451
  "displayName": "Kunyoung Express",
18422
18452
  "color": "#04378c",
@@ -1,6 +1,6 @@
1
1
  {
2
- "catalog": 777,
3
- "activeAdapters": 604,
2
+ "catalog": 778,
3
+ "activeAdapters": 605,
4
4
  "countries": 134,
5
5
  "referenceCarriers": 100,
6
6
  "comparison": {
@@ -76158,6 +76158,30 @@
76158
76158
  "la-poste"
76159
76159
  ]
76160
76160
  },
76161
+ {
76162
+ "input": "KUN6666669444",
76163
+ "carrier": "kun-express",
76164
+ "confidence": "high",
76165
+ "candidates": [
76166
+ "kun-express"
76167
+ ]
76168
+ },
76169
+ {
76170
+ "input": "KUN8000015561",
76171
+ "carrier": "kun-express",
76172
+ "confidence": "high",
76173
+ "candidates": [
76174
+ "kun-express"
76175
+ ]
76176
+ },
76177
+ {
76178
+ "input": "KUN9991027071",
76179
+ "carrier": "kun-express",
76180
+ "confidence": "high",
76181
+ "candidates": [
76182
+ "kun-express"
76183
+ ]
76184
+ },
76161
76185
  {
76162
76186
  "input": "KYV009956937",
76163
76187
  "carrier": "purolator",
@@ -14127,6 +14127,32 @@ var Ye = {
14127
14127
  confidence: "high"
14128
14128
  }]
14129
14129
  },
14130
+ "kun-express": {
14131
+ displayName: "Kun Express",
14132
+ color: "#0761ff",
14133
+ aliases: [
14134
+ "KUN",
14135
+ "KUNEXPRESS",
14136
+ "KunExpress",
14137
+ "鲲辰",
14138
+ "鯤辰",
14139
+ "杭州鲲辰跨境供应链管理有限公司"
14140
+ ],
14141
+ countries: ["CN"],
14142
+ selectable: !0,
14143
+ timezone: "Asia/Shanghai",
14144
+ tracking: {
14145
+ mode: "automatic",
14146
+ adapter: "kun-express",
14147
+ localClocks: !0
14148
+ },
14149
+ canaryUrl: "https://t.17track.net/",
14150
+ linkRules: [],
14151
+ detectionRules: [{
14152
+ pattern: "^KUN\\d{10}$",
14153
+ confidence: "high"
14154
+ }]
14155
+ },
14130
14156
  kunyoung: {
14131
14157
  displayName: "Kunyoung Express",
14132
14158
  color: "#04378c",
@@ -23595,7 +23621,7 @@ var Ye = {
23595
23621
  rawPattern: "^\\d{2}-[A-Z0-9]{6}(?:[A-Z0-9]|[A-Z0-9]{4})?-ZR$"
23596
23622
  }]
23597
23623
  }
23598
- }, Xe = /* @__PURE__ */ "swiss-post.swiss-post-cargo.quickpac.planzer.aliexpress.sunyou.hermes.spring-gds.postlogistics.dachser.dhl.dhl-ecommerce.ups.amazon-logistics.amazon-shipping.fedex.gls-ch.dpd.dpd-fr.mondial-relay.relais-colis.la-poste.chronopost.gls-fr.colis-prive.geodis.colisweb.c-chez-vous.heppner.ciblex.paack.asendia.shipup.india-post.hermes-de.gls-de.delivengo.intl-post.unknown.royal-mail.parcelforce.evri.inpost.an-post.bpost.austrian-post.postnord.posti.correos-express.seur.mrw.nacex.ctt.ctt-express.poste-italiane.brt.ecoscooting.tipsa.ukrposhta.usps.canada-post.purolator.canpar.ontrac.speedx.uniuni.landmark-global.old-dominion.spee-dee.gofo.estafeta.correios-br.correos-chile.yunexpress.four-px.blue-dart.delhivery.nz-post.singapore-post.japan-post.sf-express.sto.yunda.yto.zto.jd-logistics.yamato.korea-post.thailand-post.dtdc.australia-post.hongkong-post.pos-malaysia.ninja-van.china-post.packeta.poczta-polska.bring-posten.aramex.tnt.correos-spain.yanwen.the-courier-guy.j-and-t.ems.139express.17feia.247express.2go.4-72.4sides.5post.99minutos.a-duie-pyle.a-tu-hora-express.a1-post.aaa-cooper.ab-courier.abf-freight.aci-express-kr.acs-courier.aeropost.aex-paraguay.afghan-post.air-star-xpress.airpak-express.ait-worldwide.ajex.akash-ganga.aks-express.alem-tat.algerie-poste.allegro-one.am-home-delivery.ameex.american-west-express.amerijet.ampm.andreani.anjun.anousith.anserx.anteraja.ap-cargo.apc-overnight.apc-postal-logistics.apple-express.aramex-au.aramex-nz.aras-kargo.arrow-xl.asyad-express.atlantic-courier.averitt.aymakan.azerpost.azul-cargo.bangladesh-post.barid-al-maghrib.belpost.best-express-my.best-express-vn.best-overnite-express.best-transport.better-trucks.bex-express.big-smart.bjs-home-delivery.blue-express.blueex.bombino.bookurier.border-express.bosta.botswana-post.box-now.bringer-parcel.bts-uz.budbee.buffalo-ex.bulgarian-posts.burd-delivery.bussgods.byhd.c3x.cacesa.campost.cargus.castores.cbl-logistica.ccfs.cdek.cdl.celeritas.central-transport.ceska-posta.ceva-logistics.chazki.chilexpress.chit-chats.chronodiali.chukou1.chunghwa-post.chunil.city-express-rs.citylink-express.citymail.citysprint.cj-logistics.cj-packet.closer-logistics.cne.codexpress.connect-couriers.coordinadora.copa-courier.corre.correo-argentino.correo-uruguayo.correos-bolivia.correos-cuba.correos-de-mexico.correos-el-salvador.correos-nicaragua.courier-center.courier-it.courier-plus-ng.couriersplease.credifin.cruz-del-sur.cse-russia.cst-italia.cttyex.custom-companies.cycloon.cyprus-post.d-express.daewoo-fastex.dai-post.daily-xpress.danske-fragtmaend.dao.day-ross.daylight-transport.dayton-freight.dellin.delnext.deppon.deprisa.designer-transport.dhl-ecommerce-es.dhl-ecommerce-nl.dhl-ecommerce-pl.dhl-ecommerce-uk.dhl-express.dhl-freight.dhlink.direct-couriers.direct-freight-express.direx.dnx-cargo.dobropost.dohrn-transfer.domain-logistics.domex.dpd-at.dpd-be.dpd-de.dpd-ie.dpd-nl.dpd-pl.dpd-pt.dpd-ro.dpd-uk.dpd-za.dpex.dragon-star-curier.drop2shop.dropp.dsv.dx.dynalogic.early-bird.easy-mail.ecms-express.eco-express-ae.econt.ecourier.egypt-post.ekart.elta.emile.emirates-post.ems-vietnam.energia-tk.energo.envia-colombia.envialia.eparcel-kr.epost-global.equick.estes.estes-forwarding.ethiopian-post.eurodis.euroexpress-ba.europochta.evdemo-lojistik.evri-uk.evropat.ewe.exelot.exline-kz.exmate.express-one.fan-courier.fargo-courier.fargo-uz.fastdrop.fastfrate.fedex-freight.fedex-pl.fermopoint.fg-delivery.first-delivery-tn.first-fly-express.first-line.flash-express.flash-express-ph.fleetex.fleetoptics.flippost.fliway.flyking.followmont.forward-air.forza-delivery.foxpost.franch-express.fukuyama.gaash.gati.gdex.gebrueder-weiss.geis.gel-express.geniki-taxydromiki.geodis-pl.ghana-post.ghn.ghtk.globalpost.gls-at.gls-es.gls-it.gls-pl.gms-worldwide.go-express.go4.gobolt.gofo-fr.gofo-it.gofo-nl.gogo-xpress.goodluck-courier.grand-slam-express.groupe-guilbault.gs-postbox.gsi-express.gta-airskip.gtl-goto.guatex.gzyl.hanjin.hapdong.happy-post.haypost.hct-logistics.helthjem.hepsijet.hercules-freight.hermes-at.hi-trans.hispapost.homexpress.horoz.hound-express.houng-ah-loun.hovership.hp-mostar.hr-parcel.hrvatska-posta.huahan.hunter-express.hywl.icc-worldwide.icl-express.ics-courier.idexpress.ids-logistik.ilyang-logis.imile.indah-logistik.instabox.integral-pack.intelcom.inter-courier.intereuropa.internet-express.interrapidisimo.intex-paketdienst.iran-post.israel-post.j-and-t-au.j-and-t-br.j-and-t-cargo.j-and-t-cn.j-and-t-de.j-and-t-middle-east.j-and-t-mx.jadlog.jamaica-post.janio.jcex.jeebly.jersey-post.jet-logistic.jetline-couriers.jhgj.jitsu.jne.jordan-post.jrs-express.jrt.js-express.jumppoint.kargoist.kazpost.kerry-tj.kex.kex-express-hk.kit-tk.kolay-gelsin.kronos-express.ktd.kuehne-nagel.kunyoung.kwick-box.kyoungdong.kyrgyz-post.l-post.la-poste-burkina-faso.la-poste-ci.la-poste-senegal.la-poste-tunisienne.laar-courier.labaih.lao-post.last-one-mile-coop.latvijas-pasts.lbc-express.leopards-courier.libanpost.liccardi.lietuvos-pastas.lightning-express.line-clear.lingdong.linhan.lion-parcel.logen.loggi.logistiq.logoix.loomis-express.lotte-global.lso.m-and-p.m-one.madhur-courier.magyar-posta.mailamericas.mailplus-au.mainfreight.major-express.makati-express.maltapost.mandae.maritime-ontario.maruti-air.matkahuolto.mauritius-post.mayiyinfu.mds-collivery.meest.messenger-cz.method.metropolitan-warehouse.micro-express.midland-transport.mng-kargo.mongol-infinity-post.montenegro-post.morning-global.mrl-global.mtscn.mylerz.naqel.nationex.ncs-courier.neighbour-express.nepal-post.netpost-vn.next-level-delivery.nhat-tin.nim-express.nipost.nippon-express.noest.nord-wheel.norsk-global.northline.nova-global.nova-poshta.nox.nz-couriers.oak-harbor.oca.ocasa.ocs-ana.olva-courier.omgo.omniva.one-world-express.opt-nc.orian.orlen-paczka.osm-worldwide.overseas-express.ozon-logistics.pack-man.packli-punkt.packlink.packs.pakistan-post.palletways.pandu-logistics.pannon-xp.paperfly.paquetexpress.parcelpoint.pargo.passport.pathao-courier.pavan-courier.paxel.paxi.pbt.pcp-express.pcs-logistics-vn.pdn-express.pdq-chile.pecom.peddler.pelican-express.peqasus-az.pfc-express.phlpost.pickupp.pickupp-sg.pigeon-express.pilot-freight.pitney-bowes.pitt-ohio.pmm.polaris-transport.pony-express.pos-indonesia.post-haste.post-luxembourg.posta-faroe.posta-kenya.posta-moldovei.posta-north-macedonia.posta-romana.posta-shqiptare.posta-slovenije.posta-srbije.postaplus.postex.postmedia-parcel-services.postplus.posturinn.ppl.precision-deliveries.pro-carrier.professional-couriers.prompt-xpress.pronto-lanka.proships.pts-worldwide-express.ptt.pullman-cargo.pushpak-courier.quantium-solutions.quicksilver-sa.quiqup.qwintry.raben.ram-hand-to-hand.redpack.redur.redx.relaytech.rivigo.rl-carriers.roadie.roadrunner.royal-express-mm.rpx-hk.rpx-indonesia.rr-express-sg.russian-post.saee.sagawa.sagawa-global.sahara-express.saia.sailpost.sameday.sapx-express.sat-ukraine.saudi-post.sbs-sokuhai.scg-express.seino.seko.sendex.sending.serpost.servientrega.seven-eleven-tw.sfc.shadowfax.shipa.shipblu.shipentegra.shiprocket.shree-anjani.shree-mahabali-express.shree-mahavir.shree-maruti.shree-nandan.sicepat.skroutz-last-mile.skyex-ae.skyking.skynet-sa.skynet-worldwide.skypostal.slgtrax.slovak-parcel-service.slovenska-posta.smsa-express.south-african-post-office.southeastern-freight-lines.sp-express.speed-and-safe.speedaf.speedex.speedpak.speedy.spx-br.spx-id.spx-my.spx-ph.spx-sg.spx-th.spx-tw.spx-vn.sri-lanka-post.st-courier.stallion-express.starex-az.starken.starlinks.steadfast.straightship.sundarban-courier.surat-kargo.swiftx.t-cat.t-group.tamdis.tanzania-posts.taxydema.tccs.tci-express.tcs-pakistan.tdn.tealca.team-express-ae.team-global-express.team-worldwide.tej-couriers.teleship.tfm-express.tforce-freight.tforce-logistics.thhy.tiki.tirupati-courier.tmm-express.tnt-it.today-kr.toptrans.torrestir.total-express.tp-logistics-th.trackon.tracx-logis.trans-o-flex.transaher.transcorp.transmission.transport-rdl.trendyol-express.tsjy.tst-cf-express.tufesa.tusass.tws-express.ubi-smart-parcel.ues-uy.united-delivery-service.united-worldwide-couriers.upaya.urbano.urvaam.uzbekistan-post.valmo.vasp-expresso.veloces.venipak.vestovoy.via-cargo.viettel-post.vimenpaq.vinted-go.vitran-express.vnpost.vozovoz.vrl-logistics.wahana.wanbexpress.ward-trucking.whistl.winion-logis.winit.x-express-ba.x-trac.xde-logistics.xdp.xlcourier.xpo-ltl.xpressbees.yalidine.yc-delivery.ycs-logistics.yilong-logistics.yimidida.yurtici-kargo.zajil.zeleris.zheldor.zoom-ve.zr-express".split("."), Ze = {
23624
+ }, Xe = /* @__PURE__ */ "swiss-post.swiss-post-cargo.quickpac.planzer.aliexpress.sunyou.hermes.spring-gds.postlogistics.dachser.dhl.dhl-ecommerce.ups.amazon-logistics.amazon-shipping.fedex.gls-ch.dpd.dpd-fr.mondial-relay.relais-colis.la-poste.chronopost.gls-fr.colis-prive.geodis.colisweb.c-chez-vous.heppner.ciblex.paack.asendia.shipup.india-post.hermes-de.gls-de.delivengo.intl-post.unknown.royal-mail.parcelforce.evri.inpost.an-post.bpost.austrian-post.postnord.posti.correos-express.seur.mrw.nacex.ctt.ctt-express.poste-italiane.brt.ecoscooting.tipsa.ukrposhta.usps.canada-post.purolator.canpar.ontrac.speedx.uniuni.landmark-global.old-dominion.spee-dee.gofo.estafeta.correios-br.correos-chile.yunexpress.four-px.blue-dart.delhivery.nz-post.singapore-post.japan-post.sf-express.sto.yunda.yto.zto.jd-logistics.yamato.korea-post.thailand-post.dtdc.australia-post.hongkong-post.pos-malaysia.ninja-van.china-post.packeta.poczta-polska.bring-posten.aramex.tnt.correos-spain.yanwen.the-courier-guy.j-and-t.ems.139express.17feia.247express.2go.4-72.4sides.5post.99minutos.a-duie-pyle.a-tu-hora-express.a1-post.aaa-cooper.ab-courier.abf-freight.aci-express-kr.acs-courier.aeropost.aex-paraguay.afghan-post.air-star-xpress.airpak-express.ait-worldwide.ajex.akash-ganga.aks-express.alem-tat.algerie-poste.allegro-one.am-home-delivery.ameex.american-west-express.amerijet.ampm.andreani.anjun.anousith.anserx.anteraja.ap-cargo.apc-overnight.apc-postal-logistics.apple-express.aramex-au.aramex-nz.aras-kargo.arrow-xl.asyad-express.atlantic-courier.averitt.aymakan.azerpost.azul-cargo.bangladesh-post.barid-al-maghrib.belpost.best-express-my.best-express-vn.best-overnite-express.best-transport.better-trucks.bex-express.big-smart.bjs-home-delivery.blue-express.blueex.bombino.bookurier.border-express.bosta.botswana-post.box-now.bringer-parcel.bts-uz.budbee.buffalo-ex.bulgarian-posts.burd-delivery.bussgods.byhd.c3x.cacesa.campost.cargus.castores.cbl-logistica.ccfs.cdek.cdl.celeritas.central-transport.ceska-posta.ceva-logistics.chazki.chilexpress.chit-chats.chronodiali.chukou1.chunghwa-post.chunil.city-express-rs.citylink-express.citymail.citysprint.cj-logistics.cj-packet.closer-logistics.cne.codexpress.connect-couriers.coordinadora.copa-courier.corre.correo-argentino.correo-uruguayo.correos-bolivia.correos-cuba.correos-de-mexico.correos-el-salvador.correos-nicaragua.courier-center.courier-it.courier-plus-ng.couriersplease.credifin.cruz-del-sur.cse-russia.cst-italia.cttyex.custom-companies.cycloon.cyprus-post.d-express.daewoo-fastex.dai-post.daily-xpress.danske-fragtmaend.dao.day-ross.daylight-transport.dayton-freight.dellin.delnext.deppon.deprisa.designer-transport.dhl-ecommerce-es.dhl-ecommerce-nl.dhl-ecommerce-pl.dhl-ecommerce-uk.dhl-express.dhl-freight.dhlink.direct-couriers.direct-freight-express.direx.dnx-cargo.dobropost.dohrn-transfer.domain-logistics.domex.dpd-at.dpd-be.dpd-de.dpd-ie.dpd-nl.dpd-pl.dpd-pt.dpd-ro.dpd-uk.dpd-za.dpex.dragon-star-curier.drop2shop.dropp.dsv.dx.dynalogic.early-bird.easy-mail.ecms-express.eco-express-ae.econt.ecourier.egypt-post.ekart.elta.emile.emirates-post.ems-vietnam.energia-tk.energo.envia-colombia.envialia.eparcel-kr.epost-global.equick.estes.estes-forwarding.ethiopian-post.eurodis.euroexpress-ba.europochta.evdemo-lojistik.evri-uk.evropat.ewe.exelot.exline-kz.exmate.express-one.fan-courier.fargo-courier.fargo-uz.fastdrop.fastfrate.fedex-freight.fedex-pl.fermopoint.fg-delivery.first-delivery-tn.first-fly-express.first-line.flash-express.flash-express-ph.fleetex.fleetoptics.flippost.fliway.flyking.followmont.forward-air.forza-delivery.foxpost.franch-express.fukuyama.gaash.gati.gdex.gebrueder-weiss.geis.gel-express.geniki-taxydromiki.geodis-pl.ghana-post.ghn.ghtk.globalpost.gls-at.gls-es.gls-it.gls-pl.gms-worldwide.go-express.go4.gobolt.gofo-fr.gofo-it.gofo-nl.gogo-xpress.goodluck-courier.grand-slam-express.groupe-guilbault.gs-postbox.gsi-express.gta-airskip.gtl-goto.guatex.gzyl.hanjin.hapdong.happy-post.haypost.hct-logistics.helthjem.hepsijet.hercules-freight.hermes-at.hi-trans.hispapost.homexpress.horoz.hound-express.houng-ah-loun.hovership.hp-mostar.hr-parcel.hrvatska-posta.huahan.hunter-express.hywl.icc-worldwide.icl-express.ics-courier.idexpress.ids-logistik.ilyang-logis.imile.indah-logistik.instabox.integral-pack.intelcom.inter-courier.intereuropa.internet-express.interrapidisimo.intex-paketdienst.iran-post.israel-post.j-and-t-au.j-and-t-br.j-and-t-cargo.j-and-t-cn.j-and-t-de.j-and-t-middle-east.j-and-t-mx.jadlog.jamaica-post.janio.jcex.jeebly.jersey-post.jet-logistic.jetline-couriers.jhgj.jitsu.jne.jordan-post.jrs-express.jrt.js-express.jumppoint.kargoist.kazpost.kerry-tj.kex.kex-express-hk.kit-tk.kolay-gelsin.kronos-express.ktd.kuehne-nagel.kun-express.kunyoung.kwick-box.kyoungdong.kyrgyz-post.l-post.la-poste-burkina-faso.la-poste-ci.la-poste-senegal.la-poste-tunisienne.laar-courier.labaih.lao-post.last-one-mile-coop.latvijas-pasts.lbc-express.leopards-courier.libanpost.liccardi.lietuvos-pastas.lightning-express.line-clear.lingdong.linhan.lion-parcel.logen.loggi.logistiq.logoix.loomis-express.lotte-global.lso.m-and-p.m-one.madhur-courier.magyar-posta.mailamericas.mailplus-au.mainfreight.major-express.makati-express.maltapost.mandae.maritime-ontario.maruti-air.matkahuolto.mauritius-post.mayiyinfu.mds-collivery.meest.messenger-cz.method.metropolitan-warehouse.micro-express.midland-transport.mng-kargo.mongol-infinity-post.montenegro-post.morning-global.mrl-global.mtscn.mylerz.naqel.nationex.ncs-courier.neighbour-express.nepal-post.netpost-vn.next-level-delivery.nhat-tin.nim-express.nipost.nippon-express.noest.nord-wheel.norsk-global.northline.nova-global.nova-poshta.nox.nz-couriers.oak-harbor.oca.ocasa.ocs-ana.olva-courier.omgo.omniva.one-world-express.opt-nc.orian.orlen-paczka.osm-worldwide.overseas-express.ozon-logistics.pack-man.packli-punkt.packlink.packs.pakistan-post.palletways.pandu-logistics.pannon-xp.paperfly.paquetexpress.parcelpoint.pargo.passport.pathao-courier.pavan-courier.paxel.paxi.pbt.pcp-express.pcs-logistics-vn.pdn-express.pdq-chile.pecom.peddler.pelican-express.peqasus-az.pfc-express.phlpost.pickupp.pickupp-sg.pigeon-express.pilot-freight.pitney-bowes.pitt-ohio.pmm.polaris-transport.pony-express.pos-indonesia.post-haste.post-luxembourg.posta-faroe.posta-kenya.posta-moldovei.posta-north-macedonia.posta-romana.posta-shqiptare.posta-slovenije.posta-srbije.postaplus.postex.postmedia-parcel-services.postplus.posturinn.ppl.precision-deliveries.pro-carrier.professional-couriers.prompt-xpress.pronto-lanka.proships.pts-worldwide-express.ptt.pullman-cargo.pushpak-courier.quantium-solutions.quicksilver-sa.quiqup.qwintry.raben.ram-hand-to-hand.redpack.redur.redx.relaytech.rivigo.rl-carriers.roadie.roadrunner.royal-express-mm.rpx-hk.rpx-indonesia.rr-express-sg.russian-post.saee.sagawa.sagawa-global.sahara-express.saia.sailpost.sameday.sapx-express.sat-ukraine.saudi-post.sbs-sokuhai.scg-express.seino.seko.sendex.sending.serpost.servientrega.seven-eleven-tw.sfc.shadowfax.shipa.shipblu.shipentegra.shiprocket.shree-anjani.shree-mahabali-express.shree-mahavir.shree-maruti.shree-nandan.sicepat.skroutz-last-mile.skyex-ae.skyking.skynet-sa.skynet-worldwide.skypostal.slgtrax.slovak-parcel-service.slovenska-posta.smsa-express.south-african-post-office.southeastern-freight-lines.sp-express.speed-and-safe.speedaf.speedex.speedpak.speedy.spx-br.spx-id.spx-my.spx-ph.spx-sg.spx-th.spx-tw.spx-vn.sri-lanka-post.st-courier.stallion-express.starex-az.starken.starlinks.steadfast.straightship.sundarban-courier.surat-kargo.swiftx.t-cat.t-group.tamdis.tanzania-posts.taxydema.tccs.tci-express.tcs-pakistan.tdn.tealca.team-express-ae.team-global-express.team-worldwide.tej-couriers.teleship.tfm-express.tforce-freight.tforce-logistics.thhy.tiki.tirupati-courier.tmm-express.tnt-it.today-kr.toptrans.torrestir.total-express.tp-logistics-th.trackon.tracx-logis.trans-o-flex.transaher.transcorp.transmission.transport-rdl.trendyol-express.tsjy.tst-cf-express.tufesa.tusass.tws-express.ubi-smart-parcel.ues-uy.united-delivery-service.united-worldwide-couriers.upaya.urbano.urvaam.uzbekistan-post.valmo.vasp-expresso.veloces.venipak.vestovoy.via-cargo.viettel-post.vimenpaq.vinted-go.vitran-express.vnpost.vozovoz.vrl-logistics.wahana.wanbexpress.ward-trucking.whistl.winion-logis.winit.x-express-ba.x-trac.xde-logistics.xdp.xlcourier.xpo-ltl.xpressbees.yalidine.yc-delivery.ycs-logistics.yilong-logistics.yimidida.yurtici-kargo.zajil.zeleris.zheldor.zoom-ve.zr-express".split("."), Ze = {
23599
23625
  "swiss-post": ["swiss-post-1", "swiss-post-2"],
23600
23626
  "swiss-post-cargo": ["swiss-post-cargo-sscc", "swiss-post-cargo-pl-reference"],
23601
23627
  quickpac: ["quickpac-1"],
@@ -24365,6 +24391,7 @@ var Ye = {
24365
24391
  "kronos-express": [],
24366
24392
  ktd: ["ktd-1"],
24367
24393
  "kuehne-nagel": ["kuehne-nagel-1", "kuehne-nagel-2"],
24394
+ "kun-express": ["kun-express-1"],
24368
24395
  kunyoung: [],
24369
24396
  "kwick-box": [],
24370
24397
  kyoungdong: [],
@@ -274,9 +274,12 @@ export class DhlExpressTracker {
274
274
  return runSteps(run, [{ id: 'trawl', run: ({ signal, remainingMs }) => this.browserPiece(piece, { signal, budgetMs: remainingMs }) }]);
275
275
  }
276
276
  const number = normalizeNumber(raw);
277
+ const trawl = !!this.environment.trawl;
277
278
  return runSteps(run, [
278
- { id: 'direct', run: ({ signal, remainingMs }) => this.direct(number, { signal, budgetMs: Math.min(remainingMs, 10_000) }) },
279
- { id: 'trawl', enabled: !!this.environment.trawl, run: ({ signal, remainingMs }) => this.browser(number, { signal, budgetMs: remainingMs }) },
279
+ // While a CAPTCHA holds the app's API would fail without a request, so a browser service is asked at once.
280
+ { id: 'direct', enabled: !(trawl && this.mobile.captchaHeld()),
281
+ run: ({ signal, remainingMs }) => this.direct(number, { signal, budgetMs: Math.min(remainingMs, 10_000) }) },
282
+ { id: 'trawl', enabled: trawl, run: ({ signal, remainingMs }) => this.browser(number, { signal, budgetMs: remainingMs }) },
280
283
  ]);
281
284
  }
282
285
  }
@@ -29,6 +29,8 @@ export declare class DhlMobileApi {
29
29
  * fail as a challenge without a request.
30
30
  */
31
31
  tracking(number: string, budget: LookupBudget): Promise<unknown>;
32
+ /** Whether a CAPTCHA drawn through this transport may still hold, so tracking would fail without a request. */
33
+ captchaHeld(): boolean;
32
34
  private checkSettings;
33
35
  private request;
34
36
  }
@@ -76,8 +76,7 @@ export class DhlMobileApi {
76
76
  */
77
77
  async tracking(number, budget) {
78
78
  const state = this.state;
79
- const captchaAt = state.captchaAt;
80
- if (captchaAt !== null && Date.now() - captchaAt < CAPTCHA_MEMORY_MS)
79
+ if (this.captchaHeld())
81
80
  throw new ChallengeError(PROVIDER, 'DHL mobile tracking recently required verification');
82
81
  let payload;
83
82
  try {
@@ -98,6 +97,11 @@ export class DhlMobileApi {
98
97
  }
99
98
  return payload;
100
99
  }
100
+ /** Whether a CAPTCHA drawn through this transport may still hold, so tracking would fail without a request. */
101
+ captchaHeld() {
102
+ const captchaAt = this.state.captchaAt;
103
+ return captchaAt !== null && Date.now() - captchaAt < CAPTCHA_MEMORY_MS;
104
+ }
101
105
  async checkSettings(budget) {
102
106
  this.state.settingsCheckedAt = null;
103
107
  const checkedAt = Date.now();
@@ -40,6 +40,7 @@ const WORDINGS = new Map([
40
40
  ['arrive at the collection warehouse', 'accepted'],
41
41
  ['the collection warehouse has completed sorting', 'accepted'],
42
42
  ['package received & scanned at warehouse', 'accepted'],
43
+ ['package received and scanned at warehouse', 'accepted'],
43
44
  ['parcel handed over to carrier,waiting for transportation', 'accepted'],
44
45
  // China Post's receipt (中国邮政 已收取邮件).
45
46
  ['package received', 'accepted'],
@@ -2,6 +2,7 @@
2
2
  "carrier": "dhlink",
3
3
  "entries": [
4
4
  {"code": "WH001", "wording": "Package received & scanned at warehouse", "stage": "accepted", "language": "en", "confirmedBy": "live", "note": "Node Dispatched: DHLink's warehouse received the parcel."},
5
+ {"wording": "Package received and scanned at warehouse", "stage": "accepted", "language": "en", "confirmedBy": "live", "firstSeen": "2026-10-20", "note": "The same receipt spelled out, on a row without a node code."},
5
6
  {"code": "WH011", "wording": "Package departed from the warehouse", "stage": "in_transit", "language": "en", "confirmedBy": "live", "note": "Node Outbound."},
6
7
  {"code": "EUBJ007", "wording": "Parcel handed over to carrier,waiting for transportation", "stage": "accepted", "language": "en", "confirmedBy": "live", "note": "Node Dispatched on the ePacket line: the collection point received the parcel."},
7
8
  {"code": "EUBJ009", "wording": "Shipment Departed From Original Country at …", "stage": "in_transit", "language": "en", "confirmedBy": "live", "note": "Node Origin leaving; the wording repeats the row's clock."},
@@ -1,6 +1,6 @@
1
1
  import { type ClassifiedWording, type Stage } from '../../core/status/index.js';
2
2
  import { type CarrierStatusMap } from '../../core/status/statusMap.js';
3
- /** The stage the map gives a wording, if it knows it. */
3
+ /** The stage the map gives a wording, if it knows it, with or without the tracker's note after it. */
4
4
  export declare function globalpostMappedStage(wording: string): Stage | undefined;
5
5
  /** A scan's stage from its wording, else the shared wording rules, else nothing, which keeps it visible for review. */
6
6
  export declare function globalpostStage(wording: string): ClassifiedWording | null;
@@ -14,6 +14,7 @@ const WORDINGS = new Map([
14
14
  // GlobalPost's own consolidation facility; a partner's inbound scans can come before it.
15
15
  ['Arrived at GlobalPost Facility', 'accepted'],
16
16
  ['Departed GlobalPost Facility', 'in_transit'],
17
+ ['Departed from Origin Country', 'in_transit'],
17
18
  ['In Transit', 'in_transit'],
18
19
  ['In-Transit', 'in_transit'],
19
20
  ['Arrived in Destination Country', 'in_transit'],
@@ -22,11 +23,15 @@ const WORDINGS = new Map([
22
23
  ['Out for Delivery', 'out_for_delivery'],
23
24
  ['Attempted Delivery', 'failed_attempt'],
24
25
  ['Exception, No Action Required', 'exception'],
26
+ ['Delayed, No Action Required', 'exception'],
25
27
  ['Delivered', 'delivered'],
26
28
  ].map(([wording, stage]) => [normalizeStatusWording(wording), stage]));
27
- /** The stage the map gives a wording, if it knows it. */
29
+ /** The tracker's reassurance that can follow a scan's wording in the same cell. */
30
+ const NOTE = /\s*tracking updates may take time\b.*$/;
31
+ /** The stage the map gives a wording, if it knows it, with or without the tracker's note after it. */
28
32
  export function globalpostMappedStage(wording) {
29
- return WORDINGS.get(normalizeStatusWording(wording));
33
+ const key = normalizeStatusWording(wording);
34
+ return WORDINGS.get(key) ?? WORDINGS.get(key.replace(NOTE, ''));
30
35
  }
31
36
  /** A scan's stage from its wording, else the shared wording rules, else nothing, which keeps it visible for review. */
32
37
  export function globalpostStage(wording) {
@@ -9,12 +9,14 @@
9
9
  {"wording": "Departed GlobalPost Facility", "stage": "in_transit", "language": "en", "confirmedBy": "portal"},
10
10
  {"wording": "In Transit", "stage": "in_transit", "language": "en", "confirmedBy": "portal"},
11
11
  {"wording": "In-Transit", "stage": "in_transit", "language": "en", "confirmedBy": "portal", "note": "Hyphenated variant of In Transit, shown alongside it in the same histories."},
12
+ {"wording": "Departed from Origin Country", "stage": "in_transit", "language": "en", "confirmedBy": "live", "firstSeen": "2026-10-20"},
12
13
  {"wording": "Arrived in Destination Country", "stage": "in_transit", "language": "en", "confirmedBy": "portal"},
13
14
  {"wording": "In Customs", "stage": "customs", "language": "en", "confirmedBy": "portal"},
14
15
  {"wording": "Cleared Customs", "stage": "in_transit", "language": "en", "confirmedBy": "portal", "note": "Customs let the parcel go on, so it is moving again."},
15
16
  {"wording": "Out for Delivery", "stage": "out_for_delivery", "language": "en", "confirmedBy": "portal"},
16
17
  {"wording": "Attempted Delivery", "stage": "failed_attempt", "language": "en", "confirmedBy": "portal"},
17
18
  {"wording": "Exception, No Action Required", "stage": "exception", "language": "en", "confirmedBy": "portal", "note": "Shown for a final-mile exception that the recipient does not need to act on."},
19
+ {"wording": "Delayed, No Action Required", "stage": "exception", "language": "en", "confirmedBy": "live", "firstSeen": "2026-10-20", "note": "The tracker's delay, in the same form as its exception the recipient need not act on."},
18
20
  {"wording": "Delivered", "stage": "delivered", "language": "en", "confirmedBy": "portal", "note": "Also ends a return to the sender; the adapter reads a delivery scan at the sender's town as returned."}
19
21
  ]
20
22
  }
@@ -20,6 +20,17 @@ export interface HualeiTenant {
20
20
  };
21
21
  /** Rows keep their wall clocks: some rows the tracker copies from another carrier come on that carrier's clock. */
22
22
  readonly wallClocks?: true;
23
+ /**
24
+ * How a row's clock reads where the record settles it row by row: on the
25
+ * platform's clock, as a wall clock, or as its day alone. It takes the place
26
+ * of `wallClocks`.
27
+ */
28
+ readonly clock?: (row: HualeiRow) => 'platform' | 'wall' | 'day';
29
+ /**
30
+ * Whether a row's wording repeats another's, at the same clock, place and
31
+ * kind, with more around it: the row then counts once, as the other.
32
+ */
33
+ readonly repeats?: (wording: string, other: string) => boolean;
23
34
  /**
24
35
  * Carriers the tenant hands records to without naming a channel: one takes a
25
36
  * record whose transfer number its own high-confidence rule claims whole.
@@ -52,6 +63,13 @@ export declare function normalizeHualeiNumber(raw: string, provider: string): st
52
63
  export declare function hualeiTrackUrl(tenant: HualeiTenant, raw: string): string;
53
64
  /** Scan text without a signatory or a postcode. */
54
65
  export declare function hualeiScanText(value: string, maxLength?: number): string;
66
+ /** One row as the reply gives it: its wall clock, text, place and kind code. */
67
+ export interface HualeiRow {
68
+ readonly clock: string;
69
+ readonly content: string;
70
+ readonly location: string;
71
+ readonly code: string;
72
+ }
55
73
  /**
56
74
  * The reply of `selectTrack.htm` for one number: the record whose own numbers
57
75
  * include the one asked, or null when the service says it holds no row for
@@ -129,7 +129,7 @@ function stageOf(tenant, code, description) {
129
129
  /**
130
130
  * The rows as scans, newest first. A row dated after the lookup on the
131
131
  * trackers' clock is not a scan yet: tenants write whole timelines ahead.
132
- * Identical rows count once.
132
+ * Identical rows count once, and so do rows the tenant says repeat another.
133
133
  */
134
134
  function scans(rows, tenant, readAt) {
135
135
  const seen = new Set();
@@ -151,16 +151,21 @@ function scans(rows, tenant, readAt) {
151
151
  return;
152
152
  seen.add(key);
153
153
  const staged = stageOf(tenant, row.code, description);
154
+ const reading = tenant.clock?.(row) ?? (tenant.wallClocks ? 'wall' : 'platform');
154
155
  kept.push({ clock: local, index, event: {
155
- ...(tenant.wallClocks ? { local_time: local } : { time: placed.iso }), description,
156
+ ...(reading === 'platform' ? { time: placed.iso } : { local_time: reading === 'day' ? local.slice(0, 10) : local }), description,
156
157
  ...(location ? { location } : {}),
157
158
  ...(row.code ? { provider_code: row.code } : {}),
158
159
  ...(staged ? { stage: staged.stage, stage_source: staged.source } : {}),
159
160
  } });
160
161
  });
162
+ const { repeats } = tenant;
163
+ const unique = repeats ? kept.filter((entry) => !kept.some((other) => other !== entry && other.clock === entry.clock
164
+ && other.event.location === entry.event.location && other.event.provider_code === entry.event.provider_code
165
+ && repeats(entry.event.description, other.event.description))) : kept;
161
166
  // Rows come newest first; rows on one clock keep the reply's order.
162
- kept.sort((a, b) => (a.clock === b.clock ? a.index - b.index : a.clock < b.clock ? 1 : -1));
163
- const events = kept.map(({ event }) => event);
167
+ unique.sort((a, b) => (a.clock === b.clock ? a.index - b.index : a.clock < b.clock ? 1 : -1));
168
+ const events = unique.map(({ event }) => event);
164
169
  return { events: events.slice(0, MAX_EVENTS), truncated: events.length > MAX_EVENTS };
165
170
  }
166
171
  /**
@@ -54,6 +54,7 @@ const PHRASES = new Map([
54
54
  ['switch off', 'failed_attempt'],
55
55
  ['customer wants to change location', 'failed_attempt'],
56
56
  ['route not completed', 'failed_attempt'],
57
+ ['traffic, strike, bad weather', 'failed_attempt'],
57
58
  ['user not at home', 'failed_attempt'],
58
59
  ['wrong address', 'failed_attempt'],
59
60
  ['<bad address>', 'failed_attempt'],
@@ -34,6 +34,7 @@
34
34
  {"code": "1003", "wording": "The driver failed to deliver due to shop(building) closure, we will try to deliver again.", "stage": "failed_attempt", "language": "en", "confirmedBy": "live"},
35
35
  {"code": "1003", "wording": "Customer Wants to Change Location", "stage": "failed_attempt", "language": "en", "confirmedBy": "live", "note": "A driver's reason, followed by the attempt's end."},
36
36
  {"code": "1003", "wording": "Route not completed", "stage": "failed_attempt", "language": "en", "confirmedBy": "live", "note": "A driver's reason, followed by the attempt's end."},
37
+ {"code": "1003", "wording": "Traffic, Strike, Bad weather", "stage": "failed_attempt", "language": "en", "confirmedBy": "live", "firstSeen": "2026-10-20", "note": "A driver's reason on the delivery run, followed by the attempt's end and the return to the centre."},
37
38
  {"code": "1003", "wording": "User not at home", "stage": "failed_attempt", "language": "en", "confirmedBy": "live", "note": "A driver's reason, followed by the attempt's end."},
38
39
  {"code": "1003", "wording": "switch off", "stage": "failed_attempt", "language": "en", "confirmedBy": "live", "note": "A driver's reason, followed by the attempt's end."},
39
40
  {"code": "1003", "wording": "wrong address", "stage": "failed_attempt", "language": "en", "confirmedBy": "live", "note": "A driver's reason, followed by the attempt's end."},
@@ -0,0 +1,6 @@
1
+ import type { AdapterFactory } from '../../core/adapter/index.js';
2
+ import { HualeiTracker } from '../gzyl/hualei.js';
3
+ export declare class KunExpressTracker extends HualeiTracker {
4
+ constructor(options?: ConstructorParameters<typeof HualeiTracker>[1]);
5
+ }
6
+ export declare const adapter: AdapterFactory;
@@ -0,0 +1,9 @@
1
+ import { HualeiTracker } from '../gzyl/hualei.js';
2
+ import { KUN_EXPRESS } from './parser.js';
3
+ export class KunExpressTracker extends HualeiTracker {
4
+ constructor(options = {}) { super(KUN_EXPRESS, options); }
5
+ }
6
+ export const adapter = (environment) => {
7
+ const tracker = new KunExpressTracker({ fetcher: environment.fetcher, recorder: environment.recorder, userAgent: environment.userAgent });
8
+ return { id: 'kun-express', recordsSteps: true, steps: ['direct', 'retry'], track: (input, context) => tracker.fetch(input.number, context) };
9
+ };
@@ -0,0 +1,97 @@
1
+ {
2
+ "id": "kun-express",
3
+ "displayName": "Kun Express",
4
+ "aliases": [
5
+ "KUN",
6
+ "KUNEXPRESS",
7
+ "KunExpress",
8
+ "鲲辰",
9
+ "鯤辰",
10
+ "杭州鲲辰跨境供应链管理有限公司"
11
+ ],
12
+ "region": {
13
+ "countries": [
14
+ "CN"
15
+ ]
16
+ },
17
+ "brand": {
18
+ "color": "#0761ff"
19
+ },
20
+ "selectable": true,
21
+ "timezone": "Asia/Shanghai",
22
+ "tracking": {
23
+ "mode": "automatic",
24
+ "adapter": "kun-express",
25
+ "steps": [
26
+ "direct",
27
+ "retry"
28
+ ],
29
+ "localClocks": true
30
+ },
31
+ "capabilities": [
32
+ "history",
33
+ "location",
34
+ "provider_code",
35
+ "service_name",
36
+ "destination_country",
37
+ "canonical_tracking_number"
38
+ ],
39
+ "portal": {
40
+ "canaryUrl": "https://t.17track.net/",
41
+ "shows": [
42
+ "status",
43
+ "history",
44
+ "location",
45
+ "provider_code",
46
+ "service_name",
47
+ "destination_country",
48
+ "canonical_tracking_number",
49
+ "parcel_count",
50
+ "weight",
51
+ "customer_reference",
52
+ "sender_name",
53
+ "recipient_name",
54
+ "recipient_address",
55
+ "postcodes",
56
+ "signatory",
57
+ "signature",
58
+ "proof_of_delivery",
59
+ "payment_details"
60
+ ],
61
+ "scraped": [
62
+ "status",
63
+ "history",
64
+ "location",
65
+ "provider_code",
66
+ "service_name",
67
+ "destination_country",
68
+ "canonical_tracking_number"
69
+ ],
70
+ "discarded": [
71
+ "parcel_count",
72
+ "weight",
73
+ "customer_reference",
74
+ "sender_name",
75
+ "recipient_name",
76
+ "recipient_address",
77
+ "postcodes",
78
+ "signatory",
79
+ "signature",
80
+ "proof_of_delivery",
81
+ "payment_details"
82
+ ],
83
+ "unavailable": [
84
+ "eta",
85
+ "delivered_at",
86
+ "offset_timestamps"
87
+ ]
88
+ },
89
+ "links": [],
90
+ "detection": [
91
+ {
92
+ "id": "kun-express-1",
93
+ "pattern": "^KUN\\d{10}$",
94
+ "confidence": "high"
95
+ }
96
+ ]
97
+ }
@@ -0,0 +1,62 @@
1
+ {
2
+ "carrier": "kun-express",
3
+ "records": [
4
+ {
5
+ "number": "KUN8000015561",
6
+ "role": "shipment",
7
+ "evidence": "public_shipment_report",
8
+ "source": {
9
+ "url": "https://packyapp.com/en/carriers/kunexpress",
10
+ "date": "2026-10-20",
11
+ "dateKind": "capture",
12
+ "access": "full_page"
13
+ },
14
+ "context": {
15
+ "assessment": "confirmed"
16
+ },
17
+ "expect": {
18
+ "carrier": "kun-express",
19
+ "confidence": "high"
20
+ },
21
+ "note": "Packy's Kun Express page gives it as the number format. Kun Express's tracker answers it as a parcel of its US line that USPS delivered."
22
+ },
23
+ {
24
+ "number": "KUN9991027071",
25
+ "role": "shipment",
26
+ "evidence": "public_shipment_report",
27
+ "source": {
28
+ "url": "https://www.parcelpanel.com/couriers/kun-express/",
29
+ "date": "2026-10-20",
30
+ "dateKind": "capture",
31
+ "access": "full_page"
32
+ },
33
+ "context": {
34
+ "assessment": "confirmed"
35
+ },
36
+ "expect": {
37
+ "carrier": "kun-express",
38
+ "confidence": "high"
39
+ },
40
+ "note": "ParcelPanel's Kun Express page offered it as a sample. Kun Express's tracker answers it as a parcel of its US line that USPS delivered."
41
+ },
42
+ {
43
+ "number": "KUN6666669444",
44
+ "role": "shipment",
45
+ "evidence": "public_shipment_report",
46
+ "source": {
47
+ "url": "https://www.parcelpanel.com/couriers/kunyi/",
48
+ "date": "2026-10-20",
49
+ "dateKind": "capture",
50
+ "access": "full_page"
51
+ },
52
+ "context": {
53
+ "assessment": "confirmed"
54
+ },
55
+ "expect": {
56
+ "carrier": "kun-express",
57
+ "confidence": "high"
58
+ },
59
+ "note": "ParcelPanel offered it as a sample on a page it labels KunYi. Kun Express's own tracker answers it as a parcel of its US line that USPS delivered."
60
+ }
61
+ ]
62
+ }
@@ -0,0 +1,31 @@
1
+ import type { CarrierResult } from '../../core/result/index.js';
2
+ import { type HualeiRow, type HualeiTenant } from '../gzyl/hualei.js';
3
+ export declare const PROVIDER = "Kun Express";
4
+ export declare const KUN_EXPRESS_ORIGIN = "http://1.117.249.36:8082";
5
+ /**
6
+ * A row copied from USPS can lead with its place and end with USPS's
7
+ * explanation after an arrow. Both are cut, and the place's commas are spaced
8
+ * one way, so the copies of one scan read alike. The place's ZIP code is dropped.
9
+ */
10
+ export declare function splitKunExpressRow(content: string, location: string): {
11
+ content: string;
12
+ location: string;
13
+ };
14
+ /**
15
+ * Kun Express writes its own rows to the second, on the platform's Beijing
16
+ * clock. The rows it copies from USPS come to the minute on the facility's
17
+ * clock, as USPS's explanation of them shows, and keep their wall clocks; one
18
+ * at midnight carries only its day.
19
+ */
20
+ export declare function kunExpressClock(row: HualeiRow): 'platform' | 'wall' | 'day';
21
+ /**
22
+ * The tracker can copy one USPS scan three times: alone, after its place, and
23
+ * with USPS's explanation, which can add the scan's category before it
24
+ * ("On the Way, Arrived at USPS Facility"). At one clock and place, a wording
25
+ * that ends with another after a comma is that scan again.
26
+ */
27
+ export declare const repeatsKunExpressRow: (wording: string, other: string) => boolean;
28
+ export declare const KUN_EXPRESS: HualeiTenant;
29
+ /** The track interface's reply, or null when it holds no row for the number. */
30
+ export declare const parseKunExpressTrack: (payload: unknown, number: string, readAt?: number) => CarrierResult | null;
31
+ export declare const parseKunExpressPage: (html: string, number: string, readAt?: number) => CarrierResult;
@@ -0,0 +1,44 @@
1
+ import { escapeRegExp } from '../../core/transport/index.js';
2
+ import { parseHualeiPage, parseHualeiTrack } from '../gzyl/hualei.js';
3
+ import { kunExpressStage } from './status.js';
4
+ export const PROVIDER = 'Kun Express';
5
+ export const KUN_EXPRESS_ORIGIN = 'http://1.117.249.36:8082';
6
+ // USPS's explanation of a row, which the tracker copies after an arrow. It repeats the
7
+ // place, and on a delivery the recipient's town and ZIP code.
8
+ const EXPLANATION = /\s+->(?:\s[\s\S]*)?$/u;
9
+ // A ZIP code ending a place, with or without its four-digit add-on.
10
+ const ZIP = /\s+\d{5}(?:-\d{4})?$/u;
11
+ /**
12
+ * A row copied from USPS can lead with its place and end with USPS's
13
+ * explanation after an arrow. Both are cut, and the place's commas are spaced
14
+ * one way, so the copies of one scan read alike. The place's ZIP code is dropped.
15
+ */
16
+ export function splitKunExpressRow(content, location) {
17
+ const parts = location.split(',').map((part) => part.trim()).filter(Boolean);
18
+ const text = content.replace(EXPLANATION, '').trim();
19
+ const lead = parts.length ? new RegExp(`^${parts.map(escapeRegExp).join('\\s*,\\s*')}\\s*,\\s*`, 'u') : null;
20
+ return { content: lead ? text.replace(lead, '') : text, location: parts.join(', ').replace(ZIP, '') };
21
+ }
22
+ /**
23
+ * Kun Express writes its own rows to the second, on the platform's Beijing
24
+ * clock. The rows it copies from USPS come to the minute on the facility's
25
+ * clock, as USPS's explanation of them shows, and keep their wall clocks; one
26
+ * at midnight carries only its day.
27
+ */
28
+ export function kunExpressClock(row) {
29
+ if (!row.clock.endsWith(':00'))
30
+ return 'platform';
31
+ return row.clock.endsWith(' 00:00:00') ? 'day' : 'wall';
32
+ }
33
+ /**
34
+ * The tracker can copy one USPS scan three times: alone, after its place, and
35
+ * with USPS's explanation, which can add the scan's category before it
36
+ * ("On the Way, Arrived at USPS Facility"). At one clock and place, a wording
37
+ * that ends with another after a comma is that scan again.
38
+ */
39
+ export const repeatsKunExpressRow = (wording, other) => wording.endsWith(`, ${other}`);
40
+ export const KUN_EXPRESS = { carrier: 'kun-express', provider: PROVIDER, origin: KUN_EXPRESS_ORIGIN, stage: kunExpressStage,
41
+ split: splitKunExpressRow, clock: kunExpressClock, repeats: repeatsKunExpressRow };
42
+ /** The track interface's reply, or null when it holds no row for the number. */
43
+ export const parseKunExpressTrack = (payload, number, readAt) => parseHualeiTrack(payload, number, KUN_EXPRESS, readAt);
44
+ export const parseKunExpressPage = (html, number, readAt) => parseHualeiPage(html, number, KUN_EXPRESS, readAt);
@@ -0,0 +1,8 @@
1
+ import type { Stage } from '../../core/status/index.js';
2
+ import { type CarrierStatusMap } from '../../core/status/statusMap.js';
3
+ /**
4
+ * The stage Kun Express's map gives one of its own rows, by its `normalizeStatusWording`
5
+ * wording. The rows it copies from USPS are left to the shared wording rules.
6
+ */
7
+ export declare function kunExpressStage(_code: string | null, wording: string): Stage | undefined;
8
+ export declare const statusMap: CarrierStatusMap;
@@ -0,0 +1,11 @@
1
+ import { normalizeStatusWording } from '../../core/status/statusMap.js';
2
+ import statuses from './statuses.json' with { type: 'json' };
3
+ const WORDINGS = new Map(statuses.entries.map((entry) => [normalizeStatusWording(entry.wording), entry.stage]));
4
+ /**
5
+ * The stage Kun Express's map gives one of its own rows, by its `normalizeStatusWording`
6
+ * wording. The rows it copies from USPS are left to the shared wording rules.
7
+ */
8
+ export function kunExpressStage(_code, wording) {
9
+ return WORDINGS.get(wording);
10
+ }
11
+ export const statusMap = { stage: kunExpressStage, gaps: [] };
@@ -0,0 +1,18 @@
1
+ {
2
+ "carrier": "kun-express",
3
+ "entries": [
4
+ {"wording": "Shipment information received", "language": "en", "stage": "registered", "confirmedBy": "live", "note": "The order data, before Kun Express has the parcel."},
5
+ {"code": "ARRIVAL", "wording": "Arrived at the receiving point", "language": "en", "stage": "accepted", "confirmedBy": "live", "note": "The warehouse's receipt, at the place KUN Warehouse."},
6
+ {"code": "SHIPMENT", "wording": "KUN Warehouse", "language": "en", "stage": "in_transit", "confirmedBy": "live", "note": "The warehouse's departure row has no text, so its place stands as the wording."},
7
+ {"wording": "Arrive at the delivery point", "language": "en", "stage": "in_transit", "confirmedBy": "live", "note": "A Hangzhou row where the shipper hands the parcel over, before the warehouse's receipt; the delivery point is not the recipient's."},
8
+ {"wording": "Cargo leaving the operation center", "language": "en", "stage": "in_transit", "confirmedBy": "live"},
9
+ {"wording": "Arrive at the sorting center for operation and transfer", "language": "en", "stage": "in_transit", "confirmedBy": "live"},
10
+ {"wording": "arrive at international airport to abroad", "language": "en", "stage": "in_transit", "confirmedBy": "live"},
11
+ {"wording": "Waiting to be loaded", "language": "en", "stage": "in_transit", "confirmedBy": "live", "note": "Waiting for the flight."},
12
+ {"wording": "Shipment started the customs clearance process at origin", "language": "en", "stage": "customs", "confirmedBy": "live", "note": "Export clearance in China."},
13
+ {"wording": "departed from airport of origin", "language": "en", "stage": "in_transit", "confirmedBy": "live"},
14
+ {"wording": "U.S. Postal Service, The goods are in transit", "language": "en", "stage": "in_transit", "confirmedBy": "live", "note": "Kun Express's own row at the airports of the flight, naming the delivery carrier; not a USPS scan."},
15
+ {"wording": "arrived at airport of destination", "language": "en", "stage": "in_transit", "confirmedBy": "live"},
16
+ {"wording": "custom clearance completed", "language": "en", "stage": "in_transit", "confirmedBy": "live", "note": "Import clearance in the United States, at the place US. Written to the minute, so it keeps its wall clock."}
17
+ ]
18
+ }
@@ -27,6 +27,8 @@
27
27
  {"wording": "The instruction data for this shipment have been provided by the sender to DHL electronically", "language": "en", "stage": "registered", "confirmedBy": "live", "note": "Relayed from DHL: the label's data, on the day the order was created."},
28
28
  {"wording": "The international shipment has been processed in the parcel center of origin", "language": "en", "stage": "in_transit", "confirmedBy": "live", "note": "Relayed from DHL in Germany after the hand-off."},
29
29
  {"wording": "The international shipment has been processed in the export parcel center", "language": "en", "stage": "in_transit", "confirmedBy": "live", "note": "Relayed from DHL in Germany."},
30
- {"wording": "The shipment has arrived in the destination country/destination area.", "language": "en", "stage": "in_transit", "confirmedBy": "live", "note": "Relayed from DHL, followed by the destination operator's tracking link in brackets; the map reads the wording without the link."}
30
+ {"wording": "The shipment has arrived in the destination country/destination area.", "language": "en", "stage": "in_transit", "confirmedBy": "live", "note": "Relayed from DHL, followed by the destination operator's tracking link in brackets; the map reads the wording without the link."},
31
+ {"wording": "The shipment has been loaded onto the delivery vehicle", "language": "en", "stage": "out_for_delivery", "confirmedBy": "live", "firstSeen": "2026-10-20", "note": "The last-mile carrier's delivery run, in Mayi Yinfu's English."},
32
+ {"wording": "The shipment has been successfully delivered", "language": "en", "stage": "delivered", "confirmedBy": "live", "firstSeen": "2026-10-20"}
31
33
  ]
32
34
  }
@@ -275,6 +275,7 @@ import { statusMap as kex } from '../../carriers/kex/status.js';
275
275
  import { statusMap as kexExpressHk } from '../../carriers/kex-express-hk/status.js';
276
276
  import { statusMap as kitTk } from '../../carriers/kit-tk/status.js';
277
277
  import { statusMap as kuehneNagel } from '../../carriers/kuehne-nagel/status.js';
278
+ import { statusMap as kunExpress } from '../../carriers/kun-express/status.js';
278
279
  import { statusMap as kunyoung } from '../../carriers/kunyoung/status.js';
279
280
  import { statusMap as kyoungdong } from '../../carriers/kyoungdong/status.js';
280
281
  import { statusMap as kyrgyzPost } from '../../carriers/kyrgyz-post/status.js';
@@ -579,7 +580,7 @@ export const STATUS_MAPS = {
579
580
  'intex-paketdienst': intexPaketdienst, 'israel-post': israelPost, 'j-and-t': jAndT, 'j-and-t-au': jAndTAu, 'j-and-t-de': jAndTDe, 'j-and-t-cargo': jntCargo,
580
581
  'j-and-t-middle-east': jAndTMiddleEast, janio, jcex, jeebly, 'jersey-post': jerseyPost, 'jet-logistic': jetLogistic, 'jetline-couriers': jetlineCouriers,
581
582
  jhgj, jitsu, jne, 'jordan-post': jordanPost, jrt, 'js-express': jsExpress, jumppoint, kazpost, kex, 'kex-express-hk': kexExpressHk,
582
- 'kit-tk': kitTk, 'kuehne-nagel': kuehneNagel, kunyoung, kyoungdong, 'kyrgyz-post': kyrgyzPost, 'l-post': lPost, 'la-poste': laPoste,
583
+ 'kit-tk': kitTk, 'kuehne-nagel': kuehneNagel, 'kun-express': kunExpress, kunyoung, kyoungdong, 'kyrgyz-post': kyrgyzPost, 'l-post': lPost, 'la-poste': laPoste,
583
584
  'la-poste-burkina-faso': laPosteBurkinaFaso, 'la-poste-senegal': laPosteSenegal, 'laar-courier': laarCourier, labaih,
584
585
  'last-one-mile-coop': lastOneMileCoop, 'latvijas-pasts': latvijasPasts, 'leopards-courier': leopardsCourier, liccardi,
585
586
  'lietuvos-pastas': lietuvosPastas, 'lightning-express': lightningExpress,
@@ -18417,6 +18417,36 @@
18417
18417
  }
18418
18418
  ]
18419
18419
  },
18420
+ "kun-express": {
18421
+ "displayName": "Kun Express",
18422
+ "color": "#0761ff",
18423
+ "aliases": [
18424
+ "KUN",
18425
+ "KUNEXPRESS",
18426
+ "KunExpress",
18427
+ "鲲辰",
18428
+ "鯤辰",
18429
+ "杭州鲲辰跨境供应链管理有限公司"
18430
+ ],
18431
+ "countries": [
18432
+ "CN"
18433
+ ],
18434
+ "selectable": true,
18435
+ "timezone": "Asia/Shanghai",
18436
+ "tracking": {
18437
+ "mode": "automatic",
18438
+ "adapter": "kun-express",
18439
+ "localClocks": true
18440
+ },
18441
+ "canaryUrl": "https://t.17track.net/",
18442
+ "linkRules": [],
18443
+ "detectionRules": [
18444
+ {
18445
+ "pattern": "^KUN\\d{10}$",
18446
+ "confidence": "high"
18447
+ }
18448
+ ]
18449
+ },
18420
18450
  "kunyoung": {
18421
18451
  "displayName": "Kunyoung Express",
18422
18452
  "color": "#04378c",
@@ -11884,6 +11884,25 @@ export declare const CARRIER_CATALOG: {
11884
11884
  readonly confidence: "high";
11885
11885
  }];
11886
11886
  };
11887
+ readonly "kun-express": {
11888
+ readonly displayName: "Kun Express";
11889
+ readonly color: "#0761ff";
11890
+ readonly aliases: readonly ["KUN", "KUNEXPRESS", "KunExpress", "鲲辰", "鯤辰", "杭州鲲辰跨境供应链管理有限公司"];
11891
+ readonly countries: readonly ["CN"];
11892
+ readonly selectable: true;
11893
+ readonly timezone: "Asia/Shanghai";
11894
+ readonly tracking: {
11895
+ readonly mode: "automatic";
11896
+ readonly adapter: "kun-express";
11897
+ readonly localClocks: true;
11898
+ };
11899
+ readonly canaryUrl: "https://t.17track.net/";
11900
+ readonly linkRules: readonly [];
11901
+ readonly detectionRules: readonly [{
11902
+ readonly pattern: "^KUN\\d{10}$";
11903
+ readonly confidence: "high";
11904
+ }];
11905
+ };
11887
11906
  readonly kunyoung: {
11888
11907
  readonly displayName: "Kunyoung Express";
11889
11908
  readonly color: "#04378c";
@@ -19990,7 +20009,7 @@ export declare const CARRIER_CATALOG: {
19990
20009
  }];
19991
20010
  };
19992
20011
  };
19993
- export declare const CARRIER_IDS: readonly ["swiss-post", "swiss-post-cargo", "quickpac", "planzer", "aliexpress", "sunyou", "hermes", "spring-gds", "postlogistics", "dachser", "dhl", "dhl-ecommerce", "ups", "amazon-logistics", "amazon-shipping", "fedex", "gls-ch", "dpd", "dpd-fr", "mondial-relay", "relais-colis", "la-poste", "chronopost", "gls-fr", "colis-prive", "geodis", "colisweb", "c-chez-vous", "heppner", "ciblex", "paack", "asendia", "shipup", "india-post", "hermes-de", "gls-de", "delivengo", "intl-post", "unknown", "royal-mail", "parcelforce", "evri", "inpost", "an-post", "bpost", "austrian-post", "postnord", "posti", "correos-express", "seur", "mrw", "nacex", "ctt", "ctt-express", "poste-italiane", "brt", "ecoscooting", "tipsa", "ukrposhta", "usps", "canada-post", "purolator", "canpar", "ontrac", "speedx", "uniuni", "landmark-global", "old-dominion", "spee-dee", "gofo", "estafeta", "correios-br", "correos-chile", "yunexpress", "four-px", "blue-dart", "delhivery", "nz-post", "singapore-post", "japan-post", "sf-express", "sto", "yunda", "yto", "zto", "jd-logistics", "yamato", "korea-post", "thailand-post", "dtdc", "australia-post", "hongkong-post", "pos-malaysia", "ninja-van", "china-post", "packeta", "poczta-polska", "bring-posten", "aramex", "tnt", "correos-spain", "yanwen", "the-courier-guy", "j-and-t", "ems", "139express", "17feia", "247express", "2go", "4-72", "4sides", "5post", "99minutos", "a-duie-pyle", "a-tu-hora-express", "a1-post", "aaa-cooper", "ab-courier", "abf-freight", "aci-express-kr", "acs-courier", "aeropost", "aex-paraguay", "afghan-post", "air-star-xpress", "airpak-express", "ait-worldwide", "ajex", "akash-ganga", "aks-express", "alem-tat", "algerie-poste", "allegro-one", "am-home-delivery", "ameex", "american-west-express", "amerijet", "ampm", "andreani", "anjun", "anousith", "anserx", "anteraja", "ap-cargo", "apc-overnight", "apc-postal-logistics", "apple-express", "aramex-au", "aramex-nz", "aras-kargo", "arrow-xl", "asyad-express", "atlantic-courier", "averitt", "aymakan", "azerpost", "azul-cargo", "bangladesh-post", "barid-al-maghrib", "belpost", "best-express-my", "best-express-vn", "best-overnite-express", "best-transport", "better-trucks", "bex-express", "big-smart", "bjs-home-delivery", "blue-express", "blueex", "bombino", "bookurier", "border-express", "bosta", "botswana-post", "box-now", "bringer-parcel", "bts-uz", "budbee", "buffalo-ex", "bulgarian-posts", "burd-delivery", "bussgods", "byhd", "c3x", "cacesa", "campost", "cargus", "castores", "cbl-logistica", "ccfs", "cdek", "cdl", "celeritas", "central-transport", "ceska-posta", "ceva-logistics", "chazki", "chilexpress", "chit-chats", "chronodiali", "chukou1", "chunghwa-post", "chunil", "city-express-rs", "citylink-express", "citymail", "citysprint", "cj-logistics", "cj-packet", "closer-logistics", "cne", "codexpress", "connect-couriers", "coordinadora", "copa-courier", "corre", "correo-argentino", "correo-uruguayo", "correos-bolivia", "correos-cuba", "correos-de-mexico", "correos-el-salvador", "correos-nicaragua", "courier-center", "courier-it", "courier-plus-ng", "couriersplease", "credifin", "cruz-del-sur", "cse-russia", "cst-italia", "cttyex", "custom-companies", "cycloon", "cyprus-post", "d-express", "daewoo-fastex", "dai-post", "daily-xpress", "danske-fragtmaend", "dao", "day-ross", "daylight-transport", "dayton-freight", "dellin", "delnext", "deppon", "deprisa", "designer-transport", "dhl-ecommerce-es", "dhl-ecommerce-nl", "dhl-ecommerce-pl", "dhl-ecommerce-uk", "dhl-express", "dhl-freight", "dhlink", "direct-couriers", "direct-freight-express", "direx", "dnx-cargo", "dobropost", "dohrn-transfer", "domain-logistics", "domex", "dpd-at", "dpd-be", "dpd-de", "dpd-ie", "dpd-nl", "dpd-pl", "dpd-pt", "dpd-ro", "dpd-uk", "dpd-za", "dpex", "dragon-star-curier", "drop2shop", "dropp", "dsv", "dx", "dynalogic", "early-bird", "easy-mail", "ecms-express", "eco-express-ae", "econt", "ecourier", "egypt-post", "ekart", "elta", "emile", "emirates-post", "ems-vietnam", "energia-tk", "energo", "envia-colombia", "envialia", "eparcel-kr", "epost-global", "equick", "estes", "estes-forwarding", "ethiopian-post", "eurodis", "euroexpress-ba", "europochta", "evdemo-lojistik", "evri-uk", "evropat", "ewe", "exelot", "exline-kz", "exmate", "express-one", "fan-courier", "fargo-courier", "fargo-uz", "fastdrop", "fastfrate", "fedex-freight", "fedex-pl", "fermopoint", "fg-delivery", "first-delivery-tn", "first-fly-express", "first-line", "flash-express", "flash-express-ph", "fleetex", "fleetoptics", "flippost", "fliway", "flyking", "followmont", "forward-air", "forza-delivery", "foxpost", "franch-express", "fukuyama", "gaash", "gati", "gdex", "gebrueder-weiss", "geis", "gel-express", "geniki-taxydromiki", "geodis-pl", "ghana-post", "ghn", "ghtk", "globalpost", "gls-at", "gls-es", "gls-it", "gls-pl", "gms-worldwide", "go-express", "go4", "gobolt", "gofo-fr", "gofo-it", "gofo-nl", "gogo-xpress", "goodluck-courier", "grand-slam-express", "groupe-guilbault", "gs-postbox", "gsi-express", "gta-airskip", "gtl-goto", "guatex", "gzyl", "hanjin", "hapdong", "happy-post", "haypost", "hct-logistics", "helthjem", "hepsijet", "hercules-freight", "hermes-at", "hi-trans", "hispapost", "homexpress", "horoz", "hound-express", "houng-ah-loun", "hovership", "hp-mostar", "hr-parcel", "hrvatska-posta", "huahan", "hunter-express", "hywl", "icc-worldwide", "icl-express", "ics-courier", "idexpress", "ids-logistik", "ilyang-logis", "imile", "indah-logistik", "instabox", "integral-pack", "intelcom", "inter-courier", "intereuropa", "internet-express", "interrapidisimo", "intex-paketdienst", "iran-post", "israel-post", "j-and-t-au", "j-and-t-br", "j-and-t-cargo", "j-and-t-cn", "j-and-t-de", "j-and-t-middle-east", "j-and-t-mx", "jadlog", "jamaica-post", "janio", "jcex", "jeebly", "jersey-post", "jet-logistic", "jetline-couriers", "jhgj", "jitsu", "jne", "jordan-post", "jrs-express", "jrt", "js-express", "jumppoint", "kargoist", "kazpost", "kerry-tj", "kex", "kex-express-hk", "kit-tk", "kolay-gelsin", "kronos-express", "ktd", "kuehne-nagel", "kunyoung", "kwick-box", "kyoungdong", "kyrgyz-post", "l-post", "la-poste-burkina-faso", "la-poste-ci", "la-poste-senegal", "la-poste-tunisienne", "laar-courier", "labaih", "lao-post", "last-one-mile-coop", "latvijas-pasts", "lbc-express", "leopards-courier", "libanpost", "liccardi", "lietuvos-pastas", "lightning-express", "line-clear", "lingdong", "linhan", "lion-parcel", "logen", "loggi", "logistiq", "logoix", "loomis-express", "lotte-global", "lso", "m-and-p", "m-one", "madhur-courier", "magyar-posta", "mailamericas", "mailplus-au", "mainfreight", "major-express", "makati-express", "maltapost", "mandae", "maritime-ontario", "maruti-air", "matkahuolto", "mauritius-post", "mayiyinfu", "mds-collivery", "meest", "messenger-cz", "method", "metropolitan-warehouse", "micro-express", "midland-transport", "mng-kargo", "mongol-infinity-post", "montenegro-post", "morning-global", "mrl-global", "mtscn", "mylerz", "naqel", "nationex", "ncs-courier", "neighbour-express", "nepal-post", "netpost-vn", "next-level-delivery", "nhat-tin", "nim-express", "nipost", "nippon-express", "noest", "nord-wheel", "norsk-global", "northline", "nova-global", "nova-poshta", "nox", "nz-couriers", "oak-harbor", "oca", "ocasa", "ocs-ana", "olva-courier", "omgo", "omniva", "one-world-express", "opt-nc", "orian", "orlen-paczka", "osm-worldwide", "overseas-express", "ozon-logistics", "pack-man", "packli-punkt", "packlink", "packs", "pakistan-post", "palletways", "pandu-logistics", "pannon-xp", "paperfly", "paquetexpress", "parcelpoint", "pargo", "passport", "pathao-courier", "pavan-courier", "paxel", "paxi", "pbt", "pcp-express", "pcs-logistics-vn", "pdn-express", "pdq-chile", "pecom", "peddler", "pelican-express", "peqasus-az", "pfc-express", "phlpost", "pickupp", "pickupp-sg", "pigeon-express", "pilot-freight", "pitney-bowes", "pitt-ohio", "pmm", "polaris-transport", "pony-express", "pos-indonesia", "post-haste", "post-luxembourg", "posta-faroe", "posta-kenya", "posta-moldovei", "posta-north-macedonia", "posta-romana", "posta-shqiptare", "posta-slovenije", "posta-srbije", "postaplus", "postex", "postmedia-parcel-services", "postplus", "posturinn", "ppl", "precision-deliveries", "pro-carrier", "professional-couriers", "prompt-xpress", "pronto-lanka", "proships", "pts-worldwide-express", "ptt", "pullman-cargo", "pushpak-courier", "quantium-solutions", "quicksilver-sa", "quiqup", "qwintry", "raben", "ram-hand-to-hand", "redpack", "redur", "redx", "relaytech", "rivigo", "rl-carriers", "roadie", "roadrunner", "royal-express-mm", "rpx-hk", "rpx-indonesia", "rr-express-sg", "russian-post", "saee", "sagawa", "sagawa-global", "sahara-express", "saia", "sailpost", "sameday", "sapx-express", "sat-ukraine", "saudi-post", "sbs-sokuhai", "scg-express", "seino", "seko", "sendex", "sending", "serpost", "servientrega", "seven-eleven-tw", "sfc", "shadowfax", "shipa", "shipblu", "shipentegra", "shiprocket", "shree-anjani", "shree-mahabali-express", "shree-mahavir", "shree-maruti", "shree-nandan", "sicepat", "skroutz-last-mile", "skyex-ae", "skyking", "skynet-sa", "skynet-worldwide", "skypostal", "slgtrax", "slovak-parcel-service", "slovenska-posta", "smsa-express", "south-african-post-office", "southeastern-freight-lines", "sp-express", "speed-and-safe", "speedaf", "speedex", "speedpak", "speedy", "spx-br", "spx-id", "spx-my", "spx-ph", "spx-sg", "spx-th", "spx-tw", "spx-vn", "sri-lanka-post", "st-courier", "stallion-express", "starex-az", "starken", "starlinks", "steadfast", "straightship", "sundarban-courier", "surat-kargo", "swiftx", "t-cat", "t-group", "tamdis", "tanzania-posts", "taxydema", "tccs", "tci-express", "tcs-pakistan", "tdn", "tealca", "team-express-ae", "team-global-express", "team-worldwide", "tej-couriers", "teleship", "tfm-express", "tforce-freight", "tforce-logistics", "thhy", "tiki", "tirupati-courier", "tmm-express", "tnt-it", "today-kr", "toptrans", "torrestir", "total-express", "tp-logistics-th", "trackon", "tracx-logis", "trans-o-flex", "transaher", "transcorp", "transmission", "transport-rdl", "trendyol-express", "tsjy", "tst-cf-express", "tufesa", "tusass", "tws-express", "ubi-smart-parcel", "ues-uy", "united-delivery-service", "united-worldwide-couriers", "upaya", "urbano", "urvaam", "uzbekistan-post", "valmo", "vasp-expresso", "veloces", "venipak", "vestovoy", "via-cargo", "viettel-post", "vimenpaq", "vinted-go", "vitran-express", "vnpost", "vozovoz", "vrl-logistics", "wahana", "wanbexpress", "ward-trucking", "whistl", "winion-logis", "winit", "x-express-ba", "x-trac", "xde-logistics", "xdp", "xlcourier", "xpo-ltl", "xpressbees", "yalidine", "yc-delivery", "ycs-logistics", "yilong-logistics", "yimidida", "yurtici-kargo", "zajil", "zeleris", "zheldor", "zoom-ve", "zr-express"];
20012
+ export declare const CARRIER_IDS: readonly ["swiss-post", "swiss-post-cargo", "quickpac", "planzer", "aliexpress", "sunyou", "hermes", "spring-gds", "postlogistics", "dachser", "dhl", "dhl-ecommerce", "ups", "amazon-logistics", "amazon-shipping", "fedex", "gls-ch", "dpd", "dpd-fr", "mondial-relay", "relais-colis", "la-poste", "chronopost", "gls-fr", "colis-prive", "geodis", "colisweb", "c-chez-vous", "heppner", "ciblex", "paack", "asendia", "shipup", "india-post", "hermes-de", "gls-de", "delivengo", "intl-post", "unknown", "royal-mail", "parcelforce", "evri", "inpost", "an-post", "bpost", "austrian-post", "postnord", "posti", "correos-express", "seur", "mrw", "nacex", "ctt", "ctt-express", "poste-italiane", "brt", "ecoscooting", "tipsa", "ukrposhta", "usps", "canada-post", "purolator", "canpar", "ontrac", "speedx", "uniuni", "landmark-global", "old-dominion", "spee-dee", "gofo", "estafeta", "correios-br", "correos-chile", "yunexpress", "four-px", "blue-dart", "delhivery", "nz-post", "singapore-post", "japan-post", "sf-express", "sto", "yunda", "yto", "zto", "jd-logistics", "yamato", "korea-post", "thailand-post", "dtdc", "australia-post", "hongkong-post", "pos-malaysia", "ninja-van", "china-post", "packeta", "poczta-polska", "bring-posten", "aramex", "tnt", "correos-spain", "yanwen", "the-courier-guy", "j-and-t", "ems", "139express", "17feia", "247express", "2go", "4-72", "4sides", "5post", "99minutos", "a-duie-pyle", "a-tu-hora-express", "a1-post", "aaa-cooper", "ab-courier", "abf-freight", "aci-express-kr", "acs-courier", "aeropost", "aex-paraguay", "afghan-post", "air-star-xpress", "airpak-express", "ait-worldwide", "ajex", "akash-ganga", "aks-express", "alem-tat", "algerie-poste", "allegro-one", "am-home-delivery", "ameex", "american-west-express", "amerijet", "ampm", "andreani", "anjun", "anousith", "anserx", "anteraja", "ap-cargo", "apc-overnight", "apc-postal-logistics", "apple-express", "aramex-au", "aramex-nz", "aras-kargo", "arrow-xl", "asyad-express", "atlantic-courier", "averitt", "aymakan", "azerpost", "azul-cargo", "bangladesh-post", "barid-al-maghrib", "belpost", "best-express-my", "best-express-vn", "best-overnite-express", "best-transport", "better-trucks", "bex-express", "big-smart", "bjs-home-delivery", "blue-express", "blueex", "bombino", "bookurier", "border-express", "bosta", "botswana-post", "box-now", "bringer-parcel", "bts-uz", "budbee", "buffalo-ex", "bulgarian-posts", "burd-delivery", "bussgods", "byhd", "c3x", "cacesa", "campost", "cargus", "castores", "cbl-logistica", "ccfs", "cdek", "cdl", "celeritas", "central-transport", "ceska-posta", "ceva-logistics", "chazki", "chilexpress", "chit-chats", "chronodiali", "chukou1", "chunghwa-post", "chunil", "city-express-rs", "citylink-express", "citymail", "citysprint", "cj-logistics", "cj-packet", "closer-logistics", "cne", "codexpress", "connect-couriers", "coordinadora", "copa-courier", "corre", "correo-argentino", "correo-uruguayo", "correos-bolivia", "correos-cuba", "correos-de-mexico", "correos-el-salvador", "correos-nicaragua", "courier-center", "courier-it", "courier-plus-ng", "couriersplease", "credifin", "cruz-del-sur", "cse-russia", "cst-italia", "cttyex", "custom-companies", "cycloon", "cyprus-post", "d-express", "daewoo-fastex", "dai-post", "daily-xpress", "danske-fragtmaend", "dao", "day-ross", "daylight-transport", "dayton-freight", "dellin", "delnext", "deppon", "deprisa", "designer-transport", "dhl-ecommerce-es", "dhl-ecommerce-nl", "dhl-ecommerce-pl", "dhl-ecommerce-uk", "dhl-express", "dhl-freight", "dhlink", "direct-couriers", "direct-freight-express", "direx", "dnx-cargo", "dobropost", "dohrn-transfer", "domain-logistics", "domex", "dpd-at", "dpd-be", "dpd-de", "dpd-ie", "dpd-nl", "dpd-pl", "dpd-pt", "dpd-ro", "dpd-uk", "dpd-za", "dpex", "dragon-star-curier", "drop2shop", "dropp", "dsv", "dx", "dynalogic", "early-bird", "easy-mail", "ecms-express", "eco-express-ae", "econt", "ecourier", "egypt-post", "ekart", "elta", "emile", "emirates-post", "ems-vietnam", "energia-tk", "energo", "envia-colombia", "envialia", "eparcel-kr", "epost-global", "equick", "estes", "estes-forwarding", "ethiopian-post", "eurodis", "euroexpress-ba", "europochta", "evdemo-lojistik", "evri-uk", "evropat", "ewe", "exelot", "exline-kz", "exmate", "express-one", "fan-courier", "fargo-courier", "fargo-uz", "fastdrop", "fastfrate", "fedex-freight", "fedex-pl", "fermopoint", "fg-delivery", "first-delivery-tn", "first-fly-express", "first-line", "flash-express", "flash-express-ph", "fleetex", "fleetoptics", "flippost", "fliway", "flyking", "followmont", "forward-air", "forza-delivery", "foxpost", "franch-express", "fukuyama", "gaash", "gati", "gdex", "gebrueder-weiss", "geis", "gel-express", "geniki-taxydromiki", "geodis-pl", "ghana-post", "ghn", "ghtk", "globalpost", "gls-at", "gls-es", "gls-it", "gls-pl", "gms-worldwide", "go-express", "go4", "gobolt", "gofo-fr", "gofo-it", "gofo-nl", "gogo-xpress", "goodluck-courier", "grand-slam-express", "groupe-guilbault", "gs-postbox", "gsi-express", "gta-airskip", "gtl-goto", "guatex", "gzyl", "hanjin", "hapdong", "happy-post", "haypost", "hct-logistics", "helthjem", "hepsijet", "hercules-freight", "hermes-at", "hi-trans", "hispapost", "homexpress", "horoz", "hound-express", "houng-ah-loun", "hovership", "hp-mostar", "hr-parcel", "hrvatska-posta", "huahan", "hunter-express", "hywl", "icc-worldwide", "icl-express", "ics-courier", "idexpress", "ids-logistik", "ilyang-logis", "imile", "indah-logistik", "instabox", "integral-pack", "intelcom", "inter-courier", "intereuropa", "internet-express", "interrapidisimo", "intex-paketdienst", "iran-post", "israel-post", "j-and-t-au", "j-and-t-br", "j-and-t-cargo", "j-and-t-cn", "j-and-t-de", "j-and-t-middle-east", "j-and-t-mx", "jadlog", "jamaica-post", "janio", "jcex", "jeebly", "jersey-post", "jet-logistic", "jetline-couriers", "jhgj", "jitsu", "jne", "jordan-post", "jrs-express", "jrt", "js-express", "jumppoint", "kargoist", "kazpost", "kerry-tj", "kex", "kex-express-hk", "kit-tk", "kolay-gelsin", "kronos-express", "ktd", "kuehne-nagel", "kun-express", "kunyoung", "kwick-box", "kyoungdong", "kyrgyz-post", "l-post", "la-poste-burkina-faso", "la-poste-ci", "la-poste-senegal", "la-poste-tunisienne", "laar-courier", "labaih", "lao-post", "last-one-mile-coop", "latvijas-pasts", "lbc-express", "leopards-courier", "libanpost", "liccardi", "lietuvos-pastas", "lightning-express", "line-clear", "lingdong", "linhan", "lion-parcel", "logen", "loggi", "logistiq", "logoix", "loomis-express", "lotte-global", "lso", "m-and-p", "m-one", "madhur-courier", "magyar-posta", "mailamericas", "mailplus-au", "mainfreight", "major-express", "makati-express", "maltapost", "mandae", "maritime-ontario", "maruti-air", "matkahuolto", "mauritius-post", "mayiyinfu", "mds-collivery", "meest", "messenger-cz", "method", "metropolitan-warehouse", "micro-express", "midland-transport", "mng-kargo", "mongol-infinity-post", "montenegro-post", "morning-global", "mrl-global", "mtscn", "mylerz", "naqel", "nationex", "ncs-courier", "neighbour-express", "nepal-post", "netpost-vn", "next-level-delivery", "nhat-tin", "nim-express", "nipost", "nippon-express", "noest", "nord-wheel", "norsk-global", "northline", "nova-global", "nova-poshta", "nox", "nz-couriers", "oak-harbor", "oca", "ocasa", "ocs-ana", "olva-courier", "omgo", "omniva", "one-world-express", "opt-nc", "orian", "orlen-paczka", "osm-worldwide", "overseas-express", "ozon-logistics", "pack-man", "packli-punkt", "packlink", "packs", "pakistan-post", "palletways", "pandu-logistics", "pannon-xp", "paperfly", "paquetexpress", "parcelpoint", "pargo", "passport", "pathao-courier", "pavan-courier", "paxel", "paxi", "pbt", "pcp-express", "pcs-logistics-vn", "pdn-express", "pdq-chile", "pecom", "peddler", "pelican-express", "peqasus-az", "pfc-express", "phlpost", "pickupp", "pickupp-sg", "pigeon-express", "pilot-freight", "pitney-bowes", "pitt-ohio", "pmm", "polaris-transport", "pony-express", "pos-indonesia", "post-haste", "post-luxembourg", "posta-faroe", "posta-kenya", "posta-moldovei", "posta-north-macedonia", "posta-romana", "posta-shqiptare", "posta-slovenije", "posta-srbije", "postaplus", "postex", "postmedia-parcel-services", "postplus", "posturinn", "ppl", "precision-deliveries", "pro-carrier", "professional-couriers", "prompt-xpress", "pronto-lanka", "proships", "pts-worldwide-express", "ptt", "pullman-cargo", "pushpak-courier", "quantium-solutions", "quicksilver-sa", "quiqup", "qwintry", "raben", "ram-hand-to-hand", "redpack", "redur", "redx", "relaytech", "rivigo", "rl-carriers", "roadie", "roadrunner", "royal-express-mm", "rpx-hk", "rpx-indonesia", "rr-express-sg", "russian-post", "saee", "sagawa", "sagawa-global", "sahara-express", "saia", "sailpost", "sameday", "sapx-express", "sat-ukraine", "saudi-post", "sbs-sokuhai", "scg-express", "seino", "seko", "sendex", "sending", "serpost", "servientrega", "seven-eleven-tw", "sfc", "shadowfax", "shipa", "shipblu", "shipentegra", "shiprocket", "shree-anjani", "shree-mahabali-express", "shree-mahavir", "shree-maruti", "shree-nandan", "sicepat", "skroutz-last-mile", "skyex-ae", "skyking", "skynet-sa", "skynet-worldwide", "skypostal", "slgtrax", "slovak-parcel-service", "slovenska-posta", "smsa-express", "south-african-post-office", "southeastern-freight-lines", "sp-express", "speed-and-safe", "speedaf", "speedex", "speedpak", "speedy", "spx-br", "spx-id", "spx-my", "spx-ph", "spx-sg", "spx-th", "spx-tw", "spx-vn", "sri-lanka-post", "st-courier", "stallion-express", "starex-az", "starken", "starlinks", "steadfast", "straightship", "sundarban-courier", "surat-kargo", "swiftx", "t-cat", "t-group", "tamdis", "tanzania-posts", "taxydema", "tccs", "tci-express", "tcs-pakistan", "tdn", "tealca", "team-express-ae", "team-global-express", "team-worldwide", "tej-couriers", "teleship", "tfm-express", "tforce-freight", "tforce-logistics", "thhy", "tiki", "tirupati-courier", "tmm-express", "tnt-it", "today-kr", "toptrans", "torrestir", "total-express", "tp-logistics-th", "trackon", "tracx-logis", "trans-o-flex", "transaher", "transcorp", "transmission", "transport-rdl", "trendyol-express", "tsjy", "tst-cf-express", "tufesa", "tusass", "tws-express", "ubi-smart-parcel", "ues-uy", "united-delivery-service", "united-worldwide-couriers", "upaya", "urbano", "urvaam", "uzbekistan-post", "valmo", "vasp-expresso", "veloces", "venipak", "vestovoy", "via-cargo", "viettel-post", "vimenpaq", "vinted-go", "vitran-express", "vnpost", "vozovoz", "vrl-logistics", "wahana", "wanbexpress", "ward-trucking", "whistl", "winion-logis", "winit", "x-express-ba", "x-trac", "xde-logistics", "xdp", "xlcourier", "xpo-ltl", "xpressbees", "yalidine", "yc-delivery", "ycs-logistics", "yilong-logistics", "yimidida", "yurtici-kargo", "zajil", "zeleris", "zheldor", "zoom-ve", "zr-express"];
19994
20013
  export type CarrierId = (typeof CARRIER_IDS)[number];
19995
20014
  /** Each carrier's detection rule ids, in the order of its `detectionRules`. */
19996
20015
  export declare const DETECTION_RULE_IDS: Readonly<Record<CarrierId, readonly string[]>>;
@@ -18418,6 +18418,36 @@ export const CARRIER_CATALOG = {
18418
18418
  }
18419
18419
  ]
18420
18420
  },
18421
+ "kun-express": {
18422
+ "displayName": "Kun Express",
18423
+ "color": "#0761ff",
18424
+ "aliases": [
18425
+ "KUN",
18426
+ "KUNEXPRESS",
18427
+ "KunExpress",
18428
+ "鲲辰",
18429
+ "鯤辰",
18430
+ "杭州鲲辰跨境供应链管理有限公司"
18431
+ ],
18432
+ "countries": [
18433
+ "CN"
18434
+ ],
18435
+ "selectable": true,
18436
+ "timezone": "Asia/Shanghai",
18437
+ "tracking": {
18438
+ "mode": "automatic",
18439
+ "adapter": "kun-express",
18440
+ "localClocks": true
18441
+ },
18442
+ "canaryUrl": "https://t.17track.net/",
18443
+ "linkRules": [],
18444
+ "detectionRules": [
18445
+ {
18446
+ "pattern": "^KUN\\d{10}$",
18447
+ "confidence": "high"
18448
+ }
18449
+ ]
18450
+ },
18421
18451
  "kunyoung": {
18422
18452
  "displayName": "Kunyoung Express",
18423
18453
  "color": "#04378c",
@@ -31763,6 +31793,7 @@ export const CARRIER_IDS = [
31763
31793
  "kronos-express",
31764
31794
  "ktd",
31765
31795
  "kuehne-nagel",
31796
+ "kun-express",
31766
31797
  "kunyoung",
31767
31798
  "kwick-box",
31768
31799
  "kyoungdong",
@@ -32543,6 +32574,7 @@ export const DETECTION_RULE_IDS = {
32543
32574
  "kronos-express": [],
32544
32575
  "ktd": ["ktd-1"],
32545
32576
  "kuehne-nagel": ["kuehne-nagel-1", "kuehne-nagel-2"],
32577
+ "kun-express": ["kun-express-1"],
32546
32578
  "kunyoung": [],
32547
32579
  "kwick-box": [],
32548
32580
  "kyoungdong": [],
@@ -312,6 +312,7 @@ import { adapter as kexExpressHk } from '../carriers/kex-express-hk/adapter.js';
312
312
  import { adapter as kitTk } from '../carriers/kit-tk/adapter.js';
313
313
  import { adapter as koreaPost } from '../carriers/korea-post/adapter.js';
314
314
  import { adapter as kuehneNagel } from '../carriers/kuehne-nagel/adapter.js';
315
+ import { adapter as kunExpress } from '../carriers/kun-express/adapter.js';
315
316
  import { adapter as kunyoung } from '../carriers/kunyoung/adapter.js';
316
317
  import { adapter as kyoungdong } from '../carriers/kyoungdong/adapter.js';
317
318
  import { adapter as kyrgyzPost } from '../carriers/kyrgyz-post/adapter.js';
@@ -918,6 +919,7 @@ export const REGISTRY = {
918
919
  "kit-tk": kitTk,
919
920
  "korea-post": koreaPost,
920
921
  "kuehne-nagel": kuehneNagel,
922
+ "kun-express": kunExpress,
921
923
  "kunyoung": kunyoung,
922
924
  "kyoungdong": kyoungdong,
923
925
  "kyrgyz-post": kyrgyzPost,
@@ -1608,6 +1610,7 @@ export const REGISTRY = {
1608
1610
  "kronos-express": "universal",
1609
1611
  "ktd": "universal",
1610
1612
  "kuehne-nagel": "kuehne-nagel",
1613
+ "kun-express": "kun-express",
1611
1614
  "kunyoung": "kunyoung",
1612
1615
  "kwick-box": "universal",
1613
1616
  "kyoungdong": "kyoungdong",
@@ -689,6 +689,8 @@ function carrierClock(payload, state, number, status = '', destination = null) {
689
689
  return null;
690
690
  if (key === 'sunyousytrack' && SUNYOU_DESTINATION_LEG.test(status.trim()))
691
691
  return countryTimeZone(destination) ?? undefined;
692
+ if (carrier === 'imile')
693
+ return countryTimeZone(destination);
692
694
  // Cainiao's copies of Speedaf's scans keep Speedaf's digits, its arrival at the linehaul office too.
693
695
  if (carrier === 'speedaf' || (key === 'cainiao' && speedafDeparture(payload)))
694
696
  return speedafZone(payload, state.date, destination);
@@ -809,6 +811,10 @@ function readState(payload, raw, status, fallback, number, inNorthAmerica = fals
809
811
  const wallClock = WALL_CLOCKS.has(nameKey(name)) && !offset;
810
812
  const laterLeg = cttyexLaterLeg(name, status);
811
813
  const own = laterLeg ? null : carrierClock(payload, raw, number, status, destination);
814
+ // iMile's page writes every scan on the recipient country's clock, wherever it happened, and
815
+ // ParcelsApp has its digits; read on iMile's catalog zone they came out early. A destination
816
+ // of one zone places them, and without one they keep their wall clock.
817
+ const imileWall = own === null && !offset && typeof name === 'string' && carrierIdFromName(name) === 'imile';
812
818
  const sited = own === undefined ? siteZone(payload, raw, number, inNorthAmerica, status, destination) : undefined;
813
819
  const placed = own !== undefined ? own : sited;
814
820
  // A posting that only its office's capital places borrows first (`postingOffice`).
@@ -823,7 +829,7 @@ function readState(payload, raw, status, fallback, number, inNorthAmerica = fals
823
829
  local: zone !== null && zone === regionScanZone(name, location, inNorthAmerica)?.zone,
824
830
  fallback: wallClock || office ? fitsPlace(fallback, location) : null, known: known?.zone ?? null, arrival: known?.country ?? null,
825
831
  // With no zone, a scan whose label nothing vouches for keeps its wall clock.
826
- wallOnly: laterLeg || unknownNetwork(name) || militaryPostOffice(location) };
832
+ wallOnly: laterLeg || imileWall || unknownNetwork(name) || militaryPostOffice(location) };
827
833
  }
828
834
  /**
829
835
  * The zone of each scan. One from a network that is not a wall clock keeps
@@ -1119,8 +1125,9 @@ function parseHistory(payload, trackingNumber, timezone = null) {
1119
1125
  // A DHL Express scan whose facility the rule cannot place is a wall clock
1120
1126
  // with no instant, and so is a UPS or FedEx scan with no location that
1121
1127
  // nothing places. A scan at a US military post office, of a network no
1122
- // table knows (`unknownNetwork`) or of CTTYEX after China (`cttyexLaterLeg`)
1123
- // keeps its wall clock as its local time. Any other scan with no zone
1128
+ // table knows (`unknownNetwork`), of CTTYEX after China (`cttyexLaterLeg`)
1129
+ // or of iMile for a destination of several zones keeps its wall clock as
1130
+ // its local time. Any other scan with no zone
1124
1131
  // keeps ParcelsApp's label.
1125
1132
  const facility = !zone && relaysFacilityClock(name);
1126
1133
  const unplaced = facility || (!zone && !entry.location && UNLOCATED_LOCAL_CLOCKS.has(nameKey(name)));
@@ -247,8 +247,10 @@ function providerWordingStage(description) {
247
247
  // A shipment manifested, with a courier on the way to collect it from the sender: not in hand yet.
248
248
  if (/^manifested(?: - out for pick-?up)?[.!]?$/i.test(value))
249
249
  return 'registered';
250
- // GZYL's destination processing centre taking the cleared parcel and sending it on, in GZYL's own spelling.
251
- if (/^internationall?i?y package received at processing cent(?:er|re)[.!]?$|^leave the e?mail processing cent(?:er|re)[.!]?$/i.test(value))
250
+ // GZYL's destination processing centre taking the cleared parcel and sending it on, in GZYL's own spelling,
251
+ // and a line's scan leaving the named city's centre after import clearance.
252
+ if (/^internationall?i?y package received at processing cent(?:er|re)[.!]?$|^leave the (?:e?mail|[a-z][a-z .'-]{1,30}?) processing cent(?:er|re)[.!]?$/i.test(value)
253
+ && !/^leave the return\b/i.test(value))
252
254
  return 'in_transit';
253
255
  // Mayi Yinfu's parcel booked out of its operations centre, and the flight booked for it, as its own map reads them.
254
256
  if (/^已出库(?:[,,]货物离开操作中心)?$|^已排航班$/u.test(value))
@@ -2,7 +2,7 @@
2
2
  "openapi": "3.1.0",
3
3
  "info": {
4
4
  "title": "Universal Parcel Scraper",
5
- "version": "0.580.0"
5
+ "version": "0.581.0"
6
6
  },
7
7
  "paths": {
8
8
  "/health": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "universal-parcel-scraper",
3
- "version": "0.580.0-main.2721",
3
+ "version": "0.581.0-main.2728",
4
4
  "description": "Self-hosted parcel tracking: carrier detection, dedicated scrapers and optional universal providers.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",