@rebuy/rebuy 3.43.0 → 3.44.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.
@@ -48,6 +48,7 @@ __export(server_exports, {
48
48
  fetchUserConfig: () => fetchUserConfig,
49
49
  postAnalyticsEvents: () => postAnalyticsEvents,
50
50
  preparePostPurchaseAdmissionView: () => preparePostPurchaseAdmissionView,
51
+ preparePostPurchaseCardSections: () => preparePostPurchaseCardSections,
51
52
  preparePostPurchaseCollectionView: () => preparePostPurchaseCollectionView,
52
53
  preparePostPurchaseDeclineDisplay: () => preparePostPurchaseDeclineDisplay,
53
54
  preparePostPurchaseGroupAdmissionView: () => preparePostPurchaseGroupAdmissionView,
@@ -6379,6 +6380,19 @@ var PostPurchaseSubscriptionSettings = subscription.extend({
6379
6380
  })
6380
6381
  });
6381
6382
 
6383
+ // src/server/postPurchaseUnavailableChoice.ts
6384
+ var VARIANT_UNAVAILABLE = "The chosen variant is unavailable";
6385
+ var PLAN_UNAVAILABLE = "Subscription plan is unavailable";
6386
+ var CHOICE_UNAVAILABLE = "Requested purchase choice is unavailable";
6387
+ var GROUP_DEFAULT_UNAVAILABLE = "Post-purchase group default is unavailable";
6388
+ var choiceLevel = /* @__PURE__ */ new Set([
6389
+ VARIANT_UNAVAILABLE,
6390
+ PLAN_UNAVAILABLE,
6391
+ CHOICE_UNAVAILABLE,
6392
+ GROUP_DEFAULT_UNAVAILABLE
6393
+ ]);
6394
+ var isChoiceUnavailable = (reason) => reason !== void 0 && choiceLevel.has(reason);
6395
+
6382
6396
  // src/server/postPurchaseVariantAvailable.ts
6383
6397
  var postPurchaseVariantAvailable = (variant2) => !(variant2.inventoryManagement && variant2.inventoryPolicy === "deny" && variant2.inventoryQuantity <= 0);
6384
6398
 
@@ -6393,12 +6407,13 @@ var subscriptionUnavailable = (normalized, plan, allowCollection, quantity3) =>
6393
6407
  return unavailable;
6394
6408
  const product = data[0];
6395
6409
  const variant2 = product.variants[0];
6396
- if (product.productGroupVariants.length || !postPurchaseVariantAvailable(variant2) || variant2.productId !== product.id)
6397
- return unavailable;
6410
+ if (product.productGroupVariants.length || variant2.productId !== product.id) return unavailable;
6398
6411
  const terms = [original, effective].map(
6399
6412
  (config) => PostPurchaseSubscriptionSettings.safeParse(config.subscription)
6400
6413
  );
6401
- if (!plan || terms.some((term) => !term.success)) return unavailable;
6414
+ if (terms.some((term) => !term.success)) return unavailable;
6415
+ if (!plan) return PLAN_UNAVAILABLE;
6416
+ if (!postPurchaseVariantAvailable(variant2)) return VARIANT_UNAVAILABLE;
6402
6417
  };
6403
6418
 
6404
6419
  // src/server/postPurchaseProductDisplay.ts
@@ -6537,13 +6552,24 @@ var readScalarReviews = (find, namespace, ratingKey, countKey) => {
6537
6552
  };
6538
6553
 
6539
6554
  // src/server/postPurchaseReviewData.ts
