@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
@@ -623,8 +623,8 @@ var CabUserConfig = z6.object({
623
623
  });
624
624
 
625
625
  // src/schema/widgets/checkout-and-beyond/image.ts
626
- import { v7 as uuidv712 } from "uuid";
627
- import { z as z26 } from "zod";
626
+ import { v7 as uuidv713 } from "uuid";
627
+ import { z as z27 } from "zod";
628
628
 
629
629
  // src/schema/widgets/checkout-and-beyond/common.ts
630
630
  var freezeEnum = (values) => Object.freeze(Object.fromEntries(values.map((v) => [v, v])));
@@ -733,6 +733,8 @@ var languageKeys = [
733
733
  "zh"
734
734
  ];
735
735
  var LanguageKey = freezeEnum(languageKeys);
736
+ var layoutFrames = ["callout", "offer-content"];
737
+ var LayoutFrame = freezeEnum(layoutFrames);
736
738
  var mutatorEvents = ["item_added", "quantity_changed", "variant_selected"];
737
739
  var MutatorEvent = freezeEnum(mutatorEvents);
738
740
  var objectFits = ["cover", "contain"];
@@ -771,6 +773,7 @@ var sectionTypes = [
771
773
  "progressBar",
772
774
  "quantity",
773
775
  "reviews",
776
+ "separator",
774
777
  "text",
775
778
  "variants"
776
779
  ];
@@ -914,7 +917,7 @@ var ROOT_RELATIVE_PATH_REGEX = /^\/(?!\/)/;
914
917
  var HTML_TAGS_REGEX = /<\/?[a-zA-Z][^>]*>/g;
915
918
 
916
919
  // src/schema/widgets/checkout-and-beyond/shared.ts
917
- import { z as z25 } from "zod";
920
+ import { z as z26 } from "zod";
918
921
 
919
922
  // src/schema/widgets/checkout-and-beyond/banner.ts
920
923
  import { z as z10 } from "zod";
