shipflow 0.1.0 → 0.2.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 +139 -33
- package/dist/carriers/aramex/adapter.d.ts +82 -0
- package/dist/carriers/aramex/adapter.d.ts.map +1 -0
- package/dist/carriers/aramex/index.d.ts +9 -0
- package/dist/carriers/aramex/index.d.ts.map +1 -0
- package/dist/carriers/aramex/index.js +694 -0
- package/dist/carriers/aramex/index.js.map +12 -0
- package/dist/carriers/aramex/mappers.d.ts +76 -0
- package/dist/carriers/aramex/mappers.d.ts.map +1 -0
- package/dist/carriers/aramex/services.d.ts +74 -0
- package/dist/carriers/aramex/services.d.ts.map +1 -0
- package/dist/carriers/aramex/types.d.ts +302 -0
- package/dist/carriers/aramex/types.d.ts.map +1 -0
- package/dist/carriers/aymakan/adapter.d.ts +8 -2
- package/dist/carriers/aymakan/adapter.d.ts.map +1 -1
- package/dist/carriers/aymakan/index.js +138 -61
- package/dist/carriers/aymakan/index.js.map +4 -4
- package/dist/carriers/aymakan/mappers.d.ts +5 -0
- package/dist/carriers/aymakan/mappers.d.ts.map +1 -1
- package/dist/carriers/aymakan/types.d.ts +4 -6
- package/dist/carriers/aymakan/types.d.ts.map +1 -1
- package/dist/carriers/base.d.ts +2 -2
- package/dist/carriers/base.d.ts.map +1 -1
- package/dist/carriers/smsaexpress/adapter.d.ts +1 -1
- package/dist/carriers/smsaexpress/adapter.d.ts.map +1 -1
- package/dist/carriers/smsaexpress/index.js +32 -22
- package/dist/carriers/smsaexpress/index.js.map +4 -4
- package/dist/carriers/smsaexpress/mappers.d.ts.map +1 -1
- package/dist/core/http.d.ts.map +1 -1
- package/dist/core/schemas.d.ts +3 -3
- package/dist/core/types.d.ts +1 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/{index-x8sk1kw9.js → index-qjtxhwzv.js} +5 -3
- package/dist/{index-x8sk1kw9.js.map → index-qjtxhwzv.js.map} +5 -5
- package/dist/index.js +1 -1
- package/package.json +8 -3
|
@@ -13,6 +13,11 @@ export declare class AymakanAdapter extends BaseCarrierAdapter {
|
|
|
13
13
|
readonly name = "aymakan";
|
|
14
14
|
readonly supportedCountries: string[];
|
|
15
15
|
private http;
|
|
16
|
+
/**
|
|
17
|
+
* Shared options applied to every Aymakan http call so fake-200 error
|
|
18
|
+
* envelopes surface as APIError instead of being silently swallowed.
|
|
19
|
+
*/
|
|
20
|
+
private readonly errorOpts;
|
|
16
21
|
/** Cached Aymakan cities list for city name resolution */
|
|
17
22
|
private citiesCache;
|
|
18
23
|
private citiesCacheTime;
|
|
@@ -58,7 +63,7 @@ export declare class AymakanAdapter extends BaseCarrierAdapter {
|
|
|
58
63
|
track(trackingNumber: string): Promise<TrackingResult>;
|
|
59
64
|
trackMultiple(trackingNumbers: string[]): Promise<TrackingResult[]>;
|
|
60
65
|
trackByReference(reference: string): Promise<TrackingResult>;
|
|
61
|
-
getLabel(trackingNumber: string,
|
|
66
|
+
getLabel(trackingNumber: string, _format?: "PDF" | "ZPL" | "PNG"): Promise<string>;
|
|
62
67
|
getBulkLabels(trackingNumbers: string[]): Promise<string>;
|
|
63
68
|
getPickupCities(): Promise<City[]>;
|
|
64
69
|
getTimeSlots(_city: string, date: string): Promise<TimeSlot[]>;
|
|
@@ -69,9 +74,10 @@ export declare class AymakanAdapter extends BaseCarrierAdapter {
|
|
|
69
74
|
getDropoffLocations(): Promise<{
|
|
70
75
|
id: string;
|
|
71
76
|
name: string;
|
|
72
|
-
nameAr?: string;
|
|
73
77
|
address?: string;
|
|
74
78
|
city?: string;
|
|
79
|
+
latitude?: number;
|
|
80
|
+
longitude?: number;
|
|
75
81
|
}[]>;
|
|
76
82
|
createCustomerAddress(address: CustomerAddress): Promise<CustomerAddress>;
|
|
77
83
|
getCustomerAddresses(): Promise<CustomerAddress[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/carriers/aymakan/adapter.ts"],"names":[],"mappings":"AACA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/carriers/aymakan/adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
WebhookVerificationError,
|
|
8
8
|
validateCreateShipmentInput,
|
|
9
9
|
validatePickupRequest
|
|
10
|
-
} from "../../index-
|
|
10
|
+
} from "../../index-qjtxhwzv.js";
|
|
11
11
|
|
|
12
12
|
// src/carriers/aymakan/services.ts
|
|
13
13
|
var AymakanService = {
|
|
@@ -43,6 +43,33 @@ function mapAymakanStatus(statusCode) {
|
|
|
43
43
|
const mapped = AymakanStatusCodes[statusCode];
|
|
44
44
|
return mapped;
|
|
45
45
|
}
|
|
46
|
+
var AymakanStatusLabels = {
|
|
47
|
+
"awb created at origin": "created",
|
|
48
|
+
"shipment created": "created",
|
|
49
|
+
"collected from collection point": "picked_up",
|
|
50
|
+
collected: "picked_up",
|
|
51
|
+
"picked up": "picked_up",
|
|
52
|
+
"received at hub": "at_warehouse",
|
|
53
|
+
"received at warehouse": "at_warehouse",
|
|
54
|
+
"out for delivery": "out_for_delivery",
|
|
55
|
+
"out for final destination": "out_for_delivery",
|
|
56
|
+
delivered: "delivered",
|
|
57
|
+
"shipment is delivered": "delivered",
|
|
58
|
+
"transferred to destination city": "in_transit",
|
|
59
|
+
"in transit": "in_transit",
|
|
60
|
+
"not delivered": "exception",
|
|
61
|
+
"failed attempt": "exception",
|
|
62
|
+
pending: "pending",
|
|
63
|
+
"future delivery": "pending",
|
|
64
|
+
returned: "returned",
|
|
65
|
+
"returned to shipper": "returned",
|
|
66
|
+
"return to origin": "returned",
|
|
67
|
+
cancelled: "cancelled",
|
|
68
|
+
canceled: "cancelled"
|
|
69
|
+
};
|
|
70
|
+
function mapAymakanStatusLabel(label) {
|
|
71
|
+
return AymakanStatusLabels[label.trim().toLowerCase()];
|
|
72
|
+
}
|
|
46
73
|
function mapNationalAddress(addr) {
|
|
47
74
|
if (!addr)
|
|
48
75
|
return;
|
|
@@ -70,17 +97,19 @@ function mapCreateShipmentRequest(input) {
|
|
|
70
97
|
const totalPieces = input.parcels.reduce((sum, p) => sum + p.pieces, 0);
|
|
71
98
|
const totalWeight = input.parcels.reduce((sum, p) => sum + (p.weight.unit === "lb" ? p.weight.value * 0.453592 : p.weight.value), 0);
|
|
72
99
|
const totalItems = input.parcels.reduce((sum, p) => sum + (p.itemsCount ?? p.pieces), 0);
|
|
100
|
+
const codEnabled = input.cod?.enabled === true;
|
|
101
|
+
const declaredValueCurrency = input.declaredValue?.currency ?? "SAR";
|
|
73
102
|
return {
|
|
74
103
|
requested_by: input.options?.requestedBy ?? input.shipper.name,
|
|
75
|
-
declared_value: input.declaredValue?.amount ??
|
|
76
|
-
declared_value_currency:
|
|
104
|
+
declared_value: input.declaredValue?.amount ?? 0,
|
|
105
|
+
declared_value_currency: declaredValueCurrency,
|
|
77
106
|
reference: input.reference,
|
|
78
107
|
customer_tracking: input.options?.customerTracking,
|
|
79
108
|
service_type: resolveServiceType(input.serviceType),
|
|
80
|
-
is_cod:
|
|
81
|
-
cod_amount:
|
|
109
|
+
is_cod: codEnabled ? 1 : 0,
|
|
110
|
+
cod_amount: codEnabled ? input.cod?.amount : undefined,
|
|
82
111
|
fulfilment_customer_name: input.options?.fulfilmentCustomerName,
|
|
83
|
-
currency: input.cod?.currency ?? "SAR",
|
|
112
|
+
currency: codEnabled ? input.cod?.currency ?? "SAR" : declaredValueCurrency,
|
|
84
113
|
delivery_name: input.consignee.name,
|
|
85
114
|
delivery_email: input.consignee.email,
|
|
86
115
|
delivery_city: input.consignee.city,
|
|
@@ -152,16 +181,22 @@ function mapShipmentResponse(data) {
|
|
|
152
181
|
statusLabel: data.status_label,
|
|
153
182
|
labelUrl: data.label || undefined,
|
|
154
183
|
pdfLabelUrl: data.pdf_label || undefined,
|
|
155
|
-
codAmount: codAmount && !Number.isNaN(codAmount) ? codAmount : undefined,
|
|
184
|
+
codAmount: codAmount != null && !Number.isNaN(codAmount) && codAmount !== 0 ? codAmount : undefined,
|
|
156
185
|
declaredValue: data.declared_value,
|
|
157
186
|
currency: data.currency,
|
|
158
187
|
createdAt: new Date(data.created_at),
|
|
159
188
|
raw: data
|
|
160
189
|
};
|
|
161
190
|
}
|
|
191
|
+
function parseAymakanDate(value) {
|
|
192
|
+
if (/[TZ]|[+-]\d{2}:?\d{2}$/.test(value)) {
|
|
193
|
+
return new Date(value);
|
|
194
|
+
}
|
|
195
|
+
return new Date(`${value.replace(" ", "T")}+03:00`);
|
|
196
|
+
}
|
|
162
197
|
function mapTrackingEvent(event) {
|
|
163
198
|
return {
|
|
164
|
-
timestamp:
|
|
199
|
+
timestamp: parseAymakanDate(event.created_at),
|
|
165
200
|
statusCode: event.status_code,
|
|
166
201
|
status: mapAymakanStatus(event.status_code) ?? "unknown",
|
|
167
202
|
description: event.description,
|
|
@@ -169,13 +204,21 @@ function mapTrackingEvent(event) {
|
|
|
169
204
|
};
|
|
170
205
|
}
|
|
171
206
|
function mapTrackingResult(data) {
|
|
207
|
+
const events = data.tracking_info.map(mapTrackingEvent);
|
|
208
|
+
const latestEvent = events.length ? [...events].sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime())[0] : undefined;
|
|
209
|
+
let status;
|
|
210
|
+
if (latestEvent && latestEvent.status !== "unknown") {
|
|
211
|
+
status = latestEvent.status;
|
|
212
|
+
} else {
|
|
213
|
+
status = mapAymakanStatus(data.status) ?? mapAymakanStatusLabel(data.status) ?? latestEvent?.status ?? "unknown";
|
|
214
|
+
}
|
|
172
215
|
return {
|
|
173
216
|
trackingNumber: data.tracking_number,
|
|
174
217
|
carrier: "aymakan",
|
|
175
218
|
reference: data.reference ?? undefined,
|
|
176
|
-
status
|
|
219
|
+
status,
|
|
177
220
|
statusLabel: data.status_label,
|
|
178
|
-
events
|
|
221
|
+
events,
|
|
179
222
|
deliveryDate: data.delivery_date ? new Date(data.delivery_date) : undefined,
|
|
180
223
|
pickupDate: data.pickup_date ? new Date(data.pickup_date) : undefined,
|
|
181
224
|
receivedAt: data.received_at ? new Date(data.received_at) : undefined,
|
|
@@ -256,7 +299,7 @@ function parseAymakanWebhook(payload, options) {
|
|
|
256
299
|
eventType,
|
|
257
300
|
trackingNumber: data.tracking_number,
|
|
258
301
|
reference: data.reference ?? undefined,
|
|
259
|
-
status:
|
|
302
|
+
status: mapAymakanStatus(data.status) ?? "unknown",
|
|
260
303
|
statusCode: data.status,
|
|
261
304
|
statusLabel: data.status_label,
|
|
262
305
|
reasonCode: data.reason_code ?? undefined,
|
|
@@ -269,11 +312,29 @@ function parseAymakanWebhook(payload, options) {
|
|
|
269
312
|
// src/carriers/aymakan/adapter.ts
|
|
270
313
|
var AYMAKAN_SANDBOX_URL = "https://dev-api.aymakan.com.sa/v2";
|
|
271
314
|
var AYMAKAN_PRODUCTION_URL = "https://api.aymakan.net/v2";
|
|
315
|
+
function aymakanErrorExtractor(json) {
|
|
316
|
+
if (!json || typeof json !== "object") {
|
|
317
|
+
return { hasError: false };
|
|
318
|
+
}
|
|
319
|
+
const obj = json;
|
|
320
|
+
const hasValidationErrors = !!obj.errors && typeof obj.errors === "object" && Object.keys(obj.errors).length > 0;
|
|
321
|
+
const hasError = obj.error === true || obj.success === false || hasValidationErrors;
|
|
322
|
+
if (!hasError) {
|
|
323
|
+
return { hasError: false };
|
|
324
|
+
}
|
|
325
|
+
const message = typeof obj.message === "string" && obj.message || typeof obj.response === "string" && obj.response || typeof obj.error === "string" && obj.error || undefined;
|
|
326
|
+
return {
|
|
327
|
+
hasError: true,
|
|
328
|
+
message,
|
|
329
|
+
errors: hasValidationErrors ? obj.errors : undefined
|
|
330
|
+
};
|
|
331
|
+
}
|
|
272
332
|
|
|
273
333
|
class AymakanAdapter extends BaseCarrierAdapter {
|
|
274
334
|
name = "aymakan";
|
|
275
335
|
supportedCountries = ["SA", "AE", "BH", "KW", "OM", "QA"];
|
|
276
336
|
http;
|
|
337
|
+
errorOpts = { errorExtractor: aymakanErrorExtractor };
|
|
277
338
|
citiesCache = null;
|
|
278
339
|
citiesCacheTime = 0;
|
|
279
340
|
static CITIES_CACHE_TTL = 60 * 60 * 1000;
|
|
@@ -348,7 +409,7 @@ class AymakanAdapter extends BaseCarrierAdapter {
|
|
|
348
409
|
await this.ensureCitiesLoaded();
|
|
349
410
|
const resolved = this.resolveCitiesInInput(input);
|
|
350
411
|
const request = mapCreateShipmentRequest(resolved);
|
|
351
|
-
const response = await this.http.post("/shipping/create", request);
|
|
412
|
+
const response = await this.http.post("/shipping/create", request, this.errorOpts);
|
|
352
413
|
if (!response.success) {
|
|
353
414
|
throw new APIError("Failed to create shipment", {
|
|
354
415
|
carrier: "aymakan",
|
|
@@ -358,27 +419,35 @@ class AymakanAdapter extends BaseCarrierAdapter {
|
|
|
358
419
|
return mapShipmentResponse(response.shipping);
|
|
359
420
|
}
|
|
360
421
|
async createBulkShipments(inputs) {
|
|
422
|
+
if (inputs.length === 0)
|
|
423
|
+
return [];
|
|
424
|
+
if (inputs.length > 30) {
|
|
425
|
+
throw new ValidationError("Aymakan bulk create accepts at most 30 shipments per request", { raw: { count: inputs.length } });
|
|
426
|
+
}
|
|
361
427
|
inputs.forEach(validateCreateShipmentInput);
|
|
362
428
|
await this.ensureCitiesLoaded();
|
|
363
429
|
const requests = inputs.map((i) => this.resolveCitiesInInput(i)).map(mapCreateShipmentRequest);
|
|
364
|
-
const response = await this.http.post("/shipping/
|
|
430
|
+
const response = await this.http.post("/shipping/create/bulk_shipping", { shipments: requests }, this.errorOpts);
|
|
365
431
|
if (!response.success) {
|
|
366
432
|
throw new APIError("Failed to create bulk shipments", {
|
|
367
433
|
carrier: "aymakan",
|
|
368
434
|
raw: response
|
|
369
435
|
});
|
|
370
436
|
}
|
|
371
|
-
|
|
437
|
+
if (!Array.isArray(response.shipments)) {
|
|
438
|
+
throw new APIError("Aymakan bulk create response is missing the shipments array", { carrier: "aymakan", raw: response });
|
|
439
|
+
}
|
|
440
|
+
return response.shipments.map(mapShipmentResponse);
|
|
372
441
|
}
|
|
373
442
|
async cancelShipment(trackingNumber) {
|
|
374
443
|
const response = await this.http.post("/shipping/cancel", {
|
|
375
444
|
tracking: trackingNumber
|
|
376
|
-
});
|
|
377
|
-
return response.success;
|
|
445
|
+
}, this.errorOpts);
|
|
446
|
+
return response.success === true;
|
|
378
447
|
}
|
|
379
448
|
async cancelByReference(reference) {
|
|
380
|
-
const response = await this.http.post(
|
|
381
|
-
return response.success;
|
|
449
|
+
const response = await this.http.post("/shipping/cancel_by_reference", { reference }, this.errorOpts);
|
|
450
|
+
return response.success === true;
|
|
382
451
|
}
|
|
383
452
|
async updateDeliveryAddress(trackingNumber, address) {
|
|
384
453
|
await this.ensureCitiesLoaded();
|
|
@@ -405,52 +474,51 @@ class AymakanAdapter extends BaseCarrierAdapter {
|
|
|
405
474
|
}
|
|
406
475
|
async trackMultiple(trackingNumbers) {
|
|
407
476
|
const ids = trackingNumbers.map(encodeURIComponent).join(",");
|
|
408
|
-
const response = await this.http.get(`/shipping/track/${ids}
|
|
477
|
+
const response = await this.http.get(`/shipping/track/${ids}`, this.errorOpts);
|
|
409
478
|
if (!response.success) {
|
|
410
479
|
throw new APIError("Failed to track shipments", {
|
|
411
480
|
carrier: "aymakan",
|
|
412
481
|
raw: response
|
|
413
482
|
});
|
|
414
483
|
}
|
|
415
|
-
|
|
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", {
|
|
484
|
+
if (!Array.isArray(response.data?.shipments)) {
|
|
485
|
+
throw new APIError("Aymakan track response is missing data.shipments", {
|
|
421
486
|
carrier: "aymakan",
|
|
422
487
|
raw: response
|
|
423
488
|
});
|
|
424
489
|
}
|
|
425
|
-
return
|
|
490
|
+
return response.data.shipments.map(mapTrackingResult);
|
|
426
491
|
}
|
|
427
|
-
async
|
|
428
|
-
const response = await this.http.get(`/shipping/
|
|
429
|
-
|
|
430
|
-
|
|
492
|
+
async trackByReference(reference) {
|
|
493
|
+
const response = await this.http.get(`/shipping/by_reference/${encodeURIComponent(reference)}`, this.errorOpts);
|
|
494
|
+
const shipment = response.data?.shipments?.[0];
|
|
495
|
+
if (!response.success || !shipment) {
|
|
496
|
+
throw new APIError("Shipment not found", {
|
|
431
497
|
carrier: "aymakan",
|
|
432
498
|
raw: response
|
|
433
499
|
});
|
|
434
500
|
}
|
|
435
|
-
|
|
436
|
-
|
|
501
|
+
return mapTrackingResult(shipment);
|
|
502
|
+
}
|
|
503
|
+
async getLabel(trackingNumber, _format) {
|
|
504
|
+
const response = await this.http.get(`/shipping/awb/tracking/${encodeURIComponent(trackingNumber)}`, this.errorOpts);
|
|
505
|
+
if (!response.success || !response.data?.awb_url) {
|
|
506
|
+
const msg = response.message ?? response.response ?? "Failed to get label";
|
|
507
|
+
throw new APIError(msg, { carrier: "aymakan", raw: response });
|
|
437
508
|
}
|
|
438
|
-
return response.data.
|
|
509
|
+
return response.data.awb_url;
|
|
439
510
|
}
|
|
440
511
|
async getBulkLabels(trackingNumbers) {
|
|
441
|
-
const
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
throw new APIError(
|
|
446
|
-
carrier: "aymakan",
|
|
447
|
-
raw: response
|
|
448
|
-
});
|
|
512
|
+
const ids = trackingNumbers.map(encodeURIComponent).join(",");
|
|
513
|
+
const response = await this.http.get(`/shipping/bulk_awb/trackings/${ids}`, this.errorOpts);
|
|
514
|
+
if (!response.success || !response.data?.bulk_awb_url) {
|
|
515
|
+
const msg = response.message ?? response.response ?? "Failed to get bulk labels";
|
|
516
|
+
throw new APIError(msg, { carrier: "aymakan", raw: response });
|
|
449
517
|
}
|
|
450
|
-
return response.data.
|
|
518
|
+
return response.data.bulk_awb_url;
|
|
451
519
|
}
|
|
452
520
|
async getPickupCities() {
|
|
453
|
-
const response = await this.http.get("/pickup_request/cities");
|
|
521
|
+
const response = await this.http.get("/pickup_request/cities", this.errorOpts);
|
|
454
522
|
if (!response.success) {
|
|
455
523
|
throw new APIError("Failed to get pickup cities", {
|
|
456
524
|
carrier: "aymakan",
|
|
@@ -475,7 +543,7 @@ class AymakanAdapter extends BaseCarrierAdapter {
|
|
|
475
543
|
await this.ensureCitiesLoaded();
|
|
476
544
|
const resolvedInput = { ...input, city: this.resolveCity(input.city) };
|
|
477
545
|
const request = mapPickupRequest(resolvedInput);
|
|
478
|
-
const response = await this.http.post("/pickup_request/create", request);
|
|
546
|
+
const response = await this.http.post("/pickup_request/create", request, this.errorOpts);
|
|
479
547
|
if (!response.success) {
|
|
480
548
|
throw new APIError("Failed to create pickup", {
|
|
481
549
|
carrier: "aymakan",
|
|
@@ -485,18 +553,22 @@ class AymakanAdapter extends BaseCarrierAdapter {
|
|
|
485
553
|
return mapPickupResponse(response.data);
|
|
486
554
|
}
|
|
487
555
|
async cancelPickup(pickupId) {
|
|
488
|
-
const response = await this.http.post(
|
|
489
|
-
return response.success;
|
|
556
|
+
const response = await this.http.post("/pickup_request/cancel", { pickup_request: Number(pickupId) }, this.errorOpts);
|
|
557
|
+
return response.success === true;
|
|
490
558
|
}
|
|
491
559
|
async getPickupRequests() {
|
|
492
|
-
const response = await this.http.get("/
|
|
560
|
+
const response = await this.http.get("/pickup_request/list", this.errorOpts);
|
|
493
561
|
if (!response.success) {
|
|
494
562
|
throw new APIError("Failed to get pickup requests", {
|
|
495
563
|
carrier: "aymakan",
|
|
496
564
|
raw: response
|
|
497
565
|
});
|
|
498
566
|
}
|
|
499
|
-
|
|
567
|
+
const list = response.data?.pickupRequests?.data;
|
|
568
|
+
if (!Array.isArray(list)) {
|
|
569
|
+
throw new APIError("Aymakan pickup list response is missing data.pickupRequests.data", { carrier: "aymakan", raw: response });
|
|
570
|
+
}
|
|
571
|
+
return list.map(mapPickupResponse);
|
|
500
572
|
}
|
|
501
573
|
async getCities() {
|
|
502
574
|
const response = await this.http.get("/cities");
|
|
@@ -516,18 +588,19 @@ class AymakanAdapter extends BaseCarrierAdapter {
|
|
|
516
588
|
raw: response
|
|
517
589
|
});
|
|
518
590
|
}
|
|
519
|
-
return response.data.
|
|
520
|
-
id:
|
|
591
|
+
return response.data.map((loc) => ({
|
|
592
|
+
id: loc.name,
|
|
521
593
|
name: loc.name,
|
|
522
|
-
nameAr: loc.name_ar,
|
|
523
594
|
address: loc.address,
|
|
524
|
-
city: loc.city
|
|
595
|
+
city: loc.city,
|
|
596
|
+
latitude: loc.location_lat ?? undefined,
|
|
597
|
+
longitude: loc.location_lng ?? undefined
|
|
525
598
|
}));
|
|
526
599
|
}
|
|
527
600
|
async createCustomerAddress(address) {
|
|
528
601
|
const request = mapCustomerAddressRequest(address);
|
|
529
|
-
const response = await this.http.post("/address/create", request);
|
|
530
|
-
if (!response.success) {
|
|
602
|
+
const response = await this.http.post("/address/create", request, this.errorOpts);
|
|
603
|
+
if (!response.success || !response.data?.address) {
|
|
531
604
|
throw new APIError("Failed to create address", {
|
|
532
605
|
carrier: "aymakan",
|
|
533
606
|
raw: response
|
|
@@ -549,14 +622,17 @@ class AymakanAdapter extends BaseCarrierAdapter {
|
|
|
549
622
|
};
|
|
550
623
|
}
|
|
551
624
|
async getCustomerAddresses() {
|
|
552
|
-
const response = await this.http.get("/
|
|
625
|
+
const response = await this.http.get("/address/list", this.errorOpts);
|
|
553
626
|
if (!response.success) {
|
|
554
627
|
throw new APIError("Failed to get customer addresses", {
|
|
555
628
|
carrier: "aymakan",
|
|
556
629
|
raw: response
|
|
557
630
|
});
|
|
558
631
|
}
|
|
559
|
-
|
|
632
|
+
if (!Array.isArray(response.data?.address)) {
|
|
633
|
+
throw new APIError("Aymakan address list response is missing data.address", { carrier: "aymakan", raw: response });
|
|
634
|
+
}
|
|
635
|
+
return response.data.address.map((addr) => ({
|
|
560
636
|
id: addr.id,
|
|
561
637
|
title: addr.title,
|
|
562
638
|
name: addr.name,
|
|
@@ -571,7 +647,8 @@ class AymakanAdapter extends BaseCarrierAdapter {
|
|
|
571
647
|
}));
|
|
572
648
|
}
|
|
573
649
|
async updateCustomerAddress(id, address) {
|
|
574
|
-
const response = await this.http.put(
|
|
650
|
+
const response = await this.http.put("/address/update", {
|
|
651
|
+
id,
|
|
575
652
|
title: address.title,
|
|
576
653
|
name: address.name,
|
|
577
654
|
email: address.email,
|
|
@@ -581,8 +658,8 @@ class AymakanAdapter extends BaseCarrierAdapter {
|
|
|
581
658
|
postcode: address.postalCode,
|
|
582
659
|
phone: address.phone,
|
|
583
660
|
description: address.description
|
|
584
|
-
});
|
|
585
|
-
if (!response.success) {
|
|
661
|
+
}, this.errorOpts);
|
|
662
|
+
if (!response.success || !response.data?.address) {
|
|
586
663
|
throw new APIError("Failed to update address", {
|
|
587
664
|
carrier: "aymakan",
|
|
588
665
|
raw: response
|
|
@@ -604,7 +681,7 @@ class AymakanAdapter extends BaseCarrierAdapter {
|
|
|
604
681
|
};
|
|
605
682
|
}
|
|
606
683
|
async deleteCustomerAddress(id) {
|
|
607
|
-
const response = await this.http.delete(
|
|
684
|
+
const response = await this.http.delete("/address/delete", { body: { id }, errorExtractor: aymakanErrorExtractor });
|
|
608
685
|
return response.success;
|
|
609
686
|
}
|
|
610
687
|
parseWebhook(payload, options) {
|
|
@@ -622,4 +699,4 @@ export {
|
|
|
622
699
|
AymakanAdapter
|
|
623
700
|
};
|
|
624
701
|
|
|
625
|
-
//# debugId=
|
|
702
|
+
//# debugId=52369388ABAA8E1964756E2164756E21
|