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

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 +582 -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 +99 -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 +133 -0
  453. package/dist/types/contracts.js +2 -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 +137 -3
@@ -0,0 +1,24 @@
1
+ import type { PayloadRequest } from 'payload';
2
+ import type { EndpointContext, RefusalCode } from '../types/endpoints.js';
3
+ import type { DocId } from '../types/contracts.js';
4
+ import type { Snapshot } from '../types/snapshot.js';
5
+ export declare function resultsError(status: number, code: RefusalCode, message: string): Response;
6
+ export type SnapshotDocument = {
7
+ id: DocId;
8
+ experiment: DocId | {
9
+ id: DocId;
10
+ };
11
+ phase: number;
12
+ computedAt: string;
13
+ snapshot: Snapshot;
14
+ };
15
+ export declare function readSnapshots(req: PayloadRequest, ids: DocId[], { per, decisionId, seriesPhase }?: {
16
+ per?: 'phase' | 'experiment';
17
+ decisionId?: DocId | null;
18
+ seriesPhase?: number;
19
+ }): Promise<SnapshotDocument[]>;
20
+ export declare function handleResults<TUser extends {
21
+ id: string | number;
22
+ } = {
23
+ id: string | number;
24
+ }>(req: PayloadRequest, _ctx: EndpointContext<TUser>): Promise<Response>;
@@ -0,0 +1,136 @@
1
+ import { resultsMetadata, newestSnapshotIds } from '../db/snapshots.js';
2
+ import { pooledExecutor } from '../db/executor.js';
3
+ const headers = {
4
+ 'Cache-Control': 'no-store'
5
+ };
6
+ export function resultsError(status, code, message) {
7
+ return Response.json({
8
+ errors: [
9
+ {
10
+ code,
11
+ message
12
+ }
13
+ ]
14
+ }, {
15
+ status,
16
+ headers
17
+ });
18
+ }
19
+ export async function readSnapshots(req, ids, { per = 'phase', decisionId, seriesPhase } = {}) {
20
+ const snapshotIds = seriesPhase === undefined ? await newestSnapshotIds(pooledExecutor(req.payload), ids, per) : [];
21
+ if (decisionId != null && !snapshotIds.some((id)=>String(id) === String(decisionId))) snapshotIds.push(decisionId);
22
+ if (seriesPhase === undefined && snapshotIds.length === 0) return [];
23
+ const { docs } = await req.payload.find({
24
+ collection: 'xp-results-snapshots',
25
+ req,
26
+ overrideAccess: false,
27
+ depth: 0,
28
+ pagination: false,
29
+ limit: seriesPhase === undefined ? snapshotIds.length : 0,
30
+ sort: '-computedAt',
31
+ where: seriesPhase === undefined ? {
32
+ id: {
33
+ in: snapshotIds
34
+ }
35
+ } : {
36
+ and: [
37
+ {
38
+ experiment: {
39
+ in: ids
40
+ }
41
+ },
42
+ {
43
+ phase: {
44
+ equals: seriesPhase
45
+ }
46
+ }
47
+ ]
48
+ }
49
+ });
50
+ return docs.sort((a, b)=>Date.parse(b.computedAt) - Date.parse(a.computedAt) || String(b.id).localeCompare(String(a.id), undefined, {
51
+ numeric: true
52
+ }));
53
+ }
54
+ export async function handleResults(req, _ctx) {
55
+ const id = req.routeParams?.id;
56
+ if (typeof id !== 'string' && typeof id !== 'number') return resultsError(404, 'not-found', 'Experiment not found');
57
+ const params = new URL(req.url ?? 'http://localhost').searchParams;
58
+ const selected = params.get('phase');
59
+ if (selected !== null && (!/^\d+$/.test(selected) || !Number.isSafeInteger(Number(selected)) || Number(selected) < 1)) return resultsError(400, 'invalid-body', 'Choose a valid round');
60
+ const metadata = await resultsMetadata(pooledExecutor(req.payload), id);
61
+ if (!metadata) return resultsError(404, 'not-found', 'Experiment not found');
62
+ const { docs } = await req.payload.find({
63
+ collection: 'xp-phases',
64
+ req,
65
+ overrideAccess: false,
66
+ depth: 0,
67
+ pagination: false,
68
+ limit: 0,
69
+ where: {
70
+ experiment: {
71
+ equals: id
72
+ }
73
+ },
74
+ sort: 'phase'
75
+ });
76
+ const records = docs.sort((a, b)=>a.phase - b.phase);
77
+ const phases = records.map((record)=>({
78
+ phase: record.phase,
79
+ phaseKind: record.phaseKind,
80
+ startedAt: String(record.startedAt),
81
+ endedAt: record.endedAt == null ? null : String(record.endedAt),
82
+ arms: record.arms.map(({ key, label, kind })=>({
83
+ key,
84
+ label,
85
+ kind
86
+ })),
87
+ metrics: record.metricDefinitions.map(({ metricId, name, kind, role, resolvedCap, historyUnits, capNotice })=>({
88
+ metricId,
89
+ name,
90
+ kind,
91
+ role,
92
+ ...resolvedCap === undefined ? {} : {
93
+ resolvedCap
94
+ },
95
+ ...historyUnits === undefined ? {} : {
96
+ historyUnits
97
+ },
98
+ ...capNotice ? {
99
+ capNotice
100
+ } : {}
101
+ }))
102
+ }));
103
+ const snapshots = await readSnapshots(req, [
104
+ id
105
+ ], {
106
+ decisionId: metadata.snapshotId
107
+ });
108
+ const decision = metadata.snapshotId == null ? undefined : snapshots.find((snapshot)=>String(snapshot.id) === String(metadata.snapshotId))?.snapshot;
109
+ const phase = selected === null ? decision?.phase ?? (metadata.status === 'decided' ? records.filter((record)=>record.phaseKind === 'test').at(-1)?.phase : records.at(-1)?.phase) : Number(selected);
110
+ if (selected !== null && !records.some((record)=>record.phase === phase)) return resultsError(404, 'not-found', 'Round not found');
111
+ const snapshot = snapshots.find((snapshot)=>snapshot.phase === phase)?.snapshot ?? null;
112
+ const response = {
113
+ phases,
114
+ snapshot,
115
+ ...decision ? {
116
+ decisionSnapshot: decision
117
+ } : {}
118
+ };
119
+ if (params.get('series') === '1') {
120
+ const series = phase === undefined ? [] : await readSnapshots(req, [
121
+ id
122
+ ], {
123
+ seriesPhase: phase
124
+ });
125
+ response.series = series.reverse().flatMap(({ snapshot, computedAt })=>snapshot.metrics.flatMap((metric)=>metric.comparisons.map((comparison)=>({
126
+ computedAt,
127
+ metricId: metric.metricId,
128
+ arm: comparison.arm,
129
+ lift: comparison.lift,
130
+ ci: comparison.ciAdjusted
131
+ }))));
132
+ }
133
+ return Response.json(response, {
134
+ headers
135
+ });
136
+ }
@@ -0,0 +1,7 @@
1
+ import type { PayloadRequest } from 'payload';
2
+ import type { EndpointContext } from '../types/endpoints.js';
3
+ export declare function handleSummary<TUser extends {
4
+ id: string | number;
5
+ } = {
6
+ id: string | number;
7
+ }>(req: PayloadRequest, _ctx: EndpointContext<TUser>): Promise<Response>;
@@ -0,0 +1,40 @@
1
+ import { readSnapshots, resultsError } from './results.js';
2
+ export async function handleSummary(req, _ctx) {
3
+ let ids;
4
+ try {
5
+ // Split before decoding: an opaque id can itself contain a comma.
6
+ const raw = new URL(req.url ?? 'http://localhost').search.slice(1).split('&').find((part)=>part.split('=')[0] === 'ids')?.slice(4);
7
+ if (raw === undefined) return resultsError(400, 'invalid-body', 'Provide experiment ids');
8
+ ids = raw.split(',').map((id)=>decodeURIComponent(id.replaceAll('+', ' ')));
9
+ } catch {
10
+ return resultsError(400, 'invalid-body', 'Could not parse experiment ids');
11
+ }
12
+ if (ids.length > 100) return resultsError(422, 'too-many-ids', 'Request at most 100 experiments');
13
+ if (ids.some((id)=>!id.trim())) return resultsError(422, 'invalid-ids', 'Experiment ids must be nonempty');
14
+ const snapshots = await readSnapshots(req, [
15
+ ...new Set(ids)
16
+ ], {
17
+ per: 'experiment'
18
+ });
19
+ const response = Object.create(null);
20
+ for (const id of ids){
21
+ const snapshot = snapshots.find((row)=>String(typeof row.experiment === 'object' ? row.experiment.id : row.experiment) === id)?.snapshot;
22
+ response[id] = snapshot ? {
23
+ exposures: snapshot.exposures.total,
24
+ days: Math.max(0, (Date.parse(snapshot.window.to) - Date.parse(snapshot.window.from)) / 86_400_000),
25
+ verdict: {
26
+ code: snapshot.verdict.code,
27
+ headline: snapshot.verdict.headline
28
+ }
29
+ } : {
30
+ exposures: 0,
31
+ days: 0,
32
+ verdict: null
33
+ };
34
+ }
35
+ return Response.json(response, {
36
+ headers: {
37
+ 'Cache-Control': 'no-store'
38
+ }
39
+ });
40
+ }
@@ -0,0 +1,42 @@
1
+ import type { PayloadRequest } from 'payload';
2
+ import type { EndpointContext } from '../types/endpoints.js';
3
+ export declare function handleStart<TUser extends {
4
+ id: string | number;
5
+ } = {
6
+ id: string | number;
7
+ }>(req: PayloadRequest, ctx: EndpointContext<TUser>): Promise<Response>;
8
+ export declare function handleAllocate<TUser extends {
9
+ id: string | number;
10
+ } = {
11
+ id: string | number;
12
+ }>(req: PayloadRequest, _ctx: EndpointContext<TUser>): Promise<Response>;
13
+ export declare function handleAddMetric<TUser extends {
14
+ id: string | number;
15
+ } = {
16
+ id: string | number;
17
+ }>(req: PayloadRequest, ctx: EndpointContext<TUser>): Promise<Response>;
18
+ export declare function handleStop<TUser extends {
19
+ id: string | number;
20
+ } = {
21
+ id: string | number;
22
+ }>(req: PayloadRequest, _ctx: EndpointContext<TUser>): Promise<Response>;
23
+ export declare function handleDecide<TUser extends {
24
+ id: string | number;
25
+ } = {
26
+ id: string | number;
27
+ }>(req: PayloadRequest, _ctx: EndpointContext<TUser>): Promise<Response>;
28
+ export declare function handleReleaseHoldout<TUser extends {
29
+ id: string | number;
30
+ } = {
31
+ id: string | number;
32
+ }>(req: PayloadRequest, _ctx: EndpointContext<TUser>): Promise<Response>;
33
+ export declare function handleMakeContent<TUser extends {
34
+ id: string | number;
35
+ } = {
36
+ id: string | number;
37
+ }>(req: PayloadRequest, ctx: EndpointContext<TUser>): Promise<Response>;
38
+ export declare function handleArchive<TUser extends {
39
+ id: string | number;
40
+ } = {
41
+ id: string | number;
42
+ }>(req: PayloadRequest, _ctx: EndpointContext<TUser>): Promise<Response>;
@@ -0,0 +1,154 @@
1
+ import { XpRefusal } from '../errors.js';
2
+ import { start } from '../transitions/start.js';
3
+ import { allocate } from '../transitions/allocate.js';
4
+ import { addMetric } from '../transitions/addMetric.js';
5
+ import { stop } from '../transitions/stop.js';
6
+ import { decide } from '../transitions/decide.js';
7
+ import { releaseHoldout } from '../transitions/releaseHoldout.js';
8
+ import { makeContent } from '../transitions/makeContent.js';
9
+ import { archive } from '../transitions/archive.js';
10
+ const invalidBody = ()=>Response.json({
11
+ errors: [
12
+ {
13
+ code: 'invalid-body',
14
+ message: 'Enter a valid request body.'
15
+ }
16
+ ]
17
+ }, {
18
+ status: 400
19
+ });
20
+ async function body(req) {
21
+ try {
22
+ if (!req.body && !req.data) return {};
23
+ // An empty body (Content-Length: 0) means no options, not a malformed request.
24
+ const text = req.data === undefined ? await req.text() : '';
25
+ const value = req.data ?? (text.trim() ? JSON.parse(text) : {});
26
+ return value && typeof value === 'object' && !Array.isArray(value) ? value : null;
27
+ } catch {
28
+ return null;
29
+ }
30
+ }
31
+ const only = (value, keys)=>Object.keys(value).every((key)=>keys.includes(key));
32
+ async function respond(req, action) {
33
+ const id = req.routeParams?.id;
34
+ if (typeof id !== 'string' && typeof id !== 'number') return Response.json({
35
+ errors: [
36
+ {
37
+ code: 'not-found',
38
+ message: 'Experiment not found'
39
+ }
40
+ ]
41
+ }, {
42
+ status: 404
43
+ });
44
+ try {
45
+ return Response.json(await action(id), {
46
+ headers: {
47
+ 'Cache-Control': 'no-store'
48
+ }
49
+ });
50
+ } catch (cause) {
51
+ if (cause instanceof XpRefusal) return Response.json({
52
+ errors: [
53
+ {
54
+ code: cause.code,
55
+ message: cause.message,
56
+ ...cause.detail === undefined ? {} : {
57
+ detail: cause.detail
58
+ }
59
+ }
60
+ ]
61
+ }, {
62
+ status: cause.status === 409 ? 422 : cause.status
63
+ });
64
+ throw cause;
65
+ }
66
+ }
67
+ export async function handleStart(req, ctx) {
68
+ const value = await body(req);
69
+ if (!value || !only(value, [])) return invalidBody();
70
+ return respond(req, (id)=>start(req, {
71
+ experimentId: id,
72
+ options: ctx.options
73
+ }));
74
+ }
75
+ export async function handleAllocate(req, _ctx) {
76
+ const value = await body(req);
77
+ if (!value || !only(value, [
78
+ 'allocation'
79
+ ]) || typeof value.allocation !== 'number' || !Number.isInteger(value.allocation) || value.allocation < 1 || value.allocation > 100) return invalidBody();
80
+ const allocation = value.allocation;
81
+ return respond(req, (id)=>allocate(req, {
82
+ experimentId: id,
83
+ allocation
84
+ }));
85
+ }
86
+ export async function handleAddMetric(req, ctx) {
87
+ const value = await body(req);
88
+ if (!value || !only(value, [
89
+ 'metric',
90
+ 'role'
91
+ ]) || !(typeof value.metric === 'string' && value.metric.trim() || typeof value.metric === 'number' && Number.isSafeInteger(value.metric)) || value.role !== 'secondary' && value.role !== 'guardrail') return invalidBody();
92
+ const metric = value.metric, role = value.role;
93
+ return respond(req, (id)=>addMetric(req, {
94
+ experimentId: id,
95
+ metric,
96
+ role,
97
+ options: ctx.options
98
+ }));
99
+ }
100
+ export async function handleStop(req, _ctx) {
101
+ const value = await body(req);
102
+ if (!value || !only(value, [])) return invalidBody();
103
+ return respond(req, (id)=>stop(req, {
104
+ experimentId: id
105
+ }));
106
+ }
107
+ export async function handleDecide(req, _ctx) {
108
+ const value = await body(req);
109
+ if (!value || !only(value, [
110
+ 'winnerArm',
111
+ 'note',
112
+ 'confirmation'
113
+ ]) || typeof value.winnerArm !== 'string' || value.note !== undefined && typeof value.note !== 'string' || value.confirmation !== undefined && typeof value.confirmation !== 'string') return invalidBody();
114
+ const { winnerArm, note, confirmation } = value;
115
+ return respond(req, (id)=>decide(req, {
116
+ experimentId: id,
117
+ winnerArm,
118
+ note,
119
+ confirmation
120
+ }));
121
+ }
122
+ export async function handleReleaseHoldout(req, _ctx) {
123
+ const value = await body(req);
124
+ if (!value || !only(value, [])) return invalidBody();
125
+ return respond(req, (id)=>releaseHoldout(req, {
126
+ experimentId: id
127
+ }));
128
+ }
129
+ export async function handleMakeContent(req, ctx) {
130
+ const value = await body(req);
131
+ if (!value || !only(value, [])) return invalidBody();
132
+ return respond(req, (id)=>makeContent(req, {
133
+ experimentId: id,
134
+ options: ctx.options
135
+ }));
136
+ }
137
+ export async function handleArchive(req, _ctx) {
138
+ const value = await body(req);
139
+ if (!value || !only(value, [
140
+ 'mode',
141
+ 'confirmation'
142
+ ]) || ![
143
+ 'stopped',
144
+ 'after-content',
145
+ 'discard',
146
+ 'hard-coded'
147
+ ].includes(value.mode) || value.confirmation !== undefined && typeof value.confirmation !== 'string') return invalidBody();
148
+ const { mode, confirmation } = value;
149
+ return respond(req, (id)=>archive(req, {
150
+ experimentId: id,
151
+ mode,
152
+ confirmation
153
+ }));
154
+ }
@@ -0,0 +1,27 @@
1
+ import type { RefusalCode } from './types/endpoints.js';
2
+ import type { Status } from './types/contracts.js';
3
+ export declare class XpNotImplemented extends Error {
4
+ readonly lane: string;
5
+ name: string;
6
+ constructor(lane: string);
7
+ }
8
+ export declare class XpLockedFieldError extends Error {
9
+ readonly field: string;
10
+ readonly experimentStatus: Status;
11
+ name: string;
12
+ readonly status = 400;
13
+ readonly isPublic = true;
14
+ constructor(field: string, experimentStatus: Status);
15
+ }
16
+ export declare class XpNoTransactionError extends Error {
17
+ name: string;
18
+ constructor();
19
+ }
20
+ export declare class XpRefusal extends Error {
21
+ readonly code: RefusalCode;
22
+ readonly detail: unknown | undefined;
23
+ readonly status: 409 | 422 | 500 | 404;
24
+ name: string;
25
+ readonly isPublic = true;
26
+ constructor(code: RefusalCode, message: string, detail: unknown | undefined, status: 409 | 422 | 500 | 404);
27
+ }
package/dist/errors.js ADDED
@@ -0,0 +1,33 @@
1
+ export class XpNotImplemented extends Error {
2
+ lane;
3
+ name = 'XpNotImplemented';
4
+ constructor(lane){
5
+ super(lane), this.lane = lane;
6
+ }
7
+ }
8
+ export class XpLockedFieldError extends Error {
9
+ field;
10
+ experimentStatus;
11
+ name = 'XpLockedFieldError';
12
+ status = 400;
13
+ isPublic = true;
14
+ constructor(field, experimentStatus){
15
+ super(`${field} is locked in ${experimentStatus}`), this.field = field, this.experimentStatus = experimentStatus;
16
+ }
17
+ }
18
+ export class XpNoTransactionError extends Error {
19
+ name = 'XpNoTransactionError';
20
+ constructor(){
21
+ super('An active transaction is required');
22
+ }
23
+ }
24
+ export class XpRefusal extends Error {
25
+ code;
26
+ detail;
27
+ status;
28
+ name = 'XpRefusal';
29
+ isPublic = true;
30
+ constructor(code, message, detail, status){
31
+ super(message), this.code = code, this.detail = detail, this.status = status;
32
+ }
33
+ }
@@ -0,0 +1,7 @@
1
+ export declare class EventsBodyError extends Error {
2
+ readonly status: 413 | 422;
3
+ readonly code: 'body-too-large' | 'invalid-body';
4
+ constructor(status: 413 | 422, code: 'body-too-large' | 'invalid-body', message: string);
5
+ }
6
+ /** Bound retained bytes while reading the original Fetch stream, before parsing. */
7
+ export declare function readEvents(body: ReadableStream<Uint8Array> | null | undefined, maxBytes: number): Promise<unknown[]>;
@@ -0,0 +1,43 @@
1
+ import { MAX_EVENTS_PER_BODY } from '../constants.js';
2
+ export class EventsBodyError extends Error {
3
+ status;
4
+ code;
5
+ constructor(status, code, message){
6
+ super(message), this.status = status, this.code = code;
7
+ }
8
+ }
9
+ /** Bound retained bytes while reading the original Fetch stream, before parsing. */ export async function readEvents(body, maxBytes) {
10
+ if (!body) throw new EventsBodyError(422, 'invalid-body', 'Expected an events array');
11
+ const reader = body.getReader();
12
+ const chunks = [];
13
+ let size = 0;
14
+ try {
15
+ while(true){
16
+ const { done, value } = await reader.read();
17
+ if (done) break;
18
+ size += value.byteLength;
19
+ if (size > maxBytes) {
20
+ // Cancellation must not wait for an uncooperative sender to finish.
21
+ void reader.cancel().catch(()=>{});
22
+ throw new EventsBodyError(413, 'body-too-large', 'Events body is too large');
23
+ }
24
+ chunks.push(value);
25
+ }
26
+ const bytes = new Uint8Array(size);
27
+ let offset = 0;
28
+ for (const chunk of chunks){
29
+ bytes.set(chunk, offset);
30
+ offset += chunk.byteLength;
31
+ }
32
+ const parsed = JSON.parse(new TextDecoder().decode(bytes));
33
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed) || !('events' in parsed) || !Array.isArray(parsed.events) || parsed.events.length > MAX_EVENTS_PER_BODY) {
34
+ throw new Error('Expected at most 20 events');
35
+ }
36
+ return parsed.events;
37
+ } catch (error) {
38
+ if (error instanceof EventsBodyError) throw error;
39
+ throw new EventsBodyError(422, 'invalid-body', 'Invalid events body');
40
+ } finally{
41
+ reader.releaseLock();
42
+ }
43
+ }
@@ -0,0 +1,4 @@
1
+ /** Startup validation; hosts may supply options from JavaScript or config files. */
2
+ export declare function validateDimensions(names: unknown): void;
3
+ /** Pick only server-computed request attributes; never pass browser event data. */
4
+ export declare function exposureDimensions(attributes: Readonly<Record<string, unknown>>, names?: readonly string[]): Record<string, string | number | boolean> | null;
@@ -0,0 +1,51 @@
1
+ const identifyingKeys = new Set([
2
+ 'userid',
3
+ 'visitorid',
4
+ 'unitid',
5
+ 'id',
6
+ 'email',
7
+ 'emailaddress',
8
+ 'sessionid',
9
+ 'session',
10
+ 'ip',
11
+ 'ipaddress',
12
+ 'phone',
13
+ 'name'
14
+ ]);
15
+ /** Startup validation; hosts may supply options from JavaScript or config files. */ export function validateDimensions(names) {
16
+ if (names === undefined) return;
17
+ if (!Array.isArray(names) || names.length > 8) {
18
+ throw new Error('Experiments events.dimensions must be an array of at most 8 unique attribute names');
19
+ }
20
+ const seen = new Set();
21
+ for (const name of names){
22
+ if (typeof name === 'string' && identifyingKeys.has(name.toLowerCase().replace(/[_-]/g, ''))) {
23
+ throw new Error(`Experiments events.dimensions forbids identifying key: ${name}`);
24
+ }
25
+ if (typeof name !== 'string' || !/^[a-zA-Z][a-zA-Z0-9_]{0,39}$/.test(name)) {
26
+ throw new Error('Experiments events.dimensions names must match ^[a-zA-Z][a-zA-Z0-9_]{0,39}$');
27
+ }
28
+ if (seen.has(name)) throw new Error(`Experiments events.dimensions names must be unique: ${name}`);
29
+ seen.add(name);
30
+ }
31
+ }
32
+ /** Pick only server-computed request attributes; never pass browser event data. */ export function exposureDimensions(attributes, names = []) {
33
+ const entries = [];
34
+ for (const name of names){
35
+ if (!Object.hasOwn(attributes, name)) continue;
36
+ const value = attributes[name];
37
+ if (typeof value === 'string') {
38
+ const truncated = Array.from(value).slice(0, 64).join('');
39
+ // JSONB rejects NUL and unpaired UTF-16 surrogates. Optional telemetry
40
+ // must never make an otherwise valid exposure fail to persist.
41
+ if (!/\u0000|[\uD800-\uDFFF]/u.test(truncated)) entries.push([
42
+ name,
43
+ truncated
44
+ ]);
45
+ } else if (typeof value === 'boolean' || typeof value === 'number' && Number.isFinite(value)) entries.push([
46
+ name,
47
+ value
48
+ ]);
49
+ }
50
+ return entries.length ? Object.fromEntries(entries) : null;
51
+ }
@@ -0,0 +1,2 @@
1
+ /** These signals only suppress telemetry; they never authorize a preview or an assignment. */
2
+ export declare function isPreview(request: Request): boolean;
@@ -0,0 +1,9 @@
1
+ import { XP_PREVIEW_PARAM } from '../constants.js';
2
+ /** These signals only suppress telemetry; they never authorize a preview or an assignment. */ export function isPreview(request) {
3
+ if (new URL(request.url).searchParams.has(XP_PREVIEW_PARAM)) return true;
4
+ const referrer = request.headers.get('referer');
5
+ try {
6
+ if (referrer && new URL(referrer).searchParams.has(XP_PREVIEW_PARAM)) return true;
7
+ } catch {}
8
+ return (request.headers.get('cookie') ?? '').split(';').some((part)=>part.trim().startsWith('__prerender_bypass='));
9
+ }
@@ -0,0 +1,3 @@
1
+ import { NextRequest } from 'next/server.js';
2
+ /** Browser beacons carry their page URL in Referer. It supplies targeting context only. */
3
+ export declare function sourceRequest(request: NextRequest): NextRequest | null;
@@ -0,0 +1,14 @@
1
+ import { NextRequest } from 'next/server.js';
2
+ /** Browser beacons carry their page URL in Referer. It supplies targeting context only. */ export function sourceRequest(request) {
3
+ const referrer = request.headers.get('referer');
4
+ if (!referrer) return null;
5
+ try {
6
+ const url = new URL(referrer);
7
+ if (url.origin !== request.nextUrl.origin) return null;
8
+ return new NextRequest(url, {
9
+ headers: request.headers
10
+ });
11
+ } catch {
12
+ return null;
13
+ }
14
+ }
@@ -0,0 +1,7 @@
1
+ import type { EventRow } from '../db/events.js';
2
+ import type { AssignmentResult } from '../runtime/assign.js';
3
+ import type { ResolvedOptions } from '../types/contracts.js';
4
+ import type { Manifest } from '../types/manifest.js';
5
+ export declare function eventRows<TUser extends {
6
+ id: string | number;
7
+ }>(events: unknown[], manifest: Manifest, assignments: AssignmentResult, options: ResolvedOptions<TUser>, visitorId: string, userId: string | undefined, ts: string, requestAttributes?: Readonly<Record<string, unknown>>): EventRow[];