@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,726 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Schemas for MPL adapter credentials
|
|
4
|
+
* Supports two auth types:
|
|
5
|
+
* 1. API Key authentication with apiKey and apiSecret
|
|
6
|
+
* 2. OAuth2 authentication with oAuth2Token
|
|
7
|
+
*/
|
|
8
|
+
const ApiKeyBranch = z.object({
|
|
9
|
+
authType: z.literal('apiKey'),
|
|
10
|
+
apiKey: z.string().min(1),
|
|
11
|
+
apiSecret: z.string().min(1),
|
|
12
|
+
accountingCode: z.string().optional(),
|
|
13
|
+
});
|
|
14
|
+
const OAuthBranch = z.object({
|
|
15
|
+
authType: z.literal('oauth2'),
|
|
16
|
+
oAuth2Token: z.string().min(1),
|
|
17
|
+
accountingCode: z.string().optional(),
|
|
18
|
+
});
|
|
19
|
+
/**
|
|
20
|
+
* Injects authType discriminant based on presence of oAuth2Token or apiKey.
|
|
21
|
+
* Allows callers to pass credentials without explicitly setting authType.
|
|
22
|
+
*/
|
|
23
|
+
export const MPLCredentialsSchema = z.preprocess((input) => {
|
|
24
|
+
if (input && typeof input === 'object') {
|
|
25
|
+
const anyInput = input;
|
|
26
|
+
// Prefer oauth2 if token is present
|
|
27
|
+
if (anyInput.oAuth2Token) {
|
|
28
|
+
return { ...anyInput, authType: 'oauth2' };
|
|
29
|
+
}
|
|
30
|
+
// Otherwise default to apiKey
|
|
31
|
+
if (anyInput.apiKey && anyInput.apiSecret) {
|
|
32
|
+
return { ...anyInput, authType: 'apiKey' };
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return input;
|
|
36
|
+
}, z.discriminatedUnion('authType', [ApiKeyBranch, OAuthBranch]));
|
|
37
|
+
/**
|
|
38
|
+
* Schema for servicePointTypes
|
|
39
|
+
*
|
|
40
|
+
* 'PM' - Postán Maradó (Post Office)
|
|
41
|
+
* 'HA' - Házhozszállítás (Home Delivery)
|
|
42
|
+
* 'RA' - Raklapos Kézbesítés (Pallet Delivery)
|
|
43
|
+
* 'PP' - PostaPont (Post Point)
|
|
44
|
+
* 'CS' - Csomagautomata (Parcel Locker)
|
|
45
|
+
*/
|
|
46
|
+
const ServicePointTypeSchema = z.enum(['PM', 'HA', 'RA', 'PP', 'CS']);
|
|
47
|
+
const PickupServicePointTypeSchema = z.enum(['PM', 'PP', 'CS']);
|
|
48
|
+
export const FetchPickupPointsMPLCarrierOptionsSchema = z.object({
|
|
49
|
+
accountingCode: z.string().min(1),
|
|
50
|
+
postCode: z.preprocess((val) => {
|
|
51
|
+
if (typeof val === 'string' && val.trim() === '')
|
|
52
|
+
return undefined;
|
|
53
|
+
return val;
|
|
54
|
+
}, z.string().length(4).optional()),
|
|
55
|
+
city: z.preprocess((val) => {
|
|
56
|
+
if (typeof val === 'string' && val.trim() === '')
|
|
57
|
+
return undefined;
|
|
58
|
+
return val;
|
|
59
|
+
}, z.string().optional()),
|
|
60
|
+
servicePointType: z.array(PickupServicePointTypeSchema).optional(),
|
|
61
|
+
});
|
|
62
|
+
export const FetchPickupPointsMPLOptionsSchema = z.object({
|
|
63
|
+
useTestApi: z.boolean().optional(),
|
|
64
|
+
mpl: FetchPickupPointsMPLCarrierOptionsSchema,
|
|
65
|
+
}).catchall(z.unknown());
|
|
66
|
+
/**
|
|
67
|
+
* Schema for fetchPickupPoints request
|
|
68
|
+
*
|
|
69
|
+
* Requires MPLCredentials
|
|
70
|
+
*
|
|
71
|
+
* Optional filters:
|
|
72
|
+
* - postCode: 4-character string
|
|
73
|
+
* - city: string
|
|
74
|
+
* - servicePointType: one of the defined ServicePointType values
|
|
75
|
+
*/
|
|
76
|
+
export const FetchPickupPointsMPLSchema = z.object({
|
|
77
|
+
credentials: MPLCredentialsSchema,
|
|
78
|
+
options: FetchPickupPointsMPLOptionsSchema,
|
|
79
|
+
});
|
|
80
|
+
/**
|
|
81
|
+
* Schema for exchangeAuthToken request
|
|
82
|
+
*
|
|
83
|
+
* Requires Basic auth credentials (apiKey + apiSecret)
|
|
84
|
+
* Optional: useTestApi flag to use sandbox OAuth endpoint
|
|
85
|
+
*/
|
|
86
|
+
export const ExchangeAuthTokenRequestSchema = z.object({
|
|
87
|
+
credentials: MPLCredentialsSchema.refine((cred) => cred.authType === 'apiKey', { message: "exchangeAuthToken requires apiKey credentials, not oauth2 token" }),
|
|
88
|
+
options: z.object({
|
|
89
|
+
useTestApi: z.boolean().optional(),
|
|
90
|
+
}).optional(),
|
|
91
|
+
});
|
|
92
|
+
/**
|
|
93
|
+
* Helper functions to validate MPL adapter requests
|
|
94
|
+
*/
|
|
95
|
+
/**
|
|
96
|
+
* Helper: validate credentials in one pass and get authType
|
|
97
|
+
*/
|
|
98
|
+
export function safeValidateCredentials(input) {
|
|
99
|
+
return MPLCredentialsSchema.safeParse(input);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Helper: validate full fetchPickupPoints request
|
|
103
|
+
*/
|
|
104
|
+
export function safeValidateFetchPickupPointsRequest(input) {
|
|
105
|
+
return FetchPickupPointsMPLSchema.safeParse(input);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Helper: validate exchangeAuthToken request
|
|
109
|
+
*/
|
|
110
|
+
export function safeValidateExchangeAuthTokenRequest(input) {
|
|
111
|
+
return ExchangeAuthTokenRequestSchema.safeParse(input);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Type guard: check if response is a gateway error
|
|
115
|
+
*/
|
|
116
|
+
export function isGatewayError(response) {
|
|
117
|
+
return (response !== null &&
|
|
118
|
+
typeof response === 'object' &&
|
|
119
|
+
'fault' in response &&
|
|
120
|
+
response.fault !== null &&
|
|
121
|
+
typeof response.fault === 'object' &&
|
|
122
|
+
'faultstring' in response.fault);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Type guard: check if response is a successful 200 response
|
|
126
|
+
*
|
|
127
|
+
* Strict validation: response MUST be an array of MPL pickup point entries.
|
|
128
|
+
* Follows Foxpost pattern for consistency across adapters.
|
|
129
|
+
*/
|
|
130
|
+
export function isSuccessResponse(response) {
|
|
131
|
+
return Array.isArray(response);
|
|
132
|
+
}
|
|
133
|
+
// ===== SHIPMENT TYPES (CREATE_PARCEL capability) =====
|
|
134
|
+
/**
|
|
135
|
+
* Basic service codes from OpenAPI
|
|
136
|
+
* Represents available postal services
|
|
137
|
+
*/
|
|
138
|
+
export const BasicServiceCodeSchema = z.enum([
|
|
139
|
+
'A_175_UZL', // Belföld alapszolgáltatás
|
|
140
|
+
'A_177_MPC', // MPC - nagyobb térfogat
|
|
141
|
+
'A_176_NET', // Nemzetközi express
|
|
142
|
+
'A_176_NKP', // Nemzetközi kiegészítő
|
|
143
|
+
'A_122_ECS', // Economy közép
|
|
144
|
+
'A_121_CSG', // Csomag
|
|
145
|
+
'A_13_EMS', // Express Mail Service (International)
|
|
146
|
+
'A_123_EUP', // Európa
|
|
147
|
+
'A_123_HAR', // Közlekedési + Ajánlott Register
|
|
148
|
+
'A_123_HAI', // Közlekedési + Ajánlott Ajánlott
|
|
149
|
+
'A_125_HAR', // Csere-csomag HAR
|
|
150
|
+
'A_125_HAI', // Csere-csomag HAI
|
|
151
|
+
]);
|
|
152
|
+
/**
|
|
153
|
+
* Delivery modes from OpenAPI
|
|
154
|
+
* HA - Házhozszállítás (Home Delivery)
|
|
155
|
+
* RA - Raklapos Kézbesítés (Pallet Delivery)
|
|
156
|
+
* PP - PostaPont (Post Point)
|
|
157
|
+
* CS - Csomagautomata (Parcel Locker)
|
|
158
|
+
* PM - Postán Maradó (Post Office)
|
|
159
|
+
*/
|
|
160
|
+
export const DeliveryModeSchema = z.enum(['HA', 'RA', 'PP', 'CS', 'PM']);
|
|
161
|
+
/**
|
|
162
|
+
* Label type/format for address labels
|
|
163
|
+
*/
|
|
164
|
+
export const LabelTypeSchema = z.enum([
|
|
165
|
+
'A4', 'A5', 'A5inA4', 'A5E', 'A5E_EXTRA', 'A5E_STAND', 'A6', 'A6inA4', 'A4ONE'
|
|
166
|
+
]);
|
|
167
|
+
/**
|
|
168
|
+
* Label file format
|
|
169
|
+
*/
|
|
170
|
+
export const LabelFormatSchema = z.enum(['PDF', 'ZPL']);
|
|
171
|
+
/**
|
|
172
|
+
* Package size enum
|
|
173
|
+
*/
|
|
174
|
+
export const PackageSizeSchema = z.enum(['S', 'M', 'L', 'PRINT', 'PACK']);
|
|
175
|
+
/**
|
|
176
|
+
* Extra services codes (subset relevant for CREATE_SHIPMENT)
|
|
177
|
+
* These are additional paid services that can be added to shipments
|
|
178
|
+
*/
|
|
179
|
+
export const ExtraServiceCodeSchema = z.enum([
|
|
180
|
+
'K_ENY', // Értéknyilvánítás (Value insurance)
|
|
181
|
+
'K_TER', // Terjedelmes kezelés (Bulky handling)
|
|
182
|
+
'K_UVT', // Árufizetés (Cash on delivery)
|
|
183
|
+
'K_TOR', // Törvényi
|
|
184
|
+
'K_ORZ', // Óvadék
|
|
185
|
+
'K_IDO', // Időablak (Time window)
|
|
186
|
+
'K_RLC', // Ragasz logikai csomag
|
|
187
|
+
'K_TEV', // Tevékenység
|
|
188
|
+
'K_CSE', // Csere-csomag alapcsomag
|
|
189
|
+
'K_CSA', // Csere-csomag inverz csomag
|
|
190
|
+
'K_IDA', // Időablak (delivery time window)
|
|
191
|
+
'K_FNK', // Fixed day delivery
|
|
192
|
+
]);
|
|
193
|
+
/**
|
|
194
|
+
* Delivery time preference (for time window delivery)
|
|
195
|
+
*/
|
|
196
|
+
export const DeliveryTimeSchema = z.enum(['earlyMorning', 'morning', 'afternoon', 'evening']);
|
|
197
|
+
/**
|
|
198
|
+
* UnitValue - weight/size with unit
|
|
199
|
+
*/
|
|
200
|
+
export const UnitValueSchema = z.object({
|
|
201
|
+
value: z.number(),
|
|
202
|
+
unit: z.enum(['kg', 'g']).optional(),
|
|
203
|
+
});
|
|
204
|
+
/**
|
|
205
|
+
* Contact information (name, organization, phone, email)
|
|
206
|
+
*/
|
|
207
|
+
export const ContactSchema = z.object({
|
|
208
|
+
name: z.string().max(120).min(1),
|
|
209
|
+
organization: z.string().max(120).optional(),
|
|
210
|
+
phone: z.string().max(20).optional(),
|
|
211
|
+
email: z.string().max(100).optional(),
|
|
212
|
+
});
|
|
213
|
+
/**
|
|
214
|
+
* Address information
|
|
215
|
+
*/
|
|
216
|
+
export const AddressSchema = z.object({
|
|
217
|
+
postCode: z.string().length(4),
|
|
218
|
+
city: z.string().max(35).min(2),
|
|
219
|
+
address: z.string().max(60).min(3),
|
|
220
|
+
});
|
|
221
|
+
/**
|
|
222
|
+
* Delivery address (same as regular address but includes optional parcelPickupSite)
|
|
223
|
+
*/
|
|
224
|
+
export const DeliveryAddressSchema = AddressSchema.extend({
|
|
225
|
+
parcelPickupSite: z.string().max(100).optional(),
|
|
226
|
+
countryCode: z.string().max(3).optional(),
|
|
227
|
+
});
|
|
228
|
+
/**
|
|
229
|
+
* Recipient information
|
|
230
|
+
*/
|
|
231
|
+
export const RecipientSchema = z.object({
|
|
232
|
+
contact: ContactSchema,
|
|
233
|
+
address: DeliveryAddressSchema,
|
|
234
|
+
luaCode: z.string().max(20).optional(),
|
|
235
|
+
disabled: z.boolean().optional(),
|
|
236
|
+
});
|
|
237
|
+
/**
|
|
238
|
+
* Sender information
|
|
239
|
+
*/
|
|
240
|
+
export const SenderSchema = z.object({
|
|
241
|
+
agreement: z.string().length(8),
|
|
242
|
+
accountNo: z.string().min(16).max(24).optional(),
|
|
243
|
+
contact: ContactSchema,
|
|
244
|
+
address: AddressSchema,
|
|
245
|
+
parcelTerminal: z.boolean().optional(),
|
|
246
|
+
});
|
|
247
|
+
/**
|
|
248
|
+
* Service configuration for a shipment item
|
|
249
|
+
*/
|
|
250
|
+
export const ServiceSchema = z.object({
|
|
251
|
+
basic: BasicServiceCodeSchema,
|
|
252
|
+
deliveryMode: DeliveryModeSchema,
|
|
253
|
+
extra: z.array(ExtraServiceCodeSchema).optional(),
|
|
254
|
+
cod: z.number().optional(), // Cash on delivery amount in HUF
|
|
255
|
+
value: z.number().int().optional(), // Value insurance amount in HUF
|
|
256
|
+
codCurrency: z.string().max(3).optional(), // For international
|
|
257
|
+
customsValue: z.number().optional(), // For international
|
|
258
|
+
});
|
|
259
|
+
/**
|
|
260
|
+
* Item/Parcel information
|
|
261
|
+
*/
|
|
262
|
+
export const ItemSchema = z.object({
|
|
263
|
+
customData1: z.string().max(40).optional(),
|
|
264
|
+
customData2: z.string().max(40).optional(),
|
|
265
|
+
weight: UnitValueSchema.optional(),
|
|
266
|
+
size: PackageSizeSchema.optional(),
|
|
267
|
+
services: ServiceSchema,
|
|
268
|
+
senderParcelPickupSite: z.string().max(100).optional(),
|
|
269
|
+
});
|
|
270
|
+
/**
|
|
271
|
+
* Invoice information (optional, for billing)
|
|
272
|
+
*/
|
|
273
|
+
export const InvoiceSchema = z.object({
|
|
274
|
+
name: z.string().max(150).min(1),
|
|
275
|
+
postCode: z.string().length(4),
|
|
276
|
+
city: z.string().max(35).min(2),
|
|
277
|
+
address: z.string().max(60).min(3),
|
|
278
|
+
vatIdentificationNumber: z.string().max(15).min(1),
|
|
279
|
+
});
|
|
280
|
+
/**
|
|
281
|
+
* Shipment creation request (maps to OpenAPI ShipmentCreateRequest)
|
|
282
|
+
* This is ONE shipment that can contain multiple items (parcels)
|
|
283
|
+
*/
|
|
284
|
+
export const ShipmentCreateRequestSchema = z.object({
|
|
285
|
+
developer: z.string().max(40).min(1),
|
|
286
|
+
sender: SenderSchema,
|
|
287
|
+
recipient: RecipientSchema,
|
|
288
|
+
webshopId: z.string().max(100).min(1),
|
|
289
|
+
orderId: z.string().max(50).optional(),
|
|
290
|
+
shipmentDate: z.string().optional(), // date format
|
|
291
|
+
labelType: LabelTypeSchema.optional(),
|
|
292
|
+
labelFormat: LabelFormatSchema.optional(),
|
|
293
|
+
tag: z.string().max(50).optional(),
|
|
294
|
+
groupTogether: z.boolean().optional(),
|
|
295
|
+
deliveryTime: DeliveryTimeSchema.optional(),
|
|
296
|
+
deliveryDate: z.string().optional(), // date format
|
|
297
|
+
item: z.array(ItemSchema).optional(),
|
|
298
|
+
paymentMode: z.enum(['UV_AT', 'UV_KP']).optional(),
|
|
299
|
+
packageRetention: z.number().int().optional(),
|
|
300
|
+
printRecipientData: z.enum(['PRINTALL', 'PRINTPHONENUMBER', 'PRINTEMAIL', 'PRINTNOTHING']).optional(),
|
|
301
|
+
});
|
|
302
|
+
/**
|
|
303
|
+
* Replacement label information in response
|
|
304
|
+
*/
|
|
305
|
+
export const ReplacementLabelSchema = z.object({
|
|
306
|
+
trackingNumber: z.string().optional(),
|
|
307
|
+
label: z.string().optional(), // base64 encoded PDF
|
|
308
|
+
});
|
|
309
|
+
/**
|
|
310
|
+
* Error descriptor from MPL API
|
|
311
|
+
*/
|
|
312
|
+
export const ErrorDescriptorSchema = z.object({
|
|
313
|
+
code: z.string().optional(),
|
|
314
|
+
parameter: z.string().optional(),
|
|
315
|
+
text: z.string().optional(),
|
|
316
|
+
text_eng: z.string().optional(),
|
|
317
|
+
});
|
|
318
|
+
/**
|
|
319
|
+
* Warning descriptor from MPL API
|
|
320
|
+
*/
|
|
321
|
+
export const WarningDescriptorSchema = z.object({
|
|
322
|
+
code: z.string().optional(),
|
|
323
|
+
parameter: z.string().optional(),
|
|
324
|
+
text: z.string().optional(),
|
|
325
|
+
text_eng: z.string().optional(),
|
|
326
|
+
});
|
|
327
|
+
/**
|
|
328
|
+
* Shipment creation result (maps to OpenAPI ShipmentCreateResult)
|
|
329
|
+
* Response for ONE shipment
|
|
330
|
+
*/
|
|
331
|
+
export const ShipmentCreateResultSchema = z.object({
|
|
332
|
+
webshopId: z.string().optional(),
|
|
333
|
+
trackingNumber: z.string().optional(),
|
|
334
|
+
replacementTrackingNumber: z.string().optional(),
|
|
335
|
+
replacementLabels: z.array(ReplacementLabelSchema).optional(),
|
|
336
|
+
packageTrackingNumbers: z.array(z.string()).optional(),
|
|
337
|
+
dispatchId: z.number().int().optional(),
|
|
338
|
+
suggestedRecipientPostCode: z.string().optional(),
|
|
339
|
+
suggestedRecipientCity: z.string().optional(),
|
|
340
|
+
suggestedRecipientAddress: z.string().optional(),
|
|
341
|
+
label: z.string().optional(), // base64 encoded PDF
|
|
342
|
+
errors: z.array(ErrorDescriptorSchema).optional(),
|
|
343
|
+
warnings: z.array(WarningDescriptorSchema).optional(),
|
|
344
|
+
});
|
|
345
|
+
/**
|
|
346
|
+
* Helper: validate shipment creation request
|
|
347
|
+
*/
|
|
348
|
+
export function safeValidateShipmentCreateRequest(input) {
|
|
349
|
+
return ShipmentCreateRequestSchema.safeParse(input);
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Helper: validate shipment creation result
|
|
353
|
+
*/
|
|
354
|
+
export function safeValidateShipmentCreateResult(input) {
|
|
355
|
+
return ShipmentCreateResultSchema.safeParse(input);
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* MPL-specific request options for CREATE_PARCELS.
|
|
359
|
+
*
|
|
360
|
+
* Cross-cutting fields stay at options root (e.g. useTestApi),
|
|
361
|
+
* while carrier-specific fields are namespaced under `options.mpl`.
|
|
362
|
+
* `accountingCode` is required for MPL.
|
|
363
|
+
*/
|
|
364
|
+
export const CreateParcelsMPLCarrierOptionsSchema = z.object({
|
|
365
|
+
accountingCode: z.string().min(1),
|
|
366
|
+
agreementCode: z.string().min(1),
|
|
367
|
+
bankAccountNumber: z.string().min(1),
|
|
368
|
+
labelType: LabelTypeSchema.optional(),
|
|
369
|
+
});
|
|
370
|
+
export const CreateParcelsMPLOptionsSchema = z.object({
|
|
371
|
+
useTestApi: z.boolean().optional(),
|
|
372
|
+
mpl: CreateParcelsMPLCarrierOptionsSchema,
|
|
373
|
+
}).catchall(z.unknown());
|
|
374
|
+
/**
|
|
375
|
+
* Full CREATE_PARCELS request validator for MPL.
|
|
376
|
+
*
|
|
377
|
+
* This validates request envelope + credentials first, then capability-specific
|
|
378
|
+
* shipment payload validation continues in the mapper/Shipment schemas.
|
|
379
|
+
*/
|
|
380
|
+
export const CreateParcelsMPLRequestSchema = z.object({
|
|
381
|
+
parcels: z.array(z.custom((value) => value !== null && typeof value === 'object', { message: 'Each parcel must be an object' })),
|
|
382
|
+
credentials: MPLCredentialsSchema,
|
|
383
|
+
options: CreateParcelsMPLOptionsSchema,
|
|
384
|
+
});
|
|
385
|
+
/**
|
|
386
|
+
* Helper: validate full createParcels request
|
|
387
|
+
*/
|
|
388
|
+
export function safeValidateCreateParcelsRequest(input) {
|
|
389
|
+
return CreateParcelsMPLRequestSchema.safeParse(input);
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Full CREATE_PARCEL request validator for MPL.
|
|
393
|
+
*
|
|
394
|
+
* Mirrors CREATE_PARCELS requirements for a single parcel envelope.
|
|
395
|
+
*/
|
|
396
|
+
export const CreateParcelMPLRequestSchema = z.object({
|
|
397
|
+
parcel: z.custom((value) => value !== null && typeof value === 'object', { message: 'parcel must be an object' }),
|
|
398
|
+
credentials: MPLCredentialsSchema,
|
|
399
|
+
options: CreateParcelsMPLOptionsSchema,
|
|
400
|
+
});
|
|
401
|
+
/**
|
|
402
|
+
* Helper: validate full createParcel request
|
|
403
|
+
*/
|
|
404
|
+
export function safeValidateCreateParcelRequest(input) {
|
|
405
|
+
return CreateParcelMPLRequestSchema.safeParse(input);
|
|
406
|
+
}
|
|
407
|
+
// ===== LABEL TYPES (CREATE_LABEL capability) =====
|
|
408
|
+
/**
|
|
409
|
+
* Label order type from OpenAPI
|
|
410
|
+
* SENDING - Order by sending sequence
|
|
411
|
+
* IDENTIFIER - Order by tracking number identifier
|
|
412
|
+
*/
|
|
413
|
+
export const LabelOrderBySchema = z.enum(['SENDING', 'IDENTIFIER']);
|
|
414
|
+
/**
|
|
415
|
+
* Single label query result from MPL API
|
|
416
|
+
* Response for each tracking number requested
|
|
417
|
+
*/
|
|
418
|
+
export const LabelQueryResultSchema = z.object({
|
|
419
|
+
trackingNumber: z.string().optional(),
|
|
420
|
+
label: z.string().optional(), // base64 encoded PDF/ZPL
|
|
421
|
+
errors: z.array(ErrorDescriptorSchema).optional(),
|
|
422
|
+
warnings: z.array(WarningDescriptorSchema).optional(),
|
|
423
|
+
});
|
|
424
|
+
/**
|
|
425
|
+
* Request for creating labels via GET /shipments/label
|
|
426
|
+
*
|
|
427
|
+
* Pattern: cross-cutting options (e.g. `size`) live at `options.size` and
|
|
428
|
+
* MPL-specific knobs (accountingCode, labelFormat, singleFile, orderBy)
|
|
429
|
+
* live under `options.mpl`.
|
|
430
|
+
*/
|
|
431
|
+
export const CreateLabelsMPLCarrierOptionsSchema = z.object({
|
|
432
|
+
accountingCode: z.string().min(1),
|
|
433
|
+
labelFormat: LabelFormatSchema.optional(),
|
|
434
|
+
singleFile: z.boolean().optional(),
|
|
435
|
+
orderBy: LabelOrderBySchema.optional(),
|
|
436
|
+
// adapter may accept an explicit labelType override under mpl,
|
|
437
|
+
// but integrators should prefer `options.size` (canonical) when present
|
|
438
|
+
labelType: LabelTypeSchema.optional(),
|
|
439
|
+
}).catchall(z.unknown());
|
|
440
|
+
export const CreateLabelsMPLOptionsSchema = z.object({
|
|
441
|
+
useTestApi: z.boolean(),
|
|
442
|
+
// canonical cross-cutting size field (maps to MPL labelType)
|
|
443
|
+
size: LabelTypeSchema.optional(),
|
|
444
|
+
mpl: CreateLabelsMPLCarrierOptionsSchema,
|
|
445
|
+
}).catchall(z.unknown());
|
|
446
|
+
export const CreateLabelsMPLRequestSchema = z.object({
|
|
447
|
+
parcelCarrierIds: z.array(z.string().min(1)).min(1),
|
|
448
|
+
credentials: MPLCredentialsSchema,
|
|
449
|
+
options: CreateLabelsMPLOptionsSchema,
|
|
450
|
+
});
|
|
451
|
+
/**
|
|
452
|
+
* Helper: validate label creation request
|
|
453
|
+
*/
|
|
454
|
+
export function safeValidateCreateLabelsRequest(input) {
|
|
455
|
+
return CreateLabelsMPLRequestSchema.safeParse(input);
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
458
|
+
* Single-label request schema (carrier-specific)
|
|
459
|
+
* Mirrors the batch request but for a single `parcelCarrierId`.
|
|
460
|
+
*/
|
|
461
|
+
export const CreateLabelMPLRequestSchema = z.object({
|
|
462
|
+
parcelCarrierId: z.string().min(1),
|
|
463
|
+
credentials: MPLCredentialsSchema,
|
|
464
|
+
options: CreateLabelsMPLOptionsSchema,
|
|
465
|
+
});
|
|
466
|
+
export function safeValidateCreateLabelRequest(input) {
|
|
467
|
+
return CreateLabelMPLRequestSchema.safeParse(input);
|
|
468
|
+
}
|
|
469
|
+
// ===== CLOSE SHIPMENTS TYPES (CLOSE_SHIPMENT capability) =====
|
|
470
|
+
/**
|
|
471
|
+
* ShipmentCloseRequest mirrors OpenAPI components.schemas.ShipmentCloseRequest
|
|
472
|
+
* Only includes fields we need for building the MPL /shipments/close request.
|
|
473
|
+
*/
|
|
474
|
+
export const ShipmentCloseRequestSchema = z.object({
|
|
475
|
+
fromDate: z.string().optional(),
|
|
476
|
+
toDate: z.string().optional(),
|
|
477
|
+
trackingNumbers: z.array(z.string().min(1)).optional(),
|
|
478
|
+
checkList: z.boolean().optional(),
|
|
479
|
+
checkListWithPrice: z.boolean().optional(),
|
|
480
|
+
tag: z.string().max(50).optional(),
|
|
481
|
+
requestId: z.string().max(100).optional(),
|
|
482
|
+
summaryList: z.boolean().optional(),
|
|
483
|
+
singleFile: z.boolean().optional(),
|
|
484
|
+
});
|
|
485
|
+
/**
|
|
486
|
+
* Full CLOSE_SHIPMENTS request envelope for MPL adapter
|
|
487
|
+
*/
|
|
488
|
+
export const CloseShipmentsMPLRequestSchema = z.object({
|
|
489
|
+
close: ShipmentCloseRequestSchema.optional(),
|
|
490
|
+
trackingNumbers: z.array(z.string().min(1)).optional(),
|
|
491
|
+
credentials: MPLCredentialsSchema,
|
|
492
|
+
options: z.object({
|
|
493
|
+
useTestApi: z.boolean().optional(),
|
|
494
|
+
mpl: z.object({ accountingCode: z.string().min(1) }).optional(),
|
|
495
|
+
}).optional(),
|
|
496
|
+
}).catchall(z.unknown());
|
|
497
|
+
export function safeValidateCloseShipmentsRequest(input) {
|
|
498
|
+
return CloseShipmentsMPLRequestSchema.safeParse(input);
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Schema for GET_SHIPMENT_DETAILS request
|
|
502
|
+
* Retrieves shipment metadata by tracking number
|
|
503
|
+
*/
|
|
504
|
+
export const GetShipmentDetailsRequestSchema = z.object({
|
|
505
|
+
trackingNumber: z.string().min(1, 'trackingNumber is required'),
|
|
506
|
+
credentials: MPLCredentialsSchema,
|
|
507
|
+
options: z.object({
|
|
508
|
+
useTestApi: z.boolean().optional(),
|
|
509
|
+
}).optional(),
|
|
510
|
+
});
|
|
511
|
+
/**
|
|
512
|
+
* Helper: validate get shipment details request
|
|
513
|
+
*/
|
|
514
|
+
export function safeValidateGetShipmentDetailsRequest(input) {
|
|
515
|
+
return GetShipmentDetailsRequestSchema.safeParse(input);
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* Helper: validate shipment query response
|
|
519
|
+
*/
|
|
520
|
+
export function safeValidateShipmentQueryResponse(input) {
|
|
521
|
+
return MPLShipmentQueryResultSchema.safeParse(input);
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
524
|
+
* Schema for Shipment query response
|
|
525
|
+
* Response from GET /shipments/{trackingNumber}
|
|
526
|
+
*/
|
|
527
|
+
export const ShipmentStateSchema = z.object({
|
|
528
|
+
trackingNumber: z.string().optional(),
|
|
529
|
+
orderId: z.string().optional(),
|
|
530
|
+
tag: z.string().optional(),
|
|
531
|
+
shipmentDate: z.string().optional(),
|
|
532
|
+
packageRetention: z.number().optional(),
|
|
533
|
+
paymentMode: z.enum(['UV_AT', 'UV_KP']).optional(),
|
|
534
|
+
sender: z.object({
|
|
535
|
+
name: z.string().optional(),
|
|
536
|
+
street: z.string().optional(),
|
|
537
|
+
city: z.string().optional(),
|
|
538
|
+
postalCode: z.string().optional(),
|
|
539
|
+
country: z.string().optional(),
|
|
540
|
+
phone: z.string().optional(),
|
|
541
|
+
}).optional(),
|
|
542
|
+
recipient: z.object({
|
|
543
|
+
name: z.string().optional(),
|
|
544
|
+
street: z.string().optional(),
|
|
545
|
+
city: z.string().optional(),
|
|
546
|
+
postalCode: z.string().optional(),
|
|
547
|
+
country: z.string().optional(),
|
|
548
|
+
phone: z.string().optional(),
|
|
549
|
+
}).optional(),
|
|
550
|
+
items: z.array(z.object({
|
|
551
|
+
id: z.string().optional(),
|
|
552
|
+
weight: z.number().optional(),
|
|
553
|
+
}).passthrough()).optional(),
|
|
554
|
+
});
|
|
555
|
+
/**
|
|
556
|
+
* Schema for the response from GET /shipments/{trackingNumber}
|
|
557
|
+
*/
|
|
558
|
+
export const MPLShipmentQueryResultSchema = z.object({
|
|
559
|
+
shipment: ShipmentStateSchema.optional().nullable(),
|
|
560
|
+
errors: z.array(ErrorDescriptorSchema).optional().nullable(),
|
|
561
|
+
metadata: z.any().optional(),
|
|
562
|
+
});
|
|
563
|
+
// ===== TRACKING TYPES (TRACK capability) =====
|
|
564
|
+
/**
|
|
565
|
+
* Schema for tracking request (Pull-1 endpoint)
|
|
566
|
+
* Retrieves tracking/trace information for one or more parcels
|
|
567
|
+
*
|
|
568
|
+
* Required:
|
|
569
|
+
* - trackingNumbers: array of one or more tracking numbers
|
|
570
|
+
* - credentials: MPLCredentials
|
|
571
|
+
*
|
|
572
|
+
* Optional:
|
|
573
|
+
* - state: 'last' (latest event only, faster) or 'all' (complete history)
|
|
574
|
+
* - useRegisteredEndpoint: false (Guest) or true (Registered with financial data)
|
|
575
|
+
* - useTestApi: use sandbox API instead of production
|
|
576
|
+
*/
|
|
577
|
+
export const TrackingRequestMPLSchema = z.object({
|
|
578
|
+
trackingNumbers: z.array(z.string().min(1)).min(1, 'At least one tracking number is required'),
|
|
579
|
+
credentials: MPLCredentialsSchema,
|
|
580
|
+
state: z.enum(['last', 'all']).optional().default('last'),
|
|
581
|
+
useRegisteredEndpoint: z.boolean().optional().default(false),
|
|
582
|
+
options: z.object({
|
|
583
|
+
useTestApi: z.boolean().optional(),
|
|
584
|
+
}).optional(),
|
|
585
|
+
});
|
|
586
|
+
/**
|
|
587
|
+
* Helper: validate tracking request
|
|
588
|
+
*/
|
|
589
|
+
export function safeValidateTrackingRequest(input) {
|
|
590
|
+
return TrackingRequestMPLSchema.safeParse(input);
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* MPL C-Code Tracking Record from Pull-1 API response
|
|
594
|
+
*
|
|
595
|
+
* Contains C0-C63 fields representing different tracking data.
|
|
596
|
+
* Guest endpoint excludes financial data (C2, C5, C41, C42, C58)
|
|
597
|
+
* Registered endpoint includes all fields
|
|
598
|
+
*/
|
|
599
|
+
export const MPLTrackingRecordSchema = z.object({
|
|
600
|
+
c0: z.string().optional(), // System ID
|
|
601
|
+
c1: z.string(), // Consignment ID (Tracking number) - REQUIRED
|
|
602
|
+
c2: z.string().optional(), // Service Code (Registered only)
|
|
603
|
+
c4: z.string().optional(), // Delivery Mode
|
|
604
|
+
c5: z.string().optional(), // Weight (Registered only)
|
|
605
|
+
c6: z.string().optional(), // Service Description
|
|
606
|
+
c8: z.string().optional(), // Location
|
|
607
|
+
c9: z.string().optional(), // Last Event Status (CRITICAL)
|
|
608
|
+
c10: z.string().optional(), // Timestamp
|
|
609
|
+
c11: z.string().optional(), // Location Details
|
|
610
|
+
c12: z.string().optional(), // Event Description
|
|
611
|
+
c13: z.string().optional(), // Event Notes
|
|
612
|
+
c38: z.string().optional(), // Service Name
|
|
613
|
+
c39: z.string().optional(), // Service Details
|
|
614
|
+
c41: z.string().optional(), // Size Length (Registered only)
|
|
615
|
+
c42: z.string().optional(), // Size Width (Registered only)
|
|
616
|
+
c43: z.string().optional(), // Size Height
|
|
617
|
+
c49: z.string().optional(), // Destination
|
|
618
|
+
c53: z.string().optional(), // Signature/Receiver
|
|
619
|
+
c55: z.string().optional(), // Insurance flag
|
|
620
|
+
c56: z.string().optional(), // COD flag
|
|
621
|
+
c57: z.string().optional(), // Signature required flag
|
|
622
|
+
c59: z.string().optional(), // Additional flag 1
|
|
623
|
+
c60: z.string().optional(), // Additional flag 2
|
|
624
|
+
c61: z.string().optional(), // Additional flag 3
|
|
625
|
+
c63: z.string().optional(), // Custom/Reference data
|
|
626
|
+
}).passthrough(); // Allow additional fields
|
|
627
|
+
/**
|
|
628
|
+
* Schema for tracking response from Pull-1 API
|
|
629
|
+
* Returns array of tracking records (one per tracking number) or error
|
|
630
|
+
*/
|
|
631
|
+
export const TrackingResponseMPLSchema = z.object({
|
|
632
|
+
trackAndTrace: z.array(MPLTrackingRecordSchema).optional(),
|
|
633
|
+
}).passthrough();
|
|
634
|
+
/**
|
|
635
|
+
* Helper: validate tracking response
|
|
636
|
+
*/
|
|
637
|
+
export function safeValidateTrackingResponse(input) {
|
|
638
|
+
return TrackingResponseMPLSchema.safeParse(input);
|
|
639
|
+
}
|
|
640
|
+
// ===== PULL-500 BATCH TRACKING TYPES =====
|
|
641
|
+
/**
|
|
642
|
+
* Schema for Pull-500 start request (batch tracking submission)
|
|
643
|
+
*
|
|
644
|
+
* Required:
|
|
645
|
+
* - trackingNumbers: array of 1-500 tracking numbers
|
|
646
|
+
* - credentials: MPLCredentials
|
|
647
|
+
*
|
|
648
|
+
* Optional:
|
|
649
|
+
* - language: 'hu' (Hungarian, default) or 'en' (English)
|
|
650
|
+
* - useTestApi: use sandbox API
|
|
651
|
+
*/
|
|
652
|
+
export const Pull500StartRequestSchema = z.object({
|
|
653
|
+
trackingNumbers: z.array(z.string().min(1)).min(1).max(500, 'Maximum 500 tracking numbers allowed'),
|
|
654
|
+
credentials: MPLCredentialsSchema,
|
|
655
|
+
language: z.enum(['hu', 'en']).default('hu').optional(),
|
|
656
|
+
options: z.object({
|
|
657
|
+
useTestApi: z.boolean().optional(),
|
|
658
|
+
}).optional(),
|
|
659
|
+
});
|
|
660
|
+
/**
|
|
661
|
+
* Helper: validate Pull-500 start request
|
|
662
|
+
*/
|
|
663
|
+
export function safeValidatePull500StartRequest(input) {
|
|
664
|
+
return Pull500StartRequestSchema.safeParse(input);
|
|
665
|
+
}
|
|
666
|
+
/**
|
|
667
|
+
* Schema for Pull-500 start response
|
|
668
|
+
* Returns trackingGUID for polling, plus any submission errors
|
|
669
|
+
*/
|
|
670
|
+
export const Pull500StartResponseSchema = z.object({
|
|
671
|
+
trackingGUID: z.string().min(1),
|
|
672
|
+
errors: z.array(ErrorDescriptorSchema).optional(),
|
|
673
|
+
}).passthrough();
|
|
674
|
+
/**
|
|
675
|
+
* Helper: validate Pull-500 start response
|
|
676
|
+
*/
|
|
677
|
+
export function safeValidatePull500StartResponse(input) {
|
|
678
|
+
return Pull500StartResponseSchema.safeParse(input);
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* Schema for Pull-500 check request (poll for results)
|
|
682
|
+
*
|
|
683
|
+
* Required:
|
|
684
|
+
* - trackingGUID: UUID returned from start request
|
|
685
|
+
* - credentials: MPLCredentials
|
|
686
|
+
*/
|
|
687
|
+
export const Pull500CheckRequestSchema = z.object({
|
|
688
|
+
trackingGUID: z.string().min(1, 'trackingGUID is required'),
|
|
689
|
+
credentials: MPLCredentialsSchema,
|
|
690
|
+
options: z.object({
|
|
691
|
+
useTestApi: z.boolean().optional(),
|
|
692
|
+
}).optional(),
|
|
693
|
+
});
|
|
694
|
+
/**
|
|
695
|
+
* Helper: validate Pull-500 check request
|
|
696
|
+
*/
|
|
697
|
+
export function safeValidatePull500CheckRequest(input) {
|
|
698
|
+
return Pull500CheckRequestSchema.safeParse(input);
|
|
699
|
+
}
|
|
700
|
+
/**
|
|
701
|
+
* Status values for Pull-500 check response
|
|
702
|
+
* NEW - Request received, queued
|
|
703
|
+
* INPROGRESS - Processing
|
|
704
|
+
* READY - Results available
|
|
705
|
+
* ERROR - Processing failed
|
|
706
|
+
*/
|
|
707
|
+
export const Pull500StatusSchema = z.enum(['NEW', 'INPROGRESS', 'READY', 'ERROR']);
|
|
708
|
+
/**
|
|
709
|
+
* Schema for Pull-500 check response
|
|
710
|
+
*
|
|
711
|
+
* Status progression: NEW -> INPROGRESS -> READY (or ERROR)
|
|
712
|
+
* When status=READY, report contains CSV-formatted tracking data
|
|
713
|
+
* report_fields contains column headers
|
|
714
|
+
*/
|
|
715
|
+
export const Pull500CheckResponseSchema = z.object({
|
|
716
|
+
status: Pull500StatusSchema,
|
|
717
|
+
report: z.string().optional(), // CSV-formatted data (when status=READY)
|
|
718
|
+
report_fields: z.string().optional(), // CSV header (when status=READY)
|
|
719
|
+
errors: z.array(ErrorDescriptorSchema).optional(),
|
|
720
|
+
}).passthrough();
|
|
721
|
+
/**
|
|
722
|
+
* Helper: validate Pull-500 check response
|
|
723
|
+
*/
|
|
724
|
+
export function safeValidatePull500CheckResponse(input) {
|
|
725
|
+
return Pull500CheckResponseSchema.safeParse(input);
|
|
726
|
+
}
|