@10x-media/form-builder 0.1.0-beta.2 → 0.1.0-beta.21
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 +360 -0
- package/README.md +7 -5
- package/dist/actions/assertNoBlockCollision.js +18 -0
- package/dist/actions/assertNoBlockCollision.js.map +1 -0
- package/dist/actions/body/converters.d.ts +20 -0
- package/dist/actions/body/converters.js +57 -0
- package/dist/actions/body/converters.js.map +1 -0
- package/dist/actions/body/escapeHtml.d.ts +6 -0
- package/dist/actions/body/escapeHtml.js +14 -0
- package/dist/actions/body/escapeHtml.js.map +1 -0
- package/dist/actions/body/serializeBody.d.ts +55 -0
- package/dist/actions/body/serializeBody.js +78 -0
- package/dist/actions/body/serializeBody.js.map +1 -0
- package/dist/actions/body/serializeSlate.js +31 -0
- package/dist/actions/body/serializeSlate.js.map +1 -0
- package/dist/actions/body/textOfBody.d.ts +13 -0
- package/dist/actions/body/textOfBody.js +35 -0
- package/dist/actions/body/textOfBody.js.map +1 -0
- package/dist/actions/body/wildcards.d.ts +10 -0
- package/dist/actions/body/wildcards.js +33 -0
- package/dist/actions/body/wildcards.js.map +1 -0
- package/dist/actions/buildActionBlocks.js +12 -9
- package/dist/actions/buildActionBlocks.js.map +1 -1
- package/dist/actions/builtin/confirmation.js +47 -43
- package/dist/actions/builtin/confirmation.js.map +1 -1
- package/dist/actions/builtin/emailAction.d.ts +20 -0
- package/dist/actions/builtin/emailAction.js +120 -0
- package/dist/actions/builtin/emailAction.js.map +1 -0
- package/dist/actions/builtin/emailTeam.js +20 -38
- package/dist/actions/builtin/emailTeam.js.map +1 -1
- package/dist/actions/builtin/index.d.ts +16 -1
- package/dist/actions/builtin/index.js +21 -7
- package/dist/actions/builtin/index.js.map +1 -1
- package/dist/actions/builtin/signedWebhook.js +6 -2
- package/dist/actions/builtin/signedWebhook.js.map +1 -1
- package/dist/actions/defineAction.d.ts +17 -5
- package/dist/actions/defineAction.js.map +1 -1
- package/dist/actions/dispatch.js +51 -6
- package/dist/actions/dispatch.js.map +1 -1
- package/dist/actions/dispatchContext.js +13 -0
- package/dist/actions/dispatchContext.js.map +1 -0
- package/dist/actions/emailRecipients.d.ts +12 -0
- package/dist/actions/emailRecipients.js +146 -0
- package/dist/actions/emailRecipients.js.map +1 -0
- package/dist/actions/fromAddresses.d.ts +37 -0
- package/dist/actions/fromAddresses.js +131 -0
- package/dist/actions/fromAddresses.js.map +1 -0
- package/dist/actions/recipientSources.d.ts +34 -0
- package/dist/actions/recipientSources.js +11 -0
- package/dist/actions/recipientSources.js.map +1 -0
- package/dist/actions/registry.d.ts +2 -1
- package/dist/actions/registry.js +5 -7
- package/dist/actions/registry.js.map +1 -1
- package/dist/actions/runActions.js +10 -1
- package/dist/actions/runActions.js.map +1 -1
- package/dist/actions/task.js +47 -16
- package/dist/actions/task.js.map +1 -1
- package/dist/aggregation/aggregateResponses.d.ts +9 -0
- package/dist/aggregation/aggregateResponses.js +8 -14
- package/dist/aggregation/aggregateResponses.js.map +1 -1
- package/dist/aggregation/resolveResultsRequest.d.ts +41 -6
- package/dist/aggregation/resolveResultsRequest.js +97 -11
- package/dist/aggregation/resolveResultsRequest.js.map +1 -1
- package/dist/calc/computeCalcFields.d.ts +5 -3
- package/dist/calc/computeCalcFields.js +6 -4
- package/dist/calc/computeCalcFields.js.map +1 -1
- package/dist/calc/evaluate.d.ts +26 -3
- package/dist/calc/evaluate.js +34 -13
- package/dist/calc/evaluate.js.map +1 -1
- package/dist/calc/formatCalc.d.ts +11 -0
- package/dist/calc/formatCalc.js +35 -0
- package/dist/calc/formatCalc.js.map +1 -0
- package/dist/calc/formatCalcValue.d.ts +17 -0
- package/dist/calc/formatCalcValue.js +17 -0
- package/dist/calc/formatCalcValue.js.map +1 -0
- package/dist/calc/normalizeCalc.d.ts +17 -3
- package/dist/calc/normalizeCalc.js +42 -33
- package/dist/calc/normalizeCalc.js.map +1 -1
- package/dist/calc/registry.d.ts +43 -0
- package/dist/calc/registry.js +27 -0
- package/dist/calc/registry.js.map +1 -0
- package/dist/calc/resolveCalcContext.d.ts +36 -0
- package/dist/calc/resolveCalcContext.js +87 -0
- package/dist/calc/resolveCalcContext.js.map +1 -0
- package/dist/calc/types.d.ts +25 -4
- package/dist/calc/types.js +23 -0
- package/dist/calc/types.js.map +1 -0
- package/dist/client/ByteSizeField.d.ts +29 -0
- package/dist/client/ByteSizeField.js +58 -0
- package/dist/client/ByteSizeField.js.map +1 -0
- package/dist/client/CalcExpressionBuilder.d.ts +20 -0
- package/dist/client/CalcExpressionBuilder.js +890 -0
- package/dist/client/CalcExpressionBuilder.js.map +1 -0
- package/dist/client/ClosePollButton.d.ts +15 -0
- package/dist/client/ClosePollButton.js +80 -0
- package/dist/client/ClosePollButton.js.map +1 -0
- package/dist/client/CondensedArray.d.ts +15 -0
- package/dist/client/CondensedArray.js +97 -0
- package/dist/client/CondensedArray.js.map +1 -0
- package/dist/client/ConditionBuilder.js +2 -1
- package/dist/client/ConditionBuilder.js.map +1 -1
- package/dist/client/ConsentBlockLabel.d.ts +15 -0
- package/dist/client/ConsentBlockLabel.js +71 -0
- package/dist/client/ConsentBlockLabel.js.map +1 -0
- package/dist/client/ConsentSourceRowLabel.d.ts +9 -0
- package/dist/client/ConsentSourceRowLabel.js +21 -0
- package/dist/client/ConsentSourceRowLabel.js.map +1 -0
- package/dist/client/EndpointOptionsSelect.d.ts +55 -0
- package/dist/client/EndpointOptionsSelect.js +112 -0
- package/dist/client/EndpointOptionsSelect.js.map +1 -0
- package/dist/client/FieldBlockLabel.d.ts +18 -0
- package/dist/client/FieldBlockLabel.js +34 -0
- package/dist/client/FieldBlockLabel.js.map +1 -0
- package/dist/client/FieldNameSelect.d.ts +37 -0
- package/dist/client/FieldNameSelect.js +72 -0
- package/dist/client/FieldNameSelect.js.map +1 -0
- package/dist/client/FlowBuilder.d.ts +2 -2
- package/dist/client/FlowBuilder.js +137 -88
- package/dist/client/FlowBuilder.js.map +1 -1
- package/dist/client/FormConditionField.js +1 -4
- package/dist/client/FormConditionField.js.map +1 -1
- package/dist/client/RecipientsSelect.d.ts +37 -0
- package/dist/client/RecipientsSelect.js +197 -0
- package/dist/client/RecipientsSelect.js.map +1 -0
- package/dist/client/RuleDescription.d.ts +21 -0
- package/dist/client/RuleDescription.js +19 -0
- package/dist/client/RuleDescription.js.map +1 -0
- package/dist/client/admin.css +557 -0
- package/dist/client/endpointOptions.d.ts +11 -0
- package/dist/client/endpointOptions.js +38 -0
- package/dist/client/endpointOptions.js.map +1 -0
- package/dist/client/flowAuthoring.js +142 -0
- package/dist/client/flowAuthoring.js.map +1 -0
- package/dist/client/synthesizeClientField.js +21 -10
- package/dist/client/synthesizeClientField.js.map +1 -1
- package/dist/client/toStaticLabel.js +13 -0
- package/dist/client/toStaticLabel.js.map +1 -0
- package/dist/collections/buttonFields.d.ts +34 -0
- package/dist/collections/buttonFields.js +35 -0
- package/dist/collections/buttonFields.js.map +1 -0
- package/dist/collections/cells/FieldCountCell.d.ts +15 -0
- package/dist/collections/cells/FieldCountCell.js +18 -0
- package/dist/collections/cells/FieldCountCell.js.map +1 -0
- package/dist/collections/cells/FlowStepsCell.d.ts +14 -0
- package/dist/collections/cells/FlowStepsCell.js +17 -0
- package/dist/collections/cells/FlowStepsCell.js.map +1 -0
- package/dist/collections/formSubmissions.js +114 -28
- package/dist/collections/formSubmissions.js.map +1 -1
- package/dist/collections/forms.js +449 -112
- package/dist/collections/forms.js.map +1 -1
- package/dist/collections/formsEndpoints.js +106 -0
- package/dist/collections/formsEndpoints.js.map +1 -0
- package/dist/collections/redirectFields.d.ts +29 -0
- package/dist/collections/settingsFields.d.ts +31 -0
- package/dist/collections/settingsFields.js +45 -0
- package/dist/collections/settingsFields.js.map +1 -0
- package/dist/conditions/conditionType.js +9 -2
- package/dist/conditions/conditionType.js.map +1 -1
- package/dist/conditions/evaluate.js +1 -1
- package/dist/conditions/evaluate.js.map +1 -1
- package/dist/conditions/fieldTypes.d.ts +3 -1
- package/dist/conditions/fieldTypes.js +4 -1
- package/dist/conditions/fieldTypes.js.map +1 -1
- package/dist/conditions/normalizeConditions.js +20 -6
- package/dist/conditions/normalizeConditions.js.map +1 -1
- package/dist/consent/applyConsentStatements.d.ts +14 -0
- package/dist/consent/applyConsentStatements.js +17 -0
- package/dist/consent/applyConsentStatements.js.map +1 -0
- package/dist/consent/captureConsent.d.ts +39 -11
- package/dist/consent/captureConsent.js +63 -13
- package/dist/consent/captureConsent.js.map +1 -1
- package/dist/consent/consentSourcesField.d.ts +66 -0
- package/dist/consent/consentSourcesField.js +98 -0
- package/dist/consent/consentSourcesField.js.map +1 -0
- package/dist/consent/effectiveStatement.js +16 -0
- package/dist/consent/effectiveStatement.js.map +1 -0
- package/dist/consent/resolveConsentEntries.d.ts +24 -0
- package/dist/consent/resolveConsentEntries.js +40 -0
- package/dist/consent/resolveConsentEntries.js.map +1 -0
- package/dist/consent/resolveConsentSourcesRequest.d.ts +37 -0
- package/dist/consent/resolveConsentSourcesRequest.js +54 -0
- package/dist/consent/resolveConsentSourcesRequest.js.map +1 -0
- package/dist/consent/resolveConsentStatements.d.ts +45 -0
- package/dist/consent/resolveConsentStatements.js +46 -0
- package/dist/consent/resolveConsentStatements.js.map +1 -0
- package/dist/consent/resolvePublishedVersionRef.d.ts +17 -11
- package/dist/consent/resolvePublishedVersionRef.js +13 -10
- package/dist/consent/resolvePublishedVersionRef.js.map +1 -1
- package/dist/consent/types.d.ts +69 -0
- package/dist/context/formContext.d.ts +30 -0
- package/dist/context/formContext.js +54 -0
- package/dist/context/formContext.js.map +1 -0
- package/dist/email/departments.d.ts +59 -0
- package/dist/email/departments.js +87 -0
- package/dist/email/departments.js.map +1 -0
- package/dist/email/departmentsField.d.ts +53 -0
- package/dist/email/departmentsField.js +73 -0
- package/dist/email/departmentsField.js.map +1 -0
- package/dist/exports/client.d.ts +14 -1
- package/dist/exports/client.js +14 -1
- package/dist/exports/i18n.d.ts +5 -2
- package/dist/exports/i18n.js +5 -2
- package/dist/exports/react.d.ts +34 -10
- package/dist/exports/react.js +24 -4
- package/dist/exports/rsc.d.ts +10 -1
- package/dist/exports/rsc.js +10 -1
- package/dist/exports/types.d.ts +20 -12
- package/dist/fields/buildFieldBlocks.js +46 -25
- package/dist/fields/buildFieldBlocks.js.map +1 -1
- package/dist/fields/builtin/calculation.d.ts +17 -0
- package/dist/fields/builtin/calculation.js +193 -18
- package/dist/fields/builtin/calculation.js.map +1 -1
- package/dist/fields/builtin/checkbox.js +23 -0
- package/dist/fields/builtin/checkbox.js.map +1 -1
- package/dist/fields/builtin/consent.js +49 -14
- package/dist/fields/builtin/consent.js.map +1 -1
- package/dist/fields/builtin/country.d.ts +13 -0
- package/dist/fields/builtin/country.js +30 -0
- package/dist/fields/builtin/country.js.map +1 -0
- package/dist/fields/builtin/date.js +31 -0
- package/dist/fields/builtin/date.js.map +1 -0
- package/dist/fields/builtin/email.js +8 -1
- package/dist/fields/builtin/email.js.map +1 -1
- package/dist/fields/builtin/file.d.ts +15 -0
- package/dist/fields/builtin/file.js +95 -8
- package/dist/fields/builtin/file.js.map +1 -1
- package/dist/fields/builtin/index.d.ts +30 -0
- package/dist/fields/builtin/index.js +37 -10
- package/dist/fields/builtin/index.js.map +1 -1
- package/dist/fields/builtin/message.js +30 -0
- package/dist/fields/builtin/message.js.map +1 -0
- package/dist/fields/builtin/repeater.js +8 -3
- package/dist/fields/builtin/repeater.js.map +1 -1
- package/dist/fields/builtin/select.js +28 -4
- package/dist/fields/builtin/select.js.map +1 -1
- package/dist/fields/builtin/state.d.ts +13 -0
- package/dist/fields/builtin/state.js +30 -0
- package/dist/fields/builtin/state.js.map +1 -0
- package/dist/fields/builtin/text.js +7 -0
- package/dist/fields/builtin/text.js.map +1 -1
- package/dist/fields/data/regions.d.ts +21 -0
- package/dist/fields/data/regions.js +1238 -0
- package/dist/fields/data/regions.js.map +1 -0
- package/dist/fields/fieldKey.d.ts +15 -0
- package/dist/fields/fieldKey.js +16 -0
- package/dist/fields/fieldKey.js.map +1 -0
- package/dist/fields/fieldNamesOfType.js +30 -0
- package/dist/fields/fieldNamesOfType.js.map +1 -0
- package/dist/fields/instanceOptions.js +20 -0
- package/dist/fields/instanceOptions.js.map +1 -0
- package/dist/fields/localizedIf.d.ts +13 -0
- package/dist/fields/localizedIf.js +12 -0
- package/dist/fields/localizedIf.js.map +1 -0
- package/dist/fields/registry.d.ts +3 -1
- package/dist/fields/registry.js +23 -8
- package/dist/fields/registry.js.map +1 -1
- package/dist/fields/sharedConfig.js +125 -59
- package/dist/fields/sharedConfig.js.map +1 -1
- package/dist/fields/types.d.ts +78 -9
- package/dist/flow/engine.d.ts +6 -4
- package/dist/flow/engine.js +11 -6
- package/dist/flow/engine.js.map +1 -1
- package/dist/flow/normalizeFlow.js +28 -9
- package/dist/flow/normalizeFlow.js.map +1 -1
- package/dist/flow/stepLabel.js +15 -0
- package/dist/flow/stepLabel.js.map +1 -0
- package/dist/flow/types.d.ts +12 -3
- package/dist/flow/types.js +11 -0
- package/dist/flow/types.js.map +1 -0
- package/dist/form/pollState.d.ts +23 -0
- package/dist/form/pollState.js +17 -0
- package/dist/form/pollState.js.map +1 -0
- package/dist/form/toFormDocument.d.ts +110 -0
- package/dist/form/toFormDocument.js +89 -0
- package/dist/form/toFormDocument.js.map +1 -0
- package/dist/form/types.d.ts +73 -0
- package/dist/index.d.ts +67 -61
- package/dist/index.js +120 -25
- package/dist/index.js.map +1 -1
- package/dist/options.d.ts +281 -0
- package/dist/plugin/applyRegistryConfig.d.ts +11 -0
- package/dist/plugin/applyRegistryConfig.js +20 -0
- package/dist/plugin/applyRegistryConfig.js.map +1 -0
- package/dist/plugin/customState.js +26 -0
- package/dist/plugin/customState.js.map +1 -0
- package/dist/plugin/registerCollections.js +43 -40
- package/dist/plugin/registerCollections.js.map +1 -1
- package/dist/plugin/uploadsCollection.d.ts +16 -0
- package/dist/plugin/uploadsCollection.js +53 -0
- package/dist/plugin/uploadsCollection.js.map +1 -0
- package/dist/poll/applyPollOptions.js +18 -0
- package/dist/poll/applyPollOptions.js.map +1 -0
- package/dist/poll/buildPollOptionSourceFields.js +50 -0
- package/dist/poll/buildPollOptionSourceFields.js.map +1 -0
- package/dist/poll/closeJob.d.ts +53 -0
- package/dist/poll/closeJob.js +121 -0
- package/dist/poll/closeJob.js.map +1 -0
- package/dist/poll/definePollOptionSource.d.ts +44 -0
- package/dist/poll/definePollOptionSource.js +6 -0
- package/dist/poll/definePollOptionSource.js.map +1 -0
- package/dist/poll/definePollType.d.ts +34 -0
- package/dist/poll/definePollType.js +6 -0
- package/dist/poll/definePollType.js.map +1 -0
- package/dist/poll/effectivePollOptions.d.ts +38 -0
- package/dist/poll/effectivePollOptions.js +64 -0
- package/dist/poll/effectivePollOptions.js.map +1 -0
- package/dist/poll/mostVoted.d.ts +21 -0
- package/dist/poll/mostVoted.js +32 -0
- package/dist/poll/mostVoted.js.map +1 -0
- package/dist/poll/outcomeBeforeChange.js +91 -0
- package/dist/poll/outcomeBeforeChange.js.map +1 -0
- package/dist/poll/outcomeFields.d.ts +38 -0
- package/dist/poll/outcomeFields.js +52 -0
- package/dist/poll/outcomeFields.js.map +1 -0
- package/dist/poll/pollTypeRegistry.d.ts +34 -0
- package/dist/poll/pollTypeRegistry.js +69 -0
- package/dist/poll/pollTypeRegistry.js.map +1 -0
- package/dist/poll/registry.d.ts +17 -0
- package/dist/poll/registry.js +12 -0
- package/dist/poll/registry.js.map +1 -0
- package/dist/poll/resolvePollCloseRequest.js +106 -0
- package/dist/poll/resolvePollCloseRequest.js.map +1 -0
- package/dist/poll/resolvePollOptions.d.ts +29 -0
- package/dist/poll/resolvePollOptions.js +52 -0
- package/dist/poll/resolvePollOptions.js.map +1 -0
- package/dist/poll/resolvePollOptionsRequest.js +50 -0
- package/dist/poll/resolvePollOptionsRequest.js.map +1 -0
- package/dist/poll/resolvePollOutcome.d.ts +40 -0
- package/dist/poll/resolvePollOutcome.js +90 -0
- package/dist/poll/resolvePollOutcome.js.map +1 -0
- package/dist/poll/resultsField.js +21 -0
- package/dist/poll/resultsField.js.map +1 -0
- package/dist/poll/votes/aggregateFromVotes.d.ts +27 -0
- package/dist/poll/votes/aggregateFromVotes.js +54 -0
- package/dist/poll/votes/aggregateFromVotes.js.map +1 -0
- package/dist/poll/votes/answerValues.js +16 -0
- package/dist/poll/votes/answerValues.js.map +1 -0
- package/dist/poll/votes/bumpPollVote.js +88 -0
- package/dist/poll/votes/bumpPollVote.js.map +1 -0
- package/dist/poll/votes/recountPollVotes.d.ts +20 -0
- package/dist/poll/votes/recountPollVotes.js +63 -0
- package/dist/poll/votes/recountPollVotes.js.map +1 -0
- package/dist/poll/votes/voteTallyHook.js +76 -0
- package/dist/poll/votes/voteTallyHook.js.map +1 -0
- package/dist/poll/votes/votesCollection.d.ts +19 -0
- package/dist/poll/votes/votesCollection.js +89 -0
- package/dist/poll/votes/votesCollection.js.map +1 -0
- package/dist/prefill/valuesFromSearchParams.js +5 -9
- package/dist/prefill/valuesFromSearchParams.js.map +1 -1
- package/dist/presentations/types.d.ts +3 -2
- package/dist/react/Form.d.ts +77 -35
- package/dist/react/Form.js +368 -222
- package/dist/react/Form.js.map +1 -1
- package/dist/react/FormContext.d.ts +51 -1
- package/dist/react/FormContext.js.map +1 -1
- package/dist/react/FormControls.d.ts +55 -0
- package/dist/react/FormControls.js +56 -0
- package/dist/react/FormControls.js.map +1 -0
- package/dist/react/FormFields.d.ts +18 -0
- package/dist/react/FormFields.js +114 -0
- package/dist/react/FormFields.js.map +1 -0
- package/dist/react/FormLayout.d.ts +4 -2
- package/dist/react/FormLayout.js +3 -2
- package/dist/react/FormLayout.js.map +1 -1
- package/dist/react/FormResults.d.ts +8 -3
- package/dist/react/FormResults.js +50 -29
- package/dist/react/FormResults.js.map +1 -1
- package/dist/react/FormSteps.d.ts +17 -0
- package/dist/react/FormSteps.js +35 -0
- package/dist/react/FormSteps.js.map +1 -0
- package/dist/react/Poll.d.ts +40 -6
- package/dist/react/Poll.js +137 -33
- package/dist/react/Poll.js.map +1 -1
- package/dist/react/adapters.d.ts +35 -0
- package/dist/react/adapters.js +11 -0
- package/dist/react/adapters.js.map +1 -0
- package/dist/react/captcha/HcaptchaCaptcha.d.ts +31 -0
- package/dist/react/captcha/HcaptchaCaptcha.js +53 -0
- package/dist/react/captcha/HcaptchaCaptcha.js.map +1 -0
- package/dist/react/captcha/RecaptchaCaptcha.d.ts +44 -0
- package/dist/react/captcha/RecaptchaCaptcha.js +93 -0
- package/dist/react/captcha/RecaptchaCaptcha.js.map +1 -0
- package/dist/react/captcha/TurnstileCaptcha.d.ts +31 -0
- package/dist/react/captcha/TurnstileCaptcha.js +53 -0
- package/dist/react/captcha/TurnstileCaptcha.js.map +1 -0
- package/dist/react/captcha/types.d.ts +8 -0
- package/dist/react/captcha/useCaptchaScript.js +63 -0
- package/dist/react/captcha/useCaptchaScript.js.map +1 -0
- package/dist/react/captcha/vendors.js +8 -0
- package/dist/react/captcha/vendors.js.map +1 -0
- package/dist/react/contract.d.ts +2 -3
- package/dist/react/contract.js.map +1 -1
- package/dist/react/fetchResults.d.ts +1 -1
- package/dist/react/fetchResults.js +1 -1
- package/dist/react/fetchResults.js.map +1 -1
- package/dist/react/presentation/DialogSurface.js +1 -4
- package/dist/react/presentation/DialogSurface.js.map +1 -1
- package/dist/react/primitives/Checkbox.d.ts +6 -2
- package/dist/react/primitives/Checkbox.js +4 -2
- package/dist/react/primitives/Checkbox.js.map +1 -1
- package/dist/react/primitives/ChoiceGroup.d.ts +40 -0
- package/dist/react/primitives/ChoiceGroup.js +33 -0
- package/dist/react/primitives/ChoiceGroup.js.map +1 -0
- package/dist/react/primitives/FieldShell.d.ts +13 -5
- package/dist/react/primitives/FieldShell.js +35 -32
- package/dist/react/primitives/FieldShell.js.map +1 -1
- package/dist/react/primitives/Input.d.ts +4 -2
- package/dist/react/primitives/Input.js +2 -1
- package/dist/react/primitives/Input.js.map +1 -1
- package/dist/react/renderers/calculation.js +7 -5
- package/dist/react/renderers/calculation.js.map +1 -1
- package/dist/react/renderers/checkbox.js +3 -5
- package/dist/react/renderers/checkbox.js.map +1 -1
- package/dist/react/renderers/consent.js +84 -36
- package/dist/react/renderers/consent.js.map +1 -1
- package/dist/react/renderers/date.js +33 -0
- package/dist/react/renderers/date.js.map +1 -0
- package/dist/react/renderers/email.js +4 -5
- package/dist/react/renderers/email.js.map +1 -1
- package/dist/react/renderers/file.js +29 -14
- package/dist/react/renderers/file.js.map +1 -1
- package/dist/react/renderers/index.js +7 -0
- package/dist/react/renderers/index.js.map +1 -1
- package/dist/react/renderers/message.js +41 -0
- package/dist/react/renderers/message.js.map +1 -0
- package/dist/react/renderers/number.js +1 -4
- package/dist/react/renderers/number.js.map +1 -1
- package/dist/react/renderers/region.js +43 -0
- package/dist/react/renderers/region.js.map +1 -0
- package/dist/react/renderers/repeater.js +32 -14
- package/dist/react/renderers/repeater.js.map +1 -1
- package/dist/react/renderers/select.js +21 -6
- package/dist/react/renderers/select.js.map +1 -1
- package/dist/react/renderers/text.js +4 -5
- package/dist/react/renderers/text.js.map +1 -1
- package/dist/react/renderers/textarea.js +1 -4
- package/dist/react/renderers/textarea.js.map +1 -1
- package/dist/react/state.d.ts +46 -3
- package/dist/react/state.js +73 -10
- package/dist/react/state.js.map +1 -1
- package/dist/react/submitForm.js +1 -1
- package/dist/react/submitForm.js.map +1 -1
- package/dist/react/uploadFile.d.ts +2 -2
- package/dist/react/uploadFile.js +1 -1
- package/dist/react/uploadFile.js.map +1 -1
- package/dist/react/useCalcValues.d.ts +10 -0
- package/dist/react/useCalcValues.js +13 -0
- package/dist/react/useCalcValues.js.map +1 -0
- package/dist/react/useField.d.ts +0 -1
- package/dist/react/useField.js +7 -6
- package/dist/react/useField.js.map +1 -1
- package/dist/react/useFormState.d.ts +1 -1
- package/dist/react/useFormState.js +1 -1
- package/dist/react/useFormState.js.map +1 -1
- package/dist/react/validateField.js +3 -6
- package/dist/react/validateField.js.map +1 -1
- package/dist/recall/interpolate.d.ts +4 -3
- package/dist/recall/interpolate.js +5 -4
- package/dist/recall/interpolate.js.map +1 -1
- package/dist/recall/resolver.d.ts +1 -1
- package/dist/recall/resolver.js +15 -3
- package/dist/recall/resolver.js.map +1 -1
- package/dist/spam/captcha.d.ts +4 -3
- package/dist/spam/captcha.js +4 -3
- package/dist/spam/captcha.js.map +1 -1
- package/dist/spam/clientIp.js +9 -0
- package/dist/spam/clientIp.js.map +1 -0
- package/dist/spam/constants.js +13 -1
- package/dist/spam/constants.js.map +1 -1
- package/dist/spam/identify.js +3 -6
- package/dist/spam/identify.js.map +1 -1
- package/dist/spam/providers/hcaptcha.d.ts +17 -0
- package/dist/spam/providers/hcaptcha.js +18 -0
- package/dist/spam/providers/hcaptcha.js.map +1 -0
- package/dist/spam/providers/recaptcha.d.ts +23 -0
- package/dist/spam/providers/recaptcha.js +23 -0
- package/dist/spam/providers/recaptcha.js.map +1 -0
- package/dist/spam/providers/siteverify.js +34 -0
- package/dist/spam/providers/siteverify.js.map +1 -0
- package/dist/spam/providers/turnstile.d.ts +17 -0
- package/dist/spam/providers/turnstile.js +18 -0
- package/dist/spam/providers/turnstile.js.map +1 -0
- package/dist/spam/resolveSpam.js +2 -1
- package/dist/spam/resolveSpam.js.map +1 -1
- package/dist/spam/spamGuard.js +25 -11
- package/dist/spam/spamGuard.js.map +1 -1
- package/dist/spam/types.d.ts +19 -4
- package/dist/submissions/SubmissionAnswers.js +6 -2
- package/dist/submissions/SubmissionAnswers.js.map +1 -1
- package/dist/submissions/SubmissionAnswersClient.js +100 -64
- package/dist/submissions/SubmissionAnswersClient.js.map +1 -1
- package/dist/submissions/coerceBoolean.js +14 -0
- package/dist/submissions/coerceBoolean.js.map +1 -0
- package/dist/submissions/createSubmission.d.ts +36 -0
- package/dist/submissions/createSubmission.js +26 -0
- package/dist/submissions/createSubmission.js.map +1 -0
- package/dist/submissions/formIdOf.js +13 -0
- package/dist/submissions/formIdOf.js.map +1 -0
- package/dist/submissions/resolveVotedSubmission.d.ts +27 -0
- package/dist/submissions/resolveVotedSubmission.js +51 -0
- package/dist/submissions/resolveVotedSubmission.js.map +1 -0
- package/dist/submissions/runSubmission.d.ts +10 -0
- package/dist/submissions/runSubmission.js +104 -54
- package/dist/submissions/runSubmission.js.map +1 -1
- package/dist/submissions/types.d.ts +11 -4
- package/dist/submissions/validateSubmission.js +99 -13
- package/dist/submissions/validateSubmission.js.map +1 -1
- package/dist/submissions/verifyContext.js +35 -0
- package/dist/submissions/verifyContext.js.map +1 -0
- package/dist/submissions/voteChangeEndpoint.js +105 -0
- package/dist/submissions/voteChangeEndpoint.js.map +1 -0
- package/dist/submissions/votedCookie.d.ts +15 -0
- package/dist/submissions/votedCookie.js +74 -0
- package/dist/submissions/votedCookie.js.map +1 -0
- package/dist/translations/clientRuntimeKeys.d.ts +17 -0
- package/dist/translations/clientRuntimeKeys.js +48 -0
- package/dist/translations/clientRuntimeKeys.js.map +1 -0
- package/dist/translations/de.d.ts +12 -0
- package/dist/translations/de.js +380 -0
- package/dist/translations/de.js.map +1 -0
- package/dist/translations/en.js +250 -28
- package/dist/translations/en.js.map +1 -1
- package/dist/translations/index.d.ts +14 -5
- package/dist/translations/index.js +14 -3
- package/dist/translations/index.js.map +1 -1
- package/dist/translations/keys.d.ts +245 -23
- package/dist/translations/keys.js +246 -24
- package/dist/translations/keys.js.map +1 -1
- package/dist/translations/makeTranslate.d.ts +7 -3
- package/dist/translations/makeTranslate.js +12 -3
- package/dist/translations/makeTranslate.js.map +1 -1
- package/dist/translations/server.js +8 -1
- package/dist/translations/server.js.map +1 -1
- package/dist/uploads/captureFileRef.d.ts +10 -3
- package/dist/uploads/captureFileRef.js +18 -9
- package/dist/uploads/captureFileRef.js.map +1 -1
- package/dist/uploads/formatBytes.d.ts +9 -0
- package/dist/uploads/formatBytes.js +25 -0
- package/dist/uploads/formatBytes.js.map +1 -0
- package/dist/uploads/resolveFileRef.js +3 -2
- package/dist/uploads/resolveFileRef.js.map +1 -1
- package/dist/uploads/types.d.ts +1 -2
- package/dist/validation/buildRuleBlocks.js +18 -17
- package/dist/validation/buildRuleBlocks.js.map +1 -1
- package/dist/validation/builtin/email.js +2 -1
- package/dist/validation/builtin/email.js.map +1 -1
- package/dist/validation/builtin/index.d.ts +14 -0
- package/dist/validation/builtin/index.js +14 -1
- package/dist/validation/builtin/index.js.map +1 -1
- package/dist/validation/builtin/integer.js +15 -0
- package/dist/validation/builtin/integer.js.map +1 -0
- package/dist/validation/builtin/matchesField.js +3 -7
- package/dist/validation/builtin/matchesField.js.map +1 -1
- package/dist/validation/builtin/max.js +1 -0
- package/dist/validation/builtin/max.js.map +1 -1
- package/dist/validation/builtin/maxDate.js +24 -0
- package/dist/validation/builtin/maxDate.js.map +1 -0
- package/dist/validation/builtin/maxLength.js +1 -0
- package/dist/validation/builtin/maxLength.js.map +1 -1
- package/dist/validation/builtin/min.js +1 -0
- package/dist/validation/builtin/min.js.map +1 -1
- package/dist/validation/builtin/minDate.js +24 -0
- package/dist/validation/builtin/minDate.js.map +1 -0
- package/dist/validation/builtin/minLength.js +1 -0
- package/dist/validation/builtin/minLength.js.map +1 -1
- package/dist/validation/builtin/notAlreadySubmitted.js +5 -1
- package/dist/validation/builtin/notAlreadySubmitted.js.map +1 -1
- package/dist/validation/builtin/oneOf.js +1 -0
- package/dist/validation/builtin/oneOf.js.map +1 -1
- package/dist/validation/builtin/pattern.js +11 -2
- package/dist/validation/builtin/pattern.js.map +1 -1
- package/dist/validation/builtin/url.js +1 -0
- package/dist/validation/builtin/url.js.map +1 -1
- package/dist/validation/builtin/validateDateBound.js +18 -0
- package/dist/validation/builtin/validateDateBound.js.map +1 -0
- package/dist/validation/builtin/validateRegexParams.js +44 -0
- package/dist/validation/builtin/validateRegexParams.js.map +1 -0
- package/dist/validation/emailPattern.js +10 -0
- package/dist/validation/emailPattern.js.map +1 -0
- package/dist/validation/fieldTargetParam.d.ts +22 -0
- package/dist/validation/fieldTargetParam.js +38 -0
- package/dist/validation/fieldTargetParam.js.map +1 -0
- package/dist/validation/registry.d.ts +2 -1
- package/dist/validation/registry.js +2 -9
- package/dist/validation/registry.js.map +1 -1
- package/dist/validation/runValidation.js +8 -29
- package/dist/validation/runValidation.js.map +1 -1
- package/dist/validation/types.d.ts +5 -11
- package/dist/validation/validateUrl.js +22 -0
- package/dist/validation/validateUrl.js.map +1 -0
- package/package.json +14 -6
- package/styles/form-builder.css +94 -190
- package/dist/collections/uploads.d.ts +0 -30
- package/dist/collections/uploads.js +0 -55
- package/dist/collections/uploads.js.map +0 -1
- package/dist/consent/buildConsentSourceConfig.js +0 -49
- package/dist/consent/buildConsentSourceConfig.js.map +0 -1
- package/dist/consent/builtin/index.d.ts +0 -7
- package/dist/consent/builtin/index.js +0 -11
- package/dist/consent/builtin/index.js.map +0 -1
- package/dist/consent/builtin/pageReference.js +0 -75
- package/dist/consent/builtin/pageReference.js.map +0 -1
- package/dist/consent/builtin/static.js +0 -44
- package/dist/consent/builtin/static.js.map +0 -1
- package/dist/consent/defineConsentSource.d.ts +0 -35
- package/dist/consent/defineConsentSource.js +0 -6
- package/dist/consent/defineConsentSource.js.map +0 -1
- package/dist/consent/registry.d.ts +0 -16
- package/dist/consent/registry.js +0 -16
- package/dist/consent/registry.js.map +0 -1
- package/dist/consent/resolveConsentLinks.d.ts +0 -19
- package/dist/consent/resolveConsentLinks.js +0 -26
- package/dist/consent/resolveConsentLinks.js.map +0 -1
- package/dist/presentations/registry.d.ts +0 -15
- package/dist/presentations/registry.js +0 -15
- package/dist/presentations/registry.js.map +0 -1
- package/dist/react/toFormDocument.d.ts +0 -24
- package/dist/react/toFormDocument.js +0 -22
- package/dist/react/toFormDocument.js.map +0 -1
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { keys } from "../translations/keys.js";
|
|
2
|
+
import { asTranslate } from "../translations/server.js";
|
|
3
|
+
import { verifyFormContext } from "../context/formContext.js";
|
|
4
|
+
import { CONTEXT_KEY } from "../spam/constants.js";
|
|
5
|
+
import { APIError } from "payload";
|
|
6
|
+
//#region src/submissions/verifyContext.ts
|
|
7
|
+
/**
|
|
8
|
+
* beforeValidate: pull the reserved signed-context entry out of the submitted values, verify it, and
|
|
9
|
+
* stamp the verified `{ relationTo, value }` on the submission's separate `context` field. Runs
|
|
10
|
+
* independently of the spam config (context must work with spam off) and before `validateSubmission`
|
|
11
|
+
* stores the answers, so the token never reaches `values`, the answers view, or `{{*}}` output.
|
|
12
|
+
*
|
|
13
|
+
* A missing context is normal (the same form on an ordinary page carries none). An invalid one is
|
|
14
|
+
* rejected loudly rather than dropped to absent, so a tampered reference cannot degrade into a send to
|
|
15
|
+
* the statically configured recipients, which would hide the attack. The stored `value` is a string
|
|
16
|
+
* for cross-adapter consistency; the id it references is already public.
|
|
17
|
+
*/
|
|
18
|
+
const verifyContext = () => async ({ data, operation, req }) => {
|
|
19
|
+
if (operation !== "create" || !data) return data;
|
|
20
|
+
const values = Array.isArray(data.values) ? data.values : [];
|
|
21
|
+
const token = values.find((entry) => entry.field === CONTEXT_KEY)?.value;
|
|
22
|
+
data.values = values.filter((entry) => entry.field !== CONTEXT_KEY);
|
|
23
|
+
if (typeof token !== "string" || token.length === 0) return data;
|
|
24
|
+
const verified = verifyFormContext(token, req.payload.secret);
|
|
25
|
+
if (!verified) throw new APIError(asTranslate(req.i18n.t)(keys.contextInvalid), 400);
|
|
26
|
+
data.context = {
|
|
27
|
+
relationTo: verified.relationTo,
|
|
28
|
+
value: String(verified.value)
|
|
29
|
+
};
|
|
30
|
+
return data;
|
|
31
|
+
};
|
|
32
|
+
//#endregion
|
|
33
|
+
export { verifyContext };
|
|
34
|
+
|
|
35
|
+
//# sourceMappingURL=verifyContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verifyContext.js","names":[],"sources":["../../src/submissions/verifyContext.ts"],"sourcesContent":["import { APIError, type CollectionBeforeValidateHook } from 'payload'\nimport { verifyFormContext } from '../context/formContext'\nimport { CONTEXT_KEY } from '../spam/constants'\nimport { keys } from '../translations/keys'\nimport { asTranslate } from '../translations/server'\nimport type { SubmissionValue } from './types'\n\n/**\n * beforeValidate: pull the reserved signed-context entry out of the submitted values, verify it, and\n * stamp the verified `{ relationTo, value }` on the submission's separate `context` field. Runs\n * independently of the spam config (context must work with spam off) and before `validateSubmission`\n * stores the answers, so the token never reaches `values`, the answers view, or `{{*}}` output.\n *\n * A missing context is normal (the same form on an ordinary page carries none). An invalid one is\n * rejected loudly rather than dropped to absent, so a tampered reference cannot degrade into a send to\n * the statically configured recipients, which would hide the attack. The stored `value` is a string\n * for cross-adapter consistency; the id it references is already public.\n */\nexport const verifyContext =\n\t(): CollectionBeforeValidateHook =>\n\tasync ({ data, operation, req }) => {\n\t\tif (operation !== 'create' || !data) {\n\t\t\treturn data\n\t\t}\n\t\tconst values = Array.isArray(data.values) ? (data.values as SubmissionValue[]) : []\n\t\tconst token = values.find((entry) => entry.field === CONTEXT_KEY)?.value\n\t\t// Always strip the reserved entry, verified or not, so it can never land in the answers.\n\t\tdata.values = values.filter((entry) => entry.field !== CONTEXT_KEY)\n\t\tif (typeof token !== 'string' || token.length === 0) {\n\t\t\treturn data\n\t\t}\n\t\tconst verified = verifyFormContext(token, req.payload.secret)\n\t\tif (!verified) {\n\t\t\tthrow new APIError(asTranslate(req.i18n.t)(keys.contextInvalid), 400)\n\t\t}\n\t\tdata.context = { relationTo: verified.relationTo, value: String(verified.value) }\n\t\treturn data\n\t}\n"],"mappings":";;;;;;;;;;;;;;;;;AAkBA,MAAa,sBAEZ,OAAO,EAAE,MAAM,WAAW,UAAU;CACnC,IAAI,cAAc,YAAY,CAAC,MAC9B,OAAO;CAER,MAAM,SAAS,MAAM,QAAQ,KAAK,MAAM,IAAK,KAAK,SAA+B,CAAC;CAClF,MAAM,QAAQ,OAAO,MAAM,UAAU,MAAM,UAAU,WAAW,GAAG;CAEnE,KAAK,SAAS,OAAO,QAAQ,UAAU,MAAM,UAAU,WAAW;CAClE,IAAI,OAAO,UAAU,YAAY,MAAM,WAAW,GACjD,OAAO;CAER,MAAM,WAAW,kBAAkB,OAAO,IAAI,QAAQ,MAAM;CAC5D,IAAI,CAAC,UACJ,MAAM,IAAI,SAAS,YAAY,IAAI,KAAK,CAAC,EAAE,KAAK,cAAc,GAAG,GAAG;CAErE,KAAK,UAAU;EAAE,YAAY,SAAS;EAAY,OAAO,OAAO,SAAS,KAAK;CAAE;CAChF,OAAO;AACR"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { keys } from "../translations/keys.js";
|
|
2
|
+
import { asTranslate } from "../translations/server.js";
|
|
3
|
+
import "../actions/dispatchContext.js";
|
|
4
|
+
import { pollConfigOf } from "../form/pollState.js";
|
|
5
|
+
import { formIdOf } from "./formIdOf.js";
|
|
6
|
+
import { VOTE_CHANGE_CONTEXT_KEY, votedSubmissionIdFromCookie } from "./votedCookie.js";
|
|
7
|
+
import { APIError, addDataAndFileToRequest, addLocalesToRequestFromData } from "payload";
|
|
8
|
+
//#region src/submissions/voteChangeEndpoint.ts
|
|
9
|
+
const FORM_SUBMISSIONS_SLUG = "form-submissions";
|
|
10
|
+
const FORMS_SLUG = "forms";
|
|
11
|
+
/** Marks the vote-submit endpoint in the sanitized endpoint list (`custom.formBuilder`). */
|
|
12
|
+
const VOTE_SUBMIT_ENDPOINT_TAG = "vote-submit";
|
|
13
|
+
const isComplete = (doc) => doc.status == null || doc.status === "complete";
|
|
14
|
+
/**
|
|
15
|
+
* The submission a cookie-identified re-vote should update, or null when the request must fall
|
|
16
|
+
* through to a plain create. Guards run cheapest-first: no valid signed cookie for the posted form
|
|
17
|
+
* means no form fetch at all, so the delegation overhead on ordinary submissions is one header
|
|
18
|
+
* parse. A token is honored only when the form is an `allowChange` poll and it names a still
|
|
19
|
+
* existing, complete submission of that same form; anything else (pruned row, cross-form replay,
|
|
20
|
+
* legacy `1` marker, tampering) makes the caller a new voter rather than an error.
|
|
21
|
+
*/
|
|
22
|
+
const resolveVoteChangeTarget = async (args) => {
|
|
23
|
+
const { req, formId } = args;
|
|
24
|
+
if (formId == null) return null;
|
|
25
|
+
const submissionId = votedSubmissionIdFromCookie(req.headers?.get("cookie"), formId, req.payload.secret);
|
|
26
|
+
if (submissionId == null) return null;
|
|
27
|
+
const form = await req.payload.findByID({
|
|
28
|
+
collection: FORMS_SLUG,
|
|
29
|
+
id: formId,
|
|
30
|
+
depth: 0,
|
|
31
|
+
overrideAccess: true,
|
|
32
|
+
req
|
|
33
|
+
}).catch(() => null);
|
|
34
|
+
if (form?.pollEnabled !== true || pollConfigOf(form.poll)?.allowChange !== true) return null;
|
|
35
|
+
const submission = await req.payload.findByID({
|
|
36
|
+
collection: FORM_SUBMISSIONS_SLUG,
|
|
37
|
+
id: submissionId,
|
|
38
|
+
depth: 0,
|
|
39
|
+
overrideAccess: true,
|
|
40
|
+
req
|
|
41
|
+
}).catch(() => null);
|
|
42
|
+
if (submission == null) return null;
|
|
43
|
+
const stored = submission;
|
|
44
|
+
if (String(formIdOf(stored.form) ?? "") !== String(formId) || !isComplete(stored)) return null;
|
|
45
|
+
return { submissionId: submission.id };
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Custom root `POST /form-submissions` endpoint. Payload matches a collection's custom endpoints
|
|
49
|
+
* ahead of its built-in REST routes, so this handler sees every REST create first: when the posted
|
|
50
|
+
* form is an `allowChange` poll and the voted cookie identifies the caller's submission, it turns
|
|
51
|
+
* the request into an in-place update (create-grade hooks opt in via the context flag); otherwise
|
|
52
|
+
* it delegates to the stock create handler found in the same sanitized endpoint list, keeping the
|
|
53
|
+
* default path semantics Payload's, not a reimplementation. The update runs `overrideAccess`
|
|
54
|
+
* because the collection is deliberately update-closed to every API caller; the signed cookie is
|
|
55
|
+
* the credential here, verified above rather than by collection access.
|
|
56
|
+
*/
|
|
57
|
+
const buildVoteSubmitEndpoint = () => {
|
|
58
|
+
const handler = async (req) => {
|
|
59
|
+
await addDataAndFileToRequest(req);
|
|
60
|
+
addLocalesToRequestFromData(req);
|
|
61
|
+
const data = req.data ?? {};
|
|
62
|
+
const target = await resolveVoteChangeTarget({
|
|
63
|
+
req,
|
|
64
|
+
formId: data.form
|
|
65
|
+
});
|
|
66
|
+
if (!target) {
|
|
67
|
+
const endpoints = req.payload.collections[FORM_SUBMISSIONS_SLUG]?.config.endpoints;
|
|
68
|
+
const stockCreate = (Array.isArray(endpoints) ? endpoints : []).find((endpoint) => endpoint.method === "post" && endpoint.path === "/" && endpoint.custom?.formBuilder !== "vote-submit");
|
|
69
|
+
if (!stockCreate) throw new APIError("form-builder: stock create endpoint not found", 500);
|
|
70
|
+
if (req.body) Object.defineProperty(req, "body", {
|
|
71
|
+
configurable: true,
|
|
72
|
+
value: null
|
|
73
|
+
});
|
|
74
|
+
const response = await stockCreate.handler(req);
|
|
75
|
+
if (req.context?.["formBuilderEssentialActionFailed"] === true && response.ok) return Response.json({ errors: [{ message: asTranslate(req.t)(keys.submissionActionFailed) }] }, { status: 502 });
|
|
76
|
+
return response;
|
|
77
|
+
}
|
|
78
|
+
req.context[VOTE_CHANGE_CONTEXT_KEY] = target.submissionId;
|
|
79
|
+
const doc = await req.payload.update.bind(req.payload)({
|
|
80
|
+
collection: FORM_SUBMISSIONS_SLUG,
|
|
81
|
+
id: target.submissionId,
|
|
82
|
+
data: {
|
|
83
|
+
form: data.form,
|
|
84
|
+
values: data.values
|
|
85
|
+
},
|
|
86
|
+
depth: 0,
|
|
87
|
+
overrideAccess: true,
|
|
88
|
+
req
|
|
89
|
+
});
|
|
90
|
+
return Response.json({
|
|
91
|
+
doc,
|
|
92
|
+
message: req.t("general:updatedSuccessfully")
|
|
93
|
+
}, { status: 200 });
|
|
94
|
+
};
|
|
95
|
+
return {
|
|
96
|
+
path: "/",
|
|
97
|
+
method: "post",
|
|
98
|
+
handler,
|
|
99
|
+
custom: { formBuilder: VOTE_SUBMIT_ENDPOINT_TAG }
|
|
100
|
+
};
|
|
101
|
+
};
|
|
102
|
+
//#endregion
|
|
103
|
+
export { buildVoteSubmitEndpoint };
|
|
104
|
+
|
|
105
|
+
//# sourceMappingURL=voteChangeEndpoint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"voteChangeEndpoint.js","names":[],"sources":["../../src/submissions/voteChangeEndpoint.ts"],"sourcesContent":["import {\n\tAPIError,\n\taddDataAndFileToRequest,\n\taddLocalesToRequestFromData,\n\ttype Endpoint,\n\ttype PayloadRequest,\n} from 'payload'\nimport { ESSENTIAL_ACTION_FAILED_CONTEXT_KEY } from '../actions/dispatchContext'\nimport { pollConfigOf } from '../form/pollState'\nimport { keys } from '../translations/keys'\nimport { asTranslate } from '../translations/server'\nimport { formIdOf } from './formIdOf'\nimport { VOTE_CHANGE_CONTEXT_KEY, votedSubmissionIdFromCookie } from './votedCookie'\n\nconst FORM_SUBMISSIONS_SLUG = 'form-submissions'\nconst FORMS_SLUG = 'forms'\n\n/** Marks the vote-submit endpoint in the sanitized endpoint list (`custom.formBuilder`). */\nexport const VOTE_SUBMIT_ENDPOINT_TAG = 'vote-submit'\n\nconst isComplete = (doc: { status?: unknown }): boolean =>\n\tdoc.status == null || doc.status === 'complete'\n\n/**\n * The submission a cookie-identified re-vote should update, or null when the request must fall\n * through to a plain create. Guards run cheapest-first: no valid signed cookie for the posted form\n * means no form fetch at all, so the delegation overhead on ordinary submissions is one header\n * parse. A token is honored only when the form is an `allowChange` poll and it names a still\n * existing, complete submission of that same form; anything else (pruned row, cross-form replay,\n * legacy `1` marker, tampering) makes the caller a new voter rather than an error.\n */\nexport const resolveVoteChangeTarget = async (args: {\n\treq: PayloadRequest\n\tformId: number | string | undefined | null\n}): Promise<{ submissionId: number | string } | null> => {\n\tconst { req, formId } = args\n\tif (formId == null) {\n\t\treturn null\n\t}\n\tconst submissionId = votedSubmissionIdFromCookie(\n\t\treq.headers?.get('cookie'),\n\t\tformId,\n\t\treq.payload.secret\n\t)\n\tif (submissionId == null) {\n\t\treturn null\n\t}\n\tconst form = await req.payload\n\t\t.findByID({ collection: FORMS_SLUG, id: formId, depth: 0, overrideAccess: true, req })\n\t\t.catch(() => null)\n\tif (form?.pollEnabled !== true || pollConfigOf(form.poll)?.allowChange !== true) {\n\t\treturn null\n\t}\n\tconst submission = await req.payload\n\t\t.findByID({\n\t\t\tcollection: FORM_SUBMISSIONS_SLUG,\n\t\t\tid: submissionId,\n\t\t\tdepth: 0,\n\t\t\toverrideAccess: true,\n\t\t\treq,\n\t\t})\n\t\t.catch(() => null)\n\tif (submission == null) {\n\t\treturn null\n\t}\n\tconst stored = submission as { form?: unknown; status?: unknown }\n\tif (String(formIdOf(stored.form) ?? '') !== String(formId) || !isComplete(stored)) {\n\t\treturn null\n\t}\n\treturn { submissionId: submission.id as number | string }\n}\n\n/**\n * Custom root `POST /form-submissions` endpoint. Payload matches a collection's custom endpoints\n * ahead of its built-in REST routes, so this handler sees every REST create first: when the posted\n * form is an `allowChange` poll and the voted cookie identifies the caller's submission, it turns\n * the request into an in-place update (create-grade hooks opt in via the context flag); otherwise\n * it delegates to the stock create handler found in the same sanitized endpoint list, keeping the\n * default path semantics Payload's, not a reimplementation. The update runs `overrideAccess`\n * because the collection is deliberately update-closed to every API caller; the signed cookie is\n * the credential here, verified above rather than by collection access.\n */\nexport const buildVoteSubmitEndpoint = (): Endpoint => {\n\tconst handler = async (req: PayloadRequest): Promise<Response> => {\n\t\tawait addDataAndFileToRequest(req)\n\t\taddLocalesToRequestFromData(req)\n\t\tconst data = (req.data ?? {}) as {\n\t\t\tform?: number | string\n\t\t\tvalues?: unknown\n\t\t}\n\t\tconst target = await resolveVoteChangeTarget({ req, formId: data.form })\n\t\tif (!target) {\n\t\t\tconst endpoints = req.payload.collections[FORM_SUBMISSIONS_SLUG]?.config.endpoints\n\t\t\tconst registered: Endpoint[] = Array.isArray(endpoints) ? endpoints : []\n\t\t\t// Next root-POST match excluding our own tag (never handler identity: a host-wrapped\n\t\t\t// handler would find itself and recurse). First-match mirrors handleEndpoints routing,\n\t\t\t// so another plugin's interceptor still wins exactly as it would without us.\n\t\t\tconst stockCreate = registered.find(\n\t\t\t\t(endpoint) =>\n\t\t\t\t\tendpoint.method === 'post' &&\n\t\t\t\t\tendpoint.path === '/' &&\n\t\t\t\t\tendpoint.custom?.formBuilder !== VOTE_SUBMIT_ENDPOINT_TAG\n\t\t\t)\n\t\t\tif (!stockCreate) {\n\t\t\t\tthrow new APIError('form-builder: stock create endpoint not found', 500)\n\t\t\t}\n\t\t\t// A consumed fetch body stays non-null, so Payload's addDataAndFileToRequest wrapper\n\t\t\t// would re-read it and 500; req.data/req.file are already populated, so hide the spent\n\t\t\t// stream (defineProperty: `body` is a getter-only prototype accessor).\n\t\t\tif (req.body) {\n\t\t\t\tObject.defineProperty(req, 'body', { configurable: true, value: null })\n\t\t\t}\n\t\t\tconst response = await stockCreate.handler(req)\n\t\t\t// An essential action's failure is the submission's failure: the row is committed and kept\n\t\t\t// (see dispatchActions), but the visitor must not be told it worked. 502 because the\n\t\t\t// upstream the submission exists for rejected or never confirmed it.\n\t\t\tif (req.context?.[ESSENTIAL_ACTION_FAILED_CONTEXT_KEY] === true && response.ok) {\n\t\t\t\treturn Response.json(\n\t\t\t\t\t{ errors: [{ message: asTranslate(req.t)(keys.submissionActionFailed) }] },\n\t\t\t\t\t{ status: 502 }\n\t\t\t\t)\n\t\t\t}\n\t\t\treturn response\n\t\t}\n\t\treq.context[VOTE_CHANGE_CONTEXT_KEY] = target.submissionId\n\t\t// Slug-agnostic cast (the `createSubmission` idiom): a host's generated types pin the\n\t\t// runtime-registered collection's `form` id flavor and `values` JSON shape, which this\n\t\t// framework-level write cannot know. Bound, because `update` is a prototype method.\n\t\tconst update = req.payload.update.bind(req.payload) as unknown as (options: {\n\t\t\tcollection: string\n\t\t\tid: number | string\n\t\t\tdata: { form?: number | string; values?: unknown }\n\t\t\tdepth?: number\n\t\t\toverrideAccess?: boolean\n\t\t\treq?: PayloadRequest\n\t\t}) => Promise<unknown>\n\t\tconst doc = await update({\n\t\t\tcollection: FORM_SUBMISSIONS_SLUG,\n\t\t\tid: target.submissionId,\n\t\t\tdata: { form: data.form, values: data.values },\n\t\t\tdepth: 0,\n\t\t\toverrideAccess: true,\n\t\t\treq,\n\t\t})\n\t\treturn Response.json({ doc, message: req.t('general:updatedSuccessfully') }, { status: 200 })\n\t}\n\treturn { path: '/', method: 'post', handler, custom: { formBuilder: VOTE_SUBMIT_ENDPOINT_TAG } }\n}\n"],"mappings":";;;;;;;;AAcA,MAAM,wBAAwB;AAC9B,MAAM,aAAa;;AAGnB,MAAa,2BAA2B;AAExC,MAAM,cAAc,QACnB,IAAI,UAAU,QAAQ,IAAI,WAAW;;;;;;;;;AAUtC,MAAa,0BAA0B,OAAO,SAGW;CACxD,MAAM,EAAE,KAAK,WAAW;CACxB,IAAI,UAAU,MACb,OAAO;CAER,MAAM,eAAe,4BACpB,IAAI,SAAS,IAAI,QAAQ,GACzB,QACA,IAAI,QAAQ,MACb;CACA,IAAI,gBAAgB,MACnB,OAAO;CAER,MAAM,OAAO,MAAM,IAAI,QACrB,SAAS;EAAE,YAAY;EAAY,IAAI;EAAQ,OAAO;EAAG,gBAAgB;EAAM;CAAI,CAAC,EACpF,YAAY,IAAI;CAClB,IAAI,MAAM,gBAAgB,QAAQ,aAAa,KAAK,IAAI,GAAG,gBAAgB,MAC1E,OAAO;CAER,MAAM,aAAa,MAAM,IAAI,QAC3B,SAAS;EACT,YAAY;EACZ,IAAI;EACJ,OAAO;EACP,gBAAgB;EAChB;CACD,CAAC,EACA,YAAY,IAAI;CAClB,IAAI,cAAc,MACjB,OAAO;CAER,MAAM,SAAS;CACf,IAAI,OAAO,SAAS,OAAO,IAAI,KAAK,EAAE,MAAM,OAAO,MAAM,KAAK,CAAC,WAAW,MAAM,GAC/E,OAAO;CAER,OAAO,EAAE,cAAc,WAAW,GAAsB;AACzD;;;;;;;;;;;AAYA,MAAa,gCAA0C;CACtD,MAAM,UAAU,OAAO,QAA2C;EACjE,MAAM,wBAAwB,GAAG;EACjC,4BAA4B,GAAG;EAC/B,MAAM,OAAQ,IAAI,QAAQ,CAAC;EAI3B,MAAM,SAAS,MAAM,wBAAwB;GAAE;GAAK,QAAQ,KAAK;EAAK,CAAC;EACvE,IAAI,CAAC,QAAQ;GACZ,MAAM,YAAY,IAAI,QAAQ,YAAY,wBAAwB,OAAO;GAKzE,MAAM,eAJyB,MAAM,QAAQ,SAAS,IAAI,YAAY,CAAC,GAIxC,MAC7B,aACA,SAAS,WAAW,UACpB,SAAS,SAAS,OAClB,SAAS,QAAQ,gBAAA,aACnB;GACA,IAAI,CAAC,aACJ,MAAM,IAAI,SAAS,iDAAiD,GAAG;GAKxE,IAAI,IAAI,MACP,OAAO,eAAe,KAAK,QAAQ;IAAE,cAAc;IAAM,OAAO;GAAK,CAAC;GAEvE,MAAM,WAAW,MAAM,YAAY,QAAQ,GAAG;GAI9C,IAAI,IAAI,UAAA,wCAAmD,QAAQ,SAAS,IAC3E,OAAO,SAAS,KACf,EAAE,QAAQ,CAAC,EAAE,SAAS,YAAY,IAAI,CAAC,EAAE,KAAK,sBAAsB,EAAE,CAAC,EAAE,GACzE,EAAE,QAAQ,IAAI,CACf;GAED,OAAO;EACR;EACA,IAAI,QAAQ,2BAA2B,OAAO;EAY9C,MAAM,MAAM,MARG,IAAI,QAAQ,OAAO,KAAK,IAAI,OAQpB,EAAE;GACxB,YAAY;GACZ,IAAI,OAAO;GACX,MAAM;IAAE,MAAM,KAAK;IAAM,QAAQ,KAAK;GAAO;GAC7C,OAAO;GACP,gBAAgB;GAChB;EACD,CAAC;EACD,OAAO,SAAS,KAAK;GAAE;GAAK,SAAS,IAAI,EAAE,6BAA6B;EAAE,GAAG,EAAE,QAAQ,IAAI,CAAC;CAC7F;CACA,OAAO;EAAE,MAAM;EAAK,QAAQ;EAAQ;EAAS,QAAQ,EAAE,aAAa,yBAAyB;CAAE;AAChG"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Payload } from "payload";
|
|
2
|
+
|
|
3
|
+
//#region src/submissions/votedCookie.d.ts
|
|
4
|
+
/** Name of the httpOnly voted cookie for a form: `fb-voted-{formId}`. */
|
|
5
|
+
declare const votedCookieName: (formId: number | string) => string;
|
|
6
|
+
/**
|
|
7
|
+
* Whether a request's `Cookie` header carries the voted marker for a form. For SSR hosts: read
|
|
8
|
+
* the header (e.g. Next's `(await headers()).get('cookie')`) and pass the result to `<Poll hasVoted>`.
|
|
9
|
+
* The cookie is httpOnly (set server-side when the plugin's `poll.votedCookie` option is on), so
|
|
10
|
+
* this server read is the only way to consume it.
|
|
11
|
+
*/
|
|
12
|
+
declare const hasVotedCookie: (cookieHeader: string | null | undefined, formId: number | string) => boolean;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { hasVotedCookie, votedCookieName };
|
|
15
|
+
//# sourceMappingURL=votedCookie.d.ts.map
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { signFormContext, verifyFormContext } from "../context/formContext.js";
|
|
2
|
+
//#region src/submissions/votedCookie.ts
|
|
3
|
+
/**
|
|
4
|
+
* `req.context` key under which `validateSubmission` stashes the loaded form's poll state
|
|
5
|
+
* (`{ pollEnabled, allowChange }`) so the voted-cookie `afterChange` hook can skip a second form
|
|
6
|
+
* fetch on the same request.
|
|
7
|
+
*/
|
|
8
|
+
const POLL_CONTEXT_KEY = "formBuilderPollConfig";
|
|
9
|
+
/**
|
|
10
|
+
* `req.context` key the vote-submit endpoint sets to the id of the submission a cookie-identified
|
|
11
|
+
* re-vote is updating. Its presence is what opts the update operation into the create-grade
|
|
12
|
+
* pipeline: the spam guard, full validation in `validateSubmission`, the dedup rule's
|
|
13
|
+
* self-exclusion, and the voted-cookie refresh all key off it, so an unflagged update (host
|
|
14
|
+
* server code, admin tooling) keeps today's behavior exactly.
|
|
15
|
+
*/
|
|
16
|
+
const VOTE_CHANGE_CONTEXT_KEY = "formBuilderVoteChange";
|
|
17
|
+
/** The change-target submission id a flagged request carries, or undefined. */
|
|
18
|
+
const voteChangeTargetOf = (req) => {
|
|
19
|
+
const target = req.context?.[VOTE_CHANGE_CONTEXT_KEY];
|
|
20
|
+
return typeof target === "string" || typeof target === "number" ? target : void 0;
|
|
21
|
+
};
|
|
22
|
+
/** Redeclared to avoid a cycle: `collections/formSubmissions` imports from this module. */
|
|
23
|
+
const FORM_SUBMISSIONS_SLUG = "form-submissions";
|
|
24
|
+
/** One year, matching the voted cookie's `Max-Age` so the token never outlives the cookie by less. */
|
|
25
|
+
const VOTED_COOKIE_MAX_AGE_SECONDS = 31536e3;
|
|
26
|
+
/** Name of the httpOnly voted cookie for a form: `fb-voted-{formId}`. */
|
|
27
|
+
const votedCookieName = (formId) => `fb-voted-${formId}`;
|
|
28
|
+
/**
|
|
29
|
+
* Whether a request's `Cookie` header carries the voted marker for a form. For SSR hosts: read
|
|
30
|
+
* the header (e.g. Next's `(await headers()).get('cookie')`) and pass the result to `<Poll hasVoted>`.
|
|
31
|
+
* The cookie is httpOnly (set server-side when the plugin's `poll.votedCookie` option is on), so
|
|
32
|
+
* this server read is the only way to consume it.
|
|
33
|
+
*/
|
|
34
|
+
const hasVotedCookie = (cookieHeader, formId) => {
|
|
35
|
+
if (!cookieHeader) return false;
|
|
36
|
+
return votedCookieValue(cookieHeader, formId) != null;
|
|
37
|
+
};
|
|
38
|
+
const votedCookieValue = (cookieHeader, formId) => {
|
|
39
|
+
if (!cookieHeader) return null;
|
|
40
|
+
const name = votedCookieName(formId);
|
|
41
|
+
for (const pair of cookieHeader.split(";")) {
|
|
42
|
+
const eq = pair.indexOf("=");
|
|
43
|
+
if (eq !== -1 && pair.slice(0, eq).trim() === name) return pair.slice(eq + 1).trim();
|
|
44
|
+
}
|
|
45
|
+
return null;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Sign a submission id into the voted cookie's value for an `allowChange` poll. The token (same
|
|
49
|
+
* HMAC format as `signFormContext`) is what lets a repeat submit update that submission in place;
|
|
50
|
+
* signing means only ids the server issued are accepted, so a forged cookie cannot point a
|
|
51
|
+
* re-vote at someone else's submission.
|
|
52
|
+
*/
|
|
53
|
+
const signVotedCookieValue = (payload, submissionId) => signFormContext({
|
|
54
|
+
payload,
|
|
55
|
+
relationTo: FORM_SUBMISSIONS_SLUG,
|
|
56
|
+
value: submissionId,
|
|
57
|
+
expiresIn: VOTED_COOKIE_MAX_AGE_SECONDS
|
|
58
|
+
});
|
|
59
|
+
/**
|
|
60
|
+
* The submission id carried by a form's voted cookie, or null when the header has no cookie for
|
|
61
|
+
* the form, the value is the legacy boolean marker (`1`), or the token fails verification
|
|
62
|
+
* (tampered, wrong secret, expired). Null means "treat the caller as a new voter".
|
|
63
|
+
*/
|
|
64
|
+
const votedSubmissionIdFromCookie = (cookieHeader, formId, secret) => {
|
|
65
|
+
const value = votedCookieValue(cookieHeader, formId);
|
|
66
|
+
if (value == null || value.length === 0) return null;
|
|
67
|
+
const reference = verifyFormContext(value, secret);
|
|
68
|
+
if (reference == null || reference.relationTo !== FORM_SUBMISSIONS_SLUG) return null;
|
|
69
|
+
return String(reference.value);
|
|
70
|
+
};
|
|
71
|
+
//#endregion
|
|
72
|
+
export { POLL_CONTEXT_KEY, VOTED_COOKIE_MAX_AGE_SECONDS, VOTE_CHANGE_CONTEXT_KEY, hasVotedCookie, signVotedCookieValue, voteChangeTargetOf, votedCookieName, votedSubmissionIdFromCookie };
|
|
73
|
+
|
|
74
|
+
//# sourceMappingURL=votedCookie.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"votedCookie.js","names":[],"sources":["../../src/submissions/votedCookie.ts"],"sourcesContent":["import type { Payload } from 'payload'\nimport { signFormContext, verifyFormContext } from '../context/formContext'\n\n/**\n * `req.context` key under which `validateSubmission` stashes the loaded form's poll state\n * (`{ pollEnabled, allowChange }`) so the voted-cookie `afterChange` hook can skip a second form\n * fetch on the same request.\n */\nexport const POLL_CONTEXT_KEY = 'formBuilderPollConfig'\n\n/** The poll state `validateSubmission` stashes under {@link POLL_CONTEXT_KEY}. */\nexport type PollContextState = { pollEnabled: boolean; allowChange: boolean }\n\n/**\n * `req.context` key the vote-submit endpoint sets to the id of the submission a cookie-identified\n * re-vote is updating. Its presence is what opts the update operation into the create-grade\n * pipeline: the spam guard, full validation in `validateSubmission`, the dedup rule's\n * self-exclusion, and the voted-cookie refresh all key off it, so an unflagged update (host\n * server code, admin tooling) keeps today's behavior exactly.\n */\nexport const VOTE_CHANGE_CONTEXT_KEY = 'formBuilderVoteChange'\n\n/** The change-target submission id a flagged request carries, or undefined. */\nexport const voteChangeTargetOf = (req: {\n\tcontext?: Record<string, unknown>\n}): number | string | undefined => {\n\tconst target = req.context?.[VOTE_CHANGE_CONTEXT_KEY]\n\treturn typeof target === 'string' || typeof target === 'number' ? target : undefined\n}\n\n/** Redeclared to avoid a cycle: `collections/formSubmissions` imports from this module. */\nconst FORM_SUBMISSIONS_SLUG = 'form-submissions'\n\n/** One year, matching the voted cookie's `Max-Age` so the token never outlives the cookie by less. */\nexport const VOTED_COOKIE_MAX_AGE_SECONDS = 31_536_000\n\n/** Name of the httpOnly voted cookie for a form: `fb-voted-{formId}`. */\nexport const votedCookieName = (formId: number | string): string => `fb-voted-${formId}`\n\n/**\n * Whether a request's `Cookie` header carries the voted marker for a form. For SSR hosts: read\n * the header (e.g. Next's `(await headers()).get('cookie')`) and pass the result to `<Poll hasVoted>`.\n * The cookie is httpOnly (set server-side when the plugin's `poll.votedCookie` option is on), so\n * this server read is the only way to consume it.\n */\nexport const hasVotedCookie = (\n\tcookieHeader: string | null | undefined,\n\tformId: number | string\n): boolean => {\n\tif (!cookieHeader) {\n\t\treturn false\n\t}\n\treturn votedCookieValue(cookieHeader, formId) != null\n}\n\nconst votedCookieValue = (\n\tcookieHeader: string | null | undefined,\n\tformId: number | string\n): string | null => {\n\tif (!cookieHeader) {\n\t\treturn null\n\t}\n\tconst name = votedCookieName(formId)\n\tfor (const pair of cookieHeader.split(';')) {\n\t\tconst eq = pair.indexOf('=')\n\t\tif (eq !== -1 && pair.slice(0, eq).trim() === name) {\n\t\t\treturn pair.slice(eq + 1).trim()\n\t\t}\n\t}\n\treturn null\n}\n\n/**\n * Sign a submission id into the voted cookie's value for an `allowChange` poll. The token (same\n * HMAC format as `signFormContext`) is what lets a repeat submit update that submission in place;\n * signing means only ids the server issued are accepted, so a forged cookie cannot point a\n * re-vote at someone else's submission.\n */\nexport const signVotedCookieValue = (payload: Payload, submissionId: number | string): string =>\n\tsignFormContext({\n\t\tpayload,\n\t\trelationTo: FORM_SUBMISSIONS_SLUG,\n\t\tvalue: submissionId,\n\t\texpiresIn: VOTED_COOKIE_MAX_AGE_SECONDS,\n\t})\n\n/**\n * The submission id carried by a form's voted cookie, or null when the header has no cookie for\n * the form, the value is the legacy boolean marker (`1`), or the token fails verification\n * (tampered, wrong secret, expired). Null means \"treat the caller as a new voter\".\n */\nexport const votedSubmissionIdFromCookie = (\n\tcookieHeader: string | null | undefined,\n\tformId: number | string,\n\tsecret: string\n): string | null => {\n\tconst value = votedCookieValue(cookieHeader, formId)\n\tif (value == null || value.length === 0) {\n\t\treturn null\n\t}\n\tconst reference = verifyFormContext(value, secret)\n\tif (reference == null || reference.relationTo !== FORM_SUBMISSIONS_SLUG) {\n\t\treturn null\n\t}\n\treturn String(reference.value)\n}\n"],"mappings":";;;;;;;AAQA,MAAa,mBAAmB;;;;;;;;AAYhC,MAAa,0BAA0B;;AAGvC,MAAa,sBAAsB,QAEA;CAClC,MAAM,SAAS,IAAI,UAAU;CAC7B,OAAO,OAAO,WAAW,YAAY,OAAO,WAAW,WAAW,SAAS,KAAA;AAC5E;;AAGA,MAAM,wBAAwB;;AAG9B,MAAa,+BAA+B;;AAG5C,MAAa,mBAAmB,WAAoC,YAAY;;;;;;;AAQhF,MAAa,kBACZ,cACA,WACa;CACb,IAAI,CAAC,cACJ,OAAO;CAER,OAAO,iBAAiB,cAAc,MAAM,KAAK;AAClD;AAEA,MAAM,oBACL,cACA,WACmB;CACnB,IAAI,CAAC,cACJ,OAAO;CAER,MAAM,OAAO,gBAAgB,MAAM;CACnC,KAAK,MAAM,QAAQ,aAAa,MAAM,GAAG,GAAG;EAC3C,MAAM,KAAK,KAAK,QAAQ,GAAG;EAC3B,IAAI,OAAO,MAAM,KAAK,MAAM,GAAG,EAAE,EAAE,KAAK,MAAM,MAC7C,OAAO,KAAK,MAAM,KAAK,CAAC,EAAE,KAAK;CAEjC;CACA,OAAO;AACR;;;;;;;AAQA,MAAa,wBAAwB,SAAkB,iBACtD,gBAAgB;CACf;CACA,YAAY;CACZ,OAAO;CACP,WAAW;AACZ,CAAC;;;;;;AAOF,MAAa,+BACZ,cACA,QACA,WACmB;CACnB,MAAM,QAAQ,iBAAiB,cAAc,MAAM;CACnD,IAAI,SAAS,QAAQ,MAAM,WAAW,GACrC,OAAO;CAER,MAAM,YAAY,kBAAkB,OAAO,MAAM;CACjD,IAAI,aAAa,QAAQ,UAAU,eAAe,uBACjD,OAAO;CAER,OAAO,OAAO,UAAU,KAAK;AAC9B"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { TranslationKey } from "./keys.js";
|
|
2
|
+
|
|
3
|
+
//#region src/translations/clientRuntimeKeys.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* The typed keys the visitor-facing runtime (`<Form>`, `<Poll>`, `<FormResults>`, and the field
|
|
6
|
+
* renderers) resolves through `RendererTranslate`. A host bridging its own i18n can assert its mirror
|
|
7
|
+
* covers these in a unit test, the non-drifting form of a hand-written `dist/` diff. Kept in exact
|
|
8
|
+
* lockstep with `src/react/**` by `clientRuntimeKeys.test.ts`.
|
|
9
|
+
*
|
|
10
|
+
* For a complete, drift-proof fallback prefer `makeTranslate(locale)` (or
|
|
11
|
+
* `makeTranslate(bundles[locale] ?? en)`): a shipped bundle covers every key, including the
|
|
12
|
+
* client-side validation messages resolved outside these components, so no key can leak English.
|
|
13
|
+
*/
|
|
14
|
+
declare const clientRuntimeKeys: readonly TranslationKey[];
|
|
15
|
+
//#endregion
|
|
16
|
+
export { clientRuntimeKeys };
|
|
17
|
+
//# sourceMappingURL=clientRuntimeKeys.d.ts.map
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { keys } from "./keys.js";
|
|
2
|
+
//#region src/translations/clientRuntimeKeys.ts
|
|
3
|
+
/**
|
|
4
|
+
* The typed keys the visitor-facing runtime (`<Form>`, `<Poll>`, `<FormResults>`, and the field
|
|
5
|
+
* renderers) resolves through `RendererTranslate`. A host bridging its own i18n can assert its mirror
|
|
6
|
+
* covers these in a unit test, the non-drifting form of a hand-written `dist/` diff. Kept in exact
|
|
7
|
+
* lockstep with `src/react/**` by `clientRuntimeKeys.test.ts`.
|
|
8
|
+
*
|
|
9
|
+
* For a complete, drift-proof fallback prefer `makeTranslate(locale)` (or
|
|
10
|
+
* `makeTranslate(bundles[locale] ?? en)`): a shipped bundle covers every key, including the
|
|
11
|
+
* client-side validation messages resolved outside these components, so no key can leak English.
|
|
12
|
+
*/
|
|
13
|
+
const clientRuntimeKeys = [
|
|
14
|
+
keys.formSubmit,
|
|
15
|
+
keys.formNext,
|
|
16
|
+
keys.formBack,
|
|
17
|
+
keys.formClose,
|
|
18
|
+
keys.formSuccess,
|
|
19
|
+
keys.formSubmitFailed,
|
|
20
|
+
keys.formStepStatus,
|
|
21
|
+
keys.formStepInvalid,
|
|
22
|
+
keys.flowStepFallbackTitle,
|
|
23
|
+
keys.repeaterAddRow,
|
|
24
|
+
keys.repeaterRemoveRow,
|
|
25
|
+
keys.repeaterRow,
|
|
26
|
+
keys.fileUploading,
|
|
27
|
+
keys.fileUploaded,
|
|
28
|
+
keys.fileRemove,
|
|
29
|
+
keys.fileTooLarge,
|
|
30
|
+
keys.fileUploadFailed,
|
|
31
|
+
keys.fileUploadMisconfigured,
|
|
32
|
+
keys.fileHintAccepted,
|
|
33
|
+
keys.fileHintMaxSize,
|
|
34
|
+
keys.pollChangeVote,
|
|
35
|
+
keys.pollClosed,
|
|
36
|
+
keys.pollFinalResult,
|
|
37
|
+
keys.pollResultsAfterClose,
|
|
38
|
+
keys.pollResultsError,
|
|
39
|
+
keys.resultsNoResponses,
|
|
40
|
+
keys.resultsResponses,
|
|
41
|
+
keys.resultsTruncated,
|
|
42
|
+
keys.resultsWinner,
|
|
43
|
+
keys.resultsYourVote
|
|
44
|
+
];
|
|
45
|
+
//#endregion
|
|
46
|
+
export { clientRuntimeKeys };
|
|
47
|
+
|
|
48
|
+
//# sourceMappingURL=clientRuntimeKeys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clientRuntimeKeys.js","names":[],"sources":["../../src/translations/clientRuntimeKeys.ts"],"sourcesContent":["import type { TranslationKey } from './keys'\nimport { keys } from './keys'\n\n/**\n * The typed keys the visitor-facing runtime (`<Form>`, `<Poll>`, `<FormResults>`, and the field\n * renderers) resolves through `RendererTranslate`. A host bridging its own i18n can assert its mirror\n * covers these in a unit test, the non-drifting form of a hand-written `dist/` diff. Kept in exact\n * lockstep with `src/react/**` by `clientRuntimeKeys.test.ts`.\n *\n * For a complete, drift-proof fallback prefer `makeTranslate(locale)` (or\n * `makeTranslate(bundles[locale] ?? en)`): a shipped bundle covers every key, including the\n * client-side validation messages resolved outside these components, so no key can leak English.\n */\nexport const clientRuntimeKeys: readonly TranslationKey[] = [\n\tkeys.formSubmit,\n\tkeys.formNext,\n\tkeys.formBack,\n\tkeys.formClose,\n\tkeys.formSuccess,\n\tkeys.formSubmitFailed,\n\tkeys.formStepStatus,\n\tkeys.formStepInvalid,\n\tkeys.flowStepFallbackTitle,\n\tkeys.repeaterAddRow,\n\tkeys.repeaterRemoveRow,\n\tkeys.repeaterRow,\n\tkeys.fileUploading,\n\tkeys.fileUploaded,\n\tkeys.fileRemove,\n\tkeys.fileTooLarge,\n\tkeys.fileUploadFailed,\n\tkeys.fileUploadMisconfigured,\n\tkeys.fileHintAccepted,\n\tkeys.fileHintMaxSize,\n\tkeys.pollChangeVote,\n\tkeys.pollClosed,\n\tkeys.pollFinalResult,\n\tkeys.pollResultsAfterClose,\n\tkeys.pollResultsError,\n\tkeys.resultsNoResponses,\n\tkeys.resultsResponses,\n\tkeys.resultsTruncated,\n\tkeys.resultsWinner,\n\tkeys.resultsYourVote,\n]\n"],"mappings":";;;;;;;;;;;;AAaA,MAAa,oBAA+C;CAC3D,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;AACN"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { TranslationKey } from "./keys.js";
|
|
2
|
+
|
|
3
|
+
//#region src/translations/de.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* German 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 de: Record<TranslationKey, string>;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { de };
|
|
12
|
+
//# sourceMappingURL=de.d.ts.map
|