@10x-media/form-builder 0.1.0-beta.4 → 0.1.0-beta.5

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 (356) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/README.md +3 -3
  3. package/dist/actions/body/serializeBody.d.ts +8 -5
  4. package/dist/actions/body/serializeBody.js.map +1 -1
  5. package/dist/actions/body/textOfBody.d.ts +13 -0
  6. package/dist/actions/body/textOfBody.js +35 -0
  7. package/dist/actions/body/textOfBody.js.map +1 -0
  8. package/dist/actions/builtin/confirmation.js +41 -11
  9. package/dist/actions/builtin/confirmation.js.map +1 -1
  10. package/dist/actions/builtin/emailTeam.js +77 -38
  11. package/dist/actions/builtin/emailTeam.js.map +1 -1
  12. package/dist/actions/builtin/index.d.ts +8 -3
  13. package/dist/actions/builtin/index.js +8 -5
  14. package/dist/actions/builtin/index.js.map +1 -1
  15. package/dist/actions/defineAction.d.ts +1 -1
  16. package/dist/actions/fromAddresses.d.ts +21 -0
  17. package/dist/actions/fromAddresses.js +74 -0
  18. package/dist/actions/fromAddresses.js.map +1 -0
  19. package/dist/actions/task.js +9 -8
  20. package/dist/actions/task.js.map +1 -1
  21. package/dist/aggregation/aggregateResponses.d.ts +9 -0
  22. package/dist/aggregation/aggregateResponses.js +8 -14
  23. package/dist/aggregation/aggregateResponses.js.map +1 -1
  24. package/dist/aggregation/resolveResultsRequest.d.ts +19 -6
  25. package/dist/aggregation/resolveResultsRequest.js +58 -12
  26. package/dist/aggregation/resolveResultsRequest.js.map +1 -1
  27. package/dist/calc/computeCalcFields.js +2 -1
  28. package/dist/calc/computeCalcFields.js.map +1 -1
  29. package/dist/client/ByteSizeField.d.ts +8 -0
  30. package/dist/client/ByteSizeField.js +3 -1
  31. package/dist/client/ByteSizeField.js.map +1 -1
  32. package/dist/client/ClosePollButton.d.ts +15 -0
  33. package/dist/client/ClosePollButton.js +80 -0
  34. package/dist/client/ClosePollButton.js.map +1 -0
  35. package/dist/client/CondensedArray.d.ts +15 -0
  36. package/dist/client/CondensedArray.js +97 -0
  37. package/dist/client/CondensedArray.js.map +1 -0
  38. package/dist/client/EndpointOptionsSelect.d.ts +45 -0
  39. package/dist/client/EndpointOptionsSelect.js +103 -0
  40. package/dist/client/EndpointOptionsSelect.js.map +1 -0
  41. package/dist/client/FieldBlockLabel.d.ts +18 -0
  42. package/dist/client/FieldBlockLabel.js +34 -0
  43. package/dist/client/FieldBlockLabel.js.map +1 -0
  44. package/dist/client/FieldNameSelect.d.ts +20 -4
  45. package/dist/client/FieldNameSelect.js +25 -14
  46. package/dist/client/FieldNameSelect.js.map +1 -1
  47. package/dist/client/FlowBuilder.d.ts +2 -1
  48. package/dist/client/FlowBuilder.js +63 -57
  49. package/dist/client/FlowBuilder.js.map +1 -1
  50. package/dist/client/RuleDescription.d.ts +21 -0
  51. package/dist/client/RuleDescription.js +19 -0
  52. package/dist/client/RuleDescription.js.map +1 -0
  53. package/dist/client/admin.css +36 -0
  54. package/dist/client/endpointOptions.js +29 -0
  55. package/dist/client/endpointOptions.js.map +1 -0
  56. package/dist/client/flowAuthoring.js +114 -7
  57. package/dist/client/flowAuthoring.js.map +1 -1
  58. package/dist/client/synthesizeClientField.js +15 -8
  59. package/dist/client/synthesizeClientField.js.map +1 -1
  60. package/dist/collections/buttonFields.d.ts +34 -0
  61. package/dist/collections/buttonFields.js +35 -0
  62. package/dist/collections/buttonFields.js.map +1 -0
  63. package/dist/collections/cells/FieldCountCell.d.ts +15 -0
  64. package/dist/collections/cells/FieldCountCell.js +18 -0
  65. package/dist/collections/cells/FieldCountCell.js.map +1 -0
  66. package/dist/collections/cells/FlowStepsCell.d.ts +14 -0
  67. package/dist/collections/cells/FlowStepsCell.js +17 -0
  68. package/dist/collections/cells/FlowStepsCell.js.map +1 -0
  69. package/dist/collections/formSubmissions.js +22 -17
  70. package/dist/collections/formSubmissions.js.map +1 -1
  71. package/dist/collections/forms.js +310 -137
  72. package/dist/collections/forms.js.map +1 -1
  73. package/dist/collections/redirectFields.d.ts +29 -0
  74. package/dist/consent/applyConsentStatements.d.ts +14 -0
  75. package/dist/consent/applyConsentStatements.js +17 -0
  76. package/dist/consent/applyConsentStatements.js.map +1 -0
  77. package/dist/consent/captureConsent.d.ts +19 -8
  78. package/dist/consent/captureConsent.js +34 -11
  79. package/dist/consent/captureConsent.js.map +1 -1
  80. package/dist/consent/consentSourcesField.d.ts +58 -0
  81. package/dist/consent/consentSourcesField.js +79 -0
  82. package/dist/consent/consentSourcesField.js.map +1 -0
  83. package/dist/consent/resolveConsentEntries.d.ts +24 -0
  84. package/dist/consent/resolveConsentEntries.js +43 -0
  85. package/dist/consent/resolveConsentEntries.js.map +1 -0
  86. package/dist/consent/resolveConsentSourcesRequest.d.ts +37 -0
  87. package/dist/consent/resolveConsentSourcesRequest.js +55 -0
  88. package/dist/consent/resolveConsentSourcesRequest.js.map +1 -0
  89. package/dist/consent/resolveConsentStatements.d.ts +45 -0
  90. package/dist/consent/resolveConsentStatements.js +44 -0
  91. package/dist/consent/resolveConsentStatements.js.map +1 -0
  92. package/dist/consent/resolvePublishedVersionRef.d.ts +17 -11
  93. package/dist/consent/resolvePublishedVersionRef.js +13 -10
  94. package/dist/consent/resolvePublishedVersionRef.js.map +1 -1
  95. package/dist/consent/types.d.ts +49 -0
  96. package/dist/email/departments.d.ts +55 -0
  97. package/dist/email/departments.js +130 -0
  98. package/dist/email/departments.js.map +1 -0
  99. package/dist/email/departmentsField.d.ts +49 -0
  100. package/dist/email/departmentsField.js +69 -0
  101. package/dist/email/departmentsField.js.map +1 -0
  102. package/dist/exports/client.d.ts +8 -1
  103. package/dist/exports/client.js +8 -1
  104. package/dist/exports/react.d.ts +8 -3
  105. package/dist/exports/react.js +6 -2
  106. package/dist/exports/rsc.d.ts +3 -1
  107. package/dist/exports/rsc.js +4 -2
  108. package/dist/exports/types.d.ts +16 -8
  109. package/dist/fields/buildFieldBlocks.js +28 -13
  110. package/dist/fields/buildFieldBlocks.js.map +1 -1
  111. package/dist/fields/builtin/calculation.js +7 -0
  112. package/dist/fields/builtin/calculation.js.map +1 -1
  113. package/dist/fields/builtin/checkbox.js +8 -0
  114. package/dist/fields/builtin/checkbox.js.map +1 -1
  115. package/dist/fields/builtin/consent.js +27 -21
  116. package/dist/fields/builtin/consent.js.map +1 -1
  117. package/dist/fields/builtin/country.d.ts +13 -0
  118. package/dist/fields/builtin/country.js +30 -0
  119. package/dist/fields/builtin/country.js.map +1 -0
  120. package/dist/fields/builtin/date.js +2 -0
  121. package/dist/fields/builtin/date.js.map +1 -1
  122. package/dist/fields/builtin/file.js +5 -4
  123. package/dist/fields/builtin/file.js.map +1 -1
  124. package/dist/fields/builtin/index.d.ts +8 -6
  125. package/dist/fields/builtin/index.js +10 -9
  126. package/dist/fields/builtin/index.js.map +1 -1
  127. package/dist/fields/builtin/message.js +8 -4
  128. package/dist/fields/builtin/message.js.map +1 -1
  129. package/dist/fields/builtin/repeater.js +1 -0
  130. package/dist/fields/builtin/repeater.js.map +1 -1
  131. package/dist/fields/builtin/select.js +1 -0
  132. package/dist/fields/builtin/select.js.map +1 -1
  133. package/dist/fields/builtin/state.d.ts +13 -0
  134. package/dist/fields/builtin/state.js +30 -0
  135. package/dist/fields/builtin/state.js.map +1 -0
  136. package/dist/fields/data/regions.d.ts +21 -0
  137. package/dist/fields/data/regions.js +1238 -0
  138. package/dist/fields/data/regions.js.map +1 -0
  139. package/dist/fields/fieldKey.d.ts +15 -0
  140. package/dist/fields/fieldKey.js +16 -0
  141. package/dist/fields/fieldKey.js.map +1 -0
  142. package/dist/fields/fieldNamesOfType.js +13 -8
  143. package/dist/fields/fieldNamesOfType.js.map +1 -1
  144. package/dist/fields/instanceOptions.js +20 -0
  145. package/dist/fields/instanceOptions.js.map +1 -0
  146. package/dist/fields/registry.d.ts +1 -0
  147. package/dist/fields/registry.js +21 -2
  148. package/dist/fields/registry.js.map +1 -1
  149. package/dist/fields/sharedConfig.js +46 -9
  150. package/dist/fields/sharedConfig.js.map +1 -1
  151. package/dist/fields/types.d.ts +54 -3
  152. package/dist/flow/engine.d.ts +6 -4
  153. package/dist/flow/engine.js +11 -6
  154. package/dist/flow/engine.js.map +1 -1
  155. package/dist/flow/normalizeFlow.js +16 -7
  156. package/dist/flow/normalizeFlow.js.map +1 -1
  157. package/dist/flow/types.d.ts +12 -3
  158. package/dist/flow/types.js +11 -0
  159. package/dist/flow/types.js.map +1 -0
  160. package/dist/form/pollState.d.ts +4 -4
  161. package/dist/form/pollState.js.map +1 -1
  162. package/dist/form/toFormDocument.d.ts +37 -12
  163. package/dist/form/toFormDocument.js +43 -7
  164. package/dist/form/toFormDocument.js.map +1 -1
  165. package/dist/form/types.d.ts +31 -14
  166. package/dist/index.d.ts +143 -28
  167. package/dist/index.js +43 -14
  168. package/dist/index.js.map +1 -1
  169. package/dist/plugin/customState.js +26 -0
  170. package/dist/plugin/customState.js.map +1 -0
  171. package/dist/plugin/registerCollections.js +23 -13
  172. package/dist/plugin/registerCollections.js.map +1 -1
  173. package/dist/plugin/uploadsCollection.d.ts +2 -0
  174. package/dist/poll/applyPollOptions.js +3 -2
  175. package/dist/poll/applyPollOptions.js.map +1 -1
  176. package/dist/poll/buildPollOptionSourceFields.js +2 -5
  177. package/dist/poll/buildPollOptionSourceFields.js.map +1 -1
  178. package/dist/poll/closeJob.d.ts +52 -0
  179. package/dist/poll/closeJob.js +119 -0
  180. package/dist/poll/closeJob.js.map +1 -0
  181. package/dist/poll/definePollOptionSource.d.ts +10 -1
  182. package/dist/poll/definePollOptionSource.js.map +1 -1
  183. package/dist/poll/definePollType.d.ts +34 -0
  184. package/dist/poll/definePollType.js +6 -0
  185. package/dist/poll/definePollType.js.map +1 -0
  186. package/dist/poll/effectivePollOptions.d.ts +38 -0
  187. package/dist/poll/effectivePollOptions.js +64 -0
  188. package/dist/poll/effectivePollOptions.js.map +1 -0
  189. package/dist/poll/mostVoted.d.ts +21 -0
  190. package/dist/poll/mostVoted.js +32 -0
  191. package/dist/poll/mostVoted.js.map +1 -0
  192. package/dist/poll/outcomeBeforeChange.js +91 -0
  193. package/dist/poll/outcomeBeforeChange.js.map +1 -0
  194. package/dist/poll/outcomeFields.d.ts +38 -0
  195. package/dist/poll/outcomeFields.js +52 -0
  196. package/dist/poll/outcomeFields.js.map +1 -0
  197. package/dist/poll/pollTypeRegistry.d.ts +34 -0
  198. package/dist/poll/pollTypeRegistry.js +71 -0
  199. package/dist/poll/pollTypeRegistry.js.map +1 -0
  200. package/dist/poll/resolvePollCloseRequest.js +105 -0
  201. package/dist/poll/resolvePollCloseRequest.js.map +1 -0
  202. package/dist/poll/resolvePollOptions.d.ts +2 -1
  203. package/dist/poll/resolvePollOptions.js +5 -17
  204. package/dist/poll/resolvePollOptions.js.map +1 -1
  205. package/dist/poll/resolvePollOptionsRequest.js +51 -0
  206. package/dist/poll/resolvePollOptionsRequest.js.map +1 -0
  207. package/dist/poll/resolvePollOutcome.d.ts +22 -9
  208. package/dist/poll/resolvePollOutcome.js +54 -14
  209. package/dist/poll/resolvePollOutcome.js.map +1 -1
  210. package/dist/poll/resultsField.js +21 -0
  211. package/dist/poll/resultsField.js.map +1 -0
  212. package/dist/prefill/valuesFromSearchParams.js +2 -1
  213. package/dist/prefill/valuesFromSearchParams.js.map +1 -1
  214. package/dist/react/Form.d.ts +8 -8
  215. package/dist/react/Form.js +74 -62
  216. package/dist/react/Form.js.map +1 -1
  217. package/dist/react/FormContext.d.ts +6 -4
  218. package/dist/react/FormContext.js.map +1 -1
  219. package/dist/react/FormControls.d.ts +3 -3
  220. package/dist/react/FormControls.js +3 -3
  221. package/dist/react/FormControls.js.map +1 -1
  222. package/dist/react/FormResults.d.ts +5 -5
  223. package/dist/react/FormResults.js +6 -6
  224. package/dist/react/FormResults.js.map +1 -1
  225. package/dist/react/Poll.d.ts +2 -2
  226. package/dist/react/Poll.js +5 -5
  227. package/dist/react/Poll.js.map +1 -1
  228. package/dist/react/contract.d.ts +2 -3
  229. package/dist/react/contract.js.map +1 -1
  230. package/dist/react/primitives/Checkbox.d.ts +4 -2
  231. package/dist/react/primitives/Checkbox.js +2 -1
  232. package/dist/react/primitives/Checkbox.js.map +1 -1
  233. package/dist/react/primitives/FieldShell.d.ts +2 -4
  234. package/dist/react/primitives/FieldShell.js +12 -19
  235. package/dist/react/primitives/FieldShell.js.map +1 -1
  236. package/dist/react/renderers/calculation.js +1 -2
  237. package/dist/react/renderers/calculation.js.map +1 -1
  238. package/dist/react/renderers/checkbox.js +1 -2
  239. package/dist/react/renderers/checkbox.js.map +1 -1
  240. package/dist/react/renderers/consent.js +78 -34
  241. package/dist/react/renderers/consent.js.map +1 -1
  242. package/dist/react/renderers/date.js +1 -3
  243. package/dist/react/renderers/date.js.map +1 -1
  244. package/dist/react/renderers/email.js +1 -2
  245. package/dist/react/renderers/email.js.map +1 -1
  246. package/dist/react/renderers/file.js +1 -2
  247. package/dist/react/renderers/file.js.map +1 -1
  248. package/dist/react/renderers/index.js +3 -0
  249. package/dist/react/renderers/index.js.map +1 -1
  250. package/dist/react/renderers/number.js +1 -2
  251. package/dist/react/renderers/number.js.map +1 -1
  252. package/dist/react/renderers/region.js +45 -0
  253. package/dist/react/renderers/region.js.map +1 -0
  254. package/dist/react/renderers/repeater.js +7 -10
  255. package/dist/react/renderers/repeater.js.map +1 -1
  256. package/dist/react/renderers/select.js +1 -2
  257. package/dist/react/renderers/select.js.map +1 -1
  258. package/dist/react/renderers/text.js +1 -2
  259. package/dist/react/renderers/text.js.map +1 -1
  260. package/dist/react/renderers/textarea.js +1 -2
  261. package/dist/react/renderers/textarea.js.map +1 -1
  262. package/dist/react/state.d.ts +0 -3
  263. package/dist/react/state.js +7 -11
  264. package/dist/react/state.js.map +1 -1
  265. package/dist/react/useField.d.ts +0 -1
  266. package/dist/react/useField.js +0 -1
  267. package/dist/react/useField.js.map +1 -1
  268. package/dist/react/useFormState.d.ts +1 -1
  269. package/dist/react/useFormState.js +1 -1
  270. package/dist/react/useFormState.js.map +1 -1
  271. package/dist/react/validateField.js +3 -6
  272. package/dist/react/validateField.js.map +1 -1
  273. package/dist/recall/interpolate.d.ts +4 -3
  274. package/dist/recall/interpolate.js +5 -4
  275. package/dist/recall/interpolate.js.map +1 -1
  276. package/dist/recall/resolver.d.ts +1 -1
  277. package/dist/recall/resolver.js +14 -2
  278. package/dist/recall/resolver.js.map +1 -1
  279. package/dist/spam/captcha.d.ts +1 -1
  280. package/dist/spam/captcha.js +1 -1
  281. package/dist/spam/captcha.js.map +1 -1
  282. package/dist/submissions/SubmissionAnswers.js +6 -2
  283. package/dist/submissions/SubmissionAnswers.js.map +1 -1
  284. package/dist/submissions/SubmissionAnswersClient.js +91 -62
  285. package/dist/submissions/SubmissionAnswersClient.js.map +1 -1
  286. package/dist/submissions/createSubmission.d.ts +36 -0
  287. package/dist/submissions/createSubmission.js +26 -0
  288. package/dist/submissions/createSubmission.js.map +1 -0
  289. package/dist/submissions/runSubmission.d.ts +10 -0
  290. package/dist/submissions/runSubmission.js +29 -18
  291. package/dist/submissions/runSubmission.js.map +1 -1
  292. package/dist/submissions/types.d.ts +11 -4
  293. package/dist/submissions/validateSubmission.js +38 -23
  294. package/dist/submissions/validateSubmission.js.map +1 -1
  295. package/dist/submissions/votedCookie.js +3 -3
  296. package/dist/submissions/votedCookie.js.map +1 -1
  297. package/dist/translations/de.js +102 -26
  298. package/dist/translations/de.js.map +1 -1
  299. package/dist/translations/en.js +103 -27
  300. package/dist/translations/en.js.map +1 -1
  301. package/dist/translations/keys.d.ts +97 -21
  302. package/dist/translations/keys.js +98 -22
  303. package/dist/translations/keys.js.map +1 -1
  304. package/dist/validation/buildRuleBlocks.js +18 -17
  305. package/dist/validation/buildRuleBlocks.js.map +1 -1
  306. package/dist/validation/builtin/email.js +1 -0
  307. package/dist/validation/builtin/email.js.map +1 -1
  308. package/dist/validation/builtin/matchesField.js +3 -7
  309. package/dist/validation/builtin/matchesField.js.map +1 -1
  310. package/dist/validation/builtin/max.js +1 -0
  311. package/dist/validation/builtin/max.js.map +1 -1
  312. package/dist/validation/builtin/maxDate.js +1 -0
  313. package/dist/validation/builtin/maxDate.js.map +1 -1
  314. package/dist/validation/builtin/maxLength.js +1 -0
  315. package/dist/validation/builtin/maxLength.js.map +1 -1
  316. package/dist/validation/builtin/min.js +1 -0
  317. package/dist/validation/builtin/min.js.map +1 -1
  318. package/dist/validation/builtin/minDate.js +1 -0
  319. package/dist/validation/builtin/minDate.js.map +1 -1
  320. package/dist/validation/builtin/minLength.js +1 -0
  321. package/dist/validation/builtin/minLength.js.map +1 -1
  322. package/dist/validation/builtin/notAlreadySubmitted.js +1 -0
  323. package/dist/validation/builtin/notAlreadySubmitted.js.map +1 -1
  324. package/dist/validation/builtin/oneOf.js +1 -0
  325. package/dist/validation/builtin/oneOf.js.map +1 -1
  326. package/dist/validation/builtin/pattern.js +11 -2
  327. package/dist/validation/builtin/pattern.js.map +1 -1
  328. package/dist/validation/builtin/url.js +1 -0
  329. package/dist/validation/builtin/url.js.map +1 -1
  330. package/dist/validation/builtin/validateRegexParams.js +44 -0
  331. package/dist/validation/builtin/validateRegexParams.js.map +1 -0
  332. package/dist/validation/fieldTargetParam.d.ts +22 -0
  333. package/dist/validation/fieldTargetParam.js +38 -0
  334. package/dist/validation/fieldTargetParam.js.map +1 -0
  335. package/dist/validation/runValidation.js +8 -29
  336. package/dist/validation/runValidation.js.map +1 -1
  337. package/dist/validation/types.d.ts +5 -11
  338. package/package.json +6 -6
  339. package/dist/consent/buildConsentSourceConfig.js +0 -49
  340. package/dist/consent/buildConsentSourceConfig.js.map +0 -1
  341. package/dist/consent/builtin/index.d.ts +0 -17
  342. package/dist/consent/builtin/index.js +0 -21
  343. package/dist/consent/builtin/index.js.map +0 -1
  344. package/dist/consent/builtin/pageReference.js +0 -75
  345. package/dist/consent/builtin/pageReference.js.map +0 -1
  346. package/dist/consent/builtin/static.js +0 -48
  347. package/dist/consent/builtin/static.js.map +0 -1
  348. package/dist/consent/defineConsentSource.d.ts +0 -35
  349. package/dist/consent/defineConsentSource.js +0 -6
  350. package/dist/consent/defineConsentSource.js.map +0 -1
  351. package/dist/consent/registry.d.ts +0 -16
  352. package/dist/consent/registry.js +0 -16
  353. package/dist/consent/registry.js.map +0 -1
  354. package/dist/consent/resolveConsentLinks.d.ts +0 -19
  355. package/dist/consent/resolveConsentLinks.js +0 -26
  356. package/dist/consent/resolveConsentLinks.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"pattern.js","names":[],"sources":["../../../src/validation/builtin/pattern.ts"],"sourcesContent":["import { keys } from '../../translations/keys'\nimport { labelFor } from '../../translations/server'\nimport { defineValidationRule } from '../defineValidationRule'\n\nconst tryRegExp = (pattern: string, flags?: string): RegExp | undefined => {\n\ttry {\n\t\treturn new RegExp(pattern, flags)\n\t} catch {\n\t\treturn undefined\n\t}\n}\n\nexport const patternRule = defineValidationRule<{ pattern: string; flags?: string }, string>({\n\ttype: 'pattern',\n\tlabel: keys.rulePattern,\n\tappliesTo: ['text', 'textarea', 'email'],\n\tparams: [\n\t\t{ name: 'pattern', type: 'text', required: true, label: labelFor(keys.ruleParamPattern) },\n\t\t{ name: 'flags', type: 'text', label: labelFor(keys.ruleParamFlags) },\n\t],\n\tdefaultMessage: keys.rulePatternMessage,\n\tvalidate: ({ value, params, message }) => {\n\t\tif (value == null || value === '') {\n\t\t\treturn true\n\t\t}\n\t\tconst regex = tryRegExp(params.pattern, params.flags)\n\t\tif (!regex) {\n\t\t\treturn true\n\t\t}\n\t\treturn regex.test(value) ? true : message()\n\t},\n})\n"],"mappings":";;;;AAIA,MAAM,aAAa,SAAiB,UAAuC;CAC1E,IAAI;EACH,OAAO,IAAI,OAAO,SAAS,KAAK;CACjC,QAAQ;EACP;CACD;AACD;AAEA,MAAa,cAAc,qBAAkE;CAC5F,MAAM;CACN,OAAO,KAAK;CACZ,WAAW;EAAC;EAAQ;EAAY;CAAO;CACvC,QAAQ,CACP;EAAE,MAAM;EAAW,MAAM;EAAQ,UAAU;EAAM,OAAO,SAAS,KAAK,gBAAgB;CAAE,GACxF;EAAE,MAAM;EAAS,MAAM;EAAQ,OAAO,SAAS,KAAK,cAAc;CAAE,CACrE;CACA,gBAAgB,KAAK;CACrB,WAAW,EAAE,OAAO,QAAQ,cAAc;EACzC,IAAI,SAAS,QAAQ,UAAU,IAC9B,OAAO;EAER,MAAM,QAAQ,UAAU,OAAO,SAAS,OAAO,KAAK;EACpD,IAAI,CAAC,OACJ,OAAO;EAER,OAAO,MAAM,KAAK,KAAK,IAAI,OAAO,QAAQ;CAC3C;AACD,CAAC"}
