@nymbalhq/types 1.4.0 → 1.6.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/LICENSE +21 -0
- package/README.md +5 -0
- package/dist/index.d.ts +690 -76
- package/dist/index.js +164 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -19,7 +19,7 @@ var ConfigError = class extends NymbalError {
|
|
|
19
19
|
};
|
|
20
20
|
var ValidationError = class extends NymbalError {
|
|
21
21
|
constructor(message, options = {}) {
|
|
22
|
-
super("validation.failed", message, options);
|
|
22
|
+
super(options.code ?? "validation.failed", message, options);
|
|
23
23
|
}
|
|
24
24
|
};
|
|
25
25
|
var NotFoundError = class extends NymbalError {
|
|
@@ -63,6 +63,26 @@ var CheckoutError = class extends NymbalError {
|
|
|
63
63
|
super(`checkout.${code}`, message, options);
|
|
64
64
|
}
|
|
65
65
|
};
|
|
66
|
+
var CartLimitError = class extends NymbalError {
|
|
67
|
+
constructor(variantId, max, onCart) {
|
|
68
|
+
super("cart.qty_limit", `a cart line holds at most ${max}`, {
|
|
69
|
+
context: { variantId, max, onCart }
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
var REVIEW_REFUSAL_MESSAGES = {
|
|
74
|
+
submit_unsupported: "This store does not take reviews on its site.",
|
|
75
|
+
already_reviewed: "You have already reviewed this product.",
|
|
76
|
+
not_a_buyer: "Only a customer who bought this product can review it.",
|
|
77
|
+
rejected: "The review was not accepted."
|
|
78
|
+
};
|
|
79
|
+
var ReviewRefusedError = class extends NymbalError {
|
|
80
|
+
refusal;
|
|
81
|
+
constructor(refusal, message = REVIEW_REFUSAL_MESSAGES[refusal], options = {}) {
|
|
82
|
+
super(`reviews.${refusal}`, message, options);
|
|
83
|
+
this.refusal = refusal;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
66
86
|
var StatusTransitionError = class extends NymbalError {
|
|
67
87
|
constructor(entity, fromStatus, toStatus, options = {}) {
|
|
68
88
|
super(
|
|
@@ -150,6 +170,9 @@ var PRODUCT_SORT_LABELS = {
|
|
|
150
170
|
"name-desc": "Name: Z to A"
|
|
151
171
|
};
|
|
152
172
|
|
|
173
|
+
// src/domain/cart.ts
|
|
174
|
+
var CART_LINE_MAX_QTY = 99;
|
|
175
|
+
|
|
153
176
|
// src/domain/order.ts
|
|
154
177
|
var ORDER_STATUS_TRANSITIONS = {
|
|
155
178
|
pending: ["confirmed", "cancelled"],
|
|
@@ -169,7 +192,12 @@ function assertOrderTransition(from, to) {
|
|
|
169
192
|
throw new StatusTransitionError("order", from, to);
|
|
170
193
|
}
|
|
171
194
|
}
|
|
195
|
+
function agentSource(name) {
|
|
196
|
+
return `agent:${name}`;
|
|
197
|
+
}
|
|
172
198
|
var ORDER_KEY_HEADER = "x-nymbal-order-key";
|
|
199
|
+
var ORDER_EMAIL_HEADER = "x-nymbal-order-email";
|
|
200
|
+
var SHOPPER_ATTESTATION_HEADER = "x-nymbal-shopper";
|
|
173
201
|
function paymentState(order) {
|
|
174
202
|
if (order.capturedMinor <= 0) return "unpaid";
|
|
175
203
|
if (order.refundedMinor <= 0) return "paid";
|
|
@@ -213,6 +241,7 @@ var EVT_ORDER_REFUNDED = "order.refunded.v1";
|
|
|
213
241
|
var EVT_ORDER_PARTIALLY_REFUNDED = "order.partially_refunded.v1";
|
|
214
242
|
var EVT_ORDER_STATUS_CHANGED = "order.status_changed.v1";
|
|
215
243
|
var EVT_ORDER_CONFIRMATION_RESEND_REQUESTED = "order.confirmation_resend_requested.v1";
|
|
244
|
+
var EVT_ORDER_DELETED = "order.deleted.v1";
|
|
216
245
|
var EVT_INVENTORY_CHANGED = "inventory.changed.v1";
|
|
217
246
|
var EVT_INVENTORY_RESERVED = "inventory.reserved.v1";
|
|
218
247
|
var EVT_INVENTORY_RELEASED = "inventory.released.v1";
|
|
@@ -234,9 +263,17 @@ var EVT_PAYMENT_CAPTURED = "payment.captured.v1";
|
|
|
234
263
|
var EVT_PAYMENT_FAILED = "payment.failed.v1";
|
|
235
264
|
var EVT_PAYMENT_REFUNDED = "payment.refunded.v1";
|
|
236
265
|
var EVT_ALERT_REQUESTED = "alert.requested.v1";
|
|
266
|
+
var EVT_ALERT_REPEATED = "alert.repeated.v1";
|
|
237
267
|
var EVT_ALERT_CONFIRMED = "alert.confirmed.v1";
|
|
238
268
|
var EVT_ALERT_UNSUBSCRIBED = "alert.unsubscribed.v1";
|
|
239
269
|
var EVT_ALERT_SENT = "alert.sent.v1";
|
|
270
|
+
var EVT_ALERT_CONFIRMATION_SENT = "alert.confirmation_sent.v1";
|
|
271
|
+
var EVT_REVIEW_SUBMITTED = "review.submitted.v1";
|
|
272
|
+
var EVT_PROPOSAL_CREATED = "proposal.created.v1";
|
|
273
|
+
var EVT_PROPOSAL_APPROVED = "proposal.approved.v1";
|
|
274
|
+
var EVT_PROPOSAL_REJECTED = "proposal.rejected.v1";
|
|
275
|
+
var EVT_PROPOSAL_APPLIED = "proposal.applied.v1";
|
|
276
|
+
var EVT_PROPOSAL_FAILED = "proposal.failed.v1";
|
|
240
277
|
var EVT_ADAPTER_ERROR = "adapter.error.v1";
|
|
241
278
|
var EVT_SETTINGS_CHANGED = "settings.changed.v1";
|
|
242
279
|
var STANDARD_EVENT_TYPES = [
|
|
@@ -261,6 +298,7 @@ var STANDARD_EVENT_TYPES = [
|
|
|
261
298
|
EVT_ORDER_PARTIALLY_REFUNDED,
|
|
262
299
|
EVT_ORDER_STATUS_CHANGED,
|
|
263
300
|
EVT_ORDER_CONFIRMATION_RESEND_REQUESTED,
|
|
301
|
+
EVT_ORDER_DELETED,
|
|
264
302
|
EVT_INVENTORY_CHANGED,
|
|
265
303
|
EVT_INVENTORY_RESERVED,
|
|
266
304
|
EVT_INVENTORY_RELEASED,
|
|
@@ -281,9 +319,17 @@ var STANDARD_EVENT_TYPES = [
|
|
|
281
319
|
EVT_PAYMENT_FAILED,
|
|
282
320
|
EVT_PAYMENT_REFUNDED,
|
|
283
321
|
EVT_ALERT_REQUESTED,
|
|
322
|
+
EVT_ALERT_REPEATED,
|
|
284
323
|
EVT_ALERT_CONFIRMED,
|
|
285
324
|
EVT_ALERT_UNSUBSCRIBED,
|
|
286
325
|
EVT_ALERT_SENT,
|
|
326
|
+
EVT_ALERT_CONFIRMATION_SENT,
|
|
327
|
+
EVT_REVIEW_SUBMITTED,
|
|
328
|
+
EVT_PROPOSAL_CREATED,
|
|
329
|
+
EVT_PROPOSAL_APPROVED,
|
|
330
|
+
EVT_PROPOSAL_REJECTED,
|
|
331
|
+
EVT_PROPOSAL_APPLIED,
|
|
332
|
+
EVT_PROPOSAL_FAILED,
|
|
287
333
|
EVT_ADAPTER_ERROR,
|
|
288
334
|
EVT_SETTINGS_CHANGED
|
|
289
335
|
];
|
|
@@ -354,7 +400,7 @@ async function boundedHealthCheck(check, options = {}) {
|
|
|
354
400
|
}
|
|
355
401
|
|
|
356
402
|
// src/adapters/document-order.ts
|
|
357
|
-
var collator
|
|
403
|
+
var collator;
|
|
358
404
|
function rankOf(value) {
|
|
359
405
|
if (typeof value === "number") return 0;
|
|
360
406
|
if (typeof value === "string") return 1;
|
|
@@ -381,6 +427,7 @@ function compareDocumentValues(a, b) {
|
|
|
381
427
|
case 0:
|
|
382
428
|
return sign(a - b);
|
|
383
429
|
case 1:
|
|
430
|
+
collator ??= new Intl.Collator(void 0, { sensitivity: "base" });
|
|
384
431
|
return sign(collator.compare(a, b));
|
|
385
432
|
case 2:
|
|
386
433
|
return sign(compareOther(a, b));
|
|
@@ -512,6 +559,9 @@ function buildSecurityHeaders(security) {
|
|
|
512
559
|
return headers;
|
|
513
560
|
}
|
|
514
561
|
|
|
562
|
+
// src/adapters/commerce.ts
|
|
563
|
+
var SHIPPING_CAPABILITIES = ["rates", "labels", "tracking"];
|
|
564
|
+
|
|
515
565
|
// src/adapters/webhook-delivery.ts
|
|
516
566
|
var VERSIONED_EVENT = /^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)*\.v[1-9][0-9]*$/;
|
|
517
567
|
function isPlainObject(value) {
|
|
@@ -545,6 +595,82 @@ function webhookDeliveryProblem(providerName, producesEvents, delivery) {
|
|
|
545
595
|
return null;
|
|
546
596
|
}
|
|
547
597
|
|
|
598
|
+
// src/adapters/email-feedback.ts
|
|
599
|
+
function emailFeedbackType(providerName, what) {
|
|
600
|
+
return `${providerName}.${what}.v1`;
|
|
601
|
+
}
|
|
602
|
+
function payloadOf(event) {
|
|
603
|
+
const payload = event?.payload;
|
|
604
|
+
return typeof payload === "object" && payload !== null ? payload : {};
|
|
605
|
+
}
|
|
606
|
+
function emailFeedbackProblem(providerName, delivery) {
|
|
607
|
+
const bounced = emailFeedbackType(providerName, "bounced");
|
|
608
|
+
const complained = emailFeedbackType(providerName, "complained");
|
|
609
|
+
if (!Array.isArray(delivery.events)) return null;
|
|
610
|
+
for (const event of delivery.events) {
|
|
611
|
+
const type = event?.type;
|
|
612
|
+
if (type !== bounced && type !== complained) continue;
|
|
613
|
+
const payload = payloadOf(event);
|
|
614
|
+
const { recipient, messageId, occurredAt } = payload;
|
|
615
|
+
if (typeof recipient !== "string" || recipient.trim() === "") {
|
|
616
|
+
return { type, reason: "the recipient is missing or empty" };
|
|
617
|
+
}
|
|
618
|
+
if (type === bounced && payload["bounce"] !== "hard" && payload["bounce"] !== "soft") {
|
|
619
|
+
return { type, reason: "the bounce is neither 'hard' nor 'soft'" };
|
|
620
|
+
}
|
|
621
|
+
if (messageId !== null && typeof messageId !== "string") {
|
|
622
|
+
return { type, reason: "the messageId is neither a string nor null" };
|
|
623
|
+
}
|
|
624
|
+
if (typeof occurredAt !== "string" || Number.isNaN(Date.parse(occurredAt))) {
|
|
625
|
+
return { type, reason: "occurredAt is not a readable date" };
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
return null;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
// src/adapters/shipping-tracking.ts
|
|
632
|
+
var SHIPPING_TRACKING_STATUSES = [
|
|
633
|
+
"pre_transit",
|
|
634
|
+
"in_transit",
|
|
635
|
+
"out_for_delivery",
|
|
636
|
+
"delivered",
|
|
637
|
+
"exception",
|
|
638
|
+
"returned",
|
|
639
|
+
"unknown"
|
|
640
|
+
];
|
|
641
|
+
function shippingTrackingType(providerName) {
|
|
642
|
+
return `${providerName}.tracking.v1`;
|
|
643
|
+
}
|
|
644
|
+
function normaliseTrackingNumber(value) {
|
|
645
|
+
return value.replace(/\s+/g, "").toUpperCase();
|
|
646
|
+
}
|
|
647
|
+
function payloadOf2(event) {
|
|
648
|
+
const payload = event?.payload;
|
|
649
|
+
return typeof payload === "object" && payload !== null ? payload : {};
|
|
650
|
+
}
|
|
651
|
+
function shippingTrackingProblem(providerName, delivery) {
|
|
652
|
+
const tracking = shippingTrackingType(providerName);
|
|
653
|
+
if (!Array.isArray(delivery.events)) return null;
|
|
654
|
+
for (const event of delivery.events) {
|
|
655
|
+
const type = event?.type;
|
|
656
|
+
if (type !== tracking) continue;
|
|
657
|
+
const { trackingNumber, carrier, status, occurredAt } = payloadOf2(event);
|
|
658
|
+
if (typeof trackingNumber !== "string" || normaliseTrackingNumber(trackingNumber) === "") {
|
|
659
|
+
return { type, reason: "the trackingNumber is missing or empty" };
|
|
660
|
+
}
|
|
661
|
+
if (carrier !== null && typeof carrier !== "string") {
|
|
662
|
+
return { type, reason: "the carrier is neither a string nor null" };
|
|
663
|
+
}
|
|
664
|
+
if (!SHIPPING_TRACKING_STATUSES.includes(status)) {
|
|
665
|
+
return { type, reason: "the status is not one of the tracking statuses" };
|
|
666
|
+
}
|
|
667
|
+
if (typeof occurredAt !== "string" || Number.isNaN(Date.parse(occurredAt))) {
|
|
668
|
+
return { type, reason: "occurredAt is not a readable date" };
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
return null;
|
|
672
|
+
}
|
|
673
|
+
|
|
548
674
|
// src/adapters/email-templates.ts
|
|
549
675
|
function render(template, vars) {
|
|
550
676
|
return template.replace(/\{\{\s*([\w.]+)\s*\}\}/g, (_, path) => {
|
|
@@ -572,10 +698,14 @@ We'll let you know when it ships.{{orderLink}}`
|
|
|
572
698
|
},
|
|
573
699
|
"order-shipped": {
|
|
574
700
|
subject: "Order {{orderNumber}} is on its way",
|
|
701
|
+
// `trackingLink` and `orderLink` are whole paragraphs, absent for an unknown carrier or a store with no URL.
|
|
575
702
|
body: `Hi {{customerName}},
|
|
576
703
|
|
|
577
704
|
Your order {{orderNumber}} has shipped via {{carrier}}.
|
|
578
|
-
Tracking: {{trackingNumber}}
|
|
705
|
+
Tracking: {{trackingNumber}}{{trackingLink}}
|
|
706
|
+
|
|
707
|
+
In this parcel:
|
|
708
|
+
{{itemsList}}{{orderLink}}`
|
|
579
709
|
},
|
|
580
710
|
welcome: {
|
|
581
711
|
subject: "Welcome to {{storeName}}",
|
|
@@ -670,16 +800,28 @@ var IDEMPOTENT_REPLAYED_HEADER = "idempotent-replayed";
|
|
|
670
800
|
function isValidIdempotencyKey(value) {
|
|
671
801
|
return /^[A-Za-z0-9._:-]{1,128}$/.test(value);
|
|
672
802
|
}
|
|
803
|
+
|
|
804
|
+
// src/proposals.ts
|
|
805
|
+
var PREVIEWED_COMMANDS = [
|
|
806
|
+
"product.update",
|
|
807
|
+
"inventory.adjust",
|
|
808
|
+
"order.refund",
|
|
809
|
+
"order.cancel"
|
|
810
|
+
];
|
|
673
811
|
export {
|
|
674
812
|
AdapterError,
|
|
675
813
|
AuthError,
|
|
814
|
+
CART_LINE_MAX_QTY,
|
|
676
815
|
CORRELATION_ID_HEADER,
|
|
816
|
+
CartLimitError,
|
|
677
817
|
CheckoutError,
|
|
678
818
|
ConfigError,
|
|
679
819
|
DEFAULT_PRODUCT_SORT,
|
|
680
820
|
DEFAULT_QUERY_LIMIT,
|
|
681
821
|
EVT_ADAPTER_ERROR,
|
|
822
|
+
EVT_ALERT_CONFIRMATION_SENT,
|
|
682
823
|
EVT_ALERT_CONFIRMED,
|
|
824
|
+
EVT_ALERT_REPEATED,
|
|
683
825
|
EVT_ALERT_REQUESTED,
|
|
684
826
|
EVT_ALERT_SENT,
|
|
685
827
|
EVT_ALERT_UNSUBSCRIBED,
|
|
@@ -703,6 +845,7 @@ export {
|
|
|
703
845
|
EVT_INVENTORY_RESERVED,
|
|
704
846
|
EVT_ORDER_CANCELLED,
|
|
705
847
|
EVT_ORDER_CONFIRMATION_RESEND_REQUESTED,
|
|
848
|
+
EVT_ORDER_DELETED,
|
|
706
849
|
EVT_ORDER_DELIVERED,
|
|
707
850
|
EVT_ORDER_FULFILLED,
|
|
708
851
|
EVT_ORDER_PAID,
|
|
@@ -723,6 +866,12 @@ export {
|
|
|
723
866
|
EVT_PRODUCT_UPDATED,
|
|
724
867
|
EVT_PRODUCT_VARIANT_PRICE_CHANGED,
|
|
725
868
|
EVT_PRODUCT_VIEWED,
|
|
869
|
+
EVT_PROPOSAL_APPLIED,
|
|
870
|
+
EVT_PROPOSAL_APPROVED,
|
|
871
|
+
EVT_PROPOSAL_CREATED,
|
|
872
|
+
EVT_PROPOSAL_FAILED,
|
|
873
|
+
EVT_PROPOSAL_REJECTED,
|
|
874
|
+
EVT_REVIEW_SUBMITTED,
|
|
726
875
|
EVT_SETTINGS_CHANGED,
|
|
727
876
|
EVT_VISITOR_MERGED,
|
|
728
877
|
HEALTH_CHECK_TIMEOUT_MS,
|
|
@@ -731,19 +880,26 @@ export {
|
|
|
731
880
|
IDEMPOTENT_REPLAYED_HEADER,
|
|
732
881
|
NotFoundError,
|
|
733
882
|
NymbalError,
|
|
883
|
+
ORDER_EMAIL_HEADER,
|
|
734
884
|
ORDER_KEY_HEADER,
|
|
735
885
|
ORDER_STATUS_TRANSITIONS,
|
|
736
886
|
ORDER_TIMELINE_KINDS,
|
|
737
887
|
OrderConflictError,
|
|
888
|
+
PREVIEWED_COMMANDS,
|
|
738
889
|
PRODUCT_SORT_KEYS,
|
|
739
890
|
PRODUCT_SORT_LABELS,
|
|
740
891
|
PaymentError,
|
|
892
|
+
ReviewRefusedError,
|
|
741
893
|
SECRET_MIN_LENGTH,
|
|
894
|
+
SHIPPING_CAPABILITIES,
|
|
895
|
+
SHIPPING_TRACKING_STATUSES,
|
|
896
|
+
SHOPPER_ATTESTATION_HEADER,
|
|
742
897
|
STANDARD_EVENT_TYPES,
|
|
743
898
|
STOCK_LABELS,
|
|
744
899
|
StatusTransitionError,
|
|
745
900
|
ValidationError,
|
|
746
901
|
add,
|
|
902
|
+
agentSource,
|
|
747
903
|
allocate,
|
|
748
904
|
assertMinorUnits,
|
|
749
905
|
assertOrderTransition,
|
|
@@ -754,6 +910,8 @@ export {
|
|
|
754
910
|
connectionSecrets,
|
|
755
911
|
displayUrl,
|
|
756
912
|
documentValueAt,
|
|
913
|
+
emailFeedbackProblem,
|
|
914
|
+
emailFeedbackType,
|
|
757
915
|
errorText,
|
|
758
916
|
handlerFailedError,
|
|
759
917
|
isValidCorrelationId,
|
|
@@ -761,10 +919,13 @@ export {
|
|
|
761
919
|
matchesSortKey,
|
|
762
920
|
money,
|
|
763
921
|
mulBy,
|
|
922
|
+
normaliseTrackingNumber,
|
|
764
923
|
paymentState,
|
|
765
924
|
queryDocuments,
|
|
766
925
|
refundableMinor,
|
|
767
926
|
renderEmailTemplate,
|
|
927
|
+
shippingTrackingProblem,
|
|
928
|
+
shippingTrackingType,
|
|
768
929
|
stockLevel,
|
|
769
930
|
sub,
|
|
770
931
|
sumMoney,
|