@rebuy/rebuy 3.26.0 → 3.28.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 +902 -750
  2. package/dist/index.mjs +901 -749
  3. package/dist/schema/checkout-and-beyond/constants.cjs +5 -0
  4. package/dist/schema/checkout-and-beyond/constants.mjs +5 -0
  5. package/dist/schema/checkout-and-beyond/index.cjs +97 -68
  6. package/dist/schema/checkout-and-beyond/index.mjs +97 -68
  7. package/dist/schema/index.d.ts +6 -0
  8. package/dist/schema/postPurchaseEligibility.d.ts +2 -2
  9. package/dist/schema/postPurchaseExitPolicy.d.ts +20 -0
  10. package/dist/schema/postPurchaseIdentity.d.ts +9 -0
  11. package/dist/schema/postPurchaseOrderDecision.d.ts +10 -0
  12. package/dist/schema/postPurchasePolicy.d.ts +62 -0
  13. package/dist/schema/postPurchaseSelection.d.ts +29 -0
  14. package/dist/schema/postPurchaseSession.d.ts +112 -0
  15. package/dist/schema/postPurchaseSessionClose.d.ts +25 -0
  16. package/dist/schema/postPurchaseShadow.d.ts +56 -1
  17. package/dist/schema/postPurchaseSkipTrace.d.ts +2 -2
  18. package/dist/schema/widget-data.cjs +160 -135
  19. package/dist/schema/widget-data.mjs +160 -135
  20. package/dist/schema/widgetData.d.ts +24 -0
  21. package/dist/schema/widgets/checkout-and-beyond/banner.d.ts +8 -0
  22. package/dist/schema/widgets/checkout-and-beyond/carousel.d.ts +8 -0
  23. package/dist/schema/widgets/checkout-and-beyond/cartLine.d.ts +8 -0
  24. package/dist/schema/widgets/checkout-and-beyond/common.d.ts +13 -1
  25. package/dist/schema/widgets/checkout-and-beyond/index.d.ts +1 -0
  26. package/dist/schema/widgets/checkout-and-beyond/layout.d.ts +17 -1
  27. package/dist/schema/widgets/checkout-and-beyond/offers.d.ts +8 -0
  28. package/dist/schema/widgets/checkout-and-beyond/progressBar.d.ts +8 -0
  29. package/dist/schema/widgets/checkout-and-beyond/reviews.d.ts +2 -0
  30. package/dist/schema/widgets/checkout-and-beyond/root.d.ts +8 -0
  31. package/dist/schema/widgets/checkout-and-beyond/separator.d.ts +192 -0
  32. package/dist/schema/widgets/checkout-and-beyond/shared.d.ts +2 -1
  33. package/dist/schema/widgets/contentBlock.d.ts +8 -0
  34. package/dist/schema/widgets/lineItemEditor.d.ts +8 -0
  35. package/dist/schema/widgets/post-purchase-offer/constants.d.ts +2 -2
  36. package/dist/schema/widgets/rebuyButton.d.ts +8 -0
  37. package/dist/server/index.cjs +601 -188
  38. package/dist/server/index.mjs +601 -188
  39. package/dist/server/requestSchemas.d.ts +1 -1
  40. package/dist/transforms/index.cjs +481 -59
  41. package/dist/transforms/index.d.ts +2 -0
  42. package/dist/transforms/index.mjs +481 -59
  43. package/dist/transforms/postPurchase/convertCalloutBlock.d.ts +8 -0
  44. package/dist/transforms/postPurchase/convertMessagePreview.d.ts +8 -0
  45. package/dist/transforms/postPurchase/convertPayButtonBlock.d.ts +4 -0
  46. package/dist/transforms/postPurchase/convertSeparatorBlock.d.ts +4 -0
  47. package/dist/transforms/postPurchase/convertTextBlock.d.ts +4 -0
  48. package/dist/transforms/postPurchase/convertTimerBlock.d.ts +4 -0
  49. package/dist/transforms/postPurchase/styledTextRun.d.ts +3 -0
  50. package/dist/transforms/postPurchase/types.d.ts +8 -0
  51. package/package.json +1 -1
@@ -674,8 +674,8 @@ var CabUserConfig = import_zod6.z.object({
674
674
  });
675
675
 
676
676
  // src/schema/widgets/checkout-and-beyond/image.ts
677
- var import_uuid12 = require("uuid");
678
- var import_zod26 = require("zod");
677
+ var import_uuid13 = require("uuid");
678
+ var import_zod27 = require("zod");
679
679
 
680
680
  // src/schema/widgets/checkout-and-beyond/common.ts
681
681
  var freezeEnum = (values) => Object.freeze(Object.fromEntries(values.map((v) => [v, v])));
@@ -784,6 +784,8 @@ var languageKeys = [
784
784
  "zh"
785
785
  ];
786
786
  var LanguageKey = freezeEnum(languageKeys);
787
+ var layoutFrames = ["callout", "offer-content"];
788
+ var LayoutFrame = freezeEnum(layoutFrames);
787
789
  var mutatorEvents = ["item_added", "quantity_changed", "variant_selected"];
788
790
  var MutatorEvent = freezeEnum(mutatorEvents);
789
791
  var objectFits = ["cover", "contain"];
@@ -822,6 +824,7 @@ var sectionTypes = [
822
824
  "progressBar",
823
825
  "quantity",
824
826
  "reviews",
827
+ "separator",
825
828
  "text",
826
829
  "variants"
827
830
  ];
@@ -965,7 +968,7 @@ var ROOT_RELATIVE_PATH_REGEX = /^\/(?!\/)/;
965
968
  var HTML_TAGS_REGEX = /<\/?[a-zA-Z][^>]*>/g;
966
969
 
967
970
  // src/schema/widgets/checkout-and-beyond/shared.ts
968
- var import_zod25 = require("zod");
971
+ var import_zod26 = require("zod");
969
972
 
970
973
  // src/schema/widgets/checkout-and-beyond/banner.ts
971
974
  var import_zod10 = require("zod");
