@10x-media/form-builder 0.1.0-beta.0 → 0.1.0-beta.1
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 +52 -0
- package/README.md +43 -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 +138 -0
- package/dist/collections/formSubmissions.js.map +1 -0
- package/dist/collections/forms.js +187 -0
- package/dist/collections/forms.js.map +1 -0
- package/dist/collections/uploads.d.ts +29 -0
- package/dist/collections/uploads.js +46 -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 +27 -5
- package/dist/fields/buildFieldBlocks.js +46 -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 +25 -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/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 +88 -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 +74 -4
- package/dist/index.js +40 -1889
- 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/registerCollections.js +40 -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 +81 -0
- package/dist/react/Form.js +457 -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 +26 -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/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 +16 -0
- package/dist/submissions/SubmissionAnswers.js +57 -0
- package/dist/submissions/SubmissionAnswers.js.map +1 -0
- package/dist/submissions/runSubmission.js +205 -0
- package/dist/submissions/runSubmission.js.map +1 -0
- package/dist/submissions/types.d.ts +33 -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} +3 -22
- 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 +132 -0
- package/dist/{keys-N5xGiUsh.js → translations/keys.js} +2 -2
- 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,205 @@
|
|
|
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 : raw;
|
|
70
|
+
if (isEmpty(effectiveRaw)) 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 (isEmpty(raw)) continue;
|
|
183
|
+
outValues.push({
|
|
184
|
+
field: instance.name,
|
|
185
|
+
value
|
|
186
|
+
});
|
|
187
|
+
const optionLabels = optionLabelsFor(instance);
|
|
188
|
+
descriptors.push({
|
|
189
|
+
field: instance.name,
|
|
190
|
+
label: instance.label ?? instance.name,
|
|
191
|
+
fieldType: instance.blockType,
|
|
192
|
+
...optionLabels ? { optionLabels } : {}
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
return {
|
|
196
|
+
errors,
|
|
197
|
+
values: outValues,
|
|
198
|
+
descriptors,
|
|
199
|
+
consent: consentProofs
|
|
200
|
+
};
|
|
201
|
+
};
|
|
202
|
+
//#endregion
|
|
203
|
+
export { runSubmission };
|
|
204
|
+
|
|
205
|
+
//# 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\tconst effectiveRaw = instance.blockType === 'consent' && isEmpty(raw) ? false : raw\n\t\tif (isEmpty(effectiveRaw)) {\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 (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,33 @@
|
|
|
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>;
|
|
15
|
+
};
|
|
16
|
+
/** A per-field validation failure (`path` is the field name, for renderer error mapping). */
|
|
17
|
+
type SubmissionFieldError = {
|
|
18
|
+
path: string;
|
|
19
|
+
message: string;
|
|
20
|
+
};
|
|
21
|
+
/** A field instance as stored in a form's `fields` blocks array (shared config plus type-specific keys). */
|
|
22
|
+
type FormFieldInstance = {
|
|
23
|
+
blockType: string;
|
|
24
|
+
name: string;
|
|
25
|
+
label?: string;
|
|
26
|
+
required?: boolean;
|
|
27
|
+
visibleWhen?: Where;
|
|
28
|
+
validateWhen?: Where;
|
|
29
|
+
[key: string]: unknown;
|
|
30
|
+
};
|
|
31
|
+
//#endregion
|
|
32
|
+
export { FormFieldInstance, SubmissionDescriptor, SubmissionFieldError, SubmissionValue };
|
|
33
|
+
//# 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
|
|
@@ -128,25 +128,6 @@ const en = {
|
|
|
128
128
|
[keys.spamCaptchaFailed]: "Captcha verification failed. Please try again."
|
|
129
129
|
};
|
|
130
130
|
//#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 };
|
|
131
|
+
export { en };
|
|
151
132
|
|
|
152
|
-
//# sourceMappingURL=
|
|
133
|
+
//# sourceMappingURL=en.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"en.js","names":[],"sources":["../../src/translations/en.ts"],"sourcesContent":["import { keys, type TranslationKey } from './keys'\n\n/**\n * English values, keyed by the typed constants in `keys.ts` so the two stay in\n * lockstep. The `Record<TranslationKey, string>` annotation makes a missing or\n * unknown key a type error. `translations/index.ts` nests these for Payload.\n */\nexport const en: Record<TranslationKey, string> = {\n\t[keys.pluginName]: 'Form Builder',\n\t[keys.fieldTitle]: 'Title',\n\t[keys.fieldTypeText]: 'Text',\n\t[keys.fieldTypeTextarea]: 'Long text',\n\t[keys.fieldTypeEmail]: 'Email',\n\t[keys.fieldTypeNumber]: 'Number',\n\t[keys.fieldTypeSelect]: 'Select',\n\t[keys.fieldTypeCheckbox]: 'Checkbox',\n\t[keys.configOptions]: 'Options',\n\t[keys.configOption]: 'Option',\n\t[keys.configOptionLabel]: 'Option label',\n\t[keys.configOptionValue]: 'Option value',\n\t[keys.validationRequired]: 'This field is required',\n\t[keys.validationEmail]: 'Enter a valid email address',\n\t[keys.validationNumber]: 'Enter a valid number',\n\t[keys.validationSelect]: 'Choose a valid option',\n\t[keys.formatYes]: 'Yes',\n\t[keys.formatNo]: 'No',\n\t[keys.configName]: 'Name',\n\t[keys.configLabel]: 'Label',\n\t[keys.configRequired]: 'Required',\n\t[keys.configWidth]: 'Width',\n\t[keys.configPlaceholder]: 'Placeholder',\n\t[keys.configDescription]: 'Description',\n\t[keys.configVisibleWhen]: 'Show this field when',\n\t[keys.configValidateWhen]: 'Validate this field only when',\n\t[keys.submissionAnswers]: 'Answers',\n\t[keys.submissionNoAnswers]: 'No answers',\n\t[keys.ruleMinLength]: 'Minimum length',\n\t[keys.ruleMaxLength]: 'Maximum length',\n\t[keys.ruleMin]: 'Minimum',\n\t[keys.ruleMax]: 'Maximum',\n\t[keys.rulePattern]: 'Pattern',\n\t[keys.ruleEmail]: 'Email',\n\t[keys.ruleUrl]: 'URL',\n\t[keys.ruleOneOf]: 'One of',\n\t[keys.ruleMatchesField]: 'Matches field',\n\t[keys.ruleNotAlreadySubmitted]: 'Not already submitted',\n\t[keys.ruleMinLengthMessage]: 'Must be at least {min} characters',\n\t[keys.ruleMaxLengthMessage]: 'Must be at most {max} characters',\n\t[keys.ruleMinMessage]: 'Must be at least {min}',\n\t[keys.ruleMaxMessage]: 'Must be at most {max}',\n\t[keys.rulePatternMessage]: 'Invalid format',\n\t[keys.ruleEmailMessage]: 'Enter a valid email address',\n\t[keys.ruleUrlMessage]: 'Enter a valid URL',\n\t[keys.ruleOneOfMessage]: 'Choose an allowed value',\n\t[keys.ruleMatchesFieldMessage]: 'Does not match',\n\t[keys.ruleNotAlreadySubmittedMessage]: 'This value was already submitted',\n\t[keys.ruleParamMin]: 'Minimum',\n\t[keys.ruleParamMax]: 'Maximum',\n\t[keys.ruleParamPattern]: 'Pattern',\n\t[keys.ruleParamFlags]: 'Flags',\n\t[keys.ruleParamValues]: 'Allowed values',\n\t[keys.ruleParamField]: 'Field name',\n\t[keys.validationsLabel]: 'Validation rules',\n\t[keys.validationMessageLabel]: 'Custom message',\n\t[keys.validationSeverityLabel]: 'Severity',\n\t[keys.validationSeverityError]: 'Error',\n\t[keys.validationSeverityWarning]: 'Warning',\n\t[keys.conditionAddCondition]: 'Add condition',\n\t[keys.conditionAddOr]: 'Add \"or\" group',\n\t[keys.conditionAnd]: 'And',\n\t[keys.conditionOr]: 'Or',\n\t[keys.conditionRemove]: 'Remove',\n\t[keys.conditionNoFields]: 'Add named fields to this form to build a condition.',\n\t[keys.conditionEmpty]: 'No conditions. This field is always shown.',\n\t[keys.conditionSelectField]: 'Select a field',\n\t[keys.conditionValuePlaceholder]: 'Value',\n\t[keys.conditionTrue]: 'True',\n\t[keys.conditionFalse]: 'False',\n\t[keys.configAdvanced]: 'Advanced',\n\t[keys.configHidden]: 'Hidden (capture without showing)',\n\t[keys.fieldTypeCalculation]: 'Calculation',\n\t[keys.configExpression]: 'Expression (JSON)',\n\t[keys.configCalcDisplay]: 'Show computed value',\n\t[keys.configDefaultPresentation]: 'Presentation',\n\t[keys.presentationPage]: 'Page',\n\t[keys.presentationModal]: 'Modal',\n\t[keys.presentationDrawer]: 'Drawer',\n\t[keys.presentationInline]: 'Inline',\n\t[keys.actionEmailTeam]: 'Email team',\n\t[keys.actionConfirmation]: 'Confirmation email',\n\t[keys.actionSignedWebhook]: 'Signed webhook',\n\t[keys.actionConfigTo]: 'To',\n\t[keys.actionConfigSubject]: 'Subject',\n\t[keys.actionConfigBody]: 'Body',\n\t[keys.actionConfigToField]: 'Email field name',\n\t[keys.actionConfigUrl]: 'URL',\n\t[keys.actionConfigSecret]: 'Secret',\n\t[keys.configActions]: 'Actions',\n\t[keys.consentSourceStatic]: 'Static text',\n\t[keys.consentSourcePageReference]: 'Page reference',\n\t[keys.consentConfigLabel]: 'Label',\n\t[keys.consentConfigUrl]: 'URL',\n\t[keys.consentConfigVersion]: 'Version',\n\t[keys.consentConfigRelationTo]: 'Collection',\n\t[keys.consentConfigDocId]: 'Document ID',\n\t[keys.consentConfigUrlField]: 'URL field',\n\t[keys.consentConfigCaptureVersion]: 'Capture published version',\n\t[keys.fieldTypeConsent]: 'Consent',\n\t[keys.consentConfigStatement]: 'Statement',\n\t[keys.consentConfigSource]: 'Source',\n\t[keys.consentConfigSourceConfig]: 'Source settings',\n\t[keys.consentConfigOptional]: 'Optional (e.g. marketing)',\n\t[keys.resultsTitle]: 'Results',\n\t[keys.resultsResponses]: 'responses',\n\t[keys.resultsNoResponses]: 'No responses yet',\n\t[keys.resultsTruncated]: 'Showing a sample of responses',\n\t[keys.configShowResults]: 'Show results publicly',\n\t[keys.configResultsField]: 'Results field (machine name)',\n\t[keys.validationFileMissing]: 'Upload a file',\n\t[keys.validationFileMimeType]: 'File type not allowed',\n\t[keys.validationFileTooLarge]: 'File is too large',\n\t[keys.fieldTypeFile]: 'File upload',\n\t[keys.fileConfigRelationTo]: 'Upload collection',\n\t[keys.fileConfigMimeTypes]: 'Allowed file types',\n\t[keys.fileConfigMaxSize]: 'Maximum size (bytes)',\n\t[keys.spamRateLimited]: 'You have sent too many requests. Please try again later.',\n\t[keys.spamRejected]: 'Your submission could not be processed.',\n\t[keys.spamCaptchaFailed]: 'Captcha verification failed. Please try again.',\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { TranslationKey, keys } from "./keys.js";
|
|
2
|
+
|
|
3
|
+
//#region src/translations/index.d.ts
|
|
4
|
+
/** Per-locale string overrides keyed by this plugin's typed translation keys. */
|
|
5
|
+
type TranslationsOption = {
|
|
6
|
+
[locale: string]: Partial<Record<TranslationKey, string>>;
|
|
7
|
+
};
|
|
8
|
+
/** Per-locale messages merged into `config.i18n.translations`. English only for now. */
|
|
9
|
+
declare const translations: {
|
|
10
|
+
en: Record<string, Record<string, string>>;
|
|
11
|
+
};
|
|
12
|
+
//#endregion
|
|
13
|
+
export { TranslationsOption, translations };
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import "./keys.js";
|
|
2
|
+
import { en } from "./en.js";
|
|
3
|
+
//#region src/translations/index.ts
|
|
4
|
+
/**
|
|
5
|
+
* Flat `formBuilder:foo` entries to the nested `{ formBuilder: { foo } }`
|
|
6
|
+
* shape Payload resolves `t('formBuilder:foo')` against (it splits on `:`).
|
|
7
|
+
* Undefined values are skipped so `Partial` override maps pass through.
|
|
8
|
+
*/
|
|
9
|
+
const toNested = (flat) => {
|
|
10
|
+
const out = {};
|
|
11
|
+
for (const [fullKey, value] of Object.entries(flat)) {
|
|
12
|
+
if (typeof value !== "string") continue;
|
|
13
|
+
const separator = fullKey.indexOf(":");
|
|
14
|
+
const namespace = fullKey.slice(0, separator);
|
|
15
|
+
const bucket = out[namespace] ?? {};
|
|
16
|
+
bucket[fullKey.slice(separator + 1)] = value;
|
|
17
|
+
out[namespace] = bucket;
|
|
18
|
+
}
|
|
19
|
+
return out;
|
|
20
|
+
};
|
|
21
|
+
/** Per-locale messages merged into `config.i18n.translations`. English only for now. */
|
|
22
|
+
const translations = { en: toNested(en) };
|
|
23
|
+
//#endregion
|
|
24
|
+
export { toNested, translations };
|
|
25
|
+
|
|
26
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/translations/index.ts"],"sourcesContent":["import { en } from './en'\nimport type { TranslationKey } from './keys'\n\nexport type { TranslationKey } from './keys'\nexport { keys } from './keys'\n\n/** Per-locale string overrides keyed by this plugin's typed translation keys. */\nexport type TranslationsOption = {\n\t[locale: string]: Partial<Record<TranslationKey, string>>\n}\n\n/**\n * Flat `formBuilder:foo` entries to the nested `{ formBuilder: { foo } }`\n * shape Payload resolves `t('formBuilder:foo')` against (it splits on `:`).\n * Undefined values are skipped so `Partial` override maps pass through.\n */\nexport const toNested = (flat: {\n\t[key: string]: string | undefined\n}): Record<string, Record<string, string>> => {\n\tconst out: Record<string, Record<string, string>> = {}\n\tfor (const [fullKey, value] of Object.entries(flat)) {\n\t\tif (typeof value !== 'string') {\n\t\t\tcontinue\n\t\t}\n\t\tconst separator = fullKey.indexOf(':')\n\t\tconst namespace = fullKey.slice(0, separator)\n\t\tconst bucket = out[namespace] ?? {}\n\t\tbucket[fullKey.slice(separator + 1)] = value\n\t\tout[namespace] = bucket\n\t}\n\treturn out\n}\n\n/** Per-locale messages merged into `config.i18n.translations`. English only for now. */\nexport const translations = {\n\ten: toNested(en),\n}\n"],"mappings":";;;;;;;;AAgBA,MAAa,YAAY,SAEqB;CAC7C,MAAM,MAA8C,CAAC;CACrD,KAAK,MAAM,CAAC,SAAS,UAAU,OAAO,QAAQ,IAAI,GAAG;EACpD,IAAI,OAAO,UAAU,UACpB;EAED,MAAM,YAAY,QAAQ,QAAQ,GAAG;EACrC,MAAM,YAAY,QAAQ,MAAM,GAAG,SAAS;EAC5C,MAAM,SAAS,IAAI,cAAc,CAAC;EAClC,OAAO,QAAQ,MAAM,YAAY,CAAC,KAAK;EACvC,IAAI,aAAa;CAClB;CACA,OAAO;AACR;;AAGA,MAAa,eAAe,EAC3B,IAAI,SAAS,EAAE,EAChB"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
//#region src/translations/keys.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Typed translation keys. Lookups must go through these constants, not string
|
|
4
|
+
* literals (enforced by requireI18nKeysTyped.grit). Every key here must have a
|
|
5
|
+
* value in every locale (`en.ts`), or it is a type error.
|
|
6
|
+
*/
|
|
7
|
+
declare const keys: {
|
|
8
|
+
readonly pluginName: "formBuilder:pluginName";
|
|
9
|
+
readonly fieldTitle: "formBuilder:fieldTitle";
|
|
10
|
+
readonly fieldTypeText: "formBuilder:fieldType.text";
|
|
11
|
+
readonly fieldTypeTextarea: "formBuilder:fieldType.textarea";
|
|
12
|
+
readonly fieldTypeEmail: "formBuilder:fieldType.email";
|
|
13
|
+
readonly fieldTypeNumber: "formBuilder:fieldType.number";
|
|
14
|
+
readonly fieldTypeSelect: "formBuilder:fieldType.select";
|
|
15
|
+
readonly fieldTypeCheckbox: "formBuilder:fieldType.checkbox";
|
|
16
|
+
readonly configOptions: "formBuilder:config.options";
|
|
17
|
+
readonly configOption: "formBuilder:config.option";
|
|
18
|
+
readonly configOptionLabel: "formBuilder:config.optionLabel";
|
|
19
|
+
readonly configOptionValue: "formBuilder:config.optionValue";
|
|
20
|
+
readonly validationRequired: "formBuilder:validation.required";
|
|
21
|
+
readonly validationEmail: "formBuilder:validation.email";
|
|
22
|
+
readonly validationNumber: "formBuilder:validation.number";
|
|
23
|
+
readonly validationSelect: "formBuilder:validation.select";
|
|
24
|
+
readonly formatYes: "formBuilder:format.yes";
|
|
25
|
+
readonly formatNo: "formBuilder:format.no";
|
|
26
|
+
readonly configName: "formBuilder:config.name";
|
|
27
|
+
readonly configLabel: "formBuilder:config.label";
|
|
28
|
+
readonly configRequired: "formBuilder:config.required";
|
|
29
|
+
readonly configWidth: "formBuilder:config.width";
|
|
30
|
+
readonly configPlaceholder: "formBuilder:config.placeholder";
|
|
31
|
+
readonly configDescription: "formBuilder:config.description";
|
|
32
|
+
readonly configVisibleWhen: "formBuilder:config.visibleWhen";
|
|
33
|
+
readonly configValidateWhen: "formBuilder:config.validateWhen";
|
|
34
|
+
readonly submissionAnswers: "formBuilder:submission.answers";
|
|
35
|
+
readonly submissionNoAnswers: "formBuilder:submission.noAnswers";
|
|
36
|
+
readonly ruleMinLength: "formBuilder:rule.minLength.label";
|
|
37
|
+
readonly ruleMaxLength: "formBuilder:rule.maxLength.label";
|
|
38
|
+
readonly ruleMin: "formBuilder:rule.min.label";
|
|
39
|
+
readonly ruleMax: "formBuilder:rule.max.label";
|
|
40
|
+
readonly rulePattern: "formBuilder:rule.pattern.label";
|
|
41
|
+
readonly ruleEmail: "formBuilder:rule.email.label";
|
|
42
|
+
readonly ruleUrl: "formBuilder:rule.url.label";
|
|
43
|
+
readonly ruleOneOf: "formBuilder:rule.oneOf.label";
|
|
44
|
+
readonly ruleMatchesField: "formBuilder:rule.matchesField.label";
|
|
45
|
+
readonly ruleNotAlreadySubmitted: "formBuilder:rule.notAlreadySubmitted.label";
|
|
46
|
+
readonly ruleMinLengthMessage: "formBuilder:rule.minLength.message";
|
|
47
|
+
readonly ruleMaxLengthMessage: "formBuilder:rule.maxLength.message";
|
|
48
|
+
readonly ruleMinMessage: "formBuilder:rule.min.message";
|
|
49
|
+
readonly ruleMaxMessage: "formBuilder:rule.max.message";
|
|
50
|
+
readonly rulePatternMessage: "formBuilder:rule.pattern.message";
|
|
51
|
+
readonly ruleEmailMessage: "formBuilder:rule.email.message";
|
|
52
|
+
readonly ruleUrlMessage: "formBuilder:rule.url.message";
|
|
53
|
+
readonly ruleOneOfMessage: "formBuilder:rule.oneOf.message";
|
|
54
|
+
readonly ruleMatchesFieldMessage: "formBuilder:rule.matchesField.message";
|
|
55
|
+
readonly ruleNotAlreadySubmittedMessage: "formBuilder:rule.notAlreadySubmitted.message";
|
|
56
|
+
readonly ruleParamMin: "formBuilder:rule.param.min";
|
|
57
|
+
readonly ruleParamMax: "formBuilder:rule.param.max";
|
|
58
|
+
readonly ruleParamPattern: "formBuilder:rule.param.pattern";
|
|
59
|
+
readonly ruleParamFlags: "formBuilder:rule.param.flags";
|
|
60
|
+
readonly ruleParamValues: "formBuilder:rule.param.values";
|
|
61
|
+
readonly ruleParamField: "formBuilder:rule.param.field";
|
|
62
|
+
readonly validationsLabel: "formBuilder:validations.label";
|
|
63
|
+
readonly validationMessageLabel: "formBuilder:validations.message";
|
|
64
|
+
readonly validationSeverityLabel: "formBuilder:validations.severity";
|
|
65
|
+
readonly validationSeverityError: "formBuilder:validations.severity.error";
|
|
66
|
+
readonly validationSeverityWarning: "formBuilder:validations.severity.warning";
|
|
67
|
+
readonly conditionAddCondition: "formBuilder:condition.addCondition";
|
|
68
|
+
readonly conditionAddOr: "formBuilder:condition.addOr";
|
|
69
|
+
readonly conditionAnd: "formBuilder:condition.and";
|
|
70
|
+
readonly conditionOr: "formBuilder:condition.or";
|
|
71
|
+
readonly conditionRemove: "formBuilder:condition.remove";
|
|
72
|
+
readonly conditionNoFields: "formBuilder:condition.noFields";
|
|
73
|
+
readonly conditionEmpty: "formBuilder:condition.empty";
|
|
74
|
+
readonly conditionSelectField: "formBuilder:condition.selectField";
|
|
75
|
+
readonly conditionValuePlaceholder: "formBuilder:condition.value";
|
|
76
|
+
readonly conditionTrue: "formBuilder:condition.true";
|
|
77
|
+
readonly conditionFalse: "formBuilder:condition.false";
|
|
78
|
+
readonly configAdvanced: "formBuilder:config.advanced";
|
|
79
|
+
readonly configHidden: "formBuilder:config.hidden";
|
|
80
|
+
readonly fieldTypeCalculation: "formBuilder:fieldType.calculation";
|
|
81
|
+
readonly configExpression: "formBuilder:config.expression";
|
|
82
|
+
readonly configCalcDisplay: "formBuilder:config.calcDisplay";
|
|
83
|
+
readonly configDefaultPresentation: "formBuilder:config.defaultPresentation";
|
|
84
|
+
readonly presentationPage: "formBuilder:presentation.page";
|
|
85
|
+
readonly presentationModal: "formBuilder:presentation.modal";
|
|
86
|
+
readonly presentationDrawer: "formBuilder:presentation.drawer";
|
|
87
|
+
readonly presentationInline: "formBuilder:presentation.inline";
|
|
88
|
+
readonly actionEmailTeam: "formBuilder:action.emailTeam";
|
|
89
|
+
readonly actionConfirmation: "formBuilder:action.confirmation";
|
|
90
|
+
readonly actionSignedWebhook: "formBuilder:action.signedWebhook";
|
|
91
|
+
readonly actionConfigTo: "formBuilder:action.config.to";
|
|
92
|
+
readonly actionConfigSubject: "formBuilder:action.config.subject";
|
|
93
|
+
readonly actionConfigBody: "formBuilder:action.config.body";
|
|
94
|
+
readonly actionConfigToField: "formBuilder:action.config.toField";
|
|
95
|
+
readonly actionConfigUrl: "formBuilder:action.config.url";
|
|
96
|
+
readonly actionConfigSecret: "formBuilder:action.config.secret";
|
|
97
|
+
readonly configActions: "formBuilder:config.actions";
|
|
98
|
+
readonly consentSourceStatic: "formBuilder:consentSource.static";
|
|
99
|
+
readonly consentSourcePageReference: "formBuilder:consentSource.pageReference";
|
|
100
|
+
readonly consentConfigLabel: "formBuilder:consent.config.label";
|
|
101
|
+
readonly consentConfigUrl: "formBuilder:consent.config.url";
|
|
102
|
+
readonly consentConfigVersion: "formBuilder:consent.config.version";
|
|
103
|
+
readonly consentConfigRelationTo: "formBuilder:consent.config.relationTo";
|
|
104
|
+
readonly consentConfigDocId: "formBuilder:consent.config.docId";
|
|
105
|
+
readonly consentConfigUrlField: "formBuilder:consent.config.urlField";
|
|
106
|
+
readonly consentConfigCaptureVersion: "formBuilder:consent.config.captureVersion";
|
|
107
|
+
readonly fieldTypeConsent: "formBuilder:fieldType.consent";
|
|
108
|
+
readonly consentConfigStatement: "formBuilder:consent.config.statement";
|
|
109
|
+
readonly consentConfigSource: "formBuilder:consent.config.source";
|
|
110
|
+
readonly consentConfigSourceConfig: "formBuilder:consent.config.sourceConfig";
|
|
111
|
+
readonly consentConfigOptional: "formBuilder:consent.config.optional";
|
|
112
|
+
readonly resultsTitle: "formBuilder:results.title";
|
|
113
|
+
readonly resultsResponses: "formBuilder:results.responses";
|
|
114
|
+
readonly resultsNoResponses: "formBuilder:results.noResponses";
|
|
115
|
+
readonly resultsTruncated: "formBuilder:results.truncated";
|
|
116
|
+
readonly configShowResults: "formBuilder:config.showResults";
|
|
117
|
+
readonly configResultsField: "formBuilder:config.resultsField";
|
|
118
|
+
readonly validationFileMissing: "formBuilder:validation.file.missing";
|
|
119
|
+
readonly validationFileMimeType: "formBuilder:validation.file.mimeType";
|
|
120
|
+
readonly validationFileTooLarge: "formBuilder:validation.file.tooLarge";
|
|
121
|
+
readonly fieldTypeFile: "formBuilder:fieldType.file";
|
|
122
|
+
readonly fileConfigRelationTo: "formBuilder:file.config.relationTo";
|
|
123
|
+
readonly fileConfigMimeTypes: "formBuilder:file.config.mimeTypes";
|
|
124
|
+
readonly fileConfigMaxSize: "formBuilder:file.config.maxSize";
|
|
125
|
+
readonly spamRateLimited: "formBuilder:spam.rateLimited";
|
|
126
|
+
readonly spamRejected: "formBuilder:spam.rejected";
|
|
127
|
+
readonly spamCaptchaFailed: "formBuilder:spam.captchaFailed";
|
|
128
|
+
};
|
|
129
|
+
type TranslationKey = (typeof keys)[keyof typeof keys];
|
|
130
|
+
//#endregion
|
|
131
|
+
export { TranslationKey, keys };
|
|
132
|
+
//# sourceMappingURL=keys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keys.js","names":[],"sources":["../../src/translations/keys.ts"],"sourcesContent":["/**\n * Typed translation keys. Lookups must go through these constants, not string\n * literals (enforced by requireI18nKeysTyped.grit). Every key here must have a\n * value in every locale (`en.ts`), or it is a type error.\n */\nexport const keys = {\n\tpluginName: 'formBuilder:pluginName',\n\tfieldTitle: 'formBuilder:fieldTitle',\n\tfieldTypeText: 'formBuilder:fieldType.text',\n\tfieldTypeTextarea: 'formBuilder:fieldType.textarea',\n\tfieldTypeEmail: 'formBuilder:fieldType.email',\n\tfieldTypeNumber: 'formBuilder:fieldType.number',\n\tfieldTypeSelect: 'formBuilder:fieldType.select',\n\tfieldTypeCheckbox: 'formBuilder:fieldType.checkbox',\n\tconfigOptions: 'formBuilder:config.options',\n\tconfigOption: 'formBuilder:config.option',\n\tconfigOptionLabel: 'formBuilder:config.optionLabel',\n\tconfigOptionValue: 'formBuilder:config.optionValue',\n\tvalidationRequired: 'formBuilder:validation.required',\n\tvalidationEmail: 'formBuilder:validation.email',\n\tvalidationNumber: 'formBuilder:validation.number',\n\tvalidationSelect: 'formBuilder:validation.select',\n\tformatYes: 'formBuilder:format.yes',\n\tformatNo: 'formBuilder:format.no',\n\tconfigName: 'formBuilder:config.name',\n\tconfigLabel: 'formBuilder:config.label',\n\tconfigRequired: 'formBuilder:config.required',\n\tconfigWidth: 'formBuilder:config.width',\n\tconfigPlaceholder: 'formBuilder:config.placeholder',\n\tconfigDescription: 'formBuilder:config.description',\n\tconfigVisibleWhen: 'formBuilder:config.visibleWhen',\n\tconfigValidateWhen: 'formBuilder:config.validateWhen',\n\tsubmissionAnswers: 'formBuilder:submission.answers',\n\tsubmissionNoAnswers: 'formBuilder:submission.noAnswers',\n\truleMinLength: 'formBuilder:rule.minLength.label',\n\truleMaxLength: 'formBuilder:rule.maxLength.label',\n\truleMin: 'formBuilder:rule.min.label',\n\truleMax: 'formBuilder:rule.max.label',\n\trulePattern: 'formBuilder:rule.pattern.label',\n\truleEmail: 'formBuilder:rule.email.label',\n\truleUrl: 'formBuilder:rule.url.label',\n\truleOneOf: 'formBuilder:rule.oneOf.label',\n\truleMatchesField: 'formBuilder:rule.matchesField.label',\n\truleNotAlreadySubmitted: 'formBuilder:rule.notAlreadySubmitted.label',\n\truleMinLengthMessage: 'formBuilder:rule.minLength.message',\n\truleMaxLengthMessage: 'formBuilder:rule.maxLength.message',\n\truleMinMessage: 'formBuilder:rule.min.message',\n\truleMaxMessage: 'formBuilder:rule.max.message',\n\trulePatternMessage: 'formBuilder:rule.pattern.message',\n\truleEmailMessage: 'formBuilder:rule.email.message',\n\truleUrlMessage: 'formBuilder:rule.url.message',\n\truleOneOfMessage: 'formBuilder:rule.oneOf.message',\n\truleMatchesFieldMessage: 'formBuilder:rule.matchesField.message',\n\truleNotAlreadySubmittedMessage: 'formBuilder:rule.notAlreadySubmitted.message',\n\truleParamMin: 'formBuilder:rule.param.min',\n\truleParamMax: 'formBuilder:rule.param.max',\n\truleParamPattern: 'formBuilder:rule.param.pattern',\n\truleParamFlags: 'formBuilder:rule.param.flags',\n\truleParamValues: 'formBuilder:rule.param.values',\n\truleParamField: 'formBuilder:rule.param.field',\n\tvalidationsLabel: 'formBuilder:validations.label',\n\tvalidationMessageLabel: 'formBuilder:validations.message',\n\tvalidationSeverityLabel: 'formBuilder:validations.severity',\n\tvalidationSeverityError: 'formBuilder:validations.severity.error',\n\tvalidationSeverityWarning: 'formBuilder:validations.severity.warning',\n\tconditionAddCondition: 'formBuilder:condition.addCondition',\n\tconditionAddOr: 'formBuilder:condition.addOr',\n\tconditionAnd: 'formBuilder:condition.and',\n\tconditionOr: 'formBuilder:condition.or',\n\tconditionRemove: 'formBuilder:condition.remove',\n\tconditionNoFields: 'formBuilder:condition.noFields',\n\tconditionEmpty: 'formBuilder:condition.empty',\n\tconditionSelectField: 'formBuilder:condition.selectField',\n\tconditionValuePlaceholder: 'formBuilder:condition.value',\n\tconditionTrue: 'formBuilder:condition.true',\n\tconditionFalse: 'formBuilder:condition.false',\n\tconfigAdvanced: 'formBuilder:config.advanced',\n\tconfigHidden: 'formBuilder:config.hidden',\n\tfieldTypeCalculation: 'formBuilder:fieldType.calculation',\n\tconfigExpression: 'formBuilder:config.expression',\n\tconfigCalcDisplay: 'formBuilder:config.calcDisplay',\n\tconfigDefaultPresentation: 'formBuilder:config.defaultPresentation',\n\tpresentationPage: 'formBuilder:presentation.page',\n\tpresentationModal: 'formBuilder:presentation.modal',\n\tpresentationDrawer: 'formBuilder:presentation.drawer',\n\tpresentationInline: 'formBuilder:presentation.inline',\n\tactionEmailTeam: 'formBuilder:action.emailTeam',\n\tactionConfirmation: 'formBuilder:action.confirmation',\n\tactionSignedWebhook: 'formBuilder:action.signedWebhook',\n\tactionConfigTo: 'formBuilder:action.config.to',\n\tactionConfigSubject: 'formBuilder:action.config.subject',\n\tactionConfigBody: 'formBuilder:action.config.body',\n\tactionConfigToField: 'formBuilder:action.config.toField',\n\tactionConfigUrl: 'formBuilder:action.config.url',\n\tactionConfigSecret: 'formBuilder:action.config.secret',\n\tconfigActions: 'formBuilder:config.actions',\n\tconsentSourceStatic: 'formBuilder:consentSource.static',\n\tconsentSourcePageReference: 'formBuilder:consentSource.pageReference',\n\tconsentConfigLabel: 'formBuilder:consent.config.label',\n\tconsentConfigUrl: 'formBuilder:consent.config.url',\n\tconsentConfigVersion: 'formBuilder:consent.config.version',\n\tconsentConfigRelationTo: 'formBuilder:consent.config.relationTo',\n\tconsentConfigDocId: 'formBuilder:consent.config.docId',\n\tconsentConfigUrlField: 'formBuilder:consent.config.urlField',\n\tconsentConfigCaptureVersion: 'formBuilder:consent.config.captureVersion',\n\tfieldTypeConsent: 'formBuilder:fieldType.consent',\n\tconsentConfigStatement: 'formBuilder:consent.config.statement',\n\tconsentConfigSource: 'formBuilder:consent.config.source',\n\tconsentConfigSourceConfig: 'formBuilder:consent.config.sourceConfig',\n\tconsentConfigOptional: 'formBuilder:consent.config.optional',\n\tresultsTitle: 'formBuilder:results.title',\n\tresultsResponses: 'formBuilder:results.responses',\n\tresultsNoResponses: 'formBuilder:results.noResponses',\n\tresultsTruncated: 'formBuilder:results.truncated',\n\tconfigShowResults: 'formBuilder:config.showResults',\n\tconfigResultsField: 'formBuilder:config.resultsField',\n\tvalidationFileMissing: 'formBuilder:validation.file.missing',\n\tvalidationFileMimeType: 'formBuilder:validation.file.mimeType',\n\tvalidationFileTooLarge: 'formBuilder:validation.file.tooLarge',\n\tfieldTypeFile: 'formBuilder:fieldType.file',\n\tfileConfigRelationTo: 'formBuilder:file.config.relationTo',\n\tfileConfigMimeTypes: 'formBuilder:file.config.mimeTypes',\n\tfileConfigMaxSize: 'formBuilder:file.config.maxSize',\n\tspamRateLimited: 'formBuilder:spam.rateLimited',\n\tspamRejected: 'formBuilder:spam.rejected',\n\tspamCaptchaFailed: 'formBuilder:spam.captchaFailed',\n} as const\n\nexport type TranslationKey = (typeof keys)[keyof typeof keys]\n"],"mappings":";;;;;;AAKA,MAAa,OAAO;CACnB,YAAY;CACZ,YAAY;CACZ,eAAe;CACf,mBAAmB;CACnB,gBAAgB;CAChB,iBAAiB;CACjB,iBAAiB;CACjB,mBAAmB;CACnB,eAAe;CACf,cAAc;CACd,mBAAmB;CACnB,mBAAmB;CACnB,oBAAoB;CACpB,iBAAiB;CACjB,kBAAkB;CAClB,kBAAkB;CAClB,WAAW;CACX,UAAU;CACV,YAAY;CACZ,aAAa;CACb,gBAAgB;CAChB,aAAa;CACb,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,oBAAoB;CACpB,mBAAmB;CACnB,qBAAqB;CACrB,eAAe;CACf,eAAe;CACf,SAAS;CACT,SAAS;CACT,aAAa;CACb,WAAW;CACX,SAAS;CACT,WAAW;CACX,kBAAkB;CAClB,yBAAyB;CACzB,sBAAsB;CACtB,sBAAsB;CACtB,gBAAgB;CAChB,gBAAgB;CAChB,oBAAoB;CACpB,kBAAkB;CAClB,gBAAgB;CAChB,kBAAkB;CAClB,yBAAyB;CACzB,gCAAgC;CAChC,cAAc;CACd,cAAc;CACd,kBAAkB;CAClB,gBAAgB;CAChB,iBAAiB;CACjB,gBAAgB;CAChB,kBAAkB;CAClB,wBAAwB;CACxB,yBAAyB;CACzB,yBAAyB;CACzB,2BAA2B;CAC3B,uBAAuB;CACvB,gBAAgB;CAChB,cAAc;CACd,aAAa;CACb,iBAAiB;CACjB,mBAAmB;CACnB,gBAAgB;CAChB,sBAAsB;CACtB,2BAA2B;CAC3B,eAAe;CACf,gBAAgB;CAChB,gBAAgB;CAChB,cAAc;CACd,sBAAsB;CACtB,kBAAkB;CAClB,mBAAmB;CACnB,2BAA2B;CAC3B,kBAAkB;CAClB,mBAAmB;CACnB,oBAAoB;CACpB,oBAAoB;CACpB,iBAAiB;CACjB,oBAAoB;CACpB,qBAAqB;CACrB,gBAAgB;CAChB,qBAAqB;CACrB,kBAAkB;CAClB,qBAAqB;CACrB,iBAAiB;CACjB,oBAAoB;CACpB,eAAe;CACf,qBAAqB;CACrB,4BAA4B;CAC5B,oBAAoB;CACpB,kBAAkB;CAClB,sBAAsB;CACtB,yBAAyB;CACzB,oBAAoB;CACpB,uBAAuB;CACvB,6BAA6B;CAC7B,kBAAkB;CAClB,wBAAwB;CACxB,qBAAqB;CACrB,2BAA2B;CAC3B,uBAAuB;CACvB,cAAc;CACd,kBAAkB;CAClB,oBAAoB;CACpB,kBAAkB;CAClB,mBAAmB;CACnB,oBAAoB;CACpB,uBAAuB;CACvB,wBAAwB;CACxB,wBAAwB;CACxB,eAAe;CACf,sBAAsB;CACtB,qBAAqB;CACrB,mBAAmB;CACnB,iBAAiB;CACjB,cAAc;CACd,mBAAmB;AACpB"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { RendererTranslate } from "../react/contract.js";
|
|
2
|
+
|
|
3
|
+
//#region src/translations/makeTranslate.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Creates a `RendererTranslate` function from a flat key→string map (e.g. the bundled `en` map).
|
|
6
|
+
* Unknown keys fall back to the key itself so nothing crashes when running against an incomplete map.
|
|
7
|
+
*/
|
|
8
|
+
declare const makeTranslate: (map: Record<string, string>) => RendererTranslate;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { makeTranslate };
|
|
11
|
+
//# sourceMappingURL=makeTranslate.d.ts.map
|