@drip-apex/sdk 0.1.0 → 0.2.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.
Files changed (245) hide show
  1. package/README.md +5 -0
  2. package/dist/bundle-report.json +584 -226
  3. package/dist/define.cjs +123 -0
  4. package/dist/define.cjs.map +7 -0
  5. package/dist/define.mjs +102 -0
  6. package/dist/define.mjs.map +7 -0
  7. package/dist/drip.cjs +19262 -0
  8. package/dist/drip.cjs.map +7 -0
  9. package/dist/drip.debug.js +1 -1
  10. package/dist/drip.debug.js.map +1 -1
  11. package/dist/drip.heatmap.js +1 -1
  12. package/dist/drip.heatmap.js.map +1 -1
  13. package/dist/drip.js +1 -1
  14. package/dist/drip.js.map +1 -1
  15. package/dist/drip.live.js +1 -1
  16. package/dist/drip.live.js.map +1 -1
  17. package/dist/drip.mjs +19246 -0
  18. package/dist/drip.mjs.map +7 -0
  19. package/dist/drip.replay-recorder.js +2 -0
  20. package/dist/drip.replay-recorder.js.map +1 -0
  21. package/dist/editor.js +147 -142
  22. package/dist/editor.js.map +4 -4
  23. package/dist/flags.cjs +1788 -0
  24. package/dist/flags.cjs.map +7 -0
  25. package/dist/flags.mjs +1765 -0
  26. package/dist/flags.mjs.map +7 -0
  27. package/dist/index.mjs +12 -0
  28. package/dist/index.mjs.map +2 -2
  29. package/dist/metafiles/define.cjs.meta.json +28 -0
  30. package/dist/metafiles/define.mjs.meta.json +32 -0
  31. package/dist/metafiles/drip.cjs.meta.json +3193 -0
  32. package/dist/metafiles/drip.debug.meta.json +2859 -574
  33. package/dist/metafiles/drip.heatmap.meta.json +2732 -460
  34. package/dist/metafiles/drip.live.meta.json +2732 -460
  35. package/dist/metafiles/drip.meta.json +2859 -574
  36. package/dist/metafiles/drip.mjs.meta.json +3235 -0
  37. package/dist/metafiles/drip.replay-recorder.meta.json +82 -0
  38. package/dist/metafiles/editor.meta.json +67 -27
  39. package/dist/metafiles/flags.cjs.meta.json +220 -0
  40. package/dist/metafiles/flags.mjs.meta.json +225 -0
  41. package/dist/metafiles/index.meta.json +2717 -491
  42. package/dist/metafiles/index.mjs.meta.json +14 -4
  43. package/dist/react/index.js +16621 -13539
  44. package/dist/react/index.js.map +4 -4
  45. package/dist/sri.json +20 -15
  46. package/dist/types/activation-runtime.d.ts +91 -0
  47. package/dist/types/analytics-runtime.d.ts +166 -0
  48. package/dist/types/antiflicker.d.ts +9 -3
  49. package/dist/types/assignment-cookie-sync.d.ts +31 -0
  50. package/dist/types/assignment-runtime.d.ts +257 -0
  51. package/dist/types/assignment-store.d.ts +4 -8
  52. package/dist/types/bucket.d.ts +1 -2
  53. package/dist/types/compact-store.d.ts +1 -0
  54. package/dist/types/config-runtime.d.ts +313 -0
  55. package/dist/types/consent-evaluation.d.ts +27 -0
  56. package/dist/types/css.d.ts +5 -3
  57. package/dist/types/debug-loader.d.ts +2 -0
  58. package/dist/types/decide-assignments.d.ts +31 -0
  59. package/dist/types/delivery-timing.d.ts +8 -0
  60. package/dist/types/early-interaction-capture.d.ts +79 -0
  61. package/dist/types/early-reassert.d.ts +32 -0
  62. package/dist/types/edge-runtime.d.ts +11 -0
  63. package/dist/types/editor/api.d.ts +3 -0
  64. package/dist/types/editor/controller.d.ts +3 -1
  65. package/dist/types/editor/publication-result.d.ts +11 -0
  66. package/dist/types/editor/types.d.ts +2 -1
  67. package/dist/types/editor/view-kit.d.ts +1 -1
  68. package/dist/types/endpoint.d.ts +8 -0
  69. package/dist/types/exclusion-groups.d.ts +4 -7
  70. package/dist/types/flags.d.ts +2 -0
  71. package/dist/types/goal-eligibility.d.ts +4 -0
  72. package/dist/types/goals.d.ts +10 -1
  73. package/dist/types/guards.d.ts +7 -7
  74. package/dist/types/handover.d.ts +12 -1
  75. package/dist/types/hash.d.ts +8 -4
  76. package/dist/types/hydration.d.ts +2 -1
  77. package/dist/types/index.d.ts +24 -128
  78. package/dist/types/init-test-helpers.d.ts +48 -0
  79. package/dist/types/inline-bootstrap.d.ts +26 -0
  80. package/dist/types/js.d.ts +3 -1
  81. package/dist/types/money.d.ts +12 -0
  82. package/dist/types/mutate.d.ts +45 -6
  83. package/dist/types/performance.d.ts +2 -0
  84. package/dist/types/persistence-decoders.d.ts +12 -0
  85. package/dist/types/public-api.d.ts +209 -0
  86. package/dist/types/qa-assistant-state.d.ts +34 -0
  87. package/dist/types/react/index.d.ts +28 -3
  88. package/dist/types/reassert-sentinel.d.ts +6 -0
  89. package/dist/types/redirect.d.ts +48 -0
  90. package/dist/types/replay-recorder-entry.d.ts +1 -0
  91. package/dist/types/replay-signal-state.d.ts +6 -0
  92. package/dist/types/replay-signals.d.ts +13 -0
  93. package/dist/types/replay.d.ts +110 -0
  94. package/dist/types/router.d.ts +12 -2
  95. package/dist/types/runtime-state.d.ts +166 -0
  96. package/dist/types/sanitize.d.ts +1 -0
  97. package/dist/types/shadow.d.ts +3 -0
  98. package/dist/types/shopify-cart.d.ts +25 -1
  99. package/dist/types/storefront-vitals.d.ts +24 -0
  100. package/dist/types/targeting-diagnostics.d.ts +1 -0
  101. package/dist/types/targeting.d.ts +16 -2
  102. package/dist/types/track.d.ts +15 -1
  103. package/dist/types/types.d.ts +115 -9
  104. package/dist/types/wait.d.ts +14 -1
  105. package/dist/types/weekday-schedule.d.ts +3 -0
  106. package/package.json +17 -8
  107. package/src/activation-runtime.ts +2737 -0
  108. package/src/analytics-runtime.ts +2175 -0
  109. package/src/antiflicker.test.ts +216 -44
  110. package/src/antiflicker.ts +103 -28
  111. package/src/artifact-concurrency.test.ts +1091 -0
  112. package/src/assignment-cookie-sync.test.ts +202 -0
  113. package/src/assignment-cookie-sync.ts +189 -0
  114. package/src/assignment-runtime.ts +3204 -0
  115. package/src/assignment-store.test.ts +56 -0
  116. package/src/assignment-store.ts +7 -38
  117. package/src/bucket.ts +3 -18
  118. package/src/commerce-analytics-lifecycle.test.ts +75 -15
  119. package/src/commerce-config-lifecycle.test.ts +81 -1
  120. package/src/commerce-price-preserve.test.ts +133 -0
  121. package/src/commerce-price.test.ts +97 -0
  122. package/src/commerce-price.ts +74 -20
  123. package/src/commerce-shipping.test.ts +53 -0
  124. package/src/commerce-shipping.ts +5 -11
  125. package/src/compact-store.ts +15 -0
  126. package/src/config-fetch.test.ts +480 -9
  127. package/src/config-runtime.ts +2070 -0
  128. package/src/consent-evaluation-cookiescript.test.ts +50 -0
  129. package/src/consent-evaluation.ts +138 -0
  130. package/src/css.test.ts +30 -0
  131. package/src/css.ts +120 -6
  132. package/src/cwv.test.ts +60 -77
  133. package/src/debug-loader.test.ts +214 -0
  134. package/src/debug-loader.ts +41 -0
  135. package/src/decide-assignments.test.ts +196 -0
  136. package/src/decide-assignments.ts +204 -0
  137. package/src/delivery-timing.test.ts +104 -0
  138. package/src/delivery-timing.ts +89 -0
  139. package/src/early-interaction-capture.test.ts +451 -0
  140. package/src/early-interaction-capture.ts +230 -0
  141. package/src/early-reassert.test.ts +207 -0
  142. package/src/early-reassert.ts +152 -0
  143. package/src/edge-adoption.test.ts +435 -0
  144. package/src/edge-runtime.ts +30 -0
  145. package/src/editor/api.test.ts +109 -0
  146. package/src/editor/api.ts +34 -3
  147. package/src/editor/controller.test.ts +297 -14
  148. package/src/editor/controller.ts +69 -5
  149. package/src/editor/index.test.ts +2 -0
  150. package/src/editor/index.ts +1 -0
  151. package/src/editor/publication-result.ts +58 -0
  152. package/src/editor/types.ts +10 -1
  153. package/src/editor/view-kit.ts +2 -1
  154. package/src/editor/view.test.ts +108 -0
  155. package/src/editor/view.ts +49 -7
  156. package/src/endpoint.test.ts +15 -0
  157. package/src/endpoint.ts +10 -0
  158. package/src/exclusion-groups.ts +8 -18
  159. package/src/flags.test.ts +88 -1
  160. package/src/flags.ts +29 -29
  161. package/src/global-runtime-reconciler.test.ts +271 -0
  162. package/src/goal-eligibility.test.ts +29 -0
  163. package/src/goal-eligibility.ts +17 -0
  164. package/src/goals.test.ts +144 -1
  165. package/src/goals.ts +97 -18
  166. package/src/guards.test.ts +99 -1
  167. package/src/guards.ts +34 -15
  168. package/src/handover-cache-order.test.ts +6 -3
  169. package/src/handover.test.ts +154 -8
  170. package/src/handover.ts +122 -12
  171. package/src/hash.ts +29 -54
  172. package/src/holdout.test.ts +26 -0
  173. package/src/hydration.test.ts +73 -2
  174. package/src/hydration.ts +18 -9
  175. package/src/index.ts +130 -7287
  176. package/src/init-analytics.test.ts +1694 -0
  177. package/src/init-anti-flicker.test.ts +1211 -0
  178. package/src/init-cart-attributes.test.ts +2003 -0
  179. package/src/init-config-resolution.test.ts +999 -0
  180. package/src/init-consent.test.ts +971 -0
  181. package/src/init-empty.test.ts +11 -5406
  182. package/src/init-integrations.test.ts +846 -0
  183. package/src/init-page-activation.test.ts +5064 -0
  184. package/src/init-qa-loading.test.ts +740 -0
  185. package/src/init-redirects.test.ts +2156 -0
  186. package/src/init-test-helpers.ts +287 -0
  187. package/src/inline-bootstrap.test.ts +184 -0
  188. package/src/inline-bootstrap.ts +73 -0
  189. package/src/js.test.ts +51 -1
  190. package/src/js.ts +86 -2
  191. package/src/money.test.ts +55 -1
  192. package/src/money.ts +104 -2
  193. package/src/money.web-parity.contract.test.ts +85 -0
  194. package/src/mutate.test.ts +474 -10
  195. package/src/mutate.ts +739 -230
  196. package/src/page-trigger.test.ts +218 -8
  197. package/src/performance.ts +10 -0
  198. package/src/persistence-decoders.ts +18 -0
  199. package/src/public-api.ts +1828 -0
  200. package/src/qa-assistant-state.test.ts +249 -3
  201. package/src/qa-assistant-state.ts +146 -6
  202. package/src/qa-assistant-view.test.ts +220 -2
  203. package/src/qa-assistant-view.ts +102 -5
  204. package/src/react/index.test.tsx +37 -0
  205. package/src/react/index.tsx +19 -3
  206. package/src/reassert-sentinel.test.ts +155 -1
  207. package/src/reassert-sentinel.ts +168 -8
  208. package/src/redirect.test.ts +541 -0
  209. package/src/redirect.ts +572 -0
  210. package/src/replay-recorder-entry.ts +115 -0
  211. package/src/replay-signal-state.ts +100 -0
  212. package/src/replay-signals.test.ts +249 -0
  213. package/src/replay-signals.ts +151 -0
  214. package/src/replay.test.ts +764 -0
  215. package/src/replay.ts +514 -0
  216. package/src/router.test.ts +61 -2
  217. package/src/router.ts +50 -12
  218. package/src/runtime-state.ts +507 -0
  219. package/src/runtime.test.ts +174 -7
  220. package/src/runtime.ts +88 -14
  221. package/src/sanitize.test.ts +34 -0
  222. package/src/sanitize.ts +23 -12
  223. package/src/shadow.test.ts +187 -0
  224. package/src/shadow.ts +99 -0
  225. package/src/shopify-cart.test.ts +733 -23
  226. package/src/shopify-cart.ts +402 -49
  227. package/src/storefront-vitals.test.ts +217 -0
  228. package/src/storefront-vitals.ts +206 -0
  229. package/src/surface-signals.ts +6 -0
  230. package/src/targeting-conformance.test.ts +9 -0
  231. package/src/targeting-diagnostics.ts +38 -8
  232. package/src/targeting-parity-corpus.json +559 -0
  233. package/src/targeting-parity-corpus.test.ts +18 -0
  234. package/src/targeting.detailed.test.ts +105 -0
  235. package/src/targeting.test.ts +211 -0
  236. package/src/targeting.ts +88 -207
  237. package/src/track.test.ts +147 -0
  238. package/src/track.ts +125 -26
  239. package/src/types.ts +120 -13
  240. package/src/wait.test.ts +23 -0
  241. package/src/wait.ts +129 -13
  242. package/src/weekday-delivery.test.ts +56 -0
  243. package/src/weekday-schedule-parity-corpus.json +92 -0
  244. package/src/weekday-schedule.test.ts +69 -0
  245. package/src/weekday-schedule.ts +20 -0
