@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,31 @@
1
+ import type { MetricSource, Status } from '../../types/contracts.js';
2
+ import type { PreflightResult } from '../../types/endpoints.js';
3
+ export declare function reviewView(preflight: PreflightResult, { status, primaryMetricKind }: {
4
+ status: Status;
5
+ primaryMetricKind?: MetricSource['kind'];
6
+ }): {
7
+ checks: {
8
+ ok: boolean;
9
+ done: string | undefined;
10
+ hint: string | undefined;
11
+ detail: string | undefined;
12
+ }[];
13
+ placements: {
14
+ previewAvailable: boolean;
15
+ collection: string;
16
+ id: import("../../types/contracts.js").DocId;
17
+ title: string;
18
+ url?: string;
19
+ ok: boolean;
20
+ detail?: string;
21
+ }[];
22
+ baseline: string;
23
+ traffic: string;
24
+ estimate: string;
25
+ estimateWarning: boolean;
26
+ canStart: boolean;
27
+ applyValues: {
28
+ plannedDurationDays: number;
29
+ sequentialTuningParameter: number;
30
+ } | null;
31
+ };
@@ -0,0 +1,40 @@
1
+ import { REVIEW_COPY as C, REVIEW_DONE, REVIEW_HINTS } from '../copy/review.js';
2
+ const number = (value)=>new Intl.NumberFormat('en-US', {
3
+ maximumFractionDigits: 1
4
+ }).format(value);
5
+ export function reviewView(preflight, { status, primaryMetricKind }) {
6
+ const { baseline, estimate } = preflight;
7
+ const weeks = estimate ? Math.round(estimate.weeks * 10) / 10 : 0;
8
+ const formatted = baseline ? new Intl.NumberFormat('en-US', primaryMetricKind === 'binomial' ? {
9
+ style: 'percent',
10
+ maximumFractionDigits: 1
11
+ } : {
12
+ minimumFractionDigits: primaryMetricKind === 'revenue' ? 2 : 0,
13
+ maximumFractionDigits: primaryMetricKind === 'revenue' ? 2 : 1
14
+ }).format(baseline.value) : null;
15
+ return {
16
+ checks: preflight.checks.map((check)=>{
17
+ const detail = typeof check.detail === 'string' ? check.detail : check.detail && typeof check.detail === 'object' && 'message' in check.detail && typeof check.detail.message === 'string' ? check.detail.message : undefined;
18
+ const hint = check.ok ? undefined : REVIEW_HINTS[check.code] ?? detail ?? C.checkFallback;
19
+ return {
20
+ ok: check.ok,
21
+ done: check.ok ? REVIEW_DONE[check.code] ?? C.checkDoneFallback : undefined,
22
+ hint,
23
+ detail: detail === hint ? undefined : detail
24
+ };
25
+ }),
26
+ placements: preflight.placements.map((placement)=>({
27
+ ...placement,
28
+ previewAvailable: Boolean(placement.url)
29
+ })),
30
+ baseline: formatted === null ? C.noBaseline : `Over the last 28 days: ${formatted}`,
31
+ traffic: preflight.trafficPerDay === null ? C.unknownTraffic : `About ${number(preflight.trafficPerDay)} people a day`,
32
+ estimate: !estimate ? C.noEstimate : !estimate.feasible ? C.infeasible : `≈ ${number(weeks)} weeks`,
33
+ estimateWarning: Boolean(estimate && (weeks > 8 || !estimate.feasible)),
34
+ canStart: preflight.checks.every((check)=>check.ok) && (status === 'draft' || status === 'stopped'),
35
+ applyValues: estimate ? {
36
+ plannedDurationDays: estimate.plannedDurationDays,
37
+ sequentialTuningParameter: estimate.sequentialTuningParameter
38
+ } : null
39
+ };
40
+ }
@@ -0,0 +1,16 @@
1
+ import type { Status } from '../types/contracts.js';
2
+ export type PillTone = 'neutral' | 'success' | 'warning' | 'info' | 'muted';
3
+ export declare function statusPill({ status, arms, decision }: {
4
+ status: Status;
5
+ arms?: readonly {
6
+ key: string;
7
+ }[] | null;
8
+ decision?: {
9
+ winnerArm?: string | null;
10
+ holdoutReleasedAt?: string | null;
11
+ } | null;
12
+ }): {
13
+ label: string;
14
+ tone: PillTone;
15
+ tooltip: string;
16
+ };
@@ -0,0 +1,17 @@
1
+ import { statusLabel } from './labels.js';
2
+ import { STATUS_TOOLTIPS } from './copy/status.js';
3
+ const TONES = {
4
+ draft: 'neutral',
5
+ running: 'success',
6
+ stopped: 'warning',
7
+ decided: 'info',
8
+ archived: 'muted'
9
+ };
10
+ export function statusPill({ status, arms = [], decision }) {
11
+ const holdout = status === 'decided' && arms?.some((group)=>group.key === 'holdout') && Boolean(decision?.winnerArm) && decision?.winnerArm !== 'control' && !decision?.holdoutReleasedAt;
12
+ return {
13
+ label: statusLabel(status),
14
+ tone: TONES[status],
15
+ tooltip: holdout ? STATUS_TOOLTIPS.decidedWithHoldout : STATUS_TOOLTIPS[status]
16
+ };
17
+ }
@@ -0,0 +1,10 @@
1
+ /* Admin styles for the experiments plugin; loaded by src/admin/styles.ts. */
2
+ .xp-status-pill { font-weight: 600; }
3
+ .xp-status-pill--neutral { background: var(--theme-elevation-150); color: var(--theme-elevation-800); }
4
+ .xp-status-pill--success { background: var(--theme-success-150); color: var(--theme-success-850); }
5
+ .xp-status-pill--warning { background: var(--theme-warning-150); color: var(--theme-warning-850); }
6
+ .xp-status-pill--info { background: var(--theme-elevation-200); color: var(--theme-elevation-900); }
7
+ .xp-status-pill--muted { background: var(--theme-elevation-100); color: var(--theme-elevation-600); }
8
+ .xp-locked-notice, .xp-notice { padding: 0.75rem; border-inline-start: 3px solid var(--theme-elevation-400); background: var(--theme-elevation-50); color: var(--theme-elevation-800); }
9
+ .xp-notice--warning { border-color: var(--theme-warning-500); background: var(--theme-warning-100); }
10
+ .xp-notice--error { border-color: var(--theme-error-500); background: var(--theme-error-100); }
@@ -0,0 +1 @@
1
+ import './styles.css';
@@ -0,0 +1,2 @@
1
+ // Load admin styles from mounted components so barrels stay free of side effects.
2
+ import './styles.css';
@@ -0,0 +1,8 @@
1
+ import type { DocId } from '../types/contracts.js';
2
+ import type { SummaryResponse } from '../types/endpoints.js';
3
+ import type { createApi } from './api.js';
4
+ export type SummaryEntry = SummaryResponse[DocId];
5
+ type Api = Pick<ReturnType<typeof createApi>, 'summary'>;
6
+ /** All list cells mounted in this tick share a request, even with separate useApi instances. */
7
+ export declare function requestSummary(api: Api, id: DocId): Promise<SummaryEntry | null>;
8
+ export {};
@@ -0,0 +1,33 @@
1
+ let pending = [];
2
+ /** All list cells mounted in this tick share a request, even with separate useApi instances. */ export function requestSummary(api, id) {
3
+ return new Promise((resolve)=>{
4
+ pending.push({
5
+ id,
6
+ resolve
7
+ });
8
+ if (pending.length !== 1) return;
9
+ queueMicrotask(()=>{
10
+ const batch = pending;
11
+ pending = [];
12
+ const ids = [
13
+ ...new Map(batch.map((item)=>[
14
+ String(item.id),
15
+ item.id
16
+ ])).values()
17
+ ];
18
+ for(let offset = 0; offset < ids.length; offset += 100){
19
+ const chunk = ids.slice(offset, offset + 100);
20
+ const keys = new Set(chunk.map(String));
21
+ const callers = batch.filter((item)=>keys.has(String(item.id)));
22
+ void (async ()=>{
23
+ try {
24
+ const result = await api.summary(chunk);
25
+ for (const caller of callers)caller.resolve(result.ok ? result.data?.[caller.id] ?? null : null);
26
+ } catch {
27
+ for (const caller of callers)caller.resolve(null);
28
+ }
29
+ })();
30
+ }
31
+ });
32
+ });
33
+ }
@@ -0,0 +1,2 @@
1
+ import type { TextFieldClientProps } from 'payload';
2
+ export declare function TargetingAttributeField({ path, field, readOnly }: TextFieldClientProps): import("react").JSX.Element;
@@ -0,0 +1,31 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { SelectInput, useField, useFormFields } from '@payloadcms/ui';
4
+ import { isEditable } from '../../collections/experiments/editability.js';
5
+ import { WHO_COPY } from '../copy/who.js';
6
+ import { humaniseAttribute } from './targeting.model.js';
7
+ export function TargetingAttributeField({ path, field, readOnly }) {
8
+ const { value, setValue } = useField({
9
+ path
10
+ });
11
+ const status = useFormFields(([fields])=>fields.status?.value ?? 'draft');
12
+ const keys = field.admin?.custom?.attributeKeys ?? {};
13
+ const locked = Boolean(readOnly || field.admin?.readOnly || !isEditable(status, 'targeting'));
14
+ return /*#__PURE__*/ _jsx("div", {
15
+ children: /*#__PURE__*/ _jsx(SelectInput, {
16
+ path: path,
17
+ name: path,
18
+ label: WHO_COPY.attribute,
19
+ required: field.required,
20
+ options: Object.keys(keys).map((key)=>({
21
+ label: humaniseAttribute(key),
22
+ value: key
23
+ })),
24
+ value: value ?? '',
25
+ readOnly: locked,
26
+ onChange: (option)=>{
27
+ if (!locked) setValue(option && !Array.isArray(option) ? option.value : null);
28
+ }
29
+ })
30
+ });
31
+ }
@@ -0,0 +1,2 @@
1
+ import type { TextFieldClientProps } from 'payload';
2
+ export declare function TargetingOpField({ path, field, readOnly }: TextFieldClientProps): import("react").JSX.Element;
@@ -0,0 +1,45 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { SelectInput, useField, useFormFields } from '@payloadcms/ui';
4
+ import { useEffect, useRef } from 'react';
5
+ import { isEditable } from '../../collections/experiments/editability.js';
6
+ import { isOpValid } from '../../targeting/ops.js';
7
+ import { WHO_COPY } from '../copy/who.js';
8
+ import { opLabel, opsFor, rowPath } from './targeting.model.js';
9
+ export function TargetingOpField({ path, field, readOnly }) {
10
+ const { value, setValue } = useField({
11
+ path
12
+ });
13
+ const row = rowPath(path);
14
+ const attribute = useFormFields(([fields])=>fields[`${row}.attribute`]?.value);
15
+ const status = useFormFields(([fields])=>fields.status?.value ?? 'draft');
16
+ const keys = field.admin?.custom?.attributeKeys ?? {};
17
+ const type = keys[attribute ?? '']?.type;
18
+ const previousType = useRef(type);
19
+ const locked = Boolean(readOnly || field.admin?.readOnly || !isEditable(status, 'targeting'));
20
+ useEffect(()=>{
21
+ const changed = previousType.current !== type;
22
+ previousType.current = type;
23
+ if (!locked && type && (changed || !isOpValid(type, value ?? ''))) setValue(opsFor(type)[0]);
24
+ }, [
25
+ type,
26
+ value,
27
+ locked,
28
+ setValue
29
+ ]);
30
+ return /*#__PURE__*/ _jsx(SelectInput, {
31
+ path: path,
32
+ name: path,
33
+ label: WHO_COPY.operator,
34
+ required: field.required,
35
+ options: opsFor(type).map((op)=>({
36
+ label: opLabel(type, op),
37
+ value: op
38
+ })),
39
+ value: value ?? '',
40
+ readOnly: locked || !type,
41
+ onChange: (option)=>{
42
+ if (!locked) setValue(option && !Array.isArray(option) ? option.value : null);
43
+ }
44
+ });
45
+ }
@@ -0,0 +1,2 @@
1
+ import type { JSONFieldClientProps } from 'payload';
2
+ export declare function TargetingValueField({ path, field, readOnly }: JSONFieldClientProps): import("react").JSX.Element;
@@ -0,0 +1,142 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { FieldError, SelectInput, TextInput, useField, useFormFields } from '@payloadcms/ui';
4
+ import { useEffect, useRef, useState } from 'react';
5
+ import { isEditable } from '../../collections/experiments/editability.js';
6
+ import { isOpValid } from '../../targeting/ops.js';
7
+ import { WHO_COPY } from '../copy/who.js';
8
+ import { coerceValue, emptyListHint, rowPath, valueInput } from './targeting.model.js';
9
+ // Preserve an unfinished comma list while the form receives its typed JSON value.
10
+ function CommaList({ path, value, setValue, readOnly, required }) {
11
+ const formatted = Array.isArray(value) ? value.join(', ') : String(value ?? '');
12
+ const [text, setText] = useState(formatted);
13
+ const lastWritten = useRef(undefined);
14
+ useEffect(()=>{
15
+ if (JSON.stringify(value) !== lastWritten.current) setText(formatted);
16
+ }, [
17
+ value,
18
+ formatted
19
+ ]);
20
+ return /*#__PURE__*/ _jsx(TextInput, {
21
+ path: path,
22
+ label: WHO_COPY.value,
23
+ value: text,
24
+ readOnly: readOnly,
25
+ required: required,
26
+ onChange: (event)=>{
27
+ if (readOnly) return;
28
+ setText(event.target.value);
29
+ const next = coerceValue('string', 'in', event.target.value);
30
+ lastWritten.current = JSON.stringify(next);
31
+ setValue(next);
32
+ }
33
+ });
34
+ }
35
+ export function TargetingValueField({ path, field, readOnly }) {
36
+ const { value, setValue } = useField({
37
+ path
38
+ });
39
+ const row = rowPath(path);
40
+ const attribute = useFormFields(([fields])=>fields[`${row}.attribute`]?.value);
41
+ const op = useFormFields(([fields])=>fields[`${row}.op`]?.value);
42
+ const status = useFormFields(([fields])=>fields.status?.value ?? 'draft');
43
+ const keys = field.admin?.custom?.attributeKeys ?? {};
44
+ const definition = keys[attribute ?? ''];
45
+ const candidate = op ?? '';
46
+ const valid = Boolean(definition && isOpValid(definition.type, candidate));
47
+ const operator = definition && isOpValid(definition.type, candidate) ? candidate : 'eq';
48
+ const input = valueInput(definition, operator);
49
+ const locked = Boolean(readOnly || field.admin?.readOnly || !isEditable(status, 'targeting') || !valid);
50
+ const type = definition?.type;
51
+ useEffect(()=>{
52
+ if (locked || !type || !isOpValid(type, candidate) || value == null) return;
53
+ const next = coerceValue(type, candidate, value);
54
+ if (JSON.stringify(next) !== JSON.stringify(value)) setValue(next);
55
+ }, [
56
+ type,
57
+ candidate,
58
+ value,
59
+ locked,
60
+ setValue
61
+ ]);
62
+ const write = (raw)=>{
63
+ if (!locked && definition && isOpValid(definition.type, operator)) setValue(coerceValue(definition.type, operator, raw));
64
+ };
65
+ const many = operator === 'in' || operator === 'nin';
66
+ const hint = emptyListHint(operator, value);
67
+ const props = {
68
+ path,
69
+ label: WHO_COPY.value,
70
+ readOnly: locked,
71
+ required: field.required
72
+ };
73
+ // position: relative anchors Payload's absolutely positioned FieldError tooltip to this field.
74
+ return /*#__PURE__*/ _jsxs("div", {
75
+ style: {
76
+ position: 'relative'
77
+ },
78
+ children: [
79
+ input.kind === 'select' || input.kind === 'multiselect' || input.kind === 'boolean' ? /*#__PURE__*/ _jsx(SelectInput, {
80
+ ...props,
81
+ name: path,
82
+ hasMany: input.kind === 'multiselect',
83
+ options: input.kind === 'boolean' ? [
84
+ {
85
+ label: WHO_COPY.true,
86
+ value: 'true'
87
+ },
88
+ {
89
+ label: WHO_COPY.false,
90
+ value: 'false'
91
+ }
92
+ ] : input.options,
93
+ value: many ? Array.isArray(value) ? value.map(String) : [] : value == null ? '' : String(value),
94
+ onChange: (option)=>write(Array.isArray(option) ? option.map((item)=>item.value) : option?.value)
95
+ }) : input.kind === 'number' ? /*#__PURE__*/ _jsxs(_Fragment, {
96
+ children: [
97
+ /*#__PURE__*/ _jsx("label", {
98
+ htmlFor: path,
99
+ children: WHO_COPY.value
100
+ }),
101
+ /*#__PURE__*/ _jsx("input", {
102
+ id: path,
103
+ name: path,
104
+ type: "number",
105
+ step: "any",
106
+ required: field.required,
107
+ readOnly: locked,
108
+ value: typeof value === 'number' || typeof value === 'string' ? value : '',
109
+ style: {
110
+ display: 'block',
111
+ color: 'var(--theme-text)',
112
+ background: 'var(--theme-input-bg)',
113
+ border: '1px solid var(--theme-elevation-200)',
114
+ padding: '0.5rem'
115
+ },
116
+ onChange: (event)=>write(event.target.value)
117
+ }),
118
+ /*#__PURE__*/ _jsx(FieldError, {
119
+ path: path
120
+ })
121
+ ]
122
+ }) : many ? /*#__PURE__*/ _jsx(CommaList, {
123
+ ...props,
124
+ value: value,
125
+ setValue: write
126
+ }, `${path}:${attribute}:${operator}`) : /*#__PURE__*/ _jsx(TextInput, {
127
+ ...props,
128
+ value: typeof value === 'string' ? value : '',
129
+ onChange: (event)=>write(event.target.value)
130
+ }),
131
+ definition?.type === 'string' ? /*#__PURE__*/ _jsx("p", {
132
+ children: WHO_COPY.caseNote
133
+ }) : null,
134
+ many && input.kind === 'text' ? /*#__PURE__*/ _jsx("p", {
135
+ children: WHO_COPY.listNote
136
+ }) : null,
137
+ hint ? /*#__PURE__*/ _jsx("p", {
138
+ children: hint
139
+ }) : null
140
+ ]
141
+ });
142
+ }
@@ -0,0 +1,18 @@
1
+ import type { SerializedAttributeKeys } from '../../types/admin.js';
2
+ import type { TargetingOp } from '../../targeting/ops.js';
3
+ type Attribute = SerializedAttributeKeys[string];
4
+ export type AttributeType = Attribute['type'];
5
+ export declare function opsFor(type?: AttributeType): readonly TargetingOp[];
6
+ export declare function opLabel(type: AttributeType, op: TargetingOp): string;
7
+ export declare function valueInput(attribute?: Attribute, op?: TargetingOp): {
8
+ kind: 'text' | 'number' | 'boolean' | 'select' | 'multiselect';
9
+ options?: {
10
+ label: string;
11
+ value: string;
12
+ }[];
13
+ };
14
+ export declare function coerceValue(type: AttributeType, op: TargetingOp, raw: unknown): string | number | boolean | string[] | null;
15
+ export declare function rowPath(path: string): string;
16
+ export declare function emptyListHint(op: TargetingOp, value: unknown): string | undefined;
17
+ export declare function humaniseAttribute(key: string): string;
18
+ export {};
@@ -0,0 +1,48 @@
1
+ import { TARGETING_OPS, isOpValid } from '../../targeting/ops.js';
2
+ import { NUMBER_OP_LABELS, STRING_OP_LABELS, WHO_COPY } from '../copy/who.js';
3
+ export function opsFor(type) {
4
+ return type ? TARGETING_OPS[type] : [];
5
+ }
6
+ export function opLabel(type, op) {
7
+ if (!isOpValid(type, op)) return '';
8
+ if (type === 'boolean') return STRING_OP_LABELS.eq;
9
+ return type === 'number' ? NUMBER_OP_LABELS[op] : STRING_OP_LABELS[op];
10
+ }
11
+ export function valueInput(attribute, op = 'eq') {
12
+ const many = op === 'in' || op === 'nin';
13
+ if (attribute?.values) return {
14
+ kind: many ? 'multiselect' : 'select',
15
+ options: attribute.values.map((value)=>({
16
+ label: value,
17
+ value
18
+ }))
19
+ };
20
+ return {
21
+ kind: attribute?.type === 'number' ? 'number' : attribute?.type === 'boolean' ? 'boolean' : 'text'
22
+ };
23
+ }
24
+ export function coerceValue(type, op, raw) {
25
+ if (!isOpValid(type, op)) return null;
26
+ if (type === 'string') {
27
+ if (op === 'in' || op === 'nin') return (Array.isArray(raw) ? raw.map(String) : String(raw ?? '').split(',')).map((value)=>value.trim()).filter(Boolean);
28
+ return raw == null ? '' : String(raw);
29
+ }
30
+ if (type === 'number') {
31
+ if (raw == null || typeof raw === 'string' && !raw.trim()) return null;
32
+ const value = Number(raw);
33
+ return Number.isFinite(value) ? value : null;
34
+ }
35
+ return raw === true || raw === 'true' ? true : raw === false || raw === 'false' ? false : null;
36
+ }
37
+ export function rowPath(path) {
38
+ return path.slice(0, Math.max(0, path.lastIndexOf('.')));
39
+ }
40
+ export function emptyListHint(op, value) {
41
+ if (op !== 'in' && op !== 'nin') return undefined;
42
+ const list = coerceValue('string', op, value);
43
+ return Array.isArray(list) && list.length === 0 ? WHO_COPY.emptyListNote : undefined;
44
+ }
45
+ export function humaniseAttribute(key) {
46
+ const words = key.replace(/([a-z0-9])([A-Z])/g, '$1 $2').replace(/[_-]+/g, ' ');
47
+ return words.charAt(0).toUpperCase() + words.slice(1);
48
+ }
@@ -0,0 +1,20 @@
1
+ export declare function useApi(): {
2
+ start: (id: import("../types/contracts.js").DocId) => Promise<import("./api.js").ApiResult<import("../types/endpoints.js").TransitionSuccess>>;
3
+ allocate: (id: import("../types/contracts.js").DocId, body: import("../types/endpoints.js").AllocateBody) => Promise<import("./api.js").ApiResult<import("../types/endpoints.js").TransitionSuccess>>;
4
+ addMetric: (id: import("../types/contracts.js").DocId, body: import("../types/endpoints.js").AddMetricBody) => Promise<import("./api.js").ApiResult<import("../types/endpoints.js").TransitionSuccess>>;
5
+ stop: (id: import("../types/contracts.js").DocId) => Promise<import("./api.js").ApiResult<import("../types/endpoints.js").TransitionSuccess>>;
6
+ decide: (id: import("../types/contracts.js").DocId, body: import("../types/endpoints.js").DecideBody) => Promise<import("./api.js").ApiResult<import("../types/endpoints.js").TransitionSuccess>>;
7
+ releaseHoldout: (id: import("../types/contracts.js").DocId) => Promise<import("./api.js").ApiResult<import("../types/endpoints.js").TransitionSuccess>>;
8
+ makeContent: (id: import("../types/contracts.js").DocId) => Promise<import("./api.js").ApiResult<import("../types/endpoints.js").MakeContentResult>>;
9
+ archive: (id: import("../types/contracts.js").DocId, body: import("../types/endpoints.js").ArchiveBody) => Promise<import("./api.js").ApiResult<import("../types/endpoints.js").TransitionSuccess>>;
10
+ preflight: (id: import("../types/contracts.js").DocId) => Promise<import("./api.js").ApiResult<import("../types/endpoints.js").PreflightResult>>;
11
+ previewToken: (id: import("../types/contracts.js").DocId, arm: string) => Promise<import("./api.js").ApiResult<import("../types/endpoints.js").PreviewTokenResult>>;
12
+ results: (id: import("../types/contracts.js").DocId, options?: {
13
+ phase?: number;
14
+ series?: boolean;
15
+ }) => Promise<import("./api.js").ApiResult<import("../types/endpoints.js").ResultsResponse>>;
16
+ recompute: (id: import("../types/contracts.js").DocId) => Promise<import("./api.js").ApiResult<{
17
+ snapshotId: string;
18
+ }>>;
19
+ summary: (ids: readonly import("../types/contracts.js").DocId[]) => Promise<import("./api.js").ApiResult<import("../types/endpoints.js").SummaryResponse>>;
20
+ };
@@ -0,0 +1,10 @@
1
+ 'use client';
2
+ import { useMemo } from 'react';
3
+ import { useConfig } from '@payloadcms/ui';
4
+ import { createApi } from './api.js';
5
+ export function useApi() {
6
+ const { config } = useConfig();
7
+ return useMemo(()=>createApi(config.routes.api), [
8
+ config.routes.api
9
+ ]);
10
+ }
@@ -0,0 +1,15 @@
1
+ import type { DocId } from '../types/contracts.js';
2
+ export declare function useLayerExperiments(layerId: DocId | null): {
3
+ used: number;
4
+ free: number;
5
+ rows: {
6
+ name: string;
7
+ status: import("../types/contracts.js").Status;
8
+ slices: number;
9
+ }[];
10
+ } | null;
11
+ export declare function useLayerUsage(layerId: DocId | null): {
12
+ name: string;
13
+ used: number;
14
+ free: number;
15
+ } | null;
@@ -0,0 +1,92 @@
1
+ 'use client';
2
+ import { useConfig } from '@payloadcms/ui';
3
+ import { useEffect, useState } from 'react';
4
+ import { layerUsage } from './layerUsage.model.js';
5
+ // Shared by the layer document and the allocation field; all requests use the editor's access.
6
+ export function useLayerExperiments(layerId) {
7
+ const { config } = useConfig();
8
+ const api = config.routes.api;
9
+ const id = layerId == null ? null : String(layerId);
10
+ const [state, setState] = useState(null);
11
+ useEffect(()=>{
12
+ setState(null);
13
+ if (id == null) return;
14
+ const controller = new AbortController();
15
+ async function load() {
16
+ const docs = [];
17
+ let page = 1;
18
+ while(!controller.signal.aborted){
19
+ const query = new URLSearchParams({
20
+ depth: '0',
21
+ limit: '100',
22
+ page: String(page),
23
+ 'where[layer][equals]': id,
24
+ 'where[status][in]': 'running,decided'
25
+ });
26
+ const response = await fetch(`${api}/xp-experiments?${query}`, {
27
+ credentials: 'include',
28
+ signal: controller.signal
29
+ });
30
+ if (!response.ok) {
31
+ if (!controller.signal.aborted) setState(null);
32
+ return;
33
+ }
34
+ const data = await response.json();
35
+ docs.push(...data.docs);
36
+ if (!data.hasNextPage) break;
37
+ page++;
38
+ }
39
+ if (!controller.signal.aborted) setState({
40
+ api,
41
+ id: id,
42
+ usage: layerUsage(docs)
43
+ });
44
+ }
45
+ void load().catch(()=>{
46
+ if (!controller.signal.aborted) setState(null);
47
+ });
48
+ return ()=>controller.abort();
49
+ }, [
50
+ api,
51
+ id
52
+ ]);
53
+ return id != null && state?.api === api && state.id === id ? state.usage : null;
54
+ }
55
+ export function useLayerUsage(layerId) {
56
+ const { config } = useConfig();
57
+ const api = config.routes.api;
58
+ const id = layerId == null ? null : String(layerId);
59
+ const usage = useLayerExperiments(layerId);
60
+ const [state, setState] = useState(null);
61
+ useEffect(()=>{
62
+ setState(null);
63
+ if (id == null) return;
64
+ const controller = new AbortController();
65
+ void fetch(`${api}/xp-layers/${encodeURIComponent(id)}?depth=0`, {
66
+ credentials: 'include',
67
+ signal: controller.signal
68
+ }).then(async (response)=>{
69
+ if (!response.ok) {
70
+ if (!controller.signal.aborted) setState(null);
71
+ return;
72
+ }
73
+ const doc = await response.json();
74
+ if (!controller.signal.aborted) setState({
75
+ api,
76
+ id,
77
+ name: doc.name
78
+ });
79
+ }).catch(()=>{
80
+ if (!controller.signal.aborted) setState(null);
81
+ });
82
+ return ()=>controller.abort();
83
+ }, [
84
+ api,
85
+ id
86
+ ]);
87
+ return usage && id != null && state?.api === api && state.id === id ? {
88
+ name: state.name,
89
+ used: usage.used,
90
+ free: usage.free
91
+ } : null;
92
+ }
@@ -0,0 +1 @@
1
+ export declare function ExperimentPageview(): null;
@@ -0,0 +1,27 @@
1
+ 'use client';
2
+ import { useContext, useEffect } from 'react';
3
+ import { sendExposure } from './beacon.js';
4
+ import { ExperimentsContext } from './context.js';
5
+ export function ExperimentPageview() {
6
+ const value = useContext(ExperimentsContext);
7
+ const pageviews = value?.pageviews;
8
+ const apiRoute = value?.apiRoute;
9
+ useEffect(()=>{
10
+ if (!pageviews || apiRoute === undefined) return;
11
+ // Read the path at commit time: on an App Router soft navigation the new page renders before the URL updates.
12
+ const pathname = window.location.pathname;
13
+ for (const { slug, phase, arm } of pageviews){
14
+ sendExposure(apiRoute, {
15
+ type: 'exposure',
16
+ experiment: slug,
17
+ phase,
18
+ arm,
19
+ policy: 'pageview'
20
+ }, pathname);
21
+ }
22
+ }, [
23
+ pageviews,
24
+ apiRoute
25
+ ]);
26
+ return null;
27
+ }
@@ -0,0 +1,6 @@
1
+ import type * as React from 'react';
2
+ import type { ClientAssignments } from '../types/assignments.js';
3
+ export declare function ExperimentsProvider(props: {
4
+ value: ClientAssignments;
5
+ children: React.ReactNode;
6
+ }): React.JSX.Element;