shipflow 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +328 -0
  2. package/dist/carriers/aymakan/adapter.d.ts +87 -0
  3. package/dist/carriers/aymakan/adapter.d.ts.map +1 -0
  4. package/dist/carriers/aymakan/index.d.ts +9 -0
  5. package/dist/carriers/aymakan/index.d.ts.map +1 -0
  6. package/dist/carriers/aymakan/index.js +625 -0
  7. package/dist/carriers/aymakan/index.js.map +12 -0
  8. package/dist/carriers/aymakan/mappers.d.ts +21 -0
  9. package/dist/carriers/aymakan/mappers.d.ts.map +1 -0
  10. package/dist/carriers/aymakan/services.d.ts +47 -0
  11. package/dist/carriers/aymakan/services.d.ts.map +1 -0
  12. package/dist/carriers/aymakan/types.d.ts +287 -0
  13. package/dist/carriers/aymakan/types.d.ts.map +1 -0
  14. package/dist/carriers/base.d.ts +88 -0
  15. package/dist/carriers/base.d.ts.map +1 -0
  16. package/dist/carriers/smsaexpress/adapter.d.ts +57 -0
  17. package/dist/carriers/smsaexpress/adapter.d.ts.map +1 -0
  18. package/dist/carriers/smsaexpress/index.d.ts +9 -0
  19. package/dist/carriers/smsaexpress/index.d.ts.map +1 -0
  20. package/dist/carriers/smsaexpress/index.js +408 -0
  21. package/dist/carriers/smsaexpress/index.js.map +12 -0
  22. package/dist/carriers/smsaexpress/mappers.d.ts +45 -0
  23. package/dist/carriers/smsaexpress/mappers.d.ts.map +1 -0
  24. package/dist/carriers/smsaexpress/services.d.ts +21 -0
  25. package/dist/carriers/smsaexpress/services.d.ts.map +1 -0
  26. package/dist/carriers/smsaexpress/types.d.ts +197 -0
  27. package/dist/carriers/smsaexpress/types.d.ts.map +1 -0
  28. package/dist/client.d.ts +44 -0
  29. package/dist/client.d.ts.map +1 -0
  30. package/dist/core/errors.d.ts +69 -0
  31. package/dist/core/errors.d.ts.map +1 -0
  32. package/dist/core/http.d.ts +72 -0
  33. package/dist/core/http.d.ts.map +1 -0
  34. package/dist/core/schemas.d.ts +832 -0
  35. package/dist/core/schemas.d.ts.map +1 -0
  36. package/dist/core/types.d.ts +234 -0
  37. package/dist/core/types.d.ts.map +1 -0
  38. package/dist/index-x8sk1kw9.js +4600 -0
  39. package/dist/index-x8sk1kw9.js.map +22 -0
  40. package/dist/index.d.ts +27 -0
  41. package/dist/index.d.ts.map +1 -0
  42. package/dist/index.js +109 -0
  43. package/dist/index.js.map +10 -0
  44. package/package.json +63 -0
