@rebuy/rebuy 3.34.0 → 3.36.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 (51) hide show
  1. package/dist/index.cjs +1003 -801
  2. package/dist/index.mjs +1005 -803
  3. package/dist/schema/index.d.ts +8 -0
  4. package/dist/schema/postPurchaseGroup.d.ts +15 -0
  5. package/dist/schema/postPurchaseGroupCatalog.d.ts +56 -0
  6. package/dist/schema/postPurchaseOfferEligibility.d.ts +32 -0
  7. package/dist/schema/postPurchaseOfferPresentation.d.ts +386 -0
  8. package/dist/schema/postPurchaseProduct.d.ts +74 -24
  9. package/dist/schema/postPurchaseProductCalculation.d.ts +87 -0
  10. package/dist/schema/postPurchaseProductCollectionView.d.ts +724 -3
  11. package/dist/schema/postPurchaseProductDisplay.d.ts +41 -12
  12. package/dist/schema/postPurchaseProductSource.d.ts +10 -5
  13. package/dist/schema/postPurchaseProductView.d.ts +708 -0
  14. package/dist/schema/postPurchaseQuantity.d.ts +26 -0
  15. package/dist/schema/postPurchaseSubscriptionProduct.d.ts +74 -17
  16. package/dist/schema/postPurchaseVariantDefault.d.ts +17 -0
  17. package/dist/schema/postPurchaseVariantDefaultContext.d.ts +10 -0
  18. package/dist/server/__fixtures__/postPurchaseGroup.d.ts +78 -0
  19. package/dist/server/classifyPostPurchaseOffer.d.ts +3 -0
  20. package/dist/server/createPostPurchaseOrderAttributes.d.ts +9 -0
  21. package/dist/server/index.cjs +1131 -210
  22. package/dist/server/index.d.ts +20 -2
  23. package/dist/server/index.mjs +1131 -210
  24. package/dist/server/postPurchaseMemberEligibility.d.ts +7 -0
  25. package/dist/server/postPurchaseOfferCopy.d.ts +3 -0
  26. package/dist/server/postPurchaseProductDisplay.d.ts +38 -6
  27. package/dist/server/postPurchaseProductEligibility.d.ts +3 -7
  28. package/dist/server/postPurchaseSubscriptionEligibility.d.ts +2 -3
  29. package/dist/server/prepareNormalizedSubscription.d.ts +2 -3
  30. package/dist/server/preparePostPurchaseAdmissionView.d.ts +418 -0
  31. package/dist/server/preparePostPurchaseCollectionGroup.d.ts +458 -0
  32. package/dist/server/preparePostPurchaseCollectionView.d.ts +442 -0
  33. package/dist/server/preparePostPurchaseGroupAdmissionView.d.ts +459 -0
  34. package/dist/server/preparePostPurchaseGroupDeclineDisplay.d.ts +12 -0
  35. package/dist/server/preparePostPurchaseGroupDefault.d.ts +459 -0
  36. package/dist/server/preparePostPurchaseGroupView.d.ts +458 -0
  37. package/dist/server/preparePostPurchaseMemberView.d.ts +1466 -0
  38. package/dist/server/preparePostPurchaseOfferPresentation.d.ts +137 -0
  39. package/dist/server/preparePostPurchaseProduct.d.ts +11 -0
  40. package/dist/server/preparePostPurchaseQuantityAdmissionView.d.ts +440 -0
  41. package/dist/server/preparePostPurchaseQuantityView.d.ts +427 -0
  42. package/dist/server/preparePostPurchaseSubscription.d.ts +37 -5
  43. package/dist/server/preparePostPurchaseView.d.ts +8 -0
  44. package/dist/server/projectPostPurchaseProduct.d.ts +42 -12
  45. package/dist/server/readPostPurchaseGroup.d.ts +101 -0
  46. package/dist/server/readPostPurchaseGroupSelection.d.ts +110 -0
  47. package/dist/server/readPostPurchaseQuantity.d.ts +27 -0
  48. package/dist/server/resolvePostPurchaseMemberDefault.d.ts +8 -0
  49. package/dist/server/selectPostPurchaseChoice.d.ts +2 -3
  50. package/dist/transforms/postPurchase/convertDescriptionRte.d.ts +11 -0
  51. package/package.json +1 -1
@@ -33,18 +33,36 @@ __export(server_exports, {
33
33
  MonetizeInputSchema: () => MonetizeInputSchema,
34
34
  MonetizeTransactionItemSchema: () => MonetizeTransactionItemSchema,
35
35
  NotFoundError: () => NotFoundError,
36
+ PostPurchaseQuantityUnavailable: () => PostPurchaseQuantityUnavailable,
36
37
  REBUY_ENGINE_HOST: () => REBUY_ENGINE_HOST,
37
38
  REQUEST_BOUNDS: () => REQUEST_BOUNDS,
38
39
  UpstreamError: () => UpstreamError,
39
40
  UserConfigInputSchema: () => UserConfigInputSchema,
40
41
  WidgetSettingsInputSchema: () => WidgetSettingsInputSchema,
41
42
  buildEngineParams: () => buildEngineParams,
43
+ classifyPostPurchaseOffer: () => classifyPostPurchaseOffer,
42
44
  convertWidgetSettings: () => convertWidgetSettings,
45
+ createPostPurchaseOrderAttributes: () => createPostPurchaseOrderAttributes,
43
46
  fetchDataSourceResults: () => fetchDataSourceResults,
44
47
  fetchMonetizeOffers: () => fetchMonetizeOffers,
45
48
  fetchUserConfig: () => fetchUserConfig,
46
49
  postAnalyticsEvents: () => postAnalyticsEvents,
50
+ preparePostPurchaseAdmissionView: () => preparePostPurchaseAdmissionView,
51
+ preparePostPurchaseCollectionView: () => preparePostPurchaseCollectionView,
52
+ preparePostPurchaseGroupAdmissionView: () => preparePostPurchaseGroupAdmissionView,
53
+ preparePostPurchaseGroupDeclineDisplay: () => preparePostPurchaseGroupDeclineDisplay,
54
+ preparePostPurchaseGroupDefault: () => preparePostPurchaseGroupDefault,
55
+ preparePostPurchaseGroupView: () => preparePostPurchaseGroupView,
56
+ preparePostPurchaseMemberAdmissionView: () => preparePostPurchaseMemberAdmissionView,
57
+ preparePostPurchaseMemberView: () => preparePostPurchaseMemberView,
58
+ preparePostPurchaseOfferPresentation: () => preparePostPurchaseOfferPresentation,
59
+ preparePostPurchaseProduct: () => preparePostPurchaseProduct,
60
+ preparePostPurchaseQuantityAdmissionView: () => preparePostPurchaseQuantityAdmissionView,
61
+ preparePostPurchaseQuantityView: () => preparePostPurchaseQuantityView,
47
62
  preparePostPurchaseSubscription: () => preparePostPurchaseSubscription,
63
+ preparePostPurchaseView: () => preparePostPurchaseView,
64
+ readPostPurchaseGroupSelection: () => readPostPurchaseGroupSelection,
65
+ readPostPurchaseQuantity: () => readPostPurchaseQuantity,
48
66
  translateAnalyticsEvent: () => translateAnalyticsEvent,
49
67
  validateGifts: () => validateGifts
50
68
  });
@@ -679,7 +697,7 @@ var import_uuid13 = require("uuid");
679
697
  var import_zod27 = require("zod");
680
698
 
681
699
  // src/schema/widgets/checkout-and-beyond/common.ts
682
- var freezeEnum = (values) => Object.freeze(Object.fromEntries(values.map((v) => [v, v])));
700
+ var freezeEnum = (values2) => Object.freeze(Object.fromEntries(values2.map((v) => [v, v])));
683
701
  var bannerColors = ["info", "success", "warning", "critical"];
684
702
  var BannerColor = freezeEnum(bannerColors);
685
703
  var borderRadii = ["none", "small", "base", "large", "fullyRounded"];
@@ -2145,15 +2163,15 @@ var CABImageSectionFields = import_zod27.z.object({
2145
2163
  width: import_zod27.z.number().default(100)
2146
2164
  });
2147
2165
  var iconNameSet = new Set(iconNames);
