@10x-media/form-builder 0.1.0-beta.0 → 0.1.0-beta.2
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.
- package/CHANGELOG.md +68 -0
- package/README.md +45 -1402
- package/dist/actions/buildActionBlocks.js +19 -0
- package/dist/actions/buildActionBlocks.js.map +1 -0
- package/dist/actions/builtin/confirmation.js +49 -0
- package/dist/actions/builtin/confirmation.js.map +1 -0
- package/dist/actions/builtin/emailTeam.js +46 -0
- package/dist/actions/builtin/emailTeam.js.map +1 -0
- package/dist/actions/builtin/index.d.ts +7 -0
- package/dist/actions/builtin/index.js +13 -0
- package/dist/actions/builtin/index.js.map +1 -0
- package/dist/actions/builtin/signedWebhook.js +49 -0
- package/dist/actions/builtin/signedWebhook.js.map +1 -0
- package/dist/actions/defineAction.d.ts +36 -0
- package/dist/actions/defineAction.js +6 -0
- package/dist/actions/defineAction.js.map +1 -0
- package/dist/actions/dispatch.js +48 -0
- package/dist/actions/dispatch.js.map +1 -0
- package/dist/actions/registry.d.ts +16 -0
- package/dist/actions/registry.js +16 -0
- package/dist/actions/registry.js.map +1 -0
- package/dist/actions/runActions.d.ts +9 -0
- package/dist/actions/runActions.js +34 -0
- package/dist/actions/runActions.js.map +1 -0
- package/dist/actions/sign.d.ts +7 -0
- package/dist/actions/sign.js +9 -0
- package/dist/actions/sign.js.map +1 -0
- package/dist/actions/task.js +82 -0
- package/dist/actions/task.js.map +1 -0
- package/dist/aggregation/aggregateResponses.d.ts +31 -0
- package/dist/aggregation/aggregateResponses.js +86 -0
- package/dist/aggregation/aggregateResponses.js.map +1 -0
- package/dist/aggregation/aggregateRows.d.ts +10 -0
- package/dist/aggregation/aggregateRows.js +64 -0
- package/dist/aggregation/aggregateRows.js.map +1 -0
- package/dist/aggregation/resolveResultsRequest.d.ts +32 -0
- package/dist/aggregation/resolveResultsRequest.js +56 -0
- package/dist/aggregation/resolveResultsRequest.js.map +1 -0
- package/dist/aggregation/types.d.ts +39 -0
- package/dist/calc/computeCalcFields.d.ts +15 -0
- package/dist/calc/computeCalcFields.js +27 -0
- package/dist/calc/computeCalcFields.js.map +1 -0
- package/dist/calc/evaluate.d.ts +8 -0
- package/dist/calc/evaluate.js +59 -0
- package/dist/calc/evaluate.js.map +1 -0
- package/dist/calc/normalizeCalc.d.ts +8 -0
- package/dist/calc/normalizeCalc.js +100 -0
- package/dist/calc/normalizeCalc.js.map +1 -0
- package/dist/calc/types.d.ts +28 -0
- package/dist/client/ConditionBuilder.js +121 -0
- package/dist/client/ConditionBuilder.js.map +1 -0
- package/dist/client/ConditionRow.js +150 -0
- package/dist/client/ConditionRow.js.map +1 -0
- package/dist/client/FlowBuilder.d.ts +15 -0
- package/dist/client/FlowBuilder.js +408 -0
- package/dist/client/FlowBuilder.js.map +1 -0
- package/dist/client/FormConditionField.d.ts +21 -0
- package/dist/client/FormConditionField.js +33 -0
- package/dist/client/FormConditionField.js.map +1 -0
- package/dist/client/synthesizeClientField.js +46 -0
- package/dist/client/synthesizeClientField.js.map +1 -0
- package/dist/collections/formSubmissions.js +157 -0
- package/dist/collections/formSubmissions.js.map +1 -0
- package/dist/collections/forms.js +198 -0
- package/dist/collections/forms.js.map +1 -0
- package/dist/collections/uploads.d.ts +30 -0
- package/dist/collections/uploads.js +55 -0
- package/dist/collections/uploads.js.map +1 -0
- package/dist/conditions/conditionType.js +14 -0
- package/dist/conditions/conditionType.js.map +1 -0
- package/dist/conditions/evaluate.d.ts +17 -0
- package/dist/conditions/evaluate.js +94 -0
- package/dist/conditions/evaluate.js.map +1 -0
- package/dist/conditions/fieldTypes.d.ts +9 -0
- package/dist/{fieldTypes-CzhhJXjg.js → conditions/fieldTypes.js} +2 -2
- package/dist/conditions/fieldTypes.js.map +1 -0
- package/dist/conditions/normalizeConditions.js +47 -0
- package/dist/conditions/normalizeConditions.js.map +1 -0
- package/dist/conditions/types.d.ts +8 -0
- package/dist/consent/buildConsentSourceConfig.js +49 -0
- package/dist/consent/buildConsentSourceConfig.js.map +1 -0
- package/dist/consent/builtin/index.d.ts +7 -0
- package/dist/consent/builtin/index.js +11 -0
- package/dist/consent/builtin/index.js.map +1 -0
- package/dist/consent/builtin/pageReference.js +75 -0
- package/dist/consent/builtin/pageReference.js.map +1 -0
- package/dist/consent/builtin/static.js +44 -0
- package/dist/consent/builtin/static.js.map +1 -0
- package/dist/consent/captureConsent.d.ts +28 -0
- package/dist/consent/captureConsent.js +26 -0
- package/dist/consent/captureConsent.js.map +1 -0
- package/dist/consent/defineConsentSource.d.ts +35 -0
- package/dist/consent/defineConsentSource.js +6 -0
- package/dist/consent/defineConsentSource.js.map +1 -0
- package/dist/consent/registry.d.ts +16 -0
- package/dist/consent/registry.js +16 -0
- package/dist/consent/registry.js.map +1 -0
- package/dist/consent/resolveConsentLinks.d.ts +19 -0
- package/dist/consent/resolveConsentLinks.js +26 -0
- package/dist/consent/resolveConsentLinks.js.map +1 -0
- package/dist/consent/resolvePublishedVersionRef.d.ts +17 -0
- package/dist/consent/resolvePublishedVersionRef.js +27 -0
- package/dist/consent/resolvePublishedVersionRef.js.map +1 -0
- package/dist/events/noopSink.js +6 -0
- package/dist/events/noopSink.js.map +1 -0
- package/dist/events/resolveEventSink.js +8 -0
- package/dist/events/resolveEventSink.js.map +1 -0
- package/dist/events/types.d.ts +31 -0
- package/dist/exports/client.d.ts +3 -21
- package/dist/exports/client.js +3 -319
- package/dist/exports/i18n.d.ts +3 -138
- package/dist/exports/i18n.js +2 -2
- package/dist/exports/react.d.ts +45 -550
- package/dist/exports/react.js +39 -1563
- package/dist/exports/rsc.d.ts +2 -16
- package/dist/exports/rsc.js +1 -54
- package/dist/exports/types.d.ts +28 -5
- package/dist/fields/buildFieldBlocks.js +60 -0
- package/dist/fields/buildFieldBlocks.js.map +1 -0
- package/dist/fields/builtin/calculation.js +24 -0
- package/dist/fields/builtin/calculation.js.map +1 -0
- package/dist/fields/builtin/checkbox.js +13 -0
- package/dist/fields/builtin/checkbox.js.map +1 -0
- package/dist/fields/builtin/consent.js +32 -0
- package/dist/fields/builtin/consent.js.map +1 -0
- package/dist/fields/builtin/email.js +18 -0
- package/dist/fields/builtin/email.js.map +1 -0
- package/dist/fields/builtin/file.js +40 -0
- package/dist/fields/builtin/file.js.map +1 -0
- package/dist/fields/builtin/index.js +27 -0
- package/dist/fields/builtin/index.js.map +1 -0
- package/dist/fields/builtin/number.js +17 -0
- package/dist/fields/builtin/number.js.map +1 -0
- package/dist/fields/builtin/repeater.js +44 -0
- package/dist/fields/builtin/repeater.js.map +1 -0
- package/dist/fields/builtin/select.js +44 -0
- package/dist/fields/builtin/select.js.map +1 -0
- package/dist/fields/builtin/text.js +13 -0
- package/dist/fields/builtin/text.js.map +1 -0
- package/dist/fields/builtin/textarea.js +13 -0
- package/dist/fields/builtin/textarea.js.map +1 -0
- package/dist/fields/defineFormField.d.ts +13 -0
- package/dist/fields/defineFormField.js +12 -0
- package/dist/fields/defineFormField.js.map +1 -0
- package/dist/fields/registry.d.ts +10 -0
- package/dist/fields/registry.js +24 -0
- package/dist/fields/registry.js.map +1 -0
- package/dist/fields/sharedConfig.js +89 -0
- package/dist/fields/sharedConfig.js.map +1 -0
- package/dist/fields/types.d.ts +89 -0
- package/dist/flow/engine.d.ts +17 -0
- package/dist/flow/engine.js +24 -0
- package/dist/flow/engine.js.map +1 -0
- package/dist/flow/normalizeFlow.js +35 -0
- package/dist/flow/normalizeFlow.js.map +1 -0
- package/dist/{types-DsJ_6kGJ.d.ts → flow/types.d.ts} +2 -2
- package/dist/index.d.ts +93 -4
- package/dist/index.js +43 -1890
- package/dist/index.js.map +1 -1
- package/dist/plugin/access.js +12 -0
- package/dist/plugin/access.js.map +1 -0
- package/dist/plugin/collectionOverrides.d.ts +22 -0
- package/dist/plugin/registerCollections.js +68 -0
- package/dist/plugin/registerCollections.js.map +1 -0
- package/dist/plugin/registerTranslations.js +19 -0
- package/dist/plugin/registerTranslations.js.map +1 -0
- package/dist/prefill/valuesFromSearchParams.d.ts +18 -0
- package/dist/prefill/valuesFromSearchParams.js +45 -0
- package/dist/prefill/valuesFromSearchParams.js.map +1 -0
- package/dist/presentations/defaults.d.ts +33 -0
- package/dist/presentations/defaults.js +35 -0
- package/dist/presentations/defaults.js.map +1 -0
- package/dist/presentations/registry.d.ts +15 -0
- package/dist/presentations/registry.js +15 -0
- package/dist/presentations/registry.js.map +1 -0
- package/dist/presentations/types.d.ts +18 -0
- package/dist/react/Form.d.ts +110 -0
- package/dist/react/Form.js +499 -0
- package/dist/react/Form.js.map +1 -0
- package/dist/react/FormContext.d.ts +16 -0
- package/dist/react/FormContext.js +14 -0
- package/dist/react/FormContext.js.map +1 -0
- package/dist/react/FormLayout.d.ts +20 -0
- package/dist/react/FormLayout.js +14 -0
- package/dist/react/FormLayout.js.map +1 -0
- package/dist/react/FormResults.d.ts +25 -0
- package/dist/react/FormResults.js +85 -0
- package/dist/react/FormResults.js.map +1 -0
- package/dist/react/Honeypot.d.ts +22 -0
- package/dist/react/Honeypot.js +38 -0
- package/dist/react/Honeypot.js.map +1 -0
- package/dist/react/Poll.d.ts +32 -0
- package/dist/react/Poll.js +77 -0
- package/dist/react/Poll.js.map +1 -0
- package/dist/react/cn.d.ts +6 -0
- package/dist/react/cn.js +8 -0
- package/dist/react/cn.js.map +1 -0
- package/dist/react/contract.d.ts +32 -0
- package/dist/react/contract.js +7 -0
- package/dist/react/contract.js.map +1 -0
- package/dist/react/events.js +14 -0
- package/dist/react/events.js.map +1 -0
- package/dist/react/fetchResults.d.ts +25 -0
- package/dist/react/fetchResults.js +31 -0
- package/dist/react/fetchResults.js.map +1 -0
- package/dist/react/presentation/Backdrop.d.ts +18 -0
- package/dist/react/presentation/Backdrop.js +14 -0
- package/dist/react/presentation/Backdrop.js.map +1 -0
- package/dist/react/presentation/DialogSurface.d.ts +35 -0
- package/dist/react/presentation/DialogSurface.js +56 -0
- package/dist/react/presentation/DialogSurface.js.map +1 -0
- package/dist/react/presentation/presentations.d.ts +7 -0
- package/dist/react/presentation/presentations.js +32 -0
- package/dist/react/presentation/presentations.js.map +1 -0
- package/dist/react/presentation/registry.d.ts +11 -0
- package/dist/react/presentation/registry.js +12 -0
- package/dist/react/presentation/registry.js.map +1 -0
- package/dist/react/presentation/types.d.ts +19 -0
- package/dist/react/presentation/useDismiss.d.ts +19 -0
- package/dist/react/presentation/useDismiss.js +33 -0
- package/dist/react/presentation/useDismiss.js.map +1 -0
- package/dist/react/presentation/useFocusTrap.d.ts +8 -0
- package/dist/react/presentation/useFocusTrap.js +35 -0
- package/dist/react/presentation/useFocusTrap.js.map +1 -0
- package/dist/react/presentation/useScrollLock.d.ts +6 -0
- package/dist/react/presentation/useScrollLock.js +18 -0
- package/dist/react/presentation/useScrollLock.js.map +1 -0
- package/dist/react/primitives/Checkbox.d.ts +26 -0
- package/dist/react/primitives/Checkbox.js +20 -0
- package/dist/react/primitives/Checkbox.js.map +1 -0
- package/dist/react/primitives/FieldShell.d.ts +31 -0
- package/dist/react/primitives/FieldShell.js +51 -0
- package/dist/react/primitives/FieldShell.js.map +1 -0
- package/dist/react/primitives/Input.d.ts +30 -0
- package/dist/react/primitives/Input.js +21 -0
- package/dist/react/primitives/Input.js.map +1 -0
- package/dist/react/primitives/Select.d.ts +34 -0
- package/dist/react/primitives/Select.js +26 -0
- package/dist/react/primitives/Select.js.map +1 -0
- package/dist/react/primitives/Textarea.d.ts +28 -0
- package/dist/react/primitives/Textarea.js +20 -0
- package/dist/react/primitives/Textarea.js.map +1 -0
- package/dist/react/recall.js +20 -0
- package/dist/react/recall.js.map +1 -0
- package/dist/react/registry.d.ts +16 -0
- package/dist/react/registry.js +16 -0
- package/dist/react/registry.js.map +1 -0
- package/dist/react/renderers/calculation.js +30 -0
- package/dist/react/renderers/calculation.js.map +1 -0
- package/dist/react/renderers/checkbox.js +35 -0
- package/dist/react/renderers/checkbox.js.map +1 -0
- package/dist/react/renderers/consent.js +54 -0
- package/dist/react/renderers/consent.js.map +1 -0
- package/dist/react/renderers/email.js +37 -0
- package/dist/react/renderers/email.js.map +1 -0
- package/dist/react/renderers/file.js +92 -0
- package/dist/react/renderers/file.js.map +1 -0
- package/dist/react/renderers/index.d.ts +8 -0
- package/dist/react/renderers/index.js +28 -0
- package/dist/react/renderers/index.js.map +1 -0
- package/dist/react/renderers/number.js +40 -0
- package/dist/react/renderers/number.js.map +1 -0
- package/dist/react/renderers/repeater.js +113 -0
- package/dist/react/renderers/repeater.js.map +1 -0
- package/dist/react/renderers/select.js +38 -0
- package/dist/react/renderers/select.js.map +1 -0
- package/dist/react/renderers/text.js +37 -0
- package/dist/react/renderers/text.js.map +1 -0
- package/dist/react/renderers/textarea.js +36 -0
- package/dist/react/renderers/textarea.js.map +1 -0
- package/dist/react/resolveForm.js +16 -0
- package/dist/react/resolveForm.js.map +1 -0
- package/dist/react/state.d.ts +15 -0
- package/dist/react/state.js +70 -0
- package/dist/react/state.js.map +1 -0
- package/dist/react/submitForm.d.ts +31 -0
- package/dist/react/submitForm.js +58 -0
- package/dist/react/submitForm.js.map +1 -0
- package/dist/react/toFormDocument.d.ts +24 -0
- package/dist/react/toFormDocument.js +22 -0
- package/dist/react/toFormDocument.js.map +1 -0
- package/dist/react/uploadFile.d.ts +23 -0
- package/dist/react/uploadFile.js +39 -0
- package/dist/react/uploadFile.js.map +1 -0
- package/dist/react/useField.d.ts +14 -0
- package/dist/react/useField.js +49 -0
- package/dist/react/useField.js.map +1 -0
- package/dist/react/useFormState.d.ts +8 -0
- package/dist/react/useFormState.js +9 -0
- package/dist/react/useFormState.js.map +1 -0
- package/dist/react/useFormStep.d.ts +8 -0
- package/dist/react/useFormStep.js +9 -0
- package/dist/react/useFormStep.js.map +1 -0
- package/dist/react/validateField.js +30 -0
- package/dist/react/validateField.js.map +1 -0
- package/dist/recall/interpolate.d.ts +10 -0
- package/dist/recall/interpolate.js +16 -0
- package/dist/recall/interpolate.js.map +1 -0
- package/dist/recall/resolver.d.ts +22 -0
- package/dist/recall/resolver.js +36 -0
- package/dist/recall/resolver.js.map +1 -0
- package/dist/spam/captcha.d.ts +12 -0
- package/dist/spam/captcha.js +11 -0
- package/dist/spam/captcha.js.map +1 -0
- package/dist/spam/constants.d.ts +12 -0
- package/dist/spam/constants.js +15 -0
- package/dist/spam/constants.js.map +1 -0
- package/dist/spam/identify.d.ts +12 -0
- package/dist/spam/identify.js +20 -0
- package/dist/spam/identify.js.map +1 -0
- package/dist/spam/rateLimiter.d.ts +18 -0
- package/dist/spam/rateLimiter.js +41 -0
- package/dist/spam/rateLimiter.js.map +1 -0
- package/dist/spam/reserved.js +30 -0
- package/dist/spam/reserved.js.map +1 -0
- package/dist/spam/resolveSpam.d.ts +12 -0
- package/dist/spam/resolveSpam.js +42 -0
- package/dist/spam/resolveSpam.js.map +1 -0
- package/dist/spam/spamGuard.js +68 -0
- package/dist/spam/spamGuard.js.map +1 -0
- package/dist/spam/types.d.ts +73 -0
- package/dist/spam/uploadHooks.js +33 -0
- package/dist/spam/uploadHooks.js.map +1 -0
- package/dist/submissions/SubmissionAnswers.d.ts +14 -0
- package/dist/submissions/SubmissionAnswers.js +133 -0
- package/dist/submissions/SubmissionAnswers.js.map +1 -0
- package/dist/submissions/SubmissionAnswersClient.js +142 -0
- package/dist/submissions/SubmissionAnswersClient.js.map +1 -0
- package/dist/submissions/runSubmission.js +257 -0
- package/dist/submissions/runSubmission.js.map +1 -0
- package/dist/submissions/types.d.ts +34 -0
- package/dist/submissions/validateSubmission.js +59 -0
- package/dist/submissions/validateSubmission.js.map +1 -0
- package/dist/translations/en.d.ts +12 -0
- package/dist/{translations-edMqq_2e.js → translations/en.js} +29 -23
- package/dist/translations/en.js.map +1 -0
- package/dist/translations/index.d.ts +14 -0
- package/dist/translations/index.js +26 -0
- package/dist/translations/index.js.map +1 -0
- package/dist/translations/keys.d.ts +157 -0
- package/dist/{keys-N5xGiUsh.js → translations/keys.js} +28 -3
- package/dist/translations/keys.js.map +1 -0
- package/dist/translations/makeTranslate.d.ts +11 -0
- package/dist/translations/makeTranslate.js +11 -0
- package/dist/translations/makeTranslate.js.map +1 -0
- package/dist/translations/server.js +25 -0
- package/dist/translations/server.js.map +1 -0
- package/dist/translations/useTranslation.js +12 -0
- package/dist/translations/useTranslation.js.map +1 -0
- package/dist/uploads/captureFileRef.d.ts +27 -0
- package/dist/uploads/captureFileRef.js +34 -0
- package/dist/uploads/captureFileRef.js.map +1 -0
- package/dist/uploads/resolveFileRef.d.ts +26 -0
- package/dist/uploads/resolveFileRef.js +44 -0
- package/dist/uploads/resolveFileRef.js.map +1 -0
- package/dist/uploads/types.d.ts +20 -0
- package/dist/validation/buildRuleBlocks.js +46 -0
- package/dist/validation/buildRuleBlocks.js.map +1 -0
- package/dist/validation/builtin/email.js +19 -0
- package/dist/validation/builtin/email.js.map +1 -0
- package/dist/validation/builtin/index.js +27 -0
- package/dist/validation/builtin/index.js.map +1 -0
- package/dist/validation/builtin/matchesField.js +20 -0
- package/dist/validation/builtin/matchesField.js.map +1 -0
- package/dist/validation/builtin/max.js +21 -0
- package/dist/validation/builtin/max.js.map +1 -0
- package/dist/validation/builtin/maxLength.js +26 -0
- package/dist/validation/builtin/maxLength.js.map +1 -0
- package/dist/validation/builtin/min.js +21 -0
- package/dist/validation/builtin/min.js.map +1 -0
- package/dist/validation/builtin/minLength.js +26 -0
- package/dist/validation/builtin/minLength.js.map +1 -0
- package/dist/validation/builtin/notAlreadySubmitted.js +32 -0
- package/dist/validation/builtin/notAlreadySubmitted.js.map +1 -0
- package/dist/validation/builtin/oneOf.js +34 -0
- package/dist/validation/builtin/oneOf.js.map +1 -0
- package/dist/validation/builtin/pattern.js +41 -0
- package/dist/validation/builtin/pattern.js.map +1 -0
- package/dist/validation/builtin/url.js +22 -0
- package/dist/validation/builtin/url.js.map +1 -0
- package/dist/validation/defineValidationRule.d.ts +12 -0
- package/dist/validation/defineValidationRule.js +11 -0
- package/dist/validation/defineValidationRule.js.map +1 -0
- package/dist/validation/message.js +14 -0
- package/dist/validation/message.js.map +1 -0
- package/dist/validation/registry.d.ts +10 -0
- package/dist/validation/registry.js +20 -0
- package/dist/validation/registry.js.map +1 -0
- package/dist/validation/runValidation.js +111 -0
- package/dist/validation/runValidation.js.map +1 -0
- package/dist/validation/types.d.ts +76 -0
- package/package.json +8 -5
- package/styles/form-builder.css +201 -11
- package/dist/constants-B-BUfetP.d.ts +0 -288
- package/dist/exports/client.js.map +0 -1
- package/dist/exports/react.js.map +0 -1
- package/dist/exports/rsc.js.map +0 -1
- package/dist/fieldTypes-B8jkNRob.d.ts +0 -188
- package/dist/fieldTypes-CzhhJXjg.js.map +0 -1
- package/dist/index-DfFYGbVF.d.ts +0 -481
- package/dist/keys-N5xGiUsh.js.map +0 -1
- package/dist/registry-CoCyhtvB.js +0 -282
- package/dist/registry-CoCyhtvB.js.map +0 -1
- package/dist/resolver-OeQyVH2N.js +0 -665
- package/dist/resolver-OeQyVH2N.js.map +0 -1
- package/dist/translations-edMqq_2e.js.map +0 -1
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { FieldLabel, TextInput } from "@payloadcms/ui";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
//#region src/submissions/SubmissionAnswersClient.tsx
|
|
5
|
+
const noop = (_e) => {};
|
|
6
|
+
const pillStyle = (agreed) => ({
|
|
7
|
+
display: "inline-block",
|
|
8
|
+
padding: "2px 8px",
|
|
9
|
+
borderRadius: "9999px",
|
|
10
|
+
fontSize: "0.75rem",
|
|
11
|
+
fontWeight: 600,
|
|
12
|
+
background: agreed ? "var(--theme-success-500)" : "var(--theme-error-500)",
|
|
13
|
+
color: "#fff"
|
|
14
|
+
});
|
|
15
|
+
const rowHeading = {
|
|
16
|
+
fontSize: "0.75rem",
|
|
17
|
+
fontWeight: 600,
|
|
18
|
+
color: "var(--theme-elevation-500)",
|
|
19
|
+
margin: "0 0 4px"
|
|
20
|
+
};
|
|
21
|
+
const SubmissionAnswersClient = ({ answers, repeaters, consent, meta, labels }) => {
|
|
22
|
+
if (!(answers.length > 0 || repeaters.length > 0 || consent.length > 0 || meta.length > 0)) return /* @__PURE__ */ jsx("p", {
|
|
23
|
+
style: { color: "var(--theme-elevation-500)" },
|
|
24
|
+
children: labels.empty
|
|
25
|
+
});
|
|
26
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
27
|
+
className: "field-type",
|
|
28
|
+
style: {
|
|
29
|
+
display: "flex",
|
|
30
|
+
flexDirection: "column",
|
|
31
|
+
gap: "32px"
|
|
32
|
+
},
|
|
33
|
+
children: [
|
|
34
|
+
(answers.length > 0 || repeaters.length > 0) && /* @__PURE__ */ jsxs("section", { children: [
|
|
35
|
+
/* @__PURE__ */ jsx(FieldLabel, { label: labels.answers }),
|
|
36
|
+
answers.map(({ field, label, value, href }) => href ? /* @__PURE__ */ jsxs("div", {
|
|
37
|
+
className: "field-type",
|
|
38
|
+
children: [/* @__PURE__ */ jsx(FieldLabel, { label }), /* @__PURE__ */ jsx("a", {
|
|
39
|
+
href,
|
|
40
|
+
target: "_blank",
|
|
41
|
+
rel: "noreferrer",
|
|
42
|
+
style: {
|
|
43
|
+
display: "block",
|
|
44
|
+
padding: "8px 0",
|
|
45
|
+
color: "var(--theme-text)",
|
|
46
|
+
textDecoration: "underline"
|
|
47
|
+
},
|
|
48
|
+
children: value
|
|
49
|
+
})]
|
|
50
|
+
}, field) : /* @__PURE__ */ jsx(TextInput, {
|
|
51
|
+
path: `sa-${field}`,
|
|
52
|
+
label,
|
|
53
|
+
value,
|
|
54
|
+
readOnly: true,
|
|
55
|
+
onChange: noop
|
|
56
|
+
}, field)),
|
|
57
|
+
repeaters.map(({ field, label, rows }) => /* @__PURE__ */ jsxs("div", {
|
|
58
|
+
className: "field-type",
|
|
59
|
+
children: [/* @__PURE__ */ jsx(FieldLabel, { label }), rows.length === 0 ? /* @__PURE__ */ jsx(TextInput, {
|
|
60
|
+
path: `sa-${field}-empty`,
|
|
61
|
+
label: "",
|
|
62
|
+
value: "—",
|
|
63
|
+
readOnly: true,
|
|
64
|
+
onChange: noop
|
|
65
|
+
}) : /* @__PURE__ */ jsx("div", {
|
|
66
|
+
style: {
|
|
67
|
+
display: "flex",
|
|
68
|
+
flexDirection: "column",
|
|
69
|
+
gap: "8px",
|
|
70
|
+
marginTop: "4px"
|
|
71
|
+
},
|
|
72
|
+
children: rows.map((row) => /* @__PURE__ */ jsxs("div", {
|
|
73
|
+
style: {
|
|
74
|
+
border: "1px solid var(--theme-elevation-150)",
|
|
75
|
+
borderRadius: "4px",
|
|
76
|
+
padding: "4px 12px 0"
|
|
77
|
+
},
|
|
78
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
79
|
+
style: rowHeading,
|
|
80
|
+
children: labels.row.replace("{n}", String(Number(row.id) + 1))
|
|
81
|
+
}), row.subFields.map((subField) => /* @__PURE__ */ jsx(TextInput, {
|
|
82
|
+
path: `sa-${field}-${row.id}-${subField.label}`,
|
|
83
|
+
label: subField.label,
|
|
84
|
+
value: subField.value,
|
|
85
|
+
readOnly: true,
|
|
86
|
+
onChange: noop
|
|
87
|
+
}, subField.label))]
|
|
88
|
+
}, row.id))
|
|
89
|
+
})]
|
|
90
|
+
}, field))
|
|
91
|
+
] }),
|
|
92
|
+
consent.length > 0 && /* @__PURE__ */ jsxs("section", { children: [/* @__PURE__ */ jsx(FieldLabel, { label: labels.consent }), consent.map((entry) => /* @__PURE__ */ jsxs("div", {
|
|
93
|
+
className: "field-type",
|
|
94
|
+
children: [/* @__PURE__ */ jsx(FieldLabel, { label: entry.field }), /* @__PURE__ */ jsxs("div", {
|
|
95
|
+
style: {
|
|
96
|
+
display: "flex",
|
|
97
|
+
flexDirection: "column",
|
|
98
|
+
gap: "4px"
|
|
99
|
+
},
|
|
100
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
101
|
+
style: {
|
|
102
|
+
display: "flex",
|
|
103
|
+
alignItems: "center",
|
|
104
|
+
gap: "8px",
|
|
105
|
+
flexWrap: "wrap"
|
|
106
|
+
},
|
|
107
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
108
|
+
style: pillStyle(entry.agreed),
|
|
109
|
+
children: entry.agreed ? labels.agreed : labels.declined
|
|
110
|
+
}), entry.ref ? /* @__PURE__ */ jsxs("a", {
|
|
111
|
+
href: entry.ref,
|
|
112
|
+
target: "_blank",
|
|
113
|
+
rel: "noreferrer",
|
|
114
|
+
style: {
|
|
115
|
+
fontSize: "0.8rem",
|
|
116
|
+
color: "var(--theme-text)"
|
|
117
|
+
},
|
|
118
|
+
children: [entry.ref, entry.versionRef ? ` (v${entry.versionRef})` : ""]
|
|
119
|
+
}) : null]
|
|
120
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
121
|
+
style: {
|
|
122
|
+
fontSize: "0.75rem",
|
|
123
|
+
color: "var(--theme-elevation-500)"
|
|
124
|
+
},
|
|
125
|
+
children: entry.at
|
|
126
|
+
})]
|
|
127
|
+
})]
|
|
128
|
+
}, entry.field))] }),
|
|
129
|
+
meta.length > 0 && /* @__PURE__ */ jsxs("section", { children: [/* @__PURE__ */ jsx(FieldLabel, { label: labels.submissionDetails }), meta.map((item) => /* @__PURE__ */ jsx(TextInput, {
|
|
130
|
+
path: `sa-meta-${item.label}`,
|
|
131
|
+
label: item.label,
|
|
132
|
+
value: item.value,
|
|
133
|
+
readOnly: true,
|
|
134
|
+
onChange: noop
|
|
135
|
+
}, item.label))] })
|
|
136
|
+
]
|
|
137
|
+
});
|
|
138
|
+
};
|
|
139
|
+
//#endregion
|
|
140
|
+
export { SubmissionAnswersClient };
|
|
141
|
+
|
|
142
|
+
//# sourceMappingURL=SubmissionAnswersClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SubmissionAnswersClient.js","names":[],"sources":["../../src/submissions/SubmissionAnswersClient.tsx"],"sourcesContent":["'use client'\n\nimport { FieldLabel, TextInput } from '@payloadcms/ui'\nimport type { ChangeEvent } from 'react'\n\nexport type AnswerItem = {\n\tfield: string\n\tlabel: string\n\tvalue: string\n\thref?: string\n\tmultiline?: boolean\n}\n\nexport type RepeaterRow = {\n\tid: string\n\tsubFields: Array<{ label: string; value: string }>\n}\n\nexport type RepeaterItem = {\n\tfield: string\n\tlabel: string\n\trows: RepeaterRow[]\n}\n\nexport type ConsentItem = {\n\tfield: string\n\tagreed: boolean\n\tref?: string\n\tversionRef?: string\n\tat: string\n}\n\nexport type MetaItem = {\n\tlabel: string\n\tvalue: string\n}\n\nexport type SubmissionAnswersLabels = {\n\tanswers: string\n\tconsent: string\n\tsubmissionDetails: string\n\tagreed: string\n\tdeclined: string\n\t/** Row heading template containing `{n}`, the 1-based row number. */\n\trow: string\n\tempty: string\n}\n\ntype Props = {\n\tanswers: AnswerItem[]\n\trepeaters: RepeaterItem[]\n\tconsent: ConsentItem[]\n\tmeta: MetaItem[]\n\tlabels: SubmissionAnswersLabels\n}\n\nconst noop = (_e: ChangeEvent<HTMLInputElement>) => {}\n\nconst pillStyle = (agreed: boolean): React.CSSProperties => ({\n\tdisplay: 'inline-block',\n\tpadding: '2px 8px',\n\tborderRadius: '9999px',\n\tfontSize: '0.75rem',\n\tfontWeight: 600,\n\tbackground: agreed ? 'var(--theme-success-500)' : 'var(--theme-error-500)',\n\tcolor: '#fff',\n})\n\nconst rowHeading: React.CSSProperties = {\n\tfontSize: '0.75rem',\n\tfontWeight: 600,\n\tcolor: 'var(--theme-elevation-500)',\n\tmargin: '0 0 4px',\n}\n\nexport const SubmissionAnswersClient = ({ answers, repeaters, consent, meta, labels }: Props) => {\n\tconst hasContent =\n\t\tanswers.length > 0 || repeaters.length > 0 || consent.length > 0 || meta.length > 0\n\n\tif (!hasContent) {\n\t\treturn <p style={{ color: 'var(--theme-elevation-500)' }}>{labels.empty}</p>\n\t}\n\n\treturn (\n\t\t<div className=\"field-type\" style={{ display: 'flex', flexDirection: 'column', gap: '32px' }}>\n\t\t\t{(answers.length > 0 || repeaters.length > 0) && (\n\t\t\t\t<section>\n\t\t\t\t\t<FieldLabel label={labels.answers} />\n\t\t\t\t\t{answers.map(({ field, label, value, href }) =>\n\t\t\t\t\t\thref ? (\n\t\t\t\t\t\t\t<div key={field} className=\"field-type\">\n\t\t\t\t\t\t\t\t<FieldLabel label={label} />\n\t\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\t\thref={href}\n\t\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\t\trel=\"noreferrer\"\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tdisplay: 'block',\n\t\t\t\t\t\t\t\t\t\tpadding: '8px 0',\n\t\t\t\t\t\t\t\t\t\tcolor: 'var(--theme-text)',\n\t\t\t\t\t\t\t\t\t\ttextDecoration: 'underline',\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{value}\n\t\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<TextInput\n\t\t\t\t\t\t\t\tkey={field}\n\t\t\t\t\t\t\t\tpath={`sa-${field}`}\n\t\t\t\t\t\t\t\tlabel={label}\n\t\t\t\t\t\t\t\tvalue={value}\n\t\t\t\t\t\t\t\treadOnly\n\t\t\t\t\t\t\t\tonChange={noop}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)\n\t\t\t\t\t)}\n\n\t\t\t\t\t{repeaters.map(({ field, label, rows }) => (\n\t\t\t\t\t\t<div key={field} className=\"field-type\">\n\t\t\t\t\t\t\t<FieldLabel label={label} />\n\t\t\t\t\t\t\t{rows.length === 0 ? (\n\t\t\t\t\t\t\t\t<TextInput path={`sa-${field}-empty`} label=\"\" value=\"—\" readOnly onChange={noop} />\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tstyle={{ display: 'flex', flexDirection: 'column', gap: '8px', marginTop: '4px' }}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{rows.map((row) => (\n\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\tkey={row.id}\n\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\tborder: '1px solid var(--theme-elevation-150)',\n\t\t\t\t\t\t\t\t\t\t\t\tborderRadius: '4px',\n\t\t\t\t\t\t\t\t\t\t\t\tpadding: '4px 12px 0',\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<p style={rowHeading}>\n\t\t\t\t\t\t\t\t\t\t\t\t{labels.row.replace('{n}', String(Number(row.id) + 1))}\n\t\t\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t\t\t\t{row.subFields.map((subField) => (\n\t\t\t\t\t\t\t\t\t\t\t\t<TextInput\n\t\t\t\t\t\t\t\t\t\t\t\t\tkey={subField.label}\n\t\t\t\t\t\t\t\t\t\t\t\t\tpath={`sa-${field}-${row.id}-${subField.label}`}\n\t\t\t\t\t\t\t\t\t\t\t\t\tlabel={subField.label}\n\t\t\t\t\t\t\t\t\t\t\t\t\tvalue={subField.value}\n\t\t\t\t\t\t\t\t\t\t\t\t\treadOnly\n\t\t\t\t\t\t\t\t\t\t\t\t\tonChange={noop}\n\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</section>\n\t\t\t)}\n\n\t\t\t{consent.length > 0 && (\n\t\t\t\t<section>\n\t\t\t\t\t<FieldLabel label={labels.consent} />\n\t\t\t\t\t{consent.map((entry) => (\n\t\t\t\t\t\t<div key={entry.field} className=\"field-type\">\n\t\t\t\t\t\t\t<FieldLabel label={entry.field} />\n\t\t\t\t\t\t\t<div style={{ display: 'flex', flexDirection: 'column', gap: '4px' }}>\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tstyle={{ display: 'flex', alignItems: 'center', gap: '8px', flexWrap: 'wrap' }}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<span style={pillStyle(entry.agreed)}>\n\t\t\t\t\t\t\t\t\t\t{entry.agreed ? labels.agreed : labels.declined}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t{entry.ref ? (\n\t\t\t\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\t\t\t\thref={entry.ref}\n\t\t\t\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\t\t\t\trel=\"noreferrer\"\n\t\t\t\t\t\t\t\t\t\t\tstyle={{ fontSize: '0.8rem', color: 'var(--theme-text)' }}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{entry.ref}\n\t\t\t\t\t\t\t\t\t\t\t{entry.versionRef ? ` (v${entry.versionRef})` : ''}\n\t\t\t\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<span style={{ fontSize: '0.75rem', color: 'var(--theme-elevation-500)' }}>\n\t\t\t\t\t\t\t\t\t{entry.at}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</section>\n\t\t\t)}\n\n\t\t\t{meta.length > 0 && (\n\t\t\t\t<section>\n\t\t\t\t\t<FieldLabel label={labels.submissionDetails} />\n\t\t\t\t\t{meta.map((item) => (\n\t\t\t\t\t\t<TextInput\n\t\t\t\t\t\t\tkey={item.label}\n\t\t\t\t\t\t\tpath={`sa-meta-${item.label}`}\n\t\t\t\t\t\t\tlabel={item.label}\n\t\t\t\t\t\t\tvalue={item.value}\n\t\t\t\t\t\t\treadOnly\n\t\t\t\t\t\t\tonChange={noop}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t</section>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { keys } from "../translations/keys.js";
|
|
2
|
+
import { calcExpressionOf, computeCalcFields } from "../calc/computeCalcFields.js";
|
|
3
|
+
import { evaluateCondition } from "../conditions/evaluate.js";
|
|
4
|
+
import { captureConsent } from "../consent/captureConsent.js";
|
|
5
|
+
import { captureFileRef } from "../uploads/captureFileRef.js";
|
|
6
|
+
import { runValidation } from "../validation/runValidation.js";
|
|
7
|
+
//#region src/submissions/runSubmission.ts
|
|
8
|
+
const errorKeyFor = (code) => {
|
|
9
|
+
if (code === "mimeType") return keys.validationFileMimeType;
|
|
10
|
+
if (code === "tooLarge") return keys.validationFileTooLarge;
|
|
11
|
+
return keys.validationFileMissing;
|
|
12
|
+
};
|
|
13
|
+
/** Normalize the authored `mimeTypes` (a `hasMany` text field) to a `string[]`. */
|
|
14
|
+
const mimeTypesOf = (raw) => {
|
|
15
|
+
if (!Array.isArray(raw)) return;
|
|
16
|
+
const out = raw.filter((entry) => typeof entry === "string");
|
|
17
|
+
return out.length > 0 ? out : void 0;
|
|
18
|
+
};
|
|
19
|
+
const fileFieldConfigOf = (instance) => ({
|
|
20
|
+
relationTo: typeof instance.relationTo === "string" ? instance.relationTo : void 0,
|
|
21
|
+
mimeTypes: mimeTypesOf(instance.mimeTypes),
|
|
22
|
+
maxSize: typeof instance.maxSize === "number" ? instance.maxSize : void 0
|
|
23
|
+
});
|
|
24
|
+
const isEmpty = (value) => value == null || value === "" || Array.isArray(value) && value.length === 0;
|
|
25
|
+
const coerce = (kind, value) => {
|
|
26
|
+
if (value == null) return value;
|
|
27
|
+
if (kind === "number") {
|
|
28
|
+
const next = typeof value === "number" ? value : Number(value);
|
|
29
|
+
return Number.isNaN(next) ? value : next;
|
|
30
|
+
}
|
|
31
|
+
if (kind === "boolean") {
|
|
32
|
+
if (typeof value === "string") {
|
|
33
|
+
const normalized = value.trim().toLowerCase();
|
|
34
|
+
return !(normalized === "" || normalized === "false" || normalized === "0" || normalized === "off" || normalized === "no");
|
|
35
|
+
}
|
|
36
|
+
return Boolean(value);
|
|
37
|
+
}
|
|
38
|
+
if (kind === "text") return typeof value === "string" ? value : String(value);
|
|
39
|
+
return value;
|
|
40
|
+
};
|
|
41
|
+
const optionLabelsFor = (instance) => {
|
|
42
|
+
const options = instance.options;
|
|
43
|
+
if (!Array.isArray(options)) return;
|
|
44
|
+
const map = {};
|
|
45
|
+
for (const option of options) if (typeof option?.value === "string") map[option.value] = option.label ?? option.value;
|
|
46
|
+
return Object.keys(map).length > 0 ? map : void 0;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Pure submission core, two-pass: first coerce every answered field to its typed kind (so cross-field
|
|
50
|
+
* rules see coerced siblings), then validate each field through `runValidation` (required, intrinsic
|
|
51
|
+
* facet, declarative rules), snapshotting a localized descriptor per answered field. Calc fields are
|
|
52
|
+
* the trust boundary: their client-sent values are never seeded, their values are derived from their
|
|
53
|
+
* expressions over the coerced answers, and those derived values are authoritative everywhere downstream
|
|
54
|
+
* (conditions, validation, storage). Conditions gate the second pass against these effective answers: a
|
|
55
|
+
* field whose `visibleWhen` is false is skipped entirely (never validated, never stored, so a client-sent
|
|
56
|
+
* value for it is ignored), and a visible field whose `validateWhen` is false stores its value but skips
|
|
57
|
+
* validation. A visible calc field stores its derived value and is never validated. Only `error` severity
|
|
58
|
+
* blocks; warnings are computed but not surfaced server-side (the renderer surfaces them).
|
|
59
|
+
*/
|
|
60
|
+
const runSubmission = async (input) => {
|
|
61
|
+
const { fields, values, registry, ruleRegistry, consentRegistry, locale, t, operation, req, payload, formId, uploadSlug, expectedOwner } = input;
|
|
62
|
+
const incoming = new Map(values.map((entry) => [entry.field, entry.value]));
|
|
63
|
+
const coercedAnswers = {};
|
|
64
|
+
const coercedByName = /* @__PURE__ */ new Map();
|
|
65
|
+
for (const instance of fields) {
|
|
66
|
+
const definition = registry.get(instance.blockType);
|
|
67
|
+
const raw = incoming.get(instance.name);
|
|
68
|
+
if (!definition || calcExpressionOf(instance)) continue;
|
|
69
|
+
const effectiveRaw = instance.blockType === "consent" && isEmpty(raw) ? false : instance.blockType === "repeater" && isEmpty(raw) ? [] : raw;
|
|
70
|
+
if (isEmpty(effectiveRaw) && instance.blockType !== "repeater") continue;
|
|
71
|
+
const value = coerce(definition.value, effectiveRaw);
|
|
72
|
+
coercedAnswers[instance.name] = value;
|
|
73
|
+
coercedByName.set(instance.name, value);
|
|
74
|
+
}
|
|
75
|
+
const effective = computeCalcFields(fields, coercedAnswers);
|
|
76
|
+
const errors = [];
|
|
77
|
+
const outValues = [];
|
|
78
|
+
const descriptors = [];
|
|
79
|
+
const consentProofs = [];
|
|
80
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
81
|
+
for (const instance of fields) {
|
|
82
|
+
const definition = registry.get(instance.blockType);
|
|
83
|
+
if (!definition) continue;
|
|
84
|
+
const raw = incoming.get(instance.name);
|
|
85
|
+
const value = coercedByName.has(instance.name) ? coercedByName.get(instance.name) : raw;
|
|
86
|
+
if (!evaluateCondition(instance.visibleWhen, effective)) continue;
|
|
87
|
+
if (calcExpressionOf(instance)) {
|
|
88
|
+
outValues.push({
|
|
89
|
+
field: instance.name,
|
|
90
|
+
value: effective[instance.name]
|
|
91
|
+
});
|
|
92
|
+
descriptors.push({
|
|
93
|
+
field: instance.name,
|
|
94
|
+
label: instance.label ?? instance.name,
|
|
95
|
+
fieldType: instance.blockType
|
|
96
|
+
});
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
if (evaluateCondition(instance.validateWhen, effective)) {
|
|
100
|
+
const { errors: issues } = await runValidation({
|
|
101
|
+
field: instance,
|
|
102
|
+
fieldDefinition: definition,
|
|
103
|
+
value,
|
|
104
|
+
fieldType: instance.blockType,
|
|
105
|
+
ruleRegistry,
|
|
106
|
+
answers: effective,
|
|
107
|
+
locale,
|
|
108
|
+
t,
|
|
109
|
+
operation,
|
|
110
|
+
event: "submit",
|
|
111
|
+
mode: "server",
|
|
112
|
+
req,
|
|
113
|
+
payload,
|
|
114
|
+
formId
|
|
115
|
+
});
|
|
116
|
+
const blocking = issues.filter((issue) => issue.severity === "error");
|
|
117
|
+
if (blocking.length > 0) {
|
|
118
|
+
for (const issue of blocking) errors.push({
|
|
119
|
+
path: instance.name,
|
|
120
|
+
message: issue.message
|
|
121
|
+
});
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (instance.blockType === "file") {
|
|
126
|
+
if (isEmpty(value)) continue;
|
|
127
|
+
if (payload) {
|
|
128
|
+
const fileConfig = fileFieldConfigOf(instance);
|
|
129
|
+
const captured = await captureFileRef({
|
|
130
|
+
payload,
|
|
131
|
+
collectionSlug: fileConfig.relationTo ?? uploadSlug ?? "form-uploads",
|
|
132
|
+
uploadId: value,
|
|
133
|
+
config: fileConfig,
|
|
134
|
+
req,
|
|
135
|
+
expectedOwner
|
|
136
|
+
});
|
|
137
|
+
if (!captured.ok) {
|
|
138
|
+
errors.push({
|
|
139
|
+
path: instance.name,
|
|
140
|
+
message: t(errorKeyFor(captured.code))
|
|
141
|
+
});
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
outValues.push({
|
|
145
|
+
field: instance.name,
|
|
146
|
+
value: captured.ref
|
|
147
|
+
});
|
|
148
|
+
descriptors.push({
|
|
149
|
+
field: instance.name,
|
|
150
|
+
label: instance.label ?? instance.name,
|
|
151
|
+
fieldType: instance.blockType
|
|
152
|
+
});
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
outValues.push({
|
|
156
|
+
field: instance.name,
|
|
157
|
+
value
|
|
158
|
+
});
|
|
159
|
+
descriptors.push({
|
|
160
|
+
field: instance.name,
|
|
161
|
+
label: instance.label ?? instance.name,
|
|
162
|
+
fieldType: instance.blockType
|
|
163
|
+
});
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
if (instance.blockType === "consent" && payload) {
|
|
167
|
+
const proof = await captureConsent({
|
|
168
|
+
field: instance,
|
|
169
|
+
agreed: value === true,
|
|
170
|
+
registry: consentRegistry,
|
|
171
|
+
payload,
|
|
172
|
+
req,
|
|
173
|
+
locale,
|
|
174
|
+
now
|
|
175
|
+
});
|
|
176
|
+
consentProofs.push({
|
|
177
|
+
field: instance.name,
|
|
178
|
+
...proof
|
|
179
|
+
});
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
if (instance.blockType === "repeater") {
|
|
183
|
+
const rows = Array.isArray(value) ? value : [];
|
|
184
|
+
const subFields = Array.isArray(instance.subFields) ? instance.subFields : [];
|
|
185
|
+
for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) {
|
|
186
|
+
const row = rows[rowIndex] ?? {};
|
|
187
|
+
for (const subField of subFields) {
|
|
188
|
+
const subDef = registry.get(subField.blockType);
|
|
189
|
+
if (!subDef) continue;
|
|
190
|
+
if (!evaluateCondition(subField.visibleWhen, row)) continue;
|
|
191
|
+
if (!evaluateCondition(subField.validateWhen, row)) continue;
|
|
192
|
+
const subValue = row[subField.name];
|
|
193
|
+
const { errors: subErrors } = await runValidation({
|
|
194
|
+
field: subField,
|
|
195
|
+
fieldDefinition: subDef,
|
|
196
|
+
value: subValue,
|
|
197
|
+
fieldType: subField.blockType,
|
|
198
|
+
ruleRegistry,
|
|
199
|
+
answers: row,
|
|
200
|
+
locale,
|
|
201
|
+
t,
|
|
202
|
+
operation,
|
|
203
|
+
event: "submit",
|
|
204
|
+
mode: "server",
|
|
205
|
+
req,
|
|
206
|
+
payload,
|
|
207
|
+
formId
|
|
208
|
+
});
|
|
209
|
+
for (const issue of subErrors.filter((e) => e.severity === "error")) errors.push({
|
|
210
|
+
path: `${instance.name}[${rowIndex}].${subField.name}`,
|
|
211
|
+
message: issue.message
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if (errors.length > 0) continue;
|
|
216
|
+
const subFieldDescriptors = subFields.map((sf) => ({
|
|
217
|
+
field: sf.name,
|
|
218
|
+
label: sf.label ?? sf.name,
|
|
219
|
+
fieldType: sf.blockType,
|
|
220
|
+
...sf.options ? { optionLabels: optionLabelsFor(sf) ?? void 0 } : {}
|
|
221
|
+
}));
|
|
222
|
+
outValues.push({
|
|
223
|
+
field: instance.name,
|
|
224
|
+
value: rows
|
|
225
|
+
});
|
|
226
|
+
descriptors.push({
|
|
227
|
+
field: instance.name,
|
|
228
|
+
label: instance.label ?? instance.name,
|
|
229
|
+
fieldType: instance.blockType,
|
|
230
|
+
...subFieldDescriptors.length > 0 ? { subFieldDescriptors } : {}
|
|
231
|
+
});
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
if (isEmpty(raw)) continue;
|
|
235
|
+
outValues.push({
|
|
236
|
+
field: instance.name,
|
|
237
|
+
value
|
|
238
|
+
});
|
|
239
|
+
const optionLabels = optionLabelsFor(instance);
|
|
240
|
+
descriptors.push({
|
|
241
|
+
field: instance.name,
|
|
242
|
+
label: instance.label ?? instance.name,
|
|
243
|
+
fieldType: instance.blockType,
|
|
244
|
+
...optionLabels ? { optionLabels } : {}
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
return {
|
|
248
|
+
errors,
|
|
249
|
+
values: outValues,
|
|
250
|
+
descriptors,
|
|
251
|
+
consent: consentProofs
|
|
252
|
+
};
|
|
253
|
+
};
|
|
254
|
+
//#endregion
|
|
255
|
+
export { runSubmission };
|
|
256
|
+
|
|
257
|
+
//# sourceMappingURL=runSubmission.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runSubmission.js","names":[],"sources":["../../src/submissions/runSubmission.ts"],"sourcesContent":["import type { Payload, PayloadRequest } from 'payload'\nimport { calcExpressionOf, computeCalcFields } from '../calc/computeCalcFields'\nimport { evaluateCondition } from '../conditions/evaluate'\nimport type { ConsentProof } from '../consent/captureConsent'\nimport { captureConsent } from '../consent/captureConsent'\nimport type { ConsentSourceRegistry } from '../consent/registry'\nimport type { FieldTypeRegistry } from '../fields/registry'\nimport type { Translate } from '../fields/types'\nimport { keys } from '../translations/keys'\nimport { captureFileRef } from '../uploads/captureFileRef'\nimport type { FileFieldConfig, FileRefError } from '../uploads/types'\nimport type { ValidationRuleRegistry } from '../validation/registry'\nimport { runValidation } from '../validation/runValidation'\nimport type {\n\tFormFieldInstance,\n\tSubmissionDescriptor,\n\tSubmissionFieldError,\n\tSubmissionValue,\n} from './types'\n\nconst errorKeyFor = (code: FileRefError): string => {\n\tif (code === 'mimeType') {\n\t\treturn keys.validationFileMimeType\n\t}\n\tif (code === 'tooLarge') {\n\t\treturn keys.validationFileTooLarge\n\t}\n\treturn keys.validationFileMissing\n}\n\n/** Normalize the authored `mimeTypes` (a `hasMany` text field) to a `string[]`. */\nconst mimeTypesOf = (raw: unknown): string[] | undefined => {\n\tif (!Array.isArray(raw)) {\n\t\treturn undefined\n\t}\n\tconst out = (raw as unknown[]).filter((entry): entry is string => typeof entry === 'string')\n\treturn out.length > 0 ? out : undefined\n}\n\nconst fileFieldConfigOf = (instance: FormFieldInstance): FileFieldConfig => ({\n\trelationTo: typeof instance.relationTo === 'string' ? instance.relationTo : undefined,\n\tmimeTypes: mimeTypesOf(instance.mimeTypes),\n\tmaxSize: typeof instance.maxSize === 'number' ? instance.maxSize : undefined,\n})\n\nconst isEmpty = (value: unknown): boolean =>\n\tvalue == null || value === '' || (Array.isArray(value) && value.length === 0)\n\nconst coerce = (kind: string, value: unknown): unknown => {\n\tif (value == null) {\n\t\treturn value\n\t}\n\tif (kind === 'number') {\n\t\tconst next = typeof value === 'number' ? value : Number(value)\n\t\treturn Number.isNaN(next) ? value : next\n\t}\n\tif (kind === 'boolean') {\n\t\t// A genuine boolean from the renderer passes through; a raw client string is parsed strictly so that\n\t\t// \"false\"/\"0\"/\"off\"/\"no\"/\"\" are not silently truthy (this matters for the required-consent check).\n\t\tif (typeof value === 'string') {\n\t\t\tconst normalized = value.trim().toLowerCase()\n\t\t\treturn !(\n\t\t\t\tnormalized === '' ||\n\t\t\t\tnormalized === 'false' ||\n\t\t\t\tnormalized === '0' ||\n\t\t\t\tnormalized === 'off' ||\n\t\t\t\tnormalized === 'no'\n\t\t\t)\n\t\t}\n\t\treturn Boolean(value)\n\t}\n\tif (kind === 'text') {\n\t\treturn typeof value === 'string' ? value : String(value)\n\t}\n\treturn value\n}\n\nconst optionLabelsFor = (instance: FormFieldInstance): Record<string, string> | undefined => {\n\tconst options = instance.options\n\tif (!Array.isArray(options)) {\n\t\treturn undefined\n\t}\n\tconst map: Record<string, string> = {}\n\tfor (const option of options as Array<{ label?: string; value?: string }>) {\n\t\tif (typeof option?.value === 'string') {\n\t\t\tmap[option.value] = option.label ?? option.value\n\t\t}\n\t}\n\treturn Object.keys(map).length > 0 ? map : undefined\n}\n\nexport type ConsentProofEntry = { field: string } & ConsentProof\n\nexport type RunSubmissionInput = {\n\tfields: FormFieldInstance[]\n\tvalues: SubmissionValue[]\n\tregistry: FieldTypeRegistry\n\truleRegistry: ValidationRuleRegistry\n\tconsentRegistry: ConsentSourceRegistry\n\tlocale: string\n\tt: Translate\n\toperation: 'create' | 'update'\n\treq?: PayloadRequest\n\tpayload?: Payload\n\tformId?: number | string\n\t/** Upload collection slug for file fields without an explicit `relationTo`. Defaults to `form-uploads`. */\n\tuploadSlug?: string\n\t/** Resolved request identity, verified against an upload's `owner` stamp when a file field is captured. */\n\texpectedOwner?: string\n}\n\nexport type RunSubmissionResult = {\n\terrors: SubmissionFieldError[]\n\tvalues: SubmissionValue[]\n\tdescriptors: SubmissionDescriptor[]\n\tconsent: ConsentProofEntry[]\n}\n\n/**\n * Pure submission core, two-pass: first coerce every answered field to its typed kind (so cross-field\n * rules see coerced siblings), then validate each field through `runValidation` (required, intrinsic\n * facet, declarative rules), snapshotting a localized descriptor per answered field. Calc fields are\n * the trust boundary: their client-sent values are never seeded, their values are derived from their\n * expressions over the coerced answers, and those derived values are authoritative everywhere downstream\n * (conditions, validation, storage). Conditions gate the second pass against these effective answers: a\n * field whose `visibleWhen` is false is skipped entirely (never validated, never stored, so a client-sent\n * value for it is ignored), and a visible field whose `validateWhen` is false stores its value but skips\n * validation. A visible calc field stores its derived value and is never validated. Only `error` severity\n * blocks; warnings are computed but not surfaced server-side (the renderer surfaces them).\n */\nexport const runSubmission = async (input: RunSubmissionInput): Promise<RunSubmissionResult> => {\n\tconst {\n\t\tfields,\n\t\tvalues,\n\t\tregistry,\n\t\truleRegistry,\n\t\tconsentRegistry,\n\t\tlocale,\n\t\tt,\n\t\toperation,\n\t\treq,\n\t\tpayload,\n\t\tformId,\n\t\tuploadSlug,\n\t\texpectedOwner,\n\t} = input\n\tconst incoming = new Map(values.map((entry) => [entry.field, entry.value]))\n\n\tconst coercedAnswers: Record<string, unknown> = {}\n\tconst coercedByName = new Map<string, unknown>()\n\tfor (const instance of fields) {\n\t\tconst definition = registry.get(instance.blockType)\n\t\tconst raw = incoming.get(instance.name)\n\t\t// Never seed a calc field's client value: its value is derived below, so the client cannot influence it (even for a self-referencing expression).\n\t\tif (!definition || calcExpressionOf(instance)) {\n\t\t\tcontinue\n\t\t}\n\t\t// A consent field's \"not agreed\" state is semantically meaningful: treat a missing value as\n\t\t// `false` so the intrinsic validate can enforce required-agreement (not optional = must be true).\n\t\t// A repeater with no rows is coerced to [] so validate() can check minRows. The empty-guard\n\t\t// below must not skip repeaters: isEmpty([]) is true, but [] still needs to reach validate()\n\t\t// so a minRows > 0 constraint correctly rejects a zero-row submission.\n\t\tconst effectiveRaw =\n\t\t\tinstance.blockType === 'consent' && isEmpty(raw)\n\t\t\t\t? false\n\t\t\t\t: instance.blockType === 'repeater' && isEmpty(raw)\n\t\t\t\t\t? []\n\t\t\t\t\t: raw\n\t\tif (isEmpty(effectiveRaw) && instance.blockType !== 'repeater') {\n\t\t\tcontinue\n\t\t}\n\t\tconst value = coerce(definition.value, effectiveRaw)\n\t\tcoercedAnswers[instance.name] = value\n\t\tcoercedByName.set(instance.name, value)\n\t}\n\n\t// Calc values are authoritative everywhere downstream (conditions, validation, storage), never the client-sent value.\n\tconst effective = computeCalcFields(fields, coercedAnswers)\n\n\tconst errors: SubmissionFieldError[] = []\n\tconst outValues: SubmissionValue[] = []\n\tconst descriptors: SubmissionDescriptor[] = []\n\tconst consentProofs: ConsentProofEntry[] = []\n\tconst now = new Date().toISOString()\n\n\tfor (const instance of fields) {\n\t\tconst definition = registry.get(instance.blockType)\n\t\tif (!definition) {\n\t\t\tcontinue\n\t\t}\n\t\tconst raw = incoming.get(instance.name)\n\t\tconst value = coercedByName.has(instance.name) ? coercedByName.get(instance.name) : raw\n\n\t\tif (!evaluateCondition(instance.visibleWhen, effective)) {\n\t\t\tcontinue\n\t\t}\n\n\t\t// A calc field's value is server-derived and always valid: skip validation and the client value entirely, storing the computed result.\n\t\tif (calcExpressionOf(instance)) {\n\t\t\toutValues.push({ field: instance.name, value: effective[instance.name] })\n\t\t\tdescriptors.push({\n\t\t\t\tfield: instance.name,\n\t\t\t\tlabel: instance.label ?? instance.name,\n\t\t\t\tfieldType: instance.blockType,\n\t\t\t})\n\t\t\tcontinue\n\t\t}\n\n\t\tif (evaluateCondition(instance.validateWhen, effective)) {\n\t\t\tconst { errors: issues } = await runValidation({\n\t\t\t\tfield: instance,\n\t\t\t\tfieldDefinition: definition,\n\t\t\t\tvalue,\n\t\t\t\tfieldType: instance.blockType,\n\t\t\t\truleRegistry,\n\t\t\t\tanswers: effective,\n\t\t\t\tlocale,\n\t\t\t\tt,\n\t\t\t\toperation,\n\t\t\t\tevent: 'submit',\n\t\t\t\tmode: 'server',\n\t\t\t\treq,\n\t\t\t\tpayload,\n\t\t\t\tformId,\n\t\t\t})\n\t\t\tconst blocking = issues.filter((issue) => issue.severity === 'error')\n\t\t\tif (blocking.length > 0) {\n\t\t\t\tfor (const issue of blocking) {\n\t\t\t\t\terrors.push({ path: instance.name, message: issue.message })\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\n\t\tif (instance.blockType === 'file') {\n\t\t\tif (isEmpty(value)) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif (payload) {\n\t\t\t\tconst fileConfig = fileFieldConfigOf(instance)\n\t\t\t\tconst slug = fileConfig.relationTo ?? uploadSlug ?? 'form-uploads'\n\t\t\t\tconst captured = await captureFileRef({\n\t\t\t\t\tpayload,\n\t\t\t\t\tcollectionSlug: slug,\n\t\t\t\t\tuploadId: value as string | number,\n\t\t\t\t\tconfig: fileConfig,\n\t\t\t\t\treq,\n\t\t\t\t\texpectedOwner,\n\t\t\t\t})\n\t\t\t\tif (!captured.ok) {\n\t\t\t\t\terrors.push({ path: instance.name, message: t(errorKeyFor(captured.code)) })\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\toutValues.push({ field: instance.name, value: captured.ref })\n\t\t\t\tdescriptors.push({\n\t\t\t\t\tfield: instance.name,\n\t\t\t\t\tlabel: instance.label ?? instance.name,\n\t\t\t\t\tfieldType: instance.blockType,\n\t\t\t\t})\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\toutValues.push({ field: instance.name, value })\n\t\t\tdescriptors.push({\n\t\t\t\tfield: instance.name,\n\t\t\t\tlabel: instance.label ?? instance.name,\n\t\t\t\tfieldType: instance.blockType,\n\t\t\t})\n\t\t\tcontinue\n\t\t}\n\n\t\tif (instance.blockType === 'consent' && payload) {\n\t\t\tconst proof = await captureConsent({\n\t\t\t\tfield: instance,\n\t\t\t\tagreed: value === true,\n\t\t\t\tregistry: consentRegistry,\n\t\t\t\tpayload,\n\t\t\t\treq,\n\t\t\t\tlocale,\n\t\t\t\tnow,\n\t\t\t})\n\t\t\tconsentProofs.push({ field: instance.name, ...proof })\n\t\t\tcontinue\n\t\t}\n\n\t\tif (instance.blockType === 'repeater') {\n\t\t\tconst rows = Array.isArray(value) ? (value as Array<Record<string, unknown>>) : []\n\t\t\tconst subFields = Array.isArray(instance.subFields)\n\t\t\t\t? (instance.subFields as FormFieldInstance[])\n\t\t\t\t: []\n\n\t\t\t// Per-row sub-field validation: evaluate each sub-field's visibleWhen against the\n\t\t\t// row's own values, then run its validation rules. Errors are reported with path\n\t\t\t// fieldName[rowIndex].subFieldName so the client can map them to the right input.\n\t\t\tfor (let rowIndex = 0; rowIndex < rows.length; rowIndex++) {\n\t\t\t\tconst row = rows[rowIndex] ?? {}\n\t\t\t\tfor (const subField of subFields) {\n\t\t\t\t\tconst subDef = registry.get(subField.blockType)\n\t\t\t\t\tif (!subDef) continue\n\t\t\t\t\tif (!evaluateCondition(subField.visibleWhen, row)) continue\n\t\t\t\t\tif (!evaluateCondition(subField.validateWhen, row)) continue\n\t\t\t\t\tconst subValue = row[subField.name]\n\t\t\t\t\tconst { errors: subErrors } = await runValidation({\n\t\t\t\t\t\tfield: subField,\n\t\t\t\t\t\tfieldDefinition: subDef,\n\t\t\t\t\t\tvalue: subValue,\n\t\t\t\t\t\tfieldType: subField.blockType,\n\t\t\t\t\t\truleRegistry,\n\t\t\t\t\t\tanswers: row,\n\t\t\t\t\t\tlocale,\n\t\t\t\t\t\tt,\n\t\t\t\t\t\toperation,\n\t\t\t\t\t\tevent: 'submit',\n\t\t\t\t\t\tmode: 'server',\n\t\t\t\t\t\treq,\n\t\t\t\t\t\tpayload,\n\t\t\t\t\t\tformId,\n\t\t\t\t\t})\n\t\t\t\t\tfor (const issue of subErrors.filter((e) => e.severity === 'error')) {\n\t\t\t\t\t\terrors.push({\n\t\t\t\t\t\t\tpath: `${instance.name}[${rowIndex}].${subField.name}`,\n\t\t\t\t\t\t\tmessage: issue.message,\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (errors.length > 0) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tconst subFieldDescriptors: SubmissionDescriptor[] = subFields.map((sf) => ({\n\t\t\t\tfield: sf.name,\n\t\t\t\tlabel: sf.label ?? sf.name,\n\t\t\t\tfieldType: sf.blockType,\n\t\t\t\t...((sf.options as unknown) ? { optionLabels: optionLabelsFor(sf) ?? undefined } : {}),\n\t\t\t}))\n\n\t\t\toutValues.push({ field: instance.name, value: rows })\n\t\t\tdescriptors.push({\n\t\t\t\tfield: instance.name,\n\t\t\t\tlabel: instance.label ?? instance.name,\n\t\t\t\tfieldType: instance.blockType,\n\t\t\t\t...(subFieldDescriptors.length > 0 ? { subFieldDescriptors } : {}),\n\t\t\t})\n\t\t\tcontinue\n\t\t}\n\n\t\tif (isEmpty(raw)) {\n\t\t\tcontinue\n\t\t}\n\n\t\toutValues.push({ field: instance.name, value })\n\t\tconst optionLabels = optionLabelsFor(instance)\n\t\tdescriptors.push({\n\t\t\tfield: instance.name,\n\t\t\tlabel: instance.label ?? instance.name,\n\t\t\tfieldType: instance.blockType,\n\t\t\t...(optionLabels ? { optionLabels } : {}),\n\t\t})\n\t}\n\n\treturn { errors, values: outValues, descriptors, consent: consentProofs }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Where } from "payload";
|
|
2
|
+
|
|
3
|
+
//#region src/submissions/types.d.ts
|
|
4
|
+
/** A single answered field: the field's machine name and its typed value. */
|
|
5
|
+
type SubmissionValue = {
|
|
6
|
+
field: string;
|
|
7
|
+
value: unknown;
|
|
8
|
+
};
|
|
9
|
+
/** A localized, self-describing snapshot of an answered field, taken at submit time. */
|
|
10
|
+
type SubmissionDescriptor = {
|
|
11
|
+
field: string;
|
|
12
|
+
label: string;
|
|
13
|
+
fieldType: string;
|
|
14
|
+
optionLabels?: Record<string, string>; /** For repeater fields: one descriptor per sub-field, shared across all rows. */
|
|
15
|
+
subFieldDescriptors?: SubmissionDescriptor[];
|
|
16
|
+
};
|
|
17
|
+
/** A per-field validation failure (`path` is the field name, for renderer error mapping). */
|
|
18
|
+
type SubmissionFieldError = {
|
|
19
|
+
path: string;
|
|
20
|
+
message: string;
|
|
21
|
+
};
|
|
22
|
+
/** A field instance as stored in a form's `fields` blocks array (shared config plus type-specific keys). */
|
|
23
|
+
type FormFieldInstance = {
|
|
24
|
+
blockType: string;
|
|
25
|
+
name: string;
|
|
26
|
+
label?: string;
|
|
27
|
+
required?: boolean;
|
|
28
|
+
visibleWhen?: Where;
|
|
29
|
+
validateWhen?: Where;
|
|
30
|
+
[key: string]: unknown;
|
|
31
|
+
};
|
|
32
|
+
//#endregion
|
|
33
|
+
export { FormFieldInstance, SubmissionDescriptor, SubmissionFieldError, SubmissionValue };
|
|
34
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { asFieldTranslate } from "../translations/server.js";
|
|
2
|
+
import { IDENTITY_CONTEXT_KEY } from "../spam/constants.js";
|
|
3
|
+
import "../collections/forms.js";
|
|
4
|
+
import { runSubmission } from "./runSubmission.js";
|
|
5
|
+
import { FORM_SUBMISSIONS_SLUG } from "../collections/formSubmissions.js";
|
|
6
|
+
import { ValidationError } from "payload";
|
|
7
|
+
//#region src/submissions/validateSubmission.ts
|
|
8
|
+
/**
|
|
9
|
+
* Server-authoritative submission validation. On create it loads the referenced form, re-runs every
|
|
10
|
+
* field's required check, intrinsic validator, and declarative rules through `runSubmission`, threading
|
|
11
|
+
* `req`/`payload` so server-only async rules can hit the DB, and throws a Payload `ValidationError` with
|
|
12
|
+
* per-field paths on any error-severity failure. The client is never trusted.
|
|
13
|
+
* Consent fields are captured into `result.consent` (array of proofs, one per visible consent field).
|
|
14
|
+
*/
|
|
15
|
+
const validateSubmission = ({ registry, ruleRegistry, consentRegistry, uploadSlug }) => async ({ data, operation, req }) => {
|
|
16
|
+
if (operation !== "create" || !data) return data;
|
|
17
|
+
const formId = data.form;
|
|
18
|
+
if (formId == null) return data;
|
|
19
|
+
const fields = (await req.payload.findByID({
|
|
20
|
+
collection: "forms",
|
|
21
|
+
id: formId,
|
|
22
|
+
depth: 0,
|
|
23
|
+
locale: req.locale,
|
|
24
|
+
req
|
|
25
|
+
})).fields ?? [];
|
|
26
|
+
const incoming = data.values ?? [];
|
|
27
|
+
const locale = req.locale ?? "en";
|
|
28
|
+
const t = asFieldTranslate(req.i18n.t);
|
|
29
|
+
const expectedOwner = typeof req.context?.["formBuilderSpamIdentity"] === "string" ? req.context[IDENTITY_CONTEXT_KEY] : void 0;
|
|
30
|
+
const result = await runSubmission({
|
|
31
|
+
fields,
|
|
32
|
+
values: incoming,
|
|
33
|
+
registry,
|
|
34
|
+
ruleRegistry,
|
|
35
|
+
consentRegistry,
|
|
36
|
+
locale,
|
|
37
|
+
t,
|
|
38
|
+
operation: "create",
|
|
39
|
+
req,
|
|
40
|
+
payload: req.payload,
|
|
41
|
+
formId,
|
|
42
|
+
uploadSlug,
|
|
43
|
+
expectedOwner
|
|
44
|
+
});
|
|
45
|
+
if (result.errors.length > 0) throw new ValidationError({
|
|
46
|
+
collection: FORM_SUBMISSIONS_SLUG,
|
|
47
|
+
errors: result.errors
|
|
48
|
+
}, req.t);
|
|
49
|
+
data.values = result.values;
|
|
50
|
+
data.descriptors = result.descriptors;
|
|
51
|
+
data.consent = result.consent.length > 0 ? result.consent : void 0;
|
|
52
|
+
data.locale = locale;
|
|
53
|
+
if (!req.user) data.status = "complete";
|
|
54
|
+
return data;
|
|
55
|
+
};
|
|
56
|
+
//#endregion
|
|
57
|
+
export { validateSubmission };
|
|
58
|
+
|
|
59
|
+
//# sourceMappingURL=validateSubmission.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validateSubmission.js","names":[],"sources":["../../src/submissions/validateSubmission.ts"],"sourcesContent":["import { type CollectionBeforeValidateHook, ValidationError } from 'payload'\nimport { FORM_SUBMISSIONS_SLUG } from '../collections/formSubmissions'\nimport { FORMS_SLUG } from '../collections/forms'\nimport type { ConsentSourceRegistry } from '../consent/registry'\nimport type { FieldTypeRegistry } from '../fields/registry'\nimport { IDENTITY_CONTEXT_KEY } from '../spam/constants'\nimport { asFieldTranslate } from '../translations/server'\nimport type { ValidationRuleRegistry } from '../validation/registry'\nimport { runSubmission } from './runSubmission'\nimport type { FormFieldInstance, SubmissionValue } from './types'\n\nexport type ValidateSubmissionArgs = {\n\tregistry: FieldTypeRegistry\n\truleRegistry: ValidationRuleRegistry\n\tconsentRegistry: ConsentSourceRegistry\n\t/** Upload collection slug for file fields without an explicit `relationTo`. */\n\tuploadSlug?: string\n}\n\n/**\n * Server-authoritative submission validation. On create it loads the referenced form, re-runs every\n * field's required check, intrinsic validator, and declarative rules through `runSubmission`, threading\n * `req`/`payload` so server-only async rules can hit the DB, and throws a Payload `ValidationError` with\n * per-field paths on any error-severity failure. The client is never trusted.\n * Consent fields are captured into `result.consent` (array of proofs, one per visible consent field).\n */\nexport const validateSubmission =\n\t({\n\t\tregistry,\n\t\truleRegistry,\n\t\tconsentRegistry,\n\t\tuploadSlug,\n\t}: ValidateSubmissionArgs): CollectionBeforeValidateHook =>\n\tasync ({ data, operation, req }) => {\n\t\tif (operation !== 'create' || !data) {\n\t\t\treturn data\n\t\t}\n\t\tconst formId = data.form\n\t\tif (formId == null) {\n\t\t\treturn data\n\t\t}\n\n\t\tconst form = await req.payload.findByID({\n\t\t\tcollection: FORMS_SLUG,\n\t\t\tid: formId as string | number,\n\t\t\tdepth: 0,\n\t\t\tlocale: req.locale,\n\t\t\treq,\n\t\t})\n\n\t\tconst fields = ((form.fields as FormFieldInstance[] | undefined) ?? []) as FormFieldInstance[]\n\t\tconst incoming = ((data.values as SubmissionValue[] | undefined) ?? []) as SubmissionValue[]\n\t\tconst locale = req.locale ?? 'en'\n\t\tconst t = asFieldTranslate(req.i18n.t)\n\t\tconst expectedOwner =\n\t\t\ttypeof req.context?.[IDENTITY_CONTEXT_KEY] === 'string'\n\t\t\t\t? (req.context[IDENTITY_CONTEXT_KEY] as string)\n\t\t\t\t: undefined\n\n\t\tconst result = await runSubmission({\n\t\t\tfields,\n\t\t\tvalues: incoming,\n\t\t\tregistry,\n\t\t\truleRegistry,\n\t\t\tconsentRegistry,\n\t\t\tlocale,\n\t\t\tt,\n\t\t\toperation: 'create',\n\t\t\treq,\n\t\t\tpayload: req.payload,\n\t\t\tformId: formId as number | string,\n\t\t\tuploadSlug,\n\t\t\texpectedOwner,\n\t\t})\n\n\t\tif (result.errors.length > 0) {\n\t\t\tthrow new ValidationError({ collection: FORM_SUBMISSIONS_SLUG, errors: result.errors }, req.t)\n\t\t}\n\n\t\tdata.values = result.values\n\t\tdata.descriptors = result.descriptors\n\t\tdata.consent = result.consent.length > 0 ? result.consent : undefined\n\t\tdata.locale = locale\n\t\t// Unauthenticated submits are always 'complete'. A client-supplied 'partial' would\n\t\t// silently skip all post-submit actions and events. Authenticated callers (e.g. an\n\t\t// admin draft-save flow) may set status themselves.\n\t\tif (!req.user) {\n\t\t\tdata.status = 'complete'\n\t\t}\n\t\treturn data\n\t}\n"],"mappings":";;;;;;;;;;;;;;AA0BA,MAAa,sBACX,EACA,UACA,cACA,iBACA,iBAED,OAAO,EAAE,MAAM,WAAW,UAAU;CACnC,IAAI,cAAc,YAAY,CAAC,MAC9B,OAAO;CAER,MAAM,SAAS,KAAK;CACpB,IAAI,UAAU,MACb,OAAO;CAWR,MAAM,UAAW,MARE,IAAI,QAAQ,SAAS;EACvC,YAAA;EACA,IAAI;EACJ,OAAO;EACP,QAAQ,IAAI;EACZ;CACD,CAAC,GAEqB,UAA8C,CAAC;CACrE,MAAM,WAAa,KAAK,UAA4C,CAAC;CACrE,MAAM,SAAS,IAAI,UAAU;CAC7B,MAAM,IAAI,iBAAiB,IAAI,KAAK,CAAC;CACrC,MAAM,gBACL,OAAO,IAAI,UAAA,+BAAoC,WAC3C,IAAI,QAAQ,wBACb,KAAA;CAEJ,MAAM,SAAS,MAAM,cAAc;EAClC;EACA,QAAQ;EACR;EACA;EACA;EACA;EACA;EACA,WAAW;EACX;EACA,SAAS,IAAI;EACL;EACR;EACA;CACD,CAAC;CAED,IAAI,OAAO,OAAO,SAAS,GAC1B,MAAM,IAAI,gBAAgB;EAAE,YAAY;EAAuB,QAAQ,OAAO;CAAO,GAAG,IAAI,CAAC;CAG9F,KAAK,SAAS,OAAO;CACrB,KAAK,cAAc,OAAO;CAC1B,KAAK,UAAU,OAAO,QAAQ,SAAS,IAAI,OAAO,UAAU,KAAA;CAC5D,KAAK,SAAS;CAId,IAAI,CAAC,IAAI,MACR,KAAK,SAAS;CAEf,OAAO;AACR"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { TranslationKey } from "./keys.js";
|
|
2
|
+
|
|
3
|
+
//#region src/translations/en.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* English values, keyed by the typed constants in `keys.ts` so the two stay in
|
|
6
|
+
* lockstep. The `Record<TranslationKey, string>` annotation makes a missing or
|
|
7
|
+
* unknown key a type error. `translations/index.ts` nests these for Payload.
|
|
8
|
+
*/
|
|
9
|
+
declare const en: Record<TranslationKey, string>;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { en };
|
|
12
|
+
//# sourceMappingURL=en.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { keys } from "./keys.js";
|
|
2
2
|
//#region src/translations/en.ts
|
|
3
3
|
/**
|
|
4
4
|
* English values, keyed by the typed constants in `keys.ts` so the two stay in
|
|
@@ -125,28 +125,34 @@ const en = {
|
|
|
125
125
|
[keys.fileConfigMaxSize]: "Maximum size (bytes)",
|
|
126
126
|
[keys.spamRateLimited]: "You have sent too many requests. Please try again later.",
|
|
127
127
|
[keys.spamRejected]: "Your submission could not be processed.",
|
|
128
|
-
[keys.spamCaptchaFailed]: "Captcha verification failed. Please try again."
|
|
128
|
+
[keys.spamCaptchaFailed]: "Captcha verification failed. Please try again.",
|
|
129
|
+
[keys.collectionFormSingular]: "Form",
|
|
130
|
+
[keys.collectionFormPlural]: "Forms",
|
|
131
|
+
[keys.collectionSubmissionSingular]: "Submission",
|
|
132
|
+
[keys.collectionSubmissionPlural]: "Submissions",
|
|
133
|
+
[keys.statusComplete]: "Complete",
|
|
134
|
+
[keys.statusPartial]: "Partial",
|
|
135
|
+
[keys.fieldTypeRepeater]: "Repeater",
|
|
136
|
+
[keys.configMinRows]: "Minimum rows",
|
|
137
|
+
[keys.configMaxRows]: "Maximum rows",
|
|
138
|
+
[keys.configAddLabel]: "Add button label",
|
|
139
|
+
[keys.configSubFields]: "Sub-fields",
|
|
140
|
+
[keys.validationRepeaterMin]: "Add at least {min} row(s)",
|
|
141
|
+
[keys.validationRepeaterMax]: "Remove rows to stay within {max}",
|
|
142
|
+
[keys.repeaterAddRow]: "Add row",
|
|
143
|
+
[keys.repeaterRemoveRow]: "Remove",
|
|
144
|
+
[keys.repeaterRow]: "Row {n}",
|
|
145
|
+
[keys.repeaterRowCount]: "{count} row(s)",
|
|
146
|
+
[keys.submissionConsent]: "Consent",
|
|
147
|
+
[keys.submissionDetails]: "Submission details",
|
|
148
|
+
[keys.submissionConsentAgreed]: "Agreed",
|
|
149
|
+
[keys.submissionConsentDeclined]: "Declined",
|
|
150
|
+
[keys.submissionMetaReceivedAt]: "Received at",
|
|
151
|
+
[keys.submissionMetaIp]: "IP address",
|
|
152
|
+
[keys.submissionMetaUserAgent]: "User agent",
|
|
153
|
+
[keys.submissionMetaCaptcha]: "Captcha"
|
|
129
154
|
};
|
|
130
155
|
//#endregion
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Flat `formBuilder:foo` entries to the nested `{ formBuilder: { foo } }`
|
|
134
|
-
* shape Payload resolves `t('formBuilder:foo')` against (it splits on `:`).
|
|
135
|
-
*/
|
|
136
|
-
const toNested = (flat) => {
|
|
137
|
-
const out = {};
|
|
138
|
-
for (const [fullKey, value] of Object.entries(flat)) {
|
|
139
|
-
const separator = fullKey.indexOf(":");
|
|
140
|
-
const namespace = fullKey.slice(0, separator);
|
|
141
|
-
const bucket = out[namespace] ?? {};
|
|
142
|
-
bucket[fullKey.slice(separator + 1)] = value;
|
|
143
|
-
out[namespace] = bucket;
|
|
144
|
-
}
|
|
145
|
-
return out;
|
|
146
|
-
};
|
|
147
|
-
/** Per-locale messages merged into `config.i18n.translations`. English only for now. */
|
|
148
|
-
const translations = { en: toNested(en) };
|
|
149
|
-
//#endregion
|
|
150
|
-
export { translations as t };
|
|
156
|
+
export { en };
|
|
151
157
|
|
|
152
|
-
//# sourceMappingURL=
|
|
158
|
+
//# sourceMappingURL=en.js.map
|