@rebuy/rebuy 3.34.0 → 3.36.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 +1003 -801
- package/dist/index.mjs +1005 -803
- package/dist/schema/index.d.ts +8 -0
- package/dist/schema/postPurchaseGroup.d.ts +15 -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/postPurchaseProduct.d.ts +74 -24
- package/dist/schema/postPurchaseProductCalculation.d.ts +87 -0
- package/dist/schema/postPurchaseProductCollectionView.d.ts +724 -3
- package/dist/schema/postPurchaseProductDisplay.d.ts +41 -12
- package/dist/schema/postPurchaseProductSource.d.ts +10 -5
- package/dist/schema/postPurchaseProductView.d.ts +708 -0
- package/dist/schema/postPurchaseQuantity.d.ts +26 -0
- package/dist/schema/postPurchaseSubscriptionProduct.d.ts +74 -17
- package/dist/schema/postPurchaseVariantDefault.d.ts +17 -0
- package/dist/schema/postPurchaseVariantDefaultContext.d.ts +10 -0
- package/dist/server/__fixtures__/postPurchaseGroup.d.ts +78 -0
- package/dist/server/classifyPostPurchaseOffer.d.ts +3 -0
- package/dist/server/createPostPurchaseOrderAttributes.d.ts +9 -0
- package/dist/server/index.cjs +1131 -210
- package/dist/server/index.d.ts +20 -2
- package/dist/server/index.mjs +1131 -210
- package/dist/server/postPurchaseMemberEligibility.d.ts +7 -0
- package/dist/server/postPurchaseOfferCopy.d.ts +3 -0
- package/dist/server/postPurchaseProductDisplay.d.ts +38 -6
- 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/preparePostPurchaseAdmissionView.d.ts +418 -0
- package/dist/server/preparePostPurchaseCollectionGroup.d.ts +458 -0
- package/dist/server/preparePostPurchaseCollectionView.d.ts +442 -0
- package/dist/server/preparePostPurchaseGroupAdmissionView.d.ts +459 -0
- package/dist/server/preparePostPurchaseGroupDeclineDisplay.d.ts +12 -0
- package/dist/server/preparePostPurchaseGroupDefault.d.ts +459 -0
- package/dist/server/preparePostPurchaseGroupView.d.ts +458 -0
- package/dist/server/preparePostPurchaseMemberView.d.ts +1466 -0
- package/dist/server/preparePostPurchaseOfferPresentation.d.ts +137 -0
- package/dist/server/preparePostPurchaseProduct.d.ts +11 -0
- package/dist/server/preparePostPurchaseQuantityAdmissionView.d.ts +440 -0
- package/dist/server/preparePostPurchaseQuantityView.d.ts +427 -0
- package/dist/server/preparePostPurchaseSubscription.d.ts +37 -5
- package/dist/server/preparePostPurchaseView.d.ts +8 -0
- package/dist/server/projectPostPurchaseProduct.d.ts +42 -12
- 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/dist/transforms/postPurchase/convertDescriptionRte.d.ts +11 -0
- package/package.json +1 -1
package/dist/server/index.cjs
CHANGED
|
@@ -33,18 +33,36 @@ __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
|
+
preparePostPurchaseAdmissionView: () => preparePostPurchaseAdmissionView,
|
|
51
|
+
preparePostPurchaseCollectionView: () => preparePostPurchaseCollectionView,
|
|
52
|
+
preparePostPurchaseGroupAdmissionView: () => preparePostPurchaseGroupAdmissionView,
|
|
53
|
+
preparePostPurchaseGroupDeclineDisplay: () => preparePostPurchaseGroupDeclineDisplay,
|
|
54
|
+
preparePostPurchaseGroupDefault: () => preparePostPurchaseGroupDefault,
|
|
55
|
+
preparePostPurchaseGroupView: () => preparePostPurchaseGroupView,
|
|
56
|
+
preparePostPurchaseMemberAdmissionView: () => preparePostPurchaseMemberAdmissionView,
|
|
57
|
+
preparePostPurchaseMemberView: () => preparePostPurchaseMemberView,
|
|
58
|
+
preparePostPurchaseOfferPresentation: () => preparePostPurchaseOfferPresentation,
|
|
59
|
+
preparePostPurchaseProduct: () => preparePostPurchaseProduct,
|
|
60
|
+
preparePostPurchaseQuantityAdmissionView: () => preparePostPurchaseQuantityAdmissionView,
|
|
61
|
+
preparePostPurchaseQuantityView: () => preparePostPurchaseQuantityView,
|
|
47
62
|
preparePostPurchaseSubscription: () => preparePostPurchaseSubscription,
|
|
63
|
+
preparePostPurchaseView: () => preparePostPurchaseView,
|
|
64
|
+
readPostPurchaseGroupSelection: () => readPostPurchaseGroupSelection,
|
|
65
|
+
readPostPurchaseQuantity: () => readPostPurchaseQuantity,
|
|
48
66
|
translateAnalyticsEvent: () => translateAnalyticsEvent,
|
|
49
67
|
validateGifts: () => validateGifts
|
|
50
68
|
});
|
|
@@ -679,7 +697,7 @@ var import_uuid13 = require("uuid");
|
|
|
679
697
|
var import_zod27 = require("zod");
|
|
680
698
|
|
|
681
699
|
// src/schema/widgets/checkout-and-beyond/common.ts
|
|
682
|
-
var freezeEnum = (
|
|
700
|
+
var freezeEnum = (values2) => Object.freeze(Object.fromEntries(values2.map((v) => [v, v])));
|
|
683
701
|
var bannerColors = ["info", "success", "warning", "critical"];
|
|
684
702
|
var BannerColor = freezeEnum(bannerColors);
|
|
685
703
|
var borderRadii = ["none", "small", "base", "large", "fullyRounded"];
|
|
@@ -2145,15 +2163,15 @@ var CABImageSectionFields = import_zod27.z.object({
|
|
|
2145
2163
|
width: import_zod27.z.number().default(100)
|
|
2146
2164
|
});
|
|
2147
2165
|
var iconNameSet = new Set(iconNames);
|
|
2148
|
-
var isIconName = (
|
|
2149
|
-
var CABImageSection = CABImageSectionFields.superRefine(({ category, source }, ctx) => {
|
|
2150
|
-
if (category === "icon" &&
|
|
2166
|
+
var isIconName = (source2) => iconNameSet.has(source2);
|
|
2167
|
+
var CABImageSection = CABImageSectionFields.superRefine(({ category, source: source2 }, ctx) => {
|
|
2168
|
+
if (category === "icon" && source2 !== "" && !isIconName(source2))
|
|
2151
2169
|
ctx.addIssue({
|
|
2152
2170
|
code: "custom",
|
|
2153
2171
|
message: "icon-mode source must be an icon name",
|
|
2154
2172
|
path: ["source"]
|
|
2155
2173
|
});
|
|
2156
|
-
if (category !== "icon" && isIconName(
|
|
2174
|
+
if (category !== "icon" && isIconName(source2))
|
|
2157
2175
|
ctx.addIssue({
|
|
2158
2176
|
code: "custom",
|
|
2159
2177
|
message: "source must be a URL or dynamic token unless category is `icon`",
|
|
@@ -2171,7 +2189,7 @@ var stripContentBlockHtml = (text2) => text2.replace(HTML_COMMENT_RE, "").replac
|
|
|
2171
2189
|
var convertTextToTiptapParagraph = ({
|
|
2172
2190
|
color,
|
|
2173
2191
|
fontSize,
|
|
2174
|
-
marks = [],
|
|
2192
|
+
marks: marks2 = [],
|
|
2175
2193
|
text: text2,
|
|
2176
2194
|
textAlign
|
|
2177
2195
|
}) => {
|
|
@@ -2180,7 +2198,7 @@ var convertTextToTiptapParagraph = ({
|
|
|
2180
2198
|
attrs: { textAlign },
|
|
2181
2199
|
content: sanitizedText ? [
|
|
2182
2200
|
{
|
|
2183
|
-
marks: [{ attrs: { color, fontSize }, type: "textStyle" }, ...
|
|
2201
|
+
marks: [{ attrs: { color, fontSize }, type: "textStyle" }, ...marks2],
|
|
2184
2202
|
text: sanitizedText,
|
|
2185
2203
|
type: "text"
|
|
2186
2204
|
}
|
|
@@ -2265,10 +2283,10 @@ var HEADER_PARAGRAPH_STYLES = {
|
|
|
2265
2283
|
superTitle: { color: "base", fontSize: "extraLarge", marks: [{ type: "bold" }] },
|
|
2266
2284
|
title: { color: "base", fontSize: "medium", marks: [{ type: "bold" }] }
|
|
2267
2285
|
};
|
|
2268
|
-
var convertContentBlockTextToV2 = (
|
|
2269
|
-
const description =
|
|
2270
|
-
const superTitle =
|
|
2271
|
-
const title =
|
|
2286
|
+
var convertContentBlockTextToV2 = (language3, text2 = literalText, textAlign = "center") => {
|
|
2287
|
+
const description = language3?.description;
|
|
2288
|
+
const superTitle = language3?.superTitle;
|
|
2289
|
+
const title = language3?.title;
|
|
2272
2290
|
return TiptapDocument.parse({
|
|
2273
2291
|
attrs: { blockSpacing: "tight" },
|
|
2274
2292
|
content: [
|
|
@@ -2380,7 +2398,7 @@ var LOCATION_TO_EDITOR_MODE = {
|
|
|
2380
2398
|
};
|
|
2381
2399
|
|
|
2382
2400
|
// src/transforms/contentBlockV1/convertContentBlockToV2.ts
|
|
2383
|
-
var hasText = (
|
|
2401
|
+
var hasText = (language3) => !!language3 && !!(language3.description || language3.superTitle || language3.title);
|
|
2384
2402
|
var convertContentBlockToV2 = ({ id, settings }) => {
|
|
2385
2403
|
const imageBlocks = settings.imageBlocks ?? [];
|
|
2386
2404
|
return CABRootSection.parse({
|
|
@@ -2637,11 +2655,11 @@ var pushText = (state, rawText) => {
|
|
|
2637
2655
|
decodeTextEntities(rawText).split("\n").forEach((segment, index) => {
|
|
2638
2656
|
if (index > 0) flushParagraph(state);
|
|
2639
2657
|
if (!segment) return;
|
|
2640
|
-
const
|
|
2641
|
-
if (state.defaultTextStyleMark && !
|
|
2642
|
-
|
|
2658
|
+
const marks2 = state.stack.flatMap((entry) => entry.marks);
|
|
2659
|
+
if (state.defaultTextStyleMark && !marks2.some((mark) => mark.type === "textStyle")) {
|
|
2660
|
+
marks2.push(state.defaultTextStyleMark);
|
|
2643
2661
|
}
|
|
2644
|
-
state.currentRuns.push(TiptapText.parse(
|
|
2662
|
+
state.currentRuns.push(TiptapText.parse(marks2.length > 0 ? { marks: marks2, text: segment } : { text: segment }));
|
|
2645
2663
|
});
|
|
2646
2664
|
};
|
|
2647
2665
|
|
|
@@ -2653,15 +2671,15 @@ var stripHtmlComments = (html = "") => html.replace(HTML_COMMENT_RE2, "");
|
|
|
2653
2671
|
var maybeFlushParagraph = (state) => {
|
|
2654
2672
|
if (state.currentRuns.length > 0) flushParagraph(state);
|
|
2655
2673
|
};
|
|
2656
|
-
var htmlToTiptap = (html,
|
|
2674
|
+
var htmlToTiptap = (html, options2 = {}) => {
|
|
2657
2675
|
const state = {
|
|
2658
2676
|
currentRuns: [],
|
|
2659
|
-
defaultTextStyleMark: buildDefaultTextStyleMark(
|
|
2677
|
+
defaultTextStyleMark: buildDefaultTextStyleMark(options2.defaultTextStyle),
|
|
2660
2678
|
listStack: [],
|
|
2661
2679
|
paragraphs: [],
|
|
2662
2680
|
stack: []
|
|
2663
2681
|
};
|
|
2664
|
-
const blockSpacing =
|
|
2682
|
+
const blockSpacing = options2.blockSpacing ?? "base";
|
|
2665
2683
|
if (typeof html !== "string" || !html) return makeDoc([makeParagraph([])], blockSpacing);
|
|
2666
2684
|
const htmlWithoutComments = stripHtmlComments(html);
|
|
2667
2685
|
let lastIndex = 0;
|
|
@@ -2906,9 +2924,9 @@ var isMonetizeV1 = isWidgetV1(WidgetType.ui_extension_ad);
|
|
|
2906
2924
|
var HTML_TAG_RE2 = /<[a-zA-Z]/;
|
|
2907
2925
|
var containsHtml = (text2) => HTML_TAG_RE2.test(text2);
|
|
2908
2926
|
var isObject = (x) => x !== null && typeof x === "object" && !Array.isArray(x);
|
|
2909
|
-
var normalizeTextValue = (value,
|
|
2927
|
+
var normalizeTextValue = (value, options2 = {}) => {
|
|
2910
2928
|
const tokenized = normalizeTokens(value);
|
|
2911
|
-
return containsHtml(tokenized) ||
|
|
2929
|
+
return containsHtml(tokenized) || options2.defaultTextStyle ? htmlToTiptap(tokenized, options2) : decodeTextEntities(tokenized);
|
|
2912
2930
|
};
|
|
2913
2931
|
var normalizeLangValue = (value) => typeof value === "string" ? normalizeTextValue(value) : value;
|
|
2914
2932
|
var normalizeTextContent = (node) => {
|
|
@@ -2941,15 +2959,15 @@ var resolveExperiment = (experiments, placeholderId, visitorId) => {
|
|
|
2941
2959
|
if (!experiment || experiment.data.length === 0) return void 0;
|
|
2942
2960
|
const roll = rollPercent(`${visitorId}:${experiment.id}`);
|
|
2943
2961
|
let cumulative = 0;
|
|
2944
|
-
const
|
|
2962
|
+
const variant2 = experiment.data.find((candidate) => {
|
|
2945
2963
|
cumulative += candidate.traffic;
|
|
2946
2964
|
return roll < cumulative;
|
|
2947
2965
|
}) ?? experiment.data[0];
|
|
2948
2966
|
return {
|
|
2949
|
-
elementId:
|
|
2967
|
+
elementId: variant2.elementId,
|
|
2950
2968
|
experimentId: experiment.id,
|
|
2951
2969
|
experimentType: experiment.type,
|
|
2952
|
-
selectedId:
|
|
2970
|
+
selectedId: variant2.id
|
|
2953
2971
|
};
|
|
2954
2972
|
};
|
|
2955
2973
|
|
|
@@ -3216,10 +3234,10 @@ var SWITCH_LABEL_TOKENS2 = ["subscriptionDiscount", "frequency", "interval"];
|
|
|
3216
3234
|
var QUANTITY_ERROR_TOKENS = ["max", "min", "step"];
|
|
3217
3235
|
var VARIANT_SELECTOR = { button: "button", radio: "radio", select: "menu" };
|
|
3218
3236
|
var buildStyledText = (token, style, fontSize = style?.textSize ?? "base") => {
|
|
3219
|
-
const
|
|
3220
|
-
if (style?.textEmphasis === "bold")
|
|
3221
|
-
if (style?.textEmphasis === "italic")
|
|
3222
|
-
return { content: [{ content: [{ marks, text: token, type: "text" }], type: "paragraph" }], type: "doc" };
|
|
3237
|
+
const marks2 = [{ attrs: { color: "base", fontSize }, type: "textStyle" }];
|
|
3238
|
+
if (style?.textEmphasis === "bold") marks2.push({ type: "bold" });
|
|
3239
|
+
if (style?.textEmphasis === "italic") marks2.push({ type: "italic" });
|
|
3240
|
+
return { content: [{ content: [{ marks: marks2, text: token, type: "text" }], type: "paragraph" }], type: "doc" };
|
|
3223
3241
|
};
|
|
3224
3242
|
var buildPriceContent = () => ({
|
|
3225
3243
|
content: [
|
|
@@ -3397,23 +3415,23 @@ var QUANTITY_INPUT_TYPE = {
|
|
|
3397
3415
|
"buttons-manual-input": "number",
|
|
3398
3416
|
"dropdown-select": "select"
|
|
3399
3417
|
};
|
|
3400
|
-
var buildQuantityErrors = (
|
|
3418
|
+
var buildQuantityErrors = (quantity2) => {
|
|
3401
3419
|
const en = {
|
|
3402
|
-
...
|
|
3403
|
-
...
|
|
3404
|
-
...
|
|
3420
|
+
...quantity2.maxError && { max: normalizeTokens(quantity2.maxError, QUANTITY_ERROR_TOKENS) },
|
|
3421
|
+
...quantity2.minError && { min: normalizeTokens(quantity2.minError, QUANTITY_ERROR_TOKENS) },
|
|
3422
|
+
...quantity2.negativeError && { neg: normalizeTokens(quantity2.negativeError, QUANTITY_ERROR_TOKENS) }
|
|
3405
3423
|
};
|
|
3406
3424
|
return Object.keys(en).length ? { errorMessages: { en } } : {};
|
|
3407
3425
|
};
|
|
3408
3426
|
var buildQuantity = (settings) => {
|
|
3409
|
-
const
|
|
3410
|
-
if (!
|
|
3411
|
-
const inputType =
|
|
3412
|
-
const max = Math.min(Math.max(
|
|
3413
|
-
const min = Math.min(Math.max(
|
|
3427
|
+
const quantity2 = settings.quantityInputs;
|
|
3428
|
+
if (!quantity2?.enabled) return [];
|
|
3429
|
+
const inputType = quantity2.type ? QUANTITY_INPUT_TYPE[quantity2.type] : void 0;
|
|
3430
|
+
const max = Math.min(Math.max(quantity2.maxValue ?? 10, 1), 100);
|
|
3431
|
+
const min = Math.min(Math.max(quantity2.minValue ?? 1, 1), max);
|
|
3414
3432
|
return [
|
|
3415
3433
|
{
|
|
3416
|
-
...buildQuantityErrors(
|
|
3434
|
+
...buildQuantityErrors(quantity2),
|
|
3417
3435
|
...inputType && { inputType },
|
|
3418
3436
|
max,
|
|
3419
3437
|
min,
|
|
@@ -3423,7 +3441,7 @@ var buildQuantity = (settings) => {
|
|
|
3423
3441
|
};
|
|
3424
3442
|
var buildSubscriptionButton = (settings) => {
|
|
3425
3443
|
if (settings.productType !== "both" && settings.productType !== "subscription") return [];
|
|
3426
|
-
const
|
|
3444
|
+
const language3 = settings.language;
|
|
3427
3445
|
const slot = (buttonField, override) => ({
|
|
3428
3446
|
buttonField,
|
|
3429
3447
|
content: localizedContent(SWITCH_LABELS[buttonField], override, SWITCH_LABEL_TOKENS2),
|
|
@@ -3437,9 +3455,9 @@ var buildSubscriptionButton = (settings) => {
|
|
|
3437
3455
|
...settings.productType === "subscription" && { disableDowngrade: true },
|
|
3438
3456
|
sections: [
|
|
3439
3457
|
slot("subscriptionOption", void 0),
|
|
3440
|
-
slot("switchToOneTimePurchase",
|
|
3441
|
-
slot("switchToSubscriptionNoDiscount",
|
|
3442
|
-
slot("switchToSubscriptionWithDiscount",
|
|
3458
|
+
slot("switchToOneTimePurchase", language3?.cartSwitchToOnetime),
|
|
3459
|
+
slot("switchToSubscriptionNoDiscount", language3?.upgradeToSubscription),
|
|
3460
|
+
slot("switchToSubscriptionWithDiscount", language3?.upgradeToSubscription)
|
|
3443
3461
|
],
|
|
3444
3462
|
sectionType: "button"
|
|
3445
3463
|
}
|
|
@@ -3494,11 +3512,11 @@ var buildOfferCard = (settings, horizontal) => {
|
|
|
3494
3512
|
const description = buildDescription(settings);
|
|
3495
3513
|
const reviews = buildReviews(settings);
|
|
3496
3514
|
const variants = buildVariants(settings);
|
|
3497
|
-
const
|
|
3515
|
+
const quantity2 = buildQuantity(settings);
|
|
3498
3516
|
const subscription2 = buildSubscriptionButton(settings);
|
|
3499
3517
|
const reveal = buildRevealButton(settings);
|
|
3500
3518
|
const addButton = buildAddButton(settings);
|
|
3501
|
-
const controls = [...description, ...
|
|
3519
|
+
const controls = [...description, ...quantity2, ...variants, ...subscription2];
|
|
3502
3520
|
const info = detailBlock([title, ...variantTitle, ...reviews, price], horizontal, variantTitle.length > 0);
|
|
3503
3521
|
const card = (sections) => [
|
|
3504
3522
|
{
|
|
@@ -3552,9 +3570,9 @@ var buildCarouselNav = () => ({
|
|
|
3552
3570
|
sectionType: "layout"
|
|
3553
3571
|
});
|
|
3554
3572
|
var HEADER_FIELDS = ["superTitle", "title", "description"];
|
|
3555
|
-
var sanitizedHeader = (
|
|
3573
|
+
var sanitizedHeader = (language3) => Object.fromEntries(
|
|
3556
3574
|
HEADER_FIELDS.flatMap((field) => {
|
|
3557
|
-
const value =
|
|
3575
|
+
const value = language3?.[field];
|
|
3558
3576
|
const sanitized = value ? stripContentBlockHtml(normalizeTokens(value)) : "";
|
|
3559
3577
|
return sanitized ? [[field, sanitized]] : [];
|
|
3560
3578
|
})
|
|
@@ -3651,7 +3669,7 @@ var coerceIntegrations = (integrations) => Object.fromEntries(
|
|
|
3651
3669
|
return [key, value];
|
|
3652
3670
|
})
|
|
3653
3671
|
);
|
|
3654
|
-
var buildBanner = (
|
|
3672
|
+
var buildBanner = (language3) => language3?.successBannerEnabled ? [
|
|
3655
3673
|
{
|
|
3656
3674
|
/**
|
|
3657
3675
|
* The banner-level tag is the extraction/routing key on BOTH renderers (React CAB's
|
|
@@ -3664,7 +3682,7 @@ var buildBanner = (language2) => language2?.successBannerEnabled ? [
|
|
|
3664
3682
|
dismissible: true,
|
|
3665
3683
|
sections: [
|
|
3666
3684
|
{
|
|
3667
|
-
content: bannerMessageContent(
|
|
3685
|
+
content: bannerMessageContent(language3.successBannerMessageRte),
|
|
3668
3686
|
sectionType: "text"
|
|
3669
3687
|
},
|
|
3670
3688
|
{
|
|
@@ -3981,14 +3999,14 @@ var convertCalloutBlock = (raw, report) => {
|
|
|
3981
3999
|
};
|
|
3982
4000
|
const shell = Shell.safeParse(raw);
|
|
3983
4001
|
if (!shell.success) return omit("Unreadable post-purchase callout");
|
|
3984
|
-
const
|
|
4002
|
+
const values2 = fields.map((field) => ({
|
|
3985
4003
|
field,
|
|
3986
4004
|
result: CalloutBannerBlock.shape.settings.shape[field].safeParse(shell.data.settings[field])
|
|
3987
4005
|
}));
|
|
3988
|
-
const styled2 =
|
|
4006
|
+
const styled2 = values2.every(({ result }) => result.success && typeof result.data === "string");
|
|
3989
4007
|
const styles2 = shell.data.styles;
|
|
3990
4008
|
const horizontal = styled2 ? { center: "center", leading: "start", trailing: "end" }[styles2.textAlignment] : "center";
|
|
3991
|
-
const sections =
|
|
4009
|
+
const sections = values2.flatMap(({ field, result }) => {
|
|
3992
4010
|
if (!result.success) return omit(`Unreadable post-purchase callout field: ${field}`);
|
|
3993
4011
|
const text2 = result.data;
|
|
3994
4012
|
if (text2 === "") return [];
|
|
@@ -4010,12 +4028,12 @@ var convertCalloutBlock = (raw, report) => {
|
|
|
4010
4028
|
var import_zod32 = require("zod");
|
|
4011
4029
|
|
|
4012
4030
|
// src/transforms/postPurchase/sizeImageSource.ts
|
|
4013
|
-
var sizeImageSource = (
|
|
4014
|
-
const extension =
|
|
4031
|
+
var sizeImageSource = (source2, size) => {
|
|
4032
|
+
const extension = source2.split(".").pop();
|
|
4015
4033
|
for (const previous of ["small", "medium", "large", "original", "master"]) {
|
|
4016
|
-
|
|
4034
|
+
source2 = source2.replace(`_${previous}.${extension}`, `.${extension}`);
|
|
4017
4035
|
}
|
|
4018
|
-
return
|
|
4036
|
+
return source2.replace(`.${extension}`, `${size === void 0 ? "" : `_${size}`}.${extension}`);
|
|
4019
4037
|
};
|
|
4020
4038
|
|
|
4021
4039
|
// src/transforms/postPurchase/convertImageFrame.ts
|
|
@@ -4025,9 +4043,9 @@ var convertImageFrame = (raw) => {
|
|
|
4025
4043
|
const parsed = ImageBlock.shape.settings.options[0].safeParse(raw);
|
|
4026
4044
|
if (!parsed.success) return null;
|
|
4027
4045
|
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 });
|
|
4046
|
+
const source2 = sizeImageSource(Source.parse(settings.image || void 0));
|
|
4047
|
+
const withAlt = CABImageSection.safeParse({ altText: settings.alt, source: source2 });
|
|
4048
|
+
const image = withAlt.success ? withAlt.data : CABImageSection.parse({ source: source2 });
|
|
4031
4049
|
const size = settings.imageSize > 0 ? settings.imageSize : DEFAULT_IMAGE_SIZE;
|
|
4032
4050
|
return CABLayoutSection.parse({
|
|
4033
4051
|
alignment: { horizontal: "center" },
|
|
@@ -4264,19 +4282,19 @@ var convertTextBlock = (raw, report) => {
|
|
|
4264
4282
|
report?.({ detail: "Unreadable post-purchase text block", kind: "section" });
|
|
4265
4283
|
return [];
|
|
4266
4284
|
}
|
|
4267
|
-
const
|
|
4285
|
+
const values2 = fields3.map((field) => ({
|
|
4268
4286
|
field,
|
|
4269
4287
|
result: settingsSchema.shape[field].safeParse(shell.data.settings[field])
|
|
4270
4288
|
}));
|
|
4271
4289
|
const horizontal = { center: "center", leading: "start", trailing: "end" }[shell.data.settings.horizontalAlignment];
|
|
4272
|
-
const styled2 =
|
|
4290
|
+
const styled2 = values2.every(
|
|
4273
4291
|
({ result }) => result.success && (result.data === null || typeof result.data === "string")
|
|
4274
4292
|
);
|
|
4275
4293
|
const omit = (field) => {
|
|
4276
4294
|
report?.({ detail: `Unreadable post-purchase text field: ${field}`, kind: "section" });
|
|
4277
4295
|
return [];
|
|
4278
4296
|
};
|
|
4279
|
-
const sections =
|
|
4297
|
+
const sections = values2.flatMap(({ field, result }) => {
|
|
4280
4298
|
if (!result.success) return omit(field);
|
|
4281
4299
|
const text2 = result.data;
|
|
4282
4300
|
if (text2 === null || text2 === "") return [];
|
|
@@ -4510,10 +4528,10 @@ var giftOf = (tier) => {
|
|
|
4510
4528
|
if (tier.type !== "product") return void 0;
|
|
4511
4529
|
const product = tier.products?.[0] ?? tier.allProducts?.[0];
|
|
4512
4530
|
if (!product) return void 0;
|
|
4513
|
-
const
|
|
4514
|
-
if (
|
|
4531
|
+
const productId2 = product.productId ?? product.id;
|
|
4532
|
+
if (productId2 === void 0) return void 0;
|
|
4515
4533
|
return {
|
|
4516
|
-
productId,
|
|
4534
|
+
productId: productId2,
|
|
4517
4535
|
title: product.title,
|
|
4518
4536
|
variantIds: positiveIds(product.variantIds)
|
|
4519
4537
|
};
|
|
@@ -4792,14 +4810,14 @@ function serialize(obj) {
|
|
|
4792
4810
|
var encodeAttributes = (pairs = []) => JSON.stringify(Object.fromEntries(pairs.map(({ key, value }) => [key, value ?? ""])));
|
|
4793
4811
|
var buildEngineParams = (input, key) => {
|
|
4794
4812
|
const { cart, customerId, filterInputs, integrations, limit, productType, shop, visitorId } = input;
|
|
4795
|
-
const items = cart.items.map(({ productId, properties, quantity, subscriptionId, variantId }) => ({
|
|
4796
|
-
product_id:
|
|
4813
|
+
const items = cart.items.map(({ productId: productId2, properties, quantity: quantity2, subscriptionId, variantId }) => ({
|
|
4814
|
+
product_id: productId2,
|
|
4797
4815
|
properties: encodeAttributes(properties),
|
|
4798
|
-
quantity,
|
|
4816
|
+
quantity: quantity2,
|
|
4799
4817
|
...subscriptionId && { subscription_id: subscriptionId },
|
|
4800
4818
|
variant_id: variantId
|
|
4801
4819
|
}));
|
|
4802
|
-
const itemCount = cart.items.reduce((total, { quantity }) => total +
|
|
4820
|
+
const itemCount = cart.items.reduce((total, { quantity: quantity2 }) => total + quantity2, 0);
|
|
4803
4821
|
const subtotal = shopSubtotalCents(cart);
|
|
4804
4822
|
return {
|
|
4805
4823
|
cart: {
|
|
@@ -4886,13 +4904,13 @@ var OFFER_LIMIT = 4;
|
|
|
4886
4904
|
var SUPPORTED_COUNTRIES = /* @__PURE__ */ new Set(["US", "CA", "GB"]);
|
|
4887
4905
|
var MAX_TRANSACTION_ITEMS = 50;
|
|
4888
4906
|
var TEST_CUSTOMER_EMAIL = "test@rebuyengine.com";
|
|
4889
|
-
var transactionItems = (input) => (input.transactionItems?.map(({ id, priceCents, quantity, title, type }) => ({
|
|
4907
|
+
var transactionItems = (input) => (input.transactionItems?.map(({ id, priceCents, quantity: quantity2, title, type }) => ({
|
|
4890
4908
|
id,
|
|
4891
4909
|
price_cents: priceCents,
|
|
4892
|
-
quantity,
|
|
4910
|
+
quantity: quantity2,
|
|
4893
4911
|
title,
|
|
4894
4912
|
type
|
|
4895
|
-
})) ?? input.cart.items.map(({ productId, quantity }) => ({ id:
|
|
4913
|
+
})) ?? input.cart.items.map(({ productId: productId2, quantity: quantity2 }) => ({ id: productId2, quantity: quantity2 }))).slice(0, MAX_TRANSACTION_ITEMS);
|
|
4896
4914
|
var AdsEngineOffer = import_zod37.z.object({
|
|
4897
4915
|
/** Pill-style value prop ("Get $45 Cashback"). Carried through the parse; the card does not render it yet (REB-24429 — pill design pending). */
|
|
4898
4916
|
callout: import_zod37.z.string().catch(""),
|
|
@@ -5010,9 +5028,9 @@ var label = (text2) => ({
|
|
|
5010
5028
|
});
|
|
5011
5029
|
var text = (content) => ({ content: { en: content }, sectionType: SectionType.text });
|
|
5012
5030
|
var AS_DOC = { defaultTextStyle: {} };
|
|
5013
|
-
var safeTextValue = (raw,
|
|
5014
|
-
const converted = normalizeTextValue(raw,
|
|
5015
|
-
return checkForHTML(converted) ? converted : normalizeTextValue(htmlToPlainText(raw),
|
|
5031
|
+
var safeTextValue = (raw, options2) => {
|
|
5032
|
+
const converted = normalizeTextValue(raw, options2);
|
|
5033
|
+
return checkForHTML(converted) ? converted : normalizeTextValue(htmlToPlainText(raw), options2);
|
|
5016
5034
|
};
|
|
5017
5035
|
var headlineText = (raw) => {
|
|
5018
5036
|
const doc = safeTextValue(raw, AS_DOC);
|
|
@@ -5496,11 +5514,11 @@ var validateGifts = async (input, ctx) => {
|
|
|
5496
5514
|
const [remove, adjust] = await Promise.all([validateGwpGifts(input, ctx), validateSelectableGifts(input, ctx)]);
|
|
5497
5515
|
const removed = new Set(remove);
|
|
5498
5516
|
const targets = /* @__PURE__ */ new Map();
|
|
5499
|
-
for (const { lineId, quantity } of adjust) {
|
|
5517
|
+
for (const { lineId, quantity: quantity2 } of adjust) {
|
|
5500
5518
|
if (removed.has(lineId)) continue;
|
|
5501
|
-
targets.set(lineId, Math.min(
|
|
5519
|
+
targets.set(lineId, Math.min(quantity2, targets.get(lineId) ?? quantity2));
|
|
5502
5520
|
}
|
|
5503
|
-
return { adjust: [...targets].map(([lineId,
|
|
5521
|
+
return { adjust: [...targets].map(([lineId, quantity2]) => ({ lineId, quantity: quantity2 })), remove: [...removed] };
|
|
5504
5522
|
};
|
|
5505
5523
|
|
|
5506
5524
|
// src/server/normalizePostPurchaseProduct.ts
|
|
@@ -5832,14 +5850,14 @@ var SourceAdjustment = import_zod47.z.object({
|
|
|
5832
5850
|
type: import_zod47.z.enum(["percentage", "fixed_amount", "amount", "price", "none", "fixed"])
|
|
5833
5851
|
});
|
|
5834
5852
|
var readPostPurchasePlanAdjustment = (raw) => {
|
|
5835
|
-
const
|
|
5836
|
-
if (
|
|
5837
|
-
if (
|
|
5853
|
+
const source2 = SourceAdjustment.parse(raw);
|
|
5854
|
+
if (source2.type === "none" || source2.type === "fixed") {
|
|
5855
|
+
if (source2.amount !== 0) throw new Error("Unsupported plan adjustment");
|
|
5838
5856
|
return void 0;
|
|
5839
5857
|
}
|
|
5840
5858
|
const adjustment = PostPurchasePlanAdjustment.parse({
|
|
5841
|
-
amount:
|
|
5842
|
-
type:
|
|
5859
|
+
amount: source2.amount,
|
|
5860
|
+
type: source2.type === "amount" ? "fixed_amount" : source2.type
|
|
5843
5861
|
});
|
|
5844
5862
|
return adjustment.amount === 0 && adjustment.type !== "price" ? void 0 : adjustment;
|
|
5845
5863
|
};
|
|
@@ -5916,12 +5934,12 @@ var projectPostPurchasePlanCatalog = (normalized, report) => {
|
|
|
5916
5934
|
const { data } = normalized;
|
|
5917
5935
|
if (data.length !== 1 || data[0].variants.length !== 1) throw new Error("Ambiguous product");
|
|
5918
5936
|
const product = data[0];
|
|
5919
|
-
const
|
|
5920
|
-
if (
|
|
5937
|
+
const variant2 = product.variants[0];
|
|
5938
|
+
if (variant2.productId !== product.id) throw new Error("Foreign variant");
|
|
5921
5939
|
const groups = product.sellingPlanGroups;
|
|
5922
5940
|
const required = groups.map((group) => group.requiresSellingPlan);
|
|
5923
5941
|
if (required.some((flag) => flag !== required[0])) throw new Error("Conflicting requirement");
|
|
5924
|
-
const plans = typeof groups[0]?.id === "number" ? readPostPurchaseLegacyPlans(groups[0],
|
|
5942
|
+
const plans = typeof groups[0]?.id === "number" ? readPostPurchaseLegacyPlans(groups[0], variant2.id) : readPostPurchaseModernPlans(groups, variant2.sellingPlanAllocations);
|
|
5925
5943
|
const unique = /* @__PURE__ */ new Map();
|
|
5926
5944
|
for (const plan of plans) {
|
|
5927
5945
|
const previous = unique.get(plan.id);
|
|
@@ -5932,7 +5950,7 @@ var projectPostPurchasePlanCatalog = (normalized, report) => {
|
|
|
5932
5950
|
plans: [...unique.values()],
|
|
5933
5951
|
productId: product.id,
|
|
5934
5952
|
requiresSellingPlan: required[0] ?? false,
|
|
5935
|
-
variantId:
|
|
5953
|
+
variantId: variant2.id
|
|
5936
5954
|
});
|
|
5937
5955
|
} catch {
|
|
5938
5956
|
report?.({ detail: "Unreadable post-purchase plan catalog", kind: "product" });
|
|
@@ -5969,14 +5987,10 @@ var PostPurchasePrimaryImageSource = import_zod51.z.string().default(
|
|
|
5969
5987
|
"https://cdn.shopify.com/shopifycloud/shopify/assets/no-image-2048-5e88c1b20e087fb7bbe9a3771824e743c244f437e4f8ba93bbf7b11b53f7824c.gif"
|
|
5970
5988
|
);
|
|
5971
5989
|
var PostPurchaseProductDisplay = import_zod51.z.object({
|
|
5990
|
+
descriptionDocument: TiptapDocument.optional(),
|
|
5972
5991
|
discountedFrom: PostPurchaseSettings.shape.discountedFrom,
|
|
5973
5992
|
gallery: PostPurchaseProductGallery.optional(),
|
|
5974
|
-
language: language.pick({
|
|
5975
|
-
description: true,
|
|
5976
|
-
descriptionEnabled: true,
|
|
5977
|
-
descriptionRte: true,
|
|
5978
|
-
descriptionSpacing: true
|
|
5979
|
-
}),
|
|
5993
|
+
language: language.pick({ description: true, descriptionEnabled: true }),
|
|
5980
5994
|
primaryImage: import_zod51.z.object({ description: import_zod51.z.string(), source: import_zod51.z.string() }),
|
|
5981
5995
|
productOptions: PostPurchaseSettings.shape.productOptions.pick({
|
|
5982
5996
|
showDeclineAll: true,
|
|
@@ -6072,20 +6086,20 @@ var PostPurchaseSubscriptionSettings = subscription.extend({
|
|
|
6072
6086
|
});
|
|
6073
6087
|
|
|
6074
6088
|
// src/server/postPurchaseVariantAvailable.ts
|
|
6075
|
-
var postPurchaseVariantAvailable = (
|
|
6089
|
+
var postPurchaseVariantAvailable = (variant2) => !(variant2.inventoryManagement && variant2.inventoryPolicy === "deny" && variant2.inventoryQuantity <= 0);
|
|
6076
6090
|
|
|
6077
6091
|
// src/server/postPurchaseSubscriptionEligibility.ts
|
|
6078
|
-
var subscriptionUnavailable = (normalized, plan, allowCollection,
|
|
6092
|
+
var subscriptionUnavailable = (normalized, plan, allowCollection, quantity2) => {
|
|
6079
6093
|
const { data, effective, original } = normalized;
|
|
6080
6094
|
const unavailable = "An eligible subscription plan with supported shipping and discount is required";
|
|
6081
6095
|
if (data.length !== 1 || data[0].variants.length !== 1) return unavailable;
|
|
6082
6096
|
if (effective.productType === "one-time" || [original, effective].some(
|
|
6083
|
-
(config) => !allowCollection && config.productLimit !== 1 || config.upgradeToSubscription.allow || !
|
|
6097
|
+
(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
6098
|
))
|
|
6085
6099
|
return unavailable;
|
|
6086
6100
|
const product = data[0];
|
|
6087
|
-
const
|
|
6088
|
-
if (product.productGroupVariants.length || !postPurchaseVariantAvailable(
|
|
6101
|
+
const variant2 = product.variants[0];
|
|
6102
|
+
if (product.productGroupVariants.length || !postPurchaseVariantAvailable(variant2) || variant2.productId !== product.id)
|
|
6089
6103
|
return unavailable;
|
|
6090
6104
|
const terms = [original, effective].map(
|
|
6091
6105
|
(config) => PostPurchaseSubscriptionSettings.safeParse(config.subscription)
|
|
@@ -6094,14 +6108,14 @@ var subscriptionUnavailable = (normalized, plan, allowCollection, quantity) => {
|
|
|
6094
6108
|
};
|
|
6095
6109
|
|
|
6096
6110
|
// src/server/postPurchaseProductDisplay.ts
|
|
6097
|
-
var
|
|
6111
|
+
var import_zod56 = require("zod");
|
|
6098
6112
|
|
|
6099
6113
|
// src/server/postPurchasePrimaryImage.ts
|
|
6100
6114
|
var postPurchasePrimaryImage = (product) => {
|
|
6101
6115
|
const variantImageId = product.variants[0].imageId;
|
|
6102
6116
|
const selectedImage = variantImageId ? product.images?.find((image) => image.id === variantImageId) : void 0;
|
|
6103
|
-
const
|
|
6104
|
-
return { description: product.title, source: sizeImageSource(
|
|
6117
|
+
const source2 = PostPurchasePrimaryImageSource.parse((selectedImage ?? product.image)?.src || void 0);
|
|
6118
|
+
return { description: product.title, source: sizeImageSource(source2, "800x800") };
|
|
6105
6119
|
};
|
|
6106
6120
|
|
|
6107
6121
|
// src/server/postPurchaseProductGallery.ts
|
|
@@ -6115,9 +6129,67 @@ var postPurchaseProductGallery = (product, limit) => ({
|
|
|
6115
6129
|
selectedImageId: product.images?.find((image) => image.id === product.variants[0].imageId)?.id
|
|
6116
6130
|
});
|
|
6117
6131
|
|
|
6132
|
+
// src/transforms/postPurchase/convertDescriptionRte.ts
|
|
6133
|
+
var import_zod55 = require("zod");
|
|
6134
|
+
var alignments = { center: "center", left: "start", right: "end" };
|
|
6135
|
+
var colors = ["critical", "subdued", "success", "warning"];
|
|
6136
|
+
var sizes2 = ["extraSmall", "small", "medium", "large", "extraLarge"];
|
|
6137
|
+
var spacings2 = {
|
|
6138
|
+
default: "base",
|
|
6139
|
+
loose: "loose",
|
|
6140
|
+
none: "none",
|
|
6141
|
+
tight: "tight",
|
|
6142
|
+
xloose: "extraLoose",
|
|
6143
|
+
xtight: "extraTight"
|
|
6144
|
+
};
|
|
6145
|
+
var Block = import_zod55.z.object({
|
|
6146
|
+
attrs: import_zod55.z.object({ alignment: import_zod55.z.enum(["left", "center", "right"]).optional().catch(void 0) }).catch({}),
|
|
6147
|
+
content: import_zod55.z.array(import_zod55.z.unknown()).catch([]),
|
|
6148
|
+
type: import_zod55.z.literal("ShopifyTextBlock")
|
|
6149
|
+
});
|
|
6150
|
+
var Run = import_zod55.z.object({ marks: import_zod55.z.array(import_zod55.z.unknown()).catch([]), text: import_zod55.z.string().min(1), type: import_zod55.z.literal("text") });
|
|
6151
|
+
var Inline = import_zod55.z.object({
|
|
6152
|
+
attrs: import_zod55.z.object({
|
|
6153
|
+
color: import_zod55.z.enum(colors).optional().catch(void 0),
|
|
6154
|
+
emphasis: import_zod55.z.array(import_zod55.z.unknown()).catch([]),
|
|
6155
|
+
size: import_zod55.z.enum(sizes2).optional().catch(void 0)
|
|
6156
|
+
}),
|
|
6157
|
+
type: import_zod55.z.literal("ShopifyTextInline")
|
|
6158
|
+
});
|
|
6159
|
+
var marks = (raw) => {
|
|
6160
|
+
const found = raw.map((mark) => Inline.safeParse(mark)).find(({ success }) => success)?.data;
|
|
6161
|
+
if (!found) return [];
|
|
6162
|
+
const { color = "base", emphasis, size = "base" } = found.attrs;
|
|
6163
|
+
return [
|
|
6164
|
+
...emphasis.includes("bold") ? [{ type: "bold" }] : [],
|
|
6165
|
+
...emphasis.includes("strikethrough") ? [{ type: "strike" }] : [],
|
|
6166
|
+
{ attrs: { color, fontSize: size }, type: "textStyle" }
|
|
6167
|
+
];
|
|
6168
|
+
};
|
|
6169
|
+
var convertDescriptionRte = (rte, spacing) => TiptapDocument.parse({
|
|
6170
|
+
attrs: { blockSpacing: spacings2[spacing ?? "none"] },
|
|
6171
|
+
content: rte.content.flatMap((node) => {
|
|
6172
|
+
const block = Block.safeParse(node);
|
|
6173
|
+
if (!block.success) return [];
|
|
6174
|
+
const { alignment } = block.data.attrs;
|
|
6175
|
+
return [
|
|
6176
|
+
{
|
|
6177
|
+
attrs: { textAlign: alignment ? alignments[alignment] : "start" },
|
|
6178
|
+
content: block.data.content.flatMap((inline) => {
|
|
6179
|
+
const run = Run.safeParse(inline);
|
|
6180
|
+
return run.success ? [{ marks: marks(run.data.marks), text: run.data.text }] : [];
|
|
6181
|
+
}),
|
|
6182
|
+
type: "paragraph"
|
|
6183
|
+
}
|
|
6184
|
+
];
|
|
6185
|
+
}),
|
|
6186
|
+
type: "doc"
|
|
6187
|
+
});
|
|
6188
|
+
|
|
6118
6189
|
// src/server/postPurchaseProductDisplay.ts
|
|
6119
|
-
var ResponseLanguage =
|
|
6190
|
+
var ResponseLanguage = import_zod56.z.object({ description: PostPurchaseProductDisplay.shape.responseDescription }).default({ description: "" });
|
|
6120
6191
|
var projectPostPurchaseProductDisplay = (effective, metadata, product) => PostPurchaseProductDisplay.parse({
|
|
6192
|
+
descriptionDocument: effective.language.descriptionRte && convertDescriptionRte(effective.language.descriptionRte, effective.language.descriptionSpacing),
|
|
6121
6193
|
discountedFrom: effective.discountedFrom,
|
|
6122
6194
|
gallery: postPurchaseProductGallery(product, effective.subImages),
|
|
6123
6195
|
language: effective.language,
|
|
@@ -6130,26 +6202,26 @@ var projectPostPurchaseProductDisplay = (effective, metadata, product) => PostPu
|
|
|
6130
6202
|
// src/server/projectPostPurchaseProduct.ts
|
|
6131
6203
|
var projectPostPurchaseProduct = ({ data, effective, metadata, original }, selectedQuantity) => {
|
|
6132
6204
|
const product = data[0];
|
|
6133
|
-
const
|
|
6205
|
+
const variant2 = product.variants[0];
|
|
6134
6206
|
return {
|
|
6135
6207
|
display: projectPostPurchaseProductDisplay(effective, metadata, product),
|
|
6136
6208
|
labels: effective.language.global,
|
|
6137
|
-
product: { ...product, variant },
|
|
6209
|
+
product: { ...product, variant: variant2 },
|
|
6138
6210
|
selection: {
|
|
6139
6211
|
productId: product.id,
|
|
6140
6212
|
quantity: selectedQuantity?.quantity ?? product.metadata?.productQuantity ?? (original.quantityInputs.enabled ? original.quantityInputs.defaultQuantity : 1),
|
|
6141
|
-
variantId:
|
|
6213
|
+
variantId: variant2.id
|
|
6142
6214
|
}
|
|
6143
6215
|
};
|
|
6144
6216
|
};
|
|
6145
6217
|
|
|
6146
6218
|
// src/server/prepareNormalizedSubscription.ts
|
|
6147
|
-
var prepareNormalizedSubscription = (normalized, report, plan,
|
|
6219
|
+
var prepareNormalizedSubscription = (normalized, report, plan, quantity2, allowCollection = false) => {
|
|
6148
6220
|
if (!plan) return { reason: "Subscription plan is unavailable", status: "unsupported" };
|
|
6149
|
-
const reason = subscriptionUnavailable(normalized, plan, allowCollection,
|
|
6221
|
+
const reason = subscriptionUnavailable(normalized, plan, allowCollection, quantity2);
|
|
6150
6222
|
if (reason) return { reason, status: "unsupported" };
|
|
6151
6223
|
const { effective } = normalized;
|
|
6152
|
-
const projected = projectPostPurchaseProduct(normalized,
|
|
6224
|
+
const projected = projectPostPurchaseProduct(normalized, quantity2);
|
|
6153
6225
|
const { discount, shipping } = PostPurchaseSubscriptionSettings.parse(effective.subscription);
|
|
6154
6226
|
const shippingPrice = shipping.type === "free" ? 0 : shipping.amount;
|
|
6155
6227
|
return PreparedPostPurchaseSubscription.parse({
|
|
@@ -6186,6 +6258,855 @@ var preparePostPurchaseSubscription = (settings, response, report) => {
|
|
|
6186
6258
|
);
|
|
6187
6259
|
};
|
|
6188
6260
|
|
|
6261
|
+
// src/server/postPurchaseProductEligibility.ts
|
|
6262
|
+
var oneTimeUnavailable = (normalized, allowCollection, quantity2) => {
|
|
6263
|
+
const { data, effective, original } = normalized;
|
|
6264
|
+
if (data.length !== 1 || data[0].variants.length !== 1) return "Only one fixed product and variant are supported";
|
|
6265
|
+
if (effective.productType === "subscription" || [original, effective].some(
|
|
6266
|
+
(config) => !allowCollection && config.productLimit !== 1 || config.upgradeToSubscription.allow || !quantity2 && config.quantityInputs.enabled && (config.quantityInputs.minValue !== config.quantityInputs.maxValue || config.quantityInputs.defaultQuantity !== config.quantityInputs.minValue)
|
|
6267
|
+
))
|
|
6268
|
+
return "Only fixed one-time configuration is supported";
|
|
6269
|
+
const product = data[0];
|
|
6270
|
+
const variant2 = product.variants[0];
|
|
6271
|
+
if (product.productGroupVariants.length || product.sellingPlanGroups?.some((group) => group.requiresSellingPlan) || !postPurchaseVariantAvailable(variant2))
|
|
6272
|
+
return "An available one-time variant without product groups is required";
|
|
6273
|
+
if (variant2.productId !== product.id) throw new Error("Product variant identity mismatch");
|
|
6274
|
+
};
|
|
6275
|
+
|
|
6276
|
+
// src/server/preparePostPurchaseProduct.ts
|
|
6277
|
+
var prepareNormalizedProduct = (normalized, report, quantity2, allowCollection = false) => {
|
|
6278
|
+
const reason = oneTimeUnavailable(normalized, allowCollection, quantity2);
|
|
6279
|
+
if (reason) return { reason, status: "unsupported" };
|
|
6280
|
+
const { effective } = normalized;
|
|
6281
|
+
return PreparedPostPurchaseProduct.parse({
|
|
6282
|
+
...projectPostPurchaseProduct(normalized, quantity2),
|
|
6283
|
+
status: "prepared",
|
|
6284
|
+
terms: {
|
|
6285
|
+
discount: { ...effective.discount, title: effective.language.global.save },
|
|
6286
|
+
shipping: effective.shipping
|
|
6287
|
+
}
|
|
6288
|
+
});
|
|
6289
|
+
};
|
|
6290
|
+
var preparePostPurchaseProduct = (settings, response, report) => prepareNormalizedProduct(normalizePostPurchaseProduct(settings, response), report);
|
|
6291
|
+
|
|
6292
|
+
// src/schema/postPurchaseProductView.ts
|
|
6293
|
+
var import_zod60 = require("zod");
|
|
6294
|
+
|
|
6295
|
+
// src/schema/postPurchaseChoice.ts
|
|
6296
|
+
var import_zod57 = require("zod");
|
|
6297
|
+
var PostPurchaseChoice = import_zod57.z.discriminatedUnion("mode", [
|
|
6298
|
+
import_zod57.z.object({ mode: import_zod57.z.literal("one-time") }).strict(),
|
|
6299
|
+
import_zod57.z.object({ mode: import_zod57.z.literal("subscription"), sellingPlanId: PostPurchasePlanOption.shape.id }).strict()
|
|
6300
|
+
]);
|
|
6301
|
+
var PostPurchaseOptions = import_zod57.z.object({
|
|
6302
|
+
defaultChoice: PostPurchaseChoice,
|
|
6303
|
+
modes: import_zod57.z.array(import_zod57.z.enum(["one-time", "subscription"])).min(1).max(2),
|
|
6304
|
+
selector: PostPurchaseSettings.shape.productTypeSelector
|
|
6305
|
+
});
|
|
6306
|
+
|
|
6307
|
+
// src/schema/postPurchaseGroupCatalog.ts
|
|
6308
|
+
var import_zod59 = require("zod");
|
|
6309
|
+
|
|
6310
|
+
// src/schema/postPurchaseVariantCatalog.ts
|
|
6311
|
+
var import_zod58 = require("zod");
|
|
6312
|
+
var PostPurchaseVariantSelector = import_zod58.z.object({ variantId: PostPurchaseVariantId }).strict();
|
|
6313
|
+
var PostPurchaseVariantOption = OfferProduct.shape.options.element.extend({
|
|
6314
|
+
id: import_zod58.z.number().int().positive(),
|
|
6315
|
+
position: import_zod58.z.number().int().min(1).max(3)
|
|
6316
|
+
});
|
|
6317
|
+
var PostPurchaseVariantValues = OfferProduct.shape.variants.element.pick({
|
|
6318
|
+
option1: true,
|
|
6319
|
+
option2: true,
|
|
6320
|
+
option3: true
|
|
6321
|
+
});
|
|
6322
|
+
var PostPurchaseVariantCatalog = import_zod58.z.object({
|
|
6323
|
+
displayMode: PostPurchaseSettings.shape.productOptions.shape.variantSelectorDisplayMode,
|
|
6324
|
+
options: import_zod58.z.array(PostPurchaseVariantOption),
|
|
6325
|
+
productId: PostPurchaseProductId,
|
|
6326
|
+
showSelectors: PostPurchaseSettings.shape.productOptions.shape.showVariantSelectors,
|
|
6327
|
+
variants: import_zod58.z.array(
|
|
6328
|
+
PostPurchaseVariantValues.partial().extend({
|
|
6329
|
+
available: import_zod58.z.boolean(),
|
|
6330
|
+
id: PostPurchaseVariantId,
|
|
6331
|
+
imageId: import_zod58.z.number().int().nonnegative().nullish(),
|
|
6332
|
+
title: OfferProduct.shape.variants.element.shape.title
|
|
6333
|
+
})
|
|
6334
|
+
)
|
|
6335
|
+
});
|
|
6336
|
+
|
|
6337
|
+
// src/schema/postPurchaseGroupCatalog.ts
|
|
6338
|
+
var productId = PreparedPostPurchaseProduct.shape.selection.shape.productId;
|
|
6339
|
+
var source = PostPurchaseProductSource.shape.data.element;
|
|
6340
|
+
var PostPurchaseGroupDescription = source.pick({ description: true, id: true, image: true, images: true, title: true }).extend({
|
|
6341
|
+
description: source.shape.description.default(null),
|
|
6342
|
+
image: source.shape.image.default(null),
|
|
6343
|
+
options: PostPurchaseVariantCatalog.shape.options.default([])
|
|
6344
|
+
});
|
|
6345
|
+
var PostPurchaseGroupCatalog = import_zod59.z.object({
|
|
6346
|
+
memberProductId: productId,
|
|
6347
|
+
options: import_zod59.z.array(import_zod59.z.object({ productId, title: import_zod59.z.string(), variantCatalog: PostPurchaseVariantCatalog }))
|
|
6348
|
+
});
|
|
6349
|
+
var PostPurchaseGroupSelection = import_zod59.z.object({
|
|
6350
|
+
memberProductId: productId,
|
|
6351
|
+
productId
|
|
6352
|
+
});
|
|
6353
|
+
|
|
6354
|
+
// src/schema/postPurchaseProductView.ts
|
|
6355
|
+
var PostPurchaseProductView = import_zod60.z.union([
|
|
6356
|
+
import_zod60.z.object({
|
|
6357
|
+
groupCatalog: PostPurchaseGroupCatalog.optional(),
|
|
6358
|
+
initialVariant: PostPurchaseVariantSelector.optional(),
|
|
6359
|
+
planCatalog: PostPurchasePlanCatalog.nullable().optional(),
|
|
6360
|
+
preparation: PreparedPostPurchaseProduct.extend({
|
|
6361
|
+
display: PreparedPostPurchaseProduct.shape.display.extend({ description: import_zod60.z.string().nullable() }).refine(
|
|
6362
|
+
({ description, descriptionDocument }) => description === null === (descriptionDocument !== void 0),
|
|
6363
|
+
"Exactly one of the plain and rich descriptions is shown"
|
|
6364
|
+
)
|
|
6365
|
+
}),
|
|
6366
|
+
purchaseOptions: PostPurchaseOptions.optional(),
|
|
6367
|
+
sections: CABRootSection,
|
|
6368
|
+
variantCatalog: PostPurchaseVariantCatalog.optional()
|
|
6369
|
+
}),
|
|
6370
|
+
import_zod60.z.object({
|
|
6371
|
+
groupCatalog: PostPurchaseGroupCatalog.optional(),
|
|
6372
|
+
initialVariant: PostPurchaseVariantSelector.optional(),
|
|
6373
|
+
planCatalog: PostPurchasePlanCatalog.nullable().optional(),
|
|
6374
|
+
preparation: PostPurchasePreparation.options[1],
|
|
6375
|
+
purchaseOptions: PostPurchaseOptions.optional(),
|
|
6376
|
+
sections: import_zod60.z.null(),
|
|
6377
|
+
variantCatalog: PostPurchaseVariantCatalog.optional()
|
|
6378
|
+
})
|
|
6379
|
+
]);
|
|
6380
|
+
|
|
6381
|
+
// src/server/postPurchaseOfferCopy.ts
|
|
6382
|
+
var import_zod61 = require("zod");
|
|
6383
|
+
var Copy = import_zod61.z.object({
|
|
6384
|
+
superTitle: CalloutBannerBlock.shape.settings.shape.superTitle.unwrap().optional().catch(void 0),
|
|
6385
|
+
title: CalloutBannerBlock.shape.settings.shape.title.unwrap().optional().catch(void 0)
|
|
6386
|
+
});
|
|
6387
|
+
var Callout = import_zod61.z.object({ settings: import_zod61.z.record(import_zod61.z.string(), import_zod61.z.unknown()), type: import_zod61.z.literal("callout_banner") });
|
|
6388
|
+
var postPurchaseOfferCopy = (blocks, metadata) => {
|
|
6389
|
+
const copy = Copy.safeParse(metadata.widget.language);
|
|
6390
|
+
if (!blocks || !copy.success) return blocks;
|
|
6391
|
+
const first = blocks.findIndex((block) => Callout.pick({ type: true }).safeParse(block).success);
|
|
6392
|
+
return blocks.map((block, index) => {
|
|
6393
|
+
if (index !== first) return block;
|
|
6394
|
+
const callout = Callout.passthrough().safeParse(block);
|
|
6395
|
+
if (!callout.success) return block;
|
|
6396
|
+
return {
|
|
6397
|
+
...callout.data,
|
|
6398
|
+
settings: {
|
|
6399
|
+
...callout.data.settings,
|
|
6400
|
+
...copy.data.title && { title: copy.data.title },
|
|
6401
|
+
...copy.data.superTitle && { superTitle: copy.data.superTitle }
|
|
6402
|
+
}
|
|
6403
|
+
};
|
|
6404
|
+
});
|
|
6405
|
+
};
|
|
6406
|
+
|
|
6407
|
+
// src/server/selectPostPurchaseChoice.ts
|
|
6408
|
+
var selectPostPurchaseChoice = (normalized, projected, requested, allowCollection, quantity2) => {
|
|
6409
|
+
const { data, effective } = normalized;
|
|
6410
|
+
const modes = [];
|
|
6411
|
+
const catalog = projected && projected.productId === data[0]?.id && projected.variantId === data[0].variants[0]?.id ? projected : null;
|
|
6412
|
+
const firstPlan = catalog?.plans[0];
|
|
6413
|
+
const oneTimeReason = oneTimeUnavailable(normalized, allowCollection, quantity2);
|
|
6414
|
+
const subscriptionReason = subscriptionUnavailable(normalized, firstPlan, allowCollection, quantity2);
|
|
6415
|
+
if (!oneTimeReason) modes.push("one-time");
|
|
6416
|
+
if (!subscriptionReason) modes.push("subscription");
|
|
6417
|
+
if (oneTimeReason && subscriptionReason)
|
|
6418
|
+
return {
|
|
6419
|
+
choice: void 0,
|
|
6420
|
+
options: void 0,
|
|
6421
|
+
plan: void 0,
|
|
6422
|
+
reason: effective.productType === "one-time" ? oneTimeReason : subscriptionReason
|
|
6423
|
+
};
|
|
6424
|
+
const defaultChoice = firstPlan && modes.includes("subscription") && (modes[0] === "subscription" || effective.subscriptionIsDefault) ? { mode: "subscription", sellingPlanId: firstPlan.id } : { mode: "one-time" };
|
|
6425
|
+
const options2 = PostPurchaseOptions.parse({ defaultChoice, modes, selector: effective.productTypeSelector });
|
|
6426
|
+
const choice = requested ?? defaultChoice;
|
|
6427
|
+
const plan = choice.mode === "subscription" ? catalog?.plans.find(({ id }) => id === choice.sellingPlanId) : void 0;
|
|
6428
|
+
const bound = modes.includes(choice.mode) && (choice.mode === "one-time" || plan) ? choice : void 0;
|
|
6429
|
+
return {
|
|
6430
|
+
choice: bound,
|
|
6431
|
+
options: options2,
|
|
6432
|
+
plan: bound ? plan : void 0,
|
|
6433
|
+
reason: bound ? void 0 : "Requested purchase choice is unavailable"
|
|
6434
|
+
};
|
|
6435
|
+
};
|
|
6436
|
+
|
|
6437
|
+
// src/server/preparePostPurchaseView.ts
|
|
6438
|
+
var resolveDescription = ({ descriptionDocument, ...display }, productDescription) => {
|
|
6439
|
+
const plain = display.language.descriptionEnabled && productDescription || display.responseDescription || (descriptionDocument ? null : display.language.description);
|
|
6440
|
+
return plain === null ? { ...display, description: null, descriptionDocument } : { ...display, description: plain };
|
|
6441
|
+
};
|
|
6442
|
+
var prepareNormalizedPostPurchaseView = (widgetId, normalized, report, choice, quantity2, allowCollection = false) => {
|
|
6443
|
+
const planCatalog = projectPostPurchasePlanCatalog(normalized, report);
|
|
6444
|
+
const selected = selectPostPurchaseChoice(normalized, planCatalog, choice, allowCollection, quantity2);
|
|
6445
|
+
const purchaseOptions = selected.options;
|
|
6446
|
+
const preparation = !selected.choice ? { reason: selected.reason, status: "unsupported" } : selected.choice.mode === "subscription" ? prepareNormalizedSubscription(normalized, report, selected.plan, quantity2, allowCollection) : prepareNormalizedProduct(normalized, report, quantity2, allowCollection);
|
|
6447
|
+
const unsupported = (reason) => ({
|
|
6448
|
+
planCatalog,
|
|
6449
|
+
preparation: { reason, status: "unsupported" },
|
|
6450
|
+
purchaseOptions,
|
|
6451
|
+
sections: null
|
|
6452
|
+
});
|
|
6453
|
+
if (preparation.status === "unsupported") return { planCatalog, preparation, purchaseOptions, sections: null };
|
|
6454
|
+
if (!normalized.effective.blocks?.length) return unsupported("One fixed product information block is required");
|
|
6455
|
+
const sections = convertMessagePreview(
|
|
6456
|
+
widgetId,
|
|
6457
|
+
{
|
|
6458
|
+
blocks: postPurchaseOfferCopy(normalized.effective.blocks, normalized.metadata),
|
|
6459
|
+
type: "shopify_post_purchase_extension"
|
|
6460
|
+
},
|
|
6461
|
+
report
|
|
6462
|
+
);
|
|
6463
|
+
if (sections.sections.filter((section) => section.sectionType === "offers").length !== 1)
|
|
6464
|
+
return unsupported("One fixed product information block is required");
|
|
6465
|
+
return PostPurchaseProductView.parse({
|
|
6466
|
+
planCatalog,
|
|
6467
|
+
preparation: {
|
|
6468
|
+
...preparation,
|
|
6469
|
+
display: resolveDescription(preparation.display, preparation.product.description)
|
|
6470
|
+
},
|
|
6471
|
+
purchaseOptions,
|
|
6472
|
+
sections
|
|
6473
|
+
});
|
|
6474
|
+
};
|
|
6475
|
+
var preparePostPurchaseView = (widgetId, settings, response, report, choice) => prepareNormalizedPostPurchaseView(widgetId, normalizePostPurchaseProduct(settings, response), report, choice);
|
|
6476
|
+
|
|
6477
|
+
// src/server/preparePostPurchaseAdmissionView.ts
|
|
6478
|
+
var preparePostPurchaseAdmissionView = (widgetId, settings, response, report, choice) => {
|
|
6479
|
+
const normalized = normalizePostPurchaseProduct(settings, response);
|
|
6480
|
+
const view = prepareNormalizedPostPurchaseView(widgetId, normalized, report, choice);
|
|
6481
|
+
const { removePartialOrder } = PostPurchaseSettings.shape.advance.parse(normalized.effective.advance);
|
|
6482
|
+
return { removePartialOrder, view };
|
|
6483
|
+
};
|
|
6484
|
+
|
|
6485
|
+
// src/schema/postPurchaseProductCollectionView.ts
|
|
6486
|
+
var import_zod62 = require("zod");
|
|
6487
|
+
var PostPurchaseProductCollectionView = import_zod62.z.object({
|
|
6488
|
+
members: import_zod62.z.array(
|
|
6489
|
+
import_zod62.z.object({
|
|
6490
|
+
productId: PostPurchaseProductId,
|
|
6491
|
+
productIndex: import_zod62.z.number().int().nonnegative(),
|
|
6492
|
+
view: PostPurchaseProductView
|
|
6493
|
+
})
|
|
6494
|
+
)
|
|
6495
|
+
});
|
|
6496
|
+
var PostPurchaseCollectionChoice = import_zod62.z.object({
|
|
6497
|
+
choice: PostPurchaseChoice.optional(),
|
|
6498
|
+
productId: PostPurchaseProductId,
|
|
6499
|
+
variantId: PostPurchaseVariantSelector.shape.variantId.optional()
|
|
6500
|
+
}).strict();
|
|
6501
|
+
var PostPurchaseExcludedProductIds = import_zod62.z.array(PostPurchaseProductId).default([]);
|
|
6502
|
+
|
|
6503
|
+
// src/server/normalizePostPurchaseCollection.ts
|
|
6504
|
+
var import_zod63 = require("zod");
|
|
6505
|
+
var normalizePostPurchaseCollection = (settings, response, excludedProductIds) => {
|
|
6506
|
+
const normalized = normalizePostPurchaseProduct(settings, response);
|
|
6507
|
+
const limit = import_zod63.z.number().int().positive();
|
|
6508
|
+
limit.parse(normalized.original.productLimit);
|
|
6509
|
+
const prefix = normalized.data.slice(0, limit.parse(normalized.effective.productLimit));
|
|
6510
|
+
if (new Set(prefix.map(({ id }) => id)).size !== prefix.length)
|
|
6511
|
+
throw new Error("Ambiguous post-purchase collection");
|
|
6512
|
+
const excluded = new Set(PostPurchaseExcludedProductIds.parse(excludedProductIds));
|
|
6513
|
+
const members = prefix.map((product, productIndex) => ({ product, productIndex })).filter(({ product }) => !excluded.has(product.id));
|
|
6514
|
+
return { members, normalized };
|
|
6515
|
+
};
|
|
6516
|
+
|
|
6517
|
+
// src/server/postPurchaseVariantCatalog.ts
|
|
6518
|
+
var projectPostPurchaseVariantCatalog = (product, settings) => {
|
|
6519
|
+
const options2 = PostPurchaseVariantCatalog.shape.options.parse(product.options === void 0 ? [] : product.options).sort((a, b) => a.position - b.position);
|
|
6520
|
+
const variants = product.variants.map((variant2) => ({
|
|
6521
|
+
...variant2,
|
|
6522
|
+
...PostPurchaseVariantValues.partial().parse(variant2)
|
|
6523
|
+
}));
|
|
6524
|
+
const tuples = variants.map(({ option1, option2, option3 }) => [option1, option2, option3]);
|
|
6525
|
+
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(
|
|
6526
|
+
({ position, values: values2 }, index) => position !== index + 1 || new Set(values2).size !== values2.length
|
|
6527
|
+
) || product.variants.length > 1 && new Set(tuples.map((tuple) => JSON.stringify(tuple))).size !== tuples.length)
|
|
6528
|
+
throw new Error("Ambiguous post-purchase variant catalog");
|
|
6529
|
+
for (const tuple of tuples) {
|
|
6530
|
+
if (options2.some(({ position, values: values2 }) => !values2.some((value) => value === tuple[position - 1])) || tuple.some((value, index) => value != null && !options2[index]))
|
|
6531
|
+
throw new Error("Variant option tuple does not match the catalog");
|
|
6532
|
+
}
|
|
6533
|
+
return PostPurchaseVariantCatalog.parse({
|
|
6534
|
+
displayMode: settings.productOptions.variantSelectorDisplayMode,
|
|
6535
|
+
options: options2,
|
|
6536
|
+
productId: product.id,
|
|
6537
|
+
showSelectors: settings.productOptions.showVariantSelectors,
|
|
6538
|
+
variants: variants.map(({ id, imageId, option1, option2, option3, title, ...inventory }) => ({
|
|
6539
|
+
available: postPurchaseVariantAvailable(inventory),
|
|
6540
|
+
id,
|
|
6541
|
+
imageId,
|
|
6542
|
+
option1,
|
|
6543
|
+
option2,
|
|
6544
|
+
option3,
|
|
6545
|
+
title
|
|
6546
|
+
}))
|
|
6547
|
+
});
|
|
6548
|
+
};
|
|
6549
|
+
|
|
6550
|
+
// src/schema/postPurchaseQuantity.ts
|
|
6551
|
+
var import_zod64 = require("zod");
|
|
6552
|
+
var quantity = PreparedPostPurchaseProduct.shape.selection.shape.quantity;
|
|
6553
|
+
var PostPurchaseQuantityChoice = PostPurchaseCollectionChoice.extend({ quantity: quantity.optional() });
|
|
6554
|
+
var PostPurchaseQuantityPolicy = PostPurchaseSettings.shape.quantityInputs.omit({ defaultQuantity: true }).extend({
|
|
6555
|
+
initialQuantity: quantity,
|
|
6556
|
+
maxValue: quantity,
|
|
6557
|
+
minValue: import_zod64.z.literal(0).transform(() => 1).or(quantity)
|
|
6558
|
+
}).refine(({ maxValue, minValue }) => minValue <= maxValue, "Quantity bounds are reversed");
|
|
6559
|
+
|
|
6560
|
+
// src/server/readPostPurchaseQuantity.ts
|
|
6561
|
+
var PostPurchaseQuantityUnavailable = class extends Error {
|
|
6562
|
+
};
|
|
6563
|
+
var readPostPurchaseQuantity = ({
|
|
6564
|
+
data,
|
|
6565
|
+
effective,
|
|
6566
|
+
original
|
|
6567
|
+
}, selection3) => {
|
|
6568
|
+
const positive = PreparedPostPurchaseProduct.shape.selection.shape.quantity;
|
|
6569
|
+
for (const config of [original, effective]) {
|
|
6570
|
+
if (!config.quantityInputs.enabled) continue;
|
|
6571
|
+
const initialQuantity2 = positive.parse(config.quantityInputs.defaultQuantity);
|
|
6572
|
+
const policy2 = PostPurchaseQuantityPolicy.parse({ ...config.quantityInputs, initialQuantity: initialQuantity2 });
|
|
6573
|
+
if (initialQuantity2 < policy2.minValue || initialQuantity2 > policy2.maxValue)
|
|
6574
|
+
throw new Error("Configured quantity default is outside its bounds");
|
|
6575
|
+
}
|
|
6576
|
+
const initialQuantity = data[0]?.metadata?.productQuantity ?? (original.quantityInputs.enabled ? original.quantityInputs.defaultQuantity : 1);
|
|
6577
|
+
const policy = PostPurchaseQuantityPolicy.parse(
|
|
6578
|
+
effective.quantityInputs.enabled ? { ...effective.quantityInputs, initialQuantity } : { enabled: false, initialQuantity, maxValue: initialQuantity, minValue: initialQuantity }
|
|
6579
|
+
);
|
|
6580
|
+
const requested = "quantity" in selection3 ? selection3.quantity : selection3.expectedQuantity === initialQuantity ? void 0 : selection3.expectedQuantity;
|
|
6581
|
+
const quantity2 = positive.parse(requested ?? initialQuantity);
|
|
6582
|
+
if (requested !== void 0 && (policy.enabled ? quantity2 < policy.minValue || quantity2 > policy.maxValue : quantity2 !== initialQuantity))
|
|
6583
|
+
throw new PostPurchaseQuantityUnavailable("Requested quantity is unavailable");
|
|
6584
|
+
return { policy, quantity: quantity2 };
|
|
6585
|
+
};
|
|
6586
|
+
|
|
6587
|
+
// src/schema/postPurchaseVariantDefault.ts
|
|
6588
|
+
var import_zod65 = require("zod");
|
|
6589
|
+
var values = PostPurchaseVariantValues.partial().extend({
|
|
6590
|
+
option1: PostPurchaseVariantValues.shape.option1.nullish()
|
|
6591
|
+
});
|
|
6592
|
+
var variant = values.extend({
|
|
6593
|
+
id: PostPurchaseVariantId,
|
|
6594
|
+
inventoryManagement: import_zod65.z.string().nullable(),
|
|
6595
|
+
inventoryPolicy: import_zod65.z.string(),
|
|
6596
|
+
inventoryQuantity: import_zod65.z.number()
|
|
6597
|
+
});
|
|
6598
|
+
var options = import_zod65.z.array(PostPurchaseVariantOption.pick({ name: true, values: true }));
|
|
6599
|
+
var PostPurchaseVariantDefaultProduct = import_zod65.z.object({
|
|
6600
|
+
id: PostPurchaseProductId,
|
|
6601
|
+
options,
|
|
6602
|
+
selectedVariant: variant.optional(),
|
|
6603
|
+
variants: import_zod65.z.array(variant)
|
|
6604
|
+
});
|
|
6605
|
+
var PostPurchaseVariantDefaultSettings = PostPurchaseSettings.shape.productOptions.pick({
|
|
6606
|
+
hideOutOfStockVariants: true,
|
|
6607
|
+
matchVariant: true
|
|
6608
|
+
});
|
|
6609
|
+
var PostPurchaseOrderAttributes = import_zod65.z.record(import_zod65.z.string(), import_zod65.z.array(import_zod65.z.string())).default({});
|
|
6610
|
+
var PostPurchaseOriginalVariants = import_zod65.z.array(
|
|
6611
|
+
import_zod65.z.object({ productId: PostPurchaseProductId, variantId: PostPurchaseVariantId })
|
|
6612
|
+
);
|
|
6613
|
+
var PostPurchaseAttributeProducts = import_zod65.z.array(
|
|
6614
|
+
import_zod65.z.object({ id: PostPurchaseProductId, options, variants: import_zod65.z.array(values.extend({ id: PostPurchaseVariantId })) })
|
|
6615
|
+
);
|
|
6616
|
+
|
|
6617
|
+
// src/schema/postPurchaseVariantDefaultContext.ts
|
|
6618
|
+
var import_zod66 = require("zod");
|
|
6619
|
+
var PostPurchaseVariantDefaultContext = import_zod66.z.object({
|
|
6620
|
+
enrichedLineItems: import_zod66.z.unknown().optional(),
|
|
6621
|
+
originalVariants: PostPurchaseOriginalVariants
|
|
6622
|
+
});
|
|
6623
|
+
|
|
6624
|
+
// src/server/createPostPurchaseOrderAttributes.ts
|
|
6625
|
+
var createPostPurchaseOrderAttributes = (original, enriched) => {
|
|
6626
|
+
const products = PostPurchaseAttributeProducts.parse(enriched);
|
|
6627
|
+
const attributes = {};
|
|
6628
|
+
for (const item of PostPurchaseOriginalVariants.parse(original)) {
|
|
6629
|
+
const product = products.find(({ id }) => id === item.productId);
|
|
6630
|
+
const variant2 = product?.variants.find(({ id }) => id === item.variantId);
|
|
6631
|
+
if (!variant2 || !product) continue;
|
|
6632
|
+
["option1", "option2", "option3"].forEach((key, index) => {
|
|
6633
|
+
const value = variant2[key];
|
|
6634
|
+
const option = product.options[index];
|
|
6635
|
+
if (!value || !option) return;
|
|
6636
|
+
const values2 = attributes[option.name] ?? [];
|
|
6637
|
+
if (!values2.includes(value)) attributes[option.name] = [...values2, value];
|
|
6638
|
+
});
|
|
6639
|
+
}
|
|
6640
|
+
return attributes;
|
|
6641
|
+
};
|
|
6642
|
+
|
|
6643
|
+
// src/server/matchPostPurchaseVariantDefault.ts
|
|
6644
|
+
var matchPostPurchaseVariantDefault = (product, attributes, filterOutOfStock) => {
|
|
6645
|
+
const keys = ["option1", "option2", "option3"];
|
|
6646
|
+
const values2 = keys.map((_, index) => {
|
|
6647
|
+
const option = product.options[index];
|
|
6648
|
+
return option ? option.values.filter((value) => attributes[option.name]?.includes(value)) : [];
|
|
6649
|
+
});
|
|
6650
|
+
if (!values2.some((entries) => entries.length)) return;
|
|
6651
|
+
let bestRank = 1;
|
|
6652
|
+
let best;
|
|
6653
|
+
for (const variant2 of product.variants) {
|
|
6654
|
+
if (filterOutOfStock && variant2.inventoryPolicy !== "continue" && variant2.inventoryQuantity <= 0) continue;
|
|
6655
|
+
const rank = keys.reduce((total, key, index) => {
|
|
6656
|
+
const value = variant2[key];
|
|
6657
|
+
return total + Number(!value && !values2[index].length || !!value && values2[index].includes(value));
|
|
6658
|
+
}, 0);
|
|
6659
|
+
if (rank > bestRank) {
|
|
6660
|
+
best = variant2;
|
|
6661
|
+
bestRank = rank;
|
|
6662
|
+
}
|
|
6663
|
+
}
|
|
6664
|
+
return best;
|
|
6665
|
+
};
|
|
6666
|
+
|
|
6667
|
+
// src/server/resolvePostPurchaseVariantDefault.ts
|
|
6668
|
+
var resolvePostPurchaseVariantDefault = (source2, settings, originalAttributes) => {
|
|
6669
|
+
const product = PostPurchaseVariantDefaultProduct.parse(source2);
|
|
6670
|
+
const policy = PostPurchaseVariantDefaultSettings.parse(settings);
|
|
6671
|
+
const attributes = PostPurchaseOrderAttributes.parse(originalAttributes);
|
|
6672
|
+
let selected = source2.selectedVariant && source2.selectedVariant === source2.variants[0] ? product.variants[0] : product.selectedVariant;
|
|
6673
|
+
if (!selected && policy.matchVariant)
|
|
6674
|
+
selected = matchPostPurchaseVariantDefault(product, attributes, policy.hideOutOfStockVariants);
|
|
6675
|
+
selected ?? (selected = product.variants[0]);
|
|
6676
|
+
if (!selected || selected === product.variants[0])
|
|
6677
|
+
selected = product.variants.find(postPurchaseVariantAvailable) ?? selected;
|
|
6678
|
+
return selected?.id ?? null;
|
|
6679
|
+
};
|
|
6680
|
+
|
|
6681
|
+
// src/server/resolvePostPurchaseMemberDefault.ts
|
|
6682
|
+
var resolvePostPurchaseMemberDefault = (product, original, context) => {
|
|
6683
|
+
const originals = PostPurchaseVariantDefaultContext.parse(context);
|
|
6684
|
+
if (product.variants.length < 2 && product.selectedVariant === void 0) return product.variants[0]?.id ?? null;
|
|
6685
|
+
const source2 = PostPurchaseVariantDefaultProduct.parse(product);
|
|
6686
|
+
const settings = PostPurchaseVariantDefaultSettings.parse(original.productOptions);
|
|
6687
|
+
const attributes = settings.matchVariant && !source2.selectedVariant && source2.options.some(({ values: values2 }) => values2.length > 0) && originals.originalVariants.length > 0 && originals.enrichedLineItems != null ? createPostPurchaseOrderAttributes(
|
|
6688
|
+
originals.originalVariants,
|
|
6689
|
+
PostPurchaseAttributeProducts.parse(deepCamelCase(originals.enrichedLineItems))
|
|
6690
|
+
) : void 0;
|
|
6691
|
+
return resolvePostPurchaseVariantDefault(source2, settings, attributes);
|
|
6692
|
+
};
|
|
6693
|
+
|
|
6694
|
+
// src/server/preparePostPurchaseMemberView.ts
|
|
6695
|
+
var prepareMember = (widgetId, settings, response, requested, report, excludedProductIds, requestedQuantity, defaults) => {
|
|
6696
|
+
const selected = PostPurchaseCollectionChoice.parse(requested);
|
|
6697
|
+
const { members, normalized } = normalizePostPurchaseCollection(settings, response, excludedProductIds);
|
|
6698
|
+
const found = members.find(({ product: product2 }) => product2.id === selected.productId);
|
|
6699
|
+
if (!found) return null;
|
|
6700
|
+
const variantId = selected.variantId ?? (defaults && resolvePostPurchaseMemberDefault(found.product, normalized.original, defaults));
|
|
6701
|
+
const product = variantId === void 0 ? found.product : {
|
|
6702
|
+
...found.product,
|
|
6703
|
+
variants: found.product.variants.filter(({ id }) => id === variantId)
|
|
6704
|
+
};
|
|
6705
|
+
const selectedInput = { ...normalized, data: [product] };
|
|
6706
|
+
const quantity2 = requestedQuantity ? readPostPurchaseQuantity(selectedInput, requestedQuantity) : void 0;
|
|
6707
|
+
const view = prepareNormalizedPostPurchaseView(widgetId, selectedInput, report, selected.choice, quantity2, true);
|
|
6708
|
+
if (selected.variantId !== void 0 || found.product.variants.length > 1)
|
|
6709
|
+
view.variantCatalog = projectPostPurchaseVariantCatalog(found.product, normalized.effective);
|
|
6710
|
+
if (defaults && selected.variantId === void 0 && variantId && view.variantCatalog?.variants.some(({ id }) => id === variantId))
|
|
6711
|
+
view.initialVariant = { variantId };
|
|
6712
|
+
return { member: { productId: found.product.id, productIndex: found.productIndex, view }, normalized, quantity: quantity2 };
|
|
6713
|
+
};
|
|
6714
|
+
var preparePostPurchaseMemberView = (widgetId, settings, response, requested, report, excludedProductIds) => prepareMember(widgetId, settings, response, requested, report, excludedProductIds)?.member ?? null;
|
|
6715
|
+
var preparePostPurchaseMemberAdmissionView = (widgetId, settings, response, requested, report, excludedProductIds) => {
|
|
6716
|
+
const prepared = prepareMember(widgetId, settings, response, requested, report, excludedProductIds);
|
|
6717
|
+
if (!prepared) return null;
|
|
6718
|
+
const { removePartialOrder } = PostPurchaseSettings.shape.advance.parse(prepared.normalized.effective.advance);
|
|
6719
|
+
return { ...prepared.member, removePartialOrder };
|
|
6720
|
+
};
|
|
6721
|
+
|
|
6722
|
+
// src/server/preparePostPurchaseQuantityView.ts
|
|
6723
|
+
var preparePostPurchaseQuantityView = (widgetId, settings, response, requested, report, excludedProductIds, defaults) => {
|
|
6724
|
+
const { quantity: quantity2, ...selection3 } = PostPurchaseQuantityChoice.parse(requested);
|
|
6725
|
+
const prepared = prepareMember(
|
|
6726
|
+
widgetId,
|
|
6727
|
+
settings,
|
|
6728
|
+
response,
|
|
6729
|
+
selection3,
|
|
6730
|
+
report,
|
|
6731
|
+
excludedProductIds,
|
|
6732
|
+
{ quantity: quantity2 },
|
|
6733
|
+
defaults
|
|
6734
|
+
);
|
|
6735
|
+
return prepared ? { ...prepared.member, quantityPolicy: prepared.quantity.policy } : null;
|
|
6736
|
+
};
|
|
6737
|
+
|
|
6738
|
+
// src/server/preparePostPurchaseQuantityAdmissionView.ts
|
|
6739
|
+
var selection = PostPurchaseQuantityChoice.required({ quantity: true });
|
|
6740
|
+
var preparePostPurchaseQuantityAdmissionView = (widgetId, settings, response, expected, report, excludedProductIds, defaults) => {
|
|
6741
|
+
const { quantity: expectedQuantity, ...requested } = selection.parse(expected);
|
|
6742
|
+
const prepared = prepareMember(
|
|
6743
|
+
widgetId,
|
|
6744
|
+
settings,
|
|
6745
|
+
response,
|
|
6746
|
+
requested,
|
|
6747
|
+
report,
|
|
6748
|
+
excludedProductIds,
|
|
6749
|
+
{ expectedQuantity },
|
|
6750
|
+
defaults
|
|
6751
|
+
);
|
|
6752
|
+
if (!prepared) return null;
|
|
6753
|
+
const { removePartialOrder } = PostPurchaseSettings.shape.advance.parse(prepared.normalized.effective.advance);
|
|
6754
|
+
return { ...prepared.member, quantityPolicy: prepared.quantity.policy, removePartialOrder };
|
|
6755
|
+
};
|
|
6756
|
+
|
|
6757
|
+
// src/schema/postPurchaseGroup.ts
|
|
6758
|
+
var PostPurchaseGroupChoice = PostPurchaseQuantityChoice.extend({
|
|
6759
|
+
memberProductId: PreparedPostPurchaseProduct.shape.selection.shape.productId
|
|
6760
|
+
});
|
|
6761
|
+
|
|
6762
|
+
// src/server/readPostPurchaseGroup.ts
|
|
6763
|
+
var readPostPurchaseGroup = (product, settings, excludedProductIds) => {
|
|
6764
|
+
const descriptions = PostPurchaseGroupDescription.nullable().array().parse(product.productGroupVariants).filter((value) => value !== null);
|
|
6765
|
+
const ids = new Set(descriptions.map((value) => value.id));
|
|
6766
|
+
if (ids.size !== descriptions.length || new Set(product.variants.map(({ id }) => id)).size !== product.variants.length || product.variants.some(({ productId: productId2 }) => !ids.has(productId2)))
|
|
6767
|
+
throw new Error("Ambiguous post-purchase group ownership");
|
|
6768
|
+
const excluded = new Set(PostPurchaseExcludedProductIds.parse(excludedProductIds));
|
|
6769
|
+
const entries = descriptions.map((description) => {
|
|
6770
|
+
const value = {
|
|
6771
|
+
...product,
|
|
6772
|
+
...description,
|
|
6773
|
+
images: description.images,
|
|
6774
|
+
productGroupVariants: [],
|
|
6775
|
+
variants: product.variants.filter(({ productId: productId2 }) => productId2 === description.id)
|
|
6776
|
+
};
|
|
6777
|
+
return { product: value, variantCatalog: projectPostPurchaseVariantCatalog(value, settings) };
|
|
6778
|
+
}).filter(({ product: value }) => !excluded.has(value.id));
|
|
6779
|
+
return {
|
|
6780
|
+
catalog: PostPurchaseGroupCatalog.parse({
|
|
6781
|
+
memberProductId: product.id,
|
|
6782
|
+
options: entries.map(({ product: value, variantCatalog }) => ({
|
|
6783
|
+
productId: value.id,
|
|
6784
|
+
title: value.title,
|
|
6785
|
+
variantCatalog
|
|
6786
|
+
}))
|
|
6787
|
+
}),
|
|
6788
|
+
entries
|
|
6789
|
+
};
|
|
6790
|
+
};
|
|
6791
|
+
|
|
6792
|
+
// src/server/readPostPurchaseGroupSelection.ts
|
|
6793
|
+
var readPostPurchaseGroupSelection = (settings, response, requested, excludedProductIds) => {
|
|
6794
|
+
const selection3 = PostPurchaseGroupSelection.parse(requested);
|
|
6795
|
+
const { members, normalized } = normalizePostPurchaseCollection(settings, response);
|
|
6796
|
+
const member = members.find(({ product }) => product.id === selection3.memberProductId);
|
|
6797
|
+
if (!member || !member.product.productGroupVariants.length) return null;
|
|
6798
|
+
const group = readPostPurchaseGroup(member.product, normalized.effective, excludedProductIds);
|
|
6799
|
+
const entry = group.entries.find(({ product }) => product.id === selection3.productId);
|
|
6800
|
+
if (!entry) return null;
|
|
6801
|
+
return {
|
|
6802
|
+
groupCatalog: group.catalog,
|
|
6803
|
+
memberProductId: member.product.id,
|
|
6804
|
+
productIndex: member.productIndex,
|
|
6805
|
+
reportingProduct: { id: member.product.id, title: member.product.title },
|
|
6806
|
+
response: { data: [entry.product], metadata: normalized.metadata },
|
|
6807
|
+
variantCatalog: entry.variantCatalog
|
|
6808
|
+
};
|
|
6809
|
+
};
|
|
6810
|
+
|
|
6811
|
+
// src/server/preparePostPurchaseGroupView.ts
|
|
6812
|
+
var preparePostPurchaseGroupView = (widgetId, settings, response, requested, report, excludedProductIds) => {
|
|
6813
|
+
const { memberProductId, ...selection3 } = PostPurchaseGroupChoice.parse(requested);
|
|
6814
|
+
const group = readPostPurchaseGroupSelection(settings, response, requested, excludedProductIds);
|
|
6815
|
+
if (!group) return null;
|
|
6816
|
+
const variantId = selection3.variantId ?? group.variantCatalog.variants.find(({ available }) => available)?.id;
|
|
6817
|
+
if (variantId === void 0) return null;
|
|
6818
|
+
const prepared = preparePostPurchaseQuantityView(
|
|
6819
|
+
widgetId,
|
|
6820
|
+
settings,
|
|
6821
|
+
group.response,
|
|
6822
|
+
{ ...selection3, variantId },
|
|
6823
|
+
report
|
|
6824
|
+
);
|
|
6825
|
+
return prepared && {
|
|
6826
|
+
...prepared,
|
|
6827
|
+
groupCatalog: group.groupCatalog,
|
|
6828
|
+
memberProductId,
|
|
6829
|
+
productIndex: group.productIndex,
|
|
6830
|
+
reportingProduct: group.reportingProduct
|
|
6831
|
+
};
|
|
6832
|
+
};
|
|
6833
|
+
|
|
6834
|
+
// src/server/preparePostPurchaseGroupAdmissionView.ts
|
|
6835
|
+
var preparePostPurchaseGroupAdmissionView = (widgetId, settings, response, requested, report, excludedProductIds) => {
|
|
6836
|
+
const { memberProductId, ...selection3 } = PostPurchaseGroupChoice.required({ quantity: true }).parse(requested);
|
|
6837
|
+
const group = readPostPurchaseGroupSelection(settings, response, requested, excludedProductIds);
|
|
6838
|
+
if (!group) return null;
|
|
6839
|
+
const variantId = selection3.variantId ?? group.variantCatalog.variants.find(({ available }) => available)?.id;
|
|
6840
|
+
if (variantId === void 0) return null;
|
|
6841
|
+
const prepared = preparePostPurchaseQuantityAdmissionView(
|
|
6842
|
+
widgetId,
|
|
6843
|
+
settings,
|
|
6844
|
+
group.response,
|
|
6845
|
+
{ ...selection3, variantId },
|
|
6846
|
+
report
|
|
6847
|
+
);
|
|
6848
|
+
return prepared && {
|
|
6849
|
+
...prepared,
|
|
6850
|
+
groupCatalog: group.groupCatalog,
|
|
6851
|
+
memberProductId,
|
|
6852
|
+
productIndex: group.productIndex,
|
|
6853
|
+
reportingProduct: group.reportingProduct
|
|
6854
|
+
};
|
|
6855
|
+
};
|
|
6856
|
+
|
|
6857
|
+
// src/server/preparePostPurchaseGroupDefault.ts
|
|
6858
|
+
var preparePostPurchaseGroupDefault = (widgetId, settings, response, memberProductId, context, report, excludedProductIds) => {
|
|
6859
|
+
const { members, normalized } = normalizePostPurchaseCollection(settings, response);
|
|
6860
|
+
const member = members.find(({ product }) => product.id === memberProductId);
|
|
6861
|
+
if (!member || !member.product.productGroupVariants.length) return null;
|
|
6862
|
+
const group = readPostPurchaseGroup(member.product, normalized.effective, excludedProductIds);
|
|
6863
|
+
const ids = new Set(group.entries.map(({ product }) => product.id));
|
|
6864
|
+
const variants = member.product.variants.filter(({ productId: productId2 }) => ids.has(productId2));
|
|
6865
|
+
const selected = PostPurchaseVariantDefaultProduct.shape.selectedVariant.parse(member.product.selectedVariant);
|
|
6866
|
+
const selectedOwner = selected && member.product.variants.find(({ id }) => id === selected.id);
|
|
6867
|
+
const variantId = resolvePostPurchaseMemberDefault(
|
|
6868
|
+
{
|
|
6869
|
+
...member.product,
|
|
6870
|
+
selectedVariant: selectedOwner && !ids.has(selectedOwner.productId) ? void 0 : member.product.selectedVariant,
|
|
6871
|
+
variants
|
|
6872
|
+
},
|
|
6873
|
+
normalized.original,
|
|
6874
|
+
context
|
|
6875
|
+
);
|
|
6876
|
+
const entry = group.entries.find(({ product }) => product.variants.some(({ id }) => id === variantId));
|
|
6877
|
+
if (!entry || variantId === null) return null;
|
|
6878
|
+
const prepared = preparePostPurchaseGroupView(
|
|
6879
|
+
widgetId,
|
|
6880
|
+
settings,
|
|
6881
|
+
response,
|
|
6882
|
+
{ memberProductId, productId: entry.product.id, variantId },
|
|
6883
|
+
report,
|
|
6884
|
+
excludedProductIds
|
|
6885
|
+
);
|
|
6886
|
+
return prepared && { ...prepared, view: { ...prepared.view, initialVariant: { variantId } } };
|
|
6887
|
+
};
|
|
6888
|
+
|
|
6889
|
+
// src/server/preparePostPurchaseCollectionGroup.ts
|
|
6890
|
+
var preparePostPurchaseCollectionGroup = (widgetId, settings, response, member, normalized, excluded, defaults, report) => {
|
|
6891
|
+
const group = readPostPurchaseGroup(member.product, normalized.effective, excluded);
|
|
6892
|
+
if (!group.entries.length) return null;
|
|
6893
|
+
const prepared = preparePostPurchaseGroupDefault(
|
|
6894
|
+
widgetId,
|
|
6895
|
+
settings,
|
|
6896
|
+
response,
|
|
6897
|
+
member.product.id,
|
|
6898
|
+
defaults,
|
|
6899
|
+
report,
|
|
6900
|
+
excluded
|
|
6901
|
+
);
|
|
6902
|
+
return {
|
|
6903
|
+
productId: member.product.id,
|
|
6904
|
+
productIndex: member.productIndex,
|
|
6905
|
+
reportingProduct: { id: member.product.id, title: member.product.title },
|
|
6906
|
+
view: prepared ? { ...prepared.view, groupCatalog: prepared.groupCatalog } : {
|
|
6907
|
+
groupCatalog: group.catalog,
|
|
6908
|
+
preparation: { reason: "Post-purchase group default is unavailable", status: "unsupported" },
|
|
6909
|
+
sections: null
|
|
6910
|
+
}
|
|
6911
|
+
};
|
|
6912
|
+
};
|
|
6913
|
+
|
|
6914
|
+
// src/server/preparePostPurchaseCollectionView.ts
|
|
6915
|
+
var CollectionChoice = PostPurchaseCollectionChoice.omit({ variantId: true });
|
|
6916
|
+
var preparePostPurchaseCollectionView = (widgetId, settings, response, report, requested, excludedProductIds, defaults = { originalVariants: [] }) => {
|
|
6917
|
+
const { members, normalized } = normalizePostPurchaseCollection(settings, response);
|
|
6918
|
+
const excluded = PostPurchaseExcludedProductIds.parse(excludedProductIds);
|
|
6919
|
+
const selected = CollectionChoice.optional().parse(requested);
|
|
6920
|
+
const projected = members.map((member) => {
|
|
6921
|
+
if (member.product.productGroupVariants.length) {
|
|
6922
|
+
if (selected?.productId === member.product.id && selected.choice)
|
|
6923
|
+
throw new Error("Grouped choices require selected merchandise");
|
|
6924
|
+
const group = preparePostPurchaseCollectionGroup(
|
|
6925
|
+
widgetId,
|
|
6926
|
+
settings,
|
|
6927
|
+
response,
|
|
6928
|
+
member,
|
|
6929
|
+
normalized,
|
|
6930
|
+
excluded,
|
|
6931
|
+
defaults,
|
|
6932
|
+
report
|
|
6933
|
+
);
|
|
6934
|
+
return group;
|
|
6935
|
+
}
|
|
6936
|
+
if (excluded.includes(member.product.id)) return null;
|
|
6937
|
+
return {
|
|
6938
|
+
productId: member.product.id,
|
|
6939
|
+
productIndex: member.productIndex,
|
|
6940
|
+
reportingProduct: void 0,
|
|
6941
|
+
view: prepareNormalizedPostPurchaseView(
|
|
6942
|
+
widgetId,
|
|
6943
|
+
{ ...normalized, data: [member.product] },
|
|
6944
|
+
report,
|
|
6945
|
+
member.product.id === selected?.productId ? selected.choice : void 0,
|
|
6946
|
+
void 0,
|
|
6947
|
+
true
|
|
6948
|
+
)
|
|
6949
|
+
};
|
|
6950
|
+
}).filter((member) => member !== null);
|
|
6951
|
+
if (selected && !projected.some(({ productId: productId2 }) => productId2 === selected.productId))
|
|
6952
|
+
throw new Error("Requested product is outside the prepared collection");
|
|
6953
|
+
const collection = PostPurchaseProductCollectionView.parse({ members: projected });
|
|
6954
|
+
return {
|
|
6955
|
+
members: collection.members.map((member, index) => ({
|
|
6956
|
+
...member,
|
|
6957
|
+
...projected[index].reportingProduct && { reportingProduct: projected[index].reportingProduct }
|
|
6958
|
+
}))
|
|
6959
|
+
};
|
|
6960
|
+
};
|
|
6961
|
+
|
|
6962
|
+
// src/schema/postPurchaseOfferEligibility.ts
|
|
6963
|
+
var import_zod67 = require("zod");
|
|
6964
|
+
var selection2 = PreparedPostPurchaseProduct.shape.selection;
|
|
6965
|
+
var PostPurchaseOfferSkipReason = import_zod67.z.enum(["empty", "no-eligible-subscription"]);
|
|
6966
|
+
var PostPurchaseOfferEligibilityContext = import_zod67.z.object({
|
|
6967
|
+
excludedProductIds: PostPurchaseExcludedProductIds,
|
|
6968
|
+
originalLineItems: import_zod67.z.array(selection2.pick({ productId: true, sellingPlanId: true, variantId: true }))
|
|
6969
|
+
});
|
|
6970
|
+
var PostPurchaseOfferEligibility = import_zod67.z.discriminatedUnion("status", [
|
|
6971
|
+
import_zod67.z.object({
|
|
6972
|
+
members: import_zod67.z.array(
|
|
6973
|
+
import_zod67.z.object({ productId: selection2.shape.productId, productIndex: import_zod67.z.number().int().nonnegative() })
|
|
6974
|
+
),
|
|
6975
|
+
status: import_zod67.z.literal("retain")
|
|
6976
|
+
}),
|
|
6977
|
+
import_zod67.z.object({ reason: PostPurchaseOfferSkipReason, status: import_zod67.z.literal("skip") }),
|
|
6978
|
+
import_zod67.z.object({ reason: import_zod67.z.literal("eligible-upgrade").optional(), status: import_zod67.z.literal("unavailable") })
|
|
6979
|
+
]);
|
|
6980
|
+
|
|
6981
|
+
// src/server/postPurchaseMemberEligibility.ts
|
|
6982
|
+
var PostPurchaseInventoryUnavailable = class extends Error {
|
|
6983
|
+
};
|
|
6984
|
+
var postPurchaseMemberEligibility = (normalized, product, excluded) => {
|
|
6985
|
+
if (product.productGroupVariants.length) {
|
|
6986
|
+
const group = readPostPurchaseGroup(product, normalized.effective, excluded);
|
|
6987
|
+
return group.entries.map(({ product: option }) => postPurchaseMemberEligibility(normalized, option)).some(Boolean);
|
|
6988
|
+
}
|
|
6989
|
+
if (!product.variants.length) throw new Error("Unsupported catalog");
|
|
6990
|
+
const variants = projectPostPurchaseVariantCatalog(product, normalized.effective).variants;
|
|
6991
|
+
const catalogs = product.variants.map((variant2) => {
|
|
6992
|
+
const catalog = projectPostPurchasePlanCatalog({
|
|
6993
|
+
...normalized,
|
|
6994
|
+
data: [{ ...product, variants: [variant2] }]
|
|
6995
|
+
});
|
|
6996
|
+
if (!catalog) throw new Error("Unreadable subscription catalog");
|
|
6997
|
+
if (normalized.effective.productType === "one-time" && catalog.requiresSellingPlan)
|
|
6998
|
+
throw new Error("Unsupported purchase mode");
|
|
6999
|
+
return catalog;
|
|
7000
|
+
});
|
|
7001
|
+
if (!variants.some((variant2) => variant2.available))
|
|
7002
|
+
throw new PostPurchaseInventoryUnavailable("Unavailable inventory");
|
|
7003
|
+
return catalogs.some(
|
|
7004
|
+
(catalog, index) => variants[index].available && (normalized.effective.productType !== "subscription" && !catalog.requiresSellingPlan || normalized.effective.productType !== "one-time" && catalog.plans.length > 0)
|
|
7005
|
+
);
|
|
7006
|
+
};
|
|
7007
|
+
|
|
7008
|
+
// src/server/classifyPostPurchaseOffer.ts
|
|
7009
|
+
var classifyPostPurchaseOffer = (settings, response, context) => {
|
|
7010
|
+
try {
|
|
7011
|
+
const trusted = PostPurchaseOfferEligibilityContext.parse(context);
|
|
7012
|
+
const { members, normalized } = normalizePostPurchaseCollection(settings, response);
|
|
7013
|
+
const configurations = [normalized.original, normalized.effective];
|
|
7014
|
+
const upgrades = configurations.some((config) => config.upgradeToSubscription.allow);
|
|
7015
|
+
const oneTime = new Set(
|
|
7016
|
+
trusted.originalLineItems.filter((line) => line.sellingPlanId === void 0).map((line) => line.variantId)
|
|
7017
|
+
);
|
|
7018
|
+
if (upgrades && members.some(
|
|
7019
|
+
({ product }) => product.sellingPlanGroups?.length && product.variants.some((variant2) => oneTime.has(variant2.id))
|
|
7020
|
+
))
|
|
7021
|
+
return { reason: "eligible-upgrade", status: "unavailable" };
|
|
7022
|
+
if (normalized.effective.productType !== "one-time") {
|
|
7023
|
+
configurations.forEach((config) => PostPurchaseSubscriptionSettings.parse(config.subscription));
|
|
7024
|
+
}
|
|
7025
|
+
const classified = members.map((member) => {
|
|
7026
|
+
try {
|
|
7027
|
+
return {
|
|
7028
|
+
...member,
|
|
7029
|
+
eligible: postPurchaseMemberEligibility(normalized, member.product, trusted.excludedProductIds)
|
|
7030
|
+
};
|
|
7031
|
+
} catch (error) {
|
|
7032
|
+
if (error instanceof PostPurchaseInventoryUnavailable && !member.product.productGroupVariants.length && trusted.excludedProductIds.includes(member.product.id))
|
|
7033
|
+
return { ...member, eligible: false };
|
|
7034
|
+
throw error;
|
|
7035
|
+
}
|
|
7036
|
+
});
|
|
7037
|
+
if (!members.length) return { reason: "empty", status: "skip" };
|
|
7038
|
+
if (upgrades) return { reason: "no-eligible-subscription", status: "skip" };
|
|
7039
|
+
const candidates = classified.filter(
|
|
7040
|
+
({ product }) => product.productGroupVariants.length ? readPostPurchaseGroup(product, normalized.effective, trusted.excludedProductIds).entries.length > 0 : !trusted.excludedProductIds.includes(product.id)
|
|
7041
|
+
);
|
|
7042
|
+
if (!candidates.length) return { reason: "empty", status: "skip" };
|
|
7043
|
+
const retained = candidates.filter(({ eligible }) => eligible);
|
|
7044
|
+
return retained.length ? {
|
|
7045
|
+
members: retained.map(({ product, productIndex }) => ({
|
|
7046
|
+
productId: product.id,
|
|
7047
|
+
productIndex
|
|
7048
|
+
})),
|
|
7049
|
+
status: "retain"
|
|
7050
|
+
} : { reason: "no-eligible-subscription", status: "skip" };
|
|
7051
|
+
} catch {
|
|
7052
|
+
return { status: "unavailable" };
|
|
7053
|
+
}
|
|
7054
|
+
};
|
|
7055
|
+
|
|
7056
|
+
// src/server/preparePostPurchaseGroupDeclineDisplay.ts
|
|
7057
|
+
var preparePostPurchaseGroupDeclineDisplay = (settings, response, requested, excludedProductIds) => {
|
|
7058
|
+
const group = readPostPurchaseGroupSelection(settings, response, requested, excludedProductIds);
|
|
7059
|
+
const variant2 = group?.variantCatalog.variants.find(({ id }) => id === requested.variantId);
|
|
7060
|
+
return group && variant2 ? {
|
|
7061
|
+
display: {
|
|
7062
|
+
productTitle: group.reportingProduct.title,
|
|
7063
|
+
variantId: variant2.id,
|
|
7064
|
+
variantTitle: variant2.title
|
|
7065
|
+
},
|
|
7066
|
+
productIndex: group.productIndex
|
|
7067
|
+
} : null;
|
|
7068
|
+
};
|
|
7069
|
+
|
|
7070
|
+
// src/server/preparePostPurchaseOfferPresentation.ts
|
|
7071
|
+
var import_compat7 = require("es-toolkit/compat");
|
|
7072
|
+
var import_zod69 = require("zod");
|
|
7073
|
+
|
|
7074
|
+
// src/schema/postPurchaseOfferPresentation.ts
|
|
7075
|
+
var import_zod68 = require("zod");
|
|
7076
|
+
var language2 = PostPurchaseSettings.shape.language.shape.global.unwrap().unwrap();
|
|
7077
|
+
var PostPurchaseOfferPresentation = import_zod68.z.strictObject({
|
|
7078
|
+
labels: language2.pick({ declineAll: true, declineThisOffer: true }),
|
|
7079
|
+
layout: PostPurchaseSettings.shape.offersLayout,
|
|
7080
|
+
sections: CABRootSection.nullable(),
|
|
7081
|
+
showDeclineAll: PostPurchaseSettings.shape.productOptions.shape.showDeclineAll
|
|
7082
|
+
});
|
|
7083
|
+
|
|
7084
|
+
// src/server/preparePostPurchaseOfferPresentation.ts
|
|
7085
|
+
var FrameSettings = PostPurchaseSettings.pick({ language: true, offersLayout: true, productOptions: true }).extend({
|
|
7086
|
+
blocks: import_zod69.z.array(import_zod69.z.unknown()).optional()
|
|
7087
|
+
});
|
|
7088
|
+
var preparePostPurchaseOfferPresentation = (widgetId, settings, response, report) => {
|
|
7089
|
+
const { metadata } = PostPurchaseProductSource.pick({ metadata: true }).parse(deepCamelCase(response));
|
|
7090
|
+
const original = FrameSettings.parse(deepCamelCase(settings));
|
|
7091
|
+
const effective = FrameSettings.parse((0, import_compat7.merge)({}, original, metadata.widget));
|
|
7092
|
+
let sections = null;
|
|
7093
|
+
try {
|
|
7094
|
+
sections = convertMessagePreview(
|
|
7095
|
+
widgetId,
|
|
7096
|
+
{ blocks: postPurchaseOfferCopy(effective.blocks, metadata), type: "shopify_post_purchase_extension" },
|
|
7097
|
+
report
|
|
7098
|
+
);
|
|
7099
|
+
} catch (error) {
|
|
7100
|
+
if (!(error instanceof NotFoundError)) throw error;
|
|
7101
|
+
}
|
|
7102
|
+
return PostPurchaseOfferPresentation.parse({
|
|
7103
|
+
labels: effective.language.global,
|
|
7104
|
+
layout: effective.offersLayout,
|
|
7105
|
+
sections,
|
|
7106
|
+
showDeclineAll: effective.productOptions.showDeclineAll
|
|
7107
|
+
});
|
|
7108
|
+
};
|
|
7109
|
+
|
|
6189
7110
|
// src/server/analytics.ts
|
|
6190
7111
|
var import_es_toolkit7 = require("es-toolkit");
|
|
6191
7112
|
|
|
@@ -6230,8 +7151,8 @@ var TAXONOMY = {
|
|
|
6230
7151
|
"added-to-cart": {
|
|
6231
7152
|
/** React credits the add to the A/B-selected variant (`defined_noun_id: selectedId`). */
|
|
6232
7153
|
buildDefinedNounId: ({ selectedId }) => selectedId != null ? String(selectedId) : void 0,
|
|
6233
|
-
buildMeta: ({ productId, variantId }) => ({
|
|
6234
|
-
...
|
|
7154
|
+
buildMeta: ({ productId: productId2, variantId }) => ({
|
|
7155
|
+
...productId2 != null && { [`product_id:${productId2}`]: true },
|
|
6235
7156
|
...variantId != null && { [`variant_id:${variantId}`]: true }
|
|
6236
7157
|
}),
|
|
6237
7158
|
buildTags: experimentTags,
|
|
@@ -6322,7 +7243,7 @@ var postAnalyticsEvents = async (input, ctx) => {
|
|
|
6322
7243
|
};
|
|
6323
7244
|
|
|
6324
7245
|
// src/server/requestSchemas.ts
|
|
6325
|
-
var
|
|
7246
|
+
var import_zod70 = require("zod");
|
|
6326
7247
|
var REQUEST_BOUNDS = {
|
|
6327
7248
|
/** Cart-level attributes per cart. */
|
|
6328
7249
|
CART_ATTRIBUTES_MAX: 100,
|
|
@@ -6353,42 +7274,42 @@ var REQUEST_BOUNDS = {
|
|
|
6353
7274
|
/** Rich ads transaction lines — the engine's ads contract. */
|
|
6354
7275
|
TRANSACTION_ITEMS_MAX: 50
|
|
6355
7276
|
};
|
|
6356
|
-
var KeyValue =
|
|
6357
|
-
key:
|
|
6358
|
-
value:
|
|
7277
|
+
var KeyValue = import_zod70.z.object({
|
|
7278
|
+
key: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
|
|
7279
|
+
value: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_VALUE_MAX).optional()
|
|
6359
7280
|
});
|
|
6360
|
-
var CartLineInputSchema =
|
|
6361
|
-
productId:
|
|
6362
|
-
properties:
|
|
6363
|
-
quantity:
|
|
6364
|
-
subscriptionId:
|
|
6365
|
-
variantId:
|
|
7281
|
+
var CartLineInputSchema = import_zod70.z.object({
|
|
7282
|
+
productId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
7283
|
+
properties: import_zod70.z.array(KeyValue).max(REQUEST_BOUNDS.LINE_PROPERTIES_MAX).optional(),
|
|
7284
|
+
quantity: import_zod70.z.number(),
|
|
7285
|
+
subscriptionId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
7286
|
+
variantId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX)
|
|
6366
7287
|
});
|
|
6367
|
-
var CartInputSchema =
|
|
6368
|
-
attributes:
|
|
7288
|
+
var CartInputSchema = import_zod70.z.object({
|
|
7289
|
+
attributes: import_zod70.z.array(KeyValue).max(REQUEST_BOUNDS.CART_ATTRIBUTES_MAX).optional(),
|
|
6369
7290
|
/**
|
|
6370
7291
|
* Presentment-per-shop-currency FX rate (buyer price ÷ shop price, e.g. `1.35` for a USD shop
|
|
6371
7292
|
* selling in CAD). Money rule thresholds are authored in SHOP currency, so the engine subtotal is
|
|
6372
7293
|
* divided by this before evaluation. Omit (or send 1) when the cart is already in the shop's currency.
|
|
6373
7294
|
*/
|
|
6374
|
-
currencyRate:
|
|
7295
|
+
currencyRate: import_zod70.z.number().optional(),
|
|
6375
7296
|
/** Applied discount codes; the engine evaluates `discount_code` rules against them (sent as `[{code}]`). */
|
|
6376
|
-
discountCodes:
|
|
7297
|
+
discountCodes: import_zod70.z.array(import_zod70.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX)).max(REQUEST_BOUNDS.DISCOUNT_CODES_MAX).optional(),
|
|
6377
7298
|
/** Presentment cents of cart-level discount allocations, subtracted from `subtotal` for the engine. */
|
|
6378
|
-
discountTotal:
|
|
6379
|
-
items:
|
|
7299
|
+
discountTotal: import_zod70.z.number().optional(),
|
|
7300
|
+
items: import_zod70.z.array(CartLineInputSchema).max(REQUEST_BOUNDS.CART_ITEMS_MAX),
|
|
6380
7301
|
/** Presentment subtotal in cents. */
|
|
6381
|
-
subtotal:
|
|
7302
|
+
subtotal: import_zod70.z.number()
|
|
6382
7303
|
});
|
|
6383
|
-
var UserConfigInputSchema =
|
|
6384
|
-
var DataSourceInputSchema =
|
|
7304
|
+
var UserConfigInputSchema = import_zod70.z.object({ shop: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX) });
|
|
7305
|
+
var DataSourceInputSchema = import_zod70.z.object({
|
|
6385
7306
|
cart: CartInputSchema,
|
|
6386
7307
|
/**
|
|
6387
7308
|
* Numeric Shopify company-location id when the buyer is a B2B session (`buyerIdentity.purchasingCompany`).
|
|
6388
7309
|
* Present ⇒ the orchestrator filters results by the location's catalog via admin-api (REB-23713); the
|
|
6389
7310
|
* client's country-context market check is bypassed for B2B (it false-negatives B2B-catalog products).
|
|
6390
7311
|
*/
|
|
6391
|
-
companyLocationId:
|
|
7312
|
+
companyLocationId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6392
7313
|
/**
|
|
6393
7314
|
* Buyer's market country (ISO 3166-1 alpha-2) — forwarded to the engine as the `country_code` PARAM
|
|
6394
7315
|
* when the shop's markets toggle is on (REB-21688; the sink was the `X-Country-Code` header under
|
|
@@ -6397,16 +7318,16 @@ var DataSourceInputSchema = import_zod56.z.object({
|
|
|
6397
7318
|
* uppercase (the wire value is forwarded verbatim as the param) so a case-sensitive engine lookup
|
|
6398
7319
|
* can't silently miss a lowercase code — `adsEngine.ts` uppercases for the same reason.
|
|
6399
7320
|
*/
|
|
6400
|
-
country:
|
|
6401
|
-
customerId:
|
|
6402
|
-
dataSourcePath:
|
|
7321
|
+
country: import_zod70.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(),
|
|
7322
|
+
customerId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
7323
|
+
dataSourcePath: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
|
|
6403
7324
|
/**
|
|
6404
7325
|
* Engine `filter_inputs` override: `'no'` keeps in-cart (input) products in the results/rule
|
|
6405
7326
|
* outputs — gift validation sends it so a gift's own product can appear in its answer. Omitted = the
|
|
6406
7327
|
* engine's default filtering.
|
|
6407
7328
|
*/
|
|
6408
|
-
filterInputs:
|
|
6409
|
-
integrations:
|
|
7329
|
+
filterInputs: import_zod70.z.enum(["no", "yes"]).optional(),
|
|
7330
|
+
integrations: import_zod70.z.record(import_zod70.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), import_zod70.z.boolean()).refine((record) => Object.keys(record).length <= REQUEST_BOUNDS.INTEGRATION_KEYS_MAX, {
|
|
6410
7331
|
message: `Too many integration keys (max ${REQUEST_BOUNDS.INTEGRATION_KEYS_MAX})`
|
|
6411
7332
|
}).optional(),
|
|
6412
7333
|
/**
|
|
@@ -6419,31 +7340,31 @@ var DataSourceInputSchema = import_zod56.z.object({
|
|
|
6419
7340
|
* request header) fails the regex. Callers should send the buyer's resolved locale (e.g. Shopify
|
|
6420
7341
|
* checkout's `localization.language.isoCode`), not the request header verbatim.
|
|
6421
7342
|
*/
|
|
6422
|
-
language:
|
|
6423
|
-
limit:
|
|
6424
|
-
productType:
|
|
6425
|
-
shop:
|
|
6426
|
-
visitorId:
|
|
6427
|
-
});
|
|
6428
|
-
var GiftInputSchema =
|
|
6429
|
-
cost:
|
|
6430
|
-
discounted:
|
|
7343
|
+
language: import_zod70.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(),
|
|
7344
|
+
limit: import_zod70.z.number().max(REQUEST_BOUNDS.LIMIT_MAX),
|
|
7345
|
+
productType: import_zod70.z.enum(["both", "one-time", "subscription"]).optional(),
|
|
7346
|
+
shop: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
7347
|
+
visitorId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
|
|
7348
|
+
});
|
|
7349
|
+
var GiftInputSchema = import_zod70.z.object({
|
|
7350
|
+
cost: import_zod70.z.number(),
|
|
7351
|
+
discounted: import_zod70.z.boolean(),
|
|
6431
7352
|
/**
|
|
6432
7353
|
* Which gift attribution the line carries (REB-24363). Defaults to `gwp` because a client that predates
|
|
6433
7354
|
* the field only ever sent GWP lines — without the default an older extension's request would 422.
|
|
6434
7355
|
*/
|
|
6435
|
-
kind:
|
|
6436
|
-
lineId:
|
|
6437
|
-
productId:
|
|
7356
|
+
kind: import_zod70.z.enum(GIFT_KINDS).default("gwp"),
|
|
7357
|
+
lineId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
7358
|
+
productId: import_zod70.z.number(),
|
|
6438
7359
|
/**
|
|
6439
7360
|
* The line's unit count (REB-24363) — the selectable-GWP verdict trims surplus units against milestone
|
|
6440
7361
|
* capacity. The second deliberate default: a client predating the field sent only GWP lines, whose
|
|
6441
7362
|
* verdict is whole-line, so a missing quantity reads as one unit rather than 422ing the older request.
|
|
6442
7363
|
*/
|
|
6443
|
-
quantity:
|
|
6444
|
-
widgetId:
|
|
7364
|
+
quantity: import_zod70.z.number().int().min(1).default(1),
|
|
7365
|
+
widgetId: import_zod70.z.number()
|
|
6445
7366
|
});
|
|
6446
|
-
var GiftValidationInputSchema =
|
|
7367
|
+
var GiftValidationInputSchema = import_zod70.z.object({
|
|
6447
7368
|
cart: CartInputSchema,
|
|
6448
7369
|
/**
|
|
6449
7370
|
* Buyer's market country — threaded into the per-widget data-source evaluations, which forward it to
|
|
@@ -6452,25 +7373,25 @@ var GiftValidationInputSchema = import_zod56.z.object({
|
|
|
6452
7373
|
* turns markets off); regex-bound and uppercase-normalized for the same reasons as
|
|
6453
7374
|
* `DataSourceInputSchema`'s `country`.
|
|
6454
7375
|
*/
|
|
6455
|
-
country:
|
|
6456
|
-
customerId:
|
|
6457
|
-
gifts:
|
|
7376
|
+
country: import_zod70.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(),
|
|
7377
|
+
customerId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
7378
|
+
gifts: import_zod70.z.array(GiftInputSchema).max(REQUEST_BOUNDS.GIFTS_MAX),
|
|
6458
7379
|
/**
|
|
6459
7380
|
* Buyer's checkout language — threaded into the per-widget data-source evaluations, which normalize
|
|
6460
7381
|
* and forward it as the engine `locale` param under the same markets-toggle gate (REB-21688). MUST be
|
|
6461
7382
|
* a single BCP-47 tag, for the same reason as `DataSourceInputSchema`'s `language` above.
|
|
6462
7383
|
*/
|
|
6463
|
-
language:
|
|
6464
|
-
shop:
|
|
6465
|
-
visitorId:
|
|
7384
|
+
language: import_zod70.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(),
|
|
7385
|
+
shop: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
7386
|
+
visitorId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
|
|
6466
7387
|
});
|
|
6467
|
-
var GiftAdjustmentSchema =
|
|
6468
|
-
lineId:
|
|
6469
|
-
quantity:
|
|
7388
|
+
var GiftAdjustmentSchema = import_zod70.z.object({
|
|
7389
|
+
lineId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
7390
|
+
quantity: import_zod70.z.number().int().nonnegative()
|
|
6470
7391
|
});
|
|
6471
|
-
var GiftValidationResponseSchema =
|
|
6472
|
-
adjust:
|
|
6473
|
-
remove:
|
|
7392
|
+
var GiftValidationResponseSchema = import_zod70.z.object({
|
|
7393
|
+
adjust: import_zod70.z.array(GiftAdjustmentSchema).max(REQUEST_BOUNDS.GIFTS_MAX).default([]),
|
|
7394
|
+
remove: import_zod70.z.array(import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX)).max(REQUEST_BOUNDS.GIFTS_MAX).refine(
|
|
6474
7395
|
(remove) => new Set(remove).size === remove.length,
|
|
6475
7396
|
"a line id may appear at most once in `remove`"
|
|
6476
7397
|
)
|
|
@@ -6481,47 +7402,47 @@ var GiftValidationResponseSchema = import_zod56.z.object({
|
|
|
6481
7402
|
({ adjust }) => new Set(adjust.map(({ lineId }) => lineId)).size === adjust.length,
|
|
6482
7403
|
"a line id may appear at most once in `adjust`"
|
|
6483
7404
|
);
|
|
6484
|
-
var MonetizeTransactionItemSchema =
|
|
6485
|
-
id:
|
|
6486
|
-
priceCents:
|
|
6487
|
-
quantity:
|
|
6488
|
-
title:
|
|
6489
|
-
type:
|
|
6490
|
-
});
|
|
6491
|
-
var MonetizeInputSchema =
|
|
7405
|
+
var MonetizeTransactionItemSchema = import_zod70.z.object({
|
|
7406
|
+
id: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
7407
|
+
priceCents: import_zod70.z.number(),
|
|
7408
|
+
quantity: import_zod70.z.number(),
|
|
7409
|
+
title: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX),
|
|
7410
|
+
type: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX)
|
|
7411
|
+
});
|
|
7412
|
+
var MonetizeInputSchema = import_zod70.z.object({
|
|
6492
7413
|
cart: CartInputSchema,
|
|
6493
7414
|
/** Client-minted render-beacon correlation id; forwarded to the ads engine as `client_request_id`. */
|
|
6494
|
-
clientRequestId:
|
|
6495
|
-
country:
|
|
6496
|
-
currency:
|
|
7415
|
+
clientRequestId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
7416
|
+
country: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
7417
|
+
currency: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6497
7418
|
/** Ads-targeting identity/geo/locale fields (React parity); folded into the engine query verbatim. */
|
|
6498
|
-
customerEmail:
|
|
6499
|
-
customerFirstName:
|
|
6500
|
-
customerId:
|
|
6501
|
-
customerLastName:
|
|
6502
|
-
language:
|
|
7419
|
+
customerEmail: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
|
|
7420
|
+
customerFirstName: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
|
|
7421
|
+
customerId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
7422
|
+
customerLastName: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
|
|
7423
|
+
language: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6503
7424
|
/** Buyer-facing order name (e.g. `#1001`) for the server-composed "Order … Confirmed" chrome line. */
|
|
6504
|
-
orderName:
|
|
7425
|
+
orderName: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_TEXT_MAX).optional(),
|
|
6505
7426
|
/** Ads surface label, forwarded verbatim; `customer_account` is measured/floored as its own surface (the account-area order list). */
|
|
6506
|
-
placement:
|
|
7427
|
+
placement: import_zod70.z.enum(["customer_account", "order_status", "thank_you_page"]),
|
|
6507
7428
|
/** Privacy Policy footer href — the Monetize widget's `privacy_policy_url` setting (React parity). */
|
|
6508
|
-
privacyPolicyUrl:
|
|
7429
|
+
privacyPolicyUrl: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_URL_MAX).optional(),
|
|
6509
7430
|
/** 30-min rolling session id (React parity); used for the ads `session_id`, else the visitor id. */
|
|
6510
|
-
sessionId:
|
|
6511
|
-
shop:
|
|
7431
|
+
sessionId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
7432
|
+
shop: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
6512
7433
|
/** Editor/QA indicator; OR-ed into the ads-engine `testing` flag so it stays out of billing/reporting. */
|
|
6513
|
-
testing:
|
|
6514
|
-
timezone:
|
|
7434
|
+
testing: import_zod70.z.boolean().optional(),
|
|
7435
|
+
timezone: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6515
7436
|
/** Decorated (numeric) order id → the ads `transaction_id`. */
|
|
6516
|
-
transactionId:
|
|
7437
|
+
transactionId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6517
7438
|
/** Rich per-line ads items; capped at the engine's ads contract. Preferred over `cart.items`. */
|
|
6518
|
-
transactionItems:
|
|
7439
|
+
transactionItems: import_zod70.z.array(MonetizeTransactionItemSchema).max(REQUEST_BOUNDS.TRANSACTION_ITEMS_MAX).optional(),
|
|
6519
7440
|
/** Order total in presentment cents (React prefers total over subtotal); else `cart.subtotal`. */
|
|
6520
|
-
transactionTotal:
|
|
6521
|
-
visitorId:
|
|
6522
|
-
zipCode:
|
|
7441
|
+
transactionTotal: import_zod70.z.number().optional(),
|
|
7442
|
+
visitorId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
7443
|
+
zipCode: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
|
|
6523
7444
|
});
|
|
6524
|
-
var WidgetSettingsInputSchema =
|
|
7445
|
+
var WidgetSettingsInputSchema = import_zod70.z.object({
|
|
6525
7446
|
/**
|
|
6526
7447
|
* Same domain as `CabShopConfig.cacheKey`, for the same reason: this side WINS the orchestrator's
|
|
6527
7448
|
* `input.cacheKey ?? config.shop.cacheKey` (and an explicit value skips the config read entirely), so
|
|
@@ -6529,9 +7450,9 @@ var WidgetSettingsInputSchema = import_zod56.z.object({
|
|
|
6529
7450
|
* and pin the edge copy permanently stale. `.catch(undefined)` because a bogus buster should degrade
|
|
6530
7451
|
* the read to un-busted, never 400 a widget render.
|
|
6531
7452
|
*/
|
|
6532
|
-
cacheKey:
|
|
6533
|
-
id:
|
|
6534
|
-
key:
|
|
7453
|
+
cacheKey: import_zod70.z.number().int().positive().optional().catch(void 0),
|
|
7454
|
+
id: import_zod70.z.number(),
|
|
7455
|
+
key: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6535
7456
|
/**
|
|
6536
7457
|
* Monetize context for inline hydration: when present AND the widget converts to a Monetize marker,
|
|
6537
7458
|
* the server fetches/composes the offer cards inside this same request (no second `/cab/monetize`
|
|
@@ -6540,34 +7461,34 @@ var WidgetSettingsInputSchema = import_zod56.z.object({
|
|
|
6540
7461
|
* `privacyPolicyUrl` comes from the widget settings server-side (more authoritative than a relay).
|
|
6541
7462
|
*/
|
|
6542
7463
|
monetize: MonetizeInputSchema.omit({ privacyPolicyUrl: true, shop: true }).optional(),
|
|
6543
|
-
shop:
|
|
7464
|
+
shop: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
6544
7465
|
/** Stable per-buyer id; when present, enables sticky server-side A/B variant selection. */
|
|
6545
|
-
visitorId:
|
|
7466
|
+
visitorId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
|
|
6546
7467
|
});
|
|
6547
|
-
var AnalyticsEventInputSchema =
|
|
6548
|
-
name:
|
|
6549
|
-
properties:
|
|
6550
|
-
sentAt:
|
|
7468
|
+
var AnalyticsEventInputSchema = import_zod70.z.object({
|
|
7469
|
+
name: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX),
|
|
7470
|
+
properties: import_zod70.z.record(import_zod70.z.string().max(REQUEST_BOUNDS.STRING_KEY_MAX), import_zod70.z.unknown()).optional(),
|
|
7471
|
+
sentAt: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
|
|
6551
7472
|
});
|
|
6552
|
-
var AnalyticsSegmentsInputSchema =
|
|
6553
|
-
device:
|
|
6554
|
-
source:
|
|
6555
|
-
visitor:
|
|
7473
|
+
var AnalyticsSegmentsInputSchema = import_zod70.z.object({
|
|
7474
|
+
device: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
|
|
7475
|
+
source: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0),
|
|
7476
|
+
visitor: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional().catch(void 0)
|
|
6556
7477
|
});
|
|
6557
|
-
var AnalyticsInputSchema =
|
|
7478
|
+
var AnalyticsInputSchema = import_zod70.z.object({
|
|
6558
7479
|
/** Rebuy cart token (the `r_cart_token` cart attribute), when available — primary aggregation key. */
|
|
6559
|
-
cartToken:
|
|
7480
|
+
cartToken: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
6560
7481
|
/** Shopify checkout token, when available — drives cart/checkout aggregation downstream. */
|
|
6561
|
-
checkoutToken:
|
|
6562
|
-
events:
|
|
7482
|
+
checkoutToken: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional(),
|
|
7483
|
+
events: import_zod70.z.array(AnalyticsEventInputSchema).max(REQUEST_BOUNDS.EVENTS_MAX),
|
|
6563
7484
|
/**
|
|
6564
7485
|
* Request-scoped like the tokens: one visitor's segments apply to every event in the batch. The container
|
|
6565
7486
|
* degrades too (`null` is a realistic wire artifact of `attributes ? {…} : null`), so the degrade rule is
|
|
6566
7487
|
* total: nothing about `segments` can cost the envelope.
|
|
6567
7488
|
*/
|
|
6568
7489
|
segments: AnalyticsSegmentsInputSchema.optional().catch(void 0),
|
|
6569
|
-
shop:
|
|
6570
|
-
visitorId:
|
|
7490
|
+
shop: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
7491
|
+
visitorId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX),
|
|
6571
7492
|
/** The widget id (smartBlockId) the events belong to. */
|
|
6572
|
-
widgetId:
|
|
7493
|
+
widgetId: import_zod70.z.string().max(REQUEST_BOUNDS.STRING_ID_MAX).optional()
|
|
6573
7494
|
});
|