6555
+ var readStandardReviews = (find) => {
6556
+ const rating = find("reviews", "rating");
6557
+ const count = find("reviews", "rating_count");
6558
+ if (!rating || !count) return null;
6559
+ const value = import_zod63.z.string().parse(rating.value);
6560
+ return {
6561
+ rating: PostPurchaseCommonReviewRating.parse(/^\d+(?:\.\d+)?$/.test(value) ? { value } : JSON.parse(value)).value,
6562
+ reviewCount: PostPurchaseReviewCount.parse(count.value)
6563
+ };
6564
+ };
6540
6565
  var readPostPurchaseReviewData = (provider, find) => {
6541
6566
  if (provider === "yotpo") return readScalarReviews(find, "yotpo", "reviews_average", "reviews_count");
6542
6567
  if (provider === "stamped") return readScalarReviews(find, "stamped", "reviews_average", "reviews_count");
6543
6568
  if (provider === "judgeme") return readJudgeMeReviews(find);
6544
6569
  if (provider === "okendo") return readOkendoReviews(find);
6545
6570
  if (provider === "opinew") return readScalarReviews(find, "opinew_metafields", "reviews_average", "reviews_count");
6546
- if (provider === "reviewsio") return readScalarReviews(find, "reviewscouk", "rating", "total");
6571
+ if (provider === "reviewsio")
6572
+ return readScalarReviews(find, "reviewscouk", "rating", "total") ?? readStandardReviews(find);
6547
6573
  if (provider === "loox") return readScalarReviews(find, "loox", "avg_rating", "num_reviews");
6548
6574
  if (provider === "junip") return readScalarReviews(find, "junip", "rating_average", "rating_count");
6549
6575
  const rating = find("reviews", "rating");
@@ -6641,7 +6667,7 @@ var projectPostPurchaseProduct = ({ data, effective, metadata, original }, repor
6641
6667
 
6642
6668
  // src/server/prepareNormalizedSubscription.ts
6643
6669
  var prepareNormalizedSubscription = (normalized, report, plan, quantity3, allowCollection = false) => {
6644
- if (!plan) return { reason: "Subscription plan is unavailable", status: "unsupported" };
6670
+ if (!plan) return { reason: PLAN_UNAVAILABLE, status: "unsupported" };
6645
6671
  const reason = subscriptionUnavailable(normalized, plan, allowCollection, quantity3);
6646
6672
  if (reason) return { reason, status: "unsupported" };
6647
6673
  const { effective } = normalized;
@@ -6692,8 +6718,9 @@ var oneTimeUnavailable = (normalized, allowCollection, quantity3) => {
6692
6718
  return "Only fixed one-time configuration is supported";
6693
6719
  const product = data[0];
6694
6720
  const variant2 = product.variants[0];
6695
- if (product.productGroupVariants.length || product.sellingPlanGroups?.some((group) => group.requiresSellingPlan) || !postPurchaseVariantAvailable(variant2))
6696
- return "An available one-time variant without product groups is required";
6721
+ if (product.productGroupVariants.length || product.sellingPlanGroups?.some((group) => group.requiresSellingPlan))
6722
+ return "A one-time variant without product groups or a required selling plan is required";
6723
+ if (!postPurchaseVariantAvailable(variant2)) return VARIANT_UNAVAILABLE;
6697
6724
  if (variant2.productId !== product.id) throw new Error("Product variant identity mismatch");
6698
6725
  };
6699
6726
 
@@ -6746,7 +6773,7 @@ var PostPurchaseSubscriptionDisplay = import_zod67.z.object({
6746
6773
  var { currencyCode: CurrencyCode, priceMinor: Minor2, savingPercent: Percent } = PostPurchaseSubscriptionDisplay.shape;
6747
6774
  var PostPurchaseDisplayPrice = import_zod68.z.object({
6748
6775
  currencyCode: CurrencyCode,
6749
- savingFormat: import_zod68.z.enum(["amount", "percent"]),
6776
+ savingFormat: import_zod68.z.enum(["amount", "percent"]).nullable(),
6750
6777
  savingMinor: Minor2,
6751
6778
  savingPercent: Percent,
6752
6779
  subscriptionUnit: PostPurchaseSubscriptionDisplay.optional(),
@@ -6900,7 +6927,8 @@ var PostPurchaseProductView = import_zod72.z.union([
6900
6927
  planCatalog: PostPurchasePlanCatalog.nullable().optional(),
6901
6928
  preparation: PostPurchasePreparation.options[1],
6902
6929
  purchaseOptions: PostPurchaseOptions.optional(),
6903
- sections: import_zod72.z.null(),
6930
+ /** A choice-level unavailable product keeps its card (values resolve blank); configuration failures send null. */
6931
+ sections: CABRootSection.nullable(),
6904
6932
  variantCatalog: PostPurchaseVariantCatalog.optional()
6905
6933
  })
6906
6934
  ]);
@@ -6931,7 +6959,24 @@ var postPurchaseOfferCopy = (blocks, metadata) => {
6931
6959
  });
6932
6960
  };
6933
6961
 
6962
+ // src/server/postPurchaseCardSections.ts
6963
+ var postPurchaseCardSections = (widgetId, { effective, metadata }, report) => {
6964
+ if (!effective.blocks?.length) return null;
6965
+ const sections = convertMessagePreview(
6966
+ widgetId,
6967
+ {
6968
+ ...effective,
6969
+ blocks: postPurchaseOfferCopy(effective.blocks, metadata),
6970
+ type: "shopify_post_purchase_extension"
6971
+ },
6972
+ report
6973
+ );
6974
+ return sections.sections.filter(({ sectionType }) => sectionType === "offers").length === 1 ? sections : null;
6975
+ };
6976
+ var preparePostPurchaseCardSections = (widgetId, settings, response, report) => postPurchaseCardSections(widgetId, normalizePostPurchaseProduct(settings, response), report);
6977
+
6934
6978
  // src/server/selectPostPurchaseChoice.ts
6979
+ var preferChoiceLevel = (preferred, other) => !isChoiceUnavailable(preferred) && isChoiceUnavailable(other) ? other : preferred;
6935
6980
  var selectPostPurchaseChoice = (normalized, projected, requested, allowCollection, quantity3) => {
6936
6981
  const { data, effective } = normalized;
6937
6982
  const modes = [];
@@ -6946,7 +6991,10 @@ var selectPostPurchaseChoice = (normalized, projected, requested, allowCollectio
6946
6991
  choice: void 0,
6947
6992
  options: void 0,
6948
6993
  plan: void 0,
6949
- reason: effective.productType === "one-time" ? oneTimeReason : subscriptionReason
6994
+ reason: preferChoiceLevel(
6995
+ effective.productType === "one-time" ? oneTimeReason : subscriptionReason,
6996
+ effective.productType === "one-time" ? subscriptionReason : oneTimeReason
6997
+ )
6950
6998
  };
6951
6999
  const defaultChoice = firstPlan && modes.includes("subscription") && (modes[0] === "subscription" || effective.subscriptionIsDefault) ? { mode: "subscription", sellingPlanId: firstPlan.id } : { mode: "one-time" };
6952
7000
  const options2 = PostPurchaseOptions.parse({ defaultChoice, modes, selector: effective.productTypeSelector });
@@ -6957,7 +7005,7 @@ var selectPostPurchaseChoice = (normalized, projected, requested, allowCollectio
6957
7005
  choice: bound,
6958
7006
  options: options2,
6959
7007
  plan: bound ? plan : void 0,
6960
- reason: bound ? void 0 : "Requested purchase choice is unavailable"
7008
+ reason: bound ? void 0 : CHOICE_UNAVAILABLE
6961
7009
  };
6962
7010
  };
6963
7011
 
@@ -6972,27 +7020,19 @@ var prepareNormalizedPostPurchaseView = (widgetId, normalized, report, choice, q
6972
7020
  const purchaseOptions = selected.options;
6973
7021
  const labels = { notAvailable: normalized.effective.language.global.notAvailable };
6974
7022
  const preparation = !selected.choice ? { reason: selected.reason, status: "unsupported" } : selected.choice.mode === "subscription" ? prepareNormalizedSubscription(normalized, report, selected.plan, quantity3, allowCollection) : prepareNormalizedProduct(normalized, report, quantity3, allowCollection);
6975
- const unsupported = (reason) => ({
6976
- labels,
6977
- planCatalog,
6978
- preparation: { reason, status: "unsupported" },
6979
- purchaseOptions,
6980
- sections: null
6981
- });
6982
- if (preparation.status === "unsupported")
6983
- return { labels, planCatalog, preparation, purchaseOptions, sections: null };
6984
- if (!normalized.effective.blocks?.length) return unsupported("One fixed product information block is required");
6985
- const sections = convertMessagePreview(
6986
- widgetId,
6987
- {
6988
- ...normalized.effective,
6989
- blocks: postPurchaseOfferCopy(normalized.effective.blocks, normalized.metadata),
6990
- type: "shopify_post_purchase_extension"
6991
- },
6992
- report
6993
- );
6994
- if (sections.sections.filter((section) => section.sectionType === "offers").length !== 1)
6995
- return unsupported("One fixed product information block is required");
7023
+ if (preparation.status === "unsupported") {
7024
+ const sections2 = isChoiceUnavailable(preparation.reason) ? postPurchaseCardSections(widgetId, normalized, report) : null;
7025
+ return PostPurchaseProductView.parse({ labels, planCatalog, preparation, purchaseOptions, sections: sections2 });
7026
+ }
7027
+ const sections = postPurchaseCardSections(widgetId, normalized, report);
7028
+ if (!sections)
7029
+ return {
7030
+ labels,
7031
+ planCatalog,
7032
+ preparation: { reason: "One fixed product information block is required", status: "unsupported" },
7033
+ purchaseOptions,
7034
+ sections: null
7035
+ };
6996
7036
  return PostPurchaseProductView.parse({
6997
7037
  planCatalog,
6998
7038
  preparation: {
@@ -7583,8 +7623,8 @@ var preparePostPurchaseCollectionGroup = (widgetId, settings, response, member,
7583
7623
  view: prepared ? { ...prepared.view, groupCatalog: prepared.groupCatalog } : {
7584
7624
  groupCatalog: group.catalog,
7585
7625
  labels: { notAvailable: normalized.effective.language.global.notAvailable },
7586
- preparation: { reason: "Post-purchase group default is unavailable", status: "unsupported" },
7587
- sections: null
7626
+ preparation: { reason: GROUP_DEFAULT_UNAVAILABLE, status: "unsupported" },
7627
+ sections: postPurchaseCardSections(widgetId, normalized, report)
7588
7628
  }
7589
7629
  };
7590
7630
  };
@@ -26,6 +26,7 @@ export { preparePostPurchaseQuantityAdmissionView } from '../server/preparePostP
26
26
  export { preparePostPurchaseGroupView } from '../server/preparePostPurchaseGroupView';
27
27
  export { preparePostPurchaseGroupAdmissionView } from '../server/preparePostPurchaseGroupAdmissionView';
28
28
  export { preparePostPurchaseGroupDefault } from '../server/preparePostPurchaseGroupDefault';
29
+ export { preparePostPurchaseCardSections } from '../server/postPurchaseCardSections';
29
30
  export { preparePostPurchaseCollectionView } from '../server/preparePostPurchaseCollectionView';
30
31
  export { classifyPostPurchaseOffer } from '../server/classifyPostPurchaseOffer';
31
32
  export { createPostPurchaseOrderAttributes } from '../server/createPostPurchaseOrderAttributes';
@@ -6308,6 +6308,19 @@ var PostPurchaseSubscriptionSettings = subscription.extend({
6308
6308
  })
6309
6309
  });
6310
6310
 
6311
+ // src/server/postPurchaseUnavailableChoice.ts
6312
+ var VARIANT_UNAVAILABLE = "The chosen variant is unavailable";
6313
+ var PLAN_UNAVAILABLE = "Subscription plan is unavailable";
6314
+ var CHOICE_UNAVAILABLE = "Requested purchase choice is unavailable";
6315
+ var GROUP_DEFAULT_UNAVAILABLE = "Post-purchase group default is unavailable";
6316
+ var choiceLevel = /* @__PURE__ */ new Set([
6317
+ VARIANT_UNAVAILABLE,
6318
+ PLAN_UNAVAILABLE,
6319
+ CHOICE_UNAVAILABLE,
6320
+ GROUP_DEFAULT_UNAVAILABLE
6321
+ ]);
6322
+ var isChoiceUnavailable = (reason) => reason !== void 0 && choiceLevel.has(reason);
6323
+
6311
6324
  // src/server/postPurchaseVariantAvailable.ts
6312
6325
  var postPurchaseVariantAvailable = (variant2) => !(variant2.inventoryManagement && variant2.inventoryPolicy === "deny" && variant2.inventoryQuantity <= 0);
6313
6326
 
@@ -6322,12 +6335,13 @@ var subscriptionUnavailable = (normalized, plan, allowCollection, quantity3) =>
6322
6335
  return unavailable;
6323
6336
  const product = data[0];
6324
6337
  const variant2 = product.variants[0];
6325
- if (product.productGroupVariants.length || !postPurchaseVariantAvailable(variant2) || variant2.productId !== product.id)
6326
- return unavailable;
6338
+ if (product.productGroupVariants.length || variant2.productId !== product.id) return unavailable;
6327
6339
  const terms = [original, effective].map(
6328
6340
  (config) => PostPurchaseSubscriptionSettings.safeParse(config.subscription)
6329
6341
  );
6330
- if (!plan || terms.some((term) => !term.success)) return unavailable;
6342
+ if (terms.some((term) => !term.success)) return unavailable;
6343
+ if (!plan) return PLAN_UNAVAILABLE;
6344
+ if (!postPurchaseVariantAvailable(variant2)) return VARIANT_UNAVAILABLE;
6331
6345
  };
6332
6346
 
6333
6347
  // src/server/postPurchaseProductDisplay.ts
@@ -6466,13 +6480,24 @@ var readScalarReviews = (find, namespace, ratingKey, countKey) => {
6466
6480
  };
6467
6481
 
6468
6482
  // src/server/postPurchaseReviewData.ts
6483
+ var readStandardReviews = (find) => {
6484
+ const rating = find("reviews", "rating");
6485
+ const count = find("reviews", "rating_count");
6486
+ if (!rating || !count) return null;
6487
+ const value = z63.string().parse(rating.value);
6488
+ return {
6489
+ rating: PostPurchaseCommonReviewRating.parse(/^\d+(?:\.\d+)?$/.test(value) ? { value } : JSON.parse(value)).value,
6490
+ reviewCount: PostPurchaseReviewCount.parse(count.value)
6491
+ };
6492
+ };
6469
6493
  var readPostPurchaseReviewData = (provider, find) => {
6470
6494
  if (provider === "yotpo") return readScalarReviews(find, "yotpo", "reviews_average", "reviews_count");
6471
6495
  if (provider === "stamped") return readScalarReviews(find, "stamped", "reviews_average", "reviews_count");
6472
6496
  if (provider === "judgeme") return readJudgeMeReviews(find);
6473
6497
  if (provider === "okendo") return readOkendoReviews(find);
6474
6498
  if (provider === "opinew") return readScalarReviews(find, "opinew_metafields", "reviews_average", "reviews_count");
6475
- if (provider === "reviewsio") return readScalarReviews(find, "reviewscouk", "rating", "total");
6499
+ if (provider === "reviewsio")
6500
+ return readScalarReviews(find, "reviewscouk", "rating", "total") ?? readStandardReviews(find);
6476
6501
  if (provider === "loox") return readScalarReviews(find, "loox", "avg_rating", "num_reviews");
6477
6502
  if (provider === "junip") return readScalarReviews(find, "junip", "rating_average", "rating_count");
6478
6503
  const rating = find("reviews", "rating");
@@ -6570,7 +6595,7 @@ var projectPostPurchaseProduct = ({ data, effective, metadata, original }, repor
6570
6595
 
6571
6596
  // src/server/prepareNormalizedSubscription.ts
6572
6597
  var prepareNormalizedSubscription = (normalized, report, plan, quantity3, allowCollection = false) => {
6573
- if (!plan) return { reason: "Subscription plan is unavailable", status: "unsupported" };
6598
+ if (!plan) return { reason: PLAN_UNAVAILABLE, status: "unsupported" };
6574
6599
  const reason = subscriptionUnavailable(normalized, plan, allowCollection, quantity3);
6575
6600
  if (reason) return { reason, status: "unsupported" };
6576
6601
  const { effective } = normalized;
@@ -6621,8 +6646,9 @@ var oneTimeUnavailable = (normalized, allowCollection, quantity3) => {
6621
6646
  return "Only fixed one-time configuration is supported";
6622
6647
  const product = data[0];
6623
6648
  const variant2 = product.variants[0];
6624
- if (product.productGroupVariants.length || product.sellingPlanGroups?.some((group) => group.requiresSellingPlan) || !postPurchaseVariantAvailable(variant2))
6625
- return "An available one-time variant without product groups is required";
6649
+ if (product.productGroupVariants.length || product.sellingPlanGroups?.some((group) => group.requiresSellingPlan))
6650
+ return "A one-time variant without product groups or a required selling plan is required";
6651
+ if (!postPurchaseVariantAvailable(variant2)) return VARIANT_UNAVAILABLE;
6626
6652
  if (variant2.productId !== product.id) throw new Error("Product variant identity mismatch");
6627
6653
  };
6628
6654
 
@@ -6675,7 +6701,7 @@ var PostPurchaseSubscriptionDisplay = z67.object({
6675
6701
  var { currencyCode: CurrencyCode, priceMinor: Minor2, savingPercent: Percent } = PostPurchaseSubscriptionDisplay.shape;
6676
6702
  var PostPurchaseDisplayPrice = z68.object({
6677
6703
  currencyCode: CurrencyCode,
6678
- savingFormat: z68.enum(["amount", "percent"]),
6704
+ savingFormat: z68.enum(["amount", "percent"]).nullable(),
6679
6705
  savingMinor: Minor2,
6680
6706
  savingPercent: Percent,
6681
6707
  subscriptionUnit: PostPurchaseSubscriptionDisplay.optional(),
@@ -6829,7 +6855,8 @@ var PostPurchaseProductView = z72.union([
6829
6855
  planCatalog: PostPurchasePlanCatalog.nullable().optional(),
6830
6856
  preparation: PostPurchasePreparation.options[1],
6831
6857
  purchaseOptions: PostPurchaseOptions.optional(),
6832
- sections: z72.null(),
6858
+ /** A choice-level unavailable product keeps its card (values resolve blank); configuration failures send null. */
6859
+ sections: CABRootSection.nullable(),
6833
6860
  variantCatalog: PostPurchaseVariantCatalog.optional()
6834
6861
  })
6835
6862
  ]);
@@ -6860,7 +6887,24 @@ var postPurchaseOfferCopy = (blocks, metadata) => {
6860
6887
  });
6861
6888
  };
6862
6889
 
6890
+ // src/server/postPurchaseCardSections.ts
6891
+ var postPurchaseCardSections = (widgetId, { effective, metadata }, report) => {
6892
+ if (!effective.blocks?.length) return null;
6893
+ const sections = convertMessagePreview(
6894
+ widgetId,
6895
+ {
6896
+ ...effective,
6897
+ blocks: postPurchaseOfferCopy(effective.blocks, metadata),
6898
+ type: "shopify_post_purchase_extension"
6899
+ },
6900
+ report
6901
+ );
6902
+ return sections.sections.filter(({ sectionType }) => sectionType === "offers").length === 1 ? sections : null;
6903
+ };
6904
+ var preparePostPurchaseCardSections = (widgetId, settings, response, report) => postPurchaseCardSections(widgetId, normalizePostPurchaseProduct(settings, response), report);
6905
+
6863
6906
  // src/server/selectPostPurchaseChoice.ts
6907
+ var preferChoiceLevel = (preferred, other) => !isChoiceUnavailable(preferred) && isChoiceUnavailable(other) ? other : preferred;
6864
6908
  var selectPostPurchaseChoice = (normalized, projected, requested, allowCollection, quantity3) => {
6865
6909
  const { data, effective } = normalized;
6866
6910
  const modes = [];
@@ -6875,7 +6919,10 @@ var selectPostPurchaseChoice = (normalized, projected, requested, allowCollectio
6875
6919
  choice: void 0,
6876
6920
  options: void 0,
6877
6921
  plan: void 0,
6878
- reason: effective.productType === "one-time" ? oneTimeReason : subscriptionReason
6922
+ reason: preferChoiceLevel(
6923
+ effective.productType === "one-time" ? oneTimeReason : subscriptionReason,
6924
+ effective.productType === "one-time" ? subscriptionReason : oneTimeReason
6925
+ )
6879
6926
  };
6880
6927
  const defaultChoice = firstPlan && modes.includes("subscription") && (modes[0] === "subscription" || effective.subscriptionIsDefault) ? { mode: "subscription", sellingPlanId: firstPlan.id } : { mode: "one-time" };
6881
6928
  const options2 = PostPurchaseOptions.parse({ defaultChoice, modes, selector: effective.productTypeSelector });
@@ -6886,7 +6933,7 @@ var selectPostPurchaseChoice = (normalized, projected, requested, allowCollectio
6886
6933
  choice: bound,
6887
6934
  options: options2,
6888
6935
  plan: bound ? plan : void 0,
6889
- reason: bound ? void 0 : "Requested purchase choice is unavailable"
6936
+ reason: bound ? void 0 : CHOICE_UNAVAILABLE
6890
6937
  };
6891
6938
  };
6892
6939
 
@@ -6901,27 +6948,19 @@ var prepareNormalizedPostPurchaseView = (widgetId, normalized, report, choice, q
6901
6948
  const purchaseOptions = selected.options;
6902
6949
  const labels = { notAvailable: normalized.effective.language.global.notAvailable };
6903
6950
  const preparation = !selected.choice ? { reason: selected.reason, status: "unsupported" } : selected.choice.mode === "subscription" ? prepareNormalizedSubscription(normalized, report, selected.plan, quantity3, allowCollection) : prepareNormalizedProduct(normalized, report, quantity3, allowCollection);
6904
- const unsupported = (reason) => ({
6905
- labels,
6906
- planCatalog,
6907
- preparation: { reason, status: "unsupported" },
6908
- purchaseOptions,
6909
- sections: null
6910
- });
6911
- if (preparation.status === "unsupported")
6912
- return { labels, planCatalog, preparation, purchaseOptions, sections: null };
6913
- if (!normalized.effective.blocks?.length) return unsupported("One fixed product information block is required");
6914
- const sections = convertMessagePreview(
6915
- widgetId,
6916
- {
6917
- ...normalized.effective,
6918
- blocks: postPurchaseOfferCopy(normalized.effective.blocks, normalized.metadata),
6919
- type: "shopify_post_purchase_extension"
6920
- },
6921
- report
6922
- );
6923
- if (sections.sections.filter((section) => section.sectionType === "offers").length !== 1)
6924
- return unsupported("One fixed product information block is required");
6951
+ if (preparation.status === "unsupported") {
6952
+ const sections2 = isChoiceUnavailable(preparation.reason) ? postPurchaseCardSections(widgetId, normalized, report) : null;
6953
+ return PostPurchaseProductView.parse({ labels, planCatalog, preparation, purchaseOptions, sections: sections2 });
6954
+ }
6955
+ const sections = postPurchaseCardSections(widgetId, normalized, report);
6956
+ if (!sections)
6957
+ return {
6958
+ labels,
6959
+ planCatalog,
6960
+ preparation: { reason: "One fixed product information block is required", status: "unsupported" },
6961
+ purchaseOptions,
6962
+ sections: null
6963
+ };
6925
6964
  return PostPurchaseProductView.parse({
6926
6965
  planCatalog,
6927
6966
  preparation: {
@@ -7512,8 +7551,8 @@ var preparePostPurchaseCollectionGroup = (widgetId, settings, response, member,
7512
7551
  view: prepared ? { ...prepared.view, groupCatalog: prepared.groupCatalog } : {
7513
7552
  groupCatalog: group.catalog,
7514
7553
  labels: { notAvailable: normalized.effective.language.global.notAvailable },
7515
- preparation: { reason: "Post-purchase group default is unavailable", status: "unsupported" },
7516
- sections: null
7554
+ preparation: { reason: GROUP_DEFAULT_UNAVAILABLE, status: "unsupported" },
7555
+ sections: postPurchaseCardSections(widgetId, normalized, report)
7517
7556
  }
7518
7557
  };
7519
7558
  };
@@ -8178,6 +8217,7 @@ export {
8178
8217
  fetchUserConfig,
8179
8218
  postAnalyticsEvents,
8180
8219
  preparePostPurchaseAdmissionView,
8220
+ preparePostPurchaseCardSections,
8181
8221
  preparePostPurchaseCollectionView,
8182
8222
  preparePostPurchaseDeclineDisplay,
8183
8223
  preparePostPurchaseGroupAdmissionView,
@@ -0,0 +1,12 @@
1
+ import { normalizePostPurchaseProduct } from '../server/normalizePostPurchaseProduct';
2
+ import type { Reporter } from '../server/shared';
3
+ /**
4
+ * The product's section tree from the effective settings snapshot, or `null` unless it holds exactly one product
5
+ * card. No product values enter the tree; the client resolves its tokens.
6
+ */
7
+ export declare const postPurchaseCardSections: (widgetId: number, { effective, metadata }: Pick<ReturnType<typeof normalizePostPurchaseProduct>, "effective" | "metadata">, report?: Reporter) => import("..").CABRootSection | null;
8
+ /**
9
+ * The same tree from the raw settings and data-source response, for a caller's own choice-level fallback — rebuy-api's
10
+ * group default that resolves no available merchandise.
11
+ */
12
+ export declare const preparePostPurchaseCardSections: (widgetId: number, settings: unknown, response: unknown, report?: Reporter) => import("..").CABRootSection | null;
@@ -1,4 +1,4 @@
1
1
  import type { normalizePostPurchaseProduct } from '../server/normalizePostPurchaseProduct';
2
2
  import type { PostPurchaseQuantity } from '../server/readPostPurchaseQuantity';
3
3
  /** The same eligibility rule drives advertised modes and their prepared terms. */
4
- export declare const oneTimeUnavailable: (normalized: ReturnType<typeof normalizePostPurchaseProduct>, allowCollection: boolean, quantity?: PostPurchaseQuantity) => "Only one fixed product and variant are supported" | "Only fixed one-time configuration is supported" | "An available one-time variant without product groups is required" | undefined;
4
+ export declare const oneTimeUnavailable: (normalized: ReturnType<typeof normalizePostPurchaseProduct>, allowCollection: boolean, quantity?: PostPurchaseQuantity) => "The chosen variant is unavailable" | "Only one fixed product and variant are supported" | "Only fixed one-time configuration is supported" | "A one-time variant without product groups or a required selling plan is required" | undefined;
@@ -1,6 +1,10 @@
1
1
  import type { ReviewFields } from '../server/postPurchaseReviewFields';
2
2
  import type { selectPostPurchaseReviewProvider } from '../server/postPurchaseReviewProvider';
3
- /** Selection is complete before reading data; a missing selected aggregate cannot fall through. */
3
+ /**
4
+ * Selection is complete before reading data; a missing selected aggregate cannot fall through. Reviews.io reading
5
+ * its own fields before Shopify's standard ones is one provider's data, not a fall-through: an incomplete reviewscouk
6
+ * pair is unusable and reads as absent, while a complete but malformed one throws rather than falling back.
7
+ */
4
8
  export declare const readPostPurchaseReviewData: (provider: NonNullable<ReturnType<typeof selectPostPurchaseReviewProvider>>, find: ReviewFields) => {
5
9
  rating: number;
6
10
  reviewCount: number;
@@ -1,4 +1,4 @@
1
1
  import type { PostPurchasePlanOption } from '../schema/postPurchasePlanCatalog';
2
2
  import type { normalizePostPurchaseProduct } from '../server/normalizePostPurchaseProduct';
3
3
  import type { PostPurchaseQuantity } from '../server/readPostPurchaseQuantity';
4
- export declare const subscriptionUnavailable: (normalized: ReturnType<typeof normalizePostPurchaseProduct>, plan: PostPurchasePlanOption | undefined, allowCollection: boolean, quantity?: PostPurchaseQuantity) => "An eligible subscription plan with supported shipping and discount is required" | undefined;
4
+ export declare const subscriptionUnavailable: (normalized: ReturnType<typeof normalizePostPurchaseProduct>, plan: PostPurchasePlanOption | undefined, allowCollection: boolean, quantity?: PostPurchaseQuantity) => "The chosen variant is unavailable" | "Subscription plan is unavailable" | "An eligible subscription plan with supported shipping and discount is required" | undefined;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Choice-level unavailability: the widget is readable and its card converts, but the choice the buyer is looking
3
+ * at cannot be bought right now — its variant is sold out, its plan is gone, the requested mode is not offered,
4
+ * or a group has no available default. Like cab-checkout's sold-out card, such a product still carries its tree
5
+ * (values resolve blank; Pay shows `notAvailable`). Every other reason is configuration-level and keeps
6
+ * `sections: null`.
7
+ */
8
+ export declare const VARIANT_UNAVAILABLE = "The chosen variant is unavailable";
9
+ export declare const PLAN_UNAVAILABLE = "Subscription plan is unavailable";
10
+ export declare const CHOICE_UNAVAILABLE = "Requested purchase choice is unavailable";
11
+ export declare const GROUP_DEFAULT_UNAVAILABLE = "Post-purchase group default is unavailable";
12
+ export declare const isChoiceUnavailable: (reason: string | undefined) => boolean;
@@ -303,7 +303,7 @@ export declare const preparePostPurchaseAdmissionView: (widgetId: number, settin
303
303
  } | undefined;
304
304
  displayPrice?: {
305
305
  currencyCode: string;
306
- savingFormat: "amount" | "percent";
306
+ savingFormat: "amount" | "percent" | null;
307
307
  savingMinor: number;
308
308
  savingPercent: number;
309
309
  variantCompareAtPriceMinor: number | null;
@@ -397,7 +397,130 @@ export declare const preparePostPurchaseAdmissionView: (widgetId: number, settin
397
397
  reason: string;
398
398
  status: "unsupported";
399
399
  };
400
- sections: null;
400
+ sections: {
401
+ alignment: {
402
+ horizontal: "start" | "center" | "end";
403
+ vertical: "top" | "middle" | "bottom";
404
+ };
405
+ border: {
406
+ radius: "small" | "none" | "base" | "large" | "fullyRounded";
407
+ style: "none" | "base" | "dotted" | "dashed";
408
+ width: "base" | "medium" | "thick";
409
+ };
410
+ direction: "columns" | "rows" | "grid";
411
+ padding: "none" | "base" | "extraTight" | "tight" | "loose" | "extraLoose";
412
+ sectionId: string;
413
+ sections: never[] | import("..").CABSection[];
414
+ sectionType: "layout";
415
+ spacing: "none" | "base" | "extraTight" | "tight" | "loose" | "extraLoose";
416
+ width: number;
417
+ editorMode: "checkoutExtension" | "postPurchaseOffer" | "thankYouPage" | "orderStatusPage" | "ordersIndexPage" | "customerProfilePage";
418
+ previewMode: boolean;
419
+ storeId: number | null;
420
+ targetArea: {
421
+ icon: string;
422
+ label: string;
423
+ width: string;
424
+ fill?: boolean | undefined;
425
+ flip?: "vertical" | "horizontal" | "both" | undefined;
426
+ } | null;
427
+ tracking: {
428
+ enableAttribution: boolean;
429
+ enableSource: boolean;
430
+ enableWidget: boolean;
431
+ };
432
+ type: "product" | "bundle_builder" | "cart" | "cart_subscription" | "dynamic_bundle" | "gift_with_purchase" | "placeholder" | "pre_purchase" | "product_addon" | "product_upsell" | "recharge_checkout" | "recharge_customer_portal" | "recharge_post_purchase" | "shopify_checkout" | "shopify_checkout_extension" | "shopify_post_purchase" | "shopify_post_purchase_extension" | "switch_to_subscription" | "ui_extension_ad" | "ui_extension_button" | "ui_extension_content_block" | "ui_extension_line_item_editor" | "ui_extension_progress_bar";
433
+ uiLabels: {
434
+ currentPage: Record<string, string>;
435
+ guest: Record<string, string>;
436
+ loadingOptions: Record<string, string>;
437
+ nextPage: Record<string, string>;
438
+ offerCarousel: Record<string, string>;
439
+ offerDialog: Record<string, string>;
440
+ page: Record<string, string>;
441
+ previousPage: Record<string, string>;
442
+ selected: Record<string, string>;
443
+ subscriptionOptions: Record<string, string>;
444
+ updating: Record<string, string>;
445
+ };
446
+ version: 2;
447
+ widgetId: number | null;
448
+ buttonField?: "declineAllOffers" | "declineOffer" | "removeFromOrder" | "undoAddToOrder" | "activePage" | "addedToCart" | "addingToCart" | "addToCart" | "buttonLabel" | "destinationUrl" | "inactivePage" | "overlayContent" | "payNow" | "progressReached" | "progressRemaining" | "redirectToCheckout" | "showVariant" | "showVariants" | "soldOut" | "subscriptionOption" | "switchToOneTimePurchase" | "switchToSubscriptionNoDiscount" | "switchToSubscriptionWithDiscount" | undefined;
449
+ frame?: "callout" | "offer-content" | undefined;
450
+ grid?: {
451
+ columns: (string | number)[];
452
+ rows: (string | number)[];
453
+ } | undefined;
454
+ name?: string | undefined;
455
+ viewUrl?: string | undefined;
456
+ wrapping?: {
457
+ breakAt: number;
458
+ maxPerLine: number;
459
+ } | undefined;
460
+ mutators?: {
461
+ effect: "set_false" | "set_true" | "toggle";
462
+ variable: string;
463
+ when: {
464
+ operator: "is_empty" | "is_not_empty";
465
+ type: "content";
466
+ } | {
467
+ operator: "equals" | "greater_than" | "less_than";
468
+ type: "result_count";
469
+ value: number;
470
+ } | {
471
+ operator: "contains" | "does_not_contain";
472
+ type: "result_tag";
473
+ value: string;
474
+ } | {
475
+ event: "item_added" | "quantity_changed" | "variant_selected";
476
+ type: "event";
477
+ };
478
+ }[] | undefined;
479
+ variables?: ({
480
+ defaultValue: string;
481
+ name: string;
482
+ type: "text";
483
+ seed?: undefined;
484
+ } | {
485
+ defaultValue: number;
486
+ name: string;
487
+ type: "number";
488
+ seed?: undefined;
489
+ } | {
490
+ defaultValue: boolean;
491
+ name: string;
492
+ type: "boolean";
493
+ seed?: {
494
+ dataSourceId: number | null;
495
+ ruleset: {
496
+ exitIfMatched: boolean;
497
+ logic: {
498
+ rules: {
499
+ operator: "equals" | "greater_than" | "less_than" | "contains" | "does_not_contain" | "after" | "anything" | "before" | "contains_any" | "does_not_contain_any" | "does_not_equal";
500
+ products: never[] | unknown[];
501
+ type: "product" | "date" | "cart" | "cart_count" | "cart_item_count" | "cart_line_count" | "cart_subtotal" | "collection" | "customer" | "customer_order_count" | "customer_tag" | "customer_total_spent" | "product_tag" | "product_title" | "product_type" | "product_vendor";
502
+ value: string;
503
+ }[];
504
+ }[];
505
+ output: {
506
+ key: string;
507
+ type: "data_json";
508
+ value: string;
509
+ }[];
510
+ }[];
511
+ } | undefined;
512
+ })[] | undefined;
513
+ visibility?: {
514
+ variable: string;
515
+ visibleWhen: boolean;
516
+ } | undefined;
517
+ experiment?: {
518
+ elementId: number;
519
+ experimentId: number;
520
+ experimentType: string;
521
+ selectedId: number;
522
+ } | undefined;
523
+ } | null;
401
524
  groupCatalog?: {
402
525
  memberProductId: number;
403
526
  options: {