2148
- var isIconName = (source) => iconNameSet.has(source);
2149
- var CABImageSection = CABImageSectionFields.superRefine(({ category, source }, ctx) => {
2150
- if (category === "icon" && source !== "" && !isIconName(source))
2166
+ var isIconName = (source2) => iconNameSet.has(source2);
2167
+ var CABImageSection = CABImageSectionFields.superRefine(({ category, source: source2 }, ctx) => {
2168
+ if (category === "icon" && source2 !== "" && !isIconName(source2))
2151
2169
  ctx.addIssue({
2152
2170
  code: "custom",
2153
2171
  message: "icon-mode source must be an icon name",
2154
2172
  path: ["source"]
2155
2173
  });
2156
- if (category !== "icon" && isIconName(source))
2174
+ if (category !== "icon" && isIconName(source2))
2157
2175
  ctx.addIssue({
2158
2176
  code: "custom",
2159
2177
  message: "source must be a URL or dynamic token unless category is `icon`",
@@ -2171,7 +2189,7 @@ var stripContentBlockHtml = (text2) => text2.replace(HTML_COMMENT_RE, "").replac
2171
2189
  var convertTextToTiptapParagraph = ({
2172
2190
  color,
2173
2191
  fontSize,
2174
- marks = [],
2192
+ marks: marks2 = [],
2175
2193
  text: text2,
2176
2194
  textAlign
2177
2195
  }) => {
@@ -2180,7 +2198,7 @@ var convertTextToTiptapParagraph = ({
2180
2198
  attrs: { textAlign },
2181
2199
  content: sanitizedText ? [
2182
2200
  {
2183
- marks: [{ attrs: { color, fontSize }, type: "textStyle" }, ...marks],
2201
+ marks: [{ attrs: { color, fontSize }, type: "textStyle" }, ...marks2],
2184
2202
  text: sanitizedText,
2185
2203
  type: "text"
2186
2204
  }
@@ -2265,10 +2283,10 @@ var HEADER_PARAGRAPH_STYLES = {
2265
2283
  superTitle: { color: "base", fontSize: "extraLarge", marks: [{ type: "bold" }] },
2266
2284
  title: { color: "base", fontSize: "medium", marks: [{ type: "bold" }] }
2267
2285
  };
2268
- var convertContentBlockTextToV2 = (language2, text2 = literalText, textAlign = "center") => {
2269
- const description = language2?.description;
2270
- const superTitle = language2?.superTitle;
2271
- const title = language2?.title;
2286
+ var convertContentBlockTextToV2 = (language3, text2 = literalText, textAlign = "center") => {
2287
+ const description = language3?.description;
2288
+ const superTitle = language3?.superTitle;
2289
+ const title = language3?.title;
2272
2290
  return TiptapDocument.parse({
2273
2291
  attrs: { blockSpacing: "tight" },
2274
2292
  content: [
@@ -2380,7 +2398,7 @@ var LOCATION_TO_EDITOR_MODE = {
2380
2398
  };
2381
2399
 
2382
2400
  // src/transforms/contentBlockV1/convertContentBlockToV2.ts
2383
- var hasText = (language2) => !!language2 && !!(language2.description || language2.superTitle || language2.title);
2401
+ var hasText = (language3) => !!language3 && !!(language3.description || language3.superTitle || language3.title);
2384
2402
  var convertContentBlockToV2 = ({ id, settings }) => {
2385
2403
  const imageBlocks = settings.imageBlocks ?? [];
2386
2404
  return CABRootSection.parse({
@@ -2637,11 +2655,11 @@ var pushText = (state, rawText) => {
2637
2655
  decodeTextEntities(rawText).split("\n").forEach((segment, index) => {
2638
2656
  if (index > 0) flushParagraph(state);
2639
2657
  if (!segment) return;
2640
- const marks = state.stack.flatMap((entry) => entry.marks);
2641
- if (state.defaultTextStyleMark && !marks.some((mark) => mark.type === "textStyle")) {
2642
- marks.push(state.defaultTextStyleMark);
2658
+ const marks2 = state.stack.flatMap((entry) => entry.marks);
2659
+ if (state.defaultTextStyleMark && !marks2.some((mark) => mark.type === "textStyle")) {
2660
+ marks2.push(state.defaultTextStyleMark);
2643
2661
  }
2644
- state.currentRuns.push(TiptapText.parse(marks.length > 0 ? { marks, text: segment } : { text: segment }));
2662
+ state.currentRuns.push(TiptapText.parse(marks2.length > 0 ? { marks: marks2, text: segment } : { text: segment }));
2645
2663
  });
2646
2664
  };
2647
2665
 
@@ -2653,15 +2671,15 @@ var stripHtmlComments = (html = "") => html.replace(HTML_COMMENT_RE2, "");
2653
2671
  var maybeFlushParagraph = (state) => {
2654
2672
  if (state.currentRuns.length > 0) flushParagraph(state);
2655
2673
  };
2656
- var htmlToTiptap = (html, options = {}) => {
2674
+ var htmlToTiptap = (html, options2 = {}) => {
2657
2675
  const state = {
2658
2676
  currentRuns: [],
2659
- defaultTextStyleMark: buildDefaultTextStyleMark(options.defaultTextStyle),
2677
+ defaultTextStyleMark: buildDefaultTextStyleMark(options2.defaultTextStyle),
2660
2678
  listStack: [],
2661
2679
  paragraphs: [],
2662
2680
  stack: []
2663
2681
  };
2664
- const blockSpacing = options.blockSpacing ?? "base";
2682
+ const blockSpacing = options2.blockSpacing ?? "base";
2665
2683
  if (typeof html !== "string" || !html) return makeDoc([makeParagraph([])], blockSpacing);
2666
2684
  const htmlWithoutComments = stripHtmlComments(html);
2667
2685
  let lastIndex = 0;
@@ -2906,9 +2924,9 @@ var isMonetizeV1 = isWidgetV1(WidgetType.ui_extension_ad);
2906
2924
  var HTML_TAG_RE2 = /<[a-zA-Z]/;
2907
2925
  var containsHtml = (text2) => HTML_TAG_RE2.test(text2);
2908
2926
  var isObject = (x) => x !== null && typeof x === "object" && !Array.isArray(x);
2909
- var normalizeTextValue = (value, options = {}) => {
2927
+ var normalizeTextValue = (value, options2 = {}) => {
2910
2928
  const tokenized = normalizeTokens(value);
2911
- return containsHtml(tokenized) || options.defaultTextStyle ? htmlToTiptap(tokenized, options) : decodeTextEntities(tokenized);
2929
+ return containsHtml(tokenized) || options2.defaultTextStyle ? htmlToTiptap(tokenized, options2) : decodeTextEntities(tokenized);
2912
2930
  };
2913
2931
  var normalizeLangValue = (value) => typeof value === "string" ? normalizeTextValue(value) : value;
2914
2932
  var normalizeTextContent = (node) => {
@@ -2941,15 +2959,15 @@ var resolveExperiment = (experiments, placeholderId, visitorId) => {
2941
2959
  if (!experiment || experiment.data.length === 0) return void 0;
2942
2960
  const roll = rollPercent(`${visitorId}:${experiment.id}`);
2943
2961
  let cumulative = 0;
2944
- const variant = experiment.data.find((candidate) => {
2962
+ const variant2 = experiment.data.find((candidate) => {
2945
2963
  cumulative += candidate.traffic;
2946
2964
  return roll < cumulative;
2947
2965
  }) ?? experiment.data[0];
2948
2966
  return {
2949
- elementId: variant.elementId,
2967
+ elementId: variant2.elementId,
2950
2968
  experimentId: experiment.id,
2951
2969
  experimentType: experiment.type,
2952
- selectedId: variant.id
2970
+ selectedId: variant2.id
2953
2971
  };
2954
2972
  };
2955
2973
 
@@ -3216,10 +3234,10 @@ var SWITCH_LABEL_TOKENS2 = ["subscriptionDiscount", "frequency", "interval"];
3216
3234
  var QUANTITY_ERROR_TOKENS = ["max", "min", "step"];
3217
3235
  var VARIANT_SELECTOR = { button: "button", radio: "radio", select: "menu" };
3218
3236
  var buildStyledText = (token, style, fontSize = style?.textSize ?? "base") => {
3219
- const marks = [{ attrs: { color: "base", fontSize }, type: "textStyle" }];
3220
- if (style?.textEmphasis === "bold") marks.push({ type: "bold" });
3221
- if (style?.textEmphasis === "italic") marks.push({ type: "italic" });
3222
- return { content: [{ content: [{ marks, text: token, type: "text" }], type: "paragraph" }], type: "doc" };
3237
+ const marks2 = [{ attrs: { color: "base", fontSize }, type: "textStyle" }];
3238
+ if (style?.textEmphasis === "bold") marks2.push({ type: "bold" });
3239
+ if (style?.textEmphasis === "italic") marks2.push({ type: "italic" });
3240
+ return { content: [{ content: [{ marks: marks2, text: token, type: "text" }], type: "paragraph" }], type: "doc" };
3223
3241
  };
3224
3242
  var buildPriceContent = () => ({
3225
3243
  content: [
@@ -3397,23 +3415,23 @@ var QUANTITY_INPUT_TYPE = {
3397
3415
  "buttons-manual-input": "number",
3398
3416
  "dropdown-select": "select"
3399
3417
  };
3400
- var buildQuantityErrors = (quantity) => {
3418
+ var buildQuantityErrors = (quantity2) => {
3401
3419
  const en = {
3402
- ...quantity.maxError && { max: normalizeTokens(quantity.maxError, QUANTITY_ERROR_TOKENS) },
3403
- ...quantity.minError && { min: normalizeTokens(quantity.minError, QUANTITY_ERROR_TOKENS) },
3404
- ...quantity.negativeError && { neg: normalizeTokens(quantity.negativeError, QUANTITY_ERROR_TOKENS) }
3420
+ ...quantity2.maxError && { max: normalizeTokens(quantity2.maxError, QUANTITY_ERROR_TOKENS) },
3421
+ ...quantity2.minError && { min: normalizeTokens(quantity2.minError, QUANTITY_ERROR_TOKENS) },
3422
+ ...quantity2.negativeError && { neg: normalizeTokens(quantity2.negativeError, QUANTITY_ERROR_TOKENS) }
3405
3423
  };
3406
3424
  return Object.keys(en).length ? { errorMessages: { en } } : {};
3407
3425
  };
3408
3426
  var buildQuantity = (settings) => {
3409
- const quantity = settings.quantityInputs;
3410
- if (!quantity?.enabled) return [];
3411
- const inputType = quantity.type ? QUANTITY_INPUT_TYPE[quantity.type] : void 0;
3412
- const max = Math.min(Math.max(quantity.maxValue ?? 10, 1), 100);
3413
- const min = Math.min(Math.max(quantity.minValue ?? 1, 1), max);
3427
+ const quantity2 = settings.quantityInputs;
3428
+ if (!quantity2?.enabled) return [];
3429
+ const inputType = quantity2.type ? QUANTITY_INPUT_TYPE[quantity2.type] : void 0;
3430
+ const max = Math.min(Math.max(quantity2.maxValue ?? 10, 1), 100);
3431
+ const min = Math.min(Math.max(quantity2.minValue ?? 1, 1), max);
3414
3432
  return [
3415
3433
  {
3416
- ...buildQuantityErrors(quantity),
3434
+ ...buildQuantityErrors(quantity2),
3417
3435
  ...inputType && { inputType },
3418
3436
  max,
3419
3437
  min,
@@ -3423,7 +3441,7 @@ var buildQuantity = (settings) => {
3423
3441
  };
3424
3442
  var buildSubscriptionButton = (settings) => {
3425
3443
  if (settings.productType !== "both" && settings.productType !== "subscription") return [];
3426
- const language2 = settings.language;
3444
+ const language3 = settings.language;
3427
3445
  const slot = (buttonField, override) => ({
3428
3446
  buttonField,
3429
3447
  content: localizedContent(SWITCH_LABELS[buttonField], override, SWITCH_LABEL_TOKENS2),
@@ -3437,9 +3455,9 @@ var buildSubscriptionButton = (settings) => {
3437
3455
  ...settings.productType === "subscription" && { disableDowngrade: true },
3438
3456
  sections: [
3439
3457
  slot("subscriptionOption", void 0),
3440
- slot("switchToOneTimePurchase", language2?.cartSwitchToOnetime),
3441
- slot("switchToSubscriptionNoDiscount", language2?.upgradeToSubscription),
3442
- slot("switchToSubscriptionWithDiscount", language2?.upgradeToSubscription)
3458
+ slot("switchToOneTimePurchase", language3?.cartSwitchToOnetime),
3459
+ slot("switchToSubscriptionNoDiscount", language3?.upgradeToSubscription),
3460
+ slot("switchToSubscriptionWithDiscount", language3?.upgradeToSubscription)
3443
3461
  ],
3444
3462
  sectionType: "button"
3445
3463
  }
@@ -3494,11 +3512,11 @@ var buildOfferCard = (settings, horizontal) => {
3494
3512
  const description = buildDescription(settings);
3495
3513
  const reviews = buildReviews(settings);
3496
3514
  const variants = buildVariants(settings);
3497
- const quantity = buildQuantity(settings);
3515
+ const quantity2 = buildQuantity(settings);
3498
3516
  const subscription2 = buildSubscriptionButton(settings);
3499
3517
  const reveal = buildRevealButton(settings);
3500
3518
  const addButton = buildAddButton(settings);
3501
- const controls = [...description, ...quantity, ...variants, ...subscription2];
3519
+ const controls = [...description, ...quantity2, ...variants, ...subscription2];
3502
3520
  const info = detailBlock([title, ...variantTitle, ...reviews, price], horizontal, variantTitle.length > 0);
3503
3521
  const card = (sections) => [
3504
3522
  {
@@ -3552,9 +3570,9 @@ var buildCarouselNav = () => ({
3552
3570
  sectionType: "layout"
3553
3571
  });
3554
3572
  var HEADER_FIELDS = ["superTitle", "title", "description"];
3555
- var sanitizedHeader = (language2) => Object.fromEntries(
3573
+ var sanitizedHeader = (language3) => Object.fromEntries(
3556
3574
  HEADER_FIELDS.flatMap((field) => {
3557
- const value = language2?.[field];
3575
+ const value = language3?.[field];
3558
3576
  const sanitized = value ? stripContentBlockHtml(normalizeTokens(value)) : "";
3559
3577
  return sanitized ? [[field, sanitized]] : [];
3560
3578
  })
@@ -3651,7 +3669,7 @@ var coerceIntegrations = (integrations) => Object.fromEntries(
3651
3669
  return [key, value];
3652
3670
  })
3653
3671
  );
3654
- var buildBanner = (language2) => language2?.successBannerEnabled ? [
3672
+ var buildBanner = (language3) => language3?.successBannerEnabled ? [
3655
3673
  {
3656
3674
  /**
3657
3675
  * The banner-level tag is the extraction/routing key on BOTH renderers (React CAB's
@@ -3664,7 +3682,7 @@ var buildBanner = (language2) => language2?.successBannerEnabled ? [
3664
3682
  dismissible: true,
3665
3683
  sections: [
3666
3684
  {
3667
- content: bannerMessageContent(language2.successBannerMessageRte),
3685
+ content: bannerMessageContent(language3.successBannerMessageRte),
3668
3686
  sectionType: "text"
3669
3687
  },
3670
3688
  {
@@ -3981,14 +3999,14 @@ var convertCalloutBlock = (raw, report) => {
3981
3999
  };
3982
4000
  const shell = Shell.safeParse(raw);
3983
4001
  if (!shell.success) return omit("Unreadable post-purchase callout");
3984
- const values = fields.map((field) => ({
4002
+ const values2 = fields.map((field) => ({
3985
4003
  field,
3986
4004
  result: CalloutBannerBlock.shape.settings.shape[field].safeParse(shell.data.settings[field])
3987
4005
  }));
3988
- const styled2 = values.every(({ result }) => result.success && typeof result.data === "string");
4006
+ const styled2 = values2.every(({ result }) => result.success && typeof result.data === "string");
3989
4007
  const styles2 = shell.data.styles;
3990
4008
  const horizontal = styled2 ? { center: "center", leading: "start", trailing: "end" }[styles2.textAlignment] : "center";
3991
- const sections = values.flatMap(({ field, result }) => {
4009
+ const sections = values2.flatMap(({ field, result }) => {
3992
4010
  if (!result.success) return omit(`Unreadable post-purchase callout field: ${field}`);
3993
4011
  const text2 = result.data;
3994
4012
  if (text2 === "") return [];
@@ -4010,12 +4028,12 @@ var convertCalloutBlock = (raw, report) => {
4010
4028
  var import_zod32 = require("zod");
4011
4029
 
4012
4030
  // src/transforms/postPurchase/sizeImageSource.ts
4013
- var sizeImageSource = (source, size) => {
4014
- const extension = source.split(".").pop();
4031
+ var sizeImageSource = (source2, size) => {
4032
+ const extension = source2.split(".").pop();
4015
4033
  for (const previous of ["small", "medium", "large", "original", "master"]) {
4016
- source = source.replace(`_${previous}.${extension}`, `.${extension}`);
4034
+ source2 = source2.replace(`_${previous}.${extension}`, `.${extension}`);
4017
4035
  }
4018
- return source.replace(`.${extension}`, `${size === void 0 ? "" : `_${size}`}.${extension}`);
4036
+ return source2.replace(`.${extension}`, `${size === void 0 ? "" : `_${size}`}.${extension}`);
4019
4037
  };
4020
4038
 
4021
4039
  // src/transforms/postPurchase/convertImageFrame.ts
@@ -4025,9 +4043,9 @@ var convertImageFrame = (raw) => {
4025
4043
  const parsed = ImageBlock.shape.settings.options[0].safeParse(raw);
4026
4044
  if (!parsed.success) return null;
4027
4045
  const settings = parsed.data;
4028
- const source = sizeImageSource(Source.parse(settings.image || void 0));
4029
- const withAlt = CABImageSection.safeParse({ altText: settings.alt, source });
4030
- const image = withAlt.success ? withAlt.data : CABImageSection.parse({ source });
4046
+ const source2 = sizeImageSource(Source.parse(settings.image || void 0));
4047
+ const withAlt = CABImageSection.safeParse({ altText: settings.alt, source: source2 });
4048
+ const image = withAlt.success ? withAlt.data : CABImageSection.parse({ source: source2 });
4031
4049
  const size = settings.imageSize > 0 ? settings.imageSize : DEFAULT_IMAGE_SIZE;
4032
4050
  return CABLayoutSection.parse({
4033
4051
  alignment: { horizontal: "center" },
@@ -4264,19 +4282,19 @@ var convertTextBlock = (raw, report) => {
4264
4282
  report?.({ detail: "Unreadable post-purchase text block", kind: "section" });
4265
4283
  return [];
4266
4284
  }
4267
- const values = fields3.map((field) => ({
4285
+ const values2 = fields3.map((field) => ({
4268
4286
  field,
4269
4287
  result: settingsSchema.shape[field].safeParse(shell.data.settings[field])
4270
4288
  }));
4271
4289
  const horizontal = { center: "center", leading: "start", trailing: "end" }[shell.data.settings.horizontalAlignment];
4272
- const styled2 = values.every(
4290
+ const styled2 = values2.every(
4273
4291
  ({ result }) => result.success && (result.data === null || typeof result.data === "string")
4274
4292
  );
4275
4293
  const omit = (field) => {
4276
4294
  report?.({ detail: `Unreadable post-purchase text field: ${field}`, kind: "section" });
4277
4295
  return [];
4278
4296
  };
4279
- const sections = values.flatMap(({ field, result }) => {
4297
+ const sections = values2.flatMap(({ field, result }) => {
4280
4298
  if (!result.success) return omit(field);
4281
4299
  const text2 = result.data;
4282
4300
  if (text2 === null || text2 === "") return [];
@@ -4510,10 +4528,10 @@ var giftOf = (tier) => {
4510
4528
  if (tier.type !== "product") return void 0;
4511
4529
  const product = tier.products?.[0] ?? tier.allProducts?.[0];
4512
4530
  if (!product) return void 0;
4513
- const productId = product.productId ?? product.id;
4514
- if (productId === void 0) return void 0;
4531
+ const productId2 = product.productId ?? product.id;
4532
+ if (productId2 === void 0) return void 0;
4515
4533
  return {
4516
- productId,
4534
+ productId: productId2,
4517
4535
  title: product.title,
4518
4536
  variantIds: positiveIds(product.variantIds)
4519
4537
  };
@@ -4792,14 +4810,14 @@ function serialize(obj) {
4792
4810
  var encodeAttributes = (pairs = []) => JSON.stringify(Object.fromEntries(pairs.map(({ key, value }) => [key, value ?? ""])));
4793
4811
  var buildEngineParams = (input, key) => {
4794
4812
  const { cart, customerId, filterInputs, integrations, limit, productType, shop, visitorId } = input;
4795
- const items = cart.items.map(({ productId, properties, quantity, subscriptionId, variantId }) => ({
4796
- product_id: productId,
4813
+ const items = cart.items.map(({ productId: productId2, properties, quantity: quantity2, subscriptionId, variantId }) => ({
4814
+ product_id: productId2,
4797
4815
  properties: encodeAttributes(properties),
4798
- quantity,
4816
+ quantity: quantity2,
4799
4817
  ...subscriptionId && { subscription_id: subscriptionId },
4800
4818
  variant_id: variantId
4801
4819
  }));
4802
- const itemCount = cart.items.reduce((total, { quantity }) => total + quantity, 0);
4820
+ const itemCount = cart.items.reduce((total, { quantity: quantity2 }) => total + quantity2, 0);
4803
4821
  const subtotal = shopSubtotalCents(cart);
4804
4822
  return {
4805
4823
  cart: {
@@ -4886,13 +4904,13 @@ var OFFER_LIMIT = 4;
4886
4904
  var SUPPORTED_COUNTRIES = /* @__PURE__ */ new Set(["US", "CA", "GB"]);
4887
4905
  var MAX_TRANSACTION_ITEMS = 50;
4888
4906
  var TEST_CUSTOMER_EMAIL = "test@rebuyengine.com";
4889
- var transactionItems = (input) => (input.transactionItems?.map(({ id, priceCents, quantity, title, type }) => ({
4907
+ var transactionItems = (input) => (input.transactionItems?.map(({ id, priceCents, quantity: quantity2, title, type }) => ({
4890
4908
  id,
4891
4909
  price_cents: priceCents,
4892
- quantity,
4910
+ quantity: quantity2,
4893
4911
  title,
4894
4912
  type
4895
- })) ?? input.cart.items.map(({ productId, quantity }) => ({ id: productId, quantity }))).slice(0, MAX_TRANSACTION_ITEMS);
4913
+ })) ?? input.cart.items.map(({ productId: productId2, quantity: quantity2 }) => ({ id: productId2, quantity: quantity2 }))).slice(0, MAX_TRANSACTION_ITEMS);
4896
4914
  var AdsEngineOffer = import_zod37.z.object({
4897
4915
  /** Pill-style value prop ("Get $45 Cashback"). Carried through the parse; the card does not render it yet (REB-24429 — pill design pending). */
4898
4916
  callout: import_zod37.z.string().catch(""),
@@ -5010,9 +5028,9 @@ var label = (text2) => ({
5010
5028
  });
5011
5029
  var text = (content) => ({ content: { en: content }, sectionType: SectionType.text });
5012
5030
  var AS_DOC = { defaultTextStyle: {} };
5013
- var safeTextValue = (raw, options) => {
5014
- const converted = normalizeTextValue(raw, options);
5015
- return checkForHTML(converted) ? converted : normalizeTextValue(htmlToPlainText(raw), options);
5031
+ var safeTextValue = (raw, options2) => {
5032
+ const converted = normalizeTextValue(raw, options2);
5033
+ return checkForHTML(converted) ? converted : normalizeTextValue(htmlToPlainText(raw), options2);
5016
5034
  };
5017
5035
  var headlineText = (raw) => {
5018
5036
  const doc = safeTextValue(raw, AS_DOC);
@@ -5496,11 +5514,11 @@ var validateGifts = async (input, ctx) => {
5496
5514
  const [remove, adjust] = await Promise.all([validateGwpGifts(input, ctx), validateSelectableGifts(input, ctx)]);
5497
5515
  const removed = new Set(remove);
5498
5516
  const targets = /* @__PURE__ */ new Map();
5499
- for (const { lineId, quantity } of adjust) {
5517
+ for (const { lineId, quantity: quantity2 } of adjust) {
5500
5518
  if (removed.has(lineId)) continue;
5501
- targets.set(lineId, Math.min(quantity, targets.get(lineId) ?? quantity));
5519
+ targets.set(lineId, Math.min(quantity2, targets.get(lineId) ?? quantity2));
5502
5520
  }
5503
- return { adjust: [...targets].map(([lineId, quantity]) => ({ lineId, quantity })), remove: [...removed] };
5521
+ return { adjust: [...targets].map(([lineId, quantity2]) => ({ lineId, quantity: quantity2 })), remove: [...removed] };
5504
5522
  };
5505
5523
 
5506
5524
  // src/server/normalizePostPurchaseProduct.ts
@@ -5832,14 +5850,14 @@ var SourceAdjustment = import_zod47.z.object({
5832
5850
  type: import_zod47.z.enum(["percentage", "fixed_amount", "amount", "price", "none", "fixed"])
5833
5851
  });
5834
5852
  var readPostPurchasePlanAdjustment = (raw) => {
5835
- const source = SourceAdjustment.parse(raw);
5836
- if (source.type === "none" || source.type === "fixed") {
5837
- if (source.amount !== 0) throw new Error("Unsupported plan adjustment");
5853
+ const source2 = SourceAdjustment.parse(raw);
5854
+ if (source2.type === "none" || source2.type === "fixed") {
5855
+ if (source2.amount !== 0) throw new Error("Unsupported plan adjustment");
5838
5856
  return void 0;
5839
5857
  }
5840
5858
  const adjustment = PostPurchasePlanAdjustment.parse({
5841
- amount: source.amount,
5842
- type: source.type === "amount" ? "fixed_amount" : source.type
5859
+ amount: source2.amount,
5860
+ type: source2.type === "amount" ? "fixed_amount" : source2.type
5843
5861
  });
5844
5862
  return adjustment.amount === 0 && adjustment.type !== "price" ? void 0 : adjustment;
5845
5863
  };
@@ -5916,12 +5934,12 @@ var projectPostPurchasePlanCatalog = (normalized, report) => {
5916
5934
  const { data } = normalized;
5917
5935
  if (data.length !== 1 || data[0].variants.length !== 1) throw new Error("Ambiguous product");
5918
5936
  const product = data[0];
5919
- const variant = product.variants[0];
5920
- if (variant.productId !== product.id) throw new Error("Foreign variant");
5937
+ const variant2 = product.variants[0];
5938
+ if (variant2.productId !== product.id) throw new Error("Foreign variant");
5921
5939
  const groups = product.sellingPlanGroups;
5922
5940
  const required = groups.map((group) => group.requiresSellingPlan);
5923
5941
  if (required.some((flag) => flag !== required[0])) throw new Error("Conflicting requirement");
5924
- const plans = typeof groups[0]?.id === "number" ? readPostPurchaseLegacyPlans(groups[0], variant.id) : readPostPurchaseModernPlans(groups, variant.sellingPlanAllocations);
5942
+ const plans = typeof groups[0]?.id === "number" ? readPostPurchaseLegacyPlans(groups[0], variant2.id) : readPostPurchaseModernPlans(groups, variant2.sellingPlanAllocations);
5925
5943
  const unique = /* @__PURE__ */ new Map();
5926
5944
  for (const plan of plans) {
5927
5945
  const previous = unique.get(plan.id);
@@ -5932,7 +5950,7 @@ var projectPostPurchasePlanCatalog = (normalized, report) => {
5932
5950
  plans: [...unique.values()],
5933
5951
  productId: product.id,
5934
5952
  requiresSellingPlan: required[0] ?? false,
5935
- variantId: variant.id
5953
+ variantId: variant2.id
5936
5954
  });
5937
5955
  } catch {
5938
5956
  report?.({ detail: "Unreadable post-purchase plan catalog", kind: "product" });
@@ -5969,14 +5987,10 @@ var PostPurchasePrimaryImageSource = import_zod51.z.string().default(
5969
5987
  "https://cdn.shopify.com/shopifycloud/shopify/assets/no-image-2048-5e88c1b20e087fb7bbe9a3771824e743c244f437e4f8ba93bbf7b11b53f7824c.gif"
5970
5988
  );
5971
5989
  var PostPurchaseProductDisplay = import_zod51.z.object({
5990
+ descriptionDocument: TiptapDocument.optional(),
5972
5991
  discountedFrom: PostPurchaseSettings.shape.discountedFrom,
5973
5992
  gallery: PostPurchaseProductGallery.optional(),
5974
- language: language.pick({
5975
- description: true,
5976
- descriptionEnabled: true,
5977
- descriptionRte: true,
5978
- descriptionSpacing: true
5979
- }),
5993
+ language: language.pick({ description: true, descriptionEnabled: true }),
5980
5994
  primaryImage: import_zod51.z.object({ description: import_zod51.z.string(), source: import_zod51.z.string() }),
5981
5995
  productOptions: PostPurchaseSettings.shape.productOptions.pick({
5982
5996
  showDeclineAll: true,
@@ -6072,20 +6086,20 @@ var PostPurchaseSubscriptionSettings = subscription.extend({
6072
6086
  });
6073
6087
 
6074
6088
  // src/server/postPurchaseVariantAvailable.ts
6075
- var postPurchaseVariantAvailable = (variant) => !(variant.inventoryManagement && variant.inventoryPolicy === "deny" && variant.inventoryQuantity <= 0);
6089
+ var postPurchaseVariantAvailable = (variant2) => !(variant2.inventoryManagement && variant2.inventoryPolicy === "deny" && variant2.inventoryQuantity <= 0);
6076
6090
 
6077
6091
  // src/server/postPurchaseSubscriptionEligibility.ts
6078
- var subscriptionUnavailable = (normalized, plan, allowCollection, quantity) => {
6092
+ var subscriptionUnavailable = (normalized, plan, allowCollection, quantity2) => {
6079
6093
  const { data, effective, original } = normalized;
6080
6094
  const unavailable = "An eligible subscription plan with supported shipping and discount is required";
6081
6095
  if (data.length !== 1 || data[0].variants.length !== 1) return unavailable;
6082
6096
  if (effective.productType === "one-time" || [original, effective].some(
6083
- (config) => !allowCollection && config.productLimit !== 1 || config.upgradeToSubscription.allow || !quantity && config.quantityInputs.enabled && (config.quantityInputs.minValue !== config.quantityInputs.maxValue || config.quantityInputs.defaultQuantity !== config.quantityInputs.minValue)
6097
+ (config) => !allowCollection && config.productLimit !== 1 || config.upgradeToSubscription.allow || !quantity2 && config.quantityInputs.enabled && (config.quantityInputs.minValue !== config.quantityInputs.maxValue || config.quantityInputs.defaultQuantity !== config.quantityInputs.minValue)
6084
6098
  ))
6085
6099
  return unavailable;
6086
6100
  const product = data[0];
6087
- const variant = product.variants[0];
6088
- if (product.productGroupVariants.length || !postPurchaseVariantAvailable(variant) || variant.productId !== product.id)
6101
+ const variant2 = product.variants[0];
6102
+ if (product.productGroupVariants.length || !postPurchaseVariantAvailable(variant2) || variant2.productId !== product.id)
6089
6103
  return unavailable;
6090
6104
  const terms = [original, effective].map(
6091
6105
  (config) => PostPurchaseSubscriptionSettings.safeParse(config.subscription)
@@ -6094,14 +6108,14 @@ var subscriptionUnavailable = (normalized, plan, allowCollection, quantity) => {
6094
6108
  };
6095
6109
 
6096
6110
  // src/server/postPurchaseProductDisplay.ts
6097
- var import_zod55 = require("zod");
6111
+ var import_zod56 = require("zod");
6098
6112
 
6099
6113
  // src/server/postPurchasePrimaryImage.ts
6100
6114
  var postPurchasePrimaryImage = (product) => {
6101
6115
  const variantImageId = product.variants[0].imageId;
6102
6116
  const selectedImage = variantImageId ? product.images?.find((image) => image.id === variantImageId) : void 0;
6103
- const source = PostPurchasePrimaryImageSource.parse((selectedImage ?? product.image)?.src || void 0);
6104
- return { description: product.title, source: sizeImageSource(source, "800x800") };
6117
+ const source2 = PostPurchasePrimaryImageSource.parse((selectedImage ?? product.image)?.src || void 0);
6118
+ return { description: product.title, source: sizeImageSource(source2, "800x800") };
6105
6119
  };
6106
6120
 
6107
6121
  // src/server/postPurchaseProductGallery.ts
@@ -6115,9 +6129,67 @@ var postPurchaseProductGallery = (product, limit) => ({
6115
6129
  selectedImageId: product.images?.find((image) => image.id === product.variants[0].imageId)?.id
6116
6130
  });
6117
6131
 
6132
+ // src/transforms/postPurchase/convertDescriptionRte.ts
6133
+ var import_zod55 = require("zod");
6134
+ var alignments = { center: "center", left: "start", right: "end" };
6135
+ var colors = ["critical", "subdued", "success", "warning"];
6136
+ var sizes2 = ["extraSmall", "small", "medium", "large", "extraLarge"];
6137
+ var spacings2 = {
6138
+ default: "base",
6139
+ loose: "loose",
6140
+ none: "none",
6141
+ tight: "tight",
6142
+ xloose: "extraLoose",
6143
+ xtight: "extraTight"
6144
+ };
6145
+ var Block = import_zod55.z.object({
6146
+ attrs: import_zod55.z.object({ alignment: import_zod55.z.enum(["left", "center", "right"]).optional().catch(void 0) }).catch({}),
6147
+ content: import_zod55.z.array(import_zod55.z.unknown()).catch([]),
6148
+ type: import_zod55.z.literal("ShopifyTextBlock")
6149
+ });
6150
+ var Run = import_zod55.z.object({ marks: import_zod55.z.array(import_zod55.z.unknown()).catch([]), text: import_zod55.z.string().min(1), type: import_zod55.z.literal("text") });
6151
+ var Inline = import_zod55.z.object({
6152
+ attrs: import_zod55.z.object({
6153
+ color: import_zod55.z.enum(colors).optional().catch(void 0),
6154
+ emphasis: import_zod55.z.array(import_zod55.z.unknown()).catch([]),
6155
+ size: import_zod55.z.enum(sizes2).optional().catch(void 0)
6156
+ }),
6157
+ type: import_zod55.z.literal("ShopifyTextInline")
6158
+ });
6159
+ var marks = (raw) => {
6160
+ const found = raw.map((mark) => Inline.safeParse(mark)).find(({ success }) => success)?.data;
6161
+ if (!found) return [];
6162
+ const { color = "base", emphasis, size = "base" } = found.attrs;
6163
+ return [
6164
+ ...emphasis.includes("bold") ? [{ type: "bold" }] : [],
6165
+ ...emphasis.includes("strikethrough") ? [{ type: "strike" }] : [],
6166
+ { attrs: { color, fontSize: size }, type: "textStyle" }
6167
+ ];
6168
+ };
6169
+ var convertDescriptionRte = (rte, spacing) => TiptapDocument.parse({
6170
+ attrs: { blockSpacing: spacings2[spacing ?? "none"] },
6171
+ content: rte.content.flatMap((node) => {
6172
+ const block = Block.safeParse(node);
6173
+ if (!block.success) return [];
6174
+ const { alignment } = block.data.attrs;
6175
+ return [
6176
+ {
6177
+ attrs: { textAlign: alignment ? alignments[alignment] : "start" },
6178
+ content: block.data.content.flatMap((inline) => {
6179
+ const run = Run.safeParse(inline);
6180
+ return run.success ? [{ marks: marks(run.data.marks), text: run.data.text }] : [];
6181
+ }),
6182
+ type: "paragraph"
6183
+ }
6184
+ ];
6185
+ }),
6186
+ type: "doc"
6187
+ });
6188
+
6118
6189
  // src/server/postPurchaseProductDisplay.ts
6119
- var ResponseLanguage = import_zod55.z.object({ description: PostPurchaseProductDisplay.shape.responseDescription }).default({ description: "" });
6190
+ var ResponseLanguage = import_zod56.z.object({ description: PostPurchaseProductDisplay.shape.responseDescription }).default({ description: "" });
6120
6191
  var projectPostPurchaseProductDisplay = (effective, metadata, product) => PostPurchaseProductDisplay.parse({
6192
+ descriptionDocument: effective.language.descriptionRte && convertDescriptionRte(effective.language.descriptionRte, effective.language.descriptionSpacing),
6121
6193
  discountedFrom: effective.discountedFrom,
6122
6194
  gallery: postPurchaseProductGallery(product, effective.subImages),
6123
6195
  language: effective.language,
@@ -6130,26 +6202,26 @@ var projectPostPurchaseProductDisplay = (effective, metadata, product) => PostPu
6130
6202
  // src/server/projectPostPurchaseProduct.ts
6131
6203
  var projectPostPurchaseProduct = ({ data, effective, metadata, original }, selectedQuantity) => {
6132
6204
  const product = data[0];
6133
- const variant = product.variants[0];
6205
+ const variant2 = product.variants[0];
6134
6206
  return {
6135
6207
  display: projectPostPurchaseProductDisplay(effective, metadata, product),
6136
6208
  labels: effective.language.global,
6137
- product: { ...product, variant },
6209
+ product: { ...product, variant: variant2 },
6138
6210
  selection: {
6139
6211
  productId: product.id,
6140
6212
  quantity: selectedQuantity?.quantity ?? product.metadata?.productQuantity ?? (original.quantityInputs.enabled ? original.quantityInputs.defaultQuantity : 1),
6141
- variantId: variant.id
6213
+ variantId: variant2.id
6142
6214
  }
6143
6215
  };
6144
6216
  };
6145
6217
 
6146
6218
  // src/server/prepareNormalizedSubscription.ts
6147
- var prepareNormalizedSubscription = (normalized, report, plan, quantity, allowCollection = false) => {
6219
+ var prepareNormalizedSubscription = (normalized, report, plan, quantity2, allowCollection = false) => {
6148
6220
  if (!plan) return { reason: "Subscription plan is unavailable", status: "unsupported" };
6149
- const reason = subscriptionUnavailable(normalized, plan, allowCollection, quantity);
6221
+ const reason = subscriptionUnavailable(normalized, plan, allowCollection, quantity2);
6150
6222
  if (reason) return { reason, status: "unsupported" };
6151
6223
  const { effective } = normalized;
6152
- const projected = projectPostPurchaseProduct(normalized, quantity);
6224
+ const projected = projectPostPurchaseProduct(normalized, quantity2);
6153
6225
  const { discount, shipping } = PostPurchaseSubscriptionSettings.parse(effective.subscription);
6154
6226
  const shippingPrice = shipping.type === "free" ? 0 : shipping.amount;
6155
6227
  return PreparedPostPurchaseSubscription.parse({
@@ -6186,6 +6258,855 @@ var preparePostPurchaseSubscription = (settings, response, report) => {
6186
6258
  );
6187
6259
  };
6188
6260
 
6261
+ // src/server/postPurchaseProductEligibility.ts
6262
+ var oneTimeUnavailable = (normalized, allowCollection, quantity2) => {
6263
+ const { data, effective, original } = normalized;
6264
+ if (data.length !== 1 || data[0].variants.length !== 1) return "Only one fixed product and variant are supported";
6265
+ if (effective.productType === "subscription" || [original, effective].some(
6266
+ (config) => !allowCollection && config.productLimit !== 1 || config.upgradeToSubscription.allow || !quantity2 && config.quantityInputs.enabled && (config.quantityInputs.minValue !== config.quantityInputs.maxValue || config.quantityInputs.defaultQuantity !== config.quantityInputs.minValue)
6267
+ ))
6268
+ return "Only fixed one-time configuration is supported";
6269
+ const product = data[0];
6270
+ const variant2 = product.variants[0];
6271
+ if (product.productGroupVariants.length || product.sellingPlanGroups?.some((group) => group.requiresSellingPlan) || !postPurchaseVariantAvailable(variant2))
6272
+ return "An available one-time variant without product groups is required";
6273
+ if (variant2.productId !== product.id) throw new Error("Product variant identity mismatch");
6274
+ };
6275
+
6276
+ // src/server/preparePostPurchaseProduct.ts
6277
+ var prepareNormalizedProduct = (normalized, report, quantity2, allowCollection = false) => {
6278
+ const reason = oneTimeUnavailable(normalized, allowCollection, quantity2);
6279
+ if (reason) return { reason, status: "unsupported" };
6280
+ const { effective } = normalized;
6281
+ return PreparedPostPurchaseProduct.parse({
6282
+ ...projectPostPurchaseProduct(normalized, quantity2),
6283
+ status: "prepared",
6284
+ terms: {
6285
+ discount: { ...effective.discount, title: effective.language.global.save },
6286
+ shipping: effective.shipping
6287
+ }
6288
+ });
6289
+ };
6290
+ var preparePostPurchaseProduct = (settings, response, report) => prepareNormalizedProduct(normalizePostPurchaseProduct(settings, response), report);
6291
+
6292
+ // src/schema/postPurchaseProductView.ts
6293
+ var import_zod60 = require("zod");
6294
+
6295
+ // src/schema/postPurchaseChoice.ts
6296
+ var import_zod57 = require("zod");
6297
+ var PostPurchaseChoice = import_zod57.z.discriminatedUnion("mode", [
6298
+ import_zod57.z.object({ mode: import_zod57.z.literal("one-time") }).strict(),
6299
+ import_zod57.z.object({ mode: import_zod57.z.literal("subscription"), sellingPlanId: PostPurchasePlanOption.shape.id }).strict()
6300
+ ]);
6301
+ var PostPurchaseOptions = import_zod57.z.object({
6302
+ defaultChoice: PostPurchaseChoice,
6303
+ modes: import_zod57.z.array(import_zod57.z.enum(["one-time", "subscription"])).min(1).max(2),
6304
+ selector: PostPurchaseSettings.shape.productTypeSelector
6305
+ });
6306
+
6307
+ // src/schema/postPurchaseGroupCatalog.ts
6308
+ var import_zod59 = require("zod");
6309
+
6310
+ // src/schema/postPurchaseVariantCatalog.ts
6311
+ var import_zod58 = require("zod");
6312
+ var PostPurchaseVariantSelector = import_zod58.z.object({ variantId: PostPurchaseVariantId }).strict();
6313
+ var PostPurchaseVariantOption = OfferProduct.shape.options.element.extend({
6314
+ id: import_zod58.z.number().int().positive(),
6315
+ position: import_zod58.z.number().int().min(1).max(3)
6316
+ });
6317
+ var PostPurchaseVariantValues = OfferProduct.shape.variants.element.pick({
6318
+ option1: true,
6319
+ option2: true,
6320
+ option3: true
6321
+ });
6322
+ var PostPurchaseVariantCatalog = import_zod58.z.object({
6323
+ displayMode: PostPurchaseSettings.shape.productOptions.shape.variantSelectorDisplayMode,
6324
+ options: import_zod58.z.array(PostPurchaseVariantOption),
6325
+ productId: PostPurchaseProductId,
6326
+ showSelectors: PostPurchaseSettings.shape.productOptions.shape.showVariantSelectors,
6327
+ variants: import_zod58.z.array(
6328
+ PostPurchaseVariantValues.partial().extend({
6329
+ available: import_zod58.z.boolean(),
6330
+ id: PostPurchaseVariantId,
6331
+ imageId: import_zod58.z.number().int().nonnegative().nullish(),
6332
+ title: OfferProduct.shape.variants.element.shape.title
6333
+ })
6334
+ )
6335
+ });
6336
+
6337
+ // src/schema/postPurchaseGroupCatalog.ts
6338
+ var productId = PreparedPostPurchaseProduct.shape.selection.shape.productId;
6339
+ var source = PostPurchaseProductSource.shape.data.element;
6340
+ var PostPurchaseGroupDescription = source.pick({ description: true, id: true, image: true, images: true, title: true }).extend({
6341
+ description: source.shape.description.default(null),
6342
+ image: source.shape.image.default(null),
6343
+ options: PostPurchaseVariantCatalog.shape.options.default([])
6344
+ });
6345
+ var PostPurchaseGroupCatalog = import_zod59.z.object({
6346
+ memberProductId: productId,
6347
+ options: import_zod59.z.array(import_zod59.z.object({ productId, title: import_zod59.z.string(), variantCatalog: PostPurchaseVariantCatalog }))
6348
+ });
6349
+ var PostPurchaseGroupSelection = import_zod59.z.object({
6350
+ memberProductId: productId,
6351
+ productId
6352
+ });
6353
+
6354
+ // src/schema/postPurchaseProductView.ts
6355
+ var PostPurchaseProductView = import_zod60.z.union([
6356
+ import_zod60.z.object({
6357
+ groupCatalog: PostPurchaseGroupCatalog.optional(),
6358
+ initialVariant: PostPurchaseVariantSelector.optional(),
6359
+ planCatalog: PostPurchasePlanCatalog.nullable().optional(),
6360
+ preparation: PreparedPostPurchaseProduct.extend({
6361
+ display: PreparedPostPurchaseProduct.shape.display.extend({ description: import_zod60.z.string().nullable() }).refine(
6362
+ ({ description, descriptionDocument }) => description === null === (descriptionDocument !== void 0),
6363
+ "Exactly one of the plain and rich descriptions is shown"
6364
+ )
6365
+ }),
6366
+ purchaseOptions: PostPurchaseOptions.optional(),
6367
+ sections: CABRootSection,
6368
+ variantCatalog: PostPurchaseVariantCatalog.optional()
6369
+ }),
6370
+ import_zod60.z.object({
6371
+ groupCatalog: PostPurchaseGroupCatalog.optional(),
6372
+ initialVariant: PostPurchaseVariantSelector.optional(),
6373
+ planCatalog: PostPurchasePlanCatalog.nullable().optional(),
6374
+ preparation: PostPurchasePreparation.options[1],
6375
+ purchaseOptions: PostPurchaseOptions.optional(),
6376
+ sections: import_zod60.z.null(),
6377
+ variantCatalog: PostPurchaseVariantCatalog.optional()
6378
+ })
6379
+ ]);
6380
+
6381
+ // src/server/postPurchaseOfferCopy.ts
6382
+ var import_zod61 = require("zod");
6383
+ var Copy = import_zod61.z.object({
6384
+ superTitle: CalloutBannerBlock.shape.settings.shape.superTitle.unwrap().optional().catch(void 0),
6385
+ title: CalloutBannerBlock.shape.settings.shape.title.unwrap().optional().catch(void 0)
6386
+ });
6387
+ var Callout = import_zod61.z.object({ settings: import_zod61.z.record(import_zod61.z.string(), import_zod61.z.unknown()), type: import_zod61.z.literal("callout_banner") });
6388
+ var postPurchaseOfferCopy = (blocks, metadata) => {
6389
+ const copy = Copy.safeParse(metadata.widget.language);
6390
+ if (!blocks || !copy.success) return blocks;
6391
+ const first = blocks.findIndex((block) => Callout.pick({ type: true }).safeParse(block).success);
6392
+ return blocks.map((block, index) => {
6393
+ if (index !== first) return block;
6394
+ const callout = Callout.passthrough().safeParse(block);
6395
+ if (!callout.success) return block;
6396
+ return {
6397
+ ...callout.data,
6398
+ settings: {
6399
+ ...callout.data.settings,
6400
+ ...copy.data.title && { title: copy.data.title },
6401
+ ...copy.data.superTitle && { superTitle: copy.data.superTitle }
6402
+ }
6403
+ };
6404
+ });
6405
+ };
6406
+
6407
+ // src/server/selectPostPurchaseChoice.ts
6408
+ var selectPostPurchaseChoice = (normalized, projected, requested, allowCollection, quantity2) => {
6409
+ const { data, effective } = normalized;
6410
+ const modes = [];
6411
+ const catalog = projected && projected.productId === data[0]?.id && projected.variantId === data[0].variants[0]?.id ? projected : null;
6412
+ const firstPlan = catalog?.plans[0];
6413
+ const oneTimeReason = oneTimeUnavailable(normalized, allowCollection, quantity2);
6414
+ const subscriptionReason = subscriptionUnavailable(normalized, firstPlan, allowCollection, quantity2);
6415
+ if (!oneTimeReason) modes.push("one-time");
6416
+ if (!subscriptionReason) modes.push("subscription");
6417
+ if (oneTimeReason && subscriptionReason)
6418
+ return {
6419
+ choice: void 0,
6420
+ options: void 0,
6421
+ plan: void 0,
6422
+ reason: effective.productType === "one-time" ? oneTimeReason : subscriptionReason
6423
+ };
6424
+ const defaultChoice = firstPlan && modes.includes("subscription") && (modes[0] === "subscription" || effective.subscriptionIsDefault) ? { mode: "subscription", sellingPlanId: firstPlan.id } : { mode: "one-time" };
6425
+ const options2 = PostPurchaseOptions.parse({ defaultChoice, modes, selector: effective.productTypeSelector });
6426
+ const choice = requested ?? defaultChoice;
6427
+ const plan = choice.mode === "subscription" ? catalog?.plans.find(({ id }) => id === choice.sellingPlanId) : void 0;
6428
+ const bound = modes.includes(choice.mode) && (choice.mode === "one-time" || plan) ? choice : void 0;
6429
+ return {
6430
+ choice: bound,
6431
+ options: options2,
6432
+ plan: bound ? plan : void 0,
6433
+ reason: bound ? void 0 : "Requested purchase choice is unavailable"
6434
+ };
6435
+ };
6436
+
6437
+ // src/server/preparePostPurchaseView.ts
6438
+ var resolveDescription = ({ descriptionDocument, ...display }, productDescription) => {
6439
+ const plain = display.language.descriptionEnabled && productDescription || display.responseDescription || (descriptionDocument ? null : display.language.description);
6440
+ return plain === null ? { ...display, description: null, descriptionDocument } : { ...display, description: plain };
6441
+ };
6442
+ var prepareNormalizedPostPurchaseView = (widgetId, normalized, report, choice, quantity2, allowCollection = false) => {
6443
+ const planCatalog = projectPostPurchasePlanCatalog(normalized, report);
6444
+ const selected = selectPostPurchaseChoice(normalized, planCatalog, choice, allowCollection, quantity2);
6445
+ const purchaseOptions = selected.options;
6446
+ 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);
6447
+ const unsupported = (reason) => ({
6448
+ planCatalog,
6449
+ preparation: { reason, status: "unsupported" },
6450
+ purchaseOptions,
6451
+ sections: null
6452
+ });
6453
+ if (preparation.status === "unsupported") return { planCatalog, preparation, purchaseOptions, sections: null };
6454
+ if (!normalized.effective.blocks?.length) return unsupported("One fixed product information block is required");
6455
+ const sections = convertMessagePreview(
6456
+ widgetId,
6457
+ {
6458
+ blocks: postPurchaseOfferCopy(normalized.effective.blocks, normalized.metadata),
6459
+ type: "shopify_post_purchase_extension"
6460
+ },
6461
+ report
6462
+ );
6463
+ if (sections.sections.filter((section) => section.sectionType === "offers").length !== 1)
6464
+ return unsupported("One fixed product information block is required");
6465
+ return PostPurchaseProductView.parse({
6466
+ planCatalog,
6467
+ preparation: {
6468
+ ...preparation,
6469
+ display: resolveDescription(preparation.display, preparation.product.description)
6470
+ },
6471
+ purchaseOptions,
6472
+ sections
6473
+ });
6474
+ };
6475
+ var preparePostPurchaseView = (widgetId, settings, response, report, choice) => prepareNormalizedPostPurchaseView(widgetId, normalizePostPurchaseProduct(settings, response), report, choice);
6476
+
6477
+ // src/server/preparePostPurchaseAdmissionView.ts
6478
+ var preparePostPurchaseAdmissionView = (widgetId, settings, response, report, choice) => {
6479
+ const normalized = normalizePostPurchaseProduct(settings, response);
6480
+ const view = prepareNormalizedPostPurchaseView(widgetId, normalized, report, choice);
6481
+ const { removePartialOrder } = PostPurchaseSettings.shape.advance.parse(normalized.effective.advance);
6482
+ return { removePartialOrder, view };
6483
+ };
6484
+
6485
+ // src/schema/postPurchaseProductCollectionView.ts
6486
+ var import_zod62 = require("zod");
6487
+ var PostPurchaseProductCollectionView = import_zod62.z.object({
6488
+ members: import_zod62.z.array(
6489
+ import_zod62.z.object({
6490
+ productId: PostPurchaseProductId,
6491
+ productIndex: import_zod62.z.number().int().nonnegative(),
6492
+ view: PostPurchaseProductView
6493
+ })
6494
+ )
6495
+ });
6496
+ var PostPurchaseCollectionChoice = import_zod62.z.object({
6497
+ choice: PostPurchaseChoice.optional(),
6498
+ productId: PostPurchaseProductId,
6499
+ variantId: PostPurchaseVariantSelector.shape.variantId.optional()
6500
+ }).strict();
6501
+ var PostPurchaseExcludedProductIds = import_zod62.z.array(PostPurchaseProductId).default([]);
6502
+
6503
+ // src/server/normalizePostPurchaseCollection.ts
6504
+ var import_zod63 = require("zod");
6505
+ var normalizePostPurchaseCollection = (settings, response, excludedProductIds) => {
6506
+ const normalized = normalizePostPurchaseProduct(settings, response);
6507
+ const limit = import_zod63.z.number().int().positive();
6508
+ limit.parse(normalized.original.productLimit);
6509
+ const prefix = normalized.data.slice(0, limit.parse(normalized.effective.productLimit));
6510
+ if (new Set(prefix.map(({ id }) => id)).size !== prefix.length)
6511
+ throw new Error("Ambiguous post-purchase collection");
6512
+ const excluded = new Set(PostPurchaseExcludedProductIds.parse(excludedProductIds));
6513
+ const members = prefix.map((product, productIndex) => ({ product, productIndex })).filter(({ product }) => !excluded.has(product.id));
6514
+ return { members, normalized };
6515
+ };
6516
+
6517
+ // src/server/postPurchaseVariantCatalog.ts
6518
+ var projectPostPurchaseVariantCatalog = (product, settings) => {
6519
+ const options2 = PostPurchaseVariantCatalog.shape.options.parse(product.options === void 0 ? [] : product.options).sort((a, b) => a.position - b.position);
6520
+ const variants = product.variants.map((variant2) => ({
6521
+ ...variant2,
6522
+ ...PostPurchaseVariantValues.partial().parse(variant2)
6523
+ }));
6524
+ const tuples = variants.map(({ option1, option2, option3 }) => [option1, option2, option3]);
6525
+ if (new Set(product.variants.map(({ id }) => id)).size !== product.variants.length || product.variants.some(({ productId: productId2 }) => productId2 !== product.id) || new Set(options2.map(({ id }) => id)).size !== options2.length || options2.some(
6526
+ ({ position, values: values2 }, index) => position !== index + 1 || new Set(values2).size !== values2.length
6527
+ ) || product.variants.length > 1 && new Set(tuples.map((tuple) => JSON.stringify(tuple))).size !== tuples.length)
6528
+ throw new Error("Ambiguous post-purchase variant catalog");
6529
+ for (const tuple of tuples) {
6530
+ if (options2.some(({ position, values: values2 }) => !values2.some((value) => value === tuple[position - 1])) || tuple.some((value, index) => value != null && !options2[index]))
6531
+ throw new Error("Variant option tuple does not match the catalog");
6532
+ }
6533
+ return PostPurchaseVariantCatalog.parse({
6534
+ displayMode: settings.productOptions.variantSelectorDisplayMode,
6535
+ options: options2,
6536
+ productId: product.id,
6537
+ showSelectors: settings.productOptions.showVariantSelectors,
6538
+ variants: variants.map(({ id, imageId, option1, option2, option3, title, ...inventory }) => ({
6539
+ available: postPurchaseVariantAvailable(inventory),
6540
+ id,
6541
+ imageId,
6542
+ option1,
6543
+ option2,
6544
+ option3,
6545
+ title
6546
+ }))
6547
+ });
6548
+ };
6549
+
6550
+ // src/schema/postPurchaseQuantity.ts
6551
+ var import_zod64 = require("zod");
6552
+ var quantity = PreparedPostPurchaseProduct.shape.selection.shape.quantity;
6553
+ var PostPurchaseQuantityChoice = PostPurchaseCollectionChoice.extend({ quantity: quantity.optional() });
6554
+ var PostPurchaseQuantityPolicy = PostPurchaseSettings.shape.quantityInputs.omit({ defaultQuantity: true }).extend({
6555
+ initialQuantity: quantity,
6556
+ maxValue: quantity,
6557
+ minValue: import_zod64.z.literal(0).transform(() => 1).or(quantity)
6558
+ }).refine(({ maxValue, minValue }) => minValue <= maxValue, "Quantity bounds are reversed");
6559
+
6560
+ // src/server/readPostPurchaseQuantity.ts
6561
+ var PostPurchaseQuantityUnavailable = class extends Error {
6562
+ };
6563
+ var readPostPurchaseQuantity = ({
6564
+ data,
6565
+ effective,
6566
+ original
6567
+ }, selection3) => {
6568
+ const positive = PreparedPostPurchaseProduct.shape.selection.shape.quantity;
6569
+ for (const config of [original, effective]) {
6570
+ if (!config.quantityInputs.enabled) continue;
6571
+ const initialQuantity2 = positive.parse(config.quantityInputs.defaultQuantity);
6572
+ const policy2 = PostPurchaseQuantityPolicy.parse({ ...config.quantityInputs, initialQuantity: initialQuantity2 });
6573
+ if (initialQuantity2 < policy2.minValue || initialQuantity2 > policy2.maxValue)
6574
+ throw new Error("Configured quantity default is outside its bounds");
6575
+ }
6576
+ const initialQuantity = data[0]?.metadata?.productQuantity ?? (original.quantityInputs.enabled ? original.quantityInputs.defaultQuantity : 1);
6577
+ const policy = PostPurchaseQuantityPolicy.parse(
6578
+ effective.quantityInputs.enabled ? { ...effective.quantityInputs, initialQuantity } : { enabled: false, initialQuantity, maxValue: initialQuantity, minValue: initialQuantity }
6579
+ );
6580
+ const requested = "quantity" in selection3 ? selection3.quantity : selection3.expectedQuantity === initialQuantity ? void 0 : selection3.expectedQuantity;
6581
+ const quantity2 = positive.parse(requested ?? initialQuantity);
6582
+ if (requested !== void 0 && (policy.enabled ? quantity2 < policy.minValue || quantity2 > policy.maxValue : quantity2 !== initialQuantity))
6583
+ throw new PostPurchaseQuantityUnavailable("Requested quantity is unavailable");
6584
+ return { policy, quantity: quantity2 };
6585
+ };
6586
+
6587
+ // src/schema/postPurchaseVariantDefault.ts
6588
+ var import_zod65 = require("zod");
6589
+ var values = PostPurchaseVariantValues.partial().extend({
6590
+ option1: PostPurchaseVariantValues.shape.option1.nullish()
6591
+ });
6592
+ var variant = values.extend({
6593
+ id: PostPurchaseVariantId,
6594
+ inventoryManagement: import_zod65.z.string().nullable(),
6595
+ inventoryPolicy: import_zod65.z.string(),
6596
+ inventoryQuantity: import_zod65.z.number()
6597
+ });
6598
+ var options = import_zod65.z.array(PostPurchaseVariantOption.pick({ name: true, values: true }));
6599
+ var PostPurchaseVariantDefaultProduct = import_zod65.z.object({
6600
+ id: PostPurchaseProductId,
6601
+ options,
6602
+ selectedVariant: variant.optional(),
6603
+ variants: import_zod65.z.array(variant)
6604
+ });
6605
+ var PostPurchaseVariantDefaultSettings = PostPurchaseSettings.shape.productOptions.pick({
6606
+ hideOutOfStockVariants: true,
6607
+ matchVariant: true
6608
+ });
6609
+ var PostPurchaseOrderAttributes = import_zod65.z.record(import_zod65.z.string(), import_zod65.z.array(import_zod65.z.string())).default({});
6610
+ var PostPurchaseOriginalVariants = import_zod65.z.array(
6611
+ import_zod65.z.object({ productId: PostPurchaseProductId, variantId: PostPurchaseVariantId })
6612
+ );
6613
+ var PostPurchaseAttributeProducts = import_zod65.z.array(
6614
+ import_zod65.z.object({ id: PostPurchaseProductId, options, variants: import_zod65.z.array(values.extend({ id: PostPurchaseVariantId })) })
6615
+ );
6616
+
6617
+ // src/schema/postPurchaseVariantDefaultContext.ts
6618
+ var import_zod66 = require("zod");
6619
+ var PostPurchaseVariantDefaultContext = import_zod66.z.object({
6620
+ enrichedLineItems: import_zod66.z.unknown().optional(),
6621
+ originalVariants: PostPurchaseOriginalVariants
6622
+ });
6623
+
6624
+ // src/server/createPostPurchaseOrderAttributes.ts
6625
+ var createPostPurchaseOrderAttributes = (original, enriched) => {
6626
+ const products = PostPurchaseAttributeProducts.parse(enriched);
6627
+ const attributes = {};
6628
+ for (const item of PostPurchaseOriginalVariants.parse(original)) {
6629
+ const product = products.find(({ id }) => id === item.productId);
6630
+ const variant2 = product?.variants.find(({ id }) => id === item.variantId);
6631
+ if (!variant2 || !product) continue;
6632
+ ["option1", "option2", "option3"].forEach((key, index) => {
6633
+ const value = variant2[key];
6634
+ const option = product.options[index];
6635
+ if (!value || !option) return;
6636
+ const values2 = attributes[option.name] ?? [];
6637
+ if (!values2.includes(value)) attributes[option.name] = [...values2, value];
6638
+ });
6639
+ }
6640
+ return attributes;
6641
+ };
6642
+
6643
+ // src/server/matchPostPurchaseVariantDefault.ts
6644
+ var matchPostPurchaseVariantDefault = (product, attributes, filterOutOfStock) => {
6645
+ const keys = ["option1", "option2", "option3"];
6646
+ const values2 = keys.map((_, index) => {
6647
+ const option = product.options[index];
6648
+ return option ? option.values.filter((value) => attributes[option.name]?.includes(value)) : [];
6649
+ });
6650
+ if (!values2.some((entries) => entries.length)) return;
6651
+ let bestRank = 1;
6652
+ let best;
6653
+ for (const variant2 of product.variants) {
6654
+ if (filterOutOfStock && variant2.inventoryPolicy !== "continue" && variant2.inventoryQuantity <= 0) continue;
6655
+ const rank = keys.reduce((total, key, index) => {
6656
+ const value = variant2[key];
6657
+ return total + Number(!value && !values2[index].length || !!value && values2[index].includes(value));
6658
+ }, 0);
6659
+ if (rank > bestRank) {
6660
+ best = variant2;
6661
+ bestRank = rank;
6662
+ }
6663
+ }
6664
+ return best;
6665
+ };
6666
+
6667
+ // src/server/resolvePostPurchaseVariantDefault.ts
6668
+ var resolvePostPurchaseVariantDefault = (source2, settings, originalAttributes) => {
6669
+ const product = PostPurchaseVariantDefaultProduct.parse(source2);
6670
+ const policy = PostPurchaseVariantDefaultSettings.parse(settings);
6671
+ const attributes = PostPurchaseOrderAttributes.parse(originalAttributes);
6672
+ let selected = source2.selectedVariant && source2.selectedVariant === source2.variants[0] ? product.variants[0] : product.selectedVariant;
6673
+ if (!selected && policy.matchVariant)
6674
+ selected = matchPostPurchaseVariantDefault(product, attributes, policy.hideOutOfStockVariants);
6675
+ selected ?? (selected = product.variants[0]);
6676
+ if (!selected || selected === product.variants[0])
6677
+ selected = product.variants.find(postPurchaseVariantAvailable) ?? selected;
6678
+ return selected?.id ?? null;
6679
+ };
6680
+
6681
+ // src/server/resolvePostPurchaseMemberDefault.ts
6682
+ var resolvePostPurchaseMemberDefault = (product, original, context) => {
6683
+ const originals = PostPurchaseVariantDefaultContext.parse(context);
6684
+ if (product.variants.length < 2 && product.selectedVariant === void 0) return product.variants[0]?.id ?? null;
6685
+ const source2 = PostPurchaseVariantDefaultProduct.parse(product);
6686
+ const settings = PostPurchaseVariantDefaultSettings.parse(original.productOptions);
6687
+ const attributes = settings.matchVariant && !source2.selectedVariant && source2.options.some(({ values: values2 }) => values2.length > 0) && originals.originalVariants.length > 0 && originals.enrichedLineItems != null ? createPostPurchaseOrderAttributes(
6688
+ originals.originalVariants,
6689
+ PostPurchaseAttributeProducts.parse(deepCamelCase(originals.enrichedLineItems))
6690
+ ) : void 0;
6691
+ return resolvePostPurchaseVariantDefault(source2, settings, attributes);
6692
+ };
6693
+
6694
+ // src/server/preparePostPurchaseMemberView.ts
6695
+ var prepareMember = (widgetId, settings, response, requested, report, excludedProductIds, requestedQuantity, defaults) => {
6696
+ const selected = PostPurchaseCollectionChoice.parse(requested);
6697
+ const { members, normalized } = normalizePostPurchaseCollection(settings, response, excludedProductIds);
6698
+ const found = members.find(({ product: product2 }) => product2.id === selected.productId);
6699
+ if (!found) return null;
6700
+ const variantId = selected.variantId ?? (defaults && resolvePostPurchaseMemberDefault(found.product, normalized.original, defaults));
6701
+ const product = variantId === void 0 ? found.product : {
6702
+ ...found.product,
6703
+ variants: found.product.variants.filter(({ id }) => id === variantId)
6704
+ };
6705
+ const selectedInput = { ...normalized, data: [product] };
6706
+ const quantity2 = requestedQuantity ? readPostPurchaseQuantity(selectedInput, requestedQuantity) : void 0;
6707
+ const view = prepareNormalizedPostPurchaseView(widgetId, selectedInput, report, selected.choice, quantity2, true);
6708
+ if (selected.variantId !== void 0 || found.product.variants.length > 1)
6709
+ view.variantCatalog = projectPostPurchaseVariantCatalog(found.product, normalized.effective);
6710
+ if (defaults && selected.variantId === void 0 && variantId && view.variantCatalog?.variants.some(({ id }) => id === variantId))
6711
+ view.initialVariant = { variantId };
6712
+ return { member: { productId: found.product.id, productIndex: found.productIndex, view }, normalized, quantity: quantity2 };
6713
+ };
6714
+ var preparePostPurchaseMemberView = (widgetId, settings, response, requested, report, excludedProductIds) => prepareMember(widgetId, settings, response, requested, report, excludedProductIds)?.member ?? null;
6715
+ var preparePostPurchaseMemberAdmissionView = (widgetId, settings, response, requested, report, excludedProductIds) => {
6716
+ const prepared = prepareMember(widgetId, settings, response, requested, report, excludedProductIds);
6717
+ if (!prepared) return null;
6718
+ const { removePartialOrder } = PostPurchaseSettings.shape.advance.parse(prepared.normalized.effective.advance);
6719
+ return { ...prepared.member, removePartialOrder };
6720
+ };
6721
+
6722
+ // src/server/preparePostPurchaseQuantityView.ts
6723
+ var preparePostPurchaseQuantityView = (widgetId, settings, response, requested, report, excludedProductIds, defaults) => {
6724
+ const { quantity: quantity2, ...selection3 } = PostPurchaseQuantityChoice.parse(requested);
6725
+ const prepared = prepareMember(
6726
+ widgetId,
6727
+ settings,
6728
+ response,
6729
+ selection3,
6730
+ report,
6731
+ excludedProductIds,
6732
+ { quantity: quantity2 },
6733
+ defaults
6734
+ );
6735
+ return prepared ? { ...prepared.member, quantityPolicy: prepared.quantity.policy } : null;
6736
+ };
6737
+
6738
+ // src/server/preparePostPurchaseQuantityAdmissionView.ts
6739
+ var selection = PostPurchaseQuantityChoice.required({ quantity: true });
6740
+ var preparePostPurchaseQuantityAdmissionView = (widgetId, settings, response, expected, report, excludedProductIds, defaults) => {
6741
+ const { quantity: expectedQuantity, ...requested } = selection.parse(expected);
6742
+ const prepared = prepareMember(
6743
+ widgetId,
6744
+ settings,
6745
+ response,
6746
+ requested,
6747
+ report,
6748
+ excludedProductIds,
6749
+ { expectedQuantity },
6750
+ defaults
6751
+ );
6752
+ if (!prepared) return null;
6753
+ const { removePartialOrder } = PostPurchaseSettings.shape.advance.parse(prepared.normalized.effective.advance);
6754
+ return { ...prepared.member, quantityPolicy: prepared.quantity.policy, removePartialOrder };
6755
+ };
6756
+
6757
+ // src/schema/postPurchaseGroup.ts
6758
+ var PostPurchaseGroupChoice = PostPurchaseQuantityChoice.extend({
6759
+ memberProductId: PreparedPostPurchaseProduct.shape.selection.shape.productId
6760
+ });
6761
+
6762
+ // src/server/readPostPurchaseGroup.ts
6763
+ var readPostPurchaseGroup = (product, settings, excludedProductIds) => {
6764
+ const descriptions = PostPurchaseGroupDescription.nullable().array().parse(product.productGroupVariants).filter((value) => value !== null);
6765
+ const ids = new Set(descriptions.map((value) => value.id));
6766
+ if (ids.size !== descriptions.length || new Set(product.variants.map(({ id }) => id)).size !== product.variants.length || product.variants.some(({ productId: productId2 }) => !ids.has(productId2)))
6767
+ throw new Error("Ambiguous post-purchase group ownership");
6768
+ const excluded = new Set(PostPurchaseExcludedProductIds.parse(excludedProductIds));
6769
+ const entries = descriptions.map((description) => {
6770
+ const value = {
6771
+ ...product,
6772
+ ...description,
6773
+ images: description.images,
6774
+ productGroupVariants: [],
6775
+ variants: product.variants.filter(({ productId: productId2 }) => productId2 === description.id)
6776
+ };
6777
+ return { product: value, variantCatalog: projectPostPurchaseVariantCatalog(value, settings) };
6778
+ }).filter(({ product: value }) => !excluded.has(value.id));
6779
+ return {
6780
+ catalog: PostPurchaseGroupCatalog.parse({
6781
+ memberProductId: product.id,
6782
+ options: entries.map(({ product: value, variantCatalog }) => ({
6783
+ productId: value.id,
6784
+ title: value.title,
6785
+ variantCatalog
6786
+ }))
6787
+ }),
6788
+ entries
6789
+ };
6790
+ };
6791
+
6792
+ // src/server/readPostPurchaseGroupSelection.ts
6793
+ var readPostPurchaseGroupSelection = (settings, response, requested, excludedProductIds) => {
6794
+ const selection3 = PostPurchaseGroupSelection.parse(requested);
6795
+ const { members, normalized } = normalizePostPurchaseCollection(settings, response);
6796
+ const member = members.find(({ product }) => product.id === selection3.memberProductId);
6797
+ if (!member || !member.product.productGroupVariants.length) return null;
6798
+ const group = readPostPurchaseGroup(member.product, normalized.effective, excludedProductIds);
6799
+ const entry = group.entries.find(({ product }) => product.id === selection3.productId);
6800
+ if (!entry) return null;
6801
+ return {
6802
+ groupCatalog: group.catalog,
6803
+ memberProductId: member.product.id,
6804
+ productIndex: member.productIndex,
6805
+ reportingProduct: { id: member.product.id, title: member.product.title },
6806
+ response: { data: [entry.product], metadata: normalized.metadata },
6807
+ variantCatalog: entry.variantCatalog
6808
+ };
6809
+ };
6810
+
6811
+ // src/server/preparePostPurchaseGroupView.ts
6812
+ var preparePostPurchaseGroupView = (widgetId, settings, response, requested, report, excludedProductIds) => {
6813
+ const { memberProductId, ...selection3 } = PostPurchaseGroupChoice.parse(requested);
6814
+ const group = readPostPurchaseGroupSelection(settings, response, requested, excludedProductIds);
6815
+ if (!group) return null;
6816
+ const variantId = selection3.variantId ?? group.variantCatalog.variants.find(({ available }) => available)?.id;
6817
+ if (variantId === void 0) return null;
6818
+ const prepared = preparePostPurchaseQuantityView(
6819
+ widgetId,
6820
+ settings,
6821
+ group.response,
6822
+ { ...selection3, variantId },
6823
+ report
6824
+ );
6825
+ return prepared && {
6826
+ ...prepared,
6827
+ groupCatalog: group.groupCatalog,
6828
+ memberProductId,
6829
+ productIndex: group.productIndex,
6830
+ reportingProduct: group.reportingProduct
6831
+ };
6832
+ };
6833
+
6834
+ // src/server/preparePostPurchaseGroupAdmissionView.ts
6835
+ var preparePostPurchaseGroupAdmissionView = (widgetId, settings, response, requested, report, excludedProductIds) => {
6836
+ const { memberProductId, ...selection3 } = PostPurchaseGroupChoice.required({ quantity: true }).parse(requested);
6837
+ const group = readPostPurchaseGroupSelection(settings, response, requested, excludedProductIds);
6838
+ if (!group) return null;
6839
+ const variantId = selection3.variantId ?? group.variantCatalog.variants.find(({ available }) => available)?.id;
6840
+ if (variantId === void 0) return null;
6841
+ const prepared = preparePostPurchaseQuantityAdmissionView(
6842
+ widgetId,
6843
+ settings,
6844
+ group.response,
6845
+ { ...selection3, variantId },
6846
+ report
6847
+ );
6848
+ return prepared && {
6849
+ ...prepared,
6850
+ groupCatalog: group.groupCatalog,
6851
+ memberProductId,
6852
+ productIndex: group.productIndex,
6853
+ reportingProduct: group.reportingProduct
6854
+ };
6855
+ };
6856
+
6857
+ // src/server/preparePostPurchaseGroupDefault.ts
6858
+ var preparePostPurchaseGroupDefault = (widgetId, settings, response, memberProductId, context, report, excludedProductIds) => {
6859
+ const { members, normalized } = normalizePostPurchaseCollection(settings, response);
6860
+ const member = members.find(({ product }) => product.id === memberProductId);
6861
+ if (!member || !member.product.productGroupVariants.length) return null;
6862
+ const group = readPostPurchaseGroup(member.product, normalized.effective, excludedProductIds);
6863
+ const ids = new Set(group.entries.map(({ product }) => product.id));
6864
+ const variants = member.product.variants.filter(({ productId: productId2 }) => ids.has(productId2));
6865
+ const selected = PostPurchaseVariantDefaultProduct.shape.selectedVariant.parse(member.product.selectedVariant);
6866
+ const selectedOwner = selected && member.product.variants.find(({ id }) => id === selected.id);
6867
+ const variantId = resolvePostPurchaseMemberDefault(
6868
+ {
6869
+ ...member.product,
6870
+ selectedVariant: selectedOwner && !ids.has(selectedOwner.productId) ? void 0 : member.product.selectedVariant,
6871
+ variants
6872
+ },
6873
+ normalized.original,
6874
+ context
6875
+ );
6876
+ const entry = group.entries.find(({ product }) => product.variants.some(({ id }) => id === variantId));
6877
+ if (!entry || variantId === null) return null;
6878
+ const prepared = preparePostPurchaseGroupView(
6879
+ widgetId,
6880
+ settings,
6881
+ response,
6882
+ { memberProductId, productId: entry.product.id, variantId },
6883
+ report,
6884
+ excludedProductIds
6885
+ );
6886
+ return prepared && { ...prepared, view: { ...prepared.view, initialVariant: { variantId } } };
6887
+ };
6888
+
6889
+ // src/server/preparePostPurchaseCollectionGroup.ts
6890
+ var preparePostPurchaseCollectionGroup = (widgetId, settings, response, member, normalized, excluded, defaults, report) => {
6891
+ const group = readPostPurchaseGroup(member.product, normalized.effective, excluded);
6892
+ if (!group.entries.length) return null;
6893
+ const prepared = preparePostPurchaseGroupDefault(
6894
+ widgetId,
6895
+ settings,
6896
+ response,
6897
+ member.product.id,
6898
+ defaults,
6899
+ report,
6900
+ excluded
6901
+ );
6902
+ return {
6903
+ productId: member.product.id,
6904
+ productIndex: member.productIndex,
6905
+ reportingProduct: { id: member.product.id, title: member.product.title },
6906
+ view: prepared ? { ...prepared.view, groupCatalog: prepared.groupCatalog } : {
6907
+ groupCatalog: group.catalog,
6908
+ preparation: { reason: "Post-purchase group default is unavailable", status: "unsupported" },
6909
+ sections: null
6910
+ }
6911
+ };
6912
+ };
6913
+
6914
+ // src/server/preparePostPurchaseCollectionView.ts
6915
+ var CollectionChoice = PostPurchaseCollectionChoice.omit({ variantId: true });
6916
+ var preparePostPurchaseCollectionView = (widgetId, settings, response, report, requested, excludedProductIds, defaults = { originalVariants: [] }) => {
6917
+ const { members, normalized } = normalizePostPurchaseCollection(settings, response);
6918
+ const excluded = PostPurchaseExcludedProductIds.parse(excludedProductIds);
6919
+ const selected = CollectionChoice.optional().parse(requested);
6920
+ const projected = members.map((member) => {
6921
+ if (member.product.productGroupVariants.length) {
6922
+ if (selected?.productId === member.product.id && selected.choice)
6923
+ throw new Error("Grouped choices require selected merchandise");
6924
+ const group = preparePostPurchaseCollectionGroup(
6925
+ widgetId,
6926
+ settings,
6927
+ response,
6928
+ member,
6929
+ normalized,
6930
+ excluded,
6931
+ defaults,
6932
+ report
6933
+ );
6934
+ return group;
6935
+ }
6936
+ if (excluded.includes(member.product.id)) return null;
6937
+ return {
6938
+ productId: member.product.id,
6939
+ productIndex: member.productIndex,
6940
+ reportingProduct: void 0,
6941
+ view: prepareNormalizedPostPurchaseView(
6942
+ widgetId,
6943
+ { ...normalized, data: [member.product] },
6944
+ report,
6945
+ member.product.id === selected?.productId ? selected.choice : void 0,
6946
+ void 0,
6947
+ true
6948
+ )
6949
+ };
6950
+ }).filter((member) => member !== null);
6951
+ if (selected && !projected.some(({ productId: productId2 }) => productId2 === selected.productId))
6952
+ throw new Error("Requested product is outside the prepared collection");
6953
+ const collection = PostPurchaseProductCollectionView.parse({ members: projected });
6954
+ return {
6955
+ members: collection.members.map((member, index) => ({
6956
+ ...member,
6957
+ ...projected[index].reportingProduct && { reportingProduct: projected[index].reportingProduct }
6958
+ }))
6959
+ };
6960
+ };
6961
+
6962
+ // src/schema/postPurchaseOfferEligibility.ts
6963
+ var import_zod67 = require("zod");
6964
+ var selection2 = PreparedPostPurchaseProduct.shape.selection;
6965
+ var PostPurchaseOfferSkipReason = import_zod67.z.enum(["empty", "no-eligible-subscription"]);
6966
+ var PostPurchaseOfferEligibilityContext = import_zod67.z.object({
6967
+ excludedProductIds: PostPurchaseExcludedProductIds,
6968
+ originalLineItems: import_zod67.z.array(selection2.pick({ productId: true, sellingPlanId: true, variantId: true }))
6969
+ });
6970
+ var PostPurchaseOfferEligibility = import_zod67.z.discriminatedUnion("status", [
6971
+ import_zod67.z.object({
6972
+ members: import_zod67.z.array(
6973
+ import_zod67.z.object({ productId: selection2.shape.productId, productIndex: import_zod67.z.number().int().nonnegative() })
6974
+ ),
6975
+ status: import_zod67.z.literal("retain")
6976
+ }),
6977
+ import_zod67.z.object({ reason: PostPurchaseOfferSkipReason, status: import_zod67.z.literal("skip") }),
6978
+ import_zod67.z.object({ reason: import_zod67.z.literal("eligible-upgrade").optional(), status: import_zod67.z.literal("unavailable") })
6979
+ ]);
6980
+
6981
+ // src/server/postPurchaseMemberEligibility.ts
6982
+ var PostPurchaseInventoryUnavailable = class extends Error {
6983
+ };
6984
+ var postPurchaseMemberEligibility = (normalized, product, excluded) => {
6985
+ if (product.productGroupVariants.length) {
6986
+ const group = readPostPurchaseGroup(product, normalized.effective, excluded);
6987
+ return group.entries.map(({ product: option }) => postPurchaseMemberEligibility(normalized, option)).some(Boolean);
6988
+ }
6989
+ if (!product.variants.length) throw new Error("Unsupported catalog");
6990
+ const variants = projectPostPurchaseVariantCatalog(product, normalized.effective).variants;
6991
+ const catalogs = product.variants.map((variant2) => {
6992
+ const catalog = projectPostPurchasePlanCatalog({
6993
+ ...normalized,
6994
+ data: [{ ...product, variants: [variant2] }]
6995
+ });
6996
+ if (!catalog) throw new Error("Unreadable subscription catalog");
6997
+ if (normalized.effective.productType === "one-time" && catalog.requiresSellingPlan)
6998
+ throw new Error("Unsupported purchase mode");
6999
+ return catalog;
7000
+ });
7001
+ if (!variants.some((variant2) => variant2.available))
7002
+ throw new PostPurchaseInventoryUnavailable("Unavailable inventory");
7003
+ return catalogs.some(
7004
+ (catalog, index) => variants[index].available && (normalized.effective.productType !== "subscription" && !catalog.requiresSellingPlan || normalized.effective.productType !== "one-time" && catalog.plans.length > 0)
7005
+ );
7006
+ };
7007
+
7008
+ // src/server/classifyPostPurchaseOffer.ts
7009
+ var classifyPostPurchaseOffer = (settings, response, context) => {
7010
+ try {
7011
+ const trusted = PostPurchaseOfferEligibilityContext.parse(context);
7012
+ const { members, normalized } = normalizePostPurchaseCollection(settings, response);
7013
+ const configurations = [normalized.original, normalized.effective];
7014
+ const upgrades = configurations.some((config) => config.upgradeToSubscription.allow);
7015
+ const oneTime = new Set(
7016
+ trusted.originalLineItems.filter((line) => line.sellingPlanId === void 0).map((line) => line.variantId)
7017
+ );
7018
+ if (upgrades && members.some(
7019
+ ({ product }) => product.sellingPlanGroups?.length && product.variants.some((variant2) => oneTime.has(variant2.id))
7020
+ ))
7021
+ return { reason: "eligible-upgrade", status: "unavailable" };
7022
+ if (normalized.effective.productType !== "one-time") {
7023
+ configurations.forEach((config) => PostPurchaseSubscriptionSettings.parse(config.subscription));
7024
+ }
7025
+ const classified = members.map((member) => {
7026
+ try {
7027
+ return {
7028
+ ...member,
7029
+ eligible: postPurchaseMemberEligibility(normalized, member.product, trusted.excludedProductIds)
7030
+ };
7031
+ } catch (error) {
7032
+ if (error instanceof PostPurchaseInventoryUnavailable && !member.product.productGroupVariants.length && trusted.excludedProductIds.includes(member.product.id))
7033
+ return { ...member, eligible: false };
7034
+ throw error;
7035
+ }
7036
+ });
7037
+ if (!members.length) return { reason: "empty", status: "skip" };
7038
+ if (upgrades) return { reason: "no-eligible-subscription", status: "skip" };
7039
+ const candidates = classified.filter(
7040
+ ({ product }) => product.productGroupVariants.length ? readPostPurchaseGroup(product, normalized.effective, trusted.excludedProductIds).entries.length > 0 : !trusted.excludedProductIds.includes(product.id)
7041
+ );
7042
+ if (!candidates.length) return { reason: "empty", status: "skip" };
7043
+ const retained = candidates.filter(({ eligible }) => eligible);
7044
+ return retained.length ? {
7045
+ members: retained.map(({ product, productIndex }) => ({
7046
+ productId: product.id,
7047
+ productIndex
7048
+ })),
7049
+ status: "retain"
7050
+ } : { reason: "no-eligible-subscription", status: "skip" };
7051
+ } catch {
7052
+ return { status: "unavailable" };
7053
+ }
7054
+ };
7055
+
7056
+ // src/server/preparePostPurchaseGroupDeclineDisplay.ts
7057
+ var preparePostPurchaseGroupDeclineDisplay = (settings, response, requested, excludedProductIds) => {
7058
+ const group = readPostPurchaseGroupSelection(settings, response, requested, excludedProductIds);
7059
+ const variant2 = group?.variantCatalog.variants.find(({ id }) => id === requested.variantId);
7060
+ return group && variant2 ? {
7061
+ display: {
7062
+ productTitle: group.reportingProduct.title,
7063
+ variantId: variant2.id,
7064
+ variantTitle: variant2.title
7065
+ },
7066
+ productIndex: group.productIndex
7067
+ } : null;
7068
+ };
7069
+
7070
+ // src/server/preparePostPurchaseOfferPresentation.ts
7071
+ var import_compat7 = require("es-toolkit/compat");
7072
+ var import_zod69 = require("zod");
7073
+
7074
+ // src/schema/postPurchaseOfferPresentation.ts
7075
+ var import_zod68 = require("zod");
7076
+ var language2 = PostPurchaseSettings.shape.language.shape.global.unwrap().unwrap();
7077
+ var PostPurchaseOfferPresentation = import_zod68.z.strictObject({
7078
+ labels: language2.pick({ declineAll: true, declineThisOffer: true }),
7079
+ layout: PostPurchaseSettings.shape.offersLayout,
7080
+ sections: CABRootSection.nullable(),
7081
+ showDeclineAll: PostPurchaseSettings.shape.productOptions.shape.showDeclineAll
7082
+ });
7083
+
7084
+ // src/server/preparePostPurchaseOfferPresentation.ts
7085
+ var FrameSettings = PostPurchaseSettings.pick({ language: true, offersLayout: true, productOptions: true }).extend({
7086
+ blocks: import_zod69.z.array(import_zod69.z.unknown()).optional()
7087
+ });
7088
+ var preparePostPurchaseOfferPresentation = (widgetId, settings, response, report) => {
7089
+ const { metadata } = PostPurchaseProductSource.pick({ metadata: true }).parse(deepCamelCase(response));
7090
+ const original = FrameSettings.parse(deepCamelCase(settings));
7091
+ const effective = FrameSettings.parse((0, import_compat7.merge)({}, original, metadata.widget));
7092
+ let sections = null;
7093
+ try {
7094
+ sections = convertMessagePreview(
7095
+ widgetId,
7096
+ { blocks: postPurchaseOfferCopy(effective.blocks, metadata), type: "shopify_post_purchase_extension" },
7097
+ report
7098
+ );
7099
+ } catch (error) {
7100
+ if (!(error instanceof NotFoundError)) throw error;
7101
+ }
7102
+ return PostPurchaseOfferPresentation.parse({
7103
+ labels: effective.language.global,
7104
+ layout: effective.offersLayout,
7105
+ sections,
7106
+ showDeclineAll: effective.productOptions.showDeclineAll
7107
+ });
7108
+ };
7109
+
6189
7110
  // src/server/analytics.ts
6190
7111
  var import_es_toolkit7 = require("es-toolkit");
6191
7112
 
@@ -6230,8 +7151,8 @@ var TAXONOMY = {
6230
7151
  "added-to-cart": {
6231
7152
  /** React credits the add to the A/B-selected variant (`defined_noun_id: selectedId`). */
6232
7153
  buildDefinedNounId: ({ selectedId }) => selectedId != null ? String(selectedId) : void 0,
6233
- buildMeta: ({ productId, variantId }) => ({
6234
- ...productId != null && { [`product_id:${productId}`]: true },
7154
+ buildMeta: ({ productId: productId2, variantId }) => ({
7155
+ ...productId2 != null && { [`product_id:${productId2}`]: true },
6235
7156
  ...variantId != null && { [`variant_id:${variantId}`]: true }
6236
7157
  }),
6237
7158
  buildTags: experimentTags,
@@ -6322,7 +7243,7 @@ var postAnalyticsEvents = async (input, ctx) => {
6322
7243
  };
6323
7244
 
6324
7245
  // src/server/requestSchemas.ts
6325
- var import_zod56 = require("zod");
7246
+ var import_zod70 = require("zod");
6326
7247
  var REQUEST_BOUNDS = {
6327
7248
  /** Cart-level attributes per cart. */
6328
7249
  CART_ATTRIBUTES_MAX: 100,
@@ -6353,42 +7274,42 @@ var REQUEST_BOUNDS = {
6353
7274
  /** Rich ads transaction lines — the engine's ads contract. */
6354
7275
  TRANSACTION_ITEMS_MAX: 50
6355
7276
  };
6356
- var KeyValue = import_zod56.z.object({
6357
- key: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
6358
- value: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_VALUE_MAX).optional()
7277
+ var KeyValue = import_zod70.z.object({
7278
+ key: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
7279
+ value: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_VALUE_MAX).optional()
6359
7280
  });
6360
- var CartLineInputSchema = import_zod56.z.object({
6361
- productId: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6362
- properties: import_zod56.z.array(KeyValue).max(REQUEST_BOUNDS.LINE_PROPERTIES_MAX).optional(),
6363
- quantity: import_zod56.z.number(),
6364
- subscriptionId: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6365
- variantId: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX)
7281
+ var CartLineInputSchema = import_zod70.z.object({
7282
+ productId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7283
+ properties: import_zod70.z.array(KeyValue).max(REQUEST_BOUNDS.LINE_PROPERTIES_MAX).optional(),
7284
+ quantity: import_zod70.z.number(),
7285
+ subscriptionId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7286
+ variantId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX)
6366
7287
  });
6367
- var CartInputSchema = import_zod56.z.object({
6368
- attributes: import_zod56.z.array(KeyValue).max(REQUEST_BOUNDS.CART_ATTRIBUTES_MAX).optional(),
7288
+ var CartInputSchema = import_zod70.z.object({
7289
+ attributes: import_zod70.z.array(KeyValue).max(REQUEST_BOUNDS.CART_ATTRIBUTES_MAX).optional(),
6369
7290
  /**
6370
7291
  * Presentment-per-shop-currency FX rate (buyer price ÷ shop price, e.g. `1.35` for a USD shop
6371
7292
  * selling in CAD). Money rule thresholds are authored in SHOP currency, so the engine subtotal is
6372
7293
  * divided by this before evaluation. Omit (or send 1) when the cart is already in the shop's currency.
6373
7294
  */
6374
- currencyRate: import_zod56.z.number().optional(),
7295
+ currencyRate: import_zod70.z.number().optional(),
6375
7296
  /** Applied discount codes; the engine evaluates `discount_code` rules against them (sent as `[{code}]`). */
6376
- discountCodes: import_zod56.z.array(import_zod56.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX)).max(REQUEST_BOUNDS.DISCOUNT_CODES_MAX).optional(),
7297
+ discountCodes: import_zod70.z.array(import_zod70.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX)).max(REQUEST_BOUNDS.DISCOUNT_CODES_MAX).optional(),
6377
7298
  /** Presentment cents of cart-level discount allocations, subtracted from `subtotal` for the engine. */
6378
- discountTotal: import_zod56.z.number().optional(),
6379
- items: import_zod56.z.array(CartLineInputSchema).max(REQUEST_BOUNDS.CART_ITEMS_MAX),
7299
+ discountTotal: import_zod70.z.number().optional(),
7300
+ items: import_zod70.z.array(CartLineInputSchema).max(REQUEST_BOUNDS.CART_ITEMS_MAX),
6380
7301
  /** Presentment subtotal in cents. */
6381
- subtotal: import_zod56.z.number()
7302
+ subtotal: import_zod70.z.number()
6382
7303
  });
6383
- var UserConfigInputSchema = import_zod56.z.object({ shop: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX) });
6384
- var DataSourceInputSchema = import_zod56.z.object({
7304
+ var UserConfigInputSchema = import_zod70.z.object({ shop: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX) });
7305
+ var DataSourceInputSchema = import_zod70.z.object({
6385
7306
  cart: CartInputSchema,
6386
7307
  /**
6387
7308
  * Numeric Shopify company-location id when the buyer is a B2B session (`buyerIdentity.purchasingCompany`).
6388
7309
  * Present ⇒ the orchestrator filters results by the location's catalog via admin-api (REB-23713); the
6389
7310
  * client's country-context market check is bypassed for B2B (it false-negatives B2B-catalog products).
6390
7311
  */
6391
- companyLocationId: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7312
+ companyLocationId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6392
7313
  /**
6393
7314
  * Buyer's market country (ISO 3166-1 alpha-2) — forwarded to the engine as the `country_code` PARAM
6394
7315
  * when the shop's markets toggle is on (REB-21688; the sink was the `X-Country-Code` header under
@@ -6397,16 +7318,16 @@ var DataSourceInputSchema = import_zod56.z.object({
6397
7318
  * uppercase (the wire value is forwarded verbatim as the param) so a case-sensitive engine lookup
6398
7319
  * can't silently miss a lowercase code — `adsEngine.ts` uppercases for the same reason.
6399
7320
  */
6400
- country: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).regex(/^[A-Za-z]{2}$/, "must be an ISO 3166-1 alpha-2 country code (e.g. CA)").transform((value) => value.toUpperCase()).optional(),
6401
- customerId: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6402
- dataSourcePath: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
7321
+ country: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).regex(/^[A-Za-z]{2}$/, "must be an ISO 3166-1 alpha-2 country code (e.g. CA)").transform((value) => value.toUpperCase()).optional(),
7322
+ customerId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7323
+ dataSourcePath: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
6403
7324
  /**
6404
7325
  * Engine `filter_inputs` override: `'no'` keeps in-cart (input) products in the results/rule
6405
7326
  * outputs — gift validation sends it so a gift's own product can appear in its answer. Omitted = the
6406
7327
  * engine's default filtering.
6407
7328
  */
6408
- filterInputs: import_zod56.z.enum(["no", "yes"]).optional(),
6409
- integrations: import_zod56.z.record(import_zod56.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), import_zod56.z.boolean()).refine((record) => Object.keys(record).length <= REQUEST_BOUNDS.INTEGRATION_KEYS_MAX, {
7329
+ filterInputs: import_zod70.z.enum(["no", "yes"]).optional(),
7330
+ integrations: import_zod70.z.record(import_zod70.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), import_zod70.z.boolean()).refine((record) => Object.keys(record).length <= REQUEST_BOUNDS.INTEGRATION_KEYS_MAX, {
6410
7331
  message: `Too many integration keys (max ${REQUEST_BOUNDS.INTEGRATION_KEYS_MAX})`
6411
7332
  }).optional(),
6412
7333
  /**
@@ -6419,31 +7340,31 @@ var DataSourceInputSchema = import_zod56.z.object({
6419
7340
  * request header) fails the regex. Callers should send the buyer's resolved locale (e.g. Shopify
6420
7341
  * checkout's `localization.language.isoCode`), not the request header verbatim.
6421
7342
  */
6422
- language: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).regex(/^[A-Za-z0-9-]+$/, "must be a single BCP-47 tag (e.g. fr-CA), not a q-value list").optional(),
6423
- limit: import_zod56.z.number().max(REQUEST_BOUNDS.LIMIT_MAX),
6424
- productType: import_zod56.z.enum(["both", "one-time", "subscription"]).optional(),
6425
- shop: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6426
- visitorId: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
6427
- });
6428
- var GiftInputSchema = import_zod56.z.object({
6429
- cost: import_zod56.z.number(),
6430
- discounted: import_zod56.z.boolean(),
7343
+ language: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).regex(/^[A-Za-z0-9-]+$/, "must be a single BCP-47 tag (e.g. fr-CA), not a q-value list").optional(),
7344
+ limit: import_zod70.z.number().max(REQUEST_BOUNDS.LIMIT_MAX),
7345
+ productType: import_zod70.z.enum(["both", "one-time", "subscription"]).optional(),
7346
+ shop: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7347
+ visitorId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
7348
+ });
7349
+ var GiftInputSchema = import_zod70.z.object({
7350
+ cost: import_zod70.z.number(),
7351
+ discounted: import_zod70.z.boolean(),
6431
7352
  /**
6432
7353
  * Which gift attribution the line carries (REB-24363). Defaults to `gwp` because a client that predates
6433
7354
  * the field only ever sent GWP lines — without the default an older extension's request would 422.
6434
7355
  */
6435
- kind: import_zod56.z.enum(GIFT_KINDS).default("gwp"),
6436
- lineId: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6437
- productId: import_zod56.z.number(),
7356
+ kind: import_zod70.z.enum(GIFT_KINDS).default("gwp"),
7357
+ lineId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7358
+ productId: import_zod70.z.number(),
6438
7359
  /**
6439
7360
  * The line's unit count (REB-24363) — the selectable-GWP verdict trims surplus units against milestone
6440
7361
  * capacity. The second deliberate default: a client predating the field sent only GWP lines, whose
6441
7362
  * verdict is whole-line, so a missing quantity reads as one unit rather than 422ing the older request.
6442
7363
  */
6443
- quantity: import_zod56.z.number().int().min(1).default(1),
6444
- widgetId: import_zod56.z.number()
7364
+ quantity: import_zod70.z.number().int().min(1).default(1),
7365
+ widgetId: import_zod70.z.number()
6445
7366
  });
6446
- var GiftValidationInputSchema = import_zod56.z.object({
7367
+ var GiftValidationInputSchema = import_zod70.z.object({
6447
7368
  cart: CartInputSchema,
6448
7369
  /**
6449
7370
  * Buyer's market country — threaded into the per-widget data-source evaluations, which forward it to
@@ -6452,25 +7373,25 @@ var GiftValidationInputSchema = import_zod56.z.object({
6452
7373
  * turns markets off); regex-bound and uppercase-normalized for the same reasons as
6453
7374
  * `DataSourceInputSchema`'s `country`.
6454
7375
  */
6455
- country: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).regex(/^[A-Za-z]{2}$/, "must be an ISO 3166-1 alpha-2 country code (e.g. CA)").transform((value) => value.toUpperCase()).optional(),
6456
- customerId: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6457
- gifts: import_zod56.z.array(GiftInputSchema).max(REQUEST_BOUNDS.GIFTS_MAX),
7376
+ country: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).regex(/^[A-Za-z]{2}$/, "must be an ISO 3166-1 alpha-2 country code (e.g. CA)").transform((value) => value.toUpperCase()).optional(),
7377
+ customerId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7378
+ gifts: import_zod70.z.array(GiftInputSchema).max(REQUEST_BOUNDS.GIFTS_MAX),
6458
7379
  /**
6459
7380
  * Buyer's checkout language — threaded into the per-widget data-source evaluations, which normalize
6460
7381
  * and forward it as the engine `locale` param under the same markets-toggle gate (REB-21688). MUST be
6461
7382
  * a single BCP-47 tag, for the same reason as `DataSourceInputSchema`'s `language` above.
6462
7383
  */
6463
- language: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).regex(/^[A-Za-z0-9-]+$/, "must be a single BCP-47 tag (e.g. fr-CA), not a q-value list").optional(),
6464
- shop: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6465
- visitorId: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
7384
+ language: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).regex(/^[A-Za-z0-9-]+$/, "must be a single BCP-47 tag (e.g. fr-CA), not a q-value list").optional(),
7385
+ shop: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7386
+ visitorId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
6466
7387
  });
6467
- var GiftAdjustmentSchema = import_zod56.z.object({
6468
- lineId: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6469
- quantity: import_zod56.z.number().int().nonnegative()
7388
+ var GiftAdjustmentSchema = import_zod70.z.object({
7389
+ lineId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7390
+ quantity: import_zod70.z.number().int().nonnegative()
6470
7391
  });
6471
- var GiftValidationResponseSchema = import_zod56.z.object({
6472
- adjust: import_zod56.z.array(GiftAdjustmentSchema).max(REQUEST_BOUNDS.GIFTS_MAX).default([]),
6473
- remove: import_zod56.z.array(import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX)).max(REQUEST_BOUNDS.GIFTS_MAX).refine(
7392
+ var GiftValidationResponseSchema = import_zod70.z.object({
7393
+ adjust: import_zod70.z.array(GiftAdjustmentSchema).max(REQUEST_BOUNDS.GIFTS_MAX).default([]),
7394
+ remove: import_zod70.z.array(import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX)).max(REQUEST_BOUNDS.GIFTS_MAX).refine(
6474
7395
  (remove) => new Set(remove).size === remove.length,
6475
7396
  "a line id may appear at most once in `remove`"
6476
7397
  )
@@ -6481,47 +7402,47 @@ var GiftValidationResponseSchema = import_zod56.z.object({
6481
7402
  ({ adjust }) => new Set(adjust.map(({ lineId }) => lineId)).size === adjust.length,
6482
7403
  "a line id may appear at most once in `adjust`"
6483
7404
  );
6484
- var MonetizeTransactionItemSchema = import_zod56.z.object({
6485
- id: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6486
- priceCents: import_zod56.z.number(),
6487
- quantity: import_zod56.z.number(),
6488
- title: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX),
6489
- type: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX)
6490
- });
6491
- var MonetizeInputSchema = import_zod56.z.object({
7405
+ var MonetizeTransactionItemSchema = import_zod70.z.object({
7406
+ id: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7407
+ priceCents: import_zod70.z.number(),
7408
+ quantity: import_zod70.z.number(),
7409
+ title: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX),
7410
+ type: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX)
7411
+ });
7412
+ var MonetizeInputSchema = import_zod70.z.object({
6492
7413
  cart: CartInputSchema,
6493
7414
  /** Client-minted render-beacon correlation id; forwarded to the ads engine as `client_request_id`. */
6494
- clientRequestId: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6495
- country: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6496
- currency: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7415
+ clientRequestId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7416
+ country: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7417
+ currency: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6497
7418
  /** Ads-targeting identity/geo/locale fields (React parity); folded into the engine query verbatim. */
6498
- customerEmail: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
6499
- customerFirstName: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
6500
- customerId: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6501
- customerLastName: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
6502
- language: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7419
+ customerEmail: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
7420
+ customerFirstName: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
7421
+ customerId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7422
+ customerLastName: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
7423
+ language: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6503
7424
  /** Buyer-facing order name (e.g. `#1001`) for the server-composed "Order … Confirmed" chrome line. */
6504
- orderName: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
7425
+ orderName: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
6505
7426
  /** Ads surface label, forwarded verbatim; `customer_account` is measured/floored as its own surface (the account-area order list). */
6506
- placement: import_zod56.z.enum(["customer_account", "order_status", "thank_you_page"]),
7427
+ placement: import_zod70.z.enum(["customer_account", "order_status", "thank_you_page"]),
6507
7428
  /** Privacy Policy footer href — the Monetize widget's `privacy_policy_url` setting (React parity). */
6508
- privacyPolicyUrl: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_URL_MAX).optional(),
7429
+ privacyPolicyUrl: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_URL_MAX).optional(),
6509
7430
  /** 30-min rolling session id (React parity); used for the ads `session_id`, else the visitor id. */
6510
- sessionId: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6511
- shop: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7431
+ sessionId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7432
+ shop: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6512
7433
  /** Editor/QA indicator; OR-ed into the ads-engine `testing` flag so it stays out of billing/reporting. */
6513
- testing: import_zod56.z.boolean().optional(),
6514
- timezone: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7434
+ testing: import_zod70.z.boolean().optional(),
7435
+ timezone: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6515
7436
  /** Decorated (numeric) order id → the ads `transaction_id`. */
6516
- transactionId: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7437
+ transactionId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6517
7438
  /** Rich per-line ads items; capped at the engine's ads contract. Preferred over `cart.items`. */
6518
- transactionItems: import_zod56.z.array(MonetizeTransactionItemSchema).max(REQUEST_BOUNDS.TRANSACTION_ITEMS_MAX).optional(),
7439
+ transactionItems: import_zod70.z.array(MonetizeTransactionItemSchema).max(REQUEST_BOUNDS.TRANSACTION_ITEMS_MAX).optional(),
6519
7440
  /** Order total in presentment cents (React prefers total over subtotal); else `cart.subtotal`. */
6520
- transactionTotal: import_zod56.z.number().optional(),
6521
- visitorId: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6522
- zipCode: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
7441
+ transactionTotal: import_zod70.z.number().optional(),
7442
+ visitorId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7443
+ zipCode: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
6523
7444
  });
6524
- var WidgetSettingsInputSchema = import_zod56.z.object({
7445
+ var WidgetSettingsInputSchema = import_zod70.z.object({
6525
7446
  /**
6526
7447
  * Same domain as `CabShopConfig.cacheKey`, for the same reason: this side WINS the orchestrator's
6527
7448
  * `input.cacheKey ?? config.shop.cacheKey` (and an explicit value skips the config read entirely), so
@@ -6529,9 +7450,9 @@ var WidgetSettingsInputSchema = import_zod56.z.object({
6529
7450
  * and pin the edge copy permanently stale. `.catch(undefined)` because a bogus buster should degrade
6530
7451
  * the read to un-busted, never 400 a widget render.
6531
7452
  */
6532
- cacheKey: import_zod56.z.number().int().positive().optional().catch(void 0),
6533
- id: import_zod56.z.number(),
6534
- key: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7453
+ cacheKey: import_zod70.z.number().int().positive().optional().catch(void 0),
7454
+ id: import_zod70.z.number(),
7455
+ key: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6535
7456
  /**
6536
7457
  * Monetize context for inline hydration: when present AND the widget converts to a Monetize marker,
6537
7458
  * the server fetches/composes the offer cards inside this same request (no second `/cab/monetize`
@@ -6540,34 +7461,34 @@ var WidgetSettingsInputSchema = import_zod56.z.object({
6540
7461
  * `privacyPolicyUrl` comes from the widget settings server-side (more authoritative than a relay).
6541
7462
  */
6542
7463
  monetize: MonetizeInputSchema.omit({ privacyPolicyUrl: true, shop: true }).optional(),
6543
- shop: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7464
+ shop: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6544
7465
  /** Stable per-buyer id; when present, enables sticky server-side A/B variant selection. */
6545
- visitorId: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
7466
+ visitorId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
6546
7467
  });
6547
- var AnalyticsEventInputSchema = import_zod56.z.object({
6548
- name: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
6549
- properties: import_zod56.z.record(import_zod56.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), import_zod56.z.unknown()).optional(),
6550
- sentAt: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
7468
+ var AnalyticsEventInputSchema = import_zod70.z.object({
7469
+ name: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
7470
+ properties: import_zod70.z.record(import_zod70.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), import_zod70.z.unknown()).optional(),
7471
+ sentAt: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
6551
7472
  });
6552
- var AnalyticsSegmentsInputSchema = import_zod56.z.object({
6553
- device: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
6554
- source: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
6555
- visitor: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0)
7473
+ var AnalyticsSegmentsInputSchema = import_zod70.z.object({
7474
+ device: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
7475
+ source: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
7476
+ visitor: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0)
6556
7477
  });
6557
- var AnalyticsInputSchema = import_zod56.z.object({
7478
+ var AnalyticsInputSchema = import_zod70.z.object({
6558
7479
  /** Rebuy cart token (the `r_cart_token` cart attribute), when available — primary aggregation key. */
6559
- cartToken: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7480
+ cartToken: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6560
7481
  /** Shopify checkout token, when available — drives cart/checkout aggregation downstream. */
6561
- checkoutToken: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6562
- events: import_zod56.z.array(AnalyticsEventInputSchema).max(REQUEST_BOUNDS.EVENTS_MAX),
7482
+ checkoutToken: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7483
+ events: import_zod70.z.array(AnalyticsEventInputSchema).max(REQUEST_BOUNDS.EVENTS_MAX),
6563
7484
  /**
6564
7485
  * Request-scoped like the tokens: one visitor's segments apply to every event in the batch. The container
6565
7486
  * degrades too (`null` is a realistic wire artifact of `attributes ? {…} : null`), so the degrade rule is
6566
7487
  * total: nothing about `segments` can cost the envelope.
6567
7488
  */
6568
7489
  segments: AnalyticsSegmentsInputSchema.optional().catch(void 0),
6569
- shop: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6570
- visitorId: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7490
+ shop: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7491
+ visitorId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6571
7492
  /** The widget id (smartBlockId) the events belong to. */
6572
- widgetId: import_zod56.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
7493
+ widgetId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
6573
7494
  });