@rebuy/rebuy 3.56.2 → 3.57.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.
- package/dist/index.cjs +9 -1
- package/dist/index.mjs +9 -1
- package/dist/schema/postPurchaseOfferEligibility.d.ts +19 -1
- package/dist/server/classifyPostPurchaseOffer.d.ts +4 -1
- package/dist/server/index.cjs +83 -45
- package/dist/server/index.mjs +83 -45
- package/dist/server/normalizePostPurchaseCollection.d.ts +3 -0
- package/dist/server/postPurchaseMemberEligibility.d.ts +11 -5
- package/dist/server/postPurchaseModernPlans.d.ts +5 -0
- package/dist/server/postPurchaseResponseDrift.d.ts +13 -0
- package/dist/server/postPurchaseSts.d.ts +7 -1
- package/dist/server/postPurchaseVariantCatalog.d.ts +6 -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,
|
|
@@ -4792,6 +4793,12 @@ var OfferPreparationResponseSchema = import_zod77.z.object({
|
|
|
4792
4793
|
var import_zod78 = require("zod");
|
|
4793
4794
|
var selection2 = PreparedPostPurchaseProduct.shape.selection;
|
|
4794
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
|
+
]);
|
|
4795
4802
|
var PostPurchaseOfferEligibilityContext = import_zod78.z.object({
|
|
4796
4803
|
excludedProductIds: PostPurchaseExcludedProductIds,
|
|
4797
4804
|
originalLineItems: import_zod78.z.array(selection2.pick({ productId: true, sellingPlanId: true, variantId: true }))
|
|
@@ -4812,7 +4819,8 @@ var PostPurchaseOfferEligibility = import_zod78.z.discriminatedUnion("status", [
|
|
|
4812
4819
|
status: import_zod78.z.literal("retain")
|
|
4813
4820
|
}),
|
|
4814
4821
|
import_zod78.z.object({ reason: PostPurchaseOfferSkipReason, status: import_zod78.z.literal("skip") }),
|
|
4815
|
-
|
|
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") })
|
|
4816
4824
|
]);
|
|
4817
4825
|
|
|
4818
4826
|
// src/schema/postPurchaseOfferPresentation.ts
|
package/dist/index.mjs
CHANGED
|
@@ -4313,6 +4313,12 @@ var OfferPreparationResponseSchema = z77.object({
|
|
|
4313
4313
|
import { z as z78 } from "zod";
|
|
4314
4314
|
var selection2 = PreparedPostPurchaseProduct.shape.selection;
|
|
4315
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
|
+
]);
|
|
4316
4322
|
var PostPurchaseOfferEligibilityContext = z78.object({
|
|
4317
4323
|
excludedProductIds: PostPurchaseExcludedProductIds,
|
|
4318
4324
|
originalLineItems: z78.array(selection2.pick({ productId: true, sellingPlanId: true, variantId: true }))
|
|
@@ -4333,7 +4339,8 @@ var PostPurchaseOfferEligibility = z78.discriminatedUnion("status", [
|
|
|
4333
4339
|
status: z78.literal("retain")
|
|
4334
4340
|
}),
|
|
4335
4341
|
z78.object({ reason: PostPurchaseOfferSkipReason, status: z78.literal("skip") }),
|
|
4336
|
-
|
|
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") })
|
|
4337
4344
|
]);
|
|
4338
4345
|
|
|
4339
4346
|
// src/schema/postPurchaseOfferPresentation.ts
|
|
@@ -6772,6 +6779,7 @@ export {
|
|
|
6772
6779
|
PostPurchaseOfferEligibilityContext,
|
|
6773
6780
|
PostPurchaseOfferPresentation,
|
|
6774
6781
|
PostPurchaseOfferSkipReason,
|
|
6782
|
+
PostPurchaseOfferUnavailableReason,
|
|
6775
6783
|
PostPurchaseOptions,
|
|
6776
6784
|
PostPurchaseOrderAttributes,
|
|
6777
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>;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { type z } from 'zod';
|
|
2
2
|
import { type PostPurchaseOfferEligibility, PostPurchaseOfferEligibilityContext, PostPurchaseStsOptions } from '../schema/postPurchaseOfferEligibility';
|
|
3
|
+
import type { Reporter } from '../server/shared';
|
|
3
4
|
export declare const classifyPostPurchaseOffer: (settings: unknown, response: unknown, context: z.input<typeof PostPurchaseOfferEligibilityContext>,
|
|
4
5
|
/** STS opt-in; absent or `{ sts: false }` keeps every pre-STS outcome. */
|
|
5
|
-
options?: PostPurchaseStsOptions
|
|
6
|
+
options?: PostPurchaseStsOptions,
|
|
7
|
+
/** Hears each purchased STS candidate whose plan data cannot be read, once per response (REB-25050). */
|
|
8
|
+
report?: Reporter) => PostPurchaseOfferEligibility;
|
package/dist/server/index.cjs
CHANGED
|
@@ -6172,17 +6172,30 @@ var PostPurchaseProductSettings = PostPurchaseSettings.pick({
|
|
|
6172
6172
|
|
|
6173
6173
|
// src/server/readPostPurchaseProductSource.ts
|
|
6174
6174
|
var import_zod45 = require("zod");
|
|
6175
|
-
|
|
6176
|
-
|
|
6177
|
-
var Identified = import_zod45.z.object({ id: PostPurchaseProductId });
|
|
6175
|
+
|
|
6176
|
+
// src/server/postPurchaseResponseDrift.ts
|
|
6178
6177
|
var heard = /* @__PURE__ */ new WeakMap();
|
|
6179
|
-
var
|
|
6180
|
-
|
|
6178
|
+
var sources = /* @__PURE__ */ new WeakMap();
|
|
6179
|
+
var rememberPostPurchaseProductSource = (product, response, productIndex) => {
|
|
6180
|
+
sources.set(product, { productIndex, response });
|
|
6181
|
+
};
|
|
6182
|
+
var postPurchaseProductSourceOf = (product) => sources.get(product);
|
|
6183
|
+
var reportOncePerResponse = (response, report, events) => {
|
|
6184
|
+
const reporters = heard.get(response) ?? /* @__PURE__ */ new WeakMap();
|
|
6181
6185
|
heard.set(response, reporters);
|
|
6182
|
-
|
|
6183
|
-
reporters.
|
|
6184
|
-
|
|
6186
|
+
const details = reporters.get(report) ?? /* @__PURE__ */ new Set();
|
|
6187
|
+
reporters.set(report, details);
|
|
6188
|
+
for (const event of events) {
|
|
6189
|
+
if (details.has(event.detail)) continue;
|
|
6190
|
+
details.add(event.detail);
|
|
6191
|
+
report(event);
|
|
6192
|
+
}
|
|
6185
6193
|
};
|
|
6194
|
+
|
|
6195
|
+
// src/server/readPostPurchaseProductSource.ts
|
|
6196
|
+
var Envelope = PostPurchaseProductSource.extend({ data: import_zod45.z.array(import_zod45.z.unknown()) });
|
|
6197
|
+
var Product3 = PostPurchaseProductSource.shape.data.element;
|
|
6198
|
+
var Identified = import_zod45.z.object({ id: PostPurchaseProductId });
|
|
6186
6199
|
var readPostPurchaseProductSource = (response, report) => {
|
|
6187
6200
|
const { data, metadata } = Envelope.parse(deepCamelCase(response));
|
|
6188
6201
|
const drift = [];
|
|
@@ -6190,6 +6203,7 @@ var readPostPurchaseProductSource = (response, report) => {
|
|
|
6190
6203
|
const products = data.flatMap((raw, productIndex) => {
|
|
6191
6204
|
const parsed = Product3.safeParse(raw);
|
|
6192
6205
|
if (parsed.success) {
|
|
6206
|
+
rememberPostPurchaseProductSource(parsed.data, response, productIndex);
|
|
6193
6207
|
if (parsed.data.requiresSellingPlan && !parsed.data.sellingPlanGroups.length)
|
|
6194
6208
|
drift.push({
|
|
6195
6209
|
detail: `Dropped post-purchase product ${parsed.data.id}: data.${productIndex}.requiresSellingPlan`,
|
|
@@ -6207,7 +6221,7 @@ var readPostPurchaseProductSource = (response, report) => {
|
|
|
6207
6221
|
});
|
|
6208
6222
|
return [];
|
|
6209
6223
|
});
|
|
6210
|
-
if (report && drift.length
|
|
6224
|
+
if (report && drift.length) reportOncePerResponse(response, report, drift);
|
|
6211
6225
|
return { dropped, metadata, products };
|
|
6212
6226
|
};
|
|
6213
6227
|
|
|
@@ -6353,7 +6367,8 @@ var Groups = import_zod52.z.array(
|
|
|
6353
6367
|
sellingPlans: import_zod52.z.unknown()
|
|
6354
6368
|
})
|
|
6355
6369
|
);
|
|
6356
|
-
var
|
|
6370
|
+
var PostPurchasePlanAllocations = import_zod52.z.array(import_zod52.z.object({ sellingPlanGroupId: import_zod52.z.string().min(1) }));
|
|
6371
|
+
var Allocations = PostPurchasePlanAllocations.default([]);
|
|
6357
6372
|
var Plans = import_zod52.z.array(
|
|
6358
6373
|
PostPurchasePlanOption.pick({ id: true, name: true }).extend({
|
|
6359
6374
|
options: import_zod52.z.array(import_zod52.z.object({ value: import_zod52.z.string().min(1) })).min(1),
|
|
@@ -7501,11 +7516,11 @@ var PostPurchaseMemberPointer = PostPurchaseProgressSchema.shape.members.element
|
|
|
7501
7516
|
|
|
7502
7517
|
// src/server/normalizePostPurchaseCollection.ts
|
|
7503
7518
|
var import_zod82 = require("zod");
|
|
7519
|
+
var PostPurchaseProductLimit = import_zod82.z.number().int().positive();
|
|
7504
7520
|
var normalizePostPurchaseCollection = (settings, response, excludedProductIds, report) => {
|
|
7505
7521
|
const { dropped, normalized, products } = normalizePostPurchaseSource(settings, response, report);
|
|
7506
|
-
|
|
7507
|
-
|
|
7508
|
-
const cap = limit.parse(normalized.effective.productLimit);
|
|
7522
|
+
PostPurchaseProductLimit.parse(normalized.original.productLimit);
|
|
7523
|
+
const cap = PostPurchaseProductLimit.parse(normalized.effective.productLimit);
|
|
7509
7524
|
const prefix = underPostPurchaseCap(products, cap);
|
|
7510
7525
|
const unread = underPostPurchaseCap(dropped, cap);
|
|
7511
7526
|
if (unread.length && !prefix.length) throw new import_zod82.ZodError(unread.flatMap(({ issues }) => issues));
|
|
@@ -7517,6 +7532,8 @@ var normalizePostPurchaseCollection = (settings, response, excludedProductIds, r
|
|
|
7517
7532
|
};
|
|
7518
7533
|
|
|
7519
7534
|
// src/server/postPurchaseVariantCatalog.ts
|
|
7535
|
+
var PostPurchaseVariantOptionMismatch = class extends Error {
|
|
7536
|
+
};
|
|
7520
7537
|
var projectPostPurchaseVariantCatalog = (product, settings) => {
|
|
7521
7538
|
const options2 = PostPurchaseVariantCatalog.shape.options.parse(product.options === void 0 ? [] : product.options).sort((a, b) => a.position - b.position);
|
|
7522
7539
|
const variants = product.variants.map((variant2) => ({
|
|
@@ -7530,7 +7547,7 @@ var projectPostPurchaseVariantCatalog = (product, settings) => {
|
|
|
7530
7547
|
throw new Error("Ambiguous post-purchase variant catalog");
|
|
7531
7548
|
for (const tuple of tuples) {
|
|
7532
7549
|
if (options2.some(({ position, values: values2 }) => !values2.some((value) => value === tuple[position - 1])) || tuple.some((value, index) => value != null && !options2[index]))
|
|
7533
|
-
throw new
|
|
7550
|
+
throw new PostPurchaseVariantOptionMismatch("Variant option tuple does not match the catalog");
|
|
7534
7551
|
}
|
|
7535
7552
|
return PostPurchaseVariantCatalog.parse({
|
|
7536
7553
|
displayMode: settings.productOptions.variantSelectorDisplayMode,
|
|
@@ -7553,6 +7570,12 @@ var projectPostPurchaseVariantCatalog = (product, settings) => {
|
|
|
7553
7570
|
var import_zod83 = require("zod");
|
|
7554
7571
|
var selection2 = PreparedPostPurchaseProduct.shape.selection;
|
|
7555
7572
|
var PostPurchaseOfferSkipReason = import_zod83.z.enum(["empty", "no-eligible-subscription"]);
|
|
7573
|
+
var PostPurchaseOfferUnavailableReason = import_zod83.z.enum([
|
|
7574
|
+
"catalog-unreadable",
|
|
7575
|
+
"context-unreadable",
|
|
7576
|
+
"eligible-sts",
|
|
7577
|
+
"settings-unreadable"
|
|
7578
|
+
]);
|
|
7556
7579
|
var PostPurchaseOfferEligibilityContext = import_zod83.z.object({
|
|
7557
7580
|
excludedProductIds: PostPurchaseExcludedProductIds,
|
|
7558
7581
|
originalLineItems: import_zod83.z.array(selection2.pick({ productId: true, sellingPlanId: true, variantId: true }))
|
|
@@ -7573,7 +7596,8 @@ var PostPurchaseOfferEligibility = import_zod83.z.discriminatedUnion("status", [
|
|
|
7573
7596
|
status: import_zod83.z.literal("retain")
|
|
7574
7597
|
}),
|
|
7575
7598
|
import_zod83.z.object({ reason: PostPurchaseOfferSkipReason, status: import_zod83.z.literal("skip") }),
|
|
7576
|
-
|
|
7599
|
+
/** The classifier always names a reason; it stays optional so a reasonless answer from before still parses. */
|
|
7600
|
+
import_zod83.z.object({ reason: PostPurchaseOfferUnavailableReason.optional(), status: import_zod83.z.literal("unavailable") })
|
|
7577
7601
|
]);
|
|
7578
7602
|
|
|
7579
7603
|
// src/schema/postPurchaseQuantity.ts
|
|
@@ -7615,18 +7639,30 @@ var readPostPurchaseQuantity = ({
|
|
|
7615
7639
|
|
|
7616
7640
|
// src/server/postPurchaseSts.ts
|
|
7617
7641
|
var stsAllowed = ({ effective, original }) => [original, effective].some((config) => config.upgradeToSubscription.allow);
|
|
7618
|
-
var
|
|
7642
|
+
var reportUnreadableStsLine = (product, field, report) => {
|
|
7643
|
+
const source2 = postPurchaseProductSourceOf(product);
|
|
7644
|
+
const path = source2 ? `data.${source2.productIndex}.${field}` : field;
|
|
7645
|
+
const detail = `Unreadable post-purchase STS product ${product.id}: ${path}`;
|
|
7646
|
+
reportOncePerResponse(source2?.response ?? product, report, [{ detail, kind: "product" }]);
|
|
7647
|
+
};
|
|
7648
|
+
var postPurchaseStsLine = (normalized, product, lines, variantId, report) => {
|
|
7619
7649
|
if (!product.sellingPlanGroups?.length || product.productGroupVariants.length) return void 0;
|
|
7620
|
-
|
|
7650
|
+
const modern = typeof product.sellingPlanGroups[0].id !== "number";
|
|
7651
|
+
for (const [index, variant2] of product.variants.entries()) {
|
|
7621
7652
|
const matched = lines.filter((line) => line.sellingPlanId === void 0 && line.variantId === variant2.id);
|
|
7622
7653
|
const data = [{ ...product, variants: [variant2] }];
|
|
7623
|
-
if ((variantId === void 0 || variant2.id === variantId) && matched.length === 1 && postPurchaseVariantAvailable(variant2)
|
|
7624
|
-
|
|
7654
|
+
if ((variantId === void 0 || variant2.id === variantId) && matched.length === 1 && postPurchaseVariantAvailable(variant2)) {
|
|
7655
|
+
const unread = [];
|
|
7656
|
+
if (projectPostPurchasePlanCatalog({ ...normalized, data }, (event) => unread.push(event))?.plans.length)
|
|
7657
|
+
return { data, line: matched[0] };
|
|
7658
|
+
const field = modern && !PostPurchasePlanAllocations.safeParse(variant2.sellingPlanAllocations).success ? `variants.${index}.sellingPlanAllocations` : unread.length ? "sellingPlanGroups" : void 0;
|
|
7659
|
+
if (report && field) reportUnreadableStsLine(product, field, report);
|
|
7660
|
+
}
|
|
7625
7661
|
}
|
|
7626
7662
|
};
|
|
7627
7663
|
var preparePostPurchaseStsView = (widgetId, normalized, product, context, requested, report) => {
|
|
7628
7664
|
const { originalLineItems } = PostPurchaseStsContext.parse(context);
|
|
7629
|
-
const found = postPurchaseStsLine(normalized, product, originalLineItems, requested.variantId);
|
|
7665
|
+
const found = postPurchaseStsLine(normalized, product, originalLineItems, requested.variantId, report);
|
|
7630
7666
|
if (!found) return null;
|
|
7631
7667
|
const whole = found.line.quantity;
|
|
7632
7668
|
if (requested.quantity !== void 0 && requested.quantity !== whole)
|
|
@@ -8057,14 +8093,13 @@ var preparePostPurchaseCollectionView = (widgetId, settings, response, report, r
|
|
|
8057
8093
|
};
|
|
8058
8094
|
|
|
8059
8095
|
// src/server/postPurchaseMemberEligibility.ts
|
|
8060
|
-
var
|
|
8061
|
-
};
|
|
8062
|
-
var postPurchaseMemberEligibility = (normalized, product, excluded) => {
|
|
8096
|
+
var eligibility = (normalized, product, excluded) => {
|
|
8063
8097
|
if (product.productGroupVariants.length) {
|
|
8064
8098
|
const group = readPostPurchaseGroup(product, normalized.effective, excluded);
|
|
8099
|
+
if (!group.entries.length) return void 0;
|
|
8065
8100
|
return group.entries.map(({ product: option }) => postPurchaseMemberEligibility(normalized, option)).some(Boolean);
|
|
8066
8101
|
}
|
|
8067
|
-
if (!product.variants.length)
|
|
8102
|
+
if (!product.variants.length) return false;
|
|
8068
8103
|
const variants = projectPostPurchaseVariantCatalog(product, normalized.effective).variants;
|
|
8069
8104
|
const catalogs = product.variants.map((variant2) => {
|
|
8070
8105
|
const catalog = projectPostPurchasePlanCatalog({
|
|
@@ -8072,23 +8107,31 @@ var postPurchaseMemberEligibility = (normalized, product, excluded) => {
|
|
|
8072
8107
|
data: [{ ...product, variants: [variant2] }]
|
|
8073
8108
|
});
|
|
8074
8109
|
if (!catalog) throw new Error("Unreadable subscription catalog");
|
|
8075
|
-
if (normalized.effective.productType === "one-time" && product.sellingPlanGroups.some((group) => group.requiresSellingPlan))
|
|
8076
|
-
throw new Error("Unsupported purchase mode");
|
|
8077
8110
|
return catalog;
|
|
8078
8111
|
});
|
|
8079
|
-
if (!variants.some((variant2) => variant2.available))
|
|
8080
|
-
throw new PostPurchaseInventoryUnavailable("Unavailable inventory");
|
|
8081
8112
|
return catalogs.some(
|
|
8082
8113
|
(catalog, index) => variants[index].available && (normalized.effective.productType !== "subscription" && !catalog.requiresSellingPlan || normalized.effective.productType !== "one-time" && catalog.plans.length > 0)
|
|
8083
8114
|
);
|
|
8084
8115
|
};
|
|
8116
|
+
var postPurchaseMemberEligibility = (normalized, product, excluded) => {
|
|
8117
|
+
try {
|
|
8118
|
+
return eligibility(normalized, product, excluded);
|
|
8119
|
+
} catch (error) {
|
|
8120
|
+
if (error instanceof PostPurchaseVariantOptionMismatch) return false;
|
|
8121
|
+
throw error;
|
|
8122
|
+
}
|
|
8123
|
+
};
|
|
8085
8124
|
|
|
8086
8125
|
// src/server/classifyPostPurchaseOffer.ts
|
|
8087
8126
|
var identities = (members) => members.map(({ product, productIndex }) => ({ productId: product.id, productIndex }));
|
|
8088
|
-
var classifyPostPurchaseOffer = (settings, response, context, options2) => {
|
|
8127
|
+
var classifyPostPurchaseOffer = (settings, response, context, options2, report) => {
|
|
8128
|
+
let unreadable = "context-unreadable";
|
|
8089
8129
|
try {
|
|
8090
8130
|
const trusted = PostPurchaseOfferEligibilityContext.parse(context);
|
|
8091
8131
|
const { sts: stsMode = false } = PostPurchaseStsOptions.parse(options2 ?? {});
|
|
8132
|
+
unreadable = "settings-unreadable";
|
|
8133
|
+
PostPurchaseProductLimit.parse(PostPurchaseProductSettings.parse(deepCamelCase(settings)).productLimit);
|
|
8134
|
+
unreadable = "catalog-unreadable";
|
|
8092
8135
|
const { members, normalized } = normalizePostPurchaseCollection(settings, response);
|
|
8093
8136
|
const configurations = [normalized.original, normalized.effective];
|
|
8094
8137
|
const stsEnabled = configurations.some((config) => config.upgradeToSubscription.allow);
|
|
@@ -8101,33 +8144,28 @@ var classifyPostPurchaseOffer = (settings, response, context, options2) => {
|
|
|
8101
8144
|
))
|
|
8102
8145
|
return { reason: "eligible-sts", status: "unavailable" };
|
|
8103
8146
|
if (normalized.effective.productType !== "one-time" || sts) {
|
|
8104
|
-
|
|
8147
|
+
unreadable = "settings-unreadable";
|
|
8148
|
+
PostPurchaseSubscriptionSettings.parse(normalized.original.subscription);
|
|
8149
|
+
unreadable = "catalog-unreadable";
|
|
8150
|
+
PostPurchaseSubscriptionSettings.parse(normalized.effective.subscription);
|
|
8105
8151
|
}
|
|
8106
8152
|
const lines = trusted.originalLineItems;
|
|
8107
|
-
const stsMembers = sts ? members.filter(({ product }) => postPurchaseStsLine(normalized, product, lines)) : [];
|
|
8153
|
+
const stsMembers = sts ? members.filter(({ product }) => postPurchaseStsLine(normalized, product, lines, void 0, report)) : [];
|
|
8108
8154
|
if (stsMembers.length) return { members: identities(stsMembers), mode: "sts", status: "retain" };
|
|
8109
|
-
const classified = members.map((member) => {
|
|
8110
|
-
|
|
8111
|
-
|
|
8112
|
-
|
|
8113
|
-
eligible: postPurchaseMemberEligibility(normalized, member.product, trusted.excludedProductIds)
|
|
8114
|
-
};
|
|
8115
|
-
} catch (error) {
|
|
8116
|
-
if (error instanceof PostPurchaseInventoryUnavailable && !member.product.productGroupVariants.length && trusted.excludedProductIds.includes(member.product.id))
|
|
8117
|
-
return { ...member, eligible: false };
|
|
8118
|
-
throw error;
|
|
8119
|
-
}
|
|
8120
|
-
});
|
|
8155
|
+
const classified = members.map((member) => ({
|
|
8156
|
+
...member,
|
|
8157
|
+
eligible: postPurchaseMemberEligibility(normalized, member.product, trusted.excludedProductIds)
|
|
8158
|
+
}));
|
|
8121
8159
|
if (!members.length) return { reason: "empty", status: "skip" };
|
|
8122
8160
|
if (stsEnabled) return { reason: "no-eligible-subscription", status: "skip" };
|
|
8123
8161
|
const candidates = classified.filter(
|
|
8124
|
-
({ product }) => product.productGroupVariants.length ?
|
|
8162
|
+
({ eligible, product }) => product.productGroupVariants.length ? eligible !== void 0 : !trusted.excludedProductIds.includes(product.id)
|
|
8125
8163
|
);
|
|
8126
8164
|
if (!candidates.length) return { reason: "empty", status: "skip" };
|
|
8127
8165
|
const retained = candidates.filter(({ eligible }) => eligible);
|
|
8128
8166
|
return retained.length ? { members: identities(retained), status: "retain" } : { reason: "no-eligible-subscription", status: "skip" };
|
|
8129
8167
|
} catch {
|
|
8130
|
-
return { status: "unavailable" };
|
|
8168
|
+
return { reason: unreadable, status: "unavailable" };
|
|
8131
8169
|
}
|
|
8132
8170
|
};
|
|
8133
8171
|
|
package/dist/server/index.mjs
CHANGED
|
@@ -6099,17 +6099,30 @@ var PostPurchaseProductSettings = PostPurchaseSettings.pick({
|
|
|
6099
6099
|
|
|
6100
6100
|
// src/server/readPostPurchaseProductSource.ts
|
|
6101
6101
|
import { z as z45 } from "zod";
|
|
6102
|
-
|
|
6103
|
-
|
|
6104
|
-
var Identified = z45.object({ id: PostPurchaseProductId });
|
|
6102
|
+
|
|
6103
|
+
// src/server/postPurchaseResponseDrift.ts
|
|
6105
6104
|
var heard = /* @__PURE__ */ new WeakMap();
|
|
6106
|
-
var
|
|
6107
|
-
|
|
6105
|
+
var sources = /* @__PURE__ */ new WeakMap();
|
|
6106
|
+
var rememberPostPurchaseProductSource = (product, response, productIndex) => {
|
|
6107
|
+
sources.set(product, { productIndex, response });
|
|
6108
|
+
};
|
|
6109
|
+
var postPurchaseProductSourceOf = (product) => sources.get(product);
|
|
6110
|
+
var reportOncePerResponse = (response, report, events) => {
|
|
6111
|
+
const reporters = heard.get(response) ?? /* @__PURE__ */ new WeakMap();
|
|
6108
6112
|
heard.set(response, reporters);
|
|
6109
|
-
|
|
6110
|
-
reporters.
|
|
6111
|
-
|
|
6113
|
+
const details = reporters.get(report) ?? /* @__PURE__ */ new Set();
|
|
6114
|
+
reporters.set(report, details);
|
|
6115
|
+
for (const event of events) {
|
|
6116
|
+
if (details.has(event.detail)) continue;
|
|
6117
|
+
details.add(event.detail);
|
|
6118
|
+
report(event);
|
|
6119
|
+
}
|
|
6112
6120
|
};
|
|
6121
|
+
|
|
6122
|
+
// src/server/readPostPurchaseProductSource.ts
|
|
6123
|
+
var Envelope = PostPurchaseProductSource.extend({ data: z45.array(z45.unknown()) });
|
|
6124
|
+
var Product3 = PostPurchaseProductSource.shape.data.element;
|
|
6125
|
+
var Identified = z45.object({ id: PostPurchaseProductId });
|
|
6113
6126
|
var readPostPurchaseProductSource = (response, report) => {
|
|
6114
6127
|
const { data, metadata } = Envelope.parse(deepCamelCase(response));
|
|
6115
6128
|
const drift = [];
|
|
@@ -6117,6 +6130,7 @@ var readPostPurchaseProductSource = (response, report) => {
|
|
|
6117
6130
|
const products = data.flatMap((raw, productIndex) => {
|
|
6118
6131
|
const parsed = Product3.safeParse(raw);
|
|
6119
6132
|
if (parsed.success) {
|
|
6133
|
+
rememberPostPurchaseProductSource(parsed.data, response, productIndex);
|
|
6120
6134
|
if (parsed.data.requiresSellingPlan && !parsed.data.sellingPlanGroups.length)
|
|
6121
6135
|
drift.push({
|
|
6122
6136
|
detail: `Dropped post-purchase product ${parsed.data.id}: data.${productIndex}.requiresSellingPlan`,
|
|
@@ -6134,7 +6148,7 @@ var readPostPurchaseProductSource = (response, report) => {
|
|
|
6134
6148
|
});
|
|
6135
6149
|
return [];
|
|
6136
6150
|
});
|
|
6137
|
-
if (report && drift.length
|
|
6151
|
+
if (report && drift.length) reportOncePerResponse(response, report, drift);
|
|
6138
6152
|
return { dropped, metadata, products };
|
|
6139
6153
|
};
|
|
6140
6154
|
|
|
@@ -6280,7 +6294,8 @@ var Groups = z52.array(
|
|
|
6280
6294
|
sellingPlans: z52.unknown()
|
|
6281
6295
|
})
|
|
6282
6296
|
);
|
|
6283
|
-
var
|
|
6297
|
+
var PostPurchasePlanAllocations = z52.array(z52.object({ sellingPlanGroupId: z52.string().min(1) }));
|
|
6298
|
+
var Allocations = PostPurchasePlanAllocations.default([]);
|
|
6284
6299
|
var Plans = z52.array(
|
|
6285
6300
|
PostPurchasePlanOption.pick({ id: true, name: true }).extend({
|
|
6286
6301
|
options: z52.array(z52.object({ value: z52.string().min(1) })).min(1),
|
|
@@ -7428,11 +7443,11 @@ var PostPurchaseMemberPointer = PostPurchaseProgressSchema.shape.members.element
|
|
|
7428
7443
|
|
|
7429
7444
|
// src/server/normalizePostPurchaseCollection.ts
|
|
7430
7445
|
import { z as z82, ZodError } from "zod";
|
|
7446
|
+
var PostPurchaseProductLimit = z82.number().int().positive();
|
|
7431
7447
|
var normalizePostPurchaseCollection = (settings, response, excludedProductIds, report) => {
|
|
7432
7448
|
const { dropped, normalized, products } = normalizePostPurchaseSource(settings, response, report);
|
|
7433
|
-
|
|
7434
|
-
|
|
7435
|
-
const cap = limit.parse(normalized.effective.productLimit);
|
|
7449
|
+
PostPurchaseProductLimit.parse(normalized.original.productLimit);
|
|
7450
|
+
const cap = PostPurchaseProductLimit.parse(normalized.effective.productLimit);
|
|
7436
7451
|
const prefix = underPostPurchaseCap(products, cap);
|
|
7437
7452
|
const unread = underPostPurchaseCap(dropped, cap);
|
|
7438
7453
|
if (unread.length && !prefix.length) throw new ZodError(unread.flatMap(({ issues }) => issues));
|
|
@@ -7444,6 +7459,8 @@ var normalizePostPurchaseCollection = (settings, response, excludedProductIds, r
|
|
|
7444
7459
|
};
|
|
7445
7460
|
|
|
7446
7461
|
// src/server/postPurchaseVariantCatalog.ts
|
|
7462
|
+
var PostPurchaseVariantOptionMismatch = class extends Error {
|
|
7463
|
+
};
|
|
7447
7464
|
var projectPostPurchaseVariantCatalog = (product, settings) => {
|
|
7448
7465
|
const options2 = PostPurchaseVariantCatalog.shape.options.parse(product.options === void 0 ? [] : product.options).sort((a, b) => a.position - b.position);
|
|
7449
7466
|
const variants = product.variants.map((variant2) => ({
|
|
@@ -7457,7 +7474,7 @@ var projectPostPurchaseVariantCatalog = (product, settings) => {
|
|
|
7457
7474
|
throw new Error("Ambiguous post-purchase variant catalog");
|
|
7458
7475
|
for (const tuple of tuples) {
|
|
7459
7476
|
if (options2.some(({ position, values: values2 }) => !values2.some((value) => value === tuple[position - 1])) || tuple.some((value, index) => value != null && !options2[index]))
|
|
7460
|
-
throw new
|
|
7477
|
+
throw new PostPurchaseVariantOptionMismatch("Variant option tuple does not match the catalog");
|
|
7461
7478
|
}
|
|
7462
7479
|
return PostPurchaseVariantCatalog.parse({
|
|
7463
7480
|
displayMode: settings.productOptions.variantSelectorDisplayMode,
|
|
@@ -7480,6 +7497,12 @@ var projectPostPurchaseVariantCatalog = (product, settings) => {
|
|
|
7480
7497
|
import { z as z83 } from "zod";
|
|
7481
7498
|
var selection2 = PreparedPostPurchaseProduct.shape.selection;
|
|
7482
7499
|
var PostPurchaseOfferSkipReason = z83.enum(["empty", "no-eligible-subscription"]);
|
|
7500
|
+
var PostPurchaseOfferUnavailableReason = z83.enum([
|
|
7501
|
+
"catalog-unreadable",
|
|
7502
|
+
"context-unreadable",
|
|
7503
|
+
"eligible-sts",
|
|
7504
|
+
"settings-unreadable"
|
|
7505
|
+
]);
|
|
7483
7506
|
var PostPurchaseOfferEligibilityContext = z83.object({
|
|
7484
7507
|
excludedProductIds: PostPurchaseExcludedProductIds,
|
|
7485
7508
|
originalLineItems: z83.array(selection2.pick({ productId: true, sellingPlanId: true, variantId: true }))
|
|
@@ -7500,7 +7523,8 @@ var PostPurchaseOfferEligibility = z83.discriminatedUnion("status", [
|
|
|
7500
7523
|
status: z83.literal("retain")
|
|
7501
7524
|
}),
|
|
7502
7525
|
z83.object({ reason: PostPurchaseOfferSkipReason, status: z83.literal("skip") }),
|
|
7503
|
-
|
|
7526
|
+
/** The classifier always names a reason; it stays optional so a reasonless answer from before still parses. */
|
|
7527
|
+
z83.object({ reason: PostPurchaseOfferUnavailableReason.optional(), status: z83.literal("unavailable") })
|
|
7504
7528
|
]);
|
|
7505
7529
|
|
|
7506
7530
|
// src/schema/postPurchaseQuantity.ts
|
|
@@ -7542,18 +7566,30 @@ var readPostPurchaseQuantity = ({
|
|
|
7542
7566
|
|
|
7543
7567
|
// src/server/postPurchaseSts.ts
|
|
7544
7568
|
var stsAllowed = ({ effective, original }) => [original, effective].some((config) => config.upgradeToSubscription.allow);
|
|
7545
|
-
var
|
|
7569
|
+
var reportUnreadableStsLine = (product, field, report) => {
|
|
7570
|
+
const source2 = postPurchaseProductSourceOf(product);
|
|
7571
|
+
const path = source2 ? `data.${source2.productIndex}.${field}` : field;
|
|
7572
|
+
const detail = `Unreadable post-purchase STS product ${product.id}: ${path}`;
|
|
7573
|
+
reportOncePerResponse(source2?.response ?? product, report, [{ detail, kind: "product" }]);
|
|
7574
|
+
};
|
|
7575
|
+
var postPurchaseStsLine = (normalized, product, lines, variantId, report) => {
|
|
7546
7576
|
if (!product.sellingPlanGroups?.length || product.productGroupVariants.length) return void 0;
|
|
7547
|
-
|
|
7577
|
+
const modern = typeof product.sellingPlanGroups[0].id !== "number";
|
|
7578
|
+
for (const [index, variant2] of product.variants.entries()) {
|
|
7548
7579
|
const matched = lines.filter((line) => line.sellingPlanId === void 0 && line.variantId === variant2.id);
|
|
7549
7580
|
const data = [{ ...product, variants: [variant2] }];
|
|
7550
|
-
if ((variantId === void 0 || variant2.id === variantId) && matched.length === 1 && postPurchaseVariantAvailable(variant2)
|
|
7551
|
-
|
|
7581
|
+
if ((variantId === void 0 || variant2.id === variantId) && matched.length === 1 && postPurchaseVariantAvailable(variant2)) {
|
|
7582
|
+
const unread = [];
|
|
7583
|
+
if (projectPostPurchasePlanCatalog({ ...normalized, data }, (event) => unread.push(event))?.plans.length)
|
|
7584
|
+
return { data, line: matched[0] };
|
|
7585
|
+
const field = modern && !PostPurchasePlanAllocations.safeParse(variant2.sellingPlanAllocations).success ? `variants.${index}.sellingPlanAllocations` : unread.length ? "sellingPlanGroups" : void 0;
|
|
7586
|
+
if (report && field) reportUnreadableStsLine(product, field, report);
|
|
7587
|
+
}
|
|
7552
7588
|
}
|
|
7553
7589
|
};
|
|
7554
7590
|
var preparePostPurchaseStsView = (widgetId, normalized, product, context, requested, report) => {
|
|
7555
7591
|
const { originalLineItems } = PostPurchaseStsContext.parse(context);
|
|
7556
|
-
const found = postPurchaseStsLine(normalized, product, originalLineItems, requested.variantId);
|
|
7592
|
+
const found = postPurchaseStsLine(normalized, product, originalLineItems, requested.variantId, report);
|
|
7557
7593
|
if (!found) return null;
|
|
7558
7594
|
const whole = found.line.quantity;
|
|
7559
7595
|
if (requested.quantity !== void 0 && requested.quantity !== whole)
|
|
@@ -7984,14 +8020,13 @@ var preparePostPurchaseCollectionView = (widgetId, settings, response, report, r
|
|
|
7984
8020
|
};
|
|
7985
8021
|
|
|
7986
8022
|
// src/server/postPurchaseMemberEligibility.ts
|
|
7987
|
-
var
|
|
7988
|
-
};
|
|
7989
|
-
var postPurchaseMemberEligibility = (normalized, product, excluded) => {
|
|
8023
|
+
var eligibility = (normalized, product, excluded) => {
|
|
7990
8024
|
if (product.productGroupVariants.length) {
|
|
7991
8025
|
const group = readPostPurchaseGroup(product, normalized.effective, excluded);
|
|
8026
|
+
if (!group.entries.length) return void 0;
|
|
7992
8027
|
return group.entries.map(({ product: option }) => postPurchaseMemberEligibility(normalized, option)).some(Boolean);
|
|
7993
8028
|
}
|
|
7994
|
-
if (!product.variants.length)
|
|
8029
|
+
if (!product.variants.length) return false;
|
|
7995
8030
|
const variants = projectPostPurchaseVariantCatalog(product, normalized.effective).variants;
|
|
7996
8031
|
const catalogs = product.variants.map((variant2) => {
|
|
7997
8032
|
const catalog = projectPostPurchasePlanCatalog({
|
|
@@ -7999,23 +8034,31 @@ var postPurchaseMemberEligibility = (normalized, product, excluded) => {
|
|
|
7999
8034
|
data: [{ ...product, variants: [variant2] }]
|
|
8000
8035
|
});
|
|
8001
8036
|
if (!catalog) throw new Error("Unreadable subscription catalog");
|
|
8002
|
-
if (normalized.effective.productType === "one-time" && product.sellingPlanGroups.some((group) => group.requiresSellingPlan))
|
|
8003
|
-
throw new Error("Unsupported purchase mode");
|
|
8004
8037
|
return catalog;
|
|
8005
8038
|
});
|
|
8006
|
-
if (!variants.some((variant2) => variant2.available))
|
|
8007
|
-
throw new PostPurchaseInventoryUnavailable("Unavailable inventory");
|
|
8008
8039
|
return catalogs.some(
|
|
8009
8040
|
(catalog, index) => variants[index].available && (normalized.effective.productType !== "subscription" && !catalog.requiresSellingPlan || normalized.effective.productType !== "one-time" && catalog.plans.length > 0)
|
|
8010
8041
|
);
|
|
8011
8042
|
};
|
|
8043
|
+
var postPurchaseMemberEligibility = (normalized, product, excluded) => {
|
|
8044
|
+
try {
|
|
8045
|
+
return eligibility(normalized, product, excluded);
|
|
8046
|
+
} catch (error) {
|
|
8047
|
+
if (error instanceof PostPurchaseVariantOptionMismatch) return false;
|
|
8048
|
+
throw error;
|
|
8049
|
+
}
|
|
8050
|
+
};
|
|
8012
8051
|
|
|
8013
8052
|
// src/server/classifyPostPurchaseOffer.ts
|
|
8014
8053
|
var identities = (members) => members.map(({ product, productIndex }) => ({ productId: product.id, productIndex }));
|
|
8015
|
-
var classifyPostPurchaseOffer = (settings, response, context, options2) => {
|
|
8054
|
+
var classifyPostPurchaseOffer = (settings, response, context, options2, report) => {
|
|
8055
|
+
let unreadable = "context-unreadable";
|
|
8016
8056
|
try {
|
|
8017
8057
|
const trusted = PostPurchaseOfferEligibilityContext.parse(context);
|
|
8018
8058
|
const { sts: stsMode = false } = PostPurchaseStsOptions.parse(options2 ?? {});
|
|
8059
|
+
unreadable = "settings-unreadable";
|
|
8060
|
+
PostPurchaseProductLimit.parse(PostPurchaseProductSettings.parse(deepCamelCase(settings)).productLimit);
|
|
8061
|
+
unreadable = "catalog-unreadable";
|
|
8019
8062
|
const { members, normalized } = normalizePostPurchaseCollection(settings, response);
|
|
8020
8063
|
const configurations = [normalized.original, normalized.effective];
|
|
8021
8064
|
const stsEnabled = configurations.some((config) => config.upgradeToSubscription.allow);
|
|
@@ -8028,33 +8071,28 @@ var classifyPostPurchaseOffer = (settings, response, context, options2) => {
|
|
|
8028
8071
|
))
|
|
8029
8072
|
return { reason: "eligible-sts", status: "unavailable" };
|
|
8030
8073
|
if (normalized.effective.productType !== "one-time" || sts) {
|
|
8031
|
-
|
|
8074
|
+
unreadable = "settings-unreadable";
|
|
8075
|
+
PostPurchaseSubscriptionSettings.parse(normalized.original.subscription);
|
|
8076
|
+
unreadable = "catalog-unreadable";
|
|
8077
|
+
PostPurchaseSubscriptionSettings.parse(normalized.effective.subscription);
|
|
8032
8078
|
}
|
|
8033
8079
|
const lines = trusted.originalLineItems;
|
|
8034
|
-
const stsMembers = sts ? members.filter(({ product }) => postPurchaseStsLine(normalized, product, lines)) : [];
|
|
8080
|
+
const stsMembers = sts ? members.filter(({ product }) => postPurchaseStsLine(normalized, product, lines, void 0, report)) : [];
|
|
8035
8081
|
if (stsMembers.length) return { members: identities(stsMembers), mode: "sts", status: "retain" };
|
|
8036
|
-
const classified = members.map((member) => {
|
|
8037
|
-
|
|
8038
|
-
|
|
8039
|
-
|
|
8040
|
-
eligible: postPurchaseMemberEligibility(normalized, member.product, trusted.excludedProductIds)
|
|
8041
|
-
};
|
|
8042
|
-
} catch (error) {
|
|
8043
|
-
if (error instanceof PostPurchaseInventoryUnavailable && !member.product.productGroupVariants.length && trusted.excludedProductIds.includes(member.product.id))
|
|
8044
|
-
return { ...member, eligible: false };
|
|
8045
|
-
throw error;
|
|
8046
|
-
}
|
|
8047
|
-
});
|
|
8082
|
+
const classified = members.map((member) => ({
|
|
8083
|
+
...member,
|
|
8084
|
+
eligible: postPurchaseMemberEligibility(normalized, member.product, trusted.excludedProductIds)
|
|
8085
|
+
}));
|
|
8048
8086
|
if (!members.length) return { reason: "empty", status: "skip" };
|
|
8049
8087
|
if (stsEnabled) return { reason: "no-eligible-subscription", status: "skip" };
|
|
8050
8088
|
const candidates = classified.filter(
|
|
8051
|
-
({ product }) => product.productGroupVariants.length ?
|
|
8089
|
+
({ eligible, product }) => product.productGroupVariants.length ? eligible !== void 0 : !trusted.excludedProductIds.includes(product.id)
|
|
8052
8090
|
);
|
|
8053
8091
|
if (!candidates.length) return { reason: "empty", status: "skip" };
|
|
8054
8092
|
const retained = candidates.filter(({ eligible }) => eligible);
|
|
8055
8093
|
return retained.length ? { members: identities(retained), status: "retain" } : { reason: "no-eligible-subscription", status: "skip" };
|
|
8056
8094
|
} catch {
|
|
8057
|
-
return { status: "unavailable" };
|
|
8095
|
+
return { reason: unreadable, status: "unavailable" };
|
|
8058
8096
|
}
|
|
8059
8097
|
};
|
|
8060
8098
|
|
|
@@ -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
|
|
@@ -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,4 +1,9 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
1
2
|
import { PostPurchasePlanOption } from '../schema/postPurchasePlanCatalog';
|
|
3
|
+
/** A variant's readable `selling_plan_allocations`; a missing list reads as none here, but STS reports it. */
|
|
4
|
+
export declare const PostPurchasePlanAllocations: z.ZodArray<z.ZodObject<{
|
|
5
|
+
sellingPlanGroupId: z.ZodString;
|
|
6
|
+
}, z.core.$strip>>;
|
|
2
7
|
/**
|
|
3
8
|
* Match allocation groups in product order, then preserve each matching group's plan order. Membership is
|
|
4
9
|
* group-level by design (frozen-branch parity): Shopify allocates every plan of a group to a member variant, and
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Reporter, ServerDrift } from '../server/shared';
|
|
2
|
+
/** Records where a parsed product came from, so drift found about it later still names its response and path. */
|
|
3
|
+
export declare const rememberPostPurchaseProductSource: (product: object, response: object, productIndex: number) => void;
|
|
4
|
+
/** The response and raw `productIndex` a parsed product was read from, when it was read by the product source. */
|
|
5
|
+
export declare const postPurchaseProductSourceOf: (product: object) => {
|
|
6
|
+
productIndex: number;
|
|
7
|
+
response: object;
|
|
8
|
+
} | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Reports each event `report` has not yet heard about `response`, keyed on the `response` object itself: every
|
|
11
|
+
* projection of one request rereads the same object, so a drift is heard once however many projections find it.
|
|
12
|
+
*/
|
|
13
|
+
export declare const reportOncePerResponse: (response: object, report: Reporter, events: ServerDrift[]) => void;
|
|
@@ -18,8 +18,14 @@ export declare const stsAllowed: ({ effective, original }: Pick<Normalized, "eff
|
|
|
18
18
|
* product is never an STS member; (4) the bound variant is the purchased line's, not the product's selected
|
|
19
19
|
* variant, and subscription is the only mode. The first such variant in catalog order wins, unless `variantId`
|
|
20
20
|
* names one.
|
|
21
|
+
*
|
|
22
|
+
* `report` hears a candidate (a purchased, in-stock variant on exactly one one-time line) whose plan data cannot be
|
|
23
|
+
* read, since it then silently switches nothing: a modern selling-plan variant whose `sellingPlanAllocations` is
|
|
24
|
+
* missing or malformed, or plan data the catalog cannot read. Each is a `product` drift naming the product id and
|
|
25
|
+
* the dotted path from the source root, never a value, heard once per response like the source's own drops. A
|
|
26
|
+
* readable variant that simply has no plan, or no candidate at all, stays silent.
|
|
21
27
|
*/
|
|
22
|
-
export declare const postPurchaseStsLine: <T extends Line>(normalized: Normalized, product: Normalized["data"][number], lines: T[], variantId?: number) => {
|
|
28
|
+
export declare const postPurchaseStsLine: <T extends Line>(normalized: Normalized, product: Normalized["data"][number], lines: T[], variantId?: number, report?: Reporter) => {
|
|
23
29
|
data: {
|
|
24
30
|
variants: {
|
|
25
31
|
title: string;
|
|
@@ -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;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rebuy/rebuy",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.57.0",
|
|
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.",
|