@rebuy/rebuy 3.33.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/README.md +1 -1
- package/dist/cab/index.cjs +12 -1
- package/dist/cab/index.d.ts +1 -0
- package/dist/cab/index.mjs +12 -1
- package/dist/cab/utf8ByteLength.d.ts +6 -0
- 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.cjs
CHANGED
|
@@ -33,18 +33,25 @@ __export(server_exports, {
|
|
|
33
33
|
MonetizeInputSchema: () => MonetizeInputSchema,
|
|
34
34
|
MonetizeTransactionItemSchema: () => MonetizeTransactionItemSchema,
|
|
35
35
|
NotFoundError: () => NotFoundError,
|
|
36
|
+
PostPurchaseQuantityUnavailable: () => PostPurchaseQuantityUnavailable,
|
|
36
37
|
REBUY_ENGINE_HOST: () => REBUY_ENGINE_HOST,
|
|
37
38
|
REQUEST_BOUNDS: () => REQUEST_BOUNDS,
|
|
38
39
|
UpstreamError: () => UpstreamError,
|
|
39
40
|
UserConfigInputSchema: () => UserConfigInputSchema,
|
|
40
41
|
WidgetSettingsInputSchema: () => WidgetSettingsInputSchema,
|
|
41
42
|
buildEngineParams: () => buildEngineParams,
|
|
43
|
+
classifyPostPurchaseOffer: () => classifyPostPurchaseOffer,
|
|
42
44
|
convertWidgetSettings: () => convertWidgetSettings,
|
|
45
|
+
createPostPurchaseOrderAttributes: () => createPostPurchaseOrderAttributes,
|
|
43
46
|
fetchDataSourceResults: () => fetchDataSourceResults,
|
|
44
47
|
fetchMonetizeOffers: () => fetchMonetizeOffers,
|
|
45
48
|
fetchUserConfig: () => fetchUserConfig,
|
|
46
49
|
postAnalyticsEvents: () => postAnalyticsEvents,
|
|
50
|
+
preparePostPurchaseGroupDeclineDisplay: () => preparePostPurchaseGroupDeclineDisplay,
|
|
51
|
+
preparePostPurchaseOfferPresentation: () => preparePostPurchaseOfferPresentation,
|
|
47
52
|
preparePostPurchaseSubscription: () => preparePostPurchaseSubscription,
|
|
53
|
+
readPostPurchaseGroupSelection: () => readPostPurchaseGroupSelection,
|
|
54
|
+
readPostPurchaseQuantity: () => readPostPurchaseQuantity,
|
|
48
55
|
translateAnalyticsEvent: () => translateAnalyticsEvent,
|
|
49
56
|
validateGifts: () => validateGifts
|
|
50
57
|
});
|
|
@@ -679,7 +686,7 @@ var import_uuid13 = require("uuid");
|
|
|
679
686
|
var import_zod27 = require("zod");
|
|
680
687
|
|
|
681
688
|
// src/schema/widgets/checkout-and-beyond/common.ts
|
|
682
|
-
var freezeEnum = (
|
|
689
|
+
var freezeEnum = (values2) => Object.freeze(Object.fromEntries(values2.map((v) => [v, v])));
|
|
683
690
|
var bannerColors = ["info", "success", "warning", "critical"];
|
|
684
691
|
var BannerColor = freezeEnum(bannerColors);
|
|
685
692
|
var borderRadii = ["none", "small", "base", "large", "fullyRounded"];
|
|
@@ -2145,15 +2152,15 @@ var CABImageSectionFields = import_zod27.z.object({
|
|
|
2145
2152
|
width: import_zod27.z.number().default(100)
|
|
2146
2153
|
});
|
|
2147
2154
|
var iconNameSet = new Set(iconNames);
|
|
2148
|
-
var isIconName = (
|
|
2149
|
-
var CABImageSection = CABImageSectionFields.superRefine(({ category, source }, ctx) => {
|
|
2150
|
-
if (category === "icon" &&
|
|
2155
|
+
var isIconName = (source2) => iconNameSet.has(source2);
|
|
2156
|
+
var CABImageSection = CABImageSectionFields.superRefine(({ category, source: source2 }, ctx) => {
|
|
2157
|
+
if (category === "icon" && source2 !== "" && !isIconName(source2))
|
|
2151
2158
|
ctx.addIssue({
|
|
2152
2159
|
code: "custom",
|
|
2153
2160
|
message: "icon-mode source must be an icon name",
|
|
2154
2161
|
path: ["source"]
|
|
2155
2162
|
});
|
|
2156
|
-
if (category !== "icon" && isIconName(
|
|
2163
|
+
if (category !== "icon" && isIconName(source2))
|
|
2157
2164
|
ctx.addIssue({
|
|
2158
2165
|
code: "custom",
|
|
2159
2166
|
message: "source must be a URL or dynamic token unless category is `icon`",
|
|
@@ -2265,10 +2272,10 @@ var HEADER_PARAGRAPH_STYLES = {
|
|
|
2265
2272
|
superTitle: { color: "base", fontSize: "extraLarge", marks: [{ type: "bold" }] },
|
|
2266
2273
|
title: { color: "base", fontSize: "medium", marks: [{ type: "bold" }] }
|
|
2267
2274
|
};
|
|
2268
|
-
var convertContentBlockTextToV2 = (
|
|
2269
|
-
const description =
|
|
2270
|
-
const superTitle =
|
|
2271
|
-
const title =
|
|
2275
|
+
var convertContentBlockTextToV2 = (language3, text2 = literalText, textAlign = "center") => {
|
|
2276
|
+
const description = language3?.description;
|
|
2277
|
+
const superTitle = language3?.superTitle;
|
|
2278
|
+
const title = language3?.title;
|
|
2272
2279
|
return TiptapDocument.parse({
|
|
2273
2280
|
attrs: { blockSpacing: "tight" },
|
|
2274
2281
|
content: [
|
|
@@ -2380,7 +2387,7 @@ var LOCATION_TO_EDITOR_MODE = {
|
|
|
2380
2387
|
};
|
|
2381
2388
|
|
|
2382
2389
|
// src/transforms/contentBlockV1/convertContentBlockToV2.ts
|
|
2383
|
-
var hasText = (
|
|
2390
|
+
var hasText = (language3) => !!language3 && !!(language3.description || language3.superTitle || language3.title);
|
|
2384
2391
|
var convertContentBlockToV2 = ({ id, settings }) => {
|
|
2385
2392
|
const imageBlocks = settings.imageBlocks ?? [];
|
|
2386
2393
|
return CABRootSection.parse({
|
|
@@ -2653,15 +2660,15 @@ var stripHtmlComments = (html = "") => html.replace(HTML_COMMENT_RE2, "");
|
|
|
2653
2660
|
var maybeFlushParagraph = (state) => {
|
|
2654
2661
|
if (state.currentRuns.length > 0) flushParagraph(state);
|
|
2655
2662
|
};
|
|
2656
|
-
var htmlToTiptap = (html,
|
|
2663
|
+
var htmlToTiptap = (html, options2 = {}) => {
|
|
2657
2664
|
const state = {
|
|
2658
2665
|
currentRuns: [],
|
|
2659
|
-
defaultTextStyleMark: buildDefaultTextStyleMark(
|
|
2666
|
+
defaultTextStyleMark: buildDefaultTextStyleMark(options2.defaultTextStyle),
|
|
2660
2667
|
listStack: [],
|
|
2661
2668
|
paragraphs: [],
|
|
2662
2669
|
stack: []
|
|
2663
2670
|
};
|
|
2664
|
-
const blockSpacing =
|
|
2671
|
+
const blockSpacing = options2.blockSpacing ?? "base";
|
|
2665
2672
|
if (typeof html !== "string" || !html) return makeDoc([makeParagraph([])], blockSpacing);
|
|
2666
2673
|
const htmlWithoutComments = stripHtmlComments(html);
|
|
2667
2674
|
let lastIndex = 0;
|
|
@@ -2906,9 +2913,9 @@ var isMonetizeV1 = isWidgetV1(WidgetType.ui_extension_ad);
|
|
|
2906
2913
|
var HTML_TAG_RE2 = /<[a-zA-Z]/;
|
|
2907
2914
|
var containsHtml = (text2) => HTML_TAG_RE2.test(text2);
|
|
2908
2915
|
var isObject = (x) => x !== null && typeof x === "object" && !Array.isArray(x);
|
|
2909
|
-
var normalizeTextValue = (value,
|
|
2916
|
+
var normalizeTextValue = (value, options2 = {}) => {
|
|
2910
2917
|
const tokenized = normalizeTokens(value);
|
|
2911
|
-
return containsHtml(tokenized) ||
|
|
2918
|
+
return containsHtml(tokenized) || options2.defaultTextStyle ? htmlToTiptap(tokenized, options2) : decodeTextEntities(tokenized);
|
|
2912
2919
|
};
|
|
2913
2920
|
var normalizeLangValue = (value) => typeof value === "string" ? normalizeTextValue(value) : value;
|
|
2914
2921
|
var normalizeTextContent = (node) => {
|
|
@@ -2941,15 +2948,15 @@ var resolveExperiment = (experiments, placeholderId, visitorId) => {
|
|
|
2941
2948
|
if (!experiment || experiment.data.length === 0) return void 0;
|
|
2942
2949
|
const roll = rollPercent(`${visitorId}:${experiment.id}`);
|
|
2943
2950
|
let cumulative = 0;
|
|
2944
|
-
const
|
|
2951
|
+
const variant2 = experiment.data.find((candidate) => {
|
|
2945
2952
|
cumulative += candidate.traffic;
|
|
2946
2953
|
return roll < cumulative;
|
|
2947
2954
|
}) ?? experiment.data[0];
|
|
2948
2955
|
return {
|
|
2949
|
-
elementId:
|
|
2956
|
+
elementId: variant2.elementId,
|
|
2950
2957
|
experimentId: experiment.id,
|
|
2951
2958
|
experimentType: experiment.type,
|
|
2952
|
-
selectedId:
|
|
2959
|
+
selectedId: variant2.id
|
|
2953
2960
|
};
|
|
2954
2961
|
};
|
|
2955
2962
|
|
|
@@ -3397,23 +3404,23 @@ var QUANTITY_INPUT_TYPE = {
|
|
|
3397
3404
|
"buttons-manual-input": "number",
|
|
3398
3405
|
"dropdown-select": "select"
|
|
3399
3406
|
};
|
|
3400
|
-
var buildQuantityErrors = (
|
|
3407
|
+
var buildQuantityErrors = (quantity2) => {
|
|
3401
3408
|
const en = {
|
|
3402
|
-
...
|
|
3403
|
-
...
|
|
3404
|
-
...
|
|
3409
|
+
...quantity2.maxError && { max: normalizeTokens(quantity2.maxError, QUANTITY_ERROR_TOKENS) },
|
|
3410
|
+
...quantity2.minError && { min: normalizeTokens(quantity2.minError, QUANTITY_ERROR_TOKENS) },
|
|
3411
|
+
...quantity2.negativeError && { neg: normalizeTokens(quantity2.negativeError, QUANTITY_ERROR_TOKENS) }
|
|
3405
3412
|
};
|
|
3406
3413
|
return Object.keys(en).length ? { errorMessages: { en } } : {};
|
|
3407
3414
|
};
|
|
3408
3415
|
var buildQuantity = (settings) => {
|
|
3409
|
-
const
|
|
3410
|
-
if (!
|
|
3411
|
-
const inputType =
|
|
3412
|
-
const max = Math.min(Math.max(
|
|
3413
|
-
const min = Math.min(Math.max(
|
|
3416
|
+
const quantity2 = settings.quantityInputs;
|
|
3417
|
+
if (!quantity2?.enabled) return [];
|
|
3418
|
+
const inputType = quantity2.type ? QUANTITY_INPUT_TYPE[quantity2.type] : void 0;
|
|
3419
|
+
const max = Math.min(Math.max(quantity2.maxValue ?? 10, 1), 100);
|
|
3420
|
+
const min = Math.min(Math.max(quantity2.minValue ?? 1, 1), max);
|
|
3414
3421
|
return [
|
|
3415
3422
|
{
|
|
3416
|
-
...buildQuantityErrors(
|
|
3423
|
+
...buildQuantityErrors(quantity2),
|
|
3417
3424
|
...inputType && { inputType },
|
|
3418
3425
|
max,
|
|
3419
3426
|
min,
|
|
@@ -3423,7 +3430,7 @@ var buildQuantity = (settings) => {
|
|
|
3423
3430
|
};
|
|
3424
3431
|
var buildSubscriptionButton = (settings) => {
|
|
3425
3432
|
if (settings.productType !== "both" && settings.productType !== "subscription") return [];
|
|
3426
|
-
const
|
|
3433
|
+
const language3 = settings.language;
|
|
3427
3434
|
const slot = (buttonField, override) => ({
|
|
3428
3435
|
buttonField,
|
|
3429
3436
|
content: localizedContent(SWITCH_LABELS[buttonField], override, SWITCH_LABEL_TOKENS2),
|
|
@@ -3437,9 +3444,9 @@ var buildSubscriptionButton = (settings) => {
|
|
|
3437
3444
|
...settings.productType === "subscription" && { disableDowngrade: true },
|
|
3438
3445
|
sections: [
|
|
3439
3446
|
slot("subscriptionOption", void 0),
|
|
3440
|
-
slot("switchToOneTimePurchase",
|
|
3441
|
-
slot("switchToSubscriptionNoDiscount",
|
|
3442
|
-
slot("switchToSubscriptionWithDiscount",
|
|
3447
|
+
slot("switchToOneTimePurchase", language3?.cartSwitchToOnetime),
|
|
3448
|
+
slot("switchToSubscriptionNoDiscount", language3?.upgradeToSubscription),
|
|
3449
|
+
slot("switchToSubscriptionWithDiscount", language3?.upgradeToSubscription)
|
|
3443
3450
|
],
|
|
3444
3451
|
sectionType: "button"
|
|
3445
3452
|
}
|
|
@@ -3494,11 +3501,11 @@ var buildOfferCard = (settings, horizontal) => {
|
|
|
3494
3501
|
const description = buildDescription(settings);
|
|
3495
3502
|
const reviews = buildReviews(settings);
|
|
3496
3503
|
const variants = buildVariants(settings);
|
|
3497
|
-
const
|
|
3504
|
+
const quantity2 = buildQuantity(settings);
|
|
3498
3505
|
const subscription2 = buildSubscriptionButton(settings);
|
|
3499
3506
|
const reveal = buildRevealButton(settings);
|
|
3500
3507
|
const addButton = buildAddButton(settings);
|
|
3501
|
-
const controls = [...description, ...
|
|
3508
|
+
const controls = [...description, ...quantity2, ...variants, ...subscription2];
|
|
3502
3509
|
const info = detailBlock([title, ...variantTitle, ...reviews, price], horizontal, variantTitle.length > 0);
|
|
3503
3510
|
const card = (sections) => [
|
|
3504
3511
|
{
|
|
@@ -3552,9 +3559,9 @@ var buildCarouselNav = () => ({
|
|
|
3552
3559
|
sectionType: "layout"
|
|
3553
3560
|
});
|
|
3554
3561
|
var HEADER_FIELDS = ["superTitle", "title", "description"];
|
|
3555
|
-
var sanitizedHeader = (
|
|
3562
|
+
var sanitizedHeader = (language3) => Object.fromEntries(
|
|
3556
3563
|
HEADER_FIELDS.flatMap((field) => {
|
|
3557
|
-
const value =
|
|
3564
|
+
const value = language3?.[field];
|
|
3558
3565
|
const sanitized = value ? stripContentBlockHtml(normalizeTokens(value)) : "";
|
|
3559
3566
|
return sanitized ? [[field, sanitized]] : [];
|
|
3560
3567
|
})
|
|
@@ -3651,7 +3658,7 @@ var coerceIntegrations = (integrations) => Object.fromEntries(
|
|
|
3651
3658
|
return [key, value];
|
|
3652
3659
|
})
|
|
3653
3660
|
);
|
|
3654
|
-
var buildBanner = (
|
|
3661
|
+
var buildBanner = (language3) => language3?.successBannerEnabled ? [
|
|
3655
3662
|
{
|
|
3656
3663
|
/**
|
|
3657
3664
|
* The banner-level tag is the extraction/routing key on BOTH renderers (React CAB's
|
|
@@ -3664,7 +3671,7 @@ var buildBanner = (language2) => language2?.successBannerEnabled ? [
|
|
|
3664
3671
|
dismissible: true,
|
|
3665
3672
|
sections: [
|
|
3666
3673
|
{
|
|
3667
|
-
content: bannerMessageContent(
|
|
3674
|
+
content: bannerMessageContent(language3.successBannerMessageRte),
|
|
3668
3675
|
sectionType: "text"
|
|
3669
3676
|
},
|
|
3670
3677
|
{
|
|
@@ -3981,14 +3988,14 @@ var convertCalloutBlock = (raw, report) => {
|
|
|
3981
3988
|
};
|
|
3982
3989
|
const shell = Shell.safeParse(raw);
|
|
3983
3990
|
if (!shell.success) return omit("Unreadable post-purchase callout");
|
|
3984
|
-
const
|
|
3991
|
+
const values2 = fields.map((field) => ({
|
|
3985
3992
|
field,
|
|
3986
3993
|
result: CalloutBannerBlock.shape.settings.shape[field].safeParse(shell.data.settings[field])
|
|
3987
3994
|
}));
|
|
3988
|
-
const styled2 =
|
|
3995
|
+
const styled2 = values2.every(({ result }) => result.success && typeof result.data === "string");
|
|
3989
3996
|
const styles2 = shell.data.styles;
|
|
3990
3997
|
const horizontal = styled2 ? { center: "center", leading: "start", trailing: "end" }[styles2.textAlignment] : "center";
|
|
3991
|
-
const sections =
|
|
3998
|
+
const sections = values2.flatMap(({ field, result }) => {
|
|
3992
3999
|
if (!result.success) return omit(`Unreadable post-purchase callout field: ${field}`);
|
|
3993
4000
|
const text2 = result.data;
|
|
3994
4001
|
if (text2 === "") return [];
|
|
@@ -4010,12 +4017,12 @@ var convertCalloutBlock = (raw, report) => {
|
|
|
4010
4017
|
var import_zod32 = require("zod");
|
|
4011
4018
|
|
|
4012
4019
|
// src/transforms/postPurchase/sizeImageSource.ts
|
|
4013
|
-
var sizeImageSource = (
|
|
4014
|
-
const extension =
|
|
4020
|
+
var sizeImageSource = (source2, size) => {
|
|
4021
|
+
const extension = source2.split(".").pop();
|
|
4015
4022
|
for (const previous of ["small", "medium", "large", "original", "master"]) {
|
|
4016
|
-
|
|
4023
|
+
source2 = source2.replace(`_${previous}.${extension}`, `.${extension}`);
|
|
4017
4024
|
}
|
|
4018
|
-
return
|
|
4025
|
+
return source2.replace(`.${extension}`, `${size === void 0 ? "" : `_${size}`}.${extension}`);
|
|
4019
4026
|
};
|
|
4020
4027
|
|
|
4021
4028
|
// src/transforms/postPurchase/convertImageFrame.ts
|
|
@@ -4025,9 +4032,9 @@ var convertImageFrame = (raw) => {
|
|
|
4025
4032
|
const parsed = ImageBlock.shape.settings.options[0].safeParse(raw);
|
|
4026
4033
|
if (!parsed.success) return null;
|
|
4027
4034
|
const settings = parsed.data;
|
|
4028
|
-
const
|
|
4029
|
-
const withAlt = CABImageSection.safeParse({ altText: settings.alt, source });
|
|
4030
|
-
const image = withAlt.success ? withAlt.data : CABImageSection.parse({ source });
|
|
4035
|
+
const source2 = sizeImageSource(Source.parse(settings.image || void 0));
|
|
4036
|
+
const withAlt = CABImageSection.safeParse({ altText: settings.alt, source: source2 });
|
|
4037
|
+
const image = withAlt.success ? withAlt.data : CABImageSection.parse({ source: source2 });
|
|
4031
4038
|
const size = settings.imageSize > 0 ? settings.imageSize : DEFAULT_IMAGE_SIZE;
|
|
4032
4039
|
return CABLayoutSection.parse({
|
|
4033
4040
|
alignment: { horizontal: "center" },
|
|
@@ -4264,19 +4271,19 @@ var convertTextBlock = (raw, report) => {
|
|
|
4264
4271
|
report?.({ detail: "Unreadable post-purchase text block", kind: "section" });
|
|
4265
4272
|
return [];
|
|
4266
4273
|
}
|
|
4267
|
-
const
|
|
4274
|
+
const values2 = fields3.map((field) => ({
|
|
4268
4275
|
field,
|
|
4269
4276
|
result: settingsSchema.shape[field].safeParse(shell.data.settings[field])
|
|
4270
4277
|
}));
|
|
4271
4278
|
const horizontal = { center: "center", leading: "start", trailing: "end" }[shell.data.settings.horizontalAlignment];
|
|
4272
|
-
const styled2 =
|
|
4279
|
+
const styled2 = values2.every(
|
|
4273
4280
|
({ result }) => result.success && (result.data === null || typeof result.data === "string")
|
|
4274
4281
|
);
|
|
4275
4282
|
const omit = (field) => {
|
|
4276
4283
|
report?.({ detail: `Unreadable post-purchase text field: ${field}`, kind: "section" });
|
|
4277
4284
|
return [];
|
|
4278
4285
|
};
|
|
4279
|
-
const sections =
|
|
4286
|
+
const sections = values2.flatMap(({ field, result }) => {
|
|
4280
4287
|
if (!result.success) return omit(field);
|
|
4281
4288
|
const text2 = result.data;
|
|
4282
4289
|
if (text2 === null || text2 === "") return [];
|
|
@@ -4510,10 +4517,10 @@ var giftOf = (tier) => {
|
|
|
4510
4517
|
if (tier.type !== "product") return void 0;
|
|
4511
4518
|
const product = tier.products?.[0] ?? tier.allProducts?.[0];
|
|
4512
4519
|
if (!product) return void 0;
|
|
4513
|
-
const
|
|
4514
|
-
if (
|
|
4520
|
+
const productId2 = product.productId ?? product.id;
|
|
4521
|
+
if (productId2 === void 0) return void 0;
|
|
4515
4522
|
return {
|
|
4516
|
-
productId,
|
|
4523
|
+
productId: productId2,
|
|
4517
4524
|
title: product.title,
|
|
4518
4525
|
variantIds: positiveIds(product.variantIds)
|
|
4519
4526
|
};
|
|
@@ -4792,14 +4799,14 @@ function serialize(obj) {
|
|
|
4792
4799
|
var encodeAttributes = (pairs = []) => JSON.stringify(Object.fromEntries(pairs.map(({ key, value }) => [key, value ?? ""])));
|
|
4793
4800
|
var buildEngineParams = (input, key) => {
|
|
4794
4801
|
const { cart, customerId, filterInputs, integrations, limit, productType, shop, visitorId } = input;
|
|
4795
|
-
const items = cart.items.map(({ productId, properties, quantity, subscriptionId, variantId }) => ({
|
|
4796
|
-
product_id:
|
|
4802
|
+
const items = cart.items.map(({ productId: productId2, properties, quantity: quantity2, subscriptionId, variantId }) => ({
|
|
4803
|
+
product_id: productId2,
|
|
4797
4804
|
properties: encodeAttributes(properties),
|
|
4798
|
-
quantity,
|
|
4805
|
+
quantity: quantity2,
|
|
4799
4806
|
...subscriptionId && { subscription_id: subscriptionId },
|
|
4800
4807
|
variant_id: variantId
|
|
4801
4808
|
}));
|
|
4802
|
-
const itemCount = cart.items.reduce((total, { quantity }) => total +
|
|
4809
|
+
const itemCount = cart.items.reduce((total, { quantity: quantity2 }) => total + quantity2, 0);
|
|
4803
4810
|
const subtotal = shopSubtotalCents(cart);
|
|
4804
4811
|
return {
|
|
4805
4812
|
cart: {
|
|
@@ -4886,13 +4893,13 @@ var OFFER_LIMIT = 4;
|
|
|
4886
4893
|
var SUPPORTED_COUNTRIES = /* @__PURE__ */ new Set(["US", "CA", "GB"]);
|
|
4887
4894
|
var MAX_TRANSACTION_ITEMS = 50;
|
|
4888
4895
|
var TEST_CUSTOMER_EMAIL = "test@rebuyengine.com";
|
|
4889
|
-
var transactionItems = (input) => (input.transactionItems?.map(({ id, priceCents, quantity, title, type }) => ({
|
|
4896
|
+
var transactionItems = (input) => (input.transactionItems?.map(({ id, priceCents, quantity: quantity2, title, type }) => ({
|
|
4890
4897
|
id,
|
|
4891
4898
|
price_cents: priceCents,
|
|
4892
|
-
quantity,
|
|
4899
|
+
quantity: quantity2,
|
|
4893
4900
|
title,
|
|
4894
4901
|
type
|
|
4895
|
-
})) ?? input.cart.items.map(({ productId, quantity }) => ({ id:
|
|
4902
|
+
})) ?? input.cart.items.map(({ productId: productId2, quantity: quantity2 }) => ({ id: productId2, quantity: quantity2 }))).slice(0, MAX_TRANSACTION_ITEMS);
|
|
4896
4903
|
var AdsEngineOffer = import_zod37.z.object({
|
|
4897
4904
|
/** Pill-style value prop ("Get $45 Cashback"). Carried through the parse; the card does not render it yet (REB-24429 — pill design pending). */
|
|
4898
4905
|
callout: import_zod37.z.string().catch(""),
|
|
@@ -5010,9 +5017,9 @@ var label = (text2) => ({
|
|
|
5010
5017
|
});
|
|
5011
5018
|
var text = (content) => ({ content: { en: content }, sectionType: SectionType.text });
|
|
5012
5019
|
var AS_DOC = { defaultTextStyle: {} };
|
|
5013
|
-
var safeTextValue = (raw,
|
|
5014
|
-
const converted = normalizeTextValue(raw,
|
|
5015
|
-
return checkForHTML(converted) ? converted : normalizeTextValue(htmlToPlainText(raw),
|
|
5020
|
+
var safeTextValue = (raw, options2) => {
|
|
5021
|
+
const converted = normalizeTextValue(raw, options2);
|
|
5022
|
+
return checkForHTML(converted) ? converted : normalizeTextValue(htmlToPlainText(raw), options2);
|
|
5016
5023
|
};
|
|
5017
5024
|
var headlineText = (raw) => {
|
|
5018
5025
|
const doc = safeTextValue(raw, AS_DOC);
|
|
@@ -5496,11 +5503,11 @@ var validateGifts = async (input, ctx) => {
|
|
|
5496
5503
|
const [remove, adjust] = await Promise.all([validateGwpGifts(input, ctx), validateSelectableGifts(input, ctx)]);
|
|
5497
5504
|
const removed = new Set(remove);
|
|
5498
5505
|
const targets = /* @__PURE__ */ new Map();
|
|
5499
|
-
for (const { lineId, quantity } of adjust) {
|
|
5506
|
+
for (const { lineId, quantity: quantity2 } of adjust) {
|
|
5500
5507
|
if (removed.has(lineId)) continue;
|
|
5501
|
-
targets.set(lineId, Math.min(
|
|
5508
|
+
targets.set(lineId, Math.min(quantity2, targets.get(lineId) ?? quantity2));
|
|
5502
5509
|
}
|
|
5503
|
-
return { adjust: [...targets].map(([lineId,
|
|
5510
|
+
return { adjust: [...targets].map(([lineId, quantity2]) => ({ lineId, quantity: quantity2 })), remove: [...removed] };
|
|
5504
5511
|
};
|
|
5505
5512
|
|
|
5506
5513
|
// src/server/normalizePostPurchaseProduct.ts
|
|
@@ -5832,14 +5839,14 @@ var SourceAdjustment = import_zod47.z.object({
|
|
|
5832
5839
|
type: import_zod47.z.enum(["percentage", "fixed_amount", "amount", "price", "none", "fixed"])
|
|
5833
5840
|
});
|
|
5834
5841
|
var readPostPurchasePlanAdjustment = (raw) => {
|
|
5835
|
-
const
|
|
5836
|
-
if (
|
|
5837
|
-
if (
|
|
5842
|
+
const source2 = SourceAdjustment.parse(raw);
|
|
5843
|
+
if (source2.type === "none" || source2.type === "fixed") {
|
|
5844
|
+
if (source2.amount !== 0) throw new Error("Unsupported plan adjustment");
|
|
5838
5845
|
return void 0;
|
|
5839
5846
|
}
|
|
5840
5847
|
const adjustment = PostPurchasePlanAdjustment.parse({
|
|
5841
|
-
amount:
|
|
5842
|
-
type:
|
|
5848
|
+
amount: source2.amount,
|
|
5849
|
+
type: source2.type === "amount" ? "fixed_amount" : source2.type
|
|
5843
5850
|
});
|
|
5844
5851
|
return adjustment.amount === 0 && adjustment.type !== "price" ? void 0 : adjustment;
|
|
5845
5852
|
};
|
|
@@ -5916,12 +5923,12 @@ var projectPostPurchasePlanCatalog = (normalized, report) => {
|
|
|
5916
5923
|
const { data } = normalized;
|
|
5917
5924
|
if (data.length !== 1 || data[0].variants.length !== 1) throw new Error("Ambiguous product");
|
|
5918
5925
|
const product = data[0];
|
|
5919
|
-
const
|
|
5920
|
-
if (
|
|
5926
|
+
const variant2 = product.variants[0];
|
|
5927
|
+
if (variant2.productId !== product.id) throw new Error("Foreign variant");
|
|
5921
5928
|
const groups = product.sellingPlanGroups;
|
|
5922
5929
|
const required = groups.map((group) => group.requiresSellingPlan);
|
|
5923
5930
|
if (required.some((flag) => flag !== required[0])) throw new Error("Conflicting requirement");
|
|
5924
|
-
const plans = typeof groups[0]?.id === "number" ? readPostPurchaseLegacyPlans(groups[0],
|
|
5931
|
+
const plans = typeof groups[0]?.id === "number" ? readPostPurchaseLegacyPlans(groups[0], variant2.id) : readPostPurchaseModernPlans(groups, variant2.sellingPlanAllocations);
|
|
5925
5932
|
const unique = /* @__PURE__ */ new Map();
|
|
5926
5933
|
for (const plan of plans) {
|
|
5927
5934
|
const previous = unique.get(plan.id);
|
|
@@ -5932,7 +5939,7 @@ var projectPostPurchasePlanCatalog = (normalized, report) => {
|
|
|
5932
5939
|
plans: [...unique.values()],
|
|
5933
5940
|
productId: product.id,
|
|
5934
5941
|
requiresSellingPlan: required[0] ?? false,
|
|
5935
|
-
variantId:
|
|
5942
|
+
variantId: variant2.id
|
|
5936
5943
|
});
|
|
5937
5944
|
} catch {
|
|
5938
5945
|
report?.({ detail: "Unreadable post-purchase plan catalog", kind: "product" });
|
|
@@ -6072,20 +6079,20 @@ var PostPurchaseSubscriptionSettings = subscription.extend({
|
|
|
6072
6079
|
});
|
|
6073
6080
|
|
|
6074
6081
|
// src/server/postPurchaseVariantAvailable.ts
|
|
6075
|
-
var postPurchaseVariantAvailable = (
|
|
6082
|
+
var postPurchaseVariantAvailable = (variant2) => !(variant2.inventoryManagement && variant2.inventoryPolicy === "deny" && variant2.inventoryQuantity <= 0);
|
|
6076
6083
|
|
|
6077
6084
|
// src/server/postPurchaseSubscriptionEligibility.ts
|
|
6078
|
-
var subscriptionUnavailable = (normalized, plan, allowCollection,
|
|
6085
|
+
var subscriptionUnavailable = (normalized, plan, allowCollection, quantity2) => {
|
|
6079
6086
|
const { data, effective, original } = normalized;
|
|
6080
6087
|
const unavailable = "An eligible subscription plan with supported shipping and discount is required";
|
|
6081
6088
|
if (data.length !== 1 || data[0].variants.length !== 1) return unavailable;
|
|
6082
6089
|
if (effective.productType === "one-time" || [original, effective].some(
|
|
6083
|
-
(config) => !allowCollection && config.productLimit !== 1 || config.upgradeToSubscription.allow || !
|
|
6090
|
+
(config) => !allowCollection && config.productLimit !== 1 || config.upgradeToSubscription.allow || !quantity2 && config.quantityInputs.enabled && (config.quantityInputs.minValue !== config.quantityInputs.maxValue || config.quantityInputs.defaultQuantity !== config.quantityInputs.minValue)
|
|
6084
6091
|
))
|
|
6085
6092
|
return unavailable;
|
|
6086
6093
|
const product = data[0];
|
|
6087
|
-
const
|
|
6088
|
-
if (product.productGroupVariants.length || !postPurchaseVariantAvailable(
|
|
6094
|
+
const variant2 = product.variants[0];
|
|
6095
|
+
if (product.productGroupVariants.length || !postPurchaseVariantAvailable(variant2) || variant2.productId !== product.id)
|
|
6089
6096
|
return unavailable;
|
|
6090
6097
|
const terms = [original, effective].map(
|
|
6091
6098
|
(config) => PostPurchaseSubscriptionSettings.safeParse(config.subscription)
|
|
@@ -6100,8 +6107,8 @@ var import_zod55 = require("zod");
|
|
|
6100
6107
|
var postPurchasePrimaryImage = (product) => {
|
|
6101
6108
|
const variantImageId = product.variants[0].imageId;
|
|
6102
6109
|
const selectedImage = variantImageId ? product.images?.find((image) => image.id === variantImageId) : void 0;
|
|
6103
|
-
const
|
|
6104
|
-
return { description: product.title, source: sizeImageSource(
|
|
6110
|
+
const source2 = PostPurchasePrimaryImageSource.parse((selectedImage ?? product.image)?.src || void 0);
|
|
6111
|
+
return { description: product.title, source: sizeImageSource(source2, "800x800") };
|
|
6105
6112
|
};
|
|
6106
6113
|
|
|
6107
6114
|
// src/server/postPurchaseProductGallery.ts
|
|
@@ -6130,26 +6137,26 @@ var projectPostPurchaseProductDisplay = (effective, metadata, product) => PostPu
|
|
|
6130
6137
|
// src/server/projectPostPurchaseProduct.ts
|
|
6131
6138
|
var projectPostPurchaseProduct = ({ data, effective, metadata, original }, selectedQuantity) => {
|
|
6132
6139
|
const product = data[0];
|
|
6133
|
-
const
|
|
6140
|
+
const variant2 = product.variants[0];
|
|
6134
6141
|
return {
|
|
6135
6142
|
display: projectPostPurchaseProductDisplay(effective, metadata, product),
|
|
6136
6143
|
labels: effective.language.global,
|
|
6137
|
-
product: { ...product, variant },
|
|
6144
|
+
product: { ...product, variant: variant2 },
|
|
6138
6145
|
selection: {
|
|
6139
6146
|
productId: product.id,
|
|
6140
6147
|
quantity: selectedQuantity?.quantity ?? product.metadata?.productQuantity ?? (original.quantityInputs.enabled ? original.quantityInputs.defaultQuantity : 1),
|
|
6141
|
-
variantId:
|
|
6148
|
+
variantId: variant2.id
|
|
6142
6149
|
}
|
|
6143
6150
|
};
|
|
6144
6151
|
};
|
|
6145
6152
|
|
|
6146
6153
|
// src/server/prepareNormalizedSubscription.ts
|
|
6147
|
-
var prepareNormalizedSubscription = (normalized, report, plan,
|
|
6154
|
+
var prepareNormalizedSubscription = (normalized, report, plan, quantity2, allowCollection = false) => {
|
|
6148
6155
|
if (!plan) return { reason: "Subscription plan is unavailable", status: "unsupported" };
|
|
6149
|
-
const reason = subscriptionUnavailable(normalized, plan, allowCollection,
|
|
6156
|
+
const reason = subscriptionUnavailable(normalized, plan, allowCollection, quantity2);
|
|
6150
6157
|
if (reason) return { reason, status: "unsupported" };
|
|
6151
6158
|
const { effective } = normalized;
|
|
6152
|
-
const projected = projectPostPurchaseProduct(normalized,
|
|
6159
|
+
const projected = projectPostPurchaseProduct(normalized, quantity2);
|
|
6153
6160
|
const { discount, shipping } = PostPurchaseSubscriptionSettings.parse(effective.subscription);
|
|
6154
6161
|
const shippingPrice = shipping.type === "free" ? 0 : shipping.amount;
|
|
6155
6162
|
return PreparedPostPurchaseSubscription.parse({
|
|
@@ -6186,6 +6193,412 @@ var preparePostPurchaseSubscription = (settings, response, report) => {
|
|
|
6186
6193
|
);
|
|
6187
6194
|
};
|
|
6188
6195
|
|
|
6196
|
+
// src/schema/postPurchaseOfferEligibility.ts
|
|
6197
|
+
var import_zod57 = require("zod");
|
|
6198
|
+
|
|
6199
|
+
// src/schema/postPurchaseProductCollectionView.ts
|
|
6200
|
+
var import_zod56 = require("zod");
|
|
6201
|
+
var PostPurchaseExcludedProductIds = import_zod56.z.array(PostPurchaseProductId).default([]);
|
|
6202
|
+
|
|
6203
|
+
// src/schema/postPurchaseOfferEligibility.ts
|
|
6204
|
+
var selection = PreparedPostPurchaseProduct.shape.selection;
|
|
6205
|
+
var PostPurchaseOfferSkipReason = import_zod57.z.enum(["empty", "no-eligible-subscription"]);
|
|
6206
|
+
var PostPurchaseOfferEligibilityContext = import_zod57.z.object({
|
|
6207
|
+
excludedProductIds: PostPurchaseExcludedProductIds,
|
|
6208
|
+
originalLineItems: import_zod57.z.array(selection.pick({ productId: true, sellingPlanId: true, variantId: true }))
|
|
6209
|
+
});
|
|
6210
|
+
var PostPurchaseOfferEligibility = import_zod57.z.discriminatedUnion("status", [
|
|
6211
|
+
import_zod57.z.object({
|
|
6212
|
+
members: import_zod57.z.array(
|
|
6213
|
+
import_zod57.z.object({ productId: selection.shape.productId, productIndex: import_zod57.z.number().int().nonnegative() })
|
|
6214
|
+
),
|
|
6215
|
+
status: import_zod57.z.literal("retain")
|
|
6216
|
+
}),
|
|
6217
|
+
import_zod57.z.object({ reason: PostPurchaseOfferSkipReason, status: import_zod57.z.literal("skip") }),
|
|
6218
|
+
import_zod57.z.object({ reason: import_zod57.z.literal("eligible-upgrade").optional(), status: import_zod57.z.literal("unavailable") })
|
|
6219
|
+
]);
|
|
6220
|
+
|
|
6221
|
+
// src/server/normalizePostPurchaseCollection.ts
|
|
6222
|
+
var import_zod58 = require("zod");
|
|
6223
|
+
var normalizePostPurchaseCollection = (settings, response, excludedProductIds) => {
|
|
6224
|
+
const normalized = normalizePostPurchaseProduct(settings, response);
|
|
6225
|
+
const limit = import_zod58.z.number().int().positive();
|
|
6226
|
+
limit.parse(normalized.original.productLimit);
|
|
6227
|
+
const prefix = normalized.data.slice(0, limit.parse(normalized.effective.productLimit));
|
|
6228
|
+
if (new Set(prefix.map(({ id }) => id)).size !== prefix.length)
|
|
6229
|
+
throw new Error("Ambiguous post-purchase collection");
|
|
6230
|
+
const excluded = new Set(PostPurchaseExcludedProductIds.parse(excludedProductIds));
|
|
6231
|
+
const members = prefix.map((product, productIndex) => ({ product, productIndex })).filter(({ product }) => !excluded.has(product.id));
|
|
6232
|
+
return { members, normalized };
|
|
6233
|
+
};
|
|
6234
|
+
|
|
6235
|
+
// src/schema/postPurchaseVariantCatalog.ts
|
|
6236
|
+
var import_zod59 = require("zod");
|
|
6237
|
+
var PostPurchaseVariantSelector = import_zod59.z.object({ variantId: PostPurchaseVariantId }).strict();
|
|
6238
|
+
var PostPurchaseVariantOption = OfferProduct.shape.options.element.extend({
|
|
6239
|
+
id: import_zod59.z.number().int().positive(),
|
|
6240
|
+
position: import_zod59.z.number().int().min(1).max(3)
|
|
6241
|
+
});
|
|
6242
|
+
var PostPurchaseVariantValues = OfferProduct.shape.variants.element.pick({
|
|
6243
|
+
option1: true,
|
|
6244
|
+
option2: true,
|
|
6245
|
+
option3: true
|
|
6246
|
+
});
|
|
6247
|
+
var PostPurchaseVariantCatalog = import_zod59.z.object({
|
|
6248
|
+
displayMode: PostPurchaseSettings.shape.productOptions.shape.variantSelectorDisplayMode,
|
|
6249
|
+
options: import_zod59.z.array(PostPurchaseVariantOption),
|
|
6250
|
+
productId: PostPurchaseProductId,
|
|
6251
|
+
showSelectors: PostPurchaseSettings.shape.productOptions.shape.showVariantSelectors,
|
|
6252
|
+
variants: import_zod59.z.array(
|
|
6253
|
+
PostPurchaseVariantValues.partial().extend({
|
|
6254
|
+
available: import_zod59.z.boolean(),
|
|
6255
|
+
id: PostPurchaseVariantId,
|
|
6256
|
+
imageId: import_zod59.z.number().int().nonnegative().nullish(),
|
|
6257
|
+
title: OfferProduct.shape.variants.element.shape.title
|
|
6258
|
+
})
|
|
6259
|
+
)
|
|
6260
|
+
});
|
|
6261
|
+
|
|
6262
|
+
// src/server/postPurchaseVariantCatalog.ts
|
|
6263
|
+
var projectPostPurchaseVariantCatalog = (product, settings) => {
|
|
6264
|
+
const options2 = PostPurchaseVariantCatalog.shape.options.parse(product.options === void 0 ? [] : product.options).sort((a, b) => a.position - b.position);
|
|
6265
|
+
const variants = product.variants.map((variant2) => ({
|
|
6266
|
+
...variant2,
|
|
6267
|
+
...PostPurchaseVariantValues.partial().parse(variant2)
|
|
6268
|
+
}));
|
|
6269
|
+
const tuples = variants.map(({ option1, option2, option3 }) => [option1, option2, option3]);
|
|
6270
|
+
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(
|
|
6271
|
+
({ position, values: values2 }, index) => position !== index + 1 || new Set(values2).size !== values2.length
|
|
6272
|
+
) || product.variants.length > 1 && new Set(tuples.map((tuple) => JSON.stringify(tuple))).size !== tuples.length)
|
|
6273
|
+
throw new Error("Ambiguous post-purchase variant catalog");
|
|
6274
|
+
for (const tuple of tuples) {
|
|
6275
|
+
if (options2.some(({ position, values: values2 }) => !values2.some((value) => value === tuple[position - 1])) || tuple.some((value, index) => value != null && !options2[index]))
|
|
6276
|
+
throw new Error("Variant option tuple does not match the catalog");
|
|
6277
|
+
}
|
|
6278
|
+
return PostPurchaseVariantCatalog.parse({
|
|
6279
|
+
displayMode: settings.productOptions.variantSelectorDisplayMode,
|
|
6280
|
+
options: options2,
|
|
6281
|
+
productId: product.id,
|
|
6282
|
+
showSelectors: settings.productOptions.showVariantSelectors,
|
|
6283
|
+
variants: variants.map(({ id, imageId, option1, option2, option3, title, ...inventory }) => ({
|
|
6284
|
+
available: postPurchaseVariantAvailable(inventory),
|
|
6285
|
+
id,
|
|
6286
|
+
imageId,
|
|
6287
|
+
option1,
|
|
6288
|
+
option2,
|
|
6289
|
+
option3,
|
|
6290
|
+
title
|
|
6291
|
+
}))
|
|
6292
|
+
});
|
|
6293
|
+
};
|
|
6294
|
+
|
|
6295
|
+
// src/schema/postPurchaseGroupCatalog.ts
|
|
6296
|
+
var import_zod60 = require("zod");
|
|
6297
|
+
var productId = PreparedPostPurchaseProduct.shape.selection.shape.productId;
|
|
6298
|
+
var source = PostPurchaseProductSource.shape.data.element;
|
|
6299
|
+
var PostPurchaseGroupDescription = source.pick({ description: true, id: true, image: true, images: true, title: true }).extend({
|
|
6300
|
+
description: source.shape.description.default(null),
|
|
6301
|
+
image: source.shape.image.default(null),
|
|
6302
|
+
options: PostPurchaseVariantCatalog.shape.options.default([])
|
|
6303
|
+
});
|
|
6304
|
+
var PostPurchaseGroupCatalog = import_zod60.z.object({
|
|
6305
|
+
memberProductId: productId,
|
|
6306
|
+
options: import_zod60.z.array(import_zod60.z.object({ productId, title: import_zod60.z.string(), variantCatalog: PostPurchaseVariantCatalog }))
|
|
6307
|
+
});
|
|
6308
|
+
var PostPurchaseGroupSelection = import_zod60.z.object({
|
|
6309
|
+
memberProductId: productId,
|
|
6310
|
+
productId
|
|
6311
|
+
});
|
|
6312
|
+
|
|
6313
|
+
// src/server/readPostPurchaseGroup.ts
|
|
6314
|
+
var readPostPurchaseGroup = (product, settings, excludedProductIds) => {
|
|
6315
|
+
const descriptions = PostPurchaseGroupDescription.nullable().array().parse(product.productGroupVariants).filter((value) => value !== null);
|
|
6316
|
+
const ids = new Set(descriptions.map((value) => value.id));
|
|
6317
|
+
if (ids.size !== descriptions.length || new Set(product.variants.map(({ id }) => id)).size !== product.variants.length || product.variants.some(({ productId: productId2 }) => !ids.has(productId2)))
|
|
6318
|
+
throw new Error("Ambiguous post-purchase group ownership");
|
|
6319
|
+
const excluded = new Set(PostPurchaseExcludedProductIds.parse(excludedProductIds));
|
|
6320
|
+
const entries = descriptions.map((description) => {
|
|
6321
|
+
const value = {
|
|
6322
|
+
...product,
|
|
6323
|
+
...description,
|
|
6324
|
+
images: description.images,
|
|
6325
|
+
productGroupVariants: [],
|
|
6326
|
+
variants: product.variants.filter(({ productId: productId2 }) => productId2 === description.id)
|
|
6327
|
+
};
|
|
6328
|
+
return { product: value, variantCatalog: projectPostPurchaseVariantCatalog(value, settings) };
|
|
6329
|
+
}).filter(({ product: value }) => !excluded.has(value.id));
|
|
6330
|
+
return {
|
|
6331
|
+
catalog: PostPurchaseGroupCatalog.parse({
|
|
6332
|
+
memberProductId: product.id,
|
|
6333
|
+
options: entries.map(({ product: value, variantCatalog }) => ({
|
|
6334
|
+
productId: value.id,
|
|
6335
|
+
title: value.title,
|
|
6336
|
+
variantCatalog
|
|
6337
|
+
}))
|
|
6338
|
+
}),
|
|
6339
|
+
entries
|
|
6340
|
+
};
|
|
6341
|
+
};
|
|
6342
|
+
|
|
6343
|
+
// src/server/postPurchaseMemberEligibility.ts
|
|
6344
|
+
var PostPurchaseInventoryUnavailable = class extends Error {
|
|
6345
|
+
};
|
|
6346
|
+
var postPurchaseMemberEligibility = (normalized, product, excluded) => {
|
|
6347
|
+
if (product.productGroupVariants.length) {
|
|
6348
|
+
const group = readPostPurchaseGroup(product, normalized.effective, excluded);
|
|
6349
|
+
return group.entries.map(({ product: option }) => postPurchaseMemberEligibility(normalized, option)).some(Boolean);
|
|
6350
|
+
}
|
|
6351
|
+
if (!product.variants.length) throw new Error("Unsupported catalog");
|
|
6352
|
+
const variants = projectPostPurchaseVariantCatalog(product, normalized.effective).variants;
|
|
6353
|
+
const catalogs = product.variants.map((variant2) => {
|
|
6354
|
+
const catalog = projectPostPurchasePlanCatalog({
|
|
6355
|
+
...normalized,
|
|
6356
|
+
data: [{ ...product, variants: [variant2] }]
|
|
6357
|
+
});
|
|
6358
|
+
if (!catalog) throw new Error("Unreadable subscription catalog");
|
|
6359
|
+
if (normalized.effective.productType === "one-time" && catalog.requiresSellingPlan)
|
|
6360
|
+
throw new Error("Unsupported purchase mode");
|
|
6361
|
+
return catalog;
|
|
6362
|
+
});
|
|
6363
|
+
if (!variants.some((variant2) => variant2.available))
|
|
6364
|
+
throw new PostPurchaseInventoryUnavailable("Unavailable inventory");
|
|
6365
|
+
return catalogs.some(
|
|
6366
|
+
(catalog, index) => variants[index].available && (normalized.effective.productType !== "subscription" && !catalog.requiresSellingPlan || normalized.effective.productType !== "one-time" && catalog.plans.length > 0)
|
|
6367
|
+
);
|
|
6368
|
+
};
|
|
6369
|
+
|
|
6370
|
+
// src/server/classifyPostPurchaseOffer.ts
|
|
6371
|
+
var classifyPostPurchaseOffer = (settings, response, context) => {
|
|
6372
|
+
try {
|
|
6373
|
+
const trusted = PostPurchaseOfferEligibilityContext.parse(context);
|
|
6374
|
+
const { members, normalized } = normalizePostPurchaseCollection(settings, response);
|
|
6375
|
+
const configurations = [normalized.original, normalized.effective];
|
|
6376
|
+
const upgrades = configurations.some((config) => config.upgradeToSubscription.allow);
|
|
6377
|
+
const oneTime = new Set(
|
|
6378
|
+
trusted.originalLineItems.filter((line) => line.sellingPlanId === void 0).map((line) => line.variantId)
|
|
6379
|
+
);
|
|
6380
|
+
if (upgrades && members.some(
|
|
6381
|
+
({ product }) => product.sellingPlanGroups?.length && product.variants.some((variant2) => oneTime.has(variant2.id))
|
|
6382
|
+
))
|
|
6383
|
+
return { reason: "eligible-upgrade", status: "unavailable" };
|
|
6384
|
+
if (normalized.effective.productType !== "one-time") {
|
|
6385
|
+
configurations.forEach((config) => PostPurchaseSubscriptionSettings.parse(config.subscription));
|
|
6386
|
+
}
|
|
6387
|
+
const classified = members.map((member) => {
|
|
6388
|
+
try {
|
|
6389
|
+
return {
|
|
6390
|
+
...member,
|
|
6391
|
+
eligible: postPurchaseMemberEligibility(normalized, member.product, trusted.excludedProductIds)
|
|
6392
|
+
};
|
|
6393
|
+
} catch (error) {
|
|
6394
|
+
if (error instanceof PostPurchaseInventoryUnavailable && !member.product.productGroupVariants.length && trusted.excludedProductIds.includes(member.product.id))
|
|
6395
|
+
return { ...member, eligible: false };
|
|
6396
|
+
throw error;
|
|
6397
|
+
}
|
|
6398
|
+
});
|
|
6399
|
+
if (!members.length) return { reason: "empty", status: "skip" };
|
|
6400
|
+
if (upgrades) return { reason: "no-eligible-subscription", status: "skip" };
|
|
6401
|
+
const candidates = classified.filter(
|
|
6402
|
+
({ product }) => product.productGroupVariants.length ? readPostPurchaseGroup(product, normalized.effective, trusted.excludedProductIds).entries.length > 0 : !trusted.excludedProductIds.includes(product.id)
|
|
6403
|
+
);
|
|
6404
|
+
if (!candidates.length) return { reason: "empty", status: "skip" };
|
|
6405
|
+
const retained = candidates.filter(({ eligible }) => eligible);
|
|
6406
|
+
return retained.length ? {
|
|
6407
|
+
members: retained.map(({ product, productIndex }) => ({
|
|
6408
|
+
productId: product.id,
|
|
6409
|
+
productIndex
|
|
6410
|
+
})),
|
|
6411
|
+
status: "retain"
|
|
6412
|
+
} : { reason: "no-eligible-subscription", status: "skip" };
|
|
6413
|
+
} catch {
|
|
6414
|
+
return { status: "unavailable" };
|
|
6415
|
+
}
|
|
6416
|
+
};
|
|
6417
|
+
|
|
6418
|
+
// src/schema/postPurchaseVariantDefault.ts
|
|
6419
|
+
var import_zod61 = require("zod");
|
|
6420
|
+
var values = PostPurchaseVariantValues.partial().extend({
|
|
6421
|
+
option1: PostPurchaseVariantValues.shape.option1.nullish()
|
|
6422
|
+
});
|
|
6423
|
+
var variant = values.extend({
|
|
6424
|
+
id: PostPurchaseVariantId,
|
|
6425
|
+
inventoryManagement: import_zod61.z.string().nullable(),
|
|
6426
|
+
inventoryPolicy: import_zod61.z.string(),
|
|
6427
|
+
inventoryQuantity: import_zod61.z.number()
|
|
6428
|
+
});
|
|
6429
|
+
var options = import_zod61.z.array(PostPurchaseVariantOption.pick({ name: true, values: true }));
|
|
6430
|
+
var PostPurchaseVariantDefaultProduct = import_zod61.z.object({
|
|
6431
|
+
id: PostPurchaseProductId,
|
|
6432
|
+
options,
|
|
6433
|
+
selectedVariant: variant.optional(),
|
|
6434
|
+
variants: import_zod61.z.array(variant)
|
|
6435
|
+
});
|
|
6436
|
+
var PostPurchaseVariantDefaultSettings = PostPurchaseSettings.shape.productOptions.pick({
|
|
6437
|
+
hideOutOfStockVariants: true,
|
|
6438
|
+
matchVariant: true
|
|
6439
|
+
});
|
|
6440
|
+
var PostPurchaseOrderAttributes = import_zod61.z.record(import_zod61.z.string(), import_zod61.z.array(import_zod61.z.string())).default({});
|
|
6441
|
+
var PostPurchaseOriginalVariants = import_zod61.z.array(
|
|
6442
|
+
import_zod61.z.object({ productId: PostPurchaseProductId, variantId: PostPurchaseVariantId })
|
|
6443
|
+
);
|
|
6444
|
+
var PostPurchaseAttributeProducts = import_zod61.z.array(
|
|
6445
|
+
import_zod61.z.object({ id: PostPurchaseProductId, options, variants: import_zod61.z.array(values.extend({ id: PostPurchaseVariantId })) })
|
|
6446
|
+
);
|
|
6447
|
+
|
|
6448
|
+
// src/server/createPostPurchaseOrderAttributes.ts
|
|
6449
|
+
var createPostPurchaseOrderAttributes = (original, enriched) => {
|
|
6450
|
+
const products = PostPurchaseAttributeProducts.parse(enriched);
|
|
6451
|
+
const attributes = {};
|
|
6452
|
+
for (const item of PostPurchaseOriginalVariants.parse(original)) {
|
|
6453
|
+
const product = products.find(({ id }) => id === item.productId);
|
|
6454
|
+
const variant2 = product?.variants.find(({ id }) => id === item.variantId);
|
|
6455
|
+
if (!variant2 || !product) continue;
|
|
6456
|
+
["option1", "option2", "option3"].forEach((key, index) => {
|
|
6457
|
+
const value = variant2[key];
|
|
6458
|
+
const option = product.options[index];
|
|
6459
|
+
if (!value || !option) return;
|
|
6460
|
+
const values2 = attributes[option.name] ?? [];
|
|
6461
|
+
if (!values2.includes(value)) attributes[option.name] = [...values2, value];
|
|
6462
|
+
});
|
|
6463
|
+
}
|
|
6464
|
+
return attributes;
|
|
6465
|
+
};
|
|
6466
|
+
|
|
6467
|
+
// src/server/readPostPurchaseGroupSelection.ts
|
|
6468
|
+
var readPostPurchaseGroupSelection = (settings, response, requested, excludedProductIds) => {
|
|
6469
|
+
const selection2 = PostPurchaseGroupSelection.parse(requested);
|
|
6470
|
+
const { members, normalized } = normalizePostPurchaseCollection(settings, response);
|
|
6471
|
+
const member = members.find(({ product }) => product.id === selection2.memberProductId);
|
|
6472
|
+
if (!member || !member.product.productGroupVariants.length) return null;
|
|
6473
|
+
const group = readPostPurchaseGroup(member.product, normalized.effective, excludedProductIds);
|
|
6474
|
+
const entry = group.entries.find(({ product }) => product.id === selection2.productId);
|
|
6475
|
+
if (!entry) return null;
|
|
6476
|
+
return {
|
|
6477
|
+
groupCatalog: group.catalog,
|
|
6478
|
+
memberProductId: member.product.id,
|
|
6479
|
+
productIndex: member.productIndex,
|
|
6480
|
+
reportingProduct: { id: member.product.id, title: member.product.title },
|
|
6481
|
+
response: { data: [entry.product], metadata: normalized.metadata },
|
|
6482
|
+
variantCatalog: entry.variantCatalog
|
|
6483
|
+
};
|
|
6484
|
+
};
|
|
6485
|
+
|
|
6486
|
+
// src/server/preparePostPurchaseGroupDeclineDisplay.ts
|
|
6487
|
+
var preparePostPurchaseGroupDeclineDisplay = (settings, response, requested, excludedProductIds) => {
|
|
6488
|
+
const group = readPostPurchaseGroupSelection(settings, response, requested, excludedProductIds);
|
|
6489
|
+
const variant2 = group?.variantCatalog.variants.find(({ id }) => id === requested.variantId);
|
|
6490
|
+
return group && variant2 ? {
|
|
6491
|
+
display: {
|
|
6492
|
+
productTitle: group.reportingProduct.title,
|
|
6493
|
+
variantId: variant2.id,
|
|
6494
|
+
variantTitle: variant2.title
|
|
6495
|
+
},
|
|
6496
|
+
productIndex: group.productIndex
|
|
6497
|
+
} : null;
|
|
6498
|
+
};
|
|
6499
|
+
|
|
6500
|
+
// src/server/preparePostPurchaseOfferPresentation.ts
|
|
6501
|
+
var import_compat7 = require("es-toolkit/compat");
|
|
6502
|
+
var import_zod64 = require("zod");
|
|
6503
|
+
|
|
6504
|
+
// src/schema/postPurchaseOfferPresentation.ts
|
|
6505
|
+
var import_zod62 = require("zod");
|
|
6506
|
+
var language2 = PostPurchaseSettings.shape.language.shape.global.unwrap().unwrap();
|
|
6507
|
+
var PostPurchaseOfferPresentation = import_zod62.z.strictObject({
|
|
6508
|
+
labels: language2.pick({ declineAll: true, declineThisOffer: true }),
|
|
6509
|
+
layout: PostPurchaseSettings.shape.offersLayout,
|
|
6510
|
+
sections: CABRootSection.nullable(),
|
|
6511
|
+
showDeclineAll: PostPurchaseSettings.shape.productOptions.shape.showDeclineAll
|
|
6512
|
+
});
|
|
6513
|
+
|
|
6514
|
+
// src/server/postPurchaseOfferCopy.ts
|
|
6515
|
+
var import_zod63 = require("zod");
|
|
6516
|
+
var Copy = import_zod63.z.object({
|
|
6517
|
+
superTitle: CalloutBannerBlock.shape.settings.shape.superTitle.unwrap().optional().catch(void 0),
|
|
6518
|
+
title: CalloutBannerBlock.shape.settings.shape.title.unwrap().optional().catch(void 0)
|
|
6519
|
+
});
|
|
6520
|
+
var Callout = import_zod63.z.object({ settings: import_zod63.z.record(import_zod63.z.string(), import_zod63.z.unknown()), type: import_zod63.z.literal("callout_banner") });
|
|
6521
|
+
var postPurchaseOfferCopy = (blocks, metadata) => {
|
|
6522
|
+
const copy = Copy.safeParse(metadata.widget.language);
|
|
6523
|
+
if (!blocks || !copy.success) return blocks;
|
|
6524
|
+
const first = blocks.findIndex((block) => Callout.pick({ type: true }).safeParse(block).success);
|
|
6525
|
+
return blocks.map((block, index) => {
|
|
6526
|
+
if (index !== first) return block;
|
|
6527
|
+
const callout = Callout.passthrough().safeParse(block);
|
|
6528
|
+
if (!callout.success) return block;
|
|
6529
|
+
return {
|
|
6530
|
+
...callout.data,
|
|
6531
|
+
settings: {
|
|
6532
|
+
...callout.data.settings,
|
|
6533
|
+
...copy.data.title && { title: copy.data.title },
|
|
6534
|
+
...copy.data.superTitle && { superTitle: copy.data.superTitle }
|
|
6535
|
+
}
|
|
6536
|
+
};
|
|
6537
|
+
});
|
|
6538
|
+
};
|
|
6539
|
+
|
|
6540
|
+
// src/server/preparePostPurchaseOfferPresentation.ts
|
|
6541
|
+
var FrameSettings = PostPurchaseSettings.pick({ language: true, offersLayout: true, productOptions: true }).extend({
|
|
6542
|
+
blocks: import_zod64.z.array(import_zod64.z.unknown()).optional()
|
|
6543
|
+
});
|
|
6544
|
+
var preparePostPurchaseOfferPresentation = (widgetId, settings, response, report) => {
|
|
6545
|
+
const { metadata } = PostPurchaseProductSource.pick({ metadata: true }).parse(deepCamelCase(response));
|
|
6546
|
+
const original = FrameSettings.parse(deepCamelCase(settings));
|
|
6547
|
+
const effective = FrameSettings.parse((0, import_compat7.merge)({}, original, metadata.widget));
|
|
6548
|
+
let sections = null;
|
|
6549
|
+
try {
|
|
6550
|
+
sections = convertMessagePreview(
|
|
6551
|
+
widgetId,
|
|
6552
|
+
{ blocks: postPurchaseOfferCopy(effective.blocks, metadata), type: "shopify_post_purchase_extension" },
|
|
6553
|
+
report
|
|
6554
|
+
);
|
|
6555
|
+
} catch (error) {
|
|
6556
|
+
if (!(error instanceof NotFoundError)) throw error;
|
|
6557
|
+
}
|
|
6558
|
+
return PostPurchaseOfferPresentation.parse({
|
|
6559
|
+
labels: effective.language.global,
|
|
6560
|
+
layout: effective.offersLayout,
|
|
6561
|
+
sections,
|
|
6562
|
+
showDeclineAll: effective.productOptions.showDeclineAll
|
|
6563
|
+
});
|
|
6564
|
+
};
|
|
6565
|
+
|
|
6566
|
+
// src/schema/postPurchaseQuantity.ts
|
|
6567
|
+
var import_zod65 = require("zod");
|
|
6568
|
+
var quantity = PreparedPostPurchaseProduct.shape.selection.shape.quantity;
|
|
6569
|
+
var PostPurchaseQuantityPolicy = PostPurchaseSettings.shape.quantityInputs.omit({ defaultQuantity: true }).extend({
|
|
6570
|
+
initialQuantity: quantity,
|
|
6571
|
+
maxValue: quantity,
|
|
6572
|
+
minValue: import_zod65.z.literal(0).transform(() => 1).or(quantity)
|
|
6573
|
+
}).refine(({ maxValue, minValue }) => minValue <= maxValue, "Quantity bounds are reversed");
|
|
6574
|
+
|
|
6575
|
+
// src/server/readPostPurchaseQuantity.ts
|
|
6576
|
+
var PostPurchaseQuantityUnavailable = class extends Error {
|
|
6577
|
+
};
|
|
6578
|
+
var readPostPurchaseQuantity = ({
|
|
6579
|
+
data,
|
|
6580
|
+
effective,
|
|
6581
|
+
original
|
|
6582
|
+
}, selection2) => {
|
|
6583
|
+
const positive = PreparedPostPurchaseProduct.shape.selection.shape.quantity;
|
|
6584
|
+
for (const config of [original, effective]) {
|
|
6585
|
+
if (!config.quantityInputs.enabled) continue;
|
|
6586
|
+
const initialQuantity2 = positive.parse(config.quantityInputs.defaultQuantity);
|
|
6587
|
+
const policy2 = PostPurchaseQuantityPolicy.parse({ ...config.quantityInputs, initialQuantity: initialQuantity2 });
|
|
6588
|
+
if (initialQuantity2 < policy2.minValue || initialQuantity2 > policy2.maxValue)
|
|
6589
|
+
throw new Error("Configured quantity default is outside its bounds");
|
|
6590
|
+
}
|
|
6591
|
+
const initialQuantity = data[0]?.metadata?.productQuantity ?? (original.quantityInputs.enabled ? original.quantityInputs.defaultQuantity : 1);
|
|
6592
|
+
const policy = PostPurchaseQuantityPolicy.parse(
|
|
6593
|
+
effective.quantityInputs.enabled ? { ...effective.quantityInputs, initialQuantity } : { enabled: false, initialQuantity, maxValue: initialQuantity, minValue: initialQuantity }
|
|
6594
|
+
);
|
|
6595
|
+
const requested = "quantity" in selection2 ? selection2.quantity : selection2.expectedQuantity === initialQuantity ? void 0 : selection2.expectedQuantity;
|
|
6596
|
+
const quantity2 = positive.parse(requested ?? initialQuantity);
|
|
6597
|
+
if (requested !== void 0 && (policy.enabled ? quantity2 < policy.minValue || quantity2 > policy.maxValue : quantity2 !== initialQuantity))
|
|
6598
|
+
throw new PostPurchaseQuantityUnavailable("Requested quantity is unavailable");
|
|
6599
|
+
return { policy, quantity: quantity2 };
|
|
6600
|
+
};
|
|
6601
|
+
|
|
6189
6602
|
// src/server/analytics.ts
|
|
6190
6603
|
var import_es_toolkit7 = require("es-toolkit");
|
|
6191
6604
|
|
|
@@ -6230,8 +6643,8 @@ var TAXONOMY = {
|
|
|
6230
6643
|
"added-to-cart": {
|
|
6231
6644
|
/** React credits the add to the A/B-selected variant (`defined_noun_id: selectedId`). */
|
|
6232
6645
|
buildDefinedNounId: ({ selectedId }) => selectedId != null ? String(selectedId) : void 0,
|
|
6233
|
-
buildMeta: ({ productId, variantId }) => ({
|
|
6234
|
-
...
|
|
6646
|
+
buildMeta: ({ productId: productId2, variantId }) => ({
|
|
6647
|
+
...productId2 != null && { [`product_id:${productId2}`]: true },
|
|
6235
6648
|
...variantId != null && { [`variant_id:${variantId}`]: true }
|
|
6236
6649
|
}),
|
|
6237
6650
|
buildTags: experimentTags,
|
|
@@ -6322,7 +6735,7 @@ var postAnalyticsEvents = async (input, ctx) => {
|
|
|
6322
6735
|
};
|
|
6323
6736
|
|
|
6324
6737
|
// src/server/requestSchemas.ts
|
|
6325
|
-
var
|
|
6738
|
+
var import_zod66 = require("zod");
|
|
6326
6739
|
var REQUEST_BOUNDS = {
|
|
6327
6740
|
/** Cart-level attributes per cart. */
|
|
6328
6741
|
CART_ATTRIBUTES_MAX: 100,
|
|
@@ -6353,42 +6766,42 @@ var REQUEST_BOUNDS = {
|
|
|
6353
6766
|
/** Rich ads transaction lines — the engine's ads contract. */
|
|
6354
6767
|
TRANSACTION_ITEMS_MAX: 50
|
|
6355
6768
|
};
|
|
6356
|
-
var KeyValue =
|
|
6357
|
-
key:
|
|
6358
|
-
value:
|
|
6769
|
+
var KeyValue = import_zod66.z.object({
|
|
6770
|
+
key: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
|
|
6771
|
+
value: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_VALUE_MAX).optional()
|
|
6359
6772
|
});
|
|
6360
|
-
var CartLineInputSchema =
|
|
6361
|
-
productId:
|
|
6362
|
-
properties:
|
|
6363
|
-
quantity:
|
|
6364
|
-
subscriptionId:
|
|
6365
|
-
variantId:
|
|
6773
|
+
var CartLineInputSchema = import_zod66.z.object({
|
|
6774
|
+
productId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
6775
|
+
properties: import_zod66.z.array(KeyValue).max(REQUEST_BOUNDS.LINE_PROPERTIES_MAX).optional(),
|
|
6776
|
+
quantity: import_zod66.z.number(),
|
|
6777
|
+
subscriptionId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6778
|
+
variantId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX)
|
|
6366
6779
|
});
|
|
6367
|
-
var CartInputSchema =
|
|
6368
|
-
attributes:
|
|
6780
|
+
var CartInputSchema = import_zod66.z.object({
|
|
6781
|
+
attributes: import_zod66.z.array(KeyValue).max(REQUEST_BOUNDS.CART_ATTRIBUTES_MAX).optional(),
|
|
6369
6782
|
/**
|
|
6370
6783
|
* Presentment-per-shop-currency FX rate (buyer price ÷ shop price, e.g. `1.35` for a USD shop
|
|
6371
6784
|
* selling in CAD). Money rule thresholds are authored in SHOP currency, so the engine subtotal is
|
|
6372
6785
|
* divided by this before evaluation. Omit (or send 1) when the cart is already in the shop's currency.
|
|
6373
6786
|
*/
|
|
6374
|
-
currencyRate:
|
|
6787
|
+
currencyRate: import_zod66.z.number().optional(),
|
|
6375
6788
|
/** Applied discount codes; the engine evaluates `discount_code` rules against them (sent as `[{code}]`). */
|
|
6376
|
-
discountCodes:
|
|
6789
|
+
discountCodes: import_zod66.z.array(import_zod66.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX)).max(REQUEST_BOUNDS.DISCOUNT_CODES_MAX).optional(),
|
|
6377
6790
|
/** Presentment cents of cart-level discount allocations, subtracted from `subtotal` for the engine. */
|
|
6378
|
-
discountTotal:
|
|
6379
|
-
items:
|
|
6791
|
+
discountTotal: import_zod66.z.number().optional(),
|
|
6792
|
+
items: import_zod66.z.array(CartLineInputSchema).max(REQUEST_BOUNDS.CART_ITEMS_MAX),
|
|
6380
6793
|
/** Presentment subtotal in cents. */
|
|
6381
|
-
subtotal:
|
|
6794
|
+
subtotal: import_zod66.z.number()
|
|
6382
6795
|
});
|
|
6383
|
-
var UserConfigInputSchema =
|
|
6384
|
-
var DataSourceInputSchema =
|
|
6796
|
+
var UserConfigInputSchema = import_zod66.z.object({ shop: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX) });
|
|
6797
|
+
var DataSourceInputSchema = import_zod66.z.object({
|
|
6385
6798
|
cart: CartInputSchema,
|
|
6386
6799
|
/**
|
|
6387
6800
|
* Numeric Shopify company-location id when the buyer is a B2B session (`buyerIdentity.purchasingCompany`).
|
|
6388
6801
|
* Present ⇒ the orchestrator filters results by the location's catalog via admin-api (REB-23713); the
|
|
6389
6802
|
* client's country-context market check is bypassed for B2B (it false-negatives B2B-catalog products).
|
|
6390
6803
|
*/
|
|
6391
|
-
companyLocationId:
|
|
6804
|
+
companyLocationId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6392
6805
|
/**
|
|
6393
6806
|
* Buyer's market country (ISO 3166-1 alpha-2) — forwarded to the engine as the `country_code` PARAM
|
|
6394
6807
|
* when the shop's markets toggle is on (REB-21688; the sink was the `X-Country-Code` header under
|
|
@@ -6397,16 +6810,16 @@ var DataSourceInputSchema = import_zod56.z.object({
|
|
|
6397
6810
|
* uppercase (the wire value is forwarded verbatim as the param) so a case-sensitive engine lookup
|
|
6398
6811
|
* can't silently miss a lowercase code — `adsEngine.ts` uppercases for the same reason.
|
|
6399
6812
|
*/
|
|
6400
|
-
country:
|
|
6401
|
-
customerId:
|
|
6402
|
-
dataSourcePath:
|
|
6813
|
+
country: import_zod66.z.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(),
|
|
6814
|
+
customerId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6815
|
+
dataSourcePath: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
|
|
6403
6816
|
/**
|
|
6404
6817
|
* Engine `filter_inputs` override: `'no'` keeps in-cart (input) products in the results/rule
|
|
6405
6818
|
* outputs — gift validation sends it so a gift's own product can appear in its answer. Omitted = the
|
|
6406
6819
|
* engine's default filtering.
|
|
6407
6820
|
*/
|
|
6408
|
-
filterInputs:
|
|
6409
|
-
integrations:
|
|
6821
|
+
filterInputs: import_zod66.z.enum(["no", "yes"]).optional(),
|
|
6822
|
+
integrations: import_zod66.z.record(import_zod66.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), import_zod66.z.boolean()).refine((record) => Object.keys(record).length <= REQUEST_BOUNDS.INTEGRATION_KEYS_MAX, {
|
|
6410
6823
|
message: `Too many integration keys (max ${REQUEST_BOUNDS.INTEGRATION_KEYS_MAX})`
|
|
6411
6824
|
}).optional(),
|
|
6412
6825
|
/**
|
|
@@ -6419,31 +6832,31 @@ var DataSourceInputSchema = import_zod56.z.object({
|
|
|
6419
6832
|
* request header) fails the regex. Callers should send the buyer's resolved locale (e.g. Shopify
|
|
6420
6833
|
* checkout's `localization.language.isoCode`), not the request header verbatim.
|
|
6421
6834
|
*/
|
|
6422
|
-
language:
|
|
6423
|
-
limit:
|
|
6424
|
-
productType:
|
|
6425
|
-
shop:
|
|
6426
|
-
visitorId:
|
|
6427
|
-
});
|
|
6428
|
-
var GiftInputSchema =
|
|
6429
|
-
cost:
|
|
6430
|
-
discounted:
|
|
6835
|
+
language: import_zod66.z.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(),
|
|
6836
|
+
limit: import_zod66.z.number().max(REQUEST_BOUNDS.LIMIT_MAX),
|
|
6837
|
+
productType: import_zod66.z.enum(["both", "one-time", "subscription"]).optional(),
|
|
6838
|
+
shop: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
6839
|
+
visitorId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
|
|
6840
|
+
});
|
|
6841
|
+
var GiftInputSchema = import_zod66.z.object({
|
|
6842
|
+
cost: import_zod66.z.number(),
|
|
6843
|
+
discounted: import_zod66.z.boolean(),
|
|
6431
6844
|
/**
|
|
6432
6845
|
* Which gift attribution the line carries (REB-24363). Defaults to `gwp` because a client that predates
|
|
6433
6846
|
* the field only ever sent GWP lines — without the default an older extension's request would 422.
|
|
6434
6847
|
*/
|
|
6435
|
-
kind:
|
|
6436
|
-
lineId:
|
|
6437
|
-
productId:
|
|
6848
|
+
kind: import_zod66.z.enum(GIFT_KINDS).default("gwp"),
|
|
6849
|
+
lineId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
6850
|
+
productId: import_zod66.z.number(),
|
|
6438
6851
|
/**
|
|
6439
6852
|
* The line's unit count (REB-24363) — the selectable-GWP verdict trims surplus units against milestone
|
|
6440
6853
|
* capacity. The second deliberate default: a client predating the field sent only GWP lines, whose
|
|
6441
6854
|
* verdict is whole-line, so a missing quantity reads as one unit rather than 422ing the older request.
|
|
6442
6855
|
*/
|
|
6443
|
-
quantity:
|
|
6444
|
-
widgetId:
|
|
6856
|
+
quantity: import_zod66.z.number().int().min(1).default(1),
|
|
6857
|
+
widgetId: import_zod66.z.number()
|
|
6445
6858
|
});
|
|
6446
|
-
var GiftValidationInputSchema =
|
|
6859
|
+
var GiftValidationInputSchema = import_zod66.z.object({
|
|
6447
6860
|
cart: CartInputSchema,
|
|
6448
6861
|
/**
|
|
6449
6862
|
* Buyer's market country — threaded into the per-widget data-source evaluations, which forward it to
|
|
@@ -6452,25 +6865,25 @@ var GiftValidationInputSchema = import_zod56.z.object({
|
|
|
6452
6865
|
* turns markets off); regex-bound and uppercase-normalized for the same reasons as
|
|
6453
6866
|
* `DataSourceInputSchema`'s `country`.
|
|
6454
6867
|
*/
|
|
6455
|
-
country:
|
|
6456
|
-
customerId:
|
|
6457
|
-
gifts:
|
|
6868
|
+
country: import_zod66.z.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(),
|
|
6869
|
+
customerId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6870
|
+
gifts: import_zod66.z.array(GiftInputSchema).max(REQUEST_BOUNDS.GIFTS_MAX),
|
|
6458
6871
|
/**
|
|
6459
6872
|
* Buyer's checkout language — threaded into the per-widget data-source evaluations, which normalize
|
|
6460
6873
|
* and forward it as the engine `locale` param under the same markets-toggle gate (REB-21688). MUST be
|
|
6461
6874
|
* a single BCP-47 tag, for the same reason as `DataSourceInputSchema`'s `language` above.
|
|
6462
6875
|
*/
|
|
6463
|
-
language:
|
|
6464
|
-
shop:
|
|
6465
|
-
visitorId:
|
|
6876
|
+
language: import_zod66.z.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(),
|
|
6877
|
+
shop: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
6878
|
+
visitorId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
|
|
6466
6879
|
});
|
|
6467
|
-
var GiftAdjustmentSchema =
|
|
6468
|
-
lineId:
|
|
6469
|
-
quantity:
|
|
6880
|
+
var GiftAdjustmentSchema = import_zod66.z.object({
|
|
6881
|
+
lineId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
6882
|
+
quantity: import_zod66.z.number().int().nonnegative()
|
|
6470
6883
|
});
|
|
6471
|
-
var GiftValidationResponseSchema =
|
|
6472
|
-
adjust:
|
|
6473
|
-
remove:
|
|
6884
|
+
var GiftValidationResponseSchema = import_zod66.z.object({
|
|
6885
|
+
adjust: import_zod66.z.array(GiftAdjustmentSchema).max(REQUEST_BOUNDS.GIFTS_MAX).default([]),
|
|
6886
|
+
remove: import_zod66.z.array(import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX)).max(REQUEST_BOUNDS.GIFTS_MAX).refine(
|
|
6474
6887
|
(remove) => new Set(remove).size === remove.length,
|
|
6475
6888
|
"a line id may appear at most once in `remove`"
|
|
6476
6889
|
)
|
|
@@ -6481,47 +6894,47 @@ var GiftValidationResponseSchema = import_zod56.z.object({
|
|
|
6481
6894
|
({ adjust }) => new Set(adjust.map(({ lineId }) => lineId)).size === adjust.length,
|
|
6482
6895
|
"a line id may appear at most once in `adjust`"
|
|
6483
6896
|
);
|
|
6484
|
-
var MonetizeTransactionItemSchema =
|
|
6485
|
-
id:
|
|
6486
|
-
priceCents:
|
|
6487
|
-
quantity:
|
|
6488
|
-
title:
|
|
6489
|
-
type:
|
|
6490
|
-
});
|
|
6491
|
-
var MonetizeInputSchema =
|
|
6897
|
+
var MonetizeTransactionItemSchema = import_zod66.z.object({
|
|
6898
|
+
id: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
6899
|
+
priceCents: import_zod66.z.number(),
|
|
6900
|
+
quantity: import_zod66.z.number(),
|
|
6901
|
+
title: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX),
|
|
6902
|
+
type: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX)
|
|
6903
|
+
});
|
|
6904
|
+
var MonetizeInputSchema = import_zod66.z.object({
|
|
6492
6905
|
cart: CartInputSchema,
|
|
6493
6906
|
/** Client-minted render-beacon correlation id; forwarded to the ads engine as `client_request_id`. */
|
|
6494
|
-
clientRequestId:
|
|
6495
|
-
country:
|
|
6496
|
-
currency:
|
|
6907
|
+
clientRequestId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6908
|
+
country: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6909
|
+
currency: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6497
6910
|
/** Ads-targeting identity/geo/locale fields (React parity); folded into the engine query verbatim. */
|
|
6498
|
-
customerEmail:
|
|
6499
|
-
customerFirstName:
|
|
6500
|
-
customerId:
|
|
6501
|
-
customerLastName:
|
|
6502
|
-
language:
|
|
6911
|
+
customerEmail: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
|
|
6912
|
+
customerFirstName: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
|
|
6913
|
+
customerId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6914
|
+
customerLastName: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
|
|
6915
|
+
language: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6503
6916
|
/** Buyer-facing order name (e.g. `#1001`) for the server-composed "Order … Confirmed" chrome line. */
|
|
6504
|
-
orderName:
|
|
6917
|
+
orderName: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
|
|
6505
6918
|
/** Ads surface label, forwarded verbatim; `customer_account` is measured/floored as its own surface (the account-area order list). */
|
|
6506
|
-
placement:
|
|
6919
|
+
placement: import_zod66.z.enum(["customer_account", "order_status", "thank_you_page"]),
|
|
6507
6920
|
/** Privacy Policy footer href — the Monetize widget's `privacy_policy_url` setting (React parity). */
|
|
6508
|
-
privacyPolicyUrl:
|
|
6921
|
+
privacyPolicyUrl: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_URL_MAX).optional(),
|
|
6509
6922
|
/** 30-min rolling session id (React parity); used for the ads `session_id`, else the visitor id. */
|
|
6510
|
-
sessionId:
|
|
6511
|
-
shop:
|
|
6923
|
+
sessionId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6924
|
+
shop: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
6512
6925
|
/** Editor/QA indicator; OR-ed into the ads-engine `testing` flag so it stays out of billing/reporting. */
|
|
6513
|
-
testing:
|
|
6514
|
-
timezone:
|
|
6926
|
+
testing: import_zod66.z.boolean().optional(),
|
|
6927
|
+
timezone: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6515
6928
|
/** Decorated (numeric) order id → the ads `transaction_id`. */
|
|
6516
|
-
transactionId:
|
|
6929
|
+
transactionId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6517
6930
|
/** Rich per-line ads items; capped at the engine's ads contract. Preferred over `cart.items`. */
|
|
6518
|
-
transactionItems:
|
|
6931
|
+
transactionItems: import_zod66.z.array(MonetizeTransactionItemSchema).max(REQUEST_BOUNDS.TRANSACTION_ITEMS_MAX).optional(),
|
|
6519
6932
|
/** Order total in presentment cents (React prefers total over subtotal); else `cart.subtotal`. */
|
|
6520
|
-
transactionTotal:
|
|
6521
|
-
visitorId:
|
|
6522
|
-
zipCode:
|
|
6933
|
+
transactionTotal: import_zod66.z.number().optional(),
|
|
6934
|
+
visitorId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6935
|
+
zipCode: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
|
|
6523
6936
|
});
|
|
6524
|
-
var WidgetSettingsInputSchema =
|
|
6937
|
+
var WidgetSettingsInputSchema = import_zod66.z.object({
|
|
6525
6938
|
/**
|
|
6526
6939
|
* Same domain as `CabShopConfig.cacheKey`, for the same reason: this side WINS the orchestrator's
|
|
6527
6940
|
* `input.cacheKey ?? config.shop.cacheKey` (and an explicit value skips the config read entirely), so
|
|
@@ -6529,9 +6942,9 @@ var WidgetSettingsInputSchema = import_zod56.z.object({
|
|
|
6529
6942
|
* and pin the edge copy permanently stale. `.catch(undefined)` because a bogus buster should degrade
|
|
6530
6943
|
* the read to un-busted, never 400 a widget render.
|
|
6531
6944
|
*/
|
|
6532
|
-
cacheKey:
|
|
6533
|
-
id:
|
|
6534
|
-
key:
|
|
6945
|
+
cacheKey: import_zod66.z.number().int().positive().optional().catch(void 0),
|
|
6946
|
+
id: import_zod66.z.number(),
|
|
6947
|
+
key: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6535
6948
|
/**
|
|
6536
6949
|
* Monetize context for inline hydration: when present AND the widget converts to a Monetize marker,
|
|
6537
6950
|
* the server fetches/composes the offer cards inside this same request (no second `/cab/monetize`
|
|
@@ -6540,34 +6953,34 @@ var WidgetSettingsInputSchema = import_zod56.z.object({
|
|
|
6540
6953
|
* `privacyPolicyUrl` comes from the widget settings server-side (more authoritative than a relay).
|
|
6541
6954
|
*/
|
|
6542
6955
|
monetize: MonetizeInputSchema.omit({ privacyPolicyUrl: true, shop: true }).optional(),
|
|
6543
|
-
shop:
|
|
6956
|
+
shop: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
6544
6957
|
/** Stable per-buyer id; when present, enables sticky server-side A/B variant selection. */
|
|
6545
|
-
visitorId:
|
|
6958
|
+
visitorId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
|
|
6546
6959
|
});
|
|
6547
|
-
var AnalyticsEventInputSchema =
|
|
6548
|
-
name:
|
|
6549
|
-
properties:
|
|
6550
|
-
sentAt:
|
|
6960
|
+
var AnalyticsEventInputSchema = import_zod66.z.object({
|
|
6961
|
+
name: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
|
|
6962
|
+
properties: import_zod66.z.record(import_zod66.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), import_zod66.z.unknown()).optional(),
|
|
6963
|
+
sentAt: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
|
|
6551
6964
|
});
|
|
6552
|
-
var AnalyticsSegmentsInputSchema =
|
|
6553
|
-
device:
|
|
6554
|
-
source:
|
|
6555
|
-
visitor:
|
|
6965
|
+
var AnalyticsSegmentsInputSchema = import_zod66.z.object({
|
|
6966
|
+
device: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
|
|
6967
|
+
source: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
|
|
6968
|
+
visitor: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0)
|
|
6556
6969
|
});
|
|
6557
|
-
var AnalyticsInputSchema =
|
|
6970
|
+
var AnalyticsInputSchema = import_zod66.z.object({
|
|
6558
6971
|
/** Rebuy cart token (the `r_cart_token` cart attribute), when available — primary aggregation key. */
|
|
6559
|
-
cartToken:
|
|
6972
|
+
cartToken: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6560
6973
|
/** Shopify checkout token, when available — drives cart/checkout aggregation downstream. */
|
|
6561
|
-
checkoutToken:
|
|
6562
|
-
events:
|
|
6974
|
+
checkoutToken: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6975
|
+
events: import_zod66.z.array(AnalyticsEventInputSchema).max(REQUEST_BOUNDS.EVENTS_MAX),
|
|
6563
6976
|
/**
|
|
6564
6977
|
* Request-scoped like the tokens: one visitor's segments apply to every event in the batch. The container
|
|
6565
6978
|
* degrades too (`null` is a realistic wire artifact of `attributes ? {…} : null`), so the degrade rule is
|
|
6566
6979
|
* total: nothing about `segments` can cost the envelope.
|
|
6567
6980
|
*/
|
|
6568
6981
|
segments: AnalyticsSegmentsInputSchema.optional().catch(void 0),
|
|
6569
|
-
shop:
|
|
6570
|
-
visitorId:
|
|
6982
|
+
shop: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
6983
|
+
visitorId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
6571
6984
|
/** The widget id (smartBlockId) the events belong to. */
|
|
6572
|
-
widgetId:
|
|
6985
|
+
widgetId: import_zod66.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
|
|
6573
6986
|
});
|