@rebuy/rebuy 3.35.0 → 3.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/dist/index.cjs +689 -571
  2. package/dist/index.mjs +689 -571
  3. package/dist/schema/index.d.ts +3 -0
  4. package/dist/schema/postPurchaseGroup.d.ts +15 -0
  5. package/dist/schema/postPurchaseProduct.d.ts +74 -24
  6. package/dist/schema/postPurchaseProductCalculation.d.ts +87 -0
  7. package/dist/schema/postPurchaseProductCollectionView.d.ts +724 -3
  8. package/dist/schema/postPurchaseProductDisplay.d.ts +41 -12
  9. package/dist/schema/postPurchaseProductView.d.ts +708 -0
  10. package/dist/schema/postPurchaseQuantity.d.ts +16 -3
  11. package/dist/schema/postPurchaseSubscriptionProduct.d.ts +74 -17
  12. package/dist/server/__fixtures__/postPurchaseGroup.d.ts +3 -0
  13. package/dist/server/index.cjs +818 -310
  14. package/dist/server/index.d.ts +13 -2
  15. package/dist/server/index.mjs +818 -310
  16. package/dist/server/postPurchaseProductDisplay.d.ts +38 -6
  17. package/dist/server/preparePostPurchaseAdmissionView.d.ts +418 -0
  18. package/dist/server/preparePostPurchaseCollectionGroup.d.ts +458 -0
  19. package/dist/server/preparePostPurchaseCollectionView.d.ts +442 -0
  20. package/dist/server/preparePostPurchaseGroupAdmissionView.d.ts +459 -0
  21. package/dist/server/preparePostPurchaseGroupDefault.d.ts +459 -0
  22. package/dist/server/preparePostPurchaseGroupView.d.ts +458 -0
  23. package/dist/server/preparePostPurchaseMemberView.d.ts +1466 -0
  24. package/dist/server/preparePostPurchaseProduct.d.ts +11 -0
  25. package/dist/server/preparePostPurchaseQuantityAdmissionView.d.ts +440 -0
  26. package/dist/server/preparePostPurchaseQuantityView.d.ts +427 -0
  27. package/dist/server/preparePostPurchaseSubscription.d.ts +37 -5
  28. package/dist/server/preparePostPurchaseView.d.ts +8 -0
  29. package/dist/server/projectPostPurchaseProduct.d.ts +37 -5
  30. package/dist/transforms/postPurchase/convertDescriptionRte.d.ts +11 -0
  31. package/package.json +1 -1
