@delmaredigital/payload-experiments 0.0.0-stage → 0.1.0-rc.6

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 (466) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +590 -2
  3. package/dist/access.d.ts +1 -0
  4. package/dist/access.js +2 -0
  5. package/dist/admin/AllocationField.d.ts +2 -0
  6. package/dist/admin/AllocationField.js +80 -0
  7. package/dist/admin/FlagPointSelect.d.ts +2 -0
  8. package/dist/admin/FlagPointSelect.js +54 -0
  9. package/dist/admin/LayerUsage.d.ts +2 -0
  10. package/dist/admin/LayerUsage.js +24 -0
  11. package/dist/admin/LockedFieldNotice.d.ts +2 -0
  12. package/dist/admin/LockedFieldNotice.js +26 -0
  13. package/dist/admin/MetricSourceSelect.d.ts +2 -0
  14. package/dist/admin/MetricSourceSelect.js +32 -0
  15. package/dist/admin/PhaseHistory.d.ts +2 -0
  16. package/dist/admin/PhaseHistory.js +76 -0
  17. package/dist/admin/PreviewLinks.d.ts +11 -0
  18. package/dist/admin/PreviewLinks.js +69 -0
  19. package/dist/admin/StatusCell.d.ts +3 -0
  20. package/dist/admin/StatusCell.js +19 -0
  21. package/dist/admin/SummaryCell.d.ts +2 -0
  22. package/dist/admin/SummaryCell.js +32 -0
  23. package/dist/admin/actions/AddMetricDialog.d.ts +6 -0
  24. package/dist/admin/actions/AddMetricDialog.js +138 -0
  25. package/dist/admin/actions/AllocateDialog.d.ts +6 -0
  26. package/dist/admin/actions/AllocateDialog.js +81 -0
  27. package/dist/admin/actions/ConfirmDialog.d.ts +14 -0
  28. package/dist/admin/actions/ConfirmDialog.js +192 -0
  29. package/dist/admin/actions/DecideDialog.d.ts +7 -0
  30. package/dist/admin/actions/DecideDialog.js +173 -0
  31. package/dist/admin/actions/ExperimentActions.d.ts +3 -0
  32. package/dist/admin/actions/ExperimentActions.js +110 -0
  33. package/dist/admin/actions/MakeContentResult.d.ts +6 -0
  34. package/dist/admin/actions/MakeContentResult.js +50 -0
  35. package/dist/admin/actions/actions.model.d.ts +37 -0
  36. package/dist/admin/actions/actions.model.js +71 -0
  37. package/dist/admin/actions/decide.model.d.ts +21 -0
  38. package/dist/admin/actions/decide.model.js +38 -0
  39. package/dist/admin/allocation.model.d.ts +20 -0
  40. package/dist/admin/allocation.model.js +38 -0
  41. package/dist/admin/api.d.ts +32 -0
  42. package/dist/admin/api.js +95 -0
  43. package/dist/admin/armSelect/ArmSelectField.d.ts +2 -0
  44. package/dist/admin/armSelect/ArmSelectField.js +185 -0
  45. package/dist/admin/armSelect/armSelect.model.d.ts +30 -0
  46. package/dist/admin/armSelect/armSelect.model.js +20 -0
  47. package/dist/admin/arms/ArmsField.d.ts +2 -0
  48. package/dist/admin/arms/ArmsField.js +310 -0
  49. package/dist/admin/arms/ParamsEditor.d.ts +16 -0
  50. package/dist/admin/arms/ParamsEditor.js +79 -0
  51. package/dist/admin/arms/arms.model.d.ts +21 -0
  52. package/dist/admin/arms/arms.model.js +153 -0
  53. package/dist/admin/arms/pageTarget.model.d.ts +4 -0
  54. package/dist/admin/arms/pageTarget.model.js +19 -0
  55. package/dist/admin/arms/params.model.d.ts +7 -0
  56. package/dist/admin/arms/params.model.js +35 -0
  57. package/dist/admin/copy/actions.d.ts +38 -0
  58. package/dist/admin/copy/actions.js +38 -0
  59. package/dist/admin/copy/armSelect.d.ts +11 -0
  60. package/dist/admin/copy/armSelect.js +11 -0
  61. package/dist/admin/copy/arms.d.ts +37 -0
  62. package/dist/admin/copy/arms.js +47 -0
  63. package/dist/admin/copy/common.d.ts +20 -0
  64. package/dist/admin/copy/common.js +27 -0
  65. package/dist/admin/copy/history.d.ts +9 -0
  66. package/dist/admin/copy/history.js +9 -0
  67. package/dist/admin/copy/metrics.d.ts +9 -0
  68. package/dist/admin/copy/metrics.js +9 -0
  69. package/dist/admin/copy/results.d.ts +78 -0
  70. package/dist/admin/copy/results.js +81 -0
  71. package/dist/admin/copy/review.d.ts +33 -0
  72. package/dist/admin/copy/review.js +127 -0
  73. package/dist/admin/copy/status.d.ts +8 -0
  74. package/dist/admin/copy/status.js +8 -0
  75. package/dist/admin/copy/tabs.d.ts +7 -0
  76. package/dist/admin/copy/tabs.js +7 -0
  77. package/dist/admin/copy/who.d.ts +36 -0
  78. package/dist/admin/copy/who.js +36 -0
  79. package/dist/admin/labels.d.ts +45 -0
  80. package/dist/admin/labels.js +53 -0
  81. package/dist/admin/layerUsage.model.d.ts +15 -0
  82. package/dist/admin/layerUsage.model.js +18 -0
  83. package/dist/admin/lockedNotice.model.d.ts +3 -0
  84. package/dist/admin/lockedNotice.model.js +18 -0
  85. package/dist/admin/metricSource.model.d.ts +7 -0
  86. package/dist/admin/metricSource.model.js +11 -0
  87. package/dist/admin/paths.d.ts +16 -0
  88. package/dist/admin/paths.js +16 -0
  89. package/dist/admin/permissions.model.d.ts +10 -0
  90. package/dist/admin/permissions.model.js +4 -0
  91. package/dist/admin/phaseHistory.model.d.ts +19 -0
  92. package/dist/admin/phaseHistory.model.js +19 -0
  93. package/dist/admin/reload.d.ts +1 -0
  94. package/dist/admin/reload.js +1 -0
  95. package/dist/admin/results/ArmTable.d.ts +8 -0
  96. package/dist/admin/results/ArmTable.js +112 -0
  97. package/dist/admin/results/CappedCell.d.ts +4 -0
  98. package/dist/admin/results/CappedCell.js +24 -0
  99. package/dist/admin/results/CiChart.d.ts +10 -0
  100. package/dist/admin/results/CiChart.js +178 -0
  101. package/dist/admin/results/DataQualityPanel.d.ts +4 -0
  102. package/dist/admin/results/DataQualityPanel.js +40 -0
  103. package/dist/admin/results/ResultsView.d.ts +3 -0
  104. package/dist/admin/results/ResultsView.js +312 -0
  105. package/dist/admin/results/VerdictCard.d.ts +9 -0
  106. package/dist/admin/results/VerdictCard.js +49 -0
  107. package/dist/admin/results/chart.model.d.ts +32 -0
  108. package/dist/admin/results/chart.model.js +52 -0
  109. package/dist/admin/results/format.d.ts +10 -0
  110. package/dist/admin/results/format.js +55 -0
  111. package/dist/admin/results/results.model.d.ts +105 -0
  112. package/dist/admin/results/results.model.js +175 -0
  113. package/dist/admin/review/ReviewPanel.d.ts +2 -0
  114. package/dist/admin/review/ReviewPanel.js +268 -0
  115. package/dist/admin/review/review.model.d.ts +31 -0
  116. package/dist/admin/review/review.model.js +40 -0
  117. package/dist/admin/status.model.d.ts +16 -0
  118. package/dist/admin/status.model.js +17 -0
  119. package/dist/admin/styles.css +10 -0
  120. package/dist/admin/styles.d.ts +1 -0
  121. package/dist/admin/styles.js +2 -0
  122. package/dist/admin/summaryBatcher.d.ts +8 -0
  123. package/dist/admin/summaryBatcher.js +33 -0
  124. package/dist/admin/targeting/TargetingAttributeField.d.ts +2 -0
  125. package/dist/admin/targeting/TargetingAttributeField.js +31 -0
  126. package/dist/admin/targeting/TargetingOpField.d.ts +2 -0
  127. package/dist/admin/targeting/TargetingOpField.js +45 -0
  128. package/dist/admin/targeting/TargetingValueField.d.ts +2 -0
  129. package/dist/admin/targeting/TargetingValueField.js +142 -0
  130. package/dist/admin/targeting/targeting.model.d.ts +18 -0
  131. package/dist/admin/targeting/targeting.model.js +48 -0
  132. package/dist/admin/useApi.d.ts +20 -0
  133. package/dist/admin/useApi.js +10 -0
  134. package/dist/admin/useLayerUsage.d.ts +15 -0
  135. package/dist/admin/useLayerUsage.js +92 -0
  136. package/dist/client/ExperimentPageview.d.ts +1 -0
  137. package/dist/client/ExperimentPageview.js +27 -0
  138. package/dist/client/ExperimentsProvider.d.ts +6 -0
  139. package/dist/client/ExperimentsProvider.js +22 -0
  140. package/dist/client/ViewportExposure.d.ts +9 -0
  141. package/dist/client/ViewportExposure.js +69 -0
  142. package/dist/client/beacon.d.ts +17 -0
  143. package/dist/client/beacon.js +71 -0
  144. package/dist/client/context.d.ts +2 -0
  145. package/dist/client/context.js +2 -0
  146. package/dist/client/idempotency.d.ts +2 -0
  147. package/dist/client/idempotency.js +13 -0
  148. package/dist/client/trackConversionBeacon.d.ts +3 -0
  149. package/dist/client/trackConversionBeacon.js +16 -0
  150. package/dist/client/useExperiment.d.ts +5 -0
  151. package/dist/client/useExperiment.js +27 -0
  152. package/dist/client/useFlagPoint.d.ts +9 -0
  153. package/dist/client/useFlagPoint.js +32 -0
  154. package/dist/collections/access.d.ts +21 -0
  155. package/dist/collections/access.js +25 -0
  156. package/dist/collections/events.d.ts +3 -0
  157. package/dist/collections/events.js +117 -0
  158. package/dist/collections/experiments/armInvariants.d.ts +12 -0
  159. package/dist/collections/experiments/armInvariants.js +89 -0
  160. package/dist/collections/experiments/config.d.ts +3 -0
  161. package/dist/collections/experiments/config.js +574 -0
  162. package/dist/collections/experiments/createDefaults.d.ts +2 -0
  163. package/dist/collections/experiments/createDefaults.js +7 -0
  164. package/dist/collections/experiments/deleteGuard.d.ts +3 -0
  165. package/dist/collections/experiments/deleteGuard.js +8 -0
  166. package/dist/collections/experiments/editability.d.ts +4 -0
  167. package/dist/collections/experiments/editability.js +35 -0
  168. package/dist/collections/experiments/flagControlParams.d.ts +2 -0
  169. package/dist/collections/experiments/flagControlParams.js +32 -0
  170. package/dist/collections/experiments/lockHook.d.ts +2 -0
  171. package/dist/collections/experiments/lockHook.js +134 -0
  172. package/dist/collections/identities.d.ts +3 -0
  173. package/dist/collections/identities.js +30 -0
  174. package/dist/collections/index.d.ts +6 -0
  175. package/dist/collections/index.js +24 -0
  176. package/dist/collections/layers.d.ts +3 -0
  177. package/dist/collections/layers.js +77 -0
  178. package/dist/collections/metrics.d.ts +3 -0
  179. package/dist/collections/metrics.js +115 -0
  180. package/dist/collections/phases.d.ts +3 -0
  181. package/dist/collections/phases.js +59 -0
  182. package/dist/collections/serialize.d.ts +5 -0
  183. package/dist/collections/serialize.js +40 -0
  184. package/dist/collections/snapshots.d.ts +3 -0
  185. package/dist/collections/snapshots.js +47 -0
  186. package/dist/constants.d.ts +7 -0
  187. package/dist/constants.js +7 -0
  188. package/dist/db/adapter.d.ts +3 -0
  189. package/dist/db/adapter.js +9 -0
  190. package/dist/db/appends.d.ts +58 -0
  191. package/dist/db/appends.js +116 -0
  192. package/dist/db/delete.d.ts +17 -0
  193. package/dist/db/delete.js +35 -0
  194. package/dist/db/erase.d.ts +12 -0
  195. package/dist/db/erase.js +55 -0
  196. package/dist/db/events.d.ts +21 -0
  197. package/dist/db/events.js +100 -0
  198. package/dist/db/executor.d.ts +10 -0
  199. package/dist/db/executor.js +37 -0
  200. package/dist/db/identities.d.ts +11 -0
  201. package/dist/db/identities.js +29 -0
  202. package/dist/db/locks.d.ts +15 -0
  203. package/dist/db/locks.js +23 -0
  204. package/dist/db/manifest.d.ts +8 -0
  205. package/dist/db/manifest.js +8 -0
  206. package/dist/db/names.d.ts +271 -0
  207. package/dist/db/names.js +270 -0
  208. package/dist/db/pgExecutor.d.ts +41 -0
  209. package/dist/db/pgExecutor.js +250 -0
  210. package/dist/db/results.d.ts +53 -0
  211. package/dist/db/results.js +103 -0
  212. package/dist/db/slices.d.ts +18 -0
  213. package/dist/db/slices.js +51 -0
  214. package/dist/db/snapshots.d.ts +47 -0
  215. package/dist/db/snapshots.js +89 -0
  216. package/dist/db/sql.d.ts +5 -0
  217. package/dist/db/sql.js +5 -0
  218. package/dist/db/state.d.ts +12 -0
  219. package/dist/db/state.js +27 -0
  220. package/dist/db/sweep.d.ts +13 -0
  221. package/dist/db/sweep.js +90 -0
  222. package/dist/db/txid.d.ts +7 -0
  223. package/dist/db/txid.js +12 -0
  224. package/dist/define.d.ts +3 -0
  225. package/dist/define.js +6 -0
  226. package/dist/endpoints/events.d.ts +7 -0
  227. package/dist/endpoints/events.js +98 -0
  228. package/dist/endpoints/index.d.ts +18 -0
  229. package/dist/endpoints/index.js +160 -0
  230. package/dist/endpoints/manifest.d.ts +7 -0
  231. package/dist/endpoints/manifest.js +30 -0
  232. package/dist/endpoints/preflight.d.ts +8 -0
  233. package/dist/endpoints/preflight.js +25 -0
  234. package/dist/endpoints/previewToken.d.ts +7 -0
  235. package/dist/endpoints/previewToken.js +54 -0
  236. package/dist/endpoints/recompute.d.ts +7 -0
  237. package/dist/endpoints/recompute.js +41 -0
  238. package/dist/endpoints/results.d.ts +24 -0
  239. package/dist/endpoints/results.js +136 -0
  240. package/dist/endpoints/summary.d.ts +7 -0
  241. package/dist/endpoints/summary.js +40 -0
  242. package/dist/endpoints/transitions.d.ts +42 -0
  243. package/dist/endpoints/transitions.js +154 -0
  244. package/dist/errors.d.ts +27 -0
  245. package/dist/errors.js +33 -0
  246. package/dist/events/body.d.ts +7 -0
  247. package/dist/events/body.js +43 -0
  248. package/dist/events/dimensions.d.ts +4 -0
  249. package/dist/events/dimensions.js +51 -0
  250. package/dist/events/preview.d.ts +2 -0
  251. package/dist/events/preview.js +9 -0
  252. package/dist/events/request.d.ts +3 -0
  253. package/dist/events/request.js +14 -0
  254. package/dist/events/rows.d.ts +7 -0
  255. package/dist/events/rows.js +65 -0
  256. package/dist/exports/adminClient.d.ts +16 -0
  257. package/dist/exports/adminClient.js +17 -0
  258. package/dist/exports/client.d.ts +7 -0
  259. package/dist/exports/client.js +7 -0
  260. package/dist/exports/index.d.ts +4 -0
  261. package/dist/exports/index.js +3 -0
  262. package/dist/exports/proxy.d.ts +4 -0
  263. package/dist/exports/proxy.js +3 -0
  264. package/dist/exports/puck.d.ts +4 -0
  265. package/dist/exports/puck.js +3 -0
  266. package/dist/exports/puckEditor.d.ts +1 -0
  267. package/dist/exports/puckEditor.js +2 -0
  268. package/dist/exports/rsc.d.ts +13 -0
  269. package/dist/exports/rsc.js +13 -0
  270. package/dist/exports/runtimeProxy.d.ts +4 -0
  271. package/dist/exports/runtimeProxy.js +2 -0
  272. package/dist/exports/runtimeServer.d.ts +2 -0
  273. package/dist/exports/runtimeServer.js +1 -0
  274. package/dist/fields/armSelect.d.ts +7 -0
  275. package/dist/fields/armSelect.js +33 -0
  276. package/dist/globals/state.d.ts +3 -0
  277. package/dist/globals/state.js +31 -0
  278. package/dist/hooks/contentChanges.d.ts +3 -0
  279. package/dist/hooks/contentChanges.js +10 -0
  280. package/dist/hooks/hostHook.d.ts +5 -0
  281. package/dist/hooks/hostHook.js +20 -0
  282. package/dist/index.d.ts +1 -0
  283. package/dist/index.js +4 -0
  284. package/dist/manifest/cache.d.ts +10 -0
  285. package/dist/manifest/cache.js +51 -0
  286. package/dist/manifest/compile.d.ts +63 -0
  287. package/dist/manifest/compile.js +237 -0
  288. package/dist/onInit.d.ts +5 -0
  289. package/dist/onInit.js +13 -0
  290. package/dist/options/fromReq.d.ts +3 -0
  291. package/dist/options/fromReq.js +5 -0
  292. package/dist/options.d.ts +9 -0
  293. package/dist/options.js +107 -0
  294. package/dist/plugin.d.ts +7 -0
  295. package/dist/plugin.js +62 -0
  296. package/dist/proxy/apply.d.ts +3 -0
  297. package/dist/proxy/apply.js +5 -0
  298. package/dist/proxy/consentFallback.d.ts +5 -0
  299. package/dist/proxy/consentFallback.js +27 -0
  300. package/dist/proxy/control.d.ts +6 -0
  301. package/dist/proxy/control.js +36 -0
  302. package/dist/proxy/createProxy.d.ts +3 -0
  303. package/dist/proxy/createProxy.js +15 -0
  304. package/dist/proxy/pageRewrite.d.ts +4 -0
  305. package/dist/proxy/pageRewrite.js +41 -0
  306. package/dist/proxy/resolve.d.ts +13 -0
  307. package/dist/proxy/resolve.js +163 -0
  308. package/dist/proxy/skip.d.ts +1 -0
  309. package/dist/proxy/skip.js +9 -0
  310. package/dist/puck/ExperimentPicker.d.ts +5 -0
  311. package/dist/puck/ExperimentPicker.js +88 -0
  312. package/dist/puck/ExperimentSlot.d.ts +3 -0
  313. package/dist/puck/ExperimentSlot.js +16 -0
  314. package/dist/puck/copy.d.ts +14 -0
  315. package/dist/puck/copy.js +14 -0
  316. package/dist/puck/editor/CreateExperimentDrawer.d.ts +5 -0
  317. package/dist/puck/editor/CreateExperimentDrawer.js +120 -0
  318. package/dist/puck/editor/ExperimentSlotEditor.d.ts +3 -0
  319. package/dist/puck/editor/ExperimentSlotEditor.js +225 -0
  320. package/dist/puck/editor/cloneSlot.d.ts +3 -0
  321. package/dist/puck/editor/cloneSlot.js +41 -0
  322. package/dist/puck/editor/copy.d.ts +25 -0
  323. package/dist/puck/editor/copy.js +25 -0
  324. package/dist/puck/editor/editor.model.d.ts +16 -0
  325. package/dist/puck/editor/editor.model.js +33 -0
  326. package/dist/puck/experimentSlotField.d.ts +5 -0
  327. package/dist/puck/experimentSlotField.js +13 -0
  328. package/dist/puck/slot.model.d.ts +2 -0
  329. package/dist/puck/slot.model.js +11 -0
  330. package/dist/puck/slotConfig.d.ts +5 -0
  331. package/dist/puck/slotConfig.js +25 -0
  332. package/dist/results/aggregate.d.ts +34 -0
  333. package/dist/results/aggregate.js +66 -0
  334. package/dist/results/analyse.d.ts +79 -0
  335. package/dist/results/analyse.js +378 -0
  336. package/dist/results/cuped.d.ts +16 -0
  337. package/dist/results/cuped.js +31 -0
  338. package/dist/results/decideGuard.d.ts +3 -0
  339. package/dist/results/decideGuard.js +8 -0
  340. package/dist/results/guardrails.d.ts +17 -0
  341. package/dist/results/guardrails.js +10 -0
  342. package/dist/results/history.d.ts +13 -0
  343. package/dist/results/history.js +39 -0
  344. package/dist/results/identityCredit.d.ts +16 -0
  345. package/dist/results/identityCredit.js +46 -0
  346. package/dist/results/power.d.ts +15 -0
  347. package/dist/results/power.js +60 -0
  348. package/dist/results/rolloutUnits.d.ts +17 -0
  349. package/dist/results/rolloutUnits.js +26 -0
  350. package/dist/results/snapshot.d.ts +9 -0
  351. package/dist/results/snapshot.js +154 -0
  352. package/dist/results/srm.d.ts +9 -0
  353. package/dist/results/srm.js +22 -0
  354. package/dist/results/verdict.d.ts +82 -0
  355. package/dist/results/verdict.js +85 -0
  356. package/dist/runtime/assign.d.ts +23 -0
  357. package/dist/runtime/assign.js +104 -0
  358. package/dist/runtime/bot.d.ts +1 -0
  359. package/dist/runtime/bot.js +7 -0
  360. package/dist/runtime/cookie.d.ts +17 -0
  361. package/dist/runtime/cookie.js +35 -0
  362. package/dist/runtime/eligibility.d.ts +22 -0
  363. package/dist/runtime/eligibility.js +20 -0
  364. package/dist/runtime/header.d.ts +17 -0
  365. package/dist/runtime/header.js +97 -0
  366. package/dist/runtime/loaders.d.ts +17 -0
  367. package/dist/runtime/loaders.js +29 -0
  368. package/dist/runtime/normalisePath.d.ts +7 -0
  369. package/dist/runtime/normalisePath.js +15 -0
  370. package/dist/runtime/previewToken.d.ts +9 -0
  371. package/dist/runtime/previewToken.js +23 -0
  372. package/dist/runtime/proxyRuntime.d.ts +2 -0
  373. package/dist/runtime/proxyRuntime.js +22 -0
  374. package/dist/runtime/seed.d.ts +2 -0
  375. package/dist/runtime/seed.js +4 -0
  376. package/dist/runtime/signing.d.ts +3 -0
  377. package/dist/runtime/signing.js +16 -0
  378. package/dist/runtime/targeting.d.ts +6 -0
  379. package/dist/runtime/targeting.js +9 -0
  380. package/dist/server/context.d.ts +10 -0
  381. package/dist/server/context.js +59 -0
  382. package/dist/server/eraseUser.d.ts +7 -0
  383. package/dist/server/eraseUser.js +4 -0
  384. package/dist/server/getAssignments.d.ts +9 -0
  385. package/dist/server/getAssignments.js +227 -0
  386. package/dist/server/getFlagPoint.d.ts +11 -0
  387. package/dist/server/getFlagPoint.js +36 -0
  388. package/dist/server/headerRevision.d.ts +6 -0
  389. package/dist/server/headerRevision.js +10 -0
  390. package/dist/server/linkIdentity.d.ts +9 -0
  391. package/dist/server/linkIdentity.js +34 -0
  392. package/dist/server/metadata.d.ts +7 -0
  393. package/dist/server/metadata.js +24 -0
  394. package/dist/server/previewDraft.d.ts +7 -0
  395. package/dist/server/previewDraft.js +51 -0
  396. package/dist/server/recordContentChange.d.ts +7 -0
  397. package/dist/server/recordContentChange.js +150 -0
  398. package/dist/server/recordExposures.d.ts +7 -0
  399. package/dist/server/recordExposures.js +56 -0
  400. package/dist/server/request.d.ts +7 -0
  401. package/dist/server/request.js +39 -0
  402. package/dist/server/resolveExperimentData.d.ts +6 -0
  403. package/dist/server/resolveExperimentData.js +64 -0
  404. package/dist/server/runResults.d.ts +22 -0
  405. package/dist/server/runResults.js +307 -0
  406. package/dist/server/serverRuntime.d.ts +7 -0
  407. package/dist/server/serverRuntime.js +20 -0
  408. package/dist/server/sitemap.d.ts +3 -0
  409. package/dist/server/sitemap.js +6 -0
  410. package/dist/server/toClientAssignments.d.ts +7 -0
  411. package/dist/server/toClientAssignments.js +56 -0
  412. package/dist/server/trackConversion.d.ts +12 -0
  413. package/dist/server/trackConversion.js +69 -0
  414. package/dist/targeting/ops.d.ts +8 -0
  415. package/dist/targeting/ops.js +58 -0
  416. package/dist/transitions/addMetric.d.ts +16 -0
  417. package/dist/transitions/addMetric.js +126 -0
  418. package/dist/transitions/allocate.d.ts +9 -0
  419. package/dist/transitions/allocate.js +84 -0
  420. package/dist/transitions/archive.d.ts +9 -0
  421. package/dist/transitions/archive.js +46 -0
  422. package/dist/transitions/checkStart.d.ts +61 -0
  423. package/dist/transitions/checkStart.js +104 -0
  424. package/dist/transitions/confirmPhrases.d.ts +5 -0
  425. package/dist/transitions/confirmPhrases.js +18 -0
  426. package/dist/transitions/decide.d.ts +9 -0
  427. package/dist/transitions/decide.js +138 -0
  428. package/dist/transitions/deleteExperiment.d.ts +5 -0
  429. package/dist/transitions/deleteExperiment.js +66 -0
  430. package/dist/transitions/kernel.d.ts +31 -0
  431. package/dist/transitions/kernel.js +69 -0
  432. package/dist/transitions/makeContent.d.ts +20 -0
  433. package/dist/transitions/makeContent.js +411 -0
  434. package/dist/transitions/phaseRecord.d.ts +27 -0
  435. package/dist/transitions/phaseRecord.js +81 -0
  436. package/dist/transitions/placements.d.ts +26 -0
  437. package/dist/transitions/placements.js +89 -0
  438. package/dist/transitions/preflightData.d.ts +21 -0
  439. package/dist/transitions/preflightData.js +317 -0
  440. package/dist/transitions/releaseHoldout.d.ts +8 -0
  441. package/dist/transitions/releaseHoldout.js +30 -0
  442. package/dist/transitions/resolveCaps.d.ts +28 -0
  443. package/dist/transitions/resolveCaps.js +68 -0
  444. package/dist/transitions/start.d.ts +26 -0
  445. package/dist/transitions/start.js +220 -0
  446. package/dist/transitions/stop.d.ts +8 -0
  447. package/dist/transitions/stop.js +25 -0
  448. package/dist/types/admin.d.ts +20 -0
  449. package/dist/types/admin.js +1 -0
  450. package/dist/types/assignments.d.ts +57 -0
  451. package/dist/types/assignments.js +1 -0
  452. package/dist/types/contracts.d.ts +141 -0
  453. package/dist/types/contracts.js +1 -0
  454. package/dist/types/endpoints.d.ts +135 -0
  455. package/dist/types/endpoints.js +1 -0
  456. package/dist/types/index.d.ts +8 -0
  457. package/dist/types/index.js +8 -0
  458. package/dist/types/manifest.d.ts +42 -0
  459. package/dist/types/manifest.js +1 -0
  460. package/dist/types/puck.d.ts +23 -0
  461. package/dist/types/puck.js +1 -0
  462. package/dist/types/runtime.d.ts +59 -0
  463. package/dist/types/runtime.js +1 -0
  464. package/dist/types/snapshot.d.ts +117 -0
  465. package/dist/types/snapshot.js +1 -0
  466. package/package.json +138 -3