1
+ {"version":3,"file":"pattern.js","names":[],"sources":["../../../src/validation/builtin/pattern.ts"],"sourcesContent":["import { keys } from '../../translations/keys'\nimport { labelFor } from '../../translations/server'\nimport { defineValidationRule } from '../defineValidationRule'\nimport { validateRegexFlags, validateRegexPattern } from './validateRegexParams'\n\nconst tryRegExp = (pattern: string, flags?: string): RegExp | undefined => {\n\ttry {\n\t\treturn new RegExp(pattern, flags)\n\t} catch {\n\t\treturn undefined\n\t}\n}\n\n/**\n * Regex match. The params carry authoring-time `validate`s so an uncompilable pattern or flag set\n * cannot be saved; at submit time an uncompilable regex still fails open, since a stored rule that\n * predates those guards must not start rejecting every visitor's answer.\n */\nexport const patternRule = defineValidationRule<{ pattern: string; flags?: string }, string>({\n\ttype: 'pattern',\n\tlabel: keys.rulePattern,\n\tdescription: keys.rulePatternDescription,\n\tappliesTo: ['text', 'textarea', 'email'],\n\tparams: [\n\t\t{\n\t\t\tname: 'pattern',\n\t\t\ttype: 'text',\n\t\t\trequired: true,\n\t\t\tlabel: labelFor(keys.ruleParamPattern),\n\t\t\tvalidate: validateRegexPattern,\n\t\t},\n\t\t{\n\t\t\tname: 'flags',\n\t\t\ttype: 'text',\n\t\t\tlabel: labelFor(keys.ruleParamFlags),\n\t\t\tvalidate: validateRegexFlags,\n\t\t},\n\t],\n\tdefaultMessage: keys.rulePatternMessage,\n\tvalidate: ({ value, params, message }) => {\n\t\tif (value == null || value === '') {\n\t\t\treturn true\n\t\t}\n\t\tconst regex = tryRegExp(params.pattern, params.flags)\n\t\tif (!regex) {\n\t\t\treturn true\n\t\t}\n\t\treturn regex.test(value) ? true : message()\n\t},\n})\n"],"mappings":";;;;;AAKA,MAAM,aAAa,SAAiB,UAAuC;CAC1E,IAAI;EACH,OAAO,IAAI,OAAO,SAAS,KAAK;CACjC,QAAQ;EACP;CACD;AACD;;;;;;AAOA,MAAa,cAAc,qBAAkE;CAC5F,MAAM;CACN,OAAO,KAAK;CACZ,aAAa,KAAK;CAClB,WAAW;EAAC;EAAQ;EAAY;CAAO;CACvC,QAAQ,CACP;EACC,MAAM;EACN,MAAM;EACN,UAAU;EACV,OAAO,SAAS,KAAK,gBAAgB;EACrC,UAAU;CACX,GACA;EACC,MAAM;EACN,MAAM;EACN,OAAO,SAAS,KAAK,cAAc;EACnC,UAAU;CACX,CACD;CACA,gBAAgB,KAAK;CACrB,WAAW,EAAE,OAAO,QAAQ,cAAc;EACzC,IAAI,SAAS,QAAQ,UAAU,IAC9B,OAAO;EAER,MAAM,QAAQ,UAAU,OAAO,SAAS,OAAO,KAAK;EACpD,IAAI,CAAC,OACJ,OAAO;EAER,OAAO,MAAM,KAAK,KAAK,IAAI,OAAO,QAAQ;CAC3C;AACD,CAAC"}
@@ -12,6 +12,7 @@ const isUrl = (value) => {
12
12
  const urlRule = defineValidationRule({
13
13
  type: "url",
14
14
  label: keys.ruleUrl,
15
+ description: keys.ruleUrlDescription,
15
16
  appliesTo: ["text", "textarea"],
16
17
  defaultMessage: keys.ruleUrlMessage,
17
18
  validate: ({ value, message }) => value == null || value === "" || isUrl(value) ? true : message()
@@ -1 +1 @@
1
- {"version":3,"file":"url.js","names":[],"sources":["../../../src/validation/builtin/url.ts"],"sourcesContent":["import { keys } from '../../translations/keys'\nimport { defineValidationRule } from '../defineValidationRule'\n\nconst isUrl = (value: string): boolean => {\n\ttry {\n\t\tconst url = new URL(value)\n\t\treturn url.protocol === 'http:' || url.protocol === 'https:'\n\t} catch {\n\t\treturn false\n\t}\n}\n\nexport const urlRule = defineValidationRule<Record<string, never>, string>({\n\ttype: 'url',\n\tlabel: keys.ruleUrl,\n\tappliesTo: ['text', 'textarea'],\n\tdefaultMessage: keys.ruleUrlMessage,\n\tvalidate: ({ value, message }) =>\n\t\tvalue == null || value === '' || isUrl(value) ? true : message(),\n})\n"],"mappings":";;;AAGA,MAAM,SAAS,UAA2B;CACzC,IAAI;EACH,MAAM,MAAM,IAAI,IAAI,KAAK;EACzB,OAAO,IAAI,aAAa,WAAW,IAAI,aAAa;CACrD,QAAQ;EACP,OAAO;CACR;AACD;AAEA,MAAa,UAAU,qBAAoD;CAC1E,MAAM;CACN,OAAO,KAAK;CACZ,WAAW,CAAC,QAAQ,UAAU;CAC9B,gBAAgB,KAAK;CACrB,WAAW,EAAE,OAAO,cACnB,SAAS,QAAQ,UAAU,MAAM,MAAM,KAAK,IAAI,OAAO,QAAQ;AACjE,CAAC"}
1
+ {"version":3,"file":"url.js","names":[],"sources":["../../../src/validation/builtin/url.ts"],"sourcesContent":["import { keys } from '../../translations/keys'\nimport { defineValidationRule } from '../defineValidationRule'\n\nconst isUrl = (value: string): boolean => {\n\ttry {\n\t\tconst url = new URL(value)\n\t\treturn url.protocol === 'http:' || url.protocol === 'https:'\n\t} catch {\n\t\treturn false\n\t}\n}\n\nexport const urlRule = defineValidationRule<Record<string, never>, string>({\n\ttype: 'url',\n\tlabel: keys.ruleUrl,\n\tdescription: keys.ruleUrlDescription,\n\tappliesTo: ['text', 'textarea'],\n\tdefaultMessage: keys.ruleUrlMessage,\n\tvalidate: ({ value, message }) =>\n\t\tvalue == null || value === '' || isUrl(value) ? true : message(),\n})\n"],"mappings":";;;AAGA,MAAM,SAAS,UAA2B;CACzC,IAAI;EACH,MAAM,MAAM,IAAI,IAAI,KAAK;EACzB,OAAO,IAAI,aAAa,WAAW,IAAI,aAAa;CACrD,QAAQ;EACP,OAAO;CACR;AACD;AAEA,MAAa,UAAU,qBAAoD;CAC1E,MAAM;CACN,OAAO,KAAK;CACZ,aAAa,KAAK;CAClB,WAAW,CAAC,QAAQ,UAAU;CAC9B,gBAAgB,KAAK;CACrB,WAAW,EAAE,OAAO,cACnB,SAAS,QAAQ,UAAU,MAAM,MAAM,KAAK,IAAI,OAAO,QAAQ;AACjE,CAAC"}
@@ -0,0 +1,44 @@
1
+ import { keys } from "../../translations/keys.js";
2
+ import { asTranslate } from "../../translations/server.js";
3
+ //#region src/validation/builtin/validateRegexParams.ts
4
+ /** Compiles to `undefined` instead of throwing, so callers can branch on validity. */
5
+ const tryCompile = (pattern, flags) => {
6
+ try {
7
+ return new RegExp(pattern, flags);
8
+ } catch {
9
+ return;
10
+ }
11
+ };
12
+ const flagsOf = (siblingData) => {
13
+ const flags = siblingData?.flags;
14
+ return typeof flags === "string" && flags !== "" ? flags : void 0;
15
+ };
16
+ /**
17
+ * Field-level `validate` for the pattern rule's `flags` param: an unset value is tolerated,
18
+ * otherwise the flag set must be one `RegExp` accepts (an empty source isolates flag validity
19
+ * from pattern validity, so the two params report their own errors).
20
+ * Exported for unit testing.
21
+ */
22
+ const validateRegexFlags = (value, { req }) => {
23
+ if (typeof value !== "string" || value === "") return true;
24
+ return tryCompile("", value) ? true : asTranslate(req.t)(keys.validationRegexFlags);
25
+ };
26
+ /**
27
+ * Field-level `validate` for the pattern rule's `pattern` param. The rule itself fails open on an
28
+ * uncompilable pattern so a bad regex can never break the submit path, which would otherwise let an
29
+ * author save a rule that silently never fires; this catches it at authoring time instead.
30
+ *
31
+ * Compiled against the sibling `flags` because flags decide validity (`\p{Foo}` is a literal
32
+ * without `u` and a syntax error with it). Invalid flags are ignored here and left to
33
+ * `validateRegexFlags`, so a flag typo reports once, on the field that owns it.
34
+ * Exported for unit testing.
35
+ */
36
+ const validateRegexPattern = (value, { req, siblingData }) => {
37
+ if (typeof value !== "string" || value === "") return true;
38
+ const flags = flagsOf(siblingData);
39
+ return tryCompile(value, flags && tryCompile("", flags) ? flags : void 0) ? true : asTranslate(req.t)(keys.validationRegexPattern);
40
+ };
41
+ //#endregion
42
+ export { validateRegexFlags, validateRegexPattern };
43
+
44
+ //# sourceMappingURL=validateRegexParams.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validateRegexParams.js","names":[],"sources":["../../../src/validation/builtin/validateRegexParams.ts"],"sourcesContent":["import type { PayloadRequest } from 'payload'\nimport { keys } from '../../translations/keys'\nimport { asTranslate } from '../../translations/server'\n\n/** Compiles to `undefined` instead of throwing, so callers can branch on validity. */\nconst tryCompile = (pattern: string, flags?: string): RegExp | undefined => {\n\ttry {\n\t\treturn new RegExp(pattern, flags)\n\t} catch {\n\t\treturn undefined\n\t}\n}\n\nconst flagsOf = (siblingData: unknown): string | undefined => {\n\tconst flags = (siblingData as { flags?: unknown } | undefined)?.flags\n\treturn typeof flags === 'string' && flags !== '' ? flags : undefined\n}\n\n/**\n * Field-level `validate` for the pattern rule's `flags` param: an unset value is tolerated,\n * otherwise the flag set must be one `RegExp` accepts (an empty source isolates flag validity\n * from pattern validity, so the two params report their own errors).\n * Exported for unit testing.\n */\nexport const validateRegexFlags = (\n\tvalue: unknown,\n\t{ req }: { req: PayloadRequest; siblingData?: unknown }\n): string | true => {\n\tif (typeof value !== 'string' || value === '') {\n\t\treturn true\n\t}\n\treturn tryCompile('', value) ? true : asTranslate(req.t)(keys.validationRegexFlags)\n}\n\n/**\n * Field-level `validate` for the pattern rule's `pattern` param. The rule itself fails open on an\n * uncompilable pattern so a bad regex can never break the submit path, which would otherwise let an\n * author save a rule that silently never fires; this catches it at authoring time instead.\n *\n * Compiled against the sibling `flags` because flags decide validity (`\\p{Foo}` is a literal\n * without `u` and a syntax error with it). Invalid flags are ignored here and left to\n * `validateRegexFlags`, so a flag typo reports once, on the field that owns it.\n * Exported for unit testing.\n */\nexport const validateRegexPattern = (\n\tvalue: unknown,\n\t{ req, siblingData }: { req: PayloadRequest; siblingData?: unknown }\n): string | true => {\n\tif (typeof value !== 'string' || value === '') {\n\t\treturn true\n\t}\n\tconst flags = flagsOf(siblingData)\n\tconst effectiveFlags = flags && tryCompile('', flags) ? flags : undefined\n\treturn tryCompile(value, effectiveFlags) ? true : asTranslate(req.t)(keys.validationRegexPattern)\n}\n"],"mappings":";;;;AAKA,MAAM,cAAc,SAAiB,UAAuC;CAC3E,IAAI;EACH,OAAO,IAAI,OAAO,SAAS,KAAK;CACjC,QAAQ;EACP;CACD;AACD;AAEA,MAAM,WAAW,gBAA6C;CAC7D,MAAM,QAAS,aAAiD;CAChE,OAAO,OAAO,UAAU,YAAY,UAAU,KAAK,QAAQ,KAAA;AAC5D;;;;;;;AAQA,MAAa,sBACZ,OACA,EAAE,UACiB;CACnB,IAAI,OAAO,UAAU,YAAY,UAAU,IAC1C,OAAO;CAER,OAAO,WAAW,IAAI,KAAK,IAAI,OAAO,YAAY,IAAI,CAAC,EAAE,KAAK,oBAAoB;AACnF;;;;;;;;;;;AAYA,MAAa,wBACZ,OACA,EAAE,KAAK,kBACY;CACnB,IAAI,OAAO,UAAU,YAAY,UAAU,IAC1C,OAAO;CAER,MAAM,QAAQ,QAAQ,WAAW;CAEjC,OAAO,WAAW,OADK,SAAS,WAAW,IAAI,KAAK,IAAI,QAAQ,KAAA,CACzB,IAAI,OAAO,YAAY,IAAI,CAAC,EAAE,KAAK,sBAAsB;AACjG"}
@@ -0,0 +1,22 @@
1
+ import { TranslationKey } from "../translations/keys.js";
2
+ import { Field } from "payload";
3
+
4
+ //#region src/validation/fieldTargetParam.d.ts
5
+ type FieldTargetParamOptions = {
6
+ /** Field label; defaults to the shared `Field name` key. */label?: TranslationKey; /** Whether a target must be chosen; defaults to `true`. */
7
+ required?: boolean; /** Restrict the picker (and the save-time check) to these field-type slugs; omit for every field. */
8
+ types?: string[]; /** Optional description shown under the picker, resolved client-side from this key. */
9
+ description?: TranslationKey;
10
+ };
11
+ /**
12
+ * A rule/action param that targets another field on the same form by name. Stores the field name as a
13
+ * plain text value (no data migration), but authors it with the `FieldNameSelect` picker and enforces
14
+ * a save-time existence check so a name that no longer resolves (typically because the field was
15
+ * removed) is a save error rather than a silently dead reference. The picker options and this check
16
+ * read the same name set from `fieldNamesOfType`/`fieldNames`, so they cannot drift. Reusable by
17
+ * custom rules via the package's public export.
18
+ */
19
+ declare const fieldTargetParam: (name: string, opts?: FieldTargetParamOptions) => Field;
20
+ //#endregion
21
+ export { FieldTargetParamOptions, fieldTargetParam };
22
+ //# sourceMappingURL=fieldTargetParam.d.ts.map
@@ -0,0 +1,38 @@
1
+ import { fieldNames, fieldNamesOfType } from "../fields/fieldNamesOfType.js";
2
+ import { keys } from "../translations/keys.js";
3
+ import { asTranslate, labelFor } from "../translations/server.js";
4
+ //#region src/validation/fieldTargetParam.ts
5
+ const FIELD_NAME_SELECT_REF = "@10x-media/form-builder/client#FieldNameSelect";
6
+ /**
7
+ * A rule/action param that targets another field on the same form by name. Stores the field name as a
8
+ * plain text value (no data migration), but authors it with the `FieldNameSelect` picker and enforces
9
+ * a save-time existence check so a name that no longer resolves (typically because the field was
10
+ * removed) is a save error rather than a silently dead reference. The picker options and this check
11
+ * read the same name set from `fieldNamesOfType`/`fieldNames`, so they cannot drift. Reusable by
12
+ * custom rules via the package's public export.
13
+ */
14
+ const fieldTargetParam = (name, opts) => {
15
+ const types = opts?.types;
16
+ return {
17
+ name,
18
+ type: "text",
19
+ required: opts?.required ?? true,
20
+ label: labelFor(opts?.label ?? keys.ruleParamField),
21
+ admin: { components: { Field: {
22
+ path: FIELD_NAME_SELECT_REF,
23
+ clientProps: {
24
+ types,
25
+ ...opts?.description ? { descriptionKey: opts.description } : {}
26
+ }
27
+ } } },
28
+ validate: (value, { data, req }) => {
29
+ if (typeof value !== "string" || value.length === 0) return true;
30
+ const fields = data && typeof data === "object" ? data.fields : void 0;
31
+ return (types ? fieldNamesOfType(fields, types) : fieldNames(fields)).includes(value) ? true : asTranslate(req.t)(keys.ruleFieldTargetInvalid);
32
+ }
33
+ };
34
+ };
35
+ //#endregion
36
+ export { fieldTargetParam };
37
+
38
+ //# sourceMappingURL=fieldTargetParam.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fieldTargetParam.js","names":[],"sources":["../../src/validation/fieldTargetParam.ts"],"sourcesContent":["import type { Field, PayloadRequest } from 'payload'\nimport { fieldNames, fieldNamesOfType } from '../fields/fieldNamesOfType'\nimport { keys, type TranslationKey } from '../translations/keys'\nimport { asTranslate, labelFor } from '../translations/server'\n\nconst FIELD_NAME_SELECT_REF = '@10x-media/form-builder/client#FieldNameSelect'\n\nexport type FieldTargetParamOptions = {\n\t/** Field label; defaults to the shared `Field name` key. */\n\tlabel?: TranslationKey\n\t/** Whether a target must be chosen; defaults to `true`. */\n\trequired?: boolean\n\t/** Restrict the picker (and the save-time check) to these field-type slugs; omit for every field. */\n\ttypes?: string[]\n\t/** Optional description shown under the picker, resolved client-side from this key. */\n\tdescription?: TranslationKey\n}\n\n/**\n * A rule/action param that targets another field on the same form by name. Stores the field name as a\n * plain text value (no data migration), but authors it with the `FieldNameSelect` picker and enforces\n * a save-time existence check so a name that no longer resolves (typically because the field was\n * removed) is a save error rather than a silently dead reference. The picker options and this check\n * read the same name set from `fieldNamesOfType`/`fieldNames`, so they cannot drift. Reusable by\n * custom rules via the package's public export.\n */\nexport const fieldTargetParam = (name: string, opts?: FieldTargetParamOptions): Field => {\n\tconst types = opts?.types\n\treturn {\n\t\tname,\n\t\ttype: 'text',\n\t\trequired: opts?.required ?? true,\n\t\tlabel: labelFor(opts?.label ?? keys.ruleParamField),\n\t\tadmin: {\n\t\t\tcomponents: {\n\t\t\t\tField: {\n\t\t\t\t\tpath: FIELD_NAME_SELECT_REF,\n\t\t\t\t\tclientProps: {\n\t\t\t\t\t\ttypes,\n\t\t\t\t\t\t...(opts?.description ? { descriptionKey: opts.description } : {}),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tvalidate: (value: unknown, { data, req }: { data?: unknown; req: PayloadRequest }) => {\n\t\t\tif (typeof value !== 'string' || value.length === 0) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tconst fields =\n\t\t\t\tdata && typeof data === 'object' ? (data as Record<string, unknown>).fields : undefined\n\t\t\tconst names = types ? fieldNamesOfType(fields, types) : fieldNames(fields)\n\t\t\treturn names.includes(value) ? true : asTranslate(req.t)(keys.ruleFieldTargetInvalid)\n\t\t},\n\t}\n}\n"],"mappings":";;;;AAKA,MAAM,wBAAwB;;;;;;;;;AAqB9B,MAAa,oBAAoB,MAAc,SAA0C;CACxF,MAAM,QAAQ,MAAM;CACpB,OAAO;EACN;EACA,MAAM;EACN,UAAU,MAAM,YAAY;EAC5B,OAAO,SAAS,MAAM,SAAS,KAAK,cAAc;EAClD,OAAO,EACN,YAAY,EACX,OAAO;GACN,MAAM;GACN,aAAa;IACZ;IACA,GAAI,MAAM,cAAc,EAAE,gBAAgB,KAAK,YAAY,IAAI,CAAC;GACjE;EACD,EACD,EACD;EACA,WAAW,OAAgB,EAAE,MAAM,UAAmD;GACrF,IAAI,OAAO,UAAU,YAAY,MAAM,WAAW,GACjD,OAAO;GAER,MAAM,SACL,QAAQ,OAAO,SAAS,WAAY,KAAiC,SAAS,KAAA;GAE/E,QADc,QAAQ,iBAAiB,QAAQ,KAAK,IAAI,WAAW,MAAM,GAC5D,SAAS,KAAK,IAAI,OAAO,YAAY,IAAI,CAAC,EAAE,KAAK,sBAAsB;EACrF;CACD;AACD"}
@@ -5,39 +5,25 @@ const RULE_TIMEOUT_MS = 5e3;
5
5
  const isEmpty = (value) => value == null || value === "" || Array.isArray(value) && value.length === 0;
6
6
  /** Build the per-instance message resolver: custom override (a literal template) or the localized default. */
7
7
  const makeMessage = (instance, defaultMessageKey, t) => {
8
- const { blockType: _blockType, message: _message, severity: _severity, ...params } = instance;
8
+ const { blockType: _blockType, message: _message, ...params } = instance;
9
9
  const template = typeof instance.message === "string" && instance.message.length > 0 ? instance.message : t(defaultMessageKey);
10
10
  return (vars = {}) => resolveMessage(template, {
11
11
  ...params,
12
12
  ...vars
13
13
  });
14
14
  };
15
- const toIssue = (result, fallbackSeverity) => {
16
- if (result === true) return null;
17
- if (typeof result === "string") return {
18
- message: result,
19
- severity: fallbackSeverity
20
- };
21
- return {
22
- message: result.message,
23
- severity: result.severity ?? fallbackSeverity
24
- };
25
- };
26
15
  /**
27
16
  * The one validation engine, run per field on client and server. Order: required, the field type's
28
17
  * intrinsic validator, then each declarative rule instance. Server-only rules are skipped in client
29
18
  * mode; every rule is wrapped in try/catch + a timeout so a bad rule cannot crash or stall the submit
30
- * path (a thrown or timed-out rule fails open, logged on the server). Only `error`-severity issues
31
- * block submission; the caller filters severity.
19
+ * path (a thrown or timed-out rule fails open, logged on the server). Every returned message is a
20
+ * blocking error.
32
21
  */
33
22
  const runValidation = async (input) => {
34
23
  const { field, fieldDefinition, value, fieldType, ruleRegistry, answers, locale, t, operation, event, mode, req, payload, formId, timeoutMs } = input;
35
24
  const timeout = timeoutMs ?? RULE_TIMEOUT_MS;
36
25
  const errors = [];
37
- if (field.required && isEmpty(value)) return { errors: [{
38
- message: t(keys.validationRequired),
39
- severity: "error"
40
- }] };
26
+ if (field.required && isEmpty(value)) return { errors: [t(keys.validationRequired)] };
41
27
  if (isEmpty(value) && field.blockType !== "repeater") return { errors: [] };
42
28
  if (fieldDefinition?.validate) try {
43
29
  const ran = fieldDefinition.validate({
@@ -49,10 +35,7 @@ const runValidation = async (input) => {
49
35
  t
50
36
  });
51
37
  const result = ran instanceof Promise ? await withTimeout(ran, timeout, true) : ran;
52
- if (result !== true) errors.push({
53
- message: result,
54
- severity: "error"
55
- });
38
+ if (result !== true) errors.push(result);
56
39
  } catch (error) {
57
40
  req?.payload?.logger?.error?.({
58
41
  err: error,
@@ -61,10 +44,7 @@ const runValidation = async (input) => {
61
44
  }
62
45
  if (fieldDefinition?.schema) try {
63
46
  const outcome = await fieldDefinition.schema["~standard"].validate(value);
64
- if (outcome.issues) for (const issue of outcome.issues) errors.push({
65
- message: issue.message,
66
- severity: "error"
67
- });
47
+ if (outcome.issues) for (const issue of outcome.issues) errors.push(issue.message);
68
48
  } catch (error) {
69
49
  req?.payload?.logger?.error?.({
70
50
  err: error,
@@ -77,7 +57,6 @@ const runValidation = async (input) => {
77
57
  if (!rule) continue;
78
58
  if (mode === "client" && rule.client === false) continue;
79
59
  const message = makeMessage(instance, rule.defaultMessage, t);
80
- const fallbackSeverity = instance.severity ?? rule.severity ?? "error";
81
60
  try {
82
61
  const ran = rule.validate({
83
62
  value,
@@ -94,8 +73,8 @@ const runValidation = async (input) => {
94
73
  payload: mode === "server" ? payload : void 0,
95
74
  formId: mode === "server" ? formId : void 0
96
75
  });
97
- const issue = toIssue(ran instanceof Promise ? await withTimeout(ran, timeout, true) : ran, fallbackSeverity);
98
- if (issue) errors.push(issue);
76
+ const result = ran instanceof Promise ? await withTimeout(ran, timeout, true) : ran;
77
+ if (result !== true) errors.push(result);
99
78
  } catch (error) {
100
79
  req?.payload?.logger?.error?.({
101
80
  err: error,
@@ -1 +1 @@
1
- {"version":3,"file":"runValidation.js","names":[],"sources":["../../src/validation/runValidation.ts"],"sourcesContent":["import type { Payload, PayloadRequest } from 'payload'\nimport type { AnyFormFieldDefinition, Translate } from '../fields/types'\nimport type { FormFieldInstance } from '../submissions/types'\nimport { keys } from '../translations/keys'\nimport { resolveMessage, withTimeout } from './message'\nimport type { ValidationRuleRegistry } from './registry'\nimport type { MessageFn, ValidationRuleResult, ValidationSeverity } from './types'\n\nconst RULE_TIMEOUT_MS = 5000\n\nexport type ValidationIssue = { message: string; severity: ValidationSeverity }\n\nexport type RunValidationInput = {\n\tfield: FormFieldInstance\n\tfieldDefinition?: AnyFormFieldDefinition\n\tvalue: unknown\n\tfieldType: string\n\truleRegistry: ValidationRuleRegistry\n\tanswers: Record<string, unknown>\n\tlocale: string\n\tt: Translate\n\toperation: 'create' | 'update'\n\tevent: 'onChange' | 'submit'\n\tmode: 'client' | 'server'\n\treq?: PayloadRequest\n\tpayload?: Payload\n\tformId?: number | string\n\t/** Override the per-rule timeout in ms. Defaults to RULE_TIMEOUT_MS; primarily for tests. */\n\ttimeoutMs?: number\n}\n\nexport type RunValidationResult = { errors: ValidationIssue[] }\n\nconst isEmpty = (value: unknown): boolean =>\n\tvalue == null || value === '' || (Array.isArray(value) && value.length === 0)\n\ntype RuleInstance = { blockType: string; message?: string; severity?: ValidationSeverity } & Record<\n\tstring,\n\tunknown\n>\n\n/** Build the per-instance message resolver: custom override (a literal template) or the localized default. */\nconst makeMessage = (\n\tinstance: RuleInstance,\n\tdefaultMessageKey: string,\n\tt: Translate\n): MessageFn => {\n\tconst { blockType: _blockType, message: _message, severity: _severity, ...params } = instance\n\tconst template =\n\t\ttypeof instance.message === 'string' && instance.message.length > 0\n\t\t\t? instance.message\n\t\t\t: t(defaultMessageKey)\n\treturn (vars = {}) => resolveMessage(template, { ...params, ...vars })\n}\n\nconst toIssue = (\n\tresult: ValidationRuleResult,\n\tfallbackSeverity: ValidationSeverity\n): ValidationIssue | null => {\n\tif (result === true) {\n\t\treturn null\n\t}\n\tif (typeof result === 'string') {\n\t\treturn { message: result, severity: fallbackSeverity }\n\t}\n\treturn { message: result.message, severity: result.severity ?? fallbackSeverity }\n}\n\n/**\n * The one validation engine, run per field on client and server. Order: required, the field type's\n * intrinsic validator, then each declarative rule instance. Server-only rules are skipped in client\n * mode; every rule is wrapped in try/catch + a timeout so a bad rule cannot crash or stall the submit\n * path (a thrown or timed-out rule fails open, logged on the server). Only `error`-severity issues\n * block submission; the caller filters severity.\n */\nexport const runValidation = async (input: RunValidationInput): Promise<RunValidationResult> => {\n\tconst {\n\t\tfield,\n\t\tfieldDefinition,\n\t\tvalue,\n\t\tfieldType,\n\t\truleRegistry,\n\t\tanswers,\n\t\tlocale,\n\t\tt,\n\t\toperation,\n\t\tevent,\n\t\tmode,\n\t\treq,\n\t\tpayload,\n\t\tformId,\n\t\ttimeoutMs,\n\t} = input\n\tconst timeout = timeoutMs ?? RULE_TIMEOUT_MS\n\tconst errors: ValidationIssue[] = []\n\n\tif (field.required && isEmpty(value)) {\n\t\treturn { errors: [{ message: t(keys.validationRequired), severity: 'error' }] }\n\t}\n\t// Repeaters coerced to [] must reach fieldDefinition.validate so minRows is enforced;\n\t// all other empty fields have no intrinsic rules to run.\n\tif (isEmpty(value) && field.blockType !== 'repeater') {\n\t\treturn { errors: [] }\n\t}\n\n\tif (fieldDefinition?.validate) {\n\t\ttry {\n\t\t\tconst ran = fieldDefinition.validate({\n\t\t\t\tvalue,\n\t\t\t\tconfig: field,\n\t\t\t\tsiblingData: answers,\n\t\t\t\tdata: answers,\n\t\t\t\tlocale,\n\t\t\t\tt,\n\t\t\t})\n\t\t\tconst result = ran instanceof Promise ? await withTimeout(ran, timeout, true) : ran\n\t\t\tif (result !== true) {\n\t\t\t\terrors.push({ message: result, severity: 'error' })\n\t\t\t}\n\t\t} catch (error) {\n\t\t\treq?.payload?.logger?.error?.(\n\t\t\t\t{ err: error, field: field.name },\n\t\t\t\t'form-builder intrinsic field validator threw'\n\t\t\t)\n\t\t}\n\t}\n\n\tif (fieldDefinition?.schema) {\n\t\ttry {\n\t\t\tconst outcome = await fieldDefinition.schema['~standard'].validate(value)\n\t\t\tif (outcome.issues) {\n\t\t\t\tfor (const issue of outcome.issues) {\n\t\t\t\t\terrors.push({ message: issue.message, severity: 'error' })\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\treq?.payload?.logger?.error?.(\n\t\t\t\t{ err: error, field: field.name },\n\t\t\t\t'form-builder field schema threw'\n\t\t\t)\n\t\t}\n\t}\n\n\tconst instances = (Array.isArray(field.validations) ? field.validations : []) as RuleInstance[]\n\tfor (const instance of instances) {\n\t\tconst rule = ruleRegistry.get(instance.blockType)\n\t\tif (!rule) {\n\t\t\tcontinue\n\t\t}\n\t\tif (mode === 'client' && rule.client === false) {\n\t\t\tcontinue\n\t\t}\n\t\tconst message = makeMessage(instance, rule.defaultMessage, t)\n\t\tconst fallbackSeverity: ValidationSeverity = instance.severity ?? rule.severity ?? 'error'\n\t\ttry {\n\t\t\tconst ran = rule.validate({\n\t\t\t\tvalue,\n\t\t\t\tparams: instance,\n\t\t\t\tsiblingData: answers,\n\t\t\t\tdata: answers,\n\t\t\t\tfield,\n\t\t\t\tfieldType,\n\t\t\t\toperation,\n\t\t\t\tevent,\n\t\t\t\tlocale,\n\t\t\t\tmessage,\n\t\t\t\treq: mode === 'server' ? req : undefined,\n\t\t\t\tpayload: mode === 'server' ? payload : undefined,\n\t\t\t\tformId: mode === 'server' ? formId : undefined,\n\t\t\t})\n\t\t\tconst result = ran instanceof Promise ? await withTimeout(ran, timeout, true) : ran\n\t\t\tconst issue = toIssue(result, fallbackSeverity)\n\t\t\tif (issue) {\n\t\t\t\terrors.push(issue)\n\t\t\t}\n\t\t} catch (error) {\n\t\t\treq?.payload?.logger?.error?.(\n\t\t\t\t{ err: error, rule: rule.type },\n\t\t\t\t'form-builder validation rule threw'\n\t\t\t)\n\t\t}\n\t}\n\n\treturn { errors }\n}\n"],"mappings":";;;AAQA,MAAM,kBAAkB;AAyBxB,MAAM,WAAW,UAChB,SAAS,QAAQ,UAAU,MAAO,MAAM,QAAQ,KAAK,KAAK,MAAM,WAAW;;AAQ5E,MAAM,eACL,UACA,mBACA,MACe;CACf,MAAM,EAAE,WAAW,YAAY,SAAS,UAAU,UAAU,WAAW,GAAG,WAAW;CACrF,MAAM,WACL,OAAO,SAAS,YAAY,YAAY,SAAS,QAAQ,SAAS,IAC/D,SAAS,UACT,EAAE,iBAAiB;CACvB,QAAQ,OAAO,CAAC,MAAM,eAAe,UAAU;EAAE,GAAG;EAAQ,GAAG;CAAK,CAAC;AACtE;AAEA,MAAM,WACL,QACA,qBAC4B;CAC5B,IAAI,WAAW,MACd,OAAO;CAER,IAAI,OAAO,WAAW,UACrB,OAAO;EAAE,SAAS;EAAQ,UAAU;CAAiB;CAEtD,OAAO;EAAE,SAAS,OAAO;EAAS,UAAU,OAAO,YAAY;CAAiB;AACjF;;;;;;;;AASA,MAAa,gBAAgB,OAAO,UAA4D;CAC/F,MAAM,EACL,OACA,iBACA,OACA,WACA,cACA,SACA,QACA,GACA,WACA,OACA,MACA,KACA,SACA,QACA,cACG;CACJ,MAAM,UAAU,aAAa;CAC7B,MAAM,SAA4B,CAAC;CAEnC,IAAI,MAAM,YAAY,QAAQ,KAAK,GAClC,OAAO,EAAE,QAAQ,CAAC;EAAE,SAAS,EAAE,KAAK,kBAAkB;EAAG,UAAU;CAAQ,CAAC,EAAE;CAI/E,IAAI,QAAQ,KAAK,KAAK,MAAM,cAAc,YACzC,OAAO,EAAE,QAAQ,CAAC,EAAE;CAGrB,IAAI,iBAAiB,UACpB,IAAI;EACH,MAAM,MAAM,gBAAgB,SAAS;GACpC;GACA,QAAQ;GACR,aAAa;GACb,MAAM;GACN;GACA;EACD,CAAC;EACD,MAAM,SAAS,eAAe,UAAU,MAAM,YAAY,KAAK,SAAS,IAAI,IAAI;EAChF,IAAI,WAAW,MACd,OAAO,KAAK;GAAE,SAAS;GAAQ,UAAU;EAAQ,CAAC;CAEpD,SAAS,OAAO;EACf,KAAK,SAAS,QAAQ,QACrB;GAAE,KAAK;GAAO,OAAO,MAAM;EAAK,GAChC,8CACD;CACD;CAGD,IAAI,iBAAiB,QACpB,IAAI;EACH,MAAM,UAAU,MAAM,gBAAgB,OAAO,aAAa,SAAS,KAAK;EACxE,IAAI,QAAQ,QACX,KAAK,MAAM,SAAS,QAAQ,QAC3B,OAAO,KAAK;GAAE,SAAS,MAAM;GAAS,UAAU;EAAQ,CAAC;CAG5D,SAAS,OAAO;EACf,KAAK,SAAS,QAAQ,QACrB;GAAE,KAAK;GAAO,OAAO,MAAM;EAAK,GAChC,iCACD;CACD;CAGD,MAAM,YAAa,MAAM,QAAQ,MAAM,WAAW,IAAI,MAAM,cAAc,CAAC;CAC3E,KAAK,MAAM,YAAY,WAAW;EACjC,MAAM,OAAO,aAAa,IAAI,SAAS,SAAS;EAChD,IAAI,CAAC,MACJ;EAED,IAAI,SAAS,YAAY,KAAK,WAAW,OACxC;EAED,MAAM,UAAU,YAAY,UAAU,KAAK,gBAAgB,CAAC;EAC5D,MAAM,mBAAuC,SAAS,YAAY,KAAK,YAAY;EACnF,IAAI;GACH,MAAM,MAAM,KAAK,SAAS;IACzB;IACA,QAAQ;IACR,aAAa;IACb,MAAM;IACN;IACA;IACA;IACA;IACA;IACA;IACA,KAAK,SAAS,WAAW,MAAM,KAAA;IAC/B,SAAS,SAAS,WAAW,UAAU,KAAA;IACvC,QAAQ,SAAS,WAAW,SAAS,KAAA;GACtC,CAAC;GAED,MAAM,QAAQ,QADC,eAAe,UAAU,MAAM,YAAY,KAAK,SAAS,IAAI,IAAI,KAClD,gBAAgB;GAC9C,IAAI,OACH,OAAO,KAAK,KAAK;EAEnB,SAAS,OAAO;GACf,KAAK,SAAS,QAAQ,QACrB;IAAE,KAAK;IAAO,MAAM,KAAK;GAAK,GAC9B,oCACD;EACD;CACD;CAEA,OAAO,EAAE,OAAO;AACjB"}
1
+ {"version":3,"file":"runValidation.js","names":[],"sources":["../../src/validation/runValidation.ts"],"sourcesContent":["import type { Payload, PayloadRequest } from 'payload'\nimport type { AnyFormFieldDefinition, Translate } from '../fields/types'\nimport type { FormFieldInstance } from '../submissions/types'\nimport { keys } from '../translations/keys'\nimport { resolveMessage, withTimeout } from './message'\nimport type { ValidationRuleRegistry } from './registry'\nimport type { MessageFn } from './types'\n\nconst RULE_TIMEOUT_MS = 5000\n\nexport type RunValidationInput = {\n\tfield: FormFieldInstance\n\tfieldDefinition?: AnyFormFieldDefinition\n\tvalue: unknown\n\tfieldType: string\n\truleRegistry: ValidationRuleRegistry\n\tanswers: Record<string, unknown>\n\tlocale: string\n\tt: Translate\n\toperation: 'create' | 'update'\n\tevent: 'onChange' | 'submit'\n\tmode: 'client' | 'server'\n\treq?: PayloadRequest\n\tpayload?: Payload\n\tformId?: number | string\n\t/** Override the per-rule timeout in ms. Defaults to RULE_TIMEOUT_MS; primarily for tests. */\n\ttimeoutMs?: number\n}\n\nexport type RunValidationResult = { errors: string[] }\n\nconst isEmpty = (value: unknown): boolean =>\n\tvalue == null || value === '' || (Array.isArray(value) && value.length === 0)\n\ntype RuleInstance = { blockType: string; message?: string } & Record<string, unknown>\n\n/** Build the per-instance message resolver: custom override (a literal template) or the localized default. */\nconst makeMessage = (\n\tinstance: RuleInstance,\n\tdefaultMessageKey: string,\n\tt: Translate\n): MessageFn => {\n\tconst { blockType: _blockType, message: _message, ...params } = instance\n\tconst template =\n\t\ttypeof instance.message === 'string' && instance.message.length > 0\n\t\t\t? instance.message\n\t\t\t: t(defaultMessageKey)\n\treturn (vars = {}) => resolveMessage(template, { ...params, ...vars })\n}\n\n/**\n * The one validation engine, run per field on client and server. Order: required, the field type's\n * intrinsic validator, then each declarative rule instance. Server-only rules are skipped in client\n * mode; every rule is wrapped in try/catch + a timeout so a bad rule cannot crash or stall the submit\n * path (a thrown or timed-out rule fails open, logged on the server). Every returned message is a\n * blocking error.\n */\nexport const runValidation = async (input: RunValidationInput): Promise<RunValidationResult> => {\n\tconst {\n\t\tfield,\n\t\tfieldDefinition,\n\t\tvalue,\n\t\tfieldType,\n\t\truleRegistry,\n\t\tanswers,\n\t\tlocale,\n\t\tt,\n\t\toperation,\n\t\tevent,\n\t\tmode,\n\t\treq,\n\t\tpayload,\n\t\tformId,\n\t\ttimeoutMs,\n\t} = input\n\tconst timeout = timeoutMs ?? RULE_TIMEOUT_MS\n\tconst errors: string[] = []\n\n\tif (field.required && isEmpty(value)) {\n\t\treturn { errors: [t(keys.validationRequired)] }\n\t}\n\t// Repeaters coerced to [] must reach fieldDefinition.validate so minRows is enforced;\n\t// all other empty fields have no intrinsic rules to run.\n\tif (isEmpty(value) && field.blockType !== 'repeater') {\n\t\treturn { errors: [] }\n\t}\n\n\tif (fieldDefinition?.validate) {\n\t\ttry {\n\t\t\tconst ran = fieldDefinition.validate({\n\t\t\t\tvalue,\n\t\t\t\tconfig: field,\n\t\t\t\tsiblingData: answers,\n\t\t\t\tdata: answers,\n\t\t\t\tlocale,\n\t\t\t\tt,\n\t\t\t})\n\t\t\tconst result = ran instanceof Promise ? await withTimeout(ran, timeout, true) : ran\n\t\t\tif (result !== true) {\n\t\t\t\terrors.push(result)\n\t\t\t}\n\t\t} catch (error) {\n\t\t\treq?.payload?.logger?.error?.(\n\t\t\t\t{ err: error, field: field.name },\n\t\t\t\t'form-builder intrinsic field validator threw'\n\t\t\t)\n\t\t}\n\t}\n\n\tif (fieldDefinition?.schema) {\n\t\ttry {\n\t\t\tconst outcome = await fieldDefinition.schema['~standard'].validate(value)\n\t\t\tif (outcome.issues) {\n\t\t\t\tfor (const issue of outcome.issues) {\n\t\t\t\t\terrors.push(issue.message)\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\treq?.payload?.logger?.error?.(\n\t\t\t\t{ err: error, field: field.name },\n\t\t\t\t'form-builder field schema threw'\n\t\t\t)\n\t\t}\n\t}\n\n\tconst instances = (Array.isArray(field.validations) ? field.validations : []) as RuleInstance[]\n\tfor (const instance of instances) {\n\t\tconst rule = ruleRegistry.get(instance.blockType)\n\t\tif (!rule) {\n\t\t\tcontinue\n\t\t}\n\t\tif (mode === 'client' && rule.client === false) {\n\t\t\tcontinue\n\t\t}\n\t\tconst message = makeMessage(instance, rule.defaultMessage, t)\n\t\ttry {\n\t\t\tconst ran = rule.validate({\n\t\t\t\tvalue,\n\t\t\t\tparams: instance,\n\t\t\t\tsiblingData: answers,\n\t\t\t\tdata: answers,\n\t\t\t\tfield,\n\t\t\t\tfieldType,\n\t\t\t\toperation,\n\t\t\t\tevent,\n\t\t\t\tlocale,\n\t\t\t\tmessage,\n\t\t\t\treq: mode === 'server' ? req : undefined,\n\t\t\t\tpayload: mode === 'server' ? payload : undefined,\n\t\t\t\tformId: mode === 'server' ? formId : undefined,\n\t\t\t})\n\t\t\tconst result = ran instanceof Promise ? await withTimeout(ran, timeout, true) : ran\n\t\t\tif (result !== true) {\n\t\t\t\terrors.push(result)\n\t\t\t}\n\t\t} catch (error) {\n\t\t\treq?.payload?.logger?.error?.(\n\t\t\t\t{ err: error, rule: rule.type },\n\t\t\t\t'form-builder validation rule threw'\n\t\t\t)\n\t\t}\n\t}\n\n\treturn { errors }\n}\n"],"mappings":";;;AAQA,MAAM,kBAAkB;AAuBxB,MAAM,WAAW,UAChB,SAAS,QAAQ,UAAU,MAAO,MAAM,QAAQ,KAAK,KAAK,MAAM,WAAW;;AAK5E,MAAM,eACL,UACA,mBACA,MACe;CACf,MAAM,EAAE,WAAW,YAAY,SAAS,UAAU,GAAG,WAAW;CAChE,MAAM,WACL,OAAO,SAAS,YAAY,YAAY,SAAS,QAAQ,SAAS,IAC/D,SAAS,UACT,EAAE,iBAAiB;CACvB,QAAQ,OAAO,CAAC,MAAM,eAAe,UAAU;EAAE,GAAG;EAAQ,GAAG;CAAK,CAAC;AACtE;;;;;;;;AASA,MAAa,gBAAgB,OAAO,UAA4D;CAC/F,MAAM,EACL,OACA,iBACA,OACA,WACA,cACA,SACA,QACA,GACA,WACA,OACA,MACA,KACA,SACA,QACA,cACG;CACJ,MAAM,UAAU,aAAa;CAC7B,MAAM,SAAmB,CAAC;CAE1B,IAAI,MAAM,YAAY,QAAQ,KAAK,GAClC,OAAO,EAAE,QAAQ,CAAC,EAAE,KAAK,kBAAkB,CAAC,EAAE;CAI/C,IAAI,QAAQ,KAAK,KAAK,MAAM,cAAc,YACzC,OAAO,EAAE,QAAQ,CAAC,EAAE;CAGrB,IAAI,iBAAiB,UACpB,IAAI;EACH,MAAM,MAAM,gBAAgB,SAAS;GACpC;GACA,QAAQ;GACR,aAAa;GACb,MAAM;GACN;GACA;EACD,CAAC;EACD,MAAM,SAAS,eAAe,UAAU,MAAM,YAAY,KAAK,SAAS,IAAI,IAAI;EAChF,IAAI,WAAW,MACd,OAAO,KAAK,MAAM;CAEpB,SAAS,OAAO;EACf,KAAK,SAAS,QAAQ,QACrB;GAAE,KAAK;GAAO,OAAO,MAAM;EAAK,GAChC,8CACD;CACD;CAGD,IAAI,iBAAiB,QACpB,IAAI;EACH,MAAM,UAAU,MAAM,gBAAgB,OAAO,aAAa,SAAS,KAAK;EACxE,IAAI,QAAQ,QACX,KAAK,MAAM,SAAS,QAAQ,QAC3B,OAAO,KAAK,MAAM,OAAO;CAG5B,SAAS,OAAO;EACf,KAAK,SAAS,QAAQ,QACrB;GAAE,KAAK;GAAO,OAAO,MAAM;EAAK,GAChC,iCACD;CACD;CAGD,MAAM,YAAa,MAAM,QAAQ,MAAM,WAAW,IAAI,MAAM,cAAc,CAAC;CAC3E,KAAK,MAAM,YAAY,WAAW;EACjC,MAAM,OAAO,aAAa,IAAI,SAAS,SAAS;EAChD,IAAI,CAAC,MACJ;EAED,IAAI,SAAS,YAAY,KAAK,WAAW,OACxC;EAED,MAAM,UAAU,YAAY,UAAU,KAAK,gBAAgB,CAAC;EAC5D,IAAI;GACH,MAAM,MAAM,KAAK,SAAS;IACzB;IACA,QAAQ;IACR,aAAa;IACb,MAAM;IACN;IACA;IACA;IACA;IACA;IACA;IACA,KAAK,SAAS,WAAW,MAAM,KAAA;IAC/B,SAAS,SAAS,WAAW,UAAU,KAAA;IACvC,QAAQ,SAAS,WAAW,SAAS,KAAA;GACtC,CAAC;GACD,MAAM,SAAS,eAAe,UAAU,MAAM,YAAY,KAAK,SAAS,IAAI,IAAI;GAChF,IAAI,WAAW,MACd,OAAO,KAAK,MAAM;EAEpB,SAAS,OAAO;GACf,KAAK,SAAS,QAAQ,QACrB;IAAE,KAAK;IAAO,MAAM,KAAK;GAAK,GAC9B,oCACD;EACD;CACD;CAEA,OAAO,EAAE,OAAO;AACjB"}
@@ -2,12 +2,8 @@ import { FormFieldInstance } from "../submissions/types.js";
2
2
  import { Field, Payload, PayloadRequest } from "payload";
3
3
 
4
4
  //#region src/validation/types.d.ts
5
- type ValidationSeverity = 'error' | 'warning';
6
- /** A rule outcome: pass, a plain error string, or an explicit message + severity. */
7
- type ValidationRuleResult = true | string | {
8
- message: string;
9
- severity?: ValidationSeverity;
10
- };
5
+ /** A rule outcome: pass (`true`) or a blocking error message. */
6
+ type ValidationRuleResult = true | string;
11
7
  /** Resolves this rule instance's message (custom override or localized default) with `{var}` interpolation. */
12
8
  type MessageFn = (vars?: Record<string, unknown>) => string;
13
9
  /** Resolved per-instance rule params (loose at the DB boundary, narrowed by the author's generic). */
@@ -30,7 +26,7 @@ type ValidationRuleValidateArgs<TParams extends ValidationParams, TValue, TData
30
26
  type ValidationRuleValidate<TParams extends ValidationParams, TValue, TData extends Record<string, unknown> = Record<string, unknown>> = (args: ValidationRuleValidateArgs<TParams, TValue, TData>) => Promise<ValidationRuleResult> | ValidationRuleResult;
31
27
  /**
32
28
  * A validation rule type, authored once. `params` is a Payload `Field[]` rendered in the per-field
33
- * constraint list; `validate` returns `true | string | { message, severity }`. `client` defaults from
29
+ * constraint list; `validate` returns `true | string`. `client` defaults from
34
30
  * whether the rule is pure (a rule that is async or uses `req`/`payload` must set `client: false`).
35
31
  */
36
32
  type ValidationRuleDefinition<TParams extends ValidationParams = ValidationParams, TValue = unknown, TData extends Record<string, unknown> = Record<string, unknown>> = {
@@ -40,8 +36,7 @@ type ValidationRuleDefinition<TParams extends ValidationParams = ValidationParam
40
36
  appliesTo?: string[];
41
37
  params?: Field[];
42
38
  defaultMessage: string; /** Runs client-side too. Defaults to `true`; set `false` for async or `req`/`payload`-using rules. */
43
- client?: boolean; /** Default severity when `validate` returns a bare string. Defaults to `error`. */
44
- severity?: ValidationSeverity;
39
+ client?: boolean;
45
40
  validate: ValidationRuleValidate<TParams, TValue, TData>;
46
41
  };
47
42
  /** Erased shape stored in the heterogeneous registry; params re-narrow per matched rule at execution. */
@@ -68,9 +63,8 @@ type AnyValidationRuleDefinition = {
68
63
  params?: Field[];
69
64
  defaultMessage: string;
70
65
  client?: boolean;
71
- severity?: ValidationSeverity;
72
66
  validate: AnyValidationRuleValidate;
73
67
  };
74
68
  //#endregion
75
- export { AnyValidationRuleDefinition, ValidationParams, ValidationRuleDefinition, ValidationRuleResult, ValidationSeverity };
69
+ export { AnyValidationRuleDefinition, ValidationParams, ValidationRuleDefinition, ValidationRuleResult };
76
70
  //# sourceMappingURL=types.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@10x-media/form-builder",
3
- "version": "0.1.0-beta.4",
3
+ "version": "0.1.0-beta.5",
4
4
  "description": "End-to-end forms platform for Payload: author, validate, render, collect, aggregate, and act.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -62,8 +62,8 @@
62
62
  "LICENSE"
63
63
  ],
64
64
  "peerDependencies": {
65
- "@payloadcms/ui": "^3.82.0",
66
- "payload": "^3.82.0",
65
+ "@payloadcms/ui": "^3.83.0",
66
+ "payload": "^3.83.0",
67
67
  "react": "^19.0.0",
68
68
  "react-dom": "^19.0.0"
69
69
  },
@@ -94,9 +94,9 @@
94
94
  "typescript": "5.9.3",
95
95
  "vitest": "4.1.7",
96
96
  "@10x-media/payload-test-harness": "0.0.0",
97
- "@10x-media/vitest-config": "0.0.0",
97
+ "@10x-media/tsconfig": "0.0.0",
98
98
  "@10x-media/tsdown-config": "0.0.0",
99
- "@10x-media/tsconfig": "0.0.0"
99
+ "@10x-media/vitest-config": "0.0.0"
100
100
  },
101
101
  "publishConfig": {
102
102
  "access": "public"
@@ -110,7 +110,7 @@
110
110
  "test": "vitest run",
111
111
  "test:unit": "vitest run src",
112
112
  "test:int": "vitest run tests/int",
113
- "test:matrix": "DB_MATRIX=mongo vitest run tests/int/matrix.int.spec.ts && DB_MATRIX=postgres vitest run tests/int/matrix.int.spec.ts",
113
+ "test:matrix": "DB_MATRIX=mongo vitest run tests/int/matrix.int.spec.ts tests/int/messageResponse.int.spec.ts tests/int/pollAutoClose.int.spec.ts && DB_MATRIX=postgres vitest run tests/int/matrix.int.spec.ts tests/int/messageResponse.int.spec.ts tests/int/pollAutoClose.int.spec.ts",
114
114
  "test:container": "TEST_DB=container DB_MATRIX=mongo vitest run tests/int/matrix.int.spec.ts && TEST_DB=container DB_MATRIX=postgres vitest run tests/int/matrix.int.spec.ts",
115
115
  "test:e2e": "bash scripts/e2e.sh",
116
116
  "dev": "pnpm --filter @10x-media/form-builder-dev dev",
@@ -1,49 +0,0 @@
1
- import { keys } from "../translations/keys.js";
2
- import { labelFor } from "../translations/server.js";
3
- //#region src/consent/buildConsentSourceConfig.ts
4
- /**
5
- * Builds the `source` select and `sourceConfig` group for the consent field block.
6
- * Fields inside `sourceConfig` are annotated with `admin.condition` so only the
7
- * fields that belong to the currently selected source type are visible in the admin UI.
8
- *
9
- * `resolveConsentLinks` reads `field.sourceConfig` as a flat object; field names within
10
- * that group must be unique across all registered sources. Built-in sources (static,
11
- * pageReference) have no overlapping names. Custom sources should follow the same rule.
12
- */
13
- const buildConsentSourceConfig = (registry) => {
14
- const sources = [...registry.values()];
15
- const firstType = sources[0]?.type ?? "static";
16
- const sourceConfigFields = sources.flatMap((source) => (source.config ?? []).map((field) => {
17
- const existingAdmin = typeof field.admin === "object" && field.admin !== null ? field.admin : {};
18
- return {
19
- ...field,
20
- admin: {
21
- ...existingAdmin,
22
- condition: (data) => data?.source === source.type
23
- }
24
- };
25
- }));
26
- return [{
27
- name: "source",
28
- type: "select",
29
- defaultValue: firstType,
30
- label: labelFor(keys.consentConfigSource),
31
- options: sources.map((s) => ({
32
- label: labelFor(s.label),
33
- value: s.type
34
- }))
35
- }, {
36
- name: "sourceConfig",
37
- type: "group",
38
- label: labelFor(keys.consentConfigSourceConfig),
39
- fields: sourceConfigFields.length > 0 ? sourceConfigFields : [{
40
- name: "_placeholder",
41
- type: "text",
42
- admin: { hidden: true }
43
- }]
44
- }];
45
- };
46
- //#endregion
47
- export { buildConsentSourceConfig };
48
-
49
- //# sourceMappingURL=buildConsentSourceConfig.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"buildConsentSourceConfig.js","names":[],"sources":["../../src/consent/buildConsentSourceConfig.ts"],"sourcesContent":["import type { Field } from 'payload'\nimport { keys } from '../translations/keys'\nimport { labelFor } from '../translations/server'\nimport type { ConsentSourceRegistry } from './registry'\n\n/**\n * Builds the `source` select and `sourceConfig` group for the consent field block.\n * Fields inside `sourceConfig` are annotated with `admin.condition` so only the\n * fields that belong to the currently selected source type are visible in the admin UI.\n *\n * `resolveConsentLinks` reads `field.sourceConfig` as a flat object; field names within\n * that group must be unique across all registered sources. Built-in sources (static,\n * pageReference) have no overlapping names. Custom sources should follow the same rule.\n */\nexport const buildConsentSourceConfig = (registry: ConsentSourceRegistry): Field[] => {\n\tconst sources = [...registry.values()]\n\tconst firstType = sources[0]?.type ?? 'static'\n\n\tconst sourceConfigFields: Field[] = sources.flatMap((source) =>\n\t\t(source.config ?? []).map((field) => {\n\t\t\tconst existingAdmin =\n\t\t\t\ttypeof field.admin === 'object' && field.admin !== null ? field.admin : {}\n\t\t\treturn {\n\t\t\t\t...field,\n\t\t\t\tadmin: {\n\t\t\t\t\t...existingAdmin,\n\t\t\t\t\tcondition: (data: unknown) => (data as Record<string, unknown>)?.source === source.type,\n\t\t\t\t},\n\t\t\t} as Field\n\t\t})\n\t)\n\n\treturn [\n\t\t{\n\t\t\tname: 'source',\n\t\t\ttype: 'select',\n\t\t\tdefaultValue: firstType,\n\t\t\tlabel: labelFor(keys.consentConfigSource),\n\t\t\toptions: sources.map((s) => ({\n\t\t\t\tlabel: labelFor(s.label),\n\t\t\t\tvalue: s.type,\n\t\t\t})),\n\t\t},\n\t\t{\n\t\t\tname: 'sourceConfig',\n\t\t\ttype: 'group',\n\t\t\tlabel: labelFor(keys.consentConfigSourceConfig),\n\t\t\tfields:\n\t\t\t\tsourceConfigFields.length > 0\n\t\t\t\t\t? sourceConfigFields\n\t\t\t\t\t: [{ name: '_placeholder', type: 'text', admin: { hidden: true } }],\n\t\t},\n\t]\n}\n"],"mappings":";;;;;;;;;;;;AAcA,MAAa,4BAA4B,aAA6C;CACrF,MAAM,UAAU,CAAC,GAAG,SAAS,OAAO,CAAC;CACrC,MAAM,YAAY,QAAQ,IAAI,QAAQ;CAEtC,MAAM,qBAA8B,QAAQ,SAAS,YACnD,OAAO,UAAU,CAAC,GAAG,KAAK,UAAU;EACpC,MAAM,gBACL,OAAO,MAAM,UAAU,YAAY,MAAM,UAAU,OAAO,MAAM,QAAQ,CAAC;EAC1E,OAAO;GACN,GAAG;GACH,OAAO;IACN,GAAG;IACH,YAAY,SAAmB,MAAkC,WAAW,OAAO;GACpF;EACD;CACD,CAAC,CACF;CAEA,OAAO,CACN;EACC,MAAM;EACN,MAAM;EACN,cAAc;EACd,OAAO,SAAS,KAAK,mBAAmB;EACxC,SAAS,QAAQ,KAAK,OAAO;GAC5B,OAAO,SAAS,EAAE,KAAK;GACvB,OAAO,EAAE;EACV,EAAE;CACH,GACA;EACC,MAAM;EACN,MAAM;EACN,OAAO,SAAS,KAAK,yBAAyB;EAC9C,QACC,mBAAmB,SAAS,IACzB,qBACA,CAAC;GAAE,MAAM;GAAgB,MAAM;GAAQ,OAAO,EAAE,QAAQ,KAAK;EAAE,CAAC;CACrE,CACD;AACD"}
@@ -1,17 +0,0 @@
1
- import { AnyConsentSource } from "../defineConsentSource.js";
2
-
3
- //#region src/consent/builtin/index.d.ts
4
- /**
5
- * Built-in consent sources with content-bearing config fields (the static source's link label)
6
- * carrying `localized: true` when `localize` is true. `pageReference` config holds only
7
- * identifiers and is shared static.
8
- */
9
- declare const buildDefaultConsentSources: (localize: boolean) => Record<string, AnyConsentSource>;
10
- /**
11
- * Prebuilt with content localization on; with `localizeContent: false`, derive overrides from
12
- * `buildDefaultConsentSources(false)` instead so a spread does not reintroduce `localized`.
13
- */
14
- declare const defaultConsentSources: Record<string, AnyConsentSource>;
15
- //#endregion
16
- export { buildDefaultConsentSources, defaultConsentSources };
17
- //# sourceMappingURL=index.d.ts.map
@@ -1,21 +0,0 @@
1
- import { pageReferenceSource } from "./pageReference.js";
2
- import { buildStaticSource } from "./static.js";
3
- //#region src/consent/builtin/index.ts
4
- /**
5
- * Built-in consent sources with content-bearing config fields (the static source's link label)
6
- * carrying `localized: true` when `localize` is true. `pageReference` config holds only
7
- * identifiers and is shared static.
8
- */
9
- const buildDefaultConsentSources = (localize) => ({
10
- static: buildStaticSource(localize),
11
- pageReference: pageReferenceSource
12
- });
13
- /**
14
- * Prebuilt with content localization on; with `localizeContent: false`, derive overrides from
15
- * `buildDefaultConsentSources(false)` instead so a spread does not reintroduce `localized`.
16
- */
17
- const defaultConsentSources = buildDefaultConsentSources(true);
18
- //#endregion
19
- export { buildDefaultConsentSources, defaultConsentSources };
20
-
21
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/consent/builtin/index.ts"],"sourcesContent":["import type { AnyConsentSource } from '../defineConsentSource'\nimport { pageReferenceSource } from './pageReference'\nimport { buildStaticSource } from './static'\n\n/**\n * Built-in consent sources with content-bearing config fields (the static source's link label)\n * carrying `localized: true` when `localize` is true. `pageReference` config holds only\n * identifiers and is shared static.\n */\nexport const buildDefaultConsentSources = (\n\tlocalize: boolean\n): Record<string, AnyConsentSource> => ({\n\tstatic: buildStaticSource(localize) as AnyConsentSource,\n\tpageReference: pageReferenceSource as AnyConsentSource,\n})\n\n/**\n * Prebuilt with content localization on; with `localizeContent: false`, derive overrides from\n * `buildDefaultConsentSources(false)` instead so a spread does not reintroduce `localized`.\n */\nexport const defaultConsentSources: Record<string, AnyConsentSource> =\n\tbuildDefaultConsentSources(true)\n"],"mappings":";;;;;;;;AASA,MAAa,8BACZ,cACuC;CACvC,QAAQ,kBAAkB,QAAQ;CAClC,eAAe;AAChB;;;;;AAMA,MAAa,wBACZ,2BAA2B,IAAI"}
@@ -1,75 +0,0 @@
1
- import { keys } from "../../translations/keys.js";
2
- import { labelFor } from "../../translations/server.js";
3
- import { defineConsentSource } from "../defineConsentSource.js";
4
- import { resolvePublishedVersionRef } from "../resolvePublishedVersionRef.js";
5
- //#region src/consent/builtin/pageReference.ts
6
- const pageReferenceSource = defineConsentSource({
7
- type: "pageReference",
8
- label: keys.consentSourcePageReference,
9
- config: [
10
- {
11
- name: "relationTo",
12
- type: "text",
13
- label: labelFor(keys.consentConfigRelationTo)
14
- },
15
- {
16
- name: "docId",
17
- type: "text",
18
- label: labelFor(keys.consentConfigDocId)
19
- },
20
- {
21
- name: "urlField",
22
- type: "text",
23
- label: labelFor(keys.consentConfigUrlField),
24
- defaultValue: "slug"
25
- },
26
- {
27
- name: "captureVersion",
28
- type: "checkbox",
29
- label: labelFor(keys.consentConfigCaptureVersion)
30
- }
31
- ],
32
- resolve: async ({ config, payload, req, locale }) => {
33
- const relationTo = String(config.relationTo ?? "");
34
- const docId = String(config.docId ?? "");
35
- const urlField = String(config.urlField ?? "slug");
36
- const captureVersion = Boolean(config.captureVersion);
37
- if (!relationTo || !docId) return { links: [] };
38
- const doc = await payload.findByID({
39
- collection: relationTo,
40
- id: docId,
41
- depth: 0,
42
- locale,
43
- req
44
- }).catch(() => null);
45
- if (!doc) return { links: [{
46
- label: relationTo,
47
- url: ""
48
- }] };
49
- const docRecord = doc;
50
- const label = String(docRecord.title ?? docRecord[urlField] ?? relationTo);
51
- const url = String(docRecord[urlField] ?? "");
52
- if (!captureVersion) return { links: [{
53
- label,
54
- url
55
- }] };
56
- const v = await resolvePublishedVersionRef(payload, {
57
- collection: relationTo,
58
- id: docId
59
- });
60
- return {
61
- links: [{
62
- label,
63
- url
64
- }],
65
- ...v ? {
66
- versionRef: v.versionId,
67
- versionLabel: v.updatedAt
68
- } : {}
69
- };
70
- }
71
- });
72
- //#endregion
73
- export { pageReferenceSource };
74
-
75
- //# sourceMappingURL=pageReference.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pageReference.js","names":[],"sources":["../../../src/consent/builtin/pageReference.ts"],"sourcesContent":["import { keys } from '../../translations/keys'\nimport { labelFor } from '../../translations/server'\nimport { defineConsentSource } from '../defineConsentSource'\nimport { resolvePublishedVersionRef } from '../resolvePublishedVersionRef'\n\ntype PageReferenceConfig = {\n\trelationTo?: string\n\tdocId?: string\n\turlField?: string\n\tcaptureVersion?: boolean\n}\n\nexport const pageReferenceSource = defineConsentSource<PageReferenceConfig>({\n\ttype: 'pageReference',\n\tlabel: keys.consentSourcePageReference,\n\tconfig: [\n\t\t{ name: 'relationTo', type: 'text', label: labelFor(keys.consentConfigRelationTo) },\n\t\t{ name: 'docId', type: 'text', label: labelFor(keys.consentConfigDocId) },\n\t\t{\n\t\t\tname: 'urlField',\n\t\t\ttype: 'text',\n\t\t\tlabel: labelFor(keys.consentConfigUrlField),\n\t\t\tdefaultValue: 'slug',\n\t\t},\n\t\t{\n\t\t\tname: 'captureVersion',\n\t\t\ttype: 'checkbox',\n\t\t\tlabel: labelFor(keys.consentConfigCaptureVersion),\n\t\t},\n\t],\n\tresolve: async ({ config, payload, req, locale }) => {\n\t\tconst relationTo = String(config.relationTo ?? '')\n\t\tconst docId = String(config.docId ?? '')\n\t\tconst urlField = String(config.urlField ?? 'slug')\n\t\tconst captureVersion = Boolean(config.captureVersion)\n\n\t\tif (!relationTo || !docId) {\n\t\t\treturn { links: [] }\n\t\t}\n\n\t\tconst doc = await payload\n\t\t\t.findByID({\n\t\t\t\tcollection: relationTo as never,\n\t\t\t\tid: docId,\n\t\t\t\tdepth: 0,\n\t\t\t\tlocale: locale as never,\n\t\t\t\treq,\n\t\t\t})\n\t\t\t.catch(() => null)\n\n\t\tif (!doc) {\n\t\t\treturn { links: [{ label: relationTo, url: '' }] }\n\t\t}\n\n\t\tconst docRecord = doc as Record<string, unknown>\n\t\tconst label = String(docRecord.title ?? docRecord[urlField] ?? relationTo)\n\t\tconst url = String(docRecord[urlField] ?? '')\n\n\t\tif (!captureVersion) {\n\t\t\treturn { links: [{ label, url }] }\n\t\t}\n\n\t\tconst v = await resolvePublishedVersionRef(payload, { collection: relationTo, id: docId })\n\t\treturn {\n\t\t\tlinks: [{ label, url }],\n\t\t\t...(v ? { versionRef: v.versionId, versionLabel: v.updatedAt } : {}),\n\t\t}\n\t},\n})\n"],"mappings":";;;;;AAYA,MAAa,sBAAsB,oBAAyC;CAC3E,MAAM;CACN,OAAO,KAAK;CACZ,QAAQ;EACP;GAAE,MAAM;GAAc,MAAM;GAAQ,OAAO,SAAS,KAAK,uBAAuB;EAAE;EAClF;GAAE,MAAM;GAAS,MAAM;GAAQ,OAAO,SAAS,KAAK,kBAAkB;EAAE;EACxE;GACC,MAAM;GACN,MAAM;GACN,OAAO,SAAS,KAAK,qBAAqB;GAC1C,cAAc;EACf;EACA;GACC,MAAM;GACN,MAAM;GACN,OAAO,SAAS,KAAK,2BAA2B;EACjD;CACD;CACA,SAAS,OAAO,EAAE,QAAQ,SAAS,KAAK,aAAa;EACpD,MAAM,aAAa,OAAO,OAAO,cAAc,EAAE;EACjD,MAAM,QAAQ,OAAO,OAAO,SAAS,EAAE;EACvC,MAAM,WAAW,OAAO,OAAO,YAAY,MAAM;EACjD,MAAM,iBAAiB,QAAQ,OAAO,cAAc;EAEpD,IAAI,CAAC,cAAc,CAAC,OACnB,OAAO,EAAE,OAAO,CAAC,EAAE;EAGpB,MAAM,MAAM,MAAM,QAChB,SAAS;GACT,YAAY;GACZ,IAAI;GACJ,OAAO;GACC;GACR;EACD,CAAC,EACA,YAAY,IAAI;EAElB,IAAI,CAAC,KACJ,OAAO,EAAE,OAAO,CAAC;GAAE,OAAO;GAAY,KAAK;EAAG,CAAC,EAAE;EAGlD,MAAM,YAAY;EAClB,MAAM,QAAQ,OAAO,UAAU,SAAS,UAAU,aAAa,UAAU;EACzE,MAAM,MAAM,OAAO,UAAU,aAAa,EAAE;EAE5C,IAAI,CAAC,gBACJ,OAAO,EAAE,OAAO,CAAC;GAAE;GAAO;EAAI,CAAC,EAAE;EAGlC,MAAM,IAAI,MAAM,2BAA2B,SAAS;GAAE,YAAY;GAAY,IAAI;EAAM,CAAC;EACzF,OAAO;GACN,OAAO,CAAC;IAAE;IAAO;GAAI,CAAC;GACtB,GAAI,IAAI;IAAE,YAAY,EAAE;IAAW,cAAc,EAAE;GAAU,IAAI,CAAC;EACnE;CACD;AACD,CAAC"}
@@ -1,48 +0,0 @@
1
- import { localizedIf } from "../../fields/localizedIf.js";
2
- import { keys } from "../../translations/keys.js";
3
- import { labelFor } from "../../translations/server.js";
4
- import { defineConsentSource } from "../defineConsentSource.js";
5
- //#region src/consent/builtin/static.ts
6
- /** The link `label` is visitor-facing text and follows `localize`; `url` and `version` are identifiers and never do. */
7
- const buildStaticSource = (localize) => defineConsentSource({
8
- type: "static",
9
- label: keys.consentSourceStatic,
10
- config: [
11
- {
12
- name: "label",
13
- type: "text",
14
- label: labelFor(keys.consentConfigLabel),
15
- ...localizedIf(localize)
16
- },
17
- {
18
- name: "url",
19
- type: "text",
20
- label: labelFor(keys.consentConfigUrl)
21
- },
22
- {
23
- name: "version",
24
- type: "text",
25
- label: labelFor(keys.consentConfigVersion)
26
- }
27
- ],
28
- resolve({ config }) {
29
- const label = String(config.label ?? "");
30
- const url = String(config.url ?? "");
31
- const version = config.version ? String(config.version) : void 0;
32
- return {
33
- links: [{
34
- label,
35
- url
36
- }],
37
- ...version ? {
38
- versionRef: version,
39
- versionLabel: version
40
- } : {}
41
- };
42
- }
43
- });
44
- buildStaticSource(true);
45
- //#endregion
46
- export { buildStaticSource };
47
-
48
- //# sourceMappingURL=static.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"static.js","names":[],"sources":["../../../src/consent/builtin/static.ts"],"sourcesContent":["import { localizedIf } from '../../fields/localizedIf'\nimport { keys } from '../../translations/keys'\nimport { labelFor } from '../../translations/server'\nimport { defineConsentSource } from '../defineConsentSource'\n\ntype StaticConfig = { label?: string; url?: string; version?: string }\n\n/** The link `label` is visitor-facing text and follows `localize`; `url` and `version` are identifiers and never do. */\nexport const buildStaticSource = (localize: boolean) =>\n\tdefineConsentSource<StaticConfig>({\n\t\ttype: 'static',\n\t\tlabel: keys.consentSourceStatic,\n\t\tconfig: [\n\t\t\t{\n\t\t\t\tname: 'label',\n\t\t\t\ttype: 'text',\n\t\t\t\tlabel: labelFor(keys.consentConfigLabel),\n\t\t\t\t...localizedIf(localize),\n\t\t\t},\n\t\t\t{ name: 'url', type: 'text', label: labelFor(keys.consentConfigUrl) },\n\t\t\t{ name: 'version', type: 'text', label: labelFor(keys.consentConfigVersion) },\n\t\t],\n\t\tresolve({ config }) {\n\t\t\tconst label = String(config.label ?? '')\n\t\t\tconst url = String(config.url ?? '')\n\t\t\tconst version = config.version ? String(config.version) : undefined\n\t\t\treturn {\n\t\t\t\tlinks: [{ label, url }],\n\t\t\t\t...(version ? { versionRef: version, versionLabel: version } : {}),\n\t\t\t}\n\t\t},\n\t})\n\nexport const staticSource = buildStaticSource(true)\n"],"mappings":";;;;;;AAQA,MAAa,qBAAqB,aACjC,oBAAkC;CACjC,MAAM;CACN,OAAO,KAAK;CACZ,QAAQ;EACP;GACC,MAAM;GACN,MAAM;GACN,OAAO,SAAS,KAAK,kBAAkB;GACvC,GAAG,YAAY,QAAQ;EACxB;EACA;GAAE,MAAM;GAAO,MAAM;GAAQ,OAAO,SAAS,KAAK,gBAAgB;EAAE;EACpE;GAAE,MAAM;GAAW,MAAM;GAAQ,OAAO,SAAS,KAAK,oBAAoB;EAAE;CAC7E;CACA,QAAQ,EAAE,UAAU;EACnB,MAAM,QAAQ,OAAO,OAAO,SAAS,EAAE;EACvC,MAAM,MAAM,OAAO,OAAO,OAAO,EAAE;EACnC,MAAM,UAAU,OAAO,UAAU,OAAO,OAAO,OAAO,IAAI,KAAA;EAC1D,OAAO;GACN,OAAO,CAAC;IAAE;IAAO;GAAI,CAAC;GACtB,GAAI,UAAU;IAAE,YAAY;IAAS,cAAc;GAAQ,IAAI,CAAC;EACjE;CACD;AACD,CAAC;AAE0B,kBAAkB,IAAI"}