@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.
Files changed (50) hide show
  1. package/README.md +43 -0
  2. package/dist/capabilities/auth.d.ts +39 -0
  3. package/dist/capabilities/auth.d.ts.map +1 -0
  4. package/dist/capabilities/auth.js +130 -0
  5. package/dist/capabilities/close.d.ts +8 -0
  6. package/dist/capabilities/close.d.ts.map +1 -0
  7. package/dist/capabilities/close.js +70 -0
  8. package/dist/capabilities/get-shipment-details.d.ts +63 -0
  9. package/dist/capabilities/get-shipment-details.d.ts.map +1 -0
  10. package/dist/capabilities/get-shipment-details.js +97 -0
  11. package/dist/capabilities/index.d.ts +10 -0
  12. package/dist/capabilities/index.d.ts.map +1 -0
  13. package/dist/capabilities/index.js +9 -0
  14. package/dist/capabilities/label.d.ts +33 -0
  15. package/dist/capabilities/label.d.ts.map +1 -0
  16. package/dist/capabilities/label.js +328 -0
  17. package/dist/capabilities/parcels.d.ts +33 -0
  18. package/dist/capabilities/parcels.d.ts.map +1 -0
  19. package/dist/capabilities/parcels.js +284 -0
  20. package/dist/capabilities/pickup-points.d.ts +41 -0
  21. package/dist/capabilities/pickup-points.d.ts.map +1 -0
  22. package/dist/capabilities/pickup-points.js +294 -0
  23. package/dist/capabilities/track.d.ts +72 -0
  24. package/dist/capabilities/track.d.ts.map +1 -0
  25. package/dist/capabilities/track.js +331 -0
  26. package/dist/index.d.ts +83 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +142 -0
  29. package/dist/mappers/label.d.ts +67 -0
  30. package/dist/mappers/label.d.ts.map +1 -0
  31. package/dist/mappers/label.js +83 -0
  32. package/dist/mappers/shipment.d.ts +110 -0
  33. package/dist/mappers/shipment.d.ts.map +1 -0
  34. package/dist/mappers/shipment.js +258 -0
  35. package/dist/mappers/tracking.d.ts +60 -0
  36. package/dist/mappers/tracking.d.ts.map +1 -0
  37. package/dist/mappers/tracking.js +187 -0
  38. package/dist/utils/httpUtils.d.ts +36 -0
  39. package/dist/utils/httpUtils.d.ts.map +1 -0
  40. package/dist/utils/httpUtils.js +76 -0
  41. package/dist/utils/oauthFallback.d.ts +47 -0
  42. package/dist/utils/oauthFallback.d.ts.map +1 -0
  43. package/dist/utils/oauthFallback.js +250 -0
  44. package/dist/utils/resolveBaseUrl.d.ts +75 -0
  45. package/dist/utils/resolveBaseUrl.d.ts.map +1 -0
  46. package/dist/utils/resolveBaseUrl.js +65 -0
  47. package/dist/validation.d.ts +1890 -0
  48. package/dist/validation.d.ts.map +1 -0
  49. package/dist/validation.js +726 -0
  50. 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
+ }