@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
@@ -2119,7 +2119,7 @@ var stripContentBlockHtml = (text2) => text2.replace(HTML_COMMENT_RE, "").replac
2119
2119
  var convertTextToTiptapParagraph = ({
2120
2120
  color,
2121
2121
  fontSize,
2122
- marks = [],
2122
+ marks: marks2 = [],
2123
2123
  text: text2,
2124
2124
  textAlign
2125
2125
  }) => {
@@ -2128,7 +2128,7 @@ var convertTextToTiptapParagraph = ({
2128
2128
  attrs: { textAlign },
2129
2129
  content: sanitizedText ? [
2130
2130
  {
2131
- marks: [{ attrs: { color, fontSize }, type: "textStyle" }, ...marks],
2131
+ marks: [{ attrs: { color, fontSize }, type: "textStyle" }, ...marks2],
2132
2132
  text: sanitizedText,
2133
2133
  type: "text"
2134
2134
  }
@@ -2585,11 +2585,11 @@ var pushText = (state, rawText) => {
2585
2585
  decodeTextEntities(rawText).split("\n").forEach((segment, index) => {
2586
2586
  if (index > 0) flushParagraph(state);
2587
2587
  if (!segment) return;
2588
- const marks = state.stack.flatMap((entry) => entry.marks);
2589
- if (state.defaultTextStyleMark && !marks.some((mark) => mark.type === "textStyle")) {
2590
- marks.push(state.defaultTextStyleMark);
2588
+ const marks2 = state.stack.flatMap((entry) => entry.marks);
2589
+ if (state.defaultTextStyleMark && !marks2.some((mark) => mark.type === "textStyle")) {
2590
+ marks2.push(state.defaultTextStyleMark);
2591
2591
  }
2592
- state.currentRuns.push(TiptapText.parse(marks.length > 0 ? { marks, text: segment } : { text: segment }));
2592
+ state.currentRuns.push(TiptapText.parse(marks2.length > 0 ? { marks: marks2, text: segment } : { text: segment }));
2593
2593
  });
2594
2594
  };
2595
2595
 
@@ -3164,10 +3164,10 @@ var SWITCH_LABEL_TOKENS2 = ["subscriptionDiscount", "frequency", "interval"];
3164
3164
  var QUANTITY_ERROR_TOKENS = ["max", "min", "step"];
3165
3165
  var VARIANT_SELECTOR = { button: "button", radio: "radio", select: "menu" };
3166
3166
  var buildStyledText = (token, style, fontSize = style?.textSize ?? "base") => {
3167
- const marks = [{ attrs: { color: "base", fontSize }, type: "textStyle" }];
3168
- if (style?.textEmphasis === "bold") marks.push({ type: "bold" });
3169
- if (style?.textEmphasis === "italic") marks.push({ type: "italic" });
3170
- return { content: [{ content: [{ marks, text: token, type: "text" }], type: "paragraph" }], type: "doc" };
3167
+ const marks2 = [{ attrs: { color: "base", fontSize }, type: "textStyle" }];
3168
+ if (style?.textEmphasis === "bold") marks2.push({ type: "bold" });
3169
+ if (style?.textEmphasis === "italic") marks2.push({ type: "italic" });
3170
+ return { content: [{ content: [{ marks: marks2, text: token, type: "text" }], type: "paragraph" }], type: "doc" };
3171
3171
  };
3172
3172
  var buildPriceContent = () => ({
3173
3173
  content: [
@@ -5889,13 +5889,13 @@ var projectPostPurchasePlanCatalog = (normalized, report) => {
5889
5889
  };
5890
5890
 
5891
5891
  // src/schema/postPurchaseSubscriptionProduct.ts
5892
- import { z as z54 } from "zod";
5892
+ import { z as z55 } from "zod";
5893
5893
 
5894
5894
  // src/schema/postPurchaseProduct.ts
5895
- import { z as z53 } from "zod";
5895
+ import { z as z54 } from "zod";
5896
5896
 
5897
5897
  // src/schema/postPurchaseProductDisplay.ts
5898
- import { z as z51 } from "zod";
5898
+ import { z as z52 } from "zod";
5899
5899
 
5900
5900
  // src/schema/postPurchaseProductGallery.ts
5901
5901
  import { z as z50 } from "zod";
@@ -5911,21 +5911,44 @@ var PostPurchaseProductGallery = z50.object({
5911
5911
  selectedImageId: z50.number().int().positive().optional()
5912
5912
  });
5913
5913
 
5914
+ // src/schema/postPurchaseProductReviews.ts
5915
+ import { z as z51 } from "zod";
5916
+ var decimal = z51.union([
5917
+ z51.number(),
5918
+ z51.string().regex(/^\d+(?:\.\d+)?$/).transform(Number)
5919
+ ]);
5920
+ var PostPurchaseCommonReviewRating = z51.object({ value: decimal.pipe(z51.number().min(0).max(5)) });
5921
+ var PostPurchaseKlaviyoReviewRating = PostPurchaseCommonReviewRating.extend({
5922
+ // Legacy validates key presence, then displays the raw value on five stars without rescaling.
5923
+ scale_max: z51.unknown().nonoptional(),
5924
+ scale_min: z51.unknown().nonoptional()
5925
+ });
5926
+ var PostPurchaseReviewCount = z51.string().regex(/^\d+(?:\.\d+)?$/).transform(Number).pipe(z51.number().int().nonnegative());
5927
+ var PostPurchaseReviewStyles = PostPurchaseSettings.shape.styles.unwrap().extend({
5928
+ strokeWidth: decimal.pipe(z51.number().nonnegative()).default(1)
5929
+ }).prefault({});
5930
+ var PostPurchaseProductReviews = z51.object({
5931
+ color: z51.string(),
5932
+ rating: z51.number().positive().max(5),
5933
+ reviewCount: z51.number().int().nonnegative(),
5934
+ reviewsPlural: z51.string(),
5935
+ reviewsSingular: z51.string(),
5936
+ size: z51.enum(["small", "medium", "large"]),
5937
+ strokeColor: z51.string(),
5938
+ strokeWidth: z51.number().nonnegative()
5939
+ });
5940
+
5914
5941
  // src/schema/postPurchaseProductDisplay.ts
5915
5942
  var language = PostPurchaseSettings.shape.language;
5916
- var PostPurchasePrimaryImageSource = z51.string().default(
5943
+ var PostPurchasePrimaryImageSource = z52.string().default(
5917
5944
  "https://cdn.shopify.com/shopifycloud/shopify/assets/no-image-2048-5e88c1b20e087fb7bbe9a3771824e743c244f437e4f8ba93bbf7b11b53f7824c.gif"
5918
5945
  );
5919
- var PostPurchaseProductDisplay = z51.object({
5946
+ var PostPurchaseProductDisplay = z52.object({
5947
+ descriptionDocument: TiptapDocument.optional(),
5920
5948
  discountedFrom: PostPurchaseSettings.shape.discountedFrom,
5921
5949
  gallery: PostPurchaseProductGallery.optional(),
5922
- language: language.pick({
5923
- description: true,
5924
- descriptionEnabled: true,
5925
- descriptionRte: true,
5926
- descriptionSpacing: true
5927
- }),
5928
- primaryImage: z51.object({ description: z51.string(), source: z51.string() }),
5950
+ language: language.pick({ description: true, descriptionEnabled: true }),
5951
+ primaryImage: z52.object({ description: z52.string(), source: z52.string() }),
5929
5952
  productOptions: PostPurchaseSettings.shape.productOptions.pick({
5930
5953
  showDeclineAll: true,
5931
5954
  showShipping: true,
@@ -5935,18 +5958,19 @@ var PostPurchaseProductDisplay = z51.object({
5935
5958
  showVariantSelectors: true
5936
5959
  }),
5937
5960
  responseDescription: language.shape.description,
5961
+ reviews: PostPurchaseProductReviews.nullable().default(null),
5938
5962
  shouldShowSavingText: PostPurchaseSettings.shape.discount.shape.shouldShowSavingText
5939
5963
  });
5940
5964
 
5941
5965
  // src/schema/postPurchaseSubscription.ts
5942
- import { z as z52 } from "zod";
5943
- var PostPurchaseSubscriptionTerms = z52.object({
5966
+ import { z as z53 } from "zod";
5967
+ var PostPurchaseSubscriptionTerms = z53.object({
5944
5968
  adjustment: PostPurchasePlanAdjustment.optional(),
5945
- initialShippingPrice: z52.number().nonnegative(),
5946
- intervalLabel: z52.string().min(1),
5947
- name: z52.string().min(1),
5948
- recurringShippingPrice: z52.number().nonnegative(),
5949
- shippingOption: z52.object({ presentmentTitle: z52.string(), title: z52.string() })
5969
+ initialShippingPrice: z53.number().nonnegative(),
5970
+ intervalLabel: z53.string().min(1),
5971
+ name: z53.string().min(1),
5972
+ recurringShippingPrice: z53.number().nonnegative(),
5973
+ shippingOption: z53.object({ presentmentTitle: z53.string(), title: z53.string() })
5950
5974
  });
5951
5975
 
5952
5976
  // src/schema/postPurchaseProduct.ts
@@ -5956,51 +5980,51 @@ var PostPurchaseVariant = OfferProduct.shape.variants.element.pick({ id: true, t
5956
5980
  id: PostPurchaseVariantId,
5957
5981
  price: PostPurchaseAmount
5958
5982
  });
5959
- var PreparedPostPurchaseProduct = z53.object({
5983
+ var PreparedPostPurchaseProduct = z54.object({
5960
5984
  display: PostPurchaseProductDisplay,
5961
- labels: z53.object({
5985
+ labels: z54.object({
5962
5986
  declineAll: global.declineAll,
5963
- free: z53.string(),
5964
- payNow: z53.string(),
5965
- quantity: z53.string(),
5987
+ free: z54.string(),
5988
+ payNow: z54.string(),
5989
+ quantity: z54.string(),
5966
5990
  recurringShipping: global.recurringShipping,
5967
5991
  recurringSubtotal: global.recurringSubtotal,
5968
- save: z53.string(),
5969
- shipping: z53.string(),
5970
- subtotal: z53.string(),
5971
- taxes: z53.string(),
5972
- total: z53.string()
5992
+ save: z54.string(),
5993
+ shipping: z54.string(),
5994
+ subtotal: z54.string(),
5995
+ taxes: z54.string(),
5996
+ total: z54.string()
5973
5997
  }),
5974
5998
  product: OfferProduct.pick({ description: true, id: true, image: true, title: true }).extend({
5975
5999
  description: OfferProduct.shape.description.nullable(),
5976
6000
  id: PostPurchaseProductId,
5977
6001
  variant: PostPurchaseVariant
5978
6002
  }),
5979
- selection: z53.object({
6003
+ selection: z54.object({
5980
6004
  productId: PostPurchaseProductId,
5981
- quantity: z53.number().int().positive(),
5982
- sellingPlanId: z53.number().int().positive().optional(),
6005
+ quantity: z54.number().int().positive(),
6006
+ sellingPlanId: z54.number().int().positive().optional(),
5983
6007
  variantId: PostPurchaseVariantId
5984
6008
  }),
5985
- status: z53.literal("prepared"),
5986
- terms: z53.object({
6009
+ status: z54.literal("prepared"),
6010
+ terms: z54.object({
5987
6011
  discount: PostPurchaseDiscount,
5988
- shipping: z53.object({
5989
- amount: z53.number().nonnegative(),
5990
- title: z53.string(),
5991
- type: z53.enum(["free", "fixed_amount"])
6012
+ shipping: z54.object({
6013
+ amount: z54.number().nonnegative(),
6014
+ title: z54.string(),
6015
+ type: z54.enum(["free", "fixed_amount"])
5992
6016
  }),
5993
6017
  subscription: PostPurchaseSubscriptionTerms.optional()
5994
6018
  })
5995
6019
  });
5996
- var PostPurchasePreparation = z53.discriminatedUnion("status", [
6020
+ var PostPurchasePreparation = z54.discriminatedUnion("status", [
5997
6021
  PreparedPostPurchaseProduct,
5998
- z53.object({ reason: z53.string(), status: z53.literal("unsupported") })
6022
+ z54.object({ reason: z54.string(), status: z54.literal("unsupported") })
5999
6023
  ]);
6000
6024
 
6001
6025
  // src/schema/postPurchaseSubscriptionProduct.ts
6002
6026
  var PreparedPostPurchaseSubscription = PreparedPostPurchaseProduct.extend({
6003
- selection: PreparedPostPurchaseProduct.shape.selection.extend({ sellingPlanId: z54.number().int().positive() }),
6027
+ selection: PreparedPostPurchaseProduct.shape.selection.extend({ sellingPlanId: z55.number().int().positive() }),
6004
6028
  terms: PreparedPostPurchaseProduct.shape.terms.extend({
6005
6029
  subscription: PostPurchaseSubscriptionTerms
6006
6030
  }).refine(
@@ -6042,7 +6066,7 @@ var subscriptionUnavailable = (normalized, plan, allowCollection, quantity2) =>
6042
6066
  };
6043
6067
 
6044
6068
  // src/server/postPurchaseProductDisplay.ts
6045
- import { z as z55 } from "zod";
6069
+ import { z as z57 } from "zod";
6046
6070
 
6047
6071
  // src/server/postPurchasePrimaryImage.ts
6048
6072
  var postPurchasePrimaryImage = (product) => {
@@ -6063,9 +6087,67 @@ var postPurchaseProductGallery = (product, limit) => ({
6063
6087
  selectedImageId: product.images?.find((image) => image.id === product.variants[0].imageId)?.id
6064
6088
  });
6065
6089
 
6090
+ // src/transforms/postPurchase/convertDescriptionRte.ts
6091
+ import { z as z56 } from "zod";
6092
+ var alignments = { center: "center", left: "start", right: "end" };
6093
+ var colors = ["critical", "subdued", "success", "warning"];
6094
+ var sizes2 = ["extraSmall", "small", "medium", "large", "extraLarge"];
6095
+ var spacings2 = {
6096
+ default: "base",
6097
+ loose: "loose",
6098
+ none: "none",
6099
+ tight: "tight",
6100
+ xloose: "extraLoose",
6101
+ xtight: "extraTight"
6102
+ };
6103
+ var Block = z56.object({
6104
+ attrs: z56.object({ alignment: z56.enum(["left", "center", "right"]).optional().catch(void 0) }).catch({}),
6105
+ content: z56.array(z56.unknown()).catch([]),
6106
+ type: z56.literal("ShopifyTextBlock")
6107
+ });
6108
+ var Run = z56.object({ marks: z56.array(z56.unknown()).catch([]), text: z56.string().min(1), type: z56.literal("text") });
6109
+ var Inline = z56.object({
6110
+ attrs: z56.object({
6111
+ color: z56.enum(colors).optional().catch(void 0),
6112
+ emphasis: z56.array(z56.unknown()).catch([]),
6113
+ size: z56.enum(sizes2).optional().catch(void 0)
6114
+ }),
6115
+ type: z56.literal("ShopifyTextInline")
6116
+ });
6117
+ var marks = (raw) => {
6118
+ const found = raw.map((mark) => Inline.safeParse(mark)).find(({ success }) => success)?.data;
6119
+ if (!found) return [];
6120
+ const { color = "base", emphasis, size = "base" } = found.attrs;
6121
+ return [
6122
+ ...emphasis.includes("bold") ? [{ type: "bold" }] : [],
6123
+ ...emphasis.includes("strikethrough") ? [{ type: "strike" }] : [],
6124
+ { attrs: { color, fontSize: size }, type: "textStyle" }
6125
+ ];
6126
+ };
6127
+ var convertDescriptionRte = (rte, spacing) => TiptapDocument.parse({
6128
+ attrs: { blockSpacing: spacings2[spacing ?? "none"] },
6129
+ content: rte.content.flatMap((node) => {
6130
+ const block = Block.safeParse(node);
6131
+ if (!block.success) return [];
6132
+ const { alignment } = block.data.attrs;
6133
+ return [
6134
+ {
6135
+ attrs: { textAlign: alignment ? alignments[alignment] : "start" },
6136
+ content: block.data.content.flatMap((inline) => {
6137
+ const run = Run.safeParse(inline);
6138
+ return run.success ? [{ marks: marks(run.data.marks), text: run.data.text }] : [];
6139
+ }),
6140
+ type: "paragraph"
6141
+ }
6142
+ ];
6143
+ }),
6144
+ type: "doc"
6145
+ });
6146
+
6066
6147
  // src/server/postPurchaseProductDisplay.ts
6067
- var ResponseLanguage = z55.object({ description: PostPurchaseProductDisplay.shape.responseDescription }).default({ description: "" });
6148
+ var ResponseLanguage = z57.object({ description: PostPurchaseProductDisplay.shape.responseDescription }).default({ description: "" });
6068
6149
  var projectPostPurchaseProductDisplay = (effective, metadata, product) => PostPurchaseProductDisplay.parse({
6150
+ descriptionDocument: effective.language.descriptionRte && convertDescriptionRte(effective.language.descriptionRte, effective.language.descriptionSpacing),
6069
6151
  discountedFrom: effective.discountedFrom,
6070
6152
  gallery: postPurchaseProductGallery(product, effective.subImages),
6071
6153
  language: effective.language,
@@ -6075,12 +6157,142 @@ var projectPostPurchaseProductDisplay = (effective, metadata, product) => PostPu
6075
6157
  shouldShowSavingText: effective.discount.shouldShowSavingText
6076
6158
  });
6077
6159
 
6160
+ // src/server/postPurchaseReviewData.ts
6161
+ import { z as z61 } from "zod";
6162
+
6163
+ // src/server/postPurchaseJudgeMeReviews.ts
6164
+ import { z as z58 } from "zod";
6165
+ var readJudgeMeReviews = (find) => {
6166
+ const field = find("judgeme", "badge");
6167
+ if (!field) return null;
6168
+ const html = z58.string().parse(field.value);
6169
+ const rating = html.match(/data-average-rating=['"](\d+(?:\.\d+)?)['"]/);
6170
+ const count = html.match(/data-number-of-reviews=['"](\d+)['"]/);
6171
+ if (!rating || !count) throw new Error("Unreadable Judge.me attributes");
6172
+ return {
6173
+ rating: PostPurchaseCommonReviewRating.parse({ value: rating[1] }).value,
6174
+ reviewCount: PostPurchaseReviewCount.parse(count[1])
6175
+ };
6176
+ };
6177
+
6178
+ // src/server/postPurchaseOkendoReviews.ts
6179
+ import { z as z59 } from "zod";
6180
+ var Summary = z59.object({
6181
+ reviewAverageValue: PostPurchaseCommonReviewRating.shape.value,
6182
+ reviewCount: z59.union([PostPurchaseProductReviews.shape.reviewCount, PostPurchaseReviewCount])
6183
+ });
6184
+ var readOkendoReviews = (find) => {
6185
+ const field = find("okendo", "summaryData");
6186
+ if (!field) return null;
6187
+ const summary = Summary.parse(JSON.parse(z59.string().parse(field.value)));
6188
+ return { rating: summary.reviewAverageValue, reviewCount: summary.reviewCount };
6189
+ };
6190
+
6191
+ // src/server/postPurchaseScalarReviews.ts
6192
+ import { z as z60 } from "zod";
6193
+ var readScalarReviews = (find, namespace, ratingKey, countKey) => {
6194
+ const rating = find(namespace, ratingKey);
6195
+ const count = find(namespace, countKey);
6196
+ if (!rating || !count) return null;
6197
+ return {
6198
+ rating: PostPurchaseCommonReviewRating.parse({ value: z60.string().parse(rating.value) }).value,
6199
+ reviewCount: PostPurchaseReviewCount.parse(count.value)
6200
+ };
6201
+ };
6202
+
6203
+ // src/server/postPurchaseReviewData.ts
6204
+ var readPostPurchaseReviewData = (provider, find) => {
6205
+ if (provider === "yotpo") return readScalarReviews(find, "yotpo", "reviews_average", "reviews_count");
6206
+ if (provider === "stamped") return readScalarReviews(find, "stamped", "reviews_average", "reviews_count");
6207
+ if (provider === "judgeme") return readJudgeMeReviews(find);
6208
+ if (provider === "okendo") return readOkendoReviews(find);
6209
+ if (provider === "opinew") return readScalarReviews(find, "opinew_metafields", "reviews_average", "reviews_count");
6210
+ if (provider === "reviewsio") return readScalarReviews(find, "reviewscouk", "rating", "total");
6211
+ if (provider === "loox") return readScalarReviews(find, "loox", "avg_rating", "num_reviews");
6212
+ if (provider === "junip") return readScalarReviews(find, "junip", "rating_average", "rating_count");
6213
+ const rating = find("reviews", "rating");
6214
+ const count = find("reviews", "rating_count");
6215
+ if (!rating || !count) return null;
6216
+ return {
6217
+ rating: PostPurchaseKlaviyoReviewRating.parse(JSON.parse(z61.string().parse(rating.value))).value,
6218
+ reviewCount: PostPurchaseReviewCount.parse(count.value)
6219
+ };
6220
+ };
6221
+
6222
+ // src/server/postPurchaseReviewFields.ts
6223
+ import { z as z62 } from "zod";
6224
+ var Field = z62.object({ key: z62.string(), namespace: z62.string(), value: z62.unknown().optional() });
6225
+ var reviewFields = (raw) => {
6226
+ const fields4 = z62.array(z62.unknown()).parse(raw).flatMap((field) => {
6227
+ const parsed = Field.safeParse(field);
6228
+ return parsed.success ? [parsed.data] : [];
6229
+ });
6230
+ return (namespace, key) => fields4.find((field) => field.namespace === namespace && field.key === key);
6231
+ };
6232
+
6233
+ // src/server/postPurchaseReviewProvider.ts
6234
+ import { z as z63 } from "zod";
6235
+ var IntegrationInput = z63.record(z63.string(), z63.unknown()).prefault({});
6236
+ var precedence = [
6237
+ "klaviyo",
6238
+ "judgeme",
6239
+ "junip",
6240
+ "loox",
6241
+ "okendo",
6242
+ "opinew",
6243
+ "reviewsio",
6244
+ "stamped",
6245
+ "yotpo"
6246
+ ];
6247
+ var ReviewsIoFlag = z63.preprocess((value) => {
6248
+ if (typeof value === "string") {
6249
+ const flag = value.toLowerCase();
6250
+ if (flag === "true" || flag === "yes") return true;
6251
+ if (flag === "false" || flag === "no") return false;
6252
+ }
6253
+ return value;
6254
+ }, PostPurchaseSettings.shape.integrations.shape.reviewsio);
6255
+ var selectPostPurchaseReviewProvider = (raw) => {
6256
+ const integrations = IntegrationInput.parse(raw);
6257
+ for (const provider of precedence) {
6258
+ const schema = provider === "reviewsio" ? ReviewsIoFlag : PostPurchaseSettings.shape.integrations.shape[provider];
6259
+ if (schema.parse(integrations[provider])) return provider;
6260
+ }
6261
+ return null;
6262
+ };
6263
+
6264
+ // src/server/postPurchaseReviews.ts
6265
+ var projectPostPurchaseReviews = (settings, metafields, report) => {
6266
+ try {
6267
+ const provider = selectPostPurchaseReviewProvider(settings.integrations);
6268
+ if (!provider || metafields == null) return null;
6269
+ const data = readPostPurchaseReviewData(provider, reviewFields(metafields));
6270
+ if (data === null || data.rating === 0) return null;
6271
+ const styles2 = PostPurchaseReviewStyles.parse(settings.styles);
6272
+ return PostPurchaseProductReviews.parse({
6273
+ color: styles2.starColor,
6274
+ ...data,
6275
+ reviewsPlural: settings.language.global.reviewsPlural,
6276
+ reviewsSingular: settings.language.global.reviewsSingular,
6277
+ size: styles2.starSize,
6278
+ strokeColor: styles2.starStrokeColor,
6279
+ strokeWidth: styles2.strokeWidth
6280
+ });
6281
+ } catch {
6282
+ report?.({ detail: "Unreadable post-purchase reviews", kind: "product" });
6283
+ return null;
6284
+ }
6285
+ };
6286
+
6078
6287
  // src/server/projectPostPurchaseProduct.ts
6079
- var projectPostPurchaseProduct = ({ data, effective, metadata, original }, selectedQuantity) => {
6288
+ var projectPostPurchaseProduct = ({ data, effective, metadata, original }, report, selectedQuantity) => {
6080
6289
  const product = data[0];
6081
6290
  const variant2 = product.variants[0];
6082
6291
  return {
6083
- display: projectPostPurchaseProductDisplay(effective, metadata, product),
6292
+ display: {
6293
+ ...projectPostPurchaseProductDisplay(effective, metadata, product),
6294
+ reviews: projectPostPurchaseReviews(effective, product.metafields, report)
6295
+ },
6084
6296
  labels: effective.language.global,
6085
6297
  product: { ...product, variant: variant2 },
6086
6298
  selection: {
@@ -6097,7 +6309,7 @@ var prepareNormalizedSubscription = (normalized, report, plan, quantity2, allowC
6097
6309
  const reason = subscriptionUnavailable(normalized, plan, allowCollection, quantity2);
6098
6310
  if (reason) return { reason, status: "unsupported" };
6099
6311
  const { effective } = normalized;
6100
- const projected = projectPostPurchaseProduct(normalized, quantity2);
6312
+ const projected = projectPostPurchaseProduct(normalized, report, quantity2);
6101
6313
  const { discount, shipping } = PostPurchaseSubscriptionSettings.parse(effective.subscription);
6102
6314
  const shippingPrice = shipping.type === "free" ? 0 : shipping.amount;
6103
6315
  return PreparedPostPurchaseSubscription.parse({
@@ -6134,72 +6346,262 @@ var preparePostPurchaseSubscription = (settings, response, report) => {
6134
6346
  );
6135
6347
  };
6136
6348
 
6137
- // src/schema/postPurchaseOfferEligibility.ts
6138
- import { z as z57 } from "zod";
6349
+ // src/server/postPurchaseProductEligibility.ts
6350
+ var oneTimeUnavailable = (normalized, allowCollection, quantity2) => {
6351
+ const { data, effective, original } = normalized;
6352
+ if (data.length !== 1 || data[0].variants.length !== 1) return "Only one fixed product and variant are supported";
6353
+ if (effective.productType === "subscription" || [original, effective].some(
6354
+ (config) => !allowCollection && config.productLimit !== 1 || config.upgradeToSubscription.allow || !quantity2 && config.quantityInputs.enabled && (config.quantityInputs.minValue !== config.quantityInputs.maxValue || config.quantityInputs.defaultQuantity !== config.quantityInputs.minValue)
6355
+ ))
6356
+ return "Only fixed one-time configuration is supported";
6357
+ const product = data[0];
6358
+ const variant2 = product.variants[0];
6359
+ if (product.productGroupVariants.length || product.sellingPlanGroups?.some((group) => group.requiresSellingPlan) || !postPurchaseVariantAvailable(variant2))
6360
+ return "An available one-time variant without product groups is required";
6361
+ if (variant2.productId !== product.id) throw new Error("Product variant identity mismatch");
6362
+ };
6139
6363
 
6140
- // src/schema/postPurchaseProductCollectionView.ts
6141
- import { z as z56 } from "zod";
6142
- var PostPurchaseExcludedProductIds = z56.array(PostPurchaseProductId).default([]);
6364
+ // src/server/preparePostPurchaseProduct.ts
6365
+ var prepareNormalizedProduct = (normalized, report, quantity2, allowCollection = false) => {
6366
+ const reason = oneTimeUnavailable(normalized, allowCollection, quantity2);
6367
+ if (reason) return { reason, status: "unsupported" };
6368
+ const { effective } = normalized;
6369
+ return PreparedPostPurchaseProduct.parse({
6370
+ ...projectPostPurchaseProduct(normalized, report, quantity2),
6371
+ status: "prepared",
6372
+ terms: {
6373
+ discount: { ...effective.discount, title: effective.language.global.save },
6374
+ shipping: effective.shipping
6375
+ }
6376
+ });
6377
+ };
6378
+ var preparePostPurchaseProduct = (settings, response, report) => prepareNormalizedProduct(normalizePostPurchaseProduct(settings, response), report);
6143
6379
 
6144
- // src/schema/postPurchaseOfferEligibility.ts
6145
- var selection = PreparedPostPurchaseProduct.shape.selection;
6146
- var PostPurchaseOfferSkipReason = z57.enum(["empty", "no-eligible-subscription"]);
6147
- var PostPurchaseOfferEligibilityContext = z57.object({
6148
- excludedProductIds: PostPurchaseExcludedProductIds,
6149
- originalLineItems: z57.array(selection.pick({ productId: true, sellingPlanId: true, variantId: true }))
6150
- });
6151
- var PostPurchaseOfferEligibility = z57.discriminatedUnion("status", [
6152
- z57.object({
6153
- members: z57.array(
6154
- z57.object({ productId: selection.shape.productId, productIndex: z57.number().int().nonnegative() })
6155
- ),
6156
- status: z57.literal("retain")
6157
- }),
6158
- z57.object({ reason: PostPurchaseOfferSkipReason, status: z57.literal("skip") }),
6159
- z57.object({ reason: z57.literal("eligible-upgrade").optional(), status: z57.literal("unavailable") })
6380
+ // src/schema/postPurchaseProductView.ts
6381
+ import { z as z67 } from "zod";
6382
+
6383
+ // src/schema/postPurchaseChoice.ts
6384
+ import { z as z64 } from "zod";
6385
+ var PostPurchaseChoice = z64.discriminatedUnion("mode", [
6386
+ z64.object({ mode: z64.literal("one-time") }).strict(),
6387
+ z64.object({ mode: z64.literal("subscription"), sellingPlanId: PostPurchasePlanOption.shape.id }).strict()
6160
6388
  ]);
6389
+ var PostPurchaseOptions = z64.object({
6390
+ defaultChoice: PostPurchaseChoice,
6391
+ modes: z64.array(z64.enum(["one-time", "subscription"])).min(1).max(2),
6392
+ selector: PostPurchaseSettings.shape.productTypeSelector
6393
+ });
6161
6394
 
6162
- // src/server/normalizePostPurchaseCollection.ts
6163
- import { z as z58 } from "zod";
6164
- var normalizePostPurchaseCollection = (settings, response, excludedProductIds) => {
6165
- const normalized = normalizePostPurchaseProduct(settings, response);
6166
- const limit = z58.number().int().positive();
6167
- limit.parse(normalized.original.productLimit);
6168
- const prefix = normalized.data.slice(0, limit.parse(normalized.effective.productLimit));
6169
- if (new Set(prefix.map(({ id }) => id)).size !== prefix.length)
6170
- throw new Error("Ambiguous post-purchase collection");
6171
- const excluded = new Set(PostPurchaseExcludedProductIds.parse(excludedProductIds));
6172
- const members = prefix.map((product, productIndex) => ({ product, productIndex })).filter(({ product }) => !excluded.has(product.id));
6173
- return { members, normalized };
6174
- };
6395
+ // src/schema/postPurchaseGroupCatalog.ts
6396
+ import { z as z66 } from "zod";
6175
6397
 
6176
6398
  // src/schema/postPurchaseVariantCatalog.ts
6177
- import { z as z59 } from "zod";
6178
- var PostPurchaseVariantSelector = z59.object({ variantId: PostPurchaseVariantId }).strict();
6399
+ import { z as z65 } from "zod";
6400
+ var PostPurchaseVariantSelector = z65.object({ variantId: PostPurchaseVariantId }).strict();
6179
6401
  var PostPurchaseVariantOption = OfferProduct.shape.options.element.extend({
6180
- id: z59.number().int().positive(),
6181
- position: z59.number().int().min(1).max(3)
6402
+ id: z65.number().int().positive(),
6403
+ position: z65.number().int().min(1).max(3)
6182
6404
  });
6183
6405
  var PostPurchaseVariantValues = OfferProduct.shape.variants.element.pick({
6184
6406
  option1: true,
6185
6407
  option2: true,
6186
6408
  option3: true
6187
6409
  });
6188
- var PostPurchaseVariantCatalog = z59.object({
6410
+ var PostPurchaseVariantCatalog = z65.object({
6189
6411
  displayMode: PostPurchaseSettings.shape.productOptions.shape.variantSelectorDisplayMode,
6190
- options: z59.array(PostPurchaseVariantOption),
6412
+ options: z65.array(PostPurchaseVariantOption),
6191
6413
  productId: PostPurchaseProductId,
6192
6414
  showSelectors: PostPurchaseSettings.shape.productOptions.shape.showVariantSelectors,
6193
- variants: z59.array(
6415
+ variants: z65.array(
6194
6416
  PostPurchaseVariantValues.partial().extend({
6195
- available: z59.boolean(),
6417
+ available: z65.boolean(),
6196
6418
  id: PostPurchaseVariantId,
6197
- imageId: z59.number().int().nonnegative().nullish(),
6419
+ imageId: z65.number().int().nonnegative().nullish(),
6198
6420
  title: OfferProduct.shape.variants.element.shape.title
6199
6421
  })
6200
6422
  )
6201
6423
  });
6202
6424
 
6425
+ // src/schema/postPurchaseGroupCatalog.ts
6426
+ var productId = PreparedPostPurchaseProduct.shape.selection.shape.productId;
6427
+ var source = PostPurchaseProductSource.shape.data.element;
6428
+ var PostPurchaseGroupDescription = source.pick({ description: true, id: true, image: true, images: true, title: true }).extend({
6429
+ description: source.shape.description.default(null),
6430
+ image: source.shape.image.default(null),
6431
+ options: PostPurchaseVariantCatalog.shape.options.default([])
6432
+ });
6433
+ var PostPurchaseGroupCatalog = z66.object({
6434
+ memberProductId: productId,
6435
+ options: z66.array(z66.object({ productId, title: z66.string(), variantCatalog: PostPurchaseVariantCatalog }))
6436
+ });
6437
+ var PostPurchaseGroupSelection = z66.object({
6438
+ memberProductId: productId,
6439
+ productId
6440
+ });
6441
+
6442
+ // src/schema/postPurchaseProductView.ts
6443
+ var PostPurchaseProductView = z67.union([
6444
+ z67.object({
6445
+ groupCatalog: PostPurchaseGroupCatalog.optional(),
6446
+ initialVariant: PostPurchaseVariantSelector.optional(),
6447
+ planCatalog: PostPurchasePlanCatalog.nullable().optional(),
6448
+ preparation: PreparedPostPurchaseProduct.extend({
6449
+ display: PreparedPostPurchaseProduct.shape.display.extend({ description: z67.string().nullable() }).refine(
6450
+ ({ description, descriptionDocument }) => description === null === (descriptionDocument !== void 0),
6451
+ "Exactly one of the plain and rich descriptions is shown"
6452
+ )
6453
+ }),
6454
+ purchaseOptions: PostPurchaseOptions.optional(),
6455
+ sections: CABRootSection,
6456
+ variantCatalog: PostPurchaseVariantCatalog.optional()
6457
+ }),
6458
+ z67.object({
6459
+ groupCatalog: PostPurchaseGroupCatalog.optional(),
6460
+ initialVariant: PostPurchaseVariantSelector.optional(),
6461
+ planCatalog: PostPurchasePlanCatalog.nullable().optional(),
6462
+ preparation: PostPurchasePreparation.options[1],
6463
+ purchaseOptions: PostPurchaseOptions.optional(),
6464
+ sections: z67.null(),
6465
+ variantCatalog: PostPurchaseVariantCatalog.optional()
6466
+ })
6467
+ ]);
6468
+
6469
+ // src/server/postPurchaseOfferCopy.ts
6470
+ import { z as z68 } from "zod";
6471
+ var Copy = z68.object({
6472
+ superTitle: CalloutBannerBlock.shape.settings.shape.superTitle.unwrap().optional().catch(void 0),
6473
+ title: CalloutBannerBlock.shape.settings.shape.title.unwrap().optional().catch(void 0)
6474
+ });
6475
+ var Callout = z68.object({ settings: z68.record(z68.string(), z68.unknown()), type: z68.literal("callout_banner") });
6476
+ var postPurchaseOfferCopy = (blocks, metadata) => {
6477
+ const copy = Copy.safeParse(metadata.widget.language);
6478
+ if (!blocks || !copy.success) return blocks;
6479
+ const first = blocks.findIndex((block) => Callout.pick({ type: true }).safeParse(block).success);
6480
+ return blocks.map((block, index) => {
6481
+ if (index !== first) return block;
6482
+ const callout = Callout.passthrough().safeParse(block);
6483
+ if (!callout.success) return block;
6484
+ return {
6485
+ ...callout.data,
6486
+ settings: {
6487
+ ...callout.data.settings,
6488
+ ...copy.data.title && { title: copy.data.title },
6489
+ ...copy.data.superTitle && { superTitle: copy.data.superTitle }
6490
+ }
6491
+ };
6492
+ });
6493
+ };
6494
+
6495
+ // src/server/selectPostPurchaseChoice.ts
6496
+ var selectPostPurchaseChoice = (normalized, projected, requested, allowCollection, quantity2) => {
6497
+ const { data, effective } = normalized;
6498
+ const modes = [];
6499
+ const catalog = projected && projected.productId === data[0]?.id && projected.variantId === data[0].variants[0]?.id ? projected : null;
6500
+ const firstPlan = catalog?.plans[0];
6501
+ const oneTimeReason = oneTimeUnavailable(normalized, allowCollection, quantity2);
6502
+ const subscriptionReason = subscriptionUnavailable(normalized, firstPlan, allowCollection, quantity2);
6503
+ if (!oneTimeReason) modes.push("one-time");
6504
+ if (!subscriptionReason) modes.push("subscription");
6505
+ if (oneTimeReason && subscriptionReason)
6506
+ return {
6507
+ choice: void 0,
6508
+ options: void 0,
6509
+ plan: void 0,
6510
+ reason: effective.productType === "one-time" ? oneTimeReason : subscriptionReason
6511
+ };
6512
+ const defaultChoice = firstPlan && modes.includes("subscription") && (modes[0] === "subscription" || effective.subscriptionIsDefault) ? { mode: "subscription", sellingPlanId: firstPlan.id } : { mode: "one-time" };
6513
+ const options2 = PostPurchaseOptions.parse({ defaultChoice, modes, selector: effective.productTypeSelector });
6514
+ const choice = requested ?? defaultChoice;
6515
+ const plan = choice.mode === "subscription" ? catalog?.plans.find(({ id }) => id === choice.sellingPlanId) : void 0;
6516
+ const bound = modes.includes(choice.mode) && (choice.mode === "one-time" || plan) ? choice : void 0;
6517
+ return {
6518
+ choice: bound,
6519
+ options: options2,
6520
+ plan: bound ? plan : void 0,
6521
+ reason: bound ? void 0 : "Requested purchase choice is unavailable"
6522
+ };
6523
+ };
6524
+
6525
+ // src/server/preparePostPurchaseView.ts
6526
+ var resolveDescription = ({ descriptionDocument, ...display }, productDescription) => {
6527
+ const plain = display.language.descriptionEnabled && productDescription || display.responseDescription || (descriptionDocument ? null : display.language.description);
6528
+ return plain === null ? { ...display, description: null, descriptionDocument } : { ...display, description: plain };
6529
+ };
6530
+ var prepareNormalizedPostPurchaseView = (widgetId, normalized, report, choice, quantity2, allowCollection = false) => {
6531
+ const planCatalog = projectPostPurchasePlanCatalog(normalized, report);
6532
+ const selected = selectPostPurchaseChoice(normalized, planCatalog, choice, allowCollection, quantity2);
6533
+ const purchaseOptions = selected.options;
6534
+ 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);
6535
+ const unsupported = (reason) => ({
6536
+ planCatalog,
6537
+ preparation: { reason, status: "unsupported" },
6538
+ purchaseOptions,
6539
+ sections: null
6540
+ });
6541
+ if (preparation.status === "unsupported") return { planCatalog, preparation, purchaseOptions, sections: null };
6542
+ if (!normalized.effective.blocks?.length) return unsupported("One fixed product information block is required");
6543
+ const sections = convertMessagePreview(
6544
+ widgetId,
6545
+ {
6546
+ blocks: postPurchaseOfferCopy(normalized.effective.blocks, normalized.metadata),
6547
+ type: "shopify_post_purchase_extension"
6548
+ },
6549
+ report
6550
+ );
6551
+ if (sections.sections.filter((section) => section.sectionType === "offers").length !== 1)
6552
+ return unsupported("One fixed product information block is required");
6553
+ return PostPurchaseProductView.parse({
6554
+ planCatalog,
6555
+ preparation: {
6556
+ ...preparation,
6557
+ display: resolveDescription(preparation.display, preparation.product.description)
6558
+ },
6559
+ purchaseOptions,
6560
+ sections
6561
+ });
6562
+ };
6563
+ var preparePostPurchaseView = (widgetId, settings, response, report, choice) => prepareNormalizedPostPurchaseView(widgetId, normalizePostPurchaseProduct(settings, response), report, choice);
6564
+
6565
+ // src/server/preparePostPurchaseAdmissionView.ts
6566
+ var preparePostPurchaseAdmissionView = (widgetId, settings, response, report, choice) => {
6567
+ const normalized = normalizePostPurchaseProduct(settings, response);
6568
+ const view = prepareNormalizedPostPurchaseView(widgetId, normalized, report, choice);
6569
+ const { removePartialOrder } = PostPurchaseSettings.shape.advance.parse(normalized.effective.advance);
6570
+ return { removePartialOrder, view };
6571
+ };
6572
+
6573
+ // src/schema/postPurchaseProductCollectionView.ts
6574
+ import { z as z69 } from "zod";
6575
+ var PostPurchaseProductCollectionView = z69.object({
6576
+ members: z69.array(
6577
+ z69.object({
6578
+ productId: PostPurchaseProductId,
6579
+ productIndex: z69.number().int().nonnegative(),
6580
+ view: PostPurchaseProductView
6581
+ })
6582
+ )
6583
+ });
6584
+ var PostPurchaseCollectionChoice = z69.object({
6585
+ choice: PostPurchaseChoice.optional(),
6586
+ productId: PostPurchaseProductId,
6587
+ variantId: PostPurchaseVariantSelector.shape.variantId.optional()
6588
+ }).strict();
6589
+ var PostPurchaseExcludedProductIds = z69.array(PostPurchaseProductId).default([]);
6590
+
6591
+ // src/server/normalizePostPurchaseCollection.ts
6592
+ import { z as z70 } from "zod";
6593
+ var normalizePostPurchaseCollection = (settings, response, excludedProductIds) => {
6594
+ const normalized = normalizePostPurchaseProduct(settings, response);
6595
+ const limit = z70.number().int().positive();
6596
+ limit.parse(normalized.original.productLimit);
6597
+ const prefix = normalized.data.slice(0, limit.parse(normalized.effective.productLimit));
6598
+ if (new Set(prefix.map(({ id }) => id)).size !== prefix.length)
6599
+ throw new Error("Ambiguous post-purchase collection");
6600
+ const excluded = new Set(PostPurchaseExcludedProductIds.parse(excludedProductIds));
6601
+ const members = prefix.map((product, productIndex) => ({ product, productIndex })).filter(({ product }) => !excluded.has(product.id));
6602
+ return { members, normalized };
6603
+ };
6604
+
6203
6605
  // src/server/postPurchaseVariantCatalog.ts
6204
6606
  var projectPostPurchaseVariantCatalog = (product, settings) => {
6205
6607
  const options2 = PostPurchaseVariantCatalog.shape.options.parse(product.options === void 0 ? [] : product.options).sort((a, b) => a.position - b.position);
@@ -6233,22 +6635,216 @@ var projectPostPurchaseVariantCatalog = (product, settings) => {
6233
6635
  });
6234
6636
  };
6235
6637
 
6236
- // src/schema/postPurchaseGroupCatalog.ts
6237
- import { z as z60 } from "zod";
6238
- var productId = PreparedPostPurchaseProduct.shape.selection.shape.productId;
6239
- var source = PostPurchaseProductSource.shape.data.element;
6240
- var PostPurchaseGroupDescription = source.pick({ description: true, id: true, image: true, images: true, title: true }).extend({
6241
- description: source.shape.description.default(null),
6242
- image: source.shape.image.default(null),
6243
- options: PostPurchaseVariantCatalog.shape.options.default([])
6638
+ // src/schema/postPurchaseQuantity.ts
6639
+ import { z as z71 } from "zod";
6640
+ var quantity = PreparedPostPurchaseProduct.shape.selection.shape.quantity;
6641
+ var PostPurchaseQuantityChoice = PostPurchaseCollectionChoice.extend({ quantity: quantity.optional() });
6642
+ var PostPurchaseQuantityPolicy = PostPurchaseSettings.shape.quantityInputs.omit({ defaultQuantity: true }).extend({
6643
+ initialQuantity: quantity,
6644
+ maxValue: quantity,
6645
+ minValue: z71.literal(0).transform(() => 1).or(quantity)
6646
+ }).refine(({ maxValue, minValue }) => minValue <= maxValue, "Quantity bounds are reversed");
6647
+
6648
+ // src/server/readPostPurchaseQuantity.ts
6649
+ var PostPurchaseQuantityUnavailable = class extends Error {
6650
+ };
6651
+ var readPostPurchaseQuantity = ({
6652
+ data,
6653
+ effective,
6654
+ original
6655
+ }, selection3) => {
6656
+ const positive = PreparedPostPurchaseProduct.shape.selection.shape.quantity;
6657
+ for (const config of [original, effective]) {
6658
+ if (!config.quantityInputs.enabled) continue;
6659
+ const initialQuantity2 = positive.parse(config.quantityInputs.defaultQuantity);
6660
+ const policy2 = PostPurchaseQuantityPolicy.parse({ ...config.quantityInputs, initialQuantity: initialQuantity2 });
6661
+ if (initialQuantity2 < policy2.minValue || initialQuantity2 > policy2.maxValue)
6662
+ throw new Error("Configured quantity default is outside its bounds");
6663
+ }
6664
+ const initialQuantity = data[0]?.metadata?.productQuantity ?? (original.quantityInputs.enabled ? original.quantityInputs.defaultQuantity : 1);
6665
+ const policy = PostPurchaseQuantityPolicy.parse(
6666
+ effective.quantityInputs.enabled ? { ...effective.quantityInputs, initialQuantity } : { enabled: false, initialQuantity, maxValue: initialQuantity, minValue: initialQuantity }
6667
+ );
6668
+ const requested = "quantity" in selection3 ? selection3.quantity : selection3.expectedQuantity === initialQuantity ? void 0 : selection3.expectedQuantity;
6669
+ const quantity2 = positive.parse(requested ?? initialQuantity);
6670
+ if (requested !== void 0 && (policy.enabled ? quantity2 < policy.minValue || quantity2 > policy.maxValue : quantity2 !== initialQuantity))
6671
+ throw new PostPurchaseQuantityUnavailable("Requested quantity is unavailable");
6672
+ return { policy, quantity: quantity2 };
6673
+ };
6674
+
6675
+ // src/schema/postPurchaseVariantDefault.ts
6676
+ import { z as z72 } from "zod";
6677
+ var values = PostPurchaseVariantValues.partial().extend({
6678
+ option1: PostPurchaseVariantValues.shape.option1.nullish()
6244
6679
  });
6245
- var PostPurchaseGroupCatalog = z60.object({
6246
- memberProductId: productId,
6247
- options: z60.array(z60.object({ productId, title: z60.string(), variantCatalog: PostPurchaseVariantCatalog }))
6680
+ var variant = values.extend({
6681
+ id: PostPurchaseVariantId,
6682
+ inventoryManagement: z72.string().nullable(),
6683
+ inventoryPolicy: z72.string(),
6684
+ inventoryQuantity: z72.number()
6248
6685
  });
6249
- var PostPurchaseGroupSelection = z60.object({
6250
- memberProductId: productId,
6251
- productId
6686
+ var options = z72.array(PostPurchaseVariantOption.pick({ name: true, values: true }));
6687
+ var PostPurchaseVariantDefaultProduct = z72.object({
6688
+ id: PostPurchaseProductId,
6689
+ options,
6690
+ selectedVariant: variant.optional(),
6691
+ variants: z72.array(variant)
6692
+ });
6693
+ var PostPurchaseVariantDefaultSettings = PostPurchaseSettings.shape.productOptions.pick({
6694
+ hideOutOfStockVariants: true,
6695
+ matchVariant: true
6696
+ });
6697
+ var PostPurchaseOrderAttributes = z72.record(z72.string(), z72.array(z72.string())).default({});
6698
+ var PostPurchaseOriginalVariants = z72.array(
6699
+ z72.object({ productId: PostPurchaseProductId, variantId: PostPurchaseVariantId })
6700
+ );
6701
+ var PostPurchaseAttributeProducts = z72.array(
6702
+ z72.object({ id: PostPurchaseProductId, options, variants: z72.array(values.extend({ id: PostPurchaseVariantId })) })
6703
+ );
6704
+
6705
+ // src/schema/postPurchaseVariantDefaultContext.ts
6706
+ import { z as z73 } from "zod";
6707
+ var PostPurchaseVariantDefaultContext = z73.object({
6708
+ enrichedLineItems: z73.unknown().optional(),
6709
+ originalVariants: PostPurchaseOriginalVariants
6710
+ });
6711
+
6712
+ // src/server/createPostPurchaseOrderAttributes.ts
6713
+ var createPostPurchaseOrderAttributes = (original, enriched) => {
6714
+ const products = PostPurchaseAttributeProducts.parse(enriched);
6715
+ const attributes = {};
6716
+ for (const item of PostPurchaseOriginalVariants.parse(original)) {
6717
+ const product = products.find(({ id }) => id === item.productId);
6718
+ const variant2 = product?.variants.find(({ id }) => id === item.variantId);
6719
+ if (!variant2 || !product) continue;
6720
+ ["option1", "option2", "option3"].forEach((key, index) => {
6721
+ const value = variant2[key];
6722
+ const option = product.options[index];
6723
+ if (!value || !option) return;
6724
+ const values2 = attributes[option.name] ?? [];
6725
+ if (!values2.includes(value)) attributes[option.name] = [...values2, value];
6726
+ });
6727
+ }
6728
+ return attributes;
6729
+ };
6730
+
6731
+ // src/server/matchPostPurchaseVariantDefault.ts
6732
+ var matchPostPurchaseVariantDefault = (product, attributes, filterOutOfStock) => {
6733
+ const keys = ["option1", "option2", "option3"];
6734
+ const values2 = keys.map((_, index) => {
6735
+ const option = product.options[index];
6736
+ return option ? option.values.filter((value) => attributes[option.name]?.includes(value)) : [];
6737
+ });
6738
+ if (!values2.some((entries) => entries.length)) return;
6739
+ let bestRank = 1;
6740
+ let best;
6741
+ for (const variant2 of product.variants) {
6742
+ if (filterOutOfStock && variant2.inventoryPolicy !== "continue" && variant2.inventoryQuantity <= 0) continue;
6743
+ const rank = keys.reduce((total, key, index) => {
6744
+ const value = variant2[key];
6745
+ return total + Number(!value && !values2[index].length || !!value && values2[index].includes(value));
6746
+ }, 0);
6747
+ if (rank > bestRank) {
6748
+ best = variant2;
6749
+ bestRank = rank;
6750
+ }
6751
+ }
6752
+ return best;
6753
+ };
6754
+
6755
+ // src/server/resolvePostPurchaseVariantDefault.ts
6756
+ var resolvePostPurchaseVariantDefault = (source2, settings, originalAttributes) => {
6757
+ const product = PostPurchaseVariantDefaultProduct.parse(source2);
6758
+ const policy = PostPurchaseVariantDefaultSettings.parse(settings);
6759
+ const attributes = PostPurchaseOrderAttributes.parse(originalAttributes);
6760
+ let selected = source2.selectedVariant && source2.selectedVariant === source2.variants[0] ? product.variants[0] : product.selectedVariant;
6761
+ if (!selected && policy.matchVariant)
6762
+ selected = matchPostPurchaseVariantDefault(product, attributes, policy.hideOutOfStockVariants);
6763
+ selected ?? (selected = product.variants[0]);
6764
+ if (!selected || selected === product.variants[0])
6765
+ selected = product.variants.find(postPurchaseVariantAvailable) ?? selected;
6766
+ return selected?.id ?? null;
6767
+ };
6768
+
6769
+ // src/server/resolvePostPurchaseMemberDefault.ts
6770
+ var resolvePostPurchaseMemberDefault = (product, original, context) => {
6771
+ const originals = PostPurchaseVariantDefaultContext.parse(context);
6772
+ if (product.variants.length < 2 && product.selectedVariant === void 0) return product.variants[0]?.id ?? null;
6773
+ const source2 = PostPurchaseVariantDefaultProduct.parse(product);
6774
+ const settings = PostPurchaseVariantDefaultSettings.parse(original.productOptions);
6775
+ const attributes = settings.matchVariant && !source2.selectedVariant && source2.options.some(({ values: values2 }) => values2.length > 0) && originals.originalVariants.length > 0 && originals.enrichedLineItems != null ? createPostPurchaseOrderAttributes(
6776
+ originals.originalVariants,
6777
+ PostPurchaseAttributeProducts.parse(deepCamelCase(originals.enrichedLineItems))
6778
+ ) : void 0;
6779
+ return resolvePostPurchaseVariantDefault(source2, settings, attributes);
6780
+ };
6781
+
6782
+ // src/server/preparePostPurchaseMemberView.ts
6783
+ var prepareMember = (widgetId, settings, response, requested, report, excludedProductIds, requestedQuantity, defaults) => {
6784
+ const selected = PostPurchaseCollectionChoice.parse(requested);
6785
+ const { members, normalized } = normalizePostPurchaseCollection(settings, response, excludedProductIds);
6786
+ const found = members.find(({ product: product2 }) => product2.id === selected.productId);
6787
+ if (!found) return null;
6788
+ const variantId = selected.variantId ?? (defaults && resolvePostPurchaseMemberDefault(found.product, normalized.original, defaults));
6789
+ const product = variantId === void 0 ? found.product : {
6790
+ ...found.product,
6791
+ variants: found.product.variants.filter(({ id }) => id === variantId)
6792
+ };
6793
+ const selectedInput = { ...normalized, data: [product] };
6794
+ const quantity2 = requestedQuantity ? readPostPurchaseQuantity(selectedInput, requestedQuantity) : void 0;
6795
+ const view = prepareNormalizedPostPurchaseView(widgetId, selectedInput, report, selected.choice, quantity2, true);
6796
+ if (selected.variantId !== void 0 || found.product.variants.length > 1)
6797
+ view.variantCatalog = projectPostPurchaseVariantCatalog(found.product, normalized.effective);
6798
+ if (defaults && selected.variantId === void 0 && variantId && view.variantCatalog?.variants.some(({ id }) => id === variantId))
6799
+ view.initialVariant = { variantId };
6800
+ return { member: { productId: found.product.id, productIndex: found.productIndex, view }, normalized, quantity: quantity2 };
6801
+ };
6802
+ var preparePostPurchaseMemberView = (widgetId, settings, response, requested, report, excludedProductIds) => prepareMember(widgetId, settings, response, requested, report, excludedProductIds)?.member ?? null;
6803
+ var preparePostPurchaseMemberAdmissionView = (widgetId, settings, response, requested, report, excludedProductIds) => {
6804
+ const prepared = prepareMember(widgetId, settings, response, requested, report, excludedProductIds);
6805
+ if (!prepared) return null;
6806
+ const { removePartialOrder } = PostPurchaseSettings.shape.advance.parse(prepared.normalized.effective.advance);
6807
+ return { ...prepared.member, removePartialOrder };
6808
+ };
6809
+
6810
+ // src/server/preparePostPurchaseQuantityView.ts
6811
+ var preparePostPurchaseQuantityView = (widgetId, settings, response, requested, report, excludedProductIds, defaults) => {
6812
+ const { quantity: quantity2, ...selection3 } = PostPurchaseQuantityChoice.parse(requested);
6813
+ const prepared = prepareMember(
6814
+ widgetId,
6815
+ settings,
6816
+ response,
6817
+ selection3,
6818
+ report,
6819
+ excludedProductIds,
6820
+ { quantity: quantity2 },
6821
+ defaults
6822
+ );
6823
+ return prepared ? { ...prepared.member, quantityPolicy: prepared.quantity.policy } : null;
6824
+ };
6825
+
6826
+ // src/server/preparePostPurchaseQuantityAdmissionView.ts
6827
+ var selection = PostPurchaseQuantityChoice.required({ quantity: true });
6828
+ var preparePostPurchaseQuantityAdmissionView = (widgetId, settings, response, expected, report, excludedProductIds, defaults) => {
6829
+ const { quantity: expectedQuantity, ...requested } = selection.parse(expected);
6830
+ const prepared = prepareMember(
6831
+ widgetId,
6832
+ settings,
6833
+ response,
6834
+ requested,
6835
+ report,
6836
+ excludedProductIds,
6837
+ { expectedQuantity },
6838
+ defaults
6839
+ );
6840
+ if (!prepared) return null;
6841
+ const { removePartialOrder } = PostPurchaseSettings.shape.advance.parse(prepared.normalized.effective.advance);
6842
+ return { ...prepared.member, quantityPolicy: prepared.quantity.policy, removePartialOrder };
6843
+ };
6844
+
6845
+ // src/schema/postPurchaseGroup.ts
6846
+ var PostPurchaseGroupChoice = PostPurchaseQuantityChoice.extend({
6847
+ memberProductId: PreparedPostPurchaseProduct.shape.selection.shape.productId
6252
6848
  });
6253
6849
 
6254
6850
  // src/server/readPostPurchaseGroup.ts
@@ -6281,6 +6877,195 @@ var readPostPurchaseGroup = (product, settings, excludedProductIds) => {
6281
6877
  };
6282
6878
  };
6283
6879
 
6880
+ // src/server/readPostPurchaseGroupSelection.ts
6881
+ var readPostPurchaseGroupSelection = (settings, response, requested, excludedProductIds) => {
6882
+ const selection3 = PostPurchaseGroupSelection.parse(requested);
6883
+ const { members, normalized } = normalizePostPurchaseCollection(settings, response);
6884
+ const member = members.find(({ product }) => product.id === selection3.memberProductId);
6885
+ if (!member || !member.product.productGroupVariants.length) return null;
6886
+ const group = readPostPurchaseGroup(member.product, normalized.effective, excludedProductIds);
6887
+ const entry = group.entries.find(({ product }) => product.id === selection3.productId);
6888
+ if (!entry) return null;
6889
+ return {
6890
+ groupCatalog: group.catalog,
6891
+ memberProductId: member.product.id,
6892
+ productIndex: member.productIndex,
6893
+ reportingProduct: { id: member.product.id, title: member.product.title },
6894
+ response: { data: [entry.product], metadata: normalized.metadata },
6895
+ variantCatalog: entry.variantCatalog
6896
+ };
6897
+ };
6898
+
6899
+ // src/server/preparePostPurchaseGroupView.ts
6900
+ var preparePostPurchaseGroupView = (widgetId, settings, response, requested, report, excludedProductIds) => {
6901
+ const { memberProductId, ...selection3 } = PostPurchaseGroupChoice.parse(requested);
6902
+ const group = readPostPurchaseGroupSelection(settings, response, requested, excludedProductIds);
6903
+ if (!group) return null;
6904
+ const variantId = selection3.variantId ?? group.variantCatalog.variants.find(({ available }) => available)?.id;
6905
+ if (variantId === void 0) return null;
6906
+ const prepared = preparePostPurchaseQuantityView(
6907
+ widgetId,
6908
+ settings,
6909
+ group.response,
6910
+ { ...selection3, variantId },
6911
+ report
6912
+ );
6913
+ return prepared && {
6914
+ ...prepared,
6915
+ groupCatalog: group.groupCatalog,
6916
+ memberProductId,
6917
+ productIndex: group.productIndex,
6918
+ reportingProduct: group.reportingProduct
6919
+ };
6920
+ };
6921
+
6922
+ // src/server/preparePostPurchaseGroupAdmissionView.ts
6923
+ var preparePostPurchaseGroupAdmissionView = (widgetId, settings, response, requested, report, excludedProductIds) => {
6924
+ const { memberProductId, ...selection3 } = PostPurchaseGroupChoice.required({ quantity: true }).parse(requested);
6925
+ const group = readPostPurchaseGroupSelection(settings, response, requested, excludedProductIds);
6926
+ if (!group) return null;
6927
+ const variantId = selection3.variantId ?? group.variantCatalog.variants.find(({ available }) => available)?.id;
6928
+ if (variantId === void 0) return null;
6929
+ const prepared = preparePostPurchaseQuantityAdmissionView(
6930
+ widgetId,
6931
+ settings,
6932
+ group.response,
6933
+ { ...selection3, variantId },
6934
+ report
6935
+ );
6936
+ return prepared && {
6937
+ ...prepared,
6938
+ groupCatalog: group.groupCatalog,
6939
+ memberProductId,
6940
+ productIndex: group.productIndex,
6941
+ reportingProduct: group.reportingProduct
6942
+ };
6943
+ };
6944
+
6945
+ // src/server/preparePostPurchaseGroupDefault.ts
6946
+ var preparePostPurchaseGroupDefault = (widgetId, settings, response, memberProductId, context, report, excludedProductIds) => {
6947
+ const { members, normalized } = normalizePostPurchaseCollection(settings, response);
6948
+ const member = members.find(({ product }) => product.id === memberProductId);
6949
+ if (!member || !member.product.productGroupVariants.length) return null;
6950
+ const group = readPostPurchaseGroup(member.product, normalized.effective, excludedProductIds);
6951
+ const ids = new Set(group.entries.map(({ product }) => product.id));
6952
+ const variants = member.product.variants.filter(({ productId: productId2 }) => ids.has(productId2));
6953
+ const selected = PostPurchaseVariantDefaultProduct.shape.selectedVariant.parse(member.product.selectedVariant);
6954
+ const selectedOwner = selected && member.product.variants.find(({ id }) => id === selected.id);
6955
+ const variantId = resolvePostPurchaseMemberDefault(
6956
+ {
6957
+ ...member.product,
6958
+ selectedVariant: selectedOwner && !ids.has(selectedOwner.productId) ? void 0 : member.product.selectedVariant,
6959
+ variants
6960
+ },
6961
+ normalized.original,
6962
+ context
6963
+ );
6964
+ const entry = group.entries.find(({ product }) => product.variants.some(({ id }) => id === variantId));
6965
+ if (!entry || variantId === null) return null;
6966
+ const prepared = preparePostPurchaseGroupView(
6967
+ widgetId,
6968
+ settings,
6969
+ response,
6970
+ { memberProductId, productId: entry.product.id, variantId },
6971
+ report,
6972
+ excludedProductIds
6973
+ );
6974
+ return prepared && { ...prepared, view: { ...prepared.view, initialVariant: { variantId } } };
6975
+ };
6976
+
6977
+ // src/server/preparePostPurchaseCollectionGroup.ts
6978
+ var preparePostPurchaseCollectionGroup = (widgetId, settings, response, member, normalized, excluded, defaults, report) => {
6979
+ const group = readPostPurchaseGroup(member.product, normalized.effective, excluded);
6980
+ if (!group.entries.length) return null;
6981
+ const prepared = preparePostPurchaseGroupDefault(
6982
+ widgetId,
6983
+ settings,
6984
+ response,
6985
+ member.product.id,
6986
+ defaults,
6987
+ report,
6988
+ excluded
6989
+ );
6990
+ return {
6991
+ productId: member.product.id,
6992
+ productIndex: member.productIndex,
6993
+ reportingProduct: { id: member.product.id, title: member.product.title },
6994
+ view: prepared ? { ...prepared.view, groupCatalog: prepared.groupCatalog } : {
6995
+ groupCatalog: group.catalog,
6996
+ preparation: { reason: "Post-purchase group default is unavailable", status: "unsupported" },
6997
+ sections: null
6998
+ }
6999
+ };
7000
+ };
7001
+
7002
+ // src/server/preparePostPurchaseCollectionView.ts
7003
+ var CollectionChoice = PostPurchaseCollectionChoice.omit({ variantId: true });
7004
+ var preparePostPurchaseCollectionView = (widgetId, settings, response, report, requested, excludedProductIds, defaults = { originalVariants: [] }) => {
7005
+ const { members, normalized } = normalizePostPurchaseCollection(settings, response);
7006
+ const excluded = PostPurchaseExcludedProductIds.parse(excludedProductIds);
7007
+ const selected = CollectionChoice.optional().parse(requested);
7008
+ const projected = members.map((member) => {
7009
+ if (member.product.productGroupVariants.length) {
7010
+ if (selected?.productId === member.product.id && selected.choice)
7011
+ throw new Error("Grouped choices require selected merchandise");
7012
+ const group = preparePostPurchaseCollectionGroup(
7013
+ widgetId,
7014
+ settings,
7015
+ response,
7016
+ member,
7017
+ normalized,
7018
+ excluded,
7019
+ defaults,
7020
+ report
7021
+ );
7022
+ return group;
7023
+ }
7024
+ if (excluded.includes(member.product.id)) return null;
7025
+ return {
7026
+ productId: member.product.id,
7027
+ productIndex: member.productIndex,
7028
+ reportingProduct: void 0,
7029
+ view: prepareNormalizedPostPurchaseView(
7030
+ widgetId,
7031
+ { ...normalized, data: [member.product] },
7032
+ report,
7033
+ member.product.id === selected?.productId ? selected.choice : void 0,
7034
+ void 0,
7035
+ true
7036
+ )
7037
+ };
7038
+ }).filter((member) => member !== null);
7039
+ if (selected && !projected.some(({ productId: productId2 }) => productId2 === selected.productId))
7040
+ throw new Error("Requested product is outside the prepared collection");
7041
+ const collection = PostPurchaseProductCollectionView.parse({ members: projected });
7042
+ return {
7043
+ members: collection.members.map((member, index) => ({
7044
+ ...member,
7045
+ ...projected[index].reportingProduct && { reportingProduct: projected[index].reportingProduct }
7046
+ }))
7047
+ };
7048
+ };
7049
+
7050
+ // src/schema/postPurchaseOfferEligibility.ts
7051
+ import { z as z74 } from "zod";
7052
+ var selection2 = PreparedPostPurchaseProduct.shape.selection;
7053
+ var PostPurchaseOfferSkipReason = z74.enum(["empty", "no-eligible-subscription"]);
7054
+ var PostPurchaseOfferEligibilityContext = z74.object({
7055
+ excludedProductIds: PostPurchaseExcludedProductIds,
7056
+ originalLineItems: z74.array(selection2.pick({ productId: true, sellingPlanId: true, variantId: true }))
7057
+ });
7058
+ var PostPurchaseOfferEligibility = z74.discriminatedUnion("status", [
7059
+ z74.object({
7060
+ members: z74.array(
7061
+ z74.object({ productId: selection2.shape.productId, productIndex: z74.number().int().nonnegative() })
7062
+ ),
7063
+ status: z74.literal("retain")
7064
+ }),
7065
+ z74.object({ reason: PostPurchaseOfferSkipReason, status: z74.literal("skip") }),
7066
+ z74.object({ reason: z74.literal("eligible-upgrade").optional(), status: z74.literal("unavailable") })
7067
+ ]);
7068
+
6284
7069
  // src/server/postPurchaseMemberEligibility.ts
6285
7070
  var PostPurchaseInventoryUnavailable = class extends Error {
6286
7071
  };
@@ -6356,74 +7141,6 @@ var classifyPostPurchaseOffer = (settings, response, context) => {
6356
7141
  }
6357
7142
  };
6358
7143
 
6359
- // src/schema/postPurchaseVariantDefault.ts
6360
- import { z as z61 } from "zod";
6361
- var values = PostPurchaseVariantValues.partial().extend({
6362
- option1: PostPurchaseVariantValues.shape.option1.nullish()
6363
- });
6364
- var variant = values.extend({
6365
- id: PostPurchaseVariantId,
6366
- inventoryManagement: z61.string().nullable(),
6367
- inventoryPolicy: z61.string(),
6368
- inventoryQuantity: z61.number()
6369
- });
6370
- var options = z61.array(PostPurchaseVariantOption.pick({ name: true, values: true }));
6371
- var PostPurchaseVariantDefaultProduct = z61.object({
6372
- id: PostPurchaseProductId,
6373
- options,
6374
- selectedVariant: variant.optional(),
6375
- variants: z61.array(variant)
6376
- });
6377
- var PostPurchaseVariantDefaultSettings = PostPurchaseSettings.shape.productOptions.pick({
6378
- hideOutOfStockVariants: true,
6379
- matchVariant: true
6380
- });
6381
- var PostPurchaseOrderAttributes = z61.record(z61.string(), z61.array(z61.string())).default({});
6382
- var PostPurchaseOriginalVariants = z61.array(
6383
- z61.object({ productId: PostPurchaseProductId, variantId: PostPurchaseVariantId })
6384
- );
6385
- var PostPurchaseAttributeProducts = z61.array(
6386
- z61.object({ id: PostPurchaseProductId, options, variants: z61.array(values.extend({ id: PostPurchaseVariantId })) })
6387
- );
6388
-
6389
- // src/server/createPostPurchaseOrderAttributes.ts
6390
- var createPostPurchaseOrderAttributes = (original, enriched) => {
6391
- const products = PostPurchaseAttributeProducts.parse(enriched);
6392
- const attributes = {};
6393
- for (const item of PostPurchaseOriginalVariants.parse(original)) {
6394
- const product = products.find(({ id }) => id === item.productId);
6395
- const variant2 = product?.variants.find(({ id }) => id === item.variantId);
6396
- if (!variant2 || !product) continue;
6397
- ["option1", "option2", "option3"].forEach((key, index) => {
6398
- const value = variant2[key];
6399
- const option = product.options[index];
6400
- if (!value || !option) return;
6401
- const values2 = attributes[option.name] ?? [];
6402
- if (!values2.includes(value)) attributes[option.name] = [...values2, value];
6403
- });
6404
- }
6405
- return attributes;
6406
- };
6407
-
6408
- // src/server/readPostPurchaseGroupSelection.ts
6409
- var readPostPurchaseGroupSelection = (settings, response, requested, excludedProductIds) => {
6410
- const selection2 = PostPurchaseGroupSelection.parse(requested);
6411
- const { members, normalized } = normalizePostPurchaseCollection(settings, response);
6412
- const member = members.find(({ product }) => product.id === selection2.memberProductId);
6413
- if (!member || !member.product.productGroupVariants.length) return null;
6414
- const group = readPostPurchaseGroup(member.product, normalized.effective, excludedProductIds);
6415
- const entry = group.entries.find(({ product }) => product.id === selection2.productId);
6416
- if (!entry) return null;
6417
- return {
6418
- groupCatalog: group.catalog,
6419
- memberProductId: member.product.id,
6420
- productIndex: member.productIndex,
6421
- reportingProduct: { id: member.product.id, title: member.product.title },
6422
- response: { data: [entry.product], metadata: normalized.metadata },
6423
- variantCatalog: entry.variantCatalog
6424
- };
6425
- };
6426
-
6427
7144
  // src/server/preparePostPurchaseGroupDeclineDisplay.ts
6428
7145
  var preparePostPurchaseGroupDeclineDisplay = (settings, response, requested, excludedProductIds) => {
6429
7146
  const group = readPostPurchaseGroupSelection(settings, response, requested, excludedProductIds);
@@ -6440,47 +7157,21 @@ var preparePostPurchaseGroupDeclineDisplay = (settings, response, requested, exc
6440
7157
 
6441
7158
  // src/server/preparePostPurchaseOfferPresentation.ts
6442
7159
  import { merge as merge2 } from "es-toolkit/compat";
6443
- import { z as z64 } from "zod";
7160
+ import { z as z76 } from "zod";
6444
7161
 
6445
7162
  // src/schema/postPurchaseOfferPresentation.ts
6446
- import { z as z62 } from "zod";
7163
+ import { z as z75 } from "zod";
6447
7164
  var language2 = PostPurchaseSettings.shape.language.shape.global.unwrap().unwrap();
6448
- var PostPurchaseOfferPresentation = z62.strictObject({
7165
+ var PostPurchaseOfferPresentation = z75.strictObject({
6449
7166
  labels: language2.pick({ declineAll: true, declineThisOffer: true }),
6450
7167
  layout: PostPurchaseSettings.shape.offersLayout,
6451
7168
  sections: CABRootSection.nullable(),
6452
7169
  showDeclineAll: PostPurchaseSettings.shape.productOptions.shape.showDeclineAll
6453
7170
  });
6454
7171
 
6455
- // src/server/postPurchaseOfferCopy.ts
6456
- import { z as z63 } from "zod";
6457
- var Copy = z63.object({
6458
- superTitle: CalloutBannerBlock.shape.settings.shape.superTitle.unwrap().optional().catch(void 0),
6459
- title: CalloutBannerBlock.shape.settings.shape.title.unwrap().optional().catch(void 0)
6460
- });
6461
- var Callout = z63.object({ settings: z63.record(z63.string(), z63.unknown()), type: z63.literal("callout_banner") });
6462
- var postPurchaseOfferCopy = (blocks, metadata) => {
6463
- const copy = Copy.safeParse(metadata.widget.language);
6464
- if (!blocks || !copy.success) return blocks;
6465
- const first = blocks.findIndex((block) => Callout.pick({ type: true }).safeParse(block).success);
6466
- return blocks.map((block, index) => {
6467
- if (index !== first) return block;
6468
- const callout = Callout.passthrough().safeParse(block);
6469
- if (!callout.success) return block;
6470
- return {
6471
- ...callout.data,
6472
- settings: {
6473
- ...callout.data.settings,
6474
- ...copy.data.title && { title: copy.data.title },
6475
- ...copy.data.superTitle && { superTitle: copy.data.superTitle }
6476
- }
6477
- };
6478
- });
6479
- };
6480
-
6481
7172
  // src/server/preparePostPurchaseOfferPresentation.ts
6482
7173
  var FrameSettings = PostPurchaseSettings.pick({ language: true, offersLayout: true, productOptions: true }).extend({
6483
- blocks: z64.array(z64.unknown()).optional()
7174
+ blocks: z76.array(z76.unknown()).optional()
6484
7175
  });
6485
7176
  var preparePostPurchaseOfferPresentation = (widgetId, settings, response, report) => {
6486
7177
  const { metadata } = PostPurchaseProductSource.pick({ metadata: true }).parse(deepCamelCase(response));
@@ -6504,42 +7195,6 @@ var preparePostPurchaseOfferPresentation = (widgetId, settings, response, report
6504
7195
  });
6505
7196
  };
6506
7197
 
6507
- // src/schema/postPurchaseQuantity.ts
6508
- import { z as z65 } from "zod";
6509
- var quantity = PreparedPostPurchaseProduct.shape.selection.shape.quantity;
6510
- var PostPurchaseQuantityPolicy = PostPurchaseSettings.shape.quantityInputs.omit({ defaultQuantity: true }).extend({
6511
- initialQuantity: quantity,
6512
- maxValue: quantity,
6513
- minValue: z65.literal(0).transform(() => 1).or(quantity)
6514
- }).refine(({ maxValue, minValue }) => minValue <= maxValue, "Quantity bounds are reversed");
6515
-
6516
- // src/server/readPostPurchaseQuantity.ts
6517
- var PostPurchaseQuantityUnavailable = class extends Error {
6518
- };
6519
- var readPostPurchaseQuantity = ({
6520
- data,
6521
- effective,
6522
- original
6523
- }, selection2) => {
6524
- const positive = PreparedPostPurchaseProduct.shape.selection.shape.quantity;
6525
- for (const config of [original, effective]) {
6526
- if (!config.quantityInputs.enabled) continue;
6527
- const initialQuantity2 = positive.parse(config.quantityInputs.defaultQuantity);
6528
- const policy2 = PostPurchaseQuantityPolicy.parse({ ...config.quantityInputs, initialQuantity: initialQuantity2 });
6529
- if (initialQuantity2 < policy2.minValue || initialQuantity2 > policy2.maxValue)
6530
- throw new Error("Configured quantity default is outside its bounds");
6531
- }
6532
- const initialQuantity = data[0]?.metadata?.productQuantity ?? (original.quantityInputs.enabled ? original.quantityInputs.defaultQuantity : 1);
6533
- const policy = PostPurchaseQuantityPolicy.parse(
6534
- effective.quantityInputs.enabled ? { ...effective.quantityInputs, initialQuantity } : { enabled: false, initialQuantity, maxValue: initialQuantity, minValue: initialQuantity }
6535
- );
6536
- const requested = "quantity" in selection2 ? selection2.quantity : selection2.expectedQuantity === initialQuantity ? void 0 : selection2.expectedQuantity;
6537
- const quantity2 = positive.parse(requested ?? initialQuantity);
6538
- if (requested !== void 0 && (policy.enabled ? quantity2 < policy.minValue || quantity2 > policy.maxValue : quantity2 !== initialQuantity))
6539
- throw new PostPurchaseQuantityUnavailable("Requested quantity is unavailable");
6540
- return { policy, quantity: quantity2 };
6541
- };
6542
-
6543
7198
  // src/server/analytics.ts
6544
7199
  import { chunk } from "es-toolkit";
6545
7200
 
@@ -6676,7 +7331,7 @@ var postAnalyticsEvents = async (input, ctx) => {
6676
7331
  };
6677
7332
 
6678
7333
  // src/server/requestSchemas.ts
6679
- import { z as z66 } from "zod";
7334
+ import { z as z77 } from "zod";
6680
7335
  var REQUEST_BOUNDS = {
6681
7336
  /** Cart-level attributes per cart. */
6682
7337
  CART_ATTRIBUTES_MAX: 100,
@@ -6707,42 +7362,42 @@ var REQUEST_BOUNDS = {
6707
7362
  /** Rich ads transaction lines — the engine's ads contract. */
6708
7363
  TRANSACTION_ITEMS_MAX: 50
6709
7364
  };
6710
- var KeyValue = z66.object({
6711
- key: z66.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
6712
- value: z66.string().max(REQUEST_BOUNDS.STRING_VALUE_MAX).optional()
7365
+ var KeyValue = z77.object({
7366
+ key: z77.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
7367
+ value: z77.string().max(REQUEST_BOUNDS.STRING_VALUE_MAX).optional()
6713
7368
  });
6714
- var CartLineInputSchema = z66.object({
6715
- productId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6716
- properties: z66.array(KeyValue).max(REQUEST_BOUNDS.LINE_PROPERTIES_MAX).optional(),
6717
- quantity: z66.number(),
6718
- subscriptionId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6719
- variantId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX)
7369
+ var CartLineInputSchema = z77.object({
7370
+ productId: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7371
+ properties: z77.array(KeyValue).max(REQUEST_BOUNDS.LINE_PROPERTIES_MAX).optional(),
7372
+ quantity: z77.number(),
7373
+ subscriptionId: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7374
+ variantId: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX)
6720
7375
  });
6721
- var CartInputSchema = z66.object({
6722
- attributes: z66.array(KeyValue).max(REQUEST_BOUNDS.CART_ATTRIBUTES_MAX).optional(),
7376
+ var CartInputSchema = z77.object({
7377
+ attributes: z77.array(KeyValue).max(REQUEST_BOUNDS.CART_ATTRIBUTES_MAX).optional(),
6723
7378
  /**
6724
7379
  * Presentment-per-shop-currency FX rate (buyer price ÷ shop price, e.g. `1.35` for a USD shop
6725
7380
  * selling in CAD). Money rule thresholds are authored in SHOP currency, so the engine subtotal is
6726
7381
  * divided by this before evaluation. Omit (or send 1) when the cart is already in the shop's currency.
6727
7382
  */
6728
- currencyRate: z66.number().optional(),
7383
+ currencyRate: z77.number().optional(),
6729
7384
  /** Applied discount codes; the engine evaluates `discount_code` rules against them (sent as `[{code}]`). */
6730
- discountCodes: z66.array(z66.string().max(REQUEST_BOUNDS.STRING_KEY_MAX)).max(REQUEST_BOUNDS.DISCOUNT_CODES_MAX).optional(),
7385
+ discountCodes: z77.array(z77.string().max(REQUEST_BOUNDS.STRING_KEY_MAX)).max(REQUEST_BOUNDS.DISCOUNT_CODES_MAX).optional(),
6731
7386
  /** Presentment cents of cart-level discount allocations, subtracted from `subtotal` for the engine. */
6732
- discountTotal: z66.number().optional(),
6733
- items: z66.array(CartLineInputSchema).max(REQUEST_BOUNDS.CART_ITEMS_MAX),
7387
+ discountTotal: z77.number().optional(),
7388
+ items: z77.array(CartLineInputSchema).max(REQUEST_BOUNDS.CART_ITEMS_MAX),
6734
7389
  /** Presentment subtotal in cents. */
6735
- subtotal: z66.number()
7390
+ subtotal: z77.number()
6736
7391
  });
6737
- var UserConfigInputSchema = z66.object({ shop: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX) });
6738
- var DataSourceInputSchema = z66.object({
7392
+ var UserConfigInputSchema = z77.object({ shop: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX) });
7393
+ var DataSourceInputSchema = z77.object({
6739
7394
  cart: CartInputSchema,
6740
7395
  /**
6741
7396
  * Numeric Shopify company-location id when the buyer is a B2B session (`buyerIdentity.purchasingCompany`).
6742
7397
  * Present ⇒ the orchestrator filters results by the location's catalog via admin-api (REB-23713); the
6743
7398
  * client's country-context market check is bypassed for B2B (it false-negatives B2B-catalog products).
6744
7399
  */
6745
- companyLocationId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7400
+ companyLocationId: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6746
7401
  /**
6747
7402
  * Buyer's market country (ISO 3166-1 alpha-2) — forwarded to the engine as the `country_code` PARAM
6748
7403
  * when the shop's markets toggle is on (REB-21688; the sink was the `X-Country-Code` header under
@@ -6751,16 +7406,16 @@ var DataSourceInputSchema = z66.object({
6751
7406
  * uppercase (the wire value is forwarded verbatim as the param) so a case-sensitive engine lookup
6752
7407
  * can't silently miss a lowercase code — `adsEngine.ts` uppercases for the same reason.
6753
7408
  */
6754
- country: z66.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(),
6755
- customerId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6756
- dataSourcePath: z66.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
7409
+ country: z77.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(),
7410
+ customerId: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7411
+ dataSourcePath: z77.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
6757
7412
  /**
6758
7413
  * Engine `filter_inputs` override: `'no'` keeps in-cart (input) products in the results/rule
6759
7414
  * outputs — gift validation sends it so a gift's own product can appear in its answer. Omitted = the
6760
7415
  * engine's default filtering.
6761
7416
  */
6762
- filterInputs: z66.enum(["no", "yes"]).optional(),
6763
- integrations: z66.record(z66.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), z66.boolean()).refine((record) => Object.keys(record).length <= REQUEST_BOUNDS.INTEGRATION_KEYS_MAX, {
7417
+ filterInputs: z77.enum(["no", "yes"]).optional(),
7418
+ integrations: z77.record(z77.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), z77.boolean()).refine((record) => Object.keys(record).length <= REQUEST_BOUNDS.INTEGRATION_KEYS_MAX, {
6764
7419
  message: `Too many integration keys (max ${REQUEST_BOUNDS.INTEGRATION_KEYS_MAX})`
6765
7420
  }).optional(),
6766
7421
  /**
@@ -6773,31 +7428,31 @@ var DataSourceInputSchema = z66.object({
6773
7428
  * request header) fails the regex. Callers should send the buyer's resolved locale (e.g. Shopify
6774
7429
  * checkout's `localization.language.isoCode`), not the request header verbatim.
6775
7430
  */
6776
- language: z66.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(),
6777
- limit: z66.number().max(REQUEST_BOUNDS.LIMIT_MAX),
6778
- productType: z66.enum(["both", "one-time", "subscription"]).optional(),
6779
- shop: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6780
- visitorId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
6781
- });
6782
- var GiftInputSchema = z66.object({
6783
- cost: z66.number(),
6784
- discounted: z66.boolean(),
7431
+ language: z77.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(),
7432
+ limit: z77.number().max(REQUEST_BOUNDS.LIMIT_MAX),
7433
+ productType: z77.enum(["both", "one-time", "subscription"]).optional(),
7434
+ shop: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7435
+ visitorId: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
7436
+ });
7437
+ var GiftInputSchema = z77.object({
7438
+ cost: z77.number(),
7439
+ discounted: z77.boolean(),
6785
7440
  /**
6786
7441
  * Which gift attribution the line carries (REB-24363). Defaults to `gwp` because a client that predates
6787
7442
  * the field only ever sent GWP lines — without the default an older extension's request would 422.
6788
7443
  */
6789
- kind: z66.enum(GIFT_KINDS).default("gwp"),
6790
- lineId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6791
- productId: z66.number(),
7444
+ kind: z77.enum(GIFT_KINDS).default("gwp"),
7445
+ lineId: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7446
+ productId: z77.number(),
6792
7447
  /**
6793
7448
  * The line's unit count (REB-24363) — the selectable-GWP verdict trims surplus units against milestone
6794
7449
  * capacity. The second deliberate default: a client predating the field sent only GWP lines, whose
6795
7450
  * verdict is whole-line, so a missing quantity reads as one unit rather than 422ing the older request.
6796
7451
  */
6797
- quantity: z66.number().int().min(1).default(1),
6798
- widgetId: z66.number()
7452
+ quantity: z77.number().int().min(1).default(1),
7453
+ widgetId: z77.number()
6799
7454
  });
6800
- var GiftValidationInputSchema = z66.object({
7455
+ var GiftValidationInputSchema = z77.object({
6801
7456
  cart: CartInputSchema,
6802
7457
  /**
6803
7458
  * Buyer's market country — threaded into the per-widget data-source evaluations, which forward it to
@@ -6806,25 +7461,25 @@ var GiftValidationInputSchema = z66.object({
6806
7461
  * turns markets off); regex-bound and uppercase-normalized for the same reasons as
6807
7462
  * `DataSourceInputSchema`'s `country`.
6808
7463
  */
6809
- country: z66.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(),
6810
- customerId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6811
- gifts: z66.array(GiftInputSchema).max(REQUEST_BOUNDS.GIFTS_MAX),
7464
+ country: z77.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(),
7465
+ customerId: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7466
+ gifts: z77.array(GiftInputSchema).max(REQUEST_BOUNDS.GIFTS_MAX),
6812
7467
  /**
6813
7468
  * Buyer's checkout language — threaded into the per-widget data-source evaluations, which normalize
6814
7469
  * and forward it as the engine `locale` param under the same markets-toggle gate (REB-21688). MUST be
6815
7470
  * a single BCP-47 tag, for the same reason as `DataSourceInputSchema`'s `language` above.
6816
7471
  */
6817
- language: z66.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(),
6818
- shop: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6819
- visitorId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
7472
+ language: z77.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(),
7473
+ shop: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7474
+ visitorId: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
6820
7475
  });
6821
- var GiftAdjustmentSchema = z66.object({
6822
- lineId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6823
- quantity: z66.number().int().nonnegative()
7476
+ var GiftAdjustmentSchema = z77.object({
7477
+ lineId: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7478
+ quantity: z77.number().int().nonnegative()
6824
7479
  });
6825
- var GiftValidationResponseSchema = z66.object({
6826
- adjust: z66.array(GiftAdjustmentSchema).max(REQUEST_BOUNDS.GIFTS_MAX).default([]),
6827
- remove: z66.array(z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX)).max(REQUEST_BOUNDS.GIFTS_MAX).refine(
7480
+ var GiftValidationResponseSchema = z77.object({
7481
+ adjust: z77.array(GiftAdjustmentSchema).max(REQUEST_BOUNDS.GIFTS_MAX).default([]),
7482
+ remove: z77.array(z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX)).max(REQUEST_BOUNDS.GIFTS_MAX).refine(
6828
7483
  (remove) => new Set(remove).size === remove.length,
6829
7484
  "a line id may appear at most once in `remove`"
6830
7485
  )
@@ -6835,47 +7490,47 @@ var GiftValidationResponseSchema = z66.object({
6835
7490
  ({ adjust }) => new Set(adjust.map(({ lineId }) => lineId)).size === adjust.length,
6836
7491
  "a line id may appear at most once in `adjust`"
6837
7492
  );
6838
- var MonetizeTransactionItemSchema = z66.object({
6839
- id: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6840
- priceCents: z66.number(),
6841
- quantity: z66.number(),
6842
- title: z66.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX),
6843
- type: z66.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX)
6844
- });
6845
- var MonetizeInputSchema = z66.object({
7493
+ var MonetizeTransactionItemSchema = z77.object({
7494
+ id: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7495
+ priceCents: z77.number(),
7496
+ quantity: z77.number(),
7497
+ title: z77.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX),
7498
+ type: z77.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX)
7499
+ });
7500
+ var MonetizeInputSchema = z77.object({
6846
7501
  cart: CartInputSchema,
6847
7502
  /** Client-minted render-beacon correlation id; forwarded to the ads engine as `client_request_id`. */
6848
- clientRequestId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6849
- country: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6850
- currency: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7503
+ clientRequestId: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7504
+ country: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7505
+ currency: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6851
7506
  /** Ads-targeting identity/geo/locale fields (React parity); folded into the engine query verbatim. */
6852
- customerEmail: z66.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
6853
- customerFirstName: z66.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
6854
- customerId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6855
- customerLastName: z66.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
6856
- language: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7507
+ customerEmail: z77.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
7508
+ customerFirstName: z77.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
7509
+ customerId: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7510
+ customerLastName: z77.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
7511
+ language: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6857
7512
  /** Buyer-facing order name (e.g. `#1001`) for the server-composed "Order … Confirmed" chrome line. */
6858
- orderName: z66.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
7513
+ orderName: z77.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
6859
7514
  /** Ads surface label, forwarded verbatim; `customer_account` is measured/floored as its own surface (the account-area order list). */
6860
- placement: z66.enum(["customer_account", "order_status", "thank_you_page"]),
7515
+ placement: z77.enum(["customer_account", "order_status", "thank_you_page"]),
6861
7516
  /** Privacy Policy footer href — the Monetize widget's `privacy_policy_url` setting (React parity). */
6862
- privacyPolicyUrl: z66.string().max(REQUEST_BOUNDS.STRING_URL_MAX).optional(),
7517
+ privacyPolicyUrl: z77.string().max(REQUEST_BOUNDS.STRING_URL_MAX).optional(),
6863
7518
  /** 30-min rolling session id (React parity); used for the ads `session_id`, else the visitor id. */
6864
- sessionId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6865
- shop: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7519
+ sessionId: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7520
+ shop: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6866
7521
  /** Editor/QA indicator; OR-ed into the ads-engine `testing` flag so it stays out of billing/reporting. */
6867
- testing: z66.boolean().optional(),
6868
- timezone: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7522
+ testing: z77.boolean().optional(),
7523
+ timezone: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6869
7524
  /** Decorated (numeric) order id → the ads `transaction_id`. */
6870
- transactionId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7525
+ transactionId: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6871
7526
  /** Rich per-line ads items; capped at the engine's ads contract. Preferred over `cart.items`. */
6872
- transactionItems: z66.array(MonetizeTransactionItemSchema).max(REQUEST_BOUNDS.TRANSACTION_ITEMS_MAX).optional(),
7527
+ transactionItems: z77.array(MonetizeTransactionItemSchema).max(REQUEST_BOUNDS.TRANSACTION_ITEMS_MAX).optional(),
6873
7528
  /** Order total in presentment cents (React prefers total over subtotal); else `cart.subtotal`. */
6874
- transactionTotal: z66.number().optional(),
6875
- visitorId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6876
- zipCode: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
7529
+ transactionTotal: z77.number().optional(),
7530
+ visitorId: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7531
+ zipCode: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
6877
7532
  });
6878
- var WidgetSettingsInputSchema = z66.object({
7533
+ var WidgetSettingsInputSchema = z77.object({
6879
7534
  /**
6880
7535
  * Same domain as `CabShopConfig.cacheKey`, for the same reason: this side WINS the orchestrator's
6881
7536
  * `input.cacheKey ?? config.shop.cacheKey` (and an explicit value skips the config read entirely), so
@@ -6883,9 +7538,9 @@ var WidgetSettingsInputSchema = z66.object({
6883
7538
  * and pin the edge copy permanently stale. `.catch(undefined)` because a bogus buster should degrade
6884
7539
  * the read to un-busted, never 400 a widget render.
6885
7540
  */
6886
- cacheKey: z66.number().int().positive().optional().catch(void 0),
6887
- id: z66.number(),
6888
- key: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7541
+ cacheKey: z77.number().int().positive().optional().catch(void 0),
7542
+ id: z77.number(),
7543
+ key: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6889
7544
  /**
6890
7545
  * Monetize context for inline hydration: when present AND the widget converts to a Monetize marker,
6891
7546
  * the server fetches/composes the offer cards inside this same request (no second `/cab/monetize`
@@ -6894,36 +7549,36 @@ var WidgetSettingsInputSchema = z66.object({
6894
7549
  * `privacyPolicyUrl` comes from the widget settings server-side (more authoritative than a relay).
6895
7550
  */
6896
7551
  monetize: MonetizeInputSchema.omit({ privacyPolicyUrl: true, shop: true }).optional(),
6897
- shop: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7552
+ shop: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6898
7553
  /** Stable per-buyer id; when present, enables sticky server-side A/B variant selection. */
6899
- visitorId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
7554
+ visitorId: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
6900
7555
  });
6901
- var AnalyticsEventInputSchema = z66.object({
6902
- name: z66.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
6903
- properties: z66.record(z66.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), z66.unknown()).optional(),
6904
- sentAt: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
7556
+ var AnalyticsEventInputSchema = z77.object({
7557
+ name: z77.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
7558
+ properties: z77.record(z77.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), z77.unknown()).optional(),
7559
+ sentAt: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
6905
7560
  });
6906
- var AnalyticsSegmentsInputSchema = z66.object({
6907
- device: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
6908
- source: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
6909
- visitor: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0)
7561
+ var AnalyticsSegmentsInputSchema = z77.object({
7562
+ device: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
7563
+ source: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
7564
+ visitor: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0)
6910
7565
  });
6911
- var AnalyticsInputSchema = z66.object({
7566
+ var AnalyticsInputSchema = z77.object({
6912
7567
  /** Rebuy cart token (the `r_cart_token` cart attribute), when available — primary aggregation key. */
6913
- cartToken: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7568
+ cartToken: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6914
7569
  /** Shopify checkout token, when available — drives cart/checkout aggregation downstream. */
6915
- checkoutToken: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6916
- events: z66.array(AnalyticsEventInputSchema).max(REQUEST_BOUNDS.EVENTS_MAX),
7570
+ checkoutToken: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7571
+ events: z77.array(AnalyticsEventInputSchema).max(REQUEST_BOUNDS.EVENTS_MAX),
6917
7572
  /**
6918
7573
  * Request-scoped like the tokens: one visitor's segments apply to every event in the batch. The container
6919
7574
  * degrades too (`null` is a realistic wire artifact of `attributes ? {…} : null`), so the degrade rule is
6920
7575
  * total: nothing about `segments` can cost the envelope.
6921
7576
  */
6922
7577
  segments: AnalyticsSegmentsInputSchema.optional().catch(void 0),
6923
- shop: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6924
- visitorId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7578
+ shop: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7579
+ visitorId: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6925
7580
  /** The widget id (smartBlockId) the events belong to. */
6926
- widgetId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
7581
+ widgetId: z77.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
6927
7582
  });
6928
7583
  export {
6929
7584
  AnalyticsEventInputSchema,
@@ -6953,9 +7608,20 @@ export {
6953
7608
  fetchMonetizeOffers,
6954
7609
  fetchUserConfig,
6955
7610
  postAnalyticsEvents,
7611
+ preparePostPurchaseAdmissionView,
7612
+ preparePostPurchaseCollectionView,
7613
+ preparePostPurchaseGroupAdmissionView,
6956
7614
  preparePostPurchaseGroupDeclineDisplay,
7615
+ preparePostPurchaseGroupDefault,
7616
+ preparePostPurchaseGroupView,
7617
+ preparePostPurchaseMemberAdmissionView,
7618
+ preparePostPurchaseMemberView,
6957
7619
  preparePostPurchaseOfferPresentation,
7620
+ preparePostPurchaseProduct,
7621
+ preparePostPurchaseQuantityAdmissionView,
7622
+ preparePostPurchaseQuantityView,
6958
7623
  preparePostPurchaseSubscription,
7624
+ preparePostPurchaseView,
6959
7625
  readPostPurchaseGroupSelection,
6960
7626
  readPostPurchaseQuantity,
6961
7627
  translateAnalyticsEvent,