@rebuy/rebuy 3.56.1 → 3.56.3
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.
- package/dist/index.cjs +11 -1
- package/dist/index.mjs +11 -1
- package/dist/schema/postPurchaseOfferEligibility.d.ts +19 -1
- package/dist/schema/postPurchaseProductSource.d.ts +1 -0
- package/dist/server/index.cjs +52 -31
- package/dist/server/index.mjs +52 -31
- package/dist/server/normalizePostPurchaseCollection.d.ts +5 -0
- package/dist/server/normalizePostPurchaseProduct.d.ts +3 -0
- package/dist/server/postPurchaseMemberEligibility.d.ts +11 -5
- package/dist/server/postPurchaseSts.d.ts +1 -0
- package/dist/server/postPurchaseVariantCatalog.d.ts +6 -0
- package/dist/server/preparePostPurchaseMemberView.d.ts +2 -0
- package/dist/server/preparePostPurchaseStsMember.d.ts +1 -0
- package/dist/server/projectPostPurchaseProduct.d.ts +1 -0
- package/dist/server/readPostPurchaseGroup.d.ts +1 -0
- package/dist/server/readPostPurchaseGroupSelection.d.ts +1 -0
- package/dist/server/readPostPurchaseProductSource.d.ts +5 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -206,6 +206,7 @@ __export(src_exports, {
|
|
|
206
206
|
PostPurchaseOfferEligibilityContext: () => PostPurchaseOfferEligibilityContext,
|
|
207
207
|
PostPurchaseOfferPresentation: () => PostPurchaseOfferPresentation,
|
|
208
208
|
PostPurchaseOfferSkipReason: () => PostPurchaseOfferSkipReason,
|
|
209
|
+
PostPurchaseOfferUnavailableReason: () => PostPurchaseOfferUnavailableReason,
|
|
209
210
|
PostPurchaseOptions: () => PostPurchaseOptions,
|
|
210
211
|
PostPurchaseOrderAttributes: () => PostPurchaseOrderAttributes,
|
|
211
212
|
PostPurchaseOrderIdSchema: () => PostPurchaseOrderIdSchema,
|
|
@@ -2769,6 +2770,8 @@ var Product2 = ProductBase.extend({
|
|
|
2769
2770
|
metafields: import_zod19.z.unknown().optional(),
|
|
2770
2771
|
options: import_zod19.z.unknown().optional(),
|
|
2771
2772
|
productGroupVariants: import_zod19.z.array(import_zod19.z.unknown()).default([]),
|
|
2773
|
+
// REB-25048: the v2 data source flags a subscription-only product here and sends no selling plan groups
|
|
2774
|
+
requiresSellingPlan: import_zod19.z.boolean().nullish(),
|
|
2772
2775
|
selectedVariant: import_zod19.z.unknown().optional(),
|
|
2773
2776
|
sellingPlanGroups: import_zod19.z.array(
|
|
2774
2777
|
OfferProduct.shape.sellingPlanGroups.unwrap().element.extend({
|
|
@@ -4790,6 +4793,12 @@ var OfferPreparationResponseSchema = import_zod77.z.object({
|
|
|
4790
4793
|
var import_zod78 = require("zod");
|
|
4791
4794
|
var selection2 = PreparedPostPurchaseProduct.shape.selection;
|
|
4792
4795
|
var PostPurchaseOfferSkipReason = import_zod78.z.enum(["empty", "no-eligible-subscription"]);
|
|
4796
|
+
var PostPurchaseOfferUnavailableReason = import_zod78.z.enum([
|
|
4797
|
+
"catalog-unreadable",
|
|
4798
|
+
"context-unreadable",
|
|
4799
|
+
"eligible-sts",
|
|
4800
|
+
"settings-unreadable"
|
|
4801
|
+
]);
|
|
4793
4802
|
var PostPurchaseOfferEligibilityContext = import_zod78.z.object({
|
|
4794
4803
|
excludedProductIds: PostPurchaseExcludedProductIds,
|
|
4795
4804
|
originalLineItems: import_zod78.z.array(selection2.pick({ productId: true, sellingPlanId: true, variantId: true }))
|
|
@@ -4810,7 +4819,8 @@ var PostPurchaseOfferEligibility = import_zod78.z.discriminatedUnion("status", [
|
|
|
4810
4819
|
status: import_zod78.z.literal("retain")
|
|
4811
4820
|
}),
|
|
4812
4821
|
import_zod78.z.object({ reason: PostPurchaseOfferSkipReason, status: import_zod78.z.literal("skip") }),
|
|
4813
|
-
|
|
4822
|
+
/** The classifier always names a reason; it stays optional so a reasonless answer from before still parses. */
|
|
4823
|
+
import_zod78.z.object({ reason: PostPurchaseOfferUnavailableReason.optional(), status: import_zod78.z.literal("unavailable") })
|
|
4814
4824
|
]);
|
|
4815
4825
|
|
|
4816
4826
|
// src/schema/postPurchaseOfferPresentation.ts
|
package/dist/index.mjs
CHANGED
|
@@ -2290,6 +2290,8 @@ var Product2 = ProductBase.extend({
|
|
|
2290
2290
|
metafields: z19.unknown().optional(),
|
|
2291
2291
|
options: z19.unknown().optional(),
|
|
2292
2292
|
productGroupVariants: z19.array(z19.unknown()).default([]),
|
|
2293
|
+
// REB-25048: the v2 data source flags a subscription-only product here and sends no selling plan groups
|
|
2294
|
+
requiresSellingPlan: z19.boolean().nullish(),
|
|
2293
2295
|
selectedVariant: z19.unknown().optional(),
|
|
2294
2296
|
sellingPlanGroups: z19.array(
|
|
2295
2297
|
OfferProduct.shape.sellingPlanGroups.unwrap().element.extend({
|
|
@@ -4311,6 +4313,12 @@ var OfferPreparationResponseSchema = z77.object({
|
|
|
4311
4313
|
import { z as z78 } from "zod";
|
|
4312
4314
|
var selection2 = PreparedPostPurchaseProduct.shape.selection;
|
|
4313
4315
|
var PostPurchaseOfferSkipReason = z78.enum(["empty", "no-eligible-subscription"]);
|
|
4316
|
+
var PostPurchaseOfferUnavailableReason = z78.enum([
|
|
4317
|
+
"catalog-unreadable",
|
|
4318
|
+
"context-unreadable",
|
|
4319
|
+
"eligible-sts",
|
|
4320
|
+
"settings-unreadable"
|
|
4321
|
+
]);
|
|
4314
4322
|
var PostPurchaseOfferEligibilityContext = z78.object({
|
|
4315
4323
|
excludedProductIds: PostPurchaseExcludedProductIds,
|
|
4316
4324
|
originalLineItems: z78.array(selection2.pick({ productId: true, sellingPlanId: true, variantId: true }))
|
|
@@ -4331,7 +4339,8 @@ var PostPurchaseOfferEligibility = z78.discriminatedUnion("status", [
|
|
|
4331
4339
|
status: z78.literal("retain")
|
|
4332
4340
|
}),
|
|
4333
4341
|
z78.object({ reason: PostPurchaseOfferSkipReason, status: z78.literal("skip") }),
|
|
4334
|
-
|
|
4342
|
+
/** The classifier always names a reason; it stays optional so a reasonless answer from before still parses. */
|
|
4343
|
+
z78.object({ reason: PostPurchaseOfferUnavailableReason.optional(), status: z78.literal("unavailable") })
|
|
4335
4344
|
]);
|
|
4336
4345
|
|
|
4337
4346
|
// src/schema/postPurchaseOfferPresentation.ts
|
|
@@ -6770,6 +6779,7 @@ export {
|
|
|
6770
6779
|
PostPurchaseOfferEligibilityContext,
|
|
6771
6780
|
PostPurchaseOfferPresentation,
|
|
6772
6781
|
PostPurchaseOfferSkipReason,
|
|
6782
|
+
PostPurchaseOfferUnavailableReason,
|
|
6773
6783
|
PostPurchaseOptions,
|
|
6774
6784
|
PostPurchaseOrderAttributes,
|
|
6775
6785
|
PostPurchaseOrderIdSchema,
|
|
@@ -3,6 +3,19 @@ export declare const PostPurchaseOfferSkipReason: z.ZodEnum<{
|
|
|
3
3
|
empty: "empty";
|
|
4
4
|
"no-eligible-subscription": "no-eligible-subscription";
|
|
5
5
|
}>;
|
|
6
|
+
/**
|
|
7
|
+
* Why an Offer could not be classified (REB-25054). `eligible-sts` is an STS candidate classified without the STS
|
|
8
|
+
* opt-in; each other reason names what was unreadable: the caller's context, the merchant's settings, or the
|
|
9
|
+
* catalog (the data source's products, or its metadata overrides). An ordinary product reason (sold out,
|
|
10
|
+
* plan-only, no variants, undeclared options) never answers `unavailable`: that member is ineligible instead.
|
|
11
|
+
*/
|
|
12
|
+
export declare const PostPurchaseOfferUnavailableReason: z.ZodEnum<{
|
|
13
|
+
"catalog-unreadable": "catalog-unreadable";
|
|
14
|
+
"context-unreadable": "context-unreadable";
|
|
15
|
+
"eligible-sts": "eligible-sts";
|
|
16
|
+
"settings-unreadable": "settings-unreadable";
|
|
17
|
+
}>;
|
|
18
|
+
export type PostPurchaseOfferUnavailableReason = z.infer<typeof PostPurchaseOfferUnavailableReason>;
|
|
6
19
|
export declare const PostPurchaseOfferEligibilityContext: z.ZodObject<{
|
|
7
20
|
excludedProductIds: z.ZodDefault<z.ZodArray<z.ZodNumber>>;
|
|
8
21
|
originalLineItems: z.ZodArray<z.ZodObject<{
|
|
@@ -49,7 +62,12 @@ export declare const PostPurchaseOfferEligibility: z.ZodDiscriminatedUnion<[z.Zo
|
|
|
49
62
|
}>;
|
|
50
63
|
status: z.ZodLiteral<"skip">;
|
|
51
64
|
}, z.core.$strip>, z.ZodObject<{
|
|
52
|
-
reason: z.ZodOptional<z.
|
|
65
|
+
reason: z.ZodOptional<z.ZodEnum<{
|
|
66
|
+
"catalog-unreadable": "catalog-unreadable";
|
|
67
|
+
"context-unreadable": "context-unreadable";
|
|
68
|
+
"eligible-sts": "eligible-sts";
|
|
69
|
+
"settings-unreadable": "settings-unreadable";
|
|
70
|
+
}>>;
|
|
53
71
|
status: z.ZodLiteral<"unavailable">;
|
|
54
72
|
}, z.core.$strip>], "status">;
|
|
55
73
|
export type PostPurchaseOfferEligibility = z.infer<typeof PostPurchaseOfferEligibility>;
|
|
@@ -42,6 +42,7 @@ export declare const PostPurchaseProductSource: z.ZodObject<{
|
|
|
42
42
|
metafields: z.ZodOptional<z.ZodUnknown>;
|
|
43
43
|
options: z.ZodOptional<z.ZodUnknown>;
|
|
44
44
|
productGroupVariants: z.ZodDefault<z.ZodArray<z.ZodUnknown>>;
|
|
45
|
+
requiresSellingPlan: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
45
46
|
selectedVariant: z.ZodOptional<z.ZodUnknown>;
|
|
46
47
|
sellingPlanGroups: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
47
48
|
discountAmount: z.ZodOptional<z.ZodUnknown>;
|
package/dist/server/index.cjs
CHANGED
|
@@ -6128,6 +6128,8 @@ var Product2 = ProductBase.extend({
|
|
|
6128
6128
|
metafields: import_zod43.z.unknown().optional(),
|
|
6129
6129
|
options: import_zod43.z.unknown().optional(),
|
|
6130
6130
|
productGroupVariants: import_zod43.z.array(import_zod43.z.unknown()).default([]),
|
|
6131
|
+
// REB-25048: the v2 data source flags a subscription-only product here and sends no selling plan groups
|
|
6132
|
+
requiresSellingPlan: import_zod43.z.boolean().nullish(),
|
|
6131
6133
|
selectedVariant: import_zod43.z.unknown().optional(),
|
|
6132
6134
|
sellingPlanGroups: import_zod43.z.array(
|
|
6133
6135
|
OfferProduct.shape.sellingPlanGroups.unwrap().element.extend({
|
|
@@ -6187,7 +6189,14 @@ var readPostPurchaseProductSource = (response, report) => {
|
|
|
6187
6189
|
const dropped = [];
|
|
6188
6190
|
const products = data.flatMap((raw, productIndex) => {
|
|
6189
6191
|
const parsed = Product3.safeParse(raw);
|
|
6190
|
-
if (parsed.success)
|
|
6192
|
+
if (parsed.success) {
|
|
6193
|
+
if (parsed.data.requiresSellingPlan && !parsed.data.sellingPlanGroups.length)
|
|
6194
|
+
drift.push({
|
|
6195
|
+
detail: `Dropped post-purchase product ${parsed.data.id}: data.${productIndex}.requiresSellingPlan`,
|
|
6196
|
+
kind: "product"
|
|
6197
|
+
});
|
|
6198
|
+
return [{ product: parsed.data, productIndex }];
|
|
6199
|
+
}
|
|
6191
6200
|
const id = Identified.safeParse(raw);
|
|
6192
6201
|
const issues = parsed.error.issues.map((issue) => ({ ...issue, path: ["data", productIndex, ...issue.path] }));
|
|
6193
6202
|
const path = issues[0].path.join(".");
|
|
@@ -6398,7 +6407,8 @@ var projectPostPurchasePlanCatalog = (normalized, report) => {
|
|
|
6398
6407
|
discountPercentage: postPurchasePlanDiscountPercentage(variant2.price, plan.adjustment)
|
|
6399
6408
|
})),
|
|
6400
6409
|
productId: product.id,
|
|
6401
|
-
|
|
6410
|
+
// REB-25048: a v2 product flags the requirement on itself and carries no selling plan groups
|
|
6411
|
+
requiresSellingPlan: (required[0] ?? false) || product.requiresSellingPlan === true,
|
|
6402
6412
|
variantId: variant2.id
|
|
6403
6413
|
});
|
|
6404
6414
|
} catch {
|
|
@@ -6951,7 +6961,7 @@ var oneTimeUnavailable = (normalized, allowCollection, quantity3) => {
|
|
|
6951
6961
|
return "Only fixed one-time configuration is supported";
|
|
6952
6962
|
const product = data[0];
|
|
6953
6963
|
const variant2 = product.variants[0];
|
|
6954
|
-
if (product.productGroupVariants.length || product.sellingPlanGroups?.some((group) => group.requiresSellingPlan))
|
|
6964
|
+
if (product.productGroupVariants.length || product.requiresSellingPlan === true || product.sellingPlanGroups?.some((group) => group.requiresSellingPlan))
|
|
6955
6965
|
return "A one-time variant without product groups or a required selling plan is required";
|
|
6956
6966
|
if (!postPurchaseVariantAvailable(variant2)) return VARIANT_UNAVAILABLE;
|
|
6957
6967
|
if (variant2.productId !== product.id) throw new Error("Product variant identity mismatch");
|
|
@@ -7491,11 +7501,11 @@ var PostPurchaseMemberPointer = PostPurchaseProgressSchema.shape.members.element
|
|
|
7491
7501
|
|
|
7492
7502
|
// src/server/normalizePostPurchaseCollection.ts
|
|
7493
7503
|
var import_zod82 = require("zod");
|
|
7504
|
+
var PostPurchaseProductLimit = import_zod82.z.number().int().positive();
|
|
7494
7505
|
var normalizePostPurchaseCollection = (settings, response, excludedProductIds, report) => {
|
|
7495
7506
|
const { dropped, normalized, products } = normalizePostPurchaseSource(settings, response, report);
|
|
7496
|
-
|
|
7497
|
-
|
|
7498
|
-
const cap = limit.parse(normalized.effective.productLimit);
|
|
7507
|
+
PostPurchaseProductLimit.parse(normalized.original.productLimit);
|
|
7508
|
+
const cap = PostPurchaseProductLimit.parse(normalized.effective.productLimit);
|
|
7499
7509
|
const prefix = underPostPurchaseCap(products, cap);
|
|
7500
7510
|
const unread = underPostPurchaseCap(dropped, cap);
|
|
7501
7511
|
if (unread.length && !prefix.length) throw new import_zod82.ZodError(unread.flatMap(({ issues }) => issues));
|
|
@@ -7507,6 +7517,8 @@ var normalizePostPurchaseCollection = (settings, response, excludedProductIds, r
|
|
|
7507
7517
|
};
|
|
7508
7518
|
|
|
7509
7519
|
// src/server/postPurchaseVariantCatalog.ts
|
|
7520
|
+
var PostPurchaseVariantOptionMismatch = class extends Error {
|
|
7521
|
+
};
|
|
7510
7522
|
var projectPostPurchaseVariantCatalog = (product, settings) => {
|
|
7511
7523
|
const options2 = PostPurchaseVariantCatalog.shape.options.parse(product.options === void 0 ? [] : product.options).sort((a, b) => a.position - b.position);
|
|
7512
7524
|
const variants = product.variants.map((variant2) => ({
|
|
@@ -7520,7 +7532,7 @@ var projectPostPurchaseVariantCatalog = (product, settings) => {
|
|
|
7520
7532
|
throw new Error("Ambiguous post-purchase variant catalog");
|
|
7521
7533
|
for (const tuple of tuples) {
|
|
7522
7534
|
if (options2.some(({ position, values: values2 }) => !values2.some((value) => value === tuple[position - 1])) || tuple.some((value, index) => value != null && !options2[index]))
|
|
7523
|
-
throw new
|
|
7535
|
+
throw new PostPurchaseVariantOptionMismatch("Variant option tuple does not match the catalog");
|
|
7524
7536
|
}
|
|
7525
7537
|
return PostPurchaseVariantCatalog.parse({
|
|
7526
7538
|
displayMode: settings.productOptions.variantSelectorDisplayMode,
|
|
@@ -7543,6 +7555,12 @@ var projectPostPurchaseVariantCatalog = (product, settings) => {
|
|
|
7543
7555
|
var import_zod83 = require("zod");
|
|
7544
7556
|
var selection2 = PreparedPostPurchaseProduct.shape.selection;
|
|
7545
7557
|
var PostPurchaseOfferSkipReason = import_zod83.z.enum(["empty", "no-eligible-subscription"]);
|
|
7558
|
+
var PostPurchaseOfferUnavailableReason = import_zod83.z.enum([
|
|
7559
|
+
"catalog-unreadable",
|
|
7560
|
+
"context-unreadable",
|
|
7561
|
+
"eligible-sts",
|
|
7562
|
+
"settings-unreadable"
|
|
7563
|
+
]);
|
|
7546
7564
|
var PostPurchaseOfferEligibilityContext = import_zod83.z.object({
|
|
7547
7565
|
excludedProductIds: PostPurchaseExcludedProductIds,
|
|
7548
7566
|
originalLineItems: import_zod83.z.array(selection2.pick({ productId: true, sellingPlanId: true, variantId: true }))
|
|
@@ -7563,7 +7581,8 @@ var PostPurchaseOfferEligibility = import_zod83.z.discriminatedUnion("status", [
|
|
|
7563
7581
|
status: import_zod83.z.literal("retain")
|
|
7564
7582
|
}),
|
|
7565
7583
|
import_zod83.z.object({ reason: PostPurchaseOfferSkipReason, status: import_zod83.z.literal("skip") }),
|
|
7566
|
-
|
|
7584
|
+
/** The classifier always names a reason; it stays optional so a reasonless answer from before still parses. */
|
|
7585
|
+
import_zod83.z.object({ reason: PostPurchaseOfferUnavailableReason.optional(), status: import_zod83.z.literal("unavailable") })
|
|
7567
7586
|
]);
|
|
7568
7587
|
|
|
7569
7588
|
// src/schema/postPurchaseQuantity.ts
|
|
@@ -8047,14 +8066,13 @@ var preparePostPurchaseCollectionView = (widgetId, settings, response, report, r
|
|
|
8047
8066
|
};
|
|
8048
8067
|
|
|
8049
8068
|
// src/server/postPurchaseMemberEligibility.ts
|
|
8050
|
-
var
|
|
8051
|
-
};
|
|
8052
|
-
var postPurchaseMemberEligibility = (normalized, product, excluded) => {
|
|
8069
|
+
var eligibility = (normalized, product, excluded) => {
|
|
8053
8070
|
if (product.productGroupVariants.length) {
|
|
8054
8071
|
const group = readPostPurchaseGroup(product, normalized.effective, excluded);
|
|
8072
|
+
if (!group.entries.length) return void 0;
|
|
8055
8073
|
return group.entries.map(({ product: option }) => postPurchaseMemberEligibility(normalized, option)).some(Boolean);
|
|
8056
8074
|
}
|
|
8057
|
-
if (!product.variants.length)
|
|
8075
|
+
if (!product.variants.length) return false;
|
|
8058
8076
|
const variants = projectPostPurchaseVariantCatalog(product, normalized.effective).variants;
|
|
8059
8077
|
const catalogs = product.variants.map((variant2) => {
|
|
8060
8078
|
const catalog = projectPostPurchasePlanCatalog({
|
|
@@ -8062,23 +8080,31 @@ var postPurchaseMemberEligibility = (normalized, product, excluded) => {
|
|
|
8062
8080
|
data: [{ ...product, variants: [variant2] }]
|
|
8063
8081
|
});
|
|
8064
8082
|
if (!catalog) throw new Error("Unreadable subscription catalog");
|
|
8065
|
-
if (normalized.effective.productType === "one-time" && catalog.requiresSellingPlan)
|
|
8066
|
-
throw new Error("Unsupported purchase mode");
|
|
8067
8083
|
return catalog;
|
|
8068
8084
|
});
|
|
8069
|
-
if (!variants.some((variant2) => variant2.available))
|
|
8070
|
-
throw new PostPurchaseInventoryUnavailable("Unavailable inventory");
|
|
8071
8085
|
return catalogs.some(
|
|
8072
8086
|
(catalog, index) => variants[index].available && (normalized.effective.productType !== "subscription" && !catalog.requiresSellingPlan || normalized.effective.productType !== "one-time" && catalog.plans.length > 0)
|
|
8073
8087
|
);
|
|
8074
8088
|
};
|
|
8089
|
+
var postPurchaseMemberEligibility = (normalized, product, excluded) => {
|
|
8090
|
+
try {
|
|
8091
|
+
return eligibility(normalized, product, excluded);
|
|
8092
|
+
} catch (error) {
|
|
8093
|
+
if (error instanceof PostPurchaseVariantOptionMismatch) return false;
|
|
8094
|
+
throw error;
|
|
8095
|
+
}
|
|
8096
|
+
};
|
|
8075
8097
|
|
|
8076
8098
|
// src/server/classifyPostPurchaseOffer.ts
|
|
8077
8099
|
var identities = (members) => members.map(({ product, productIndex }) => ({ productId: product.id, productIndex }));
|
|
8078
8100
|
var classifyPostPurchaseOffer = (settings, response, context, options2) => {
|
|
8101
|
+
let unreadable = "context-unreadable";
|
|
8079
8102
|
try {
|
|
8080
8103
|
const trusted = PostPurchaseOfferEligibilityContext.parse(context);
|
|
8081
8104
|
const { sts: stsMode = false } = PostPurchaseStsOptions.parse(options2 ?? {});
|
|
8105
|
+
unreadable = "settings-unreadable";
|
|
8106
|
+
PostPurchaseProductLimit.parse(PostPurchaseProductSettings.parse(deepCamelCase(settings)).productLimit);
|
|
8107
|
+
unreadable = "catalog-unreadable";
|
|
8082
8108
|
const { members, normalized } = normalizePostPurchaseCollection(settings, response);
|
|
8083
8109
|
const configurations = [normalized.original, normalized.effective];
|
|
8084
8110
|
const stsEnabled = configurations.some((config) => config.upgradeToSubscription.allow);
|
|
@@ -8091,33 +8117,28 @@ var classifyPostPurchaseOffer = (settings, response, context, options2) => {
|
|
|
8091
8117
|
))
|
|
8092
8118
|
return { reason: "eligible-sts", status: "unavailable" };
|
|
8093
8119
|
if (normalized.effective.productType !== "one-time" || sts) {
|
|
8094
|
-
|
|
8120
|
+
unreadable = "settings-unreadable";
|
|
8121
|
+
PostPurchaseSubscriptionSettings.parse(normalized.original.subscription);
|
|
8122
|
+
unreadable = "catalog-unreadable";
|
|
8123
|
+
PostPurchaseSubscriptionSettings.parse(normalized.effective.subscription);
|
|
8095
8124
|
}
|
|
8096
8125
|
const lines = trusted.originalLineItems;
|
|
8097
8126
|
const stsMembers = sts ? members.filter(({ product }) => postPurchaseStsLine(normalized, product, lines)) : [];
|
|
8098
8127
|
if (stsMembers.length) return { members: identities(stsMembers), mode: "sts", status: "retain" };
|
|
8099
|
-
const classified = members.map((member) => {
|
|
8100
|
-
|
|
8101
|
-
|
|
8102
|
-
|
|
8103
|
-
eligible: postPurchaseMemberEligibility(normalized, member.product, trusted.excludedProductIds)
|
|
8104
|
-
};
|
|
8105
|
-
} catch (error) {
|
|
8106
|
-
if (error instanceof PostPurchaseInventoryUnavailable && !member.product.productGroupVariants.length && trusted.excludedProductIds.includes(member.product.id))
|
|
8107
|
-
return { ...member, eligible: false };
|
|
8108
|
-
throw error;
|
|
8109
|
-
}
|
|
8110
|
-
});
|
|
8128
|
+
const classified = members.map((member) => ({
|
|
8129
|
+
...member,
|
|
8130
|
+
eligible: postPurchaseMemberEligibility(normalized, member.product, trusted.excludedProductIds)
|
|
8131
|
+
}));
|
|
8111
8132
|
if (!members.length) return { reason: "empty", status: "skip" };
|
|
8112
8133
|
if (stsEnabled) return { reason: "no-eligible-subscription", status: "skip" };
|
|
8113
8134
|
const candidates = classified.filter(
|
|
8114
|
-
({ product }) => product.productGroupVariants.length ?
|
|
8135
|
+
({ eligible, product }) => product.productGroupVariants.length ? eligible !== void 0 : !trusted.excludedProductIds.includes(product.id)
|
|
8115
8136
|
);
|
|
8116
8137
|
if (!candidates.length) return { reason: "empty", status: "skip" };
|
|
8117
8138
|
const retained = candidates.filter(({ eligible }) => eligible);
|
|
8118
8139
|
return retained.length ? { members: identities(retained), status: "retain" } : { reason: "no-eligible-subscription", status: "skip" };
|
|
8119
8140
|
} catch {
|
|
8120
|
-
return { status: "unavailable" };
|
|
8141
|
+
return { reason: unreadable, status: "unavailable" };
|
|
8121
8142
|
}
|
|
8122
8143
|
};
|
|
8123
8144
|
|
package/dist/server/index.mjs
CHANGED
|
@@ -6055,6 +6055,8 @@ var Product2 = ProductBase.extend({
|
|
|
6055
6055
|
metafields: z43.unknown().optional(),
|
|
6056
6056
|
options: z43.unknown().optional(),
|
|
6057
6057
|
productGroupVariants: z43.array(z43.unknown()).default([]),
|
|
6058
|
+
// REB-25048: the v2 data source flags a subscription-only product here and sends no selling plan groups
|
|
6059
|
+
requiresSellingPlan: z43.boolean().nullish(),
|
|
6058
6060
|
selectedVariant: z43.unknown().optional(),
|
|
6059
6061
|
sellingPlanGroups: z43.array(
|
|
6060
6062
|
OfferProduct.shape.sellingPlanGroups.unwrap().element.extend({
|
|
@@ -6114,7 +6116,14 @@ var readPostPurchaseProductSource = (response, report) => {
|
|
|
6114
6116
|
const dropped = [];
|
|
6115
6117
|
const products = data.flatMap((raw, productIndex) => {
|
|
6116
6118
|
const parsed = Product3.safeParse(raw);
|
|
6117
|
-
if (parsed.success)
|
|
6119
|
+
if (parsed.success) {
|
|
6120
|
+
if (parsed.data.requiresSellingPlan && !parsed.data.sellingPlanGroups.length)
|
|
6121
|
+
drift.push({
|
|
6122
|
+
detail: `Dropped post-purchase product ${parsed.data.id}: data.${productIndex}.requiresSellingPlan`,
|
|
6123
|
+
kind: "product"
|
|
6124
|
+
});
|
|
6125
|
+
return [{ product: parsed.data, productIndex }];
|
|
6126
|
+
}
|
|
6118
6127
|
const id = Identified.safeParse(raw);
|
|
6119
6128
|
const issues = parsed.error.issues.map((issue) => ({ ...issue, path: ["data", productIndex, ...issue.path] }));
|
|
6120
6129
|
const path = issues[0].path.join(".");
|
|
@@ -6325,7 +6334,8 @@ var projectPostPurchasePlanCatalog = (normalized, report) => {
|
|
|
6325
6334
|
discountPercentage: postPurchasePlanDiscountPercentage(variant2.price, plan.adjustment)
|
|
6326
6335
|
})),
|
|
6327
6336
|
productId: product.id,
|
|
6328
|
-
|
|
6337
|
+
// REB-25048: a v2 product flags the requirement on itself and carries no selling plan groups
|
|
6338
|
+
requiresSellingPlan: (required[0] ?? false) || product.requiresSellingPlan === true,
|
|
6329
6339
|
variantId: variant2.id
|
|
6330
6340
|
});
|
|
6331
6341
|
} catch {
|
|
@@ -6878,7 +6888,7 @@ var oneTimeUnavailable = (normalized, allowCollection, quantity3) => {
|
|
|
6878
6888
|
return "Only fixed one-time configuration is supported";
|
|
6879
6889
|
const product = data[0];
|
|
6880
6890
|
const variant2 = product.variants[0];
|
|
6881
|
-
if (product.productGroupVariants.length || product.sellingPlanGroups?.some((group) => group.requiresSellingPlan))
|
|
6891
|
+
if (product.productGroupVariants.length || product.requiresSellingPlan === true || product.sellingPlanGroups?.some((group) => group.requiresSellingPlan))
|
|
6882
6892
|
return "A one-time variant without product groups or a required selling plan is required";
|
|
6883
6893
|
if (!postPurchaseVariantAvailable(variant2)) return VARIANT_UNAVAILABLE;
|
|
6884
6894
|
if (variant2.productId !== product.id) throw new Error("Product variant identity mismatch");
|
|
@@ -7418,11 +7428,11 @@ var PostPurchaseMemberPointer = PostPurchaseProgressSchema.shape.members.element
|
|
|
7418
7428
|
|
|
7419
7429
|
// src/server/normalizePostPurchaseCollection.ts
|
|
7420
7430
|
import { z as z82, ZodError } from "zod";
|
|
7431
|
+
var PostPurchaseProductLimit = z82.number().int().positive();
|
|
7421
7432
|
var normalizePostPurchaseCollection = (settings, response, excludedProductIds, report) => {
|
|
7422
7433
|
const { dropped, normalized, products } = normalizePostPurchaseSource(settings, response, report);
|
|
7423
|
-
|
|
7424
|
-
|
|
7425
|
-
const cap = limit.parse(normalized.effective.productLimit);
|
|
7434
|
+
PostPurchaseProductLimit.parse(normalized.original.productLimit);
|
|
7435
|
+
const cap = PostPurchaseProductLimit.parse(normalized.effective.productLimit);
|
|
7426
7436
|
const prefix = underPostPurchaseCap(products, cap);
|
|
7427
7437
|
const unread = underPostPurchaseCap(dropped, cap);
|
|
7428
7438
|
if (unread.length && !prefix.length) throw new ZodError(unread.flatMap(({ issues }) => issues));
|
|
@@ -7434,6 +7444,8 @@ var normalizePostPurchaseCollection = (settings, response, excludedProductIds, r
|
|
|
7434
7444
|
};
|
|
7435
7445
|
|
|
7436
7446
|
// src/server/postPurchaseVariantCatalog.ts
|
|
7447
|
+
var PostPurchaseVariantOptionMismatch = class extends Error {
|
|
7448
|
+
};
|
|
7437
7449
|
var projectPostPurchaseVariantCatalog = (product, settings) => {
|
|
7438
7450
|
const options2 = PostPurchaseVariantCatalog.shape.options.parse(product.options === void 0 ? [] : product.options).sort((a, b) => a.position - b.position);
|
|
7439
7451
|
const variants = product.variants.map((variant2) => ({
|
|
@@ -7447,7 +7459,7 @@ var projectPostPurchaseVariantCatalog = (product, settings) => {
|
|
|
7447
7459
|
throw new Error("Ambiguous post-purchase variant catalog");
|
|
7448
7460
|
for (const tuple of tuples) {
|
|
7449
7461
|
if (options2.some(({ position, values: values2 }) => !values2.some((value) => value === tuple[position - 1])) || tuple.some((value, index) => value != null && !options2[index]))
|
|
7450
|
-
throw new
|
|
7462
|
+
throw new PostPurchaseVariantOptionMismatch("Variant option tuple does not match the catalog");
|
|
7451
7463
|
}
|
|
7452
7464
|
return PostPurchaseVariantCatalog.parse({
|
|
7453
7465
|
displayMode: settings.productOptions.variantSelectorDisplayMode,
|
|
@@ -7470,6 +7482,12 @@ var projectPostPurchaseVariantCatalog = (product, settings) => {
|
|
|
7470
7482
|
import { z as z83 } from "zod";
|
|
7471
7483
|
var selection2 = PreparedPostPurchaseProduct.shape.selection;
|
|
7472
7484
|
var PostPurchaseOfferSkipReason = z83.enum(["empty", "no-eligible-subscription"]);
|
|
7485
|
+
var PostPurchaseOfferUnavailableReason = z83.enum([
|
|
7486
|
+
"catalog-unreadable",
|
|
7487
|
+
"context-unreadable",
|
|
7488
|
+
"eligible-sts",
|
|
7489
|
+
"settings-unreadable"
|
|
7490
|
+
]);
|
|
7473
7491
|
var PostPurchaseOfferEligibilityContext = z83.object({
|
|
7474
7492
|
excludedProductIds: PostPurchaseExcludedProductIds,
|
|
7475
7493
|
originalLineItems: z83.array(selection2.pick({ productId: true, sellingPlanId: true, variantId: true }))
|
|
@@ -7490,7 +7508,8 @@ var PostPurchaseOfferEligibility = z83.discriminatedUnion("status", [
|
|
|
7490
7508
|
status: z83.literal("retain")
|
|
7491
7509
|
}),
|
|
7492
7510
|
z83.object({ reason: PostPurchaseOfferSkipReason, status: z83.literal("skip") }),
|
|
7493
|
-
|
|
7511
|
+
/** The classifier always names a reason; it stays optional so a reasonless answer from before still parses. */
|
|
7512
|
+
z83.object({ reason: PostPurchaseOfferUnavailableReason.optional(), status: z83.literal("unavailable") })
|
|
7494
7513
|
]);
|
|
7495
7514
|
|
|
7496
7515
|
// src/schema/postPurchaseQuantity.ts
|
|
@@ -7974,14 +7993,13 @@ var preparePostPurchaseCollectionView = (widgetId, settings, response, report, r
|
|
|
7974
7993
|
};
|
|
7975
7994
|
|
|
7976
7995
|
// src/server/postPurchaseMemberEligibility.ts
|
|
7977
|
-
var
|
|
7978
|
-
};
|
|
7979
|
-
var postPurchaseMemberEligibility = (normalized, product, excluded) => {
|
|
7996
|
+
var eligibility = (normalized, product, excluded) => {
|
|
7980
7997
|
if (product.productGroupVariants.length) {
|
|
7981
7998
|
const group = readPostPurchaseGroup(product, normalized.effective, excluded);
|
|
7999
|
+
if (!group.entries.length) return void 0;
|
|
7982
8000
|
return group.entries.map(({ product: option }) => postPurchaseMemberEligibility(normalized, option)).some(Boolean);
|
|
7983
8001
|
}
|
|
7984
|
-
if (!product.variants.length)
|
|
8002
|
+
if (!product.variants.length) return false;
|
|
7985
8003
|
const variants = projectPostPurchaseVariantCatalog(product, normalized.effective).variants;
|
|
7986
8004
|
const catalogs = product.variants.map((variant2) => {
|
|
7987
8005
|
const catalog = projectPostPurchasePlanCatalog({
|
|
@@ -7989,23 +8007,31 @@ var postPurchaseMemberEligibility = (normalized, product, excluded) => {
|
|
|
7989
8007
|
data: [{ ...product, variants: [variant2] }]
|
|
7990
8008
|
});
|
|
7991
8009
|
if (!catalog) throw new Error("Unreadable subscription catalog");
|
|
7992
|
-
if (normalized.effective.productType === "one-time" && catalog.requiresSellingPlan)
|
|
7993
|
-
throw new Error("Unsupported purchase mode");
|
|
7994
8010
|
return catalog;
|
|
7995
8011
|
});
|
|
7996
|
-
if (!variants.some((variant2) => variant2.available))
|
|
7997
|
-
throw new PostPurchaseInventoryUnavailable("Unavailable inventory");
|
|
7998
8012
|
return catalogs.some(
|
|
7999
8013
|
(catalog, index) => variants[index].available && (normalized.effective.productType !== "subscription" && !catalog.requiresSellingPlan || normalized.effective.productType !== "one-time" && catalog.plans.length > 0)
|
|
8000
8014
|
);
|
|
8001
8015
|
};
|
|
8016
|
+
var postPurchaseMemberEligibility = (normalized, product, excluded) => {
|
|
8017
|
+
try {
|
|
8018
|
+
return eligibility(normalized, product, excluded);
|
|
8019
|
+
} catch (error) {
|
|
8020
|
+
if (error instanceof PostPurchaseVariantOptionMismatch) return false;
|
|
8021
|
+
throw error;
|
|
8022
|
+
}
|
|
8023
|
+
};
|
|
8002
8024
|
|
|
8003
8025
|
// src/server/classifyPostPurchaseOffer.ts
|
|
8004
8026
|
var identities = (members) => members.map(({ product, productIndex }) => ({ productId: product.id, productIndex }));
|
|
8005
8027
|
var classifyPostPurchaseOffer = (settings, response, context, options2) => {
|
|
8028
|
+
let unreadable = "context-unreadable";
|
|
8006
8029
|
try {
|
|
8007
8030
|
const trusted = PostPurchaseOfferEligibilityContext.parse(context);
|
|
8008
8031
|
const { sts: stsMode = false } = PostPurchaseStsOptions.parse(options2 ?? {});
|
|
8032
|
+
unreadable = "settings-unreadable";
|
|
8033
|
+
PostPurchaseProductLimit.parse(PostPurchaseProductSettings.parse(deepCamelCase(settings)).productLimit);
|
|
8034
|
+
unreadable = "catalog-unreadable";
|
|
8009
8035
|
const { members, normalized } = normalizePostPurchaseCollection(settings, response);
|
|
8010
8036
|
const configurations = [normalized.original, normalized.effective];
|
|
8011
8037
|
const stsEnabled = configurations.some((config) => config.upgradeToSubscription.allow);
|
|
@@ -8018,33 +8044,28 @@ var classifyPostPurchaseOffer = (settings, response, context, options2) => {
|
|
|
8018
8044
|
))
|
|
8019
8045
|
return { reason: "eligible-sts", status: "unavailable" };
|
|
8020
8046
|
if (normalized.effective.productType !== "one-time" || sts) {
|
|
8021
|
-
|
|
8047
|
+
unreadable = "settings-unreadable";
|
|
8048
|
+
PostPurchaseSubscriptionSettings.parse(normalized.original.subscription);
|
|
8049
|
+
unreadable = "catalog-unreadable";
|
|
8050
|
+
PostPurchaseSubscriptionSettings.parse(normalized.effective.subscription);
|
|
8022
8051
|
}
|
|
8023
8052
|
const lines = trusted.originalLineItems;
|
|
8024
8053
|
const stsMembers = sts ? members.filter(({ product }) => postPurchaseStsLine(normalized, product, lines)) : [];
|
|
8025
8054
|
if (stsMembers.length) return { members: identities(stsMembers), mode: "sts", status: "retain" };
|
|
8026
|
-
const classified = members.map((member) => {
|
|
8027
|
-
|
|
8028
|
-
|
|
8029
|
-
|
|
8030
|
-
eligible: postPurchaseMemberEligibility(normalized, member.product, trusted.excludedProductIds)
|
|
8031
|
-
};
|
|
8032
|
-
} catch (error) {
|
|
8033
|
-
if (error instanceof PostPurchaseInventoryUnavailable && !member.product.productGroupVariants.length && trusted.excludedProductIds.includes(member.product.id))
|
|
8034
|
-
return { ...member, eligible: false };
|
|
8035
|
-
throw error;
|
|
8036
|
-
}
|
|
8037
|
-
});
|
|
8055
|
+
const classified = members.map((member) => ({
|
|
8056
|
+
...member,
|
|
8057
|
+
eligible: postPurchaseMemberEligibility(normalized, member.product, trusted.excludedProductIds)
|
|
8058
|
+
}));
|
|
8038
8059
|
if (!members.length) return { reason: "empty", status: "skip" };
|
|
8039
8060
|
if (stsEnabled) return { reason: "no-eligible-subscription", status: "skip" };
|
|
8040
8061
|
const candidates = classified.filter(
|
|
8041
|
-
({ product }) => product.productGroupVariants.length ?
|
|
8062
|
+
({ eligible, product }) => product.productGroupVariants.length ? eligible !== void 0 : !trusted.excludedProductIds.includes(product.id)
|
|
8042
8063
|
);
|
|
8043
8064
|
if (!candidates.length) return { reason: "empty", status: "skip" };
|
|
8044
8065
|
const retained = candidates.filter(({ eligible }) => eligible);
|
|
8045
8066
|
return retained.length ? { members: identities(retained), status: "retain" } : { reason: "no-eligible-subscription", status: "skip" };
|
|
8046
8067
|
} catch {
|
|
8047
|
-
return { status: "unavailable" };
|
|
8068
|
+
return { reason: unreadable, status: "unavailable" };
|
|
8048
8069
|
}
|
|
8049
8070
|
};
|
|
8050
8071
|
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
1
2
|
import { PostPurchaseExcludedProductIds } from '../schema/postPurchaseProductCollectionView';
|
|
2
3
|
import type { Reporter } from '../server/shared';
|
|
4
|
+
/** A collection's `productLimit`, original or effective: a positive whole number. */
|
|
5
|
+
export declare const PostPurchaseProductLimit: z.ZodNumber;
|
|
3
6
|
/**
|
|
4
7
|
* Preserve the original capped positions before applying product-wide exclusions. `productLimit` caps raw
|
|
5
8
|
* positions, and a member's `productIndex` is its raw position: a product the schema dropped leaves its slot
|
|
@@ -51,6 +54,7 @@ export declare const normalizePostPurchaseCollection: (settings: unknown, respon
|
|
|
51
54
|
} | undefined;
|
|
52
55
|
metafields?: unknown;
|
|
53
56
|
options?: unknown;
|
|
57
|
+
requiresSellingPlan?: boolean | null | undefined;
|
|
54
58
|
selectedVariant?: unknown;
|
|
55
59
|
};
|
|
56
60
|
productIndex: number;
|
|
@@ -96,6 +100,7 @@ export declare const normalizePostPurchaseCollection: (settings: unknown, respon
|
|
|
96
100
|
} | undefined;
|
|
97
101
|
metafields?: unknown;
|
|
98
102
|
options?: unknown;
|
|
103
|
+
requiresSellingPlan?: boolean | null | undefined;
|
|
99
104
|
selectedVariant?: unknown;
|
|
100
105
|
}[];
|
|
101
106
|
effective: {
|
|
@@ -52,6 +52,7 @@ export declare const normalizePostPurchaseSource: (settings: unknown, response:
|
|
|
52
52
|
} | undefined;
|
|
53
53
|
metafields?: unknown;
|
|
54
54
|
options?: unknown;
|
|
55
|
+
requiresSellingPlan?: boolean | null | undefined;
|
|
55
56
|
selectedVariant?: unknown;
|
|
56
57
|
}[];
|
|
57
58
|
effective: {
|
|
@@ -254,6 +255,7 @@ export declare const normalizePostPurchaseSource: (settings: unknown, response:
|
|
|
254
255
|
} | undefined;
|
|
255
256
|
metafields?: unknown;
|
|
256
257
|
options?: unknown;
|
|
258
|
+
requiresSellingPlan?: boolean | null | undefined;
|
|
257
259
|
selectedVariant?: unknown;
|
|
258
260
|
};
|
|
259
261
|
productIndex: number;
|
|
@@ -317,6 +319,7 @@ export declare const normalizePostPurchaseProduct: (settings: unknown, response:
|
|
|
317
319
|
} | undefined;
|
|
318
320
|
metafields?: unknown;
|
|
319
321
|
options?: unknown;
|
|
322
|
+
requiresSellingPlan?: boolean | null | undefined;
|
|
320
323
|
selectedVariant?: unknown;
|
|
321
324
|
}[];
|
|
322
325
|
effective: {
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import type { PostPurchaseExcludedProductIds } from '../schema/postPurchaseProductCollectionView';
|
|
2
2
|
import type { normalizePostPurchaseProduct } from '../server/normalizePostPurchaseProduct';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
type Normalized = ReturnType<typeof normalizePostPurchaseProduct>;
|
|
4
|
+
/**
|
|
5
|
+
* Catalog facts only: preparation still owns defaults, quantity, terms, and presentation. `false` is an ordinary
|
|
6
|
+
* product reason (REB-25054): no available variant, plan-only on a one-time Offer, or option values the product
|
|
7
|
+
* does not declare, for the member or, for a group, every sibling. A sibling with undeclared options leaves its
|
|
8
|
+
* whole group ineligible, as preparation cannot read that group either. `undefined` is a group whose every
|
|
9
|
+
* sibling is excluded, so nothing is left to offer; the group is read before exclusions apply, though, so an
|
|
10
|
+
* excluded sibling with undeclared options still answers `false`. A throw is unreadable data.
|
|
11
|
+
*/
|
|
12
|
+
export declare const postPurchaseMemberEligibility: (normalized: Normalized, product: Normalized["data"][number], excluded?: PostPurchaseExcludedProductIds) => boolean | undefined;
|
|
13
|
+
export {};
|
|
@@ -1,3 +1,9 @@
|
|
|
1
1
|
import { PostPurchaseVariantCatalog } from '../schema/postPurchaseVariantCatalog';
|
|
2
2
|
import type { normalizePostPurchaseProduct } from '../server/normalizePostPurchaseProduct';
|
|
3
|
+
/**
|
|
4
|
+
* A variant carries an option value its product does not declare (an optionless product, say): the merchandise is
|
|
5
|
+
* readable but cannot be offered as it stands, so member eligibility leaves it out rather than failing the Offer.
|
|
6
|
+
*/
|
|
7
|
+
export declare class PostPurchaseVariantOptionMismatch extends Error {
|
|
8
|
+
}
|
|
3
9
|
export declare const projectPostPurchaseVariantCatalog: (product: ReturnType<typeof normalizePostPurchaseProduct>["data"][number], settings: ReturnType<typeof normalizePostPurchaseProduct>["effective"]) => PostPurchaseVariantCatalog;
|
|
@@ -651,6 +651,7 @@ export declare const prepareMember: (widgetId: number, settings: unknown, respon
|
|
|
651
651
|
} | undefined;
|
|
652
652
|
metafields?: unknown;
|
|
653
653
|
options?: unknown;
|
|
654
|
+
requiresSellingPlan?: boolean | null | undefined;
|
|
654
655
|
selectedVariant?: unknown;
|
|
655
656
|
}[];
|
|
656
657
|
effective: {
|
|
@@ -1468,6 +1469,7 @@ export declare const prepareMember: (widgetId: number, settings: unknown, respon
|
|
|
1468
1469
|
} | undefined;
|
|
1469
1470
|
metafields?: unknown;
|
|
1470
1471
|
options?: unknown;
|
|
1472
|
+
requiresSellingPlan?: boolean | null | undefined;
|
|
1471
1473
|
selectedVariant?: unknown;
|
|
1472
1474
|
}[];
|
|
1473
1475
|
effective: {
|
|
@@ -656,6 +656,7 @@ export declare const preparePostPurchaseStsMember: (widgetId: number, settings:
|
|
|
656
656
|
} | undefined;
|
|
657
657
|
metafields?: unknown;
|
|
658
658
|
options?: unknown;
|
|
659
|
+
requiresSellingPlan?: boolean | null | undefined;
|
|
659
660
|
selectedVariant?: unknown;
|
|
660
661
|
}[];
|
|
661
662
|
effective: {
|
|
@@ -159,6 +159,7 @@ export declare const projectPostPurchaseProduct: ({ data, effective, metadata, o
|
|
|
159
159
|
} | undefined;
|
|
160
160
|
metafields?: unknown;
|
|
161
161
|
options?: unknown;
|
|
162
|
+
requiresSellingPlan?: boolean | null | undefined;
|
|
162
163
|
selectedVariant?: unknown;
|
|
163
164
|
};
|
|
164
165
|
selection: {
|
|
@@ -75,6 +75,7 @@ export declare const readPostPurchaseGroup: (product: ReturnType<typeof normaliz
|
|
|
75
75
|
productQuantity?: number | undefined;
|
|
76
76
|
} | undefined;
|
|
77
77
|
metafields?: unknown;
|
|
78
|
+
requiresSellingPlan?: boolean | null | undefined;
|
|
78
79
|
selectedVariant?: unknown;
|
|
79
80
|
};
|
|
80
81
|
variantCatalog: {
|
|
@@ -81,6 +81,7 @@ export declare const readPostPurchaseGroupSelection: (settings: unknown, respons
|
|
|
81
81
|
productQuantity?: number | undefined;
|
|
82
82
|
} | undefined;
|
|
83
83
|
metafields?: unknown;
|
|
84
|
+
requiresSellingPlan?: boolean | null | undefined;
|
|
84
85
|
selectedVariant?: unknown;
|
|
85
86
|
}[];
|
|
86
87
|
metadata: {
|
|
@@ -9,6 +9,10 @@ import type { Reporter } from '../server/shared';
|
|
|
9
9
|
* one request (a re-parse or clone per projection reports the drops again). The envelope (an object, `data`
|
|
10
10
|
* an array, readable `metadata`) still throws.
|
|
11
11
|
*
|
|
12
|
+
* A product that parses but requires a selling plan on itself with no selling plan groups (a v2 subscription-only
|
|
13
|
+
* product, REB-25048) is kept for eligibility to drop, and reported here as the same once-per-response drift,
|
|
14
|
+
* naming its `requiresSellingPlan` path: it has no plan to sell it with and may never be sold one-time.
|
|
15
|
+
*
|
|
12
16
|
* Every survivor keeps `productIndex`, its position in the raw `data` array: Decision, Render and Offer
|
|
13
17
|
* members identify a product by that index, so a drop never renumbers the products after it. `dropped` keeps
|
|
14
18
|
* each drop's `productIndex` and its zod issues with paths from the source root, so a caller can fail a source
|
|
@@ -63,6 +67,7 @@ export declare const readPostPurchaseProductSource: (response: unknown, report?:
|
|
|
63
67
|
} | undefined;
|
|
64
68
|
metafields?: unknown;
|
|
65
69
|
options?: unknown;
|
|
70
|
+
requiresSellingPlan?: boolean | null | undefined;
|
|
66
71
|
selectedVariant?: unknown;
|
|
67
72
|
};
|
|
68
73
|
productIndex: number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rebuy/rebuy",
|
|
3
|
-
"version": "3.56.
|
|
3
|
+
"version": "3.56.3",
|
|
4
4
|
"description": "Shared zod schemas, legacy-to-CAB widget transforms, and server orchestrators for Rebuy's Shopify consumers (rebuy-api, admin-nextjs, rebuy-shopify-extensions)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Rebuy, Inc.",
|