@@ -1120,6 +1123,10 @@ var CABVariableFields = {
1120
1123
 
1121
1124
  // src/schema/widgets/checkout-and-beyond/layout.ts
1122
1125
  var GridItem = import_zod9.z.union([import_zod9.z.literal("auto"), import_zod9.z.literal("fill"), import_zod9.z.string().regex(/^\d+%$/), import_zod9.z.number()]);
1126
+ var CABLayoutWrapping = import_zod9.z.object({
1127
+ breakAt: import_zod9.z.number().positive(),
1128
+ maxPerLine: import_zod9.z.number().int().positive()
1129
+ });
1123
1130
  var CABLayoutSection = import_zod9.z.object({
1124
1131
  ...CABVariableFields,
1125
1132
  alignment: import_zod9.z.object({
@@ -1132,6 +1139,11 @@ var CABLayoutSection = import_zod9.z.object({
1132
1139
  border: import_zod9.z.lazy(() => CABBorder),
1133
1140
  buttonField: import_zod9.z.enum(buttonFields).optional(),
1134
1141
  direction: import_zod9.z.enum(directions).default(Direction.rows),
1142
+ /**
1143
+ * Platform chrome around the section, not a layout behavior: `callout` is a subdued box with block borders
1144
+ * (the legacy post-purchase callout banner), `offer-content` the post-purchase offer's own content card.
1145
+ */
1146
+ frame: import_zod9.z.enum(layoutFrames).optional(),
1135
1147
  grid: import_zod9.z.object({
1136
1148
  columns: import_zod9.z.union([import_zod9.z.array(GridItem), import_zod9.z.undefined()]).default(() => ["auto"]),
1137
1149
  rows: import_zod9.z.union([import_zod9.z.array(GridItem), import_zod9.z.undefined()]).default(() => ["auto"])
@@ -1144,7 +1156,8 @@ var CABLayoutSection = import_zod9.z.object({
1144
1156
  spacing: import_zod9.z.enum(spacings).default(Spacing.base),
1145
1157
  /** Fire-and-forget impression pixel POSTed once when the section is shown (e.g. a Monetize offer view). */
1146
1158
  viewUrl: import_zod9.z.string().optional(),
1147
- width: import_zod9.z.number().default(100)
1159
+ width: import_zod9.z.number().default(100),
1160
+ wrapping: CABLayoutWrapping.optional()
1148
1161
  });
1149
1162
 
1150
1163
  // src/schema/widgets/checkout-and-beyond/utils.ts
@@ -2008,35 +2021,46 @@ var CABReviewsSection = import_zod23.z.object({
2008
2021
  name: import_zod23.z.string().optional(),
2009
2022
  sectionId: import_zod23.z.uuid().default(() => (0, import_uuid10.v7)()),
2010
2023
  sectionType: import_zod23.z.literal(SectionType.reviews).default(SectionType.reviews),
2011
- size: import_zod23.z.enum(reviewsSizes).default(ReviewsSize.default)
2024
+ size: import_zod23.z.enum(reviewsSizes).default(ReviewsSize.default),
2025
+ strokeColor: import_zod23.z.string().default("#fadb14"),
2026
+ strokeWidth: import_zod23.z.number().nonnegative().default(0)
2012
2027
  });
2013
2028
 
2014
- // src/schema/widgets/checkout-and-beyond/variants.ts
2015
- var import_compat3 = require("es-toolkit/compat");
2029
+ // src/schema/widgets/checkout-and-beyond/separator.ts
2016
2030
  var import_uuid11 = require("uuid");
2017
2031
  var import_zod24 = require("zod");
2018
- var CABVariantsSection = import_zod24.z.object({
2032
+ var CABSeparatorSection = import_zod24.z.object({
2019
2033
  ...CABVariableFields,
2020
- hideOutOfStockVariants: import_zod24.z.boolean().default(false),
2021
- name: import_zod24.z.string().optional(),
2022
2034
  sectionId: import_zod24.z.uuid().default(() => (0, import_uuid11.v7)()),
2023
- sectionType: import_zod24.z.literal(SectionType.variants).default(SectionType.variants),
2024
- selector: import_zod24.z.enum((0, import_compat3.slice)(variantSelectors, 0, 3)).default(VariantSelector.menu),
2025
- variantMode: import_zod24.z.enum(variantModes).default(VariantMode.multiple)
2035
+ sectionType: import_zod24.z.literal(SectionType.separator).default(SectionType.separator)
2036
+ });
2037
+
2038
+ // src/schema/widgets/checkout-and-beyond/variants.ts
2039
+ var import_compat3 = require("es-toolkit/compat");
2040
+ var import_uuid12 = require("uuid");
2041
+ var import_zod25 = require("zod");
2042
+ var CABVariantsSection = import_zod25.z.object({
2043
+ ...CABVariableFields,
2044
+ hideOutOfStockVariants: import_zod25.z.boolean().default(false),
2045
+ name: import_zod25.z.string().optional(),
2046
+ sectionId: import_zod25.z.uuid().default(() => (0, import_uuid12.v7)()),
2047
+ sectionType: import_zod25.z.literal(SectionType.variants).default(SectionType.variants),
2048
+ selector: import_zod25.z.enum((0, import_compat3.slice)(variantSelectors, 0, 3)).default(VariantSelector.menu),
2049
+ variantMode: import_zod25.z.enum(variantModes).default(VariantMode.multiple)
2026
2050
  });
2027
2051
 
2028
2052
  // src/schema/widgets/checkout-and-beyond/shared.ts
2029
- var CABBorder = import_zod25.z.object({
2030
- radius: import_zod25.z.enum(borderRadii).default(BorderRadius.base),
2031
- style: import_zod25.z.enum(borderStyles).default(BorderStyle.none),
2032
- width: import_zod25.z.enum(borderWidths).default(BorderWidth.base)
2053
+ var CABBorder = import_zod26.z.object({
2054
+ radius: import_zod26.z.enum(borderRadii).default(BorderRadius.base),
2055
+ style: import_zod26.z.enum(borderStyles).default(BorderStyle.none),
2056
+ width: import_zod26.z.enum(borderWidths).default(BorderWidth.base)
2033
2057
  }).default({
2034
2058
  radius: BorderRadius.base,
2035
2059
  style: BorderStyle.none,
2036
2060
  width: BorderWidth.base
2037
2061
  });
2038
- var CABSection = import_zod25.z.lazy(
2039
- () => import_zod25.z.discriminatedUnion("sectionType", [
2062
+ var CABSection = import_zod26.z.lazy(
2063
+ () => import_zod26.z.discriminatedUnion("sectionType", [
2040
2064
  CABBannerSection,
2041
2065
  CABButtonSection,
2042
2066
  CABCarouselSection,
@@ -2052,23 +2076,24 @@ var CABSection = import_zod25.z.lazy(
2052
2076
  CABProgressBarSection,
2053
2077
  CABQuantitySection,
2054
2078
  CABReviewsSection,
2079
+ CABSeparatorSection,
2055
2080
  CABTextSection,
2056
2081
  CABVariantsSection
2057
2082
  ])
2058
2083
  );
2059
2084
 
2060
2085
  // src/schema/widgets/checkout-and-beyond/image.ts
2061
- var CABImageSectionFields = import_zod26.z.object({
2086
+ var CABImageSectionFields = import_zod27.z.object({
2062
2087
  ...CABVariableFields,
2063
- altText: import_zod26.z.string().refine(checkForHTML, NO_HTML).default(""),
2088
+ altText: import_zod27.z.string().refine(checkForHTML, NO_HTML).default(""),
2064
2089
  /**
2065
2090
  * Image width÷height (e.g. `46` for the progress-bar fill); `null` renders at natural size. Any POSITIVE
2066
2091
  * ratio — never limited to 1, but never `0`/negative either: a renderer dividing by it would get `Infinity`,
2067
2092
  * and CSS `aspect-ratio` drops a negative value and silently reverts to natural size.
2068
2093
  */
2069
- aspectRatio: import_zod26.z.number().positive().nullable().default(null),
2070
- border: import_zod26.z.lazy(() => CABBorder),
2071
- buttonField: import_zod26.z.enum(buttonFields).optional(),
2094
+ aspectRatio: import_zod27.z.number().positive().nullable().default(null),
2095
+ border: import_zod27.z.lazy(() => CABBorder),
2096
+ buttonField: import_zod27.z.enum(buttonFields).optional(),
2072
2097
  /**
2073
2098
  * `icon` renders `source` as a single `s-icon` by name (the uber-image path covers icons too), reading
2074
2099
  * `iconSize`/`iconTone`. The other values are a harmless informational holdover from the previous
@@ -2087,29 +2112,29 @@ var CABImageSectionFields = import_zod26.z.object({
2087
2112
  * behavior degraded gracefully and told us about it. The client-assembled half of the invariant was never
2088
2113
  * the risky half.
2089
2114
  */
2090
- category: import_zod26.z.enum(["gallery", "icon", "icons", "payment-methods", "secure-checkout"]).nullable().default(null),
2115
+ category: import_zod27.z.enum(["gallery", "icon", "icons", "payment-methods", "secure-checkout"]).nullable().default(null),
2091
2116
  /** `icon`-mode only: the `s-icon` `size`; `null` ⇒ the component default (`base`). Ignored by image treatments. */
2092
- iconSize: import_zod26.z.enum(iconSizes).nullable().default(null),
2117
+ iconSize: import_zod27.z.enum(iconSizes).nullable().default(null),
2093
2118
  /** `icon`-mode only: the `s-icon` `tone`; `null` ⇒ the component default (`auto`). Ignored by image treatments. */
2094
- iconTone: import_zod26.z.enum(iconTones).nullable().default(null),
2095
- name: import_zod26.z.string().optional(),
2096
- naturalHeight: import_zod26.z.number().default(0),
2097
- naturalWidth: import_zod26.z.number().default(0),
2119
+ iconTone: import_zod27.z.enum(iconTones).nullable().default(null),
2120
+ name: import_zod27.z.string().optional(),
2121
+ naturalHeight: import_zod27.z.number().default(0),
2122
+ naturalWidth: import_zod27.z.number().default(0),
2098
2123
  /**
2099
2124
  * `contain` (the component default): dimensionless images render in s-image's 1/1 default frame, and
2100
2125
  * `cover` would crop non-square art (payment badges lost their edges — 15993); `contain` letterboxes.
2101
2126
  */
2102
- objectFit: import_zod26.z.enum(objectFits).default(ObjectFit.contain),
2103
- sectionId: import_zod26.z.uuid().default(() => (0, import_uuid12.v7)()),
2104
- sectionType: import_zod26.z.literal(SectionType.image).default(SectionType.image),
2127
+ objectFit: import_zod27.z.enum(objectFits).default(ObjectFit.contain),
2128
+ sectionId: import_zod27.z.uuid().default(() => (0, import_uuid13.v7)()),
2129
+ sectionType: import_zod27.z.literal(SectionType.image).default(SectionType.image),
2105
2130
  /**
2106
2131
  * An image URL or dynamic token, an empty default, or — when `category: 'icon'` — an icon NAME. Icon mode
2107
2132
  * takes a name or `''` only, NOT a token: no renderer resolves a token to an icon today, so accepting one
2108
2133
  * would promise a capability that doesn't exist. Widen the refine's carve-out to `DYNAMIC_TOKEN_REGEX` when a
2109
2134
  * server-chosen tier icon actually needs it.
2110
2135
  */
2111
- source: import_zod26.z.union([import_zod26.z.url(), import_zod26.z.literal(""), import_zod26.z.string().regex(DYNAMIC_TOKEN_REGEX), import_zod26.z.enum(iconNames)]).default(""),
2112
- width: import_zod26.z.number().default(100)
2136
+ source: import_zod27.z.union([import_zod27.z.url(), import_zod27.z.literal(""), import_zod27.z.string().regex(DYNAMIC_TOKEN_REGEX), import_zod27.z.enum(iconNames)]).default(""),
2137
+ width: import_zod27.z.number().default(100)
2113
2138
  });
2114
2139
  var iconNameSet = new Set(iconNames);
2115
2140
  var isIconName = (source) => iconNameSet.has(source);
@@ -2260,7 +2285,7 @@ var convertContentBlockTextToV2 = (language, text2 = literalText, textAlign = "c
2260
2285
  };
2261
2286
 
2262
2287
  // src/schema/widgets/checkout-and-beyond/root.ts
2263
- var import_zod27 = require("zod");
2288
+ var import_zod28 = require("zod");
2264
2289
 
2265
2290
  // src/schema/widgets/checkout-and-beyond/uiLabels.ts
2266
2291
  var UI_LABELS = {
@@ -2280,8 +2305,8 @@ var UI_LABELS = {
2280
2305
  };
2281
2306
 
2282
2307
  // src/schema/widgets/checkout-and-beyond/root.ts
2283
- var localized = (fallback) => import_zod27.z.record(import_zod27.z.string(), import_zod27.z.string()).default(() => ({ ...fallback })).transform((labels) => Object.keys(labels).length > 0 ? labels : { ...fallback });
2284
- var CABUILabels = import_zod27.z.object({
2308
+ var localized = (fallback) => import_zod28.z.record(import_zod28.z.string(), import_zod28.z.string()).default(() => ({ ...fallback })).transform((labels) => Object.keys(labels).length > 0 ? labels : { ...fallback });
2309
+ var CABUILabels = import_zod28.z.object({
2285
2310
  currentPage: localized(UI_LABELS.currentPage),
2286
2311
  guest: localized(UI_LABELS.guest),
2287
2312
  loadingOptions: localized(UI_LABELS.loadingOptions),
@@ -2306,37 +2331,37 @@ var CABUILabels = import_zod27.z.object({
2306
2331
  subscriptionOptions: { ...UI_LABELS.subscriptionOptions },
2307
2332
  updating: { ...UI_LABELS.updating }
2308
2333
  }));
2309
- var TargetArea = import_zod27.z.object({
2310
- fill: import_zod27.z.boolean().optional(),
2311
- flip: import_zod27.z.enum(["both", "horizontal", "vertical"]).optional(),
2312
- icon: import_zod27.z.string(),
2313
- label: import_zod27.z.string(),
2314
- width: import_zod27.z.string()
2334
+ var TargetArea = import_zod28.z.object({
2335
+ fill: import_zod28.z.boolean().optional(),
2336
+ flip: import_zod28.z.enum(["both", "horizontal", "vertical"]).optional(),
2337
+ icon: import_zod28.z.string(),
2338
+ label: import_zod28.z.string(),
2339
+ width: import_zod28.z.string()
2315
2340
  }).default(targetAreas[EditorMode.checkoutExtension][1]);
2316
- var CABTracking = import_zod27.z.object({
2317
- enableAttribution: import_zod27.z.boolean().nullish().transform((value) => value ?? true),
2318
- enableSource: import_zod27.z.boolean().nullish().transform((value) => value ?? true),
2319
- enableWidget: import_zod27.z.boolean().nullish().transform((value) => value ?? true)
2341
+ var CABTracking = import_zod28.z.object({
2342
+ enableAttribution: import_zod28.z.boolean().nullish().transform((value) => value ?? true),
2343
+ enableSource: import_zod28.z.boolean().nullish().transform((value) => value ?? true),
2344
+ enableWidget: import_zod28.z.boolean().nullish().transform((value) => value ?? true)
2320
2345
  }).nullish().transform((value) => value ?? { enableAttribution: true, enableSource: true, enableWidget: true });
2321
- var CABExperiment = import_zod27.z.object({
2322
- elementId: import_zod27.z.number(),
2323
- experimentId: import_zod27.z.number(),
2324
- experimentType: import_zod27.z.string(),
2325
- selectedId: import_zod27.z.number()
2346
+ var CABExperiment = import_zod28.z.object({
2347
+ elementId: import_zod28.z.number(),
2348
+ experimentId: import_zod28.z.number(),
2349
+ experimentType: import_zod28.z.string(),
2350
+ selectedId: import_zod28.z.number()
2326
2351
  });
2327
2352
  var CABRootSection = CABLayoutSection.extend({
2328
- editorMode: import_zod27.z.enum(editorModes).default(EditorMode.checkoutExtension),
2353
+ editorMode: import_zod28.z.enum(editorModes).default(EditorMode.checkoutExtension),
2329
2354
  experiment: CABExperiment.optional(),
2330
2355
  // Same rule as CABTracking above: the v1 converters pass raw legacy `previewMode` through, so a
2331
2356
  // `null` must fall back rather than throw the widget; malformed values still throw.
2332
- previewMode: import_zod27.z.boolean().nullish().transform((value) => value ?? false),
2333
- storeId: import_zod27.z.number().nullable().default(null),
2357
+ previewMode: import_zod28.z.boolean().nullish().transform((value) => value ?? false),
2358
+ storeId: import_zod28.z.number().nullable().default(null),
2334
2359
  targetArea: TargetArea.nullable(),
2335
2360
  tracking: CABTracking,
2336
- type: import_zod27.z.enum(widgetTypes).default(WidgetType.ui_extension_content_block),
2361
+ type: import_zod28.z.enum(widgetTypes).default(WidgetType.ui_extension_content_block),
2337
2362
  uiLabels: CABUILabels,
2338
- version: import_zod27.z.literal(2).default(2),
2339
- widgetId: import_zod27.z.number().nullable().default(null)
2363
+ version: import_zod28.z.literal(2).default(2),
2364
+ widgetId: import_zod28.z.number().nullable().default(null)
2340
2365
  });
2341
2366
 
2342
2367
  // src/transforms/v1Location.ts
@@ -3745,6 +3770,393 @@ var convertOfferToV2 = ({ id, name, settings }) => {
3745
3770
  // src/transforms/parseShielded.ts
3746
3771
  var parseShielded = (schema, raw, transform = (input) => input) => schema.parse(transform(convertNumericObjects(deepCamelCase(raw))));
3747
3772
 
3773
+ // src/transforms/postPurchase/convertMessagePreview.ts
3774
+ var import_zod33 = require("zod");
3775
+
3776
+ // src/transforms/postPurchase/convertCalloutBlock.ts
3777
+ var import_zod31 = require("zod");
3778
+
3779
+ // src/schema/widgets/post-purchase-offer/postPurchaseBlocks.ts
3780
+ var import_compat4 = require("es-toolkit/compat");
3781
+ var import_uuid14 = require("uuid");
3782
+ var import_zod30 = require("zod");
3783
+
3784
+ // src/schema/widgets/post-purchase-offer/constants.ts
3785
+ var import_zod29 = require("zod");
3786
+ var blockTypes = [
3787
+ "callout_banner",
3788
+ "image",
3789
+ "image_content",
3790
+ "pay_button",
3791
+ "product_information",
3792
+ "separator",
3793
+ "text",
3794
+ "timer"
3795
+ ];
3796
+ var blockType = import_zod29.z.enum(blockTypes);
3797
+ var BlockType = blockType.enum;
3798
+
3799
+ // src/schema/widgets/post-purchase-offer/postPurchaseBlocks.ts
3800
+ var TextAlignment2 = import_zod30.z.union([import_zod30.z.enum(["leading", "center", "trailing"]), import_zod30.z.unknown().transform(() => "leading")]);
3801
+ var TextSize = import_zod30.z.union([
3802
+ import_zod30.z.enum(["xsmall", "small", "base", "default", "medium", "large", "xlarge"]),
3803
+ import_zod30.z.unknown().transform(() => "medium")
3804
+ ]);
3805
+ var CalloutBannerBlock = import_zod30.z.object({
3806
+ id: import_zod30.z.string().optional().default(() => (0, import_uuid14.v4)()),
3807
+ name: import_zod30.z.string().optional(),
3808
+ settings: import_zod30.z.object({
3809
+ superTitle: import_zod30.z.union([import_zod30.z.string(), TiptapDocument]).default(() => "Limited-time Offer"),
3810
+ title: import_zod30.z.union([import_zod30.z.string(), TiptapDocument]).default(() => "Add this customer favorite to your order")
3811
+ }),
3812
+ styles: import_zod30.z.object({
3813
+ superTitleEmphasized: import_zod30.z.boolean().default(false),
3814
+ superTitleSize: TextSize.default("large"),
3815
+ textAlignment: TextAlignment2.default("center"),
3816
+ titleEmphasized: import_zod30.z.boolean().default(true),
3817
+ titleSize: TextSize.default("large")
3818
+ }),
3819
+ type: import_zod30.z.literal(BlockType.callout_banner).default(BlockType.callout_banner)
3820
+ });
3821
+ var ImageBlock = import_zod30.z.object({
3822
+ id: import_zod30.z.string().optional().default(() => (0, import_uuid14.v4)()),
3823
+ name: import_zod30.z.string().optional(),
3824
+ settings: import_zod30.z.union([
3825
+ import_zod30.z.object({
3826
+ /** This isn't used in the post-purchase offer widget */
3827
+ alt: import_zod30.z.string().optional().default(""),
3828
+ image: import_zod30.z.union([import_zod30.z.literal(""), import_zod30.z.url()]).default(""),
3829
+ imageSize: import_zod30.z.number().default(20),
3830
+ imageType: import_zod30.z.enum(["URL", "UPLOAD"]).default("URL")
3831
+ }),
3832
+ import_zod30.z.array(import_zod30.z.never()).transform(() => ({}))
3833
+ ]),
3834
+ type: import_zod30.z.literal(BlockType.image).default(BlockType.image)
3835
+ });
3836
+ var ImageContentBlock = import_zod30.z.object({
3837
+ id: import_zod30.z.string().optional().default(() => (0, import_uuid14.v4)()),
3838
+ name: import_zod30.z.string().optional(),
3839
+ settings: import_zod30.z.object({
3840
+ alt: import_zod30.z.string().optional().default(""),
3841
+ description: import_zod30.z.union([import_zod30.z.string(), TiptapDocument, import_zod30.z.null()]).default(
3842
+ "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
3843
+ ),
3844
+ descriptionSize: TextSize.default("medium"),
3845
+ horizontalAlignment: TextAlignment2.default("leading"),
3846
+ image: import_zod30.z.union([import_zod30.z.literal(""), import_zod30.z.url()]).default(""),
3847
+ imagePlacement: import_zod30.z.enum(["bottom", "left", "right", "top"]).optional().default("left"),
3848
+ imageSize: import_zod30.z.number().default(20),
3849
+ superTitle: import_zod30.z.union([import_zod30.z.string(), TiptapDocument]).default("Lorem Ipsum!"),
3850
+ superTitleSize: TextSize.default("medium"),
3851
+ /** This isn't configurable in the admin-nextjs editor */
3852
+ swapContent: import_zod30.z.boolean().optional().default(false),
3853
+ title: import_zod30.z.union([import_zod30.z.string(), TiptapDocument]).nullable().default("Lorem ipsum dolor sit amet"),
3854
+ titleSize: TextSize.default("medium")
3855
+ }),
3856
+ type: import_zod30.z.literal(BlockType.image_content).default(BlockType.image_content)
3857
+ });
3858
+ var PayButtonBlock = import_zod30.z.object({
3859
+ id: import_zod30.z.string().optional().default(() => (0, import_uuid14.v4)()),
3860
+ name: import_zod30.z.string().optional(),
3861
+ settings: import_zod30.z.union([
3862
+ import_zod30.z.object({
3863
+ label: import_zod30.z.string().default("Pay Now")
3864
+ }),
3865
+ import_zod30.z.array(import_zod30.z.never()).transform(() => ({
3866
+ label: "Pay Now"
3867
+ }))
3868
+ ]),
3869
+ styles: import_zod30.z.union([
3870
+ import_zod30.z.object({
3871
+ buttonWidth: import_zod30.z.number().min(10).max(100).default(50)
3872
+ }),
3873
+ import_zod30.z.array(import_zod30.z.never()).transform(() => ({
3874
+ buttonWidth: 50
3875
+ }))
3876
+ ]),
3877
+ type: import_zod30.z.literal(BlockType.pay_button).default(BlockType.pay_button)
3878
+ });
3879
+ var ProductInformationBlock = import_zod30.z.object({
3880
+ /** This isn't configurable in the admin-nextjs editor */
3881
+ hideProductImage: import_zod30.z.boolean().optional().default(false),
3882
+ id: import_zod30.z.string().optional().default(() => (0, import_uuid14.v4)()),
3883
+ name: import_zod30.z.string().optional(),
3884
+ type: import_zod30.z.literal(BlockType.product_information).default(BlockType.product_information)
3885
+ });
3886
+ var SeparatorBlock = import_zod30.z.object({
3887
+ id: import_zod30.z.string().optional().default(() => (0, import_uuid14.v4)()),
3888
+ name: import_zod30.z.string().optional(),
3889
+ type: import_zod30.z.literal(BlockType.separator).default(BlockType.separator)
3890
+ });
3891
+ var TextBlock = import_zod30.z.object({
3892
+ id: import_zod30.z.string().optional().default(() => (0, import_uuid14.v4)()),
3893
+ name: import_zod30.z.string().optional(),
3894
+ settings: import_zod30.z.object({
3895
+ description: import_zod30.z.union([import_zod30.z.string(), TiptapDocument]).optional().default(
3896
+ "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
3897
+ ),
3898
+ /** This isn't used in the post-purchase offer widget */
3899
+ descriptionSize: TextSize.default("medium"),
3900
+ horizontalAlignment: TextAlignment2.default("leading"),
3901
+ superTitle: import_zod30.z.union([import_zod30.z.string(), TiptapDocument]).default("Super Title"),
3902
+ /** This isn't used in the post-purchase offer widget */
3903
+ superTitleSize: TextSize.default("medium"),
3904
+ title: import_zod30.z.union([import_zod30.z.string(), TiptapDocument]).nullable().default("Lorem ipsum dolor sit amet."),
3905
+ /** This isn't used in the post-purchase offer widget */
3906
+ titleSize: TextSize.default("medium")
3907
+ }),
3908
+ type: import_zod30.z.literal(BlockType.text).default(BlockType.text)
3909
+ });
3910
+ var TimerBlock = import_zod30.z.object({
3911
+ id: import_zod30.z.string().optional().default(() => (0, import_uuid14.v4)()),
3912
+ name: import_zod30.z.string().optional(),
3913
+ settings: import_zod30.z.object({
3914
+ durationMinutes: import_zod30.z.number().min(0).default(10),
3915
+ durationSeconds: import_zod30.z.union([import_zod30.z.number().min(0), import_zod30.z.unknown().transform(() => 0)]).default(0),
3916
+ endOffer: import_zod30.z.boolean().default(true),
3917
+ title: import_zod30.z.union([import_zod30.z.string(), TiptapDocument]).default("Hurry \u2014 your special offer ends in:")
3918
+ }),
3919
+ styles: import_zod30.z.object({
3920
+ textAlignment: TextAlignment2.default("center"),
3921
+ timerBackgroundColor: import_zod30.z.enum(["info", "warning", "success", "critical"]).default("warning"),
3922
+ timerEmphasized: import_zod30.z.union([import_zod30.z.boolean(), import_zod30.z.unknown().transform(() => true)]).default(true),
3923
+ timerSize: TextSize.default("medium"),
3924
+ timerWidth: import_zod30.z.number().min(10).max(100).optional().default(100),
3925
+ titleEmphasized: import_zod30.z.union([import_zod30.z.boolean(), import_zod30.z.unknown().transform(() => true)]).default(false),
3926
+ titleSize: TextSize.default("medium")
3927
+ }),
3928
+ type: import_zod30.z.literal(BlockType.timer).default(BlockType.timer)
3929
+ });
3930
+ var PostPurchaseBlock = import_zod30.z.discriminatedUnion("type", [
3931
+ CalloutBannerBlock,
3932
+ ImageBlock,
3933
+ ImageContentBlock,
3934
+ PayButtonBlock,
3935
+ ProductInformationBlock,
3936
+ SeparatorBlock,
3937
+ TextBlock,
3938
+ TimerBlock
3939
+ ]);
3940
+
3941
+ // src/transforms/postPurchase/styledTextRun.ts
3942
+ var sizes = {
3943
+ base: "base",
3944
+ default: "base",
3945
+ large: "large",
3946
+ medium: "medium",
3947
+ small: "small",
3948
+ xlarge: "extraLarge",
3949
+ xsmall: "extraSmall"
3950
+ };
3951
+ var styledTextRun = (text2, emphasized, size) => ({
3952
+ marks: [
3953
+ ...emphasized ? [{ type: "bold" }] : [],
3954
+ { attrs: { color: "base", fontSize: sizes[size] }, type: "textStyle" }
3955
+ ],
3956
+ text: text2,
3957
+ type: "text"
3958
+ });
3959
+
3960
+ // src/transforms/postPurchase/convertCalloutBlock.ts
3961
+ var fields = ["superTitle", "title"];
3962
+ var Shell = CalloutBannerBlock.pick({ styles: true }).extend({
3963
+ settings: import_zod31.z.object({ superTitle: import_zod31.z.unknown().optional(), title: import_zod31.z.unknown().optional() })
3964
+ });
3965
+ var convertCalloutBlock = (raw, report) => {
3966
+ const omit = (detail) => {
3967
+ report?.({ detail, kind: "section" });
3968
+ return [];
3969
+ };
3970
+ const shell = Shell.safeParse(raw);
3971
+ if (!shell.success) return omit("Unreadable post-purchase callout");
3972
+ const values = fields.map((field) => ({
3973
+ field,
3974
+ result: CalloutBannerBlock.shape.settings.shape[field].safeParse(shell.data.settings[field])
3975
+ }));
3976
+ const styled2 = values.every(({ result }) => result.success && typeof result.data === "string");
3977
+ const styles2 = shell.data.styles;
3978
+ const horizontal = styled2 ? { center: "center", leading: "start", trailing: "end" }[styles2.textAlignment] : "center";
3979
+ const sections = values.flatMap(({ field, result }) => {
3980
+ if (!result.success) return omit(`Unreadable post-purchase callout field: ${field}`);
3981
+ const text2 = result.data;
3982
+ if (text2 === "") return [];
3983
+ const content = styled2 && typeof text2 === "string" ? {
3984
+ content: [
3985
+ {
3986
+ attrs: { textAlign: horizontal },
3987
+ content: [styledTextRun(text2, styles2[`${field}Emphasized`], styles2[`${field}Size`])]
3988
+ }
3989
+ ]
3990
+ } : text2;
3991
+ const section = CABTextSection.safeParse({ content: { en: content } });
3992
+ return section.success ? [section.data] : omit(`Unreadable post-purchase callout field: ${field}`);
3993
+ });
3994
+ return sections.length ? [CABLayoutSection.parse({ alignment: { horizontal }, frame: "callout", sections })] : [];
3995
+ };
3996
+
3997
+ // src/transforms/postPurchase/convertPayButtonBlock.ts
3998
+ var convertPayButtonBlock = (raw, report) => {
3999
+ const omit = () => {
4000
+ report?.({ detail: "Unreadable post-purchase Pay block", kind: "section" });
4001
+ return [];
4002
+ };
4003
+ const parsed = PayButtonBlock.safeParse(raw);
4004
+ if (!parsed.success) return omit();
4005
+ const { settings, styles: styles2 } = parsed.data;
4006
+ const label2 = settings.label ? `${settings.label} \xB7 {{total}}` : "{{total}}";
4007
+ const text2 = CABTextSection.safeParse({ content: { en: label2 } });
4008
+ if (!text2.success) return omit();
4009
+ return [
4010
+ CABLayoutSection.parse({
4011
+ alignment: { horizontal: "center" },
4012
+ direction: "grid",
4013
+ grid: { columns: ["100%"] },
4014
+ sections: [
4015
+ CABButtonSection.parse({
4016
+ action: "addToOrder",
4017
+ sections: [text2.data]
4018
+ })
4019
+ ],
4020
+ width: styles2.buttonWidth
4021
+ })
4022
+ ];
4023
+ };
4024
+
4025
+ // src/transforms/postPurchase/convertSeparatorBlock.ts
4026
+ var convertSeparatorBlock = (raw, report) => {
4027
+ if (!SeparatorBlock.safeParse(raw).success) {
4028
+ report?.({ detail: "Unreadable post-purchase separator", kind: "section" });
4029
+ return [];
4030
+ }
4031
+ return [CABSeparatorSection.parse({})];
4032
+ };
4033
+
4034
+ // src/transforms/postPurchase/convertTextBlock.ts
4035
+ var import_zod32 = require("zod");
4036
+ var fields2 = ["superTitle", "title", "description"];
4037
+ var styles = {
4038
+ description: [{ attrs: { color: "base", fontSize: "small" }, type: "textStyle" }],
4039
+ superTitle: [{ attrs: { color: "subdued", fontSize: "small" }, type: "textStyle" }],
4040
+ title: [{ type: "bold" }, { attrs: { color: "base", fontSize: "large" }, type: "textStyle" }]
4041
+ };
4042
+ var settingsSchema = TextBlock.shape.settings;
4043
+ var Shell2 = import_zod32.z.object({
4044
+ settings: settingsSchema.pick({ horizontalAlignment: true }).extend({
4045
+ description: import_zod32.z.unknown().optional(),
4046
+ superTitle: import_zod32.z.unknown().optional(),
4047
+ title: import_zod32.z.unknown().optional()
4048
+ }),
4049
+ type: import_zod32.z.literal("text")
4050
+ });
4051
+ var convertTextBlock = (raw, report) => {
4052
+ const shell = Shell2.safeParse(raw);
4053
+ if (!shell.success) {
4054
+ report?.({ detail: "Unreadable post-purchase text block", kind: "section" });
4055
+ return [];
4056
+ }
4057
+ const values = fields2.map((field) => ({
4058
+ field,
4059
+ result: settingsSchema.shape[field].safeParse(shell.data.settings[field])
4060
+ }));
4061
+ const horizontal = { center: "center", leading: "start", trailing: "end" }[shell.data.settings.horizontalAlignment];
4062
+ const styled2 = values.every(({ result }) => result.success && typeof result.data === "string");
4063
+ const omit = (field) => {
4064
+ report?.({ detail: `Unreadable post-purchase text field: ${field}`, kind: "section" });
4065
+ return [];
4066
+ };
4067
+ const sections = values.flatMap(({ field, result }) => {
4068
+ if (!result.success) return omit(field);
4069
+ const text2 = result.data;
4070
+ if (text2 === null || text2 === "") return [];
4071
+ const content = styled2 ? { content: [{ attrs: { textAlign: horizontal }, content: [{ marks: styles[field], text: text2 }] }] } : text2;
4072
+ const section = CABTextSection.safeParse({ content: { en: content } });
4073
+ return section.success ? [section.data] : omit(field);
4074
+ });
4075
+ return [
4076
+ CABLayoutSection.parse({
4077
+ alignment: {
4078
+ horizontal
4079
+ },
4080
+ sections
4081
+ })
4082
+ ];
4083
+ };
4084
+
4085
+ // src/transforms/postPurchase/convertTimerBlock.ts
4086
+ var Presentation = TimerBlock.pick({ styles: true }).extend({
4087
+ settings: TimerBlock.shape.settings.pick({ title: true })
4088
+ });
4089
+ var convertTimerBlock = (raw, report) => {
4090
+ const omit = () => {
4091
+ report?.({ detail: "Unreadable post-purchase timer display", kind: "section" });
4092
+ return [];
4093
+ };
4094
+ const parsed = Presentation.safeParse(raw);
4095
+ if (!parsed.success) return omit();
4096
+ const { title } = parsed.data.settings;
4097
+ const styles2 = parsed.data.styles;
4098
+ const horizontal = { center: "center", leading: "start", trailing: "end" }[styles2.textAlignment];
4099
+ const content = typeof title === "string" ? {
4100
+ content: [
4101
+ {
4102
+ attrs: { textAlign: horizontal },
4103
+ content: [
4104
+ styledTextRun(title, styles2.titleEmphasized, styles2.titleSize),
4105
+ styledTextRun(" {{timeRemaining}}", styles2.timerEmphasized, styles2.timerSize)
4106
+ ]
4107
+ }
4108
+ ]
4109
+ } : title;
4110
+ const text2 = CABTextSection.safeParse({ content: { en: content } });
4111
+ if (!text2.success) return omit();
4112
+ return [
4113
+ CABBannerSection.parse({
4114
+ color: styles2.timerBackgroundColor,
4115
+ dismissible: false,
4116
+ sections: [text2.data],
4117
+ width: styles2.timerWidth
4118
+ })
4119
+ ];
4120
+ };
4121
+
4122
+ // src/transforms/postPurchase/convertMessagePreview.ts
4123
+ var MessageWidget = import_zod33.z.object({
4124
+ blocks: import_zod33.z.array(import_zod33.z.unknown()).min(1),
4125
+ type: import_zod33.z.literal("shopify_post_purchase_extension")
4126
+ });
4127
+ var BlockType2 = import_zod33.z.object({ type: import_zod33.z.string() });
4128
+ var converters = {
4129
+ callout_banner: convertCalloutBlock,
4130
+ pay_button: convertPayButtonBlock,
4131
+ separator: convertSeparatorBlock,
4132
+ text: convertTextBlock,
4133
+ timer: convertTimerBlock
4134
+ };
4135
+ var convertMessagePreview = (id, settings, report) => {
4136
+ const parsed = MessageWidget.safeParse(settings);
4137
+ if (!parsed.success) throw new NotFoundError("Unsupported post-purchase message preview");
4138
+ return CABRootSection.parse({
4139
+ editorMode: "postPurchaseOffer",
4140
+ previewMode: true,
4141
+ sections: parsed.data.blocks.flatMap((block) => {
4142
+ const type = BlockType2.safeParse(block);
4143
+ const kind = type.success ? type.data.type : void 0;
4144
+ const convert2 = kind ? converters[kind] : void 0;
4145
+ if (convert2) return convert2(block, report);
4146
+ report?.({
4147
+ detail: kind ? `Unsupported post-purchase block type: ${kind}` : "Unreadable post-purchase block: missing type",
4148
+ kind: "section"
4149
+ });
4150
+ return [];
4151
+ }),
4152
+ sectionType: "layout",
4153
+ widgetId: id
4154
+ });
4155
+ };
4156
+
4157
+ // src/transforms/postPurchase/types.ts
4158
+ var isPostPurchaseV1 = (data) => !!data && typeof data === "object" && data.type === WidgetType.shopify_post_purchase_extension && Array.isArray(data.blocks);
4159
+
3748
4160
  // src/transforms/presentmentThresholds.ts
3749
4161
  var presentmentThresholds = (presentment) => {
3750
4162
  if (!presentment?.enabled) return {};
@@ -4129,7 +4541,7 @@ var fetchUserConfig = async (input, ctx) => {
4129
4541
  };
4130
4542
 
4131
4543
  // src/utilities.ts
4132
- var import_uuid13 = require("uuid");
4544
+ var import_uuid15 = require("uuid");
4133
4545
  function serialize(obj) {
4134
4546
  const serialized = [];
4135
4547
  const add = (key, value) => {
@@ -4257,7 +4669,7 @@ var fetchDataSourceResults = async (input, ctx) => {
4257
4669
  };
4258
4670
 
4259
4671
  // src/server/adsEngine.ts
4260
- var import_zod28 = require("zod");
4672
+ var import_zod34 = require("zod");
4261
4673
  var SUPPLY_KEY = { production: "AQF5RKLR", staging: "Z56LQ7PS" };
4262
4674
  var OFFER_LIMIT = 4;
4263
4675
  var SUPPORTED_COUNTRIES = /* @__PURE__ */ new Set(["US", "CA"]);
@@ -4270,28 +4682,28 @@ var transactionItems = (input) => (input.transactionItems?.map(({ id, priceCents
4270
4682
  title,
4271
4683
  type
4272
4684
  })) ?? input.cart.items.map(({ productId, quantity }) => ({ id: productId, quantity }))).slice(0, MAX_TRANSACTION_ITEMS);
4273
- var AdsEngineOffer = import_zod28.z.object({
4685
+ var AdsEngineOffer = import_zod34.z.object({
4274
4686
  /** Pill-style value prop ("Get $45 Cashback"). Carried through the parse; the card does not render it yet (REB-24429 — pill design pending). */
4275
- callout: import_zod28.z.string().catch(""),
4276
- click_url: import_zod28.z.string(),
4277
- cta: import_zod28.z.string(),
4687
+ callout: import_zod34.z.string().catch(""),
4688
+ click_url: import_zod34.z.string(),
4689
+ cta: import_zod34.z.string(),
4278
4690
  /** `omitempty` on the ad server — a bid without it must not fail the parse and drop the whole batch (composeOffer falls back to 'No Thanks'). */
4279
- decline_cta: import_zod28.z.string().catch(""),
4280
- decline_url: import_zod28.z.string(),
4281
- description: import_zod28.z.string(),
4691
+ decline_cta: import_zod34.z.string().catch(""),
4692
+ decline_url: import_zod34.z.string(),
4693
+ description: import_zod34.z.string(),
4282
4694
  /** Short legal disclosure (FDIC / auto-renewal / FTC-affiliation lines). Rendered subdued under the CTAs. */
4283
- disclaimer: import_zod28.z.string().catch(""),
4695
+ disclaimer: import_zod34.z.string().catch(""),
4284
4696
  /** Long legal text behind the disclosure toggle in the composed card (REB-24429). */
4285
- extended_disclaimer: import_zod28.z.string().catch(""),
4286
- headline: import_zod28.z.string(),
4287
- id: import_zod28.z.string(),
4697
+ extended_disclaimer: import_zod34.z.string().catch(""),
4698
+ headline: import_zod34.z.string(),
4699
+ id: import_zod34.z.string(),
4288
4700
  /** Advertiser-supplied image alt; the composed card falls back to the stripped headline when empty. */
4289
- image_alt: import_zod28.z.string().catch(""),
4290
- image_url: import_zod28.z.string().optional(),
4291
- view_url: import_zod28.z.string()
4701
+ image_alt: import_zod34.z.string().catch(""),
4702
+ image_url: import_zod34.z.string().optional(),
4703
+ view_url: import_zod34.z.string()
4292
4704
  });
4293
- var AdsEngineResponse = import_zod28.z.object({
4294
- offers: import_zod28.z.array(import_zod28.z.unknown()).default([]).transform(
4705
+ var AdsEngineResponse = import_zod34.z.object({
4706
+ offers: import_zod34.z.array(import_zod34.z.unknown()).default([]).transform(
4295
4707
  (offers) => offers.flatMap((offer) => {
4296
4708
  const result = AdsEngineOffer.safeParse(offer);
4297
4709
  return result.success ? [result.data] : [];
@@ -4303,8 +4715,8 @@ var AdsEngineResponse = import_zod28.z.object({
4303
4715
  * offers-testing fixture on a test store forces it, REB-24467). Both optional: an older engine or a
4304
4716
  * non-JSON body must not fail the parse and drop the offers.
4305
4717
  */
4306
- request_id: import_zod28.z.string().optional().catch(void 0),
4307
- testing: import_zod28.z.boolean().optional().catch(void 0)
4718
+ request_id: import_zod34.z.string().optional().catch(void 0),
4719
+ testing: import_zod34.z.boolean().optional().catch(void 0)
4308
4720
  });
4309
4721
  var adsHost = (host) => `offers.${host}`;
4310
4722
  var isTestingRequest = (input, isProduction) => !isProduction || !!input.testing || input.customerEmail?.toLowerCase() === TEST_CUSTOMER_EMAIL;
@@ -4577,7 +4989,7 @@ var fetchMonetizeOffers = async (input, ctx, prefetched) => {
4577
4989
  };
4578
4990
 
4579
4991
  // src/server/salvageSections.ts
4580
- var import_uuid14 = require("uuid");
4992
+ var import_uuid16 = require("uuid");
4581
4993
  var STUB_SECTION_TYPE = "unknown";
4582
4994
  var knownSectionTypes = new Set(sectionTypes);
4583
4995
  var hasSectionsArray = (raw) => typeof raw === "object" && raw !== null && Array.isArray(raw.sections);
@@ -4590,7 +5002,7 @@ var stubSection = (raw, report) => {
4590
5002
  kind: "section"
4591
5003
  });
4592
5004
  return {
4593
- sectionId: typeof rawId === "string" && rawId ? rawId : (0, import_uuid14.v7)(),
5005
+ sectionId: typeof rawId === "string" && rawId ? rawId : (0, import_uuid16.v7)(),
4594
5006
  sectionType: typeof original === "string" && !knownSectionTypes.has(original) ? original : STUB_SECTION_TYPE
4595
5007
  };
4596
5008
  };
@@ -4619,6 +5031,7 @@ var dispatchWidgetTransform = (id, normalized, report) => {
4619
5031
  if (isLineItemEditorV1(normalized)) return convertLineItemEditorToV2({ id, settings: normalized });
4620
5032
  if (isMonetizeV1(normalized)) return convertMonetizeToV2({ id, settings: normalized });
4621
5033
  if (isPlaceholderV1(normalized)) return convertPlaceholderToV2({ id, settings: normalized });
5034
+ if (isPostPurchaseV1(normalized)) return convertMessagePreview(id, normalized, report);
4622
5035
  if (isOfferV1(normalized)) return convertOfferToV2({ id, name: normalized.name, settings: normalized });
4623
5036
  return normalized;
4624
5037
  };
@@ -4733,13 +5146,13 @@ var convertWidgetSettings = async (input, ctx) => {
4733
5146
  };
4734
5147
 
4735
5148
  // src/server/giftWidgets.ts
4736
- var import_zod29 = require("zod");
4737
- var SettingsNumber = import_zod29.z.union([
4738
- import_zod29.z.number(),
4739
- import_zod29.z.string().trim().regex(/^-?\d+(\.\d+)?$/)
4740
- ]).pipe(import_zod29.z.coerce.number());
4741
- var SgwpMilestoneSchema = import_zod29.z.object({
4742
- selectable_product_quantity: SettingsNumber.pipe(import_zod29.z.number().int().nonnegative()),
5149
+ var import_zod35 = require("zod");
5150
+ var SettingsNumber = import_zod35.z.union([
5151
+ import_zod35.z.number(),
5152
+ import_zod35.z.string().trim().regex(/^-?\d+(\.\d+)?$/)
5153
+ ]).pipe(import_zod35.z.coerce.number());
5154
+ var SgwpMilestoneSchema = import_zod35.z.object({
5155
+ selectable_product_quantity: SettingsNumber.pipe(import_zod35.z.number().int().nonnegative()),
4743
5156
  unlock_price: SettingsNumber
4744
5157
  });
4745
5158
  var fetchGiftWidgetSettings = async (widgetId, shop, ctx) => unwrapData(await ctx.fetchUpstream("/api/v1/widgets/settings", { id: String(widgetId), shop }, { host: ctx.host }));
@@ -4750,7 +5163,7 @@ var readDataSourcePath = (settings) => {
4750
5163
  var readMilestones = (settings, report) => {
4751
5164
  const raw = settings && typeof settings === "object" ? settings.milestones : void 0;
4752
5165
  if (raw == null) return [];
4753
- const parsed = import_zod29.z.array(SgwpMilestoneSchema).safeParse(raw);
5166
+ const parsed = import_zod35.z.array(SgwpMilestoneSchema).safeParse(raw);
4754
5167
  if (parsed.success) return parsed.data;
4755
5168
  report?.({
4756
5169
  detail: [
@@ -4999,7 +5412,7 @@ var postAnalyticsEvents = async (input, ctx) => {
4999
5412
  };
5000
5413
 
5001
5414
  // src/server/requestSchemas.ts
5002
- var import_zod30 = require("zod");
5415
+ var import_zod36 = require("zod");
5003
5416
  var REQUEST_BOUNDS = {
5004
5417
  /** Cart-level attributes per cart. */
5005
5418
  CART_ATTRIBUTES_MAX: 100,
@@ -5030,42 +5443,42 @@ var REQUEST_BOUNDS = {
5030
5443
  /** Rich ads transaction lines — the engine's ads contract. */
5031
5444
  TRANSACTION_ITEMS_MAX: 50
5032
5445
  };
5033
- var KeyValue = import_zod30.z.object({
5034
- key: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
5035
- value: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_VALUE_MAX).optional()
5446
+ var KeyValue = import_zod36.z.object({
5447
+ key: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
5448
+ value: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_VALUE_MAX).optional()
5036
5449
  });
5037
- var CartLineInputSchema = import_zod30.z.object({
5038
- productId: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5039
- properties: import_zod30.z.array(KeyValue).max(REQUEST_BOUNDS.LINE_PROPERTIES_MAX).optional(),
5040
- quantity: import_zod30.z.number(),
5041
- subscriptionId: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5042
- variantId: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX)
5450
+ var CartLineInputSchema = import_zod36.z.object({
5451
+ productId: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5452
+ properties: import_zod36.z.array(KeyValue).max(REQUEST_BOUNDS.LINE_PROPERTIES_MAX).optional(),
5453
+ quantity: import_zod36.z.number(),
5454
+ subscriptionId: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5455
+ variantId: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX)
5043
5456
  });
5044
- var CartInputSchema = import_zod30.z.object({
5045
- attributes: import_zod30.z.array(KeyValue).max(REQUEST_BOUNDS.CART_ATTRIBUTES_MAX).optional(),
5457
+ var CartInputSchema = import_zod36.z.object({
5458
+ attributes: import_zod36.z.array(KeyValue).max(REQUEST_BOUNDS.CART_ATTRIBUTES_MAX).optional(),
5046
5459
  /**
5047
5460
  * Presentment-per-shop-currency FX rate (buyer price ÷ shop price, e.g. `1.35` for a USD shop
5048
5461
  * selling in CAD). Money rule thresholds are authored in SHOP currency, so the engine subtotal is
5049
5462
  * divided by this before evaluation. Omit (or send 1) when the cart is already in the shop's currency.
5050
5463
  */
5051
- currencyRate: import_zod30.z.number().optional(),
5464
+ currencyRate: import_zod36.z.number().optional(),
5052
5465
  /** Applied discount codes; the engine evaluates `discount_code` rules against them (sent as `[{code}]`). */
5053
- discountCodes: import_zod30.z.array(import_zod30.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX)).max(REQUEST_BOUNDS.DISCOUNT_CODES_MAX).optional(),
5466
+ discountCodes: import_zod36.z.array(import_zod36.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX)).max(REQUEST_BOUNDS.DISCOUNT_CODES_MAX).optional(),
5054
5467
  /** Presentment cents of cart-level discount allocations, subtracted from `subtotal` for the engine. */
5055
- discountTotal: import_zod30.z.number().optional(),
5056
- items: import_zod30.z.array(CartLineInputSchema).max(REQUEST_BOUNDS.CART_ITEMS_MAX),
5468
+ discountTotal: import_zod36.z.number().optional(),
5469
+ items: import_zod36.z.array(CartLineInputSchema).max(REQUEST_BOUNDS.CART_ITEMS_MAX),
5057
5470
  /** Presentment subtotal in cents. */
5058
- subtotal: import_zod30.z.number()
5471
+ subtotal: import_zod36.z.number()
5059
5472
  });
5060
- var UserConfigInputSchema = import_zod30.z.object({ shop: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX) });
5061
- var DataSourceInputSchema = import_zod30.z.object({
5473
+ var UserConfigInputSchema = import_zod36.z.object({ shop: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX) });
5474
+ var DataSourceInputSchema = import_zod36.z.object({
5062
5475
  cart: CartInputSchema,
5063
5476
  /**
5064
5477
  * Numeric Shopify company-location id when the buyer is a B2B session (`buyerIdentity.purchasingCompany`).
5065
5478
  * Present ⇒ the orchestrator filters results by the location's catalog via admin-api (REB-23713); the
5066
5479
  * client's country-context market check is bypassed for B2B (it false-negatives B2B-catalog products).
5067
5480
  */
5068
- companyLocationId: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5481
+ companyLocationId: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5069
5482
  /**
5070
5483
  * Buyer's market country (ISO 3166-1 alpha-2) — forwarded to the engine as the `country_code` PARAM
5071
5484
  * when the shop's markets toggle is on (REB-21688; the sink was the `X-Country-Code` header under
@@ -5074,16 +5487,16 @@ var DataSourceInputSchema = import_zod30.z.object({
5074
5487
  * uppercase (the wire value is forwarded verbatim as the param) so a case-sensitive engine lookup
5075
5488
  * can't silently miss a lowercase code — `adsEngine.ts` uppercases for the same reason.
5076
5489
  */
5077
- country: import_zod30.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(),
5078
- customerId: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5079
- dataSourcePath: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
5490
+ country: import_zod36.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(),
5491
+ customerId: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5492
+ dataSourcePath: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
5080
5493
  /**
5081
5494
  * Engine `filter_inputs` override: `'no'` keeps in-cart (input) products in the results/rule
5082
5495
  * outputs — gift validation sends it so a gift's own product can appear in its answer. Omitted = the
5083
5496
  * engine's default filtering.
5084
5497
  */
5085
- filterInputs: import_zod30.z.enum(["no", "yes"]).optional(),
5086
- integrations: import_zod30.z.record(import_zod30.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), import_zod30.z.boolean()).refine((record) => Object.keys(record).length <= REQUEST_BOUNDS.INTEGRATION_KEYS_MAX, {
5498
+ filterInputs: import_zod36.z.enum(["no", "yes"]).optional(),
5499
+ integrations: import_zod36.z.record(import_zod36.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), import_zod36.z.boolean()).refine((record) => Object.keys(record).length <= REQUEST_BOUNDS.INTEGRATION_KEYS_MAX, {
5087
5500
  message: `Too many integration keys (max ${REQUEST_BOUNDS.INTEGRATION_KEYS_MAX})`
5088
5501
  }).optional(),
5089
5502
  /**
@@ -5096,31 +5509,31 @@ var DataSourceInputSchema = import_zod30.z.object({
5096
5509
  * request header) fails the regex. Callers should send the buyer's resolved locale (e.g. Shopify
5097
5510
  * checkout's `localization.language.isoCode`), not the request header verbatim.
5098
5511
  */
5099
- language: import_zod30.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(),
5100
- limit: import_zod30.z.number().max(REQUEST_BOUNDS.LIMIT_MAX),
5101
- productType: import_zod30.z.enum(["both", "one-time", "subscription"]).optional(),
5102
- shop: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5103
- visitorId: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
5512
+ language: import_zod36.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(),
5513
+ limit: import_zod36.z.number().max(REQUEST_BOUNDS.LIMIT_MAX),
5514
+ productType: import_zod36.z.enum(["both", "one-time", "subscription"]).optional(),
5515
+ shop: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5516
+ visitorId: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
5104
5517
  });
5105
- var GiftInputSchema = import_zod30.z.object({
5106
- cost: import_zod30.z.number(),
5107
- discounted: import_zod30.z.boolean(),
5518
+ var GiftInputSchema = import_zod36.z.object({
5519
+ cost: import_zod36.z.number(),
5520
+ discounted: import_zod36.z.boolean(),
5108
5521
  /**
5109
5522
  * Which gift attribution the line carries (REB-24363). Defaults to `gwp` because a client that predates
5110
5523
  * the field only ever sent GWP lines — without the default an older extension's request would 422.
5111
5524
  */
5112
- kind: import_zod30.z.enum(GIFT_KINDS).default("gwp"),
5113
- lineId: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5114
- productId: import_zod30.z.number(),
5525
+ kind: import_zod36.z.enum(GIFT_KINDS).default("gwp"),
5526
+ lineId: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5527
+ productId: import_zod36.z.number(),
5115
5528
  /**
5116
5529
  * The line's unit count (REB-24363) — the selectable-GWP verdict trims surplus units against milestone
5117
5530
  * capacity. The second deliberate default: a client predating the field sent only GWP lines, whose
5118
5531
  * verdict is whole-line, so a missing quantity reads as one unit rather than 422ing the older request.
5119
5532
  */
5120
- quantity: import_zod30.z.number().int().min(1).default(1),
5121
- widgetId: import_zod30.z.number()
5533
+ quantity: import_zod36.z.number().int().min(1).default(1),
5534
+ widgetId: import_zod36.z.number()
5122
5535
  });
5123
- var GiftValidationInputSchema = import_zod30.z.object({
5536
+ var GiftValidationInputSchema = import_zod36.z.object({
5124
5537
  cart: CartInputSchema,
5125
5538
  /**
5126
5539
  * Buyer's market country — threaded into the per-widget data-source evaluations, which forward it to
@@ -5129,25 +5542,25 @@ var GiftValidationInputSchema = import_zod30.z.object({
5129
5542
  * turns markets off); regex-bound and uppercase-normalized for the same reasons as
5130
5543
  * `DataSourceInputSchema`'s `country`.
5131
5544
  */
5132
- country: import_zod30.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(),
5133
- customerId: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5134
- gifts: import_zod30.z.array(GiftInputSchema).max(REQUEST_BOUNDS.GIFTS_MAX),
5545
+ country: import_zod36.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(),
5546
+ customerId: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5547
+ gifts: import_zod36.z.array(GiftInputSchema).max(REQUEST_BOUNDS.GIFTS_MAX),
5135
5548
  /**
5136
5549
  * Buyer's checkout language — threaded into the per-widget data-source evaluations, which normalize
5137
5550
  * and forward it as the engine `locale` param under the same markets-toggle gate (REB-21688). MUST be
5138
5551
  * a single BCP-47 tag, for the same reason as `DataSourceInputSchema`'s `language` above.
5139
5552
  */
5140
- language: import_zod30.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(),
5141
- shop: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5142
- visitorId: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
5553
+ language: import_zod36.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(),
5554
+ shop: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5555
+ visitorId: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
5143
5556
  });
5144
- var GiftAdjustmentSchema = import_zod30.z.object({
5145
- lineId: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5146
- quantity: import_zod30.z.number().int().nonnegative()
5557
+ var GiftAdjustmentSchema = import_zod36.z.object({
5558
+ lineId: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5559
+ quantity: import_zod36.z.number().int().nonnegative()
5147
5560
  });
5148
- var GiftValidationResponseSchema = import_zod30.z.object({
5149
- adjust: import_zod30.z.array(GiftAdjustmentSchema).max(REQUEST_BOUNDS.GIFTS_MAX).default([]),
5150
- remove: import_zod30.z.array(import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX)).max(REQUEST_BOUNDS.GIFTS_MAX).refine(
5561
+ var GiftValidationResponseSchema = import_zod36.z.object({
5562
+ adjust: import_zod36.z.array(GiftAdjustmentSchema).max(REQUEST_BOUNDS.GIFTS_MAX).default([]),
5563
+ remove: import_zod36.z.array(import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX)).max(REQUEST_BOUNDS.GIFTS_MAX).refine(
5151
5564
  (remove) => new Set(remove).size === remove.length,
5152
5565
  "a line id may appear at most once in `remove`"
5153
5566
  )
@@ -5158,47 +5571,47 @@ var GiftValidationResponseSchema = import_zod30.z.object({
5158
5571
  ({ adjust }) => new Set(adjust.map(({ lineId }) => lineId)).size === adjust.length,
5159
5572
  "a line id may appear at most once in `adjust`"
5160
5573
  );
5161
- var MonetizeTransactionItemSchema = import_zod30.z.object({
5162
- id: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5163
- priceCents: import_zod30.z.number(),
5164
- quantity: import_zod30.z.number(),
5165
- title: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX),
5166
- type: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX)
5574
+ var MonetizeTransactionItemSchema = import_zod36.z.object({
5575
+ id: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5576
+ priceCents: import_zod36.z.number(),
5577
+ quantity: import_zod36.z.number(),
5578
+ title: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX),
5579
+ type: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX)
5167
5580
  });
5168
- var MonetizeInputSchema = import_zod30.z.object({
5581
+ var MonetizeInputSchema = import_zod36.z.object({
5169
5582
  cart: CartInputSchema,
5170
5583
  /** Client-minted render-beacon correlation id; forwarded to the ads engine as `client_request_id`. */
5171
- clientRequestId: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5172
- country: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5173
- currency: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5584
+ clientRequestId: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5585
+ country: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5586
+ currency: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5174
5587
  /** Ads-targeting identity/geo/locale fields (React parity); folded into the engine query verbatim. */
5175
- customerEmail: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
5176
- customerFirstName: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
5177
- customerId: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5178
- customerLastName: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
5179
- language: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5588
+ customerEmail: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
5589
+ customerFirstName: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
5590
+ customerId: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5591
+ customerLastName: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
5592
+ language: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5180
5593
  /** Buyer-facing order name (e.g. `#1001`) for the server-composed "Order … Confirmed" chrome line. */
5181
- orderName: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
5594
+ orderName: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
5182
5595
  /** Ads surface label, forwarded verbatim; `customer_account` is measured/floored as its own surface (the account-area order list). */
5183
- placement: import_zod30.z.enum(["customer_account", "order_status", "thank_you_page"]),
5596
+ placement: import_zod36.z.enum(["customer_account", "order_status", "thank_you_page"]),
5184
5597
  /** Privacy Policy footer href — the Monetize widget's `privacy_policy_url` setting (React parity). */
5185
- privacyPolicyUrl: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_URL_MAX).optional(),
5598
+ privacyPolicyUrl: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_URL_MAX).optional(),
5186
5599
  /** 30-min rolling session id (React parity); used for the ads `session_id`, else the visitor id. */
5187
- sessionId: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5188
- shop: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5600
+ sessionId: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5601
+ shop: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5189
5602
  /** Editor/QA indicator; OR-ed into the ads-engine `testing` flag so it stays out of billing/reporting. */
5190
- testing: import_zod30.z.boolean().optional(),
5191
- timezone: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5603
+ testing: import_zod36.z.boolean().optional(),
5604
+ timezone: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5192
5605
  /** Decorated (numeric) order id → the ads `transaction_id`. */
5193
- transactionId: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5606
+ transactionId: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5194
5607
  /** Rich per-line ads items; capped at the engine's ads contract. Preferred over `cart.items`. */
5195
- transactionItems: import_zod30.z.array(MonetizeTransactionItemSchema).max(REQUEST_BOUNDS.TRANSACTION_ITEMS_MAX).optional(),
5608
+ transactionItems: import_zod36.z.array(MonetizeTransactionItemSchema).max(REQUEST_BOUNDS.TRANSACTION_ITEMS_MAX).optional(),
5196
5609
  /** Order total in presentment cents (React prefers total over subtotal); else `cart.subtotal`. */
5197
- transactionTotal: import_zod30.z.number().optional(),
5198
- visitorId: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5199
- zipCode: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
5610
+ transactionTotal: import_zod36.z.number().optional(),
5611
+ visitorId: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5612
+ zipCode: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
5200
5613
  });
5201
- var WidgetSettingsInputSchema = import_zod30.z.object({
5614
+ var WidgetSettingsInputSchema = import_zod36.z.object({
5202
5615
  /**
5203
5616
  * Same domain as `CabShopConfig.cacheKey`, for the same reason: this side WINS the orchestrator's
5204
5617
  * `input.cacheKey ?? config.shop.cacheKey` (and an explicit value skips the config read entirely), so
@@ -5206,9 +5619,9 @@ var WidgetSettingsInputSchema = import_zod30.z.object({
5206
5619
  * and pin the edge copy permanently stale. `.catch(undefined)` because a bogus buster should degrade
5207
5620
  * the read to un-busted, never 400 a widget render.
5208
5621
  */
5209
- cacheKey: import_zod30.z.number().int().positive().optional().catch(void 0),
5210
- id: import_zod30.z.number(),
5211
- key: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5622
+ cacheKey: import_zod36.z.number().int().positive().optional().catch(void 0),
5623
+ id: import_zod36.z.number(),
5624
+ key: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5212
5625
  /**
5213
5626
  * Monetize context for inline hydration: when present AND the widget converts to a Monetize marker,
5214
5627
  * the server fetches/composes the offer cards inside this same request (no second `/cab/monetize`
@@ -5217,34 +5630,34 @@ var WidgetSettingsInputSchema = import_zod30.z.object({
5217
5630
  * `privacyPolicyUrl` comes from the widget settings server-side (more authoritative than a relay).
5218
5631
  */
5219
5632
  monetize: MonetizeInputSchema.omit({ privacyPolicyUrl: true, shop: true }).optional(),
5220
- shop: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5633
+ shop: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5221
5634
  /** Stable per-buyer id; when present, enables sticky server-side A/B variant selection. */
5222
- visitorId: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
5635
+ visitorId: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
5223
5636
  });
5224
- var AnalyticsEventInputSchema = import_zod30.z.object({
5225
- name: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
5226
- properties: import_zod30.z.record(import_zod30.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), import_zod30.z.unknown()).optional(),
5227
- sentAt: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
5637
+ var AnalyticsEventInputSchema = import_zod36.z.object({
5638
+ name: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
5639
+ properties: import_zod36.z.record(import_zod36.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), import_zod36.z.unknown()).optional(),
5640
+ sentAt: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
5228
5641
  });
5229
- var AnalyticsSegmentsInputSchema = import_zod30.z.object({
5230
- device: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
5231
- source: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
5232
- visitor: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0)
5642
+ var AnalyticsSegmentsInputSchema = import_zod36.z.object({
5643
+ device: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
5644
+ source: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
5645
+ visitor: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0)
5233
5646
  });
5234
- var AnalyticsInputSchema = import_zod30.z.object({
5647
+ var AnalyticsInputSchema = import_zod36.z.object({
5235
5648
  /** Rebuy cart token (the `r_cart_token` cart attribute), when available — primary aggregation key. */
5236
- cartToken: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5649
+ cartToken: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5237
5650
  /** Shopify checkout token, when available — drives cart/checkout aggregation downstream. */
5238
- checkoutToken: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5239
- events: import_zod30.z.array(AnalyticsEventInputSchema).max(REQUEST_BOUNDS.EVENTS_MAX),
5651
+ checkoutToken: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5652
+ events: import_zod36.z.array(AnalyticsEventInputSchema).max(REQUEST_BOUNDS.EVENTS_MAX),
5240
5653
  /**
5241
5654
  * Request-scoped like the tokens: one visitor's segments apply to every event in the batch. The container
5242
5655
  * degrades too (`null` is a realistic wire artifact of `attributes ? {…} : null`), so the degrade rule is
5243
5656
  * total: nothing about `segments` can cost the envelope.
5244
5657
  */
5245
5658
  segments: AnalyticsSegmentsInputSchema.optional().catch(void 0),
5246
- shop: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5247
- visitorId: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5659
+ shop: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5660
+ visitorId: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5248
5661
  /** The widget id (smartBlockId) the events belong to. */
5249
- widgetId: import_zod30.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
5662
+ widgetId: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
5250
5663
  });