@rebuy/rebuy 3.28.0 → 3.29.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.
@@ -2022,7 +2022,14 @@ var CABReviewsSection = import_zod23.z.object({
2022
2022
  sectionId: import_zod23.z.uuid().default(() => (0, import_uuid10.v7)()),
2023
2023
  sectionType: import_zod23.z.literal(SectionType.reviews).default(SectionType.reviews),
2024
2024
  size: import_zod23.z.enum(reviewsSizes).default(ReviewsSize.default),
2025
- strokeColor: import_zod23.z.string().default("#fadb14"),
2025
+ /**
2026
+ * Star outline color, interpolated into a style by the renderer, so it is hex-constrained like
2027
+ * `CABButtonSection.color`. The legacy source (`PostPurchaseSettings.styles.starStrokeColor`) is a free
2028
+ * string: its converter must validate and fall back to this default rather than let one odd value drop
2029
+ * the whole reviews section.
2030
+ */
2031
+ strokeColor: import_zod23.z.string().regex(HEX_COLOR_REGEX).default("#fadb14"),
2032
+ /** Star outline width in px; `0` draws no outline. The legacy `styles.strokeWidth` is a STRING ('1') — its converter coerces. */
2026
2033
  strokeWidth: import_zod23.z.number().nonnegative().default(0)
2027
2034
  });
2028
2035
 
