@drip-apex/sdk 0.1.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/LICENSE +21 -0
- package/README.md +46 -0
- package/dist/_headers +3 -0
- package/dist/bundle-report.json +564 -0
- package/dist/drip.debug.js +2 -0
- package/dist/drip.debug.js.map +1 -0
- package/dist/drip.heatmap.js +2 -0
- package/dist/drip.heatmap.js.map +1 -0
- package/dist/drip.js +2 -0
- package/dist/drip.js.map +1 -0
- package/dist/drip.live.js +2 -0
- package/dist/drip.live.js.map +1 -0
- package/dist/editor.js +480 -0
- package/dist/editor.js.map +7 -0
- package/dist/index.mjs +645 -0
- package/dist/index.mjs.map +7 -0
- package/dist/metafiles/drip.debug.meta.json +973 -0
- package/dist/metafiles/drip.heatmap.meta.json +918 -0
- package/dist/metafiles/drip.live.meta.json +918 -0
- package/dist/metafiles/drip.meta.json +973 -0
- package/dist/metafiles/editor.meta.json +321 -0
- package/dist/metafiles/index.meta.json +1039 -0
- package/dist/metafiles/index.mjs.meta.json +78 -0
- package/dist/react/index.js +16973 -0
- package/dist/react/index.js.map +7 -0
- package/dist/sri.json +27 -0
- package/dist/types/analytics.d.ts +15 -0
- package/dist/types/antiflicker.d.ts +14 -0
- package/dist/types/assignment-store.d.ts +30 -0
- package/dist/types/audit.d.ts +9 -0
- package/dist/types/bucket.d.ts +2 -0
- package/dist/types/bucketing-cleanup.d.ts +5 -0
- package/dist/types/commerce-gift.d.ts +41 -0
- package/dist/types/commerce-price.d.ts +22 -0
- package/dist/types/commerce-shipping.d.ts +28 -0
- package/dist/types/css.d.ts +5 -0
- package/dist/types/cwv.d.ts +10 -0
- package/dist/types/data-layer-normalize.d.ts +1 -0
- package/dist/types/debug.d.ts +23 -0
- package/dist/types/define.d.ts +87 -0
- package/dist/types/devtools.d.ts +32 -0
- package/dist/types/dom-trigger.d.ts +3 -0
- package/dist/types/editor/api.d.ts +37 -0
- package/dist/types/editor/artifacts.d.ts +15 -0
- package/dist/types/editor/command-runtime.d.ts +48 -0
- package/dist/types/editor/controller.d.ts +97 -0
- package/dist/types/editor/device-preview.d.ts +23 -0
- package/dist/types/editor/index.d.ts +9 -0
- package/dist/types/editor/operator.d.ts +39 -0
- package/dist/types/editor/picker.d.ts +23 -0
- package/dist/types/editor/selector.d.ts +2 -0
- package/dist/types/editor/types.d.ts +55 -0
- package/dist/types/editor/view-kit.d.ts +33 -0
- package/dist/types/editor/view.d.ts +5 -0
- package/dist/types/editor-bootstrap.d.ts +37 -0
- package/dist/types/exclusion-groups.d.ts +59 -0
- package/dist/types/exposure-signals.d.ts +7 -0
- package/dist/types/flags.d.ts +65 -0
- package/dist/types/goals.d.ts +16 -0
- package/dist/types/guards.d.ts +39 -0
- package/dist/types/handover.d.ts +10 -0
- package/dist/types/hash.d.ts +19 -0
- package/dist/types/heatmap.d.ts +8 -0
- package/dist/types/hideflicker.d.ts +15 -0
- package/dist/types/hydration.d.ts +11 -0
- package/dist/types/index.d.ts +144 -0
- package/dist/types/js.d.ts +6 -0
- package/dist/types/module.d.ts +4 -0
- package/dist/types/money.d.ts +14 -0
- package/dist/types/mutate.d.ts +34 -0
- package/dist/types/observer-mute.d.ts +3 -0
- package/dist/types/pii-keys.d.ts +1 -0
- package/dist/types/prerequisites.d.ts +12 -0
- package/dist/types/qa-assistant-state.d.ts +68 -0
- package/dist/types/qa-assistant-view.d.ts +6 -0
- package/dist/types/qa-assistant.d.ts +9 -0
- package/dist/types/qa-toolbar.d.ts +19 -0
- package/dist/types/react/index.d.ts +84 -0
- package/dist/types/reassert-sentinel.d.ts +6 -0
- package/dist/types/router.d.ts +9 -0
- package/dist/types/runtime-tools.d.ts +50 -0
- package/dist/types/runtime.d.ts +22 -0
- package/dist/types/safe-regex.d.ts +6 -0
- package/dist/types/sanitize.d.ts +5 -0
- package/dist/types/semantic.d.ts +7 -0
- package/dist/types/shopify-cart-events.d.ts +7 -0
- package/dist/types/shopify-cart.d.ts +62 -0
- package/dist/types/signals.d.ts +31 -0
- package/dist/types/surface-signals.d.ts +6 -0
- package/dist/types/targeting-diagnostics.d.ts +5 -0
- package/dist/types/targeting.d.ts +50 -0
- package/dist/types/test-fixtures/commerce.d.ts +12 -0
- package/dist/types/track.d.ts +79 -0
- package/dist/types/types.d.ts +859 -0
- package/dist/types/wait.d.ts +7 -0
- package/package.json +74 -0
- package/src/analytics.ts +146 -0
- package/src/antiflicker.test.ts +127 -0
- package/src/antiflicker.ts +147 -0
- package/src/assignment-store.test.ts +171 -0
- package/src/assignment-store.ts +208 -0
- package/src/audit.test.ts +17 -0
- package/src/audit.ts +362 -0
- package/src/bucket.test.ts +65 -0
- package/src/bucket.ts +18 -0
- package/src/bucketing-cleanup.test.ts +30 -0
- package/src/bucketing-cleanup.ts +72 -0
- package/src/bucketing-parity.test.ts +41 -0
- package/src/commerce-analytics-lifecycle.test.ts +1416 -0
- package/src/commerce-config-lifecycle.test.ts +274 -0
- package/src/commerce-epoch-lifecycle.test.ts +62 -0
- package/src/commerce-gift.test.ts +1293 -0
- package/src/commerce-gift.ts +979 -0
- package/src/commerce-offers-display.test.ts +154 -0
- package/src/commerce-price.test.ts +1145 -0
- package/src/commerce-price.ts +941 -0
- package/src/commerce-revocation-lifecycle.test.ts +78 -0
- package/src/commerce-shipping.test.ts +630 -0
- package/src/commerce-shipping.ts +447 -0
- package/src/config-fetch.test.ts +325 -0
- package/src/css.ts +54 -0
- package/src/cwv.test.ts +95 -0
- package/src/cwv.ts +129 -0
- package/src/data-layer-normalize.ts +21 -0
- package/src/debug.test.ts +83 -0
- package/src/debug.ts +138 -0
- package/src/define.test.ts +327 -0
- package/src/define.ts +208 -0
- package/src/devtools.ts +582 -0
- package/src/dom-trigger.test.ts +70 -0
- package/src/dom-trigger.ts +55 -0
- package/src/editor/api.test.ts +154 -0
- package/src/editor/api.ts +185 -0
- package/src/editor/artifacts.test.ts +57 -0
- package/src/editor/artifacts.ts +115 -0
- package/src/editor/command-runtime.test.ts +225 -0
- package/src/editor/command-runtime.ts +572 -0
- package/src/editor/controller.test.ts +371 -0
- package/src/editor/controller.ts +596 -0
- package/src/editor/device-preview.test.ts +60 -0
- package/src/editor/device-preview.ts +120 -0
- package/src/editor/index.test.ts +161 -0
- package/src/editor/index.ts +169 -0
- package/src/editor/operator.test.ts +148 -0
- package/src/editor/operator.ts +256 -0
- package/src/editor/picker.test.ts +58 -0
- package/src/editor/picker.ts +152 -0
- package/src/editor/selector.test.ts +44 -0
- package/src/editor/selector.ts +110 -0
- package/src/editor/types.ts +92 -0
- package/src/editor/view-kit.ts +162 -0
- package/src/editor/view.test.ts +535 -0
- package/src/editor/view.ts +1395 -0
- package/src/editor-bootstrap.test.ts +116 -0
- package/src/editor-bootstrap.ts +213 -0
- package/src/event-schema-contract.test.ts +35 -0
- package/src/exclusion-groups.test.ts +383 -0
- package/src/exclusion-groups.ts +270 -0
- package/src/exposure-signals.test.ts +182 -0
- package/src/exposure-signals.ts +110 -0
- package/src/flags.test.ts +322 -0
- package/src/flags.ts +201 -0
- package/src/goals.test.ts +42 -0
- package/src/goals.ts +200 -0
- package/src/guards.test.ts +249 -0
- package/src/guards.ts +250 -0
- package/src/handover-cache-order.test.ts +32 -0
- package/src/handover.test.ts +349 -0
- package/src/handover.ts +309 -0
- package/src/hash.ts +214 -0
- package/src/heatmap.test.ts +305 -0
- package/src/heatmap.ts +373 -0
- package/src/hideflicker.ts +21 -0
- package/src/hydration.test.ts +252 -0
- package/src/hydration.ts +203 -0
- package/src/index.ts +7513 -0
- package/src/init-empty.test.ts +5572 -0
- package/src/js.test.ts +26 -0
- package/src/js.ts +61 -0
- package/src/module.ts +50 -0
- package/src/money.test.ts +35 -0
- package/src/money.ts +53 -0
- package/src/mutate.test.ts +304 -0
- package/src/mutate.ts +469 -0
- package/src/observer-mute.test.ts +88 -0
- package/src/observer-mute.ts +45 -0
- package/src/page-trigger.test.ts +84 -0
- package/src/personalization.test.ts +68 -0
- package/src/pii-keys.ts +17 -0
- package/src/prerequisites.test.ts +39 -0
- package/src/prerequisites.ts +94 -0
- package/src/qa-assistant-state.test.ts +471 -0
- package/src/qa-assistant-state.ts +505 -0
- package/src/qa-assistant-view.test.ts +185 -0
- package/src/qa-assistant-view.ts +768 -0
- package/src/qa-assistant.ts +40 -0
- package/src/qa-toolbar.ts +444 -0
- package/src/react/index.test.tsx +177 -0
- package/src/react/index.tsx +252 -0
- package/src/reassert-sentinel.test.ts +314 -0
- package/src/reassert-sentinel.ts +191 -0
- package/src/router.test.ts +78 -0
- package/src/router.ts +92 -0
- package/src/runtime-tools.test.ts +112 -0
- package/src/runtime-tools.ts +403 -0
- package/src/runtime.test.ts +217 -0
- package/src/runtime.ts +268 -0
- package/src/safe-regex.ts +35 -0
- package/src/sanitize.ts +34 -0
- package/src/semantic.ts +245 -0
- package/src/shopify-cart-events.test.ts +76 -0
- package/src/shopify-cart-events.ts +115 -0
- package/src/shopify-cart.test.ts +2823 -0
- package/src/shopify-cart.ts +1256 -0
- package/src/signals.ts +226 -0
- package/src/surface-signals.test.ts +83 -0
- package/src/surface-signals.ts +165 -0
- package/src/targeting-diagnostics.ts +560 -0
- package/src/targeting.detailed.test.ts +443 -0
- package/src/targeting.test.ts +1054 -0
- package/src/targeting.ts +1024 -0
- package/src/test-fixtures/commerce.ts +65 -0
- package/src/track.test.ts +817 -0
- package/src/track.ts +519 -0
- package/src/types.ts +991 -0
- package/src/wait.test.ts +96 -0
- package/src/wait.ts +238 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,645 @@
|
|
|
1
|
+
// src/shopify-cart-events.ts
|
|
2
|
+
var suppressNotifications = 0;
|
|
3
|
+
function fetchWithoutShopifyCartMutationNotification(...args) {
|
|
4
|
+
suppressNotifications += 1;
|
|
5
|
+
try {
|
|
6
|
+
const activeFetch = typeof window.fetch === "function" ? window.fetch : globalThis.fetch;
|
|
7
|
+
return activeFetch.call(window, ...args);
|
|
8
|
+
} finally {
|
|
9
|
+
suppressNotifications -= 1;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// src/shopify-cart.ts
|
|
14
|
+
function isShopifyStorefront() {
|
|
15
|
+
return typeof window !== "undefined" && !!window.Shopify;
|
|
16
|
+
}
|
|
17
|
+
function shopifyRoutesRoot() {
|
|
18
|
+
const configuredRoot = window.Shopify?.routes?.root;
|
|
19
|
+
if (typeof configuredRoot !== "string") return "/";
|
|
20
|
+
try {
|
|
21
|
+
const storefrontOrigin = window.location?.origin;
|
|
22
|
+
if (!storefrontOrigin) return "/";
|
|
23
|
+
const parsed = new URL(configuredRoot, storefrontOrigin);
|
|
24
|
+
if (parsed.origin !== storefrontOrigin || parsed.search || parsed.hash) return "/";
|
|
25
|
+
return parsed.pathname.endsWith("/") ? parsed.pathname : `${parsed.pathname}/`;
|
|
26
|
+
} catch {
|
|
27
|
+
return "/";
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function shopifyCartPath() {
|
|
31
|
+
return `${shopifyRoutesRoot()}cart.js`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// src/commerce-gift.ts
|
|
35
|
+
var MARKER = "_apex_gwp";
|
|
36
|
+
var DECLINE_PREFIX = "drip_gwp_declined:";
|
|
37
|
+
var INSERTED_PREFIX = "drip_gwp_inserted:";
|
|
38
|
+
var ANY_CART = "*";
|
|
39
|
+
var inFlight = null;
|
|
40
|
+
var queuedArgs = null;
|
|
41
|
+
var insertedThisSession = /* @__PURE__ */ new Map();
|
|
42
|
+
var selectedGiftOptions = /* @__PURE__ */ new Map();
|
|
43
|
+
var dispatchedChoices = /* @__PURE__ */ new Set();
|
|
44
|
+
var activeChoiceTier = /* @__PURE__ */ new Map();
|
|
45
|
+
var choiceTierGeneration = 0;
|
|
46
|
+
var latestArgs = null;
|
|
47
|
+
function giftTiers(variant) {
|
|
48
|
+
const raw = Array.isArray(variant.tiers) && variant.tiers.length > 0 ? variant.tiers : [{ threshold: variant.threshold, gift_variant_gid: variant.gift_variant_gid }];
|
|
49
|
+
const tiers = [];
|
|
50
|
+
for (const item of raw) {
|
|
51
|
+
if (!item || typeof item !== "object" || Array.isArray(item)) return null;
|
|
52
|
+
const tier = item;
|
|
53
|
+
if (typeof tier.threshold !== "string" || !/^\d+$/.test(tier.threshold) || typeof tier.gift_variant_gid !== "string" || // Malformed fixed-tier GIDs would reach choice dispatch with a null
|
|
54
|
+
// giftId and abort reconciliation mid-run; money-path config fails
|
|
55
|
+
// closed at parse time instead.
|
|
56
|
+
numericVariantId(tier.gift_variant_gid) === null) return null;
|
|
57
|
+
const choices = tier.gift_choice_variant_gids;
|
|
58
|
+
if (choices !== void 0 && (!Array.isArray(choices) || choices.length < 2 || choices.length > 4 || !choices.every((gid) => typeof gid === "string" && numericVariantId(gid) !== null))) return null;
|
|
59
|
+
tiers.push({
|
|
60
|
+
threshold: tier.threshold,
|
|
61
|
+
gift_variant_gid: tier.gift_variant_gid,
|
|
62
|
+
...choices ? { gift_choice_variant_gids: choices } : {}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
if (tiers.length < 1 || tiers.length > 3 || tiers.some((tier, index) => !Number.isSafeInteger(Number(tier.threshold)) || index > 0 && Number(tier.threshold) <= Number(tiers[index - 1].threshold))) return null;
|
|
66
|
+
return tiers;
|
|
67
|
+
}
|
|
68
|
+
function declined(experimentId) {
|
|
69
|
+
try {
|
|
70
|
+
return sessionStorage.getItem(`${DECLINE_PREFIX}${experimentId}`) === "1";
|
|
71
|
+
} catch {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function recordDecline(experimentId) {
|
|
76
|
+
try {
|
|
77
|
+
sessionStorage.setItem(`${DECLINE_PREFIX}${experimentId}`, "1");
|
|
78
|
+
} catch {
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function insertionRecord(experimentId) {
|
|
82
|
+
try {
|
|
83
|
+
return localStorage.getItem(`${INSERTED_PREFIX}${experimentId}`) ?? insertedThisSession.get(experimentId) ?? null;
|
|
84
|
+
} catch {
|
|
85
|
+
return insertedThisSession.get(experimentId) ?? null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function recordCart(record) {
|
|
89
|
+
if (!record.startsWith("{")) return record;
|
|
90
|
+
try {
|
|
91
|
+
const parsed = JSON.parse(record);
|
|
92
|
+
return typeof parsed.cart === "string" ? parsed.cart : record;
|
|
93
|
+
} catch {
|
|
94
|
+
return record;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function recordVariantGid(record) {
|
|
98
|
+
if (!record.startsWith("{")) return null;
|
|
99
|
+
try {
|
|
100
|
+
const parsed = JSON.parse(record);
|
|
101
|
+
return typeof parsed.variantGid === "string" ? parsed.variantGid : null;
|
|
102
|
+
} catch {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function recordTierThreshold(record) {
|
|
107
|
+
if (!record.startsWith("{")) return null;
|
|
108
|
+
try {
|
|
109
|
+
const parsed = JSON.parse(record);
|
|
110
|
+
return typeof parsed.tierThreshold === "string" ? parsed.tierThreshold : null;
|
|
111
|
+
} catch {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function insertionMatchesCart(record, cartToken) {
|
|
116
|
+
const token = recordCart(record);
|
|
117
|
+
return token === ANY_CART || cartToken == null || token === cartToken;
|
|
118
|
+
}
|
|
119
|
+
function recordInserted(experimentId, cartToken, variantGid, tierThreshold) {
|
|
120
|
+
const token = cartToken ?? ANY_CART;
|
|
121
|
+
const value = variantGid || tierThreshold ? JSON.stringify({ cart: token, variantGid, tierThreshold }) : token;
|
|
122
|
+
insertedThisSession.set(experimentId, value);
|
|
123
|
+
try {
|
|
124
|
+
localStorage.setItem(`${INSERTED_PREFIX}${experimentId}`, value);
|
|
125
|
+
} catch {
|
|
126
|
+
}
|
|
127
|
+
const selection = selectedGiftOptions.get(experimentId);
|
|
128
|
+
if (selection?.pending && selection.gid === variantGid) {
|
|
129
|
+
selectedGiftOptions.set(experimentId, {
|
|
130
|
+
gid: selection.gid,
|
|
131
|
+
tierThreshold: selection.tierThreshold
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
function clearInserted(experimentId) {
|
|
136
|
+
insertedThisSession.delete(experimentId);
|
|
137
|
+
try {
|
|
138
|
+
localStorage.removeItem(`${INSERTED_PREFIX}${experimentId}`);
|
|
139
|
+
} catch {
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function clearDispatchedChoices(experimentId) {
|
|
143
|
+
dispatchedChoices.forEach((key) => {
|
|
144
|
+
if (key.startsWith(`${experimentId}:`)) dispatchedChoices.delete(key);
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
function listInsertionRecords() {
|
|
148
|
+
const ids = new Set(insertedThisSession.keys());
|
|
149
|
+
try {
|
|
150
|
+
for (let i = 0; i < localStorage.length; i += 1) {
|
|
151
|
+
const key = localStorage.key(i);
|
|
152
|
+
if (key?.startsWith(INSERTED_PREFIX)) ids.add(key.slice(INSERTED_PREFIX.length));
|
|
153
|
+
}
|
|
154
|
+
} catch {
|
|
155
|
+
}
|
|
156
|
+
return [...ids];
|
|
157
|
+
}
|
|
158
|
+
function hasInsertionRecords() {
|
|
159
|
+
return listInsertionRecords().length > 0;
|
|
160
|
+
}
|
|
161
|
+
var teardownChecked = false;
|
|
162
|
+
function markTeardownChecked() {
|
|
163
|
+
teardownChecked = true;
|
|
164
|
+
}
|
|
165
|
+
function numericVariantId(gid) {
|
|
166
|
+
const match = /^gid:\/\/shopify\/ProductVariant\/(\d+)$/.exec(gid);
|
|
167
|
+
if (!match) return null;
|
|
168
|
+
const id = Number(match[1]);
|
|
169
|
+
return Number.isSafeInteger(id) && id > 0 ? id : null;
|
|
170
|
+
}
|
|
171
|
+
function marker(line) {
|
|
172
|
+
if (!line.properties || typeof line.properties !== "object" || Array.isArray(line.properties)) return null;
|
|
173
|
+
const value = line.properties[MARKER];
|
|
174
|
+
return typeof value === "string" ? value : null;
|
|
175
|
+
}
|
|
176
|
+
function lineVariantId(line) {
|
|
177
|
+
if (typeof line.variant_id === "number" && Number.isSafeInteger(line.variant_id)) return String(line.variant_id);
|
|
178
|
+
if (typeof line.variant_id === "string" && /^\d+$/.test(line.variant_id)) return line.variant_id;
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
function lineAmount(line) {
|
|
182
|
+
const value = line.line_price;
|
|
183
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : null;
|
|
184
|
+
}
|
|
185
|
+
async function mutate(path, body) {
|
|
186
|
+
try {
|
|
187
|
+
const response = await fetchWithoutShopifyCartMutationNotification(path, {
|
|
188
|
+
method: "POST",
|
|
189
|
+
headers: { "Content-Type": "application/json" },
|
|
190
|
+
body: JSON.stringify(body)
|
|
191
|
+
});
|
|
192
|
+
return response.ok;
|
|
193
|
+
} catch {
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
async function run(settings, assignments, options, generation) {
|
|
198
|
+
if (!isShopifyStorefront() || typeof fetch !== "function") return false;
|
|
199
|
+
let response;
|
|
200
|
+
try {
|
|
201
|
+
response = await fetchWithoutShopifyCartMutationNotification(shopifyCartPath(), {
|
|
202
|
+
method: "GET",
|
|
203
|
+
headers: { Accept: "application/json" },
|
|
204
|
+
cache: "no-store"
|
|
205
|
+
});
|
|
206
|
+
} catch {
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
if (!response.ok) return false;
|
|
210
|
+
const cart = await response.json();
|
|
211
|
+
if (!Array.isArray(cart.items) || typeof cart.currency !== "string") return false;
|
|
212
|
+
let cartMutated = false;
|
|
213
|
+
const lines = cart.items.filter((item) => !!item && typeof item === "object");
|
|
214
|
+
const cartToken = typeof cart.token === "string" && cart.token ? cart.token : null;
|
|
215
|
+
const assigned = new Map(assignments.map((item) => [item.experimentId, item.variationId]));
|
|
216
|
+
const chargeOnlyExperimentIds = new Set(
|
|
217
|
+
assignments.filter((item) => item.commercePriceOnly).map((item) => item.experimentId)
|
|
218
|
+
);
|
|
219
|
+
const experiments = settings?.experiments ?? [];
|
|
220
|
+
const authorizedOfferExperimentIds = new Set(
|
|
221
|
+
settings?.authorization?.experimentIds ?? []
|
|
222
|
+
);
|
|
223
|
+
const root = shopifyRoutesRoot();
|
|
224
|
+
const changePath = `${root}cart/change.js`;
|
|
225
|
+
const insertedVariantIdsThisRun = /* @__PURE__ */ new Set();
|
|
226
|
+
const removedLineKeys = /* @__PURE__ */ new Set();
|
|
227
|
+
const removeLine = async (line) => {
|
|
228
|
+
if (typeof line.key !== "string") return false;
|
|
229
|
+
if (!await mutate(changePath, { id: line.key, quantity: 0 })) return false;
|
|
230
|
+
removedLineKeys.add(line.key);
|
|
231
|
+
cartMutated = true;
|
|
232
|
+
return true;
|
|
233
|
+
};
|
|
234
|
+
const linePresent = (line) => typeof line.key === "string" ? !removedLineKeys.has(line.key) : true;
|
|
235
|
+
const activeGiftExperiments = new Set(
|
|
236
|
+
experiments.filter((experiment) => {
|
|
237
|
+
const variationId = assigned.get(experiment.experiment_id);
|
|
238
|
+
const variant = variationId ? experiment.variants[variationId] : void 0;
|
|
239
|
+
if (!variant || typeof variant !== "object") return false;
|
|
240
|
+
if (options?.isArmProven) {
|
|
241
|
+
const assignment = assignments.find(
|
|
242
|
+
(candidate) => candidate.experimentId === experiment.experiment_id
|
|
243
|
+
);
|
|
244
|
+
if (!assignment || !options.isArmProven(assignment)) return false;
|
|
245
|
+
}
|
|
246
|
+
if ("control" in variant && variant.control === true) return true;
|
|
247
|
+
return "offer_type" in variant && variant.offer_type === "gwp_threshold" && giftTiers(variant) !== null;
|
|
248
|
+
}).map((experiment) => experiment.experiment_id)
|
|
249
|
+
);
|
|
250
|
+
for (const line of lines) {
|
|
251
|
+
const mark = marker(line);
|
|
252
|
+
if (mark == null || activeGiftExperiments.has(mark)) continue;
|
|
253
|
+
recordInserted(mark, cartToken);
|
|
254
|
+
if (await removeLine(line)) clearInserted(mark);
|
|
255
|
+
}
|
|
256
|
+
for (const experimentId of listInsertionRecords()) {
|
|
257
|
+
if (activeGiftExperiments.has(experimentId)) continue;
|
|
258
|
+
if (lines.some((line) => marker(line) === experimentId && linePresent(line))) continue;
|
|
259
|
+
clearInserted(experimentId);
|
|
260
|
+
}
|
|
261
|
+
if (settings && experiments.length === 0) markTeardownChecked();
|
|
262
|
+
for (const experiment of experiments) {
|
|
263
|
+
activeChoiceTier.delete(experiment.experiment_id);
|
|
264
|
+
const variationId = assigned.get(experiment.experiment_id);
|
|
265
|
+
if (!variationId) continue;
|
|
266
|
+
const variant = experiment.variants[variationId];
|
|
267
|
+
if (!variant || typeof variant !== "object") continue;
|
|
268
|
+
const managedLines = () => lines.filter(
|
|
269
|
+
(line) => marker(line) === experiment.experiment_id && linePresent(line)
|
|
270
|
+
);
|
|
271
|
+
const removeAllManaged = async () => {
|
|
272
|
+
let allRemoved = true;
|
|
273
|
+
for (const line of managedLines()) {
|
|
274
|
+
if (typeof line.key !== "string") continue;
|
|
275
|
+
if (!await removeLine(line)) {
|
|
276
|
+
allRemoved = false;
|
|
277
|
+
cartMutated = true;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
return allRemoved;
|
|
281
|
+
};
|
|
282
|
+
if ("control" in variant && variant.control === true) {
|
|
283
|
+
if (await removeAllManaged()) clearInserted(experiment.experiment_id);
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
if (!("offer_type" in variant) || variant.offer_type !== "gwp_threshold") continue;
|
|
287
|
+
const tiers = giftTiers(variant);
|
|
288
|
+
if (!tiers) continue;
|
|
289
|
+
if (cart.currency.toUpperCase() !== experiment.currency.toUpperCase()) {
|
|
290
|
+
if (await removeAllManaged()) clearInserted(experiment.experiment_id);
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
const allGiftIds = new Set(tiers.flatMap((tier) => tier.gift_choice_variant_gids ?? [tier.gift_variant_gid]).map(numericVariantId).filter((id) => id !== null).map(String));
|
|
294
|
+
let subtotal = 0;
|
|
295
|
+
let valid = true;
|
|
296
|
+
for (const line of lines) {
|
|
297
|
+
if (!linePresent(line) || allGiftIds.has(lineVariantId(line) ?? "")) continue;
|
|
298
|
+
const amount = lineAmount(line);
|
|
299
|
+
if (amount == null || !Number.isSafeInteger(subtotal + amount)) {
|
|
300
|
+
valid = false;
|
|
301
|
+
break;
|
|
302
|
+
}
|
|
303
|
+
subtotal += amount;
|
|
304
|
+
}
|
|
305
|
+
const applicableTier = valid ? tiers.reduce((chosen, tier) => {
|
|
306
|
+
const threshold = Number(tier.threshold);
|
|
307
|
+
return Number.isSafeInteger(threshold) && threshold >= 0 && subtotal >= threshold ? tier : chosen;
|
|
308
|
+
}, null) : null;
|
|
309
|
+
if (!valid || tiers.some((tier) => !Number.isSafeInteger(Number(tier.threshold)))) {
|
|
310
|
+
for (const line of managedLines()) {
|
|
311
|
+
if (typeof line.key !== "string") continue;
|
|
312
|
+
await removeLine(line);
|
|
313
|
+
}
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
if (!applicableTier) {
|
|
317
|
+
clearDispatchedChoices(experiment.experiment_id);
|
|
318
|
+
activeChoiceTier.delete(experiment.experiment_id);
|
|
319
|
+
if (await removeAllManaged()) clearInserted(experiment.experiment_id);
|
|
320
|
+
continue;
|
|
321
|
+
}
|
|
322
|
+
const choiceGids = applicableTier.gift_choice_variant_gids;
|
|
323
|
+
if (generation === choiceTierGeneration) {
|
|
324
|
+
const currentKey = choiceGids ? `${experiment.experiment_id}:${applicableTier.threshold}:${choiceGids.join(",")}` : null;
|
|
325
|
+
dispatchedChoices.forEach((key) => {
|
|
326
|
+
if (key.startsWith(`${experiment.experiment_id}:`) && key !== currentKey) {
|
|
327
|
+
dispatchedChoices.delete(key);
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
const markChoicePromptLive = () => {
|
|
332
|
+
if (choiceGids && !options?.suppressInsertion && authorizedOfferExperimentIds.has(experiment.experiment_id) && !declined(experiment.experiment_id)) {
|
|
333
|
+
const assignment = assignments.find(
|
|
334
|
+
(candidate) => candidate.experimentId === experiment.experiment_id
|
|
335
|
+
);
|
|
336
|
+
if ((!options?.isArmProven || assignment && options.isArmProven(assignment)) && generation === choiceTierGeneration) {
|
|
337
|
+
activeChoiceTier.set(experiment.experiment_id, applicableTier.threshold);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
};
|
|
341
|
+
const extendedRecord = Array.isArray(variant.tiers);
|
|
342
|
+
const persistedRecord = insertionRecord(experiment.experiment_id);
|
|
343
|
+
const persistedGid = persistedRecord && insertionMatchesCart(persistedRecord, cartToken) ? recordVariantGid(persistedRecord) : null;
|
|
344
|
+
const lowestChoiceTierThresholdFor = (gid) => gid == null ? void 0 : tiers.find((tier) => tier.gift_choice_variant_gids?.includes(gid))?.threshold;
|
|
345
|
+
const persistedTierThreshold = persistedRecord === null ? null : recordTierThreshold(persistedRecord);
|
|
346
|
+
const tierlessRecoveryAllowed = (gid) => lowestChoiceTierThresholdFor(gid) === applicableTier.threshold;
|
|
347
|
+
const inMemorySelection = selectedGiftOptions.get(experiment.experiment_id);
|
|
348
|
+
let inMemoryGid = inMemorySelection?.tierThreshold === applicableTier.threshold ? inMemorySelection.gid : void 0;
|
|
349
|
+
const markedCurrentTierGid = choiceGids?.find((gid) => {
|
|
350
|
+
const variantId = numericVariantId(gid);
|
|
351
|
+
return variantId !== null && lines.some((line) => linePresent(line) && marker(line) === experiment.experiment_id && lineVariantId(line) === String(variantId));
|
|
352
|
+
});
|
|
353
|
+
const persistedChoiceIsCurrentTier = persistedRecord !== null && (persistedTierThreshold === applicableTier.threshold || persistedTierThreshold === null && tierlessRecoveryAllowed(persistedGid ?? markedCurrentTierGid));
|
|
354
|
+
if (inMemorySelection && inMemoryGid) {
|
|
355
|
+
const persistedCurrentTierGid = persistedChoiceIsCurrentTier && choiceGids?.includes(persistedGid ?? "") ? persistedGid : null;
|
|
356
|
+
if (inMemorySelection.pending && persistedCurrentTierGid === inMemoryGid) {
|
|
357
|
+
selectedGiftOptions.set(experiment.experiment_id, {
|
|
358
|
+
gid: inMemorySelection.gid,
|
|
359
|
+
tierThreshold: inMemorySelection.tierThreshold
|
|
360
|
+
});
|
|
361
|
+
} else if (!inMemorySelection.pending && persistedCurrentTierGid && persistedCurrentTierGid !== inMemoryGid) {
|
|
362
|
+
selectedGiftOptions.delete(experiment.experiment_id);
|
|
363
|
+
inMemoryGid = void 0;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
const selectedGid = choiceGids?.includes(inMemoryGid ?? "") ? inMemoryGid : persistedChoiceIsCurrentTier && choiceGids?.includes(persistedGid ?? "") ? persistedGid : persistedChoiceIsCurrentTier ? markedCurrentTierGid : void 0;
|
|
367
|
+
if (selectedGid) {
|
|
368
|
+
const priorPending = selectedGiftOptions.get(experiment.experiment_id)?.gid === selectedGid && selectedGiftOptions.get(experiment.experiment_id)?.pending === true;
|
|
369
|
+
selectedGiftOptions.set(experiment.experiment_id, {
|
|
370
|
+
gid: selectedGid,
|
|
371
|
+
tierThreshold: applicableTier.threshold,
|
|
372
|
+
...priorPending ? { pending: true } : {}
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
const desiredGid = choiceGids ? selectedGid : applicableTier.gift_variant_gid;
|
|
376
|
+
const giftId = desiredGid ? numericVariantId(desiredGid) : null;
|
|
377
|
+
const allowedCurrentIds = new Set((choiceGids ?? [applicableTier.gift_variant_gid]).map(numericVariantId).filter((id) => id !== null).map(String));
|
|
378
|
+
let managed;
|
|
379
|
+
let staleRemovalFailed = false;
|
|
380
|
+
let removedStaleForExperiment = false;
|
|
381
|
+
for (const line of managedLines()) {
|
|
382
|
+
if (!managed && giftId !== null && lineVariantId(line) === String(giftId)) {
|
|
383
|
+
managed = line;
|
|
384
|
+
continue;
|
|
385
|
+
}
|
|
386
|
+
if (typeof line.key !== "string") continue;
|
|
387
|
+
if (await removeLine(line)) removedStaleForExperiment = true;
|
|
388
|
+
else staleRemovalFailed = true;
|
|
389
|
+
}
|
|
390
|
+
if (staleRemovalFailed) cartMutated = true;
|
|
391
|
+
if (staleRemovalFailed && !managed) continue;
|
|
392
|
+
if (!managed && removedStaleForExperiment) {
|
|
393
|
+
clearInserted(experiment.experiment_id);
|
|
394
|
+
}
|
|
395
|
+
if (managed && lines.some((line) => line !== managed && linePresent(line) && marker(line) !== experiment.experiment_id && allowedCurrentIds.has(lineVariantId(line) ?? ""))) {
|
|
396
|
+
if (typeof managed.key === "string" && await removeLine(managed)) {
|
|
397
|
+
clearInserted(experiment.experiment_id);
|
|
398
|
+
} else {
|
|
399
|
+
cartMutated = true;
|
|
400
|
+
}
|
|
401
|
+
continue;
|
|
402
|
+
}
|
|
403
|
+
if (!desiredGid || giftId === null) {
|
|
404
|
+
clearInserted(experiment.experiment_id);
|
|
405
|
+
markChoicePromptLive();
|
|
406
|
+
if (!options?.suppressInsertion && authorizedOfferExperimentIds.has(experiment.experiment_id) && !declined(experiment.experiment_id)) {
|
|
407
|
+
const assignment = assignments.find((candidate) => candidate.experimentId === experiment.experiment_id);
|
|
408
|
+
if (!options?.isArmProven || assignment && options.isArmProven(assignment)) {
|
|
409
|
+
const eventKey = `${experiment.experiment_id}:${applicableTier.threshold}:${choiceGids.join(",")}`;
|
|
410
|
+
if (generation === choiceTierGeneration) {
|
|
411
|
+
if (!dispatchedChoices.has(eventKey) && typeof window !== "undefined") {
|
|
412
|
+
dispatchedChoices.add(eventKey);
|
|
413
|
+
emitChoicePrompt({ experimentId: experiment.experiment_id, threshold: applicableTier.threshold, options: [...choiceGids] });
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
continue;
|
|
419
|
+
}
|
|
420
|
+
if (managed) {
|
|
421
|
+
markChoicePromptLive();
|
|
422
|
+
if (options?.suppressInsertion) {
|
|
423
|
+
const record2 = insertionRecord(experiment.experiment_id);
|
|
424
|
+
if (!record2 || !insertionMatchesCart(record2, cartToken)) {
|
|
425
|
+
if (await removeAllManaged()) clearInserted(experiment.experiment_id);
|
|
426
|
+
continue;
|
|
427
|
+
}
|
|
428
|
+
} else {
|
|
429
|
+
recordInserted(experiment.experiment_id, cartToken, extendedRecord ? desiredGid : void 0, extendedRecord ? applicableTier.threshold : void 0);
|
|
430
|
+
}
|
|
431
|
+
if (typeof managed.key === "string" && typeof managed.quantity === "number" && managed.quantity !== 1) {
|
|
432
|
+
cartMutated = true;
|
|
433
|
+
await mutate(changePath, { id: managed.key, quantity: 1 });
|
|
434
|
+
}
|
|
435
|
+
continue;
|
|
436
|
+
}
|
|
437
|
+
if (chargeOnlyExperimentIds.has(experiment.experiment_id)) {
|
|
438
|
+
if (insertionRecord(experiment.experiment_id) != null && lines.some(
|
|
439
|
+
(line) => !linePresent(line) && allowedCurrentIds.has(lineVariantId(line) ?? "")
|
|
440
|
+
)) {
|
|
441
|
+
clearInserted(experiment.experiment_id);
|
|
442
|
+
}
|
|
443
|
+
continue;
|
|
444
|
+
}
|
|
445
|
+
const satisfyingLine = lines.find(
|
|
446
|
+
(line) => linePresent(line) && allowedCurrentIds.has(lineVariantId(line) ?? "")
|
|
447
|
+
);
|
|
448
|
+
const insertedAllowedId = [...insertedVariantIdsThisRun].find((id) => allowedCurrentIds.has(id));
|
|
449
|
+
if (satisfyingLine || insertedAllowedId) {
|
|
450
|
+
markChoicePromptLive();
|
|
451
|
+
if (insertedAllowedId || satisfyingLine && marker(satisfyingLine) != null) {
|
|
452
|
+
const satisfyingGid = satisfyingLine ? choiceGids?.find((gid) => String(numericVariantId(gid)) === lineVariantId(satisfyingLine)) : choiceGids?.find((gid) => String(numericVariantId(gid)) === insertedAllowedId);
|
|
453
|
+
recordInserted(experiment.experiment_id, cartToken, extendedRecord ? satisfyingGid ?? desiredGid : void 0, extendedRecord ? applicableTier.threshold : void 0);
|
|
454
|
+
}
|
|
455
|
+
continue;
|
|
456
|
+
}
|
|
457
|
+
const record = insertionRecord(experiment.experiment_id);
|
|
458
|
+
if (record != null) {
|
|
459
|
+
clearInserted(experiment.experiment_id);
|
|
460
|
+
const removedByUsThisRun = lines.some(
|
|
461
|
+
(line) => !linePresent(line) && lineVariantId(line) === String(giftId)
|
|
462
|
+
);
|
|
463
|
+
if (!removedByUsThisRun && insertionMatchesCart(record, cartToken)) {
|
|
464
|
+
recordDecline(experiment.experiment_id);
|
|
465
|
+
continue;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
if (declined(experiment.experiment_id)) continue;
|
|
469
|
+
if (options?.suppressInsertion) continue;
|
|
470
|
+
if (!authorizedOfferExperimentIds.has(experiment.experiment_id)) continue;
|
|
471
|
+
if (options?.isArmProven) {
|
|
472
|
+
const localAssignment = assignments.find(
|
|
473
|
+
(candidate) => candidate.experimentId === experiment.experiment_id
|
|
474
|
+
);
|
|
475
|
+
if (!localAssignment || !options.isArmProven(localAssignment)) continue;
|
|
476
|
+
}
|
|
477
|
+
const addResponse = await fetchWithoutShopifyCartMutationNotification(`${root}cart/add.js`, {
|
|
478
|
+
method: "POST",
|
|
479
|
+
headers: { "Content-Type": "application/json" },
|
|
480
|
+
body: JSON.stringify({
|
|
481
|
+
items: [{ id: giftId, quantity: 1, properties: { [MARKER]: experiment.experiment_id } }]
|
|
482
|
+
})
|
|
483
|
+
}).catch(() => null);
|
|
484
|
+
if (!addResponse?.ok) {
|
|
485
|
+
const failedSelection = selectedGiftOptions.get(experiment.experiment_id);
|
|
486
|
+
if (choiceGids && failedSelection?.gid === desiredGid) {
|
|
487
|
+
selectedGiftOptions.delete(experiment.experiment_id);
|
|
488
|
+
clearDispatchedChoices(experiment.experiment_id);
|
|
489
|
+
markChoicePromptLive();
|
|
490
|
+
if (generation === choiceTierGeneration && typeof window !== "undefined") {
|
|
491
|
+
const retryKey = `${experiment.experiment_id}:${applicableTier.threshold}:${choiceGids.join(",")}`;
|
|
492
|
+
if (!dispatchedChoices.has(retryKey)) {
|
|
493
|
+
dispatchedChoices.add(retryKey);
|
|
494
|
+
emitChoicePrompt({ experimentId: experiment.experiment_id, threshold: applicableTier.threshold, options: [...choiceGids] });
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
continue;
|
|
499
|
+
}
|
|
500
|
+
if (addResponse?.ok) {
|
|
501
|
+
cartMutated = true;
|
|
502
|
+
recordInserted(experiment.experiment_id, cartToken, extendedRecord ? desiredGid : void 0, extendedRecord ? applicableTier.threshold : void 0);
|
|
503
|
+
insertedVariantIdsThisRun.add(String(giftId));
|
|
504
|
+
try {
|
|
505
|
+
const body = await addResponse.json();
|
|
506
|
+
const addedLine = Array.isArray(body.items) ? body.items.find((item) => !!item && typeof item === "object" && marker(item) === experiment.experiment_id) : void 0;
|
|
507
|
+
if (addedLine && typeof addedLine.key === "string" && typeof addedLine.quantity === "number" && addedLine.quantity > 1) {
|
|
508
|
+
cartMutated = true;
|
|
509
|
+
await mutate(changePath, { id: addedLine.key, quantity: 1 });
|
|
510
|
+
}
|
|
511
|
+
} catch {
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
return cartMutated;
|
|
516
|
+
}
|
|
517
|
+
function syncGiftWithPurchase(settings, assignments, options) {
|
|
518
|
+
latestArgs = { settings, assignments, options };
|
|
519
|
+
installChoiceRequestListener();
|
|
520
|
+
choiceTierGeneration += 1;
|
|
521
|
+
const batchGeneration = choiceTierGeneration;
|
|
522
|
+
activeChoiceTier.clear();
|
|
523
|
+
if (options?.recheckTeardown) teardownChecked = false;
|
|
524
|
+
if (!settings?.experiments.length && !hasInsertionRecords()) {
|
|
525
|
+
if (!settings || teardownChecked) return Promise.resolve();
|
|
526
|
+
}
|
|
527
|
+
if (inFlight) {
|
|
528
|
+
queuedArgs = { settings, assignments, options, generation: batchGeneration };
|
|
529
|
+
return inFlight;
|
|
530
|
+
}
|
|
531
|
+
const runToFixpoint = async (nextSettings, nextAssignments, nextOptions, generation) => {
|
|
532
|
+
let anyMutated = false;
|
|
533
|
+
for (let pass = 0; pass < 3; pass += 1) {
|
|
534
|
+
const mutated = await run(nextSettings, nextAssignments, nextOptions, generation).catch(() => false);
|
|
535
|
+
if (mutated) anyMutated = true;
|
|
536
|
+
if (!mutated) break;
|
|
537
|
+
}
|
|
538
|
+
if (anyMutated && typeof window !== "undefined") {
|
|
539
|
+
try {
|
|
540
|
+
window.dispatchEvent(
|
|
541
|
+
new CustomEvent("apex:cart:changed", { detail: { source: "gwp_gift" } })
|
|
542
|
+
);
|
|
543
|
+
} catch {
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
};
|
|
547
|
+
const pending = (async () => {
|
|
548
|
+
await runToFixpoint(settings, assignments, options, batchGeneration);
|
|
549
|
+
while (queuedArgs) {
|
|
550
|
+
const next = queuedArgs;
|
|
551
|
+
queuedArgs = null;
|
|
552
|
+
await runToFixpoint(next.settings, next.assignments, next.options, next.generation);
|
|
553
|
+
}
|
|
554
|
+
if (choiceReplayRequested) getPendingGiftChoices().forEach(emitChoicePrompt);
|
|
555
|
+
choiceReplayRequested = false;
|
|
556
|
+
})().finally(() => {
|
|
557
|
+
if (inFlight === pending) inFlight = null;
|
|
558
|
+
if (!inFlight && queuedArgs) {
|
|
559
|
+
const next = queuedArgs;
|
|
560
|
+
queuedArgs = null;
|
|
561
|
+
void syncGiftWithPurchase(next.settings, next.assignments, next.options);
|
|
562
|
+
}
|
|
563
|
+
});
|
|
564
|
+
inFlight = pending;
|
|
565
|
+
return pending;
|
|
566
|
+
}
|
|
567
|
+
function selectGiftOption(experimentId, variantGid) {
|
|
568
|
+
if (!latestArgs || numericVariantId(variantGid) === null) return Promise.resolve();
|
|
569
|
+
const experiment = latestArgs.settings?.experiments.find((item) => item.experiment_id === experimentId);
|
|
570
|
+
const variationId = latestArgs.assignments.find((item) => item.experimentId === experimentId)?.variationId;
|
|
571
|
+
const variant = variationId ? experiment?.variants[variationId] : void 0;
|
|
572
|
+
if (!variant || typeof variant !== "object") return Promise.resolve();
|
|
573
|
+
const tiers = giftTiers(variant);
|
|
574
|
+
const containingTiers = tiers?.filter((tier) => tier.gift_choice_variant_gids?.includes(variantGid)) ?? [];
|
|
575
|
+
const applicableThreshold = activeChoiceTier.get(experimentId);
|
|
576
|
+
const owningTier = containingTiers.find(
|
|
577
|
+
(tier) => tier.threshold === applicableThreshold
|
|
578
|
+
);
|
|
579
|
+
if (!owningTier) return Promise.resolve();
|
|
580
|
+
selectedGiftOptions.set(experimentId, {
|
|
581
|
+
gid: variantGid,
|
|
582
|
+
tierThreshold: owningTier.threshold,
|
|
583
|
+
pending: true
|
|
584
|
+
});
|
|
585
|
+
clearDispatchedChoices(experimentId);
|
|
586
|
+
return syncGiftWithPurchase(latestArgs.settings, latestArgs.assignments, latestArgs.options);
|
|
587
|
+
}
|
|
588
|
+
function emitChoicePrompt(detail) {
|
|
589
|
+
dispatchEvent(new CustomEvent("apex:gwp:choice", { detail }));
|
|
590
|
+
}
|
|
591
|
+
var choiceRequestListenerInstalled = false;
|
|
592
|
+
var choiceReplayRequested = false;
|
|
593
|
+
function installChoiceRequestListener() {
|
|
594
|
+
if (choiceRequestListenerInstalled || typeof window === "undefined") return;
|
|
595
|
+
choiceRequestListenerInstalled = true;
|
|
596
|
+
window.addEventListener("apex:gwp:choice:request", () => {
|
|
597
|
+
if (inFlight) choiceReplayRequested = true;
|
|
598
|
+
getPendingGiftChoices().forEach(emitChoicePrompt);
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
function getPendingGiftChoices(experimentId) {
|
|
602
|
+
if (!latestArgs) return [];
|
|
603
|
+
const prompts = [];
|
|
604
|
+
for (const [activeExperimentId, threshold] of activeChoiceTier) {
|
|
605
|
+
if (experimentId !== void 0 && activeExperimentId !== experimentId) continue;
|
|
606
|
+
const selected = selectedGiftOptions.get(activeExperimentId);
|
|
607
|
+
if (selected?.tierThreshold === threshold) continue;
|
|
608
|
+
const experiment = latestArgs.settings?.experiments.find(
|
|
609
|
+
(item) => item.experiment_id === activeExperimentId
|
|
610
|
+
);
|
|
611
|
+
const variationId = latestArgs.assignments.find(
|
|
612
|
+
(item) => item.experimentId === activeExperimentId
|
|
613
|
+
)?.variationId;
|
|
614
|
+
const variant = variationId ? experiment?.variants[variationId] : void 0;
|
|
615
|
+
if (!variant || typeof variant !== "object") continue;
|
|
616
|
+
const tier = giftTiers(variant)?.find(
|
|
617
|
+
(candidate) => candidate.threshold === threshold
|
|
618
|
+
);
|
|
619
|
+
if (!tier?.gift_choice_variant_gids) continue;
|
|
620
|
+
prompts.push({
|
|
621
|
+
experimentId: activeExperimentId,
|
|
622
|
+
threshold,
|
|
623
|
+
options: [...tier.gift_choice_variant_gids]
|
|
624
|
+
});
|
|
625
|
+
}
|
|
626
|
+
return prompts;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
// src/module.ts
|
|
630
|
+
function activeRuntime() {
|
|
631
|
+
return typeof window === "undefined" ? void 0 : window.drip;
|
|
632
|
+
}
|
|
633
|
+
function getPendingGiftChoices2(experimentId) {
|
|
634
|
+
const runtime = activeRuntime();
|
|
635
|
+
return runtime?.getPendingGiftChoices ? runtime.getPendingGiftChoices(experimentId) : getPendingGiftChoices(experimentId);
|
|
636
|
+
}
|
|
637
|
+
function selectGiftOption2(experimentId, variantGid) {
|
|
638
|
+
const runtime = activeRuntime();
|
|
639
|
+
return runtime?.selectGiftOption ? runtime.selectGiftOption(experimentId, variantGid) : selectGiftOption(experimentId, variantGid);
|
|
640
|
+
}
|
|
641
|
+
export {
|
|
642
|
+
getPendingGiftChoices2 as getPendingGiftChoices,
|
|
643
|
+
selectGiftOption2 as selectGiftOption
|
|
644
|
+
};
|
|
645
|
+
//# sourceMappingURL=index.mjs.map
|