@cosmicdrift/kumiko-samples 0.366.0 → 0.368.0
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/package.json +1 -1
- package/packages/bundled-features/package.json +16 -2
- package/packages/bundled-features/src/audit/handlers/details.query.ts +1 -1
- package/packages/bundled-features/src/audit/handlers/list.query.ts +1 -1
- package/packages/bundled-features/src/audit/run-escape-hatch-retention.ts +5 -5
- package/packages/bundled-features/src/auth-email-password/bootstrap.ts +1 -1
- package/packages/bundled-features/src/auth-email-password/handlers/invite-accept-with-login.write.ts +10 -3
- package/packages/bundled-features/src/auth-email-password/handlers/invite-accept.write.ts +10 -3
- package/packages/bundled-features/src/auth-email-password/handlers/invite-info.query.ts +1 -1
- package/packages/bundled-features/src/auth-email-password/handlers/invite-signup-complete.write.ts +6 -2
- package/packages/bundled-features/src/auth-email-password/handlers/signup-confirm.write.ts +1 -1
- package/packages/bundled-features/src/auth-email-password/seeding.ts +2 -2
- package/packages/bundled-features/src/auth-foundation/feature.ts +43 -34
- package/packages/bundled-features/src/auth-foundation/index.ts +1 -0
- package/packages/bundled-features/src/auth-mfa/db/queries.ts +5 -2
- package/packages/bundled-features/src/auth-mfa/handlers/enable-confirm-preauth.write.ts +1 -1
- package/packages/bundled-features/src/auth-mfa/handlers/enable-start-preauth.write.ts +1 -1
- package/packages/bundled-features/src/auth-mfa/handlers/reencrypt.job.ts +2 -2
- package/packages/bundled-features/src/auth-mfa/handlers/status.query.ts +1 -1
- package/packages/bundled-features/src/auth-mfa/handlers/verify.write.ts +1 -1
- package/packages/bundled-features/src/auth-mfa/mfa-code-verifier.ts +1 -1
- package/packages/bundled-features/src/auth-mfa/mfa-status-checker.ts +1 -1
- package/packages/bundled-features/src/auth-mfa-user-data/index.ts +19 -10
- package/packages/bundled-features/src/billing-foundation/billing-info-query.ts +1 -1
- package/packages/bundled-features/src/billing-foundation/feature.ts +138 -135
- package/packages/bundled-features/src/billing-foundation/handlers/create-portal-session.write.ts +1 -1
- package/packages/bundled-features/src/billing-foundation/projection.ts +3 -2
- package/packages/bundled-features/src/cap-counter/calendar-cap-usage-reservation.ts +52 -1
- package/packages/bundled-features/src/cap-counter/cap-reservation.ts +203 -15
- package/packages/bundled-features/src/cap-counter/changes.json +13 -0
- package/packages/bundled-features/src/cap-counter/feature.ts +84 -73
- package/packages/bundled-features/src/cap-counter/handlers/increment-rolling.write.ts +3 -4
- package/packages/bundled-features/src/cap-counter/index.ts +9 -1
- package/packages/bundled-features/src/cap-counter/tables.ts +10 -3
- package/packages/bundled-features/src/cap-overview/handlers/caps-usage.query.ts +1 -2
- package/packages/bundled-features/src/cap-overview/handlers/tenant-caps-list.query.ts +6 -2
- package/packages/bundled-features/src/cap-overview/handlers/tenant-options.query.ts +1 -1
- package/packages/bundled-features/src/channel-email/changes.json +6 -0
- package/packages/bundled-features/src/channel-email/email-channel.ts +12 -2
- package/packages/bundled-features/src/channel-email/feature.ts +1 -1
- package/packages/bundled-features/src/channel-in-app/handlers/inbox.query.ts +1 -1
- package/packages/bundled-features/src/channel-in-app/handlers/mark-all-read.write.ts +1 -1
- package/packages/bundled-features/src/channel-in-app/handlers/mark-read.write.ts +1 -1
- package/packages/bundled-features/src/channel-in-app/handlers/unread-count.query.ts +1 -1
- package/packages/bundled-features/src/channel-in-app/tables.ts +1 -1
- package/packages/bundled-features/src/compliance-profiles/handlers/for-tenant.query.ts +1 -1
- package/packages/bundled-features/src/compliance-profiles/handlers/needs-profile.query.ts +1 -1
- package/packages/bundled-features/src/compliance-profiles/handlers/set-profile.write.ts +1 -2
- package/packages/bundled-features/src/compliance-profiles/resolve-for-tenant.ts +1 -1
- package/packages/bundled-features/src/compliance-profiles/seeding.ts +8 -4
- package/packages/bundled-features/src/compliance-profiles-ops/index.ts +26 -17
- package/packages/bundled-features/src/config/db/queries/resolver.ts +1 -1
- package/packages/bundled-features/src/config/handlers/reencrypt.job.ts +2 -2
- package/packages/bundled-features/src/config/resolver.ts +1 -1
- package/packages/bundled-features/src/config/write-helpers.ts +1 -1
- package/packages/bundled-features/src/crypto-shredding/changes.json +6 -0
- package/packages/bundled-features/src/crypto-shredding/handlers/forget-subject.write.ts +9 -7
- package/packages/bundled-features/src/custom-fields/db/queries/field-access.ts +1 -1
- package/packages/bundled-features/src/custom-fields/db/queries/projection.ts +1 -1
- package/packages/bundled-features/src/custom-fields/db/queries/quota.ts +1 -1
- package/packages/bundled-features/src/custom-fields/db/queries/retention.ts +6 -2
- package/packages/bundled-features/src/custom-fields/db/queries/user-data-rights.ts +1 -1
- package/packages/bundled-features/src/custom-fields/feature.ts +11 -14
- package/packages/bundled-features/src/custom-fields/handlers/clear-custom-field.write.ts +2 -2
- package/packages/bundled-features/src/custom-fields/handlers/delete-system-field.write.ts +2 -2
- package/packages/bundled-features/src/custom-fields/handlers/delete-tenant-field.write.ts +2 -2
- package/packages/bundled-features/src/custom-fields/handlers/set-custom-field.write.ts +2 -2
- package/packages/bundled-features/src/custom-fields/wire-for-entity.ts +4 -4
- package/packages/bundled-features/src/data-retention/resolve-for-tenant.ts +1 -1
- package/packages/bundled-features/src/data-retention/run-retention-cleanup.ts +16 -10
- package/packages/bundled-features/src/delivery/address-opt-out.ts +5 -2
- package/packages/bundled-features/src/delivery/attempt-log-retention.ts +1 -1
- package/packages/bundled-features/src/delivery/changes.json +12 -0
- package/packages/bundled-features/src/delivery/channel-context.ts +2 -1
- package/packages/bundled-features/src/delivery/db/queries/address-opt-outs.ts +1 -1
- package/packages/bundled-features/src/delivery/db/queries/preferences.ts +1 -1
- package/packages/bundled-features/src/delivery/delivery-service.ts +70 -8
- package/packages/bundled-features/src/delivery/feature.ts +2 -2
- package/packages/bundled-features/src/delivery/handlers/log.query.ts +3 -2
- package/packages/bundled-features/src/delivery/handlers/preferences.query.ts +1 -1
- package/packages/bundled-features/src/delivery/handlers/unsubscribe-address.write.ts +10 -5
- package/packages/bundled-features/src/delivery/index.ts +6 -0
- package/packages/bundled-features/src/delivery/testing.ts +2 -0
- package/packages/bundled-features/src/delivery/types.ts +4 -0
- package/packages/bundled-features/src/delivery/unsubscribe-link.ts +73 -0
- package/packages/bundled-features/src/delivery/unsubscribe-page-strings.ts +17 -0
- package/packages/bundled-features/src/delivery/unsubscribe.ts +94 -31
- package/packages/bundled-features/src/delivery/upsert-preference.ts +5 -2
- package/packages/bundled-features/src/derivatives-sharp/feature.ts +21 -12
- package/packages/bundled-features/src/derivatives-sharp/index.ts +1 -1
- package/packages/bundled-features/src/document-ingest-foundation/feature.ts +112 -103
- package/packages/bundled-features/src/document-ingest-foundation/forget-extract-with-file-ref.ts +3 -3
- package/packages/bundled-features/src/document-ingest-foundation/index.ts +4 -1
- package/packages/bundled-features/src/feature-toggles/global-feature-state-table.ts +1 -1
- package/packages/bundled-features/src/feature-toggles/handlers/set.write.ts +3 -5
- package/packages/bundled-features/src/feature-toggles/toggle-runtime.ts +1 -1
- package/packages/bundled-features/src/file-derivatives/feature.ts +134 -129
- package/packages/bundled-features/src/file-derivatives/handlers/public-variant-by-file-ref.query.ts +1 -1
- package/packages/bundled-features/src/file-derivatives/handlers/public-variant.query.ts +1 -1
- package/packages/bundled-features/src/file-foundation/feature.ts +38 -29
- package/packages/bundled-features/src/file-foundation/index.ts +1 -0
- package/packages/bundled-features/src/file-foundation/read-file-ref-content.ts +1 -1
- package/packages/bundled-features/src/file-provider-inmemory/feature.ts +32 -21
- package/packages/bundled-features/src/file-provider-inmemory/index.ts +6 -1
- package/packages/bundled-features/src/file-provider-s3/changes.json +10 -1
- package/packages/bundled-features/src/file-provider-s3/env-feature.ts +62 -0
- package/packages/bundled-features/src/file-provider-s3/feature.ts +107 -73
- package/packages/bundled-features/src/file-provider-s3/index.ts +6 -1
- package/packages/bundled-features/src/file-provider-s3/lib/index.ts +3 -0
- package/packages/bundled-features/src/{files-provider-s3 → file-provider-s3/lib}/s3-provider.ts +19 -19
- package/packages/bundled-features/src/file-provider-s3-env/index.ts +7 -2
- package/packages/bundled-features/src/files-provider-s3/index.ts +11 -3
- package/packages/bundled-features/src/files-tenant-data/handlers/sweep-orphaned-derivatives.job.ts +1 -1
- package/packages/bundled-features/src/files-tenant-data/hooks.ts +1 -2
- package/packages/bundled-features/src/folders/feature.ts +8 -3
- package/packages/bundled-features/src/folders-user-data/index.ts +27 -18
- package/packages/bundled-features/src/form-draft/db/queries/cleanup.ts +1 -1
- package/packages/bundled-features/src/form-draft/db/queries/draft-count.ts +1 -1
- package/packages/bundled-features/src/form-draft/db/queries/owned-file-refs.ts +3 -2
- package/packages/bundled-features/src/form-draft/feature.ts +6 -1
- package/packages/bundled-features/src/form-draft/handlers/cleanup.job.ts +2 -2
- package/packages/bundled-features/src/form-draft/index.ts +1 -1
- package/packages/bundled-features/src/form-draft/lookup.ts +1 -1
- package/packages/bundled-features/src/form-draft-user-data/index.ts +19 -10
- package/packages/bundled-features/src/inbound-mail-foundation/feature.ts +165 -154
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/ingest-message.write.ts +1 -2
- package/packages/bundled-features/src/inbound-mail-foundation/index.ts +1 -1
- package/packages/bundled-features/src/inbound-mail-foundation/oauth-access-token.ts +5 -2
- package/packages/bundled-features/src/inbound-mail-foundation/projection.ts +3 -2
- package/packages/bundled-features/src/inbound-mail-foundation/watch-supervisor.ts +1 -1
- package/packages/bundled-features/src/inbound-provider-imap/feature.ts +22 -13
- package/packages/bundled-features/src/inbound-provider-imap/index.ts +6 -1
- package/packages/bundled-features/src/inbound-provider-inmemory/feature.ts +20 -12
- package/packages/bundled-features/src/inbound-provider-inmemory/index.ts +1 -0
- package/packages/bundled-features/src/jobs/db/queries/retention.ts +1 -1
- package/packages/bundled-features/src/jobs/db/queries/stale-run-sweep.ts +1 -1
- package/packages/bundled-features/src/jobs/handlers/detail.query.ts +1 -1
- package/packages/bundled-features/src/jobs/handlers/list.query.ts +7 -2
- package/packages/bundled-features/src/jobs/handlers/retry.write.ts +1 -1
- package/packages/bundled-features/src/jobs/handlers/tenant-failures.query.ts +1 -1
- package/packages/bundled-features/src/jobs/handlers/tenant-runs.query.ts +1 -1
- package/packages/bundled-features/src/jobs/job-run-logger.ts +11 -10
- package/packages/bundled-features/src/jobs/tenant-job-failure-table.ts +1 -1
- package/packages/bundled-features/src/jobs/tenant-job-run-table.ts +1 -1
- package/packages/bundled-features/src/ledger/feature.ts +6 -3
- package/packages/bundled-features/src/mail-foundation/feature.ts +107 -55
- package/packages/bundled-features/src/mail-foundation/index.ts +4 -0
- package/packages/bundled-features/src/mail-transport-inmemory/feature.ts +25 -17
- package/packages/bundled-features/src/mail-transport-inmemory/index.ts +6 -1
- package/packages/bundled-features/src/mail-transport-smtp/feature.ts +91 -79
- package/packages/bundled-features/src/mail-transport-smtp/index.ts +1 -0
- package/packages/bundled-features/src/managed-pages/handlers/by-slug.query.ts +1 -1
- package/packages/bundled-features/src/managed-pages/handlers/by-tenant-published.query.ts +1 -2
- package/packages/bundled-features/src/managed-pages/handlers/set.write.ts +1 -2
- package/packages/bundled-features/src/managed-pages/seeding.ts +8 -4
- package/packages/bundled-features/src/metrics/compute.ts +1 -1
- package/packages/bundled-features/src/metrics/filters.ts +1 -1
- package/packages/bundled-features/src/metrics/validate.ts +1 -1
- package/packages/bundled-features/src/notes-history/feature.ts +6 -3
- package/packages/bundled-features/src/notes-history/handlers/add-note.write.ts +1 -1
- package/packages/bundled-features/src/notes-history-user-data/hooks.ts +1 -1
- package/packages/bundled-features/src/notes-history-user-data/index.ts +27 -18
- package/packages/bundled-features/src/personal-access-tokens/changes.json +6 -0
- package/packages/bundled-features/src/personal-access-tokens/feature.ts +17 -2
- package/packages/bundled-features/src/personal-access-tokens/handlers/create.write.ts +1 -1
- package/packages/bundled-features/src/personal-access-tokens/handlers/list.query.ts +2 -2
- package/packages/bundled-features/src/personal-access-tokens/handlers/revoke.write.ts +1 -1
- package/packages/bundled-features/src/personal-access-tokens/resolver.ts +1 -1
- package/packages/bundled-features/src/personal-access-tokens/revoke-for-user.ts +2 -2
- package/packages/bundled-features/src/personal-access-tokens/roles.ts +8 -6
- package/packages/bundled-features/src/personal-access-tokens/screens.ts +2 -0
- package/packages/bundled-features/src/readiness/feature.ts +25 -16
- package/packages/bundled-features/src/readiness/index.ts +1 -1
- package/packages/bundled-features/src/secrets/db/queries/read.ts +1 -1
- package/packages/bundled-features/src/secrets/feature.ts +8 -3
- package/packages/bundled-features/src/secrets/handlers/rotate.job.ts +2 -2
- package/packages/bundled-features/src/secrets/secrets-context.ts +4 -3
- package/packages/bundled-features/src/sessions/db/queries/cleanup.ts +1 -1
- package/packages/bundled-features/src/sessions/handlers/detail.query.ts +1 -1
- package/packages/bundled-features/src/sessions/handlers/list.query.ts +2 -2
- package/packages/bundled-features/src/sessions/handlers/mine.query.ts +1 -1
- package/packages/bundled-features/src/sessions/handlers/revoke-all-for-user.write.ts +1 -1
- package/packages/bundled-features/src/sessions/handlers/revoke-all-others.write.ts +1 -1
- package/packages/bundled-features/src/sessions/handlers/revoke.write.ts +1 -1
- package/packages/bundled-features/src/sessions/session-callbacks.ts +14 -7
- package/packages/bundled-features/src/sessions/testing.ts +1 -1
- package/packages/bundled-features/src/tags/feature.ts +6 -3
- package/packages/bundled-features/src/template-resolver/api.ts +1 -1
- package/packages/bundled-features/src/template-resolver/changes.json +25 -0
- package/packages/bundled-features/src/template-resolver/compile-document-body.ts +61 -9
- package/packages/bundled-features/src/template-resolver/document-sanitizer.ts +19 -0
- package/packages/bundled-features/src/template-resolver/document-schema.ts +33 -0
- package/packages/bundled-features/src/template-resolver/handlers/bundle-import.ts +10 -2
- package/packages/bundled-features/src/template-resolver/handlers/by-slug.query.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/by-tenant.query.ts +1 -2
- package/packages/bundled-features/src/template-resolver/handlers/collection-item.query.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/collection-list.query.ts +1 -2
- package/packages/bundled-features/src/template-resolver/handlers/collection-set.write.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/copy-locale.write.ts +9 -3
- package/packages/bundled-features/src/template-resolver/handlers/diff-to-system.query.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/export-bundle.query.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/find-by-id.query.ts +9 -2
- package/packages/bundled-features/src/template-resolver/handlers/layout-source.query.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/list.query.ts +7 -2
- package/packages/bundled-features/src/template-resolver/handlers/overview.query.ts +8 -3
- package/packages/bundled-features/src/template-resolver/handlers/reset-to-system.write.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/resource-remove.write.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/set.write.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/template-write.ts +22 -2
- package/packages/bundled-features/src/template-resolver/handlers/tenant-overrides.query.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/toggle-status.write.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/usage.query.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/validate.query.ts +1 -1
- package/packages/bundled-features/src/template-resolver/index.ts +4 -0
- package/packages/bundled-features/src/template-resolver/qualified-names.ts +1 -0
- package/packages/bundled-features/src/template-resolver/seeding.ts +57 -10
- package/packages/bundled-features/src/template-resolver/store-template-resource.ts +1 -1
- package/packages/bundled-features/src/template-resolver/template-preview.ts +3 -1
- package/packages/bundled-features/src/template-resolver/template-resources.ts +1 -1
- package/packages/bundled-features/src/template-resolver/template-system-only.ts +21 -0
- package/packages/bundled-features/src/template-resolver/template-validation.ts +48 -24
- package/packages/bundled-features/src/template-resolver/testing.ts +1 -1
- package/packages/bundled-features/src/template-resolver/web/i18n.ts +2 -0
- package/packages/bundled-features/src/template-resolver-user-data/index.ts +23 -14
- package/packages/bundled-features/src/tenant/handlers/active-tenant-ids.query.ts +1 -1
- package/packages/bundled-features/src/tenant/handlers/add-member.write.ts +1 -2
- package/packages/bundled-features/src/tenant/handlers/cancel-invitation.write.ts +1 -1
- package/packages/bundled-features/src/tenant/handlers/invitations.query.ts +1 -1
- package/packages/bundled-features/src/tenant/handlers/me.query.ts +1 -1
- package/packages/bundled-features/src/tenant/handlers/member-directory.query.ts +1 -1
- package/packages/bundled-features/src/tenant/handlers/members.query.ts +1 -1
- package/packages/bundled-features/src/tenant/handlers/memberships.query.ts +1 -1
- package/packages/bundled-features/src/tenant/handlers/remove-member.write.ts +2 -1
- package/packages/bundled-features/src/tenant/handlers/resolve-user-ids.query.ts +1 -1
- package/packages/bundled-features/src/tenant/handlers/team-list.query.ts +1 -1
- package/packages/bundled-features/src/tenant/handlers/tenant-directory.query.ts +1 -1
- package/packages/bundled-features/src/tenant/handlers/update-member-roles.write.ts +1 -2
- package/packages/bundled-features/src/tenant/invited-membership.ts +2 -2
- package/packages/bundled-features/src/tenant/last-tenant-admin.ts +1 -2
- package/packages/bundled-features/src/tenant/seeding.ts +12 -12
- package/packages/bundled-features/src/tenant-lifecycle/handlers/cancel-destruction.write.ts +1 -2
- package/packages/bundled-features/src/tenant-lifecycle/handlers/request-destruction.write.ts +1 -2
- package/packages/bundled-features/src/tenant-lifecycle/lib/revoke-tenant-sessions.ts +1 -1
- package/packages/bundled-features/src/tenant-lifecycle/lifecycle-gate.ts +1 -1
- package/packages/bundled-features/src/tenant-lifecycle/run-tenant-destroy.ts +3 -3
- package/packages/bundled-features/src/tenant-lifecycle/stages.ts +10 -5
- package/packages/bundled-features/src/tenant-lifecycle/testing.ts +3 -3
- package/packages/bundled-features/src/tenant-settings/feature.ts +34 -29
- package/packages/bundled-features/src/tier-engine/feature.ts +426 -428
- package/packages/bundled-features/src/tier-engine/handlers/get-tenant-tier.query.ts +2 -3
- package/packages/bundled-features/src/tier-engine/handlers/set-tenant-tier.write.ts +5 -2
- package/packages/bundled-features/src/user/changes.json +6 -0
- package/packages/bundled-features/src/user/db/queries/stream-tenant-backfill.ts +1 -1
- package/packages/bundled-features/src/user/handlers/create.write.ts +1 -2
- package/packages/bundled-features/src/user/handlers/find-for-auth.query.ts +1 -1
- package/packages/bundled-features/src/user/handlers/list.query.ts +1 -1
- package/packages/bundled-features/src/user/handlers/update-roles.ts +2 -1
- package/packages/bundled-features/src/user/index.ts +5 -1
- package/packages/bundled-features/src/user/invited-global-roles.ts +2 -2
- package/packages/bundled-features/src/user/principal-status.ts +13 -3
- package/packages/bundled-features/src/user/resolve-display-names.ts +1 -1
- package/packages/bundled-features/src/user/seeding.ts +5 -5
- package/packages/bundled-features/src/user-data-rights/audit-download.ts +2 -2
- package/packages/bundled-features/src/user-data-rights/changes.json +6 -0
- package/packages/bundled-features/src/user-data-rights/db/queries/export-jobs.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/db/queries/forget-cleanup.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/handlers/download-by-job.query.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/handlers/download-by-token.query.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/handlers/export-status.query.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/handlers/list-download-attempts.query.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/handlers/my-audit-log.query.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/handlers/request-export.write.ts +1 -2
- package/packages/bundled-features/src/user-data-rights/handlers/run-forget-cleanup.write.ts +3 -3
- package/packages/bundled-features/src/user-data-rights/lib/deny-if-target-outside-admin-tenant.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/lib/update-user-lifecycle.ts +7 -2
- package/packages/bundled-features/src/user-data-rights/run-export-jobs.ts +7 -3
- package/packages/bundled-features/src/user-data-rights/run-forget-cleanup.ts +11 -5
- package/packages/bundled-features/src/user-data-rights/run-user-export.ts +10 -5
- package/packages/bundled-features/src/waitlist/handlers/invite.write.ts +1 -2
- package/packages/bundled-features/src/waitlist/handlers/reject.write.ts +1 -1
- package/packages/bundled-features/src/waitlist/lib.ts +5 -2
- package/packages/bundled-features/src/workflow-runner/event-subscriber.ts +1 -1
- package/packages/bundled-features/src/workflow-runner/feature.ts +58 -47
- package/packages/bundled-features/src/workflow-runner/handlers/resume-run.write.ts +1 -1
- package/packages/bundled-features/src/workflow-runner/index.ts +1 -1
- package/packages/bundled-features/src/workflow-runner/pending-projection.ts +1 -1
- package/samples/apps/admin-console/src/run-config.ts +2 -2
- package/samples/apps/cap-billing-demo/package.json +3 -0
- package/samples/apps/cap-billing-demo/src/feature.ts +2 -2
- package/samples/apps/cap-billing-demo/src/run-config.ts +8 -8
- package/samples/apps/marketing-demo/src/app/seed.ts +1 -1
- package/samples/apps/marketing-demo/src/db/queries/seed-counts.ts +1 -1
- package/samples/apps/showcase/package.json +3 -0
- package/samples/apps/showcase/src/app/seed-items.ts +1 -1
- package/samples/apps/styleguide/src/app/seed.ts +2 -2
- package/samples/apps/styleguide/src/features/ai-settings/seed.ts +2 -2
- package/samples/apps/ui-walkthrough/scripts/emit-e2e-data.ts +1 -1
- package/samples/apps/ui-walkthrough/src/app/auth-constants.ts +1 -1
- package/samples/apps/ui-walkthrough/src/app/seed-rental.ts +2 -2
- package/samples/apps/ui-walkthrough/src/app/seed-templates.ts +2 -0
- package/samples/apps/ui-walkthrough/src/app/seed-vehicles.ts +1 -1
- package/samples/apps/ui-walkthrough/src/app/seed.ts +1 -1
- package/samples/apps/ui-walkthrough/src/app/template-seed-data.ts +12 -0
- package/samples/apps/ui-walkthrough/src/db/queries/row-counts.ts +1 -1
- package/samples/apps/ui-walkthrough/src/db/queries/task-counts.ts +1 -1
- package/samples/apps/ui-walkthrough/src/features/billing/feature.ts +7 -0
- package/samples/apps/ui-walkthrough/src/features/billing/i18n.ts +2 -0
- package/samples/apps/use-all-bundled/feature-manifest.json +4 -4
- package/samples/apps/use-all-bundled/package.json +4 -0
- package/samples/apps/use-all-bundled/scripts/check-coverage.ts +2 -2
- package/samples/apps/use-all-bundled/src/app/auth-constants.ts +1 -1
- package/samples/apps/use-all-bundled/src/app/cap-overview-caps.ts +2 -2
- package/samples/apps/use-all-bundled/src/app/dev-app-options.ts +1 -1
- package/samples/apps/use-all-bundled/src/app/seed-documents.ts +1 -1
- package/samples/apps/use-all-bundled/src/app/seed.ts +11 -5
- package/samples/apps/use-all-bundled/src/run-config.ts +55 -56
- package/samples/apps/user-data-rights-demo/README.md +2 -2
- package/samples/apps/user-data-rights-demo/package.json +3 -0
- package/samples/apps/user-data-rights-demo/src/run-config.ts +7 -7
- package/samples/apps/workspaces/package.json +3 -0
- package/samples/recipes/access-control/package.json +3 -0
- package/samples/recipes/anonymous-access/package.json +3 -0
- package/samples/recipes/anonymous-access-multitenant/package.json +3 -0
- package/samples/recipes/apex-landing/package.json +1 -0
- package/samples/recipes/apex-surface-auth/package.json +3 -0
- package/samples/recipes/apex-surface-auth/src/feature.ts +2 -2
- package/samples/recipes/api-worker-split/package.json +3 -0
- package/samples/recipes/api-worker-split/src/feature.ts +1 -2
- package/samples/recipes/auth-claims/package.json +3 -0
- package/samples/recipes/auth-foundation-providers/src/feature.ts +1 -1
- package/samples/recipes/auth-mfa/package.json +3 -0
- package/samples/recipes/basic-entity/package.json +3 -0
- package/samples/recipes/chat-channels/package.json +3 -0
- package/samples/recipes/compliance-profiles-demo/package.json +3 -0
- package/samples/recipes/cross-feature-events/package.json +3 -1
- package/samples/recipes/cross-feature-events/src/feature.ts +1 -1
- package/samples/recipes/crypto-shredding-hr/package.json +3 -0
- package/samples/recipes/currencies-global/package.json +3 -0
- package/samples/recipes/currencies-per-tenant/package.json +3 -0
- package/samples/recipes/custom-fields-basic/package.json +3 -0
- package/samples/recipes/custom-handlers/package.json +3 -0
- package/samples/recipes/dashboard-stats/package.json +3 -0
- package/samples/recipes/delivery-notifications/package.json +3 -0
- package/samples/recipes/e2e-generator/package.json +3 -0
- package/samples/recipes/embedded/package.json +3 -0
- package/samples/recipes/embedded-entity-form/package.json +1 -0
- package/samples/recipes/encrypted-tenant-config/README.md +1 -1
- package/samples/recipes/encrypted-tenant-config/package.json +3 -0
- package/samples/recipes/error-contract/package.json +3 -0
- package/samples/recipes/event-sourcing/package.json +3 -1
- package/samples/recipes/event-sourcing/src/feature.ts +16 -20
- package/samples/recipes/event-sourcing/tsconfig.json +2 -6
- package/samples/recipes/feature-toggles/package.json +3 -0
- package/samples/recipes/field-access/package.json +3 -0
- package/samples/recipes/files-post-processing/package.json +1 -0
- package/samples/recipes/golden-path/README.md +30 -0
- package/samples/recipes/golden-path/package.json +11 -0
- package/samples/recipes/golden-path/src/feature.ts +70 -0
- package/samples/recipes/idempotency/package.json +3 -0
- package/samples/recipes/inbound-mail-triage/package.json +3 -0
- package/samples/recipes/lane-routing/package.json +3 -0
- package/samples/recipes/ledger-banking/package.json +3 -0
- package/samples/recipes/ledger-invoicing/package.json +3 -0
- package/samples/recipes/legal-pages/package.json +3 -0
- package/samples/recipes/lifecycle-hooks/package.json +3 -0
- package/samples/recipes/managed-config/package.json +3 -0
- package/samples/recipes/managed-pages/package.json +3 -0
- package/samples/recipes/notes-history-basic/package.json +3 -0
- package/samples/recipes/ownership/package.json +3 -0
- package/samples/recipes/pdf-audit-export/package.json +1 -0
- package/samples/recipes/pipeline-basics/package.json +3 -0
- package/samples/recipes/public-share-token/package.json +3 -0
- package/samples/recipes/public-share-token/src/feature.ts +1 -1
- package/samples/recipes/rate-limiting/package.json +3 -0
- package/samples/recipes/realtime-sse/package.json +3 -0
- package/samples/recipes/record-detail-layout/package.json +1 -0
- package/samples/recipes/reference-data/package.json +3 -0
- package/samples/recipes/relations/package.json +3 -0
- package/samples/recipes/screens-nav/package.json +3 -0
- package/samples/recipes/search/package.json +3 -0
- package/samples/recipes/secrets-demo/package.json +3 -0
- package/samples/recipes/security-baseline/src/feature.ts +2 -2
- package/samples/recipes/session-revocation/README.md +1 -1
- package/samples/recipes/session-revocation/package.json +3 -0
- package/samples/recipes/session-revocation/src/feature.ts +1 -1
- package/samples/recipes/state-machine/package.json +3 -1
- package/samples/recipes/state-machine/src/entities/invoice.ts +2 -2
- package/samples/recipes/state-machine/src/events.ts +19 -0
- package/samples/recipes/state-machine/src/feature.ts +25 -30
- package/samples/recipes/state-machine/src/handlers/_helpers.ts +13 -14
- package/samples/recipes/state-machine/src/handlers/create.ts +1 -1
- package/samples/recipes/state-machine/src/handlers/transitions.ts +129 -122
- package/samples/recipes/state-machine/src/reducer.ts +1 -1
- package/samples/recipes/state-machine/tsconfig.json +2 -6
- package/samples/recipes/tags-basic/package.json +3 -0
- package/samples/recipes/tenant-isolation/package.json +3 -0
- package/samples/recipes/tenant-settings/package.json +3 -0
- package/samples/recipes/tier-admin/package.json +3 -0
- package/samples/recipes/timezones/package.json +3 -0
- package/samples/recipes/tsconfig.base.json +1 -1
- package/samples/recipes/user-data-rights/package.json +3 -0
- package/samples/recipes/user-data-rights/src/feature.ts +6 -2
- package/samples/recipes/user-profile/package.json +3 -0
- package/samples/recipes/user-profile/src/feature.ts +2 -2
- package/samples/recipes/webhook-step/package.json +3 -0
- package/samples/recipes/wizard-form/package.json +1 -0
- package/samples/recipes/workflow-engine/package.json +3 -0
- package/samples/recipes/workflow-engine/src/db/queries/suspended-runs.ts +5 -2
- package/samples/recipes/writeform-section/package.json +1 -0
- package/packages/bundled-features/src/file-provider-s3-env/feature.ts +0 -58
- /package/packages/bundled-features/src/{files-provider-s3 → file-provider-s3/lib}/env-helper.ts +0 -0
|
@@ -3,8 +3,9 @@ import { isOneOf } from "@cosmicdrift/kumiko-types/type-guards";
|
|
|
3
3
|
import type { Element as ScanElement } from "happy-dom";
|
|
4
4
|
import { isResourceImageContentType } from "../shared/index.js";
|
|
5
5
|
import { rewriteStepsBlock } from "./compile-steps-block.js";
|
|
6
|
-
import { withParsedDocument } from "./document-sanitizer.js";
|
|
6
|
+
import { conditionScopeElement, withParsedDocument } from "./document-sanitizer.js";
|
|
7
7
|
import {
|
|
8
|
+
DOCUMENT_CONDITION_ATTRIBUTE,
|
|
8
9
|
DOCUMENT_TEXT_ALIGNMENTS,
|
|
9
10
|
isAllowedDocumentLinkHref,
|
|
10
11
|
isDocumentPlaceholderHref,
|
|
@@ -25,6 +26,8 @@ type RowScope = { readonly listName: string; readonly itemFields: TemplateVariab
|
|
|
25
26
|
type CompileState = {
|
|
26
27
|
readonly variables: TemplateVariables;
|
|
27
28
|
readonly expressions: string[];
|
|
29
|
+
// richText spans that fill a whole block; their value brings its own paragraphs.
|
|
30
|
+
readonly blockRichTextSpans: Set<ScanElement>;
|
|
28
31
|
};
|
|
29
32
|
|
|
30
33
|
function marker(state: CompileState, expression: string): string {
|
|
@@ -59,10 +62,19 @@ function resolveReference(
|
|
|
59
62
|
return { path: scope === null ? name : `@root.${name}`, def: ownVariable(variables, name) };
|
|
60
63
|
}
|
|
61
64
|
|
|
62
|
-
|
|
65
|
+
// The sanitized rich text value always consists of blocks; inside a line of
|
|
66
|
+
// other text it renders inline so no paragraph ends up inside a paragraph.
|
|
67
|
+
function valueExpression(
|
|
68
|
+
path: string,
|
|
69
|
+
def: TemplateVariableDef | undefined,
|
|
70
|
+
isWholeBlock: boolean,
|
|
71
|
+
): string {
|
|
63
72
|
if (def?.type === "money") return `{{money ${path}}}`;
|
|
64
73
|
if (def?.type === "date") return `{{date ${path}}}`;
|
|
65
|
-
if (def?.type === "
|
|
74
|
+
if (def?.type === "percent") return `{{percent ${path}}}`;
|
|
75
|
+
if (def?.type === "richText") {
|
|
76
|
+
return isWholeBlock ? `{{richText ${path}}}` : `{{richText ${path} inline=true}}`;
|
|
77
|
+
}
|
|
66
78
|
return `{{${path}}}`;
|
|
67
79
|
}
|
|
68
80
|
|
|
@@ -70,7 +82,13 @@ function rewriteVariable(element: ScanElement, state: CompileState): void {
|
|
|
70
82
|
const name = element.getAttribute("data-variable") ?? "";
|
|
71
83
|
const replacement = element.ownerDocument.createTextNode(
|
|
72
84
|
isDocumentReferenceName(name)
|
|
73
|
-
? marker(
|
|
85
|
+
? marker(
|
|
86
|
+
state,
|
|
87
|
+
valueExpression(
|
|
88
|
+
...pathAndDef(name, element, state),
|
|
89
|
+
state.blockRichTextSpans.has(element),
|
|
90
|
+
),
|
|
91
|
+
)
|
|
74
92
|
: "",
|
|
75
93
|
);
|
|
76
94
|
element.replaceWith(replacement);
|
|
@@ -112,10 +130,27 @@ function wrapVariableOnlyBlock(block: ScanElement, state: CompileState): void {
|
|
|
112
130
|
const name = soleVariableName(block);
|
|
113
131
|
// skip: a line with static content or several placeholders stays as it is
|
|
114
132
|
if (name === null) return;
|
|
115
|
-
const [path] = pathAndDef(name, block, state);
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
133
|
+
const [path, def] = pathAndDef(name, block, state);
|
|
134
|
+
const host =
|
|
135
|
+
def?.type === "richText" && block.tagName === "P" ? richTextBlockHost(block, state) : block;
|
|
136
|
+
const document = host.ownerDocument;
|
|
137
|
+
host.before(document.createTextNode(marker(state, `{{#if ${path} includeZero=true}}`)));
|
|
138
|
+
host.after(document.createTextNode(marker(state, "{{/if}}")));
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// A paragraph cannot hold the paragraphs of a rich text value, a div can; it
|
|
142
|
+
// keeps the paragraph's attributes so alignment and size still apply.
|
|
143
|
+
function richTextBlockHost(paragraph: ScanElement, state: CompileState): ScanElement {
|
|
144
|
+
const host = paragraph.ownerDocument.createElement("div");
|
|
145
|
+
for (const attribute of Array.from(paragraph.attributes)) {
|
|
146
|
+
host.setAttribute(attribute.name, attribute.value ?? "");
|
|
147
|
+
}
|
|
148
|
+
for (const span of Array.from(paragraph.querySelectorAll("span[data-variable]"))) {
|
|
149
|
+
state.blockRichTextSpans.add(span);
|
|
150
|
+
}
|
|
151
|
+
host.append(...Array.from(paragraph.childNodes));
|
|
152
|
+
paragraph.replaceWith(host);
|
|
153
|
+
return host;
|
|
119
154
|
}
|
|
120
155
|
|
|
121
156
|
function rewriteLink(element: ScanElement, state: CompileState): void {
|
|
@@ -146,6 +181,20 @@ function rewriteRepeatRow(row: ScanElement, state: CompileState): void {
|
|
|
146
181
|
}
|
|
147
182
|
}
|
|
148
183
|
|
|
184
|
+
function rewriteConditionalBlock(block: ScanElement, state: CompileState): void {
|
|
185
|
+
const name = block.getAttribute(DOCUMENT_CONDITION_ATTRIBUTE) ?? "";
|
|
186
|
+
block.removeAttribute(DOCUMENT_CONDITION_ATTRIBUTE);
|
|
187
|
+
if (!isDocumentReferenceName(name)) {
|
|
188
|
+
block.remove();
|
|
189
|
+
// skip: a condition on a name that cannot be a variable never shows
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
const [path] = pathAndDef(name, conditionScopeElement(block), state);
|
|
193
|
+
const document = block.ownerDocument;
|
|
194
|
+
block.before(document.createTextNode(marker(state, `{{#if ${path} includeZero=true}}`)));
|
|
195
|
+
block.after(document.createTextNode(marker(state, "{{/if}}")));
|
|
196
|
+
}
|
|
197
|
+
|
|
149
198
|
function stripActiveContent(element: ScanElement): void {
|
|
150
199
|
for (const attribute of Array.from(element.attributes)) {
|
|
151
200
|
if (/^on/i.test(attribute.name)) element.removeAttribute(attribute.name);
|
|
@@ -311,7 +360,7 @@ export function compileDocumentBodyToHandlebars(
|
|
|
311
360
|
variables: TemplateVariables,
|
|
312
361
|
options: CompileDocumentBodyOptions = {},
|
|
313
362
|
): string {
|
|
314
|
-
const state: CompileState = { variables, expressions: [] };
|
|
363
|
+
const state: CompileState = { variables, expressions: [], blockRichTextSpans: new Set() };
|
|
315
364
|
const scrubbed = html.replaceAll(EXPRESSION_OPEN, "").replaceAll(EXPRESSION_CLOSE, "");
|
|
316
365
|
const compiled = withParsedDocument(scrubbed, (root) => {
|
|
317
366
|
stripScriptsAndActiveContent(root, options);
|
|
@@ -325,6 +374,9 @@ export function compileDocumentBodyToHandlebars(
|
|
|
325
374
|
color: options.stepsColor,
|
|
326
375
|
});
|
|
327
376
|
}
|
|
377
|
+
for (const block of Array.from(root.querySelectorAll(`[${DOCUMENT_CONDITION_ATTRIBUTE}]`))) {
|
|
378
|
+
rewriteConditionalBlock(block, state);
|
|
379
|
+
}
|
|
328
380
|
for (const block of Array.from(root.querySelectorAll(VARIABLE_ONLY_BLOCK_SELECTOR))) {
|
|
329
381
|
wrapVariableOnlyBlock(block, state);
|
|
330
382
|
}
|
|
@@ -7,6 +7,7 @@ import { type Element as ScanElement, Window } from "happy-dom";
|
|
|
7
7
|
import type { ContentFormat } from "./constants.js";
|
|
8
8
|
import { DOCUMENT_HTML_KINDS } from "./constants.js";
|
|
9
9
|
import {
|
|
10
|
+
DOCUMENT_CONDITION_ATTRIBUTE,
|
|
10
11
|
documentExtensions,
|
|
11
12
|
isAllowedDocumentLinkHref,
|
|
12
13
|
isDocumentPlaceholderHref,
|
|
@@ -138,6 +139,7 @@ function scanImage(element: ScanElement, out: DocumentViolation[]): void {
|
|
|
138
139
|
const REFERENCE_ATTRIBUTES: ReadonlyArray<readonly [string, (value: string) => boolean]> = [
|
|
139
140
|
["data-variable", isDocumentReferenceName],
|
|
140
141
|
["data-each", isDocumentReferenceName],
|
|
142
|
+
[DOCUMENT_CONDITION_ATTRIBUTE, isDocumentReferenceName],
|
|
141
143
|
["data-resource", isDocumentResourceKey],
|
|
142
144
|
["data-steps", isDocumentReferenceName],
|
|
143
145
|
["data-step", isDocumentStepKey],
|
|
@@ -270,6 +272,17 @@ export function sanitizeDocumentHtml(html: string): SanitizeHtmlResult {
|
|
|
270
272
|
};
|
|
271
273
|
}
|
|
272
274
|
|
|
275
|
+
// For a sanitized value placed inside a line of text: paragraphs become line
|
|
276
|
+
// breaks. Other blocks (lists, headings) cannot be made inline and stay as they are.
|
|
277
|
+
export function flattenParagraphsToLineBreaks(sanitizedHtml: string): string {
|
|
278
|
+
return withParsedDocument(sanitizedHtml, (body) => {
|
|
279
|
+
const blocks = Array.from(body.children);
|
|
280
|
+
const isParagraphsOnly =
|
|
281
|
+
blocks.length === body.childNodes.length && blocks.every((block) => block.tagName === "P");
|
|
282
|
+
return isParagraphsOnly ? blocks.map((block) => block.innerHTML).join("<br>") : sanitizedHtml;
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
|
|
273
286
|
// Snippets accept any format, but their html is as untrusted as a mail body.
|
|
274
287
|
function isSanitizedHtmlKind(kind: string): boolean {
|
|
275
288
|
return kind === "snippet" || isOneOf(DOCUMENT_HTML_KINDS, kind);
|
|
@@ -336,3 +349,9 @@ export function documentViolationsToFieldIssues(
|
|
|
336
349
|
params: { detail: item.detail },
|
|
337
350
|
}));
|
|
338
351
|
}
|
|
352
|
+
|
|
353
|
+
// A repeat row's own data-if is decided per list, outside the row's item scope,
|
|
354
|
+
// because the compiled {{#if}} lands outside its {{#each}}.
|
|
355
|
+
export function conditionScopeElement(block: ScanElement): ScanElement {
|
|
356
|
+
return block.matches("tr[data-each]") ? (block.parentElement ?? block) : block;
|
|
357
|
+
}
|
|
@@ -314,6 +314,38 @@ export const DocumentTextSize = Extension.create({
|
|
|
314
314
|
},
|
|
315
315
|
});
|
|
316
316
|
|
|
317
|
+
// A block shown only when the named variable has a value (data-if, the
|
|
318
|
+
// conditional counterpart of data-each). Table rows qualify so an invoice can
|
|
319
|
+
// drop a discount line; tiptap merges the attribute into paragraph, heading
|
|
320
|
+
// and row markup only.
|
|
321
|
+
export const DOCUMENT_CONDITION_ATTRIBUTE = "data-if";
|
|
322
|
+
|
|
323
|
+
export const DocumentCondition = Extension.create({
|
|
324
|
+
name: "documentCondition",
|
|
325
|
+
addGlobalAttributes() {
|
|
326
|
+
return [
|
|
327
|
+
{
|
|
328
|
+
types: ["paragraph", "heading", "tableRow"],
|
|
329
|
+
attributes: {
|
|
330
|
+
showIf: {
|
|
331
|
+
default: null,
|
|
332
|
+
parseHTML: (element) => {
|
|
333
|
+
const name = element.getAttribute(DOCUMENT_CONDITION_ATTRIBUTE);
|
|
334
|
+
return name !== null && isDocumentReferenceName(name) ? name : null;
|
|
335
|
+
},
|
|
336
|
+
renderHTML: (attributes) => {
|
|
337
|
+
const name: unknown = attributes["showIf"];
|
|
338
|
+
return typeof name === "string" && isDocumentReferenceName(name)
|
|
339
|
+
? { [DOCUMENT_CONDITION_ATTRIBUTE]: name }
|
|
340
|
+
: {};
|
|
341
|
+
},
|
|
342
|
+
},
|
|
343
|
+
},
|
|
344
|
+
},
|
|
345
|
+
];
|
|
346
|
+
},
|
|
347
|
+
});
|
|
348
|
+
|
|
317
349
|
export const documentExtensions: Extensions = [
|
|
318
350
|
StarterKit.configure({
|
|
319
351
|
blockquote: false,
|
|
@@ -348,4 +380,5 @@ export const documentExtensions: Extensions = [
|
|
|
348
380
|
DocumentSteps,
|
|
349
381
|
DocumentTextAlign,
|
|
350
382
|
DocumentTextSize,
|
|
383
|
+
DocumentCondition,
|
|
351
384
|
];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { fetchOne } from "@cosmicdrift/kumiko-framework/
|
|
1
|
+
import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import type {
|
|
3
3
|
BeforeTransactionResult,
|
|
4
4
|
HandlerContext,
|
|
@@ -32,6 +32,7 @@ import { resolveTemplateVariables } from "../template-validation.js";
|
|
|
32
32
|
import { MAX_FILE_ATTACHMENTS_PER_TEMPLATE } from "./resource-shared.js";
|
|
33
33
|
import { evaluateTemplateWrite } from "./template-gates.js";
|
|
34
34
|
import {
|
|
35
|
+
refuseSystemOnlyTenantOverride,
|
|
35
36
|
refuseTenantScopeUnderSystemTenant,
|
|
36
37
|
type TemplateRowPayload,
|
|
37
38
|
writeTemplateRow,
|
|
@@ -113,7 +114,14 @@ function checkBundleAttachments(bundle: TemplateBundle): WriteResult<null> {
|
|
|
113
114
|
export async function prepareTemplateBundleBeforeTransaction(
|
|
114
115
|
args: BundleImport & { readonly status: BundleImportStatus },
|
|
115
116
|
): Promise<BeforeTransactionResult<PreparedBundleResources>> {
|
|
116
|
-
const refused =
|
|
117
|
+
const refused =
|
|
118
|
+
refuseTenantScopeUnderSystemTenant(args.scope, args.tenantId) ??
|
|
119
|
+
refuseSystemOnlyTenantOverride(
|
|
120
|
+
args.ctx.registry,
|
|
121
|
+
args.scope,
|
|
122
|
+
args.bundle.slug,
|
|
123
|
+
args.bundle.kind,
|
|
124
|
+
);
|
|
117
125
|
if (refused !== null) return refused;
|
|
118
126
|
const issues = await collectBundleIssues(args, args.status);
|
|
119
127
|
if (issues.length > 0) return writeFailure(new ValidationError({ fields: [...issues] }));
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { fetchOne } from "@cosmicdrift/kumiko-framework/
|
|
1
|
+
import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import * as z from "zod";
|
|
4
4
|
import { TEXT_BLOCK_KIND } from "../constants.js";
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { selectMany } from "@cosmicdrift/kumiko-framework/
|
|
2
|
-
import { castTenantRows } from "@cosmicdrift/kumiko-framework/db";
|
|
1
|
+
import { castTenantRows, selectMany } from "@cosmicdrift/kumiko-framework/db";
|
|
3
2
|
import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
|
|
4
3
|
import type { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
5
4
|
import * as z from "zod";
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { selectMany } from "@cosmicdrift/kumiko-framework/
|
|
2
|
-
import { castTenantRows } from "@cosmicdrift/kumiko-framework/db";
|
|
1
|
+
import { castTenantRows, selectMany } from "@cosmicdrift/kumiko-framework/db";
|
|
3
2
|
import {
|
|
4
3
|
type ContentCollectionDefinition,
|
|
5
4
|
defineQueryHandler,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { fetchOne } from "@cosmicdrift/kumiko-framework/
|
|
1
|
+
import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import {
|
|
3
3
|
defineWriteHandler,
|
|
4
4
|
type HandlerContext,
|
|
@@ -30,7 +30,11 @@ import { resolveTemplateVariables } from "../template-validation.js";
|
|
|
30
30
|
import { targetExistsIssue } from "./bundle-import.js";
|
|
31
31
|
import { kindSchema, localeSchema, templateSlugSchema } from "./shared.js";
|
|
32
32
|
import { parseStoredJson, storedRecord } from "./template-gates.js";
|
|
33
|
-
import {
|
|
33
|
+
import {
|
|
34
|
+
refuseSystemOnlyTenantOverride,
|
|
35
|
+
refuseTenantScopeUnderSystemTenant,
|
|
36
|
+
writeTemplateRow,
|
|
37
|
+
} from "./template-write.js";
|
|
34
38
|
|
|
35
39
|
type CopyScope = "tenant" | "system";
|
|
36
40
|
type WriteCtx = HandlerContext;
|
|
@@ -108,7 +112,9 @@ async function checkCopyRequest(
|
|
|
108
112
|
);
|
|
109
113
|
}
|
|
110
114
|
const tenantId = scope === "system" ? SYSTEM_TENANT_ID : event.user.tenantId;
|
|
111
|
-
const refused =
|
|
115
|
+
const refused =
|
|
116
|
+
refuseTenantScopeUnderSystemTenant(scope, tenantId) ??
|
|
117
|
+
refuseSystemOnlyTenantOverride(ctx.registry, scope, slug, kind);
|
|
112
118
|
if (refused !== null) return refused;
|
|
113
119
|
|
|
114
120
|
const readDb = readDbFor(ctx, scope);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { fetchOne } from "@cosmicdrift/kumiko-framework/
|
|
1
|
+
import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import { defineQueryHandler, SYSTEM_TENANT_ID } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import { NotFoundError } from "@cosmicdrift/kumiko-framework/errors";
|
|
4
4
|
import * as z from "zod";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isDeepStrictEqual } from "node:util";
|
|
2
|
-
import { selectMany } from "@cosmicdrift/kumiko-framework/
|
|
2
|
+
import { selectMany } from "@cosmicdrift/kumiko-framework/db";
|
|
3
3
|
import { defineQueryHandler, SYSTEM_TENANT_ID } from "@cosmicdrift/kumiko-framework/engine";
|
|
4
4
|
import { NotFoundError, ValidationError } from "@cosmicdrift/kumiko-framework/errors";
|
|
5
5
|
import * as z from "zod";
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { fetchOne } from "@cosmicdrift/kumiko-framework/
|
|
1
|
+
import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import * as z from "zod";
|
|
4
4
|
import { type TemplateResourceRow, templateResourcesTable } from "../table.js";
|
|
5
5
|
import { draftViewerTenantId, isHiddenSystemDraft, toWorkingRow } from "../template-draft.js";
|
|
6
|
+
import { isSystemOnlyTemplateHiddenFrom } from "../template-system-only.js";
|
|
6
7
|
|
|
7
8
|
// Admin-Lookup für UI-Edit-Flow. Returnt das raw Template inkl. draft/
|
|
8
9
|
// archived Status. Tenant-Isolation: User sieht nur Templates des
|
|
@@ -19,7 +20,13 @@ export const findByIdQuery = defineQueryHandler({
|
|
|
19
20
|
const stored = await fetchOne<TemplateResourceRow>(ctx.db, templateResourcesTable, {
|
|
20
21
|
id: query.payload.id,
|
|
21
22
|
});
|
|
22
|
-
if (
|
|
23
|
+
if (
|
|
24
|
+
!stored ||
|
|
25
|
+
isHiddenSystemDraft(query.user, stored) ||
|
|
26
|
+
isSystemOnlyTemplateHiddenFrom(query.user, ctx.registry, stored)
|
|
27
|
+
) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
23
30
|
const row = toWorkingRow(stored, draftViewerTenantId(query.user, stored));
|
|
24
31
|
const isOwnTenant = row.tenantId === query.user.tenantId;
|
|
25
32
|
const isSystemTemplate = row.scope === "system";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { selectMany } from "@cosmicdrift/kumiko-framework/
|
|
1
|
+
import { selectMany } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import * as z from "zod";
|
|
4
4
|
import { FALLBACK_LOCALE } from "../constants.js";
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { selectMany } from "@cosmicdrift/kumiko-framework/
|
|
1
|
+
import { selectMany } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import * as z from "zod";
|
|
4
4
|
import { TEMPLATE_KINDS, TEMPLATE_STATUSES } from "../constants.js";
|
|
5
5
|
import { type TemplateResourceRow, templateResourcesTable } from "../table.js";
|
|
6
6
|
import { isHiddenSystemDraft } from "../template-draft.js";
|
|
7
|
+
import { isSystemOnlyTemplateHiddenFrom } from "../template-system-only.js";
|
|
7
8
|
|
|
8
9
|
// ctx.db is tenant-scoped even for SystemAdmin: every caller sees its own
|
|
9
10
|
// tenant's rows plus the system defaults, never another tenant's rows.
|
|
@@ -45,7 +46,11 @@ export const listQuery = defineQueryHandler({
|
|
|
45
46
|
})) as TemplateResourceRow[];
|
|
46
47
|
|
|
47
48
|
return rows
|
|
48
|
-
.filter(
|
|
49
|
+
.filter(
|
|
50
|
+
(row) =>
|
|
51
|
+
!isHiddenSystemDraft(query.user, row) &&
|
|
52
|
+
!isSystemOnlyTemplateHiddenFrom(query.user, ctx.registry, row),
|
|
53
|
+
)
|
|
49
54
|
.map((row) => ({
|
|
50
55
|
id: String(row.id),
|
|
51
56
|
tenantId: row.tenantId,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { selectMany } from "@cosmicdrift/kumiko-framework/
|
|
1
|
+
import { selectMany } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import * as z from "zod";
|
|
4
4
|
import { DEFAULT_MAIL_LAYOUT_SLUG, FALLBACK_LOCALE, type TemplateStatus } from "../constants.js";
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
parseTemplateDraft,
|
|
12
12
|
servedVersionOf,
|
|
13
13
|
} from "../template-draft.js";
|
|
14
|
+
import { isSystemOnlyTemplateHiddenFrom } from "../template-system-only.js";
|
|
14
15
|
import { collectTemplateUsage, type EffectiveMailLayoutSlugs } from "../template-usage.js";
|
|
15
16
|
import { storedRecord } from "./template-gates.js";
|
|
16
17
|
|
|
@@ -284,7 +285,7 @@ export const overviewQuery = defineQueryHandler({
|
|
|
284
285
|
}),
|
|
285
286
|
access: { roles: ["TenantAdmin", "SystemAdmin"] },
|
|
286
287
|
description:
|
|
287
|
-
"Lists mail, PDF and layout templates as one row per slug and kind for the caller's tenant (optionally only the mails and PDFs using one layout slug): where the effective version comes from (own override or system), its locales, status and version (the served one; `draftVersion` is set when an unpublished draft waits beside it, `activeSince` says since when the served version applies), the system version it overrides, the layout it uses and which notifications or templates use it; use it to browse and filter all templates at a glance.",
|
|
288
|
+
"Lists mail, PDF and layout templates as one row per slug and kind for the caller's tenant (optionally only the mails and PDFs using one layout slug): where the effective version comes from (own override or system), its locales, status and version (the served one; `draftVersion` is set when an unpublished draft waits beside it, `activeSince` says since when the served version applies), the system version it overrides, the layout it uses and which notifications or templates use it; templates of notifications registered with `systemOnly` are listed for SystemAdmins only; use it to browse and filter all templates at a glance.",
|
|
288
289
|
handler: async (query, ctx) => {
|
|
289
290
|
const payload = query.payload;
|
|
290
291
|
const fetchedRows = await selectMany<TemplateResourceRow>(
|
|
@@ -301,7 +302,11 @@ export const overviewQuery = defineQueryHandler({
|
|
|
301
302
|
});
|
|
302
303
|
}
|
|
303
304
|
|
|
304
|
-
const visibleRows = rows.filter(
|
|
305
|
+
const visibleRows = rows.filter(
|
|
306
|
+
(row) =>
|
|
307
|
+
!isHiddenSystemDraft(query.user, row) &&
|
|
308
|
+
!isSystemOnlyTemplateHiddenFrom(query.user, ctx.registry, row),
|
|
309
|
+
);
|
|
305
310
|
const { drafts, layoutSlugByDocument } = buildDrafts(
|
|
306
311
|
groupBySlugAndKind(visibleRows),
|
|
307
312
|
query.user,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { fetchOne } from "@cosmicdrift/kumiko-framework/
|
|
1
|
+
import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import { defineWriteHandler, SYSTEM_TENANT_ID } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import { NotFoundError, ValidationError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
|
|
4
4
|
import * as z from "zod";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { fetchOne } from "@cosmicdrift/kumiko-framework/
|
|
1
|
+
import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import { defineWriteHandler } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import { NotFoundError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
|
|
4
4
|
import * as z from "zod";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { fetchOne } from "@cosmicdrift/kumiko-framework/
|
|
1
|
+
import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import {
|
|
3
3
|
type HandlerContext,
|
|
4
|
+
type Registry,
|
|
4
5
|
type SessionUser,
|
|
5
6
|
SYSTEM_TENANT_ID,
|
|
6
7
|
type TemplateVariables,
|
|
@@ -16,8 +17,10 @@ import {
|
|
|
16
17
|
import { requireForTenant } from "../../shared/index.js";
|
|
17
18
|
import type { ContentFormat, TemplateKind } from "../constants.js";
|
|
18
19
|
import type { TemplateWriteScope } from "../layout-regions.js";
|
|
20
|
+
import { TemplateResolverErrors } from "../qualified-names.js";
|
|
19
21
|
import { type TemplateResourceRow, templateResourcesTable } from "../table.js";
|
|
20
22
|
import { activationChanges, serializeTemplateDraft } from "../template-draft.js";
|
|
23
|
+
import { isSystemOnlyTemplate } from "../template-system-only.js";
|
|
21
24
|
import type { TemplateValidation } from "../template-validation.js";
|
|
22
25
|
import { executor } from "./shared.js";
|
|
23
26
|
import {
|
|
@@ -71,6 +74,21 @@ export function refuseTenantScopeUnderSystemTenant(
|
|
|
71
74
|
);
|
|
72
75
|
}
|
|
73
76
|
|
|
77
|
+
export function refuseSystemOnlyTenantOverride(
|
|
78
|
+
registry: Registry,
|
|
79
|
+
scope: TemplateWriteScope,
|
|
80
|
+
slug: string,
|
|
81
|
+
kind: string,
|
|
82
|
+
): WriteFailure | null {
|
|
83
|
+
if (scope !== "tenant" || !isSystemOnlyTemplate(registry, slug, kind)) return null;
|
|
84
|
+
return writeFailure(
|
|
85
|
+
new AccessDeniedError({
|
|
86
|
+
i18nKey: "templateResolver.errors.systemOnlyTemplate",
|
|
87
|
+
details: { reason: TemplateResolverErrors.systemOnlyTemplate },
|
|
88
|
+
}),
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
74
92
|
export type GatedTemplateWrite =
|
|
75
93
|
| { readonly ok: true; readonly evaluated: Extract<TemplateWriteResult, { ok: true }> }
|
|
76
94
|
| { readonly ok: false; readonly failure: WriteFailure };
|
|
@@ -141,7 +159,9 @@ export async function writeTemplateRow(
|
|
|
141
159
|
args: TemplateRowWrite,
|
|
142
160
|
): Promise<WriteResult<WrittenTemplateRow>> {
|
|
143
161
|
const { ctx, user, tenantId, scope, status, payload } = args;
|
|
144
|
-
const refused =
|
|
162
|
+
const refused =
|
|
163
|
+
refuseTenantScopeUnderSystemTenant(scope, tenantId) ??
|
|
164
|
+
refuseSystemOnlyTenantOverride(ctx.registry, scope, payload.slug, payload.kind);
|
|
145
165
|
if (refused !== null) return refused;
|
|
146
166
|
const { db, streamTenantId } = requireForTenant(ctx, tenantId);
|
|
147
167
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { selectMany } from "@cosmicdrift/kumiko-framework/
|
|
1
|
+
import { selectMany } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import { defineQueryHandler, SYSTEM_TENANT_ID } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import * as z from "zod";
|
|
4
4
|
import { TenantQueries } from "../../tenant/index.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { selectMany } from "@cosmicdrift/kumiko-framework/
|
|
1
|
+
import { selectMany } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import * as z from "zod";
|
|
4
4
|
import { TEMPLATE_KINDS } from "../constants.js";
|
|
@@ -46,15 +46,18 @@ export {
|
|
|
46
46
|
type DocumentViolation,
|
|
47
47
|
type DocumentViolationCode,
|
|
48
48
|
documentViolationsToFieldIssues,
|
|
49
|
+
flattenParagraphsToLineBreaks,
|
|
49
50
|
type SanitizeBodyResult,
|
|
50
51
|
type SanitizeHtmlResult,
|
|
51
52
|
sanitizeDocumentHtml,
|
|
52
53
|
sanitizeTemplateBody,
|
|
53
54
|
} from "./document-sanitizer.js";
|
|
54
55
|
export {
|
|
56
|
+
DOCUMENT_CONDITION_ATTRIBUTE,
|
|
55
57
|
DOCUMENT_NODE_NAMES,
|
|
56
58
|
DOCUMENT_TEXT_ALIGNMENTS,
|
|
57
59
|
DocumentButton,
|
|
60
|
+
DocumentCondition,
|
|
58
61
|
DocumentDivider,
|
|
59
62
|
DocumentLink,
|
|
60
63
|
DocumentPageBreak,
|
|
@@ -144,6 +147,7 @@ export {
|
|
|
144
147
|
} from "./template-meta.js";
|
|
145
148
|
export { type DocumentDraftOutcome, evaluateDocumentDraft } from "./template-preview.js";
|
|
146
149
|
export { readTemplateResource, type TemplateResourceFile } from "./template-resources.js";
|
|
150
|
+
export { isSystemOnlyTemplate } from "./template-system-only.js";
|
|
147
151
|
export { collectTemplateUsage, type TemplateUsageEntry } from "./template-usage.js";
|
|
148
152
|
export {
|
|
149
153
|
hasPlaceholderProblems,
|
|
@@ -60,6 +60,7 @@ export const TemplateResolverErrors = {
|
|
|
60
60
|
alreadyArchived: "template_already_archived",
|
|
61
61
|
targetExists: "target_exists",
|
|
62
62
|
systemResourcesNeedSystemTenant: "system_resources_need_system_tenant",
|
|
63
|
+
systemOnlyTemplate: "system_only_template",
|
|
63
64
|
bundleLocalesDiffer: "bundle_locales_differ",
|
|
64
65
|
resourceTooLarge: "template_resource_too_large",
|
|
65
66
|
resourceUnsupportedImage: "template_resource_unsupported_image",
|