@@ -47,9 +47,20 @@ __export(server_exports, {
47
47
  fetchMonetizeOffers: () => fetchMonetizeOffers,
48
48
  fetchUserConfig: () => fetchUserConfig,
49
49
  postAnalyticsEvents: () => postAnalyticsEvents,
50
+ preparePostPurchaseAdmissionView: () => preparePostPurchaseAdmissionView,
51
+ preparePostPurchaseCollectionView: () => preparePostPurchaseCollectionView,
52
+ preparePostPurchaseGroupAdmissionView: () => preparePostPurchaseGroupAdmissionView,
50
53
  preparePostPurchaseGroupDeclineDisplay: () => preparePostPurchaseGroupDeclineDisplay,
54
+ preparePostPurchaseGroupDefault: () => preparePostPurchaseGroupDefault,
55
+ preparePostPurchaseGroupView: () => preparePostPurchaseGroupView,
56
+ preparePostPurchaseMemberAdmissionView: () => preparePostPurchaseMemberAdmissionView,
57
+ preparePostPurchaseMemberView: () => preparePostPurchaseMemberView,
51
58
  preparePostPurchaseOfferPresentation: () => preparePostPurchaseOfferPresentation,
59
+ preparePostPurchaseProduct: () => preparePostPurchaseProduct,
60
+ preparePostPurchaseQuantityAdmissionView: () => preparePostPurchaseQuantityAdmissionView,
61
+ preparePostPurchaseQuantityView: () => preparePostPurchaseQuantityView,
52
62
  preparePostPurchaseSubscription: () => preparePostPurchaseSubscription,
63
+ preparePostPurchaseView: () => preparePostPurchaseView,
53
64
  readPostPurchaseGroupSelection: () => readPostPurchaseGroupSelection,
54
65
  readPostPurchaseQuantity: () => readPostPurchaseQuantity,
55
66
  translateAnalyticsEvent: () => translateAnalyticsEvent,
@@ -2178,7 +2189,7 @@ var stripContentBlockHtml = (text2) => text2.replace(HTML_COMMENT_RE, "").replac
2178
2189
  var convertTextToTiptapParagraph = ({
2179
2190
  color,
2180
2191
  fontSize,
2181
- marks = [],
2192
+ marks: marks2 = [],
2182
2193
  text: text2,
2183
2194
  textAlign
2184
2195
  }) => {
@@ -2187,7 +2198,7 @@ var convertTextToTiptapParagraph = ({
2187
2198
  attrs: { textAlign },
2188
2199
  content: sanitizedText ? [
2189
2200
  {
2190
- marks: [{ attrs: { color, fontSize }, type: "textStyle" }, ...marks],
2201
+ marks: [{ attrs: { color, fontSize }, type: "textStyle" }, ...marks2],
2191
2202
  text: sanitizedText,
2192
2203
  type: "text"
2193
2204
  }
@@ -2644,11 +2655,11 @@ var pushText = (state, rawText) => {
2644
2655
  decodeTextEntities(rawText).split("\n").forEach((segment, index) => {
2645
2656
  if (index > 0) flushParagraph(state);
2646
2657
  if (!segment) return;
2647
- const marks = state.stack.flatMap((entry) => entry.marks);
2648
- if (state.defaultTextStyleMark && !marks.some((mark) => mark.type === "textStyle")) {
2649
- marks.push(state.defaultTextStyleMark);
2658
+ const marks2 = state.stack.flatMap((entry) => entry.marks);
2659
+ if (state.defaultTextStyleMark && !marks2.some((mark) => mark.type === "textStyle")) {
2660
+ marks2.push(state.defaultTextStyleMark);
2650
2661
  }
2651
- state.currentRuns.push(TiptapText.parse(marks.length > 0 ? { marks, text: segment } : { text: segment }));
2662
+ state.currentRuns.push(TiptapText.parse(marks2.length > 0 ? { marks: marks2, text: segment } : { text: segment }));
2652
2663
  });
2653
2664
  };
2654
2665
 
@@ -3223,10 +3234,10 @@ var SWITCH_LABEL_TOKENS2 = ["subscriptionDiscount", "frequency", "interval"];
3223
3234
  var QUANTITY_ERROR_TOKENS = ["max", "min", "step"];
3224
3235
  var VARIANT_SELECTOR = { button: "button", radio: "radio", select: "menu" };
3225
3236
  var buildStyledText = (token, style, fontSize = style?.textSize ?? "base") => {
3226
- const marks = [{ attrs: { color: "base", fontSize }, type: "textStyle" }];
3227
- if (style?.textEmphasis === "bold") marks.push({ type: "bold" });
3228
- if (style?.textEmphasis === "italic") marks.push({ type: "italic" });
3229
- return { content: [{ content: [{ marks, text: token, type: "text" }], type: "paragraph" }], type: "doc" };
3237
+ const marks2 = [{ attrs: { color: "base", fontSize }, type: "textStyle" }];
3238
+ if (style?.textEmphasis === "bold") marks2.push({ type: "bold" });
3239
+ if (style?.textEmphasis === "italic") marks2.push({ type: "italic" });
3240
+ return { content: [{ content: [{ marks: marks2, text: token, type: "text" }], type: "paragraph" }], type: "doc" };
3230
3241
  };
3231
3242
  var buildPriceContent = () => ({
3232
3243
  content: [
@@ -5976,14 +5987,10 @@ var PostPurchasePrimaryImageSource = import_zod51.z.string().default(
5976
5987
  "https://cdn.shopify.com/shopifycloud/shopify/assets/no-image-2048-5e88c1b20e087fb7bbe9a3771824e743c244f437e4f8ba93bbf7b11b53f7824c.gif"
5977
5988
  );
5978
5989
  var PostPurchaseProductDisplay = import_zod51.z.object({
5990
+ descriptionDocument: TiptapDocument.optional(),
5979
5991
  discountedFrom: PostPurchaseSettings.shape.discountedFrom,
5980
5992
  gallery: PostPurchaseProductGallery.optional(),
5981
- language: language.pick({
5982
- description: true,
5983
- descriptionEnabled: true,
5984
- descriptionRte: true,
5985
- descriptionSpacing: true
5986
- }),
5993
+ language: language.pick({ description: true, descriptionEnabled: true }),
5987
5994
  primaryImage: import_zod51.z.object({ description: import_zod51.z.string(), source: import_zod51.z.string() }),
5988
5995
  productOptions: PostPurchaseSettings.shape.productOptions.pick({
5989
5996
  showDeclineAll: true,
@@ -6101,7 +6108,7 @@ var subscriptionUnavailable = (normalized, plan, allowCollection, quantity2) =>
6101
6108
  };
6102
6109
 
6103
6110
  // src/server/postPurchaseProductDisplay.ts
6104
- var import_zod55 = require("zod");
6111
+ var import_zod56 = require("zod");
6105
6112
 
6106
6113
  // src/server/postPurchasePrimaryImage.ts
6107
6114
  var postPurchasePrimaryImage = (product) => {
@@ -6122,9 +6129,67 @@ var postPurchaseProductGallery = (product, limit) => ({
6122
6129
  selectedImageId: product.images?.find((image) => image.id === product.variants[0].imageId)?.id
6123
6130
  });
6124
6131
 
6132
+ // src/transforms/postPurchase/convertDescriptionRte.ts
6133
+ var import_zod55 = require("zod");
6134
+ var alignments = { center: "center", left: "start", right: "end" };
6135
+ var colors = ["critical", "subdued", "success", "warning"];
6136
+ var sizes2 = ["extraSmall", "small", "medium", "large", "extraLarge"];
6137
+ var spacings2 = {
6138
+ default: "base",
6139
+ loose: "loose",
6140
+ none: "none",
6141
+ tight: "tight",
6142
+ xloose: "extraLoose",
6143
+ xtight: "extraTight"
6144
+ };
6145
+ var Block = import_zod55.z.object({
6146
+ attrs: import_zod55.z.object({ alignment: import_zod55.z.enum(["left", "center", "right"]).optional().catch(void 0) }).catch({}),
6147
+ content: import_zod55.z.array(import_zod55.z.unknown()).catch([]),
6148
+ type: import_zod55.z.literal("ShopifyTextBlock")
6149
+ });
6150
+ var Run = import_zod55.z.object({ marks: import_zod55.z.array(import_zod55.z.unknown()).catch([]), text: import_zod55.z.string().min(1), type: import_zod55.z.literal("text") });
6151
+ var Inline = import_zod55.z.object({
6152
+ attrs: import_zod55.z.object({
6153
+ color: import_zod55.z.enum(colors).optional().catch(void 0),
6154
+ emphasis: import_zod55.z.array(import_zod55.z.unknown()).catch([]),
6155
+ size: import_zod55.z.enum(sizes2).optional().catch(void 0)
6156
+ }),
6157
+ type: import_zod55.z.literal("ShopifyTextInline")
6158
+ });
6159
+ var marks = (raw) => {
6160
+ const found = raw.map((mark) => Inline.safeParse(mark)).find(({ success }) => success)?.data;
6161
+ if (!found) return [];
6162
+ const { color = "base", emphasis, size = "base" } = found.attrs;
6163
+ return [
6164
+ ...emphasis.includes("bold") ? [{ type: "bold" }] : [],
6165
+ ...emphasis.includes("strikethrough") ? [{ type: "strike" }] : [],
6166
+ { attrs: { color, fontSize: size }, type: "textStyle" }
6167
+ ];
6168
+ };
6169
+ var convertDescriptionRte = (rte, spacing) => TiptapDocument.parse({
6170
+ attrs: { blockSpacing: spacings2[spacing ?? "none"] },
6171
+ content: rte.content.flatMap((node) => {
6172
+ const block = Block.safeParse(node);
6173
+ if (!block.success) return [];
6174
+ const { alignment } = block.data.attrs;
6175
+ return [
6176
+ {
6177
+ attrs: { textAlign: alignment ? alignments[alignment] : "start" },
6178
+ content: block.data.content.flatMap((inline) => {
6179
+ const run = Run.safeParse(inline);
6180
+ return run.success ? [{ marks: marks(run.data.marks), text: run.data.text }] : [];
6181
+ }),
6182
+ type: "paragraph"
6183
+ }
6184
+ ];
6185
+ }),
6186
+ type: "doc"
6187
+ });
6188
+
6125
6189
  // src/server/postPurchaseProductDisplay.ts
6126
- var ResponseLanguage = import_zod55.z.object({ description: PostPurchaseProductDisplay.shape.responseDescription }).default({ description: "" });
6190
+ var ResponseLanguage = import_zod56.z.object({ description: PostPurchaseProductDisplay.shape.responseDescription }).default({ description: "" });
6127
6191
  var projectPostPurchaseProductDisplay = (effective, metadata, product) => PostPurchaseProductDisplay.parse({
6192
+ descriptionDocument: effective.language.descriptionRte && convertDescriptionRte(effective.language.descriptionRte, effective.language.descriptionSpacing),
6128
6193
  discountedFrom: effective.discountedFrom,
6129
6194
  gallery: postPurchaseProductGallery(product, effective.subImages),
6130
6195
  language: effective.language,
@@ -6193,72 +6258,262 @@ var preparePostPurchaseSubscription = (settings, response, report) => {
6193
6258
  );
6194
6259
  };
6195
6260
 
6196
- // src/schema/postPurchaseOfferEligibility.ts
6197
- var import_zod57 = require("zod");
6261
+ // src/server/postPurchaseProductEligibility.ts
6262
+ var oneTimeUnavailable = (normalized, allowCollection, quantity2) => {
6263
+ const { data, effective, original } = normalized;
6264
+ if (data.length !== 1 || data[0].variants.length !== 1) return "Only one fixed product and variant are supported";
6265
+ if (effective.productType === "subscription" || [original, effective].some(
6266
+ (config) => !allowCollection && config.productLimit !== 1 || config.upgradeToSubscription.allow || !quantity2 && config.quantityInputs.enabled && (config.quantityInputs.minValue !== config.quantityInputs.maxValue || config.quantityInputs.defaultQuantity !== config.quantityInputs.minValue)
6267
+ ))
6268
+ return "Only fixed one-time configuration is supported";
6269
+ const product = data[0];
6270
+ const variant2 = product.variants[0];
6271
+ if (product.productGroupVariants.length || product.sellingPlanGroups?.some((group) => group.requiresSellingPlan) || !postPurchaseVariantAvailable(variant2))
6272
+ return "An available one-time variant without product groups is required";
6273
+ if (variant2.productId !== product.id) throw new Error("Product variant identity mismatch");
6274
+ };
6198
6275
 
6199
- // src/schema/postPurchaseProductCollectionView.ts
6200
- var import_zod56 = require("zod");
6201
- var PostPurchaseExcludedProductIds = import_zod56.z.array(PostPurchaseProductId).default([]);
6276
+ // src/server/preparePostPurchaseProduct.ts
6277
+ var prepareNormalizedProduct = (normalized, report, quantity2, allowCollection = false) => {
6278
+ const reason = oneTimeUnavailable(normalized, allowCollection, quantity2);
6279
+ if (reason) return { reason, status: "unsupported" };
6280
+ const { effective } = normalized;
6281
+ return PreparedPostPurchaseProduct.parse({
6282
+ ...projectPostPurchaseProduct(normalized, quantity2),
6283
+ status: "prepared",
6284
+ terms: {
6285
+ discount: { ...effective.discount, title: effective.language.global.save },
6286
+ shipping: effective.shipping
6287
+ }
6288
+ });
6289
+ };
6290
+ var preparePostPurchaseProduct = (settings, response, report) => prepareNormalizedProduct(normalizePostPurchaseProduct(settings, response), report);
6202
6291
 
6203
- // src/schema/postPurchaseOfferEligibility.ts
6204
- var selection = PreparedPostPurchaseProduct.shape.selection;
6205
- var PostPurchaseOfferSkipReason = import_zod57.z.enum(["empty", "no-eligible-subscription"]);
6206
- var PostPurchaseOfferEligibilityContext = import_zod57.z.object({
6207
- excludedProductIds: PostPurchaseExcludedProductIds,
6208
- originalLineItems: import_zod57.z.array(selection.pick({ productId: true, sellingPlanId: true, variantId: true }))
6209
- });
6210
- var PostPurchaseOfferEligibility = import_zod57.z.discriminatedUnion("status", [
6211
- import_zod57.z.object({
6212
- members: import_zod57.z.array(
6213
- import_zod57.z.object({ productId: selection.shape.productId, productIndex: import_zod57.z.number().int().nonnegative() })
6214
- ),
6215
- status: import_zod57.z.literal("retain")
6216
- }),
6217
- import_zod57.z.object({ reason: PostPurchaseOfferSkipReason, status: import_zod57.z.literal("skip") }),
6218
- import_zod57.z.object({ reason: import_zod57.z.literal("eligible-upgrade").optional(), status: import_zod57.z.literal("unavailable") })
6292
+ // src/schema/postPurchaseProductView.ts
6293
+ var import_zod60 = require("zod");
6294
+
6295
+ // src/schema/postPurchaseChoice.ts
6296
+ var import_zod57 = require("zod");
6297
+ var PostPurchaseChoice = import_zod57.z.discriminatedUnion("mode", [
6298
+ import_zod57.z.object({ mode: import_zod57.z.literal("one-time") }).strict(),
6299
+ import_zod57.z.object({ mode: import_zod57.z.literal("subscription"), sellingPlanId: PostPurchasePlanOption.shape.id }).strict()
6219
6300
  ]);
6301
+ var PostPurchaseOptions = import_zod57.z.object({
6302
+ defaultChoice: PostPurchaseChoice,
6303
+ modes: import_zod57.z.array(import_zod57.z.enum(["one-time", "subscription"])).min(1).max(2),
6304
+ selector: PostPurchaseSettings.shape.productTypeSelector
6305
+ });
6220
6306
 
6221
- // src/server/normalizePostPurchaseCollection.ts
6222
- var import_zod58 = require("zod");
6223
- var normalizePostPurchaseCollection = (settings, response, excludedProductIds) => {
6224
- const normalized = normalizePostPurchaseProduct(settings, response);
6225
- const limit = import_zod58.z.number().int().positive();
6226
- limit.parse(normalized.original.productLimit);
6227
- const prefix = normalized.data.slice(0, limit.parse(normalized.effective.productLimit));
6228
- if (new Set(prefix.map(({ id }) => id)).size !== prefix.length)
6229
- throw new Error("Ambiguous post-purchase collection");
6230
- const excluded = new Set(PostPurchaseExcludedProductIds.parse(excludedProductIds));
6231
- const members = prefix.map((product, productIndex) => ({ product, productIndex })).filter(({ product }) => !excluded.has(product.id));
6232
- return { members, normalized };
6233
- };
6307
+ // src/schema/postPurchaseGroupCatalog.ts
6308
+ var import_zod59 = require("zod");
6234
6309
 
6235
6310
  // src/schema/postPurchaseVariantCatalog.ts
6236
- var import_zod59 = require("zod");
6237
- var PostPurchaseVariantSelector = import_zod59.z.object({ variantId: PostPurchaseVariantId }).strict();
6311
+ var import_zod58 = require("zod");
6312
+ var PostPurchaseVariantSelector = import_zod58.z.object({ variantId: PostPurchaseVariantId }).strict();
6238
6313
  var PostPurchaseVariantOption = OfferProduct.shape.options.element.extend({
6239
- id: import_zod59.z.number().int().positive(),
6240
- position: import_zod59.z.number().int().min(1).max(3)
6314
+ id: import_zod58.z.number().int().positive(),
6315
+ position: import_zod58.z.number().int().min(1).max(3)
6241
6316
  });
6242
6317
  var PostPurchaseVariantValues = OfferProduct.shape.variants.element.pick({
6243
6318
  option1: true,
6244
6319
  option2: true,
6245
6320
  option3: true
6246
6321
  });
6247
- var PostPurchaseVariantCatalog = import_zod59.z.object({
6322
+ var PostPurchaseVariantCatalog = import_zod58.z.object({
6248
6323
  displayMode: PostPurchaseSettings.shape.productOptions.shape.variantSelectorDisplayMode,
6249
- options: import_zod59.z.array(PostPurchaseVariantOption),
6324
+ options: import_zod58.z.array(PostPurchaseVariantOption),
6250
6325
  productId: PostPurchaseProductId,
6251
6326
  showSelectors: PostPurchaseSettings.shape.productOptions.shape.showVariantSelectors,
6252
- variants: import_zod59.z.array(
6327
+ variants: import_zod58.z.array(
6253
6328
  PostPurchaseVariantValues.partial().extend({
6254
- available: import_zod59.z.boolean(),
6329
+ available: import_zod58.z.boolean(),
6255
6330
  id: PostPurchaseVariantId,
6256
- imageId: import_zod59.z.number().int().nonnegative().nullish(),
6331
+ imageId: import_zod58.z.number().int().nonnegative().nullish(),
6257
6332
  title: OfferProduct.shape.variants.element.shape.title
6258
6333
  })
6259
6334
  )
6260
6335
  });
6261
6336
 
6337
+ // src/schema/postPurchaseGroupCatalog.ts
6338
+ var productId = PreparedPostPurchaseProduct.shape.selection.shape.productId;
6339
+ var source = PostPurchaseProductSource.shape.data.element;
6340
+ var PostPurchaseGroupDescription = source.pick({ description: true, id: true, image: true, images: true, title: true }).extend({
6341
+ description: source.shape.description.default(null),
6342
+ image: source.shape.image.default(null),
6343
+ options: PostPurchaseVariantCatalog.shape.options.default([])
6344
+ });
6345
+ var PostPurchaseGroupCatalog = import_zod59.z.object({
6346
+ memberProductId: productId,
6347
+ options: import_zod59.z.array(import_zod59.z.object({ productId, title: import_zod59.z.string(), variantCatalog: PostPurchaseVariantCatalog }))
6348
+ });
6349
+ var PostPurchaseGroupSelection = import_zod59.z.object({
6350
+ memberProductId: productId,
6351
+ productId
6352
+ });
6353
+
6354
+ // src/schema/postPurchaseProductView.ts
6355
+ var PostPurchaseProductView = import_zod60.z.union([
6356
+ import_zod60.z.object({
6357
+ groupCatalog: PostPurchaseGroupCatalog.optional(),
6358
+ initialVariant: PostPurchaseVariantSelector.optional(),
6359
+ planCatalog: PostPurchasePlanCatalog.nullable().optional(),
6360
+ preparation: PreparedPostPurchaseProduct.extend({
6361
+ display: PreparedPostPurchaseProduct.shape.display.extend({ description: import_zod60.z.string().nullable() }).refine(
6362
+ ({ description, descriptionDocument }) => description === null === (descriptionDocument !== void 0),
6363
+ "Exactly one of the plain and rich descriptions is shown"
6364
+ )
6365
+ }),
6366
+ purchaseOptions: PostPurchaseOptions.optional(),
6367
+ sections: CABRootSection,
6368
+ variantCatalog: PostPurchaseVariantCatalog.optional()
6369
+ }),
6370
+ import_zod60.z.object({
6371
+ groupCatalog: PostPurchaseGroupCatalog.optional(),
6372
+ initialVariant: PostPurchaseVariantSelector.optional(),
6373
+ planCatalog: PostPurchasePlanCatalog.nullable().optional(),
6374
+ preparation: PostPurchasePreparation.options[1],
6375
+ purchaseOptions: PostPurchaseOptions.optional(),
6376
+ sections: import_zod60.z.null(),
6377
+ variantCatalog: PostPurchaseVariantCatalog.optional()
6378
+ })
6379
+ ]);
6380
+
6381
+ // src/server/postPurchaseOfferCopy.ts
6382
+ var import_zod61 = require("zod");
6383
+ var Copy = import_zod61.z.object({
6384
+ superTitle: CalloutBannerBlock.shape.settings.shape.superTitle.unwrap().optional().catch(void 0),
6385
+ title: CalloutBannerBlock.shape.settings.shape.title.unwrap().optional().catch(void 0)
6386
+ });
6387
+ var Callout = import_zod61.z.object({ settings: import_zod61.z.record(import_zod61.z.string(), import_zod61.z.unknown()), type: import_zod61.z.literal("callout_banner") });
6388
+ var postPurchaseOfferCopy = (blocks, metadata) => {
6389
+ const copy = Copy.safeParse(metadata.widget.language);
6390
+ if (!blocks || !copy.success) return blocks;
6391
+ const first = blocks.findIndex((block) => Callout.pick({ type: true }).safeParse(block).success);
6392
+ return blocks.map((block, index) => {
6393
+ if (index !== first) return block;
6394
+ const callout = Callout.passthrough().safeParse(block);
6395
+ if (!callout.success) return block;
6396
+ return {
6397
+ ...callout.data,
6398
+ settings: {
6399
+ ...callout.data.settings,
6400
+ ...copy.data.title && { title: copy.data.title },
6401
+ ...copy.data.superTitle && { superTitle: copy.data.superTitle }
6402
+ }
6403
+ };
6404
+ });
6405
+ };
6406
+
6407
+ // src/server/selectPostPurchaseChoice.ts
6408
+ var selectPostPurchaseChoice = (normalized, projected, requested, allowCollection, quantity2) => {
6409
+ const { data, effective } = normalized;
6410
+ const modes = [];
6411
+ const catalog = projected && projected.productId === data[0]?.id && projected.variantId === data[0].variants[0]?.id ? projected : null;
6412
+ const firstPlan = catalog?.plans[0];
6413
+ const oneTimeReason = oneTimeUnavailable(normalized, allowCollection, quantity2);
6414
+ const subscriptionReason = subscriptionUnavailable(normalized, firstPlan, allowCollection, quantity2);
6415
+ if (!oneTimeReason) modes.push("one-time");
6416
+ if (!subscriptionReason) modes.push("subscription");
6417
+ if (oneTimeReason && subscriptionReason)
6418
+ return {
6419
+ choice: void 0,
6420
+ options: void 0,
6421
+ plan: void 0,
6422
+ reason: effective.productType === "one-time" ? oneTimeReason : subscriptionReason
6423
+ };
6424
+ const defaultChoice = firstPlan && modes.includes("subscription") && (modes[0] === "subscription" || effective.subscriptionIsDefault) ? { mode: "subscription", sellingPlanId: firstPlan.id } : { mode: "one-time" };
6425
+ const options2 = PostPurchaseOptions.parse({ defaultChoice, modes, selector: effective.productTypeSelector });
6426
+ const choice = requested ?? defaultChoice;
6427
+ const plan = choice.mode === "subscription" ? catalog?.plans.find(({ id }) => id === choice.sellingPlanId) : void 0;
6428
+ const bound = modes.includes(choice.mode) && (choice.mode === "one-time" || plan) ? choice : void 0;
6429
+ return {
6430
+ choice: bound,
6431
+ options: options2,
6432
+ plan: bound ? plan : void 0,
6433
+ reason: bound ? void 0 : "Requested purchase choice is unavailable"
6434
+ };
6435
+ };
6436
+
6437
+ // src/server/preparePostPurchaseView.ts
6438
+ var resolveDescription = ({ descriptionDocument, ...display }, productDescription) => {
6439
+ const plain = display.language.descriptionEnabled && productDescription || display.responseDescription || (descriptionDocument ? null : display.language.description);
6440
+ return plain === null ? { ...display, description: null, descriptionDocument } : { ...display, description: plain };
6441
+ };
6442
+ var prepareNormalizedPostPurchaseView = (widgetId, normalized, report, choice, quantity2, allowCollection = false) => {
6443
+ const planCatalog = projectPostPurchasePlanCatalog(normalized, report);
6444
+ const selected = selectPostPurchaseChoice(normalized, planCatalog, choice, allowCollection, quantity2);
6445
+ const purchaseOptions = selected.options;
6446
+ const preparation = !selected.choice ? { reason: selected.reason, status: "unsupported" } : selected.choice.mode === "subscription" ? prepareNormalizedSubscription(normalized, report, selected.plan, quantity2, allowCollection) : prepareNormalizedProduct(normalized, report, quantity2, allowCollection);
6447
+ const unsupported = (reason) => ({
6448
+ planCatalog,
6449
+ preparation: { reason, status: "unsupported" },
6450
+ purchaseOptions,
6451
+ sections: null
6452
+ });
6453
+ if (preparation.status === "unsupported") return { planCatalog, preparation, purchaseOptions, sections: null };
6454
+ if (!normalized.effective.blocks?.length) return unsupported("One fixed product information block is required");
6455
+ const sections = convertMessagePreview(
6456
+ widgetId,
6457
+ {
6458
+ blocks: postPurchaseOfferCopy(normalized.effective.blocks, normalized.metadata),
6459
+ type: "shopify_post_purchase_extension"
6460
+ },
6461
+ report
6462
+ );
6463
+ if (sections.sections.filter((section) => section.sectionType === "offers").length !== 1)
6464
+ return unsupported("One fixed product information block is required");
6465
+ return PostPurchaseProductView.parse({
6466
+ planCatalog,
6467
+ preparation: {
6468
+ ...preparation,
6469
+ display: resolveDescription(preparation.display, preparation.product.description)
6470
+ },
6471
+ purchaseOptions,
6472
+ sections
6473
+ });
6474
+ };
6475
+ var preparePostPurchaseView = (widgetId, settings, response, report, choice) => prepareNormalizedPostPurchaseView(widgetId, normalizePostPurchaseProduct(settings, response), report, choice);
6476
+
6477
+ // src/server/preparePostPurchaseAdmissionView.ts
6478
+ var preparePostPurchaseAdmissionView = (widgetId, settings, response, report, choice) => {
6479
+ const normalized = normalizePostPurchaseProduct(settings, response);
6480
+ const view = prepareNormalizedPostPurchaseView(widgetId, normalized, report, choice);
6481
+ const { removePartialOrder } = PostPurchaseSettings.shape.advance.parse(normalized.effective.advance);
6482
+ return { removePartialOrder, view };
6483
+ };
6484
+
6485
+ // src/schema/postPurchaseProductCollectionView.ts
6486
+ var import_zod62 = require("zod");
6487
+ var PostPurchaseProductCollectionView = import_zod62.z.object({
6488
+ members: import_zod62.z.array(
6489
+ import_zod62.z.object({
6490
+ productId: PostPurchaseProductId,
6491
+ productIndex: import_zod62.z.number().int().nonnegative(),
6492
+ view: PostPurchaseProductView
6493
+ })
6494
+ )
6495
+ });
6496
+ var PostPurchaseCollectionChoice = import_zod62.z.object({
6497
+ choice: PostPurchaseChoice.optional(),
6498
+ productId: PostPurchaseProductId,
6499
+ variantId: PostPurchaseVariantSelector.shape.variantId.optional()
6500
+ }).strict();
6501
+ var PostPurchaseExcludedProductIds = import_zod62.z.array(PostPurchaseProductId).default([]);
6502
+
6503
+ // src/server/normalizePostPurchaseCollection.ts
6504
+ var import_zod63 = require("zod");
6505
+ var normalizePostPurchaseCollection = (settings, response, excludedProductIds) => {
6506
+ const normalized = normalizePostPurchaseProduct(settings, response);
6507
+ const limit = import_zod63.z.number().int().positive();
6508
+ limit.parse(normalized.original.productLimit);
6509
+ const prefix = normalized.data.slice(0, limit.parse(normalized.effective.productLimit));
6510
+ if (new Set(prefix.map(({ id }) => id)).size !== prefix.length)
6511
+ throw new Error("Ambiguous post-purchase collection");
6512
+ const excluded = new Set(PostPurchaseExcludedProductIds.parse(excludedProductIds));
6513
+ const members = prefix.map((product, productIndex) => ({ product, productIndex })).filter(({ product }) => !excluded.has(product.id));
6514
+ return { members, normalized };
6515
+ };
6516
+
6262
6517
  // src/server/postPurchaseVariantCatalog.ts
6263
6518
  var projectPostPurchaseVariantCatalog = (product, settings) => {
6264
6519
  const options2 = PostPurchaseVariantCatalog.shape.options.parse(product.options === void 0 ? [] : product.options).sort((a, b) => a.position - b.position);
@@ -6292,22 +6547,216 @@ var projectPostPurchaseVariantCatalog = (product, settings) => {
6292
6547
  });
6293
6548
  };
6294
6549
 
6295
- // src/schema/postPurchaseGroupCatalog.ts
6296
- var import_zod60 = require("zod");
6297
- var productId = PreparedPostPurchaseProduct.shape.selection.shape.productId;
6298
- var source = PostPurchaseProductSource.shape.data.element;
6299
- var PostPurchaseGroupDescription = source.pick({ description: true, id: true, image: true, images: true, title: true }).extend({
6300
- description: source.shape.description.default(null),
6301
- image: source.shape.image.default(null),
6302
- options: PostPurchaseVariantCatalog.shape.options.default([])
6550
+ // src/schema/postPurchaseQuantity.ts
6551
+ var import_zod64 = require("zod");
6552
+ var quantity = PreparedPostPurchaseProduct.shape.selection.shape.quantity;
6553
+ var PostPurchaseQuantityChoice = PostPurchaseCollectionChoice.extend({ quantity: quantity.optional() });
6554
+ var PostPurchaseQuantityPolicy = PostPurchaseSettings.shape.quantityInputs.omit({ defaultQuantity: true }).extend({
6555
+ initialQuantity: quantity,
6556
+ maxValue: quantity,
6557
+ minValue: import_zod64.z.literal(0).transform(() => 1).or(quantity)
6558
+ }).refine(({ maxValue, minValue }) => minValue <= maxValue, "Quantity bounds are reversed");
6559
+
6560
+ // src/server/readPostPurchaseQuantity.ts
6561
+ var PostPurchaseQuantityUnavailable = class extends Error {
6562
+ };
6563
+ var readPostPurchaseQuantity = ({
6564
+ data,
6565
+ effective,
6566
+ original
6567
+ }, selection3) => {
6568
+ const positive = PreparedPostPurchaseProduct.shape.selection.shape.quantity;
6569
+ for (const config of [original, effective]) {
6570
+ if (!config.quantityInputs.enabled) continue;
6571
+ const initialQuantity2 = positive.parse(config.quantityInputs.defaultQuantity);
6572
+ const policy2 = PostPurchaseQuantityPolicy.parse({ ...config.quantityInputs, initialQuantity: initialQuantity2 });
6573
+ if (initialQuantity2 < policy2.minValue || initialQuantity2 > policy2.maxValue)
6574
+ throw new Error("Configured quantity default is outside its bounds");
6575
+ }
6576
+ const initialQuantity = data[0]?.metadata?.productQuantity ?? (original.quantityInputs.enabled ? original.quantityInputs.defaultQuantity : 1);
6577
+ const policy = PostPurchaseQuantityPolicy.parse(
6578
+ effective.quantityInputs.enabled ? { ...effective.quantityInputs, initialQuantity } : { enabled: false, initialQuantity, maxValue: initialQuantity, minValue: initialQuantity }
6579
+ );
6580
+ const requested = "quantity" in selection3 ? selection3.quantity : selection3.expectedQuantity === initialQuantity ? void 0 : selection3.expectedQuantity;
6581
+ const quantity2 = positive.parse(requested ?? initialQuantity);
6582
+ if (requested !== void 0 && (policy.enabled ? quantity2 < policy.minValue || quantity2 > policy.maxValue : quantity2 !== initialQuantity))
6583
+ throw new PostPurchaseQuantityUnavailable("Requested quantity is unavailable");
6584
+ return { policy, quantity: quantity2 };
6585
+ };
6586
+
6587
+ // src/schema/postPurchaseVariantDefault.ts
6588
+ var import_zod65 = require("zod");
6589
+ var values = PostPurchaseVariantValues.partial().extend({
6590
+ option1: PostPurchaseVariantValues.shape.option1.nullish()
6303
6591
  });
6304
- var PostPurchaseGroupCatalog = import_zod60.z.object({
6305
- memberProductId: productId,
6306
- options: import_zod60.z.array(import_zod60.z.object({ productId, title: import_zod60.z.string(), variantCatalog: PostPurchaseVariantCatalog }))
6592
+ var variant = values.extend({
6593
+ id: PostPurchaseVariantId,
6594
+ inventoryManagement: import_zod65.z.string().nullable(),
6595
+ inventoryPolicy: import_zod65.z.string(),
6596
+ inventoryQuantity: import_zod65.z.number()
6307
6597
  });
6308
- var PostPurchaseGroupSelection = import_zod60.z.object({
6309
- memberProductId: productId,
6310
- productId
6598
+ var options = import_zod65.z.array(PostPurchaseVariantOption.pick({ name: true, values: true }));
6599
+ var PostPurchaseVariantDefaultProduct = import_zod65.z.object({
6600
+ id: PostPurchaseProductId,
6601
+ options,
6602
+ selectedVariant: variant.optional(),
6603
+ variants: import_zod65.z.array(variant)
6604
+ });
6605
+ var PostPurchaseVariantDefaultSettings = PostPurchaseSettings.shape.productOptions.pick({
6606
+ hideOutOfStockVariants: true,
6607
+ matchVariant: true
6608
+ });
6609
+ var PostPurchaseOrderAttributes = import_zod65.z.record(import_zod65.z.string(), import_zod65.z.array(import_zod65.z.string())).default({});
6610
+ var PostPurchaseOriginalVariants = import_zod65.z.array(
6611
+ import_zod65.z.object({ productId: PostPurchaseProductId, variantId: PostPurchaseVariantId })
6612
+ );
6613
+ var PostPurchaseAttributeProducts = import_zod65.z.array(
6614
+ import_zod65.z.object({ id: PostPurchaseProductId, options, variants: import_zod65.z.array(values.extend({ id: PostPurchaseVariantId })) })
6615
+ );
6616
+
6617
+ // src/schema/postPurchaseVariantDefaultContext.ts
6618
+ var import_zod66 = require("zod");
6619
+ var PostPurchaseVariantDefaultContext = import_zod66.z.object({
6620
+ enrichedLineItems: import_zod66.z.unknown().optional(),
6621
+ originalVariants: PostPurchaseOriginalVariants
6622
+ });
6623
+
6624
+ // src/server/createPostPurchaseOrderAttributes.ts
6625
+ var createPostPurchaseOrderAttributes = (original, enriched) => {
6626
+ const products = PostPurchaseAttributeProducts.parse(enriched);
6627
+ const attributes = {};
6628
+ for (const item of PostPurchaseOriginalVariants.parse(original)) {
6629
+ const product = products.find(({ id }) => id === item.productId);
6630
+ const variant2 = product?.variants.find(({ id }) => id === item.variantId);
6631
+ if (!variant2 || !product) continue;
6632
+ ["option1", "option2", "option3"].forEach((key, index) => {
6633
+ const value = variant2[key];
6634
+ const option = product.options[index];
6635
+ if (!value || !option) return;
6636
+ const values2 = attributes[option.name] ?? [];
6637
+ if (!values2.includes(value)) attributes[option.name] = [...values2, value];
6638
+ });
6639
+ }
6640
+ return attributes;
6641
+ };
6642
+
6643
+ // src/server/matchPostPurchaseVariantDefault.ts
6644
+ var matchPostPurchaseVariantDefault = (product, attributes, filterOutOfStock) => {
6645
+ const keys = ["option1", "option2", "option3"];
6646
+ const values2 = keys.map((_, index) => {
6647
+ const option = product.options[index];
6648
+ return option ? option.values.filter((value) => attributes[option.name]?.includes(value)) : [];
6649
+ });
6650
+ if (!values2.some((entries) => entries.length)) return;
6651
+ let bestRank = 1;
6652
+ let best;
6653
+ for (const variant2 of product.variants) {
6654
+ if (filterOutOfStock && variant2.inventoryPolicy !== "continue" && variant2.inventoryQuantity <= 0) continue;
6655
+ const rank = keys.reduce((total, key, index) => {
6656
+ const value = variant2[key];
6657
+ return total + Number(!value && !values2[index].length || !!value && values2[index].includes(value));
6658
+ }, 0);
6659
+ if (rank > bestRank) {
6660
+ best = variant2;
6661
+ bestRank = rank;
6662
+ }
6663
+ }
6664
+ return best;
6665
+ };
6666
+
6667
+ // src/server/resolvePostPurchaseVariantDefault.ts
6668
+ var resolvePostPurchaseVariantDefault = (source2, settings, originalAttributes) => {
6669
+ const product = PostPurchaseVariantDefaultProduct.parse(source2);
6670
+ const policy = PostPurchaseVariantDefaultSettings.parse(settings);
6671
+ const attributes = PostPurchaseOrderAttributes.parse(originalAttributes);
6672
+ let selected = source2.selectedVariant && source2.selectedVariant === source2.variants[0] ? product.variants[0] : product.selectedVariant;
6673
+ if (!selected && policy.matchVariant)
6674
+ selected = matchPostPurchaseVariantDefault(product, attributes, policy.hideOutOfStockVariants);
6675
+ selected ?? (selected = product.variants[0]);
6676
+ if (!selected || selected === product.variants[0])
6677
+ selected = product.variants.find(postPurchaseVariantAvailable) ?? selected;
6678
+ return selected?.id ?? null;
6679
+ };
6680
+
6681
+ // src/server/resolvePostPurchaseMemberDefault.ts
6682
+ var resolvePostPurchaseMemberDefault = (product, original, context) => {
6683
+ const originals = PostPurchaseVariantDefaultContext.parse(context);
6684
+ if (product.variants.length < 2 && product.selectedVariant === void 0) return product.variants[0]?.id ?? null;
6685
+ const source2 = PostPurchaseVariantDefaultProduct.parse(product);
6686
+ const settings = PostPurchaseVariantDefaultSettings.parse(original.productOptions);
6687
+ const attributes = settings.matchVariant && !source2.selectedVariant && source2.options.some(({ values: values2 }) => values2.length > 0) && originals.originalVariants.length > 0 && originals.enrichedLineItems != null ? createPostPurchaseOrderAttributes(
6688
+ originals.originalVariants,
6689
+ PostPurchaseAttributeProducts.parse(deepCamelCase(originals.enrichedLineItems))
6690
+ ) : void 0;
6691
+ return resolvePostPurchaseVariantDefault(source2, settings, attributes);
6692
+ };
6693
+
6694
+ // src/server/preparePostPurchaseMemberView.ts
6695
+ var prepareMember = (widgetId, settings, response, requested, report, excludedProductIds, requestedQuantity, defaults) => {
6696
+ const selected = PostPurchaseCollectionChoice.parse(requested);
6697
+ const { members, normalized } = normalizePostPurchaseCollection(settings, response, excludedProductIds);
6698
+ const found = members.find(({ product: product2 }) => product2.id === selected.productId);
6699
+ if (!found) return null;
6700
+ const variantId = selected.variantId ?? (defaults && resolvePostPurchaseMemberDefault(found.product, normalized.original, defaults));
6701
+ const product = variantId === void 0 ? found.product : {
6702
+ ...found.product,
6703
+ variants: found.product.variants.filter(({ id }) => id === variantId)
6704
+ };
6705
+ const selectedInput = { ...normalized, data: [product] };
6706
+ const quantity2 = requestedQuantity ? readPostPurchaseQuantity(selectedInput, requestedQuantity) : void 0;
6707
+ const view = prepareNormalizedPostPurchaseView(widgetId, selectedInput, report, selected.choice, quantity2, true);
6708
+ if (selected.variantId !== void 0 || found.product.variants.length > 1)
6709
+ view.variantCatalog = projectPostPurchaseVariantCatalog(found.product, normalized.effective);
6710
+ if (defaults && selected.variantId === void 0 && variantId && view.variantCatalog?.variants.some(({ id }) => id === variantId))
6711
+ view.initialVariant = { variantId };
6712
+ return { member: { productId: found.product.id, productIndex: found.productIndex, view }, normalized, quantity: quantity2 };
6713
+ };
6714
+ var preparePostPurchaseMemberView = (widgetId, settings, response, requested, report, excludedProductIds) => prepareMember(widgetId, settings, response, requested, report, excludedProductIds)?.member ?? null;
6715
+ var preparePostPurchaseMemberAdmissionView = (widgetId, settings, response, requested, report, excludedProductIds) => {
6716
+ const prepared = prepareMember(widgetId, settings, response, requested, report, excludedProductIds);
6717
+ if (!prepared) return null;
6718
+ const { removePartialOrder } = PostPurchaseSettings.shape.advance.parse(prepared.normalized.effective.advance);
6719
+ return { ...prepared.member, removePartialOrder };
6720
+ };
6721
+
6722
+ // src/server/preparePostPurchaseQuantityView.ts
6723
+ var preparePostPurchaseQuantityView = (widgetId, settings, response, requested, report, excludedProductIds, defaults) => {
6724
+ const { quantity: quantity2, ...selection3 } = PostPurchaseQuantityChoice.parse(requested);
6725
+ const prepared = prepareMember(
6726
+ widgetId,
6727
+ settings,
6728
+ response,
6729
+ selection3,
6730
+ report,
6731
+ excludedProductIds,
6732
+ { quantity: quantity2 },
6733
+ defaults
6734
+ );
6735
+ return prepared ? { ...prepared.member, quantityPolicy: prepared.quantity.policy } : null;
6736
+ };
6737
+
6738
+ // src/server/preparePostPurchaseQuantityAdmissionView.ts
6739
+ var selection = PostPurchaseQuantityChoice.required({ quantity: true });
6740
+ var preparePostPurchaseQuantityAdmissionView = (widgetId, settings, response, expected, report, excludedProductIds, defaults) => {
6741
+ const { quantity: expectedQuantity, ...requested } = selection.parse(expected);
6742
+ const prepared = prepareMember(
6743
+ widgetId,
6744
+ settings,
6745
+ response,
6746
+ requested,
6747
+ report,
6748
+ excludedProductIds,
6749
+ { expectedQuantity },
6750
+ defaults
6751
+ );
6752
+ if (!prepared) return null;
6753
+ const { removePartialOrder } = PostPurchaseSettings.shape.advance.parse(prepared.normalized.effective.advance);
6754
+ return { ...prepared.member, quantityPolicy: prepared.quantity.policy, removePartialOrder };
6755
+ };
6756
+
6757
+ // src/schema/postPurchaseGroup.ts
6758
+ var PostPurchaseGroupChoice = PostPurchaseQuantityChoice.extend({
6759
+ memberProductId: PreparedPostPurchaseProduct.shape.selection.shape.productId
6311
6760
  });
6312
6761
 
6313
6762
  // src/server/readPostPurchaseGroup.ts
@@ -6340,6 +6789,195 @@ var readPostPurchaseGroup = (product, settings, excludedProductIds) => {
6340
6789
  };
6341
6790
  };
6342
6791
 
6792
+ // src/server/readPostPurchaseGroupSelection.ts
6793
+ var readPostPurchaseGroupSelection = (settings, response, requested, excludedProductIds) => {
6794
+ const selection3 = PostPurchaseGroupSelection.parse(requested);
6795
+ const { members, normalized } = normalizePostPurchaseCollection(settings, response);
6796
+ const member = members.find(({ product }) => product.id === selection3.memberProductId);
6797
+ if (!member || !member.product.productGroupVariants.length) return null;
6798
+ const group = readPostPurchaseGroup(member.product, normalized.effective, excludedProductIds);
6799
+ const entry = group.entries.find(({ product }) => product.id === selection3.productId);
6800
+ if (!entry) return null;
6801
+ return {
6802
+ groupCatalog: group.catalog,
6803
+ memberProductId: member.product.id,
6804
+ productIndex: member.productIndex,
6805
+ reportingProduct: { id: member.product.id, title: member.product.title },
6806
+ response: { data: [entry.product], metadata: normalized.metadata },
6807
+ variantCatalog: entry.variantCatalog
6808
+ };
6809
+ };
6810
+
6811
+ // src/server/preparePostPurchaseGroupView.ts
6812
+ var preparePostPurchaseGroupView = (widgetId, settings, response, requested, report, excludedProductIds) => {
6813
+ const { memberProductId, ...selection3 } = PostPurchaseGroupChoice.parse(requested);
6814
+ const group = readPostPurchaseGroupSelection(settings, response, requested, excludedProductIds);
6815
+ if (!group) return null;
6816
+ const variantId = selection3.variantId ?? group.variantCatalog.variants.find(({ available }) => available)?.id;
6817
+ if (variantId === void 0) return null;
6818
+ const prepared = preparePostPurchaseQuantityView(
6819
+ widgetId,
6820
+ settings,
6821
+ group.response,
6822
+ { ...selection3, variantId },
6823
+ report
6824
+ );
6825
+ return prepared && {
6826
+ ...prepared,
6827
+ groupCatalog: group.groupCatalog,
6828
+ memberProductId,
6829
+ productIndex: group.productIndex,
6830
+ reportingProduct: group.reportingProduct
6831
+ };
6832
+ };
6833
+
6834
+ // src/server/preparePostPurchaseGroupAdmissionView.ts
6835
+ var preparePostPurchaseGroupAdmissionView = (widgetId, settings, response, requested, report, excludedProductIds) => {
6836
+ const { memberProductId, ...selection3 } = PostPurchaseGroupChoice.required({ quantity: true }).parse(requested);
6837
+ const group = readPostPurchaseGroupSelection(settings, response, requested, excludedProductIds);
6838
+ if (!group) return null;
6839
+ const variantId = selection3.variantId ?? group.variantCatalog.variants.find(({ available }) => available)?.id;
6840
+ if (variantId === void 0) return null;
6841
+ const prepared = preparePostPurchaseQuantityAdmissionView(
6842
+ widgetId,
6843
+ settings,
6844
+ group.response,
6845
+ { ...selection3, variantId },
6846
+ report
6847
+ );
6848
+ return prepared && {
6849
+ ...prepared,
6850
+ groupCatalog: group.groupCatalog,
6851
+ memberProductId,
6852
+ productIndex: group.productIndex,
6853
+ reportingProduct: group.reportingProduct
6854
+ };
6855
+ };
6856
+
6857
+ // src/server/preparePostPurchaseGroupDefault.ts
6858
+ var preparePostPurchaseGroupDefault = (widgetId, settings, response, memberProductId, context, report, excludedProductIds) => {
6859
+ const { members, normalized } = normalizePostPurchaseCollection(settings, response);
6860
+ const member = members.find(({ product }) => product.id === memberProductId);
6861
+ if (!member || !member.product.productGroupVariants.length) return null;
6862
+ const group = readPostPurchaseGroup(member.product, normalized.effective, excludedProductIds);
6863
+ const ids = new Set(group.entries.map(({ product }) => product.id));
6864
+ const variants = member.product.variants.filter(({ productId: productId2 }) => ids.has(productId2));
6865
+ const selected = PostPurchaseVariantDefaultProduct.shape.selectedVariant.parse(member.product.selectedVariant);
6866
+ const selectedOwner = selected && member.product.variants.find(({ id }) => id === selected.id);
6867
+ const variantId = resolvePostPurchaseMemberDefault(
6868
+ {
6869
+ ...member.product,
6870
+ selectedVariant: selectedOwner && !ids.has(selectedOwner.productId) ? void 0 : member.product.selectedVariant,
6871
+ variants
6872
+ },
6873
+ normalized.original,
6874
+ context
6875
+ );
6876
+ const entry = group.entries.find(({ product }) => product.variants.some(({ id }) => id === variantId));
6877
+ if (!entry || variantId === null) return null;
6878
+ const prepared = preparePostPurchaseGroupView(
6879
+ widgetId,
6880
+ settings,
6881
+ response,
6882
+ { memberProductId, productId: entry.product.id, variantId },
6883
+ report,
6884
+ excludedProductIds
6885
+ );
6886
+ return prepared && { ...prepared, view: { ...prepared.view, initialVariant: { variantId } } };
6887
+ };
6888
+
6889
+ // src/server/preparePostPurchaseCollectionGroup.ts
6890
+ var preparePostPurchaseCollectionGroup = (widgetId, settings, response, member, normalized, excluded, defaults, report) => {
6891
+ const group = readPostPurchaseGroup(member.product, normalized.effective, excluded);
6892
+ if (!group.entries.length) return null;
6893
+ const prepared = preparePostPurchaseGroupDefault(
6894
+ widgetId,
6895
+ settings,
6896
+ response,
6897
+ member.product.id,
6898
+ defaults,
6899
+ report,
6900
+ excluded
6901
+ );
6902
+ return {
6903
+ productId: member.product.id,
6904
+ productIndex: member.productIndex,
6905
+ reportingProduct: { id: member.product.id, title: member.product.title },
6906
+ view: prepared ? { ...prepared.view, groupCatalog: prepared.groupCatalog } : {
6907
+ groupCatalog: group.catalog,
6908
+ preparation: { reason: "Post-purchase group default is unavailable", status: "unsupported" },
6909
+ sections: null
6910
+ }
6911
+ };
6912
+ };
6913
+
6914
+ // src/server/preparePostPurchaseCollectionView.ts
6915
+ var CollectionChoice = PostPurchaseCollectionChoice.omit({ variantId: true });
6916
+ var preparePostPurchaseCollectionView = (widgetId, settings, response, report, requested, excludedProductIds, defaults = { originalVariants: [] }) => {
6917
+ const { members, normalized } = normalizePostPurchaseCollection(settings, response);
6918
+ const excluded = PostPurchaseExcludedProductIds.parse(excludedProductIds);
6919
+ const selected = CollectionChoice.optional().parse(requested);
6920
+ const projected = members.map((member) => {
6921
+ if (member.product.productGroupVariants.length) {
6922
+ if (selected?.productId === member.product.id && selected.choice)
6923
+ throw new Error("Grouped choices require selected merchandise");
6924
+ const group = preparePostPurchaseCollectionGroup(
6925
+ widgetId,
6926
+ settings,
6927
+ response,
6928
+ member,
6929
+ normalized,
6930
+ excluded,
6931
+ defaults,
6932
+ report
6933
+ );
6934
+ return group;
6935
+ }
6936
+ if (excluded.includes(member.product.id)) return null;
6937
+ return {
6938
+ productId: member.product.id,
6939
+ productIndex: member.productIndex,
6940
+ reportingProduct: void 0,
6941
+ view: prepareNormalizedPostPurchaseView(
6942
+ widgetId,
6943
+ { ...normalized, data: [member.product] },
6944
+ report,
6945
+ member.product.id === selected?.productId ? selected.choice : void 0,
6946
+ void 0,
6947
+ true
6948
+ )
6949
+ };
6950
+ }).filter((member) => member !== null);
6951
+ if (selected && !projected.some(({ productId: productId2 }) => productId2 === selected.productId))
6952
+ throw new Error("Requested product is outside the prepared collection");
6953
+ const collection = PostPurchaseProductCollectionView.parse({ members: projected });
6954
+ return {
6955
+ members: collection.members.map((member, index) => ({
6956
+ ...member,
6957
+ ...projected[index].reportingProduct && { reportingProduct: projected[index].reportingProduct }
6958
+ }))
6959
+ };
6960
+ };
6961
+
6962
+ // src/schema/postPurchaseOfferEligibility.ts
6963
+ var import_zod67 = require("zod");
6964
+ var selection2 = PreparedPostPurchaseProduct.shape.selection;
6965
+ var PostPurchaseOfferSkipReason = import_zod67.z.enum(["empty", "no-eligible-subscription"]);
6966
+ var PostPurchaseOfferEligibilityContext = import_zod67.z.object({
6967
+ excludedProductIds: PostPurchaseExcludedProductIds,
6968
+ originalLineItems: import_zod67.z.array(selection2.pick({ productId: true, sellingPlanId: true, variantId: true }))
6969
+ });
6970
+ var PostPurchaseOfferEligibility = import_zod67.z.discriminatedUnion("status", [
6971
+ import_zod67.z.object({
6972
+ members: import_zod67.z.array(
6973
+ import_zod67.z.object({ productId: selection2.shape.productId, productIndex: import_zod67.z.number().int().nonnegative() })
6974
+ ),
6975
+ status: import_zod67.z.literal("retain")
6976
+ }),
6977
+ import_zod67.z.object({ reason: PostPurchaseOfferSkipReason, status: import_zod67.z.literal("skip") }),
6978
+ import_zod67.z.object({ reason: import_zod67.z.literal("eligible-upgrade").optional(), status: import_zod67.z.literal("unavailable") })
6979
+ ]);
6980
+
6343
6981
  // src/server/postPurchaseMemberEligibility.ts
6344
6982
  var PostPurchaseInventoryUnavailable = class extends Error {
6345
6983
  };
@@ -6415,74 +7053,6 @@ var classifyPostPurchaseOffer = (settings, response, context) => {
6415
7053
  }
6416
7054
  };
6417
7055
 
6418
- // src/schema/postPurchaseVariantDefault.ts
6419
- var import_zod61 = require("zod");
6420
- var values = PostPurchaseVariantValues.partial().extend({
6421
- option1: PostPurchaseVariantValues.shape.option1.nullish()
6422
- });
6423
- var variant = values.extend({
6424
- id: PostPurchaseVariantId,
6425
- inventoryManagement: import_zod61.z.string().nullable(),
6426
- inventoryPolicy: import_zod61.z.string(),
6427
- inventoryQuantity: import_zod61.z.number()
6428
- });
6429
- var options = import_zod61.z.array(PostPurchaseVariantOption.pick({ name: true, values: true }));
6430
- var PostPurchaseVariantDefaultProduct = import_zod61.z.object({
6431
- id: PostPurchaseProductId,
6432
- options,
6433
- selectedVariant: variant.optional(),
6434
- variants: import_zod61.z.array(variant)
6435
- });
6436
- var PostPurchaseVariantDefaultSettings = PostPurchaseSettings.shape.productOptions.pick({
6437
- hideOutOfStockVariants: true,
6438
- matchVariant: true
6439
- });
6440
- var PostPurchaseOrderAttributes = import_zod61.z.record(import_zod61.z.string(), import_zod61.z.array(import_zod61.z.string())).default({});
6441
- var PostPurchaseOriginalVariants = import_zod61.z.array(
6442
- import_zod61.z.object({ productId: PostPurchaseProductId, variantId: PostPurchaseVariantId })
6443
- );
6444
- var PostPurchaseAttributeProducts = import_zod61.z.array(
6445
- import_zod61.z.object({ id: PostPurchaseProductId, options, variants: import_zod61.z.array(values.extend({ id: PostPurchaseVariantId })) })
6446
- );
6447
-
6448
- // src/server/createPostPurchaseOrderAttributes.ts
6449
- var createPostPurchaseOrderAttributes = (original, enriched) => {
6450
- const products = PostPurchaseAttributeProducts.parse(enriched);
6451
- const attributes = {};
6452
- for (const item of PostPurchaseOriginalVariants.parse(original)) {
6453
- const product = products.find(({ id }) => id === item.productId);
6454
- const variant2 = product?.variants.find(({ id }) => id === item.variantId);
6455
- if (!variant2 || !product) continue;
6456
- ["option1", "option2", "option3"].forEach((key, index) => {
6457
- const value = variant2[key];
6458
- const option = product.options[index];
6459
- if (!value || !option) return;
6460
- const values2 = attributes[option.name] ?? [];
6461
- if (!values2.includes(value)) attributes[option.name] = [...values2, value];
6462
- });
6463
- }
6464
- return attributes;
6465
- };
6466
-
6467
- // src/server/readPostPurchaseGroupSelection.ts
6468
- var readPostPurchaseGroupSelection = (settings, response, requested, excludedProductIds) => {
6469
- const selection2 = PostPurchaseGroupSelection.parse(requested);
6470
- const { members, normalized } = normalizePostPurchaseCollection(settings, response);
6471
- const member = members.find(({ product }) => product.id === selection2.memberProductId);
6472
- if (!member || !member.product.productGroupVariants.length) return null;
6473
- const group = readPostPurchaseGroup(member.product, normalized.effective, excludedProductIds);
6474
- const entry = group.entries.find(({ product }) => product.id === selection2.productId);
6475
- if (!entry) return null;
6476
- return {
6477
- groupCatalog: group.catalog,
6478
- memberProductId: member.product.id,
6479
- productIndex: member.productIndex,
6480
- reportingProduct: { id: member.product.id, title: member.product.title },
6481
- response: { data: [entry.product], metadata: normalized.metadata },
6482
- variantCatalog: entry.variantCatalog
6483
- };
6484
- };
6485
-
6486
7056
  // src/server/preparePostPurchaseGroupDeclineDisplay.ts
6487
7057
  var preparePostPurchaseGroupDeclineDisplay = (settings, response, requested, excludedProductIds) => {
6488
7058
  const group = readPostPurchaseGroupSelection(settings, response, requested, excludedProductIds);
@@ -6499,47 +7069,21 @@ var preparePostPurchaseGroupDeclineDisplay = (settings, response, requested, exc
6499
7069
 
6500
7070
  // src/server/preparePostPurchaseOfferPresentation.ts
6501
7071
  var import_compat7 = require("es-toolkit/compat");
6502
- var import_zod64 = require("zod");
7072
+ var import_zod69 = require("zod");
6503
7073
 
6504
7074
  // src/schema/postPurchaseOfferPresentation.ts
6505
- var import_zod62 = require("zod");
7075
+ var import_zod68 = require("zod");
6506
7076
  var language2 = PostPurchaseSettings.shape.language.shape.global.unwrap().unwrap();
6507
- var PostPurchaseOfferPresentation = import_zod62.z.strictObject({
7077
+ var PostPurchaseOfferPresentation = import_zod68.z.strictObject({
6508
7078
  labels: language2.pick({ declineAll: true, declineThisOffer: true }),
6509
7079
  layout: PostPurchaseSettings.shape.offersLayout,
6510
7080
  sections: CABRootSection.nullable(),
6511
7081
  showDeclineAll: PostPurchaseSettings.shape.productOptions.shape.showDeclineAll
6512
7082
  });
6513
7083
 
6514
- // src/server/postPurchaseOfferCopy.ts
6515
- var import_zod63 = require("zod");
6516
- var Copy = import_zod63.z.object({
6517
- superTitle: CalloutBannerBlock.shape.settings.shape.superTitle.unwrap().optional().catch(void 0),
6518
- title: CalloutBannerBlock.shape.settings.shape.title.unwrap().optional().catch(void 0)
6519
- });
6520
- var Callout = import_zod63.z.object({ settings: import_zod63.z.record(import_zod63.z.string(), import_zod63.z.unknown()), type: import_zod63.z.literal("callout_banner") });
6521
- var postPurchaseOfferCopy = (blocks, metadata) => {
6522
- const copy = Copy.safeParse(metadata.widget.language);
6523
- if (!blocks || !copy.success) return blocks;
6524
- const first = blocks.findIndex((block) => Callout.pick({ type: true }).safeParse(block).success);
6525
- return blocks.map((block, index) => {
6526
- if (index !== first) return block;
6527
- const callout = Callout.passthrough().safeParse(block);
6528
- if (!callout.success) return block;
6529
- return {
6530
- ...callout.data,
6531
- settings: {
6532
- ...callout.data.settings,
6533
- ...copy.data.title && { title: copy.data.title },
6534
- ...copy.data.superTitle && { superTitle: copy.data.superTitle }
6535
- }
6536
- };
6537
- });
6538
- };
6539
-
6540
7084
  // src/server/preparePostPurchaseOfferPresentation.ts
6541
7085
  var FrameSettings = PostPurchaseSettings.pick({ language: true, offersLayout: true, productOptions: true }).extend({
6542
- blocks: import_zod64.z.array(import_zod64.z.unknown()).optional()
7086
+ blocks: import_zod69.z.array(import_zod69.z.unknown()).optional()
6543
7087
  });
6544
7088
  var preparePostPurchaseOfferPresentation = (widgetId, settings, response, report) => {
6545
7089
  const { metadata } = PostPurchaseProductSource.pick({ metadata: true }).parse(deepCamelCase(response));
@@ -6563,42 +7107,6 @@ var preparePostPurchaseOfferPresentation = (widgetId, settings, response, report
6563
7107
  });
6564
7108
  };
6565
7109
 
6566
- // src/schema/postPurchaseQuantity.ts
6567
- var import_zod65 = require("zod");
6568
- var quantity = PreparedPostPurchaseProduct.shape.selection.shape.quantity;
6569
- var PostPurchaseQuantityPolicy = PostPurchaseSettings.shape.quantityInputs.omit({ defaultQuantity: true }).extend({
6570
- initialQuantity: quantity,
6571
- maxValue: quantity,
6572
- minValue: import_zod65.z.literal(0).transform(() => 1).or(quantity)
6573
- }).refine(({ maxValue, minValue }) => minValue <= maxValue, "Quantity bounds are reversed");
6574
-
6575
- // src/server/readPostPurchaseQuantity.ts
6576
- var PostPurchaseQuantityUnavailable = class extends Error {
6577
- };
6578
- var readPostPurchaseQuantity = ({
6579
- data,
6580
- effective,
6581
- original
6582
- }, selection2) => {
6583
- const positive = PreparedPostPurchaseProduct.shape.selection.shape.quantity;
6584
- for (const config of [original, effective]) {
6585
- if (!config.quantityInputs.enabled) continue;
6586
- const initialQuantity2 = positive.parse(config.quantityInputs.defaultQuantity);
6587
- const policy2 = PostPurchaseQuantityPolicy.parse({ ...config.quantityInputs, initialQuantity: initialQuantity2 });
6588
- if (initialQuantity2 < policy2.minValue || initialQuantity2 > policy2.maxValue)
6589
- throw new Error("Configured quantity default is outside its bounds");
6590
- }
6591
- const initialQuantity = data[0]?.metadata?.productQuantity ?? (original.quantityInputs.enabled ? original.quantityInputs.defaultQuantity : 1);
6592
- const policy = PostPurchaseQuantityPolicy.parse(
6593
- effective.quantityInputs.enabled ? { ...effective.quantityInputs, initialQuantity } : { enabled: false, initialQuantity, maxValue: initialQuantity, minValue: initialQuantity }
6594
- );
6595
- const requested = "quantity" in selection2 ? selection2.quantity : selection2.expectedQuantity === initialQuantity ? void 0 : selection2.expectedQuantity;
6596
- const quantity2 = positive.parse(requested ?? initialQuantity);
6597
- if (requested !== void 0 && (policy.enabled ? quantity2 < policy.minValue || quantity2 > policy.maxValue : quantity2 !== initialQuantity))
6598
- throw new PostPurchaseQuantityUnavailable("Requested quantity is unavailable");
6599
- return { policy, quantity: quantity2 };
6600
- };
6601
-
6602
7110
  // src/server/analytics.ts
6603
7111
  var import_es_toolkit7 = require("es-toolkit");
6604
7112
 
@@ -6735,7 +7243,7 @@ var postAnalyticsEvents = async (input, ctx) => {
6735
7243
  };
6736
7244
 
6737
7245
  // src/server/requestSchemas.ts
6738
- var import_zod66 = require("zod");
7246
+ var import_zod70 = require("zod");
6739
7247
  var REQUEST_BOUNDS = {
6740
7248
  /** Cart-level attributes per cart. */
6741
7249
  CART_ATTRIBUTES_MAX: 100,
@@ -6766,42 +7274,42 @@ var REQUEST_BOUNDS = {
6766
7274
  /** Rich ads transaction lines — the engine's ads contract. */
6767
7275
  TRANSACTION_ITEMS_MAX: 50
6768
7276
  };
6769
- var KeyValue = import_zod66.z.object({
6770
- key: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
6771
- value: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_VALUE_MAX).optional()
7277
+ var KeyValue = import_zod70.z.object({
7278
+ key: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
7279
+ value: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_VALUE_MAX).optional()
6772
7280
  });
6773
- var CartLineInputSchema = import_zod66.z.object({
6774
- productId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6775
- properties: import_zod66.z.array(KeyValue).max(REQUEST_BOUNDS.LINE_PROPERTIES_MAX).optional(),
6776
- quantity: import_zod66.z.number(),
6777
- subscriptionId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6778
- variantId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX)
7281
+ var CartLineInputSchema = import_zod70.z.object({
7282
+ productId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7283
+ properties: import_zod70.z.array(KeyValue).max(REQUEST_BOUNDS.LINE_PROPERTIES_MAX).optional(),
7284
+ quantity: import_zod70.z.number(),
7285
+ subscriptionId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7286
+ variantId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX)
6779
7287
  });
6780
- var CartInputSchema = import_zod66.z.object({
6781
- attributes: import_zod66.z.array(KeyValue).max(REQUEST_BOUNDS.CART_ATTRIBUTES_MAX).optional(),
7288
+ var CartInputSchema = import_zod70.z.object({
7289
+ attributes: import_zod70.z.array(KeyValue).max(REQUEST_BOUNDS.CART_ATTRIBUTES_MAX).optional(),
6782
7290
  /**
6783
7291
  * Presentment-per-shop-currency FX rate (buyer price ÷ shop price, e.g. `1.35` for a USD shop
6784
7292
  * selling in CAD). Money rule thresholds are authored in SHOP currency, so the engine subtotal is
6785
7293
  * divided by this before evaluation. Omit (or send 1) when the cart is already in the shop's currency.
6786
7294
  */
6787
- currencyRate: import_zod66.z.number().optional(),
7295
+ currencyRate: import_zod70.z.number().optional(),
6788
7296
  /** Applied discount codes; the engine evaluates `discount_code` rules against them (sent as `[{code}]`). */
6789
- discountCodes: import_zod66.z.array(import_zod66.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX)).max(REQUEST_BOUNDS.DISCOUNT_CODES_MAX).optional(),
7297
+ discountCodes: import_zod70.z.array(import_zod70.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX)).max(REQUEST_BOUNDS.DISCOUNT_CODES_MAX).optional(),
6790
7298
  /** Presentment cents of cart-level discount allocations, subtracted from `subtotal` for the engine. */
6791
- discountTotal: import_zod66.z.number().optional(),
6792
- items: import_zod66.z.array(CartLineInputSchema).max(REQUEST_BOUNDS.CART_ITEMS_MAX),
7299
+ discountTotal: import_zod70.z.number().optional(),
7300
+ items: import_zod70.z.array(CartLineInputSchema).max(REQUEST_BOUNDS.CART_ITEMS_MAX),
6793
7301
  /** Presentment subtotal in cents. */
6794
- subtotal: import_zod66.z.number()
7302
+ subtotal: import_zod70.z.number()
6795
7303
  });
6796
- var UserConfigInputSchema = import_zod66.z.object({ shop: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX) });
6797
- var DataSourceInputSchema = import_zod66.z.object({
7304
+ var UserConfigInputSchema = import_zod70.z.object({ shop: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX) });
7305
+ var DataSourceInputSchema = import_zod70.z.object({
6798
7306
  cart: CartInputSchema,
6799
7307
  /**
6800
7308
  * Numeric Shopify company-location id when the buyer is a B2B session (`buyerIdentity.purchasingCompany`).
6801
7309
  * Present ⇒ the orchestrator filters results by the location's catalog via admin-api (REB-23713); the
6802
7310
  * client's country-context market check is bypassed for B2B (it false-negatives B2B-catalog products).
6803
7311
  */
6804
- companyLocationId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7312
+ companyLocationId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6805
7313
  /**
6806
7314
  * Buyer's market country (ISO 3166-1 alpha-2) — forwarded to the engine as the `country_code` PARAM
6807
7315
  * when the shop's markets toggle is on (REB-21688; the sink was the `X-Country-Code` header under
@@ -6810,16 +7318,16 @@ var DataSourceInputSchema = import_zod66.z.object({
6810
7318
  * uppercase (the wire value is forwarded verbatim as the param) so a case-sensitive engine lookup
6811
7319
  * can't silently miss a lowercase code — `adsEngine.ts` uppercases for the same reason.
6812
7320
  */
6813
- country: import_zod66.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(),
6814
- customerId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6815
- dataSourcePath: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
7321
+ country: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).regex(/^[A-Za-z]{2}$/, "must be an ISO 3166-1 alpha-2 country code (e.g. CA)").transform((value) => value.toUpperCase()).optional(),
7322
+ customerId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7323
+ dataSourcePath: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
6816
7324
  /**
6817
7325
  * Engine `filter_inputs` override: `'no'` keeps in-cart (input) products in the results/rule
6818
7326
  * outputs — gift validation sends it so a gift's own product can appear in its answer. Omitted = the
6819
7327
  * engine's default filtering.
6820
7328
  */
6821
- filterInputs: import_zod66.z.enum(["no", "yes"]).optional(),
6822
- integrations: import_zod66.z.record(import_zod66.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), import_zod66.z.boolean()).refine((record) => Object.keys(record).length <= REQUEST_BOUNDS.INTEGRATION_KEYS_MAX, {
7329
+ filterInputs: import_zod70.z.enum(["no", "yes"]).optional(),
7330
+ integrations: import_zod70.z.record(import_zod70.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), import_zod70.z.boolean()).refine((record) => Object.keys(record).length <= REQUEST_BOUNDS.INTEGRATION_KEYS_MAX, {
6823
7331
  message: `Too many integration keys (max ${REQUEST_BOUNDS.INTEGRATION_KEYS_MAX})`
6824
7332
  }).optional(),
6825
7333
  /**
@@ -6832,31 +7340,31 @@ var DataSourceInputSchema = import_zod66.z.object({
6832
7340
  * request header) fails the regex. Callers should send the buyer's resolved locale (e.g. Shopify
6833
7341
  * checkout's `localization.language.isoCode`), not the request header verbatim.
6834
7342
  */
6835
- language: import_zod66.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(),
6836
- limit: import_zod66.z.number().max(REQUEST_BOUNDS.LIMIT_MAX),
6837
- productType: import_zod66.z.enum(["both", "one-time", "subscription"]).optional(),
6838
- shop: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6839
- visitorId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
6840
- });
6841
- var GiftInputSchema = import_zod66.z.object({
6842
- cost: import_zod66.z.number(),
6843
- discounted: import_zod66.z.boolean(),
7343
+ language: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).regex(/^[A-Za-z0-9-]+$/, "must be a single BCP-47 tag (e.g. fr-CA), not a q-value list").optional(),
7344
+ limit: import_zod70.z.number().max(REQUEST_BOUNDS.LIMIT_MAX),
7345
+ productType: import_zod70.z.enum(["both", "one-time", "subscription"]).optional(),
7346
+ shop: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7347
+ visitorId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
7348
+ });
7349
+ var GiftInputSchema = import_zod70.z.object({
7350
+ cost: import_zod70.z.number(),
7351
+ discounted: import_zod70.z.boolean(),
6844
7352
  /**
6845
7353
  * Which gift attribution the line carries (REB-24363). Defaults to `gwp` because a client that predates
6846
7354
  * the field only ever sent GWP lines — without the default an older extension's request would 422.
6847
7355
  */
6848
- kind: import_zod66.z.enum(GIFT_KINDS).default("gwp"),
6849
- lineId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6850
- productId: import_zod66.z.number(),
7356
+ kind: import_zod70.z.enum(GIFT_KINDS).default("gwp"),
7357
+ lineId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7358
+ productId: import_zod70.z.number(),
6851
7359
  /**
6852
7360
  * The line's unit count (REB-24363) — the selectable-GWP verdict trims surplus units against milestone
6853
7361
  * capacity. The second deliberate default: a client predating the field sent only GWP lines, whose
6854
7362
  * verdict is whole-line, so a missing quantity reads as one unit rather than 422ing the older request.
6855
7363
  */
6856
- quantity: import_zod66.z.number().int().min(1).default(1),
6857
- widgetId: import_zod66.z.number()
7364
+ quantity: import_zod70.z.number().int().min(1).default(1),
7365
+ widgetId: import_zod70.z.number()
6858
7366
  });
6859
- var GiftValidationInputSchema = import_zod66.z.object({
7367
+ var GiftValidationInputSchema = import_zod70.z.object({
6860
7368
  cart: CartInputSchema,
6861
7369
  /**
6862
7370
  * Buyer's market country — threaded into the per-widget data-source evaluations, which forward it to
@@ -6865,25 +7373,25 @@ var GiftValidationInputSchema = import_zod66.z.object({
6865
7373
  * turns markets off); regex-bound and uppercase-normalized for the same reasons as
6866
7374
  * `DataSourceInputSchema`'s `country`.
6867
7375
  */
6868
- country: import_zod66.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(),
6869
- customerId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6870
- gifts: import_zod66.z.array(GiftInputSchema).max(REQUEST_BOUNDS.GIFTS_MAX),
7376
+ country: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).regex(/^[A-Za-z]{2}$/, "must be an ISO 3166-1 alpha-2 country code (e.g. CA)").transform((value) => value.toUpperCase()).optional(),
7377
+ customerId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7378
+ gifts: import_zod70.z.array(GiftInputSchema).max(REQUEST_BOUNDS.GIFTS_MAX),
6871
7379
  /**
6872
7380
  * Buyer's checkout language — threaded into the per-widget data-source evaluations, which normalize
6873
7381
  * and forward it as the engine `locale` param under the same markets-toggle gate (REB-21688). MUST be
6874
7382
  * a single BCP-47 tag, for the same reason as `DataSourceInputSchema`'s `language` above.
6875
7383
  */
6876
- language: import_zod66.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(),
6877
- shop: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6878
- visitorId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
7384
+ language: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).regex(/^[A-Za-z0-9-]+$/, "must be a single BCP-47 tag (e.g. fr-CA), not a q-value list").optional(),
7385
+ shop: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7386
+ visitorId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
6879
7387
  });
6880
- var GiftAdjustmentSchema = import_zod66.z.object({
6881
- lineId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6882
- quantity: import_zod66.z.number().int().nonnegative()
7388
+ var GiftAdjustmentSchema = import_zod70.z.object({
7389
+ lineId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7390
+ quantity: import_zod70.z.number().int().nonnegative()
6883
7391
  });
6884
- var GiftValidationResponseSchema = import_zod66.z.object({
6885
- adjust: import_zod66.z.array(GiftAdjustmentSchema).max(REQUEST_BOUNDS.GIFTS_MAX).default([]),
6886
- remove: import_zod66.z.array(import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX)).max(REQUEST_BOUNDS.GIFTS_MAX).refine(
7392
+ var GiftValidationResponseSchema = import_zod70.z.object({
7393
+ adjust: import_zod70.z.array(GiftAdjustmentSchema).max(REQUEST_BOUNDS.GIFTS_MAX).default([]),
7394
+ remove: import_zod70.z.array(import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX)).max(REQUEST_BOUNDS.GIFTS_MAX).refine(
6887
7395
  (remove) => new Set(remove).size === remove.length,
6888
7396
  "a line id may appear at most once in `remove`"
6889
7397
  )
@@ -6894,47 +7402,47 @@ var GiftValidationResponseSchema = import_zod66.z.object({
6894
7402
  ({ adjust }) => new Set(adjust.map(({ lineId }) => lineId)).size === adjust.length,
6895
7403
  "a line id may appear at most once in `adjust`"
6896
7404
  );
6897
- var MonetizeTransactionItemSchema = import_zod66.z.object({
6898
- id: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6899
- priceCents: import_zod66.z.number(),
6900
- quantity: import_zod66.z.number(),
6901
- title: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX),
6902
- type: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX)
6903
- });
6904
- var MonetizeInputSchema = import_zod66.z.object({
7405
+ var MonetizeTransactionItemSchema = import_zod70.z.object({
7406
+ id: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7407
+ priceCents: import_zod70.z.number(),
7408
+ quantity: import_zod70.z.number(),
7409
+ title: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX),
7410
+ type: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX)
7411
+ });
7412
+ var MonetizeInputSchema = import_zod70.z.object({
6905
7413
  cart: CartInputSchema,
6906
7414
  /** Client-minted render-beacon correlation id; forwarded to the ads engine as `client_request_id`. */
6907
- clientRequestId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6908
- country: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6909
- currency: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7415
+ clientRequestId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7416
+ country: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7417
+ currency: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6910
7418
  /** Ads-targeting identity/geo/locale fields (React parity); folded into the engine query verbatim. */
6911
- customerEmail: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
6912
- customerFirstName: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
6913
- customerId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6914
- customerLastName: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
6915
- language: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7419
+ customerEmail: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
7420
+ customerFirstName: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
7421
+ customerId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7422
+ customerLastName: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
7423
+ language: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6916
7424
  /** Buyer-facing order name (e.g. `#1001`) for the server-composed "Order … Confirmed" chrome line. */
6917
- orderName: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
7425
+ orderName: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
6918
7426
  /** Ads surface label, forwarded verbatim; `customer_account` is measured/floored as its own surface (the account-area order list). */
6919
- placement: import_zod66.z.enum(["customer_account", "order_status", "thank_you_page"]),
7427
+ placement: import_zod70.z.enum(["customer_account", "order_status", "thank_you_page"]),
6920
7428
  /** Privacy Policy footer href — the Monetize widget's `privacy_policy_url` setting (React parity). */
6921
- privacyPolicyUrl: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_URL_MAX).optional(),
7429
+ privacyPolicyUrl: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_URL_MAX).optional(),
6922
7430
  /** 30-min rolling session id (React parity); used for the ads `session_id`, else the visitor id. */
6923
- sessionId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6924
- shop: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7431
+ sessionId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7432
+ shop: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6925
7433
  /** Editor/QA indicator; OR-ed into the ads-engine `testing` flag so it stays out of billing/reporting. */
6926
- testing: import_zod66.z.boolean().optional(),
6927
- timezone: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7434
+ testing: import_zod70.z.boolean().optional(),
7435
+ timezone: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6928
7436
  /** Decorated (numeric) order id → the ads `transaction_id`. */
6929
- transactionId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7437
+ transactionId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6930
7438
  /** Rich per-line ads items; capped at the engine's ads contract. Preferred over `cart.items`. */
6931
- transactionItems: import_zod66.z.array(MonetizeTransactionItemSchema).max(REQUEST_BOUNDS.TRANSACTION_ITEMS_MAX).optional(),
7439
+ transactionItems: import_zod70.z.array(MonetizeTransactionItemSchema).max(REQUEST_BOUNDS.TRANSACTION_ITEMS_MAX).optional(),
6932
7440
  /** Order total in presentment cents (React prefers total over subtotal); else `cart.subtotal`. */
6933
- transactionTotal: import_zod66.z.number().optional(),
6934
- visitorId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6935
- zipCode: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
7441
+ transactionTotal: import_zod70.z.number().optional(),
7442
+ visitorId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7443
+ zipCode: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
6936
7444
  });
6937
- var WidgetSettingsInputSchema = import_zod66.z.object({
7445
+ var WidgetSettingsInputSchema = import_zod70.z.object({
6938
7446
  /**
6939
7447
  * Same domain as `CabShopConfig.cacheKey`, for the same reason: this side WINS the orchestrator's
6940
7448
  * `input.cacheKey ?? config.shop.cacheKey` (and an explicit value skips the config read entirely), so
@@ -6942,9 +7450,9 @@ var WidgetSettingsInputSchema = import_zod66.z.object({
6942
7450
  * and pin the edge copy permanently stale. `.catch(undefined)` because a bogus buster should degrade
6943
7451
  * the read to un-busted, never 400 a widget render.
6944
7452
  */
6945
- cacheKey: import_zod66.z.number().int().positive().optional().catch(void 0),
6946
- id: import_zod66.z.number(),
6947
- key: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7453
+ cacheKey: import_zod70.z.number().int().positive().optional().catch(void 0),
7454
+ id: import_zod70.z.number(),
7455
+ key: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6948
7456
  /**
6949
7457
  * Monetize context for inline hydration: when present AND the widget converts to a Monetize marker,
6950
7458
  * the server fetches/composes the offer cards inside this same request (no second `/cab/monetize`
@@ -6953,34 +7461,34 @@ var WidgetSettingsInputSchema = import_zod66.z.object({
6953
7461
  * `privacyPolicyUrl` comes from the widget settings server-side (more authoritative than a relay).
6954
7462
  */
6955
7463
  monetize: MonetizeInputSchema.omit({ privacyPolicyUrl: true, shop: true }).optional(),
6956
- shop: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7464
+ shop: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6957
7465
  /** Stable per-buyer id; when present, enables sticky server-side A/B variant selection. */
6958
- visitorId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
7466
+ visitorId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
6959
7467
  });
6960
- var AnalyticsEventInputSchema = import_zod66.z.object({
6961
- name: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
6962
- properties: import_zod66.z.record(import_zod66.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), import_zod66.z.unknown()).optional(),
6963
- sentAt: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
7468
+ var AnalyticsEventInputSchema = import_zod70.z.object({
7469
+ name: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
7470
+ properties: import_zod70.z.record(import_zod70.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), import_zod70.z.unknown()).optional(),
7471
+ sentAt: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
6964
7472
  });
6965
- var AnalyticsSegmentsInputSchema = import_zod66.z.object({
6966
- device: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
6967
- source: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
6968
- visitor: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0)
7473
+ var AnalyticsSegmentsInputSchema = import_zod70.z.object({
7474
+ device: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
7475
+ source: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
7476
+ visitor: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0)
6969
7477
  });
6970
- var AnalyticsInputSchema = import_zod66.z.object({
7478
+ var AnalyticsInputSchema = import_zod70.z.object({
6971
7479
  /** Rebuy cart token (the `r_cart_token` cart attribute), when available — primary aggregation key. */
6972
- cartToken: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7480
+ cartToken: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6973
7481
  /** Shopify checkout token, when available — drives cart/checkout aggregation downstream. */
6974
- checkoutToken: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
6975
- events: import_zod66.z.array(AnalyticsEventInputSchema).max(REQUEST_BOUNDS.EVENTS_MAX),
7482
+ checkoutToken: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
7483
+ events: import_zod70.z.array(AnalyticsEventInputSchema).max(REQUEST_BOUNDS.EVENTS_MAX),
6976
7484
  /**
6977
7485
  * Request-scoped like the tokens: one visitor's segments apply to every event in the batch. The container
6978
7486
  * degrades too (`null` is a realistic wire artifact of `attributes ? {…} : null`), so the degrade rule is
6979
7487
  * total: nothing about `segments` can cost the envelope.
6980
7488
  */
6981
7489
  segments: AnalyticsSegmentsInputSchema.optional().catch(void 0),
6982
- shop: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6983
- visitorId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7490
+ shop: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
7491
+ visitorId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
6984
7492
  /** The widget id (smartBlockId) the events belong to. */
6985
- widgetId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
7493
+ widgetId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
6986
7494
  });