@10x-media/form-builder 0.1.0-beta.0 → 0.1.0-beta.10
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 +345 -0
- package/README.md +45 -1402
- 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 +22 -0
- package/dist/actions/buildActionBlocks.js.map +1 -0
- package/dist/actions/builtin/confirmation.js +52 -0
- package/dist/actions/builtin/confirmation.js.map +1 -0
- package/dist/actions/builtin/emailAction.d.ts +17 -0
- package/dist/actions/builtin/emailAction.js +83 -0
- package/dist/actions/builtin/emailAction.js.map +1 -0
- package/dist/actions/builtin/emailTeam.js +22 -0
- package/dist/actions/builtin/emailTeam.js.map +1 -0
- package/dist/actions/builtin/index.d.ts +22 -0
- package/dist/actions/builtin/index.js +27 -0
- package/dist/actions/builtin/index.js.map +1 -0
- package/dist/actions/builtin/signedWebhook.js +53 -0
- package/dist/actions/builtin/signedWebhook.js.map +1 -0
- package/dist/actions/defineAction.d.ts +37 -0
- package/dist/actions/defineAction.js +6 -0
- package/dist/actions/defineAction.js.map +1 -0
- package/dist/actions/dispatch.js +49 -0
- package/dist/actions/dispatch.js.map +1 -0
- package/dist/actions/emailRecipients.d.ts +12 -0
- package/dist/actions/emailRecipients.js +116 -0
- package/dist/actions/emailRecipients.js.map +1 -0
- package/dist/actions/fromAddresses.d.ts +21 -0
- package/dist/actions/fromAddresses.js +74 -0
- package/dist/actions/fromAddresses.js.map +1 -0
- package/dist/actions/registry.d.ts +17 -0
- package/dist/actions/registry.js +12 -0
- package/dist/actions/registry.js.map +1 -0
- package/dist/actions/runActions.d.ts +9 -0
- package/dist/actions/runActions.js +43 -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 +87 -0
- package/dist/actions/task.js.map +1 -0
- package/dist/aggregation/aggregateResponses.d.ts +40 -0
- package/dist/aggregation/aggregateResponses.js +80 -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 +61 -0
- package/dist/aggregation/resolveResultsRequest.js +113 -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 +28 -0
- package/dist/calc/computeCalcFields.js.map +1 -0
- package/dist/calc/evaluate.d.ts +8 -0
- package/dist/calc/evaluate.js +58 -0
- package/dist/calc/evaluate.js.map +1 -0
- package/dist/calc/normalizeCalc.d.ts +8 -0
- package/dist/calc/normalizeCalc.js +87 -0
- package/dist/calc/normalizeCalc.js.map +1 -0
- package/dist/calc/types.d.ts +34 -0
- package/dist/calc/types.js +22 -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/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 +122 -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/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 +46 -0
- package/dist/client/EndpointOptionsSelect.js +106 -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 +15 -0
- package/dist/client/FlowBuilder.js +457 -0
- package/dist/client/FlowBuilder.js.map +1 -0
- package/dist/client/FormConditionField.d.ts +21 -0
- package/dist/client/FormConditionField.js +30 -0
- package/dist/client/FormConditionField.js.map +1 -0
- package/dist/client/RecipientsSelect.d.ts +31 -0
- package/dist/client/RecipientsSelect.js +174 -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 +275 -0
- package/dist/client/endpointOptions.js +29 -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 +57 -0
- package/dist/client/synthesizeClientField.js.map +1 -0
- 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 +204 -0
- package/dist/collections/formSubmissions.js.map +1 -0
- package/dist/collections/forms.js +482 -0
- package/dist/collections/forms.js.map +1 -0
- package/dist/collections/formsEndpoints.js +101 -0
- package/dist/collections/formsEndpoints.js.map +1 -0
- package/dist/collections/redirectFields.d.ts +29 -0
- package/dist/conditions/conditionType.js +21 -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 +11 -0
- package/dist/{fieldTypes-CzhhJXjg.js → conditions/fieldTypes.js} +6 -3
- package/dist/conditions/fieldTypes.js.map +1 -0
- package/dist/conditions/normalizeConditions.js +61 -0
- package/dist/conditions/normalizeConditions.js.map +1 -0
- package/dist/conditions/types.d.ts +8 -0
- 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 +55 -0
- package/dist/consent/captureConsent.js +73 -0
- package/dist/consent/captureConsent.js.map +1 -0
- package/dist/consent/consentSourcesField.d.ts +66 -0
- package/dist/consent/consentSourcesField.js +90 -0
- package/dist/consent/consentSourcesField.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 +44 -0
- package/dist/consent/resolveConsentStatements.js.map +1 -0
- package/dist/consent/resolvePublishedVersionRef.d.ts +23 -0
- package/dist/consent/resolvePublishedVersionRef.js +30 -0
- package/dist/consent/resolvePublishedVersionRef.js.map +1 -0
- package/dist/consent/types.d.ts +61 -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/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 +15 -21
- package/dist/exports/client.js +15 -319
- package/dist/exports/i18n.d.ts +6 -138
- package/dist/exports/i18n.js +6 -3
- package/dist/exports/react.d.ts +63 -550
- package/dist/exports/react.js +55 -1563
- package/dist/exports/rsc.d.ts +9 -16
- package/dist/exports/rsc.js +9 -55
- package/dist/exports/types.d.ts +36 -5
- package/dist/fields/buildFieldBlocks.js +80 -0
- package/dist/fields/buildFieldBlocks.js.map +1 -0
- package/dist/fields/builtin/calculation.js +144 -0
- package/dist/fields/builtin/calculation.js.map +1 -0
- package/dist/fields/builtin/checkbox.js +21 -0
- package/dist/fields/builtin/checkbox.js.map +1 -0
- package/dist/fields/builtin/consent.js +47 -0
- package/dist/fields/builtin/consent.js.map +1 -0
- 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 +18 -0
- package/dist/fields/builtin/email.js.map +1 -0
- package/dist/fields/builtin/file.d.ts +15 -0
- package/dist/fields/builtin/file.js +127 -0
- package/dist/fields/builtin/file.js.map +1 -0
- package/dist/fields/builtin/index.d.ts +26 -0
- package/dist/fields/builtin/index.js +49 -0
- package/dist/fields/builtin/index.js.map +1 -0
- package/dist/fields/builtin/message.js +30 -0
- package/dist/fields/builtin/message.js.map +1 -0
- package/dist/fields/builtin/number.js +17 -0
- package/dist/fields/builtin/number.js.map +1 -0
- package/dist/fields/builtin/repeater.js +49 -0
- package/dist/fields/builtin/repeater.js.map +1 -0
- package/dist/fields/builtin/select.js +49 -0
- package/dist/fields/builtin/select.js.map +1 -0
- 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 +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/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/defineFormField.d.ts +13 -0
- package/dist/fields/defineFormField.js +12 -0
- package/dist/fields/defineFormField.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 +12 -0
- package/dist/fields/registry.js +39 -0
- package/dist/fields/registry.js.map +1 -0
- package/dist/fields/sharedConfig.js +151 -0
- package/dist/fields/sharedConfig.js.map +1 -0
- package/dist/fields/types.d.ts +152 -0
- package/dist/flow/engine.d.ts +19 -0
- package/dist/flow/engine.js +29 -0
- package/dist/flow/engine.js.map +1 -0
- package/dist/flow/normalizeFlow.js +54 -0
- package/dist/flow/normalizeFlow.js.map +1 -0
- package/dist/flow/stepLabel.js +15 -0
- package/dist/flow/stepLabel.js.map +1 -0
- package/dist/flow/types.d.ts +32 -0
- package/dist/flow/types.js +11 -0
- package/dist/flow/types.js.map +1 -0
- package/dist/form/pollState.d.ts +22 -0
- package/dist/form/pollState.js +17 -0
- package/dist/form/pollState.js.map +1 -0
- package/dist/form/toFormDocument.d.ts +102 -0
- package/dist/form/toFormDocument.js +87 -0
- package/dist/form/toFormDocument.js.map +1 -0
- package/dist/form/types.d.ts +65 -0
- package/dist/index.d.ts +88 -4
- package/dist/index.js +111 -1898
- package/dist/index.js.map +1 -1
- package/dist/options.d.ts +229 -0
- package/dist/plugin/access.js +12 -0
- package/dist/plugin/access.js.map +1 -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/collectionOverrides.d.ts +22 -0
- package/dist/plugin/customState.js +26 -0
- package/dist/plugin/customState.js.map +1 -0
- package/dist/plugin/registerCollections.js +60 -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/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 +52 -0
- package/dist/poll/closeJob.js +119 -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 +105 -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 +34 -0
- package/dist/poll/resolvePollOutcome.js +76 -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/prefill/valuesFromSearchParams.d.ts +18 -0
- package/dist/prefill/valuesFromSearchParams.js +41 -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/types.d.ts +19 -0
- package/dist/react/Form.d.ts +128 -0
- package/dist/react/Form.js +619 -0
- package/dist/react/Form.js.map +1 -0
- package/dist/react/FormContext.d.ts +59 -0
- package/dist/react/FormContext.js +14 -0
- package/dist/react/FormContext.js.map +1 -0
- 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 +22 -0
- package/dist/react/FormLayout.js +15 -0
- package/dist/react/FormLayout.js.map +1 -0
- package/dist/react/FormResults.d.ts +28 -0
- package/dist/react/FormResults.js +93 -0
- package/dist/react/FormResults.js.map +1 -0
- 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/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 +43 -0
- package/dist/react/Poll.js +135 -0
- package/dist/react/Poll.js.map +1 -0
- package/dist/react/captcha/HcaptchaCaptcha.d.ts +28 -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 +41 -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 +28 -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 +45 -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/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 +31 -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 +53 -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 +28 -0
- package/dist/react/primitives/Checkbox.js +21 -0
- package/dist/react/primitives/Checkbox.js.map +1 -0
- package/dist/react/primitives/FieldShell.d.ts +29 -0
- package/dist/react/primitives/FieldShell.js +44 -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 +27 -0
- package/dist/react/renderers/calculation.js.map +1 -0
- package/dist/react/renderers/checkbox.js +32 -0
- package/dist/react/renderers/checkbox.js.map +1 -0
- package/dist/react/renderers/consent.js +97 -0
- package/dist/react/renderers/consent.js.map +1 -0
- package/dist/react/renderers/date.js +33 -0
- package/dist/react/renderers/date.js.map +1 -0
- package/dist/react/renderers/email.js +34 -0
- package/dist/react/renderers/email.js.map +1 -0
- package/dist/react/renderers/file.js +107 -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 +35 -0
- package/dist/react/renderers/index.js.map +1 -0
- package/dist/react/renderers/message.js +41 -0
- package/dist/react/renderers/message.js.map +1 -0
- package/dist/react/renderers/number.js +37 -0
- package/dist/react/renderers/number.js.map +1 -0
- package/dist/react/renderers/region.js +43 -0
- package/dist/react/renderers/region.js.map +1 -0
- package/dist/react/renderers/repeater.js +131 -0
- package/dist/react/renderers/repeater.js.map +1 -0
- package/dist/react/renderers/select.js +35 -0
- package/dist/react/renderers/select.js.map +1 -0
- package/dist/react/renderers/text.js +34 -0
- package/dist/react/renderers/text.js.map +1 -0
- package/dist/react/renderers/textarea.js +33 -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 +52 -0
- package/dist/react/state.js +125 -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/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 +13 -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 +27 -0
- package/dist/react/validateField.js.map +1 -0
- package/dist/recall/interpolate.d.ts +11 -0
- package/dist/recall/interpolate.js +17 -0
- package/dist/recall/interpolate.js.map +1 -0
- package/dist/recall/resolver.d.ts +22 -0
- package/dist/recall/resolver.js +48 -0
- package/dist/recall/resolver.js.map +1 -0
- package/dist/spam/captcha.d.ts +13 -0
- package/dist/spam/captcha.js +12 -0
- package/dist/spam/captcha.js.map +1 -0
- package/dist/spam/clientIp.js +9 -0
- package/dist/spam/clientIp.js.map +1 -0
- package/dist/spam/constants.d.ts +12 -0
- package/dist/spam/constants.js +21 -0
- package/dist/spam/constants.js.map +1 -0
- package/dist/spam/identify.d.ts +12 -0
- package/dist/spam/identify.js +17 -0
- package/dist/spam/identify.js.map +1 -0
- 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/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 +43 -0
- package/dist/spam/resolveSpam.js.map +1 -0
- package/dist/spam/spamGuard.js +81 -0
- package/dist/spam/spamGuard.js.map +1 -0
- package/dist/spam/types.d.ts +88 -0
- package/dist/spam/uploadHooks.js +33 -0
- package/dist/spam/uploadHooks.js.map +1 -0
- package/dist/submissions/SubmissionAnswers.d.ts +14 -0
- package/dist/submissions/SubmissionAnswers.js +137 -0
- package/dist/submissions/SubmissionAnswers.js.map +1 -0
- package/dist/submissions/SubmissionAnswersClient.js +178 -0
- package/dist/submissions/SubmissionAnswersClient.js.map +1 -0
- 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/runSubmission.d.ts +10 -0
- package/dist/submissions/runSubmission.js +306 -0
- package/dist/submissions/runSubmission.js.map +1 -0
- package/dist/submissions/types.d.ts +41 -0
- package/dist/submissions/validateSubmission.js +110 -0
- package/dist/submissions/validateSubmission.js.map +1 -0
- package/dist/submissions/votedCookie.d.ts +13 -0
- package/dist/submissions/votedCookie.js +27 -0
- package/dist/submissions/votedCookie.js.map +1 -0
- package/dist/translations/clientRuntimeKeys.d.ts +17 -0
- package/dist/translations/clientRuntimeKeys.js +46 -0
- package/dist/translations/clientRuntimeKeys.js.map +1 -0
- package/dist/translations/de.d.ts +12 -0
- package/dist/translations/de.js +309 -0
- package/dist/translations/de.js.map +1 -0
- package/dist/translations/en.d.ts +12 -0
- package/dist/translations/en.js +309 -0
- package/dist/translations/en.js.map +1 -0
- package/dist/translations/index.d.ts +23 -0
- package/dist/translations/index.js +37 -0
- package/dist/translations/index.js.map +1 -0
- package/dist/translations/keys.d.ts +308 -0
- package/dist/translations/keys.js +308 -0
- package/dist/translations/keys.js.map +1 -0
- package/dist/translations/makeTranslate.d.ts +15 -0
- package/dist/translations/makeTranslate.js +20 -0
- package/dist/translations/makeTranslate.js.map +1 -0
- package/dist/translations/server.js +32 -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 +34 -0
- package/dist/uploads/captureFileRef.js +43 -0
- package/dist/uploads/captureFileRef.js.map +1 -0
- 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.d.ts +26 -0
- package/dist/uploads/resolveFileRef.js +45 -0
- package/dist/uploads/resolveFileRef.js.map +1 -0
- package/dist/uploads/types.d.ts +19 -0
- package/dist/validation/buildRuleBlocks.js +47 -0
- package/dist/validation/buildRuleBlocks.js.map +1 -0
- package/dist/validation/builtin/email.js +20 -0
- package/dist/validation/builtin/email.js.map +1 -0
- package/dist/validation/builtin/index.d.ts +14 -0
- package/dist/validation/builtin/index.js +38 -0
- package/dist/validation/builtin/index.js.map +1 -0
- package/dist/validation/builtin/matchesField.js +16 -0
- package/dist/validation/builtin/matchesField.js.map +1 -0
- package/dist/validation/builtin/max.js +22 -0
- package/dist/validation/builtin/max.js.map +1 -0
- package/dist/validation/builtin/maxDate.js +24 -0
- package/dist/validation/builtin/maxDate.js.map +1 -0
- package/dist/validation/builtin/maxLength.js +27 -0
- package/dist/validation/builtin/maxLength.js.map +1 -0
- package/dist/validation/builtin/min.js +22 -0
- package/dist/validation/builtin/min.js.map +1 -0
- package/dist/validation/builtin/minDate.js +24 -0
- package/dist/validation/builtin/minDate.js.map +1 -0
- package/dist/validation/builtin/minLength.js +27 -0
- package/dist/validation/builtin/minLength.js.map +1 -0
- package/dist/validation/builtin/notAlreadySubmitted.js +34 -0
- package/dist/validation/builtin/notAlreadySubmitted.js.map +1 -0
- package/dist/validation/builtin/oneOf.js +35 -0
- package/dist/validation/builtin/oneOf.js.map +1 -0
- package/dist/validation/builtin/pattern.js +50 -0
- package/dist/validation/builtin/pattern.js.map +1 -0
- package/dist/validation/builtin/url.js +23 -0
- package/dist/validation/builtin/url.js.map +1 -0
- 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/defineValidationRule.d.ts +12 -0
- package/dist/validation/defineValidationRule.js +11 -0
- package/dist/validation/defineValidationRule.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/message.js +14 -0
- package/dist/validation/message.js.map +1 -0
- package/dist/validation/registry.d.ts +11 -0
- package/dist/validation/registry.js +13 -0
- package/dist/validation/registry.js.map +1 -0
- package/dist/validation/runValidation.js +90 -0
- package/dist/validation/runValidation.js.map +1 -0
- package/dist/validation/types.d.ts +70 -0
- package/dist/validation/validateUrl.js +22 -0
- package/dist/validation/validateUrl.js.map +1 -0
- package/package.json +12 -7
- package/styles/form-builder.css +21 -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 +0 -132
- 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 +0 -152
- package/dist/translations-edMqq_2e.js.map +0 -1
- package/dist/types-DsJ_6kGJ.d.ts +0 -23
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"captureConsent.js","names":[],"sources":["../../src/consent/captureConsent.ts"],"sourcesContent":["import { createHash } from 'node:crypto'\nimport type { Payload, PayloadRequest } from 'payload'\nimport { hasDraftsEnabled } from 'payload/shared'\nimport { textOfBody } from '../actions/body/textOfBody'\nimport type { FormFieldInstance } from '../submissions/types'\nimport { resolvePublishedVersionRef } from './resolvePublishedVersionRef'\nimport type { ConsentSourceEntry, ConsentSourcePage } from './types'\n\n/** What a submission snapshots of the agreed wording. `'hash'` and `'text'` combine as `'both'`. */\nexport type ConsentSnapshotMode = 'hash' | 'text' | 'both' | false\n\nexport type ConsentProof = {\n\tagreed: boolean\n\t/** The source `id` the field referenced; empty when the author never picked one. */\n\tsource: string\n\tpage?: ConsentSourcePage\n\tversionRef?: string\n\t/** The source label at submit time, so an audit names the statement even after a rename or delete. */\n\tname?: string\n\t/** sha256 of the statement plain text agreed to: tamper-evident and PII-free. */\n\tstatementHash?: string\n\t/** Plain-text snapshot of the statement agreed to, for a human-readable audit. */\n\tstatementText?: string\n\tat: string\n}\n\n/**\n * The authoritative consent proof, built at submit time from the server's own view of the source\n * (the field carries an id, never a statement, so there is nothing here the client could forge).\n *\n * Proof is id-based on purpose: it records which document was agreed to, so renaming, re-slugging,\n * or re-routing the policy leaves every past proof intact and resolvable. `snapshot` additionally\n * captures the agreed wording (a `statementHash`, the plain `statementText`, or both) plus the source\n * `name`, so an audit shows exactly what was agreed to independent of later edits; `false` keeps the\n * lean id-only proof. The snapshot is captured in every branch, including a refusal and a page-less\n * source.\n *\n * Time-of-check/time-of-use: a visitor reads the wording resolved when the form loaded, but the\n * snapshot here is re-resolved from the source at submit. If the source text changed in that window,\n * the proof records the submit-time wording, not the exact bytes rendered earlier. This is\n * deliberate, the server's live view is authoritative and the window is one visitor session; a form\n * that must freeze the exact wording agreed to should version the source (drafts give a `versionRef`\n * pinning the published version, below).\n *\n * `versionRef` is recorded only when the page's collection has drafts enabled, and then it is the\n * published version document's own id. Versions without drafts get no `versionRef`, because there\n * is no published/draft distinction to pin to: `_status` only exists under drafts, so a\n * published-version lookup there matches nothing, and recording that as a version reference would\n * be inventing one. Absent means absent, in both cases.\n *\n * `now` is injected by the caller (`new Date().toISOString()`) for testability.\n */\nexport const captureConsent = async (args: {\n\tfield: FormFieldInstance\n\tagreed: boolean\n\t/** The host's resolved sources for this request (see `resolveConsentEntries`). */\n\tentries: ConsentSourceEntry[]\n\tpayload: Payload\n\treq?: PayloadRequest\n\tnow: string\n\t/** What to snapshot of the agreed wording (plugin option `consent.snapshot`); defaults to `'both'`. */\n\tsnapshot?: ConsentSnapshotMode\n}): Promise<ConsentProof> => {\n\tconst source = typeof args.field.source === 'string' ? args.field.source : ''\n\tconst entry = source ? args.entries.find((candidate) => candidate.id === source) : undefined\n\tconst snapshot = args.snapshot ?? 'both'\n\n\t// Capture the agreed wording (and the source label) onto every proof branch. Kept out of the two\n\t// returns so a refusal and a page-less source are snapshotted the same as the happy path.\n\tconst withSnapshot = (proof: ConsentProof): ConsentProof => {\n\t\tif (!entry || snapshot === false) {\n\t\t\treturn proof\n\t\t}\n\t\tif (typeof entry.name === 'string' && entry.name.trim().length > 0) {\n\t\t\tproof.name = entry.name.trim()\n\t\t}\n\t\tconst text = textOfBody(entry.statement)\n\t\tif (text.length > 0) {\n\t\t\tif (snapshot === 'hash' || snapshot === 'both') {\n\t\t\t\tproof.statementHash = createHash('sha256').update(text).digest('hex')\n\t\t\t}\n\t\t\tif (snapshot === 'text' || snapshot === 'both') {\n\t\t\t\tproof.statementText = text\n\t\t\t}\n\t\t}\n\t\treturn proof\n\t}\n\n\tconst page = entry?.page\n\tif (!page) {\n\t\treturn withSnapshot({ agreed: args.agreed, source, at: args.now })\n\t}\n\t// `page.relationTo` is a runtime string; cast the key so the lookup type-checks against a host's\n\t// narrowed collection map (a consumer's generated `CollectionSlug`) as well as the plugin's own\n\t// broad one. The value is still guarded below, since an unregistered slug resolves to undefined.\n\tconst collection = args.payload.collections[page.relationTo as keyof Payload['collections']]\n\tconst versionRef =\n\t\tcollection && hasDraftsEnabled(collection.config)\n\t\t\t? await resolvePublishedVersionRef({\n\t\t\t\t\tpayload: args.payload,\n\t\t\t\t\tcollection: page.relationTo,\n\t\t\t\t\tid: page.id,\n\t\t\t\t\treq: args.req,\n\t\t\t\t})\n\t\t\t: null\n\treturn withSnapshot({\n\t\tagreed: args.agreed,\n\t\tsource,\n\t\tpage: { relationTo: page.relationTo, id: page.id },\n\t\t...(versionRef ? { versionRef } : {}),\n\t\tat: args.now,\n\t})\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDA,MAAa,iBAAiB,OAAO,SAUR;CAC5B,MAAM,SAAS,OAAO,KAAK,MAAM,WAAW,WAAW,KAAK,MAAM,SAAS;CAC3E,MAAM,QAAQ,SAAS,KAAK,QAAQ,MAAM,cAAc,UAAU,OAAO,MAAM,IAAI,KAAA;CACnF,MAAM,WAAW,KAAK,YAAY;CAIlC,MAAM,gBAAgB,UAAsC;EAC3D,IAAI,CAAC,SAAS,aAAa,OAC1B,OAAO;EAER,IAAI,OAAO,MAAM,SAAS,YAAY,MAAM,KAAK,KAAK,EAAE,SAAS,GAChE,MAAM,OAAO,MAAM,KAAK,KAAK;EAE9B,MAAM,OAAO,WAAW,MAAM,SAAS;EACvC,IAAI,KAAK,SAAS,GAAG;GACpB,IAAI,aAAa,UAAU,aAAa,QACvC,MAAM,gBAAgB,WAAW,QAAQ,EAAE,OAAO,IAAI,EAAE,OAAO,KAAK;GAErE,IAAI,aAAa,UAAU,aAAa,QACvC,MAAM,gBAAgB;EAExB;EACA,OAAO;CACR;CAEA,MAAM,OAAO,OAAO;CACpB,IAAI,CAAC,MACJ,OAAO,aAAa;EAAE,QAAQ,KAAK;EAAQ;EAAQ,IAAI,KAAK;CAAI,CAAC;CAKlE,MAAM,aAAa,KAAK,QAAQ,YAAY,KAAK;CACjD,MAAM,aACL,cAAc,iBAAiB,WAAW,MAAM,IAC7C,MAAM,2BAA2B;EACjC,SAAS,KAAK;EACd,YAAY,KAAK;EACjB,IAAI,KAAK;EACT,KAAK,KAAK;CACX,CAAC,IACA;CACJ,OAAO,aAAa;EACnB,QAAQ,KAAK;EACb;EACA,MAAM;GAAE,YAAY,KAAK;GAAY,IAAI,KAAK;EAAG;EACjD,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC;EACnC,IAAI,KAAK;CACV,CAAC;AACF"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { ArrayField, CollectionSlug, RichTextField } from "payload";
|
|
2
|
+
|
|
3
|
+
//#region src/consent/consentSourcesField.d.ts
|
|
4
|
+
type ConsentSourcesFieldOptions = {
|
|
5
|
+
/** Field name, i.e. what the row array is stored under. Defaults to `consentSources`. */name?: string; /** Field label. Defaults to the plugin's translated one. */
|
|
6
|
+
label?: ArrayField['label'];
|
|
7
|
+
/**
|
|
8
|
+
* Collections whose documents can be picked as a source's policy page. Omitted (the default):
|
|
9
|
+
* no page picker at all, so sources are statement-only and their proofs carry no page or
|
|
10
|
+
* version reference. Always stored polymorphically, even for a single slug (see below).
|
|
11
|
+
*/
|
|
12
|
+
relationTo?: CollectionSlug | CollectionSlug[];
|
|
13
|
+
/**
|
|
14
|
+
* Whether the visitor-facing `statement` and `name` carry `localized: true`. Default `true`;
|
|
15
|
+
* Payload strips the flag on hosts without `localization`, so it is safe either way. Mirrors
|
|
16
|
+
* the plugin's `localizeContent` option, which this host-called factory cannot see.
|
|
17
|
+
*/
|
|
18
|
+
localized?: boolean; /** Overrides the project's default richText editor for the `statement`, as `richText.editor` does plugin-side. */
|
|
19
|
+
editor?: RichTextField['editor'];
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* The consent sources array, for the host to place on any collection or global they own: a
|
|
23
|
+
* settings global, a tenants collection, a legal-pages parent, wherever the sources belong. The
|
|
24
|
+
* plugin never registers it and never guesses where it lives; a matching `consent.sources` resolver
|
|
25
|
+
* reads it back (see {@link ConsentSourcesResolver}), which is also where multi-tenant scoping goes:
|
|
26
|
+
* place this on the tenant-scoped document and have the resolver return only the sources of the
|
|
27
|
+
* tenant it derives from `req`.
|
|
28
|
+
*
|
|
29
|
+
* A row is a `name` (shown when picking the source on a form, and used as the policy link text
|
|
30
|
+
* beside the statement), the `statement` the visitor agrees to, and optionally the `page` that
|
|
31
|
+
* statement belongs to. The stable reference a consent field stores, and the only part that must
|
|
32
|
+
* outlive edits, is the row's own auto-assigned `id`: it survives a `name` edit or reordering,
|
|
33
|
+
* unlike a hand-authored key would. Authors fill in no version, no URL, and no document id by
|
|
34
|
+
* hand: the version is detected and recorded at submit time, and the page is a picker.
|
|
35
|
+
*
|
|
36
|
+
* `page` is always polymorphic, even when `relationTo` names a single collection, because a
|
|
37
|
+
* monomorphic relationship stores a bare id: the proof needs the collection alongside it to stay
|
|
38
|
+
* resolvable, and a host adding a second collection later would otherwise change the stored shape.
|
|
39
|
+
*
|
|
40
|
+
* ```ts
|
|
41
|
+
* // The host's own collection or global:
|
|
42
|
+
* fields: [consentSourcesField({ relationTo: ['pages', 'legal-notices'] })]
|
|
43
|
+
*
|
|
44
|
+
* // The plugin, reading it back:
|
|
45
|
+
* formBuilder({
|
|
46
|
+
* consent: {
|
|
47
|
+
* sources: async ({ req }) => {
|
|
48
|
+
* const settings = await req.payload.findGlobal({ slug: 'settings', depth: 0, locale: req.locale, req })
|
|
49
|
+
* return (settings.consentSources ?? []).map((row) => ({ ... }))
|
|
50
|
+
* },
|
|
51
|
+
* },
|
|
52
|
+
* })
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* The resolver receives the whole form document, so derive tenant scoping from a field on it rather
|
|
56
|
+
* than reading the form back: reading the `forms` collection from the resolver re-enters this form's
|
|
57
|
+
* afterRead hook (the plugin guards against the resulting recursion, but the read is still wasted).
|
|
58
|
+
*
|
|
59
|
+
* A resolver reading its settings document must not thread the save's `req` into a `locale: 'all'`
|
|
60
|
+
* read from within a form's save validation: that flips `req.locale` to `all` and corrupts the
|
|
61
|
+
* localized write of the document being saved. It reads already-committed data, so no `req` is needed.
|
|
62
|
+
*/
|
|
63
|
+
declare const consentSourcesField: (options?: ConsentSourcesFieldOptions) => ArrayField;
|
|
64
|
+
//#endregion
|
|
65
|
+
export { ConsentSourcesFieldOptions, consentSourcesField };
|
|
66
|
+
//# sourceMappingURL=consentSourcesField.d.ts.map
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { keys } from "../translations/keys.js";
|
|
2
|
+
import { labelForKey } from "../translations/server.js";
|
|
3
|
+
import { localizedIf } from "../fields/localizedIf.js";
|
|
4
|
+
//#region src/consent/consentSourcesField.ts
|
|
5
|
+
/**
|
|
6
|
+
* The consent sources array, for the host to place on any collection or global they own: a
|
|
7
|
+
* settings global, a tenants collection, a legal-pages parent, wherever the sources belong. The
|
|
8
|
+
* plugin never registers it and never guesses where it lives; a matching `consent.sources` resolver
|
|
9
|
+
* reads it back (see {@link ConsentSourcesResolver}), which is also where multi-tenant scoping goes:
|
|
10
|
+
* place this on the tenant-scoped document and have the resolver return only the sources of the
|
|
11
|
+
* tenant it derives from `req`.
|
|
12
|
+
*
|
|
13
|
+
* A row is a `name` (shown when picking the source on a form, and used as the policy link text
|
|
14
|
+
* beside the statement), the `statement` the visitor agrees to, and optionally the `page` that
|
|
15
|
+
* statement belongs to. The stable reference a consent field stores, and the only part that must
|
|
16
|
+
* outlive edits, is the row's own auto-assigned `id`: it survives a `name` edit or reordering,
|
|
17
|
+
* unlike a hand-authored key would. Authors fill in no version, no URL, and no document id by
|
|
18
|
+
* hand: the version is detected and recorded at submit time, and the page is a picker.
|
|
19
|
+
*
|
|
20
|
+
* `page` is always polymorphic, even when `relationTo` names a single collection, because a
|
|
21
|
+
* monomorphic relationship stores a bare id: the proof needs the collection alongside it to stay
|
|
22
|
+
* resolvable, and a host adding a second collection later would otherwise change the stored shape.
|
|
23
|
+
*
|
|
24
|
+
* ```ts
|
|
25
|
+
* // The host's own collection or global:
|
|
26
|
+
* fields: [consentSourcesField({ relationTo: ['pages', 'legal-notices'] })]
|
|
27
|
+
*
|
|
28
|
+
* // The plugin, reading it back:
|
|
29
|
+
* formBuilder({
|
|
30
|
+
* consent: {
|
|
31
|
+
* sources: async ({ req }) => {
|
|
32
|
+
* const settings = await req.payload.findGlobal({ slug: 'settings', depth: 0, locale: req.locale, req })
|
|
33
|
+
* return (settings.consentSources ?? []).map((row) => ({ ... }))
|
|
34
|
+
* },
|
|
35
|
+
* },
|
|
36
|
+
* })
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* The resolver receives the whole form document, so derive tenant scoping from a field on it rather
|
|
40
|
+
* than reading the form back: reading the `forms` collection from the resolver re-enters this form's
|
|
41
|
+
* afterRead hook (the plugin guards against the resulting recursion, but the read is still wasted).
|
|
42
|
+
*
|
|
43
|
+
* A resolver reading its settings document must not thread the save's `req` into a `locale: 'all'`
|
|
44
|
+
* read from within a form's save validation: that flips `req.locale` to `all` and corrupts the
|
|
45
|
+
* localized write of the document being saved. It reads already-committed data, so no `req` is needed.
|
|
46
|
+
*/
|
|
47
|
+
const consentSourcesField = (options = {}) => {
|
|
48
|
+
const localize = options.localized !== false;
|
|
49
|
+
const relationTo = options.relationTo && (!Array.isArray(options.relationTo) || options.relationTo.length > 0) ? options.relationTo : void 0;
|
|
50
|
+
const pageField = relationTo ? [{
|
|
51
|
+
name: "page",
|
|
52
|
+
type: "relationship",
|
|
53
|
+
relationTo: Array.isArray(relationTo) ? relationTo : [relationTo],
|
|
54
|
+
label: labelForKey(keys.consentSourcePage),
|
|
55
|
+
admin: { description: labelForKey(keys.consentSourcePageDescription) }
|
|
56
|
+
}] : [];
|
|
57
|
+
return {
|
|
58
|
+
name: options.name ?? "consentSources",
|
|
59
|
+
type: "array",
|
|
60
|
+
label: options.label ?? labelForKey(keys.consentSourcesField),
|
|
61
|
+
labels: {
|
|
62
|
+
singular: labelForKey(keys.consentSourceSingular),
|
|
63
|
+
plural: labelForKey(keys.consentSourcePlural)
|
|
64
|
+
},
|
|
65
|
+
admin: {
|
|
66
|
+
description: labelForKey(keys.consentSourcesFieldDescription),
|
|
67
|
+
components: { RowLabel: "@10x-media/form-builder/client#ConsentSourceRowLabel" }
|
|
68
|
+
},
|
|
69
|
+
fields: [
|
|
70
|
+
{
|
|
71
|
+
name: "name",
|
|
72
|
+
type: "text",
|
|
73
|
+
label: labelForKey(keys.consentSourceLabel),
|
|
74
|
+
...localizedIf(localize)
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: "statement",
|
|
78
|
+
type: "richText",
|
|
79
|
+
label: labelForKey(keys.consentSourceStatement),
|
|
80
|
+
...options.editor ? { editor: options.editor } : {},
|
|
81
|
+
...localizedIf(localize)
|
|
82
|
+
},
|
|
83
|
+
...pageField
|
|
84
|
+
]
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
//#endregion
|
|
88
|
+
export { consentSourcesField };
|
|
89
|
+
|
|
90
|
+
//# sourceMappingURL=consentSourcesField.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consentSourcesField.js","names":[],"sources":["../../src/consent/consentSourcesField.ts"],"sourcesContent":["import type { ArrayField, CollectionSlug, Field, RichTextField } from 'payload'\nimport { localizedIf } from '../fields/localizedIf'\nimport { keys } from '../translations/keys'\nimport { labelForKey } from '../translations/server'\n\nexport type ConsentSourcesFieldOptions = {\n\t/** Field name, i.e. what the row array is stored under. Defaults to `consentSources`. */\n\tname?: string\n\t/** Field label. Defaults to the plugin's translated one. */\n\tlabel?: ArrayField['label']\n\t/**\n\t * Collections whose documents can be picked as a source's policy page. Omitted (the default):\n\t * no page picker at all, so sources are statement-only and their proofs carry no page or\n\t * version reference. Always stored polymorphically, even for a single slug (see below).\n\t */\n\trelationTo?: CollectionSlug | CollectionSlug[]\n\t/**\n\t * Whether the visitor-facing `statement` and `name` carry `localized: true`. Default `true`;\n\t * Payload strips the flag on hosts without `localization`, so it is safe either way. Mirrors\n\t * the plugin's `localizeContent` option, which this host-called factory cannot see.\n\t */\n\tlocalized?: boolean\n\t/** Overrides the project's default richText editor for the `statement`, as `richText.editor` does plugin-side. */\n\teditor?: RichTextField['editor']\n}\n\n/**\n * The consent sources array, for the host to place on any collection or global they own: a\n * settings global, a tenants collection, a legal-pages parent, wherever the sources belong. The\n * plugin never registers it and never guesses where it lives; a matching `consent.sources` resolver\n * reads it back (see {@link ConsentSourcesResolver}), which is also where multi-tenant scoping goes:\n * place this on the tenant-scoped document and have the resolver return only the sources of the\n * tenant it derives from `req`.\n *\n * A row is a `name` (shown when picking the source on a form, and used as the policy link text\n * beside the statement), the `statement` the visitor agrees to, and optionally the `page` that\n * statement belongs to. The stable reference a consent field stores, and the only part that must\n * outlive edits, is the row's own auto-assigned `id`: it survives a `name` edit or reordering,\n * unlike a hand-authored key would. Authors fill in no version, no URL, and no document id by\n * hand: the version is detected and recorded at submit time, and the page is a picker.\n *\n * `page` is always polymorphic, even when `relationTo` names a single collection, because a\n * monomorphic relationship stores a bare id: the proof needs the collection alongside it to stay\n * resolvable, and a host adding a second collection later would otherwise change the stored shape.\n *\n * ```ts\n * // The host's own collection or global:\n * fields: [consentSourcesField({ relationTo: ['pages', 'legal-notices'] })]\n *\n * // The plugin, reading it back:\n * formBuilder({\n * consent: {\n * sources: async ({ req }) => {\n * const settings = await req.payload.findGlobal({ slug: 'settings', depth: 0, locale: req.locale, req })\n * return (settings.consentSources ?? []).map((row) => ({ ... }))\n * },\n * },\n * })\n * ```\n *\n * The resolver receives the whole form document, so derive tenant scoping from a field on it rather\n * than reading the form back: reading the `forms` collection from the resolver re-enters this form's\n * afterRead hook (the plugin guards against the resulting recursion, but the read is still wasted).\n *\n * A resolver reading its settings document must not thread the save's `req` into a `locale: 'all'`\n * read from within a form's save validation: that flips `req.locale` to `all` and corrupts the\n * localized write of the document being saved. It reads already-committed data, so no `req` is needed.\n */\nexport const consentSourcesField = (options: ConsentSourcesFieldOptions = {}): ArrayField => {\n\tconst localize = options.localized !== false\n\t// An empty `relationTo` array is treated as \"no page picker\", not a relationship field pointing\n\t// at nothing (which Payload rejects at boot).\n\tconst relationTo =\n\t\toptions.relationTo && (!Array.isArray(options.relationTo) || options.relationTo.length > 0)\n\t\t\t? options.relationTo\n\t\t\t: undefined\n\tconst pageField: Field[] = relationTo\n\t\t? [\n\t\t\t\t{\n\t\t\t\t\tname: 'page',\n\t\t\t\t\ttype: 'relationship',\n\t\t\t\t\trelationTo: Array.isArray(relationTo) ? relationTo : [relationTo],\n\t\t\t\t\tlabel: labelForKey(keys.consentSourcePage),\n\t\t\t\t\tadmin: { description: labelForKey(keys.consentSourcePageDescription) },\n\t\t\t\t},\n\t\t\t]\n\t\t: []\n\n\treturn {\n\t\tname: options.name ?? 'consentSources',\n\t\ttype: 'array',\n\t\tlabel: options.label ?? labelForKey(keys.consentSourcesField),\n\t\tlabels: {\n\t\t\tsingular: labelForKey(keys.consentSourceSingular),\n\t\t\tplural: labelForKey(keys.consentSourcePlural),\n\t\t},\n\t\tadmin: {\n\t\t\tdescription: labelForKey(keys.consentSourcesFieldDescription),\n\t\t\tcomponents: { RowLabel: '@10x-media/form-builder/client#ConsentSourceRowLabel' },\n\t\t},\n\t\tfields: [\n\t\t\t{\n\t\t\t\tname: 'name',\n\t\t\t\ttype: 'text',\n\t\t\t\tlabel: labelForKey(keys.consentSourceLabel),\n\t\t\t\t...localizedIf(localize),\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: 'statement',\n\t\t\t\ttype: 'richText',\n\t\t\t\tlabel: labelForKey(keys.consentSourceStatement),\n\t\t\t\t...(options.editor ? { editor: options.editor } : {}),\n\t\t\t\t...localizedIf(localize),\n\t\t\t},\n\t\t\t...pageField,\n\t\t],\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoEA,MAAa,uBAAuB,UAAsC,CAAC,MAAkB;CAC5F,MAAM,WAAW,QAAQ,cAAc;CAGvC,MAAM,aACL,QAAQ,eAAe,CAAC,MAAM,QAAQ,QAAQ,UAAU,KAAK,QAAQ,WAAW,SAAS,KACtF,QAAQ,aACR,KAAA;CACJ,MAAM,YAAqB,aACxB,CACA;EACC,MAAM;EACN,MAAM;EACN,YAAY,MAAM,QAAQ,UAAU,IAAI,aAAa,CAAC,UAAU;EAChE,OAAO,YAAY,KAAK,iBAAiB;EACzC,OAAO,EAAE,aAAa,YAAY,KAAK,4BAA4B,EAAE;CACtE,CACD,IACC,CAAC;CAEJ,OAAO;EACN,MAAM,QAAQ,QAAQ;EACtB,MAAM;EACN,OAAO,QAAQ,SAAS,YAAY,KAAK,mBAAmB;EAC5D,QAAQ;GACP,UAAU,YAAY,KAAK,qBAAqB;GAChD,QAAQ,YAAY,KAAK,mBAAmB;EAC7C;EACA,OAAO;GACN,aAAa,YAAY,KAAK,8BAA8B;GAC5D,YAAY,EAAE,UAAU,uDAAuD;EAChF;EACA,QAAQ;GACP;IACC,MAAM;IACN,MAAM;IACN,OAAO,YAAY,KAAK,kBAAkB;IAC1C,GAAG,YAAY,QAAQ;GACxB;GACA;IACC,MAAM;IACN,MAAM;IACN,OAAO,YAAY,KAAK,sBAAsB;IAC9C,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;IACnD,GAAG,YAAY,QAAQ;GACxB;GACA,GAAG;EACJ;CACD;AACD"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ConsentSourceEntry, ConsentSourcesResolver } from "./types.js";
|
|
2
|
+
import { Payload, PayloadRequest } from "payload";
|
|
3
|
+
|
|
4
|
+
//#region src/consent/resolveConsentEntries.d.ts
|
|
5
|
+
type ResolveConsentEntriesArgs = {
|
|
6
|
+
payload: Payload;
|
|
7
|
+
req: PayloadRequest; /** The whole form being resolved; forwarded to the resolver, which casts for non-standard fields (e.g. tenant). */
|
|
8
|
+
form: {
|
|
9
|
+
id: number | string;
|
|
10
|
+
title?: string | null;
|
|
11
|
+
}; /** Resolver override for plugin-internal callers; defaults to the one the plugin stashed on the config. */
|
|
12
|
+
sources?: ConsentSourcesResolver;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* The host's consent sources for this request, or an empty list when no resolver is configured
|
|
16
|
+
* (in which case the `consent` field type is not registered either, so nothing can reference one).
|
|
17
|
+
* Throws whatever the resolver throws: every caller decides how to fail, and none of them fail open.
|
|
18
|
+
* Cached per request and form id, so one submission resolves the host's sources once no matter how
|
|
19
|
+
* many consent fields the form carries.
|
|
20
|
+
*/
|
|
21
|
+
declare const resolveConsentEntries: (args: ResolveConsentEntriesArgs) => Promise<ConsentSourceEntry[]>;
|
|
22
|
+
//#endregion
|
|
23
|
+
export { ResolveConsentEntriesArgs, resolveConsentEntries };
|
|
24
|
+
//# sourceMappingURL=resolveConsentEntries.d.ts.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { customStateOf, stashCustomState } from "../plugin/customState.js";
|
|
2
|
+
//#region src/consent/resolveConsentEntries.ts
|
|
3
|
+
/** Park the host's resolver on the config so root-level helpers can find it via `payload.config`. */
|
|
4
|
+
const stashConsentSources = (custom, sources) => stashCustomState(custom, { consentSources: sources });
|
|
5
|
+
const consentSourcesOf = (payload) => customStateOf(payload).consentSources;
|
|
6
|
+
const CACHE_KEY = "formBuilderConsentSourcesCache";
|
|
7
|
+
const cacheOf = (req) => {
|
|
8
|
+
if (!req.context) return;
|
|
9
|
+
const existing = req.context[CACHE_KEY];
|
|
10
|
+
if (existing instanceof Map) return existing;
|
|
11
|
+
const created = /* @__PURE__ */ new Map();
|
|
12
|
+
req.context[CACHE_KEY] = created;
|
|
13
|
+
return created;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* The host's consent sources for this request, or an empty list when no resolver is configured
|
|
17
|
+
* (in which case the `consent` field type is not registered either, so nothing can reference one).
|
|
18
|
+
* Throws whatever the resolver throws: every caller decides how to fail, and none of them fail open.
|
|
19
|
+
* Cached per request and form id, so one submission resolves the host's sources once no matter how
|
|
20
|
+
* many consent fields the form carries.
|
|
21
|
+
*/
|
|
22
|
+
const resolveConsentEntries = async (args) => {
|
|
23
|
+
const { payload, req, form } = args;
|
|
24
|
+
const resolver = args.sources ?? consentSourcesOf(payload);
|
|
25
|
+
if (!resolver) return [];
|
|
26
|
+
const cache = cacheOf(req);
|
|
27
|
+
const cacheKey = String(form.id);
|
|
28
|
+
const cached = cache?.get(cacheKey);
|
|
29
|
+
if (cached) return cached;
|
|
30
|
+
const entries = await resolver({
|
|
31
|
+
req,
|
|
32
|
+
form
|
|
33
|
+
});
|
|
34
|
+
cache?.set(cacheKey, entries);
|
|
35
|
+
return entries;
|
|
36
|
+
};
|
|
37
|
+
//#endregion
|
|
38
|
+
export { resolveConsentEntries, stashConsentSources };
|
|
39
|
+
|
|
40
|
+
//# sourceMappingURL=resolveConsentEntries.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolveConsentEntries.js","names":[],"sources":["../../src/consent/resolveConsentEntries.ts"],"sourcesContent":["import type { Payload, PayloadRequest } from 'payload'\nimport { customStateOf, stashCustomState } from '../plugin/customState'\nimport type { ConsentSourceEntry, ConsentSourcesResolver } from './types'\n\ntype ConsentCustomState = { consentSources: ConsentSourcesResolver }\n\n/** Park the host's resolver on the config so root-level helpers can find it via `payload.config`. */\nexport const stashConsentSources = (\n\tcustom: Record<string, unknown> | undefined,\n\tsources: ConsentSourcesResolver\n): Record<string, unknown> =>\n\tstashCustomState<ConsentCustomState>(custom, { consentSources: sources })\n\nexport const consentSourcesOf = (payload: Payload): ConsentSourcesResolver | undefined =>\n\tcustomStateOf<ConsentCustomState>(payload).consentSources\n\nconst CACHE_KEY = 'formBuilderConsentSourcesCache'\n\ntype EntriesCache = Map<string, ConsentSourceEntry[]>\n\nconst cacheOf = (req: PayloadRequest): EntriesCache | undefined => {\n\tif (!req.context) {\n\t\treturn undefined\n\t}\n\tconst existing = req.context[CACHE_KEY]\n\tif (existing instanceof Map) {\n\t\treturn existing as EntriesCache\n\t}\n\tconst created: EntriesCache = new Map()\n\treq.context[CACHE_KEY] = created\n\treturn created\n}\n\nexport type ResolveConsentEntriesArgs = {\n\tpayload: Payload\n\treq: PayloadRequest\n\t/** The whole form being resolved; forwarded to the resolver, which casts for non-standard fields (e.g. tenant). */\n\tform: { id: number | string; title?: string | null }\n\t/** Resolver override for plugin-internal callers; defaults to the one the plugin stashed on the config. */\n\tsources?: ConsentSourcesResolver\n}\n\n/**\n * The host's consent sources for this request, or an empty list when no resolver is configured\n * (in which case the `consent` field type is not registered either, so nothing can reference one).\n * Throws whatever the resolver throws: every caller decides how to fail, and none of them fail open.\n * Cached per request and form id, so one submission resolves the host's sources once no matter how\n * many consent fields the form carries.\n */\nexport const resolveConsentEntries = async (\n\targs: ResolveConsentEntriesArgs\n): Promise<ConsentSourceEntry[]> => {\n\tconst { payload, req, form } = args\n\tconst resolver = args.sources ?? consentSourcesOf(payload)\n\tif (!resolver) {\n\t\treturn []\n\t}\n\tconst cache = cacheOf(req)\n\tconst cacheKey = String(form.id)\n\tconst cached = cache?.get(cacheKey)\n\tif (cached) {\n\t\treturn cached\n\t}\n\tconst entries = await resolver({ req, form })\n\tcache?.set(cacheKey, entries)\n\treturn entries\n}\n"],"mappings":";;;AAOA,MAAa,uBACZ,QACA,YAEA,iBAAqC,QAAQ,EAAE,gBAAgB,QAAQ,CAAC;AAEzE,MAAa,oBAAoB,YAChC,cAAkC,OAAO,EAAE;AAE5C,MAAM,YAAY;AAIlB,MAAM,WAAW,QAAkD;CAClE,IAAI,CAAC,IAAI,SACR;CAED,MAAM,WAAW,IAAI,QAAQ;CAC7B,IAAI,oBAAoB,KACvB,OAAO;CAER,MAAM,0BAAwB,IAAI,IAAI;CACtC,IAAI,QAAQ,aAAa;CACzB,OAAO;AACR;;;;;;;;AAkBA,MAAa,wBAAwB,OACpC,SACmC;CACnC,MAAM,EAAE,SAAS,KAAK,SAAS;CAC/B,MAAM,WAAW,KAAK,WAAW,iBAAiB,OAAO;CACzD,IAAI,CAAC,UACJ,OAAO,CAAC;CAET,MAAM,QAAQ,QAAQ,GAAG;CACzB,MAAM,WAAW,OAAO,KAAK,EAAE;CAC/B,MAAM,SAAS,OAAO,IAAI,QAAQ;CAClC,IAAI,QACH,OAAO;CAER,MAAM,UAAU,MAAM,SAAS;EAAE;EAAK;CAAK,CAAC;CAC5C,OAAO,IAAI,UAAU,OAAO;CAC5B,OAAO;AACR"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { ConsentSourcesResolver } from "./types.js";
|
|
2
|
+
import { Payload, PayloadRequest } from "payload";
|
|
3
|
+
|
|
4
|
+
//#region src/consent/resolveConsentSourcesRequest.d.ts
|
|
5
|
+
/** One selectable consent source for the consent field's `source` select. */
|
|
6
|
+
type ConsentSourceOption = {
|
|
7
|
+
label: string;
|
|
8
|
+
value: string;
|
|
9
|
+
};
|
|
10
|
+
type ResolveConsentSourcesRequestArgs = {
|
|
11
|
+
payload: Payload;
|
|
12
|
+
formId: number | string | undefined; /** Whether the caller is authenticated (an admin/user). */
|
|
13
|
+
isAuthed: boolean;
|
|
14
|
+
req: PayloadRequest;
|
|
15
|
+
resolver: ConsentSourcesResolver;
|
|
16
|
+
};
|
|
17
|
+
type ResolveConsentSourcesRequestResult = {
|
|
18
|
+
status: number;
|
|
19
|
+
body: {
|
|
20
|
+
options: ConsentSourceOption[];
|
|
21
|
+
} | {
|
|
22
|
+
errors: {
|
|
23
|
+
message: string;
|
|
24
|
+
}[];
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Authorize and resolve the `GET /:id/consent-sources` request backing the consent `source` select:
|
|
29
|
+
* authenticated callers get the host's sources for this request (a multi-tenant resolver scoping by
|
|
30
|
+
* `req` therefore offers an author only their own tenant's), anonymous callers are always refused.
|
|
31
|
+
* Statuses mirror the poll-options endpoint: 400 missing id, 403 unauthenticated, 404 unknown form,
|
|
32
|
+
* 503 when the resolver throws (fail closed).
|
|
33
|
+
*/
|
|
34
|
+
declare const resolveConsentSourcesRequest: (args: ResolveConsentSourcesRequestArgs) => Promise<ResolveConsentSourcesRequestResult>;
|
|
35
|
+
//#endregion
|
|
36
|
+
export { ConsentSourceOption, ResolveConsentSourcesRequestArgs, ResolveConsentSourcesRequestResult, resolveConsentSourcesRequest };
|
|
37
|
+
//# sourceMappingURL=resolveConsentSourcesRequest.d.ts.map
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { resolveConsentEntries } from "./resolveConsentEntries.js";
|
|
2
|
+
import { FORMS_SLUG } from "../collections/forms.js";
|
|
3
|
+
//#region src/consent/resolveConsentSourcesRequest.ts
|
|
4
|
+
/**
|
|
5
|
+
* Authorize and resolve the `GET /:id/consent-sources` request backing the consent `source` select:
|
|
6
|
+
* authenticated callers get the host's sources for this request (a multi-tenant resolver scoping by
|
|
7
|
+
* `req` therefore offers an author only their own tenant's), anonymous callers are always refused.
|
|
8
|
+
* Statuses mirror the poll-options endpoint: 400 missing id, 403 unauthenticated, 404 unknown form,
|
|
9
|
+
* 503 when the resolver throws (fail closed).
|
|
10
|
+
*/
|
|
11
|
+
const resolveConsentSourcesRequest = async (args) => {
|
|
12
|
+
const { payload, formId, isAuthed, req, resolver } = args;
|
|
13
|
+
if (!isAuthed) return {
|
|
14
|
+
status: 403,
|
|
15
|
+
body: { errors: [{ message: "Forbidden" }] }
|
|
16
|
+
};
|
|
17
|
+
if (formId == null) return {
|
|
18
|
+
status: 400,
|
|
19
|
+
body: { errors: [{ message: "Missing form id" }] }
|
|
20
|
+
};
|
|
21
|
+
const form = await payload.findByID({
|
|
22
|
+
collection: FORMS_SLUG,
|
|
23
|
+
id: formId,
|
|
24
|
+
depth: 0,
|
|
25
|
+
req
|
|
26
|
+
}).catch(() => null);
|
|
27
|
+
if (!form) return {
|
|
28
|
+
status: 404,
|
|
29
|
+
body: { errors: [{ message: "Not found" }] }
|
|
30
|
+
};
|
|
31
|
+
try {
|
|
32
|
+
return {
|
|
33
|
+
status: 200,
|
|
34
|
+
body: { options: (await resolveConsentEntries({
|
|
35
|
+
payload,
|
|
36
|
+
req,
|
|
37
|
+
form,
|
|
38
|
+
sources: resolver
|
|
39
|
+
})).map((entry) => ({
|
|
40
|
+
label: entry.name ?? entry.id,
|
|
41
|
+
value: entry.id
|
|
42
|
+
})) }
|
|
43
|
+
};
|
|
44
|
+
} catch {
|
|
45
|
+
return {
|
|
46
|
+
status: 503,
|
|
47
|
+
body: { errors: [{ message: "Consent sources unavailable" }] }
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
//#endregion
|
|
52
|
+
export { resolveConsentSourcesRequest };
|
|
53
|
+
|
|
54
|
+
//# sourceMappingURL=resolveConsentSourcesRequest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolveConsentSourcesRequest.js","names":[],"sources":["../../src/consent/resolveConsentSourcesRequest.ts"],"sourcesContent":["import type { Payload, PayloadRequest } from 'payload'\nimport { FORMS_SLUG } from '../collections/forms'\nimport { resolveConsentEntries } from './resolveConsentEntries'\nimport type { ConsentSourcesResolver } from './types'\n\n/** One selectable consent source for the consent field's `source` select. */\nexport type ConsentSourceOption = { label: string; value: string }\n\nexport type ResolveConsentSourcesRequestArgs = {\n\tpayload: Payload\n\tformId: number | string | undefined\n\t/** Whether the caller is authenticated (an admin/user). */\n\tisAuthed: boolean\n\treq: PayloadRequest\n\tresolver: ConsentSourcesResolver\n}\n\nexport type ResolveConsentSourcesRequestResult = {\n\tstatus: number\n\tbody: { options: ConsentSourceOption[] } | { errors: { message: string }[] }\n}\n\n/**\n * Authorize and resolve the `GET /:id/consent-sources` request backing the consent `source` select:\n * authenticated callers get the host's sources for this request (a multi-tenant resolver scoping by\n * `req` therefore offers an author only their own tenant's), anonymous callers are always refused.\n * Statuses mirror the poll-options endpoint: 400 missing id, 403 unauthenticated, 404 unknown form,\n * 503 when the resolver throws (fail closed).\n */\nexport const resolveConsentSourcesRequest = async (\n\targs: ResolveConsentSourcesRequestArgs\n): Promise<ResolveConsentSourcesRequestResult> => {\n\tconst { payload, formId, isAuthed, req, resolver } = args\n\tif (!isAuthed) {\n\t\treturn { status: 403, body: { errors: [{ message: 'Forbidden' }] } }\n\t}\n\tif (formId == null) {\n\t\treturn { status: 400, body: { errors: [{ message: 'Missing form id' }] } }\n\t}\n\t// Load under the caller's own read access (no overrideAccess): a tenant-scoped `forms.access.read`\n\t// then refuses a cross-tenant form id (null -> 404), so an authed user can never enumerate another\n\t// tenant's consent source labels/ids.\n\tconst form = await payload\n\t\t.findByID({ collection: FORMS_SLUG, id: formId, depth: 0, req })\n\t\t.catch(() => null)\n\tif (!form) {\n\t\treturn { status: 404, body: { errors: [{ message: 'Not found' }] } }\n\t}\n\ttry {\n\t\tconst entries = await resolveConsentEntries({ payload, req, form, sources: resolver })\n\t\treturn {\n\t\t\tstatus: 200,\n\t\t\tbody: {\n\t\t\t\toptions: entries.map((entry) => ({ label: entry.name ?? entry.id, value: entry.id })),\n\t\t\t},\n\t\t}\n\t} catch {\n\t\treturn { status: 503, body: { errors: [{ message: 'Consent sources unavailable' }] } }\n\t}\n}\n"],"mappings":";;;;;;;;;;AA6BA,MAAa,+BAA+B,OAC3C,SACiD;CACjD,MAAM,EAAE,SAAS,QAAQ,UAAU,KAAK,aAAa;CACrD,IAAI,CAAC,UACJ,OAAO;EAAE,QAAQ;EAAK,MAAM,EAAE,QAAQ,CAAC,EAAE,SAAS,YAAY,CAAC,EAAE;CAAE;CAEpE,IAAI,UAAU,MACb,OAAO;EAAE,QAAQ;EAAK,MAAM,EAAE,QAAQ,CAAC,EAAE,SAAS,kBAAkB,CAAC,EAAE;CAAE;CAK1E,MAAM,OAAO,MAAM,QACjB,SAAS;EAAE,YAAY;EAAY,IAAI;EAAQ,OAAO;EAAG;CAAI,CAAC,EAC9D,YAAY,IAAI;CAClB,IAAI,CAAC,MACJ,OAAO;EAAE,QAAQ;EAAK,MAAM,EAAE,QAAQ,CAAC,EAAE,SAAS,YAAY,CAAC,EAAE;CAAE;CAEpE,IAAI;EAEH,OAAO;GACN,QAAQ;GACR,MAAM,EACL,UAAS,MAJW,sBAAsB;IAAE;IAAS;IAAK;IAAM,SAAS;GAAS,CAAC,GAIlE,KAAK,WAAW;IAAE,OAAO,MAAM,QAAQ,MAAM;IAAI,OAAO,MAAM;GAAG,EAAE,EACrF;EACD;CACD,QAAQ;EACP,OAAO;GAAE,QAAQ;GAAK,MAAM,EAAE,QAAQ,CAAC,EAAE,SAAS,8BAA8B,CAAC,EAAE;EAAE;CACtF;AACD"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { ConsentSourcesResolver } from "./types.js";
|
|
2
|
+
import { Payload, PayloadRequest } from "payload";
|
|
3
|
+
|
|
4
|
+
//#region src/consent/resolveConsentStatements.d.ts
|
|
5
|
+
/** What a consent field shows the visitor, resolved from its source at request time. */
|
|
6
|
+
type ConsentStatement = {
|
|
7
|
+
/** Rich text state (or whatever the host's resolver returned), for the request's locale. */statement?: unknown; /** The policy link beside the statement, present only when the source carries both a `url` and a `label`. */
|
|
8
|
+
link?: {
|
|
9
|
+
label: string;
|
|
10
|
+
url: string;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
/** Resolved statements keyed by consent field name, as `toFormDocument`'s `consentStatements` takes them. */
|
|
14
|
+
type ConsentStatements = Record<string, ConsentStatement>;
|
|
15
|
+
type ResolveConsentStatementsArgs = {
|
|
16
|
+
payload: Payload;
|
|
17
|
+
req: PayloadRequest; /** A loaded forms document; its consent fields' `source` ids drive resolution. The whole doc is forwarded to the resolver. */
|
|
18
|
+
form: {
|
|
19
|
+
id: number | string;
|
|
20
|
+
title?: string | null;
|
|
21
|
+
fields?: {
|
|
22
|
+
blockType: string;
|
|
23
|
+
name?: string;
|
|
24
|
+
[key: string]: unknown;
|
|
25
|
+
}[] | null;
|
|
26
|
+
}; /** Resolver override for plugin-internal callers; defaults to the one the plugin stashed on the config. */
|
|
27
|
+
sources?: ConsentSourcesResolver;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Resolve every consent field's statement for this request, ready to hand to
|
|
31
|
+
* `toFormDocument(doc, { consentStatements })`.
|
|
32
|
+
*
|
|
33
|
+
* The statement is a live reference, not a copy: a form stores only its source id, and the
|
|
34
|
+
* sentence the visitor reads is resolved here, in their locale, from whatever the source says
|
|
35
|
+
* right now. So correcting a policy sentence corrects every form referencing it, with nothing to
|
|
36
|
+
* re-save, and a form rendered without this step shows no statement at all rather than a stale one.
|
|
37
|
+
*
|
|
38
|
+
* Call it server-side (a Server Component, a route handler) before rendering `<Form>`. Throws
|
|
39
|
+
* whatever the host's resolver throws, so a page can decide between failing and rendering without
|
|
40
|
+
* consent; a submit resolves the source again regardless, and the proof is built from that.
|
|
41
|
+
*/
|
|
42
|
+
declare const resolveConsentStatements: (args: ResolveConsentStatementsArgs) => Promise<ConsentStatements>;
|
|
43
|
+
//#endregion
|
|
44
|
+
export { ConsentStatement, ConsentStatements, ResolveConsentStatementsArgs, resolveConsentStatements };
|
|
45
|
+
//# sourceMappingURL=resolveConsentStatements.d.ts.map
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { resolveConsentEntries } from "./resolveConsentEntries.js";
|
|
2
|
+
//#region src/consent/resolveConsentStatements.ts
|
|
3
|
+
/**
|
|
4
|
+
* Resolve every consent field's statement for this request, ready to hand to
|
|
5
|
+
* `toFormDocument(doc, { consentStatements })`.
|
|
6
|
+
*
|
|
7
|
+
* The statement is a live reference, not a copy: a form stores only its source id, and the
|
|
8
|
+
* sentence the visitor reads is resolved here, in their locale, from whatever the source says
|
|
9
|
+
* right now. So correcting a policy sentence corrects every form referencing it, with nothing to
|
|
10
|
+
* re-save, and a form rendered without this step shows no statement at all rather than a stale one.
|
|
11
|
+
*
|
|
12
|
+
* Call it server-side (a Server Component, a route handler) before rendering `<Form>`. Throws
|
|
13
|
+
* whatever the host's resolver throws, so a page can decide between failing and rendering without
|
|
14
|
+
* consent; a submit resolves the source again regardless, and the proof is built from that.
|
|
15
|
+
*/
|
|
16
|
+
const resolveConsentStatements = async (args) => {
|
|
17
|
+
const { payload, req, form, sources } = args;
|
|
18
|
+
const consentFields = (form.fields ?? []).filter((field) => field.blockType === "consent" && typeof field.name === "string" && field.name.length > 0);
|
|
19
|
+
if (consentFields.length === 0) return {};
|
|
20
|
+
const entries = await resolveConsentEntries({
|
|
21
|
+
payload,
|
|
22
|
+
req,
|
|
23
|
+
form,
|
|
24
|
+
sources
|
|
25
|
+
});
|
|
26
|
+
const statements = {};
|
|
27
|
+
for (const field of consentFields) {
|
|
28
|
+
const entry = entries.find((candidate) => candidate.id === field.source);
|
|
29
|
+
if (!entry) continue;
|
|
30
|
+
const label = typeof entry.name === "string" && entry.name.trim() !== "" ? entry.name : "";
|
|
31
|
+
statements[field.name] = {
|
|
32
|
+
...entry.statement != null ? { statement: entry.statement } : {},
|
|
33
|
+
...label && typeof entry.url === "string" && entry.url.length > 0 ? { link: {
|
|
34
|
+
label,
|
|
35
|
+
url: entry.url
|
|
36
|
+
} } : {}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
return statements;
|
|
40
|
+
};
|
|
41
|
+
//#endregion
|
|
42
|
+
export { resolveConsentStatements };
|
|
43
|
+
|
|
44
|
+
//# sourceMappingURL=resolveConsentStatements.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolveConsentStatements.js","names":[],"sources":["../../src/consent/resolveConsentStatements.ts"],"sourcesContent":["import type { Payload, PayloadRequest } from 'payload'\nimport { resolveConsentEntries } from './resolveConsentEntries'\nimport type { ConsentSourcesResolver } from './types'\n\n/** What a consent field shows the visitor, resolved from its source at request time. */\nexport type ConsentStatement = {\n\t/** Rich text state (or whatever the host's resolver returned), for the request's locale. */\n\tstatement?: unknown\n\t/** The policy link beside the statement, present only when the source carries both a `url` and a `label`. */\n\tlink?: { label: string; url: string }\n}\n\n/** Resolved statements keyed by consent field name, as `toFormDocument`'s `consentStatements` takes them. */\nexport type ConsentStatements = Record<string, ConsentStatement>\n\nexport type ResolveConsentStatementsArgs = {\n\tpayload: Payload\n\treq: PayloadRequest\n\t/** A loaded forms document; its consent fields' `source` ids drive resolution. The whole doc is forwarded to the resolver. */\n\tform: {\n\t\tid: number | string\n\t\ttitle?: string | null\n\t\tfields?: { blockType: string; name?: string; [key: string]: unknown }[] | null\n\t}\n\t/** Resolver override for plugin-internal callers; defaults to the one the plugin stashed on the config. */\n\tsources?: ConsentSourcesResolver\n}\n\n/**\n * Resolve every consent field's statement for this request, ready to hand to\n * `toFormDocument(doc, { consentStatements })`.\n *\n * The statement is a live reference, not a copy: a form stores only its source id, and the\n * sentence the visitor reads is resolved here, in their locale, from whatever the source says\n * right now. So correcting a policy sentence corrects every form referencing it, with nothing to\n * re-save, and a form rendered without this step shows no statement at all rather than a stale one.\n *\n * Call it server-side (a Server Component, a route handler) before rendering `<Form>`. Throws\n * whatever the host's resolver throws, so a page can decide between failing and rendering without\n * consent; a submit resolves the source again regardless, and the proof is built from that.\n */\nexport const resolveConsentStatements = async (\n\targs: ResolveConsentStatementsArgs\n): Promise<ConsentStatements> => {\n\tconst { payload, req, form, sources } = args\n\tconst consentFields = (form.fields ?? []).filter(\n\t\t(field): field is { blockType: string; name: string; source?: unknown } =>\n\t\t\tfield.blockType === 'consent' && typeof field.name === 'string' && field.name.length > 0\n\t)\n\tif (consentFields.length === 0) {\n\t\treturn {}\n\t}\n\tconst entries = await resolveConsentEntries({ payload, req, form, sources })\n\tconst statements: ConsentStatements = {}\n\tfor (const field of consentFields) {\n\t\tconst entry = entries.find((candidate) => candidate.id === field.source)\n\t\tif (!entry) {\n\t\t\tcontinue\n\t\t}\n\t\t// The link needs a name of its own, so it takes the source's `name` and never falls back to\n\t\t// the `id`: the id is a machine identifier, and showing it as the words a visitor clicks is\n\t\t// worse than no link at all. A source with a url and no name simply has no link.\n\t\tconst label = typeof entry.name === 'string' && entry.name.trim() !== '' ? entry.name : ''\n\t\tstatements[field.name] = {\n\t\t\t...(entry.statement != null ? { statement: entry.statement } : {}),\n\t\t\t...(label && typeof entry.url === 'string' && entry.url.length > 0\n\t\t\t\t? { link: { label, url: entry.url } }\n\t\t\t\t: {}),\n\t\t}\n\t}\n\treturn statements\n}\n"],"mappings":";;;;;;;;;;;;;;;AAyCA,MAAa,2BAA2B,OACvC,SACgC;CAChC,MAAM,EAAE,SAAS,KAAK,MAAM,YAAY;CACxC,MAAM,iBAAiB,KAAK,UAAU,CAAC,GAAG,QACxC,UACA,MAAM,cAAc,aAAa,OAAO,MAAM,SAAS,YAAY,MAAM,KAAK,SAAS,CACzF;CACA,IAAI,cAAc,WAAW,GAC5B,OAAO,CAAC;CAET,MAAM,UAAU,MAAM,sBAAsB;EAAE;EAAS;EAAK;EAAM;CAAQ,CAAC;CAC3E,MAAM,aAAgC,CAAC;CACvC,KAAK,MAAM,SAAS,eAAe;EAClC,MAAM,QAAQ,QAAQ,MAAM,cAAc,UAAU,OAAO,MAAM,MAAM;EACvE,IAAI,CAAC,OACJ;EAKD,MAAM,QAAQ,OAAO,MAAM,SAAS,YAAY,MAAM,KAAK,KAAK,MAAM,KAAK,MAAM,OAAO;EACxF,WAAW,MAAM,QAAQ;GACxB,GAAI,MAAM,aAAa,OAAO,EAAE,WAAW,MAAM,UAAU,IAAI,CAAC;GAChE,GAAI,SAAS,OAAO,MAAM,QAAQ,YAAY,MAAM,IAAI,SAAS,IAC9D,EAAE,MAAM;IAAE;IAAO,KAAK,MAAM;GAAI,EAAE,IAClC,CAAC;EACL;CACD;CACA,OAAO;AACR"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Payload, PayloadRequest } from "payload";
|
|
2
|
+
|
|
3
|
+
//#region src/consent/resolvePublishedVersionRef.d.ts
|
|
4
|
+
type ResolvePublishedVersionRefArgs = {
|
|
5
|
+
payload: Payload;
|
|
6
|
+
collection: string;
|
|
7
|
+
id: number | string; /** Threaded into `findVersions` so a version written earlier in the same transaction is visible. */
|
|
8
|
+
req?: PayloadRequest;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* The id of a document's latest published version, or null when nothing is published.
|
|
12
|
+
*
|
|
13
|
+
* Drafts-only, and deliberately not a versions check: `_status` exists only where
|
|
14
|
+
* `versions.drafts` is on (Payload adds the base version fields inside that branch when
|
|
15
|
+
* sanitizing), so on a collection with plain versions and no drafts this query matches nothing and
|
|
16
|
+
* returns null, which is indistinguishable from having no versions at all. Callers must decide the
|
|
17
|
+
* difference themselves with `hasDraftsEnabled` rather than reading null as "no versions" (see
|
|
18
|
+
* `captureConsent`). Never throws.
|
|
19
|
+
*/
|
|
20
|
+
declare const resolvePublishedVersionRef: (args: ResolvePublishedVersionRefArgs) => Promise<string | null>;
|
|
21
|
+
//#endregion
|
|
22
|
+
export { ResolvePublishedVersionRefArgs, resolvePublishedVersionRef };
|
|
23
|
+
//# sourceMappingURL=resolvePublishedVersionRef.d.ts.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//#region src/consent/resolvePublishedVersionRef.ts
|
|
2
|
+
/**
|
|
3
|
+
* The id of a document's latest published version, or null when nothing is published.
|
|
4
|
+
*
|
|
5
|
+
* Drafts-only, and deliberately not a versions check: `_status` exists only where
|
|
6
|
+
* `versions.drafts` is on (Payload adds the base version fields inside that branch when
|
|
7
|
+
* sanitizing), so on a collection with plain versions and no drafts this query matches nothing and
|
|
8
|
+
* returns null, which is indistinguishable from having no versions at all. Callers must decide the
|
|
9
|
+
* difference themselves with `hasDraftsEnabled` rather than reading null as "no versions" (see
|
|
10
|
+
* `captureConsent`). Never throws.
|
|
11
|
+
*/
|
|
12
|
+
const resolvePublishedVersionRef = async (args) => {
|
|
13
|
+
try {
|
|
14
|
+
const doc = (await args.payload.findVersions({
|
|
15
|
+
collection: args.collection,
|
|
16
|
+
where: { and: [{ parent: { equals: args.id } }, { "version._status": { equals: "published" } }] },
|
|
17
|
+
sort: "-updatedAt",
|
|
18
|
+
limit: 1,
|
|
19
|
+
depth: 0,
|
|
20
|
+
req: args.req
|
|
21
|
+
}))?.docs?.[0];
|
|
22
|
+
return doc ? String(doc.id) : null;
|
|
23
|
+
} catch {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
//#endregion
|
|
28
|
+
export { resolvePublishedVersionRef };
|
|
29
|
+
|
|
30
|
+
//# sourceMappingURL=resolvePublishedVersionRef.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolvePublishedVersionRef.js","names":[],"sources":["../../src/consent/resolvePublishedVersionRef.ts"],"sourcesContent":["import type { Payload, PayloadRequest } from 'payload'\n\nexport type ResolvePublishedVersionRefArgs = {\n\tpayload: Payload\n\tcollection: string\n\tid: number | string\n\t/** Threaded into `findVersions` so a version written earlier in the same transaction is visible. */\n\treq?: PayloadRequest\n}\n\n/**\n * The id of a document's latest published version, or null when nothing is published.\n *\n * Drafts-only, and deliberately not a versions check: `_status` exists only where\n * `versions.drafts` is on (Payload adds the base version fields inside that branch when\n * sanitizing), so on a collection with plain versions and no drafts this query matches nothing and\n * returns null, which is indistinguishable from having no versions at all. Callers must decide the\n * difference themselves with `hasDraftsEnabled` rather than reading null as \"no versions\" (see\n * `captureConsent`). Never throws.\n */\nexport const resolvePublishedVersionRef = async (\n\targs: ResolvePublishedVersionRefArgs\n): Promise<string | null> => {\n\ttry {\n\t\tconst result = await args.payload.findVersions({\n\t\t\tcollection: args.collection as never,\n\t\t\twhere: {\n\t\t\t\tand: [{ parent: { equals: args.id } }, { 'version._status': { equals: 'published' } }],\n\t\t\t},\n\t\t\tsort: '-updatedAt',\n\t\t\tlimit: 1,\n\t\t\tdepth: 0,\n\t\t\treq: args.req,\n\t\t})\n\t\tconst doc = result?.docs?.[0]\n\t\treturn doc ? String(doc.id) : null\n\t} catch {\n\t\treturn null\n\t}\n}\n"],"mappings":";;;;;;;;;;;AAoBA,MAAa,6BAA6B,OACzC,SAC4B;CAC5B,IAAI;EAWH,MAAM,OAAM,MAVS,KAAK,QAAQ,aAAa;GAC9C,YAAY,KAAK;GACjB,OAAO,EACN,KAAK,CAAC,EAAE,QAAQ,EAAE,QAAQ,KAAK,GAAG,EAAE,GAAG,EAAE,mBAAmB,EAAE,QAAQ,YAAY,EAAE,CAAC,EACtF;GACA,MAAM;GACN,OAAO;GACP,OAAO;GACP,KAAK,KAAK;EACX,CAAC,IACmB,OAAO;EAC3B,OAAO,MAAM,OAAO,IAAI,EAAE,IAAI;CAC/B,QAAQ;EACP,OAAO;CACR;AACD"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { PayloadRequest } from "payload";
|
|
2
|
+
|
|
3
|
+
//#region src/consent/types.d.ts
|
|
4
|
+
/** A document reference, kept id-based so renaming or re-slugging the page never breaks it. */
|
|
5
|
+
type ConsentSourcePage = {
|
|
6
|
+
relationTo: string;
|
|
7
|
+
id: number | string;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* One consent source a form author can reference by `id`: the statement the visitor agrees to, and
|
|
11
|
+
* optionally the policy document that statement belongs to. Produced by the host's
|
|
12
|
+
* {@link ConsentSourcesResolver}, normally by mapping the rows of a placed `consentSourcesField()`.
|
|
13
|
+
*
|
|
14
|
+
* `id` is the array row's own auto-assigned identifier, so it survives name edits and reordering
|
|
15
|
+
* and is the stable reference stored on the consent field and in every proof. `statement` is rich
|
|
16
|
+
* text state (the visitor-facing sentence), already resolved for the request's locale by virtue of
|
|
17
|
+
* the resolver reading its own localized field under `req.locale`. `page` drives proof: an id and
|
|
18
|
+
* its collection, never a URL, so the document can be renamed, re-slugged, or re-routed without
|
|
19
|
+
* stranding past proofs. `url` is the visitor-facing link the renderer shows beside the statement;
|
|
20
|
+
* only the host knows how a document id maps to a public route, so the plugin never derives one.
|
|
21
|
+
*/
|
|
22
|
+
type ConsentSourceEntry = {
|
|
23
|
+
id: string;
|
|
24
|
+
name?: string;
|
|
25
|
+
statement?: unknown;
|
|
26
|
+
page?: ConsentSourcePage;
|
|
27
|
+
url?: string;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Host seam resolving the consent sources a form's authors can reference (plugin option
|
|
31
|
+
* `consent.sources`). Without it there are no sources, so the `consent` field type is not
|
|
32
|
+
* registered at all.
|
|
33
|
+
*
|
|
34
|
+
* The intended shape: place `consentSourcesField()` on a collection or global you own, then read it
|
|
35
|
+
* back here. Multi-tenant hosts scope the read by the tenant derived from `req` (host header,
|
|
36
|
+
* cookie, or auth context) and return only that tenant's sources, so one tenant's statements are
|
|
37
|
+
* never selectable, resolvable, or provable under another's. Read under `req.locale` so the
|
|
38
|
+
* statement the visitor agrees to is the one they were shown.
|
|
39
|
+
*
|
|
40
|
+
* Do not thread the save's `req` into a `find({ locale: 'all' })` from within a form's save
|
|
41
|
+
* validation: it flips `req.locale` to `all` and corrupts the localized write of the document being
|
|
42
|
+
* saved. Read the settings document without the save's `req` (already-committed data, no transaction).
|
|
43
|
+
*/
|
|
44
|
+
type ConsentSourcesResolver = (args: {
|
|
45
|
+
req: PayloadRequest;
|
|
46
|
+
/**
|
|
47
|
+
* The form document being read: `id`, `title`, and (at runtime) every other field. Derive
|
|
48
|
+
* multi-tenant scoping from a field on it, casting for non-standard fields (e.g.
|
|
49
|
+
* `(form as { tenant?: string }).tenant`), rather than reading the form back: reading the same
|
|
50
|
+
* `forms` collection from within this resolver re-enters the form's afterRead hook. The type is
|
|
51
|
+
* kept index-signature-free so a generated `Form` interface assigns without a cast. Treat `form`
|
|
52
|
+
* as read-only.
|
|
53
|
+
*/
|
|
54
|
+
form: {
|
|
55
|
+
id: number | string;
|
|
56
|
+
title?: string | null;
|
|
57
|
+
};
|
|
58
|
+
}) => ConsentSourceEntry[] | Promise<ConsentSourceEntry[]>;
|
|
59
|
+
//#endregion
|
|
60
|
+
export { ConsentSourceEntry, ConsentSourcePage, ConsentSourcesResolver };
|
|
61
|
+
//# sourceMappingURL=types.d.ts.map
|