shipflow 0.1.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +179 -37
- package/dist/carriers/aramex/adapter.d.ts +7 -0
- package/dist/carriers/aramex/adapter.d.ts.map +1 -1
- package/dist/carriers/aramex/index.js +58 -23
- package/dist/carriers/aramex/index.js.map +4 -4
- package/dist/carriers/aramex/mappers.d.ts +8 -0
- package/dist/carriers/aramex/mappers.d.ts.map +1 -1
- package/dist/carriers/aymakan/adapter.d.ts +5 -0
- package/dist/carriers/aymakan/adapter.d.ts.map +1 -1
- package/dist/carriers/aymakan/index.js +96 -30
- 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/smsaexpress/index.js +22 -16
- package/dist/carriers/smsaexpress/index.js.map +3 -3
- package/dist/carriers/smsaexpress/mappers.d.ts.map +1 -1
- package/dist/core/errors.d.ts +19 -1
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/http.d.ts +24 -3
- package/dist/core/http.d.ts.map +1 -1
- package/dist/core/retry.d.ts +42 -0
- package/dist/core/retry.d.ts.map +1 -0
- package/dist/core/schemas.d.ts +196 -812
- package/dist/core/schemas.d.ts.map +1 -1
- package/dist/index-qnxj8bct.js +1067 -0
- package/dist/index-qnxj8bct.js.map +15 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +2 -2
- package/package.json +4 -4
- package/dist/index-qjtxhwzv.js +0 -4602
- package/dist/index-qjtxhwzv.js.map +0 -22
|
@@ -0,0 +1,1067 @@
|
|
|
1
|
+
// src/core/errors.ts
|
|
2
|
+
class ShipFlowError extends Error {
|
|
3
|
+
carrier;
|
|
4
|
+
code;
|
|
5
|
+
raw;
|
|
6
|
+
constructor(message, options) {
|
|
7
|
+
super(message, { cause: options?.cause });
|
|
8
|
+
this.name = "ShipFlowError";
|
|
9
|
+
this.carrier = options?.carrier;
|
|
10
|
+
this.code = options?.code;
|
|
11
|
+
this.raw = options?.raw;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
class NetworkError extends ShipFlowError {
|
|
16
|
+
constructor(message, options) {
|
|
17
|
+
super(message, options);
|
|
18
|
+
this.name = "NetworkError";
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
class APIError extends ShipFlowError {
|
|
23
|
+
statusCode;
|
|
24
|
+
errors;
|
|
25
|
+
constructor(message, options) {
|
|
26
|
+
super(message, options);
|
|
27
|
+
this.name = "APIError";
|
|
28
|
+
this.statusCode = options?.statusCode;
|
|
29
|
+
this.errors = options?.errors;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
class RateLimitError extends APIError {
|
|
34
|
+
retryAfterMs;
|
|
35
|
+
constructor(message, options) {
|
|
36
|
+
super(message, options);
|
|
37
|
+
this.name = "RateLimitError";
|
|
38
|
+
this.retryAfterMs = options?.retryAfterMs;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
class ValidationError extends ShipFlowError {
|
|
43
|
+
field;
|
|
44
|
+
issues;
|
|
45
|
+
constructor(message, options) {
|
|
46
|
+
super(message, options);
|
|
47
|
+
this.name = "ValidationError";
|
|
48
|
+
this.field = options?.field;
|
|
49
|
+
this.issues = options?.issues;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
class AuthenticationError extends ShipFlowError {
|
|
54
|
+
constructor(message, options) {
|
|
55
|
+
super(message, options);
|
|
56
|
+
this.name = "AuthenticationError";
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
class WebhookVerificationError extends ShipFlowError {
|
|
61
|
+
constructor(message, options) {
|
|
62
|
+
super(message, options);
|
|
63
|
+
this.name = "WebhookVerificationError";
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
class UnsupportedOperationError extends ShipFlowError {
|
|
68
|
+
operation;
|
|
69
|
+
constructor(carrier, operation) {
|
|
70
|
+
super(`${carrier} does not support operation: ${operation}`, { carrier });
|
|
71
|
+
this.name = "UnsupportedOperationError";
|
|
72
|
+
this.operation = operation;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// ../../node_modules/.bun/valibot@1.4.1+7524df1edfed9f02/node_modules/valibot/dist/index.mjs
|
|
77
|
+
var store$4;
|
|
78
|
+
var DEFAULT_CONFIG = {
|
|
79
|
+
lang: undefined,
|
|
80
|
+
message: undefined,
|
|
81
|
+
abortEarly: undefined,
|
|
82
|
+
abortPipeEarly: undefined
|
|
83
|
+
};
|
|
84
|
+
function getGlobalConfig(config$1) {
|
|
85
|
+
if (!config$1 && !store$4)
|
|
86
|
+
return DEFAULT_CONFIG;
|
|
87
|
+
return {
|
|
88
|
+
lang: config$1?.lang ?? store$4?.lang,
|
|
89
|
+
message: config$1?.message,
|
|
90
|
+
abortEarly: config$1?.abortEarly ?? store$4?.abortEarly,
|
|
91
|
+
abortPipeEarly: config$1?.abortPipeEarly ?? store$4?.abortPipeEarly
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
var store$3;
|
|
95
|
+
function getGlobalMessage(lang) {
|
|
96
|
+
return store$3?.get(lang);
|
|
97
|
+
}
|
|
98
|
+
var store$2;
|
|
99
|
+
function getSchemaMessage(lang) {
|
|
100
|
+
return store$2?.get(lang);
|
|
101
|
+
}
|
|
102
|
+
var store$1;
|
|
103
|
+
function getSpecificMessage(reference, lang) {
|
|
104
|
+
return store$1?.get(reference)?.get(lang);
|
|
105
|
+
}
|
|
106
|
+
function _stringify(input) {
|
|
107
|
+
const type = typeof input;
|
|
108
|
+
if (type === "string")
|
|
109
|
+
return `"${input}"`;
|
|
110
|
+
if (type === "number" || type === "bigint" || type === "boolean")
|
|
111
|
+
return `${input}`;
|
|
112
|
+
if (type === "object" || type === "function")
|
|
113
|
+
return (input && Object.getPrototypeOf(input)?.constructor?.name) ?? "null";
|
|
114
|
+
return type;
|
|
115
|
+
}
|
|
116
|
+
function _addIssue(context, label, dataset, config$1, other) {
|
|
117
|
+
const input = other && "input" in other ? other.input : dataset.value;
|
|
118
|
+
const expected = other?.expected ?? context.expects ?? null;
|
|
119
|
+
const received = other?.received ?? /* @__PURE__ */ _stringify(input);
|
|
120
|
+
const issue = {
|
|
121
|
+
kind: context.kind,
|
|
122
|
+
type: context.type,
|
|
123
|
+
input,
|
|
124
|
+
expected,
|
|
125
|
+
received,
|
|
126
|
+
message: `Invalid ${label}: ${expected ? `Expected ${expected} but r` : "R"}eceived ${received}`,
|
|
127
|
+
requirement: context.requirement,
|
|
128
|
+
path: other?.path,
|
|
129
|
+
issues: other?.issues,
|
|
130
|
+
lang: config$1.lang,
|
|
131
|
+
abortEarly: config$1.abortEarly,
|
|
132
|
+
abortPipeEarly: config$1.abortPipeEarly
|
|
133
|
+
};
|
|
134
|
+
const isSchema = context.kind === "schema";
|
|
135
|
+
const message$1 = other?.message ?? context.message ?? /* @__PURE__ */ getSpecificMessage(context.reference, issue.lang) ?? (isSchema ? /* @__PURE__ */ getSchemaMessage(issue.lang) : null) ?? config$1.message ?? /* @__PURE__ */ getGlobalMessage(issue.lang);
|
|
136
|
+
if (message$1 !== undefined)
|
|
137
|
+
issue.message = typeof message$1 === "function" ? message$1(issue) : message$1;
|
|
138
|
+
if (isSchema)
|
|
139
|
+
dataset.typed = false;
|
|
140
|
+
if (dataset.issues)
|
|
141
|
+
dataset.issues.push(issue);
|
|
142
|
+
else
|
|
143
|
+
dataset.issues = [issue];
|
|
144
|
+
}
|
|
145
|
+
var _standardCache = /* @__PURE__ */ new WeakMap;
|
|
146
|
+
function _getStandardProps(context) {
|
|
147
|
+
let cached = _standardCache.get(context);
|
|
148
|
+
if (!cached) {
|
|
149
|
+
cached = {
|
|
150
|
+
version: 1,
|
|
151
|
+
vendor: "valibot",
|
|
152
|
+
validate(value$1) {
|
|
153
|
+
return context["~run"]({ value: value$1 }, /* @__PURE__ */ getGlobalConfig());
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
_standardCache.set(context, cached);
|
|
157
|
+
}
|
|
158
|
+
return cached;
|
|
159
|
+
}
|
|
160
|
+
function _isValidObjectKey(object$1, key) {
|
|
161
|
+
return Object.prototype.hasOwnProperty.call(object$1, key) && key !== "__proto__" && key !== "prototype" && key !== "constructor";
|
|
162
|
+
}
|
|
163
|
+
function _joinExpects(values$1, separator) {
|
|
164
|
+
const list = [...new Set(values$1)];
|
|
165
|
+
if (list.length > 1)
|
|
166
|
+
return `(${list.join(` ${separator} `)})`;
|
|
167
|
+
return list[0] ?? "never";
|
|
168
|
+
}
|
|
169
|
+
function getDotPath(issue) {
|
|
170
|
+
if (issue.path) {
|
|
171
|
+
let key = "";
|
|
172
|
+
for (const item of issue.path)
|
|
173
|
+
if (typeof item.key === "string" || typeof item.key === "number")
|
|
174
|
+
if (key)
|
|
175
|
+
key += `.${item.key}`;
|
|
176
|
+
else
|
|
177
|
+
key += item.key;
|
|
178
|
+
else
|
|
179
|
+
return null;
|
|
180
|
+
return key;
|
|
181
|
+
}
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
var EMAIL_REGEX = /^[\w+-]+(?:\.[\w+-]+)*@[\da-z]+(?:[.-][\da-z]+)*\.[a-z]{2,}$/iu;
|
|
185
|
+
function email(message$1) {
|
|
186
|
+
return {
|
|
187
|
+
kind: "validation",
|
|
188
|
+
type: "email",
|
|
189
|
+
reference: email,
|
|
190
|
+
expects: null,
|
|
191
|
+
async: false,
|
|
192
|
+
requirement: EMAIL_REGEX,
|
|
193
|
+
message: message$1,
|
|
194
|
+
"~run"(dataset, config$1) {
|
|
195
|
+
if (dataset.typed && !this.requirement.test(dataset.value))
|
|
196
|
+
_addIssue(this, "email", dataset, config$1);
|
|
197
|
+
return dataset;
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
function gtValue(requirement, message$1) {
|
|
202
|
+
return {
|
|
203
|
+
kind: "validation",
|
|
204
|
+
type: "gt_value",
|
|
205
|
+
reference: gtValue,
|
|
206
|
+
async: false,
|
|
207
|
+
expects: `>${requirement instanceof Date ? requirement.toJSON() : /* @__PURE__ */ _stringify(requirement)}`,
|
|
208
|
+
requirement,
|
|
209
|
+
message: message$1,
|
|
210
|
+
"~run"(dataset, config$1) {
|
|
211
|
+
if (dataset.typed && !(dataset.value > this.requirement))
|
|
212
|
+
_addIssue(this, "value", dataset, config$1, { received: dataset.value instanceof Date ? dataset.value.toJSON() : /* @__PURE__ */ _stringify(dataset.value) });
|
|
213
|
+
return dataset;
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
function integer(message$1) {
|
|
218
|
+
return {
|
|
219
|
+
kind: "validation",
|
|
220
|
+
type: "integer",
|
|
221
|
+
reference: integer,
|
|
222
|
+
async: false,
|
|
223
|
+
expects: null,
|
|
224
|
+
requirement: Number.isInteger,
|
|
225
|
+
message: message$1,
|
|
226
|
+
"~run"(dataset, config$1) {
|
|
227
|
+
if (dataset.typed && !this.requirement(dataset.value))
|
|
228
|
+
_addIssue(this, "integer", dataset, config$1);
|
|
229
|
+
return dataset;
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
function length(requirement, message$1) {
|
|
234
|
+
return {
|
|
235
|
+
kind: "validation",
|
|
236
|
+
type: "length",
|
|
237
|
+
reference: length,
|
|
238
|
+
async: false,
|
|
239
|
+
expects: `${requirement}`,
|
|
240
|
+
requirement,
|
|
241
|
+
message: message$1,
|
|
242
|
+
"~run"(dataset, config$1) {
|
|
243
|
+
if (dataset.typed && dataset.value.length !== this.requirement)
|
|
244
|
+
_addIssue(this, "length", dataset, config$1, { received: `${dataset.value.length}` });
|
|
245
|
+
return dataset;
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
function maxValue(requirement, message$1) {
|
|
250
|
+
return {
|
|
251
|
+
kind: "validation",
|
|
252
|
+
type: "max_value",
|
|
253
|
+
reference: maxValue,
|
|
254
|
+
async: false,
|
|
255
|
+
expects: `<=${requirement instanceof Date ? requirement.toJSON() : /* @__PURE__ */ _stringify(requirement)}`,
|
|
256
|
+
requirement,
|
|
257
|
+
message: message$1,
|
|
258
|
+
"~run"(dataset, config$1) {
|
|
259
|
+
if (dataset.typed && !(dataset.value <= this.requirement))
|
|
260
|
+
_addIssue(this, "value", dataset, config$1, { received: dataset.value instanceof Date ? dataset.value.toJSON() : /* @__PURE__ */ _stringify(dataset.value) });
|
|
261
|
+
return dataset;
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
function minLength(requirement, message$1) {
|
|
266
|
+
return {
|
|
267
|
+
kind: "validation",
|
|
268
|
+
type: "min_length",
|
|
269
|
+
reference: minLength,
|
|
270
|
+
async: false,
|
|
271
|
+
expects: `>=${requirement}`,
|
|
272
|
+
requirement,
|
|
273
|
+
message: message$1,
|
|
274
|
+
"~run"(dataset, config$1) {
|
|
275
|
+
if (dataset.typed && dataset.value.length < this.requirement)
|
|
276
|
+
_addIssue(this, "length", dataset, config$1, { received: `${dataset.value.length}` });
|
|
277
|
+
return dataset;
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
function minValue(requirement, message$1) {
|
|
282
|
+
return {
|
|
283
|
+
kind: "validation",
|
|
284
|
+
type: "min_value",
|
|
285
|
+
reference: minValue,
|
|
286
|
+
async: false,
|
|
287
|
+
expects: `>=${requirement instanceof Date ? requirement.toJSON() : /* @__PURE__ */ _stringify(requirement)}`,
|
|
288
|
+
requirement,
|
|
289
|
+
message: message$1,
|
|
290
|
+
"~run"(dataset, config$1) {
|
|
291
|
+
if (dataset.typed && !(dataset.value >= this.requirement))
|
|
292
|
+
_addIssue(this, "value", dataset, config$1, { received: dataset.value instanceof Date ? dataset.value.toJSON() : /* @__PURE__ */ _stringify(dataset.value) });
|
|
293
|
+
return dataset;
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
function regex(requirement, message$1) {
|
|
298
|
+
return {
|
|
299
|
+
kind: "validation",
|
|
300
|
+
type: "regex",
|
|
301
|
+
reference: regex,
|
|
302
|
+
async: false,
|
|
303
|
+
expects: `${requirement}`,
|
|
304
|
+
requirement,
|
|
305
|
+
message: message$1,
|
|
306
|
+
"~run"(dataset, config$1) {
|
|
307
|
+
if (dataset.typed && !this.requirement.test(dataset.value))
|
|
308
|
+
_addIssue(this, "format", dataset, config$1);
|
|
309
|
+
return dataset;
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
function getFallback(schema, dataset, config$1) {
|
|
314
|
+
return typeof schema.fallback === "function" ? schema.fallback(dataset, config$1) : schema.fallback;
|
|
315
|
+
}
|
|
316
|
+
function getDefault(schema, dataset, config$1) {
|
|
317
|
+
return typeof schema.default === "function" ? schema.default(dataset, config$1) : schema.default;
|
|
318
|
+
}
|
|
319
|
+
function array(item, message$1) {
|
|
320
|
+
return {
|
|
321
|
+
kind: "schema",
|
|
322
|
+
type: "array",
|
|
323
|
+
reference: array,
|
|
324
|
+
expects: "Array",
|
|
325
|
+
async: false,
|
|
326
|
+
item,
|
|
327
|
+
message: message$1,
|
|
328
|
+
get "~standard"() {
|
|
329
|
+
return /* @__PURE__ */ _getStandardProps(this);
|
|
330
|
+
},
|
|
331
|
+
"~run"(dataset, config$1) {
|
|
332
|
+
const input = dataset.value;
|
|
333
|
+
if (Array.isArray(input)) {
|
|
334
|
+
dataset.typed = true;
|
|
335
|
+
dataset.value = [];
|
|
336
|
+
for (let key = 0;key < input.length; key++) {
|
|
337
|
+
const value$1 = input[key];
|
|
338
|
+
const itemDataset = this.item["~run"]({ value: value$1 }, config$1);
|
|
339
|
+
if (itemDataset.issues) {
|
|
340
|
+
const pathItem = {
|
|
341
|
+
type: "array",
|
|
342
|
+
origin: "value",
|
|
343
|
+
input,
|
|
344
|
+
key,
|
|
345
|
+
value: value$1
|
|
346
|
+
};
|
|
347
|
+
for (const issue of itemDataset.issues) {
|
|
348
|
+
if (issue.path)
|
|
349
|
+
issue.path.unshift(pathItem);
|
|
350
|
+
else
|
|
351
|
+
issue.path = [pathItem];
|
|
352
|
+
dataset.issues?.push(issue);
|
|
353
|
+
}
|
|
354
|
+
if (!dataset.issues)
|
|
355
|
+
dataset.issues = itemDataset.issues;
|
|
356
|
+
if (config$1.abortEarly) {
|
|
357
|
+
dataset.typed = false;
|
|
358
|
+
break;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
if (!itemDataset.typed)
|
|
362
|
+
dataset.typed = false;
|
|
363
|
+
dataset.value.push(itemDataset.value);
|
|
364
|
+
}
|
|
365
|
+
} else
|
|
366
|
+
_addIssue(this, "type", dataset, config$1);
|
|
367
|
+
return dataset;
|
|
368
|
+
}
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
function boolean(message$1) {
|
|
372
|
+
return {
|
|
373
|
+
kind: "schema",
|
|
374
|
+
type: "boolean",
|
|
375
|
+
reference: boolean,
|
|
376
|
+
expects: "boolean",
|
|
377
|
+
async: false,
|
|
378
|
+
message: message$1,
|
|
379
|
+
get "~standard"() {
|
|
380
|
+
return /* @__PURE__ */ _getStandardProps(this);
|
|
381
|
+
},
|
|
382
|
+
"~run"(dataset, config$1) {
|
|
383
|
+
if (typeof dataset.value === "boolean")
|
|
384
|
+
dataset.typed = true;
|
|
385
|
+
else
|
|
386
|
+
_addIssue(this, "type", dataset, config$1);
|
|
387
|
+
return dataset;
|
|
388
|
+
}
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
function number(message$1) {
|
|
392
|
+
return {
|
|
393
|
+
kind: "schema",
|
|
394
|
+
type: "number",
|
|
395
|
+
reference: number,
|
|
396
|
+
expects: "number",
|
|
397
|
+
async: false,
|
|
398
|
+
message: message$1,
|
|
399
|
+
get "~standard"() {
|
|
400
|
+
return /* @__PURE__ */ _getStandardProps(this);
|
|
401
|
+
},
|
|
402
|
+
"~run"(dataset, config$1) {
|
|
403
|
+
if (typeof dataset.value === "number" && !isNaN(dataset.value))
|
|
404
|
+
dataset.typed = true;
|
|
405
|
+
else
|
|
406
|
+
_addIssue(this, "type", dataset, config$1);
|
|
407
|
+
return dataset;
|
|
408
|
+
}
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
function object(entries$1, message$1) {
|
|
412
|
+
return {
|
|
413
|
+
kind: "schema",
|
|
414
|
+
type: "object",
|
|
415
|
+
reference: object,
|
|
416
|
+
expects: "Object",
|
|
417
|
+
async: false,
|
|
418
|
+
entries: entries$1,
|
|
419
|
+
message: message$1,
|
|
420
|
+
get "~standard"() {
|
|
421
|
+
return /* @__PURE__ */ _getStandardProps(this);
|
|
422
|
+
},
|
|
423
|
+
"~run"(dataset, config$1) {
|
|
424
|
+
const input = dataset.value;
|
|
425
|
+
if (input && typeof input === "object") {
|
|
426
|
+
dataset.typed = true;
|
|
427
|
+
dataset.value = {};
|
|
428
|
+
for (const key in this.entries) {
|
|
429
|
+
const valueSchema = this.entries[key];
|
|
430
|
+
if (key in input || (valueSchema.type === "exact_optional" || valueSchema.type === "optional" || valueSchema.type === "nullish") && valueSchema.default !== undefined) {
|
|
431
|
+
const value$1 = key in input ? input[key] : /* @__PURE__ */ getDefault(valueSchema);
|
|
432
|
+
const valueDataset = valueSchema["~run"]({ value: value$1 }, config$1);
|
|
433
|
+
if (valueDataset.issues) {
|
|
434
|
+
const pathItem = {
|
|
435
|
+
type: "object",
|
|
436
|
+
origin: "value",
|
|
437
|
+
input,
|
|
438
|
+
key,
|
|
439
|
+
value: value$1
|
|
440
|
+
};
|
|
441
|
+
for (const issue of valueDataset.issues) {
|
|
442
|
+
if (issue.path)
|
|
443
|
+
issue.path.unshift(pathItem);
|
|
444
|
+
else
|
|
445
|
+
issue.path = [pathItem];
|
|
446
|
+
dataset.issues?.push(issue);
|
|
447
|
+
}
|
|
448
|
+
if (!dataset.issues)
|
|
449
|
+
dataset.issues = valueDataset.issues;
|
|
450
|
+
if (config$1.abortEarly) {
|
|
451
|
+
dataset.typed = false;
|
|
452
|
+
break;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
if (!valueDataset.typed)
|
|
456
|
+
dataset.typed = false;
|
|
457
|
+
dataset.value[key] = valueDataset.value;
|
|
458
|
+
} else if (valueSchema.fallback !== undefined)
|
|
459
|
+
dataset.value[key] = /* @__PURE__ */ getFallback(valueSchema);
|
|
460
|
+
else if (valueSchema.type !== "exact_optional" && valueSchema.type !== "optional" && valueSchema.type !== "nullish") {
|
|
461
|
+
_addIssue(this, "key", dataset, config$1, {
|
|
462
|
+
input: undefined,
|
|
463
|
+
expected: `"${key}"`,
|
|
464
|
+
path: [{
|
|
465
|
+
type: "object",
|
|
466
|
+
origin: "key",
|
|
467
|
+
input,
|
|
468
|
+
key,
|
|
469
|
+
value: input[key]
|
|
470
|
+
}]
|
|
471
|
+
});
|
|
472
|
+
if (config$1.abortEarly)
|
|
473
|
+
break;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
} else
|
|
477
|
+
_addIssue(this, "type", dataset, config$1);
|
|
478
|
+
return dataset;
|
|
479
|
+
}
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
function optional(wrapped, default_) {
|
|
483
|
+
return {
|
|
484
|
+
kind: "schema",
|
|
485
|
+
type: "optional",
|
|
486
|
+
reference: optional,
|
|
487
|
+
expects: `(${wrapped.expects} | undefined)`,
|
|
488
|
+
async: false,
|
|
489
|
+
wrapped,
|
|
490
|
+
default: default_,
|
|
491
|
+
get "~standard"() {
|
|
492
|
+
return /* @__PURE__ */ _getStandardProps(this);
|
|
493
|
+
},
|
|
494
|
+
"~run"(dataset, config$1) {
|
|
495
|
+
if (dataset.value === undefined) {
|
|
496
|
+
if (this.default !== undefined)
|
|
497
|
+
dataset.value = /* @__PURE__ */ getDefault(this, dataset, config$1);
|
|
498
|
+
if (dataset.value === undefined) {
|
|
499
|
+
dataset.typed = true;
|
|
500
|
+
return dataset;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
return this.wrapped["~run"](dataset, config$1);
|
|
504
|
+
}
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
function picklist(options, message$1) {
|
|
508
|
+
return {
|
|
509
|
+
kind: "schema",
|
|
510
|
+
type: "picklist",
|
|
511
|
+
reference: picklist,
|
|
512
|
+
expects: /* @__PURE__ */ _joinExpects(options.map(_stringify), "|"),
|
|
513
|
+
async: false,
|
|
514
|
+
options,
|
|
515
|
+
message: message$1,
|
|
516
|
+
get "~standard"() {
|
|
517
|
+
return /* @__PURE__ */ _getStandardProps(this);
|
|
518
|
+
},
|
|
519
|
+
"~run"(dataset, config$1) {
|
|
520
|
+
if (this.options.includes(dataset.value))
|
|
521
|
+
dataset.typed = true;
|
|
522
|
+
else
|
|
523
|
+
_addIssue(this, "type", dataset, config$1);
|
|
524
|
+
return dataset;
|
|
525
|
+
}
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
function record(key, value$1, message$1) {
|
|
529
|
+
return {
|
|
530
|
+
kind: "schema",
|
|
531
|
+
type: "record",
|
|
532
|
+
reference: record,
|
|
533
|
+
expects: "Object",
|
|
534
|
+
async: false,
|
|
535
|
+
key,
|
|
536
|
+
value: value$1,
|
|
537
|
+
message: message$1,
|
|
538
|
+
get "~standard"() {
|
|
539
|
+
return /* @__PURE__ */ _getStandardProps(this);
|
|
540
|
+
},
|
|
541
|
+
"~run"(dataset, config$1) {
|
|
542
|
+
const input = dataset.value;
|
|
543
|
+
if (input && typeof input === "object") {
|
|
544
|
+
dataset.typed = true;
|
|
545
|
+
dataset.value = {};
|
|
546
|
+
for (const entryKey in input)
|
|
547
|
+
if (/* @__PURE__ */ _isValidObjectKey(input, entryKey)) {
|
|
548
|
+
const entryValue = input[entryKey];
|
|
549
|
+
const keyDataset = this.key["~run"]({ value: entryKey }, config$1);
|
|
550
|
+
if (keyDataset.issues) {
|
|
551
|
+
const pathItem = {
|
|
552
|
+
type: "object",
|
|
553
|
+
origin: "key",
|
|
554
|
+
input,
|
|
555
|
+
key: entryKey,
|
|
556
|
+
value: entryValue
|
|
557
|
+
};
|
|
558
|
+
for (const issue of keyDataset.issues) {
|
|
559
|
+
issue.path = [pathItem];
|
|
560
|
+
dataset.issues?.push(issue);
|
|
561
|
+
}
|
|
562
|
+
if (!dataset.issues)
|
|
563
|
+
dataset.issues = keyDataset.issues;
|
|
564
|
+
if (config$1.abortEarly) {
|
|
565
|
+
dataset.typed = false;
|
|
566
|
+
break;
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
const valueDataset = this.value["~run"]({ value: entryValue }, config$1);
|
|
570
|
+
if (valueDataset.issues) {
|
|
571
|
+
const pathItem = {
|
|
572
|
+
type: "object",
|
|
573
|
+
origin: "value",
|
|
574
|
+
input,
|
|
575
|
+
key: entryKey,
|
|
576
|
+
value: entryValue
|
|
577
|
+
};
|
|
578
|
+
for (const issue of valueDataset.issues) {
|
|
579
|
+
if (issue.path)
|
|
580
|
+
issue.path.unshift(pathItem);
|
|
581
|
+
else
|
|
582
|
+
issue.path = [pathItem];
|
|
583
|
+
dataset.issues?.push(issue);
|
|
584
|
+
}
|
|
585
|
+
if (!dataset.issues)
|
|
586
|
+
dataset.issues = valueDataset.issues;
|
|
587
|
+
if (config$1.abortEarly) {
|
|
588
|
+
dataset.typed = false;
|
|
589
|
+
break;
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
if (!keyDataset.typed || !valueDataset.typed)
|
|
593
|
+
dataset.typed = false;
|
|
594
|
+
if (keyDataset.typed)
|
|
595
|
+
dataset.value[keyDataset.value] = valueDataset.value;
|
|
596
|
+
}
|
|
597
|
+
} else
|
|
598
|
+
_addIssue(this, "type", dataset, config$1);
|
|
599
|
+
return dataset;
|
|
600
|
+
}
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
function string(message$1) {
|
|
604
|
+
return {
|
|
605
|
+
kind: "schema",
|
|
606
|
+
type: "string",
|
|
607
|
+
reference: string,
|
|
608
|
+
expects: "string",
|
|
609
|
+
async: false,
|
|
610
|
+
message: message$1,
|
|
611
|
+
get "~standard"() {
|
|
612
|
+
return /* @__PURE__ */ _getStandardProps(this);
|
|
613
|
+
},
|
|
614
|
+
"~run"(dataset, config$1) {
|
|
615
|
+
if (typeof dataset.value === "string")
|
|
616
|
+
dataset.typed = true;
|
|
617
|
+
else
|
|
618
|
+
_addIssue(this, "type", dataset, config$1);
|
|
619
|
+
return dataset;
|
|
620
|
+
}
|
|
621
|
+
};
|
|
622
|
+
}
|
|
623
|
+
function unknown() {
|
|
624
|
+
return {
|
|
625
|
+
kind: "schema",
|
|
626
|
+
type: "unknown",
|
|
627
|
+
reference: unknown,
|
|
628
|
+
expects: "unknown",
|
|
629
|
+
async: false,
|
|
630
|
+
get "~standard"() {
|
|
631
|
+
return /* @__PURE__ */ _getStandardProps(this);
|
|
632
|
+
},
|
|
633
|
+
"~run"(dataset) {
|
|
634
|
+
dataset.typed = true;
|
|
635
|
+
return dataset;
|
|
636
|
+
}
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
function pipe(...pipe$1) {
|
|
640
|
+
return {
|
|
641
|
+
...pipe$1[0],
|
|
642
|
+
pipe: pipe$1,
|
|
643
|
+
get "~standard"() {
|
|
644
|
+
return /* @__PURE__ */ _getStandardProps(this);
|
|
645
|
+
},
|
|
646
|
+
"~run"(dataset, config$1) {
|
|
647
|
+
for (const item of pipe$1)
|
|
648
|
+
if (item.kind !== "metadata") {
|
|
649
|
+
if (dataset.issues && (item.kind === "schema" || item.kind === "transformation")) {
|
|
650
|
+
dataset.typed = false;
|
|
651
|
+
break;
|
|
652
|
+
}
|
|
653
|
+
if (!dataset.issues || !config$1.abortEarly && !config$1.abortPipeEarly)
|
|
654
|
+
dataset = item["~run"](dataset, config$1);
|
|
655
|
+
}
|
|
656
|
+
return dataset;
|
|
657
|
+
}
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
function safeParse(schema, input, config$1) {
|
|
661
|
+
const dataset = schema["~run"]({ value: input }, /* @__PURE__ */ getGlobalConfig(config$1));
|
|
662
|
+
return {
|
|
663
|
+
typed: dataset.typed,
|
|
664
|
+
success: !dataset.issues,
|
|
665
|
+
output: dataset.value,
|
|
666
|
+
issues: dataset.issues
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
// src/core/schemas.ts
|
|
671
|
+
var NationalAddressSchema = object({
|
|
672
|
+
shortCode: pipe(string(), minLength(1)),
|
|
673
|
+
buildingNumber: optional(string()),
|
|
674
|
+
streetName: optional(string()),
|
|
675
|
+
district: optional(string()),
|
|
676
|
+
additionalNumber: optional(string())
|
|
677
|
+
});
|
|
678
|
+
var AddressSchema = object({
|
|
679
|
+
name: pipe(string(), minLength(1, "Name is required")),
|
|
680
|
+
company: optional(string()),
|
|
681
|
+
email: optional(pipe(string(), email("Invalid email format"))),
|
|
682
|
+
phone: pipe(string(), minLength(1, "Phone is required")),
|
|
683
|
+
line1: pipe(string(), minLength(1, "Address line 1 is required")),
|
|
684
|
+
line2: optional(string()),
|
|
685
|
+
neighbourhood: optional(string()),
|
|
686
|
+
city: pipe(string(), minLength(1, "City is required")),
|
|
687
|
+
state: optional(string()),
|
|
688
|
+
postalCode: optional(string()),
|
|
689
|
+
countryCode: pipe(string(), length(2, "Country code must be ISO 3166-1 alpha-2 (2 characters)")),
|
|
690
|
+
coordinates: optional(object({
|
|
691
|
+
latitude: pipe(number(), minValue(-90), maxValue(90)),
|
|
692
|
+
longitude: pipe(number(), minValue(-180), maxValue(180))
|
|
693
|
+
})),
|
|
694
|
+
description: optional(string()),
|
|
695
|
+
nationalAddress: optional(NationalAddressSchema)
|
|
696
|
+
});
|
|
697
|
+
var WeightSchema = object({
|
|
698
|
+
value: pipe(number(), gtValue(0, "Weight must be positive")),
|
|
699
|
+
unit: picklist(["kg", "lb"])
|
|
700
|
+
});
|
|
701
|
+
var DimensionsSchema = object({
|
|
702
|
+
length: pipe(number(), gtValue(0, "Length must be positive")),
|
|
703
|
+
width: pipe(number(), gtValue(0, "Width must be positive")),
|
|
704
|
+
height: pipe(number(), gtValue(0, "Height must be positive")),
|
|
705
|
+
unit: picklist(["cm", "in"])
|
|
706
|
+
});
|
|
707
|
+
var ParcelSchema = object({
|
|
708
|
+
weight: WeightSchema,
|
|
709
|
+
dimensions: optional(DimensionsSchema),
|
|
710
|
+
pieces: pipe(number(), integer(), gtValue(0, "Pieces must be a positive integer")),
|
|
711
|
+
itemsCount: optional(pipe(number(), integer(), gtValue(0))),
|
|
712
|
+
description: optional(string())
|
|
713
|
+
});
|
|
714
|
+
var CODDetailsSchema = object({
|
|
715
|
+
enabled: boolean(),
|
|
716
|
+
amount: pipe(number(), minValue(0, "COD amount must be non-negative")),
|
|
717
|
+
currency: pipe(string(), minLength(1, "COD currency is required"))
|
|
718
|
+
});
|
|
719
|
+
var DeclaredValueSchema = object({
|
|
720
|
+
amount: pipe(number(), minValue(0, "Declared value must be non-negative")),
|
|
721
|
+
currency: pipe(string(), minLength(1, "Currency is required"))
|
|
722
|
+
});
|
|
723
|
+
var InternationalMetadataSchema = object({
|
|
724
|
+
taxId: optional(string()),
|
|
725
|
+
invoiceNumber: optional(string()),
|
|
726
|
+
invoiceDate: optional(string()),
|
|
727
|
+
documentId: optional(number())
|
|
728
|
+
});
|
|
729
|
+
var ShipmentOptionsSchema = object({
|
|
730
|
+
requestedBy: optional(string()),
|
|
731
|
+
isInsured: optional(boolean()),
|
|
732
|
+
customerTracking: optional(string()),
|
|
733
|
+
fulfilmentCustomerName: optional(string()),
|
|
734
|
+
internationalMetadata: optional(InternationalMetadataSchema),
|
|
735
|
+
metadata: optional(record(string(), unknown()))
|
|
736
|
+
});
|
|
737
|
+
var CreateShipmentInputSchema = object({
|
|
738
|
+
shipper: AddressSchema,
|
|
739
|
+
consignee: AddressSchema,
|
|
740
|
+
parcels: pipe(array(ParcelSchema), minLength(1, "At least one parcel is required")),
|
|
741
|
+
serviceType: optional(pipe(string(), minLength(1))),
|
|
742
|
+
reference: optional(string()),
|
|
743
|
+
cod: optional(CODDetailsSchema),
|
|
744
|
+
declaredValue: optional(DeclaredValueSchema),
|
|
745
|
+
labelFormat: optional(picklist(["PDF", "ZPL", "PNG"])),
|
|
746
|
+
options: optional(ShipmentOptionsSchema)
|
|
747
|
+
});
|
|
748
|
+
var PickupRequestSchema = object({
|
|
749
|
+
date: pipe(string(), regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be YYYY-MM-DD format")),
|
|
750
|
+
timeSlot: pipe(string(), minLength(1, "Time slot is required")),
|
|
751
|
+
city: pipe(string(), minLength(1, "City is required")),
|
|
752
|
+
contactName: pipe(string(), minLength(1, "Contact name is required")),
|
|
753
|
+
contactPhone: pipe(string(), minLength(1, "Contact phone is required")),
|
|
754
|
+
address: pipe(string(), minLength(1, "Address is required")),
|
|
755
|
+
shipmentCount: pipe(number(), integer(), gtValue(0, "Shipment count must be a positive integer")),
|
|
756
|
+
trackingNumbers: optional(array(string()))
|
|
757
|
+
});
|
|
758
|
+
var WebhookConfigSchema = object({
|
|
759
|
+
authHeader: optional(string()),
|
|
760
|
+
authValue: optional(string()),
|
|
761
|
+
authQueryParam: optional(string()),
|
|
762
|
+
authQueryValue: optional(string())
|
|
763
|
+
});
|
|
764
|
+
function formatIssues(issues) {
|
|
765
|
+
return issues.map((issue) => ({
|
|
766
|
+
path: getDotPath(issue) ?? "",
|
|
767
|
+
message: issue.message
|
|
768
|
+
}));
|
|
769
|
+
}
|
|
770
|
+
function validateCreateShipmentInput(input) {
|
|
771
|
+
const result = safeParse(CreateShipmentInputSchema, input);
|
|
772
|
+
if (!result.success) {
|
|
773
|
+
throw new ValidationError("Invalid shipment input", {
|
|
774
|
+
issues: formatIssues(result.issues),
|
|
775
|
+
raw: input
|
|
776
|
+
});
|
|
777
|
+
}
|
|
778
|
+
return result.output;
|
|
779
|
+
}
|
|
780
|
+
function validatePickupRequest(input) {
|
|
781
|
+
const result = safeParse(PickupRequestSchema, input);
|
|
782
|
+
if (!result.success) {
|
|
783
|
+
throw new ValidationError("Invalid pickup request", {
|
|
784
|
+
issues: formatIssues(result.issues),
|
|
785
|
+
raw: input
|
|
786
|
+
});
|
|
787
|
+
}
|
|
788
|
+
return result.output;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
// src/carriers/base.ts
|
|
792
|
+
class BaseCarrierAdapter {
|
|
793
|
+
config;
|
|
794
|
+
constructor(config) {
|
|
795
|
+
this.config = config;
|
|
796
|
+
}
|
|
797
|
+
async createShipment(input) {
|
|
798
|
+
validateCreateShipmentInput(input);
|
|
799
|
+
return this.executeCreateShipment(input);
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
// src/core/retry.ts
|
|
804
|
+
import { setTimeout as sleep } from "node:timers/promises";
|
|
805
|
+
async function withRetry(fn, options) {
|
|
806
|
+
const {
|
|
807
|
+
retries,
|
|
808
|
+
baseMs = 500,
|
|
809
|
+
maxMs = 20000,
|
|
810
|
+
inlineCapMs = 15000,
|
|
811
|
+
shouldRetry,
|
|
812
|
+
retryAfterMs,
|
|
813
|
+
signal
|
|
814
|
+
} = options;
|
|
815
|
+
for (let attempt = 0;; attempt++) {
|
|
816
|
+
try {
|
|
817
|
+
return await fn();
|
|
818
|
+
} catch (error) {
|
|
819
|
+
if (attempt >= retries || !shouldRetry(error))
|
|
820
|
+
throw error;
|
|
821
|
+
const retryAfter = retryAfterMs?.(error);
|
|
822
|
+
let delay;
|
|
823
|
+
if (retryAfter != null) {
|
|
824
|
+
if (retryAfter > inlineCapMs)
|
|
825
|
+
throw error;
|
|
826
|
+
delay = retryAfter + Math.random() * 1000;
|
|
827
|
+
} else {
|
|
828
|
+
delay = Math.random() * Math.min(maxMs, baseMs * 2 ** attempt);
|
|
829
|
+
}
|
|
830
|
+
try {
|
|
831
|
+
await sleep(delay, undefined, { signal });
|
|
832
|
+
} catch {
|
|
833
|
+
throw error;
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
function parseRetryAfter(headerValue) {
|
|
839
|
+
if (headerValue == null)
|
|
840
|
+
return;
|
|
841
|
+
const trimmed = headerValue.trim();
|
|
842
|
+
if (trimmed === "")
|
|
843
|
+
return;
|
|
844
|
+
if (/^\d+$/.test(trimmed))
|
|
845
|
+
return Number(trimmed) * 1000;
|
|
846
|
+
const date = Date.parse(trimmed);
|
|
847
|
+
if (Number.isNaN(date))
|
|
848
|
+
return;
|
|
849
|
+
return Math.max(0, date - Date.now());
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
// src/core/http.ts
|
|
853
|
+
class HttpClient {
|
|
854
|
+
config;
|
|
855
|
+
retryConfig;
|
|
856
|
+
static DEFAULT_RETRYABLE = [429, 500, 502, 503, 504];
|
|
857
|
+
static SAFE_METHODS = new Set(["GET", "HEAD", "OPTIONS"]);
|
|
858
|
+
constructor(config) {
|
|
859
|
+
this.config = {
|
|
860
|
+
...config,
|
|
861
|
+
timeout: config.timeout ?? 30000
|
|
862
|
+
};
|
|
863
|
+
const retry = config.retry === false ? { retries: 0 } : config.retry ?? {};
|
|
864
|
+
this.retryConfig = {
|
|
865
|
+
retries: retry.retries ?? 2,
|
|
866
|
+
retryableStatuses: retry.retryableStatuses ?? HttpClient.DEFAULT_RETRYABLE,
|
|
867
|
+
baseMs: retry.baseMs ?? 500,
|
|
868
|
+
maxMs: retry.maxMs ?? 20000,
|
|
869
|
+
inlineCapMs: retry.inlineCapMs ?? 15000
|
|
870
|
+
};
|
|
871
|
+
}
|
|
872
|
+
async request(endpoint, options = {}) {
|
|
873
|
+
const method = options.method ?? "GET";
|
|
874
|
+
const shouldRetry = this.shouldRetry(method, options.retry);
|
|
875
|
+
if (!shouldRetry) {
|
|
876
|
+
return this.executeRequest(endpoint, options);
|
|
877
|
+
}
|
|
878
|
+
return withRetry(() => this.executeRequest(endpoint, options), {
|
|
879
|
+
retries: this.retryConfig.retries,
|
|
880
|
+
baseMs: this.retryConfig.baseMs,
|
|
881
|
+
maxMs: this.retryConfig.maxMs,
|
|
882
|
+
inlineCapMs: this.retryConfig.inlineCapMs,
|
|
883
|
+
shouldRetry: (error) => this.isRetryable(error),
|
|
884
|
+
retryAfterMs: (error) => error instanceof RateLimitError ? error.retryAfterMs : undefined,
|
|
885
|
+
signal: options.signal
|
|
886
|
+
});
|
|
887
|
+
}
|
|
888
|
+
shouldRetry(method, requestRetry) {
|
|
889
|
+
if (this.retryConfig.retries === 0)
|
|
890
|
+
return false;
|
|
891
|
+
if (requestRetry !== undefined)
|
|
892
|
+
return requestRetry;
|
|
893
|
+
return HttpClient.SAFE_METHODS.has(method);
|
|
894
|
+
}
|
|
895
|
+
isRetryable(error) {
|
|
896
|
+
if (error instanceof NetworkError)
|
|
897
|
+
return true;
|
|
898
|
+
if (error instanceof RateLimitError)
|
|
899
|
+
return true;
|
|
900
|
+
if (error instanceof APIError && error.statusCode != null) {
|
|
901
|
+
return this.retryConfig.retryableStatuses.includes(error.statusCode);
|
|
902
|
+
}
|
|
903
|
+
return false;
|
|
904
|
+
}
|
|
905
|
+
async executeRequest(endpoint, options = {}) {
|
|
906
|
+
const {
|
|
907
|
+
method = "GET",
|
|
908
|
+
headers = {},
|
|
909
|
+
body,
|
|
910
|
+
params,
|
|
911
|
+
errorExtractor,
|
|
912
|
+
signal: callerSignal
|
|
913
|
+
} = options;
|
|
914
|
+
let url = `${this.config.baseUrl}${endpoint}`;
|
|
915
|
+
if (params) {
|
|
916
|
+
const searchParams = new URLSearchParams;
|
|
917
|
+
for (const [key, value] of Object.entries(params)) {
|
|
918
|
+
if (value !== undefined) {
|
|
919
|
+
searchParams.set(key, String(value));
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
const queryString = searchParams.toString();
|
|
923
|
+
if (queryString) {
|
|
924
|
+
url += `?${queryString}`;
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
const timeoutSignal = AbortSignal.timeout(this.config.timeout);
|
|
928
|
+
const signal = callerSignal ? AbortSignal.any([callerSignal, timeoutSignal]) : timeoutSignal;
|
|
929
|
+
try {
|
|
930
|
+
const response = await fetch(url, {
|
|
931
|
+
method,
|
|
932
|
+
headers: {
|
|
933
|
+
"Content-Type": "application/json",
|
|
934
|
+
Accept: "application/json",
|
|
935
|
+
...this.config.headers,
|
|
936
|
+
...headers
|
|
937
|
+
},
|
|
938
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
939
|
+
signal
|
|
940
|
+
});
|
|
941
|
+
let json;
|
|
942
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
943
|
+
if (contentType.includes("application/json")) {
|
|
944
|
+
json = await response.json();
|
|
945
|
+
} else {
|
|
946
|
+
const text = await response.text();
|
|
947
|
+
try {
|
|
948
|
+
json = JSON.parse(text);
|
|
949
|
+
} catch {
|
|
950
|
+
json = text;
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
if (!response.ok) {
|
|
954
|
+
const retryAfterMs = response.status === 429 || response.status === 503 ? parseRetryAfter(response.headers.get("retry-after")) : undefined;
|
|
955
|
+
this.handleHttpError(response.status, json, retryAfterMs);
|
|
956
|
+
}
|
|
957
|
+
if (errorExtractor) {
|
|
958
|
+
const extracted = errorExtractor(json);
|
|
959
|
+
if (extracted.hasError) {
|
|
960
|
+
if (extracted.rateLimited) {
|
|
961
|
+
throw new RateLimitError(extracted.message ?? "Carrier rate limit", {
|
|
962
|
+
carrier: this.config.carrier,
|
|
963
|
+
statusCode: 200,
|
|
964
|
+
errors: extracted.errors,
|
|
965
|
+
retryAfterMs: extracted.retryAfterMs,
|
|
966
|
+
raw: json
|
|
967
|
+
});
|
|
968
|
+
}
|
|
969
|
+
throw new APIError(extracted.message ?? "API returned an error", {
|
|
970
|
+
carrier: this.config.carrier,
|
|
971
|
+
statusCode: 200,
|
|
972
|
+
errors: extracted.errors,
|
|
973
|
+
raw: json
|
|
974
|
+
});
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
return json;
|
|
978
|
+
} catch (error) {
|
|
979
|
+
if (error instanceof ShipFlowError) {
|
|
980
|
+
throw error;
|
|
981
|
+
}
|
|
982
|
+
if (callerSignal?.aborted) {
|
|
983
|
+
throw error;
|
|
984
|
+
}
|
|
985
|
+
if (error instanceof DOMException && (error.name === "TimeoutError" || error.name === "AbortError")) {
|
|
986
|
+
throw new NetworkError(`Request timeout after ${this.config.timeout}ms`, {
|
|
987
|
+
carrier: this.config.carrier
|
|
988
|
+
});
|
|
989
|
+
}
|
|
990
|
+
if (error instanceof TypeError && error.message.includes("fetch")) {
|
|
991
|
+
throw new NetworkError(`Network error: ${error.message}`, {
|
|
992
|
+
carrier: this.config.carrier,
|
|
993
|
+
cause: error
|
|
994
|
+
});
|
|
995
|
+
}
|
|
996
|
+
throw new NetworkError(`Unexpected error: ${error.message}`, {
|
|
997
|
+
carrier: this.config.carrier,
|
|
998
|
+
cause: error
|
|
999
|
+
});
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
handleHttpError(status, json, retryAfterMs) {
|
|
1003
|
+
const message = this.extractErrorMessage(json) ?? `HTTP ${status}`;
|
|
1004
|
+
if (status === 401) {
|
|
1005
|
+
throw new AuthenticationError(message, {
|
|
1006
|
+
carrier: this.config.carrier,
|
|
1007
|
+
raw: json
|
|
1008
|
+
});
|
|
1009
|
+
}
|
|
1010
|
+
if (status === 429 || status === 503) {
|
|
1011
|
+
throw new RateLimitError(message, {
|
|
1012
|
+
carrier: this.config.carrier,
|
|
1013
|
+
statusCode: status,
|
|
1014
|
+
errors: this.extractValidationErrors(json),
|
|
1015
|
+
retryAfterMs,
|
|
1016
|
+
raw: json
|
|
1017
|
+
});
|
|
1018
|
+
}
|
|
1019
|
+
throw new APIError(message, {
|
|
1020
|
+
carrier: this.config.carrier,
|
|
1021
|
+
statusCode: status,
|
|
1022
|
+
errors: this.extractValidationErrors(json),
|
|
1023
|
+
raw: json
|
|
1024
|
+
});
|
|
1025
|
+
}
|
|
1026
|
+
extractErrorMessage(json) {
|
|
1027
|
+
if (typeof json === "string")
|
|
1028
|
+
return json.trim() || undefined;
|
|
1029
|
+
if (!json || typeof json !== "object")
|
|
1030
|
+
return;
|
|
1031
|
+
const obj = json;
|
|
1032
|
+
if (typeof obj.message === "string")
|
|
1033
|
+
return obj.message;
|
|
1034
|
+
if (typeof obj.error === "string")
|
|
1035
|
+
return obj.error;
|
|
1036
|
+
if (typeof obj.response === "string")
|
|
1037
|
+
return obj.response;
|
|
1038
|
+
if (obj.Message && typeof obj.Message === "string")
|
|
1039
|
+
return obj.Message;
|
|
1040
|
+
return;
|
|
1041
|
+
}
|
|
1042
|
+
extractValidationErrors(json) {
|
|
1043
|
+
if (!json || typeof json !== "object")
|
|
1044
|
+
return;
|
|
1045
|
+
const obj = json;
|
|
1046
|
+
if (obj.errors && typeof obj.errors === "object") {
|
|
1047
|
+
return obj.errors;
|
|
1048
|
+
}
|
|
1049
|
+
return;
|
|
1050
|
+
}
|
|
1051
|
+
get(endpoint, options) {
|
|
1052
|
+
return this.request(endpoint, { ...options, method: "GET" });
|
|
1053
|
+
}
|
|
1054
|
+
post(endpoint, body, options) {
|
|
1055
|
+
return this.request(endpoint, { ...options, method: "POST", body });
|
|
1056
|
+
}
|
|
1057
|
+
put(endpoint, body, options) {
|
|
1058
|
+
return this.request(endpoint, { ...options, method: "PUT", body });
|
|
1059
|
+
}
|
|
1060
|
+
delete(endpoint, options) {
|
|
1061
|
+
return this.request(endpoint, { ...options, method: "DELETE" });
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
export { ShipFlowError, NetworkError, APIError, RateLimitError, ValidationError, AuthenticationError, WebhookVerificationError, UnsupportedOperationError, AddressSchema, WeightSchema, DimensionsSchema, ParcelSchema, CODDetailsSchema, DeclaredValueSchema, CreateShipmentInputSchema, PickupRequestSchema, WebhookConfigSchema, validateCreateShipmentInput, validatePickupRequest, BaseCarrierAdapter, HttpClient };
|
|
1066
|
+
|
|
1067
|
+
//# debugId=B88EAD18635FEEDC64756E2164756E21
|