@rebuy/rebuy 3.35.0 → 3.37.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.
Files changed (42) hide show
  1. package/dist/index.cjs +799 -648
  2. package/dist/index.mjs +799 -648
  3. package/dist/schema/index.d.ts +4 -0
  4. package/dist/schema/postPurchaseGroup.d.ts +15 -0
  5. package/dist/schema/postPurchaseProduct.d.ts +102 -24
  6. package/dist/schema/postPurchaseProductCalculation.d.ts +87 -0
  7. package/dist/schema/postPurchaseProductCollectionView.d.ts +738 -3
  8. package/dist/schema/postPurchaseProductDisplay.d.ts +57 -16
  9. package/dist/schema/postPurchaseProductReviews.d.ts +36 -0
  10. package/dist/schema/postPurchaseProductView.d.ts +722 -0
  11. package/dist/schema/postPurchaseQuantity.d.ts +16 -3
  12. package/dist/schema/postPurchaseSubscriptionProduct.d.ts +98 -17
  13. package/dist/server/__fixtures__/postPurchaseGroup.d.ts +3 -0
  14. package/dist/server/__fixtures__/postPurchaseReviewProviders.d.ts +30 -0
  15. package/dist/server/__fixtures__/postPurchaseReviews.d.ts +67 -0
  16. package/dist/server/index.cjs +1014 -348
  17. package/dist/server/index.d.ts +13 -2
  18. package/dist/server/index.mjs +1014 -348
  19. package/dist/server/postPurchaseJudgeMeReviews.d.ts +6 -0
  20. package/dist/server/postPurchaseOkendoReviews.d.ts +6 -0
  21. package/dist/server/postPurchaseProductDisplay.d.ts +49 -7
  22. package/dist/server/postPurchaseReviewData.d.ts +7 -0
  23. package/dist/server/postPurchaseReviewFields.d.ts +7 -0
  24. package/dist/server/postPurchaseReviewProvider.d.ts +2 -0
  25. package/dist/server/postPurchaseReviews.d.ts +5 -0
  26. package/dist/server/postPurchaseScalarReviews.d.ts +6 -0
  27. package/dist/server/prepareNormalizedSubscription.d.ts +2 -2
  28. package/dist/server/preparePostPurchaseAdmissionView.d.ts +428 -0
  29. package/dist/server/preparePostPurchaseCollectionGroup.d.ts +468 -0
  30. package/dist/server/preparePostPurchaseCollectionView.d.ts +452 -0
  31. package/dist/server/preparePostPurchaseGroupAdmissionView.d.ts +469 -0
  32. package/dist/server/preparePostPurchaseGroupDefault.d.ts +469 -0
  33. package/dist/server/preparePostPurchaseGroupView.d.ts +468 -0
  34. package/dist/server/preparePostPurchaseMemberView.d.ts +1496 -0
  35. package/dist/server/preparePostPurchaseProduct.d.ts +8 -0
  36. package/dist/server/preparePostPurchaseQuantityAdmissionView.d.ts +450 -0
  37. package/dist/server/preparePostPurchaseQuantityView.d.ts +437 -0
  38. package/dist/server/preparePostPurchaseSubscription.d.ts +47 -5
  39. package/dist/server/preparePostPurchaseView.d.ts +8 -0
  40. package/dist/server/projectPostPurchaseProduct.d.ts +49 -6
  41. package/dist/transforms/postPurchase/convertDescriptionRte.d.ts +11 -0
  42. package/package.json +1 -1
