@rebuy/rebuy 3.52.0 → 3.53.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.
@@ -0,0 +1,98 @@
1
+ /** The STS Flow: the subscription fixture with STS on and the refund notice asked for. */
2
+ export declare const stsSettings: {
3
+ upgrade_to_subscription: {
4
+ allow: boolean;
5
+ email_refund_notice: boolean;
6
+ };
7
+ discount: {
8
+ amount: number;
9
+ type: string;
10
+ };
11
+ product_type: string;
12
+ subscription: {
13
+ discount: {
14
+ amount: number;
15
+ type: string;
16
+ };
17
+ shipping: {
18
+ amount: number;
19
+ type: string;
20
+ };
21
+ };
22
+ blocks: {
23
+ type: string;
24
+ }[];
25
+ endpoint: string;
26
+ integrations: {};
27
+ key: string;
28
+ language: {};
29
+ product_limit: number;
30
+ product_options: {};
31
+ quantity_inputs: {
32
+ default_quantity: number;
33
+ enabled: boolean;
34
+ };
35
+ shipping: {
36
+ amount: string;
37
+ title: string;
38
+ type: string;
39
+ };
40
+ };
41
+ export declare const stsResponse: {
42
+ data: {
43
+ selling_plan_groups: {
44
+ id: string;
45
+ requires_selling_plan: boolean;
46
+ selling_plans: {
47
+ id: number;
48
+ name: string;
49
+ options: {
50
+ name: string;
51
+ position: number;
52
+ value: string;
53
+ }[];
54
+ price_adjustments: never[];
55
+ }[];
56
+ }[];
57
+ variants: {
58
+ selling_plan_allocations: {
59
+ selling_plan_group_id: string;
60
+ selling_plan_id: number;
61
+ }[];
62
+ compare_at_price: string;
63
+ id: number;
64
+ inventory_management: string;
65
+ inventory_policy: string;
66
+ inventory_quantity: number;
67
+ price: string;
68
+ product_id: number;
69
+ title: string;
70
+ }[];
71
+ description: string;
72
+ id: number;
73
+ image: {
74
+ src: string;
75
+ };
76
+ title: string;
77
+ }[];
78
+ metadata: {};
79
+ };
80
+ /** The buyer bought variant 411 of product 410 one-time, three of them. */
81
+ export declare const oneTimeLine: {
82
+ productId: number;
83
+ quantity: number;
84
+ variantId: number;
85
+ };
86
+ export declare const stsContext: {
87
+ originalLineItems: {
88
+ productId: number;
89
+ quantity: number;
90
+ variantId: number;
91
+ }[];
92
+ };
93
+ /**
94
+ * Wraps `call` so every existing case also runs with the STS argument at position `index` and proves the
95
+ * output byte-identical (or the same failure). Use it only where the Offer does not enable STS, or with
96
+ * an argument that leaves STS off.
97
+ */
98
+ export declare const provingStsInert: <A extends unknown[], R>(call: (...args: A) => R, index: number, sts: unknown) => (...args: A) => R;
@@ -1,3 +1,5 @@
1
1
  import { type z } from 'zod';
2
- import { type PostPurchaseOfferEligibility, PostPurchaseOfferEligibilityContext } from '../schema/postPurchaseOfferEligibility';
3
- export declare const classifyPostPurchaseOffer: (settings: unknown, response: unknown, context: z.input<typeof PostPurchaseOfferEligibilityContext>) => PostPurchaseOfferEligibility;
2
+ import { type PostPurchaseOfferEligibility, PostPurchaseOfferEligibilityContext, PostPurchaseStsOptions } from '../schema/postPurchaseOfferEligibility';
3
+ export declare const classifyPostPurchaseOffer: (settings: unknown, response: unknown, context: z.input<typeof PostPurchaseOfferEligibilityContext>,
4
+ /** STS opt-in; absent or `{ sts: false }` keeps every pre-STS outcome. */
5
+ options?: PostPurchaseStsOptions) => PostPurchaseOfferEligibility;
@@ -6369,9 +6369,9 @@ var import_zod54 = require("zod");
6369
6369
  var import_zod52 = require("zod");