package/src/router.ts CHANGED
@@ -3,29 +3,53 @@ import { RouterMode } from "./types";
3
3
  export type RouteChangeEvent = {
4
4
  previousUrl: string;
5
5
  nextUrl: string;
6
- reason: "pushState" | "replaceState" | "popstate" | "hashchange" | "navigation";
6
+ reason: "pushState" | "replaceState" | "popstate" | "hashchange" | "navigation" | "polling";
7
7
  };
8
8
 
9
9
  type RouteObserver = (event: RouteChangeEvent) => void;
10
10
 
11
- function notifyIfChanged(
11
+ export function notifyIfChanged(
12
12
  lastUrlRef: { value: string },
13
13
  reason: RouteChangeEvent["reason"],
14
14
  observer: RouteObserver,
15
+ onObserverError?: (error: unknown) => void,
15
16
  ): void {
16
17
  const next = location.href;
17
18
  if (next === lastUrlRef.value) return;
18
19
  const previous = lastUrlRef.value;
19
20
  lastUrlRef.value = next;
20
- observer({ previousUrl: previous, nextUrl: next, reason });
21
+ try {
22
+ observer({ previousUrl: previous, nextUrl: next, reason });
23
+ } catch (error) {
24
+ onObserverError?.(error);
25
+ }
21
26
  }
22
27
 
23
- function observeHistoryChanges(observer: RouteObserver, lastUrlRef: { value: string }): () => void {
28
+ export const PAGE_URL_POLL_INTERVAL_MS = 250;
29
+
30
+ export function observePollingChanges(
31
+ observer: RouteObserver,
32
+ intervalMs = PAGE_URL_POLL_INTERVAL_MS,
33
+ lastUrlRef: { value: string } = { value: location.href },
34
+ onObserverError?: (error: unknown) => void,
35
+ ): () => void {
36
+ const timer = window.setInterval(
37
+ () => notifyIfChanged(lastUrlRef, "polling", observer, onObserverError),
38
+ intervalMs,
39
+ );
40
+ return () => window.clearInterval(timer);
41
+ }
42
+
43
+ function observeHistoryChanges(
44
+ observer: RouteObserver,
45
+ lastUrlRef: { value: string },
46
+ onObserverError?: (error: unknown) => void,
47
+ ): () => void {
24
48
  const wrap = (method: "pushState" | "replaceState") => {
25
49
  const original = history[method];
26
50
  history[method] = function (...args: Parameters<History["pushState"]>) {
27
51
  const ret = original.apply(this, args);
28
- notifyIfChanged(lastUrlRef, method, observer);
52
+ notifyIfChanged(lastUrlRef, method, observer, onObserverError);
29
53
  return ret;
30
54
  };
31
55
  return () => {
@@ -35,8 +59,8 @@ function observeHistoryChanges(observer: RouteObserver, lastUrlRef: { value: str
35
59
 
36
60
  const restorePush = wrap("pushState");
37
61
  const restoreReplace = wrap("replaceState");
38
- const popHandler = () => notifyIfChanged(lastUrlRef, "popstate", observer);
39
- const hashHandler = () => notifyIfChanged(lastUrlRef, "hashchange", observer);
62
+ const popHandler = () => notifyIfChanged(lastUrlRef, "popstate", observer, onObserverError);
63
+ const hashHandler = () => notifyIfChanged(lastUrlRef, "hashchange", observer, onObserverError);
40
64
 
41
65
  window.addEventListener("popstate", popHandler);
42
66
  window.addEventListener("hashchange", hashHandler);
@@ -49,7 +73,11 @@ function observeHistoryChanges(observer: RouteObserver, lastUrlRef: { value: str
49
73
  };
50
74
  }
51
75
 
52
- function observeNavigationApi(observer: RouteObserver, lastUrlRef: { value: string }): () => void {
76
+ function observeNavigationApi(
77
+ observer: RouteObserver,
78
+ lastUrlRef: { value: string },
79
+ onObserverError?: (error: unknown) => void,
80
+ ): () => void {
53
81
  const w = globalThis as Record<string, unknown>;
54
82
  const navigation = w.navigation as {
55
83
  addEventListener?: (type: string, listener: () => void) => void;
@@ -59,7 +87,7 @@ function observeNavigationApi(observer: RouteObserver, lastUrlRef: { value: stri
59
87
  return () => {};
60
88
  }
61
89
 
62
- const listener = () => notifyIfChanged(lastUrlRef, "navigation", observer);
90
+ const listener = () => notifyIfChanged(lastUrlRef, "navigation", observer, onObserverError);
63
91
  navigation.addEventListener("navigate", listener);
64
92
 
65
93
  return () => {
@@ -72,6 +100,7 @@ function observeNavigationApi(observer: RouteObserver, lastUrlRef: { value: stri
72
100
  export function observeRouteChanges(
73
101
  mode: RouterMode,
74
102
  observer: RouteObserver,
103
+ options: { pollingIntervalMs?: number; onObserverError?: (error: unknown) => void } = {},
75
104
  ): () => void {
76
105
  if (mode === "none") return () => {};
77
106
 
@@ -79,11 +108,20 @@ export function observeRouteChanges(
79
108
  const cleanups: Array<() => void> = [];
80
109
 
81
110
  if (mode === "navigation") {
82
- cleanups.push(observeNavigationApi(observer, lastUrlRef));
111
+ cleanups.push(observeNavigationApi(observer, lastUrlRef, options.onObserverError));
112
+ }
113
+
114
+ if (mode === "history" || mode === "navigation" || mode === "polling") {
115
+ cleanups.push(observeHistoryChanges(observer, lastUrlRef, options.onObserverError));
83
116
  }
84
117
 
85
- if (mode === "history" || mode === "navigation") {
86
- cleanups.push(observeHistoryChanges(observer, lastUrlRef));
118
+ if (mode === "polling" || options.pollingIntervalMs !== undefined) {
119
+ cleanups.push(observePollingChanges(
120
+ observer,
121
+ options.pollingIntervalMs ?? PAGE_URL_POLL_INTERVAL_MS,
122
+ lastUrlRef,
123
+ options.onObserverError,
124
+ ));
87
125
  }
88
126
 
89
127
  return () => {
@@ -0,0 +1,507 @@
1
+ import { cleanUrl, onPageEnter, onPageExit } from "./analytics";
2
+ import { normalizeEndpoint } from "./endpoint";
3
+ import { EVENT_TYPE_PATTERN, normalizeEventName } from "@drip/event-schema/event-name";
4
+ import {
5
+ applyAntiFlicker,
6
+ bootedTooLateForAntiFlicker,
7
+ removeAntiFlicker,
8
+ } from "./antiflicker";
9
+ import {
10
+ clearPersistedAssignments,
11
+ findPersistedVariation,
12
+ persistAssignmentForExperiment,
13
+ prunePersistedAssignments,
14
+ removePersistedAssignmentsForExperiments,
15
+ __assignmentStoreInternals,
16
+ } from "./assignment-store";
17
+ import { cleanupBucketingStorage } from "./bucketing-cleanup";
18
+ import { chooseVariation, inTrafficAllocation } from "./bucket";
19
+ import { buildAssignment, decideAssignments } from "./decide-assignments";
20
+ import { weekdayScheduleBlocksDelivery } from "./weekday-schedule";
21
+ import { CONSENT_REQUIRED, DNT_BLOCKED, evaluateSynchronousConsent, readConfiguredConsent, readPath, resolveSynchronousConsentGranted } from "./consent-evaluation";
22
+ import { clearEarlyInteractions, drainBootstrapEarlyInteractions, drainEarlyInteractions } from "./early-interaction-capture";
23
+ import { getCwvMetrics, markCwvReveal, startCwvMeasurement, waitForCwvMetrics } from "./cwv";
24
+ import { collectDeliveryTiming } from "./delivery-timing";
25
+ import {
26
+ startStorefrontVitals,
27
+ stopStorefrontVitals,
28
+ type StorefrontVitalsContext,
29
+ } from "./storefront-vitals";
30
+ import {
31
+ browserGroupStickyStore,
32
+ clearBrowserGroupStickyStore,
33
+ resolveExclusionGroups,
34
+ type ExclusionGroupDecision,
35
+ type PersistedGroupSelection,
36
+ } from "./exclusion-groups";
37
+ import type { CompactGroupSelections } from "./persistence-decoders";
38
+ import {
39
+ applyCommercePrice,
40
+ isCommercePriceWorkPending,
41
+ cleanupCommercePrice,
42
+ hasCommercePriceState,
43
+ COMMERCE_PRICE_SELECTORS,
44
+ isCommercePriceActive,
45
+ isCommercePriceExposureEligible,
46
+ notifyCommerceCartStampConfirmed,
47
+ setCommercePriceExposureListener,
48
+ } from "./commerce-price";
49
+ import {
50
+ applyCommerceShipping,
51
+ classifyShippingExposure,
52
+ cleanupCommerceShipping,
53
+ isShippingCartEligible,
54
+ isShippingCartEligibilityConfirmed,
55
+ } from "./commerce-shipping";
56
+ import {
57
+ addCssOwners,
58
+ injectCss,
59
+ injectExperimentCss,
60
+ injectExternalCss,
61
+ removeCssForOwner,
62
+ } from "./css";
63
+ import { configureDebug, debugLog, debugWarn, debugGroup, debugGroupEnd, isDebugEnabled } from "./debug";
64
+ import { loadDebugBuild } from "./debug-loader";
65
+ import { observeDomChanges } from "./dom-trigger";
66
+ import { edgeRuntimeActive, readEdgeRuntimeAssignments } from "./edge-runtime";
67
+ import { normalizeDataLayerEntry } from "./data-layer-normalize";
68
+ import { interceptEditorLaunch, isEditorDevicePreview } from "./editor-bootstrap";
69
+ import { cleanupGoals, goalWiringKeys, setupGoals, triggerGoal, triggerGoalsForEvent } from "./goals";
70
+ import { clearQaForceFromUrl, isBot, isDuplicate, isIframe, isOptedOut, isQaMode, isScreenshotMode, parseForceParam, persistQaForce, persistUrlQaForce, exitQaMode, getQaSessionId } from "./guards";
71
+ import { adoptUserId, applyHoldoutGate, configureIdentityStorage, getEphemeralUserId, getUserId, hashToFloat, isHoldoutVisitor, variationHashToFloat } from "./hash";
72
+ import { createBucketingHandoverPayload, handoverMintTimeoutMs, hasBucketingHandover, installBucketingHandover, readBucketingHandover } from "./handover";
73
+ import { revealAll } from "./hideflicker";
74
+ import {
75
+ addExternalJsOwners,
76
+ execJs,
77
+ loadExternalJs,
78
+ removeExternalJsForOwner,
79
+ setJsPolicy,
80
+ } from "./js";
81
+ import {
82
+ addAppliedMutationOwners,
83
+ applyMutations,
84
+ applyToElement,
85
+ invalidateArtifact,
86
+ reassertNonStructuralMutations,
87
+ replayArtifact,
88
+ resetAppliedMutationsForOwner,
89
+ } from "./mutate";
90
+ import { registerMutedObserver, runMuted, unregisterMutedObserver } from "./observer-mute";
91
+ import { assignmentsHaveVisualWork, awaitHydration, hasMutationHold, holdMutations, releaseMutations, signalHydrated } from "./hydration";
92
+ import {
93
+ assignmentsHaveCustomJs,
94
+ assignmentsHaveStructuralMutations,
95
+ installEarlyReassert,
96
+ shouldUseEarlyReassert,
97
+ } from "./early-reassert";
98
+ import { trackAppliedMutation } from "./reassert-sentinel";
99
+ import { observeRouteChanges, PAGE_URL_POLL_INTERVAL_MS } from "./router";
100
+ import { buildExposureSignalContext } from "./exposure-signals";
101
+ import {
102
+ buildRedirectDestination,
103
+ clearPendingRedirectAssignmentCarry,
104
+ finalizeRedirectAssignmentCarryHandover,
105
+ hasGeneratedRedirectAssignmentCarry,
106
+ filterUnsafeRedirectAssignments,
107
+ importRedirectAssignmentCarry,
108
+ isRedirectLoop,
109
+ markRedirectAssignmentCarryExposed,
110
+ parseRedirectAssignmentCarry,
111
+ persistPendingRedirectAssignmentCarry,
112
+ readPendingRedirectAssignmentCarry,
113
+ REDIRECT_ASSIGNMENT_PARAM,
114
+ redirectPlanForAssignment,
115
+ stripRedirectAssignmentCarry,
116
+ validateRedirectAssignmentCarry,
117
+ verifyRedirectAssignmentCarry,
118
+ } from "./redirect";
119
+ import type { VerifiedRedirectCarry } from "./redirect";
120
+ import { buildPrerequisiteContext, evaluateProjectPrerequisite } from "./prerequisites";
121
+ import {
122
+ REPLAY_PROGRESS_KEY_PREFIX,
123
+ REPLAY_SAMPLE_KEY_PREFIX,
124
+ resolveReplayRecorderUrl,
125
+ startReplayCapture,
126
+ type ReplayController,
127
+ } from "./replay";
128
+ import {
129
+ buildCartAttributeEntries,
130
+ buildCartMetafieldInputs,
131
+ buildSignedCartAttributeEntries,
132
+ APEX_CART_ATTRIBUTE_KEYS,
133
+ cannotRequestRequiredCommerceAuthorization,
134
+ getCartMetafieldStaleKeys as collectCartMetafieldStaleKeys,
135
+ invalidateShopifyCartAttributeSync,
136
+ normalizeCartMetafieldNamespace,
137
+ syncShopifyCartAttributes,
138
+ type CartAssignment,
139
+ type CartAttributeEntry,
140
+ type CartMetafieldInput,
141
+ type CartAttributeSyncInput,
142
+ } from "./shopify-cart";
143
+ import { onShopifyCartMutation } from "./shopify-cart-events";
144
+ import {
145
+ getPendingGiftChoices,
146
+ noteCartSnapshotForGifts,
147
+ selectGiftOption,
148
+ syncGiftWithPurchase,
149
+ type GiftSyncOptions,
150
+ } from "./commerce-gift";
151
+ import { CART_DRAWER_OPEN_SIGNAL, installSurfaceSignals } from "./surface-signals";
152
+ import {
153
+ assignmentSignature,
154
+ canUseEmptyProjectProfile,
155
+ computeUrlDiffNeeds,
156
+ getBlankScreenMs,
157
+ readPerfFlags,
158
+ resolveActivationMode,
159
+ resolvePlatform,
160
+ resolveRouterMode,
161
+ shouldReevaluateForUrlChange,
162
+ } from "./runtime";
163
+ import type { PerfFlagState } from "./runtime";
164
+ import {
165
+ buildTargetingAttributes,
166
+ evaluateTargetingGatesDetailed,
167
+ matchPageTargetingRule,
168
+ readShopifySignal,
169
+ targetingHasJsTriggers,
170
+ } from "./targeting";
171
+ import { createApexRuntimeTools, type ApexRuntimeTools } from "./runtime-tools";
172
+ import { createEventId, Tracker } from "./track";
173
+ import {
174
+ clearStoredSignals,
175
+ configureSignalPersistenceAllowed,
176
+ clearRuntimeSignal,
177
+ getSignals as getStoredSignals,
178
+ getSignalDiagnostics,
179
+ rememberProduct,
180
+ setCartSignals,
181
+ setRuntimeSignal,
182
+ setSearchSignal,
183
+ setSignal as setStoredSignal,
184
+ } from "./signals";
185
+ import {
186
+ evaluateFlag as evaluateFlagFromExperiments,
187
+ evaluateFlagAssignment as evaluateFlagAssignmentFromExperiments,
188
+ evaluateFlagValue as evaluateFlagValueFromExperiments,
189
+ } from "./flags";
190
+ import {
191
+ ActivationMode,
192
+ AntiFlickerMode,
193
+ Assignment,
194
+ ActivationDiagnostics,
195
+ ActivationGateDiagnostic,
196
+ ConditionDiagnostic,
197
+ ConfigProfile,
198
+ ConsentModeSettings,
199
+ CustomJsPolicy,
200
+ DebugSettings,
201
+ ExecutionMode,
202
+ Experiment,
203
+ ExperimentActivationDiagnostic,
204
+ ExclusionGroupConfig,
205
+ ExclusionGroupMemberConfig,
206
+ Goal,
207
+ InitConfig,
208
+ PageTargetingRule,
209
+ PageActivationDiagnostic,
210
+ PageDeactivationMode,
211
+ PageTriggerMode,
212
+ PageTriggerSettings,
213
+ PerfFeatureFlag,
214
+ PerfFeatureFlags,
215
+ PlatformHint,
216
+ ProjectPrerequisites,
217
+ RouterMode,
218
+ SegmentCondition,
219
+ SpaSettings,
220
+ Targeting,
221
+ ExternalTrackingSettings,
222
+ ProjectCodeSettings,
223
+ RuntimeEnvironmentSettings,
224
+ RuntimeSignalDefinition,
225
+ SdkDiagnostics,
226
+ SnippetCriticalMutation,
227
+ SnippetCriticalMutationPlanItem,
228
+ SnippetDeliveryUrlRule,
229
+ BucketingCleanupSettings,
230
+ DataProtectionSettings,
231
+ DataLayerSignalMapping,
232
+ DataLayerTriggerSettings,
233
+ ExposureDestinationsSettings,
234
+ Mutation,
235
+ TrackEvent,
236
+ TrackingStart,
237
+ Variation,
238
+ } from "./types";
239
+ import {
240
+ addWaitEntryOwners,
241
+ applyMutationWithWait,
242
+ resetWaitEntriesForOwner,
243
+ } from "./wait";
244
+
245
+
246
+ import type {
247
+ HeatmapController, SemanticController, UrlDiffNeeds, PendingPerfEvent, ConfigSource,
248
+ ResolvedRuntimeConfig, RouteDiagnostic, DataLayerDiagnostic, ShopifySyncDiagnostic,
249
+ ShopifyAssignmentSyncDiagnostic,
250
+ ExposureDestinationDiagnostic, PageRuleReconcileScope, RuntimeLoadDiagnostic, PageDetectorMode,
251
+ } from "./config-runtime";
252
+
253
+ // Shared runtime state. Owners: config, analytics, assignment, activation, and public API seams.
254
+ export type OrderIdentityPlatform =
255
+ | "shopify"
256
+ | "shopware"
257
+ | "woocommerce"
258
+ | "centra"
259
+ | "custom";
260
+
261
+ export type SDKState = {
262
+ config: InitConfig | null;
263
+ userId: string | null;
264
+ tracker: Tracker | null;
265
+ assignments: Assignment[];
266
+ pageActivation: Map<string, PageActivationRuntimeState>;
267
+ stopObserver: (() => void) | null;
268
+ stopDomObserver: (() => void) | null;
269
+ stopHandover: (() => void) | null;
270
+ heatmapController: HeatmapController | null;
271
+ replayController: ReplayController | null;
272
+ replayStartPromise: Promise<void> | null;
273
+ replayGeneration: number;
274
+ semanticController: SemanticController | null;
275
+ forceMap: Record<string, string> | null;
276
+ forcedUnavailable: Array<{
277
+ experimentId: string;
278
+ reason: "archived" | "runtime_disabled" | "not_found" | "environment_mismatch" | "not_in_config";
279
+ }>;
280
+ edgeDeviceAudienceUnsupported: Array<{
281
+ experimentId: string;
282
+ audienceName: string;
283
+ }>;
284
+ analyticsStarted: boolean;
285
+ trackingStart: TrackingStart;
286
+ trackingIdleTimeoutMs: number;
287
+ consentRequired: boolean;
288
+ consentGranted: boolean;
289
+ consentModeEnabled: boolean;
290
+ trackingPrerequisiteMet: boolean;
291
+ variationPrerequisiteMet: boolean;
292
+ activationDiagnostics: ActivationDiagnostics;
293
+ trackingDisabledByDnt: boolean;
294
+ holdout: boolean;
295
+ analyticsTimeoutId: number | null;
296
+ analyticsIdleId: number | null;
297
+ qaMode: boolean;
298
+ qaSessionId: string;
299
+ screenshotMode: boolean;
300
+ platform: PlatformHint;
301
+ routerMode: RouterMode;
302
+ activationMode: ActivationMode;
303
+ perfFlags: PerfFlagState;
304
+ urlDiffNeeds: UrlDiffNeeds;
305
+ lastUrl: string;
306
+ lastAssignmentSignature: string;
307
+ wiredGoalKeys: Set<string>;
308
+ wiredGoalUrl: string | null;
309
+ pendingPerf: PendingPerfEvent | null;
310
+ configSource: ConfigSource;
311
+ runtimeConfig: ResolvedRuntimeConfig | null;
312
+ pageTriggerMode: PageTriggerMode;
313
+ stopSignalCaptures: (() => void) | null;
314
+ stopSurfaceSignals: (() => void) | null;
315
+ stopJsTriggerSignals: (() => void) | null;
316
+ stopDataLayerTriggers: (() => void) | null;
317
+ stopConsentListeners: (() => void) | null;
318
+ stopShopifyCartMutationSync: (() => void) | null;
319
+ lastRouteChange: RouteDiagnostic | null;
320
+ lastDataLayerTrigger: DataLayerDiagnostic | null;
321
+ observerErrors: {
322
+ count: number;
323
+ last?: { source: "route" | "data_layer" | "dom"; message: string; at: number };
324
+ };
325
+ deferredRouteReevaluationTimer: number | null;
326
+ lastShopifyAssignmentSync: ShopifyAssignmentSyncDiagnostic | null;
327
+ lastShopifyCartSync: ShopifySyncDiagnostic | null;
328
+ shopifyCartToken: string | null;
329
+ shopwareAttributionEnvelope: string | null;
330
+ exposureDestinationDiagnostics: ExposureDestinationDiagnostic[];
331
+ exposedAssignmentKeys: Set<string>;
332
+ mutationPendingAssignmentKeys: Set<string>;
333
+ contaminatedAssignmentKeys: Set<string>;
334
+ authorizedPriceAssignmentKeys: Set<string> | null;
335
+ authorizedShippingAssignmentKeys: Set<string> | null;
336
+ authorizedOffersAssignmentKeys: Set<string> | null;
337
+ initializingAssignments: boolean;
338
+ pendingInitialApply: Promise<void> | null;
339
+ queuedRecheck: {
340
+ reason: "url" | "dom" | "manual" | "prerequisite";
341
+ forceReapply: boolean;
342
+ pageRuleScope?: PageRuleReconcileScope;
343
+ } | null;
344
+ redirectNavigationPending: boolean;
345
+ routeAnalyticsGeneration: number;
346
+ /** Re-entrancy guard and unwind-drain flag for `reevaluateAssignments`. */
347
+ reconcileInProgress: boolean;
348
+ reconcilePending: boolean;
349
+ pendingDeliveryHealth: TrackEvent[];
350
+ load: RuntimeLoadDiagnostic;
351
+ orderIdentityInFlight: Set<string>;
352
+ orderIdentityDetectionUrl: string;
353
+ orderIdentityDetection: {
354
+ platform: OrderIdentityPlatform;
355
+ platformOrderId: string | null;
356
+ orderNumber: string | null;
357
+ } | null | undefined;
358
+ carryImportedAssignmentKeys: Set<string>;
359
+ };
360
+
361
+ export type QaAssistantRuntimeSnapshot = {
362
+ config: InitConfig | null;
363
+ assignments: Assignment[];
364
+ activationDiagnostics: ActivationDiagnostics;
365
+ pageActivation: PageActivationDiagnostic[];
366
+ goalScopeUrl: string | null;
367
+ forceMap: Record<string, string> | null;
368
+ forcedUnavailable: Array<{
369
+ experimentId: string;
370
+ reason: "archived" | "runtime_disabled" | "not_found" | "environment_mismatch" | "not_in_config";
371
+ }>;
372
+ edgeDeviceAudienceUnsupported: Array<{
373
+ experimentId: string;
374
+ audienceName: string;
375
+ }>;
376
+ platform: PlatformHint;
377
+ qaMode: boolean;
378
+ orderIdentity: {
379
+ platform: OrderIdentityPlatform;
380
+ platformOrderId: string | null;
381
+ orderNumber: string | null;
382
+ } | null;
383
+ };
384
+
385
+ export type PageActivationRuntimeState = {
386
+ active: boolean;
387
+ appliedKeys: Set<string>;
388
+ /** Goal-scope state only; never participates in render transitions. */
389
+ scopeOnly?: boolean;
390
+ configuredMode?: PageDeactivationMode;
391
+ lastTransitionMode?: PageDeactivationMode;
392
+ isolationFallback?: "whole_experiment";
393
+ isolationFallbackExperimentId?: string;
394
+ triggerDetector?: PageDetectorMode;
395
+ triggerPollAttempts?: number;
396
+ triggerOutcome?: "activated" | "condition_failed" | "window_expired";
397
+ triggerElapsedMs?: number;
398
+ };
399
+
400
+ export type PageRulePollController = {
401
+ intervalId: number;
402
+ startedAt: number;
403
+ };
404
+
405
+ export const runtimeSharedState = {
406
+ runtimeBootedTooLateForAntiFlicker: null as boolean | null,
407
+ stopEarlyReassert: null as (() => void) | null,
408
+ earlyReassertTeardownTimer: null as ReturnType<typeof setTimeout> | null,
409
+ storefrontVitalsContext: null as StorefrontVitalsContext | null,
410
+ initialPredecidedByExperiment: null as Map<string, string> | null,
411
+ shopifyCartSyncGeneration: 0,
412
+ // Owners: config and activation seams.
413
+ pageDetectorRules: new Map<PageDetectorMode, PageTargetingRule[]>(),
414
+ pageDetectorLastUrls: new Map<string, string>(),
415
+ pageRulePollControllers: new Map<string, PageRulePollController>(),
416
+ // Owners: activation and public API seams.
417
+ qaAssistantRuntimeListeners: new Set<() => void>(),
418
+ clearingQaForceFromRoute: false,
419
+ // Owners: analytics and assignment seams.
420
+ attributionLedger: new Map<string, Assignment>(),
421
+ };
422
+
423
+ // Shared SDK lifecycle state. Owners: all runtime seams.
424
+ export const state: SDKState = {
425
+ config: null,
426
+ userId: null,
427
+ tracker: null,
428
+ assignments: [],
429
+ pageActivation: new Map(),
430
+ stopObserver: null,
431
+ stopDomObserver: null,
432
+ stopHandover: null,
433
+ heatmapController: null,
434
+ replayController: null,
435
+ replayStartPromise: null,
436
+ replayGeneration: 0,
437
+ semanticController: null,
438
+ forceMap: null,
439
+ forcedUnavailable: [],
440
+ edgeDeviceAudienceUnsupported: [],
441
+ analyticsStarted: false,
442
+ trackingStart: "idle",
443
+ trackingIdleTimeoutMs: 2000,
444
+ consentRequired: false,
445
+ consentGranted: true,
446
+ consentModeEnabled: false,
447
+ trackingPrerequisiteMet: true,
448
+ variationPrerequisiteMet: true,
449
+ activationDiagnostics: {
450
+ project: { gates: [] },
451
+ experiments: [],
452
+ },
453
+ trackingDisabledByDnt: false,
454
+ holdout: false,
455
+ analyticsTimeoutId: null,
456
+ analyticsIdleId: null,
457
+ qaMode: false,
458
+ qaSessionId: "",
459
+ screenshotMode: false,
460
+ platform: "auto",
461
+ routerMode: "history",
462
+ activationMode: "observer",
463
+ perfFlags: readPerfFlags({}),
464
+ urlDiffNeeds: { path: false, search: false, hash: false },
465
+ lastUrl: "",
466
+ lastAssignmentSignature: "none",
467
+ wiredGoalKeys: new Set(),
468
+ wiredGoalUrl: null,
469
+ pendingPerf: null,
470
+ configSource: "none",
471
+ runtimeConfig: null,
472
+ pageTriggerMode: "direct",
473
+ stopSignalCaptures: null,
474
+ stopSurfaceSignals: null,
475
+ stopJsTriggerSignals: null,
476
+ stopDataLayerTriggers: null,
477
+ stopConsentListeners: null,
478
+ stopShopifyCartMutationSync: null,
479
+ lastRouteChange: null,
480
+ lastDataLayerTrigger: null,
481
+ observerErrors: { count: 0 },
482
+ deferredRouteReevaluationTimer: null,
483
+ lastShopifyAssignmentSync: null,
484
+ lastShopifyCartSync: null,
485
+ shopifyCartToken: null,
486
+ shopwareAttributionEnvelope: null,
487
+ exposureDestinationDiagnostics: [],
488
+ exposedAssignmentKeys: new Set(),
489
+ mutationPendingAssignmentKeys: new Set(),
490
+ contaminatedAssignmentKeys: new Set(),
491
+ authorizedPriceAssignmentKeys: null,
492
+ authorizedShippingAssignmentKeys: null,
493
+ authorizedOffersAssignmentKeys: null,
494
+ initializingAssignments: false,
495
+ pendingInitialApply: null,
496
+ queuedRecheck: null,
497
+ redirectNavigationPending: false,
498
+ routeAnalyticsGeneration: 0,
499
+ reconcileInProgress: false,
500
+ reconcilePending: false,
501
+ pendingDeliveryHealth: [],
502
+ load: { stage: "idle", configFetchStatus: "idle" },
503
+ orderIdentityInFlight: new Set(),
504
+ orderIdentityDetectionUrl: "",
505
+ orderIdentityDetection: undefined,
506
+ carryImportedAssignmentKeys: new Set(),
507
+ };