@@ -47,9 +47,20 @@ __export(server_exports, {
47
47
  fetchMonetizeOffers: () => fetchMonetizeOffers,
48
48
  fetchUserConfig: () => fetchUserConfig,
49
49
  postAnalyticsEvents: () => postAnalyticsEvents,
50
+ preparePostPurchaseAdmissionView: () => preparePostPurchaseAdmissionView,
51
+ preparePostPurchaseCollectionView: () => preparePostPurchaseCollectionView,
52
+ preparePostPurchaseGroupAdmissionView: () => preparePostPurchaseGroupAdmissionView,
50
53
  preparePostPurchaseGroupDeclineDisplay: () => preparePostPurchaseGroupDeclineDisplay,
54
+ preparePostPurchaseGroupDefault: () => preparePostPurchaseGroupDefault,
55
+ preparePostPurchaseGroupView: () => preparePostPurchaseGroupView,
56
+ preparePostPurchaseMemberAdmissionView: () => preparePostPurchaseMemberAdmissionView,
57
+ preparePostPurchaseMemberView: () => preparePostPurchaseMemberView,
51
58
  preparePostPurchaseOfferPresentation: () => preparePostPurchaseOfferPresentation,
59
+ preparePostPurchaseProduct: () => preparePostPurchaseProduct,
60
+ preparePostPurchaseQuantityAdmissionView: () => preparePostPurchaseQuantityAdmissionView,
61
+ preparePostPurchaseQuantityView: () => preparePostPurchaseQuantityView,
52
62
  preparePostPurchaseSubscription: () => preparePostPurchaseSubscription,
63
+ preparePostPurchaseView: () => preparePostPurchaseView,
53
64
  readPostPurchaseGroupSelection: () => readPostPurchaseGroupSelection,
54
65
  readPostPurchaseQuantity: () => readPostPurchaseQuantity,
55
66
  translateAnalyticsEvent: () => translateAnalyticsEvent,
@@ -2178,7 +2189,7 @@ var stripContentBlockHtml = (text2) => text2.replace(HTML_COMMENT_RE, "").replac
2178
2189
  var convertTextToTiptapParagraph = ({
2179
2190
  color,
2180
2191
  fontSize,
2181
- marks = [],
2192
+ marks: marks2 = [],
2182
2193
  text: text2,
2183
2194
  textAlign
2184
2195
  }) => {
@@ -2187,7 +2198,7 @@ var convertTextToTiptapParagraph = ({
2187
2198
  attrs: { textAlign },
2188
2199
  content: sanitizedText ? [
2189
2200
  {
2190
- marks: [{ attrs: { color, fontSize }, type: "textStyle" }, ...marks],
2201
+ marks: [{ attrs: { color, fontSize }, type: "textStyle" }, ...marks2],
2191
2202
  text: sanitizedText,
2192
2203
  type: "text"
2193
2204
  }
@@ -2644,11 +2655,11 @@ var pushText = (state, rawText) => {
2644
2655
  decodeTextEntities(rawText).split("\n").forEach((segment, index) => {
2645
2656
  if (index > 0) flushParagraph(state);
2646
2657
  if (!segment) return;
2647
- const marks = state.stack.flatMap((entry) => entry.marks);
2648
- if (state.defaultTextStyleMark && !marks.some((mark) => mark.type === "textStyle")) {
2649
- marks.push(state.defaultTextStyleMark);
2658
+ const marks2 = state.stack.flatMap((entry) => entry.marks);
2659
+ if (state.defaultTextStyleMark && !marks2.some((mark) => mark.type === "textStyle")) {
2660
+ marks2.push(state.defaultTextStyleMark);
2650
2661
  }
2651
- state.currentRuns.push(TiptapText.parse(marks.length > 0 ? { marks, text: segment } : { text: segment }));
2662
+ state.currentRuns.push(TiptapText.parse(marks2.length > 0 ? { marks: marks2, text: segment } : { text: segment }));
2652
2663
  });
2653
2664
  };
2654
2665
 
@@ -3223,10 +3234,10 @@ var SWITCH_LABEL_TOKENS2 = ["subscriptionDiscount", "frequency", "interval"];
3223
3234
  var QUANTITY_ERROR_TOKENS = ["max", "min", "step"];
3224
3235
  var VARIANT_SELECTOR = { button: "button", radio: "radio", select: "menu" };
3225
3236
  var buildStyledText = (token, style, fontSize = style?.textSize ?? "base") => {
3226
- const marks = [{ attrs: { color: "base", fontSize }, type: "textStyle" }];
3227
- if (style?.textEmphasis === "bold") marks.push({ type: "bold" });
3228
- if (style?.textEmphasis === "italic") marks.push({ type: "italic" });
3229
- return { content: [{ content: [{ marks, text: token, type: "text" }], type: "paragraph" }], type: "doc" };
3237
+ const marks2 = [{ attrs: { color: "base", fontSize }, type: "textStyle" }];
3238
+ if (style?.textEmphasis === "bold") marks2.push({ type: "bold" });
3239
+ if (style?.textEmphasis === "italic") marks2.push({ type: "italic" });
3240
+ return { content: [{ content: [{ marks: marks2, text: token, type: "text" }], type: "paragraph" }], type: "doc" };
3230
3241
  };
3231
3242
  var buildPriceContent = () => ({
3232
3243
  content: [
@@ -5948,13 +5959,13 @@ var projectPostPurchasePlanCatalog = (normalized, report) => {
5948
5959
  };
5949
5960
 
5950
5961
  // src/schema/postPurchaseSubscriptionProduct.ts
5951
- var import_zod54 = require("zod");
5962
+ var import_zod55 = require("zod");
5952
5963
 
5953
5964
  // src/schema/postPurchaseProduct.ts
5954
- var import_zod53 = require("zod");
5965
+ var import_zod54 = require("zod");
5955
5966
 
5956
5967
  // src/schema/postPurchaseProductDisplay.ts
5957
- var import_zod51 = require("zod");
5968
+ var import_zod52 = require("zod");
5958
5969
 
5959
5970
  // src/schema/postPurchaseProductGallery.ts
5960
5971
  var import_zod50 = require("zod");
@@ -5970,21 +5981,44 @@ var PostPurchaseProductGallery = import_zod50.z.object({
5970
5981
  selectedImageId: import_zod50.z.number().int().positive().optional()
5971
5982
  });
5972
5983
 
5984
+ // src/schema/postPurchaseProductReviews.ts
5985
+ var import_zod51 = require("zod");
5986
+ var decimal = import_zod51.z.union([
5987
+ import_zod51.z.number(),
5988
+ import_zod51.z.string().regex(/^\d+(?:\.\d+)?$/).transform(Number)
5989
+ ]);
5990
+ var PostPurchaseCommonReviewRating = import_zod51.z.object({ value: decimal.pipe(import_zod51.z.number().min(0).max(5)) });
5991
+ var PostPurchaseKlaviyoReviewRating = PostPurchaseCommonReviewRating.extend({
5992
+ // Legacy validates key presence, then displays the raw value on five stars without rescaling.
5993
+ scale_max: import_zod51.z.unknown().nonoptional(),
5994
+ scale_min: import_zod51.z.unknown().nonoptional()
5995
+ });
5996
+ var PostPurchaseReviewCount = import_zod51.z.string().regex(/^\d+(?:\.\d+)?$/).transform(Number).pipe(import_zod51.z.number().int().nonnegative());
5997
+ var PostPurchaseReviewStyles = PostPurchaseSettings.shape.styles.unwrap().extend({
5998
+ strokeWidth: decimal.pipe(import_zod51.z.number().nonnegative()).default(1)
5999
+ }).prefault({});
6000
+ var PostPurchaseProductReviews = import_zod51.z.object({
6001
+ color: import_zod51.z.string(),
6002
+ rating: import_zod51.z.number().positive().max(5),
6003
+ reviewCount: import_zod51.z.number().int().nonnegative(),
6004
+ reviewsPlural: import_zod51.z.string(),
6005
+ reviewsSingular: import_zod51.z.string(),
6006
+ size: import_zod51.z.enum(["small", "medium", "large"]),
6007
+ strokeColor: import_zod51.z.string(),
6008
+ strokeWidth: import_zod51.z.number().nonnegative()
6009
+ });
6010
+
5973
6011
  // src/schema/postPurchaseProductDisplay.ts
5974
6012
  var language = PostPurchaseSettings.shape.language;
5975
- var PostPurchasePrimaryImageSource = import_zod51.z.string().default(
6013
+ var PostPurchasePrimaryImageSource = import_zod52.z.string().default(
5976
6014
  "https://cdn.shopify.com/shopifycloud/shopify/assets/no-image-2048-5e88c1b20e087fb7bbe9a3771824e743c244f437e4f8ba93bbf7b11b53f7824c.gif"
5977
6015
  );
5978
- var PostPurchaseProductDisplay = import_zod51.z.object({
6016
+ var PostPurchaseProductDisplay = import_zod52.z.object({
6017
+ descriptionDocument: TiptapDocument.optional(),
5979
6018
  discountedFrom: PostPurchaseSettings.shape.discountedFrom,
5980
6019
  gallery: PostPurchaseProductGallery.optional(),
5981
- language: language.pick({
5982
- description: true,
5983
- descriptionEnabled: true,
5984
- descriptionRte: true,
5985
- descriptionSpacing: true
5986
- }),
5987
- primaryImage: import_zod51.z.object({ description: import_zod51.z.string(), source: import_zod51.z.string() }),
6020
+ language: language.pick({ description: true, descriptionEnabled: true }),
6021
+ primaryImage: import_zod52.z.object({ description: import_zod52.z.string(), source: import_zod52.z.string() }),
5988
6022
  productOptions: PostPurchaseSettings.shape.productOptions.pick({
5989
6023
  showDeclineAll: true,
5990
6024
  showShipping: true,
@@ -5994,18 +6028,19 @@ var PostPurchaseProductDisplay = import_zod51.z.object({
5994
6028
  showVariantSelectors: true
5995
6029
  }),
5996
6030
  responseDescription: language.shape.description,
6031
+ reviews: PostPurchaseProductReviews.nullable().default(null),
5997
6032
  shouldShowSavingText: PostPurchaseSettings.shape.discount.shape.shouldShowSavingText
5998
6033
  });
5999
6034
 
6000
6035
  // src/schema/postPurchaseSubscription.ts
6001
- var import_zod52 = require("zod");
6002
- var PostPurchaseSubscriptionTerms = import_zod52.z.object({
6036
+ var import_zod53 = require("zod");
6037
+ var PostPurchaseSubscriptionTerms = import_zod53.z.object({
6003
6038
  adjustment: PostPurchasePlanAdjustment.optional(),
6004
- initialShippingPrice: import_zod52.z.number().nonnegative(),
6005
- intervalLabel: import_zod52.z.string().min(1),
6006
- name: import_zod52.z.string().min(1),
6007
- recurringShippingPrice: import_zod52.z.number().nonnegative(),
6008
- shippingOption: import_zod52.z.object({ presentmentTitle: import_zod52.z.string(), title: import_zod52.z.string() })
6039
+ initialShippingPrice: import_zod53.z.number().nonnegative(),
6040
+ intervalLabel: import_zod53.z.string().min(1),
6041
+ name: import_zod53.z.string().min(1),
6042
+ recurringShippingPrice: import_zod53.z.number().nonnegative(),
6043
+ shippingOption: import_zod53.z.object({ presentmentTitle: import_zod53.z.string(), title: import_zod53.z.string() })
6009
6044
  });
6010
6045
 
6011
6046
  // src/schema/postPurchaseProduct.ts
@@ -6015,51 +6050,51 @@ var PostPurchaseVariant = OfferProduct.shape.variants.element.pick({ id: true, t
6015
6050
  id: PostPurchaseVariantId,
6016
6051
  price: PostPurchaseAmount
6017
6052
  });
6018
- var PreparedPostPurchaseProduct = import_zod53.z.object({
6053
+ var PreparedPostPurchaseProduct = import_zod54.z.object({
6019
6054
  display: PostPurchaseProductDisplay,
6020
- labels: import_zod53.z.object({
6055
+ labels: import_zod54.z.object({
6021
6056
  declineAll: global.declineAll,
6022
- free: import_zod53.z.string(),
6023
- payNow: import_zod53.z.string(),
6024
- quantity: import_zod53.z.string(),
6057
+ free: import_zod54.z.string(),
6058
+ payNow: import_zod54.z.string(),
6059
+ quantity: import_zod54.z.string(),
6025
6060
  recurringShipping: global.recurringShipping,
6026
6061
  recurringSubtotal: global.recurringSubtotal,
6027
- save: import_zod53.z.string(),
6028
- shipping: import_zod53.z.string(),
6029
- subtotal: import_zod53.z.string(),
6030
- taxes: import_zod53.z.string(),
6031
- total: import_zod53.z.string()
6062
+ save: import_zod54.z.string(),
6063
+ shipping: import_zod54.z.string(),
6064
+ subtotal: import_zod54.z.string(),
6065
+ taxes: import_zod54.z.string(),
6066
+ total: import_zod54.z.string()
6032
6067
  }),
6033
6068
  product: OfferProduct.pick({ description: true, id: true, image: true, title: true }).extend({
6034
6069
  description: OfferProduct.shape.description.nullable(),
6035
6070
  id: PostPurchaseProductId,
6036
6071
  variant: PostPurchaseVariant
6037
6072
  }),
6038
- selection: import_zod53.z.object({
6073
+ selection: import_zod54.z.object({
6039
6074
  productId: PostPurchaseProductId,
6040
- quantity: import_zod53.z.number().int().positive(),
6041
- sellingPlanId: import_zod53.z.number().int().positive().optional(),
6075
+ quantity: import_zod54.z.number().int().positive(),
6076
+ sellingPlanId: import_zod54.z.number().int().positive().optional(),
6042
6077
  variantId: PostPurchaseVariantId
6043
6078
  }),
6044
- status: import_zod53.z.literal("prepared"),
6045
- terms: import_zod53.z.object({
6079
+ status: import_zod54.z.literal("prepared"),
6080
+ terms: import_zod54.z.object({
6046
6081
  discount: PostPurchaseDiscount,
6047
- shipping: import_zod53.z.object({
6048
- amount: import_zod53.z.number().nonnegative(),
6049
- title: import_zod53.z.string(),
6050
- type: import_zod53.z.enum(["free", "fixed_amount"])
6082
+ shipping: import_zod54.z.object({
6083
+ amount: import_zod54.z.number().nonnegative(),
6084
+ title: import_zod54.z.string(),
6085
+ type: import_zod54.z.enum(["free", "fixed_amount"])
6051
6086
  }),
6052
6087
  subscription: PostPurchaseSubscriptionTerms.optional()
6053
6088
  })
6054
6089
  });
6055
- var PostPurchasePreparation = import_zod53.z.discriminatedUnion("status", [
6090
+ var PostPurchasePreparation = import_zod54.z.discriminatedUnion("status", [
6056
6091
  PreparedPostPurchaseProduct,
6057
- import_zod53.z.object({ reason: import_zod53.z.string(), status: import_zod53.z.literal("unsupported") })
6092
+ import_zod54.z.object({ reason: import_zod54.z.string(), status: import_zod54.z.literal("unsupported") })
6058
6093
  ]);
6059
6094
 
6060
6095
  // src/schema/postPurchaseSubscriptionProduct.ts
6061
6096
  var PreparedPostPurchaseSubscription = PreparedPostPurchaseProduct.extend({
6062
- selection: PreparedPostPurchaseProduct.shape.selection.extend({ sellingPlanId: import_zod54.z.number().int().positive() }),
6097
+ selection: PreparedPostPurchaseProduct.shape.selection.extend({ sellingPlanId: import_zod55.z.number().int().positive() }),
6063
6098
  terms: PreparedPostPurchaseProduct.shape.terms.extend({
6064
6099
  subscription: PostPurchaseSubscriptionTerms
6065
6100
  }).refine(
@@ -6101,7 +6136,7 @@ var subscriptionUnavailable = (normalized, plan, allowCollection, quantity2) =>
6101
6136
  };
6102
6137
 
6103
6138
  // src/server/postPurchaseProductDisplay.ts
6104
- var import_zod55 = require("zod");
6139
+ var import_zod57 = require("zod");
6105
6140
 
6106
6141
  // src/server/postPurchasePrimaryImage.ts
6107
6142
  var postPurchasePrimaryImage = (product) => {
@@ -6122,9 +6157,67 @@ var postPurchaseProductGallery = (product, limit) => ({
6122
6157
  selectedImageId: product.images?.find((image) => image.id === product.variants[0].imageId)?.id
6123
6158
  });
6124
6159
 
6160
+ // src/transforms/postPurchase/convertDescriptionRte.ts
6161
+ var import_zod56 = require("zod");
6162
+ var alignments = { center: "center", left: "start", right: "end" };
6163
+ var colors = ["critical", "subdued", "success", "warning"];
6164
+ var sizes2 = ["extraSmall", "small", "medium", "large", "extraLarge"];
6165
+ var spacings2 = {
6166
+ default: "base",
6167
+ loose: "loose",
6168
+ none: "none",
6169
+ tight: "tight",
6170
+ xloose: "extraLoose",
6171
+ xtight: "extraTight"
6172
+ };
6173
+ var Block = import_zod56.z.object({
6174
+ attrs: import_zod56.z.object({ alignment: import_zod56.z.enum(["left", "center", "right"]).optional().catch(void 0) }).catch({}),
6175
+ content: import_zod56.z.array(import_zod56.z.unknown()).catch([]),
6176
+ type: import_zod56.z.literal("ShopifyTextBlock")
6177
+ });
6178
+ var Run = import_zod56.z.object({ marks: import_zod56.z.array(import_zod56.z.unknown()).catch([]), text: import_zod56.z.string().min(1), type: import_zod56.z.literal("text") });
6179
+ var Inline = import_zod56.z.object({
6180
+ attrs: import_zod56.z.object({
6181
+ color: import_zod56.z.enum(colors).optional().catch(void 0),
6182
+ emphasis: import_zod56.z.array(import_zod56.z.unknown()).catch([]),
6183
+ size: import_zod56.z.enum(sizes2).optional().catch(void 0)
6184
+ }),
6185
+ type: import_zod56.z.literal("ShopifyTextInline")
6186
+ });
6187
+ var marks = (raw) => {
6188
+ const found = raw.map((mark) => Inline.safeParse(mark)).find(({ success }) => success)?.data;
6189
+ if (!found) return [];
6190
+ const { color = "base", emphasis, size = "base" } = found.attrs;
6191
+ return [
6192
+ ...emphasis.includes("bold") ? [{ type: "bold" }] : [],
6193
+ ...emphasis.includes("strikethrough") ? [{ type: "strike" }] : [],
6194
+ { attrs: { color, fontSize: size }, type: "textStyle" }
6195
+ ];
6196
+ };
6197
+ var convertDescriptionRte = (rte, spacing) => TiptapDocument.parse({
6198
+ attrs: { blockSpacing: spacings2[spacing ?? "none"] },
6199
+ content: rte.content.flatMap((node) => {
6200
+ const block = Block.safeParse(node);
6201
+ if (!block.success) return [];
6202
+ const { alignment } = block.data.attrs;
6203
+ return [
6204
+ {
6205
+ attrs: { textAlign: alignment ? alignments[alignment] : "start" },
6206
+ content: block.data.content.flatMap((inline) => {
6207
+ const run = Run.safeParse(inline);
6208
+ return run.success ? [{ marks: marks(run.data.marks), text: run.data.text }] : [];
6209
+ }),
6210
+ type: "paragraph"
6211
+ }
6212
+ ];
6213
+ }),
6214
+ type: "doc"
6215
+ });
6216
+
6125
6217
  // src/server/postPurchaseProductDisplay.ts
6126
- var ResponseLanguage = import_zod55.z.object({ description: PostPurchaseProductDisplay.shape.responseDescription }).default({ description: "" });
6218
+ var ResponseLanguage = import_zod57.z.object({ description: PostPurchaseProductDisplay.shape.responseDescription }).default({ description: "" });
6127
6219
  var projectPostPurchaseProductDisplay = (effective, metadata, product) => PostPurchaseProductDisplay.parse({
6220
+ descriptionDocument: effective.language.descriptionRte && convertDescriptionRte(effective.language.descriptionRte, effective.language.descriptionSpacing),
6128
6221
  discountedFrom: effective.discountedFrom,
6129
6222
  gallery: postPurchaseProductGallery(product, effective.subImages),
6130
6223
  language: effective.language,
@@ -6134,12 +6227,142 @@ var projectPostPurchaseProductDisplay = (effective, metadata, product) => PostPu
6134
6227
  shouldShowSavingText: effective.discount.shouldShowSavingText
6135
6228
  });
6136
6229
 
6230
+ // src/server/postPurchaseReviewData.ts
6231
+ var import_zod61 = require("zod");
6232
+
6233
+ // src/server/postPurchaseJudgeMeReviews.ts
6234
+ var import_zod58 = require("zod");
6235
+ var readJudgeMeReviews = (find) => {
6236
+ const field = find("judgeme", "badge");
6237
+ if (!field) return null;
6238
+ const html = import_zod58.z.string().parse(field.value);
6239
+ const rating = html.match(/data-average-rating=['"](\d+(?:\.\d+)?)['"]/);
6240
+ const count = html.match(/data-number-of-reviews=['"](\d+)['"]/);
6241
+ if (!rating || !count) throw new Error("Unreadable Judge.me attributes");
6242
+ return {
6243
+ rating: PostPurchaseCommonReviewRating.parse({ value: rating[1] }).value,
6244
+ reviewCount: PostPurchaseReviewCount.parse(count[1])
6245
+ };
6246
+ };
6247
+
6248
+ // src/server/postPurchaseOkendoReviews.ts
6249
+ var import_zod59 = require("zod");
6250
+ var Summary = import_zod59.z.object({
6251
+ reviewAverageValue: PostPurchaseCommonReviewRating.shape.value,
6252
+ reviewCount: import_zod59.z.union([PostPurchaseProductReviews.shape.reviewCount, PostPurchaseReviewCount])
6253
+ });
6254
+ var readOkendoReviews = (find) => {
6255
+ const field = find("okendo", "summaryData");
6256
+ if (!field) return null;
6257
+ const summary = Summary.parse(JSON.parse(import_zod59.z.string().parse(field.value)));
6258
+ return { rating: summary.reviewAverageValue, reviewCount: summary.reviewCount };
6259
+ };
6260
+
6261
+ // src/server/postPurchaseScalarReviews.ts
6262
+ var import_zod60 = require("zod");
6263
+ var readScalarReviews = (find, namespace, ratingKey, countKey) => {
6264
+ const rating = find(namespace, ratingKey);
6265
+ const count = find(namespace, countKey);
6266
+ if (!rating || !count) return null;
6267
+ return {
6268
+ rating: PostPurchaseCommonReviewRating.parse({ value: import_zod60.z.string().parse(rating.value) }).value,
6269
+ reviewCount: PostPurchaseReviewCount.parse(count.value)
6270
+ };
6271
+ };
6272
+
6273
+ // src/server/postPurchaseReviewData.ts
6274
+ var readPostPurchaseReviewData = (provider, find) => {
6275
+ if (provider === "yotpo") return readScalarReviews(find, "yotpo", "reviews_average", "reviews_count");
6276
+ if (provider === "stamped") return readScalarReviews(find, "stamped", "reviews_average", "reviews_count");
6277
+ if (provider === "judgeme") return readJudgeMeReviews(find);
6278
+ if (provider === "okendo") return readOkendoReviews(find);
6279
+ if (provider === "opinew") return readScalarReviews(find, "opinew_metafields", "reviews_average", "reviews_count");
6280
+ if (provider === "reviewsio") return readScalarReviews(find, "reviewscouk", "rating", "total");
6281
+ if (provider === "loox") return readScalarReviews(find, "loox", "avg_rating", "num_reviews");
6282
+ if (provider === "junip") return readScalarReviews(find, "junip", "rating_average", "rating_count");
6283
+ const rating = find("reviews", "rating");
6284
+ const count = find("reviews", "rating_count");
6285
+ if (!rating || !count) return null;
6286
+ return {
6287
+ rating: PostPurchaseKlaviyoReviewRating.parse(JSON.parse(import_zod61.z.string().parse(rating.value))).value,
6288
+ reviewCount: PostPurchaseReviewCount.parse(count.value)
6289
+ };
6290
+ };
6291
+
6292
+ // src/server/postPurchaseReviewFields.ts
6293
+ var import_zod62 = require("zod");
6294
+ var Field = import_zod62.z.object({ key: import_zod62.z.string(), namespace: import_zod62.z.string(), value: import_zod62.z.unknown().optional() });
6295
+ var reviewFields = (raw) => {
6296
+ const fields4 = import_zod62.z.array(import_zod62.z.unknown()).parse(raw).flatMap((field) => {
6297
+ const parsed = Field.safeParse(field);
6298
+ return parsed.success ? [parsed.data] : [];
6299
+ });
6300
+ return (namespace, key) => fields4.find((field) => field.namespace === namespace && field.key === key);
6301
+ };
6302
+
6303
+ // src/server/postPurchaseReviewProvider.ts
6304
+ var import_zod63 = require("zod");
6305
+ var IntegrationInput = import_zod63.z.record(import_zod63.z.string(), import_zod63.z.unknown()).prefault({});
6306
+ var precedence = [
6307
+ "klaviyo",
6308
+ "judgeme",
6309
+ "junip",
6310
+ "loox",
6311
+ "okendo",
6312
+ "opinew",
6313
+ "reviewsio",
6314
+ "stamped",
6315
+ "yotpo"
6316
+ ];
6317
+ var ReviewsIoFlag = import_zod63.z.preprocess((value) => {
6318
+ if (typeof value === "string") {
6319
+ const flag = value.toLowerCase();
6320
+ if (flag === "true" || flag === "yes") return true;
6321
+ if (flag === "false" || flag === "no") return false;
6322
+ }
6323
+ return value;
6324
+ }, PostPurchaseSettings.shape.integrations.shape.reviewsio);
6325
+ var selectPostPurchaseReviewProvider = (raw) => {
6326
+ const integrations = IntegrationInput.parse(raw);
6327
+ for (const provider of precedence) {
6328
+ const schema = provider === "reviewsio" ? ReviewsIoFlag : PostPurchaseSettings.shape.integrations.shape[provider];
6329
+ if (schema.parse(integrations[provider])) return provider;
6330
+ }
6331
+ return null;
6332
+ };
6333
+
6334
+ // src/server/postPurchaseReviews.ts
6335
+ var projectPostPurchaseReviews = (settings, metafields, report) => {
6336
+ try {
6337
+ const provider = selectPostPurchaseReviewProvider(settings.integrations);
6338
+ if (!provider || metafields == null) return null;
6339
+ const data = readPostPurchaseReviewData(provider, reviewFields(metafields));
6340
+ if (data === null || data.rating === 0) return null;
6341
+ const styles2 = PostPurchaseReviewStyles.parse(settings.styles);
6342
+ return PostPurchaseProductReviews.parse({
6343
+ color: styles2.starColor,
6344
+ ...data,
6345
+ reviewsPlural: settings.language.global.reviewsPlural,
6346
+ reviewsSingular: settings.language.global.reviewsSingular,
6347
+ size: styles2.starSize,
6348
+ strokeColor: styles2.starStrokeColor,
6349
+ strokeWidth: styles2.strokeWidth
6350
+ });
6351
+ } catch {
6352
+ report?.({ detail: "Unreadable post-purchase reviews", kind: "product" });
6353
+ return null;
6354
+ }
6355
+ };
6356
+
6137
6357
  // src/server/projectPostPurchaseProduct.ts
6138
- var projectPostPurchaseProduct = ({ data, effective, metadata, original }, selectedQuantity) => {
6358
+ var projectPostPurchaseProduct = ({ data, effective, metadata, original }, report, selectedQuantity) => {
6139
6359
  const product = data[0];
6140
6360
  const variant2 = product.variants[0];
6141
6361
  return {
6142
- display: projectPostPurchaseProductDisplay(effective, metadata, product),
6362
+ display: {
6363
+ ...projectPostPurchaseProductDisplay(effective, metadata, product),
6364
+ reviews: projectPostPurchaseReviews(effective, product.metafields, report)
6365
+ },
6143
6366
  labels: effective.language.global,
6144
6367
  product: { ...product, variant: variant2 },
6145
6368
  selection: {
@@ -6156,7 +6379,7 @@ var prepareNormalizedSubscription = (normalized, report, plan, quantity2, allowC
6156
6379
  const reason = subscriptionUnavailable(normalized, plan, allowCollection, quantity2);
6157
6380
  if (reason) return { reason, status: "unsupported" };
6158
6381
  const { effective } = normalized;
6159
- const projected = projectPostPurchaseProduct(normalized, quantity2);
6382
+ const projected = projectPostPurchaseProduct(normalized, report, quantity2);
6160
6383
  const { discount, shipping } = PostPurchaseSubscriptionSettings.parse(effective.subscription);
6161
6384
  const shippingPrice = shipping.type === "free" ? 0 : shipping.amount;
6162
6385
  return PreparedPostPurchaseSubscription.parse({
@@ -6193,72 +6416,262 @@ var preparePostPurchaseSubscription = (settings, response, report) => {
6193
6416
  );
6194
6417
  };
6195
6418
 
6196
- // src/schema/postPurchaseOfferEligibility.ts
6197
- var import_zod57 = require("zod");
6419
+ // src/server/postPurchaseProductEligibility.ts
6420
+ var oneTimeUnavailable = (normalized, allowCollection, quantity2) => {
6421
+ const { data, effective, original } = normalized;
6422
+ if (data.length !== 1 || data[0].variants.length !== 1) return "Only one fixed product and variant are supported";
6423
+ if (effective.productType === "subscription" || [original, effective].some(
6424
+ (config) => !allowCollection && config.productLimit !== 1 || config.upgradeToSubscription.allow || !quantity2 && config.quantityInputs.enabled && (config.quantityInputs.minValue !== config.quantityInputs.maxValue || config.quantityInputs.defaultQuantity !== config.quantityInputs.minValue)
6425
+ ))
6426
+ return "Only fixed one-time configuration is supported";
6427
+ const product = data[0];
6428
+ const variant2 = product.variants[0];
6429
+ if (product.productGroupVariants.length || product.sellingPlanGroups?.some((group) => group.requiresSellingPlan) || !postPurchaseVariantAvailable(variant2))
6430
+ return "An available one-time variant without product groups is required";
6431
+ if (variant2.productId !== product.id) throw new Error("Product variant identity mismatch");
6432
+ };
6198
6433
 
6199
- // src/schema/postPurchaseProductCollectionView.ts
6200
- var import_zod56 = require("zod");
6201
- var PostPurchaseExcludedProductIds = import_zod56.z.array(PostPurchaseProductId).default([]);
6434
+ // src/server/preparePostPurchaseProduct.ts
6435
+ var prepareNormalizedProduct = (normalized, report, quantity2, allowCollection = false) => {
6436
+ const reason = oneTimeUnavailable(normalized, allowCollection, quantity2);
6437
+ if (reason) return { reason, status: "unsupported" };
6438
+ const { effective } = normalized;
6439
+ return PreparedPostPurchaseProduct.parse({
6440
+ ...projectPostPurchaseProduct(normalized, report, quantity2),
6441
+ status: "prepared",
6442
+ terms: {
6443
+ discount: { ...effective.discount, title: effective.language.global.save },
6444
+ shipping: effective.shipping
6445
+ }
6446
+ });
6447
+ };
6448
+ var preparePostPurchaseProduct = (settings, response, report) => prepareNormalizedProduct(normalizePostPurchaseProduct(settings, response), report);
6202
6449
 
6203
- // src/schema/postPurchaseOfferEligibility.ts
6204
- var selection = PreparedPostPurchaseProduct.shape.selection;
6205
- var PostPurchaseOfferSkipReason = import_zod57.z.enum(["empty", "no-eligible-subscription"]);
6206
- var PostPurchaseOfferEligibilityContext = import_zod57.z.object({
6207
- excludedProductIds: PostPurchaseExcludedProductIds,
6208
- originalLineItems: import_zod57.z.array(selection.pick({ productId: true, sellingPlanId: true, variantId: true }))
6209
- });
6210
- var PostPurchaseOfferEligibility = import_zod57.z.discriminatedUnion("status", [
6211
- import_zod57.z.object({
6212
- members: import_zod57.z.array(
6213
- import_zod57.z.object({ productId: selection.shape.productId, productIndex: import_zod57.z.number().int().nonnegative() })
6214
- ),
6215
- status: import_zod57.z.literal("retain")
6216
- }),
6217
- import_zod57.z.object({ reason: PostPurchaseOfferSkipReason, status: import_zod57.z.literal("skip") }),
6218
- import_zod57.z.object({ reason: import_zod57.z.literal("eligible-upgrade").optional(), status: import_zod57.z.literal("unavailable") })
6450
+ // src/schema/postPurchaseProductView.ts
6451
+ var import_zod67 = require("zod");
6452
+
6453
+ // src/schema/postPurchaseChoice.ts
6454
+ var import_zod64 = require("zod");
6455
+ var PostPurchaseChoice = import_zod64.z.discriminatedUnion("mode", [
6456
+ import_zod64.z.object({ mode: import_zod64.z.literal("one-time") }).strict(),
6457
+ import_zod64.z.object({ mode: import_zod64.z.literal("subscription"), sellingPlanId: PostPurchasePlanOption.shape.id }).strict()
6219
6458
  ]);
6459
+ var PostPurchaseOptions = import_zod64.z.object({
6460
+ defaultChoice: PostPurchaseChoice,
6461
+ modes: import_zod64.z.array(import_zod64.z.enum(["one-time", "subscription"])).min(1).max(2),
6462
+ selector: PostPurchaseSettings.shape.productTypeSelector
6463
+ });
6220
6464
 
6221
- // src/server/normalizePostPurchaseCollection.ts
6222
- var import_zod58 = require("zod");
6223
- var normalizePostPurchaseCollection = (settings, response, excludedProductIds) => {
6224
- const normalized = normalizePostPurchaseProduct(settings, response);
6225
- const limit = import_zod58.z.number().int().positive();
6226
- limit.parse(normalized.original.productLimit);
6227
- const prefix = normalized.data.slice(0, limit.parse(normalized.effective.productLimit));
6228
- if (new Set(prefix.map(({ id }) => id)).size !== prefix.length)
6229
- throw new Error("Ambiguous post-purchase collection");
6230
- const excluded = new Set(PostPurchaseExcludedProductIds.parse(excludedProductIds));
6231
- const members = prefix.map((product, productIndex) => ({ product, productIndex })).filter(({ product }) => !excluded.has(product.id));
6232
- return { members, normalized };
6233
- };
6465
+ // src/schema/postPurchaseGroupCatalog.ts
6466
+ var import_zod66 = require("zod");
6234
6467
 
6235
6468
  // src/schema/postPurchaseVariantCatalog.ts
6236
- var import_zod59 = require("zod");
6237
- var PostPurchaseVariantSelector = import_zod59.z.object({ variantId: PostPurchaseVariantId }).strict();
6469
+ var import_zod65 = require("zod");
6470
+ var PostPurchaseVariantSelector = import_zod65.z.object({ variantId: PostPurchaseVariantId }).strict();
6238
6471
  var PostPurchaseVariantOption = OfferProduct.shape.options.element.extend({
6239
- id: import_zod59.z.number().int().positive(),
6240
- position: import_zod59.z.number().int().min(1).max(3)
6472
+ id: import_zod65.z.number().int().positive(),
6473
+ position: import_zod65.z.number().int().min(1).max(3)
6241
6474
  });
6242
6475
  var PostPurchaseVariantValues = OfferProduct.shape.variants.element.pick({
6243
6476
  option1: true,
6244
6477
  option2: true,
6245
6478
  option3: true
6246
6479
  });
6247
- var PostPurchaseVariantCatalog = import_zod59.z.object({
6480
+ var PostPurchaseVariantCatalog = import_zod65.z.object({
6248
6481
  displayMode: PostPurchaseSettings.shape.productOptions.shape.variantSelectorDisplayMode,
6249
- options: import_zod59.z.array(PostPurchaseVariantOption),
6482
+ options: import_zod65.z.array(PostPurchaseVariantOption),
6250
6483
  productId: PostPurchaseProductId,
6251
6484
  showSelectors: PostPurchaseSettings.shape.productOptions.shape.showVariantSelectors,
6252
- variants: import_zod59.z.array(
6485
+ variants: import_zod65.z.array(
6253
6486
  PostPurchaseVariantValues.partial().extend({
6254
- available: import_zod59.z.boolean(),
6487
+ available: import_zod65.z.boolean(),
6255
6488
  id: PostPurchaseVariantId,
6256
- imageId: import_zod59.z.number().int().nonnegative().nullish(),
6489
+ imageId: import_zod65.z.number().int().nonnegative().nullish(),
6257
6490
  title: OfferProduct.shape.variants.element.shape.title
6258
6491
  })
6259
6492
  )
6260
6493
  });
6261
6494
 
6495
+ // src/schema/postPurchaseGroupCatalog.ts
6496
+ var productId = PreparedPostPurchaseProduct.shape.selection.shape.productId;
6497
+ var source = PostPurchaseProductSource.shape.data.element;
6498
+ var PostPurchaseGroupDescription = source.pick({ description: true, id: true, image: true, images: true, title: true }).extend({
6499
+ description: source.shape.description.default(null),
6500
+ image: source.shape.image.default(null),
6501
+ options: PostPurchaseVariantCatalog.shape.options.default([])
6502
+ });
6503
+ var PostPurchaseGroupCatalog = import_zod66.z.object({
6504
+ memberProductId: productId,
6505
+ options: import_zod66.z.array(import_zod66.z.object({ productId, title: import_zod66.z.string(), variantCatalog: PostPurchaseVariantCatalog }))
6506
+ });
6507
+ var PostPurchaseGroupSelection = import_zod66.z.object({
6508
+ memberProductId: productId,
6509
+ productId
6510
+ });
6511
+
6512
+ // src/schema/postPurchaseProductView.ts
6513
+ var PostPurchaseProductView = import_zod67.z.union([
6514
+ import_zod67.z.object({
6515
+ groupCatalog: PostPurchaseGroupCatalog.optional(),
6516
+ initialVariant: PostPurchaseVariantSelector.optional(),
6517
+ planCatalog: PostPurchasePlanCatalog.nullable().optional(),
6518
+ preparation: PreparedPostPurchaseProduct.extend({
6519
+ display: PreparedPostPurchaseProduct.shape.display.extend({ description: import_zod67.z.string().nullable() }).refine(
6520
+ ({ description, descriptionDocument }) => description === null === (descriptionDocument !== void 0),
6521
+ "Exactly one of the plain and rich descriptions is shown"
6522
+ )
6523
+ }),
6524
+ purchaseOptions: PostPurchaseOptions.optional(),
6525
+ sections: CABRootSection,
6526
+ variantCatalog: PostPurchaseVariantCatalog.optional()
6527
+ }),
6528
+ import_zod67.z.object({
6529
+ groupCatalog: PostPurchaseGroupCatalog.optional(),
6530
+ initialVariant: PostPurchaseVariantSelector.optional(),
6531
+ planCatalog: PostPurchasePlanCatalog.nullable().optional(),
6532
+ preparation: PostPurchasePreparation.options[1],
6533
+ purchaseOptions: PostPurchaseOptions.optional(),
6534
+ sections: import_zod67.z.null(),
6535
+ variantCatalog: PostPurchaseVariantCatalog.optional()
6536
+ })
6537
+ ]);
6538
+
6539
+ // src/server/postPurchaseOfferCopy.ts
6540
+ var import_zod68 = require("zod");
6541
+ var Copy = import_zod68.z.object({
6542
+ superTitle: CalloutBannerBlock.shape.settings.shape.superTitle.unwrap().optional().catch(void 0),
6543
+ title: CalloutBannerBlock.shape.settings.shape.title.unwrap().optional().catch(void 0)
6544
+ });
6545
+ var Callout = import_zod68.z.object({ settings: import_zod68.z.record(import_zod68.z.string(), import_zod68.z.unknown()), type: import_zod68.z.literal("callout_banner") });
6546
+ var postPurchaseOfferCopy = (blocks, metadata) => {
6547
+ const copy = Copy.safeParse(metadata.widget.language);
6548
+ if (!blocks || !copy.success) return blocks;
6549
+ const first = blocks.findIndex((block) => Callout.pick({ type: true }).safeParse(block).success);
6550
+ return blocks.map((block, index) => {
6551
+ if (index !== first) return block;
6552
+ const callout = Callout.passthrough().safeParse(block);
6553
+ if (!callout.success) return block;
6554
+ return {
6555
+ ...callout.data,
6556
+ settings: {
6557
+ ...callout.data.settings,
6558
+ ...copy.data.title && { title: copy.data.title },
6559
+ ...copy.data.superTitle && { superTitle: copy.data.superTitle }
6560
+ }
6561
+ };
6562
+ });
6563
+ };
6564
+
6565
+ // src/server/selectPostPurchaseChoice.ts
6566
+ var selectPostPurchaseChoice = (normalized, projected, requested, allowCollection, quantity2) => {
6567
+ const { data, effective } = normalized;
6568
+ const modes = [];
6569
+ const catalog = projected && projected.productId === data[0]?.id && projected.variantId === data[0].variants[0]?.id ? projected : null;
6570
+ const firstPlan = catalog?.plans[0];
6571
+ const oneTimeReason = oneTimeUnavailable(normalized, allowCollection, quantity2);
6572
+ const subscriptionReason = subscriptionUnavailable(normalized, firstPlan, allowCollection, quantity2);
6573
+ if (!oneTimeReason) modes.push("one-time");
6574
+ if (!subscriptionReason) modes.push("subscription");
6575
+ if (oneTimeReason && subscriptionReason)
6576
+ return {
6577
+ choice: void 0,
6578
+ options: void 0,
6579
+ plan: void 0,
6580
+ reason: effective.productType === "one-time" ? oneTimeReason : subscriptionReason
6581
+ };
6582
+ const defaultChoice = firstPlan && modes.includes("subscription") && (modes[0] === "subscription" || effective.subscriptionIsDefault) ? { mode: "subscription", sellingPlanId: firstPlan.id } : { mode: "one-time" };
6583
+ const options2 = PostPurchaseOptions.parse({ defaultChoice, modes, selector: effective.productTypeSelector });
6584
+ const choice = requested ?? defaultChoice;
6585
+ const plan = choice.mode === "subscription" ? catalog?.plans.find(({ id }) => id === choice.sellingPlanId) : void 0;
6586
+ const bound = modes.includes(choice.mode) && (choice.mode === "one-time" || plan) ? choice : void 0;
6587
+ return {
6588
+ choice: bound,
6589
+ options: options2,
6590
+ plan: bound ? plan : void 0,
6591
+ reason: bound ? void 0 : "Requested purchase choice is unavailable"
6592
+ };
6593
+ };
6594
+
6595
+ // src/server/preparePostPurchaseView.ts
6596
+ var resolveDescription = ({ descriptionDocument, ...display }, productDescription) => {
6597
+ const plain = display.language.descriptionEnabled && productDescription || display.responseDescription || (descriptionDocument ? null : display.language.description);
6598
+ return plain === null ? { ...display, description: null, descriptionDocument } : { ...display, description: plain };
6599
+ };
6600
+ var prepareNormalizedPostPurchaseView = (widgetId, normalized, report, choice, quantity2, allowCollection = false) => {
6601
+ const planCatalog = projectPostPurchasePlanCatalog(normalized, report);
6602
+ const selected = selectPostPurchaseChoice(normalized, planCatalog, choice, allowCollection, quantity2);
6603
+ const purchaseOptions = selected.options;
6604
+ const preparation = !selected.choice ? { reason: selected.reason, status: "unsupported" } : selected.choice.mode === "subscription" ? prepareNormalizedSubscription(normalized, report, selected.plan, quantity2, allowCollection) : prepareNormalizedProduct(normalized, report, quantity2, allowCollection);
6605
+ const unsupported = (reason) => ({
6606
+ planCatalog,
6607
+ preparation: { reason, status: "unsupported" },
6608
+ purchaseOptions,
6609
+ sections: null
6610
+ });
6611
+ if (preparation.status === "unsupported") return { planCatalog, preparation, purchaseOptions, sections: null };
6612
+ if (!normalized.effective.blocks?.length) return unsupported("One fixed product information block is required");
6613
+ const sections = convertMessagePreview(
6614
+ widgetId,
6615
+ {
6616
+ blocks: postPurchaseOfferCopy(normalized.effective.blocks, normalized.metadata),
6617
+ type: "shopify_post_purchase_extension"
6618
+ },
6619
+ report
6620
+ );
6621
+ if (sections.sections.filter((section) => section.sectionType === "offers").length !== 1)
6622
+ return unsupported("One fixed product information block is required");
6623
+ return PostPurchaseProductView.parse({
6624
+ planCatalog,
6625
+ preparation: {
6626
+ ...preparation,
6627
+ display: resolveDescription(preparation.display, preparation.product.description)
6628
+ },
6629
+ purchaseOptions,
6630
+ sections
6631
+ });
6632
+ };
6633
+ var preparePostPurchaseView = (widgetId, settings, response, report, choice) => prepareNormalizedPostPurchaseView(widgetId, normalizePostPurchaseProduct(settings, response), report, choice);
6634
+
6635
+ // src/server/preparePostPurchaseAdmissionView.ts
6636
+ var preparePostPurchaseAdmissionView = (widgetId, settings, response, report, choice) => {
6637
+ const normalized = normalizePostPurchaseProduct(settings, response);
6638
+ const view = prepareNormalizedPostPurchaseView(widgetId, normalized, report, choice);
6639
+ const { removePartialOrder } = PostPurchaseSettings.shape.advance.parse(normalized.effective.advance);
6640
+ return { removePartialOrder, view };
6641
+ };
6642
+
6643
+ // src/schema/postPurchaseProductCollectionView.ts
6644
+ var import_zod69 = require("zod");
6645
+ var PostPurchaseProductCollectionView = import_zod69.z.object({
6646
+ members: import_zod69.z.array(
6647
+ import_zod69.z.object({
6648
+ productId: PostPurchaseProductId,
6649
+ productIndex: import_zod69.z.number().int().nonnegative(),
6650
+ view: PostPurchaseProductView
6651
+ })
6652
+ )
6653
+ });
6654
+ var PostPurchaseCollectionChoice = import_zod69.z.object({
6655
+ choice: PostPurchaseChoice.optional(),
6656
+ productId: PostPurchaseProductId,
6657
+ variantId: PostPurchaseVariantSelector.shape.variantId.optional()
6658
+ }).strict();
6659
+ var PostPurchaseExcludedProductIds = import_zod69.z.array(PostPurchaseProductId).default([]);
6660
+
6661
+ // src/server/normalizePostPurchaseCollection.ts
6662
+ var import_zod70 = require("zod");
6663
+ var normalizePostPurchaseCollection = (settings, response, excludedProductIds) => {
6664
+ const normalized = normalizePostPurchaseProduct(settings, response);
6665
+ const limit = import_zod70.z.number().int().positive();
6666
+ limit.parse(normalized.original.productLimit);
6667
+ const prefix = normalized.data.slice(0, limit.parse(normalized.effective.productLimit));
6668
+ if (new Set(prefix.map(({ id }) => id)).size !== prefix.length)
6669
+ throw new Error("Ambiguous post-purchase collection");
6670
+ const excluded = new Set(PostPurchaseExcludedProductIds.parse(excludedProductIds));
6671
+ const members = prefix.map((product, productIndex) => ({ product, productIndex })).filter(({ product }) => !excluded.has(product.id));
6672
+ return { members, normalized };
6673
+ };
6674
+
6262
6675
  // src/server/postPurchaseVariantCatalog.ts
6263
6676
  var projectPostPurchaseVariantCatalog = (product, settings) => {
6264
6677
  const options2 = PostPurchaseVariantCatalog.shape.options.parse(product.options === void 0 ? [] : product.options).sort((a, b) => a.position - b.position);
@@ -6292,22 +6705,216 @@ var projectPostPurchaseVariantCatalog = (product, settings) => {
6292
6705
  });
6293
6706
  };
6294
6707
 
6295
- // src/schema/postPurchaseGroupCatalog.ts
6296
- var import_zod60 = require("zod");
6297
- var productId = PreparedPostPurchaseProduct.shape.selection.shape.productId;
6298
- var source = PostPurchaseProductSource.shape.data.element;
6299
- var PostPurchaseGroupDescription = source.pick({ description: true, id: true, image: true, images: true, title: true }).extend({
6300
- description: source.shape.description.default(null),
6301
- image: source.shape.image.default(null),
6302
- options: PostPurchaseVariantCatalog.shape.options.default([])
6708
+ // src/schema/postPurchaseQuantity.ts
6709
+ var import_zod71 = require("zod");
6710
+ var quantity = PreparedPostPurchaseProduct.shape.selection.shape.quantity;
6711
+ var PostPurchaseQuantityChoice = PostPurchaseCollectionChoice.extend({ quantity: quantity.optional() });
6712
+ var PostPurchaseQuantityPolicy = PostPurchaseSettings.shape.quantityInputs.omit({ defaultQuantity: true }).extend({
6713
+ initialQuantity: quantity,
6714
+ maxValue: quantity,
6715
+ minValue: import_zod71.z.literal(0).transform(() => 1).or(quantity)
6716
+ }).refine(({ maxValue, minValue }) => minValue <= maxValue, "Quantity bounds are reversed");
6717
+
6718
+ // src/server/readPostPurchaseQuantity.ts
6719
+ var PostPurchaseQuantityUnavailable = class extends Error {
6720
+ };
6721
+ var readPostPurchaseQuantity = ({
6722
+ data,
6723
+ effective,
6724
+ original
6725
+ }, selection3) => {
6726
+ const positive = PreparedPostPurchaseProduct.shape.selection.shape.quantity;
6727
+ for (const config of [original, effective]) {
6728
+ if (!config.quantityInputs.enabled) continue;
6729
+ const initialQuantity2 = positive.parse(config.quantityInputs.defaultQuantity);
6730
+ const policy2 = PostPurchaseQuantityPolicy.parse({ ...config.quantityInputs, initialQuantity: initialQuantity2 });
6731
+ if (initialQuantity2 < policy2.minValue || initialQuantity2 > policy2.maxValue)
6732
+ throw new Error("Configured quantity default is outside its bounds");
6733
+ }
6734
+ const initialQuantity = data[0]?.metadata?.productQuantity ?? (original.quantityInputs.enabled ? original.quantityInputs.defaultQuantity : 1);
6735
+ const policy = PostPurchaseQuantityPolicy.parse(
6736
+ effective.quantityInputs.enabled ? { ...effective.quantityInputs, initialQuantity } : { enabled: false, initialQuantity, maxValue: initialQuantity, minValue: initialQuantity }
6737
+ );
6738
+ const requested = "quantity" in selection3 ? selection3.quantity : selection3.expectedQuantity === initialQuantity ? void 0 : selection3.expectedQuantity;
6739
+ const quantity2 = positive.parse(requested ?? initialQuantity);
6740
+ if (requested !== void 0 && (policy.enabled ? quantity2 < policy.minValue || quantity2 > policy.maxValue : quantity2 !== initialQuantity))
6741
+ throw new PostPurchaseQuantityUnavailable("Requested quantity is unavailable");
6742
+ return { policy, quantity: quantity2 };
6743
+ };
6744
+
6745
+ // src/schema/postPurchaseVariantDefault.ts
6746
+ var import_zod72 = require("zod");
6747
+ var values = PostPurchaseVariantValues.partial().extend({
6748
+ option1: PostPurchaseVariantValues.shape.option1.nullish()
6303
6749
  });
6304
- var PostPurchaseGroupCatalog = import_zod60.z.object({
6305
- memberProductId: productId,
6306
- options: import_zod60.z.array(import_zod60.z.object({ productId, title: import_zod60.z.string(), variantCatalog: PostPurchaseVariantCatalog }))
6750
+ var variant = values.extend({
6751
+ id: PostPurchaseVariantId,
6752
+ inventoryManagement: import_zod72.z.string().nullable(),
6753
+ inventoryPolicy: import_zod72.z.string(),
6754
+ inventoryQuantity: import_zod72.z.number()
6307
6755
  });
6308
- var PostPurchaseGroupSelection = import_zod60.z.object({
6309
- memberProductId: productId,
6310
- productId
6756
+ var options = import_zod72.z.array(PostPurchaseVariantOption.pick({ name: true, values: true }));
6757
+ var PostPurchaseVariantDefaultProduct = import_zod72.z.object({
6758
+ id: PostPurchaseProductId,
6759
+ options,
6760
+ selectedVariant: variant.optional(),
6761
+ variants: import_zod72.z.array(variant)
6762
+ });
6763
+ var PostPurchaseVariantDefaultSettings = PostPurchaseSettings.shape.productOptions.pick({
6764
+ hideOutOfStockVariants: true,
6765
+ matchVariant: true
6766
+ });
6767
+ var PostPurchaseOrderAttributes = import_zod72.z.record(import_zod72.z.string(), import_zod72.z.array(import_zod72.z.string())).default({});
6768
+ var PostPurchaseOriginalVariants = import_zod72.z.array(
6769
+ import_zod72.z.object({ productId: PostPurchaseProductId, variantId: PostPurchaseVariantId })
6770
+ );
6771
+ var PostPurchaseAttributeProducts = import_zod72.z.array(
6772
+ import_zod72.z.object({ id: PostPurchaseProductId, options, variants: import_zod72.z.array(values.extend({ id: PostPurchaseVariantId })) })
6773
+ );
6774
+
6775
+ // src/schema/postPurchaseVariantDefaultContext.ts
6776
+ var import_zod73 = require("zod");
6777
+ var PostPurchaseVariantDefaultContext = import_zod73.z.object({
6778
+ enrichedLineItems: import_zod73.z.unknown().optional(),
6779
+ originalVariants: PostPurchaseOriginalVariants
6780
+ });
6781
+
6782
+ // src/server/createPostPurchaseOrderAttributes.ts
6783
+ var createPostPurchaseOrderAttributes = (original, enriched) => {
6784
+ const products = PostPurchaseAttributeProducts.parse(enriched);
6785
+ const attributes = {};
6786
+ for (const item of PostPurchaseOriginalVariants.parse(original)) {
6787
+ const product = products.find(({ id }) => id === item.productId);
6788
+ const variant2 = product?.variants.find(({ id }) => id === item.variantId);
6789
+ if (!variant2 || !product) continue;
6790
+ ["option1", "option2", "option3"].forEach((key, index) => {
6791
+ const value = variant2[key];
6792
+ const option = product.options[index];
6793
+ if (!value || !option) return;
6794
+ const values2 = attributes[option.name] ?? [];
6795
+ if (!values2.includes(value)) attributes[option.name] = [...values2, value];
6796
+ });
6797
+ }
6798
+ return attributes;
6799
+ };
6800
+
6801
+ // src/server/matchPostPurchaseVariantDefault.ts
6802
+ var matchPostPurchaseVariantDefault = (product, attributes, filterOutOfStock) => {
6803
+ const keys = ["option1", "option2", "option3"];
6804
+ const values2 = keys.map((_, index) => {
6805
+ const option = product.options[index];
6806
+ return option ? option.values.filter((value) => attributes[option.name]?.includes(value)) : [];
6807
+ });
6808
+ if (!values2.some((entries) => entries.length)) return;
6809
+ let bestRank = 1;
6810
+ let best;
6811
+ for (const variant2 of product.variants) {
6812
+ if (filterOutOfStock && variant2.inventoryPolicy !== "continue" && variant2.inventoryQuantity <= 0) continue;
6813
+ const rank = keys.reduce((total, key, index) => {
6814
+ const value = variant2[key];
6815
+ return total + Number(!value && !values2[index].length || !!value && values2[index].includes(value));
6816
+ }, 0);
6817
+ if (rank > bestRank) {
6818
+ best = variant2;
6819
+ bestRank = rank;
6820
+ }
6821
+ }
6822
+ return best;
6823
+ };
6824
+
6825
+ // src/server/resolvePostPurchaseVariantDefault.ts
6826
+ var resolvePostPurchaseVariantDefault = (source2, settings, originalAttributes) => {
6827
+ const product = PostPurchaseVariantDefaultProduct.parse(source2);
6828
+ const policy = PostPurchaseVariantDefaultSettings.parse(settings);
6829
+ const attributes = PostPurchaseOrderAttributes.parse(originalAttributes);
6830
+ let selected = source2.selectedVariant && source2.selectedVariant === source2.variants[0] ? product.variants[0] : product.selectedVariant;
6831
+ if (!selected && policy.matchVariant)
6832
+ selected = matchPostPurchaseVariantDefault(product, attributes, policy.hideOutOfStockVariants);
6833
+ selected ?? (selected = product.variants[0]);
6834
+ if (!selected || selected === product.variants[0])
6835
+ selected = product.variants.find(postPurchaseVariantAvailable) ?? selected;
6836
+ return selected?.id ?? null;
6837
+ };
6838
+
6839
+ // src/server/resolvePostPurchaseMemberDefault.ts
6840
+ var resolvePostPurchaseMemberDefault = (product, original, context) => {
6841
+ const originals = PostPurchaseVariantDefaultContext.parse(context);
6842
+ if (product.variants.length < 2 && product.selectedVariant === void 0) return product.variants[0]?.id ?? null;
6843
+ const source2 = PostPurchaseVariantDefaultProduct.parse(product);
6844
+ const settings = PostPurchaseVariantDefaultSettings.parse(original.productOptions);
6845
+ const attributes = settings.matchVariant && !source2.selectedVariant && source2.options.some(({ values: values2 }) => values2.length > 0) && originals.originalVariants.length > 0 && originals.enrichedLineItems != null ? createPostPurchaseOrderAttributes(
6846
+ originals.originalVariants,
6847
+ PostPurchaseAttributeProducts.parse(deepCamelCase(originals.enrichedLineItems))
6848
+ ) : void 0;
6849
+ return resolvePostPurchaseVariantDefault(source2, settings, attributes);
6850
+ };
6851
+
6852
+ // src/server/preparePostPurchaseMemberView.ts
6853
+ var prepareMember = (widgetId, settings, response, requested, report, excludedProductIds, requestedQuantity, defaults) => {
6854
+ const selected = PostPurchaseCollectionChoice.parse(requested);
6855
+ const { members, normalized } = normalizePostPurchaseCollection(settings, response, excludedProductIds);
6856
+ const found = members.find(({ product: product2 }) => product2.id === selected.productId);
6857
+ if (!found) return null;
6858
+ const variantId = selected.variantId ?? (defaults && resolvePostPurchaseMemberDefault(found.product, normalized.original, defaults));
6859
+ const product = variantId === void 0 ? found.product : {
6860
+ ...found.product,
6861
+ variants: found.product.variants.filter(({ id }) => id === variantId)
6862
+ };
6863
+ const selectedInput = { ...normalized, data: [product] };
6864
+ const quantity2 = requestedQuantity ? readPostPurchaseQuantity(selectedInput, requestedQuantity) : void 0;
6865
+ const view = prepareNormalizedPostPurchaseView(widgetId, selectedInput, report, selected.choice, quantity2, true);
6866
+ if (selected.variantId !== void 0 || found.product.variants.length > 1)
6867
+ view.variantCatalog = projectPostPurchaseVariantCatalog(found.product, normalized.effective);
6868
+ if (defaults && selected.variantId === void 0 && variantId && view.variantCatalog?.variants.some(({ id }) => id === variantId))
6869
+ view.initialVariant = { variantId };
6870
+ return { member: { productId: found.product.id, productIndex: found.productIndex, view }, normalized, quantity: quantity2 };
6871
+ };
6872
+ var preparePostPurchaseMemberView = (widgetId, settings, response, requested, report, excludedProductIds) => prepareMember(widgetId, settings, response, requested, report, excludedProductIds)?.member ?? null;
6873
+ var preparePostPurchaseMemberAdmissionView = (widgetId, settings, response, requested, report, excludedProductIds) => {
6874
+ const prepared = prepareMember(widgetId, settings, response, requested, report, excludedProductIds);
6875
+ if (!prepared) return null;
6876
+ const { removePartialOrder } = PostPurchaseSettings.shape.advance.parse(prepared.normalized.effective.advance);
6877
+ return { ...prepared.member, removePartialOrder };
6878
+ };
6879
+
6880
+ // src/server/preparePostPurchaseQuantityView.ts
6881
+ var preparePostPurchaseQuantityView = (widgetId, settings, response, requested, report, excludedProductIds, defaults) => {
6882
+ const { quantity: quantity2, ...selection3 } = PostPurchaseQuantityChoice.parse(requested);
6883
+ const prepared = prepareMember(
6884
+ widgetId,
6885
+ settings,
6886
+ response,
6887
+ selection3,
6888
+ report,
6889
+ excludedProductIds,
6890
+ { quantity: quantity2 },
6891
+ defaults
6892
+ );
6893
+ return prepared ? { ...prepared.member, quantityPolicy: prepared.quantity.policy } : null;
6894
+ };
6895
+
6896
+ // src/server/preparePostPurchaseQuantityAdmissionView.ts
6897
+ var selection = PostPurchaseQuantityChoice.required({ quantity: true });
6898
+ var preparePostPurchaseQuantityAdmissionView = (widgetId, settings, response, expected, report, excludedProductIds, defaults) => {
6899
+ const { quantity: expectedQuantity, ...requested } = selection.parse(expected);
6900
+ const prepared = prepareMember(
6901
+ widgetId,
6902
+ settings,
6903
+ response,
6904
+ requested,
6905
+ report,
6906
+ excludedProductIds,
6907
+ { expectedQuantity },
6908
+ defaults
6909
+ );
6910
+ if (!prepared) return null;
6911
+ const { removePartialOrder } = PostPurchaseSettings.shape.advance.parse(prepared.normalized.effective.advance);
6912
+ return { ...prepared.member, quantityPolicy: prepared.quantity.policy, removePartialOrder };
6913
+ };
6914
+
6915
+ // src/schema/postPurchaseGroup.ts
6916
+ var PostPurchaseGroupChoice = PostPurchaseQuantityChoice.extend({
6917
+ memberProductId: PreparedPostPurchaseProduct.shape.selection.shape.productId
6311
6918
  });
6312
6919
 
6313
6920
  // src/server/readPostPurchaseGroup.ts
@@ -6340,6 +6947,195 @@ var readPostPurchaseGroup = (product, settings, excludedProductIds) => {
6340
6947
  };
6341
6948
  };
6342
6949
 
6950
+ // src/server/readPostPurchaseGroupSelection.ts
6951
+ var readPostPurchaseGroupSelection = (settings, response, requested, excludedProductIds) => {
6952
+ const selection3 = PostPurchaseGroupSelection.parse(requested);
6953
+ const { members, normalized } = normalizePostPurchaseCollection(settings, response);
6954
+ const member = members.find(({ product }) => product.id === selection3.memberProductId);
6955
+ if (!member || !member.product.productGroupVariants.length) return null;
6956
+ const group = readPostPurchaseGroup(member.product, normalized.effective, excludedProductIds);
6957
+ const entry = group.entries.find(({ product }) => product.id === selection3.productId);
6958
+ if (!entry) return null;
6959
+ return {
6960
+ groupCatalog: group.catalog,
6961
+ memberProductId: member.product.id,
6962
+ productIndex: member.productIndex,
6963
+ reportingProduct: { id: member.product.id, title: member.product.title },
6964
+ response: { data: [entry.product], metadata: normalized.metadata },
6965
+ variantCatalog: entry.variantCatalog
6966
+ };
6967
+ };
6968
+
6969
+ // src/server/preparePostPurchaseGroupView.ts
6970
+ var preparePostPurchaseGroupView = (widgetId, settings, response, requested, report, excludedProductIds) => {
6971
+ const { memberProductId, ...selection3 } = PostPurchaseGroupChoice.parse(requested);
6972
+ const group = readPostPurchaseGroupSelection(settings, response, requested, excludedProductIds);
6973
+ if (!group) return null;
6974
+ const variantId = selection3.variantId ?? group.variantCatalog.variants.find(({ available }) => available)?.id;
6975
+ if (variantId === void 0) return null;
6976
+ const prepared = preparePostPurchaseQuantityView(
6977
+ widgetId,
6978
+ settings,
6979
+ group.response,
6980
+ { ...selection3, variantId },
6981
+ report
6982
+ );
6983
+ return prepared && {
6984
+ ...prepared,
6985
+ groupCatalog: group.groupCatalog,
6986
+ memberProductId,
6987
+ productIndex: group.productIndex,
6988
+ reportingProduct: group.reportingProduct
6989
+ };
6990
+ };
6991
+
6992
+ // src/server/preparePostPurchaseGroupAdmissionView.ts
6993
+ var preparePostPurchaseGroupAdmissionView = (widgetId, settings, response, requested, report, excludedProductIds) => {
6994
+ const { memberProductId, ...selection3 } = PostPurchaseGroupChoice.required({ quantity: true }).parse(requested);
6995
+ const group = readPostPurchaseGroupSelection(settings, response, requested, excludedProductIds);
6996
+ if (!group) return null;
6997
+ const variantId = selection3.variantId ?? group.variantCatalog.variants.find(({ available }) => available)?.id;
6998
+ if (variantId === void 0) return null;
6999
+ const prepared = preparePostPurchaseQuantityAdmissionView(
7000
+ widgetId,
7001
+ settings,
7002
+ group.response,
7003
+ { ...selection3, variantId },
7004
+ report
7005
+ );
7006
+ return prepared && {
7007
+ ...prepared,
7008
+ groupCatalog: group.groupCatalog,
7009
+ memberProductId,
7010
+ productIndex: group.productIndex,
7011
+ reportingProduct: group.reportingProduct
7012
+ };
7013
+ };
7014
+
7015
+ // src/server/preparePostPurchaseGroupDefault.ts
7016
+ var preparePostPurchaseGroupDefault = (widgetId, settings, response, memberProductId, context, report, excludedProductIds) => {
7017
+ const { members, normalized } = normalizePostPurchaseCollection(settings, response);
7018
+ const member = members.find(({ product }) => product.id === memberProductId);
7019
+ if (!member || !member.product.productGroupVariants.length) return null;
7020
+ const group = readPostPurchaseGroup(member.product, normalized.effective, excludedProductIds);
7021
+ const ids = new Set(group.entries.map(({ product }) => product.id));
7022
+ const variants = member.product.variants.filter(({ productId: productId2 }) => ids.has(productId2));
7023
+ const selected = PostPurchaseVariantDefaultProduct.shape.selectedVariant.parse(member.product.selectedVariant);
7024
+ const selectedOwner = selected && member.product.variants.find(({ id }) => id === selected.id);
7025
+ const variantId = resolvePostPurchaseMemberDefault(
7026
+ {
7027
+ ...member.product,
7028
+ selectedVariant: selectedOwner && !ids.has(selectedOwner.productId) ? void 0 : member.product.selectedVariant,
7029
+ variants
7030
+ },
7031
+ normalized.original,
7032
+ context
7033
+ );
7034
+ const entry = group.entries.find(({ product }) => product.variants.some(({ id }) => id === variantId));
7035
+ if (!entry || variantId === null) return null;
7036
+ const prepared = preparePostPurchaseGroupView(
7037
+ widgetId,
7038
+ settings,
7039
+ response,
7040
+ { memberProductId, productId: entry.product.id, variantId },
7041
+ report,
7042
+ excludedProductIds
7043
+ );
7044
+ return prepared && { ...prepared, view: { ...prepared.view, initialVariant: { variantId } } };
7045
+ };
7046
+
7047
+ // src/server/preparePostPurchaseCollectionGroup.ts
7048
+ var preparePostPurchaseCollectionGroup = (widgetId, settings, response, member, normalized, excluded, defaults, report) => {
7049
+ const group = readPostPurchaseGroup(member.product, normalized.effective, excluded);
7050
+ if (!group.entries.length) return null;
7051
+ const prepared = preparePostPurchaseGroupDefault(
7052
+ widgetId,
7053
+ settings,
7054
+ response,
7055
+ member.product.id,
7056
+ defaults,
7057
+ report,
7058
+ excluded
7059
+ );
7060
+ return {
7061
+ productId: member.product.id,
7062
+ productIndex: member.productIndex,
7063
+ reportingProduct: { id: member.product.id, title: member.product.title },
7064
+ view: prepared ? { ...prepared.view, groupCatalog: prepared.groupCatalog } : {
7065
+ groupCatalog: group.catalog,
7066
+ preparation: { reason: "Post-purchase group default is unavailable", status: "unsupported" },
7067
+ sections: null
7068
+ }
7069
+ };
7070
+ };
7071
+
7072
+ // src/server/preparePostPurchaseCollectionView.ts
7073
+ var CollectionChoice = PostPurchaseCollectionChoice.omit({ variantId: true });
7074
+ var preparePostPurchaseCollectionView = (widgetId, settings, response, report, requested, excludedProductIds, defaults = { originalVariants: [] }) => {
7075
+ const { members, normalized } = normalizePostPurchaseCollection(settings, response);
7076
+ const excluded = PostPurchaseExcludedProductIds.parse(excludedProductIds);
7077
+ const selected = CollectionChoice.optional().parse(requested);
7078
+ const projected = members.map((member) => {
7079
+ if (member.product.productGroupVariants.length) {
7080
+ if (selected?.productId === member.product.id && selected.choice)
7081
+ throw new Error("Grouped choices require selected merchandise");
7082
+ const group = preparePostPurchaseCollectionGroup(
7083
+ widgetId,
7084
+ settings,
7085
+ response,
7086
+ member,
7087
+ normalized,
7088
+ excluded,
7089
+ defaults,
7090
+ report
7091
+ );
7092
+ return group;
7093
+ }
7094
+ if (excluded.includes(member.product.id)) return null;
7095
+ return {
7096
+ productId: member.product.id,
7097
+ productIndex: member.productIndex,
7098
+ reportingProduct: void 0,
7099
+ view: prepareNormalizedPostPurchaseView(
7100
+ widgetId,
7101
+ { ...normalized, data: [member.product] },
7102
+ report,
7103
+ member.product.id === selected?.productId ? selected.choice : void 0,
7104
+ void 0,
7105
+ true
7106
+ )
7107
+ };
7108
+ }).filter((member) => member !== null);
7109
+ if (selected && !projected.some(({ productId: productId2 }) => productId2 === selected.productId))
7110
+ throw new Error("Requested product is outside the prepared collection");
7111
+ const collection = PostPurchaseProductCollectionView.parse({ members: projected });
7112
+ return {
7113
+ members: collection.members.map((member, index) => ({
7114
+ ...member,
7115
+ ...projected[index].reportingProduct && { reportingProduct: projected[index].reportingProduct }
7116
+ }))
7117
+ };
7118
+ };
7119
+
7120
+ // src/schema/postPurchaseOfferEligibility.ts
7121
+ var import_zod74 = require("zod");
7122
+ var selection2 = PreparedPostPurchaseProduct.shape.selection;
7123
+ var PostPurchaseOfferSkipReason = import_zod74.z.enum(["empty", "no-eligible-subscription"]);
7124
+ var PostPurchaseOfferEligibilityContext = import_zod74.z.object({
7125
+ excludedProductIds: PostPurchaseExcludedProductIds,
7126
+ originalLineItems: import_zod74.z.array(selection2.pick({ productId: true, sellingPlanId: true, variantId: true }))
7127
+ });
7128
+ var PostPurchaseOfferEligibility = import_zod74.z.discriminatedUnion("status", [
7129
+ import_zod74.z.object({
7130
+ members: import_zod74.z.array(
7131
+ import_zod74.z.object({ productId: selection2.shape.productId, productIndex: import_zod74.z.number().int().nonnegative() })
7132
+ ),
7133
+ status: import_zod74.z.literal("retain")
7134
+ }),
7135
+ import_zod74.z.object({ reason: PostPurchaseOfferSkipReason, status: import_zod74.z.literal("skip") }),
7136
+ import_zod74.z.object({ reason: import_zod74.z.literal("eligible-upgrade").optional(), status: import_zod74.z.literal("unavailable") })
7137
+ ]);
7138
+
6343
7139
  // src/server/postPurchaseMemberEligibility.ts
6344
7140
  var PostPurchaseInventoryUnavailable = class extends Error {
6345
7141
  };
@@ -6415,74 +7211,6 @@ var classifyPostPurchaseOffer = (settings, response, context) => {
6415
7211
  }
6416
7212
  };
6417
7213
 
6418
- // src/schema/postPurchaseVariantDefault.ts
6419
- var import_zod61 = require("zod");
6420
- var values = PostPurchaseVariantValues.partial().extend({
6421
- option1: PostPurchaseVariantValues.shape.option1.nullish()
6422
- });
6423
- var variant = values.extend({
6424
- id: PostPurchaseVariantId,
6425
- inventoryManagement: import_zod61.z.string().nullable(),
6426
- inventoryPolicy: import_zod61.z.string(),
6427
- inventoryQuantity: import_zod61.z.number()
6428
- });
6429
- var options = import_zod61.z.array(PostPurchaseVariantOption.pick({ name: true, values: true }));
6430
- var PostPurchaseVariantDefaultProduct = import_zod61.z.object({
6431
- id: PostPurchaseProductId,
6432
- options,
6433
- selectedVariant: variant.optional(),
6434
- variants: import_zod61.z.array(variant)
6435
- });
6436
- var PostPurchaseVariantDefaultSettings = PostPurchaseSettings.shape.productOptions.pick({
6437
- hideOutOfStockVariants: true,
6438
- matchVariant: true
6439
- });
6440
- var PostPurchaseOrderAttributes = import_zod61.z.record(import_zod61.z.string(), import_zod61.z.array(import_zod61.z.string())).default({});
6441
- var PostPurchaseOriginalVariants = import_zod61.z.array(
6442
- import_zod61.z.object({ productId: PostPurchaseProductId, variantId: PostPurchaseVariantId })
6443
- );
6444
- var PostPurchaseAttributeProducts = import_zod61.z.array(
6445
- import_zod61.z.object({ id: PostPurchaseProductId, options, variants: import_zod61.z.array(values.extend({ id: PostPurchaseVariantId })) })
6446
- );
6447
-
6448
- // src/server/createPostPurchaseOrderAttributes.ts
6449
- var createPostPurchaseOrderAttributes = (original, enriched) => {
6450
- const products = PostPurchaseAttributeProducts.parse(enriched);
6451
- const attributes = {};
6452
- for (const item of PostPurchaseOriginalVariants.parse(original)) {
6453
- const product = products.find(({ id }) => id === item.productId);
6454
- const variant2 = product?.variants.find(({ id }) => id === item.variantId);
6455
- if (!variant2 || !product) continue;
6456
- ["option1", "option2", "option3"].forEach((key, index) => {
6457
- const value = variant2[key];
6458
- const option = product.options[index];
6459
- if (!value || !option) return;
6460
- const values2 = attributes[option.name] ?? [];
6461
- if (!values2.includes(value)) attributes[option.name] = [...values2, value];
6462
- });
6463
- }
6464
- return attributes;
6465
- };
6466
-
6467
- // src/server/readPostPurchaseGroupSelection.ts
6468
- var readPostPurchaseGroupSelection = (settings, response, requested, excludedProductIds) => {
6469
- const selection2 = PostPurchaseGroupSelection.parse(requested);
6470
- const { members, normalized } = normalizePostPurchaseCollection(settings, response);
6471
- const member = members.find(({ product }) => product.id === selection2.memberProductId);
6472
- if (!member || !member.product.productGroupVariants.length) return null;
6473
- const group = readPostPurchaseGroup(member.product, normalized.effective, excludedProductIds);
6474
- const entry = group.entries.find(({ product }) => product.id === selection2.productId);
6475
- if (!entry) return null;
6476
- return {
6477
- groupCatalog: group.catalog,
6478
- memberProductId: member.product.id,
6479
- productIndex: member.productIndex,
6480
- reportingProduct: { id: member.product.id, title: member.product.title },
6481
- response: { data: [entry.product], metadata: normalized.metadata },
6482
- variantCatalog: entry.variantCatalog
6483
- };
6484
- };
6485
-
6486
7214
  // src/server/preparePostPurchaseGroupDeclineDisplay.ts
6487
7215
  var preparePostPurchaseGroupDeclineDisplay = (settings, response, requested, excludedProductIds) => {
6488
7216
  const group = readPostPurchaseGroupSelection(settings, response, requested, excludedProductIds);
@@ -6499,47 +7227,21 @@ var preparePostPurchaseGroupDeclineDisplay = (settings, response, requested, exc
6499
7227
 
6500
7228
  // src/server/preparePostPurchaseOfferPresentation.ts
6501
7229
  var import_compat7 = require("es-toolkit/compat");
6502
- var import_zod64 = require("zod");
7230
+ var import_zod76 = require("zod");
6503
7231
 
6504
7232
  // src/schema/postPurchaseOfferPresentation.ts
6505
- var import_zod62 = require("zod");
7233
+ var import_zod75 = require("zod");
6506
7234
  var language2 = PostPurchaseSettings.shape.language.shape.global.unwrap().unwrap();
6507
- var PostPurchaseOfferPresentation = import_zod62.z.strictObject({
7235
+ var PostPurchaseOfferPresentation = import_zod75.z.strictObject({
6508
7236
  labels: language2.pick({ declineAll: true, declineThisOffer: true }),
6509
7237
  layout: PostPurchaseSettings.shape.offersLayout,
6510
7238
  sections: CABRootSection.nullable(),
6511
7239
  showDeclineAll: PostPurchaseSettings.shape.productOptions.shape.showDeclineAll
6512
7240
  });
6513
7241
 
6514
- // src/server/postPurchaseOfferCopy.ts
6515
- var import_zod63 = require("zod");
6516
- var Copy = import_zod63.z.object({
6517
- superTitle: CalloutBannerBlock.shape.settings.shape.superTitle.unwrap().optional().catch(void 0),
6518
- title: CalloutBannerBlock.shape.settings.shape.title.unwrap().optional().catch(void 0)
6519
- });
6520
- var Callout = import_zod63.z.object({ settings: import_zod63.z.record(import_zod63.z.string(), import_zod63.z.unknown()), type: import_zod63.z.literal("callout_banner") });
6521
- var postPurchaseOfferCopy = (blocks, metadata) => {
6522
- const copy = Copy.safeParse(metadata.widget.language);
6523
- if (!blocks || !copy.success) return blocks;
6524
- const first = blocks.findIndex((block) => Callout.pick({ type: true }).safeParse(block).success);
6525
- return blocks.map((block, index) => {
6526
- if (index !== first) return block;
6527
- const callout = Callout.passthrough().safeParse(block);
6528
- if (!callout.success) return block;
6529
- return {
6530
- ...callout.data,
6531
- settings: {
6532
- ...callout.data.settings,
6533
- ...copy.data.title && { title: copy.data.title },
6534
- ...copy.data.superTitle && { superTitle: copy.data.superTitle }
6535
- }
6536
- };
6537
- });
6538
- };
6539
-
6540
7242
  // src/server/preparePostPurchaseOfferPresentation.ts
6541
7243
  var FrameSettings = PostPurchaseSettings.pick({ language: true, offersLayout: true, productOptions: true }).extend({
6542
- blocks: import_zod64.z.array(import_zod64.z.unknown()).optional()
7244
+ blocks: import_zod76.z.array(import_zod76.z.unknown()).optional()
6543
7245
  });
6544
7246
  var preparePostPurchaseOfferPresentation = (widgetId, settings, response, report) => {
6545
7247
  const { metadata } = PostPurchaseProductSource.pick({ metadata: true }).parse(deepCamelCase(response));
@@ -6563,42 +7265,6 @@ var preparePostPurchaseOfferPresentation = (widgetId, settings, response, report
6563
7265
  });
6564
7266
  };
6565
7267
 
6566
- // src/schema/postPurchaseQuantity.ts
6567
- var import_zod65 = require("zod");
6568
- var quantity = PreparedPostPurchaseProduct.shape.selection.shape.quantity;
6569
- var PostPurchaseQuantityPolicy = PostPurchaseSettings.shape.quantityInputs.omit({ defaultQuantity: true }).extend({
6570
- initialQuantity: quantity,
6571
- maxValue: quantity,
6572
- minValue: import_zod65.z.literal(0).transform(() => 1).or(quantity)
6573
- }).refine(({ maxValue, minValue }) => minValue <= maxValue, "Quantity bounds are reversed");
6574
-
6575
- // src/server/readPostPurchaseQuantity.ts
6576
- var PostPurchaseQuantityUnavailable = class extends Error {
6577
- };
6578
- var readPostPurchaseQuantity = ({
6579
- data,
6580
- effective,
6581
- original
6582
- }, selection2) => {
6583
- const positive = PreparedPostPurchaseProduct.shape.selection.shape.quantity;
6584
- for (const config of [original, effective]) {
6585
- if (!config.quantityInputs.enabled) continue;
6586
- const initialQuantity2 = positive.parse(config.quantityInputs.defaultQuantity);
6587
- const policy2 = PostPurchaseQuantityPolicy.parse({ ...config.quantityInputs, initialQuantity: initialQuantity2 });
6588
- if (initialQuantity2 < policy2.minValue || initialQuantity2 > policy2.maxValue)
6589
- throw new Error("Configured quantity default is outside its bounds");
6590
- }
6591
- const initialQuantity = data[0]?.metadata?.productQuantity ?? (original.quantityInputs.enabled ? original.quantityInputs.defaultQuantity : 1);
6592
- const policy = PostPurchaseQuantityPolicy.parse(
6593
- effective.quantityInputs.enabled ? { ...effective.quantityInputs, initialQuantity } : { enabled: false, initialQuantity, maxValue: initialQuantity, minValue: initialQuantity }
6594
- );
6595
- const requested = "quantity" in selection2 ? selection2.quantity : selection2.expectedQuantity === initialQuantity ? void 0 : selection2.expectedQuantity;
6596
- const quantity2 = positive.parse(requested ?? initialQuantity);
6597
- if (requested !== void 0 && (policy.enabled ? quantity2 < policy.minValue || quantity2 > policy.maxValue : quantity2 !== initialQuantity))
6598
- throw new PostPurchaseQuantityUnavailable("Requested quantity is unavailable");
6599
- return { policy, quantity: quantity2 };
6600
- };
6601
-
6602
7268
  // src/server/analytics.ts
6603
7269
  var import_es_toolkit7 = require("es-toolkit");
6604
7270
 
@@ -6735,7 +7401,7 @@ var postAnalyticsEvents = async (input, ctx) => {
6735
7401
  };
6736
7402
 
6737
7403
  // src/server/requestSchemas.ts
6738
- var import_zod66 = require("zod");
7404
+ var import_zod77 = require("zod");
6739
7405
  var REQUEST_BOUNDS = {
6740
7406
  /** Cart-level attributes per cart. */
6741
7407
  CART_ATTRIBUTES_MAX: 100,
@@ -6766,42 +7432,42 @@ var REQUEST_BOUNDS = {
6766
7432
  /** Rich ads transaction lines — the engine's ads contract. */
6767
7433
  TRANSACTION_ITEMS_MAX: 50
6768
7434
  };
6769
- var KeyValue = import_zod66.z.object({
6770
- key: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
6771
- value: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_VALUE_MAX).optional()
7435
+ var KeyValue = import_zod77.z.object({
7436
+ key: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
7437
+ value: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_VALUE_MAX).optional()
6772
7438
  });
6773
- var CartLineInputSchema = import_zod66.z.object({
6774
- productId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6775
- properties: import_zod66.z.array(KeyValue).max(REQUEST_BOUNDS.LINE_PROPERTIES_MAX).optional(),
6776
- quantity: import_zod66.z.number(),
6777
- subscriptionId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6778
- variantId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX)
7439
+ var CartLineInputSchema = import_zod77.z.object({
7440
+ productId: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7441
+ properties: import_zod77.z.array(KeyValue).max(REQUEST_BOUNDS.LINE_PROPERTIES_MAX).optional(),
7442
+ quantity: import_zod77.z.number(),
7443
+ subscriptionId: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7444
+ variantId: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX)
6779
7445
  });
6780
- var CartInputSchema = import_zod66.z.object({
6781
- attributes: import_zod66.z.array(KeyValue).max(REQUEST_BOUNDS.CART_ATTRIBUTES_MAX).optional(),
7446
+ var CartInputSchema = import_zod77.z.object({
7447
+ attributes: import_zod77.z.array(KeyValue).max(REQUEST_BOUNDS.CART_ATTRIBUTES_MAX).optional(),
6782
7448
  /**
6783
7449
  * Presentment-per-shop-currency FX rate (buyer price ÷ shop price, e.g. `1.35` for a USD shop
6784
7450
  * selling in CAD). Money rule thresholds are authored in SHOP currency, so the engine subtotal is
6785
7451
  * divided by this before evaluation. Omit (or send 1) when the cart is already in the shop's currency.
6786
7452
  */
6787
- currencyRate: import_zod66.z.number().optional(),
7453
+ currencyRate: import_zod77.z.number().optional(),
6788
7454
  /** Applied discount codes; the engine evaluates `discount_code` rules against them (sent as `[{code}]`). */
6789
- discountCodes: import_zod66.z.array(import_zod66.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX)).max(REQUEST_BOUNDS.DISCOUNT_CODES_MAX).optional(),
7455
+ discountCodes: import_zod77.z.array(import_zod77.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX)).max(REQUEST_BOUNDS.DISCOUNT_CODES_MAX).optional(),
6790
7456
  /** Presentment cents of cart-level discount allocations, subtracted from `subtotal` for the engine. */
6791
- discountTotal: import_zod66.z.number().optional(),
6792
- items: import_zod66.z.array(CartLineInputSchema).max(REQUEST_BOUNDS.CART_ITEMS_MAX),
7457
+ discountTotal: import_zod77.z.number().optional(),
7458
+ items: import_zod77.z.array(CartLineInputSchema).max(REQUEST_BOUNDS.CART_ITEMS_MAX),
6793
7459
  /** Presentment subtotal in cents. */
6794
- subtotal: import_zod66.z.number()
7460
+ subtotal: import_zod77.z.number()
6795
7461
  });
6796
- var UserConfigInputSchema = import_zod66.z.object({ shop: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX) });
6797
- var DataSourceInputSchema = import_zod66.z.object({
7462
+ var UserConfigInputSchema = import_zod77.z.object({ shop: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX) });
7463
+ var DataSourceInputSchema = import_zod77.z.object({
6798
7464
  cart: CartInputSchema,
6799
7465
  /**
6800
7466
  * Numeric Shopify company-location id when the buyer is a B2B session (`buyerIdentity.purchasingCompany`).
6801
7467
  * Present ⇒ the orchestrator filters results by the location's catalog via admin-api (REB-23713); the
6802
7468
  * client's country-context market check is bypassed for B2B (it false-negatives B2B-catalog products).
6803
7469
  */
6804
- companyLocationId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7470
+ companyLocationId: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6805
7471
  /**
6806
7472
  * Buyer's market country (ISO 3166-1 alpha-2) — forwarded to the engine as the `country_code` PARAM
6807
7473
  * when the shop's markets toggle is on (REB-21688; the sink was the `X-Country-Code` header under
@@ -6810,16 +7476,16 @@ var DataSourceInputSchema = import_zod66.z.object({
6810
7476
  * uppercase (the wire value is forwarded verbatim as the param) so a case-sensitive engine lookup
6811
7477
  * can't silently miss a lowercase code — `adsEngine.ts` uppercases for the same reason.
6812
7478
  */
6813
- country: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).regex(/^[A-Za-z]{2}$/, "must be an ISO 3166-1 alpha-2 country code (e.g. CA)").transform((value) => value.toUpperCase()).optional(),
6814
- customerId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6815
- dataSourcePath: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
7479
+ country: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).regex(/^[A-Za-z]{2}$/, "must be an ISO 3166-1 alpha-2 country code (e.g. CA)").transform((value) => value.toUpperCase()).optional(),
7480
+ customerId: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7481
+ dataSourcePath: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
6816
7482
  /**
6817
7483
  * Engine `filter_inputs` override: `'no'` keeps in-cart (input) products in the results/rule
6818
7484
  * outputs — gift validation sends it so a gift's own product can appear in its answer. Omitted = the
6819
7485
  * engine's default filtering.
6820
7486
  */
6821
- filterInputs: import_zod66.z.enum(["no", "yes"]).optional(),
6822
- integrations: import_zod66.z.record(import_zod66.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), import_zod66.z.boolean()).refine((record) => Object.keys(record).length <= REQUEST_BOUNDS.INTEGRATION_KEYS_MAX, {
7487
+ filterInputs: import_zod77.z.enum(["no", "yes"]).optional(),
7488
+ integrations: import_zod77.z.record(import_zod77.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), import_zod77.z.boolean()).refine((record) => Object.keys(record).length <= REQUEST_BOUNDS.INTEGRATION_KEYS_MAX, {
6823
7489
  message: `Too many integration keys (max ${REQUEST_BOUNDS.INTEGRATION_KEYS_MAX})`
6824
7490
  }).optional(),
6825
7491
  /**
@@ -6832,31 +7498,31 @@ var DataSourceInputSchema = import_zod66.z.object({
6832
7498
  * request header) fails the regex. Callers should send the buyer's resolved locale (e.g. Shopify
6833
7499
  * checkout's `localization.language.isoCode`), not the request header verbatim.
6834
7500
  */
6835
- language: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).regex(/^[A-Za-z0-9-]+$/, "must be a single BCP-47 tag (e.g. fr-CA), not a q-value list").optional(),
6836
- limit: import_zod66.z.number().max(REQUEST_BOUNDS.LIMIT_MAX),
6837
- productType: import_zod66.z.enum(["both", "one-time", "subscription"]).optional(),
6838
- shop: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6839
- visitorId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
6840
- });
6841
- var GiftInputSchema = import_zod66.z.object({
6842
- cost: import_zod66.z.number(),
6843
- discounted: import_zod66.z.boolean(),
7501
+ language: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).regex(/^[A-Za-z0-9-]+$/, "must be a single BCP-47 tag (e.g. fr-CA), not a q-value list").optional(),
7502
+ limit: import_zod77.z.number().max(REQUEST_BOUNDS.LIMIT_MAX),
7503
+ productType: import_zod77.z.enum(["both", "one-time", "subscription"]).optional(),
7504
+ shop: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7505
+ visitorId: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
7506
+ });
7507
+ var GiftInputSchema = import_zod77.z.object({
7508
+ cost: import_zod77.z.number(),
7509
+ discounted: import_zod77.z.boolean(),
6844
7510
  /**
6845
7511
  * Which gift attribution the line carries (REB-24363). Defaults to `gwp` because a client that predates
6846
7512
  * the field only ever sent GWP lines — without the default an older extension's request would 422.
6847
7513
  */
6848
- kind: import_zod66.z.enum(GIFT_KINDS).default("gwp"),
6849
- lineId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6850
- productId: import_zod66.z.number(),
7514
+ kind: import_zod77.z.enum(GIFT_KINDS).default("gwp"),
7515
+ lineId: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7516
+ productId: import_zod77.z.number(),
6851
7517
  /**
6852
7518
  * The line's unit count (REB-24363) — the selectable-GWP verdict trims surplus units against milestone
6853
7519
  * capacity. The second deliberate default: a client predating the field sent only GWP lines, whose
6854
7520
  * verdict is whole-line, so a missing quantity reads as one unit rather than 422ing the older request.
6855
7521
  */
6856
- quantity: import_zod66.z.number().int().min(1).default(1),
6857
- widgetId: import_zod66.z.number()
7522
+ quantity: import_zod77.z.number().int().min(1).default(1),
7523
+ widgetId: import_zod77.z.number()
6858
7524
  });
6859
- var GiftValidationInputSchema = import_zod66.z.object({
7525
+ var GiftValidationInputSchema = import_zod77.z.object({
6860
7526
  cart: CartInputSchema,
6861
7527
  /**
6862
7528
  * Buyer's market country — threaded into the per-widget data-source evaluations, which forward it to
@@ -6865,25 +7531,25 @@ var GiftValidationInputSchema = import_zod66.z.object({
6865
7531
  * turns markets off); regex-bound and uppercase-normalized for the same reasons as
6866
7532
  * `DataSourceInputSchema`'s `country`.
6867
7533
  */
6868
- country: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).regex(/^[A-Za-z]{2}$/, "must be an ISO 3166-1 alpha-2 country code (e.g. CA)").transform((value) => value.toUpperCase()).optional(),
6869
- customerId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6870
- gifts: import_zod66.z.array(GiftInputSchema).max(REQUEST_BOUNDS.GIFTS_MAX),
7534
+ country: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).regex(/^[A-Za-z]{2}$/, "must be an ISO 3166-1 alpha-2 country code (e.g. CA)").transform((value) => value.toUpperCase()).optional(),
7535
+ customerId: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7536
+ gifts: import_zod77.z.array(GiftInputSchema).max(REQUEST_BOUNDS.GIFTS_MAX),
6871
7537
  /**
6872
7538
  * Buyer's checkout language — threaded into the per-widget data-source evaluations, which normalize
6873
7539
  * and forward it as the engine `locale` param under the same markets-toggle gate (REB-21688). MUST be
6874
7540
  * a single BCP-47 tag, for the same reason as `DataSourceInputSchema`'s `language` above.
6875
7541
  */
6876
- language: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).regex(/^[A-Za-z0-9-]+$/, "must be a single BCP-47 tag (e.g. fr-CA), not a q-value list").optional(),
6877
- shop: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6878
- visitorId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
7542
+ language: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).regex(/^[A-Za-z0-9-]+$/, "must be a single BCP-47 tag (e.g. fr-CA), not a q-value list").optional(),
7543
+ shop: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7544
+ visitorId: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
6879
7545
  });
6880
- var GiftAdjustmentSchema = import_zod66.z.object({
6881
- lineId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6882
- quantity: import_zod66.z.number().int().nonnegative()
7546
+ var GiftAdjustmentSchema = import_zod77.z.object({
7547
+ lineId: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7548
+ quantity: import_zod77.z.number().int().nonnegative()
6883
7549
  });
6884
- var GiftValidationResponseSchema = import_zod66.z.object({
6885
- adjust: import_zod66.z.array(GiftAdjustmentSchema).max(REQUEST_BOUNDS.GIFTS_MAX).default([]),
6886
- remove: import_zod66.z.array(import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX)).max(REQUEST_BOUNDS.GIFTS_MAX).refine(
7550
+ var GiftValidationResponseSchema = import_zod77.z.object({
7551
+ adjust: import_zod77.z.array(GiftAdjustmentSchema).max(REQUEST_BOUNDS.GIFTS_MAX).default([]),
7552
+ remove: import_zod77.z.array(import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX)).max(REQUEST_BOUNDS.GIFTS_MAX).refine(
6887
7553
  (remove) => new Set(remove).size === remove.length,
6888
7554
  "a line id may appear at most once in `remove`"
6889
7555
  )
@@ -6894,47 +7560,47 @@ var GiftValidationResponseSchema = import_zod66.z.object({
6894
7560
  ({ adjust }) => new Set(adjust.map(({ lineId }) => lineId)).size === adjust.length,
6895
7561
  "a line id may appear at most once in `adjust`"
6896
7562
  );
6897
- var MonetizeTransactionItemSchema = import_zod66.z.object({
6898
- id: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6899
- priceCents: import_zod66.z.number(),
6900
- quantity: import_zod66.z.number(),
6901
- title: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX),
6902
- type: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX)
6903
- });
6904
- var MonetizeInputSchema = import_zod66.z.object({
7563
+ var MonetizeTransactionItemSchema = import_zod77.z.object({
7564
+ id: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7565
+ priceCents: import_zod77.z.number(),
7566
+ quantity: import_zod77.z.number(),
7567
+ title: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX),
7568
+ type: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX)
7569
+ });
7570
+ var MonetizeInputSchema = import_zod77.z.object({
6905
7571
  cart: CartInputSchema,
6906
7572
  /** Client-minted render-beacon correlation id; forwarded to the ads engine as `client_request_id`. */
6907
- clientRequestId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6908
- country: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6909
- currency: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7573
+ clientRequestId: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7574
+ country: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7575
+ currency: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6910
7576
  /** Ads-targeting identity/geo/locale fields (React parity); folded into the engine query verbatim. */
6911
- customerEmail: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
6912
- customerFirstName: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
6913
- customerId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6914
- customerLastName: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
6915
- language: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7577
+ customerEmail: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
7578
+ customerFirstName: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
7579
+ customerId: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7580
+ customerLastName: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
7581
+ language: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6916
7582
  /** Buyer-facing order name (e.g. `#1001`) for the server-composed "Order … Confirmed" chrome line. */
6917
- orderName: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
7583
+ orderName: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
6918
7584
  /** Ads surface label, forwarded verbatim; `customer_account` is measured/floored as its own surface (the account-area order list). */
6919
- placement: import_zod66.z.enum(["customer_account", "order_status", "thank_you_page"]),
7585
+ placement: import_zod77.z.enum(["customer_account", "order_status", "thank_you_page"]),
6920
7586
  /** Privacy Policy footer href — the Monetize widget's `privacy_policy_url` setting (React parity). */
6921
- privacyPolicyUrl: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_URL_MAX).optional(),
7587
+ privacyPolicyUrl: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_URL_MAX).optional(),
6922
7588
  /** 30-min rolling session id (React parity); used for the ads `session_id`, else the visitor id. */
6923
- sessionId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6924
- shop: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7589
+ sessionId: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7590
+ shop: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6925
7591
  /** Editor/QA indicator; OR-ed into the ads-engine `testing` flag so it stays out of billing/reporting. */
6926
- testing: import_zod66.z.boolean().optional(),
6927
- timezone: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7592
+ testing: import_zod77.z.boolean().optional(),
7593
+ timezone: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6928
7594
  /** Decorated (numeric) order id → the ads `transaction_id`. */
6929
- transactionId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7595
+ transactionId: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6930
7596
  /** Rich per-line ads items; capped at the engine's ads contract. Preferred over `cart.items`. */
6931
- transactionItems: import_zod66.z.array(MonetizeTransactionItemSchema).max(REQUEST_BOUNDS.TRANSACTION_ITEMS_MAX).optional(),
7597
+ transactionItems: import_zod77.z.array(MonetizeTransactionItemSchema).max(REQUEST_BOUNDS.TRANSACTION_ITEMS_MAX).optional(),
6932
7598
  /** Order total in presentment cents (React prefers total over subtotal); else `cart.subtotal`. */
6933
- transactionTotal: import_zod66.z.number().optional(),
6934
- visitorId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6935
- zipCode: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
7599
+ transactionTotal: import_zod77.z.number().optional(),
7600
+ visitorId: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7601
+ zipCode: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
6936
7602
  });
6937
- var WidgetSettingsInputSchema = import_zod66.z.object({
7603
+ var WidgetSettingsInputSchema = import_zod77.z.object({
6938
7604
  /**
6939
7605
  * Same domain as `CabShopConfig.cacheKey`, for the same reason: this side WINS the orchestrator's
6940
7606
  * `input.cacheKey ?? config.shop.cacheKey` (and an explicit value skips the config read entirely), so
@@ -6942,9 +7608,9 @@ var WidgetSettingsInputSchema = import_zod66.z.object({
6942
7608
  * and pin the edge copy permanently stale. `.catch(undefined)` because a bogus buster should degrade
6943
7609
  * the read to un-busted, never 400 a widget render.
6944
7610
  */
6945
- cacheKey: import_zod66.z.number().int().positive().optional().catch(void 0),
6946
- id: import_zod66.z.number(),
6947
- key: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7611
+ cacheKey: import_zod77.z.number().int().positive().optional().catch(void 0),
7612
+ id: import_zod77.z.number(),
7613
+ key: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6948
7614
  /**
6949
7615
  * Monetize context for inline hydration: when present AND the widget converts to a Monetize marker,
6950
7616
  * the server fetches/composes the offer cards inside this same request (no second `/cab/monetize`
@@ -6953,34 +7619,34 @@ var WidgetSettingsInputSchema = import_zod66.z.object({
6953
7619
  * `privacyPolicyUrl` comes from the widget settings server-side (more authoritative than a relay).
6954
7620
  */
6955
7621
  monetize: MonetizeInputSchema.omit({ privacyPolicyUrl: true, shop: true }).optional(),
6956
- shop: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7622
+ shop: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6957
7623
  /** Stable per-buyer id; when present, enables sticky server-side A/B variant selection. */
6958
- visitorId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
7624
+ visitorId: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
6959
7625
  });
6960
- var AnalyticsEventInputSchema = import_zod66.z.object({
6961
- name: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
6962
- properties: import_zod66.z.record(import_zod66.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), import_zod66.z.unknown()).optional(),
6963
- sentAt: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
7626
+ var AnalyticsEventInputSchema = import_zod77.z.object({
7627
+ name: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
7628
+ properties: import_zod77.z.record(import_zod77.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), import_zod77.z.unknown()).optional(),
7629
+ sentAt: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
6964
7630
  });
6965
- var AnalyticsSegmentsInputSchema = import_zod66.z.object({
6966
- device: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
6967
- source: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
6968
- visitor: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0)
7631
+ var AnalyticsSegmentsInputSchema = import_zod77.z.object({
7632
+ device: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
7633
+ source: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
7634
+ visitor: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0)
6969
7635
  });
6970
- var AnalyticsInputSchema = import_zod66.z.object({
7636
+ var AnalyticsInputSchema = import_zod77.z.object({
6971
7637
  /** Rebuy cart token (the `r_cart_token` cart attribute), when available — primary aggregation key. */
6972
- cartToken: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7638
+ cartToken: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6973
7639
  /** Shopify checkout token, when available — drives cart/checkout aggregation downstream. */
6974
- checkoutToken: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6975
- events: import_zod66.z.array(AnalyticsEventInputSchema).max(REQUEST_BOUNDS.EVENTS_MAX),
7640
+ checkoutToken: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7641
+ events: import_zod77.z.array(AnalyticsEventInputSchema).max(REQUEST_BOUNDS.EVENTS_MAX),
6976
7642
  /**
6977
7643
  * Request-scoped like the tokens: one visitor's segments apply to every event in the batch. The container
6978
7644
  * degrades too (`null` is a realistic wire artifact of `attributes ? {…} : null`), so the degrade rule is
6979
7645
  * total: nothing about `segments` can cost the envelope.
6980
7646
  */
6981
7647
  segments: AnalyticsSegmentsInputSchema.optional().catch(void 0),
6982
- shop: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6983
- visitorId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7648
+ shop: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7649
+ visitorId: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6984
7650
  /** The widget id (smartBlockId) the events belong to. */
6985
- widgetId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
7651
+ widgetId: import_zod77.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
6986
7652
  });