6370
6370
  var PostPurchaseProductGallery = import_zod52.z.object({
6371
6371
  /**
6372
- * The product had more than one image before `images` was capped at the sub-image limit, so a
6373
- * renderer shows the thumbnail row even when the cap leaves one image (legacy checks the count
6374
- * before slicing). Older replies omit it; fall back to `images.length > 1`.
6372
+ * Show the thumbnail row: the product had more than one image before `images` was capped at the
6373
+ * sub-image limit, and that limit allows at least one thumbnail. It stays true when the cap leaves one
6374
+ * image (legacy checks the count before slicing). Older replies omit it; fall back to `images.length > 1`.
6375
6375
  */
6376
6376
  hasMultiple: import_zod52.z.boolean().optional(),
6377
6377
  images: import_zod52.z.array(
@@ -6539,9 +6539,12 @@ var subscriptionUnavailable = (normalized, plan, allowCollection, quantity3) =>
6539
6539
  const { data, effective, original } = normalized;
6540
6540
  const unavailable = "An eligible subscription plan with supported shipping and discount is required";
6541
6541
  if (data.length !== 1 || data[0].variants.length !== 1) return unavailable;
6542
- if (effective.productType === "one-time" || [original, effective].some(
6543
- (config) => !allowCollection && config.productLimit !== 1 || config.upgradeToSubscription.allow || !quantity3 && config.quantityInputs.enabled && (config.quantityInputs.minValue !== config.quantityInputs.maxValue || config.quantityInputs.defaultQuantity !== config.quantityInputs.minValue)
6544
- ))
6542
+ if (
6543
+ // Legacy STS ran whatever the product type: its trigger forced the subscription option on.
6544
+ effective.productType === "one-time" && !quantity3?.sts || [original, effective].some(
6545
+ (config) => !allowCollection && config.productLimit !== 1 || config.upgradeToSubscription.allow && !quantity3?.sts || !quantity3 && config.quantityInputs.enabled && (config.quantityInputs.minValue !== config.quantityInputs.maxValue || config.quantityInputs.defaultQuantity !== config.quantityInputs.minValue)
6546
+ )
6547
+ )
6545
6548
  return unavailable;
6546
6549
  const product = data[0];
6547
6550
  const variant2 = product.variants[0];
@@ -6566,16 +6569,19 @@ var postPurchasePrimaryImage = (product) => {
6566
6569
  };
6567
6570
 
6568
6571
  // src/server/postPurchaseProductGallery.ts
6569
- var postPurchaseProductGallery = (product, limit) => ({
6570
- hasMultiple: (product.images?.length ?? 0) > 1,
6571
- images: (product.images ?? []).slice(0, limit ?? 0).map((image) => ({
6572
- description: image.alt ?? product.title,
6573
- id: image.id,
6574
- source: sizeImageSource(image.src, "800x800"),
6575
- thumbnail: sizeImageSource(image.src, "200x200")
6576
- })),
6577
- selectedImageId: product.images?.find((image) => image.id === product.variants[0].imageId)?.id
6578
- });
6572
+ var postPurchaseProductGallery = (product, limit) => {
6573
+ const cap = Math.max(Math.floor(limit ?? 0), 0);
6574
+ return {
6575
+ hasMultiple: (product.images?.length ?? 0) > 1 && cap >= 1,
6576
+ images: (product.images ?? []).slice(0, cap).map((image) => ({
6577
+ description: image.alt ?? product.title,
6578
+ id: image.id,
6579
+ source: sizeImageSource(image.src, "800x800"),
6580
+ thumbnail: sizeImageSource(image.src, "200x200")
6581
+ })),
6582
+ selectedImageId: product.images?.find((image) => image.id === product.variants[0].imageId)?.id
6583
+ };
6584
+ };
6579
6585
 
6580
6586
  // src/transforms/postPurchase/convertDescriptionRte.ts
6581
6587
  var import_zod58 = require("zod");
@@ -7268,7 +7274,7 @@ var PostPurchaseMemberIdentity = import_zod75.z.object({
7268
7274
  }).strict();
7269
7275
 
7270
7276
  // src/schema/postPurchaseAdmission.ts
7271
- var PurchaseAdmissionModeSchema = import_zod76.z.enum(["purchase", "upgrade"]);
7277
+ var PurchaseAdmissionModeSchema = import_zod76.z.enum(["purchase", "sts"]);
7272
7278
  var selection = PreparedPostPurchaseProduct.shape.selection;
7273
7279
  var EventCalculationSchema = PostPurchaseProductCosts.pick({ currencyCode: true, totalMinor: true }).strict();
7274
7280
  var PurchaseExpectedSchema = import_zod76.z.object({
@@ -7290,8 +7296,8 @@ var PurchaseExpectedSchema = import_zod76.z.object({
7290
7296
  ({ member, progressRevision }) => !member || progressRevision !== void 0,
7291
7297
  "Captured member requires progress"
7292
7298
  ).refine(
7293
- ({ mode, selection: { sellingPlanId } }) => mode !== "upgrade" || sellingPlanId !== void 0,
7294
- "An upgrade selects a subscription"
7299
+ ({ mode, selection: { sellingPlanId } }) => mode !== "sts" || sellingPlanId !== void 0,
7300
+ "An STS selects a subscription"
7295
7301
  ).refine(({ buyerConsentToSubscriptions: consent, changeset, selection: selection4 }) => {
7296
7302
  const [change, shipping] = changeset.changes;
7297
7303
  if (selection4.sellingPlanId === void 0)
@@ -7307,7 +7313,7 @@ var PurchaseReceiptSchema = import_zod76.z.object({
7307
7313
  changesetToken: import_zod76.z.string().min(1),
7308
7314
  mode: PurchaseAdmissionModeSchema.optional(),
7309
7315
  operationId: import_zod76.z.uuid(),
7310
- /** The server-bound one-time line an upgrade refunds; its quantity is the order's, not the selection's. */
7316
+ /** The server-bound one-time line an STS refunds; its quantity is the order's, not the selection's. */
7311
7317
  originalLine: import_zod76.z.strictObject({ quantity: selection.shape.quantity, variantId: selection.shape.variantId }).optional(),
7312
7318
  requiresSubscriptionConsent: import_zod76.z.boolean(),
7313
7319
  selection
@@ -7315,8 +7321,8 @@ var PurchaseReceiptSchema = import_zod76.z.object({
7315
7321
  ({ requiresSubscriptionConsent, selection: selection4 }) => requiresSubscriptionConsent === (selection4.sellingPlanId !== void 0),
7316
7322
  "Receipt consent must match its selected plan"
7317
7323
  ).refine(
7318
- ({ mode, originalLine, selection: { sellingPlanId, variantId } }) => mode === "upgrade" ? sellingPlanId !== void 0 && originalLine?.variantId === variantId : originalLine === void 0,
7319
- "An upgrade Receipt binds the original line of its subscribed variant, and only an upgrade does"
7324
+ ({ mode, originalLine, selection: { sellingPlanId, variantId } }) => mode === "sts" ? sellingPlanId !== void 0 && originalLine?.variantId === variantId : originalLine === void 0,
7325
+ "An STS Receipt binds the original line of its subscribed variant, and only an STS does"
7320
7326
  );
7321
7327
  var PurchaseResponseSchema = import_zod76.z.object({ data: PurchaseReceiptSchema, successful: import_zod76.z.literal(true) });
7322
7328
 
@@ -7440,14 +7446,41 @@ var projectPostPurchaseVariantCatalog = (product, settings) => {
7440
7446
  });
7441
7447
  };
7442
7448
 
7443
- // src/schema/postPurchaseQuantity.ts
7449
+ // src/schema/postPurchaseOfferEligibility.ts
7444
7450
  var import_zod82 = require("zod");
7451
+ var selection2 = PreparedPostPurchaseProduct.shape.selection;
7452
+ var PostPurchaseOfferSkipReason = import_zod82.z.enum(["empty", "no-eligible-subscription"]);
7453
+ var PostPurchaseOfferEligibilityContext = import_zod82.z.object({
7454
+ excludedProductIds: PostPurchaseExcludedProductIds,
7455
+ originalLineItems: import_zod82.z.array(selection2.pick({ productId: true, sellingPlanId: true, variantId: true }))
7456
+ });
7457
+ var PostPurchaseStsOptions = import_zod82.z.object({ sts: import_zod82.z.boolean().optional() }).strict();
7458
+ var PostPurchaseStsContext = import_zod82.z.object({
7459
+ originalLineItems: import_zod82.z.array(
7460
+ selection2.pick({ productId: true, quantity: true, sellingPlanId: true, variantId: true })
7461
+ )
7462
+ });
7463
+ var PostPurchaseOfferEligibility = import_zod82.z.discriminatedUnion("status", [
7464
+ import_zod82.z.object({
7465
+ members: import_zod82.z.array(
7466
+ import_zod82.z.object({ productId: selection2.shape.productId, productIndex: import_zod82.z.number().int().nonnegative() })
7467
+ ),
7468
+ /** Present only with STS on: each member switches one original one-time line to subscription. */
7469
+ mode: import_zod82.z.literal("sts").optional(),
7470
+ status: import_zod82.z.literal("retain")
7471
+ }),
7472
+ import_zod82.z.object({ reason: PostPurchaseOfferSkipReason, status: import_zod82.z.literal("skip") }),
7473
+ import_zod82.z.object({ reason: import_zod82.z.literal("eligible-sts").optional(), status: import_zod82.z.literal("unavailable") })
7474
+ ]);
7475
+
7476
+ // src/schema/postPurchaseQuantity.ts
7477
+ var import_zod83 = require("zod");
7445
7478
  var quantity2 = PreparedPostPurchaseProduct.shape.selection.shape.quantity;
7446
7479
  var PostPurchaseQuantityChoice = PostPurchaseCollectionChoice.extend({ quantity: quantity2.optional() });
7447
7480
  var PostPurchaseQuantityPolicy = PostPurchaseSettings.shape.quantityInputs.omit({ defaultQuantity: true }).extend({
7448
7481
  initialQuantity: quantity2,
7449
7482
  maxValue: quantity2,
7450
- minValue: import_zod82.z.literal(0).transform(() => 1).or(quantity2)
7483
+ minValue: import_zod83.z.literal(0).transform(() => 1).or(quantity2)
7451
7484
  }).refine(({ maxValue, minValue }) => minValue <= maxValue, "Quantity bounds are reversed");
7452
7485
 
7453
7486
  // src/server/readPostPurchaseQuantity.ts
@@ -7477,40 +7510,88 @@ var readPostPurchaseQuantity = ({
7477
7510
  return { policy, quantity: quantity3 };
7478
7511
  };
7479
7512
 
7513
+ // src/server/postPurchaseSts.ts
7514
+ var stsAllowed = ({ effective, original }) => [original, effective].some((config) => config.upgradeToSubscription.allow);
7515
+ var postPurchaseStsLine = (normalized, product, lines, variantId) => {
7516
+ if (!product.sellingPlanGroups?.length || product.productGroupVariants.length) return void 0;
7517
+ for (const variant2 of product.variants) {
7518
+ const matched = lines.filter((line) => line.sellingPlanId === void 0 && line.variantId === variant2.id);
7519
+ const data = [{ ...product, variants: [variant2] }];
7520
+ if ((variantId === void 0 || variant2.id === variantId) && matched.length === 1 && postPurchaseVariantAvailable(variant2) && projectPostPurchasePlanCatalog({ ...normalized, data })?.plans.length)
7521
+ return { data, line: matched[0] };
7522
+ }
7523
+ };
7524
+ var preparePostPurchaseStsView = (widgetId, normalized, product, context, requested, report) => {
7525
+ const { originalLineItems } = PostPurchaseStsContext.parse(context);
7526
+ const found = postPurchaseStsLine(normalized, product, originalLineItems, requested.variantId);
7527
+ if (!found) return null;
7528
+ const whole = found.line.quantity;
7529
+ if (requested.quantity !== void 0 && requested.quantity !== whole)
7530
+ throw new PostPurchaseQuantityUnavailable("An STS covers the whole original quantity");
7531
+ const bounds = { initialQuantity: whole, maxValue: whole, minValue: whole };
7532
+ const policy = PostPurchaseQuantityPolicy.parse({ enabled: false, ...bounds });
7533
+ const quantity3 = { policy, quantity: whole, sts: true };
7534
+ const input = { ...normalized, data: found.data };
7535
+ return {
7536
+ quantity: quantity3,
7537
+ sts: {
7538
+ emailRefundNotice: normalized.effective.upgradeToSubscription.emailRefundNotice,
7539
+ originalLine: { quantity: whole, variantId: found.line.variantId }
7540
+ },
7541
+ view: prepareNormalizedPostPurchaseView(widgetId, input, report, requested.choice, quantity3, true)
7542
+ };
7543
+ };
7544
+ var prepareStsCollectionMember = (widgetId, normalized, { product, productIndex }, context, choice, report) => {
7545
+ const stsResult = preparePostPurchaseStsView(widgetId, normalized, product, context, { choice }, report);
7546
+ return stsResult && { productId: product.id, productIndex, reportingProduct: void 0, view: stsResult.view };
7547
+ };
7548
+
7549
+ // src/server/preparePostPurchaseStsMember.ts
7550
+ var preparePostPurchaseStsMember = (widgetId, settings, response, selected, sts, requestedQuantity, report) => {
7551
+ const { members, normalized } = normalizePostPurchaseCollection(settings, response);
7552
+ if (!stsAllowed(normalized)) return void 0;
7553
+ const member = members.find(({ product }) => product.id === selected.productId);
7554
+ const quantity3 = requestedQuantity && ("quantity" in requestedQuantity ? requestedQuantity.quantity : requestedQuantity.expectedQuantity);
7555
+ const prepared = member && preparePostPurchaseStsView(widgetId, normalized, member.product, sts, { ...selected, quantity: quantity3 }, report);
7556
+ if (!member || !prepared) return null;
7557
+ const { view, ...facts } = prepared;
7558
+ return { ...facts, member: { productId: member.product.id, productIndex: member.productIndex, view }, normalized };
7559
+ };
7560
+
7480
7561
  // src/schema/postPurchaseVariantDefault.ts
7481
- var import_zod83 = require("zod");
7562
+ var import_zod84 = require("zod");
7482
7563
  var values = PostPurchaseVariantValues.partial().extend({
7483
7564
  option1: PostPurchaseVariantValues.shape.option1.nullish()
7484
7565
  });
7485
7566
  var variant = values.extend({
7486
7567
  id: PostPurchaseVariantId,
7487
- inventoryManagement: import_zod83.z.string().nullable(),
7488
- inventoryPolicy: import_zod83.z.string(),
7489
- inventoryQuantity: import_zod83.z.number()
7568
+ inventoryManagement: import_zod84.z.string().nullable(),
7569
+ inventoryPolicy: import_zod84.z.string(),
7570
+ inventoryQuantity: import_zod84.z.number()
7490
7571
  });
7491
- var options = import_zod83.z.array(PostPurchaseVariantOption.pick({ name: true, values: true }));
7492
- var PostPurchaseVariantDefaultProduct = import_zod83.z.object({
7572
+ var options = import_zod84.z.array(PostPurchaseVariantOption.pick({ name: true, values: true }));
7573
+ var PostPurchaseVariantDefaultProduct = import_zod84.z.object({
7493
7574
  id: PostPurchaseProductId,
7494
7575
  options,
7495
7576
  selectedVariant: variant.optional(),
7496
- variants: import_zod83.z.array(variant)
7577
+ variants: import_zod84.z.array(variant)
7497
7578
  });
7498
7579
  var PostPurchaseVariantDefaultSettings = PostPurchaseSettings.shape.productOptions.pick({
7499
7580
  hideOutOfStockVariants: true,
7500
7581
  matchVariant: true
7501
7582
  });
7502
- var PostPurchaseOrderAttributes = import_zod83.z.record(import_zod83.z.string(), import_zod83.z.array(import_zod83.z.string())).default({});
7503
- var PostPurchaseOriginalVariants = import_zod83.z.array(
7504
- import_zod83.z.object({ productId: PostPurchaseProductId, variantId: PostPurchaseVariantId })
7583
+ var PostPurchaseOrderAttributes = import_zod84.z.record(import_zod84.z.string(), import_zod84.z.array(import_zod84.z.string())).default({});
7584
+ var PostPurchaseOriginalVariants = import_zod84.z.array(
7585
+ import_zod84.z.object({ productId: PostPurchaseProductId, variantId: PostPurchaseVariantId })
7505
7586
  );
7506
- var PostPurchaseAttributeProducts = import_zod83.z.array(
7507
- import_zod83.z.object({ id: PostPurchaseProductId, options, variants: import_zod83.z.array(values.extend({ id: PostPurchaseVariantId })) })
7587
+ var PostPurchaseAttributeProducts = import_zod84.z.array(
7588
+ import_zod84.z.object({ id: PostPurchaseProductId, options, variants: import_zod84.z.array(values.extend({ id: PostPurchaseVariantId })) })
7508
7589
  );
7509
7590
 
7510
7591
  // src/schema/postPurchaseVariantDefaultContext.ts
7511
- var import_zod84 = require("zod");
7512
- var PostPurchaseVariantDefaultContext = import_zod84.z.object({
7513
- enrichedLineItems: import_zod84.z.unknown().optional(),
7592
+ var import_zod85 = require("zod");
7593
+ var PostPurchaseVariantDefaultContext = import_zod85.z.object({
7594
+ enrichedLineItems: import_zod85.z.unknown().optional(),
7514
7595
  originalVariants: PostPurchaseOriginalVariants
7515
7596
  });
7516
7597
 
@@ -7585,8 +7666,10 @@ var resolvePostPurchaseMemberDefault = (product, original, context) => {
7585
7666
  };
7586
7667
 
7587
7668
  // src/server/preparePostPurchaseMemberView.ts
7588
- var prepareMember = (widgetId, settings, response, requested, report, excludedProductIds, requestedQuantity, defaults) => {
7669
+ var prepareMember = (widgetId, settings, response, requested, report, excludedProductIds, requestedQuantity, defaults, sts) => {
7589
7670
  const selected = PostPurchaseCollectionChoice.parse(requested);
7671
+ const stsResult = sts && preparePostPurchaseStsMember(widgetId, settings, response, selected, sts, requestedQuantity, report);
7672
+ if (stsResult !== void 0) return stsResult;
7590
7673
  const { members, normalized } = normalizePostPurchaseCollection(settings, response, excludedProductIds);
7591
7674
  const found = members.find(({ product: product2 }) => product2.id === selected.productId);
7592
7675
  if (!found) return null;
@@ -7613,7 +7696,7 @@ var preparePostPurchaseMemberAdmissionView = (widgetId, settings, response, requ
7613
7696
  };
7614
7697
 
7615
7698
  // src/server/preparePostPurchaseQuantityView.ts
7616
- var preparePostPurchaseQuantityView = (widgetId, settings, response, requested, report, excludedProductIds, defaults) => {
7699
+ var preparePostPurchaseQuantityView = (widgetId, settings, response, requested, report, excludedProductIds, defaults, sts) => {
7617
7700
  const { quantity: quantity3, ...selection4 } = PostPurchaseQuantityChoice.parse(requested);
7618
7701
  const prepared = prepareMember(
7619
7702
  widgetId,
@@ -7623,15 +7706,21 @@ var preparePostPurchaseQuantityView = (widgetId, settings, response, requested,
7623
7706
  report,
7624
7707
  excludedProductIds,
7625
7708
  { quantity: quantity3 },
7626
- defaults
7709
+ defaults,
7710
+ sts
7627
7711
  );
7628
- return prepared ? { ...prepared.member, quantityPolicy: prepared.quantity.policy } : null;
7712
+ if (!prepared) return null;
7713
+ return {
7714
+ ...prepared.member,
7715
+ quantityPolicy: prepared.quantity.policy,
7716
+ ..."sts" in prepared && { sts: prepared.sts }
7717
+ };
7629
7718
  };
7630
7719
 
7631
7720
  // src/server/preparePostPurchaseQuantityAdmissionView.ts
7632
- var selection2 = PostPurchaseQuantityChoice.required({ quantity: true });
7633
- var preparePostPurchaseQuantityAdmissionView = (widgetId, settings, response, expected, report, excludedProductIds, defaults) => {
7634
- const { quantity: expectedQuantity, ...requested } = selection2.parse(expected);
7721
+ var selection3 = PostPurchaseQuantityChoice.required({ quantity: true });
7722
+ var preparePostPurchaseQuantityAdmissionView = (widgetId, settings, response, expected, report, excludedProductIds, defaults, sts) => {
7723
+ const { quantity: expectedQuantity, ...requested } = selection3.parse(expected);
7635
7724
  const prepared = prepareMember(
7636
7725
  widgetId,
7637
7726
  settings,
@@ -7640,11 +7729,17 @@ var preparePostPurchaseQuantityAdmissionView = (widgetId, settings, response, ex
7640
7729
  report,
7641
7730
  excludedProductIds,
7642
7731
  { expectedQuantity },
7643
- defaults
7732
+ defaults,
7733
+ sts
7644
7734
  );
7645
7735
  if (!prepared) return null;
7646
7736
  const { removePartialOrder } = PostPurchaseSettings.shape.advance.parse(prepared.normalized.effective.advance);
7647
- return { ...prepared.member, quantityPolicy: prepared.quantity.policy, removePartialOrder };
7737
+ return {
7738
+ ...prepared.member,
7739
+ quantityPolicy: prepared.quantity.policy,
7740
+ removePartialOrder,
7741
+ ..."sts" in prepared && { sts: prepared.sts }
7742
+ };
7648
7743
  };
7649
7744
 
7650
7745
  // src/schema/postPurchaseGroup.ts
@@ -7807,11 +7902,16 @@ var preparePostPurchaseCollectionGroup = (widgetId, settings, response, member,
7807
7902
 
7808
7903
  // src/server/preparePostPurchaseCollectionView.ts
7809
7904
  var CollectionChoice = PostPurchaseCollectionChoice.omit({ variantId: true });
7810
- var preparePostPurchaseCollectionView = (widgetId, settings, response, report, requested, excludedProductIds, defaults = { originalVariants: [] }) => {
7905
+ var preparePostPurchaseCollectionView = (widgetId, settings, response, report, requested, excludedProductIds, defaults, sts) => {
7811
7906
  const { members, normalized } = normalizePostPurchaseCollection(settings, response);
7812
7907
  const excluded = PostPurchaseExcludedProductIds.parse(excludedProductIds);
7813
7908
  const selected = CollectionChoice.optional().parse(requested);
7909
+ const stsMode = sts && stsAllowed(normalized) ? sts : void 0;
7814
7910
  const projected = members.map((member) => {
7911
+ if (stsMode) {
7912
+ const choice = member.product.id === selected?.productId ? selected.choice : void 0;
7913
+ return prepareStsCollectionMember(widgetId, normalized, member, stsMode, choice, report);
7914
+ }
7815
7915
  if (member.product.productGroupVariants.length) {
7816
7916
  if (selected?.productId === member.product.id && selected.choice)
7817
7917
  throw new Error("Grouped choices require selected merchandise");
@@ -7822,7 +7922,7 @@ var preparePostPurchaseCollectionView = (widgetId, settings, response, report, r
7822
7922
  member,
7823
7923
  normalized,
7824
7924
  excluded,
7825
- defaults,
7925
+ defaults ?? { originalVariants: [] },
7826
7926
  report
7827
7927
  );
7828
7928
  return group;
@@ -7853,25 +7953,6 @@ var preparePostPurchaseCollectionView = (widgetId, settings, response, report, r
7853
7953
  };
7854
7954
  };
7855
7955
 
7856
- // src/schema/postPurchaseOfferEligibility.ts
7857
- var import_zod85 = require("zod");
7858
- var selection3 = PreparedPostPurchaseProduct.shape.selection;
7859
- var PostPurchaseOfferSkipReason = import_zod85.z.enum(["empty", "no-eligible-subscription"]);
7860
- var PostPurchaseOfferEligibilityContext = import_zod85.z.object({
7861
- excludedProductIds: PostPurchaseExcludedProductIds,
7862
- originalLineItems: import_zod85.z.array(selection3.pick({ productId: true, sellingPlanId: true, variantId: true }))
7863
- });
7864
- var PostPurchaseOfferEligibility = import_zod85.z.discriminatedUnion("status", [
7865
- import_zod85.z.object({
7866
- members: import_zod85.z.array(
7867
- import_zod85.z.object({ productId: selection3.shape.productId, productIndex: import_zod85.z.number().int().nonnegative() })
7868
- ),
7869
- status: import_zod85.z.literal("retain")
7870
- }),
7871
- import_zod85.z.object({ reason: PostPurchaseOfferSkipReason, status: import_zod85.z.literal("skip") }),
7872
- import_zod85.z.object({ reason: import_zod85.z.literal("eligible-upgrade").optional(), status: import_zod85.z.literal("unavailable") })
7873
- ]);
7874
-
7875
7956
  // src/server/postPurchaseMemberEligibility.ts
7876
7957
  var PostPurchaseInventoryUnavailable = class extends Error {
7877
7958
  };
@@ -7900,22 +7981,28 @@ var postPurchaseMemberEligibility = (normalized, product, excluded) => {
7900
7981
  };
7901
7982
 
7902
7983
  // src/server/classifyPostPurchaseOffer.ts
7903
- var classifyPostPurchaseOffer = (settings, response, context) => {
7984
+ var identities = (members) => members.map(({ product, productIndex }) => ({ productId: product.id, productIndex }));
7985
+ var classifyPostPurchaseOffer = (settings, response, context, options2) => {
7904
7986
  try {
7905
7987
  const trusted = PostPurchaseOfferEligibilityContext.parse(context);
7988
+ const { sts: stsMode = false } = PostPurchaseStsOptions.parse(options2 ?? {});
7906
7989
  const { members, normalized } = normalizePostPurchaseCollection(settings, response);
7907
7990
  const configurations = [normalized.original, normalized.effective];
7908
- const upgrades = configurations.some((config) => config.upgradeToSubscription.allow);
7991
+ const stsEnabled = configurations.some((config) => config.upgradeToSubscription.allow);
7992
+ const sts = stsEnabled && stsMode;
7909
7993
  const oneTime = new Set(
7910
7994
  trusted.originalLineItems.filter((line) => line.sellingPlanId === void 0).map((line) => line.variantId)
7911
7995
  );
7912
- if (upgrades && members.some(
7996
+ if (stsEnabled && !stsMode && members.some(
7913
7997
  ({ product }) => product.sellingPlanGroups?.length && product.variants.some((variant2) => oneTime.has(variant2.id))
7914
7998
  ))
7915
- return { reason: "eligible-upgrade", status: "unavailable" };
7916
- if (normalized.effective.productType !== "one-time") {
7999
+ return { reason: "eligible-sts", status: "unavailable" };
8000
+ if (normalized.effective.productType !== "one-time" || sts) {
7917
8001
  configurations.forEach((config) => PostPurchaseSubscriptionSettings.parse(config.subscription));
7918
8002
  }
8003
+ const lines = trusted.originalLineItems;
8004
+ const stsMembers = sts ? members.filter(({ product }) => postPurchaseStsLine(normalized, product, lines)) : [];
8005
+ if (stsMembers.length) return { members: identities(stsMembers), mode: "sts", status: "retain" };
7919
8006
  const classified = members.map((member) => {
7920
8007
  try {
7921
8008
  return {
@@ -7929,19 +8016,13 @@ var classifyPostPurchaseOffer = (settings, response, context) => {
7929
8016
  }
7930
8017
  });
7931
8018
  if (!members.length) return { reason: "empty", status: "skip" };
7932
- if (upgrades) return { reason: "no-eligible-subscription", status: "skip" };
8019
+ if (stsEnabled) return { reason: "no-eligible-subscription", status: "skip" };
7933
8020
  const candidates = classified.filter(
7934
8021
  ({ product }) => product.productGroupVariants.length ? readPostPurchaseGroup(product, normalized.effective, trusted.excludedProductIds).entries.length > 0 : !trusted.excludedProductIds.includes(product.id)
7935
8022
  );
7936
8023
  if (!candidates.length) return { reason: "empty", status: "skip" };
7937
8024
  const retained = candidates.filter(({ eligible }) => eligible);
7938
- return retained.length ? {
7939
- members: retained.map(({ product, productIndex }) => ({
7940
- productId: product.id,
7941
- productIndex
7942
- })),
7943
- status: "retain"
7944
- } : { reason: "no-eligible-subscription", status: "skip" };
8025
+ return retained.length ? { members: identities(retained), status: "retain" } : { reason: "no-eligible-subscription", status: "skip" };
7945
8026
  } catch {
7946
8027
  return { status: "unavailable" };
7947
8028
  }