@shopickup/adapters-mpl 0.0.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 +43 -0
- package/dist/capabilities/auth.d.ts +39 -0
- package/dist/capabilities/auth.d.ts.map +1 -0
- package/dist/capabilities/auth.js +130 -0
- package/dist/capabilities/close.d.ts +8 -0
- package/dist/capabilities/close.d.ts.map +1 -0
- package/dist/capabilities/close.js +70 -0
- package/dist/capabilities/get-shipment-details.d.ts +63 -0
- package/dist/capabilities/get-shipment-details.d.ts.map +1 -0
- package/dist/capabilities/get-shipment-details.js +97 -0
- package/dist/capabilities/index.d.ts +10 -0
- package/dist/capabilities/index.d.ts.map +1 -0
- package/dist/capabilities/index.js +9 -0
- package/dist/capabilities/label.d.ts +33 -0
- package/dist/capabilities/label.d.ts.map +1 -0
- package/dist/capabilities/label.js +328 -0
- package/dist/capabilities/parcels.d.ts +33 -0
- package/dist/capabilities/parcels.d.ts.map +1 -0
- package/dist/capabilities/parcels.js +284 -0
- package/dist/capabilities/pickup-points.d.ts +41 -0
- package/dist/capabilities/pickup-points.d.ts.map +1 -0
- package/dist/capabilities/pickup-points.js +294 -0
- package/dist/capabilities/track.d.ts +72 -0
- package/dist/capabilities/track.d.ts.map +1 -0
- package/dist/capabilities/track.js +331 -0
- package/dist/index.d.ts +83 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +142 -0
- package/dist/mappers/label.d.ts +67 -0
- package/dist/mappers/label.d.ts.map +1 -0
- package/dist/mappers/label.js +83 -0
- package/dist/mappers/shipment.d.ts +110 -0
- package/dist/mappers/shipment.d.ts.map +1 -0
- package/dist/mappers/shipment.js +258 -0
- package/dist/mappers/tracking.d.ts +60 -0
- package/dist/mappers/tracking.d.ts.map +1 -0
- package/dist/mappers/tracking.js +187 -0
- package/dist/utils/httpUtils.d.ts +36 -0
- package/dist/utils/httpUtils.d.ts.map +1 -0
- package/dist/utils/httpUtils.js +76 -0
- package/dist/utils/oauthFallback.d.ts +47 -0
- package/dist/utils/oauthFallback.d.ts.map +1 -0
- package/dist/utils/oauthFallback.js +250 -0
- package/dist/utils/resolveBaseUrl.d.ts +75 -0
- package/dist/utils/resolveBaseUrl.d.ts.map +1 -0
- package/dist/utils/resolveBaseUrl.js +65 -0
- package/dist/validation.d.ts +1890 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +726 -0
- package/package.json +69 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MPL Pickup Points Capability
|
|
3
|
+
*
|
|
4
|
+
* Fetches and normalizes the list of delivery places and pickup points
|
|
5
|
+
* from the MPL API endpoint `/deliveryplace`.
|
|
6
|
+
*
|
|
7
|
+
* Supports filtering by postCode, city, or servicePointType.
|
|
8
|
+
* Returns normalized PickupPoint entries in canonical format.
|
|
9
|
+
*/
|
|
10
|
+
import type { FetchPickupPointsRequest, FetchPickupPointsResponse, AdapterContext } from "@shopickup/core";
|
|
11
|
+
import type { ResolveBaseUrl } from "../utils/resolveBaseUrl.js";
|
|
12
|
+
/**
|
|
13
|
+
* Fetch pickup points from MPL API
|
|
14
|
+
*
|
|
15
|
+
* Makes an authenticated request to the `/deliveryplace` endpoint with optional filters.
|
|
16
|
+
*
|
|
17
|
+
* Handles both success and error responses:
|
|
18
|
+
* - 200 OK: Returns normalized PickupPoint array
|
|
19
|
+
* - 4xx/5xx: Translates to CarrierError with appropriate retry category
|
|
20
|
+
*
|
|
21
|
+
* Note on logging: By default, raw responses are logged as summaries only
|
|
22
|
+
* to avoid polluting logs with hundreds of pickup point entries.
|
|
23
|
+
* To customize logging behavior, pass loggingOptions in the adapter context:
|
|
24
|
+
* {
|
|
25
|
+
* loggingOptions: {
|
|
26
|
+
* logRawResponse: true, // Log full response
|
|
27
|
+
* logRawResponse: false, // Skip logging raw entirely
|
|
28
|
+
* logRawResponse: 'summary', // Log only summary (default)
|
|
29
|
+
* maxArrayItems: 50, // Increase items shown in arrays
|
|
30
|
+
* silentOperations: [] // Enable logging for this operation
|
|
31
|
+
* }
|
|
32
|
+
* }
|
|
33
|
+
*
|
|
34
|
+
* @param req Request containing credentials and optional filters (postCode, city, servicePointType)
|
|
35
|
+
* @param ctx Adapter context with HTTP client and logger
|
|
36
|
+
* @param resolveBaseUrl Function to resolve API base URL (test vs. production)
|
|
37
|
+
* @returns FetchPickupPointsResponse with normalized pickup points
|
|
38
|
+
* @throws CarrierError on HTTP error or response parsing failure
|
|
39
|
+
*/
|
|
40
|
+
export declare function fetchPickupPoints(req: FetchPickupPointsRequest, ctx: AdapterContext, resolveBaseUrl: ResolveBaseUrl): Promise<FetchPickupPointsResponse>;
|
|
41
|
+
//# sourceMappingURL=pickup-points.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pickup-points.d.ts","sourceRoot":"","sources":["../../src/capabilities/pickup-points.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACV,wBAAwB,EACxB,yBAAyB,EAEzB,cAAc,EACf,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAwJjE;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,wBAAwB,EAC7B,GAAG,EAAE,cAAc,EACnB,cAAc,EAAE,cAAc,GAC7B,OAAO,CAAC,yBAAyB,CAAC,CAgOpC"}
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MPL Pickup Points Capability
|
|
3
|
+
*
|
|
4
|
+
* Fetches and normalizes the list of delivery places and pickup points
|
|
5
|
+
* from the MPL API endpoint `/deliveryplace`.
|
|
6
|
+
*
|
|
7
|
+
* Supports filtering by postCode, city, or servicePointType.
|
|
8
|
+
* Returns normalized PickupPoint entries in canonical format.
|
|
9
|
+
*/
|
|
10
|
+
import { CarrierError, safeLog, createLogEntry, serializeForLog } from "@shopickup/core";
|
|
11
|
+
import { safeValidateFetchPickupPointsRequest, isGatewayError, isSuccessResponse, } from "../validation.js";
|
|
12
|
+
import { buildMPLHeaders } from "../utils/httpUtils.js";
|
|
13
|
+
/**
|
|
14
|
+
* Maps an MPL delivery place entry to canonical PickupPoint
|
|
15
|
+
*
|
|
16
|
+
* Handles:
|
|
17
|
+
* - Coordinate parsing from geocodeLat/geocodeLong (may be numbers)
|
|
18
|
+
* - Address construction from address field
|
|
19
|
+
* - Service point type validation
|
|
20
|
+
* - Metadata preservation for carrier-specific fields
|
|
21
|
+
*/
|
|
22
|
+
function mapMplDeliveryPlaceToPickupPoint(entry) {
|
|
23
|
+
const qr = entry.deliveryplacesQueryResult;
|
|
24
|
+
// Use the delivery place ID as primary identifier
|
|
25
|
+
const id = qr.id || `mpl-${Math.random().toString(36).slice(2, 9)}`;
|
|
26
|
+
// Parse coordinates - geocodeLat and geocodeLong are numbers
|
|
27
|
+
let latitude;
|
|
28
|
+
let longitude;
|
|
29
|
+
if (qr.geocodeLat !== undefined && qr.geocodeLat !== null) {
|
|
30
|
+
latitude = typeof qr.geocodeLat === 'string' ? parseFloat(qr.geocodeLat) : qr.geocodeLat;
|
|
31
|
+
latitude = isNaN(latitude) ? undefined : latitude;
|
|
32
|
+
}
|
|
33
|
+
if (qr.geocodeLong !== undefined && qr.geocodeLong !== null) {
|
|
34
|
+
longitude = typeof qr.geocodeLong === 'string' ? parseFloat(qr.geocodeLong) : qr.geocodeLong;
|
|
35
|
+
longitude = isNaN(longitude) ? undefined : longitude;
|
|
36
|
+
}
|
|
37
|
+
// Determine allowed services based on servicePointType
|
|
38
|
+
// For MPL, servicePointType indicates what types of operations are allowed at this point
|
|
39
|
+
// These are the pickup-capable service point types available in the request filter
|
|
40
|
+
let pickupAllowed = true; // Most delivery places support pickup
|
|
41
|
+
let dropoffAllowed = true; // Most delivery places support dropoff
|
|
42
|
+
const types = entry.servicePointType || [];
|
|
43
|
+
// ServicePointType options include:
|
|
44
|
+
// 'PM' - Postán Maradó (Post Office) - typically both
|
|
45
|
+
// 'PP' - PostaPont (Post Point) - typically both
|
|
46
|
+
// 'CS' - Csomagautomata (Parcel Locker) - typically both pickup and dropoff
|
|
47
|
+
// Note: 'HA' and 'RA' are not in the pickup filter list but may appear in responses
|
|
48
|
+
// If no pickup-enabled service types are present, restrict to dropoff only
|
|
49
|
+
const pickupEnabledTypes = types.filter(t => t === 'PM' || t === 'PP' || t === 'CS');
|
|
50
|
+
if (types.length > 0 && pickupEnabledTypes.length === 0) {
|
|
51
|
+
pickupAllowed = false;
|
|
52
|
+
}
|
|
53
|
+
// Collect carrier-specific metadata
|
|
54
|
+
const metadata = {
|
|
55
|
+
deliveryplace: qr.deliveryplace,
|
|
56
|
+
errors: qr.errors && qr.errors.length > 0 ? qr.errors : null,
|
|
57
|
+
};
|
|
58
|
+
// Clean metadata - remove undefined keys
|
|
59
|
+
const cleanedMetadata = Object.fromEntries(Object.entries(metadata).filter(([, value]) => value !== undefined));
|
|
60
|
+
return {
|
|
61
|
+
id,
|
|
62
|
+
name: qr.deliveryplace,
|
|
63
|
+
country: 'hu', // MPL is Hungary-based
|
|
64
|
+
postalCode: qr.postCode,
|
|
65
|
+
city: qr.city,
|
|
66
|
+
address: qr.address,
|
|
67
|
+
latitude,
|
|
68
|
+
longitude,
|
|
69
|
+
dropoffAllowed,
|
|
70
|
+
pickupAllowed,
|
|
71
|
+
metadata: Object.keys(cleanedMetadata).length > 0 ? cleanedMetadata : undefined,
|
|
72
|
+
raw: entry,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Translates an MPL gateway error to a CarrierError with appropriate category and details
|
|
77
|
+
*
|
|
78
|
+
* Categorizes errors based on HTTP status and error details:
|
|
79
|
+
* - 400/404: Validation errors (Permanent - don't retry)
|
|
80
|
+
* - 401/403: Auth errors (Auth - don't retry, check credentials)
|
|
81
|
+
* - 429: Rate limit (RateLimit - retry with backoff)
|
|
82
|
+
* - 500/503: Server errors (Transient - retry)
|
|
83
|
+
*/
|
|
84
|
+
function translateMplError(error, httpStatus, headers) {
|
|
85
|
+
const faultString = error.fault?.faultstring || 'Unknown error';
|
|
86
|
+
const errorCode = error.fault?.detail?.errorcode || 'UNKNOWN';
|
|
87
|
+
let category;
|
|
88
|
+
const details = {
|
|
89
|
+
mplErrorCode: errorCode,
|
|
90
|
+
mplFaultString: faultString,
|
|
91
|
+
raw: error,
|
|
92
|
+
};
|
|
93
|
+
if (httpStatus === 400 || httpStatus === 404) {
|
|
94
|
+
category = httpStatus === 404 ? 'NotFound' : 'Validation';
|
|
95
|
+
}
|
|
96
|
+
else if (httpStatus === 401) {
|
|
97
|
+
category = 'Auth';
|
|
98
|
+
}
|
|
99
|
+
else if (httpStatus === 403) {
|
|
100
|
+
category = 'Auth';
|
|
101
|
+
}
|
|
102
|
+
else if (httpStatus === 429) {
|
|
103
|
+
category = 'RateLimit';
|
|
104
|
+
// Extract quota information from headers
|
|
105
|
+
const retryAfter = headers['retry-after'];
|
|
106
|
+
if (retryAfter) {
|
|
107
|
+
const retryAfterMs = parseInt(String(retryAfter)) * 1000;
|
|
108
|
+
details.retryAfterMs = retryAfterMs;
|
|
109
|
+
}
|
|
110
|
+
// Include quota headers if available
|
|
111
|
+
if (headers['x-quota-reset'])
|
|
112
|
+
details.quotaReset = headers['x-quota-reset'];
|
|
113
|
+
if (headers['x-quota-allowed'])
|
|
114
|
+
details.quotaAllowed = headers['x-quota-allowed'];
|
|
115
|
+
if (headers['x-quota-available'])
|
|
116
|
+
details.quotaAvailable = headers['x-quota-available'];
|
|
117
|
+
}
|
|
118
|
+
else if (httpStatus >= 500) {
|
|
119
|
+
category = 'Transient';
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
category = 'Transient'; // Default to transient for unknown statuses
|
|
123
|
+
}
|
|
124
|
+
return new CarrierError(`MPL API error: ${faultString} (${errorCode})`, category, details);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Fetch pickup points from MPL API
|
|
128
|
+
*
|
|
129
|
+
* Makes an authenticated request to the `/deliveryplace` endpoint with optional filters.
|
|
130
|
+
*
|
|
131
|
+
* Handles both success and error responses:
|
|
132
|
+
* - 200 OK: Returns normalized PickupPoint array
|
|
133
|
+
* - 4xx/5xx: Translates to CarrierError with appropriate retry category
|
|
134
|
+
*
|
|
135
|
+
* Note on logging: By default, raw responses are logged as summaries only
|
|
136
|
+
* to avoid polluting logs with hundreds of pickup point entries.
|
|
137
|
+
* To customize logging behavior, pass loggingOptions in the adapter context:
|
|
138
|
+
* {
|
|
139
|
+
* loggingOptions: {
|
|
140
|
+
* logRawResponse: true, // Log full response
|
|
141
|
+
* logRawResponse: false, // Skip logging raw entirely
|
|
142
|
+
* logRawResponse: 'summary', // Log only summary (default)
|
|
143
|
+
* maxArrayItems: 50, // Increase items shown in arrays
|
|
144
|
+
* silentOperations: [] // Enable logging for this operation
|
|
145
|
+
* }
|
|
146
|
+
* }
|
|
147
|
+
*
|
|
148
|
+
* @param req Request containing credentials and optional filters (postCode, city, servicePointType)
|
|
149
|
+
* @param ctx Adapter context with HTTP client and logger
|
|
150
|
+
* @param resolveBaseUrl Function to resolve API base URL (test vs. production)
|
|
151
|
+
* @returns FetchPickupPointsResponse with normalized pickup points
|
|
152
|
+
* @throws CarrierError on HTTP error or response parsing failure
|
|
153
|
+
*/
|
|
154
|
+
export async function fetchPickupPoints(req, ctx, resolveBaseUrl) {
|
|
155
|
+
if (!ctx.http) {
|
|
156
|
+
throw new CarrierError("HTTP client not provided in adapter context", "Permanent", { raw: "Missing ctx.http" });
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
// Validate request format and credentials
|
|
160
|
+
const validated = safeValidateFetchPickupPointsRequest(req);
|
|
161
|
+
if (!validated.success) {
|
|
162
|
+
throw new CarrierError(`Invalid request: ${validated.error.message}`, "Validation", { raw: serializeForLog(validated.error) });
|
|
163
|
+
}
|
|
164
|
+
// Normalize namespaced options into a flat internal shape for adapter logic.
|
|
165
|
+
const internalOptions = {
|
|
166
|
+
useTestApi: validated.data.options.useTestApi ?? false,
|
|
167
|
+
accountingCode: validated.data.options.mpl.accountingCode,
|
|
168
|
+
postCode: validated.data.options.mpl.postCode || "",
|
|
169
|
+
city: validated.data.options.mpl.city || "",
|
|
170
|
+
servicePointType: validated.data.options.mpl.servicePointType || [],
|
|
171
|
+
};
|
|
172
|
+
const useTestApi = internalOptions.useTestApi;
|
|
173
|
+
const postCode = internalOptions.postCode;
|
|
174
|
+
const city = internalOptions.city;
|
|
175
|
+
const servicePointType = internalOptions.servicePointType;
|
|
176
|
+
const filters = { postCode, city, servicePointType };
|
|
177
|
+
const credentialType = validated.data.credentials.authType;
|
|
178
|
+
const baseUrl = resolveBaseUrl(validated.data.options);
|
|
179
|
+
// Log the fetch attempt
|
|
180
|
+
safeLog(ctx.logger, 'debug', 'Fetching MPL pickup points with filters', createLogEntry({ useTestApi, filters, credentialType, endpoint: '/deliveryplace' }, null, ctx, ['fetchPickupPoints']), ctx, ['fetchPickupPoints']);
|
|
181
|
+
// Make the API request
|
|
182
|
+
const httpResponse = await ctx.http.post(`${baseUrl}/deliveryplace`, {
|
|
183
|
+
deliveryPlacesQuery: {
|
|
184
|
+
postCode,
|
|
185
|
+
city,
|
|
186
|
+
},
|
|
187
|
+
servicePointType,
|
|
188
|
+
}, {
|
|
189
|
+
headers: buildMPLHeaders(validated.data.credentials, internalOptions.accountingCode),
|
|
190
|
+
});
|
|
191
|
+
// Handle non-200 responses (gateway errors)
|
|
192
|
+
if (httpResponse.status !== 200) {
|
|
193
|
+
const body = httpResponse.body;
|
|
194
|
+
if (isGatewayError(body)) {
|
|
195
|
+
const translatedError = translateMplError(body, httpResponse.status, httpResponse.headers);
|
|
196
|
+
ctx.logger?.warn("MPL API error response", {
|
|
197
|
+
status: httpResponse.status,
|
|
198
|
+
error: translatedError.message,
|
|
199
|
+
category: translatedError.category,
|
|
200
|
+
});
|
|
201
|
+
throw translatedError;
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
// Unexpected response format for error status
|
|
205
|
+
throw new CarrierError(`MPL API returned status ${httpResponse.status} with unexpected response format`, "Transient", { raw: body });
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
// Validate 200 response structure - strict array check
|
|
209
|
+
const body = httpResponse.body;
|
|
210
|
+
if (!isSuccessResponse(body)) {
|
|
211
|
+
throw new CarrierError("Invalid response format from MPL API: expected array of pickup points", "Permanent", { raw: body });
|
|
212
|
+
}
|
|
213
|
+
// Body is now guaranteed to be an array of MPLPickupPointEntry
|
|
214
|
+
const apmData = body;
|
|
215
|
+
if (apmData.length === 0) {
|
|
216
|
+
safeLog(ctx.logger, 'debug', 'MPL API returned empty pickup points array', createLogEntry({ count: 0, filters }, null, ctx, ['fetchPickupPoints']), ctx, ['fetchPickupPoints']);
|
|
217
|
+
return {
|
|
218
|
+
points: [],
|
|
219
|
+
summary: {
|
|
220
|
+
totalCount: 0,
|
|
221
|
+
updatedAt: new Date().toISOString(),
|
|
222
|
+
},
|
|
223
|
+
rawCarrierResponse: apmData,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
safeLog(ctx.logger, 'debug', 'MPL API response received', createLogEntry({ count: apmData.length, filters }, apmData, ctx, ['fetchPickupPoints']), ctx, ['fetchPickupPoints']);
|
|
227
|
+
// Map each delivery place to canonical PickupPoint with per-entry validation
|
|
228
|
+
const points = apmData
|
|
229
|
+
.map((entry, index) => {
|
|
230
|
+
try {
|
|
231
|
+
// Validate entry structure - lenient approach like Foxpost
|
|
232
|
+
if (!entry || typeof entry !== 'object') {
|
|
233
|
+
ctx.logger?.warn("Skipping invalid delivery place entry: not an object", {
|
|
234
|
+
index,
|
|
235
|
+
entryType: typeof entry,
|
|
236
|
+
});
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
239
|
+
const typedEntry = entry;
|
|
240
|
+
// Validate that required fields are present
|
|
241
|
+
if (!typedEntry.deliveryplacesQueryResult || !typedEntry.servicePointType) {
|
|
242
|
+
ctx.logger?.warn("Skipping invalid delivery place entry: missing required fields", {
|
|
243
|
+
index,
|
|
244
|
+
hasQueryResult: !!typedEntry.deliveryplacesQueryResult,
|
|
245
|
+
hasServicePointType: !!typedEntry.servicePointType,
|
|
246
|
+
});
|
|
247
|
+
return null;
|
|
248
|
+
}
|
|
249
|
+
return mapMplDeliveryPlaceToPickupPoint(typedEntry);
|
|
250
|
+
}
|
|
251
|
+
catch (err) {
|
|
252
|
+
ctx.logger?.warn("Failed to map delivery place entry", {
|
|
253
|
+
index,
|
|
254
|
+
error: err instanceof Error ? err.message : String(err),
|
|
255
|
+
});
|
|
256
|
+
// Skip entries that can't be mapped
|
|
257
|
+
return null;
|
|
258
|
+
}
|
|
259
|
+
})
|
|
260
|
+
.filter((p) => p !== null);
|
|
261
|
+
safeLog(ctx.logger, 'info', 'Successfully fetched and mapped MPL pickup points', {
|
|
262
|
+
count: points.length,
|
|
263
|
+
succeeded: points.length,
|
|
264
|
+
failed: apmData.length - points.length,
|
|
265
|
+
filters,
|
|
266
|
+
}, ctx, ['fetchPickupPoints']);
|
|
267
|
+
return {
|
|
268
|
+
points,
|
|
269
|
+
summary: {
|
|
270
|
+
totalCount: points.length,
|
|
271
|
+
updatedAt: new Date().toISOString(),
|
|
272
|
+
},
|
|
273
|
+
rawCarrierResponse: apmData,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
catch (err) {
|
|
277
|
+
// Handle caught CarrierErrors
|
|
278
|
+
if (err instanceof CarrierError) {
|
|
279
|
+
throw err;
|
|
280
|
+
}
|
|
281
|
+
// Convert unknown errors to CarrierError
|
|
282
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
283
|
+
ctx.logger?.error("Failed to fetch MPL pickup points", {
|
|
284
|
+
error: errorMessage,
|
|
285
|
+
type: err instanceof Error ? err.constructor.name : typeof err,
|
|
286
|
+
});
|
|
287
|
+
// Determine error category based on error type
|
|
288
|
+
let category = 'Transient';
|
|
289
|
+
if (err instanceof Error && err.message.includes('Invalid response format')) {
|
|
290
|
+
category = 'Permanent';
|
|
291
|
+
}
|
|
292
|
+
throw new CarrierError(`Failed to fetch MPL pickup points: ${errorMessage}`, category, { raw: err });
|
|
293
|
+
}
|
|
294
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MPL Tracking Implementation
|
|
3
|
+
*
|
|
4
|
+
* Implements the TRACK capability using MPL's Pull-1 endpoints:
|
|
5
|
+
* - /v2/nyomkovetes/guest - Guest endpoint (public, no financial data)
|
|
6
|
+
* - /v2/nyomkovetes/registered - Registered endpoint (authenticated, includes financial data)
|
|
7
|
+
*
|
|
8
|
+
* Both endpoints return C-code tracking records that are normalized to canonical TrackingUpdate format.
|
|
9
|
+
*/
|
|
10
|
+
import type { AdapterContext, TrackingUpdate } from '@shopickup/core';
|
|
11
|
+
import { type TrackingRequestMPL, type Pull500StartRequest, type Pull500StartResponse, type Pull500CheckRequest, type Pull500CheckResponse } from '../validation.js';
|
|
12
|
+
import type { ResolveTrackingUrl } from '../utils/resolveBaseUrl.js';
|
|
13
|
+
/**
|
|
14
|
+
* Submit batch tracking request using Pull-500 endpoint
|
|
15
|
+
*
|
|
16
|
+
* Submits up to 500 tracking numbers in a single request.
|
|
17
|
+
* Returns trackingGUID for polling results.
|
|
18
|
+
* Results are processed asynchronously by MPL (takes 1+ minutes).
|
|
19
|
+
*
|
|
20
|
+
* @param request - Pull-500 request with tracking numbers
|
|
21
|
+
* @param ctx - Adapter context with HTTP client
|
|
22
|
+
* @param resolveTrackingUrl - Function to resolve tracking API base URL
|
|
23
|
+
* @returns trackingGUID for use with trackPull500Check()
|
|
24
|
+
* @throws CarrierError for validation, auth, or network errors
|
|
25
|
+
*/
|
|
26
|
+
export declare function trackPull500Start(request: Pull500StartRequest, ctx: AdapterContext, resolveTrackingUrl: ResolveTrackingUrl): Promise<Pull500StartResponse>;
|
|
27
|
+
/**
|
|
28
|
+
* Poll for Pull-500 batch tracking results
|
|
29
|
+
*
|
|
30
|
+
* Checks status of previously submitted batch request.
|
|
31
|
+
* Status progression: NEW -> INPROGRESS -> READY (or ERROR)
|
|
32
|
+
* When READY, response includes CSV report with tracking data.
|
|
33
|
+
*
|
|
34
|
+
* Recommendation: Wait 1+ minute before first poll, then poll every 30-60 seconds.
|
|
35
|
+
*
|
|
36
|
+
* @param request - Pull-500 check request with trackingGUID
|
|
37
|
+
* @param ctx - Adapter context with HTTP client
|
|
38
|
+
* @param resolveTrackingUrl - Function to resolve tracking API base URL
|
|
39
|
+
* @returns Pull-500 response with status and report (when ready)
|
|
40
|
+
* @throws CarrierError for validation, auth, or network errors
|
|
41
|
+
*/
|
|
42
|
+
export declare function trackPull500Check(request: Pull500CheckRequest, ctx: AdapterContext, resolveTrackingUrl: ResolveTrackingUrl): Promise<Pull500CheckResponse>;
|
|
43
|
+
/**
|
|
44
|
+
* Track parcels using the registered endpoint (with financial data)
|
|
45
|
+
*
|
|
46
|
+
* Extends the core track() function to use /v2/nyomkovetes/registered
|
|
47
|
+
* instead of /v2/nyomkovetes/guest. Includes financial data:
|
|
48
|
+
* - Weight (C5)
|
|
49
|
+
* - Service Code (C2)
|
|
50
|
+
* - Dimensions (C41, C42, C43)
|
|
51
|
+
* - Declared value (C58)
|
|
52
|
+
*
|
|
53
|
+
* Requires authentication and is intended for power users / internal use.
|
|
54
|
+
*
|
|
55
|
+
* @param request - Tracking request with tracking numbers
|
|
56
|
+
* @param ctx - Adapter context with HTTP client
|
|
57
|
+
* @param resolveTrackingUrl - Function to resolve tracking API base URL
|
|
58
|
+
* @returns Array of TrackingUpdate objects with financial data included
|
|
59
|
+
* @throws CarrierError for validation, auth, or network errors
|
|
60
|
+
*/
|
|
61
|
+
export declare function trackRegistered(request: TrackingRequestMPL, ctx: AdapterContext, resolveTrackingUrl: ResolveTrackingUrl): Promise<TrackingUpdate[]>;
|
|
62
|
+
/**
|
|
63
|
+
* Track one or more parcels using the Pull-1 endpoint
|
|
64
|
+
*
|
|
65
|
+
* @param request - Tracking request with tracking numbers and credentials
|
|
66
|
+
* @param ctx - Adapter context with HTTP client
|
|
67
|
+
* @param resolveTrackingUrl - Function to resolve tracking API base URL
|
|
68
|
+
* @returns Array of TrackingUpdate objects (one per tracking number)
|
|
69
|
+
* @throws CarrierError for various error scenarios
|
|
70
|
+
*/
|
|
71
|
+
export declare function track(request: TrackingRequestMPL, ctx: AdapterContext, resolveTrackingUrl: ResolveTrackingUrl): Promise<TrackingUpdate[]>;
|
|
72
|
+
//# sourceMappingURL=track.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"track.d.ts","sourceRoot":"","sources":["../../src/capabilities/track.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtE,OAAO,EAOL,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EAC1B,MAAM,kBAAkB,CAAC;AAK1B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAGrE;;;;;;;;;;;;GAYG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,mBAAmB,EAC5B,GAAG,EAAE,cAAc,EACnB,kBAAkB,EAAE,kBAAkB,GACrC,OAAO,CAAC,oBAAoB,CAAC,CAuF/B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,mBAAmB,EAC5B,GAAG,EAAE,cAAc,EACnB,kBAAkB,EAAE,kBAAkB,GACrC,OAAO,CAAC,oBAAoB,CAAC,CAkE/B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,kBAAkB,EAC3B,GAAG,EAAE,cAAc,EACnB,kBAAkB,EAAE,kBAAkB,GACrC,OAAO,CAAC,cAAc,EAAE,CAAC,CAU3B;AAED;;;;;;;;GAQG;AACH,wBAAsB,KAAK,CACzB,OAAO,EAAE,kBAAkB,EAC3B,GAAG,EAAE,cAAc,EACnB,kBAAkB,EAAE,kBAAkB,GACrC,OAAO,CAAC,cAAc,EAAE,CAAC,CAmH3B"}
|