@@ -0,0 +1,36 @@
1
+ import { getAssignments } from './getAssignments.js';
2
+ import { recordExposures } from './recordExposures.js';
3
+ import { suppressExposure } from './context.js';
4
+ export async function getFlagPoint(serverRuntime, id, opts) {
5
+ const assignments = await getAssignments(serverRuntime, opts);
6
+ const point = Object.hasOwn(assignments.flagPoints, id) ? assignments.flagPoints[id] : {
7
+ arm: 'control',
8
+ params: {},
9
+ source: 'default',
10
+ exposable: false
11
+ };
12
+ const result = {
13
+ ...point,
14
+ params: {
15
+ ...point.params
16
+ },
17
+ exposable: point.exposable && !suppressExposure(assignments)
18
+ };
19
+ return {
20
+ ...result,
21
+ async expose (renderedArm) {
22
+ if (result.policy !== 'manual' || !result.exposable || !result.experiment || result.phase === undefined) return;
23
+ try {
24
+ await recordExposures(serverRuntime, [
25
+ {
26
+ slug: result.experiment,
27
+ arm: renderedArm,
28
+ phase: result.phase
29
+ }
30
+ ], assignments);
31
+ } catch {
32
+ console.error('[payload-experiments] flag point exposure failed');
33
+ }
34
+ }
35
+ };
36
+ }
@@ -0,0 +1,6 @@
1
+ /** Authenticate before a revision can trigger I/O. Entry/phase validation stays in the shared decoder. */
2
+ export declare function verifiedHeaderRevision(value: string | null, opts: {
3
+ secrets: readonly string[];
4
+ visitorId?: string;
5
+ userId?: string;
6
+ }): number | null;
@@ -0,0 +1,10 @@
1
+ import { verify } from '../runtime/signing.js';
2
+ /** Authenticate before a revision can trigger I/O. Entry/phase validation stays in the shared decoder. */ export function verifiedHeaderRevision(value, opts) {
3
+ if (!value || Buffer.byteLength(value) > 1024) return null;
4
+ const parts = value.split('.');
5
+ if (parts.length !== 5) return null;
6
+ const [version, revision, flags, entries, mac] = parts;
7
+ if (version !== 'v1' || !/^(0|[1-9]\d*)$/.test(revision) || !Number.isSafeInteger(Number(revision))) return null;
8
+ if (!/^[sbpu]*$/.test(flags) || new Set(flags).size !== flags.length) return null;
9
+ return verify(`xp:assign:${opts.visitorId ?? ''}|${opts.userId ?? ''}|${flags}|${entries}|${revision}`, mac, opts.secrets) ? Number(revision) : null;
10
+ }
@@ -0,0 +1,9 @@
1
+ import type { ExperimentsServerRuntime } from '../types/runtime.js';
2
+ export declare function linkIdentity<TUser extends {
3
+ id: string | number;
4
+ } = {
5
+ id: string | number;
6
+ }>(serverRuntime: ExperimentsServerRuntime<TUser>, opts: {
7
+ headers: Headers;
8
+ userId: string;
9
+ }): Promise<void>;
@@ -0,0 +1,34 @@
1
+ import { NextRequest } from 'next/server.js';
2
+ import { insertIdentityOnOwnConnection } from '../db/identities.js';
3
+ import { readUnitCookie } from '../runtime/cookie.js';
4
+ export async function linkIdentity(serverRuntime, opts) {
5
+ let payload;
6
+ try {
7
+ const runtime = serverRuntime.proxyRuntime;
8
+ // Consent sees cookies and headers only; the URL is a placeholder.
9
+ let consent = true;
10
+ try {
11
+ consent = runtime.cookie.consent?.(new NextRequest('http://consent.invalid/', {
12
+ headers: opts.headers
13
+ })) !== false;
14
+ } catch {
15
+ console.error('[payload-experiments] consent failed; treating consent as false');
16
+ consent = false;
17
+ }
18
+ if (!consent) return;
19
+ const anonymousId = readUnitCookie(opts.headers, runtime);
20
+ if (!anonymousId) return;
21
+ payload = await serverRuntime.getPayload();
22
+ await insertIdentityOnOwnConnection(payload, {
23
+ anonymousId,
24
+ userId: opts.userId
25
+ });
26
+ } catch (error) {
27
+ try {
28
+ payload?.logger.error({
29
+ err: error,
30
+ msg: 'Experiments: linkIdentity failed'
31
+ });
32
+ } catch {}
33
+ }
34
+ }
@@ -0,0 +1,7 @@
1
+ import type { Metadata } from 'next';
2
+ import type { ExperimentsServerRuntime } from '../types/runtime.js';
3
+ export declare function experimentMetadata<TUser extends {
4
+ id: string | number;
5
+ } = {
6
+ id: string | number;
7
+ }>(serverRuntime: ExperimentsServerRuntime<TUser>, path: string): Promise<Pick<Metadata, 'robots' | 'alternates'>>;
@@ -0,0 +1,24 @@
1
+ import { findNormalisedPathKey, normalisePath } from '../runtime/normalisePath.js';
2
+ import { serverManifest } from './context.js';
3
+ export async function experimentMetadata(serverRuntime, path) {
4
+ const manifest = await serverManifest(serverRuntime.proxyRuntime);
5
+ const live = manifest?.experiments.find((e)=>e.kind === 'page' && e.arms.some((a)=>a.pageTarget !== undefined && normalisePath(a.pageTarget) === normalisePath(path)));
6
+ if (live) {
7
+ const controlPath = live.arms.find((a)=>a.kind === 'control')?.pageTarget;
8
+ return controlPath && normalisePath(path) !== normalisePath(controlPath) ? {
9
+ robots: {
10
+ index: false
11
+ },
12
+ alternates: {
13
+ canonical: controlPath
14
+ }
15
+ } : {};
16
+ }
17
+ const archivedPath = manifest ? findNormalisedPathKey(manifest.archivedPages, path) : undefined;
18
+ const archived = archivedPath === undefined ? undefined : manifest?.archivedPages[archivedPath];
19
+ return archived ? {
20
+ alternates: {
21
+ canonical: archived.winnerPath
22
+ }
23
+ } : {};
24
+ }
@@ -0,0 +1,7 @@
1
+ import type { Payload } from 'payload';
2
+ import type { PreviewToken } from '../runtime/previewToken.js';
3
+ import type { Assignments } from '../types/assignments.js';
4
+ /** Draft previews use the authenticated manager's normal collection access. */
5
+ export declare function previewDraft(payload: Payload, user: {
6
+ id: string | number;
7
+ } | null, token: PreviewToken, assignments: Assignments, headers: Headers): Promise<void>;
@@ -0,0 +1,51 @@
1
+ /** Draft previews use the authenticated manager's normal collection access. */ export async function previewDraft(payload, user, token, assignments, headers) {
2
+ if (!user) return;
3
+ try {
4
+ const doc = await payload.findByID({
5
+ collection: 'xp-experiments',
6
+ id: token.e,
7
+ depth: 0,
8
+ overrideAccess: false,
9
+ user,
10
+ req: {
11
+ user: user,
12
+ headers
13
+ }
14
+ });
15
+ if (doc.status !== 'draft' && doc.status !== 'stopped' || doc.phase !== token.p || typeof doc.slug !== 'string' || !Array.isArray(doc.arms)) return;
16
+ const arm = doc.arms.find((a)=>a.key === token.a);
17
+ if (!arm || ![
18
+ 'render',
19
+ 'viewport',
20
+ 'pageview',
21
+ 'manual'
22
+ ].includes(doc.exposurePolicy)) return;
23
+ assignments.preview = true;
24
+ assignments.bySlug[doc.slug] = {
25
+ slug: doc.slug,
26
+ experimentId: doc.id,
27
+ arm: token.a,
28
+ phase: token.p,
29
+ exposable: false,
30
+ policy: doc.exposurePolicy,
31
+ source: 'preview'
32
+ };
33
+ if (typeof doc.flagPoint === 'string') {
34
+ const content = arm.kind === 'holdout' ? doc.arms.find((a)=>a.kind === 'control') : arm;
35
+ assignments.flagPoints[doc.flagPoint] = {
36
+ arm: token.a,
37
+ params: {
38
+ ...content?.params
39
+ },
40
+ source: 'experiment',
41
+ experiment: doc.slug,
42
+ experimentId: doc.id,
43
+ phase: token.p,
44
+ policy: doc.exposurePolicy,
45
+ exposable: false
46
+ };
47
+ }
48
+ } catch {
49
+ console.error('[payload-experiments] draft preview unavailable');
50
+ }
51
+ }
@@ -0,0 +1,7 @@
1
+ import type { CollectionAfterChangeHook, CollectionBeforeChangeHook } from 'payload';
2
+ /** Paired beforeChange capture: previousDoc may be an autosaved draft. */
3
+ export declare function capturePublishedContent({ req, collection, originalDoc, operation }: Parameters<CollectionBeforeChangeHook>[0]): Promise<void>;
4
+ type ContentChangeArgs = Pick<Parameters<CollectionAfterChangeHook>[0], 'doc' | 'previousDoc' | 'req' | 'collection'>;
5
+ /** Publish-only host helper. Audit failures are logged, never thrown into saves. */
6
+ export declare function recordContentChange(args: ContentChangeArgs): Promise<void>;
7
+ export {};
@@ -0,0 +1,150 @@
1
+ import { isDeepStrictEqual } from 'node:util';
2
+ import { appendContentChange, contentChangeSavepoint, previousPublishedContent, runningContentExperiment } from '../db/appends.js';
3
+ import { txExecutor } from '../db/executor.js';
4
+ import { puckCollections } from '../options.js';
5
+ import { withTransition } from '../transitions/kernel.js';
6
+ const slots = [
7
+ 'control',
8
+ 'variantA',
9
+ 'variantB',
10
+ 'variantC'
11
+ ];
12
+ const object = (value)=>value !== null && typeof value === 'object' && !Array.isArray(value);
13
+ function bindings(data, puck) {
14
+ const found = new Map();
15
+ function add(field, value, content) {
16
+ const key = field + ':' + value;
17
+ const binding = found.get(key) ?? {
18
+ field,
19
+ value,
20
+ contents: []
21
+ };
22
+ binding.contents.push(content);
23
+ found.set(key, binding);
24
+ }
25
+ function walk(value) {
26
+ if (Array.isArray(value)) {
27
+ value.forEach(walk);
28
+ return;
29
+ }
30
+ if (!object(value)) return;
31
+ if (puck && value.type === 'ExperimentSlot' && object(value.props)) {
32
+ const props = value.props;
33
+ const slug = typeof props.experiment === 'string' ? props.experiment : object(props.experiment) ? props.experiment.slug : undefined;
34
+ if (typeof slug === 'string' && slug) add('slug', slug, {
35
+ id: props.id,
36
+ ...Object.fromEntries(slots.map((slot)=>[
37
+ slot,
38
+ props[slot] ?? []
39
+ ]))
40
+ });
41
+ } else if (!puck) {
42
+ // Arm-select stores { experiment, arm }. The containing host row owns the
43
+ // content (e.g. vars[].experimentArm + vars[].blocks), not the tag alone.
44
+ for (const tag of Object.values(value)){
45
+ if (object(tag) && typeof tag.experiment === 'string' && tag.experiment && typeof tag.arm === 'string') {
46
+ add('id', tag.experiment, value);
47
+ }
48
+ }
49
+ }
50
+ Object.values(value).forEach(walk);
51
+ }
52
+ walk(data);
53
+ return found;
54
+ }
55
+ const baselineKey = (collection, id)=>`${collection}:${id}`;
56
+ /** Paired beforeChange capture: previousDoc may be an autosaved draft. */ export async function capturePublishedContent({ req, collection, originalDoc, operation }) {
57
+ if (!collection.versions || !collection.versions.drafts) return;
58
+ if (await req.transactionID == null) {
59
+ req.payload.logger?.debug('[payload-experiments] contentChanges baseline skipped without a transaction');
60
+ return;
61
+ }
62
+ const id = operation === 'create' ? '__create__' : originalDoc.id;
63
+ const baselines = req.context.xpPublishedContent ??= {};
64
+ const key = baselineKey(collection.slug, id);
65
+ delete baselines[key];
66
+ const audit = await contentChangeSavepoint(txExecutor(req), async ()=>operation === 'create' ? undefined : previousPublishedContent(req, collection.slug, id));
67
+ if (!audit.ok) throw audit.error;
68
+ baselines[key] = {
69
+ collection: collection.slug,
70
+ id,
71
+ doc: audit.result
72
+ };
73
+ }
74
+ /** Publish-only host helper. Audit failures are logged, never thrown into saves. */ export async function recordContentChange(args) {
75
+ try {
76
+ await auditContentChange(args);
77
+ } catch (error) {
78
+ console.error('[payload-experiments] contentChanges failed; the document was saved without it', error);
79
+ }
80
+ }
81
+ async function auditContentChange({ doc, previousDoc, req, collection }) {
82
+ const drafts = Boolean(collection.versions && collection.versions.drafts);
83
+ if (drafts && doc._status !== 'published') return;
84
+ if (await req.transactionID == null) {
85
+ req.payload.logger?.debug('[payload-experiments] contentChanges skipped without a transaction');
86
+ return;
87
+ }
88
+ const baselines = req.context.xpPublishedContent;
89
+ const key = baselineKey(collection.slug, previousDoc?.id == null ? '__create__' : doc.id);
90
+ const baseline = baselines?.[key];
91
+ if (baselines) delete baselines[key];
92
+ // Missing capture must never turn an unchanged publish into a false marker.
93
+ if (drafts && !baseline) {
94
+ req.payload.logger?.debug('[payload-experiments] contentChanges skipped without a captured published baseline');
95
+ return;
96
+ }
97
+ const options = req.payload.config.custom?.xp;
98
+ const registration = puckCollections(options ?? {}).find((entry)=>entry.slug === collection.slug);
99
+ const after = bindings(registration ? doc[registration.field] : doc, Boolean(registration));
100
+ const changes = (previous)=>{
101
+ const before = bindings(registration && object(previous) ? previous[registration.field] : previous, Boolean(registration));
102
+ return [
103
+ ...new Set([
104
+ ...before.keys(),
105
+ ...after.keys()
106
+ ])
107
+ ].filter((key)=>!isDeepStrictEqual(before.get(key)?.contents, after.get(key)?.contents)).map((key)=>after.get(key) ?? before.get(key));
108
+ };
109
+ if (!drafts && !changes(previousDoc).length) return;
110
+ // Include discovery reads in the savepoint: a SQL read error also aborts Postgres.
111
+ // An explicit host call must supply its afterChange request's transaction.
112
+ const executor = txExecutor(req);
113
+ const audit = await contentChangeSavepoint(executor, async ()=>{
114
+ const changed = changes(drafts ? baseline?.doc : previousDoc);
115
+ const experiments = new Map();
116
+ for (const binding of changed){
117
+ const experiment = await runningContentExperiment(executor, binding);
118
+ if (experiment) experiments.set(String(experiment.id), experiment.id);
119
+ }
120
+ // Successful audit locks persist until commit; acquire multiple E locks in order.
121
+ for (const [, experimentId] of [
122
+ ...experiments
123
+ ].sort(([a], [b])=>a.localeCompare(b))){
124
+ await withTransition(req, {
125
+ experimentId,
126
+ bump: false,
127
+ audit: true
128
+ }, async ({ exec })=>{
129
+ const experiment = await runningContentExperiment(exec, {
130
+ field: 'id',
131
+ value: experimentId
132
+ });
133
+ if (!experiment) return;
134
+ await appendContentChange(exec, {
135
+ experimentId,
136
+ phase: experiment.phase,
137
+ entry: {
138
+ at: new Date().toISOString(),
139
+ doc: {
140
+ collection: collection.slug,
141
+ id: doc.id
142
+ },
143
+ by: req.user?.id ?? null
144
+ }
145
+ });
146
+ });
147
+ }
148
+ });
149
+ if (!audit.ok) throw audit.error;
150
+ }
@@ -0,0 +1,7 @@
1
+ import type { ExperimentsServerRuntime } from '../types/runtime.js';
2
+ import type { Assignments, RenderedExposure } from '../types/assignments.js';
3
+ export declare function recordExposures<TUser extends {
4
+ id: string | number;
5
+ } = {
6
+ id: string | number;
7
+ }>(serverRuntime: ExperimentsServerRuntime<TUser>, rendered: RenderedExposure[], ctx: Assignments): Promise<void>;
@@ -0,0 +1,56 @@
1
+ import { pooledExecutor } from '../db/executor.js';
2
+ import { insertEvents } from '../db/events.js';
3
+ import { exposureDimensions } from '../events/dimensions.js';
4
+ import { requestAttributesOf } from './context.js';
5
+ import { readManifestRow } from '../db/manifest.js';
6
+ export async function recordExposures(serverRuntime, rendered, ctx) {
7
+ let payload;
8
+ try {
9
+ if (ctx.bot || ctx.staff || ctx.preview || ctx.method === 'HEAD') return;
10
+ const candidates = rendered.flatMap((entry)=>{
11
+ const assignment = ctx.bySlug[entry.slug];
12
+ return assignment?.exposable && (assignment.policy === 'render' || assignment.policy === 'manual') && assignment.arm === entry.arm && assignment.phase === entry.phase ? [
13
+ {
14
+ ...assignment
15
+ }
16
+ ] : [];
17
+ });
18
+ if (!candidates.length) return;
19
+ const { visitorId, userId } = ctx;
20
+ const ts = new Date().toISOString();
21
+ payload = await serverRuntime.getPayload();
22
+ const options = payload.config?.custom?.xp;
23
+ const dimensions = exposureDimensions(requestAttributesOf(ctx), options?.events?.dimensions);
24
+ const exec = pooledExecutor(payload);
25
+ // Assignments intentionally omit unitType; the immutable manifest field selects the unit.
26
+ const manifest = await readManifestRow(exec);
27
+ const rows = candidates.flatMap((assignment)=>{
28
+ const experiment = manifest?.manifest.experiments.find((exp)=>exp.id === assignment.experimentId && exp.slug === assignment.slug);
29
+ if (!experiment) return [];
30
+ const unitId = experiment.unitType === 'visitor' ? visitorId : userId;
31
+ if (!unitId) return [];
32
+ return [
33
+ {
34
+ type: 'exposure',
35
+ experimentId: assignment.experimentId,
36
+ phase: assignment.phase,
37
+ arm: assignment.arm,
38
+ unitType: experiment.unitType,
39
+ unitId,
40
+ userId,
41
+ ts,
42
+ dimensions,
43
+ dedupeKey: `exposure:${assignment.experimentId}:${assignment.phase}:${assignment.arm}:${unitId}:${ts.slice(0, 10)}`
44
+ }
45
+ ];
46
+ });
47
+ await insertEvents(exec, rows, (message)=>payload.logger.error(message));
48
+ } catch (error) {
49
+ try {
50
+ payload?.logger.error({
51
+ err: error,
52
+ msg: 'Experiments: recordExposures failed'
53
+ });
54
+ } catch {}
55
+ }
56
+ }
@@ -0,0 +1,7 @@
1
+ import { NextRequest } from 'next/server.js';
2
+ /** Only proxy-signed context can supply a URL, method or consent decision. */
3
+ export declare function serverRequest(headers: Headers, secrets: readonly string[]): {
4
+ request: NextRequest;
5
+ hasContext: boolean;
6
+ consent?: boolean;
7
+ };
@@ -0,0 +1,39 @@
1
+ import { NextRequest } from 'next/server.js';
2
+ import { XP_REQUEST_HEADER } from '../constants.js';
3
+ import { verify } from '../runtime/signing.js';
4
+ /** Only proxy-signed context can supply a URL, method or consent decision. */ export function serverRequest(headers, secrets) {
5
+ const fallback = ()=>({
6
+ request: new NextRequest('https://xp.invalid/', {
7
+ headers,
8
+ method: 'UNKNOWN'
9
+ }),
10
+ hasContext: false
11
+ });
12
+ const value = headers.get(XP_REQUEST_HEADER);
13
+ if (!value || Buffer.byteLength(value) > 2048) return fallback();
14
+ const parts = /^([^|]*)\|(.+)\|(c[01])\|([A-Za-z0-9_-]{43})$/.exec(value);
15
+ if (!parts) return fallback();
16
+ const verb = parts[1], path = parts[2], consent = parts[3], mac = parts[4];
17
+ if (!verify(`xp:request:${verb}|${path}|${consent}`, mac, secrets) || !path.startsWith('/') || /[\\\r\n#]/.test(path)) return fallback();
18
+ const method = [
19
+ 'GET',
20
+ 'HEAD',
21
+ 'POST',
22
+ 'PUT',
23
+ 'PATCH',
24
+ 'DELETE',
25
+ 'OPTIONS'
26
+ ].includes(verb) ? verb : 'UNKNOWN';
27
+ try {
28
+ return {
29
+ request: new NextRequest(`https://xp.invalid${path}`, {
30
+ headers,
31
+ method
32
+ }),
33
+ hasContext: true,
34
+ consent: consent === 'c1'
35
+ };
36
+ } catch {
37
+ return fallback();
38
+ }
39
+ }
@@ -0,0 +1,6 @@
1
+ import type { Data } from '@puckeditor/core';
2
+ import type { Assignments, RenderedExposure } from '../types/assignments.js';
3
+ export declare function resolveExperimentData<TData extends Data>(puckData: TData, assignments: Assignments): {
4
+ data: TData;
5
+ rendered: RenderedExposure[];
6
+ };
@@ -0,0 +1,64 @@
1
+ import { manifestOf, suppressExposure } from './context.js';
2
+ export function resolveExperimentData(puckData, assignments) {
3
+ const rendered = new Map();
4
+ const slots = [
5
+ 'control',
6
+ 'variantA',
7
+ 'variantB',
8
+ 'variantC'
9
+ ];
10
+ const manifest = manifestOf(assignments);
11
+ function walk(value) {
12
+ if (Array.isArray(value)) return value.map(walk);
13
+ if (!value || typeof value !== 'object') return value;
14
+ const node = value;
15
+ if (node.type !== 'ExperimentSlot') return Object.fromEntries(Object.entries(node).map(([key, item])=>[
16
+ key,
17
+ walk(item)
18
+ ]));
19
+ const props = node.props && typeof node.props === 'object' ? node.props : {};
20
+ // Stored Puck JSON is untrusted, including unbound and unknown experiments.
21
+ const clean = {
22
+ ...props
23
+ };
24
+ delete clean.xpSlot;
25
+ delete clean.xpArm;
26
+ delete clean.xpExpose;
27
+ const ref = props.experiment;
28
+ const slug = typeof ref?.slug === 'string' ? ref.slug : undefined;
29
+ const assignment = slug && Object.hasOwn(assignments.bySlug, slug) ? assignments.bySlug[slug] : undefined;
30
+ const experiment = manifest?.experiments.find((e)=>e.slug === slug);
31
+ const arm = experiment?.arms.find((a)=>a.key === assignment?.arm);
32
+ const archived = slug && Object.hasOwn(assignments.archivedWinners, slug) ? assignments.archivedWinners[slug] : undefined;
33
+ const selected = assignment ? assignment.arm === 'holdout' ? 'control' : arm?.slot ?? assignment.arm : archived ?? 'control';
34
+ const slot = slots.includes(selected) ? selected : 'control';
35
+ clean.xpSlot = slot;
36
+ if (assignment) {
37
+ clean.xpArm = assignment.arm;
38
+ if (assignment.exposable && !suppressExposure(assignments)) {
39
+ const exposure = {
40
+ slug: assignment.slug,
41
+ arm: assignment.arm,
42
+ phase: assignment.phase
43
+ };
44
+ // A missing slot has rendered no experimental content.
45
+ if (Array.isArray(props[slot])) {
46
+ if (assignment.policy === 'render') rendered.set(`${assignment.slug}|${assignment.phase}|${assignment.arm}`, exposure);
47
+ if (assignment.policy === 'viewport') clean.xpExpose = exposure;
48
+ }
49
+ }
50
+ }
51
+ for (const name of slots)clean[name] = name === slot ? walk(props[name] ?? []) : [];
52
+ for (const [key, item] of Object.entries(clean))if (!slots.includes(key)) clean[key] = walk(item);
53
+ return Object.fromEntries(Object.entries(node).map(([key, item])=>[
54
+ key,
55
+ key === 'props' ? clean : walk(item)
56
+ ]));
57
+ }
58
+ return {
59
+ data: walk(puckData),
60
+ rendered: [
61
+ ...rendered.values()
62
+ ]
63
+ };
64
+ }
@@ -0,0 +1,22 @@
1
+ import type { Payload } from 'payload';
2
+ import type { DocId } from '../types/contracts.js';
3
+ type UnavailableMetric = {
4
+ experimentId: DocId;
5
+ phase: number;
6
+ metricId: DocId;
7
+ reason: string;
8
+ };
9
+ export declare function runResults(payload: Payload, { budgetMs, experimentId, sweep }?: {
10
+ budgetMs?: number;
11
+ experimentId?: DocId;
12
+ sweep?: boolean;
13
+ }): Promise<{
14
+ ran: number;
15
+ skipped: number;
16
+ swept: number;
17
+ processedIds: DocId[];
18
+ budgetExhausted: boolean;
19
+ unavailableMetrics?: UnavailableMetric[];
20
+ sweepAttempted?: boolean;
21
+ }>;
22
+ export {};