@@ -0,0 +1,625 @@
1
+ import {
2
+ APIError,
3
+ BaseCarrierAdapter,
4
+ HttpClient,
5
+ UnsupportedOperationError,
6
+ ValidationError,
7
+ WebhookVerificationError,
8
+ validateCreateShipmentInput,
9
+ validatePickupRequest
10
+ } from "../../index-x8sk1kw9.js";
11
+
12
+ // src/carriers/aymakan/services.ts
13
+ var AymakanService = {
14
+ ECOMMERCE: "ONP",
15
+ DOCUMENTS: "DOC",
16
+ SAME_DAY: "SDD",
17
+ REVERSE_PICKUP: "RVP",
18
+ EXCHANGE: "EXH",
19
+ LOCKERS: "LOC",
20
+ HEAVY: "BLK",
21
+ PALLET: "PLT",
22
+ IMPORT_EXPRESS: "IPX",
23
+ EXPORT_EXPRESS: "EPX"
24
+ };
25
+ var AymakanStatusCodes = {
26
+ "AY-0001": "created",
27
+ "AY-0002": "picked_up",
28
+ "AY-0003": "at_warehouse",
29
+ "AY-0004": "out_for_delivery",
30
+ "AY-0005": "delivered",
31
+ "AY-0006": "exception",
32
+ "AY-0026": "at_warehouse",
33
+ "AY-0027": "in_transit",
34
+ "AY-0028": "in_transit",
35
+ "AY-0032": "pending",
36
+ "AY-0007": "returned",
37
+ "AY-0008": "cancelled",
38
+ "AY-0009": "returned"
39
+ };
40
+
41
+ // src/carriers/aymakan/mappers.ts
42
+ function mapAymakanStatus(statusCode) {
43
+ const mapped = AymakanStatusCodes[statusCode];
44
+ return mapped;
45
+ }
46
+ function mapNationalAddress(addr) {
47
+ if (!addr)
48
+ return;
49
+ return {
50
+ short_code: addr.shortCode,
51
+ building_number: addr.buildingNumber,
52
+ street_name: addr.streetName,
53
+ district: addr.district,
54
+ additional_number: addr.additionalNumber
55
+ };
56
+ }
57
+ function sanitizePhone(phone) {
58
+ return phone.replace(/\D/g, "");
59
+ }
60
+ var VALID_AYMAKAN_SERVICE_TYPES = new Set(Object.values(AymakanService));
61
+ function resolveServiceType(serviceType) {
62
+ if (!serviceType)
63
+ return;
64
+ if (VALID_AYMAKAN_SERVICE_TYPES.has(serviceType))
65
+ return serviceType;
66
+ return;
67
+ }
68
+ function mapCreateShipmentRequest(input) {
69
+ const firstParcel = input.parcels[0];
70
+ const totalPieces = input.parcels.reduce((sum, p) => sum + p.pieces, 0);
71
+ const totalWeight = input.parcels.reduce((sum, p) => sum + (p.weight.unit === "lb" ? p.weight.value * 0.453592 : p.weight.value), 0);
72
+ const totalItems = input.parcels.reduce((sum, p) => sum + (p.itemsCount ?? p.pieces), 0);
73
+ return {
74
+ requested_by: input.options?.requestedBy ?? input.shipper.name,
75
+ declared_value: input.declaredValue?.amount ?? input.cod?.amount ?? 0,
76
+ declared_value_currency: input.declaredValue?.currency ?? input.cod?.currency ?? "SAR",
77
+ reference: input.reference,
78
+ customer_tracking: input.options?.customerTracking,
79
+ service_type: resolveServiceType(input.serviceType),
80
+ is_cod: input.cod?.enabled ? 1 : 0,
81
+ cod_amount: input.cod?.enabled ? input.cod.amount : undefined,
82
+ fulfilment_customer_name: input.options?.fulfilmentCustomerName,
83
+ currency: input.cod?.currency ?? "SAR",
84
+ delivery_name: input.consignee.name,
85
+ delivery_email: input.consignee.email,
86
+ delivery_city: input.consignee.city,
87
+ delivery_address: input.consignee.line1,
88
+ delivery_neighbourhood: input.consignee.neighbourhood ?? input.consignee.state,
89
+ delivery_postcode: input.consignee.postalCode,
90
+ delivery_country: input.consignee.countryCode,
91
+ delivery_phone: sanitizePhone(input.consignee.phone),
92
+ delivery_description: input.consignee.description,
93
+ delivery_national_address: mapNationalAddress(input.consignee.nationalAddress),
94
+ collection_name: input.shipper.company ?? input.shipper.name,
95
+ collection_email: input.shipper.email,
96
+ collection_city: input.shipper.city,
97
+ collection_address: input.shipper.line1,
98
+ collection_neighbourhood: input.shipper.neighbourhood ?? input.shipper.state,
99
+ collection_postcode: input.shipper.postalCode,
100
+ collection_country: input.shipper.countryCode,
101
+ collection_phone: sanitizePhone(input.shipper.phone),
102
+ collection_description: input.shipper.description,
103
+ collection_national_address: mapNationalAddress(input.shipper.nationalAddress),
104
+ weight: totalWeight,
105
+ length: firstParcel?.dimensions?.length,
106
+ width: firstParcel?.dimensions?.width,
107
+ height: firstParcel?.dimensions?.height,
108
+ pieces: totalPieces,
109
+ items_count: totalItems,
110
+ is_insured: input.options?.isInsured ? 1 : 0,
111
+ international_metadata: input.options?.internationalMetadata ? {
112
+ document_id: input.options.internationalMetadata.documentId,
113
+ tax_identification_number: input.options.internationalMetadata.taxId,
114
+ invoice_number: input.options.internationalMetadata.invoiceNumber,
115
+ invoice_date: input.options.internationalMetadata.invoiceDate
116
+ } : undefined
117
+ };
118
+ }
119
+ function mapPickupRequest(input) {
120
+ return {
121
+ reference: input.trackingNumbers?.[0],
122
+ pickup_date: input.date,
123
+ time_slot: input.timeSlot,
124
+ city: input.city,
125
+ contact_name: input.contactName,
126
+ contact_phone: input.contactPhone,
127
+ address: input.address,
128
+ shipments: input.shipmentCount
129
+ };
130
+ }
131
+ function mapCustomerAddressRequest(addr) {
132
+ return {
133
+ title: addr.title,
134
+ name: addr.name,
135
+ email: addr.email,
136
+ city: addr.city,
137
+ address: addr.address,
138
+ neighbourhood: addr.neighbourhood,
139
+ postcode: addr.postalCode ?? "",
140
+ phone: addr.phone,
141
+ description: addr.description ?? ""
142
+ };
143
+ }
144
+ function mapShipmentResponse(data) {
145
+ const codAmount = data.cod_amount != null ? typeof data.cod_amount === "string" ? parseFloat(data.cod_amount) : data.cod_amount : undefined;
146
+ return {
147
+ carrier: "aymakan",
148
+ trackingNumber: data.tracking_number,
149
+ customerTracking: data.customer_tracking ?? undefined,
150
+ reference: data.reference ?? undefined,
151
+ status: mapAymakanStatus(data.status) ?? "created",
152
+ statusLabel: data.status_label,
153
+ labelUrl: data.label || undefined,
154
+ pdfLabelUrl: data.pdf_label || undefined,
155
+ codAmount: codAmount && !Number.isNaN(codAmount) ? codAmount : undefined,
156
+ declaredValue: data.declared_value,
157
+ currency: data.currency,
158
+ createdAt: new Date(data.created_at),
159
+ raw: data
160
+ };
161
+ }
162
+ function mapTrackingEvent(event) {
163
+ return {
164
+ timestamp: new Date(event.created_at),
165
+ statusCode: event.status_code,
166
+ status: mapAymakanStatus(event.status_code) ?? "unknown",
167
+ description: event.description,
168
+ descriptionArabic: event.description_ar ?? undefined
169
+ };
170
+ }
171
+ function mapTrackingResult(data) {
172
+ return {
173
+ trackingNumber: data.tracking_number,
174
+ carrier: "aymakan",
175
+ reference: data.reference ?? undefined,
176
+ status: mapAymakanStatus(data.status) ?? "unknown",
177
+ statusLabel: data.status_label,
178
+ events: data.tracking_info.map(mapTrackingEvent),
179
+ deliveryDate: data.delivery_date ? new Date(data.delivery_date) : undefined,
180
+ pickupDate: data.pickup_date ? new Date(data.pickup_date) : undefined,
181
+ receivedAt: data.received_at ? new Date(data.received_at) : undefined,
182
+ codAmount: data.cod_amount ? Number.isNaN(parseFloat(data.cod_amount)) ? undefined : parseFloat(data.cod_amount) : undefined,
183
+ weight: Number.isNaN(parseFloat(data.weight)) ? undefined : parseFloat(data.weight),
184
+ pieces: data.pieces,
185
+ raw: data
186
+ };
187
+ }
188
+ function mapCity(city) {
189
+ return {
190
+ nameEn: city.city_en,
191
+ nameAr: city.city_ar
192
+ };
193
+ }
194
+ function mapPickupResponse(data) {
195
+ return {
196
+ id: data.id,
197
+ carrier: "aymakan",
198
+ status: ["pending", "processing", "completed", "cancelled"].includes(data.status) ? data.status : "pending",
199
+ date: data.pickup_date,
200
+ timeSlot: data.time_slot,
201
+ city: data.city,
202
+ contactName: data.contact_name,
203
+ contactPhone: data.contact_phone,
204
+ address: data.address,
205
+ shipmentCount: data.shipments,
206
+ warehouseId: data.warehouse_id,
207
+ warehouseName: data.warehouse_name,
208
+ createdAt: new Date(data.created_at),
209
+ raw: data
210
+ };
211
+ }
212
+ function timingSafeEqual(a, b) {
213
+ const encoder = new TextEncoder;
214
+ const bufA = encoder.encode(a);
215
+ const bufB = encoder.encode(b);
216
+ if (bufA.byteLength !== bufB.byteLength)
217
+ return false;
218
+ let mismatch = 0;
219
+ for (let i = 0;i < bufA.byteLength; i++) {
220
+ mismatch |= bufA[i] ^ bufB[i];
221
+ }
222
+ return mismatch === 0;
223
+ }
224
+ function parseAymakanWebhook(payload, options) {
225
+ const { headers = {}, queryParams = {}, config } = options ?? {};
226
+ if (!payload || typeof payload !== "object" || !("tracking_number" in payload) || !("status" in payload)) {
227
+ throw new ValidationError("Invalid webhook payload: missing required fields", {
228
+ raw: payload
229
+ });
230
+ }
231
+ const data = payload;
232
+ if (config?.authHeader && config?.authValue) {
233
+ const lowerKey = config.authHeader.toLowerCase();
234
+ const headerValue = Object.entries(headers).find(([k]) => k.toLowerCase() === lowerKey)?.[1];
235
+ if (!headerValue || !timingSafeEqual(headerValue, config.authValue)) {
236
+ throw new WebhookVerificationError("Invalid webhook auth header", {
237
+ carrier: "aymakan"
238
+ });
239
+ }
240
+ }
241
+ if (config?.authQueryParam && config?.authQueryValue) {
242
+ const paramValue = queryParams[config.authQueryParam];
243
+ if (!paramValue || !timingSafeEqual(paramValue, config.authQueryValue)) {
244
+ throw new WebhookVerificationError("Invalid webhook auth query param", {
245
+ carrier: "aymakan"
246
+ });
247
+ }
248
+ }
249
+ const eventType = data.event ?? "status_update";
250
+ const timestamp = new Date(data.date_time);
251
+ if (Number.isNaN(timestamp.getTime())) {
252
+ throw new ValidationError("Invalid webhook payload: invalid date_time value", { raw: data.date_time });
253
+ }
254
+ return {
255
+ carrier: "aymakan",
256
+ eventType,
257
+ trackingNumber: data.tracking_number,
258
+ reference: data.reference ?? undefined,
259
+ status: eventType === "weight_update" ? "unknown" : mapAymakanStatus(data.status) ?? "unknown",
260
+ statusCode: data.status,
261
+ statusLabel: data.status_label,
262
+ reasonCode: data.reason_code ?? undefined,
263
+ reasonLabel: data.reason_en ?? undefined,
264
+ timestamp,
265
+ raw: data
266
+ };
267
+ }
268
+
269
+ // src/carriers/aymakan/adapter.ts
270
+ var AYMAKAN_SANDBOX_URL = "https://dev-api.aymakan.com.sa/v2";
271
+ var AYMAKAN_PRODUCTION_URL = "https://api.aymakan.net/v2";
272
+
273
+ class AymakanAdapter extends BaseCarrierAdapter {
274
+ name = "aymakan";
275
+ supportedCountries = ["SA", "AE", "BH", "KW", "OM", "QA"];
276
+ http;
277
+ citiesCache = null;
278
+ citiesCacheTime = 0;
279
+ static CITIES_CACHE_TTL = 60 * 60 * 1000;
280
+ constructor(config) {
281
+ super(config);
282
+ this.http = new HttpClient({
283
+ baseUrl: this.getBaseUrl(),
284
+ carrier: "aymakan",
285
+ headers: {
286
+ Authorization: config.credentials.apiKey
287
+ }
288
+ });
289
+ }
290
+ getBaseUrl() {
291
+ return this.config.mode === "production" ? AYMAKAN_PRODUCTION_URL : AYMAKAN_SANDBOX_URL;
292
+ }
293
+ async ensureCitiesLoaded() {
294
+ if (this.citiesCache && Date.now() - this.citiesCacheTime < AymakanAdapter.CITIES_CACHE_TTL) {
295
+ return;
296
+ }
297
+ try {
298
+ this.citiesCache = await this.getCities();
299
+ this.citiesCacheTime = Date.now();
300
+ } catch {
301
+ if (!this.citiesCache)
302
+ this.citiesCache = [];
303
+ }
304
+ }
305
+ static normalizeArabic(text) {
306
+ return text.trim().replace(/[\u064B-\u065F\u0670]/g, "").replace(/[أإآ]/g, "ا").replace(/ة/g, "ه");
307
+ }
308
+ resolveCity(inputCity) {
309
+ if (!this.citiesCache || this.citiesCache.length === 0)
310
+ return inputCity;
311
+ const trimmed = inputCity.trim();
312
+ if (!trimmed)
313
+ return inputCity;
314
+ const lower = trimmed.toLowerCase();
315
+ const exactEn = this.citiesCache.find((c) => c.nameEn.toLowerCase() === lower);
316
+ if (exactEn)
317
+ return exactEn.nameEn;
318
+ const exactAr = this.citiesCache.find((c) => c.nameAr === trimmed);
319
+ if (exactAr)
320
+ return exactAr.nameEn;
321
+ const normalizedInput = AymakanAdapter.normalizeArabic(trimmed);
322
+ const normalizedAr = this.citiesCache.find((c) => c.nameAr && AymakanAdapter.normalizeArabic(c.nameAr) === normalizedInput);
323
+ if (normalizedAr)
324
+ return normalizedAr.nameEn;
325
+ const withoutAl = normalizedInput.startsWith("ال") ? normalizedInput.slice(2) : `ال${normalizedInput}`;
326
+ const alMatch = this.citiesCache.find((c) => c.nameAr && AymakanAdapter.normalizeArabic(c.nameAr) === withoutAl);
327
+ if (alMatch)
328
+ return alMatch.nameEn;
329
+ const containsEn = this.citiesCache.find((c) => c.nameEn.toLowerCase().includes(lower) || lower.includes(c.nameEn.toLowerCase()));
330
+ if (containsEn)
331
+ return containsEn.nameEn;
332
+ return trimmed;
333
+ }
334
+ resolveCitiesInInput(input) {
335
+ return {
336
+ ...input,
337
+ shipper: {
338
+ ...input.shipper,
339
+ city: this.resolveCity(input.shipper.city)
340
+ },
341
+ consignee: {
342
+ ...input.consignee,
343
+ city: this.resolveCity(input.consignee.city)
344
+ }
345
+ };
346
+ }
347
+ async executeCreateShipment(input) {
348
+ await this.ensureCitiesLoaded();
349
+ const resolved = this.resolveCitiesInInput(input);
350
+ const request = mapCreateShipmentRequest(resolved);
351
+ const response = await this.http.post("/shipping/create", request);
352
+ if (!response.success) {
353
+ throw new APIError("Failed to create shipment", {
354
+ carrier: "aymakan",
355
+ raw: response
356
+ });
357
+ }
358
+ return mapShipmentResponse(response.shipping);
359
+ }
360
+ async createBulkShipments(inputs) {
361
+ inputs.forEach(validateCreateShipmentInput);
362
+ await this.ensureCitiesLoaded();
363
+ const requests = inputs.map((i) => this.resolveCitiesInInput(i)).map(mapCreateShipmentRequest);
364
+ const response = await this.http.post("/shipping/create_bulk", { data: requests });
365
+ if (!response.success) {
366
+ throw new APIError("Failed to create bulk shipments", {
367
+ carrier: "aymakan",
368
+ raw: response
369
+ });
370
+ }
371
+ return response.data.shipments.map(mapShipmentResponse);
372
+ }
373
+ async cancelShipment(trackingNumber) {
374
+ const response = await this.http.post("/shipping/cancel", {
375
+ tracking: trackingNumber
376
+ });
377
+ return response.success;
378
+ }
379
+ async cancelByReference(reference) {
380
+ const response = await this.http.post(`/shipping/cancel/reference/${encodeURIComponent(reference)}`);
381
+ return response.success;
382
+ }
383
+ async updateDeliveryAddress(trackingNumber, address) {
384
+ await this.ensureCitiesLoaded();
385
+ const resolvedCity = this.resolveCity(address.city);
386
+ const response = await this.http.post(`/shipping/update_delivery_address/${encodeURIComponent(trackingNumber)}`, {
387
+ delivery_name: address.name,
388
+ delivery_email: address.email,
389
+ delivery_city: resolvedCity,
390
+ delivery_address: address.line1,
391
+ delivery_neighbourhood: address.neighbourhood,
392
+ delivery_postcode: address.postalCode,
393
+ delivery_country: address.countryCode,
394
+ delivery_phone: address.phone
395
+ });
396
+ return response.success;
397
+ }
398
+ async track(trackingNumber) {
399
+ const results = await this.trackMultiple([trackingNumber]);
400
+ const result = results[0];
401
+ if (!result) {
402
+ throw new APIError("Shipment not found", { carrier: "aymakan" });
403
+ }
404
+ return result;
405
+ }
406
+ async trackMultiple(trackingNumbers) {
407
+ const ids = trackingNumbers.map(encodeURIComponent).join(",");
408
+ const response = await this.http.get(`/shipping/track/${ids}`);
409
+ if (!response.success) {
410
+ throw new APIError("Failed to track shipments", {
411
+ carrier: "aymakan",
412
+ raw: response
413
+ });
414
+ }
415
+ return response.data.shipments.map(mapTrackingResult);
416
+ }
417
+ async trackByReference(reference) {
418
+ const response = await this.http.get(`/shipments/by_reference/${encodeURIComponent(reference)}`);
419
+ if (!response.success || !response.data.shipments[0]) {
420
+ throw new APIError("Shipment not found", {
421
+ carrier: "aymakan",
422
+ raw: response
423
+ });
424
+ }
425
+ return mapTrackingResult(response.data.shipments[0]);
426
+ }
427
+ async getLabel(trackingNumber, format) {
428
+ const response = await this.http.get(`/shipping/awb/tracking/${encodeURIComponent(trackingNumber)}`);
429
+ if (!response.success) {
430
+ throw new APIError("Failed to get label", {
431
+ carrier: "aymakan",
432
+ raw: response
433
+ });
434
+ }
435
+ if (format === "PNG") {
436
+ return response.data.label || response.data.awb_url || response.data.pdf_label;
437
+ }
438
+ return response.data.pdf_label || response.data.awb_url || response.data.label;
439
+ }
440
+ async getBulkLabels(trackingNumbers) {
441
+ const response = await this.http.post("/shipping/bulk_awb_labels", {
442
+ tracking_numbers: trackingNumbers
443
+ });
444
+ if (!response.success) {
445
+ throw new APIError("Failed to get bulk labels", {
446
+ carrier: "aymakan",
447
+ raw: response
448
+ });
449
+ }
450
+ return response.data.label_url;
451
+ }
452
+ async getPickupCities() {
453
+ const response = await this.http.get("/pickup_request/cities");
454
+ if (!response.success) {
455
+ throw new APIError("Failed to get pickup cities", {
456
+ carrier: "aymakan",
457
+ raw: response
458
+ });
459
+ }
460
+ return response.data.cities.map(mapCity);
461
+ }
462
+ async getTimeSlots(_city, date) {
463
+ const response = await this.http.get(`/time_slots/${date}`);
464
+ if (!response.success || response.error || !response.data?.slots) {
465
+ const msg = response.message ?? "No slots available";
466
+ throw new APIError(msg, { carrier: "aymakan", raw: response });
467
+ }
468
+ return Object.entries(response.data.slots).map(([id, label]) => ({
469
+ id,
470
+ label
471
+ }));
472
+ }
473
+ async createPickup(input) {
474
+ validatePickupRequest(input);
475
+ await this.ensureCitiesLoaded();
476
+ const resolvedInput = { ...input, city: this.resolveCity(input.city) };
477
+ const request = mapPickupRequest(resolvedInput);
478
+ const response = await this.http.post("/pickup_request/create", request);
479
+ if (!response.success) {
480
+ throw new APIError("Failed to create pickup", {
481
+ carrier: "aymakan",
482
+ raw: response
483
+ });
484
+ }
485
+ return mapPickupResponse(response.data);
486
+ }
487
+ async cancelPickup(pickupId) {
488
+ const response = await this.http.post(`/pickup_request/cancel/${encodeURIComponent(String(pickupId))}`);
489
+ return response.success;
490
+ }
491
+ async getPickupRequests() {
492
+ const response = await this.http.get("/pickup_requests");
493
+ if (!response.success) {
494
+ throw new APIError("Failed to get pickup requests", {
495
+ carrier: "aymakan",
496
+ raw: response
497
+ });
498
+ }
499
+ return response.data.pickup_requests.map(mapPickupResponse);
500
+ }
501
+ async getCities() {
502
+ const response = await this.http.get("/cities");
503
+ if (!response.success) {
504
+ throw new APIError("Failed to get cities", {
505
+ carrier: "aymakan",
506
+ raw: response
507
+ });
508
+ }
509
+ return response.data.cities.map(mapCity);
510
+ }
511
+ async getDropoffLocations() {
512
+ const response = await this.http.get("/dropoff_locations");
513
+ if (!response.success) {
514
+ throw new APIError("Failed to get dropoff locations", {
515
+ carrier: "aymakan",
516
+ raw: response
517
+ });
518
+ }
519
+ return response.data.locations.map((loc) => ({
520
+ id: String(loc.id),
521
+ name: loc.name,
522
+ nameAr: loc.name_ar,
523
+ address: loc.address,
524
+ city: loc.city
525
+ }));
526
+ }
527
+ async createCustomerAddress(address) {
528
+ const request = mapCustomerAddressRequest(address);
529
+ const response = await this.http.post("/address/create", request);
530
+ if (!response.success) {
531
+ throw new APIError("Failed to create address", {
532
+ carrier: "aymakan",
533
+ raw: response
534
+ });
535
+ }
536
+ const addr = response.data.address;
537
+ return {
538
+ id: addr.id,
539
+ title: addr.title,
540
+ name: addr.name,
541
+ email: addr.email,
542
+ phone: addr.phone,
543
+ city: addr.city,
544
+ address: addr.address,
545
+ neighbourhood: addr.neighbourhood,
546
+ postalCode: addr.postcode,
547
+ countryCode: addr.country,
548
+ description: addr.description
549
+ };
550
+ }
551
+ async getCustomerAddresses() {
552
+ const response = await this.http.get("/addresses");
553
+ if (!response.success) {
554
+ throw new APIError("Failed to get customer addresses", {
555
+ carrier: "aymakan",
556
+ raw: response
557
+ });
558
+ }
559
+ return response.data.addresses.map((addr) => ({
560
+ id: addr.id,
561
+ title: addr.title,
562
+ name: addr.name,
563
+ email: addr.email,
564
+ phone: addr.phone,
565
+ city: addr.city,
566
+ address: addr.address,
567
+ neighbourhood: addr.neighbourhood,
568
+ postalCode: addr.postcode,
569
+ countryCode: addr.country,
570
+ description: addr.description
571
+ }));
572
+ }
573
+ async updateCustomerAddress(id, address) {
574
+ const response = await this.http.put(`/address/update/${id}`, {
575
+ title: address.title,
576
+ name: address.name,
577
+ email: address.email,
578
+ city: address.city,
579
+ address: address.address,
580
+ neighbourhood: address.neighbourhood,
581
+ postcode: address.postalCode,
582
+ phone: address.phone,
583
+ description: address.description
584
+ });
585
+ if (!response.success) {
586
+ throw new APIError("Failed to update address", {
587
+ carrier: "aymakan",
588
+ raw: response
589
+ });
590
+ }
591
+ const addr = response.data.address;
592
+ return {
593
+ id: addr.id,
594
+ title: addr.title,
595
+ name: addr.name,
596
+ email: addr.email,
597
+ phone: addr.phone,
598
+ city: addr.city,
599
+ address: addr.address,
600
+ neighbourhood: addr.neighbourhood,
601
+ postalCode: addr.postcode,
602
+ countryCode: addr.country,
603
+ description: addr.description
604
+ };
605
+ }
606
+ async deleteCustomerAddress(id) {
607
+ const response = await this.http.delete(`/address/delete/${id}`);
608
+ return response.success;
609
+ }
610
+ parseWebhook(payload, options) {
611
+ return parseAymakanWebhook(payload, options);
612
+ }
613
+ getRates() {
614
+ throw new UnsupportedOperationError("aymakan", "getRates");
615
+ }
616
+ }
617
+ export {
618
+ parseAymakanWebhook,
619
+ mapAymakanStatus,
620
+ AymakanStatusCodes,
621
+ AymakanService,
622
+ AymakanAdapter
623
+ };
624
+
625
+ //# debugId=ECFB3CDDA31BC0F864756E2164756E21