@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,307 @@
1
+ import { resultsCandidates, resultsExecutor, writeSnapshots } from '../db/snapshots.js';
2
+ import { sweepEvents } from '../db/sweep.js';
3
+ import { armMismatchCount, identityRows, metricEventRows, phaseExposureRows, rolloutExposureRows } from '../db/results.js';
4
+ import { raceDeadline, ResultsBudgetError, RESULTS_TIMEOUT_MARGIN_MS } from '../db/executor.js';
5
+ import { analysePhase } from '../results/analyse.js';
6
+ import { firstExposures, perUnitValues, timestampMs } from '../results/aggregate.js';
7
+ import { rolloutAnalysisUnits } from '../results/rolloutUnits.js';
8
+ import { creditUserEvents } from '../results/identityCredit.js';
9
+ async function analyseCandidate(exec, candidate, options, now, deadline, unavailableMetrics) {
10
+ const { phase } = candidate;
11
+ // Rollout assignment preserves the original test ranges, but its SRM compares
12
+ // only the shipped group against holdout with weights {100-h, h}.
13
+ const analysisPhase = phase.phaseKind === 'rollout' ? {
14
+ ...phase,
15
+ arms: phase.arms.map((arm)=>({
16
+ ...arm,
17
+ weight: arm.kind === 'holdout' ? candidate.testArms.at(-1).weight : 100 - candidate.testArms.at(-1).weight
18
+ }))
19
+ } : phase;
20
+ const to = new Date(Math.min(+now, phase.endedAt == null ? Infinity : timestampMs(phase.endedAt)));
21
+ const query = {
22
+ experimentId: phase.experiment,
23
+ phase: phase.phase,
24
+ endedAt: to
25
+ };
26
+ const exposed = firstExposures(await phaseExposureRows(exec, query), {
27
+ endedAt: to
28
+ });
29
+ let units = exposed.units;
30
+ if (phase.phaseKind === 'rollout') {
31
+ const eligible = rolloutAnalysisUnits({
32
+ exposuresAllPhases: await rolloutExposureRows(exec, {
33
+ ...query,
34
+ respectPhaseEnds: true
35
+ }),
36
+ rolloutPhase: phase.phase,
37
+ seed: phase.seed,
38
+ testWeights: candidate.testArms.map((arm)=>arm.weight),
39
+ coverage: candidate.layerSlug ? 1 : phase.allocation / 100,
40
+ ...candidate.layerSlug && candidate.layerSlices?.length ? {
41
+ layer: {
42
+ slug: candidate.layerSlug,
43
+ slices: candidate.layerSlices
44
+ }
45
+ } : {}
46
+ });
47
+ units = new Map([
48
+ ...units
49
+ ].filter(([id])=>eligible.has(id)));
50
+ }
51
+ const ids = [
52
+ ...units.keys()
53
+ ];
54
+ const identities = candidate.unitType === 'visitor' ? await identityRows(exec, {
55
+ anonymousIds: ids
56
+ }) : [];
57
+ const userIds = [
58
+ ...new Set(identities.map((identity)=>identity.userId))
59
+ ];
60
+ const linked = new Set(userIds);
61
+ const credit = (events, userKeyed)=>{
62
+ if (candidate.unitType === 'user') return events.map((event)=>({
63
+ ...event,
64
+ unitId: event.userId ?? event.unitId
65
+ }));
66
+ const userEvents = events.filter((event)=>userKeyed || event.userId != null && linked.has(event.userId)).map((event)=>({
67
+ userId: String(event.userId ?? event.unitId),
68
+ value: event.value,
69
+ ts: event.ts
70
+ }));
71
+ const credited = creditUserEvents(units, identities, userEvents).events;
72
+ return userKeyed ? credited : [
73
+ ...events.filter((event)=>event.userId == null || !linked.has(event.userId)),
74
+ ...credited
75
+ ];
76
+ };
77
+ const diagnostics = creditUserEvents(units, identities, []);
78
+ const metricData = [];
79
+ for (const definition of phase.metricDefinitions){
80
+ try {
81
+ if (Date.now() >= deadline) throw new ResultsBudgetError();
82
+ const kind = definition.kind;
83
+ const windowHours = phase.analysis.attributionWindowHours ?? definition.attributionWindowHours ?? 168;
84
+ const from = new Date([
85
+ ...units.values()
86
+ ].reduce((earliest, unit)=>Math.min(earliest, +unit.firstTs), timestampMs(phase.startedAt)));
87
+ const preFrom = new Date(+from - 14 * 86_400_000);
88
+ let events, covariates;
89
+ if (definition.source.startsWith('events:')) {
90
+ const eventName = definition.source.slice(7);
91
+ if (!options.eventSources?.some((source)=>source.name === eventName)) throw new Error('Metric source unavailable');
92
+ const read = async (start)=>{
93
+ if (candidate.unitType === 'user') return metricEventRows(exec, {
94
+ eventName,
95
+ userIds: ids,
96
+ from: start,
97
+ to
98
+ });
99
+ const direct = await metricEventRows(exec, {
100
+ eventName,
101
+ unitIds: ids,
102
+ from: start,
103
+ to
104
+ });
105
+ const signedIn = await metricEventRows(exec, {
106
+ eventName,
107
+ userIds,
108
+ from: start,
109
+ to
110
+ });
111
+ return [
112
+ ...direct,
113
+ ...signedIn
114
+ ];
115
+ };
116
+ events = credit(await read(phase.analysis.cuped === 'auto' ? preFrom : from), false);
117
+ if (phase.analysis.cuped === 'auto') {
118
+ const preUnits = new Map([
119
+ ...units
120
+ ].map(([id, unit])=>[
121
+ id,
122
+ {
123
+ arm: unit.arm,
124
+ firstTs: new Date(+unit.firstTs - 14 * 86_400_000)
125
+ }
126
+ ]));
127
+ covariates = perUnitValues(preUnits, events, {
128
+ kind,
129
+ windowHours: 14 * 24
130
+ });
131
+ }
132
+ } else {
133
+ const source = options.metricSources?.find((source)=>source.id === definition.source);
134
+ if (!source || source.kind !== kind || definition.keyedBy && source.keyedBy !== definition.keyedBy) throw new Error('Metric source unavailable');
135
+ const userKeyed = source.keyedBy === 'user' && candidate.unitType === 'visitor';
136
+ if (candidate.unitType === 'user' && source.keyedBy !== 'user') throw new Error('Metric unit type unavailable');
137
+ const sourceIds = userKeyed ? userIds : ids;
138
+ events = credit(await raceDeadline(deadline, ()=>source.query({
139
+ from,
140
+ to,
141
+ unitIds: sourceIds
142
+ })), userKeyed);
143
+ if (phase.analysis.cuped === 'auto' && source.covariate) {
144
+ const sourceUnits = userKeyed ? creditUserEvents(units, identities, userIds.map((userId)=>({
145
+ userId,
146
+ ts: now,
147
+ value: 0
148
+ }))).events.map((event)=>({
149
+ unitId: identities.find((identity)=>identity.anonymousId === event.unitId).userId,
150
+ firstExposureTs: units.get(event.unitId).firstTs
151
+ })) : [
152
+ ...units
153
+ ].map(([unitId, unit])=>({
154
+ unitId,
155
+ firstExposureTs: unit.firstTs
156
+ }));
157
+ const pre = await raceDeadline(deadline, ()=>source.covariate({
158
+ units: sourceUnits,
159
+ lookbackDays: 14
160
+ }));
161
+ if (pre.some((row)=>!Number.isFinite(row.value))) throw new Error('Covariates must be finite');
162
+ const credited = credit(pre.map((row)=>({
163
+ ...row,
164
+ ts: now
165
+ })), userKeyed);
166
+ covariates = new Map(credited.map((row)=>[
167
+ row.unitId,
168
+ row.value
169
+ ]));
170
+ }
171
+ }
172
+ if (events.some((event)=>!Number.isFinite(event.value))) throw new Error('Metric values must be finite');
173
+ metricData.push({
174
+ metricId: definition.metricId,
175
+ values: perUnitValues(units, events, {
176
+ kind,
177
+ windowHours,
178
+ endedAt: to
179
+ }),
180
+ ...covariates ? {
181
+ covariates
182
+ } : {}
183
+ });
184
+ } catch (error) {
185
+ const reason = error instanceof Error ? error.message : 'Metric source unavailable';
186
+ metricData.push({
187
+ metricId: definition.metricId,
188
+ values: new Map(),
189
+ unavailable: reason
190
+ });
191
+ if (unavailableMetrics.length < 100) unavailableMetrics.push({
192
+ experimentId: phase.experiment,
193
+ phase: phase.phase,
194
+ metricId: definition.metricId,
195
+ reason
196
+ });
197
+ if (error instanceof ResultsBudgetError || Date.now() >= deadline) throw new ResultsBudgetError();
198
+ }
199
+ }
200
+ const status = phase.endedAt != null || candidate.status === 'archived' ? 'stopped' : candidate.status;
201
+ const snapshot = analysePhase({
202
+ phase: analysisPhase,
203
+ now,
204
+ units,
205
+ metricData,
206
+ status,
207
+ excludedMultiArm: exposed.excludedMultiArm,
208
+ armMismatch: await armMismatchCount(exec, query),
209
+ identityConflictShare: userIds.length ? diagnostics.conflicts / userIds.length : 0,
210
+ ...phase.phaseKind === 'rollout' ? {
211
+ winnerArm: phase.arms.find((arm)=>arm.kind !== 'holdout').key
212
+ } : {}
213
+ });
214
+ return snapshot;
215
+ }
216
+ export async function runResults(payload, { budgetMs = 20_000, experimentId, sweep = true } = {}) {
217
+ if (!Number.isFinite(budgetMs) || budgetMs < 0) throw new RangeError('budgetMs must be finite and nonnegative');
218
+ const started = Date.now(), deadline = started + budgetMs, now = new Date(started);
219
+ const summary = {
220
+ ran: 0,
221
+ skipped: 0,
222
+ swept: 0,
223
+ processedIds: [],
224
+ budgetExhausted: false,
225
+ unavailableMetrics: [],
226
+ sweepAttempted: false
227
+ };
228
+ if (budgetMs === 0) return {
229
+ ...summary,
230
+ budgetExhausted: true
231
+ };
232
+ const options = payload.config.custom?.xp;
233
+ const retentionDays = options.events?.retentionDays ?? 180;
234
+ // Reserve up to one second (25% of short runs) for retention, even when host
235
+ // code never settles. The safety margin also leaves time to return the summary.
236
+ const analysisDeadline = deadline - (sweep ? Math.min(1000, budgetMs / 4) : 0) - RESULTS_TIMEOUT_MARGIN_MS;
237
+ const exec = resultsExecutor(payload, ()=>analysisDeadline - Date.now());
238
+ let candidates = [];
239
+ try {
240
+ candidates = await resultsCandidates(exec, {
241
+ cutoff: new Date(started - retentionDays * 86_400_000).toISOString(),
242
+ experimentId
243
+ });
244
+ } catch (error) {
245
+ summary.skipped++;
246
+ summary.budgetExhausted = error instanceof ResultsBudgetError;
247
+ payload.logger.error({
248
+ err: error,
249
+ experimentId
250
+ }, 'Experiment scheduling failed');
251
+ }
252
+ // Query order is oldest phase snapshot first; grouping keeps each experiment's
253
+ // phases together while preserving that scheduling priority.
254
+ const experiments = new Map();
255
+ for (const candidate of candidates){
256
+ const id = candidate.phase.experiment;
257
+ experiments.set(id, [
258
+ ...experiments.get(id) ?? [],
259
+ candidate
260
+ ]);
261
+ }
262
+ for (const [id, phases] of experiments){
263
+ if (Date.now() >= analysisDeadline) {
264
+ summary.budgetExhausted = true;
265
+ summary.skipped += experiments.size - summary.ran - summary.skipped;
266
+ break;
267
+ }
268
+ try {
269
+ const snapshots = [];
270
+ for (const phase of phases){
271
+ if (Date.now() >= analysisDeadline) throw new ResultsBudgetError();
272
+ snapshots.push(await analyseCandidate(exec, phase, options, now, analysisDeadline, summary.unavailableMetrics));
273
+ }
274
+ if (Date.now() >= analysisDeadline) throw new ResultsBudgetError();
275
+ await writeSnapshots(exec, snapshots);
276
+ summary.ran++;
277
+ if (summary.processedIds.length < 100) summary.processedIds.push(id);
278
+ } catch (error) {
279
+ summary.skipped++;
280
+ summary.budgetExhausted ||= error instanceof ResultsBudgetError;
281
+ payload.logger.error({
282
+ err: error,
283
+ experimentId: id
284
+ }, 'Experiment results failed');
285
+ }
286
+ }
287
+ if (sweep) {
288
+ summary.sweepAttempted = true;
289
+ const sweepDeadline = deadline - RESULTS_TIMEOUT_MARGIN_MS;
290
+ try {
291
+ const sweepExec = resultsExecutor(payload, ()=>sweepDeadline - Date.now());
292
+ summary.swept = await sweepEvents(sweepExec, {
293
+ now,
294
+ retentionDays,
295
+ shouldContinue: ()=>Date.now() < sweepDeadline,
296
+ logger: payload.logger
297
+ });
298
+ } catch (error) {
299
+ summary.budgetExhausted ||= error instanceof ResultsBudgetError;
300
+ payload.logger.error({
301
+ err: error
302
+ }, 'Experiment retention sweep failed');
303
+ }
304
+ }
305
+ summary.budgetExhausted ||= Date.now() >= deadline;
306
+ return summary;
307
+ }
@@ -0,0 +1,7 @@
1
+ import type { ExperimentsProxyRuntime, ExperimentsServerRuntime, ExperimentsServerRuntimeOptions } from '../types/runtime.js';
2
+ export declare function hasHostAttributesOf(runtime: object): boolean;
3
+ export declare function defineExperimentsServerRuntime<TUser extends {
4
+ id: string | number;
5
+ } = {
6
+ id: string | number;
7
+ }>(proxyRuntime: ExperimentsProxyRuntime, opts: ExperimentsServerRuntimeOptions<TUser>): ExperimentsServerRuntime<TUser>;
@@ -0,0 +1,20 @@
1
+ const hostAttributesOf = Symbol('hostAttributesOf');
2
+ export function hasHostAttributesOf(runtime) {
3
+ return Object.getOwnPropertyDescriptor(runtime, hostAttributesOf)?.value === true;
4
+ }
5
+ export function defineExperimentsServerRuntime(proxyRuntime, opts) {
6
+ const runtime = {
7
+ proxyRuntime,
8
+ getPayload: opts.getPayload,
9
+ getUser: opts.getUser,
10
+ userIdOf: opts.userIdOf ?? ((u)=>String(u.id)),
11
+ attributesOf: opts.attributesOf ?? ((u)=>({
12
+ loggedIn: Boolean(u)
13
+ }))
14
+ };
15
+ if (typeof opts.attributesOf === 'function') Object.defineProperty(runtime, hostAttributesOf, {
16
+ value: true,
17
+ enumerable: false
18
+ });
19
+ return runtime;
20
+ }
@@ -0,0 +1,3 @@
1
+ import type { Manifest } from '../types/manifest.js';
2
+ /** Build-time filter: pass a server-loaded manifest when generating the sitemap. */
3
+ export declare function experimentSitemapFilter(path: string, manifest: Manifest): boolean;
@@ -0,0 +1,6 @@
1
+ import { findNormalisedPathKey, normalisePath } from '../runtime/normalisePath.js';
2
+ /** Build-time filter: pass a server-loaded manifest when generating the sitemap. */ export function experimentSitemapFilter(path, manifest) {
3
+ const live = manifest.experiments.find((e)=>e.kind === 'page' && e.arms.some((a)=>a.pageTarget !== undefined && normalisePath(a.pageTarget) === normalisePath(path)));
4
+ if (live) return live.arms.some((a)=>a.kind === 'control' && a.pageTarget !== undefined && normalisePath(a.pageTarget) === normalisePath(path));
5
+ return findNormalisedPathKey(manifest.archivedPages, path) === undefined;
6
+ }
@@ -0,0 +1,7 @@
1
+ import type { Assignments, ClientAssignments } from '../types/assignments.js';
2
+ export declare function toClientAssignments(assignments: Assignments, opts: {
3
+ pathname: string;
4
+ apiRoute?: string;
5
+ flagPoints?: string[];
6
+ experiments?: string[];
7
+ }): ClientAssignments;
@@ -0,0 +1,56 @@
1
+ import { normalisePath } from '../runtime/normalisePath.js';
2
+ import { manifestOf, suppressExposure } from './context.js';
3
+ export function toClientAssignments(assignments, opts) {
4
+ const blocked = suppressExposure(assignments);
5
+ const manifest = manifestOf(assignments);
6
+ const experiments = Object.fromEntries((opts.experiments ?? []).filter((slug)=>Object.hasOwn(assignments.bySlug, slug)).map((slug)=>{
7
+ const a = assignments.bySlug[slug];
8
+ const experiment = manifest?.experiments.find((e)=>e.slug === slug);
9
+ const arm = experiment?.arms.find((arm)=>arm.key === a.arm && arm.kind !== 'holdout') ?? experiment?.arms.find((arm)=>arm.kind === 'control');
10
+ return [
11
+ slug,
12
+ {
13
+ arm: a.arm,
14
+ experimentId: a.experimentId,
15
+ phase: a.phase,
16
+ params: {
17
+ ...arm?.params
18
+ },
19
+ policy: a.policy,
20
+ exposable: a.exposable && !blocked
21
+ }
22
+ ];
23
+ }));
24
+ const flagPoints = Object.fromEntries((opts.flagPoints ?? []).filter((id)=>Object.hasOwn(assignments.flagPoints, id)).map((id)=>{
25
+ const point = assignments.flagPoints[id];
26
+ return [
27
+ id,
28
+ {
29
+ ...point,
30
+ params: {
31
+ ...point.params
32
+ },
33
+ exposable: point.exposable && !blocked
34
+ }
35
+ ];
36
+ }));
37
+ const result = {
38
+ v: 1,
39
+ revision: assignments.revision,
40
+ apiRoute: opts.apiRoute ?? '/api',
41
+ experiments,
42
+ flagPoints,
43
+ pageviews: []
44
+ };
45
+ if (!blocked) for (const e of manifest?.experiments ?? []){
46
+ const a = assignments.bySlug[e.slug];
47
+ if (e.kind !== 'page' || !a?.exposable) continue;
48
+ const served = e.arms.find((arm)=>arm.key === a.arm && arm.kind !== 'holdout') ?? e.arms.find((arm)=>arm.kind === 'control');
49
+ if (served?.pageTarget !== undefined && normalisePath(served.pageTarget) === normalisePath(opts.pathname)) result.pageviews.push({
50
+ slug: e.slug,
51
+ arm: a.arm,
52
+ phase: a.phase
53
+ });
54
+ }
55
+ return result;
56
+ }
@@ -0,0 +1,12 @@
1
+ import type { ExperimentsServerRuntime } from '../types/runtime.js';
2
+ export declare function trackConversion<TUser extends {
3
+ id: string | number;
4
+ } = {
5
+ id: string | number;
6
+ }>(serverRuntime: ExperimentsServerRuntime<TUser>, event: {
7
+ eventName: string;
8
+ value?: number;
9
+ idempotencyKey: string;
10
+ userId?: string;
11
+ headers?: Headers;
12
+ }): Promise<void>;
@@ -0,0 +1,69 @@
1
+ import { NextRequest } from 'next/server.js';
2
+ import { pooledExecutor } from '../db/executor.js';
3
+ import { insertEvents } from '../db/events.js';
4
+ import { readUnitCookie } from '../runtime/cookie.js';
5
+ export async function trackConversion(serverRuntime, event) {
6
+ let payload;
7
+ try {
8
+ let headers = event.headers;
9
+ if (!headers) {
10
+ try {
11
+ headers = await (await import('next/headers.js')).headers();
12
+ } catch {}
13
+ }
14
+ const runtime = serverRuntime.proxyRuntime;
15
+ // Consent sees cookies and headers only; the URL is a placeholder.
16
+ let consent = true;
17
+ try {
18
+ consent = runtime.cookie.consent?.(new NextRequest('http://consent.invalid/', {
19
+ headers
20
+ })) !== false;
21
+ } catch {
22
+ console.error('[payload-experiments] consent failed; treating consent as false');
23
+ consent = false;
24
+ }
25
+ if (!consent) return;
26
+ payload = await serverRuntime.getPayload();
27
+ if (typeof event.idempotencyKey !== 'string' || !event.idempotencyKey.trim()) {
28
+ try {
29
+ payload.logger.warn('Experiments: trackConversion requires a non-empty idempotencyKey');
30
+ } catch {}
31
+ return;
32
+ }
33
+ const visitorId = headers ? readUnitCookie(headers, runtime) : null;
34
+ let userId = event.userId;
35
+ if (!userId && serverRuntime.getUser) {
36
+ try {
37
+ const user = await serverRuntime.getUser();
38
+ if (user) userId = serverRuntime.userIdOf(user);
39
+ } catch (error) {
40
+ try {
41
+ payload.logger.error({
42
+ err: error,
43
+ msg: 'Experiments: trackConversion getUser failed'
44
+ });
45
+ } catch {}
46
+ }
47
+ }
48
+ if (!visitorId && !userId) return;
49
+ await insertEvents(pooledExecutor(payload), [
50
+ {
51
+ type: 'conversion',
52
+ eventName: event.eventName,
53
+ value: event.value ?? 1,
54
+ unitId: visitorId ?? userId,
55
+ unitType: visitorId ? 'visitor' : 'user',
56
+ userId,
57
+ dedupeKey: `conversion:s:${event.idempotencyKey}`,
58
+ ts: new Date().toISOString()
59
+ }
60
+ ], (message)=>payload.logger.error(message));
61
+ } catch (error) {
62
+ try {
63
+ payload?.logger.error({
64
+ err: error,
65
+ msg: 'Experiments: trackConversion failed'
66
+ });
67
+ } catch {}
68
+ }
69
+ }
@@ -0,0 +1,8 @@
1
+ export declare const TARGETING_OPS: {
2
+ readonly string: readonly ["eq", "neq", "in", "nin", "contains"];
3
+ readonly number: readonly ["eq", "neq", "gt", "gte", "lt", "lte"];
4
+ readonly boolean: readonly ["eq"];
5
+ };
6
+ export type TargetingOp = (typeof TARGETING_OPS)[keyof typeof TARGETING_OPS][number];
7
+ export declare function isOpValid(type: string, op: string): op is TargetingOp;
8
+ export declare function evaluateOp(type: string, op: string, actual: unknown, expected: unknown): boolean;
@@ -0,0 +1,58 @@
1
+ export const TARGETING_OPS = {
2
+ string: [
3
+ 'eq',
4
+ 'neq',
5
+ 'in',
6
+ 'nin',
7
+ 'contains'
8
+ ],
9
+ number: [
10
+ 'eq',
11
+ 'neq',
12
+ 'gt',
13
+ 'gte',
14
+ 'lt',
15
+ 'lte'
16
+ ],
17
+ boolean: [
18
+ 'eq'
19
+ ]
20
+ };
21
+ export function isOpValid(type, op) {
22
+ return Object.hasOwn(TARGETING_OPS, type) && TARGETING_OPS[type].includes(op);
23
+ }
24
+ export function evaluateOp(type, op, actual, expected) {
25
+ if (!isOpValid(type, op) || typeof actual !== type) return false;
26
+ if (type === 'string') {
27
+ const value = actual.toLowerCase();
28
+ if (op === 'in' || op === 'nin') {
29
+ if (!Array.isArray(expected) || !expected.every((v)=>typeof v === 'string')) return false;
30
+ const found = expected.some((v)=>v.toLowerCase() === value);
31
+ return op === 'in' ? found : !found;
32
+ }
33
+ if (typeof expected !== 'string') return false;
34
+ const target = expected.toLowerCase();
35
+ if (op === 'contains') return value.includes(target);
36
+ return op === 'eq' ? value === target : value !== target;
37
+ }
38
+ if (typeof expected !== type) return false;
39
+ if (type === 'boolean') return actual === expected;
40
+ if (type !== 'number' || !Number.isFinite(actual) || !Number.isFinite(expected)) return false;
41
+ const a = actual, b = expected;
42
+ switch(op){
43
+ case 'eq':
44
+ return a === b;
45
+ case 'neq':
46
+ return a !== b;
47
+ case 'gt':
48
+ return a > b;
49
+ case 'gte':
50
+ return a >= b;
51
+ case 'lt':
52
+ return a < b;
53
+ case 'lte':
54
+ return a <= b;
55
+ default:
56
+ return false;
57
+ }
58
+ }
@@ -0,0 +1,16 @@
1
+ import type { PayloadRequest } from 'payload';
2
+ import type { DocId, ResolvedOptions } from '../types/contracts.js';
3
+ import type { AddMetricBody } from '../types/endpoints.js';
4
+ export declare function addMetric<TUser extends {
5
+ id: DocId;
6
+ }>(req: PayloadRequest, { experimentId, metric, role, options }: AddMetricBody & {
7
+ experimentId: DocId;
8
+ options: ResolvedOptions<TUser>;
9
+ }): Promise<{
10
+ detail?: {
11
+ metricId: DocId;
12
+ message: string;
13
+ }[] | undefined;
14
+ doc: import("payload").JsonObject & import("payload").TypeWithID;
15
+ revision: number;
16
+ }>;