@rebuy/rebuy 3.34.0 → 3.35.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 +878 -794
- package/dist/index.mjs +879 -795
- package/dist/schema/index.d.ts +5 -0
- package/dist/schema/postPurchaseGroupCatalog.d.ts +56 -0
- package/dist/schema/postPurchaseOfferEligibility.d.ts +32 -0
- package/dist/schema/postPurchaseOfferPresentation.d.ts +386 -0
- package/dist/schema/postPurchaseProductSource.d.ts +10 -5
- package/dist/schema/postPurchaseQuantity.d.ts +13 -0
- package/dist/schema/postPurchaseVariantDefault.d.ts +17 -0
- package/dist/schema/postPurchaseVariantDefaultContext.d.ts +10 -0
- package/dist/server/__fixtures__/postPurchaseGroup.d.ts +75 -0
- package/dist/server/classifyPostPurchaseOffer.d.ts +3 -0
- package/dist/server/createPostPurchaseOrderAttributes.d.ts +9 -0
- package/dist/server/index.cjs +605 -192
- package/dist/server/index.d.ts +8 -1
- package/dist/server/index.mjs +605 -192
- package/dist/server/postPurchaseMemberEligibility.d.ts +7 -0
- package/dist/server/postPurchaseOfferCopy.d.ts +3 -0
- package/dist/server/postPurchaseProductEligibility.d.ts +3 -7
- package/dist/server/postPurchaseSubscriptionEligibility.d.ts +2 -3
- package/dist/server/prepareNormalizedSubscription.d.ts +2 -3
- package/dist/server/preparePostPurchaseGroupDeclineDisplay.d.ts +12 -0
- package/dist/server/preparePostPurchaseOfferPresentation.d.ts +137 -0
- package/dist/server/projectPostPurchaseProduct.d.ts +5 -7
- package/dist/server/readPostPurchaseGroup.d.ts +101 -0
- package/dist/server/readPostPurchaseGroupSelection.d.ts +110 -0
- package/dist/server/readPostPurchaseQuantity.d.ts +27 -0
- package/dist/server/resolvePostPurchaseMemberDefault.d.ts +8 -0
- package/dist/server/selectPostPurchaseChoice.d.ts +2 -3
- package/package.json +1 -1
package/dist/server/index.mjs
CHANGED
|
@@ -627,7 +627,7 @@ import { v7 as uuidv713 } from "uuid";
|
|
|
627
627
|
import { z as z27 } from "zod";
|
|
628
628
|
|
|
629
629
|
// src/schema/widgets/checkout-and-beyond/common.ts
|
|
630
|
-
var freezeEnum = (
|
|
630
|
+
var freezeEnum = (values2) => Object.freeze(Object.fromEntries(values2.map((v) => [v, v])));
|
|
631
631
|
var bannerColors = ["info", "success", "warning", "critical"];
|
|
632
632
|
var BannerColor = freezeEnum(bannerColors);
|
|
633
633
|
var borderRadii = ["none", "small", "base", "large", "fullyRounded"];
|
|
@@ -2093,15 +2093,15 @@ var CABImageSectionFields = z27.object({
|
|
|
2093
2093
|
width: z27.number().default(100)
|
|
2094
2094
|
});
|
|
2095
2095
|
var iconNameSet = new Set(iconNames);
|
|
2096
|
-
var isIconName = (
|
|
2097
|
-
var CABImageSection = CABImageSectionFields.superRefine(({ category, source }, ctx) => {
|
|
2098
|
-
if (category === "icon" &&
|
|
2096
|
+
var isIconName = (source2) => iconNameSet.has(source2);
|
|
2097
|
+
var CABImageSection = CABImageSectionFields.superRefine(({ category, source: source2 }, ctx) => {
|
|
2098
|
+
if (category === "icon" && source2 !== "" && !isIconName(source2))
|
|
2099
2099
|
ctx.addIssue({
|
|
2100
2100
|
code: "custom",
|
|
2101
2101
|
message: "icon-mode source must be an icon name",
|
|
2102
2102
|
path: ["source"]
|
|
2103
2103
|
});
|
|
2104
|
-
if (category !== "icon" && isIconName(
|
|
2104
|
+
if (category !== "icon" && isIconName(source2))
|
|
2105
2105
|
ctx.addIssue({
|
|
2106
2106
|
code: "custom",
|
|
2107
2107
|
message: "source must be a URL or dynamic token unless category is `icon`",
|
|
@@ -2213,10 +2213,10 @@ var HEADER_PARAGRAPH_STYLES = {
|
|
|
2213
2213
|
superTitle: { color: "base", fontSize: "extraLarge", marks: [{ type: "bold" }] },
|
|
2214
2214
|
title: { color: "base", fontSize: "medium", marks: [{ type: "bold" }] }
|
|
2215
2215
|
};
|
|
2216
|
-
var convertContentBlockTextToV2 = (
|
|
2217
|
-
const description =
|
|
2218
|
-
const superTitle =
|
|
2219
|
-
const title =
|
|
2216
|
+
var convertContentBlockTextToV2 = (language3, text2 = literalText, textAlign = "center") => {
|
|
2217
|
+
const description = language3?.description;
|
|
2218
|
+
const superTitle = language3?.superTitle;
|
|
2219
|
+
const title = language3?.title;
|
|
2220
2220
|
return TiptapDocument.parse({
|
|
2221
2221
|
attrs: { blockSpacing: "tight" },
|
|
2222
2222
|
content: [
|
|
@@ -2328,7 +2328,7 @@ var LOCATION_TO_EDITOR_MODE = {
|
|
|
2328
2328
|
};
|
|
2329
2329
|
|
|
2330
2330
|
// src/transforms/contentBlockV1/convertContentBlockToV2.ts
|
|
2331
|
-
var hasText = (
|
|
2331
|
+
var hasText = (language3) => !!language3 && !!(language3.description || language3.superTitle || language3.title);
|
|
2332
2332
|
var convertContentBlockToV2 = ({ id, settings }) => {
|
|
2333
2333
|
const imageBlocks = settings.imageBlocks ?? [];
|
|
2334
2334
|
return CABRootSection.parse({
|
|
@@ -2601,15 +2601,15 @@ var stripHtmlComments = (html = "") => html.replace(HTML_COMMENT_RE2, "");
|
|
|
2601
2601
|
var maybeFlushParagraph = (state) => {
|
|
2602
2602
|
if (state.currentRuns.length > 0) flushParagraph(state);
|
|
2603
2603
|
};
|
|
2604
|
-
var htmlToTiptap = (html,
|
|
2604
|
+
var htmlToTiptap = (html, options2 = {}) => {
|
|
2605
2605
|
const state = {
|
|
2606
2606
|
currentRuns: [],
|
|
2607
|
-
defaultTextStyleMark: buildDefaultTextStyleMark(
|
|
2607
|
+
defaultTextStyleMark: buildDefaultTextStyleMark(options2.defaultTextStyle),
|
|
2608
2608
|
listStack: [],
|
|
2609
2609
|
paragraphs: [],
|
|
2610
2610
|
stack: []
|
|
2611
2611
|
};
|
|
2612
|
-
const blockSpacing =
|
|
2612
|
+
const blockSpacing = options2.blockSpacing ?? "base";
|
|
2613
2613
|
if (typeof html !== "string" || !html) return makeDoc([makeParagraph([])], blockSpacing);
|
|
2614
2614
|
const htmlWithoutComments = stripHtmlComments(html);
|
|
2615
2615
|
let lastIndex = 0;
|
|
@@ -2854,9 +2854,9 @@ var isMonetizeV1 = isWidgetV1(WidgetType.ui_extension_ad);
|
|
|
2854
2854
|
var HTML_TAG_RE2 = /<[a-zA-Z]/;
|
|
2855
2855
|
var containsHtml = (text2) => HTML_TAG_RE2.test(text2);
|
|
2856
2856
|
var isObject = (x) => x !== null && typeof x === "object" && !Array.isArray(x);
|
|
2857
|
-
var normalizeTextValue = (value,
|
|
2857
|
+
var normalizeTextValue = (value, options2 = {}) => {
|
|
2858
2858
|
const tokenized = normalizeTokens(value);
|
|
2859
|
-
return containsHtml(tokenized) ||
|
|
2859
|
+
return containsHtml(tokenized) || options2.defaultTextStyle ? htmlToTiptap(tokenized, options2) : decodeTextEntities(tokenized);
|
|
2860
2860
|
};
|
|
2861
2861
|
var normalizeLangValue = (value) => typeof value === "string" ? normalizeTextValue(value) : value;
|
|
2862
2862
|
var normalizeTextContent = (node) => {
|
|
@@ -2889,15 +2889,15 @@ var resolveExperiment = (experiments, placeholderId, visitorId) => {
|
|
|
2889
2889
|
if (!experiment || experiment.data.length === 0) return void 0;
|
|
2890
2890
|
const roll = rollPercent(`${visitorId}:${experiment.id}`);
|
|
2891
2891
|
let cumulative = 0;
|
|
2892
|
-
const
|
|
2892
|
+
const variant2 = experiment.data.find((candidate) => {
|
|
2893
2893
|
cumulative += candidate.traffic;
|
|
2894
2894
|
return roll < cumulative;
|
|
2895
2895
|
}) ?? experiment.data[0];
|
|
2896
2896
|
return {
|
|
2897
|
-
elementId:
|
|
2897
|
+
elementId: variant2.elementId,
|
|
2898
2898
|
experimentId: experiment.id,
|
|
2899
2899
|
experimentType: experiment.type,
|
|
2900
|
-
selectedId:
|
|
2900
|
+
selectedId: variant2.id
|
|
2901
2901
|
};
|
|
2902
2902
|
};
|
|
2903
2903
|
|
|
@@ -3345,23 +3345,23 @@ var QUANTITY_INPUT_TYPE = {
|
|
|
3345
3345
|
"buttons-manual-input": "number",
|
|
3346
3346
|
"dropdown-select": "select"
|
|
3347
3347
|
};
|
|
3348
|
-
var buildQuantityErrors = (
|
|
3348
|
+
var buildQuantityErrors = (quantity2) => {
|
|
3349
3349
|
const en = {
|
|
3350
|
-
...
|
|
3351
|
-
...
|
|
3352
|
-
...
|
|
3350
|
+
...quantity2.maxError && { max: normalizeTokens(quantity2.maxError, QUANTITY_ERROR_TOKENS) },
|
|
3351
|
+
...quantity2.minError && { min: normalizeTokens(quantity2.minError, QUANTITY_ERROR_TOKENS) },
|
|
3352
|
+
...quantity2.negativeError && { neg: normalizeTokens(quantity2.negativeError, QUANTITY_ERROR_TOKENS) }
|
|
3353
3353
|
};
|
|
3354
3354
|
return Object.keys(en).length ? { errorMessages: { en } } : {};
|
|
3355
3355
|
};
|
|
3356
3356
|
var buildQuantity = (settings) => {
|
|
3357
|
-
const
|
|
3358
|
-
if (!
|
|
3359
|
-
const inputType =
|
|
3360
|
-
const max = Math.min(Math.max(
|
|
3361
|
-
const min = Math.min(Math.max(
|
|
3357
|
+
const quantity2 = settings.quantityInputs;
|
|
3358
|
+
if (!quantity2?.enabled) return [];
|
|
3359
|
+
const inputType = quantity2.type ? QUANTITY_INPUT_TYPE[quantity2.type] : void 0;
|
|
3360
|
+
const max = Math.min(Math.max(quantity2.maxValue ?? 10, 1), 100);
|
|
3361
|
+
const min = Math.min(Math.max(quantity2.minValue ?? 1, 1), max);
|
|
3362
3362
|
return [
|
|
3363
3363
|
{
|
|
3364
|
-
...buildQuantityErrors(
|
|
3364
|
+
...buildQuantityErrors(quantity2),
|
|
3365
3365
|
...inputType && { inputType },
|
|
3366
3366
|
max,
|
|
3367
3367
|
min,
|
|
@@ -3371,7 +3371,7 @@ var buildQuantity = (settings) => {
|
|
|
3371
3371
|
};
|
|
3372
3372
|
var buildSubscriptionButton = (settings) => {
|
|
3373
3373
|
if (settings.productType !== "both" && settings.productType !== "subscription") return [];
|
|
3374
|
-
const
|
|
3374
|
+
const language3 = settings.language;
|
|
3375
3375
|
const slot = (buttonField, override) => ({
|
|
3376
3376
|
buttonField,
|
|
3377
3377
|
content: localizedContent(SWITCH_LABELS[buttonField], override, SWITCH_LABEL_TOKENS2),
|
|
@@ -3385,9 +3385,9 @@ var buildSubscriptionButton = (settings) => {
|
|
|
3385
3385
|
...settings.productType === "subscription" && { disableDowngrade: true },
|
|
3386
3386
|
sections: [
|
|
3387
3387
|
slot("subscriptionOption", void 0),
|
|
3388
|
-
slot("switchToOneTimePurchase",
|
|
3389
|
-
slot("switchToSubscriptionNoDiscount",
|
|
3390
|
-
slot("switchToSubscriptionWithDiscount",
|
|
3388
|
+
slot("switchToOneTimePurchase", language3?.cartSwitchToOnetime),
|
|
3389
|
+
slot("switchToSubscriptionNoDiscount", language3?.upgradeToSubscription),
|
|
3390
|
+
slot("switchToSubscriptionWithDiscount", language3?.upgradeToSubscription)
|
|
3391
3391
|
],
|
|
3392
3392
|
sectionType: "button"
|
|
3393
3393
|
}
|
|
@@ -3442,11 +3442,11 @@ var buildOfferCard = (settings, horizontal) => {
|
|
|
3442
3442
|
const description = buildDescription(settings);
|
|
3443
3443
|
const reviews = buildReviews(settings);
|
|
3444
3444
|
const variants = buildVariants(settings);
|
|
3445
|
-
const
|
|
3445
|
+
const quantity2 = buildQuantity(settings);
|
|
3446
3446
|
const subscription2 = buildSubscriptionButton(settings);
|
|
3447
3447
|
const reveal = buildRevealButton(settings);
|
|
3448
3448
|
const addButton = buildAddButton(settings);
|
|
3449
|
-
const controls = [...description, ...
|
|
3449
|
+
const controls = [...description, ...quantity2, ...variants, ...subscription2];
|
|
3450
3450
|
const info = detailBlock([title, ...variantTitle, ...reviews, price], horizontal, variantTitle.length > 0);
|
|
3451
3451
|
const card = (sections) => [
|
|
3452
3452
|
{
|
|
@@ -3500,9 +3500,9 @@ var buildCarouselNav = () => ({
|
|
|
3500
3500
|
sectionType: "layout"
|
|
3501
3501
|
});
|
|
3502
3502
|
var HEADER_FIELDS = ["superTitle", "title", "description"];
|
|
3503
|
-
var sanitizedHeader = (
|
|
3503
|
+
var sanitizedHeader = (language3) => Object.fromEntries(
|
|
3504
3504
|
HEADER_FIELDS.flatMap((field) => {
|
|
3505
|
-
const value =
|
|
3505
|
+
const value = language3?.[field];
|
|
3506
3506
|
const sanitized = value ? stripContentBlockHtml(normalizeTokens(value)) : "";
|
|
3507
3507
|
return sanitized ? [[field, sanitized]] : [];
|
|
3508
3508
|
})
|
|
@@ -3599,7 +3599,7 @@ var coerceIntegrations = (integrations) => Object.fromEntries(
|
|
|
3599
3599
|
return [key, value];
|
|
3600
3600
|
})
|
|
3601
3601
|
);
|
|
3602
|
-
var buildBanner = (
|
|
3602
|
+
var buildBanner = (language3) => language3?.successBannerEnabled ? [
|
|
3603
3603
|
{
|
|
3604
3604
|
/**
|
|
3605
3605
|
* The banner-level tag is the extraction/routing key on BOTH renderers (React CAB's
|
|
@@ -3612,7 +3612,7 @@ var buildBanner = (language2) => language2?.successBannerEnabled ? [
|
|
|
3612
3612
|
dismissible: true,
|
|
3613
3613
|
sections: [
|
|
3614
3614
|
{
|
|
3615
|
-
content: bannerMessageContent(
|
|
3615
|
+
content: bannerMessageContent(language3.successBannerMessageRte),
|
|
3616
3616
|
sectionType: "text"
|
|
3617
3617
|
},
|
|
3618
3618
|
{
|
|
@@ -3929,14 +3929,14 @@ var convertCalloutBlock = (raw, report) => {
|
|
|
3929
3929
|
};
|
|
3930
3930
|
const shell = Shell.safeParse(raw);
|
|
3931
3931
|
if (!shell.success) return omit("Unreadable post-purchase callout");
|
|
3932
|
-
const
|
|
3932
|
+
const values2 = fields.map((field) => ({
|
|
3933
3933
|
field,
|
|
3934
3934
|
result: CalloutBannerBlock.shape.settings.shape[field].safeParse(shell.data.settings[field])
|
|
3935
3935
|
}));
|
|
3936
|
-
const styled2 =
|
|
3936
|
+
const styled2 = values2.every(({ result }) => result.success && typeof result.data === "string");
|
|
3937
3937
|
const styles2 = shell.data.styles;
|
|
3938
3938
|
const horizontal = styled2 ? { center: "center", leading: "start", trailing: "end" }[styles2.textAlignment] : "center";
|
|
3939
|
-
const sections =
|
|
3939
|
+
const sections = values2.flatMap(({ field, result }) => {
|
|
3940
3940
|
if (!result.success) return omit(`Unreadable post-purchase callout field: ${field}`);
|
|
3941
3941
|
const text2 = result.data;
|
|
3942
3942
|
if (text2 === "") return [];
|
|
@@ -3958,12 +3958,12 @@ var convertCalloutBlock = (raw, report) => {
|
|
|
3958
3958
|
import { z as z32 } from "zod";
|
|
3959
3959
|
|
|
3960
3960
|
// src/transforms/postPurchase/sizeImageSource.ts
|
|
3961
|
-
var sizeImageSource = (
|
|
3962
|
-
const extension =
|
|
3961
|
+
var sizeImageSource = (source2, size) => {
|
|
3962
|
+
const extension = source2.split(".").pop();
|
|
3963
3963
|
for (const previous of ["small", "medium", "large", "original", "master"]) {
|
|
3964
|
-
|
|
3964
|
+
source2 = source2.replace(`_${previous}.${extension}`, `.${extension}`);
|
|
3965
3965
|
}
|
|
3966
|
-
return
|
|
3966
|
+
return source2.replace(`.${extension}`, `${size === void 0 ? "" : `_${size}`}.${extension}`);
|
|
3967
3967
|
};
|
|
3968
3968
|
|
|
3969
3969
|
// src/transforms/postPurchase/convertImageFrame.ts
|
|
@@ -3973,9 +3973,9 @@ var convertImageFrame = (raw) => {
|
|
|
3973
3973
|
const parsed = ImageBlock.shape.settings.options[0].safeParse(raw);
|
|
3974
3974
|
if (!parsed.success) return null;
|
|
3975
3975
|
const settings = parsed.data;
|
|
3976
|
-
const
|
|
3977
|
-
const withAlt = CABImageSection.safeParse({ altText: settings.alt, source });
|
|
3978
|
-
const image = withAlt.success ? withAlt.data : CABImageSection.parse({ source });
|
|
3976
|
+
const source2 = sizeImageSource(Source.parse(settings.image || void 0));
|
|
3977
|
+
const withAlt = CABImageSection.safeParse({ altText: settings.alt, source: source2 });
|
|
3978
|
+
const image = withAlt.success ? withAlt.data : CABImageSection.parse({ source: source2 });
|
|
3979
3979
|
const size = settings.imageSize > 0 ? settings.imageSize : DEFAULT_IMAGE_SIZE;
|
|
3980
3980
|
return CABLayoutSection.parse({
|
|
3981
3981
|
alignment: { horizontal: "center" },
|
|
@@ -4212,19 +4212,19 @@ var convertTextBlock = (raw, report) => {
|
|
|
4212
4212
|
report?.({ detail: "Unreadable post-purchase text block", kind: "section" });
|
|
4213
4213
|
return [];
|
|
4214
4214
|
}
|
|
4215
|
-
const
|
|
4215
|
+
const values2 = fields3.map((field) => ({
|
|
4216
4216
|
field,
|
|
4217
4217
|
result: settingsSchema.shape[field].safeParse(shell.data.settings[field])
|
|
4218
4218
|
}));
|
|
4219
4219
|
const horizontal = { center: "center", leading: "start", trailing: "end" }[shell.data.settings.horizontalAlignment];
|
|
4220
|
-
const styled2 =
|
|
4220
|
+
const styled2 = values2.every(
|
|
4221
4221
|
({ result }) => result.success && (result.data === null || typeof result.data === "string")
|
|
4222
4222
|
);
|
|
4223
4223
|
const omit = (field) => {
|
|
4224
4224
|
report?.({ detail: `Unreadable post-purchase text field: ${field}`, kind: "section" });
|
|
4225
4225
|
return [];
|
|
4226
4226
|
};
|
|
4227
|
-
const sections =
|
|
4227
|
+
const sections = values2.flatMap(({ field, result }) => {
|
|
4228
4228
|
if (!result.success) return omit(field);
|
|
4229
4229
|
const text2 = result.data;
|
|
4230
4230
|
if (text2 === null || text2 === "") return [];
|
|
@@ -4458,10 +4458,10 @@ var giftOf = (tier) => {
|
|
|
4458
4458
|
if (tier.type !== "product") return void 0;
|
|
4459
4459
|
const product = tier.products?.[0] ?? tier.allProducts?.[0];
|
|
4460
4460
|
if (!product) return void 0;
|
|
4461
|
-
const
|
|
4462
|
-
if (
|
|
4461
|
+
const productId2 = product.productId ?? product.id;
|
|
4462
|
+
if (productId2 === void 0) return void 0;
|
|
4463
4463
|
return {
|
|
4464
|
-
productId,
|
|
4464
|
+
productId: productId2,
|
|
4465
4465
|
title: product.title,
|
|
4466
4466
|
variantIds: positiveIds(product.variantIds)
|
|
4467
4467
|
};
|
|
@@ -4740,14 +4740,14 @@ function serialize(obj) {
|
|
|
4740
4740
|
var encodeAttributes = (pairs = []) => JSON.stringify(Object.fromEntries(pairs.map(({ key, value }) => [key, value ?? ""])));
|
|
4741
4741
|
var buildEngineParams = (input, key) => {
|
|
4742
4742
|
const { cart, customerId, filterInputs, integrations, limit, productType, shop, visitorId } = input;
|
|
4743
|
-
const items = cart.items.map(({ productId, properties, quantity, subscriptionId, variantId }) => ({
|
|
4744
|
-
product_id:
|
|
4743
|
+
const items = cart.items.map(({ productId: productId2, properties, quantity: quantity2, subscriptionId, variantId }) => ({
|
|
4744
|
+
product_id: productId2,
|
|
4745
4745
|
properties: encodeAttributes(properties),
|
|
4746
|
-
quantity,
|
|
4746
|
+
quantity: quantity2,
|
|
4747
4747
|
...subscriptionId && { subscription_id: subscriptionId },
|
|
4748
4748
|
variant_id: variantId
|
|
4749
4749
|
}));
|
|
4750
|
-
const itemCount = cart.items.reduce((total, { quantity }) => total +
|
|
4750
|
+
const itemCount = cart.items.reduce((total, { quantity: quantity2 }) => total + quantity2, 0);
|
|
4751
4751
|
const subtotal = shopSubtotalCents(cart);
|
|
4752
4752
|
return {
|
|
4753
4753
|
cart: {
|
|
@@ -4834,13 +4834,13 @@ var OFFER_LIMIT = 4;
|
|
|
4834
4834
|
var SUPPORTED_COUNTRIES = /* @__PURE__ */ new Set(["US", "CA", "GB"]);
|
|
4835
4835
|
var MAX_TRANSACTION_ITEMS = 50;
|
|
4836
4836
|
var TEST_CUSTOMER_EMAIL = "test@rebuyengine.com";
|
|
4837
|
-
var transactionItems = (input) => (input.transactionItems?.map(({ id, priceCents, quantity, title, type }) => ({
|
|
4837
|
+
var transactionItems = (input) => (input.transactionItems?.map(({ id, priceCents, quantity: quantity2, title, type }) => ({
|
|
4838
4838
|
id,
|
|
4839
4839
|
price_cents: priceCents,
|
|
4840
|
-
quantity,
|
|
4840
|
+
quantity: quantity2,
|
|
4841
4841
|
title,
|
|
4842
4842
|
type
|
|
4843
|
-
})) ?? input.cart.items.map(({ productId, quantity }) => ({ id:
|
|
4843
|
+
})) ?? input.cart.items.map(({ productId: productId2, quantity: quantity2 }) => ({ id: productId2, quantity: quantity2 }))).slice(0, MAX_TRANSACTION_ITEMS);
|
|
4844
4844
|
var AdsEngineOffer = z37.object({
|
|
4845
4845
|
/** Pill-style value prop ("Get $45 Cashback"). Carried through the parse; the card does not render it yet (REB-24429 — pill design pending). */
|
|
4846
4846
|
callout: z37.string().catch(""),
|
|
@@ -4958,9 +4958,9 @@ var label = (text2) => ({
|
|
|
4958
4958
|
});
|
|
4959
4959
|
var text = (content) => ({ content: { en: content }, sectionType: SectionType.text });
|
|
4960
4960
|
var AS_DOC = { defaultTextStyle: {} };
|
|
4961
|
-
var safeTextValue = (raw,
|
|
4962
|
-
const converted = normalizeTextValue(raw,
|
|
4963
|
-
return checkForHTML(converted) ? converted : normalizeTextValue(htmlToPlainText(raw),
|
|
4961
|
+
var safeTextValue = (raw, options2) => {
|
|
4962
|
+
const converted = normalizeTextValue(raw, options2);
|
|
4963
|
+
return checkForHTML(converted) ? converted : normalizeTextValue(htmlToPlainText(raw), options2);
|
|
4964
4964
|
};
|
|
4965
4965
|
var headlineText = (raw) => {
|
|
4966
4966
|
const doc = safeTextValue(raw, AS_DOC);
|
|
@@ -5444,11 +5444,11 @@ var validateGifts = async (input, ctx) => {
|
|
|
5444
5444
|
const [remove, adjust] = await Promise.all([validateGwpGifts(input, ctx), validateSelectableGifts(input, ctx)]);
|
|
5445
5445
|
const removed = new Set(remove);
|
|
5446
5446
|
const targets = /* @__PURE__ */ new Map();
|
|
5447
|
-
for (const { lineId, quantity } of adjust) {
|
|
5447
|
+
for (const { lineId, quantity: quantity2 } of adjust) {
|
|
5448
5448
|
if (removed.has(lineId)) continue;
|
|
5449
|
-
targets.set(lineId, Math.min(
|
|
5449
|
+
targets.set(lineId, Math.min(quantity2, targets.get(lineId) ?? quantity2));
|
|
5450
5450
|
}
|
|
5451
|
-
return { adjust: [...targets].map(([lineId,
|
|
5451
|
+
return { adjust: [...targets].map(([lineId, quantity2]) => ({ lineId, quantity: quantity2 })), remove: [...removed] };
|
|
5452
5452
|
};
|
|
5453
5453
|
|
|
5454
5454
|
// src/server/normalizePostPurchaseProduct.ts
|
|
@@ -5780,14 +5780,14 @@ var SourceAdjustment = z47.object({
|
|
|
5780
5780
|
type: z47.enum(["percentage", "fixed_amount", "amount", "price", "none", "fixed"])
|
|
5781
5781
|
});
|
|
5782
5782
|
var readPostPurchasePlanAdjustment = (raw) => {
|
|
5783
|
-
const
|
|
5784
|
-
if (
|
|
5785
|
-
if (
|
|
5783
|
+
const source2 = SourceAdjustment.parse(raw);
|
|
5784
|
+
if (source2.type === "none" || source2.type === "fixed") {
|
|
5785
|
+
if (source2.amount !== 0) throw new Error("Unsupported plan adjustment");
|
|
5786
5786
|
return void 0;
|
|
5787
5787
|
}
|
|
5788
5788
|
const adjustment = PostPurchasePlanAdjustment.parse({
|
|
5789
|
-
amount:
|
|
5790
|
-
type:
|
|
5789
|
+
amount: source2.amount,
|
|
5790
|
+
type: source2.type === "amount" ? "fixed_amount" : source2.type
|
|
5791
5791
|
});
|
|
5792
5792
|
return adjustment.amount === 0 && adjustment.type !== "price" ? void 0 : adjustment;
|
|
5793
5793
|
};
|
|
@@ -5864,12 +5864,12 @@ var projectPostPurchasePlanCatalog = (normalized, report) => {
|
|
|
5864
5864
|
const { data } = normalized;
|
|
5865
5865
|
if (data.length !== 1 || data[0].variants.length !== 1) throw new Error("Ambiguous product");
|
|
5866
5866
|
const product = data[0];
|
|
5867
|
-
const
|
|
5868
|
-
if (
|
|
5867
|
+
const variant2 = product.variants[0];
|
|
5868
|
+
if (variant2.productId !== product.id) throw new Error("Foreign variant");
|
|
5869
5869
|
const groups = product.sellingPlanGroups;
|
|
5870
5870
|
const required = groups.map((group) => group.requiresSellingPlan);
|
|
5871
5871
|
if (required.some((flag) => flag !== required[0])) throw new Error("Conflicting requirement");
|
|
5872
|
-
const plans = typeof groups[0]?.id === "number" ? readPostPurchaseLegacyPlans(groups[0],
|
|
5872
|
+
const plans = typeof groups[0]?.id === "number" ? readPostPurchaseLegacyPlans(groups[0], variant2.id) : readPostPurchaseModernPlans(groups, variant2.sellingPlanAllocations);
|
|
5873
5873
|
const unique = /* @__PURE__ */ new Map();
|
|
5874
5874
|
for (const plan of plans) {
|
|
5875
5875
|
const previous = unique.get(plan.id);
|
|
@@ -5880,7 +5880,7 @@ var projectPostPurchasePlanCatalog = (normalized, report) => {
|
|
|
5880
5880
|
plans: [...unique.values()],
|
|
5881
5881
|
productId: product.id,
|
|
5882
5882
|
requiresSellingPlan: required[0] ?? false,
|
|
5883
|
-
variantId:
|
|
5883
|
+
variantId: variant2.id
|
|
5884
5884
|
});
|
|
5885
5885
|
} catch {
|
|
5886
5886
|
report?.({ detail: "Unreadable post-purchase plan catalog", kind: "product" });
|
|
@@ -6020,20 +6020,20 @@ var PostPurchaseSubscriptionSettings = subscription.extend({
|
|
|
6020
6020
|
});
|
|
6021
6021
|
|
|
6022
6022
|
// src/server/postPurchaseVariantAvailable.ts
|
|
6023
|
-
var postPurchaseVariantAvailable = (
|
|
6023
|
+
var postPurchaseVariantAvailable = (variant2) => !(variant2.inventoryManagement && variant2.inventoryPolicy === "deny" && variant2.inventoryQuantity <= 0);
|
|
6024
6024
|
|
|
6025
6025
|
// src/server/postPurchaseSubscriptionEligibility.ts
|
|
6026
|
-
var subscriptionUnavailable = (normalized, plan, allowCollection,
|
|
6026
|
+
var subscriptionUnavailable = (normalized, plan, allowCollection, quantity2) => {
|
|
6027
6027
|
const { data, effective, original } = normalized;
|
|
6028
6028
|
const unavailable = "An eligible subscription plan with supported shipping and discount is required";
|
|
6029
6029
|
if (data.length !== 1 || data[0].variants.length !== 1) return unavailable;
|
|
6030
6030
|
if (effective.productType === "one-time" || [original, effective].some(
|
|
6031
|
-
(config) => !allowCollection && config.productLimit !== 1 || config.upgradeToSubscription.allow || !
|
|
6031
|
+
(config) => !allowCollection && config.productLimit !== 1 || config.upgradeToSubscription.allow || !quantity2 && config.quantityInputs.enabled && (config.quantityInputs.minValue !== config.quantityInputs.maxValue || config.quantityInputs.defaultQuantity !== config.quantityInputs.minValue)
|
|
6032
6032
|
))
|
|
6033
6033
|
return unavailable;
|
|
6034
6034
|
const product = data[0];
|
|
6035
|
-
const
|
|
6036
|
-
if (product.productGroupVariants.length || !postPurchaseVariantAvailable(
|
|
6035
|
+
const variant2 = product.variants[0];
|
|
6036
|
+
if (product.productGroupVariants.length || !postPurchaseVariantAvailable(variant2) || variant2.productId !== product.id)
|
|
6037
6037
|
return unavailable;
|
|
6038
6038
|
const terms = [original, effective].map(
|
|
6039
6039
|
(config) => PostPurchaseSubscriptionSettings.safeParse(config.subscription)
|
|
@@ -6048,8 +6048,8 @@ import { z as z55 } from "zod";
|
|
|
6048
6048
|
var postPurchasePrimaryImage = (product) => {
|
|
6049
6049
|
const variantImageId = product.variants[0].imageId;
|
|
6050
6050
|
const selectedImage = variantImageId ? product.images?.find((image) => image.id === variantImageId) : void 0;
|
|
6051
|
-
const
|
|
6052
|
-
return { description: product.title, source: sizeImageSource(
|
|
6051
|
+
const source2 = PostPurchasePrimaryImageSource.parse((selectedImage ?? product.image)?.src || void 0);
|
|
6052
|
+
return { description: product.title, source: sizeImageSource(source2, "800x800") };
|
|
6053
6053
|
};
|
|
6054
6054
|
|
|
6055
6055
|
// src/server/postPurchaseProductGallery.ts
|
|
@@ -6078,26 +6078,26 @@ var projectPostPurchaseProductDisplay = (effective, metadata, product) => PostPu
|
|
|
6078
6078
|
// src/server/projectPostPurchaseProduct.ts
|
|
6079
6079
|
var projectPostPurchaseProduct = ({ data, effective, metadata, original }, selectedQuantity) => {
|
|
6080
6080
|
const product = data[0];
|
|
6081
|
-
const
|
|
6081
|
+
const variant2 = product.variants[0];
|
|
6082
6082
|
return {
|
|
6083
6083
|
display: projectPostPurchaseProductDisplay(effective, metadata, product),
|
|
6084
6084
|
labels: effective.language.global,
|
|
6085
|
-
product: { ...product, variant },
|
|
6085
|
+
product: { ...product, variant: variant2 },
|
|
6086
6086
|
selection: {
|
|
6087
6087
|
productId: product.id,
|
|
6088
6088
|
quantity: selectedQuantity?.quantity ?? product.metadata?.productQuantity ?? (original.quantityInputs.enabled ? original.quantityInputs.defaultQuantity : 1),
|
|
6089
|
-
variantId:
|
|
6089
|
+
variantId: variant2.id
|
|
6090
6090
|
}
|
|
6091
6091
|
};
|
|
6092
6092
|
};
|
|
6093
6093
|
|
|
6094
6094
|
// src/server/prepareNormalizedSubscription.ts
|
|
6095
|
-
var prepareNormalizedSubscription = (normalized, report, plan,
|
|
6095
|
+
var prepareNormalizedSubscription = (normalized, report, plan, quantity2, allowCollection = false) => {
|
|
6096
6096
|
if (!plan) return { reason: "Subscription plan is unavailable", status: "unsupported" };
|
|
6097
|
-
const reason = subscriptionUnavailable(normalized, plan, allowCollection,
|
|
6097
|
+
const reason = subscriptionUnavailable(normalized, plan, allowCollection, quantity2);
|
|
6098
6098
|
if (reason) return { reason, status: "unsupported" };
|
|
6099
6099
|
const { effective } = normalized;
|
|
6100
|
-
const projected = projectPostPurchaseProduct(normalized,
|
|
6100
|
+
const projected = projectPostPurchaseProduct(normalized, quantity2);
|
|
6101
6101
|
const { discount, shipping } = PostPurchaseSubscriptionSettings.parse(effective.subscription);
|
|
6102
6102
|
const shippingPrice = shipping.type === "free" ? 0 : shipping.amount;
|
|
6103
6103
|
return PreparedPostPurchaseSubscription.parse({
|
|
@@ -6134,6 +6134,412 @@ var preparePostPurchaseSubscription = (settings, response, report) => {
|
|
|
6134
6134
|
);
|
|
6135
6135
|
};
|
|
6136
6136
|
|
|
6137
|
+
// src/schema/postPurchaseOfferEligibility.ts
|
|
6138
|
+
import { z as z57 } from "zod";
|
|
6139
|
+
|
|
6140
|
+
// src/schema/postPurchaseProductCollectionView.ts
|
|
6141
|
+
import { z as z56 } from "zod";
|
|
6142
|
+
var PostPurchaseExcludedProductIds = z56.array(PostPurchaseProductId).default([]);
|
|
6143
|
+
|
|
6144
|
+
// src/schema/postPurchaseOfferEligibility.ts
|
|
6145
|
+
var selection = PreparedPostPurchaseProduct.shape.selection;
|
|
6146
|
+
var PostPurchaseOfferSkipReason = z57.enum(["empty", "no-eligible-subscription"]);
|
|
6147
|
+
var PostPurchaseOfferEligibilityContext = z57.object({
|
|
6148
|
+
excludedProductIds: PostPurchaseExcludedProductIds,
|
|
6149
|
+
originalLineItems: z57.array(selection.pick({ productId: true, sellingPlanId: true, variantId: true }))
|
|
6150
|
+
});
|
|
6151
|
+
var PostPurchaseOfferEligibility = z57.discriminatedUnion("status", [
|
|
6152
|
+
z57.object({
|
|
6153
|
+
members: z57.array(
|
|
6154
|
+
z57.object({ productId: selection.shape.productId, productIndex: z57.number().int().nonnegative() })
|
|
6155
|
+
),
|
|
6156
|
+
status: z57.literal("retain")
|
|
6157
|
+
}),
|
|
6158
|
+
z57.object({ reason: PostPurchaseOfferSkipReason, status: z57.literal("skip") }),
|
|
6159
|
+
z57.object({ reason: z57.literal("eligible-upgrade").optional(), status: z57.literal("unavailable") })
|
|
6160
|
+
]);
|
|
6161
|
+
|
|
6162
|
+
// src/server/normalizePostPurchaseCollection.ts
|
|
6163
|
+
import { z as z58 } from "zod";
|
|
6164
|
+
var normalizePostPurchaseCollection = (settings, response, excludedProductIds) => {
|
|
6165
|
+
const normalized = normalizePostPurchaseProduct(settings, response);
|
|
6166
|
+
const limit = z58.number().int().positive();
|
|
6167
|
+
limit.parse(normalized.original.productLimit);
|
|
6168
|
+
const prefix = normalized.data.slice(0, limit.parse(normalized.effective.productLimit));
|
|
6169
|
+
if (new Set(prefix.map(({ id }) => id)).size !== prefix.length)
|
|
6170
|
+
throw new Error("Ambiguous post-purchase collection");
|
|
6171
|
+
const excluded = new Set(PostPurchaseExcludedProductIds.parse(excludedProductIds));
|
|
6172
|
+
const members = prefix.map((product, productIndex) => ({ product, productIndex })).filter(({ product }) => !excluded.has(product.id));
|
|
6173
|
+
return { members, normalized };
|
|
6174
|
+
};
|
|
6175
|
+
|
|
6176
|
+
// src/schema/postPurchaseVariantCatalog.ts
|
|
6177
|
+
import { z as z59 } from "zod";
|
|
6178
|
+
var PostPurchaseVariantSelector = z59.object({ variantId: PostPurchaseVariantId }).strict();
|
|
6179
|
+
var PostPurchaseVariantOption = OfferProduct.shape.options.element.extend({
|
|
6180
|
+
id: z59.number().int().positive(),
|
|
6181
|
+
position: z59.number().int().min(1).max(3)
|
|
6182
|
+
});
|
|
6183
|
+
var PostPurchaseVariantValues = OfferProduct.shape.variants.element.pick({
|
|
6184
|
+
option1: true,
|
|
6185
|
+
option2: true,
|
|
6186
|
+
option3: true
|
|
6187
|
+
});
|
|
6188
|
+
var PostPurchaseVariantCatalog = z59.object({
|
|
6189
|
+
displayMode: PostPurchaseSettings.shape.productOptions.shape.variantSelectorDisplayMode,
|
|
6190
|
+
options: z59.array(PostPurchaseVariantOption),
|
|
6191
|
+
productId: PostPurchaseProductId,
|
|
6192
|
+
showSelectors: PostPurchaseSettings.shape.productOptions.shape.showVariantSelectors,
|
|
6193
|
+
variants: z59.array(
|
|
6194
|
+
PostPurchaseVariantValues.partial().extend({
|
|
6195
|
+
available: z59.boolean(),
|
|
6196
|
+
id: PostPurchaseVariantId,
|
|
6197
|
+
imageId: z59.number().int().nonnegative().nullish(),
|
|
6198
|
+
title: OfferProduct.shape.variants.element.shape.title
|
|
6199
|
+
})
|
|
6200
|
+
)
|
|
6201
|
+
});
|
|
6202
|
+
|
|
6203
|
+
// src/server/postPurchaseVariantCatalog.ts
|
|
6204
|
+
var projectPostPurchaseVariantCatalog = (product, settings) => {
|
|
6205
|
+
const options2 = PostPurchaseVariantCatalog.shape.options.parse(product.options === void 0 ? [] : product.options).sort((a, b) => a.position - b.position);
|
|
6206
|
+
const variants = product.variants.map((variant2) => ({
|
|
6207
|
+
...variant2,
|
|
6208
|
+
...PostPurchaseVariantValues.partial().parse(variant2)
|
|
6209
|
+
}));
|
|
6210
|
+
const tuples = variants.map(({ option1, option2, option3 }) => [option1, option2, option3]);
|
|
6211
|
+
if (new Set(product.variants.map(({ id }) => id)).size !== product.variants.length || product.variants.some(({ productId: productId2 }) => productId2 !== product.id) || new Set(options2.map(({ id }) => id)).size !== options2.length || options2.some(
|
|
6212
|
+
({ position, values: values2 }, index) => position !== index + 1 || new Set(values2).size !== values2.length
|
|
6213
|
+
) || product.variants.length > 1 && new Set(tuples.map((tuple) => JSON.stringify(tuple))).size !== tuples.length)
|
|
6214
|
+
throw new Error("Ambiguous post-purchase variant catalog");
|
|
6215
|
+
for (const tuple of tuples) {
|
|
6216
|
+
if (options2.some(({ position, values: values2 }) => !values2.some((value) => value === tuple[position - 1])) || tuple.some((value, index) => value != null && !options2[index]))
|
|
6217
|
+
throw new Error("Variant option tuple does not match the catalog");
|
|
6218
|
+
}
|
|
6219
|
+
return PostPurchaseVariantCatalog.parse({
|
|
6220
|
+
displayMode: settings.productOptions.variantSelectorDisplayMode,
|
|
6221
|
+
options: options2,
|
|
6222
|
+
productId: product.id,
|
|
6223
|
+
showSelectors: settings.productOptions.showVariantSelectors,
|
|
6224
|
+
variants: variants.map(({ id, imageId, option1, option2, option3, title, ...inventory }) => ({
|
|
6225
|
+
available: postPurchaseVariantAvailable(inventory),
|
|
6226
|
+
id,
|
|
6227
|
+
imageId,
|
|
6228
|
+
option1,
|
|
6229
|
+
option2,
|
|
6230
|
+
option3,
|
|
6231
|
+
title
|
|
6232
|
+
}))
|
|
6233
|
+
});
|
|
6234
|
+
};
|
|
6235
|
+
|
|
6236
|
+
// src/schema/postPurchaseGroupCatalog.ts
|
|
6237
|
+
import { z as z60 } from "zod";
|
|
6238
|
+
var productId = PreparedPostPurchaseProduct.shape.selection.shape.productId;
|
|
6239
|
+
var source = PostPurchaseProductSource.shape.data.element;
|
|
6240
|
+
var PostPurchaseGroupDescription = source.pick({ description: true, id: true, image: true, images: true, title: true }).extend({
|
|
6241
|
+
description: source.shape.description.default(null),
|
|
6242
|
+
image: source.shape.image.default(null),
|
|
6243
|
+
options: PostPurchaseVariantCatalog.shape.options.default([])
|
|
6244
|
+
});
|
|
6245
|
+
var PostPurchaseGroupCatalog = z60.object({
|
|
6246
|
+
memberProductId: productId,
|
|
6247
|
+
options: z60.array(z60.object({ productId, title: z60.string(), variantCatalog: PostPurchaseVariantCatalog }))
|
|
6248
|
+
});
|
|
6249
|
+
var PostPurchaseGroupSelection = z60.object({
|
|
6250
|
+
memberProductId: productId,
|
|
6251
|
+
productId
|
|
6252
|
+
});
|
|
6253
|
+
|
|
6254
|
+
// src/server/readPostPurchaseGroup.ts
|
|
6255
|
+
var readPostPurchaseGroup = (product, settings, excludedProductIds) => {
|
|
6256
|
+
const descriptions = PostPurchaseGroupDescription.nullable().array().parse(product.productGroupVariants).filter((value) => value !== null);
|
|
6257
|
+
const ids = new Set(descriptions.map((value) => value.id));
|
|
6258
|
+
if (ids.size !== descriptions.length || new Set(product.variants.map(({ id }) => id)).size !== product.variants.length || product.variants.some(({ productId: productId2 }) => !ids.has(productId2)))
|
|
6259
|
+
throw new Error("Ambiguous post-purchase group ownership");
|
|
6260
|
+
const excluded = new Set(PostPurchaseExcludedProductIds.parse(excludedProductIds));
|
|
6261
|
+
const entries = descriptions.map((description) => {
|
|
6262
|
+
const value = {
|
|
6263
|
+
...product,
|
|
6264
|
+
...description,
|
|
6265
|
+
images: description.images,
|
|
6266
|
+
productGroupVariants: [],
|
|
6267
|
+
variants: product.variants.filter(({ productId: productId2 }) => productId2 === description.id)
|
|
6268
|
+
};
|
|
6269
|
+
return { product: value, variantCatalog: projectPostPurchaseVariantCatalog(value, settings) };
|
|
6270
|
+
}).filter(({ product: value }) => !excluded.has(value.id));
|
|
6271
|
+
return {
|
|
6272
|
+
catalog: PostPurchaseGroupCatalog.parse({
|
|
6273
|
+
memberProductId: product.id,
|
|
6274
|
+
options: entries.map(({ product: value, variantCatalog }) => ({
|
|
6275
|
+
productId: value.id,
|
|
6276
|
+
title: value.title,
|
|
6277
|
+
variantCatalog
|
|
6278
|
+
}))
|
|
6279
|
+
}),
|
|
6280
|
+
entries
|
|
6281
|
+
};
|
|
6282
|
+
};
|
|
6283
|
+
|
|
6284
|
+
// src/server/postPurchaseMemberEligibility.ts
|
|
6285
|
+
var PostPurchaseInventoryUnavailable = class extends Error {
|
|
6286
|
+
};
|
|
6287
|
+
var postPurchaseMemberEligibility = (normalized, product, excluded) => {
|
|
6288
|
+
if (product.productGroupVariants.length) {
|
|
6289
|
+
const group = readPostPurchaseGroup(product, normalized.effective, excluded);
|
|
6290
|
+
return group.entries.map(({ product: option }) => postPurchaseMemberEligibility(normalized, option)).some(Boolean);
|
|
6291
|
+
}
|
|
6292
|
+
if (!product.variants.length) throw new Error("Unsupported catalog");
|
|
6293
|
+
const variants = projectPostPurchaseVariantCatalog(product, normalized.effective).variants;
|
|
6294
|
+
const catalogs = product.variants.map((variant2) => {
|
|
6295
|
+
const catalog = projectPostPurchasePlanCatalog({
|
|
6296
|
+
...normalized,
|
|
6297
|
+
data: [{ ...product, variants: [variant2] }]
|
|
6298
|
+
});
|
|
6299
|
+
if (!catalog) throw new Error("Unreadable subscription catalog");
|
|
6300
|
+
if (normalized.effective.productType === "one-time" && catalog.requiresSellingPlan)
|
|
6301
|
+
throw new Error("Unsupported purchase mode");
|
|
6302
|
+
return catalog;
|
|
6303
|
+
});
|
|
6304
|
+
if (!variants.some((variant2) => variant2.available))
|
|
6305
|
+
throw new PostPurchaseInventoryUnavailable("Unavailable inventory");
|
|
6306
|
+
return catalogs.some(
|
|
6307
|
+
(catalog, index) => variants[index].available && (normalized.effective.productType !== "subscription" && !catalog.requiresSellingPlan || normalized.effective.productType !== "one-time" && catalog.plans.length > 0)
|
|
6308
|
+
);
|
|
6309
|
+
};
|
|
6310
|
+
|
|
6311
|
+
// src/server/classifyPostPurchaseOffer.ts
|
|
6312
|
+
var classifyPostPurchaseOffer = (settings, response, context) => {
|
|
6313
|
+
try {
|
|
6314
|
+
const trusted = PostPurchaseOfferEligibilityContext.parse(context);
|
|
6315
|
+
const { members, normalized } = normalizePostPurchaseCollection(settings, response);
|
|
6316
|
+
const configurations = [normalized.original, normalized.effective];
|
|
6317
|
+
const upgrades = configurations.some((config) => config.upgradeToSubscription.allow);
|
|
6318
|
+
const oneTime = new Set(
|
|
6319
|
+
trusted.originalLineItems.filter((line) => line.sellingPlanId === void 0).map((line) => line.variantId)
|
|
6320
|
+
);
|
|
6321
|
+
if (upgrades && members.some(
|
|
6322
|
+
({ product }) => product.sellingPlanGroups?.length && product.variants.some((variant2) => oneTime.has(variant2.id))
|
|
6323
|
+
))
|
|
6324
|
+
return { reason: "eligible-upgrade", status: "unavailable" };
|
|
6325
|
+
if (normalized.effective.productType !== "one-time") {
|
|
6326
|
+
configurations.forEach((config) => PostPurchaseSubscriptionSettings.parse(config.subscription));
|
|
6327
|
+
}
|
|
6328
|
+
const classified = members.map((member) => {
|
|
6329
|
+
try {
|
|
6330
|
+
return {
|
|
6331
|
+
...member,
|
|
6332
|
+
eligible: postPurchaseMemberEligibility(normalized, member.product, trusted.excludedProductIds)
|
|
6333
|
+
};
|
|
6334
|
+
} catch (error) {
|
|
6335
|
+
if (error instanceof PostPurchaseInventoryUnavailable && !member.product.productGroupVariants.length && trusted.excludedProductIds.includes(member.product.id))
|
|
6336
|
+
return { ...member, eligible: false };
|
|
6337
|
+
throw error;
|
|
6338
|
+
}
|
|
6339
|
+
});
|
|
6340
|
+
if (!members.length) return { reason: "empty", status: "skip" };
|
|
6341
|
+
if (upgrades) return { reason: "no-eligible-subscription", status: "skip" };
|
|
6342
|
+
const candidates = classified.filter(
|
|
6343
|
+
({ product }) => product.productGroupVariants.length ? readPostPurchaseGroup(product, normalized.effective, trusted.excludedProductIds).entries.length > 0 : !trusted.excludedProductIds.includes(product.id)
|
|
6344
|
+
);
|
|
6345
|
+
if (!candidates.length) return { reason: "empty", status: "skip" };
|
|
6346
|
+
const retained = candidates.filter(({ eligible }) => eligible);
|
|
6347
|
+
return retained.length ? {
|
|
6348
|
+
members: retained.map(({ product, productIndex }) => ({
|
|
6349
|
+
productId: product.id,
|
|
6350
|
+
productIndex
|
|
6351
|
+
})),
|
|
6352
|
+
status: "retain"
|
|
6353
|
+
} : { reason: "no-eligible-subscription", status: "skip" };
|
|
6354
|
+
} catch {
|
|
6355
|
+
return { status: "unavailable" };
|
|
6356
|
+
}
|
|
6357
|
+
};
|
|
6358
|
+
|
|
6359
|
+
// src/schema/postPurchaseVariantDefault.ts
|
|
6360
|
+
import { z as z61 } from "zod";
|
|
6361
|
+
var values = PostPurchaseVariantValues.partial().extend({
|
|
6362
|
+
option1: PostPurchaseVariantValues.shape.option1.nullish()
|
|
6363
|
+
});
|
|
6364
|
+
var variant = values.extend({
|
|
6365
|
+
id: PostPurchaseVariantId,
|
|
6366
|
+
inventoryManagement: z61.string().nullable(),
|
|
6367
|
+
inventoryPolicy: z61.string(),
|
|
6368
|
+
inventoryQuantity: z61.number()
|
|
6369
|
+
});
|
|
6370
|
+
var options = z61.array(PostPurchaseVariantOption.pick({ name: true, values: true }));
|
|
6371
|
+
var PostPurchaseVariantDefaultProduct = z61.object({
|
|
6372
|
+
id: PostPurchaseProductId,
|
|
6373
|
+
options,
|
|
6374
|
+
selectedVariant: variant.optional(),
|
|
6375
|
+
variants: z61.array(variant)
|
|
6376
|
+
});
|
|
6377
|
+
var PostPurchaseVariantDefaultSettings = PostPurchaseSettings.shape.productOptions.pick({
|
|
6378
|
+
hideOutOfStockVariants: true,
|
|
6379
|
+
matchVariant: true
|
|
6380
|
+
});
|
|
6381
|
+
var PostPurchaseOrderAttributes = z61.record(z61.string(), z61.array(z61.string())).default({});
|
|
6382
|
+
var PostPurchaseOriginalVariants = z61.array(
|
|
6383
|
+
z61.object({ productId: PostPurchaseProductId, variantId: PostPurchaseVariantId })
|
|
6384
|
+
);
|
|
6385
|
+
var PostPurchaseAttributeProducts = z61.array(
|
|
6386
|
+
z61.object({ id: PostPurchaseProductId, options, variants: z61.array(values.extend({ id: PostPurchaseVariantId })) })
|
|
6387
|
+
);
|
|
6388
|
+
|
|
6389
|
+
// src/server/createPostPurchaseOrderAttributes.ts
|
|
6390
|
+
var createPostPurchaseOrderAttributes = (original, enriched) => {
|
|
6391
|
+
const products = PostPurchaseAttributeProducts.parse(enriched);
|
|
6392
|
+
const attributes = {};
|
|
6393
|
+
for (const item of PostPurchaseOriginalVariants.parse(original)) {
|
|
6394
|
+
const product = products.find(({ id }) => id === item.productId);
|
|
6395
|
+
const variant2 = product?.variants.find(({ id }) => id === item.variantId);
|
|
6396
|
+
if (!variant2 || !product) continue;
|
|
6397
|
+
["option1", "option2", "option3"].forEach((key, index) => {
|
|
6398
|
+
const value = variant2[key];
|
|
6399
|
+
const option = product.options[index];
|
|
6400
|
+
if (!value || !option) return;
|
|
6401
|
+
const values2 = attributes[option.name] ?? [];
|
|
6402
|
+
if (!values2.includes(value)) attributes[option.name] = [...values2, value];
|
|
6403
|
+
});
|
|
6404
|
+
}
|
|
6405
|
+
return attributes;
|
|
6406
|
+
};
|
|
6407
|
+
|
|
6408
|
+
// src/server/readPostPurchaseGroupSelection.ts
|
|
6409
|
+
var readPostPurchaseGroupSelection = (settings, response, requested, excludedProductIds) => {
|
|
6410
|
+
const selection2 = PostPurchaseGroupSelection.parse(requested);
|
|
6411
|
+
const { members, normalized } = normalizePostPurchaseCollection(settings, response);
|
|
6412
|
+
const member = members.find(({ product }) => product.id === selection2.memberProductId);
|
|
6413
|
+
if (!member || !member.product.productGroupVariants.length) return null;
|
|
6414
|
+
const group = readPostPurchaseGroup(member.product, normalized.effective, excludedProductIds);
|
|
6415
|
+
const entry = group.entries.find(({ product }) => product.id === selection2.productId);
|
|
6416
|
+
if (!entry) return null;
|
|
6417
|
+
return {
|
|
6418
|
+
groupCatalog: group.catalog,
|
|
6419
|
+
memberProductId: member.product.id,
|
|
6420
|
+
productIndex: member.productIndex,
|
|
6421
|
+
reportingProduct: { id: member.product.id, title: member.product.title },
|
|
6422
|
+
response: { data: [entry.product], metadata: normalized.metadata },
|
|
6423
|
+
variantCatalog: entry.variantCatalog
|
|
6424
|
+
};
|
|
6425
|
+
};
|
|
6426
|
+
|
|
6427
|
+
// src/server/preparePostPurchaseGroupDeclineDisplay.ts
|
|
6428
|
+
var preparePostPurchaseGroupDeclineDisplay = (settings, response, requested, excludedProductIds) => {
|
|
6429
|
+
const group = readPostPurchaseGroupSelection(settings, response, requested, excludedProductIds);
|
|
6430
|
+
const variant2 = group?.variantCatalog.variants.find(({ id }) => id === requested.variantId);
|
|
6431
|
+
return group && variant2 ? {
|
|
6432
|
+
display: {
|
|
6433
|
+
productTitle: group.reportingProduct.title,
|
|
6434
|
+
variantId: variant2.id,
|
|
6435
|
+
variantTitle: variant2.title
|
|
6436
|
+
},
|
|
6437
|
+
productIndex: group.productIndex
|
|
6438
|
+
} : null;
|
|
6439
|
+
};
|
|
6440
|
+
|
|
6441
|
+
// src/server/preparePostPurchaseOfferPresentation.ts
|
|
6442
|
+
import { merge as merge2 } from "es-toolkit/compat";
|
|
6443
|
+
import { z as z64 } from "zod";
|
|
6444
|
+
|
|
6445
|
+
// src/schema/postPurchaseOfferPresentation.ts
|
|
6446
|
+
import { z as z62 } from "zod";
|
|
6447
|
+
var language2 = PostPurchaseSettings.shape.language.shape.global.unwrap().unwrap();
|
|
6448
|
+
var PostPurchaseOfferPresentation = z62.strictObject({
|
|
6449
|
+
labels: language2.pick({ declineAll: true, declineThisOffer: true }),
|
|
6450
|
+
layout: PostPurchaseSettings.shape.offersLayout,
|
|
6451
|
+
sections: CABRootSection.nullable(),
|
|
6452
|
+
showDeclineAll: PostPurchaseSettings.shape.productOptions.shape.showDeclineAll
|
|
6453
|
+
});
|
|
6454
|
+
|
|
6455
|
+
// src/server/postPurchaseOfferCopy.ts
|
|
6456
|
+
import { z as z63 } from "zod";
|
|
6457
|
+
var Copy = z63.object({
|
|
6458
|
+
superTitle: CalloutBannerBlock.shape.settings.shape.superTitle.unwrap().optional().catch(void 0),
|
|
6459
|
+
title: CalloutBannerBlock.shape.settings.shape.title.unwrap().optional().catch(void 0)
|
|
6460
|
+
});
|
|
6461
|
+
var Callout = z63.object({ settings: z63.record(z63.string(), z63.unknown()), type: z63.literal("callout_banner") });
|
|
6462
|
+
var postPurchaseOfferCopy = (blocks, metadata) => {
|
|
6463
|
+
const copy = Copy.safeParse(metadata.widget.language);
|
|
6464
|
+
if (!blocks || !copy.success) return blocks;
|
|
6465
|
+
const first = blocks.findIndex((block) => Callout.pick({ type: true }).safeParse(block).success);
|
|
6466
|
+
return blocks.map((block, index) => {
|
|
6467
|
+
if (index !== first) return block;
|
|
6468
|
+
const callout = Callout.passthrough().safeParse(block);
|
|
6469
|
+
if (!callout.success) return block;
|
|
6470
|
+
return {
|
|
6471
|
+
...callout.data,
|
|
6472
|
+
settings: {
|
|
6473
|
+
...callout.data.settings,
|
|
6474
|
+
...copy.data.title && { title: copy.data.title },
|
|
6475
|
+
...copy.data.superTitle && { superTitle: copy.data.superTitle }
|
|
6476
|
+
}
|
|
6477
|
+
};
|
|
6478
|
+
});
|
|
6479
|
+
};
|
|
6480
|
+
|
|
6481
|
+
// src/server/preparePostPurchaseOfferPresentation.ts
|
|
6482
|
+
var FrameSettings = PostPurchaseSettings.pick({ language: true, offersLayout: true, productOptions: true }).extend({
|
|
6483
|
+
blocks: z64.array(z64.unknown()).optional()
|
|
6484
|
+
});
|
|
6485
|
+
var preparePostPurchaseOfferPresentation = (widgetId, settings, response, report) => {
|
|
6486
|
+
const { metadata } = PostPurchaseProductSource.pick({ metadata: true }).parse(deepCamelCase(response));
|
|
6487
|
+
const original = FrameSettings.parse(deepCamelCase(settings));
|
|
6488
|
+
const effective = FrameSettings.parse(merge2({}, original, metadata.widget));
|
|
6489
|
+
let sections = null;
|
|
6490
|
+
try {
|
|
6491
|
+
sections = convertMessagePreview(
|
|
6492
|
+
widgetId,
|
|
6493
|
+
{ blocks: postPurchaseOfferCopy(effective.blocks, metadata), type: "shopify_post_purchase_extension" },
|
|
6494
|
+
report
|
|
6495
|
+
);
|
|
6496
|
+
} catch (error) {
|
|
6497
|
+
if (!(error instanceof NotFoundError)) throw error;
|
|
6498
|
+
}
|
|
6499
|
+
return PostPurchaseOfferPresentation.parse({
|
|
6500
|
+
labels: effective.language.global,
|
|
6501
|
+
layout: effective.offersLayout,
|
|
6502
|
+
sections,
|
|
6503
|
+
showDeclineAll: effective.productOptions.showDeclineAll
|
|
6504
|
+
});
|
|
6505
|
+
};
|
|
6506
|
+
|
|
6507
|
+
// src/schema/postPurchaseQuantity.ts
|
|
6508
|
+
import { z as z65 } from "zod";
|
|
6509
|
+
var quantity = PreparedPostPurchaseProduct.shape.selection.shape.quantity;
|
|
6510
|
+
var PostPurchaseQuantityPolicy = PostPurchaseSettings.shape.quantityInputs.omit({ defaultQuantity: true }).extend({
|
|
6511
|
+
initialQuantity: quantity,
|
|
6512
|
+
maxValue: quantity,
|
|
6513
|
+
minValue: z65.literal(0).transform(() => 1).or(quantity)
|
|
6514
|
+
}).refine(({ maxValue, minValue }) => minValue <= maxValue, "Quantity bounds are reversed");
|
|
6515
|
+
|
|
6516
|
+
// src/server/readPostPurchaseQuantity.ts
|
|
6517
|
+
var PostPurchaseQuantityUnavailable = class extends Error {
|
|
6518
|
+
};
|
|
6519
|
+
var readPostPurchaseQuantity = ({
|
|
6520
|
+
data,
|
|
6521
|
+
effective,
|
|
6522
|
+
original
|
|
6523
|
+
}, selection2) => {
|
|
6524
|
+
const positive = PreparedPostPurchaseProduct.shape.selection.shape.quantity;
|
|
6525
|
+
for (const config of [original, effective]) {
|
|
6526
|
+
if (!config.quantityInputs.enabled) continue;
|
|
6527
|
+
const initialQuantity2 = positive.parse(config.quantityInputs.defaultQuantity);
|
|
6528
|
+
const policy2 = PostPurchaseQuantityPolicy.parse({ ...config.quantityInputs, initialQuantity: initialQuantity2 });
|
|
6529
|
+
if (initialQuantity2 < policy2.minValue || initialQuantity2 > policy2.maxValue)
|
|
6530
|
+
throw new Error("Configured quantity default is outside its bounds");
|
|
6531
|
+
}
|
|
6532
|
+
const initialQuantity = data[0]?.metadata?.productQuantity ?? (original.quantityInputs.enabled ? original.quantityInputs.defaultQuantity : 1);
|
|
6533
|
+
const policy = PostPurchaseQuantityPolicy.parse(
|
|
6534
|
+
effective.quantityInputs.enabled ? { ...effective.quantityInputs, initialQuantity } : { enabled: false, initialQuantity, maxValue: initialQuantity, minValue: initialQuantity }
|
|
6535
|
+
);
|
|
6536
|
+
const requested = "quantity" in selection2 ? selection2.quantity : selection2.expectedQuantity === initialQuantity ? void 0 : selection2.expectedQuantity;
|
|
6537
|
+
const quantity2 = positive.parse(requested ?? initialQuantity);
|
|
6538
|
+
if (requested !== void 0 && (policy.enabled ? quantity2 < policy.minValue || quantity2 > policy.maxValue : quantity2 !== initialQuantity))
|
|
6539
|
+
throw new PostPurchaseQuantityUnavailable("Requested quantity is unavailable");
|
|
6540
|
+
return { policy, quantity: quantity2 };
|
|
6541
|
+
};
|
|
6542
|
+
|
|
6137
6543
|
// src/server/analytics.ts
|
|
6138
6544
|
import { chunk } from "es-toolkit";
|
|
6139
6545
|
|
|
@@ -6178,8 +6584,8 @@ var TAXONOMY = {
|
|
|
6178
6584
|
"added-to-cart": {
|
|
6179
6585
|
/** React credits the add to the A/B-selected variant (`defined_noun_id: selectedId`). */
|
|
6180
6586
|
buildDefinedNounId: ({ selectedId }) => selectedId != null ? String(selectedId) : void 0,
|
|
6181
|
-
buildMeta: ({ productId, variantId }) => ({
|
|
6182
|
-
...
|
|
6587
|
+
buildMeta: ({ productId: productId2, variantId }) => ({
|
|
6588
|
+
...productId2 != null && { [`product_id:${productId2}`]: true },
|
|
6183
6589
|
...variantId != null && { [`variant_id:${variantId}`]: true }
|
|
6184
6590
|
}),
|
|
6185
6591
|
buildTags: experimentTags,
|
|
@@ -6270,7 +6676,7 @@ var postAnalyticsEvents = async (input, ctx) => {
|
|
|
6270
6676
|
};
|
|
6271
6677
|
|
|
6272
6678
|
// src/server/requestSchemas.ts
|
|
6273
|
-
import { z as
|
|
6679
|
+
import { z as z66 } from "zod";
|
|
6274
6680
|
var REQUEST_BOUNDS = {
|
|
6275
6681
|
/** Cart-level attributes per cart. */
|
|
6276
6682
|
CART_ATTRIBUTES_MAX: 100,
|
|
@@ -6301,42 +6707,42 @@ var REQUEST_BOUNDS = {
|
|
|
6301
6707
|
/** Rich ads transaction lines — the engine's ads contract. */
|
|
6302
6708
|
TRANSACTION_ITEMS_MAX: 50
|
|
6303
6709
|
};
|
|
6304
|
-
var KeyValue =
|
|
6305
|
-
key:
|
|
6306
|
-
value:
|
|
6710
|
+
var KeyValue = z66.object({
|
|
6711
|
+
key: z66.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
|
|
6712
|
+
value: z66.string().max(REQUEST_BOUNDS.STRING_VALUE_MAX).optional()
|
|
6307
6713
|
});
|
|
6308
|
-
var CartLineInputSchema =
|
|
6309
|
-
productId:
|
|
6310
|
-
properties:
|
|
6311
|
-
quantity:
|
|
6312
|
-
subscriptionId:
|
|
6313
|
-
variantId:
|
|
6714
|
+
var CartLineInputSchema = z66.object({
|
|
6715
|
+
productId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
6716
|
+
properties: z66.array(KeyValue).max(REQUEST_BOUNDS.LINE_PROPERTIES_MAX).optional(),
|
|
6717
|
+
quantity: z66.number(),
|
|
6718
|
+
subscriptionId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6719
|
+
variantId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX)
|
|
6314
6720
|
});
|
|
6315
|
-
var CartInputSchema =
|
|
6316
|
-
attributes:
|
|
6721
|
+
var CartInputSchema = z66.object({
|
|
6722
|
+
attributes: z66.array(KeyValue).max(REQUEST_BOUNDS.CART_ATTRIBUTES_MAX).optional(),
|
|
6317
6723
|
/**
|
|
6318
6724
|
* Presentment-per-shop-currency FX rate (buyer price ÷ shop price, e.g. `1.35` for a USD shop
|
|
6319
6725
|
* selling in CAD). Money rule thresholds are authored in SHOP currency, so the engine subtotal is
|
|
6320
6726
|
* divided by this before evaluation. Omit (or send 1) when the cart is already in the shop's currency.
|
|
6321
6727
|
*/
|
|
6322
|
-
currencyRate:
|
|
6728
|
+
currencyRate: z66.number().optional(),
|
|
6323
6729
|
/** Applied discount codes; the engine evaluates `discount_code` rules against them (sent as `[{code}]`). */
|
|
6324
|
-
discountCodes:
|
|
6730
|
+
discountCodes: z66.array(z66.string().max(REQUEST_BOUNDS.STRING_KEY_MAX)).max(REQUEST_BOUNDS.DISCOUNT_CODES_MAX).optional(),
|
|
6325
6731
|
/** Presentment cents of cart-level discount allocations, subtracted from `subtotal` for the engine. */
|
|
6326
|
-
discountTotal:
|
|
6327
|
-
items:
|
|
6732
|
+
discountTotal: z66.number().optional(),
|
|
6733
|
+
items: z66.array(CartLineInputSchema).max(REQUEST_BOUNDS.CART_ITEMS_MAX),
|
|
6328
6734
|
/** Presentment subtotal in cents. */
|
|
6329
|
-
subtotal:
|
|
6735
|
+
subtotal: z66.number()
|
|
6330
6736
|
});
|
|
6331
|
-
var UserConfigInputSchema =
|
|
6332
|
-
var DataSourceInputSchema =
|
|
6737
|
+
var UserConfigInputSchema = z66.object({ shop: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX) });
|
|
6738
|
+
var DataSourceInputSchema = z66.object({
|
|
6333
6739
|
cart: CartInputSchema,
|
|
6334
6740
|
/**
|
|
6335
6741
|
* Numeric Shopify company-location id when the buyer is a B2B session (`buyerIdentity.purchasingCompany`).
|
|
6336
6742
|
* Present ⇒ the orchestrator filters results by the location's catalog via admin-api (REB-23713); the
|
|
6337
6743
|
* client's country-context market check is bypassed for B2B (it false-negatives B2B-catalog products).
|
|
6338
6744
|
*/
|
|
6339
|
-
companyLocationId:
|
|
6745
|
+
companyLocationId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6340
6746
|
/**
|
|
6341
6747
|
* Buyer's market country (ISO 3166-1 alpha-2) — forwarded to the engine as the `country_code` PARAM
|
|
6342
6748
|
* when the shop's markets toggle is on (REB-21688; the sink was the `X-Country-Code` header under
|
|
@@ -6345,16 +6751,16 @@ var DataSourceInputSchema = z56.object({
|
|
|
6345
6751
|
* uppercase (the wire value is forwarded verbatim as the param) so a case-sensitive engine lookup
|
|
6346
6752
|
* can't silently miss a lowercase code — `adsEngine.ts` uppercases for the same reason.
|
|
6347
6753
|
*/
|
|
6348
|
-
country:
|
|
6349
|
-
customerId:
|
|
6350
|
-
dataSourcePath:
|
|
6754
|
+
country: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).regex(/^[A-Za-z]{2}$/, "must be an ISO 3166-1 alpha-2 country code (e.g. CA)").transform((value) => value.toUpperCase()).optional(),
|
|
6755
|
+
customerId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6756
|
+
dataSourcePath: z66.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
|
|
6351
6757
|
/**
|
|
6352
6758
|
* Engine `filter_inputs` override: `'no'` keeps in-cart (input) products in the results/rule
|
|
6353
6759
|
* outputs — gift validation sends it so a gift's own product can appear in its answer. Omitted = the
|
|
6354
6760
|
* engine's default filtering.
|
|
6355
6761
|
*/
|
|
6356
|
-
filterInputs:
|
|
6357
|
-
integrations:
|
|
6762
|
+
filterInputs: z66.enum(["no", "yes"]).optional(),
|
|
6763
|
+
integrations: z66.record(z66.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), z66.boolean()).refine((record) => Object.keys(record).length <= REQUEST_BOUNDS.INTEGRATION_KEYS_MAX, {
|
|
6358
6764
|
message: `Too many integration keys (max ${REQUEST_BOUNDS.INTEGRATION_KEYS_MAX})`
|
|
6359
6765
|
}).optional(),
|
|
6360
6766
|
/**
|
|
@@ -6367,31 +6773,31 @@ var DataSourceInputSchema = z56.object({
|
|
|
6367
6773
|
* request header) fails the regex. Callers should send the buyer's resolved locale (e.g. Shopify
|
|
6368
6774
|
* checkout's `localization.language.isoCode`), not the request header verbatim.
|
|
6369
6775
|
*/
|
|
6370
|
-
language:
|
|
6371
|
-
limit:
|
|
6372
|
-
productType:
|
|
6373
|
-
shop:
|
|
6374
|
-
visitorId:
|
|
6375
|
-
});
|
|
6376
|
-
var GiftInputSchema =
|
|
6377
|
-
cost:
|
|
6378
|
-
discounted:
|
|
6776
|
+
language: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).regex(/^[A-Za-z0-9-]+$/, "must be a single BCP-47 tag (e.g. fr-CA), not a q-value list").optional(),
|
|
6777
|
+
limit: z66.number().max(REQUEST_BOUNDS.LIMIT_MAX),
|
|
6778
|
+
productType: z66.enum(["both", "one-time", "subscription"]).optional(),
|
|
6779
|
+
shop: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
6780
|
+
visitorId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
|
|
6781
|
+
});
|
|
6782
|
+
var GiftInputSchema = z66.object({
|
|
6783
|
+
cost: z66.number(),
|
|
6784
|
+
discounted: z66.boolean(),
|
|
6379
6785
|
/**
|
|
6380
6786
|
* Which gift attribution the line carries (REB-24363). Defaults to `gwp` because a client that predates
|
|
6381
6787
|
* the field only ever sent GWP lines — without the default an older extension's request would 422.
|
|
6382
6788
|
*/
|
|
6383
|
-
kind:
|
|
6384
|
-
lineId:
|
|
6385
|
-
productId:
|
|
6789
|
+
kind: z66.enum(GIFT_KINDS).default("gwp"),
|
|
6790
|
+
lineId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
6791
|
+
productId: z66.number(),
|
|
6386
6792
|
/**
|
|
6387
6793
|
* The line's unit count (REB-24363) — the selectable-GWP verdict trims surplus units against milestone
|
|
6388
6794
|
* capacity. The second deliberate default: a client predating the field sent only GWP lines, whose
|
|
6389
6795
|
* verdict is whole-line, so a missing quantity reads as one unit rather than 422ing the older request.
|
|
6390
6796
|
*/
|
|
6391
|
-
quantity:
|
|
6392
|
-
widgetId:
|
|
6797
|
+
quantity: z66.number().int().min(1).default(1),
|
|
6798
|
+
widgetId: z66.number()
|
|
6393
6799
|
});
|
|
6394
|
-
var GiftValidationInputSchema =
|
|
6800
|
+
var GiftValidationInputSchema = z66.object({
|
|
6395
6801
|
cart: CartInputSchema,
|
|
6396
6802
|
/**
|
|
6397
6803
|
* Buyer's market country — threaded into the per-widget data-source evaluations, which forward it to
|
|
@@ -6400,25 +6806,25 @@ var GiftValidationInputSchema = z56.object({
|
|
|
6400
6806
|
* turns markets off); regex-bound and uppercase-normalized for the same reasons as
|
|
6401
6807
|
* `DataSourceInputSchema`'s `country`.
|
|
6402
6808
|
*/
|
|
6403
|
-
country:
|
|
6404
|
-
customerId:
|
|
6405
|
-
gifts:
|
|
6809
|
+
country: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).regex(/^[A-Za-z]{2}$/, "must be an ISO 3166-1 alpha-2 country code (e.g. CA)").transform((value) => value.toUpperCase()).optional(),
|
|
6810
|
+
customerId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6811
|
+
gifts: z66.array(GiftInputSchema).max(REQUEST_BOUNDS.GIFTS_MAX),
|
|
6406
6812
|
/**
|
|
6407
6813
|
* Buyer's checkout language — threaded into the per-widget data-source evaluations, which normalize
|
|
6408
6814
|
* and forward it as the engine `locale` param under the same markets-toggle gate (REB-21688). MUST be
|
|
6409
6815
|
* a single BCP-47 tag, for the same reason as `DataSourceInputSchema`'s `language` above.
|
|
6410
6816
|
*/
|
|
6411
|
-
language:
|
|
6412
|
-
shop:
|
|
6413
|
-
visitorId:
|
|
6817
|
+
language: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).regex(/^[A-Za-z0-9-]+$/, "must be a single BCP-47 tag (e.g. fr-CA), not a q-value list").optional(),
|
|
6818
|
+
shop: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
6819
|
+
visitorId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
|
|
6414
6820
|
});
|
|
6415
|
-
var GiftAdjustmentSchema =
|
|
6416
|
-
lineId:
|
|
6417
|
-
quantity:
|
|
6821
|
+
var GiftAdjustmentSchema = z66.object({
|
|
6822
|
+
lineId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
6823
|
+
quantity: z66.number().int().nonnegative()
|
|
6418
6824
|
});
|
|
6419
|
-
var GiftValidationResponseSchema =
|
|
6420
|
-
adjust:
|
|
6421
|
-
remove:
|
|
6825
|
+
var GiftValidationResponseSchema = z66.object({
|
|
6826
|
+
adjust: z66.array(GiftAdjustmentSchema).max(REQUEST_BOUNDS.GIFTS_MAX).default([]),
|
|
6827
|
+
remove: z66.array(z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX)).max(REQUEST_BOUNDS.GIFTS_MAX).refine(
|
|
6422
6828
|
(remove) => new Set(remove).size === remove.length,
|
|
6423
6829
|
"a line id may appear at most once in `remove`"
|
|
6424
6830
|
)
|
|
@@ -6429,47 +6835,47 @@ var GiftValidationResponseSchema = z56.object({
|
|
|
6429
6835
|
({ adjust }) => new Set(adjust.map(({ lineId }) => lineId)).size === adjust.length,
|
|
6430
6836
|
"a line id may appear at most once in `adjust`"
|
|
6431
6837
|
);
|
|
6432
|
-
var MonetizeTransactionItemSchema =
|
|
6433
|
-
id:
|
|
6434
|
-
priceCents:
|
|
6435
|
-
quantity:
|
|
6436
|
-
title:
|
|
6437
|
-
type:
|
|
6438
|
-
});
|
|
6439
|
-
var MonetizeInputSchema =
|
|
6838
|
+
var MonetizeTransactionItemSchema = z66.object({
|
|
6839
|
+
id: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
6840
|
+
priceCents: z66.number(),
|
|
6841
|
+
quantity: z66.number(),
|
|
6842
|
+
title: z66.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX),
|
|
6843
|
+
type: z66.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX)
|
|
6844
|
+
});
|
|
6845
|
+
var MonetizeInputSchema = z66.object({
|
|
6440
6846
|
cart: CartInputSchema,
|
|
6441
6847
|
/** Client-minted render-beacon correlation id; forwarded to the ads engine as `client_request_id`. */
|
|
6442
|
-
clientRequestId:
|
|
6443
|
-
country:
|
|
6444
|
-
currency:
|
|
6848
|
+
clientRequestId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6849
|
+
country: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6850
|
+
currency: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6445
6851
|
/** Ads-targeting identity/geo/locale fields (React parity); folded into the engine query verbatim. */
|
|
6446
|
-
customerEmail:
|
|
6447
|
-
customerFirstName:
|
|
6448
|
-
customerId:
|
|
6449
|
-
customerLastName:
|
|
6450
|
-
language:
|
|
6852
|
+
customerEmail: z66.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
|
|
6853
|
+
customerFirstName: z66.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
|
|
6854
|
+
customerId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6855
|
+
customerLastName: z66.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
|
|
6856
|
+
language: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6451
6857
|
/** Buyer-facing order name (e.g. `#1001`) for the server-composed "Order … Confirmed" chrome line. */
|
|
6452
|
-
orderName:
|
|
6858
|
+
orderName: z66.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
|
|
6453
6859
|
/** Ads surface label, forwarded verbatim; `customer_account` is measured/floored as its own surface (the account-area order list). */
|
|
6454
|
-
placement:
|
|
6860
|
+
placement: z66.enum(["customer_account", "order_status", "thank_you_page"]),
|
|
6455
6861
|
/** Privacy Policy footer href — the Monetize widget's `privacy_policy_url` setting (React parity). */
|
|
6456
|
-
privacyPolicyUrl:
|
|
6862
|
+
privacyPolicyUrl: z66.string().max(REQUEST_BOUNDS.STRING_URL_MAX).optional(),
|
|
6457
6863
|
/** 30-min rolling session id (React parity); used for the ads `session_id`, else the visitor id. */
|
|
6458
|
-
sessionId:
|
|
6459
|
-
shop:
|
|
6864
|
+
sessionId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6865
|
+
shop: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
6460
6866
|
/** Editor/QA indicator; OR-ed into the ads-engine `testing` flag so it stays out of billing/reporting. */
|
|
6461
|
-
testing:
|
|
6462
|
-
timezone:
|
|
6867
|
+
testing: z66.boolean().optional(),
|
|
6868
|
+
timezone: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6463
6869
|
/** Decorated (numeric) order id → the ads `transaction_id`. */
|
|
6464
|
-
transactionId:
|
|
6870
|
+
transactionId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6465
6871
|
/** Rich per-line ads items; capped at the engine's ads contract. Preferred over `cart.items`. */
|
|
6466
|
-
transactionItems:
|
|
6872
|
+
transactionItems: z66.array(MonetizeTransactionItemSchema).max(REQUEST_BOUNDS.TRANSACTION_ITEMS_MAX).optional(),
|
|
6467
6873
|
/** Order total in presentment cents (React prefers total over subtotal); else `cart.subtotal`. */
|
|
6468
|
-
transactionTotal:
|
|
6469
|
-
visitorId:
|
|
6470
|
-
zipCode:
|
|
6874
|
+
transactionTotal: z66.number().optional(),
|
|
6875
|
+
visitorId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6876
|
+
zipCode: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
|
|
6471
6877
|
});
|
|
6472
|
-
var WidgetSettingsInputSchema =
|
|
6878
|
+
var WidgetSettingsInputSchema = z66.object({
|
|
6473
6879
|
/**
|
|
6474
6880
|
* Same domain as `CabShopConfig.cacheKey`, for the same reason: this side WINS the orchestrator's
|
|
6475
6881
|
* `input.cacheKey ?? config.shop.cacheKey` (and an explicit value skips the config read entirely), so
|
|
@@ -6477,9 +6883,9 @@ var WidgetSettingsInputSchema = z56.object({
|
|
|
6477
6883
|
* and pin the edge copy permanently stale. `.catch(undefined)` because a bogus buster should degrade
|
|
6478
6884
|
* the read to un-busted, never 400 a widget render.
|
|
6479
6885
|
*/
|
|
6480
|
-
cacheKey:
|
|
6481
|
-
id:
|
|
6482
|
-
key:
|
|
6886
|
+
cacheKey: z66.number().int().positive().optional().catch(void 0),
|
|
6887
|
+
id: z66.number(),
|
|
6888
|
+
key: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6483
6889
|
/**
|
|
6484
6890
|
* Monetize context for inline hydration: when present AND the widget converts to a Monetize marker,
|
|
6485
6891
|
* the server fetches/composes the offer cards inside this same request (no second `/cab/monetize`
|
|
@@ -6488,36 +6894,36 @@ var WidgetSettingsInputSchema = z56.object({
|
|
|
6488
6894
|
* `privacyPolicyUrl` comes from the widget settings server-side (more authoritative than a relay).
|
|
6489
6895
|
*/
|
|
6490
6896
|
monetize: MonetizeInputSchema.omit({ privacyPolicyUrl: true, shop: true }).optional(),
|
|
6491
|
-
shop:
|
|
6897
|
+
shop: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
6492
6898
|
/** Stable per-buyer id; when present, enables sticky server-side A/B variant selection. */
|
|
6493
|
-
visitorId:
|
|
6899
|
+
visitorId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
|
|
6494
6900
|
});
|
|
6495
|
-
var AnalyticsEventInputSchema =
|
|
6496
|
-
name:
|
|
6497
|
-
properties:
|
|
6498
|
-
sentAt:
|
|
6901
|
+
var AnalyticsEventInputSchema = z66.object({
|
|
6902
|
+
name: z66.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
|
|
6903
|
+
properties: z66.record(z66.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), z66.unknown()).optional(),
|
|
6904
|
+
sentAt: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
|
|
6499
6905
|
});
|
|
6500
|
-
var AnalyticsSegmentsInputSchema =
|
|
6501
|
-
device:
|
|
6502
|
-
source:
|
|
6503
|
-
visitor:
|
|
6906
|
+
var AnalyticsSegmentsInputSchema = z66.object({
|
|
6907
|
+
device: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
|
|
6908
|
+
source: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
|
|
6909
|
+
visitor: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0)
|
|
6504
6910
|
});
|
|
6505
|
-
var AnalyticsInputSchema =
|
|
6911
|
+
var AnalyticsInputSchema = z66.object({
|
|
6506
6912
|
/** Rebuy cart token (the `r_cart_token` cart attribute), when available — primary aggregation key. */
|
|
6507
|
-
cartToken:
|
|
6913
|
+
cartToken: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6508
6914
|
/** Shopify checkout token, when available — drives cart/checkout aggregation downstream. */
|
|
6509
|
-
checkoutToken:
|
|
6510
|
-
events:
|
|
6915
|
+
checkoutToken: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6916
|
+
events: z66.array(AnalyticsEventInputSchema).max(REQUEST_BOUNDS.EVENTS_MAX),
|
|
6511
6917
|
/**
|
|
6512
6918
|
* Request-scoped like the tokens: one visitor's segments apply to every event in the batch. The container
|
|
6513
6919
|
* degrades too (`null` is a realistic wire artifact of `attributes ? {…} : null`), so the degrade rule is
|
|
6514
6920
|
* total: nothing about `segments` can cost the envelope.
|
|
6515
6921
|
*/
|
|
6516
6922
|
segments: AnalyticsSegmentsInputSchema.optional().catch(void 0),
|
|
6517
|
-
shop:
|
|
6518
|
-
visitorId:
|
|
6923
|
+
shop: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
6924
|
+
visitorId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
6519
6925
|
/** The widget id (smartBlockId) the events belong to. */
|
|
6520
|
-
widgetId:
|
|
6926
|
+
widgetId: z66.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
|
|
6521
6927
|
});
|
|
6522
6928
|
export {
|
|
6523
6929
|
AnalyticsEventInputSchema,
|
|
@@ -6533,18 +6939,25 @@ export {
|
|
|
6533
6939
|
MonetizeInputSchema,
|
|
6534
6940
|
MonetizeTransactionItemSchema,
|
|
6535
6941
|
NotFoundError,
|
|
6942
|
+
PostPurchaseQuantityUnavailable,
|
|
6536
6943
|
REBUY_ENGINE_HOST,
|
|
6537
6944
|
REQUEST_BOUNDS,
|
|
6538
6945
|
UpstreamError,
|
|
6539
6946
|
UserConfigInputSchema,
|
|
6540
6947
|
WidgetSettingsInputSchema,
|
|
6541
6948
|
buildEngineParams,
|
|
6949
|
+
classifyPostPurchaseOffer,
|
|
6542
6950
|
convertWidgetSettings,
|
|
6951
|
+
createPostPurchaseOrderAttributes,
|
|
6543
6952
|
fetchDataSourceResults,
|
|
6544
6953
|
fetchMonetizeOffers,
|
|
6545
6954
|
fetchUserConfig,
|
|
6546
6955
|
postAnalyticsEvents,
|
|
6956
|
+
preparePostPurchaseGroupDeclineDisplay,
|
|
6957
|
+
preparePostPurchaseOfferPresentation,
|
|
6547
6958
|
preparePostPurchaseSubscription,
|
|
6959
|
+
readPostPurchaseGroupSelection,
|
|
6960
|
+
readPostPurchaseQuantity,
|
|
6548
6961
|
translateAnalyticsEvent,
|
|
6549
6962
|
validateGifts
|
|
6550
6963
|
};
|