shipflow 0.2.1 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,9 +8,10 @@ Think EasyPost / Shippo, but purpose-built for Saudi Arabia and the GCC.
8
8
 
9
9
  - **Unified types** — one `CreateShipmentInput`, one `TrackingResult`, one `WebhookEvent`, regardless of carrier
10
10
  - **Tree-shakeable** — only the carriers you import are bundled
11
- - **Auto-validation** — Zod schemas validate every `createShipment()` call before it hits the network
11
+ - **Auto-validation** — Valibot schemas validate every `createShipment()` call before it hits the network
12
12
  - **Webhook parsing** — normalize incoming carrier webhooks into a single event format
13
- - **Zero runtime dependencies** — Bun-native `fetch`, no axios/node-fetch
13
+ - **Smart retries** — dependency-free retry with jittered backoff that honors carrier `Retry-After` on 429/503, surfacing a `RateLimitError` when the wait is too long to absorb inline
14
+ - **Minimal dependencies** — only [Valibot](https://github.com/fabian-hiller/valibot) for validation; uses the runtime's global `fetch` (Node 20+, Deno, Bun, edge/workers), no axios/node-fetch
14
15
  - **TypeScript-first** — strict types, no `any`
15
16
 
16
17
  ## Installation
@@ -165,7 +166,8 @@ things make it different from the other carriers:
165
166
  set `locationBaseUrl` on the config.
166
167
  - **"Fake 200 OK" errors** — Aramex returns HTTP 200 even on logical failures, with
167
168
  `HasErrors: true` + `Notifications[]`. ShipFlow surfaces these as `APIError`, including
168
- per-shipment errors inside an otherwise-clean `CreateShipments` batch.
169
+ per-shipment errors inside an otherwise-clean `CreateShipments` batch. Throttling
170
+ notifications in that envelope are surfaced as `RateLimitError` so retries back off.
169
171
  - **Rates are supported** (`getRates` → `CalculateRate`), unlike Aymakan/SMSA.
170
172
  - **`cancelShipment` is unsupported** (the classic API has no shipment-cancel operation) and
171
173
  throws `UnsupportedOperationError`. Pickups can be cancelled via `cancelPickup`.
@@ -308,7 +310,7 @@ interface WebhookEvent {
308
310
 
309
311
  ## Input Validation
310
312
 
311
- All `createShipment()` calls are **automatically validated** using Zod schemas before hitting the carrier API. Invalid input throws a `ValidationError` with field-level details:
313
+ All `createShipment()` calls are **automatically validated** using Valibot schemas before hitting the carrier API. Invalid input throws a `ValidationError` with field-level details:
312
314
 
313
315
  ```typescript
314
316
  try {
@@ -340,7 +342,7 @@ validateCreateShipmentInput(input); // throws ValidationError or returns validat
340
342
  validatePickupRequest(pickupInput); // same pattern
341
343
  ```
342
344
 
343
- Exported Zod schemas for advanced use (custom refinements, partial validation, etc.):
345
+ Exported Valibot schemas for advanced use (custom refinements, partial validation, etc.):
344
346
 
345
347
  ```typescript
346
348
  import {
@@ -359,6 +361,7 @@ All errors extend `ShipFlowError` for easy catch-all handling:
359
361
  import {
360
362
  ShipFlowError,
361
363
  NetworkError,
364
+ RateLimitError,
362
365
  APIError,
363
366
  ValidationError,
364
367
  AuthenticationError,
@@ -373,6 +376,8 @@ try {
373
376
  // Bad input — check error.issues
374
377
  } else if (error instanceof AuthenticationError) {
375
378
  // Invalid API key
379
+ } else if (error instanceof RateLimitError) {
380
+ // Rate limited — check error.retryAfterMs (ms to wait), reschedule if set
376
381
  } else if (error instanceof APIError) {
377
382
  // Carrier returned an error — check error.statusCode, error.errors
378
383
  } else if (error instanceof NetworkError) {
@@ -381,6 +386,37 @@ try {
381
386
  }
382
387
  ```
383
388
 
389
+ > `RateLimitError extends APIError`, so check it **before** `APIError` in your
390
+ > `if`/`else` chain (a plain `catch (e) { if (e instanceof APIError) }` still
391
+ > catches it).
392
+
393
+ ### Retries & rate limiting
394
+
395
+ Safe, idempotent requests (GETs, plus tracking endpoints opted in by the
396
+ adapters) are retried automatically with **jittered exponential backoff**.
397
+ Mutating requests (create/cancel) are **not** retried by default, so a timed-out
398
+ `createShipment` never risks a duplicate on the carrier.
399
+
400
+ When a carrier replies `429`/`503` with a `Retry-After` header, ShipFlow:
401
+
402
+ - **honors it inline** if the wait is within the inline cap (15s by default),
403
+ sleeping out the window (plus a little jitter) before retrying; otherwise
404
+ - **stops and throws `RateLimitError`** carrying `retryAfterMs`, so a durable
405
+ queue/worker can reschedule instead of blocking the request for minutes.
406
+
407
+ ```typescript
408
+ try {
409
+ await client.carrier("aymakan").track(trackingNumber);
410
+ } catch (error) {
411
+ if (error instanceof RateLimitError && error.retryAfterMs != null) {
412
+ await scheduleRetryIn(error.retryAfterMs); // your queue/worker
413
+ }
414
+ }
415
+ ```
416
+
417
+ Aramex reports throttling inside its "fake 200" envelope rather than via HTTP
418
+ 429; ShipFlow detects that and raises the same `RateLimitError`.
419
+
384
420
  ## Custom Adapters
385
421
 
386
422
  Implement the `CarrierAdapter` interface or extend `BaseCarrierAdapter`:
@@ -51,6 +51,13 @@ export declare class AramexAdapter extends BaseCarrierAdapter {
51
51
  * Extracts the Aramex "Fake 200 OK" error (envelope-level `HasErrors` +
52
52
  * `Notifications`). Passed to every request so the HttpClient raises APIError.
53
53
  */
54
+ /**
55
+ * Aramex reports throttling inside its "fake 200" envelope (and sometimes on a
56
+ * non-429 status) rather than via HTTP 429, so status-code detection misses it.
57
+ * Match the rate-limit wording in the notifications and flag it so the
58
+ * HttpClient raises a retryable `RateLimitError` instead of a plain APIError.
59
+ */
60
+ private static readonly RATE_LIMIT_PATTERN;
54
61
  private static aramexErrorExtractor;
55
62
  private static notificationsToErrors;
56
63
  protected executeCreateShipment(input: CreateShipmentInput): Promise<Shipment>;
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/carriers/aramex/adapter.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;GAWG;AAYH,OAAO,KAAK,EACV,aAAa,EACb,IAAI,EACJ,mBAAmB,EACnB,QAAQ,EACR,MAAM,EACN,aAAa,EACb,IAAI,EACJ,QAAQ,EACR,cAAc,EACf,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAsD7C,MAAM,WAAW,YAAa,SAAQ,aAAa;IACjD,WAAW,EAAE;QACX,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,aAAa,EAAE,MAAM,CAAC;QACtB,UAAU,EAAE,MAAM,CAAC;QACnB,aAAa,EAAE,MAAM,CAAC;QACtB,kBAAkB,EAAE,MAAM,CAAC;KAC5B,CAAC;IACF,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4DAA4D;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,qBAAa,aAAc,SAAQ,kBAAkB;IACnD,QAAQ,CAAC,IAAI,YAAY;IACzB,QAAQ,CAAC,kBAAkB,WAWzB;IAEF,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,QAAQ,CAAa;IAC7B,OAAO,CAAC,YAAY,CAAa;gBAErB,MAAM,EAAE,YAAY;IAuBhC,SAAS,CAAC,UAAU,IAAI,MAAM;IAM9B,8EAA8E;IAC9E,OAAO,CAAC,WAAW;IAInB,OAAO,KAAK,YAAY,GAEvB;IAED,OAAO,CAAC,eAAe;IAQvB;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAyBnC,OAAO,CAAC,MAAM,CAAC,qBAAqB;cAcpB,qBAAqB,CACnC,KAAK,EAAE,mBAAmB,GACzB,OAAO,CAAC,QAAQ,CAAC;IA6CpB;;;;;;;;OAQG;IACG,mBAAmB,CACvB,MAAM,EAAE,mBAAmB,EAAE,GAC5B,OAAO,CAAC,QAAQ,EAAE,CAAC;IAwDtB;;;OAGG;IACH,cAAc,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQnD,QAAQ,CACZ,cAAc,EAAE,MAAM,EACtB,OAAO,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,GAC9B,OAAO,CAAC,MAAM,CAAC;IA8BZ,KAAK,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAetD,aAAa,CAAC,eAAe,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IA4BnE,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAU5D,QAAQ,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IA4BrD,YAAY,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC;IAyDnD,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAoBzD,SAAS,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAehD,mBAAmB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;CAcrE"}
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/carriers/aramex/adapter.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;GAWG;AAYH,OAAO,KAAK,EACV,aAAa,EACb,IAAI,EACJ,mBAAmB,EACnB,QAAQ,EACR,MAAM,EACN,aAAa,EACb,IAAI,EACJ,QAAQ,EACR,cAAc,EACf,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAsD7C,MAAM,WAAW,YAAa,SAAQ,aAAa;IACjD,WAAW,EAAE;QACX,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,aAAa,EAAE,MAAM,CAAC;QACtB,UAAU,EAAE,MAAM,CAAC;QACnB,aAAa,EAAE,MAAM,CAAC;QACtB,kBAAkB,EAAE,MAAM,CAAC;KAC5B,CAAC;IACF,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4DAA4D;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,qBAAa,aAAc,SAAQ,kBAAkB;IACnD,QAAQ,CAAC,IAAI,YAAY;IACzB,QAAQ,CAAC,kBAAkB,WAWzB;IAEF,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,QAAQ,CAAa;IAC7B,OAAO,CAAC,YAAY,CAAa;gBAErB,MAAM,EAAE,YAAY;IAuBhC,SAAS,CAAC,UAAU,IAAI,MAAM;IAM9B,8EAA8E;IAC9E,OAAO,CAAC,WAAW;IAInB,OAAO,KAAK,YAAY,GAEvB;IAED,OAAO,CAAC,eAAe;IAQvB;;;OAGG;IACH;;;;;OAKG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CACe;IAEzD,OAAO,CAAC,MAAM,CAAC,oBAAoB;IA4BnC,OAAO,CAAC,MAAM,CAAC,qBAAqB;cAcpB,qBAAqB,CACnC,KAAK,EAAE,mBAAmB,GACzB,OAAO,CAAC,QAAQ,CAAC;IA6CpB;;;;;;;;OAQG;IACG,mBAAmB,CACvB,MAAM,EAAE,mBAAmB,EAAE,GAC5B,OAAO,CAAC,QAAQ,EAAE,CAAC;IAwDtB;;;OAGG;IACH,cAAc,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQnD,QAAQ,CACZ,cAAc,EAAE,MAAM,EACtB,OAAO,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,GAC9B,OAAO,CAAC,MAAM,CAAC;IA8BZ,KAAK,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAetD,aAAa,CAAC,eAAe,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IA4BnE,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAU5D,QAAQ,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IA4BrD,YAAY,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC;IAyDnD,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAoBzD,SAAS,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAehD,mBAAmB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;CAcrE"}
@@ -6,7 +6,7 @@ import {
6
6
  ValidationError,
7
7
  validateCreateShipmentInput,
8
8
  validatePickupRequest
9
- } from "../../index-qjtxhwzv.js";
9
+ } from "../../index-qnxj8bct.js";
10
10
 
11
11
  // src/carriers/aramex/services.ts
12
12
  var AramexProductGroup = {
@@ -481,6 +481,7 @@ class AramexAdapter extends BaseCarrierAdapter {
481
481
  version: cfg.version
482
482
  });
483
483
  }
484
+ static RATE_LIMIT_PATTERN = /rate.?limit|too many request|throttl|quota exceeded/i;
484
485
  static aramexErrorExtractor(json) {
485
486
  const obj = json;
486
487
  const notifications = obj?.Notifications ?? [];
@@ -489,7 +490,8 @@ class AramexAdapter extends BaseCarrierAdapter {
489
490
  return {
490
491
  hasError,
491
492
  message,
492
- errors: notifications.length ? AramexAdapter.notificationsToErrors(notifications) : undefined
493
+ errors: notifications.length ? AramexAdapter.notificationsToErrors(notifications) : undefined,
494
+ rateLimited: hasError && AramexAdapter.RATE_LIMIT_PATTERN.test(message ?? "")
493
495
  };
494
496
  }
495
497
  static notificationsToErrors(notifications) {
@@ -691,4 +693,4 @@ export {
691
693
  AramexAdapter
692
694
  };
693
695
 
694
- //# debugId=BC16779A6E5B3D1F64756E2164756E21
696
+ //# debugId=A6EBA2B597BA645F64756E2164756E21
@@ -4,9 +4,9 @@
4
4
  "sourcesContent": [
5
5
  "// file: src/carriers/aramex/services.ts\n/**\n * Aramex Service / Product Codes\n * Use these constants for type-safe product and payment selection.\n *\n * Reference: Aramex Shipping Services API manual, Appendix A (Product Types)\n * and Appendix B (Payment Types).\n */\n\n/** Shipment product group: domestic vs international/express. */\nexport const AramexProductGroup = {\n EXPRESS: \"EXP\",\n DOMESTIC: \"DOM\",\n} as const;\n\n/** Product type codes (Appendix A). `OND` is the only domestic type. */\nexport const AramexProductType = {\n /** Domestic (DOM group) */\n DOMESTIC: \"OND\",\n /** Priority Document Express */\n PRIORITY_DOCUMENT_EXPRESS: \"PDX\",\n /** Priority Parcel Express */\n PRIORITY_PARCEL_EXPRESS: \"PPX\",\n /** Priority Letter Express */\n PRIORITY_LETTER_EXPRESS: \"PLX\",\n /** Deferred Document Express */\n DEFERRED_DOCUMENT_EXPRESS: \"DDX\",\n /** Deferred Parcel Express */\n DEFERRED_PARCEL_EXPRESS: \"DPX\",\n /** Ground Document Express */\n GROUND_DOCUMENT_EXPRESS: \"GDX\",\n /** Ground Parcel Express */\n GROUND_PARCEL_EXPRESS: \"GPX\",\n /** Economy Parcel Express */\n ECONOMY_PARCEL_EXPRESS: \"EPX\",\n /** Return */\n RETURN: \"RTN\",\n} as const;\n\n/** Payment type codes (Appendix B). */\nexport const AramexPaymentType = {\n PREPAID: \"P\",\n COLLECT: \"C\",\n THIRD_PARTY: \"3\",\n} as const;\n\n/**\n * Special service codes joined (comma-separated) into `Details.Services`.\n * e.g. `\"CODS\"` enables Cash-On-Delivery handling.\n */\nexport const AramexService = {\n COD: \"CODS\",\n INSURANCE: \"INSR\",\n} as const;\n\nexport type AramexProductGroupType =\n (typeof AramexProductGroup)[keyof typeof AramexProductGroup];\nexport type AramexProductTypeCode =\n (typeof AramexProductType)[keyof typeof AramexProductType];\nexport type AramexPaymentTypeCode =\n (typeof AramexPaymentType)[keyof typeof AramexPaymentType];\n\n/**\n * Aramex Tracking Status Codes (`UpdateCode`) → unified ShipmentStatus.\n *\n * IMPORTANT: Aramex does not publish a stable, comprehensive `UpdateCode` list,\n * and the codes vary by region/account. This table is a best-effort starter —\n * entries marked `VERIFY` should be confirmed against live tracking data. The\n * mapper falls back to a description-keyword heuristic and then `\"unknown\"`, so\n * an unmapped code never breaks tracking.\n */\nexport const AramexStatusCodes = {\n \"SH001\": \"created\", // Shipment information received (VERIFY)\n \"SH002\": \"picked_up\", // Picked up from shipper (VERIFY)\n \"SH004\": \"at_warehouse\", // Received at origin facility (VERIFY)\n \"SH005\": \"out_for_delivery\", // Out on delivery courier\n \"SH014\": \"delivered\", // Shipment delivered (VERIFY)\n \"SH060\": \"in_transit\", // Departed / in transit (VERIFY)\n \"SH074\": \"exception\", // Delivery attempt failed (VERIFY)\n \"SH159\": \"exception\", // Held / customs / address problem (VERIFY)\n \"SH212\": \"returned\", // Returned to shipper (VERIFY)\n \"SH235\": \"delivered\", // Delivered (VERIFY)\n} as const;\n",
6
6
  "// file: src/carriers/aramex/mappers.ts\n/**\n * Aramex Data Mappers\n * Transform between unified ShipFlow types and the Aramex JSON API formats.\n */\n\nimport type {\n Address,\n City,\n CreateShipmentInput,\n Dimensions,\n Location,\n Pickup,\n PickupRequest,\n Rate,\n Shipment,\n ShipmentStatus,\n TrackingEvent,\n TrackingResult,\n} from \"../../core/types\";\nimport {\n AramexProductType,\n AramexService,\n AramexStatusCodes,\n} from \"./services\";\nimport type {\n AramexCalculateRateResponse,\n AramexClientInfo,\n AramexContact,\n AramexDimensions,\n AramexMoney,\n AramexOffice,\n AramexParty,\n AramexPartyAddress,\n AramexPickupObject,\n AramexProcessedPickup,\n AramexProcessedShipment,\n AramexShipment,\n AramexShipmentDetails,\n AramexTrackingResult,\n AramexTrackShipmentsResponse,\n AramexWeight,\n} from \"./types\";\n\n// ============================================================================\n// CREDENTIALS / CLIENT INFO\n// ============================================================================\n\nexport interface AramexCredentials {\n userName: string;\n password: string;\n accountNumber: string;\n accountPin: string;\n accountEntity: string;\n accountCountryCode: string;\n}\n\n/** Build the ClientInfo block injected into every Aramex request body. */\nexport function buildClientInfo(\n credentials: AramexCredentials,\n opts?: { source?: number; version?: string },\n): AramexClientInfo {\n return {\n UserName: credentials.userName,\n Password: credentials.password,\n Version: opts?.version ?? \"v1.0\",\n AccountNumber: credentials.accountNumber,\n AccountPin: credentials.accountPin,\n AccountEntity: credentials.accountEntity,\n AccountCountryCode: credentials.accountCountryCode,\n Source: opts?.source ?? 24,\n };\n}\n\n// ============================================================================\n// STATUS MAPPING\n// ============================================================================\n\nexport function mapAramexStatus(\n updateCode: string,\n): ShipmentStatus | undefined {\n const mapped = AramexStatusCodes[updateCode as keyof typeof AramexStatusCodes];\n return mapped as ShipmentStatus | undefined;\n}\n\n/**\n * Secondary heuristic: derive a status from the human-readable update text when\n * the `UpdateCode` isn't in our table (Aramex codes vary by region). Ordered so\n * the more specific phrases win (e.g. \"out for delivery\" before \"delivered\").\n */\nexport function statusFromDescription(\n description: string | undefined,\n): ShipmentStatus | undefined {\n if (!description) return undefined;\n const d = description.toLowerCase();\n if (/out for delivery|on delivery|with delivery courier/.test(d))\n return \"out_for_delivery\";\n // Failure phrases must be checked before the generic \"deliver\" match, so\n // \"delivery failed\" / \"undeliverable\" aren't mistaken for a delivery.\n if (/fail|unable|undeliver|exception|held|on hold|problem|refused|damaged/.test(d))\n return \"exception\";\n if (/deliver/.test(d)) return \"delivered\";\n if (/return/.test(d)) return \"returned\";\n if (/cancel/.test(d)) return \"cancelled\";\n if (/picked up|collected|pickup/.test(d)) return \"picked_up\";\n if (/transit|departed|forwarded|en route/.test(d)) return \"in_transit\";\n if (/received at|arrived|facility|warehouse|sorting|hub/.test(d))\n return \"at_warehouse\";\n if (/created|information received|booked/.test(d)) return \"created\";\n return undefined;\n}\n\n// ============================================================================\n// DATES (WCF /Date(ms)/ format)\n// ============================================================================\n\n/** Parse an Aramex WCF date (`/Date(1609459200000+0300)/`) or ISO string. */\nexport function parseAramexDate(value: string | null | undefined): Date {\n if (!value) return new Date(Number.NaN);\n const wcf = /\\/Date\\((-?\\d+)(?:[+-]\\d{4})?\\)\\//.exec(value);\n if (wcf?.[1]) return new Date(Number.parseInt(wcf[1], 10));\n return new Date(value);\n}\n\nfunction toWcfDate(date: Date): string {\n return `/Date(${date.getTime()})/`;\n}\n\n// ============================================================================\n// HELPERS\n// ============================================================================\n\nfunction round(value: number): number {\n return Math.round(value * 1000) / 1000;\n}\n\nconst VALID_PRODUCT_TYPES = new Set(\n Object.values(AramexProductType) as string[],\n);\n\nfunction getMeta(\n input: CreateShipmentInput,\n key: string,\n): string | undefined {\n const value = input.options?.metadata?.[key];\n return typeof value === \"string\" ? value : undefined;\n}\n\n/**\n * Resolve ProductGroup (DOM/EXP) and ProductType. Defaults to domestic when\n * shipper and consignee share a country, else express. Overridable via\n * `serviceType` (a valid Aramex product code) or `options.metadata`.\n */\nexport function resolveProductGroupAndType(input: CreateShipmentInput): {\n productGroup: \"EXP\" | \"DOM\";\n productType: string;\n} {\n const sameCountry =\n input.shipper.countryCode.trim().toUpperCase() ===\n input.consignee.countryCode.trim().toUpperCase();\n\n const metaGroup = getMeta(input, \"productGroup\")?.toUpperCase();\n const productGroup: \"EXP\" | \"DOM\" =\n metaGroup === \"EXP\" || metaGroup === \"DOM\"\n ? metaGroup\n : sameCountry\n ? \"DOM\"\n : \"EXP\";\n\n const candidate = getMeta(input, \"productType\") ?? input.serviceType;\n const productType =\n candidate && VALID_PRODUCT_TYPES.has(candidate)\n ? candidate\n : productGroup === \"DOM\"\n ? AramexProductType.DOMESTIC\n : AramexProductType.ECONOMY_PARCEL_EXPRESS;\n\n return { productGroup, productType };\n}\n\n/**\n * Resolve the freight PaymentType — who pays the SHIPPING cost: P = prepaid\n * (billed to the shipper's Aramex account), C = collect (charged to the\n * consignee), 3 = third party.\n *\n * This is INDEPENDENT of COD. COD is the cash collected from the consignee for\n * the goods, carried by the `CODS` service + `CashOnDeliveryAmount` — not by\n * PaymentType. KSA/GCC e-commerce COD is overwhelmingly prepaid freight (billed\n * to the merchant) with the goods value collected on delivery, so freight\n * defaults to \"P\". Enabling COD must NOT force freight onto the consignee.\n * Override the freight payer with `options.metadata.paymentType`.\n */\nfunction resolvePaymentType(input: CreateShipmentInput): \"P\" | \"C\" | \"3\" {\n const meta = getMeta(input, \"paymentType\");\n if (meta === \"P\" || meta === \"C\" || meta === \"3\") return meta;\n return \"P\";\n}\n\n/** Aggregate parcel weights; preserve the unit when uniform, else normalize to kg. */\nfunction aggregateWeight(input: CreateShipmentInput): AramexWeight {\n const allLb = input.parcels.every((p) => p.weight.unit === \"lb\");\n if (allLb) {\n const value = input.parcels.reduce((s, p) => s + p.weight.value, 0);\n return { Value: round(value), Unit: \"Lb\" };\n }\n const value = input.parcels.reduce(\n (s, p) =>\n s + (p.weight.unit === \"lb\" ? p.weight.value * 0.453592 : p.weight.value),\n 0,\n );\n return { Value: round(value), Unit: \"Kg\" };\n}\n\nfunction mapDimensions(dims?: Dimensions): AramexDimensions | null {\n if (!dims) return null;\n const factor = dims.unit === \"in\" ? 2.54 : 1;\n return {\n Length: round(dims.length * factor),\n Width: round(dims.width * factor),\n Height: round(dims.height * factor),\n Unit: \"CM\",\n };\n}\n\n/**\n * Build an Aramex `PartyAddress` with every WCF-required member present. The\n * contract marks `Line2`, `Line3` and `PostCode` as REQUIRED — omitting any\n * fails deserialization (\"required data members 'Line2, Line3, PostCode' were\n * not found\") — so they default to \"\" rather than being dropped. Coordinates\n * stay optional and are omitted when unset, so a 0,0 default is never sent as a\n * real location. This is the single source of truth for the address shape;\n * every Aramex address (shipper, consignee, pickup) goes through it.\n */\nfunction buildPartyAddress(fields: {\n line1: string;\n line2?: string;\n line3?: string;\n city: string;\n state?: string;\n postCode?: string;\n countryCode: string;\n coordinates?: { latitude: number; longitude: number };\n}): AramexPartyAddress {\n return {\n Line1: fields.line1,\n Line2: fields.line2 ?? \"\",\n Line3: fields.line3 ?? \"\",\n City: fields.city,\n StateOrProvinceCode: fields.state,\n PostCode: fields.postCode ?? \"\",\n CountryCode: fields.countryCode,\n Longitude: fields.coordinates?.longitude,\n Latitude: fields.coordinates?.latitude,\n };\n}\n\nfunction mapAddress(addr: Address): AramexPartyAddress {\n return buildPartyAddress({\n line1: addr.line1,\n line2: addr.line2,\n line3: addr.neighbourhood,\n city: addr.city,\n state: addr.state,\n postCode: addr.postalCode,\n countryCode: addr.countryCode,\n coordinates: addr.coordinates,\n });\n}\n\n/**\n * Build an Aramex `Contact`. Aramex's WCF Contact contract marks its string\n * members as REQUIRED (the same pattern confirmed live for Address and\n * Transaction — an empty value fails deserialization, an empty string is\n * accepted), so every member is sent, defaulting to \"\".\n */\nfunction buildContact(opts: {\n personName: string;\n companyName: string;\n phone: string;\n email?: string;\n}): AramexContact {\n return {\n Department: \"\",\n PersonName: opts.personName,\n Title: \"\",\n CompanyName: opts.companyName,\n PhoneNumber1: opts.phone,\n PhoneNumber1Ext: \"\",\n PhoneNumber2: \"\",\n CellPhone: opts.phone,\n EmailAddress: opts.email ?? \"\",\n Type: \"\",\n };\n}\n\nfunction mapContact(addr: Address, fallbackCompany?: string): AramexContact {\n return buildContact({\n personName: addr.name,\n companyName: addr.company ?? fallbackCompany ?? addr.name,\n phone: addr.phone,\n email: addr.email,\n });\n}\n\nfunction mapParty(\n addr: Address,\n accountNumber?: string,\n fallbackCompany?: string,\n): AramexParty {\n return {\n AccountNumber: accountNumber,\n PartyAddress: mapAddress(addr),\n Contact: mapContact(addr, fallbackCompany),\n };\n}\n\n/** Shared between CreateShipments and CalculateRate. */\nfunction mapShipmentDetails(\n input: CreateShipmentInput,\n productGroup: \"EXP\" | \"DOM\",\n productType: string,\n paymentType: \"P\" | \"C\" | \"3\",\n): AramexShipmentDetails {\n const numberOfPieces =\n input.parcels.reduce((s, p) => s + p.pieces, 0) || 1;\n const description =\n input.parcels\n .map((p) => p.description)\n .filter(Boolean)\n .join(\", \") || \"Goods\";\n\n const services: string[] = [];\n let cashOnDelivery: AramexMoney | null = null;\n if (input.cod?.enabled) {\n // Use the caller-supplied COD currency — never hardcode.\n cashOnDelivery = {\n Value: input.cod.amount,\n CurrencyCode: input.cod.currency,\n };\n services.push(AramexService.COD);\n }\n\n const customsValue: AramexMoney | null = input.declaredValue\n ? {\n Value: input.declaredValue.amount,\n CurrencyCode: input.declaredValue.currency,\n }\n : null;\n\n // Insurance (INSR) must be accompanied by an amount to insure. Aramex rejects\n // the service with a null InsuranceAmount, so only request it when a declared\n // value is present to base the insured amount on.\n const insuranceAmount: AramexMoney | null =\n input.options?.isInsured && customsValue ? customsValue : null;\n if (insuranceAmount) services.push(AramexService.INSURANCE);\n\n return {\n Dimensions: mapDimensions(input.parcels[0]?.dimensions),\n ActualWeight: aggregateWeight(input),\n ChargeableWeight: null,\n DescriptionOfGoods: description,\n GoodsOriginCountry: input.shipper.countryCode,\n NumberOfPieces: numberOfPieces,\n ProductGroup: productGroup,\n ProductType: productType,\n PaymentType: paymentType,\n PaymentOptions: \"\",\n CustomsValueAmount: customsValue,\n CashOnDeliveryAmount: cashOnDelivery,\n InsuranceAmount: insuranceAmount,\n Services: services.join(\",\") || undefined,\n };\n}\n\n// ============================================================================\n// REQUEST MAPPERS\n// ============================================================================\n\nexport interface AramexShipmentContext {\n accountNumber: string;\n companyName?: string;\n}\n\nexport function mapCreateShipmentRequest(\n input: CreateShipmentInput,\n ctx: AramexShipmentContext,\n): AramexShipment {\n const { productGroup, productType } = resolveProductGroupAndType(input);\n const paymentType = resolvePaymentType(input);\n const now = new Date();\n const due = new Date(now.getTime() + 24 * 60 * 60 * 1000);\n\n return {\n Reference1: input.reference,\n Reference2: input.options?.customerTracking,\n Shipper: mapParty(input.shipper, ctx.accountNumber, ctx.companyName),\n Consignee: mapParty(input.consignee),\n ThirdParty: null,\n ShippingDateTime: toWcfDate(now),\n DueDate: toWcfDate(due),\n Comments: getMeta(input, \"comments\"),\n PickupLocation: getMeta(input, \"pickupLocation\"),\n Details: mapShipmentDetails(input, productGroup, productType, paymentType),\n Attachments: null,\n ForeignHAWB: null,\n TransportType: 0,\n Number: null,\n };\n}\n\nexport function mapCalculateRateRequest(\n input: CreateShipmentInput,\n preferredCurrency?: string,\n): {\n OriginAddress: AramexPartyAddress;\n DestinationAddress: AramexPartyAddress;\n ShipmentDetails: AramexShipmentDetails;\n PreferredCurrencyCode?: string;\n} {\n const { productGroup, productType } = resolveProductGroupAndType(input);\n const paymentType = resolvePaymentType(input);\n return {\n OriginAddress: mapAddress(input.shipper),\n DestinationAddress: mapAddress(input.consignee),\n ShipmentDetails: mapShipmentDetails(\n input,\n productGroup,\n productType,\n paymentType,\n ),\n PreferredCurrencyCode:\n preferredCurrency ??\n input.cod?.currency ??\n input.declaredValue?.currency,\n };\n}\n\nexport interface AramexPickupContext {\n accountNumber: string;\n countryCode: string;\n companyName?: string;\n}\n\nexport function mapPickupRequest(\n input: PickupRequest,\n ctx: AramexPickupContext,\n): AramexPickupObject {\n const pickupDate = new Date(`${input.date}T00:00:00`);\n const ready = new Date(`${input.date}T09:00:00`);\n const closing = new Date(`${input.date}T17:00:00`);\n\n return {\n Reference1: input.trackingNumbers?.[0],\n // Routed through buildPartyAddress so the pickup address carries the same\n // WCF-required members (Line2/Line3/PostCode) as shipper/consignee — a\n // hand-built address that omits them fails Aramex deserialization.\n PickupAddress: buildPartyAddress({\n line1: input.address,\n city: input.city,\n countryCode: ctx.countryCode,\n }),\n PickupContact: buildContact({\n personName: input.contactName,\n companyName: ctx.companyName ?? input.contactName,\n phone: input.contactPhone,\n }),\n PickupLocation: \"Reception\",\n PickupDate: toWcfDate(pickupDate),\n ReadyTime: toWcfDate(ready),\n LastPickupTime: toWcfDate(closing),\n ClosingTime: toWcfDate(closing),\n Comments: input.timeSlot,\n Status: \"Ready\",\n PickupItems: {\n PickupItemDetail: [\n {\n ProductGroup: \"DOM\",\n ProductType: AramexProductType.DOMESTIC,\n Payment: \"P\",\n NumberOfShipments: input.shipmentCount,\n NumberOfPieces: input.shipmentCount,\n ShipmentWeight: { Value: 1, Unit: \"Kg\" },\n },\n ],\n },\n };\n}\n\n// ============================================================================\n// RESPONSE MAPPERS\n// ============================================================================\n\nexport function mapShipmentResponse(\n processed: AramexProcessedShipment,\n input?: CreateShipmentInput,\n): Shipment {\n const trackingNumber = processed.ID || processed.ShipmentNumber || \"\";\n const labelUrl = processed.ShipmentLabel?.LabelURL || undefined;\n\n return {\n carrier: \"aramex\",\n trackingNumber,\n customerTracking: input?.options?.customerTracking,\n reference: input?.reference,\n // Aramex returns no status code on create — the shipment is freshly created.\n status: \"created\",\n statusLabel: \"Created\",\n labelUrl,\n pdfLabelUrl: labelUrl,\n codAmount: input?.cod?.enabled ? input.cod.amount : undefined,\n declaredValue: input?.declaredValue?.amount,\n currency:\n input?.cod?.currency ?? input?.declaredValue?.currency ?? \"SAR\",\n createdAt: new Date(),\n raw: processed,\n };\n}\n\nexport function mapTrackingEvent(\n result: AramexTrackingResult,\n): TrackingEvent {\n return {\n timestamp: parseAramexDate(result.UpdateDateTime),\n statusCode: result.UpdateCode,\n status:\n mapAramexStatus(result.UpdateCode) ??\n statusFromDescription(result.UpdateDescription) ??\n \"unknown\",\n description: result.UpdateDescription,\n location: result.UpdateLocation || undefined,\n };\n}\n\nexport function mapTrackingResult(\n waybill: string,\n results: AramexTrackingResult[],\n): TrackingResult {\n const events = results\n .map(mapTrackingEvent)\n .sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime());\n\n const latest = events[0];\n const delivered = events.find((e) => e.status === \"delivered\");\n\n // Pull a weight from the most recent raw result that reports one.\n const weightStr = [...results]\n .reverse()\n .find((r) => r.GrossWeight)?.GrossWeight;\n const weight = weightStr ? Number.parseFloat(weightStr) : undefined;\n\n return {\n trackingNumber: waybill,\n carrier: \"aramex\",\n status: latest?.status ?? \"unknown\",\n statusLabel: latest?.description ?? \"Unknown\",\n events,\n deliveryDate: delivered?.timestamp,\n weight: weight != null && !Number.isNaN(weight) ? weight : undefined,\n raw: results,\n };\n}\n\n/**\n * Normalize the `TrackingResults` envelope into a plain map. The WCF JSON\n * serializer renders the dictionary as `[{ Key, Value }]`, but some gateways\n * return a plain object map instead — accept both.\n */\nexport function normalizeTrackingResults(\n raw: AramexTrackShipmentsResponse[\"TrackingResults\"],\n): Record<string, AramexTrackingResult[]> {\n if (!raw) return {};\n if (Array.isArray(raw)) {\n const map: Record<string, AramexTrackingResult[]> = {};\n for (const kv of raw) {\n if (kv && typeof kv === \"object\" && \"Key\" in kv) {\n map[kv.Key] = kv.Value ?? [];\n }\n }\n return map;\n }\n return raw;\n}\n\n/**\n * Build a placeholder `TrackingResult` for a waybill Aramex reports under\n * `NonExistingWaybills`. Aramex splits the TrackShipments response into found\n * (`TrackingResults`) and not-found (`NonExistingWaybills`) buckets; emitting an\n * \"unknown\" entry for the latter keeps the returned array aligned to the input\n * waybills so callers can map inputs→results positionally/by trackingNumber.\n */\nexport function mapNonExistingWaybill(waybill: string): TrackingResult {\n return {\n trackingNumber: waybill,\n carrier: \"aramex\",\n status: \"unknown\",\n statusLabel: \"Waybill not found\",\n events: [],\n raw: { nonExisting: true, waybill },\n };\n}\n\nexport function mapRate(\n response: AramexCalculateRateResponse,\n input: CreateShipmentInput,\n): Rate {\n const { productType } = resolveProductGroupAndType(input);\n return {\n carrier: \"aramex\",\n serviceType: productType,\n serviceName: productType,\n amount: response.TotalAmount?.Value ?? 0,\n currency:\n response.TotalAmount?.CurrencyCode ??\n input.cod?.currency ??\n input.declaredValue?.currency ??\n \"SAR\",\n raw: response,\n };\n}\n\nexport function mapPickupResponse(\n processed: AramexProcessedPickup,\n input: PickupRequest,\n): Pickup {\n // CancelPickup keys on the GUID (PickupGUID), NOT the numeric ID — a pickup\n // that also carries an ID must still surface the GUID as its `id` so the\n // round-trip createPickup → cancelPickup works. Prefer GUID; only fall back\n // to ID when no GUID is present (cancellation then isn't possible, but the\n // caller still gets a usable identifier).\n return {\n id: processed.GUID || processed.ID,\n carrier: \"aramex\",\n status: \"pending\",\n date: input.date,\n timeSlot: input.timeSlot,\n city: input.city,\n contactName: input.contactName,\n contactPhone: input.contactPhone,\n address: input.address,\n shipmentCount: input.shipmentCount,\n createdAt: new Date(),\n raw: processed,\n };\n}\n\nexport function mapCity(name: string): City {\n return { nameEn: name };\n}\n\nexport function mapOffice(office: AramexOffice): Location {\n const addr = office.Address;\n const lines = [addr?.Line1, addr?.Line2, addr?.Line3].filter(Boolean);\n return {\n id: office.EntityCode,\n name: office.EntityName ?? office.EntityCode,\n address: lines.length ? lines.join(\", \") : undefined,\n city: addr?.City,\n latitude: addr?.Latitude,\n longitude: addr?.Longitude,\n };\n}\n",
7
- "// file: src/carriers/aramex/adapter.ts\n/**\n * Aramex Carrier Adapter\n * Implementation of the CarrierAdapter interface for the Aramex JSON Shipping\n * Services API v2.\n *\n * Key differences from the other carriers:\n * - Auth is a `ClientInfo` object sent in EVERY request body (not headers).\n * - The four Aramex services (Shipping, Tracking, RateCalculator, Location)\n * live on different base URLs, so the adapter holds one HttpClient per service.\n * - Errors use the \"Fake 200 OK\" pattern (HTTP 200 + `HasErrors`/`Notifications`),\n * surfaced via the shared HttpClient's `errorExtractor` hook on every call.\n */\n\nimport {\n APIError,\n UnsupportedOperationError,\n ValidationError,\n} from \"../../core/errors\";\nimport { HttpClient } from \"../../core/http\";\nimport {\n validateCreateShipmentInput,\n validatePickupRequest,\n} from \"../../core/schemas\";\nimport type {\n CarrierConfig,\n City,\n CreateShipmentInput,\n Location,\n Pickup,\n PickupRequest,\n Rate,\n Shipment,\n TrackingResult,\n} from \"../../core/types\";\nimport { BaseCarrierAdapter } from \"../base\";\nimport {\n buildClientInfo,\n mapCalculateRateRequest,\n mapCity,\n mapCreateShipmentRequest,\n mapNonExistingWaybill,\n mapOffice,\n mapPickupRequest,\n mapPickupResponse,\n mapRate,\n mapShipmentResponse,\n mapTrackingResult,\n normalizeTrackingResults,\n} from \"./mappers\";\nimport type {\n AramexCalculateRateResponse,\n AramexClientInfo,\n AramexCreatePickupResponse,\n AramexCancelPickupResponse,\n AramexCreateShipmentsResponse,\n AramexFetchCitiesResponse,\n AramexFetchOfficesResponse,\n AramexLabelInfo,\n AramexNotification,\n AramexPrintLabelResponse,\n AramexTrackShipmentsResponse,\n} from \"./types\";\n\nconst SHIPPING_SANDBOX_URL =\n \"https://ws.dev.aramex.net/ShippingAPI.V2/Shipping/Service_1_0.svc\";\nconst SHIPPING_PRODUCTION_URL =\n \"https://ws.aramex.net/ShippingAPI.V2/Shipping/Service_1_0.svc\";\n\n/** Default Aramex label report (HTML/PDF label at 9.7x21cm), returned as a URL. */\nconst DEFAULT_LABEL_INFO: AramexLabelInfo = {\n ReportID: 9201,\n ReportType: \"URL\",\n};\n\n/**\n * Aramex's WCF `Transaction` data contract marks Reference1–Reference5 as\n * REQUIRED members, so an empty `{}` fails deserialization (\"required data\n * members 'Reference1..Reference5' were not found\") on every operation. All five\n * must be present; empty strings are accepted.\n */\nconst EMPTY_TRANSACTION = {\n Reference1: \"\",\n Reference2: \"\",\n Reference3: \"\",\n Reference4: \"\",\n Reference5: \"\",\n} as const;\n\nexport interface AramexConfig extends CarrierConfig {\n credentials: {\n userName: string;\n password: string;\n accountNumber: string;\n accountPin: string;\n accountEntity: string;\n accountCountryCode: string;\n };\n /** API source channel (default 24). */\n source?: number;\n /** ClientInfo version (default \"v1.0\"). */\n version?: string;\n /** Company name used when an address has no company set. */\n companyName?: string;\n /**\n * Optional override for the Location service base URL. Live Aramex WSDLs\n * disagree on the production Location host (ws.aramex.net vs anfe02.aramex.com);\n * set this if your account is provisioned on a different host.\n */\n locationBaseUrl?: string;\n}\n\nexport class AramexAdapter extends BaseCarrierAdapter {\n readonly name = \"aramex\";\n readonly supportedCountries = [\n \"SA\",\n \"AE\",\n \"BH\",\n \"KW\",\n \"OM\",\n \"QA\",\n \"JO\",\n \"EG\",\n \"LB\",\n \"IQ\",\n ];\n\n private shippingHttp: HttpClient;\n private trackingHttp: HttpClient;\n private rateHttp: HttpClient;\n private locationHttp: HttpClient;\n\n constructor(config: AramexConfig) {\n super(config);\n const shippingBase = this.getBaseUrl();\n const common = {\n carrier: \"aramex\",\n // Aramex auth lives in the request body (ClientInfo), so no auth headers.\n };\n this.shippingHttp = new HttpClient({ ...common, baseUrl: shippingBase });\n this.trackingHttp = new HttpClient({\n ...common,\n baseUrl: this.serviceBase(shippingBase, \"Tracking\"),\n });\n this.rateHttp = new HttpClient({\n ...common,\n baseUrl: this.serviceBase(shippingBase, \"RateCalculator\"),\n });\n this.locationHttp = new HttpClient({\n ...common,\n baseUrl:\n config.locationBaseUrl ?? this.serviceBase(shippingBase, \"Location\"),\n });\n }\n\n protected getBaseUrl(): string {\n return this.config.mode === \"production\"\n ? SHIPPING_PRODUCTION_URL\n : SHIPPING_SANDBOX_URL;\n }\n\n /** Derive a sibling service base URL by swapping the `/Shipping/` segment. */\n private serviceBase(shippingBase: string, service: string): string {\n return shippingBase.replace(\"/Shipping/\", `/${service}/`);\n }\n\n private get aramexConfig(): AramexConfig {\n return this.config as AramexConfig;\n }\n\n private buildClientInfo(): AramexClientInfo {\n const cfg = this.aramexConfig;\n return buildClientInfo(cfg.credentials, {\n source: cfg.source,\n version: cfg.version,\n });\n }\n\n /**\n * Extracts the Aramex \"Fake 200 OK\" error (envelope-level `HasErrors` +\n * `Notifications`). Passed to every request so the HttpClient raises APIError.\n */\n private static aramexErrorExtractor(json: unknown): {\n hasError: boolean;\n message?: string;\n errors?: Record<string, string[]>;\n } {\n const obj = json as {\n HasErrors?: boolean;\n Notifications?: AramexNotification[];\n } | null;\n const notifications = obj?.Notifications ?? [];\n const hasError = obj?.HasErrors === true;\n const message =\n notifications\n .map((n) => n?.Message)\n .filter(Boolean)\n .join(\"; \") || (hasError ? \"Aramex returned an error\" : undefined);\n return {\n hasError,\n message,\n errors: notifications.length\n ? AramexAdapter.notificationsToErrors(notifications)\n : undefined,\n };\n }\n\n private static notificationsToErrors(\n notifications: AramexNotification[],\n ): Record<string, string[]> {\n return {\n _aramex: notifications.map((n) =>\n `${n?.Code ?? \"\"}: ${n?.Message ?? \"\"}`.trim(),\n ),\n };\n }\n\n // =========================================================================\n // SHIPPING\n // =========================================================================\n\n protected async executeCreateShipment(\n input: CreateShipmentInput,\n ): Promise<Shipment> {\n const cfg = this.aramexConfig;\n const shipment = mapCreateShipmentRequest(input, {\n accountNumber: cfg.credentials.accountNumber,\n companyName: cfg.companyName,\n });\n\n const response = await this.shippingHttp.post<AramexCreateShipmentsResponse>(\n \"/json/CreateShipments\",\n {\n ClientInfo: this.buildClientInfo(),\n Transaction: EMPTY_TRANSACTION,\n LabelInfo: DEFAULT_LABEL_INFO,\n Shipments: [shipment],\n },\n { errorExtractor: AramexAdapter.aramexErrorExtractor },\n );\n\n const processed = response.Shipments?.[0];\n if (!processed) {\n throw new APIError(\"Aramex returned no shipment\", {\n carrier: \"aramex\",\n raw: response,\n });\n }\n\n // CreateShipments can also fail per-shipment while the envelope is clean.\n if (processed.HasErrors) {\n const notifications = processed.Notifications ?? [];\n throw new APIError(\n notifications\n .map((n) => n.Message)\n .filter(Boolean)\n .join(\"; \") || \"Failed to create shipment\",\n {\n carrier: \"aramex\",\n errors: AramexAdapter.notificationsToErrors(notifications),\n raw: processed,\n },\n );\n }\n\n return mapShipmentResponse(processed, input);\n }\n\n /**\n * Create multiple shipments in a single request. Aramex's `CreateShipments`\n * operation is natively batch — it takes a `Shipments` array and returns one\n * processed result per shipment, in request order.\n *\n * Fails loud: if ANY shipment in the batch errors, an `APIError` is thrown\n * whose `raw` holds the full response, so already-created AWBs remain\n * recoverable (the unified `Shipment` type has no per-item error channel).\n */\n async createBulkShipments(\n inputs: CreateShipmentInput[],\n ): Promise<Shipment[]> {\n if (inputs.length === 0) {\n throw new ValidationError(\n \"At least one shipment is required for bulk create\",\n { raw: { count: 0 } },\n );\n }\n for (const input of inputs) validateCreateShipmentInput(input);\n\n const cfg = this.aramexConfig;\n const shipments = inputs.map((input) =>\n mapCreateShipmentRequest(input, {\n accountNumber: cfg.credentials.accountNumber,\n companyName: cfg.companyName,\n }),\n );\n\n const response = await this.shippingHttp.post<AramexCreateShipmentsResponse>(\n \"/json/CreateShipments\",\n {\n ClientInfo: this.buildClientInfo(),\n Transaction: EMPTY_TRANSACTION,\n LabelInfo: DEFAULT_LABEL_INFO,\n Shipments: shipments,\n },\n { errorExtractor: AramexAdapter.aramexErrorExtractor },\n );\n\n const processed = response.Shipments ?? [];\n if (processed.length === 0) {\n throw new APIError(\"Aramex returned no shipments\", {\n carrier: \"aramex\",\n raw: response,\n });\n }\n\n const failed = processed.filter((p) => p.HasErrors);\n if (failed.length > 0) {\n const notifications = failed.flatMap((p) => p.Notifications ?? []);\n throw new APIError(\n notifications\n .map((n) => n.Message)\n .filter(Boolean)\n .join(\"; \") ||\n `Failed to create ${failed.length} of ${processed.length} shipments`,\n {\n carrier: \"aramex\",\n errors: AramexAdapter.notificationsToErrors(notifications),\n raw: response,\n },\n );\n }\n\n return processed.map((p, i) => mapShipmentResponse(p, inputs[i]));\n }\n\n /**\n * Aramex's classic Shipping Services API has no shipment-cancellation\n * endpoint, so this is unsupported. (Pickups can be cancelled via cancelPickup.)\n */\n cancelShipment(_trackingNumber: string): Promise<boolean> {\n throw new UnsupportedOperationError(\"aramex\", \"cancelShipment\");\n }\n\n // =========================================================================\n // LABELS\n // =========================================================================\n\n async getLabel(\n trackingNumber: string,\n _format?: \"PDF\" | \"ZPL\" | \"PNG\",\n ): Promise<string> {\n // Aramex PrintLabel returns a URL to the label document. The requested\n // `format` cannot be honored (ZPL/PNG are not selectable) — always a URL.\n const response = await this.shippingHttp.post<AramexPrintLabelResponse>(\n \"/json/PrintLabel\",\n {\n ClientInfo: this.buildClientInfo(),\n Transaction: EMPTY_TRANSACTION,\n ShipmentNumber: trackingNumber,\n LabelInfo: DEFAULT_LABEL_INFO,\n },\n // PrintLabel is a side-effect-free read (it returns a URL for an existing\n // shipment), so it's safe to retry like the other read operations.\n { retry: true, errorExtractor: AramexAdapter.aramexErrorExtractor },\n );\n\n const url = response.ShipmentLabel?.LabelURL;\n if (!url) {\n throw new APIError(\"Failed to get label\", {\n carrier: \"aramex\",\n raw: response,\n });\n }\n return url;\n }\n\n // =========================================================================\n // TRACKING\n // =========================================================================\n\n async track(trackingNumber: string): Promise<TrackingResult> {\n const results = await this.trackMultiple([trackingNumber]);\n const result = results[0];\n // trackMultiple now emits an \"unknown\"/not-found entry for waybills Aramex\n // returns under NonExistingWaybills, so a missing-or-not-found waybill must\n // raise a precise not-found rather than returning a misleading \"unknown\".\n if (!result || (result.status === \"unknown\" && result.events.length === 0)) {\n throw new APIError(\"Shipment not found\", {\n carrier: \"aramex\",\n raw: result?.raw ?? { trackingNumber },\n });\n }\n return result;\n }\n\n async trackMultiple(trackingNumbers: string[]): Promise<TrackingResult[]> {\n const response = await this.trackingHttp.post<AramexTrackShipmentsResponse>(\n \"/json/TrackShipments\",\n {\n ClientInfo: this.buildClientInfo(),\n Transaction: EMPTY_TRANSACTION,\n Shipments: trackingNumbers,\n GetLastTrackingUpdateOnly: false,\n },\n { retry: true, errorExtractor: AramexAdapter.aramexErrorExtractor },\n );\n\n const map = normalizeTrackingResults(response.TrackingResults);\n const found = Object.entries(map).map(([waybill, results]) =>\n mapTrackingResult(waybill, results),\n );\n\n // Aramex returns not-found waybills in a separate NonExistingWaybills bucket\n // rather than as empty TrackingResults. Surface them as \"unknown\" entries so\n // the returned array stays aligned to the input waybills (callers can map\n // inputs→results); silently dropping them desynchronizes that mapping.\n const nonExisting = (response.NonExistingWaybills ?? []).map(\n mapNonExistingWaybill,\n );\n\n return [...found, ...nonExisting];\n }\n\n async trackByReference(reference: string): Promise<TrackingResult> {\n // Aramex tracks references through the same TrackShipments operation.\n const result = await this.track(reference);\n return { ...result, reference };\n }\n\n // =========================================================================\n // RATES\n // =========================================================================\n\n async getRates(input: CreateShipmentInput): Promise<Rate[]> {\n const rateRequest = mapCalculateRateRequest(input);\n const response = await this.rateHttp.post<AramexCalculateRateResponse>(\n \"/json/CalculateRate\",\n {\n ClientInfo: this.buildClientInfo(),\n Transaction: EMPTY_TRANSACTION,\n ...rateRequest,\n },\n { retry: true, errorExtractor: AramexAdapter.aramexErrorExtractor },\n );\n\n // A clean envelope with no TotalAmount means Aramex couldn't price the\n // route. Surface it as an error rather than returning a misleading 0 rate.\n if (response.TotalAmount?.Value == null) {\n throw new APIError(\"Aramex returned no rate for this shipment\", {\n carrier: \"aramex\",\n raw: response,\n });\n }\n\n return [mapRate(response, input)];\n }\n\n // =========================================================================\n // PICKUPS\n // =========================================================================\n\n async createPickup(input: PickupRequest): Promise<Pickup> {\n validatePickupRequest(input);\n const cfg = this.aramexConfig;\n const pickup = mapPickupRequest(input, {\n accountNumber: cfg.credentials.accountNumber,\n countryCode: cfg.credentials.accountCountryCode,\n companyName: cfg.companyName,\n });\n\n const response = await this.shippingHttp.post<AramexCreatePickupResponse>(\n \"/json/CreatePickup\",\n {\n ClientInfo: this.buildClientInfo(),\n Transaction: EMPTY_TRANSACTION,\n Pickup: pickup,\n },\n { errorExtractor: AramexAdapter.aramexErrorExtractor },\n );\n\n // Judge success on the body payload, not the HTTP status: a \"Fake 200 OK\"\n // can carry an empty ProcessedPickup. A usable pickup needs a GUID — that's\n // the key CancelPickup requires (PickupGUID), so a pickup with only a\n // numeric ID can't be cancelled and isn't a usable round-trip result.\n const processed = response.ProcessedPickup;\n if (!processed || (!processed.GUID && !processed.ID)) {\n throw new APIError(\"Failed to create pickup\", {\n carrier: \"aramex\",\n raw: response,\n });\n }\n\n // A pickup can succeed at the header level (it has a GUID) while individual\n // shipments inside it fail (ProcessedShipments[].HasErrors). Those per-\n // shipment errors are otherwise swallowed — scan and surface them so a\n // partially-failed pickup isn't reported as a clean success.\n const failedShipments = (processed.ProcessedShipments ?? []).filter(\n (s) => s.HasErrors,\n );\n if (failedShipments.length > 0) {\n const notifications = failedShipments.flatMap((s) => s.Notifications ?? []);\n throw new APIError(\n notifications\n .map((n) => n.Message)\n .filter(Boolean)\n .join(\"; \") ||\n `Pickup created but ${failedShipments.length} shipment(s) failed`,\n {\n carrier: \"aramex\",\n errors: AramexAdapter.notificationsToErrors(notifications),\n raw: response,\n },\n );\n }\n\n return mapPickupResponse(processed, input);\n }\n\n async cancelPickup(pickupId: string | number): Promise<boolean> {\n const response = await this.shippingHttp.post<AramexCancelPickupResponse>(\n \"/json/CancelPickup\",\n {\n ClientInfo: this.buildClientInfo(),\n Transaction: EMPTY_TRANSACTION,\n PickupGUID: String(pickupId),\n },\n { errorExtractor: AramexAdapter.aramexErrorExtractor },\n );\n // The errorExtractor already throws on `HasErrors: true`, so reaching here\n // means the body reported no error — judge success from that, treating a\n // missing flag as success (consistent with the extractor's `=== true`).\n return response.HasErrors !== true;\n }\n\n // =========================================================================\n // CITIES & LOCATIONS\n // =========================================================================\n\n async getCities(countryCode?: string): Promise<City[]> {\n const response = await this.locationHttp.post<AramexFetchCitiesResponse>(\n \"/json/FetchCities\",\n {\n ClientInfo: this.buildClientInfo(),\n Transaction: EMPTY_TRANSACTION,\n CountryCode:\n countryCode ?? this.aramexConfig.credentials.accountCountryCode,\n },\n { retry: true, errorExtractor: AramexAdapter.aramexErrorExtractor },\n );\n\n return (response.Cities ?? []).map(mapCity);\n }\n\n async getDropoffLocations(countryCode?: string): Promise<Location[]> {\n const response = await this.locationHttp.post<AramexFetchOfficesResponse>(\n \"/json/FetchOffices\",\n {\n ClientInfo: this.buildClientInfo(),\n Transaction: EMPTY_TRANSACTION,\n CountryCode:\n countryCode ?? this.aramexConfig.credentials.accountCountryCode,\n },\n { retry: true, errorExtractor: AramexAdapter.aramexErrorExtractor },\n );\n\n return (response.Offices ?? []).map(mapOffice);\n }\n}\n"
7
+ "// file: src/carriers/aramex/adapter.ts\n/**\n * Aramex Carrier Adapter\n * Implementation of the CarrierAdapter interface for the Aramex JSON Shipping\n * Services API v2.\n *\n * Key differences from the other carriers:\n * - Auth is a `ClientInfo` object sent in EVERY request body (not headers).\n * - The four Aramex services (Shipping, Tracking, RateCalculator, Location)\n * live on different base URLs, so the adapter holds one HttpClient per service.\n * - Errors use the \"Fake 200 OK\" pattern (HTTP 200 + `HasErrors`/`Notifications`),\n * surfaced via the shared HttpClient's `errorExtractor` hook on every call.\n */\n\nimport {\n APIError,\n UnsupportedOperationError,\n ValidationError,\n} from \"../../core/errors\";\nimport { HttpClient } from \"../../core/http\";\nimport {\n validateCreateShipmentInput,\n validatePickupRequest,\n} from \"../../core/schemas\";\nimport type {\n CarrierConfig,\n City,\n CreateShipmentInput,\n Location,\n Pickup,\n PickupRequest,\n Rate,\n Shipment,\n TrackingResult,\n} from \"../../core/types\";\nimport { BaseCarrierAdapter } from \"../base\";\nimport {\n buildClientInfo,\n mapCalculateRateRequest,\n mapCity,\n mapCreateShipmentRequest,\n mapNonExistingWaybill,\n mapOffice,\n mapPickupRequest,\n mapPickupResponse,\n mapRate,\n mapShipmentResponse,\n mapTrackingResult,\n normalizeTrackingResults,\n} from \"./mappers\";\nimport type {\n AramexCalculateRateResponse,\n AramexClientInfo,\n AramexCreatePickupResponse,\n AramexCancelPickupResponse,\n AramexCreateShipmentsResponse,\n AramexFetchCitiesResponse,\n AramexFetchOfficesResponse,\n AramexLabelInfo,\n AramexNotification,\n AramexPrintLabelResponse,\n AramexTrackShipmentsResponse,\n} from \"./types\";\n\nconst SHIPPING_SANDBOX_URL =\n \"https://ws.dev.aramex.net/ShippingAPI.V2/Shipping/Service_1_0.svc\";\nconst SHIPPING_PRODUCTION_URL =\n \"https://ws.aramex.net/ShippingAPI.V2/Shipping/Service_1_0.svc\";\n\n/** Default Aramex label report (HTML/PDF label at 9.7x21cm), returned as a URL. */\nconst DEFAULT_LABEL_INFO: AramexLabelInfo = {\n ReportID: 9201,\n ReportType: \"URL\",\n};\n\n/**\n * Aramex's WCF `Transaction` data contract marks Reference1–Reference5 as\n * REQUIRED members, so an empty `{}` fails deserialization (\"required data\n * members 'Reference1..Reference5' were not found\") on every operation. All five\n * must be present; empty strings are accepted.\n */\nconst EMPTY_TRANSACTION = {\n Reference1: \"\",\n Reference2: \"\",\n Reference3: \"\",\n Reference4: \"\",\n Reference5: \"\",\n} as const;\n\nexport interface AramexConfig extends CarrierConfig {\n credentials: {\n userName: string;\n password: string;\n accountNumber: string;\n accountPin: string;\n accountEntity: string;\n accountCountryCode: string;\n };\n /** API source channel (default 24). */\n source?: number;\n /** ClientInfo version (default \"v1.0\"). */\n version?: string;\n /** Company name used when an address has no company set. */\n companyName?: string;\n /**\n * Optional override for the Location service base URL. Live Aramex WSDLs\n * disagree on the production Location host (ws.aramex.net vs anfe02.aramex.com);\n * set this if your account is provisioned on a different host.\n */\n locationBaseUrl?: string;\n}\n\nexport class AramexAdapter extends BaseCarrierAdapter {\n readonly name = \"aramex\";\n readonly supportedCountries = [\n \"SA\",\n \"AE\",\n \"BH\",\n \"KW\",\n \"OM\",\n \"QA\",\n \"JO\",\n \"EG\",\n \"LB\",\n \"IQ\",\n ];\n\n private shippingHttp: HttpClient;\n private trackingHttp: HttpClient;\n private rateHttp: HttpClient;\n private locationHttp: HttpClient;\n\n constructor(config: AramexConfig) {\n super(config);\n const shippingBase = this.getBaseUrl();\n const common = {\n carrier: \"aramex\",\n // Aramex auth lives in the request body (ClientInfo), so no auth headers.\n };\n this.shippingHttp = new HttpClient({ ...common, baseUrl: shippingBase });\n this.trackingHttp = new HttpClient({\n ...common,\n baseUrl: this.serviceBase(shippingBase, \"Tracking\"),\n });\n this.rateHttp = new HttpClient({\n ...common,\n baseUrl: this.serviceBase(shippingBase, \"RateCalculator\"),\n });\n this.locationHttp = new HttpClient({\n ...common,\n baseUrl:\n config.locationBaseUrl ?? this.serviceBase(shippingBase, \"Location\"),\n });\n }\n\n protected getBaseUrl(): string {\n return this.config.mode === \"production\"\n ? SHIPPING_PRODUCTION_URL\n : SHIPPING_SANDBOX_URL;\n }\n\n /** Derive a sibling service base URL by swapping the `/Shipping/` segment. */\n private serviceBase(shippingBase: string, service: string): string {\n return shippingBase.replace(\"/Shipping/\", `/${service}/`);\n }\n\n private get aramexConfig(): AramexConfig {\n return this.config as AramexConfig;\n }\n\n private buildClientInfo(): AramexClientInfo {\n const cfg = this.aramexConfig;\n return buildClientInfo(cfg.credentials, {\n source: cfg.source,\n version: cfg.version,\n });\n }\n\n /**\n * Extracts the Aramex \"Fake 200 OK\" error (envelope-level `HasErrors` +\n * `Notifications`). Passed to every request so the HttpClient raises APIError.\n */\n /**\n * Aramex reports throttling inside its \"fake 200\" envelope (and sometimes on a\n * non-429 status) rather than via HTTP 429, so status-code detection misses it.\n * Match the rate-limit wording in the notifications and flag it so the\n * HttpClient raises a retryable `RateLimitError` instead of a plain APIError.\n */\n private static readonly RATE_LIMIT_PATTERN =\n /rate.?limit|too many request|throttl|quota exceeded/i;\n\n private static aramexErrorExtractor(json: unknown): {\n hasError: boolean;\n message?: string;\n errors?: Record<string, string[]>;\n rateLimited?: boolean;\n } {\n const obj = json as {\n HasErrors?: boolean;\n Notifications?: AramexNotification[];\n } | null;\n const notifications = obj?.Notifications ?? [];\n const hasError = obj?.HasErrors === true;\n const message =\n notifications\n .map((n) => n?.Message)\n .filter(Boolean)\n .join(\"; \") || (hasError ? \"Aramex returned an error\" : undefined);\n return {\n hasError,\n message,\n errors: notifications.length\n ? AramexAdapter.notificationsToErrors(notifications)\n : undefined,\n rateLimited:\n hasError && AramexAdapter.RATE_LIMIT_PATTERN.test(message ?? \"\"),\n };\n }\n\n private static notificationsToErrors(\n notifications: AramexNotification[],\n ): Record<string, string[]> {\n return {\n _aramex: notifications.map((n) =>\n `${n?.Code ?? \"\"}: ${n?.Message ?? \"\"}`.trim(),\n ),\n };\n }\n\n // =========================================================================\n // SHIPPING\n // =========================================================================\n\n protected async executeCreateShipment(\n input: CreateShipmentInput,\n ): Promise<Shipment> {\n const cfg = this.aramexConfig;\n const shipment = mapCreateShipmentRequest(input, {\n accountNumber: cfg.credentials.accountNumber,\n companyName: cfg.companyName,\n });\n\n const response = await this.shippingHttp.post<AramexCreateShipmentsResponse>(\n \"/json/CreateShipments\",\n {\n ClientInfo: this.buildClientInfo(),\n Transaction: EMPTY_TRANSACTION,\n LabelInfo: DEFAULT_LABEL_INFO,\n Shipments: [shipment],\n },\n { errorExtractor: AramexAdapter.aramexErrorExtractor },\n );\n\n const processed = response.Shipments?.[0];\n if (!processed) {\n throw new APIError(\"Aramex returned no shipment\", {\n carrier: \"aramex\",\n raw: response,\n });\n }\n\n // CreateShipments can also fail per-shipment while the envelope is clean.\n if (processed.HasErrors) {\n const notifications = processed.Notifications ?? [];\n throw new APIError(\n notifications\n .map((n) => n.Message)\n .filter(Boolean)\n .join(\"; \") || \"Failed to create shipment\",\n {\n carrier: \"aramex\",\n errors: AramexAdapter.notificationsToErrors(notifications),\n raw: processed,\n },\n );\n }\n\n return mapShipmentResponse(processed, input);\n }\n\n /**\n * Create multiple shipments in a single request. Aramex's `CreateShipments`\n * operation is natively batch — it takes a `Shipments` array and returns one\n * processed result per shipment, in request order.\n *\n * Fails loud: if ANY shipment in the batch errors, an `APIError` is thrown\n * whose `raw` holds the full response, so already-created AWBs remain\n * recoverable (the unified `Shipment` type has no per-item error channel).\n */\n async createBulkShipments(\n inputs: CreateShipmentInput[],\n ): Promise<Shipment[]> {\n if (inputs.length === 0) {\n throw new ValidationError(\n \"At least one shipment is required for bulk create\",\n { raw: { count: 0 } },\n );\n }\n for (const input of inputs) validateCreateShipmentInput(input);\n\n const cfg = this.aramexConfig;\n const shipments = inputs.map((input) =>\n mapCreateShipmentRequest(input, {\n accountNumber: cfg.credentials.accountNumber,\n companyName: cfg.companyName,\n }),\n );\n\n const response = await this.shippingHttp.post<AramexCreateShipmentsResponse>(\n \"/json/CreateShipments\",\n {\n ClientInfo: this.buildClientInfo(),\n Transaction: EMPTY_TRANSACTION,\n LabelInfo: DEFAULT_LABEL_INFO,\n Shipments: shipments,\n },\n { errorExtractor: AramexAdapter.aramexErrorExtractor },\n );\n\n const processed = response.Shipments ?? [];\n if (processed.length === 0) {\n throw new APIError(\"Aramex returned no shipments\", {\n carrier: \"aramex\",\n raw: response,\n });\n }\n\n const failed = processed.filter((p) => p.HasErrors);\n if (failed.length > 0) {\n const notifications = failed.flatMap((p) => p.Notifications ?? []);\n throw new APIError(\n notifications\n .map((n) => n.Message)\n .filter(Boolean)\n .join(\"; \") ||\n `Failed to create ${failed.length} of ${processed.length} shipments`,\n {\n carrier: \"aramex\",\n errors: AramexAdapter.notificationsToErrors(notifications),\n raw: response,\n },\n );\n }\n\n return processed.map((p, i) => mapShipmentResponse(p, inputs[i]));\n }\n\n /**\n * Aramex's classic Shipping Services API has no shipment-cancellation\n * endpoint, so this is unsupported. (Pickups can be cancelled via cancelPickup.)\n */\n cancelShipment(_trackingNumber: string): Promise<boolean> {\n throw new UnsupportedOperationError(\"aramex\", \"cancelShipment\");\n }\n\n // =========================================================================\n // LABELS\n // =========================================================================\n\n async getLabel(\n trackingNumber: string,\n _format?: \"PDF\" | \"ZPL\" | \"PNG\",\n ): Promise<string> {\n // Aramex PrintLabel returns a URL to the label document. The requested\n // `format` cannot be honored (ZPL/PNG are not selectable) — always a URL.\n const response = await this.shippingHttp.post<AramexPrintLabelResponse>(\n \"/json/PrintLabel\",\n {\n ClientInfo: this.buildClientInfo(),\n Transaction: EMPTY_TRANSACTION,\n ShipmentNumber: trackingNumber,\n LabelInfo: DEFAULT_LABEL_INFO,\n },\n // PrintLabel is a side-effect-free read (it returns a URL for an existing\n // shipment), so it's safe to retry like the other read operations.\n { retry: true, errorExtractor: AramexAdapter.aramexErrorExtractor },\n );\n\n const url = response.ShipmentLabel?.LabelURL;\n if (!url) {\n throw new APIError(\"Failed to get label\", {\n carrier: \"aramex\",\n raw: response,\n });\n }\n return url;\n }\n\n // =========================================================================\n // TRACKING\n // =========================================================================\n\n async track(trackingNumber: string): Promise<TrackingResult> {\n const results = await this.trackMultiple([trackingNumber]);\n const result = results[0];\n // trackMultiple now emits an \"unknown\"/not-found entry for waybills Aramex\n // returns under NonExistingWaybills, so a missing-or-not-found waybill must\n // raise a precise not-found rather than returning a misleading \"unknown\".\n if (!result || (result.status === \"unknown\" && result.events.length === 0)) {\n throw new APIError(\"Shipment not found\", {\n carrier: \"aramex\",\n raw: result?.raw ?? { trackingNumber },\n });\n }\n return result;\n }\n\n async trackMultiple(trackingNumbers: string[]): Promise<TrackingResult[]> {\n const response = await this.trackingHttp.post<AramexTrackShipmentsResponse>(\n \"/json/TrackShipments\",\n {\n ClientInfo: this.buildClientInfo(),\n Transaction: EMPTY_TRANSACTION,\n Shipments: trackingNumbers,\n GetLastTrackingUpdateOnly: false,\n },\n { retry: true, errorExtractor: AramexAdapter.aramexErrorExtractor },\n );\n\n const map = normalizeTrackingResults(response.TrackingResults);\n const found = Object.entries(map).map(([waybill, results]) =>\n mapTrackingResult(waybill, results),\n );\n\n // Aramex returns not-found waybills in a separate NonExistingWaybills bucket\n // rather than as empty TrackingResults. Surface them as \"unknown\" entries so\n // the returned array stays aligned to the input waybills (callers can map\n // inputs→results); silently dropping them desynchronizes that mapping.\n const nonExisting = (response.NonExistingWaybills ?? []).map(\n mapNonExistingWaybill,\n );\n\n return [...found, ...nonExisting];\n }\n\n async trackByReference(reference: string): Promise<TrackingResult> {\n // Aramex tracks references through the same TrackShipments operation.\n const result = await this.track(reference);\n return { ...result, reference };\n }\n\n // =========================================================================\n // RATES\n // =========================================================================\n\n async getRates(input: CreateShipmentInput): Promise<Rate[]> {\n const rateRequest = mapCalculateRateRequest(input);\n const response = await this.rateHttp.post<AramexCalculateRateResponse>(\n \"/json/CalculateRate\",\n {\n ClientInfo: this.buildClientInfo(),\n Transaction: EMPTY_TRANSACTION,\n ...rateRequest,\n },\n { retry: true, errorExtractor: AramexAdapter.aramexErrorExtractor },\n );\n\n // A clean envelope with no TotalAmount means Aramex couldn't price the\n // route. Surface it as an error rather than returning a misleading 0 rate.\n if (response.TotalAmount?.Value == null) {\n throw new APIError(\"Aramex returned no rate for this shipment\", {\n carrier: \"aramex\",\n raw: response,\n });\n }\n\n return [mapRate(response, input)];\n }\n\n // =========================================================================\n // PICKUPS\n // =========================================================================\n\n async createPickup(input: PickupRequest): Promise<Pickup> {\n validatePickupRequest(input);\n const cfg = this.aramexConfig;\n const pickup = mapPickupRequest(input, {\n accountNumber: cfg.credentials.accountNumber,\n countryCode: cfg.credentials.accountCountryCode,\n companyName: cfg.companyName,\n });\n\n const response = await this.shippingHttp.post<AramexCreatePickupResponse>(\n \"/json/CreatePickup\",\n {\n ClientInfo: this.buildClientInfo(),\n Transaction: EMPTY_TRANSACTION,\n Pickup: pickup,\n },\n { errorExtractor: AramexAdapter.aramexErrorExtractor },\n );\n\n // Judge success on the body payload, not the HTTP status: a \"Fake 200 OK\"\n // can carry an empty ProcessedPickup. A usable pickup needs a GUID — that's\n // the key CancelPickup requires (PickupGUID), so a pickup with only a\n // numeric ID can't be cancelled and isn't a usable round-trip result.\n const processed = response.ProcessedPickup;\n if (!processed || (!processed.GUID && !processed.ID)) {\n throw new APIError(\"Failed to create pickup\", {\n carrier: \"aramex\",\n raw: response,\n });\n }\n\n // A pickup can succeed at the header level (it has a GUID) while individual\n // shipments inside it fail (ProcessedShipments[].HasErrors). Those per-\n // shipment errors are otherwise swallowed — scan and surface them so a\n // partially-failed pickup isn't reported as a clean success.\n const failedShipments = (processed.ProcessedShipments ?? []).filter(\n (s) => s.HasErrors,\n );\n if (failedShipments.length > 0) {\n const notifications = failedShipments.flatMap((s) => s.Notifications ?? []);\n throw new APIError(\n notifications\n .map((n) => n.Message)\n .filter(Boolean)\n .join(\"; \") ||\n `Pickup created but ${failedShipments.length} shipment(s) failed`,\n {\n carrier: \"aramex\",\n errors: AramexAdapter.notificationsToErrors(notifications),\n raw: response,\n },\n );\n }\n\n return mapPickupResponse(processed, input);\n }\n\n async cancelPickup(pickupId: string | number): Promise<boolean> {\n const response = await this.shippingHttp.post<AramexCancelPickupResponse>(\n \"/json/CancelPickup\",\n {\n ClientInfo: this.buildClientInfo(),\n Transaction: EMPTY_TRANSACTION,\n PickupGUID: String(pickupId),\n },\n { errorExtractor: AramexAdapter.aramexErrorExtractor },\n );\n // The errorExtractor already throws on `HasErrors: true`, so reaching here\n // means the body reported no error — judge success from that, treating a\n // missing flag as success (consistent with the extractor's `=== true`).\n return response.HasErrors !== true;\n }\n\n // =========================================================================\n // CITIES & LOCATIONS\n // =========================================================================\n\n async getCities(countryCode?: string): Promise<City[]> {\n const response = await this.locationHttp.post<AramexFetchCitiesResponse>(\n \"/json/FetchCities\",\n {\n ClientInfo: this.buildClientInfo(),\n Transaction: EMPTY_TRANSACTION,\n CountryCode:\n countryCode ?? this.aramexConfig.credentials.accountCountryCode,\n },\n { retry: true, errorExtractor: AramexAdapter.aramexErrorExtractor },\n );\n\n return (response.Cities ?? []).map(mapCity);\n }\n\n async getDropoffLocations(countryCode?: string): Promise<Location[]> {\n const response = await this.locationHttp.post<AramexFetchOfficesResponse>(\n \"/json/FetchOffices\",\n {\n ClientInfo: this.buildClientInfo(),\n Transaction: EMPTY_TRANSACTION,\n CountryCode:\n countryCode ?? this.aramexConfig.credentials.accountCountryCode,\n },\n { retry: true, errorExtractor: AramexAdapter.aramexErrorExtractor },\n );\n\n return (response.Offices ?? []).map(mapOffice);\n }\n}\n"
8
8
  ],
9
- "mappings": "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",
10
- "debugId": "BC16779A6E5B3D1F64756E2164756E21",
9
+ "mappings": "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",
10
+ "debugId": "A6EBA2B597BA645F64756E2164756E21",
11
11
  "names": []
12
12
  }
@@ -7,7 +7,7 @@ import {
7
7
  WebhookVerificationError,
8
8
  validateCreateShipmentInput,
9
9
  validatePickupRequest
10
- } from "../../index-qjtxhwzv.js";
10
+ } from "../../index-qnxj8bct.js";
11
11
 
12
12
  // src/carriers/aymakan/services.ts
13
13
  var AymakanService = {
@@ -21,9 +21,13 @@ export declare class SMSAExpressAdapter extends BaseCarrierAdapter {
21
21
  /**
22
22
  * Cancel a reverse-pickup (C2B) shipment.
23
23
  *
24
- * **Important:** SMSA only supports cancellation for C2B/reverse-pickup shipments.
25
- * Calling this on a B2C shipment will result in an API error or return `false`.
26
- * B2C shipments cannot be cancelled via the SMSA API.
24
+ * **Important:** SMSA only supports cancellation for C2B/reverse-pickup
25
+ * shipments, via the C2B endpoint. B2C shipments cannot be cancelled through
26
+ * the SMSA API: the endpoint responds without a cancellation confirmation,
27
+ * which is surfaced as an {@link APIError} rather than a misleading `false`.
28
+ * That lets callers tell "the carrier could not cancel" apart from a genuine
29
+ * refusal of a cancellable shipment and fall back accordingly. Consistent with
30
+ * the other adapters, this method either returns `true` or throws.
27
31
  */
28
32
  cancelShipment(trackingNumber: string): Promise<boolean>;
29
33
  track(trackingNumber: string): Promise<TrackingResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/carriers/smsaexpress/adapter.ts"],"names":[],"mappings":"AACA;;;GAGG;AAIH,OAAO,KAAK,EACV,aAAa,EACb,IAAI,EACJ,mBAAmB,EACnB,QAAQ,EACR,QAAQ,EACR,cAAc,EACd,aAAa,EACb,YAAY,EACb,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAY7C,OAAO,KAAK,EAGV,wBAAwB,EACxB,yBAAyB,EACzB,sBAAsB,EAEtB,wBAAwB,EAEzB,MAAM,SAAS,CAAC;AAQjB,MAAM,WAAW,iBAAkB,SAAQ,aAAa;IACtD,WAAW,EAAE;QACX,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,qBAAa,kBAAmB,SAAQ,kBAAkB;IACxD,QAAQ,CAAC,IAAI,iBAAiB;IAC9B,QAAQ,CAAC,kBAAkB,WASzB;IAEF,OAAO,CAAC,IAAI,CAAa;gBAEb,MAAM,EAAE,iBAAiB;IAWrC,SAAS,CAAC,UAAU,IAAI,MAAM;cAUd,qBAAqB,CACnC,KAAK,EAAE,mBAAmB,GACzB,OAAO,CAAC,QAAQ,CAAC;YAkBN,iBAAiB;IAY/B;;;;;;OAMG;IACG,cAAc,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAgBxD,KAAK,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAQtD,aAAa,CAAC,eAAe,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAUnE,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAY5D,QAAQ,CACZ,cAAc,EAAE,MAAM,EACtB,OAAO,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,GAC9B,OAAO,CAAC,MAAM,CAAC;IAsCZ,SAAS,CAAC,WAAW,SAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAQ9C,mBAAmB,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IAY1C,kBAAkB,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAcjE,WAAW,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC;IAI7D,oBAAoB,CACxB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,wBAAwB,CAAC;IAM9B,aAAa,CACjB,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,yBAAyB,CAAC;IAWrC,YAAY,CACV,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE;QACR,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACjC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACrC,MAAM,CAAC,EAAE,aAAa,CAAC;KACxB,GACA,YAAY;IAIf;;;;;;OAMG;IACH,iBAAiB,CACf,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE;QACR,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACjC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACrC,MAAM,CAAC,EAAE,aAAa,CAAC;KACxB,GACA,YAAY,EAAE;CAGlB"}
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/carriers/smsaexpress/adapter.ts"],"names":[],"mappings":"AACA;;;GAGG;AAIH,OAAO,KAAK,EACV,aAAa,EACb,IAAI,EACJ,mBAAmB,EACnB,QAAQ,EACR,QAAQ,EACR,cAAc,EACd,aAAa,EACb,YAAY,EACb,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAY7C,OAAO,KAAK,EAGV,wBAAwB,EACxB,yBAAyB,EACzB,sBAAsB,EAEtB,wBAAwB,EAEzB,MAAM,SAAS,CAAC;AAQjB,MAAM,WAAW,iBAAkB,SAAQ,aAAa;IACtD,WAAW,EAAE;QACX,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,qBAAa,kBAAmB,SAAQ,kBAAkB;IACxD,QAAQ,CAAC,IAAI,iBAAiB;IAC9B,QAAQ,CAAC,kBAAkB,WASzB;IAEF,OAAO,CAAC,IAAI,CAAa;gBAEb,MAAM,EAAE,iBAAiB;IAWrC,SAAS,CAAC,UAAU,IAAI,MAAM;cAUd,qBAAqB,CACnC,KAAK,EAAE,mBAAmB,GACzB,OAAO,CAAC,QAAQ,CAAC;YAkBN,iBAAiB;IAY/B;;;;;;;;;;OAUG;IACG,cAAc,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAyBxD,KAAK,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAQtD,aAAa,CAAC,eAAe,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAUnE,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAY5D,QAAQ,CACZ,cAAc,EAAE,MAAM,EACtB,OAAO,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,GAC9B,OAAO,CAAC,MAAM,CAAC;IAsCZ,SAAS,CAAC,WAAW,SAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAQ9C,mBAAmB,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IAY1C,kBAAkB,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAcjE,WAAW,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC;IAI7D,oBAAoB,CACxB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,wBAAwB,CAAC;IAM9B,aAAa,CACjB,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,yBAAyB,CAAC;IAWrC,YAAY,CACV,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE;QACR,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACjC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACrC,MAAM,CAAC,EAAE,aAAa,CAAC;KACxB,GACA,YAAY;IAIf;;;;;;OAMG;IACH,iBAAiB,CACf,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE;QACR,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACjC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACrC,MAAM,CAAC,EAAE,aAAa,CAAC;KACxB,GACA,YAAY,EAAE;CAGlB"}
@@ -4,7 +4,7 @@ import {
4
4
  HttpClient,
5
5
  ValidationError,
6
6
  WebhookVerificationError
7
- } from "../../index-qjtxhwzv.js";
7
+ } from "../../index-qnxj8bct.js";
8
8
 
9
9
  // src/carriers/smsaexpress/services.ts
10
10
  var SMSAService = {
@@ -340,7 +340,13 @@ class SMSAExpressAdapter extends BaseCarrierAdapter {
340
340
  }
341
341
  async cancelShipment(trackingNumber) {
342
342
  const response = await this.http.post(`/api/c2b/cancel/${encodeURIComponent(trackingNumber)}`);
343
- return typeof response === "string" ? response.toLowerCase().includes("cancelled") : true;
343
+ if (typeof response !== "string") {
344
+ return true;
345
+ }
346
+ if (response.toLowerCase().includes("cancelled")) {
347
+ return true;
348
+ }
349
+ throw new APIError(response.trim() || "SMSA did not confirm cancellation (B2C shipments cannot be cancelled via the SMSA API)", { carrier: "smsaexpress", raw: response });
344
350
  }
345
351
  async track(trackingNumber) {
346
352
  const response = await this.http.get(`/api/track/single/${encodeURIComponent(trackingNumber)}`);
@@ -415,4 +421,4 @@ export {
415
421
  SMSAExpressAdapter
416
422
  };
417
423
 
418
- //# debugId=D913394BAA446A3064756E2164756E21
424
+ //# debugId=E494CE182FFD4CD964756E2164756E21