@@ -1069,6 +1072,10 @@ var CABVariableFields = {
1069
1072
 
1070
1073
  // src/schema/widgets/checkout-and-beyond/layout.ts
1071
1074
  var GridItem = z9.union([z9.literal("auto"), z9.literal("fill"), z9.string().regex(/^\d+%$/), z9.number()]);
1075
+ var CABLayoutWrapping = z9.object({
1076
+ breakAt: z9.number().positive(),
1077
+ maxPerLine: z9.number().int().positive()
1078
+ });
1072
1079
  var CABLayoutSection = z9.object({
1073
1080
  ...CABVariableFields,
1074
1081
  alignment: z9.object({
@@ -1081,6 +1088,11 @@ var CABLayoutSection = z9.object({
1081
1088
  border: z9.lazy(() => CABBorder),
1082
1089
  buttonField: z9.enum(buttonFields).optional(),
1083
1090
  direction: z9.enum(directions).default(Direction.rows),
1091
+ /**
1092
+ * Platform chrome around the section, not a layout behavior: `callout` is a subdued box with block borders
1093
+ * (the legacy post-purchase callout banner), `offer-content` the post-purchase offer's own content card.
1094
+ */
1095
+ frame: z9.enum(layoutFrames).optional(),
1084
1096
  grid: z9.object({
1085
1097
  columns: z9.union([z9.array(GridItem), z9.undefined()]).default(() => ["auto"]),
1086
1098
  rows: z9.union([z9.array(GridItem), z9.undefined()]).default(() => ["auto"])
@@ -1093,7 +1105,8 @@ var CABLayoutSection = z9.object({
1093
1105
  spacing: z9.enum(spacings).default(Spacing.base),
1094
1106
  /** Fire-and-forget impression pixel POSTed once when the section is shown (e.g. a Monetize offer view). */
1095
1107
  viewUrl: z9.string().optional(),
1096
- width: z9.number().default(100)
1108
+ width: z9.number().default(100),
1109
+ wrapping: CABLayoutWrapping.optional()
1097
1110
  });
1098
1111
 
1099
1112
  // src/schema/widgets/checkout-and-beyond/utils.ts
@@ -1957,35 +1970,46 @@ var CABReviewsSection = z23.object({
1957
1970
  name: z23.string().optional(),
1958
1971
  sectionId: z23.uuid().default(() => uuidv710()),
1959
1972
  sectionType: z23.literal(SectionType.reviews).default(SectionType.reviews),
1960
- size: z23.enum(reviewsSizes).default(ReviewsSize.default)
1973
+ size: z23.enum(reviewsSizes).default(ReviewsSize.default),
1974
+ strokeColor: z23.string().default("#fadb14"),
1975
+ strokeWidth: z23.number().nonnegative().default(0)
1961
1976
  });
1962
1977
 
1963
- // src/schema/widgets/checkout-and-beyond/variants.ts
1964
- import { slice } from "es-toolkit/compat";
1978
+ // src/schema/widgets/checkout-and-beyond/separator.ts
1965
1979
  import { v7 as uuidv711 } from "uuid";
1966
1980
  import { z as z24 } from "zod";
1967
- var CABVariantsSection = z24.object({
1981
+ var CABSeparatorSection = z24.object({
1968
1982
  ...CABVariableFields,
1969
- hideOutOfStockVariants: z24.boolean().default(false),
1970
- name: z24.string().optional(),
1971
1983
  sectionId: z24.uuid().default(() => uuidv711()),
1972
- sectionType: z24.literal(SectionType.variants).default(SectionType.variants),
1973
- selector: z24.enum(slice(variantSelectors, 0, 3)).default(VariantSelector.menu),
1974
- variantMode: z24.enum(variantModes).default(VariantMode.multiple)
1984
+ sectionType: z24.literal(SectionType.separator).default(SectionType.separator)
1985
+ });
1986
+
1987
+ // src/schema/widgets/checkout-and-beyond/variants.ts
1988
+ import { slice } from "es-toolkit/compat";
1989
+ import { v7 as uuidv712 } from "uuid";
1990
+ import { z as z25 } from "zod";
1991
+ var CABVariantsSection = z25.object({
1992
+ ...CABVariableFields,
1993
+ hideOutOfStockVariants: z25.boolean().default(false),
1994
+ name: z25.string().optional(),
1995
+ sectionId: z25.uuid().default(() => uuidv712()),
1996
+ sectionType: z25.literal(SectionType.variants).default(SectionType.variants),
1997
+ selector: z25.enum(slice(variantSelectors, 0, 3)).default(VariantSelector.menu),
1998
+ variantMode: z25.enum(variantModes).default(VariantMode.multiple)
1975
1999
  });
1976
2000
 
1977
2001
  // src/schema/widgets/checkout-and-beyond/shared.ts
1978
- var CABBorder = z25.object({
1979
- radius: z25.enum(borderRadii).default(BorderRadius.base),
1980
- style: z25.enum(borderStyles).default(BorderStyle.none),
1981
- width: z25.enum(borderWidths).default(BorderWidth.base)
2002
+ var CABBorder = z26.object({
2003
+ radius: z26.enum(borderRadii).default(BorderRadius.base),
2004
+ style: z26.enum(borderStyles).default(BorderStyle.none),
2005
+ width: z26.enum(borderWidths).default(BorderWidth.base)
1982
2006
  }).default({
1983
2007
  radius: BorderRadius.base,
1984
2008
  style: BorderStyle.none,
1985
2009
  width: BorderWidth.base
1986
2010
  });
1987
- var CABSection = z25.lazy(
1988
- () => z25.discriminatedUnion("sectionType", [
2011
+ var CABSection = z26.lazy(
2012
+ () => z26.discriminatedUnion("sectionType", [
1989
2013
  CABBannerSection,
1990
2014
  CABButtonSection,
1991
2015
  CABCarouselSection,
@@ -2001,23 +2025,24 @@ var CABSection = z25.lazy(
2001
2025
  CABProgressBarSection,
2002
2026
  CABQuantitySection,
2003
2027
  CABReviewsSection,
2028
+ CABSeparatorSection,
2004
2029
  CABTextSection,
2005
2030
  CABVariantsSection
2006
2031
  ])
2007
2032
  );
2008
2033
 
2009
2034
  // src/schema/widgets/checkout-and-beyond/image.ts
2010
- var CABImageSectionFields = z26.object({
2035
+ var CABImageSectionFields = z27.object({
2011
2036
  ...CABVariableFields,
2012
- altText: z26.string().refine(checkForHTML, NO_HTML).default(""),
2037
+ altText: z27.string().refine(checkForHTML, NO_HTML).default(""),
2013
2038
  /**
2014
2039
  * Image width÷height (e.g. `46` for the progress-bar fill); `null` renders at natural size. Any POSITIVE
2015
2040
  * ratio — never limited to 1, but never `0`/negative either: a renderer dividing by it would get `Infinity`,
2016
2041
  * and CSS `aspect-ratio` drops a negative value and silently reverts to natural size.
2017
2042
  */
2018
- aspectRatio: z26.number().positive().nullable().default(null),
2019
- border: z26.lazy(() => CABBorder),
2020
- buttonField: z26.enum(buttonFields).optional(),
2043
+ aspectRatio: z27.number().positive().nullable().default(null),
2044
+ border: z27.lazy(() => CABBorder),
2045
+ buttonField: z27.enum(buttonFields).optional(),
2021
2046
  /**
2022
2047
  * `icon` renders `source` as a single `s-icon` by name (the uber-image path covers icons too), reading
2023
2048
  * `iconSize`/`iconTone`. The other values are a harmless informational holdover from the previous
@@ -2036,29 +2061,29 @@ var CABImageSectionFields = z26.object({
2036
2061
  * behavior degraded gracefully and told us about it. The client-assembled half of the invariant was never
2037
2062
  * the risky half.
2038
2063
  */
2039
- category: z26.enum(["gallery", "icon", "icons", "payment-methods", "secure-checkout"]).nullable().default(null),
2064
+ category: z27.enum(["gallery", "icon", "icons", "payment-methods", "secure-checkout"]).nullable().default(null),
2040
2065
  /** `icon`-mode only: the `s-icon` `size`; `null` ⇒ the component default (`base`). Ignored by image treatments. */
2041
- iconSize: z26.enum(iconSizes).nullable().default(null),
2066
+ iconSize: z27.enum(iconSizes).nullable().default(null),
2042
2067
  /** `icon`-mode only: the `s-icon` `tone`; `null` ⇒ the component default (`auto`). Ignored by image treatments. */
2043
- iconTone: z26.enum(iconTones).nullable().default(null),
2044
- name: z26.string().optional(),
2045
- naturalHeight: z26.number().default(0),
2046
- naturalWidth: z26.number().default(0),
2068
+ iconTone: z27.enum(iconTones).nullable().default(null),
2069
+ name: z27.string().optional(),
2070
+ naturalHeight: z27.number().default(0),
2071
+ naturalWidth: z27.number().default(0),
2047
2072
  /**
2048
2073
  * `contain` (the component default): dimensionless images render in s-image's 1/1 default frame, and
2049
2074
  * `cover` would crop non-square art (payment badges lost their edges — 15993); `contain` letterboxes.
2050
2075
  */
2051
- objectFit: z26.enum(objectFits).default(ObjectFit.contain),
2052
- sectionId: z26.uuid().default(() => uuidv712()),
2053
- sectionType: z26.literal(SectionType.image).default(SectionType.image),
2076
+ objectFit: z27.enum(objectFits).default(ObjectFit.contain),
2077
+ sectionId: z27.uuid().default(() => uuidv713()),
2078
+ sectionType: z27.literal(SectionType.image).default(SectionType.image),
2054
2079
  /**
2055
2080
  * An image URL or dynamic token, an empty default, or — when `category: 'icon'` — an icon NAME. Icon mode
2056
2081
  * takes a name or `''` only, NOT a token: no renderer resolves a token to an icon today, so accepting one
2057
2082
  * would promise a capability that doesn't exist. Widen the refine's carve-out to `DYNAMIC_TOKEN_REGEX` when a
2058
2083
  * server-chosen tier icon actually needs it.
2059
2084
  */
2060
- source: z26.union([z26.url(), z26.literal(""), z26.string().regex(DYNAMIC_TOKEN_REGEX), z26.enum(iconNames)]).default(""),
2061
- width: z26.number().default(100)
2085
+ source: z27.union([z27.url(), z27.literal(""), z27.string().regex(DYNAMIC_TOKEN_REGEX), z27.enum(iconNames)]).default(""),
2086
+ width: z27.number().default(100)
2062
2087
  });
2063
2088
  var iconNameSet = new Set(iconNames);
2064
2089
  var isIconName = (source) => iconNameSet.has(source);
@@ -2209,7 +2234,7 @@ var convertContentBlockTextToV2 = (language, text2 = literalText, textAlign = "c
2209
2234
  };
2210
2235
 
2211
2236
  // src/schema/widgets/checkout-and-beyond/root.ts
2212
- import { z as z27 } from "zod";
2237
+ import { z as z28 } from "zod";
2213
2238
 
2214
2239
  // src/schema/widgets/checkout-and-beyond/uiLabels.ts
2215
2240
  var UI_LABELS = {
@@ -2229,8 +2254,8 @@ var UI_LABELS = {
2229
2254
  };
2230
2255
 
2231
2256
  // src/schema/widgets/checkout-and-beyond/root.ts
2232
- var localized = (fallback) => z27.record(z27.string(), z27.string()).default(() => ({ ...fallback })).transform((labels) => Object.keys(labels).length > 0 ? labels : { ...fallback });
2233
- var CABUILabels = z27.object({
2257
+ var localized = (fallback) => z28.record(z28.string(), z28.string()).default(() => ({ ...fallback })).transform((labels) => Object.keys(labels).length > 0 ? labels : { ...fallback });
2258
+ var CABUILabels = z28.object({
2234
2259
  currentPage: localized(UI_LABELS.currentPage),
2235
2260
  guest: localized(UI_LABELS.guest),
2236
2261
  loadingOptions: localized(UI_LABELS.loadingOptions),
@@ -2255,37 +2280,37 @@ var CABUILabels = z27.object({
2255
2280
  subscriptionOptions: { ...UI_LABELS.subscriptionOptions },
2256
2281
  updating: { ...UI_LABELS.updating }
2257
2282
  }));
2258
- var TargetArea = z27.object({
2259
- fill: z27.boolean().optional(),
2260
- flip: z27.enum(["both", "horizontal", "vertical"]).optional(),
2261
- icon: z27.string(),
2262
- label: z27.string(),
2263
- width: z27.string()
2283
+ var TargetArea = z28.object({
2284
+ fill: z28.boolean().optional(),
2285
+ flip: z28.enum(["both", "horizontal", "vertical"]).optional(),
2286
+ icon: z28.string(),
2287
+ label: z28.string(),
2288
+ width: z28.string()
2264
2289
  }).default(targetAreas[EditorMode.checkoutExtension][1]);
2265
- var CABTracking = z27.object({
2266
- enableAttribution: z27.boolean().nullish().transform((value) => value ?? true),
2267
- enableSource: z27.boolean().nullish().transform((value) => value ?? true),
2268
- enableWidget: z27.boolean().nullish().transform((value) => value ?? true)
2290
+ var CABTracking = z28.object({
2291
+ enableAttribution: z28.boolean().nullish().transform((value) => value ?? true),
2292
+ enableSource: z28.boolean().nullish().transform((value) => value ?? true),
2293
+ enableWidget: z28.boolean().nullish().transform((value) => value ?? true)
2269
2294
  }).nullish().transform((value) => value ?? { enableAttribution: true, enableSource: true, enableWidget: true });
2270
- var CABExperiment = z27.object({
2271
- elementId: z27.number(),
2272
- experimentId: z27.number(),
2273
- experimentType: z27.string(),
2274
- selectedId: z27.number()
2295
+ var CABExperiment = z28.object({
2296
+ elementId: z28.number(),
2297
+ experimentId: z28.number(),
2298
+ experimentType: z28.string(),
2299
+ selectedId: z28.number()
2275
2300
  });
2276
2301
  var CABRootSection = CABLayoutSection.extend({
2277
- editorMode: z27.enum(editorModes).default(EditorMode.checkoutExtension),
2302
+ editorMode: z28.enum(editorModes).default(EditorMode.checkoutExtension),
2278
2303
  experiment: CABExperiment.optional(),
2279
2304
  // Same rule as CABTracking above: the v1 converters pass raw legacy `previewMode` through, so a
2280
2305
  // `null` must fall back rather than throw the widget; malformed values still throw.
2281
- previewMode: z27.boolean().nullish().transform((value) => value ?? false),
2282
- storeId: z27.number().nullable().default(null),
2306
+ previewMode: z28.boolean().nullish().transform((value) => value ?? false),
2307
+ storeId: z28.number().nullable().default(null),
2283
2308
  targetArea: TargetArea.nullable(),
2284
2309
  tracking: CABTracking,
2285
- type: z27.enum(widgetTypes).default(WidgetType.ui_extension_content_block),
2310
+ type: z28.enum(widgetTypes).default(WidgetType.ui_extension_content_block),
2286
2311
  uiLabels: CABUILabels,
2287
- version: z27.literal(2).default(2),
2288
- widgetId: z27.number().nullable().default(null)
2312
+ version: z28.literal(2).default(2),
2313
+ widgetId: z28.number().nullable().default(null)
2289
2314
  });
2290
2315
 
2291
2316
  // src/transforms/v1Location.ts
@@ -3694,6 +3719,393 @@ var convertOfferToV2 = ({ id, name, settings }) => {
3694
3719
  // src/transforms/parseShielded.ts
3695
3720
  var parseShielded = (schema, raw, transform = (input) => input) => schema.parse(transform(convertNumericObjects(deepCamelCase(raw))));
3696
3721
 
3722
+ // src/transforms/postPurchase/convertMessagePreview.ts
3723
+ import { z as z33 } from "zod";
3724
+
3725
+ // src/transforms/postPurchase/convertCalloutBlock.ts
3726
+ import { z as z31 } from "zod";
3727
+
3728
+ // src/schema/widgets/post-purchase-offer/postPurchaseBlocks.ts
3729
+ import { get as get2, isEqual } from "es-toolkit/compat";
3730
+ import { v4 as uuidv4 } from "uuid";
3731
+ import { z as z30 } from "zod";
3732
+
3733
+ // src/schema/widgets/post-purchase-offer/constants.ts
3734
+ import { z as z29 } from "zod";
3735
+ var blockTypes = [
3736
+ "callout_banner",
3737
+ "image",
3738
+ "image_content",
3739
+ "pay_button",
3740
+ "product_information",
3741
+ "separator",
3742
+ "text",
3743
+ "timer"
3744
+ ];
3745
+ var blockType = z29.enum(blockTypes);
3746
+ var BlockType = blockType.enum;
3747
+
3748
+ // src/schema/widgets/post-purchase-offer/postPurchaseBlocks.ts
3749
+ var TextAlignment2 = z30.union([z30.enum(["leading", "center", "trailing"]), z30.unknown().transform(() => "leading")]);
3750
+ var TextSize = z30.union([
3751
+ z30.enum(["xsmall", "small", "base", "default", "medium", "large", "xlarge"]),
3752
+ z30.unknown().transform(() => "medium")
3753
+ ]);
3754
+ var CalloutBannerBlock = z30.object({
3755
+ id: z30.string().optional().default(() => uuidv4()),
3756
+ name: z30.string().optional(),
3757
+ settings: z30.object({
3758
+ superTitle: z30.union([z30.string(), TiptapDocument]).default(() => "Limited-time Offer"),
3759
+ title: z30.union([z30.string(), TiptapDocument]).default(() => "Add this customer favorite to your order")
3760
+ }),
3761
+ styles: z30.object({
3762
+ superTitleEmphasized: z30.boolean().default(false),
3763
+ superTitleSize: TextSize.default("large"),
3764
+ textAlignment: TextAlignment2.default("center"),
3765
+ titleEmphasized: z30.boolean().default(true),
3766
+ titleSize: TextSize.default("large")
3767
+ }),
3768
+ type: z30.literal(BlockType.callout_banner).default(BlockType.callout_banner)
3769
+ });
3770
+ var ImageBlock = z30.object({
3771
+ id: z30.string().optional().default(() => uuidv4()),
3772
+ name: z30.string().optional(),
3773
+ settings: z30.union([
3774
+ z30.object({
3775
+ /** This isn't used in the post-purchase offer widget */
3776
+ alt: z30.string().optional().default(""),
3777
+ image: z30.union([z30.literal(""), z30.url()]).default(""),
3778
+ imageSize: z30.number().default(20),
3779
+ imageType: z30.enum(["URL", "UPLOAD"]).default("URL")
3780
+ }),
3781
+ z30.array(z30.never()).transform(() => ({}))
3782
+ ]),
3783
+ type: z30.literal(BlockType.image).default(BlockType.image)
3784
+ });
3785
+ var ImageContentBlock = z30.object({
3786
+ id: z30.string().optional().default(() => uuidv4()),
3787
+ name: z30.string().optional(),
3788
+ settings: z30.object({
3789
+ alt: z30.string().optional().default(""),
3790
+ description: z30.union([z30.string(), TiptapDocument, z30.null()]).default(
3791
+ "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."
3792
+ ),
3793
+ descriptionSize: TextSize.default("medium"),
3794
+ horizontalAlignment: TextAlignment2.default("leading"),
3795
+ image: z30.union([z30.literal(""), z30.url()]).default(""),
3796
+ imagePlacement: z30.enum(["bottom", "left", "right", "top"]).optional().default("left"),
3797
+ imageSize: z30.number().default(20),
3798
+ superTitle: z30.union([z30.string(), TiptapDocument]).default("Lorem Ipsum!"),
3799
+ superTitleSize: TextSize.default("medium"),
3800
+ /** This isn't configurable in the admin-nextjs editor */
3801
+ swapContent: z30.boolean().optional().default(false),
3802
+ title: z30.union([z30.string(), TiptapDocument]).nullable().default("Lorem ipsum dolor sit amet"),
3803
+ titleSize: TextSize.default("medium")
3804
+ }),
3805
+ type: z30.literal(BlockType.image_content).default(BlockType.image_content)
3806
+ });
3807
+ var PayButtonBlock = z30.object({
3808
+ id: z30.string().optional().default(() => uuidv4()),
3809
+ name: z30.string().optional(),
3810
+ settings: z30.union([
3811
+ z30.object({
3812
+ label: z30.string().default("Pay Now")
3813
+ }),
3814
+ z30.array(z30.never()).transform(() => ({
3815
+ label: "Pay Now"
3816
+ }))
3817
+ ]),
3818
+ styles: z30.union([
3819
+ z30.object({
3820
+ buttonWidth: z30.number().min(10).max(100).default(50)
3821
+ }),
3822
+ z30.array(z30.never()).transform(() => ({
3823
+ buttonWidth: 50
3824
+ }))
3825
+ ]),
3826
+ type: z30.literal(BlockType.pay_button).default(BlockType.pay_button)
3827
+ });
3828
+ var ProductInformationBlock = z30.object({
3829
+ /** This isn't configurable in the admin-nextjs editor */
3830
+ hideProductImage: z30.boolean().optional().default(false),
3831
+ id: z30.string().optional().default(() => uuidv4()),
3832
+ name: z30.string().optional(),
3833
+ type: z30.literal(BlockType.product_information).default(BlockType.product_information)
3834
+ });
3835
+ var SeparatorBlock = z30.object({
3836
+ id: z30.string().optional().default(() => uuidv4()),
3837
+ name: z30.string().optional(),
3838
+ type: z30.literal(BlockType.separator).default(BlockType.separator)
3839
+ });
3840
+ var TextBlock = z30.object({
3841
+ id: z30.string().optional().default(() => uuidv4()),
3842
+ name: z30.string().optional(),
3843
+ settings: z30.object({
3844
+ description: z30.union([z30.string(), TiptapDocument]).optional().default(
3845
+ "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."
3846
+ ),
3847
+ /** This isn't used in the post-purchase offer widget */
3848
+ descriptionSize: TextSize.default("medium"),
3849
+ horizontalAlignment: TextAlignment2.default("leading"),
3850
+ superTitle: z30.union([z30.string(), TiptapDocument]).default("Super Title"),
3851
+ /** This isn't used in the post-purchase offer widget */
3852
+ superTitleSize: TextSize.default("medium"),
3853
+ title: z30.union([z30.string(), TiptapDocument]).nullable().default("Lorem ipsum dolor sit amet."),
3854
+ /** This isn't used in the post-purchase offer widget */
3855
+ titleSize: TextSize.default("medium")
3856
+ }),
3857
+ type: z30.literal(BlockType.text).default(BlockType.text)
3858
+ });
3859
+ var TimerBlock = z30.object({
3860
+ id: z30.string().optional().default(() => uuidv4()),
3861
+ name: z30.string().optional(),
3862
+ settings: z30.object({
3863
+ durationMinutes: z30.number().min(0).default(10),
3864
+ durationSeconds: z30.union([z30.number().min(0), z30.unknown().transform(() => 0)]).default(0),
3865
+ endOffer: z30.boolean().default(true),
3866
+ title: z30.union([z30.string(), TiptapDocument]).default("Hurry \u2014 your special offer ends in:")
3867
+ }),
3868
+ styles: z30.object({
3869
+ textAlignment: TextAlignment2.default("center"),
3870
+ timerBackgroundColor: z30.enum(["info", "warning", "success", "critical"]).default("warning"),
3871
+ timerEmphasized: z30.union([z30.boolean(), z30.unknown().transform(() => true)]).default(true),
3872
+ timerSize: TextSize.default("medium"),
3873
+ timerWidth: z30.number().min(10).max(100).optional().default(100),
3874
+ titleEmphasized: z30.union([z30.boolean(), z30.unknown().transform(() => true)]).default(false),
3875
+ titleSize: TextSize.default("medium")
3876
+ }),
3877
+ type: z30.literal(BlockType.timer).default(BlockType.timer)
3878
+ });
3879
+ var PostPurchaseBlock = z30.discriminatedUnion("type", [
3880
+ CalloutBannerBlock,
3881
+ ImageBlock,
3882
+ ImageContentBlock,
3883
+ PayButtonBlock,
3884
+ ProductInformationBlock,
3885
+ SeparatorBlock,
3886
+ TextBlock,
3887
+ TimerBlock
3888
+ ]);
3889
+
3890
+ // src/transforms/postPurchase/styledTextRun.ts
3891
+ var sizes = {
3892
+ base: "base",
3893
+ default: "base",
3894
+ large: "large",
3895
+ medium: "medium",
3896
+ small: "small",
3897
+ xlarge: "extraLarge",
3898
+ xsmall: "extraSmall"
3899
+ };
3900
+ var styledTextRun = (text2, emphasized, size) => ({
3901
+ marks: [
3902
+ ...emphasized ? [{ type: "bold" }] : [],
3903
+ { attrs: { color: "base", fontSize: sizes[size] }, type: "textStyle" }
3904
+ ],
3905
+ text: text2,
3906
+ type: "text"
3907
+ });
3908
+
3909
+ // src/transforms/postPurchase/convertCalloutBlock.ts
3910
+ var fields = ["superTitle", "title"];
3911
+ var Shell = CalloutBannerBlock.pick({ styles: true }).extend({
3912
+ settings: z31.object({ superTitle: z31.unknown().optional(), title: z31.unknown().optional() })
3913
+ });
3914
+ var convertCalloutBlock = (raw, report) => {
3915
+ const omit = (detail) => {
3916
+ report?.({ detail, kind: "section" });
3917
+ return [];
3918
+ };
3919
+ const shell = Shell.safeParse(raw);
3920
+ if (!shell.success) return omit("Unreadable post-purchase callout");
3921
+ const values = fields.map((field) => ({
3922
+ field,
3923
+ result: CalloutBannerBlock.shape.settings.shape[field].safeParse(shell.data.settings[field])
3924
+ }));
3925
+ const styled2 = values.every(({ result }) => result.success && typeof result.data === "string");
3926
+ const styles2 = shell.data.styles;
3927
+ const horizontal = styled2 ? { center: "center", leading: "start", trailing: "end" }[styles2.textAlignment] : "center";
3928
+ const sections = values.flatMap(({ field, result }) => {
3929
+ if (!result.success) return omit(`Unreadable post-purchase callout field: ${field}`);
3930
+ const text2 = result.data;
3931
+ if (text2 === "") return [];
3932
+ const content = styled2 && typeof text2 === "string" ? {
3933
+ content: [
3934
+ {
3935
+ attrs: { textAlign: horizontal },
3936
+ content: [styledTextRun(text2, styles2[`${field}Emphasized`], styles2[`${field}Size`])]
3937
+ }
3938
+ ]
3939
+ } : text2;
3940
+ const section = CABTextSection.safeParse({ content: { en: content } });
3941
+ return section.success ? [section.data] : omit(`Unreadable post-purchase callout field: ${field}`);
3942
+ });
3943
+ return sections.length ? [CABLayoutSection.parse({ alignment: { horizontal }, frame: "callout", sections })] : [];
3944
+ };
3945
+
3946
+ // src/transforms/postPurchase/convertPayButtonBlock.ts
3947
+ var convertPayButtonBlock = (raw, report) => {
3948
+ const omit = () => {
3949
+ report?.({ detail: "Unreadable post-purchase Pay block", kind: "section" });
3950
+ return [];
3951
+ };
3952
+ const parsed = PayButtonBlock.safeParse(raw);
3953
+ if (!parsed.success) return omit();
3954
+ const { settings, styles: styles2 } = parsed.data;
3955
+ const label2 = settings.label ? `${settings.label} \xB7 {{total}}` : "{{total}}";
3956
+ const text2 = CABTextSection.safeParse({ content: { en: label2 } });
3957
+ if (!text2.success) return omit();
3958
+ return [
3959
+ CABLayoutSection.parse({
3960
+ alignment: { horizontal: "center" },
3961
+ direction: "grid",
3962
+ grid: { columns: ["100%"] },
3963
+ sections: [
3964
+ CABButtonSection.parse({
3965
+ action: "addToOrder",
3966
+ sections: [text2.data]
3967
+ })
3968
+ ],
3969
+ width: styles2.buttonWidth
3970
+ })
3971
+ ];
3972
+ };
3973
+
3974
+ // src/transforms/postPurchase/convertSeparatorBlock.ts
3975
+ var convertSeparatorBlock = (raw, report) => {
3976
+ if (!SeparatorBlock.safeParse(raw).success) {
3977
+ report?.({ detail: "Unreadable post-purchase separator", kind: "section" });
3978
+ return [];
3979
+ }
3980
+ return [CABSeparatorSection.parse({})];
3981
+ };
3982
+
3983
+ // src/transforms/postPurchase/convertTextBlock.ts
3984
+ import { z as z32 } from "zod";
3985
+ var fields2 = ["superTitle", "title", "description"];
3986
+ var styles = {
3987
+ description: [{ attrs: { color: "base", fontSize: "small" }, type: "textStyle" }],
3988
+ superTitle: [{ attrs: { color: "subdued", fontSize: "small" }, type: "textStyle" }],
3989
+ title: [{ type: "bold" }, { attrs: { color: "base", fontSize: "large" }, type: "textStyle" }]
3990
+ };
3991
+ var settingsSchema = TextBlock.shape.settings;
3992
+ var Shell2 = z32.object({
3993
+ settings: settingsSchema.pick({ horizontalAlignment: true }).extend({
3994
+ description: z32.unknown().optional(),
3995
+ superTitle: z32.unknown().optional(),
3996
+ title: z32.unknown().optional()
3997
+ }),
3998
+ type: z32.literal("text")
3999
+ });
4000
+ var convertTextBlock = (raw, report) => {
4001
+ const shell = Shell2.safeParse(raw);
4002
+ if (!shell.success) {
4003
+ report?.({ detail: "Unreadable post-purchase text block", kind: "section" });
4004
+ return [];
4005
+ }
4006
+ const values = fields2.map((field) => ({
4007
+ field,
4008
+ result: settingsSchema.shape[field].safeParse(shell.data.settings[field])
4009
+ }));
4010
+ const horizontal = { center: "center", leading: "start", trailing: "end" }[shell.data.settings.horizontalAlignment];
4011
+ const styled2 = values.every(({ result }) => result.success && typeof result.data === "string");
4012
+ const omit = (field) => {
4013
+ report?.({ detail: `Unreadable post-purchase text field: ${field}`, kind: "section" });
4014
+ return [];
4015
+ };
4016
+ const sections = values.flatMap(({ field, result }) => {
4017
+ if (!result.success) return omit(field);
4018
+ const text2 = result.data;
4019
+ if (text2 === null || text2 === "") return [];
4020
+ const content = styled2 ? { content: [{ attrs: { textAlign: horizontal }, content: [{ marks: styles[field], text: text2 }] }] } : text2;
4021
+ const section = CABTextSection.safeParse({ content: { en: content } });
4022
+ return section.success ? [section.data] : omit(field);
4023
+ });
4024
+ return [
4025
+ CABLayoutSection.parse({
4026
+ alignment: {
4027
+ horizontal
4028
+ },
4029
+ sections
4030
+ })
4031
+ ];
4032
+ };
4033
+
4034
+ // src/transforms/postPurchase/convertTimerBlock.ts
4035
+ var Presentation = TimerBlock.pick({ styles: true }).extend({
4036
+ settings: TimerBlock.shape.settings.pick({ title: true })
4037
+ });
4038
+ var convertTimerBlock = (raw, report) => {
4039
+ const omit = () => {
4040
+ report?.({ detail: "Unreadable post-purchase timer display", kind: "section" });
4041
+ return [];
4042
+ };
4043
+ const parsed = Presentation.safeParse(raw);
4044
+ if (!parsed.success) return omit();
4045
+ const { title } = parsed.data.settings;
4046
+ const styles2 = parsed.data.styles;
4047
+ const horizontal = { center: "center", leading: "start", trailing: "end" }[styles2.textAlignment];
4048
+ const content = typeof title === "string" ? {
4049
+ content: [
4050
+ {
4051
+ attrs: { textAlign: horizontal },
4052
+ content: [
4053
+ styledTextRun(title, styles2.titleEmphasized, styles2.titleSize),
4054
+ styledTextRun(" {{timeRemaining}}", styles2.timerEmphasized, styles2.timerSize)
4055
+ ]
4056
+ }
4057
+ ]
4058
+ } : title;
4059
+ const text2 = CABTextSection.safeParse({ content: { en: content } });
4060
+ if (!text2.success) return omit();
4061
+ return [
4062
+ CABBannerSection.parse({
4063
+ color: styles2.timerBackgroundColor,
4064
+ dismissible: false,
4065
+ sections: [text2.data],
4066
+ width: styles2.timerWidth
4067
+ })
4068
+ ];
4069
+ };
4070
+
4071
+ // src/transforms/postPurchase/convertMessagePreview.ts
4072
+ var MessageWidget = z33.object({
4073
+ blocks: z33.array(z33.unknown()).min(1),
4074
+ type: z33.literal("shopify_post_purchase_extension")
4075
+ });
4076
+ var BlockType2 = z33.object({ type: z33.string() });
4077
+ var converters = {
4078
+ callout_banner: convertCalloutBlock,
4079
+ pay_button: convertPayButtonBlock,
4080
+ separator: convertSeparatorBlock,
4081
+ text: convertTextBlock,
4082
+ timer: convertTimerBlock
4083
+ };
4084
+ var convertMessagePreview = (id, settings, report) => {
4085
+ const parsed = MessageWidget.safeParse(settings);
4086
+ if (!parsed.success) throw new NotFoundError("Unsupported post-purchase message preview");
4087
+ return CABRootSection.parse({
4088
+ editorMode: "postPurchaseOffer",
4089
+ previewMode: true,
4090
+ sections: parsed.data.blocks.flatMap((block) => {
4091
+ const type = BlockType2.safeParse(block);
4092
+ const kind = type.success ? type.data.type : void 0;
4093
+ const convert2 = kind ? converters[kind] : void 0;
4094
+ if (convert2) return convert2(block, report);
4095
+ report?.({
4096
+ detail: kind ? `Unsupported post-purchase block type: ${kind}` : "Unreadable post-purchase block: missing type",
4097
+ kind: "section"
4098
+ });
4099
+ return [];
4100
+ }),
4101
+ sectionType: "layout",
4102
+ widgetId: id
4103
+ });
4104
+ };
4105
+
4106
+ // src/transforms/postPurchase/types.ts
4107
+ var isPostPurchaseV1 = (data) => !!data && typeof data === "object" && data.type === WidgetType.shopify_post_purchase_extension && Array.isArray(data.blocks);
4108
+
3697
4109
  // src/transforms/presentmentThresholds.ts
3698
4110
  var presentmentThresholds = (presentment) => {
3699
4111
  if (!presentment?.enabled) return {};
@@ -4078,7 +4490,7 @@ var fetchUserConfig = async (input, ctx) => {
4078
4490
  };
4079
4491
 
4080
4492
  // src/utilities.ts
4081
- import { v4 as uuidv4 } from "uuid";
4493
+ import { v4 as uuidv42 } from "uuid";
4082
4494
  function serialize(obj) {
4083
4495
  const serialized = [];
4084
4496
  const add = (key, value) => {
@@ -4206,7 +4618,7 @@ var fetchDataSourceResults = async (input, ctx) => {
4206
4618
  };
4207
4619
 
4208
4620
  // src/server/adsEngine.ts
4209
- import { z as z28 } from "zod";
4621
+ import { z as z34 } from "zod";
4210
4622
  var SUPPLY_KEY = { production: "AQF5RKLR", staging: "Z56LQ7PS" };
4211
4623
  var OFFER_LIMIT = 4;
4212
4624
  var SUPPORTED_COUNTRIES = /* @__PURE__ */ new Set(["US", "CA"]);
@@ -4219,28 +4631,28 @@ var transactionItems = (input) => (input.transactionItems?.map(({ id, priceCents
4219
4631
  title,
4220
4632
  type
4221
4633
  })) ?? input.cart.items.map(({ productId, quantity }) => ({ id: productId, quantity }))).slice(0, MAX_TRANSACTION_ITEMS);
4222
- var AdsEngineOffer = z28.object({
4634
+ var AdsEngineOffer = z34.object({
4223
4635
  /** Pill-style value prop ("Get $45 Cashback"). Carried through the parse; the card does not render it yet (REB-24429 — pill design pending). */
4224
- callout: z28.string().catch(""),
4225
- click_url: z28.string(),
4226
- cta: z28.string(),
4636
+ callout: z34.string().catch(""),
4637
+ click_url: z34.string(),
4638
+ cta: z34.string(),
4227
4639
  /** `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'). */
4228
- decline_cta: z28.string().catch(""),
4229
- decline_url: z28.string(),
4230
- description: z28.string(),
4640
+ decline_cta: z34.string().catch(""),
4641
+ decline_url: z34.string(),
4642
+ description: z34.string(),
4231
4643
  /** Short legal disclosure (FDIC / auto-renewal / FTC-affiliation lines). Rendered subdued under the CTAs. */
4232
- disclaimer: z28.string().catch(""),
4644
+ disclaimer: z34.string().catch(""),
4233
4645
  /** Long legal text behind the disclosure toggle in the composed card (REB-24429). */
4234
- extended_disclaimer: z28.string().catch(""),
4235
- headline: z28.string(),
4236
- id: z28.string(),
4646
+ extended_disclaimer: z34.string().catch(""),
4647
+ headline: z34.string(),
4648
+ id: z34.string(),
4237
4649
  /** Advertiser-supplied image alt; the composed card falls back to the stripped headline when empty. */
4238
- image_alt: z28.string().catch(""),
4239
- image_url: z28.string().optional(),
4240
- view_url: z28.string()
4650
+ image_alt: z34.string().catch(""),
4651
+ image_url: z34.string().optional(),
4652
+ view_url: z34.string()
4241
4653
  });
4242
- var AdsEngineResponse = z28.object({
4243
- offers: z28.array(z28.unknown()).default([]).transform(
4654
+ var AdsEngineResponse = z34.object({
4655
+ offers: z34.array(z34.unknown()).default([]).transform(
4244
4656
  (offers) => offers.flatMap((offer) => {
4245
4657
  const result = AdsEngineOffer.safeParse(offer);
4246
4658
  return result.success ? [result.data] : [];
@@ -4252,8 +4664,8 @@ var AdsEngineResponse = z28.object({
4252
4664
  * offers-testing fixture on a test store forces it, REB-24467). Both optional: an older engine or a
4253
4665
  * non-JSON body must not fail the parse and drop the offers.
4254
4666
  */
4255
- request_id: z28.string().optional().catch(void 0),
4256
- testing: z28.boolean().optional().catch(void 0)
4667
+ request_id: z34.string().optional().catch(void 0),
4668
+ testing: z34.boolean().optional().catch(void 0)
4257
4669
  });
4258
4670
  var adsHost = (host) => `offers.${host}`;
4259
4671
  var isTestingRequest = (input, isProduction) => !isProduction || !!input.testing || input.customerEmail?.toLowerCase() === TEST_CUSTOMER_EMAIL;
@@ -4526,7 +4938,7 @@ var fetchMonetizeOffers = async (input, ctx, prefetched) => {
4526
4938
  };
4527
4939
 
4528
4940
  // src/server/salvageSections.ts
4529
- import { v7 as uuidv713 } from "uuid";
4941
+ import { v7 as uuidv714 } from "uuid";
4530
4942
  var STUB_SECTION_TYPE = "unknown";
4531
4943
  var knownSectionTypes = new Set(sectionTypes);
4532
4944
  var hasSectionsArray = (raw) => typeof raw === "object" && raw !== null && Array.isArray(raw.sections);
@@ -4539,7 +4951,7 @@ var stubSection = (raw, report) => {
4539
4951
  kind: "section"
4540
4952
  });
4541
4953
  return {
4542
- sectionId: typeof rawId === "string" && rawId ? rawId : uuidv713(),
4954
+ sectionId: typeof rawId === "string" && rawId ? rawId : uuidv714(),
4543
4955
  sectionType: typeof original === "string" && !knownSectionTypes.has(original) ? original : STUB_SECTION_TYPE
4544
4956
  };
4545
4957
  };
@@ -4568,6 +4980,7 @@ var dispatchWidgetTransform = (id, normalized, report) => {
4568
4980
  if (isLineItemEditorV1(normalized)) return convertLineItemEditorToV2({ id, settings: normalized });
4569
4981
  if (isMonetizeV1(normalized)) return convertMonetizeToV2({ id, settings: normalized });
4570
4982
  if (isPlaceholderV1(normalized)) return convertPlaceholderToV2({ id, settings: normalized });
4983
+ if (isPostPurchaseV1(normalized)) return convertMessagePreview(id, normalized, report);
4571
4984
  if (isOfferV1(normalized)) return convertOfferToV2({ id, name: normalized.name, settings: normalized });
4572
4985
  return normalized;
4573
4986
  };
@@ -4682,13 +5095,13 @@ var convertWidgetSettings = async (input, ctx) => {
4682
5095
  };
4683
5096
 
4684
5097
  // src/server/giftWidgets.ts
4685
- import { z as z29 } from "zod";
4686
- var SettingsNumber = z29.union([
4687
- z29.number(),
4688
- z29.string().trim().regex(/^-?\d+(\.\d+)?$/)
4689
- ]).pipe(z29.coerce.number());
4690
- var SgwpMilestoneSchema = z29.object({
4691
- selectable_product_quantity: SettingsNumber.pipe(z29.number().int().nonnegative()),
5098
+ import { z as z35 } from "zod";
5099
+ var SettingsNumber = z35.union([
5100
+ z35.number(),
5101
+ z35.string().trim().regex(/^-?\d+(\.\d+)?$/)
5102
+ ]).pipe(z35.coerce.number());
5103
+ var SgwpMilestoneSchema = z35.object({
5104
+ selectable_product_quantity: SettingsNumber.pipe(z35.number().int().nonnegative()),
4692
5105
  unlock_price: SettingsNumber
4693
5106
  });
4694
5107
  var fetchGiftWidgetSettings = async (widgetId, shop, ctx) => unwrapData(await ctx.fetchUpstream("/api/v1/widgets/settings", { id: String(widgetId), shop }, { host: ctx.host }));
@@ -4699,7 +5112,7 @@ var readDataSourcePath = (settings) => {
4699
5112
  var readMilestones = (settings, report) => {
4700
5113
  const raw = settings && typeof settings === "object" ? settings.milestones : void 0;
4701
5114
  if (raw == null) return [];
4702
- const parsed = z29.array(SgwpMilestoneSchema).safeParse(raw);
5115
+ const parsed = z35.array(SgwpMilestoneSchema).safeParse(raw);
4703
5116
  if (parsed.success) return parsed.data;
4704
5117
  report?.({
4705
5118
  detail: [
@@ -4948,7 +5361,7 @@ var postAnalyticsEvents = async (input, ctx) => {
4948
5361
  };
4949
5362
 
4950
5363
  // src/server/requestSchemas.ts
4951
- import { z as z30 } from "zod";
5364
+ import { z as z36 } from "zod";
4952
5365
  var REQUEST_BOUNDS = {
4953
5366
  /** Cart-level attributes per cart. */
4954
5367
  CART_ATTRIBUTES_MAX: 100,
@@ -4979,42 +5392,42 @@ var REQUEST_BOUNDS = {
4979
5392
  /** Rich ads transaction lines — the engine's ads contract. */
4980
5393
  TRANSACTION_ITEMS_MAX: 50
4981
5394
  };
4982
- var KeyValue = z30.object({
4983
- key: z30.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
4984
- value: z30.string().max(REQUEST_BOUNDS.STRING_VALUE_MAX).optional()
5395
+ var KeyValue = z36.object({
5396
+ key: z36.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
5397
+ value: z36.string().max(REQUEST_BOUNDS.STRING_VALUE_MAX).optional()
4985
5398
  });
4986
- var CartLineInputSchema = z30.object({
4987
- productId: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
4988
- properties: z30.array(KeyValue).max(REQUEST_BOUNDS.LINE_PROPERTIES_MAX).optional(),
4989
- quantity: z30.number(),
4990
- subscriptionId: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
4991
- variantId: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX)
5399
+ var CartLineInputSchema = z36.object({
5400
+ productId: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5401
+ properties: z36.array(KeyValue).max(REQUEST_BOUNDS.LINE_PROPERTIES_MAX).optional(),
5402
+ quantity: z36.number(),
5403
+ subscriptionId: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5404
+ variantId: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX)
4992
5405
  });
4993
- var CartInputSchema = z30.object({
4994
- attributes: z30.array(KeyValue).max(REQUEST_BOUNDS.CART_ATTRIBUTES_MAX).optional(),
5406
+ var CartInputSchema = z36.object({
5407
+ attributes: z36.array(KeyValue).max(REQUEST_BOUNDS.CART_ATTRIBUTES_MAX).optional(),
4995
5408
  /**
4996
5409
  * Presentment-per-shop-currency FX rate (buyer price ÷ shop price, e.g. `1.35` for a USD shop
4997
5410
  * selling in CAD). Money rule thresholds are authored in SHOP currency, so the engine subtotal is
4998
5411
  * divided by this before evaluation. Omit (or send 1) when the cart is already in the shop's currency.
4999
5412
  */
5000
- currencyRate: z30.number().optional(),
5413
+ currencyRate: z36.number().optional(),
5001
5414
  /** Applied discount codes; the engine evaluates `discount_code` rules against them (sent as `[{code}]`). */
5002
- discountCodes: z30.array(z30.string().max(REQUEST_BOUNDS.STRING_KEY_MAX)).max(REQUEST_BOUNDS.DISCOUNT_CODES_MAX).optional(),
5415
+ discountCodes: z36.array(z36.string().max(REQUEST_BOUNDS.STRING_KEY_MAX)).max(REQUEST_BOUNDS.DISCOUNT_CODES_MAX).optional(),
5003
5416
  /** Presentment cents of cart-level discount allocations, subtracted from `subtotal` for the engine. */
5004
- discountTotal: z30.number().optional(),
5005
- items: z30.array(CartLineInputSchema).max(REQUEST_BOUNDS.CART_ITEMS_MAX),
5417
+ discountTotal: z36.number().optional(),
5418
+ items: z36.array(CartLineInputSchema).max(REQUEST_BOUNDS.CART_ITEMS_MAX),
5006
5419
  /** Presentment subtotal in cents. */
5007
- subtotal: z30.number()
5420
+ subtotal: z36.number()
5008
5421
  });
5009
- var UserConfigInputSchema = z30.object({ shop: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX) });
5010
- var DataSourceInputSchema = z30.object({
5422
+ var UserConfigInputSchema = z36.object({ shop: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX) });
5423
+ var DataSourceInputSchema = z36.object({
5011
5424
  cart: CartInputSchema,
5012
5425
  /**
5013
5426
  * Numeric Shopify company-location id when the buyer is a B2B session (`buyerIdentity.purchasingCompany`).
5014
5427
  * Present ⇒ the orchestrator filters results by the location's catalog via admin-api (REB-23713); the
5015
5428
  * client's country-context market check is bypassed for B2B (it false-negatives B2B-catalog products).
5016
5429
  */
5017
- companyLocationId: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5430
+ companyLocationId: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5018
5431
  /**
5019
5432
  * Buyer's market country (ISO 3166-1 alpha-2) — forwarded to the engine as the `country_code` PARAM
5020
5433
  * when the shop's markets toggle is on (REB-21688; the sink was the `X-Country-Code` header under
@@ -5023,16 +5436,16 @@ var DataSourceInputSchema = z30.object({
5023
5436
  * uppercase (the wire value is forwarded verbatim as the param) so a case-sensitive engine lookup
5024
5437
  * can't silently miss a lowercase code — `adsEngine.ts` uppercases for the same reason.
5025
5438
  */
5026
- country: z30.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(),
5027
- customerId: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5028
- dataSourcePath: z30.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
5439
+ country: z36.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(),
5440
+ customerId: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5441
+ dataSourcePath: z36.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
5029
5442
  /**
5030
5443
  * Engine `filter_inputs` override: `'no'` keeps in-cart (input) products in the results/rule
5031
5444
  * outputs — gift validation sends it so a gift's own product can appear in its answer. Omitted = the
5032
5445
  * engine's default filtering.
5033
5446
  */
5034
- filterInputs: z30.enum(["no", "yes"]).optional(),
5035
- integrations: z30.record(z30.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), z30.boolean()).refine((record) => Object.keys(record).length <= REQUEST_BOUNDS.INTEGRATION_KEYS_MAX, {
5447
+ filterInputs: z36.enum(["no", "yes"]).optional(),
5448
+ integrations: z36.record(z36.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), z36.boolean()).refine((record) => Object.keys(record).length <= REQUEST_BOUNDS.INTEGRATION_KEYS_MAX, {
5036
5449
  message: `Too many integration keys (max ${REQUEST_BOUNDS.INTEGRATION_KEYS_MAX})`
5037
5450
  }).optional(),
5038
5451
  /**
@@ -5045,31 +5458,31 @@ var DataSourceInputSchema = z30.object({
5045
5458
  * request header) fails the regex. Callers should send the buyer's resolved locale (e.g. Shopify
5046
5459
  * checkout's `localization.language.isoCode`), not the request header verbatim.
5047
5460
  */
5048
- language: z30.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(),
5049
- limit: z30.number().max(REQUEST_BOUNDS.LIMIT_MAX),
5050
- productType: z30.enum(["both", "one-time", "subscription"]).optional(),
5051
- shop: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5052
- visitorId: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
5461
+ language: z36.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(),
5462
+ limit: z36.number().max(REQUEST_BOUNDS.LIMIT_MAX),
5463
+ productType: z36.enum(["both", "one-time", "subscription"]).optional(),
5464
+ shop: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5465
+ visitorId: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
5053
5466
  });
5054
- var GiftInputSchema = z30.object({
5055
- cost: z30.number(),
5056
- discounted: z30.boolean(),
5467
+ var GiftInputSchema = z36.object({
5468
+ cost: z36.number(),
5469
+ discounted: z36.boolean(),
5057
5470
  /**
5058
5471
  * Which gift attribution the line carries (REB-24363). Defaults to `gwp` because a client that predates
5059
5472
  * the field only ever sent GWP lines — without the default an older extension's request would 422.
5060
5473
  */
5061
- kind: z30.enum(GIFT_KINDS).default("gwp"),
5062
- lineId: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5063
- productId: z30.number(),
5474
+ kind: z36.enum(GIFT_KINDS).default("gwp"),
5475
+ lineId: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5476
+ productId: z36.number(),
5064
5477
  /**
5065
5478
  * The line's unit count (REB-24363) — the selectable-GWP verdict trims surplus units against milestone
5066
5479
  * capacity. The second deliberate default: a client predating the field sent only GWP lines, whose
5067
5480
  * verdict is whole-line, so a missing quantity reads as one unit rather than 422ing the older request.
5068
5481
  */
5069
- quantity: z30.number().int().min(1).default(1),
5070
- widgetId: z30.number()
5482
+ quantity: z36.number().int().min(1).default(1),
5483
+ widgetId: z36.number()
5071
5484
  });
5072
- var GiftValidationInputSchema = z30.object({
5485
+ var GiftValidationInputSchema = z36.object({
5073
5486
  cart: CartInputSchema,
5074
5487
  /**
5075
5488
  * Buyer's market country — threaded into the per-widget data-source evaluations, which forward it to
@@ -5078,25 +5491,25 @@ var GiftValidationInputSchema = z30.object({
5078
5491
  * turns markets off); regex-bound and uppercase-normalized for the same reasons as
5079
5492
  * `DataSourceInputSchema`'s `country`.
5080
5493
  */
5081
- country: z30.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(),
5082
- customerId: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5083
- gifts: z30.array(GiftInputSchema).max(REQUEST_BOUNDS.GIFTS_MAX),
5494
+ country: z36.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(),
5495
+ customerId: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5496
+ gifts: z36.array(GiftInputSchema).max(REQUEST_BOUNDS.GIFTS_MAX),
5084
5497
  /**
5085
5498
  * Buyer's checkout language — threaded into the per-widget data-source evaluations, which normalize
5086
5499
  * and forward it as the engine `locale` param under the same markets-toggle gate (REB-21688). MUST be
5087
5500
  * a single BCP-47 tag, for the same reason as `DataSourceInputSchema`'s `language` above.
5088
5501
  */
5089
- language: z30.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(),
5090
- shop: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5091
- visitorId: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
5502
+ language: z36.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(),
5503
+ shop: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5504
+ visitorId: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
5092
5505
  });
5093
- var GiftAdjustmentSchema = z30.object({
5094
- lineId: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5095
- quantity: z30.number().int().nonnegative()
5506
+ var GiftAdjustmentSchema = z36.object({
5507
+ lineId: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5508
+ quantity: z36.number().int().nonnegative()
5096
5509
  });
5097
- var GiftValidationResponseSchema = z30.object({
5098
- adjust: z30.array(GiftAdjustmentSchema).max(REQUEST_BOUNDS.GIFTS_MAX).default([]),
5099
- remove: z30.array(z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX)).max(REQUEST_BOUNDS.GIFTS_MAX).refine(
5510
+ var GiftValidationResponseSchema = z36.object({
5511
+ adjust: z36.array(GiftAdjustmentSchema).max(REQUEST_BOUNDS.GIFTS_MAX).default([]),
5512
+ remove: z36.array(z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX)).max(REQUEST_BOUNDS.GIFTS_MAX).refine(
5100
5513
  (remove) => new Set(remove).size === remove.length,
5101
5514
  "a line id may appear at most once in `remove`"
5102
5515
  )
@@ -5107,47 +5520,47 @@ var GiftValidationResponseSchema = z30.object({
5107
5520
  ({ adjust }) => new Set(adjust.map(({ lineId }) => lineId)).size === adjust.length,
5108
5521
  "a line id may appear at most once in `adjust`"
5109
5522
  );
5110
- var MonetizeTransactionItemSchema = z30.object({
5111
- id: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5112
- priceCents: z30.number(),
5113
- quantity: z30.number(),
5114
- title: z30.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX),
5115
- type: z30.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX)
5523
+ var MonetizeTransactionItemSchema = z36.object({
5524
+ id: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5525
+ priceCents: z36.number(),
5526
+ quantity: z36.number(),
5527
+ title: z36.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX),
5528
+ type: z36.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX)
5116
5529
  });
5117
- var MonetizeInputSchema = z30.object({
5530
+ var MonetizeInputSchema = z36.object({
5118
5531
  cart: CartInputSchema,
5119
5532
  /** Client-minted render-beacon correlation id; forwarded to the ads engine as `client_request_id`. */
5120
- clientRequestId: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5121
- country: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5122
- currency: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5533
+ clientRequestId: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5534
+ country: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5535
+ currency: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5123
5536
  /** Ads-targeting identity/geo/locale fields (React parity); folded into the engine query verbatim. */
5124
- customerEmail: z30.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
5125
- customerFirstName: z30.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
5126
- customerId: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5127
- customerLastName: z30.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
5128
- language: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5537
+ customerEmail: z36.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
5538
+ customerFirstName: z36.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
5539
+ customerId: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5540
+ customerLastName: z36.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
5541
+ language: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5129
5542
  /** Buyer-facing order name (e.g. `#1001`) for the server-composed "Order … Confirmed" chrome line. */
5130
- orderName: z30.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
5543
+ orderName: z36.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
5131
5544
  /** Ads surface label, forwarded verbatim; `customer_account` is measured/floored as its own surface (the account-area order list). */
5132
- placement: z30.enum(["customer_account", "order_status", "thank_you_page"]),
5545
+ placement: z36.enum(["customer_account", "order_status", "thank_you_page"]),
5133
5546
  /** Privacy Policy footer href — the Monetize widget's `privacy_policy_url` setting (React parity). */
5134
- privacyPolicyUrl: z30.string().max(REQUEST_BOUNDS.STRING_URL_MAX).optional(),
5547
+ privacyPolicyUrl: z36.string().max(REQUEST_BOUNDS.STRING_URL_MAX).optional(),
5135
5548
  /** 30-min rolling session id (React parity); used for the ads `session_id`, else the visitor id. */
5136
- sessionId: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5137
- shop: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5549
+ sessionId: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5550
+ shop: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5138
5551
  /** Editor/QA indicator; OR-ed into the ads-engine `testing` flag so it stays out of billing/reporting. */
5139
- testing: z30.boolean().optional(),
5140
- timezone: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5552
+ testing: z36.boolean().optional(),
5553
+ timezone: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5141
5554
  /** Decorated (numeric) order id → the ads `transaction_id`. */
5142
- transactionId: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5555
+ transactionId: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5143
5556
  /** Rich per-line ads items; capped at the engine's ads contract. Preferred over `cart.items`. */
5144
- transactionItems: z30.array(MonetizeTransactionItemSchema).max(REQUEST_BOUNDS.TRANSACTION_ITEMS_MAX).optional(),
5557
+ transactionItems: z36.array(MonetizeTransactionItemSchema).max(REQUEST_BOUNDS.TRANSACTION_ITEMS_MAX).optional(),
5145
5558
  /** Order total in presentment cents (React prefers total over subtotal); else `cart.subtotal`. */
5146
- transactionTotal: z30.number().optional(),
5147
- visitorId: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5148
- zipCode: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
5559
+ transactionTotal: z36.number().optional(),
5560
+ visitorId: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5561
+ zipCode: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
5149
5562
  });
5150
- var WidgetSettingsInputSchema = z30.object({
5563
+ var WidgetSettingsInputSchema = z36.object({
5151
5564
  /**
5152
5565
  * Same domain as `CabShopConfig.cacheKey`, for the same reason: this side WINS the orchestrator's
5153
5566
  * `input.cacheKey ?? config.shop.cacheKey` (and an explicit value skips the config read entirely), so
@@ -5155,9 +5568,9 @@ var WidgetSettingsInputSchema = z30.object({
5155
5568
  * and pin the edge copy permanently stale. `.catch(undefined)` because a bogus buster should degrade
5156
5569
  * the read to un-busted, never 400 a widget render.
5157
5570
  */
5158
- cacheKey: z30.number().int().positive().optional().catch(void 0),
5159
- id: z30.number(),
5160
- key: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5571
+ cacheKey: z36.number().int().positive().optional().catch(void 0),
5572
+ id: z36.number(),
5573
+ key: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5161
5574
  /**
5162
5575
  * Monetize context for inline hydration: when present AND the widget converts to a Monetize marker,
5163
5576
  * the server fetches/composes the offer cards inside this same request (no second `/cab/monetize`
@@ -5166,36 +5579,36 @@ var WidgetSettingsInputSchema = z30.object({
5166
5579
  * `privacyPolicyUrl` comes from the widget settings server-side (more authoritative than a relay).
5167
5580
  */
5168
5581
  monetize: MonetizeInputSchema.omit({ privacyPolicyUrl: true, shop: true }).optional(),
5169
- shop: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5582
+ shop: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5170
5583
  /** Stable per-buyer id; when present, enables sticky server-side A/B variant selection. */
5171
- visitorId: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
5584
+ visitorId: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
5172
5585
  });
5173
- var AnalyticsEventInputSchema = z30.object({
5174
- name: z30.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
5175
- properties: z30.record(z30.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), z30.unknown()).optional(),
5176
- sentAt: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
5586
+ var AnalyticsEventInputSchema = z36.object({
5587
+ name: z36.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
5588
+ properties: z36.record(z36.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), z36.unknown()).optional(),
5589
+ sentAt: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
5177
5590
  });
5178
- var AnalyticsSegmentsInputSchema = z30.object({
5179
- device: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
5180
- source: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
5181
- visitor: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0)
5591
+ var AnalyticsSegmentsInputSchema = z36.object({
5592
+ device: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
5593
+ source: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
5594
+ visitor: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0)
5182
5595
  });
5183
- var AnalyticsInputSchema = z30.object({
5596
+ var AnalyticsInputSchema = z36.object({
5184
5597
  /** Rebuy cart token (the `r_cart_token` cart attribute), when available — primary aggregation key. */
5185
- cartToken: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5598
+ cartToken: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5186
5599
  /** Shopify checkout token, when available — drives cart/checkout aggregation downstream. */
5187
- checkoutToken: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5188
- events: z30.array(AnalyticsEventInputSchema).max(REQUEST_BOUNDS.EVENTS_MAX),
5600
+ checkoutToken: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5601
+ events: z36.array(AnalyticsEventInputSchema).max(REQUEST_BOUNDS.EVENTS_MAX),
5189
5602
  /**
5190
5603
  * Request-scoped like the tokens: one visitor's segments apply to every event in the batch. The container
5191
5604
  * degrades too (`null` is a realistic wire artifact of `attributes ? {…} : null`), so the degrade rule is
5192
5605
  * total: nothing about `segments` can cost the envelope.
5193
5606
  */
5194
5607
  segments: AnalyticsSegmentsInputSchema.optional().catch(void 0),
5195
- shop: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5196
- visitorId: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5608
+ shop: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5609
+ visitorId: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5197
5610
  /** The widget id (smartBlockId) the events belong to. */
5198
- widgetId: z30.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
5611
+ widgetId: z36.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
5199
5612
  });
5200
5613
  export {
5201
5614
  AnalyticsEventInputSchema,