@@ -3771,7 +3778,7 @@ var convertOfferToV2 = ({ id, name, settings }) => {
3771
3778
  var parseShielded = (schema, raw, transform = (input) => input) => schema.parse(transform(convertNumericObjects(deepCamelCase(raw))));
3772
3779
 
3773
3780
  // src/transforms/postPurchase/convertMessagePreview.ts
3774
- var import_zod33 = require("zod");
3781
+ var import_zod36 = require("zod");
3775
3782
 
3776
3783
  // src/transforms/postPurchase/convertCalloutBlock.ts
3777
3784
  var import_zod31 = require("zod");
@@ -3994,6 +4001,150 @@ var convertCalloutBlock = (raw, report) => {
3994
4001
  return sections.length ? [CABLayoutSection.parse({ alignment: { horizontal }, frame: "callout", sections })] : [];
3995
4002
  };
3996
4003
 
4004
+ // src/transforms/postPurchase/convertImageFrame.ts
4005
+ var import_zod32 = require("zod");
4006
+
4007
+ // src/transforms/postPurchase/sizeImageSource.ts
4008
+ var sizeImageSource = (source, size) => {
4009
+ const extension = source.split(".").pop();
4010
+ for (const previous of ["small", "medium", "large", "original", "master"]) {
4011
+ source = source.replace(`_${previous}.${extension}`, `.${extension}`);
4012
+ }
4013
+ return source.replace(`.${extension}`, `${size === void 0 ? "" : `_${size}`}.${extension}`);
4014
+ };
4015
+
4016
+ // src/transforms/postPurchase/convertImageFrame.ts
4017
+ var Source = import_zod32.z.url().default("https://cdn.shopify.com/s/files/1/0605/0555/5177/files/placeholder.jpg?v=1657762972");
4018
+ var DEFAULT_IMAGE_SIZE = 20;
4019
+ var convertImageFrame = (raw) => {
4020
+ const parsed = ImageBlock.shape.settings.options[0].safeParse(raw);
4021
+ if (!parsed.success) return null;
4022
+ const settings = parsed.data;
4023
+ const source = sizeImageSource(Source.parse(settings.image || void 0));
4024
+ const withAlt = CABImageSection.safeParse({ altText: settings.alt, source });
4025
+ const image = withAlt.success ? withAlt.data : CABImageSection.parse({ source });
4026
+ const size = settings.imageSize > 0 ? settings.imageSize : DEFAULT_IMAGE_SIZE;
4027
+ return CABLayoutSection.parse({
4028
+ alignment: { horizontal: "center" },
4029
+ direction: "grid",
4030
+ grid: { columns: size <= 1 ? ["100%"] : [size] },
4031
+ sections: [image],
4032
+ width: size <= 1 ? size * 100 : 100
4033
+ });
4034
+ };
4035
+
4036
+ // src/transforms/postPurchase/convertImageBlock.ts
4037
+ var dropMalformedAlt = (raw) => {
4038
+ if (typeof raw !== "object" || raw === null) return raw;
4039
+ const { settings, ...rest } = raw;
4040
+ if (typeof settings !== "object" || settings === null || Array.isArray(settings)) return raw;
4041
+ const { alt, ...restSettings } = settings;
4042
+ if (typeof alt === "string" || alt === void 0) return raw;
4043
+ return { ...rest, settings: restSettings };
4044
+ };
4045
+ var convertImageBlock = (raw, report) => {
4046
+ const block = ImageBlock.safeParse(dropMalformedAlt(raw));
4047
+ const image = block.success ? convertImageFrame(block.data.settings) : null;
4048
+ if (!image) {
4049
+ report?.({ detail: "Unreadable post-purchase image", kind: "section" });
4050
+ return [];
4051
+ }
4052
+ return [
4053
+ CABLayoutSection.parse({
4054
+ alignment: { horizontal: "center" },
4055
+ frame: "offer-content",
4056
+ sections: [image],
4057
+ spacing: "none"
4058
+ })
4059
+ ];
4060
+ };
4061
+
4062
+ // src/transforms/postPurchase/convertImageContentBlock.ts
4063
+ var import_zod34 = require("zod");
4064
+
4065
+ // src/transforms/postPurchase/convertImageContentText.ts
4066
+ var fields2 = ["superTitle", "title", "description"];
4067
+ var convertImageContentText = (settings, report) => {
4068
+ const horizontal = { center: "center", leading: "start", trailing: "end" }[settings.horizontalAlignment];
4069
+ const sections = fields2.flatMap((field) => {
4070
+ const omit = () => {
4071
+ report?.({ detail: `Unreadable post-purchase image-content field: ${field}`, kind: "section" });
4072
+ return [];
4073
+ };
4074
+ const value = ImageContentBlock.shape.settings.shape[field].safeParse(settings[field]);
4075
+ if (!value.success) return omit();
4076
+ const text2 = value.data;
4077
+ if (text2 === null || text2 === "") return [];
4078
+ const content = typeof text2 === "string" ? {
4079
+ content: [
4080
+ {
4081
+ attrs: { textAlign: horizontal },
4082
+ content: [styledTextRun(text2, field !== "description", settings[`${field}Size`])]
4083
+ }
4084
+ ]
4085
+ } : text2;
4086
+ const section = CABTextSection.safeParse({ content: { en: content } });
4087
+ return section.success ? [section.data] : omit();
4088
+ });
4089
+ return CABLayoutSection.parse({ alignment: { horizontal }, sections });
4090
+ };
4091
+
4092
+ // src/transforms/postPurchase/imageContentSettings.ts
4093
+ var import_zod33 = require("zod");
4094
+ var ImageContentSettings = ImageContentBlock.shape.settings.pick({
4095
+ descriptionSize: true,
4096
+ horizontalAlignment: true,
4097
+ superTitleSize: true,
4098
+ swapContent: true,
4099
+ titleSize: true
4100
+ }).extend({
4101
+ alt: import_zod33.z.unknown().optional(),
4102
+ description: import_zod33.z.unknown().optional(),
4103
+ image: import_zod33.z.unknown().optional(),
4104
+ imagePlacement: ImageContentBlock.shape.settings.shape.imagePlacement.unwrap().nullable(),
4105
+ imageSize: ImageContentBlock.shape.settings.shape.imageSize.pipe(import_zod33.z.number().positive()),
4106
+ superTitle: import_zod33.z.unknown().optional(),
4107
+ title: import_zod33.z.unknown().optional()
4108
+ });
4109
+
4110
+ // src/transforms/postPurchase/convertImageContentBlock.ts
4111
+ var Shell2 = import_zod34.z.object({ settings: ImageContentSettings, type: import_zod34.z.literal("image_content") });
4112
+ var PROPORTIONAL_BREAK_AT = 500;
4113
+ var convertImageContentBlock = (raw, report) => {
4114
+ const shell = Shell2.safeParse(raw);
4115
+ if (!shell.success) {
4116
+ report?.({ detail: "Unreadable post-purchase image-content block", kind: "section" });
4117
+ return [];
4118
+ }
4119
+ const settings = shell.data.settings;
4120
+ const alt = typeof settings.alt === "string" ? settings.alt : void 0;
4121
+ if (settings.alt !== void 0 && alt === void 0) {
4122
+ report?.({ detail: "Unreadable post-purchase image-content alt text", kind: "section" });
4123
+ }
4124
+ const image = convertImageFrame({ alt, image: settings.image, imageSize: settings.imageSize });
4125
+ if (!image) report?.({ detail: "Unreadable post-purchase image-content image", kind: "section" });
4126
+ const text2 = convertImageContentText(settings, report);
4127
+ const textFrame = CABLayoutSection.parse({ direction: "grid", grid: { columns: ["100%"] }, sections: [text2] });
4128
+ const placement = settings.imagePlacement ?? (settings.swapContent ? "right" : "left");
4129
+ const imageFirst = placement === "left" || placement === "top";
4130
+ const sections = imageFirst ? [image, textFrame] : [textFrame, image];
4131
+ const ordered = sections.filter((section) => section !== null);
4132
+ const inner = placement === "left" || placement === "right" ? CABLayoutSection.parse({
4133
+ sections: ordered,
4134
+ spacing: "loose",
4135
+ wrapping: {
4136
+ breakAt: settings.imageSize <= 1 ? PROPORTIONAL_BREAK_AT : settings.imageSize,
4137
+ maxPerLine: 2
4138
+ }
4139
+ }) : CABLayoutSection.parse({
4140
+ direction: "grid",
4141
+ grid: { columns: ["100%"] },
4142
+ sections: [CABLayoutSection.parse({ sections: ordered })],
4143
+ width: 95
4144
+ });
4145
+ return [CABLayoutSection.parse({ frame: "offer-content", sections: [inner], spacing: "none" })];
4146
+ };
4147
+
3997
4148
  // src/transforms/postPurchase/convertPayButtonBlock.ts
3998
4149
  var convertPayButtonBlock = (raw, report) => {
3999
4150
  const omit = () => {
@@ -4022,6 +4173,60 @@ var convertPayButtonBlock = (raw, report) => {
4022
4173
  ];
4023
4174
  };
4024
4175
 
4176
+ // src/transforms/postPurchase/convertProductInformation.ts
4177
+ var convertProductInformation = (raw, report) => {
4178
+ const block = ProductInformationBlock.safeParse(raw);
4179
+ if (!block.success) {
4180
+ report?.({ detail: "Unreadable post-purchase product information", kind: "section" });
4181
+ return [];
4182
+ }
4183
+ return [
4184
+ CABOffersSection.parse({
4185
+ direction: "grid",
4186
+ sections: [
4187
+ CABLayoutSection.parse({
4188
+ alignment: { horizontal: "center" },
4189
+ sections: [
4190
+ CABLayoutSection.parse({
4191
+ alignment: { horizontal: "center" },
4192
+ direction: "grid",
4193
+ grid: { columns: [250] },
4194
+ sections: [
4195
+ CABImageSection.parse({ altText: "{{productTitle}}", source: "{{productImage}}" })
4196
+ ],
4197
+ width: 90
4198
+ })
4199
+ ]
4200
+ }),
4201
+ CABLayoutSection.parse({
4202
+ sections: [
4203
+ CABTextSection.parse({
4204
+ content: {
4205
+ en: {
4206
+ content: [
4207
+ {
4208
+ content: [
4209
+ {
4210
+ marks: [{ attrs: { fontSize: "heading" }, type: "textStyle" }],
4211
+ text: "{{productTitle}}"
4212
+ }
4213
+ ]
4214
+ }
4215
+ ]
4216
+ }
4217
+ }
4218
+ }),
4219
+ CABReviewsSection.parse({}),
4220
+ CABTextSection.parse({ content: { en: "{{productDescription}}" } })
4221
+ ]
4222
+ })
4223
+ ],
4224
+ spacing: "extraLoose",
4225
+ wrapping: { breakAt: 500, maxPerLine: block.data.hideProductImage ? 1 : 2 }
4226
+ })
4227
+ ];
4228
+ };
4229
+
4025
4230
  // src/transforms/postPurchase/convertSeparatorBlock.ts
4026
4231
  var convertSeparatorBlock = (raw, report) => {
4027
4232
  if (!SeparatorBlock.safeParse(raw).success) {
@@ -4032,34 +4237,36 @@ var convertSeparatorBlock = (raw, report) => {
4032
4237
  };
4033
4238
 
4034
4239
  // src/transforms/postPurchase/convertTextBlock.ts
4035
- var import_zod32 = require("zod");
4036
- var fields2 = ["superTitle", "title", "description"];
4240
+ var import_zod35 = require("zod");
4241
+ var fields3 = ["superTitle", "title", "description"];
4037
4242
  var styles = {
4038
4243
  description: [{ attrs: { color: "base", fontSize: "small" }, type: "textStyle" }],
4039
4244
  superTitle: [{ attrs: { color: "subdued", fontSize: "small" }, type: "textStyle" }],
4040
4245
  title: [{ type: "bold" }, { attrs: { color: "base", fontSize: "large" }, type: "textStyle" }]
4041
4246
  };
4042
4247
  var settingsSchema = TextBlock.shape.settings;
4043
- var Shell2 = import_zod32.z.object({
4248
+ var Shell3 = import_zod35.z.object({
4044
4249
  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()
4250
+ description: import_zod35.z.unknown().optional(),
4251
+ superTitle: import_zod35.z.unknown().optional(),
4252
+ title: import_zod35.z.unknown().optional()
4048
4253
  }),
4049
- type: import_zod32.z.literal("text")
4254
+ type: import_zod35.z.literal("text")
4050
4255
  });
4051
4256
  var convertTextBlock = (raw, report) => {
4052
- const shell = Shell2.safeParse(raw);
4257
+ const shell = Shell3.safeParse(raw);
4053
4258
  if (!shell.success) {
4054
4259
  report?.({ detail: "Unreadable post-purchase text block", kind: "section" });
4055
4260
  return [];
4056
4261
  }
4057
- const values = fields2.map((field) => ({
4262
+ const values = fields3.map((field) => ({
4058
4263
  field,
4059
4264
  result: settingsSchema.shape[field].safeParse(shell.data.settings[field])
4060
4265
  }));
4061
4266
  const horizontal = { center: "center", leading: "start", trailing: "end" }[shell.data.settings.horizontalAlignment];
4062
- const styled2 = values.every(({ result }) => result.success && typeof result.data === "string");
4267
+ const styled2 = values.every(
4268
+ ({ result }) => result.success && (result.data === null || typeof result.data === "string")
4269
+ );
4063
4270
  const omit = (field) => {
4064
4271
  report?.({ detail: `Unreadable post-purchase text field: ${field}`, kind: "section" });
4065
4272
  return [];
@@ -4072,20 +4279,18 @@ var convertTextBlock = (raw, report) => {
4072
4279
  const section = CABTextSection.safeParse({ content: { en: content } });
4073
4280
  return section.success ? [section.data] : omit(field);
4074
4281
  });
4075
- return [
4076
- CABLayoutSection.parse({
4077
- alignment: {
4078
- horizontal
4079
- },
4080
- sections
4081
- })
4082
- ];
4282
+ return sections.length ? [CABLayoutSection.parse({ alignment: { horizontal }, sections })] : [];
4083
4283
  };
4084
4284
 
4085
4285
  // src/transforms/postPurchase/convertTimerBlock.ts
4086
4286
  var Presentation = TimerBlock.pick({ styles: true }).extend({
4087
4287
  settings: TimerBlock.shape.settings.pick({ title: true })
4088
4288
  });
4289
+ var withCountdown = (doc, run, textAlign) => {
4290
+ const paragraphs = doc.content.length ? doc.content : [TiptapParagraph.parse({ attrs: { textAlign } })];
4291
+ const last = paragraphs[paragraphs.length - 1];
4292
+ return { ...doc, content: [...paragraphs.slice(0, -1), { ...last, content: [...last.content, run] }] };
4293
+ };
4089
4294
  var convertTimerBlock = (raw, report) => {
4090
4295
  const omit = () => {
4091
4296
  report?.({ detail: "Unreadable post-purchase timer display", kind: "section" });
@@ -4096,17 +4301,15 @@ var convertTimerBlock = (raw, report) => {
4096
4301
  const { title } = parsed.data.settings;
4097
4302
  const styles2 = parsed.data.styles;
4098
4303
  const horizontal = { center: "center", leading: "start", trailing: "end" }[styles2.textAlignment];
4304
+ const countdown = styledTextRun(" {{timeRemaining}}", styles2.timerEmphasized, styles2.timerSize);
4099
4305
  const content = typeof title === "string" ? {
4100
4306
  content: [
4101
4307
  {
4102
4308
  attrs: { textAlign: horizontal },
4103
- content: [
4104
- styledTextRun(title, styles2.titleEmphasized, styles2.titleSize),
4105
- styledTextRun(" {{timeRemaining}}", styles2.timerEmphasized, styles2.timerSize)
4106
- ]
4309
+ content: [styledTextRun(title, styles2.titleEmphasized, styles2.titleSize), countdown]
4107
4310
  }
4108
4311
  ]
4109
- } : title;
4312
+ } : withCountdown(title, countdown, horizontal);
4110
4313
  const text2 = CABTextSection.safeParse({ content: { en: content } });
4111
4314
  if (!text2.success) return omit();
4112
4315
  return [
@@ -4120,14 +4323,17 @@ var convertTimerBlock = (raw, report) => {
4120
4323
  };
4121
4324
 
4122
4325
  // 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")
4326
+ var MessageWidget = import_zod36.z.object({
4327
+ blocks: import_zod36.z.array(import_zod36.z.unknown()).min(1),
4328
+ type: import_zod36.z.literal(WidgetType.shopify_post_purchase_extension)
4126
4329
  });
4127
- var BlockType2 = import_zod33.z.object({ type: import_zod33.z.string() });
4330
+ var BlockType2 = import_zod36.z.object({ type: import_zod36.z.string() });
4128
4331
  var converters = {
4129
4332
  callout_banner: convertCalloutBlock,
4333
+ image: convertImageBlock,
4334
+ image_content: convertImageContentBlock,
4130
4335
  pay_button: convertPayButtonBlock,
4336
+ product_information: convertProductInformation,
4131
4337
  separator: convertSeparatorBlock,
4132
4338
  text: convertTextBlock,
4133
4339
  timer: convertTimerBlock
@@ -4141,7 +4347,7 @@ var convertMessagePreview = (id, settings, report) => {
4141
4347
  sections: parsed.data.blocks.flatMap((block) => {
4142
4348
  const type = BlockType2.safeParse(block);
4143
4349
  const kind = type.success ? type.data.type : void 0;
4144
- const convert2 = kind ? converters[kind] : void 0;
4350
+ const convert2 = kind && Object.hasOwn(converters, kind) ? converters[kind] : void 0;
4145
4351
  if (convert2) return convert2(block, report);
4146
4352
  report?.({
4147
4353
  detail: kind ? `Unsupported post-purchase block type: ${kind}` : "Unreadable post-purchase block: missing type",
@@ -4669,7 +4875,7 @@ var fetchDataSourceResults = async (input, ctx) => {
4669
4875
  };
4670
4876
 
4671
4877
  // src/server/adsEngine.ts
4672
- var import_zod34 = require("zod");
4878
+ var import_zod37 = require("zod");
4673
4879
  var SUPPLY_KEY = { production: "AQF5RKLR", staging: "Z56LQ7PS" };
4674
4880
  var OFFER_LIMIT = 4;
4675
4881
  var SUPPORTED_COUNTRIES = /* @__PURE__ */ new Set(["US", "CA"]);
@@ -4682,28 +4888,28 @@ var transactionItems = (input) => (input.transactionItems?.map(({ id, priceCents
4682
4888
  title,
4683
4889
  type
4684
4890
  })) ?? input.cart.items.map(({ productId, quantity }) => ({ id: productId, quantity }))).slice(0, MAX_TRANSACTION_ITEMS);
4685
- var AdsEngineOffer = import_zod34.z.object({
4891
+ var AdsEngineOffer = import_zod37.z.object({
4686
4892
  /** Pill-style value prop ("Get $45 Cashback"). Carried through the parse; the card does not render it yet (REB-24429 — pill design pending). */
4687
- callout: import_zod34.z.string().catch(""),
4688
- click_url: import_zod34.z.string(),
4689
- cta: import_zod34.z.string(),
4893
+ callout: import_zod37.z.string().catch(""),
4894
+ click_url: import_zod37.z.string(),
4895
+ cta: import_zod37.z.string(),
4690
4896
  /** `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'). */
4691
- decline_cta: import_zod34.z.string().catch(""),
4692
- decline_url: import_zod34.z.string(),
4693
- description: import_zod34.z.string(),
4897
+ decline_cta: import_zod37.z.string().catch(""),
4898
+ decline_url: import_zod37.z.string(),
4899
+ description: import_zod37.z.string(),
4694
4900
  /** Short legal disclosure (FDIC / auto-renewal / FTC-affiliation lines). Rendered subdued under the CTAs. */
4695
- disclaimer: import_zod34.z.string().catch(""),
4901
+ disclaimer: import_zod37.z.string().catch(""),
4696
4902
  /** Long legal text behind the disclosure toggle in the composed card (REB-24429). */
4697
- extended_disclaimer: import_zod34.z.string().catch(""),
4698
- headline: import_zod34.z.string(),
4699
- id: import_zod34.z.string(),
4903
+ extended_disclaimer: import_zod37.z.string().catch(""),
4904
+ headline: import_zod37.z.string(),
4905
+ id: import_zod37.z.string(),
4700
4906
  /** Advertiser-supplied image alt; the composed card falls back to the stripped headline when empty. */
4701
- image_alt: import_zod34.z.string().catch(""),
4702
- image_url: import_zod34.z.string().optional(),
4703
- view_url: import_zod34.z.string()
4907
+ image_alt: import_zod37.z.string().catch(""),
4908
+ image_url: import_zod37.z.string().optional(),
4909
+ view_url: import_zod37.z.string()
4704
4910
  });
4705
- var AdsEngineResponse = import_zod34.z.object({
4706
- offers: import_zod34.z.array(import_zod34.z.unknown()).default([]).transform(
4911
+ var AdsEngineResponse = import_zod37.z.object({
4912
+ offers: import_zod37.z.array(import_zod37.z.unknown()).default([]).transform(
4707
4913
  (offers) => offers.flatMap((offer) => {
4708
4914
  const result = AdsEngineOffer.safeParse(offer);
4709
4915
  return result.success ? [result.data] : [];
@@ -4715,8 +4921,8 @@ var AdsEngineResponse = import_zod34.z.object({
4715
4921
  * offers-testing fixture on a test store forces it, REB-24467). Both optional: an older engine or a
4716
4922
  * non-JSON body must not fail the parse and drop the offers.
4717
4923
  */
4718
- request_id: import_zod34.z.string().optional().catch(void 0),
4719
- testing: import_zod34.z.boolean().optional().catch(void 0)
4924
+ request_id: import_zod37.z.string().optional().catch(void 0),
4925
+ testing: import_zod37.z.boolean().optional().catch(void 0)
4720
4926
  });
4721
4927
  var adsHost = (host) => `offers.${host}`;
4722
4928
  var isTestingRequest = (input, isProduction) => !isProduction || !!input.testing || input.customerEmail?.toLowerCase() === TEST_CUSTOMER_EMAIL;
@@ -5146,13 +5352,13 @@ var convertWidgetSettings = async (input, ctx) => {
5146
5352
  };
5147
5353
 
5148
5354
  // src/server/giftWidgets.ts
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()),
5355
+ var import_zod38 = require("zod");
5356
+ var SettingsNumber = import_zod38.z.union([
5357
+ import_zod38.z.number(),
5358
+ import_zod38.z.string().trim().regex(/^-?\d+(\.\d+)?$/)
5359
+ ]).pipe(import_zod38.z.coerce.number());
5360
+ var SgwpMilestoneSchema = import_zod38.z.object({
5361
+ selectable_product_quantity: SettingsNumber.pipe(import_zod38.z.number().int().nonnegative()),
5156
5362
  unlock_price: SettingsNumber
5157
5363
  });
5158
5364
  var fetchGiftWidgetSettings = async (widgetId, shop, ctx) => unwrapData(await ctx.fetchUpstream("/api/v1/widgets/settings", { id: String(widgetId), shop }, { host: ctx.host }));
@@ -5163,7 +5369,7 @@ var readDataSourcePath = (settings) => {
5163
5369
  var readMilestones = (settings, report) => {
5164
5370
  const raw = settings && typeof settings === "object" ? settings.milestones : void 0;
5165
5371
  if (raw == null) return [];
5166
- const parsed = import_zod35.z.array(SgwpMilestoneSchema).safeParse(raw);
5372
+ const parsed = import_zod38.z.array(SgwpMilestoneSchema).safeParse(raw);
5167
5373
  if (parsed.success) return parsed.data;
5168
5374
  report?.({
5169
5375
  detail: [
@@ -5412,7 +5618,7 @@ var postAnalyticsEvents = async (input, ctx) => {
5412
5618
  };
5413
5619
 
5414
5620
  // src/server/requestSchemas.ts
5415
- var import_zod36 = require("zod");
5621
+ var import_zod39 = require("zod");
5416
5622
  var REQUEST_BOUNDS = {
5417
5623
  /** Cart-level attributes per cart. */
5418
5624
  CART_ATTRIBUTES_MAX: 100,
@@ -5443,42 +5649,42 @@ var REQUEST_BOUNDS = {
5443
5649
  /** Rich ads transaction lines — the engine's ads contract. */
5444
5650
  TRANSACTION_ITEMS_MAX: 50
5445
5651
  };
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()
5652
+ var KeyValue = import_zod39.z.object({
5653
+ key: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
5654
+ value: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_VALUE_MAX).optional()
5449
5655
  });
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)
5656
+ var CartLineInputSchema = import_zod39.z.object({
5657
+ productId: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5658
+ properties: import_zod39.z.array(KeyValue).max(REQUEST_BOUNDS.LINE_PROPERTIES_MAX).optional(),
5659
+ quantity: import_zod39.z.number(),
5660
+ subscriptionId: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5661
+ variantId: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX)
5456
5662
  });
5457
- var CartInputSchema = import_zod36.z.object({
5458
- attributes: import_zod36.z.array(KeyValue).max(REQUEST_BOUNDS.CART_ATTRIBUTES_MAX).optional(),
5663
+ var CartInputSchema = import_zod39.z.object({
5664
+ attributes: import_zod39.z.array(KeyValue).max(REQUEST_BOUNDS.CART_ATTRIBUTES_MAX).optional(),
5459
5665
  /**
5460
5666
  * Presentment-per-shop-currency FX rate (buyer price ÷ shop price, e.g. `1.35` for a USD shop
5461
5667
  * selling in CAD). Money rule thresholds are authored in SHOP currency, so the engine subtotal is
5462
5668
  * divided by this before evaluation. Omit (or send 1) when the cart is already in the shop's currency.
5463
5669
  */
5464
- currencyRate: import_zod36.z.number().optional(),
5670
+ currencyRate: import_zod39.z.number().optional(),
5465
5671
  /** Applied discount codes; the engine evaluates `discount_code` rules against them (sent as `[{code}]`). */
5466
- discountCodes: import_zod36.z.array(import_zod36.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX)).max(REQUEST_BOUNDS.DISCOUNT_CODES_MAX).optional(),
5672
+ discountCodes: import_zod39.z.array(import_zod39.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX)).max(REQUEST_BOUNDS.DISCOUNT_CODES_MAX).optional(),
5467
5673
  /** Presentment cents of cart-level discount allocations, subtracted from `subtotal` for the engine. */
5468
- discountTotal: import_zod36.z.number().optional(),
5469
- items: import_zod36.z.array(CartLineInputSchema).max(REQUEST_BOUNDS.CART_ITEMS_MAX),
5674
+ discountTotal: import_zod39.z.number().optional(),
5675
+ items: import_zod39.z.array(CartLineInputSchema).max(REQUEST_BOUNDS.CART_ITEMS_MAX),
5470
5676
  /** Presentment subtotal in cents. */
5471
- subtotal: import_zod36.z.number()
5677
+ subtotal: import_zod39.z.number()
5472
5678
  });
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({
5679
+ var UserConfigInputSchema = import_zod39.z.object({ shop: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX) });
5680
+ var DataSourceInputSchema = import_zod39.z.object({
5475
5681
  cart: CartInputSchema,
5476
5682
  /**
5477
5683
  * Numeric Shopify company-location id when the buyer is a B2B session (`buyerIdentity.purchasingCompany`).
5478
5684
  * Present ⇒ the orchestrator filters results by the location's catalog via admin-api (REB-23713); the
5479
5685
  * client's country-context market check is bypassed for B2B (it false-negatives B2B-catalog products).
5480
5686
  */
5481
- companyLocationId: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5687
+ companyLocationId: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5482
5688
  /**
5483
5689
  * Buyer's market country (ISO 3166-1 alpha-2) — forwarded to the engine as the `country_code` PARAM
5484
5690
  * when the shop's markets toggle is on (REB-21688; the sink was the `X-Country-Code` header under
@@ -5487,16 +5693,16 @@ var DataSourceInputSchema = import_zod36.z.object({
5487
5693
  * uppercase (the wire value is forwarded verbatim as the param) so a case-sensitive engine lookup
5488
5694
  * can't silently miss a lowercase code — `adsEngine.ts` uppercases for the same reason.
5489
5695
  */
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),
5696
+ country: import_zod39.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(),
5697
+ customerId: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5698
+ dataSourcePath: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
5493
5699
  /**
5494
5700
  * Engine `filter_inputs` override: `'no'` keeps in-cart (input) products in the results/rule
5495
5701
  * outputs — gift validation sends it so a gift's own product can appear in its answer. Omitted = the
5496
5702
  * engine's default filtering.
5497
5703
  */
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, {
5704
+ filterInputs: import_zod39.z.enum(["no", "yes"]).optional(),
5705
+ integrations: import_zod39.z.record(import_zod39.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), import_zod39.z.boolean()).refine((record) => Object.keys(record).length <= REQUEST_BOUNDS.INTEGRATION_KEYS_MAX, {
5500
5706
  message: `Too many integration keys (max ${REQUEST_BOUNDS.INTEGRATION_KEYS_MAX})`
5501
5707
  }).optional(),
5502
5708
  /**
@@ -5509,31 +5715,31 @@ var DataSourceInputSchema = import_zod36.z.object({
5509
5715
  * request header) fails the regex. Callers should send the buyer's resolved locale (e.g. Shopify
5510
5716
  * checkout's `localization.language.isoCode`), not the request header verbatim.
5511
5717
  */
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()
5718
+ language: import_zod39.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(),
5719
+ limit: import_zod39.z.number().max(REQUEST_BOUNDS.LIMIT_MAX),
5720
+ productType: import_zod39.z.enum(["both", "one-time", "subscription"]).optional(),
5721
+ shop: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5722
+ visitorId: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
5517
5723
  });
5518
- var GiftInputSchema = import_zod36.z.object({
5519
- cost: import_zod36.z.number(),
5520
- discounted: import_zod36.z.boolean(),
5724
+ var GiftInputSchema = import_zod39.z.object({
5725
+ cost: import_zod39.z.number(),
5726
+ discounted: import_zod39.z.boolean(),
5521
5727
  /**
5522
5728
  * Which gift attribution the line carries (REB-24363). Defaults to `gwp` because a client that predates
5523
5729
  * the field only ever sent GWP lines — without the default an older extension's request would 422.
5524
5730
  */
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(),
5731
+ kind: import_zod39.z.enum(GIFT_KINDS).default("gwp"),
5732
+ lineId: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5733
+ productId: import_zod39.z.number(),
5528
5734
  /**
5529
5735
  * The line's unit count (REB-24363) — the selectable-GWP verdict trims surplus units against milestone
5530
5736
  * capacity. The second deliberate default: a client predating the field sent only GWP lines, whose
5531
5737
  * verdict is whole-line, so a missing quantity reads as one unit rather than 422ing the older request.
5532
5738
  */
5533
- quantity: import_zod36.z.number().int().min(1).default(1),
5534
- widgetId: import_zod36.z.number()
5739
+ quantity: import_zod39.z.number().int().min(1).default(1),
5740
+ widgetId: import_zod39.z.number()
5535
5741
  });
5536
- var GiftValidationInputSchema = import_zod36.z.object({
5742
+ var GiftValidationInputSchema = import_zod39.z.object({
5537
5743
  cart: CartInputSchema,
5538
5744
  /**
5539
5745
  * Buyer's market country — threaded into the per-widget data-source evaluations, which forward it to
@@ -5542,25 +5748,25 @@ var GiftValidationInputSchema = import_zod36.z.object({
5542
5748
  * turns markets off); regex-bound and uppercase-normalized for the same reasons as
5543
5749
  * `DataSourceInputSchema`'s `country`.
5544
5750
  */
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),
5751
+ country: import_zod39.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(),
5752
+ customerId: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5753
+ gifts: import_zod39.z.array(GiftInputSchema).max(REQUEST_BOUNDS.GIFTS_MAX),
5548
5754
  /**
5549
5755
  * Buyer's checkout language — threaded into the per-widget data-source evaluations, which normalize
5550
5756
  * and forward it as the engine `locale` param under the same markets-toggle gate (REB-21688). MUST be
5551
5757
  * a single BCP-47 tag, for the same reason as `DataSourceInputSchema`'s `language` above.
5552
5758
  */
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()
5759
+ language: import_zod39.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(),
5760
+ shop: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5761
+ visitorId: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
5556
5762
  });
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()
5763
+ var GiftAdjustmentSchema = import_zod39.z.object({
5764
+ lineId: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5765
+ quantity: import_zod39.z.number().int().nonnegative()
5560
5766
  });
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(
5767
+ var GiftValidationResponseSchema = import_zod39.z.object({
5768
+ adjust: import_zod39.z.array(GiftAdjustmentSchema).max(REQUEST_BOUNDS.GIFTS_MAX).default([]),
5769
+ remove: import_zod39.z.array(import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX)).max(REQUEST_BOUNDS.GIFTS_MAX).refine(
5564
5770
  (remove) => new Set(remove).size === remove.length,
5565
5771
  "a line id may appear at most once in `remove`"
5566
5772
  )
@@ -5571,47 +5777,47 @@ var GiftValidationResponseSchema = import_zod36.z.object({
5571
5777
  ({ adjust }) => new Set(adjust.map(({ lineId }) => lineId)).size === adjust.length,
5572
5778
  "a line id may appear at most once in `adjust`"
5573
5779
  );
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)
5780
+ var MonetizeTransactionItemSchema = import_zod39.z.object({
5781
+ id: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5782
+ priceCents: import_zod39.z.number(),
5783
+ quantity: import_zod39.z.number(),
5784
+ title: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX),
5785
+ type: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX)
5580
5786
  });
5581
- var MonetizeInputSchema = import_zod36.z.object({
5787
+ var MonetizeInputSchema = import_zod39.z.object({
5582
5788
  cart: CartInputSchema,
5583
5789
  /** Client-minted render-beacon correlation id; forwarded to the ads engine as `client_request_id`. */
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(),
5790
+ clientRequestId: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5791
+ country: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5792
+ currency: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5587
5793
  /** Ads-targeting identity/geo/locale fields (React parity); folded into the engine query verbatim. */
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(),
5794
+ customerEmail: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
5795
+ customerFirstName: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
5796
+ customerId: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5797
+ customerLastName: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
5798
+ language: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5593
5799
  /** Buyer-facing order name (e.g. `#1001`) for the server-composed "Order … Confirmed" chrome line. */
5594
- orderName: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
5800
+ orderName: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
5595
5801
  /** Ads surface label, forwarded verbatim; `customer_account` is measured/floored as its own surface (the account-area order list). */
5596
- placement: import_zod36.z.enum(["customer_account", "order_status", "thank_you_page"]),
5802
+ placement: import_zod39.z.enum(["customer_account", "order_status", "thank_you_page"]),
5597
5803
  /** Privacy Policy footer href — the Monetize widget's `privacy_policy_url` setting (React parity). */
5598
- privacyPolicyUrl: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_URL_MAX).optional(),
5804
+ privacyPolicyUrl: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_URL_MAX).optional(),
5599
5805
  /** 30-min rolling session id (React parity); used for the ads `session_id`, else the visitor id. */
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),
5806
+ sessionId: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5807
+ shop: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5602
5808
  /** Editor/QA indicator; OR-ed into the ads-engine `testing` flag so it stays out of billing/reporting. */
5603
- testing: import_zod36.z.boolean().optional(),
5604
- timezone: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5809
+ testing: import_zod39.z.boolean().optional(),
5810
+ timezone: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5605
5811
  /** Decorated (numeric) order id → the ads `transaction_id`. */
5606
- transactionId: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5812
+ transactionId: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5607
5813
  /** Rich per-line ads items; capped at the engine's ads contract. Preferred over `cart.items`. */
5608
- transactionItems: import_zod36.z.array(MonetizeTransactionItemSchema).max(REQUEST_BOUNDS.TRANSACTION_ITEMS_MAX).optional(),
5814
+ transactionItems: import_zod39.z.array(MonetizeTransactionItemSchema).max(REQUEST_BOUNDS.TRANSACTION_ITEMS_MAX).optional(),
5609
5815
  /** Order total in presentment cents (React prefers total over subtotal); else `cart.subtotal`. */
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()
5816
+ transactionTotal: import_zod39.z.number().optional(),
5817
+ visitorId: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5818
+ zipCode: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
5613
5819
  });
5614
- var WidgetSettingsInputSchema = import_zod36.z.object({
5820
+ var WidgetSettingsInputSchema = import_zod39.z.object({
5615
5821
  /**
5616
5822
  * Same domain as `CabShopConfig.cacheKey`, for the same reason: this side WINS the orchestrator's
5617
5823
  * `input.cacheKey ?? config.shop.cacheKey` (and an explicit value skips the config read entirely), so
@@ -5619,9 +5825,9 @@ var WidgetSettingsInputSchema = import_zod36.z.object({
5619
5825
  * and pin the edge copy permanently stale. `.catch(undefined)` because a bogus buster should degrade
5620
5826
  * the read to un-busted, never 400 a widget render.
5621
5827
  */
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(),
5828
+ cacheKey: import_zod39.z.number().int().positive().optional().catch(void 0),
5829
+ id: import_zod39.z.number(),
5830
+ key: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5625
5831
  /**
5626
5832
  * Monetize context for inline hydration: when present AND the widget converts to a Monetize marker,
5627
5833
  * the server fetches/composes the offer cards inside this same request (no second `/cab/monetize`
@@ -5630,34 +5836,34 @@ var WidgetSettingsInputSchema = import_zod36.z.object({
5630
5836
  * `privacyPolicyUrl` comes from the widget settings server-side (more authoritative than a relay).
5631
5837
  */
5632
5838
  monetize: MonetizeInputSchema.omit({ privacyPolicyUrl: true, shop: true }).optional(),
5633
- shop: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5839
+ shop: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5634
5840
  /** Stable per-buyer id; when present, enables sticky server-side A/B variant selection. */
5635
- visitorId: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
5841
+ visitorId: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
5636
5842
  });
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()
5843
+ var AnalyticsEventInputSchema = import_zod39.z.object({
5844
+ name: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
5845
+ properties: import_zod39.z.record(import_zod39.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), import_zod39.z.unknown()).optional(),
5846
+ sentAt: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
5641
5847
  });
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)
5848
+ var AnalyticsSegmentsInputSchema = import_zod39.z.object({
5849
+ device: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
5850
+ source: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
5851
+ visitor: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0)
5646
5852
  });
5647
- var AnalyticsInputSchema = import_zod36.z.object({
5853
+ var AnalyticsInputSchema = import_zod39.z.object({
5648
5854
  /** Rebuy cart token (the `r_cart_token` cart attribute), when available — primary aggregation key. */
5649
- cartToken: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5855
+ cartToken: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5650
5856
  /** Shopify checkout token, when available — drives cart/checkout aggregation downstream. */
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),
5857
+ checkoutToken: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
5858
+ events: import_zod39.z.array(AnalyticsEventInputSchema).max(REQUEST_BOUNDS.EVENTS_MAX),
5653
5859
  /**
5654
5860
  * Request-scoped like the tokens: one visitor's segments apply to every event in the batch. The container
5655
5861
  * degrades too (`null` is a realistic wire artifact of `attributes ? {…} : null`), so the degrade rule is
5656
5862
  * total: nothing about `segments` can cost the envelope.
5657
5863
  */
5658
5864
  segments: AnalyticsSegmentsInputSchema.optional().catch(void 0),
5659
- shop: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5660
- visitorId: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5865
+ shop: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5866
+ visitorId: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
5661
5867
  /** The widget id (smartBlockId) the events belong to. */
5662
- widgetId: import_zod36.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
5868
+ widgetId: import_zod39.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
5663
5869
  });