@cosmicdrift/kumiko-samples 0.362.0 → 0.364.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 +23 -6
- package/packages/bundled-features/src/admin-shell/changes.json +6 -0
- package/packages/bundled-features/src/admin-shell/feature.ts +8 -1
- package/packages/bundled-features/src/agent-tools/agent-manifest.ts +3 -4
- package/packages/bundled-features/src/agent-tools/filter-ops.ts +1 -3
- package/packages/bundled-features/src/agent-tools/tool-catalog.ts +1 -3
- package/packages/bundled-features/src/agent-tools/tool-dispatch.ts +2 -1
- package/packages/bundled-features/src/audit/changes.json +6 -0
- package/packages/bundled-features/src/audit/handlers/list.query.ts +10 -5
- package/packages/bundled-features/src/auth-email-password/bootstrap.ts +29 -8
- package/packages/bundled-features/src/auth-email-password/changes.json +51 -0
- package/packages/bundled-features/src/auth-email-password/email-rate-limits.ts +16 -0
- package/packages/bundled-features/src/auth-email-password/email-templates.ts +12 -138
- package/packages/bundled-features/src/auth-email-password/feature.ts +30 -9
- package/packages/bundled-features/src/auth-email-password/handlers/change-password.write.ts +6 -2
- package/packages/bundled-features/src/auth-email-password/handlers/invite-create.write.ts +4 -5
- package/packages/bundled-features/src/auth-email-password/handlers/logout.write.ts +7 -2
- package/packages/bundled-features/src/auth-email-password/handlers/request-account-unlock.write.ts +2 -5
- package/packages/bundled-features/src/auth-email-password/handlers/request-email-verification.write.ts +2 -5
- package/packages/bundled-features/src/auth-email-password/handlers/request-password-reset.write.ts +2 -5
- package/packages/bundled-features/src/auth-email-password/handlers/signup-confirm.write.ts +3 -4
- package/packages/bundled-features/src/auth-email-password/handlers/signup-request.write.ts +2 -1
- package/packages/bundled-features/src/auth-email-password/handlers/token-request-handler.ts +5 -13
- package/packages/bundled-features/src/auth-email-password/index.ts +2 -17
- package/packages/bundled-features/src/auth-email-password/magic-link-mail.ts +30 -22
- package/packages/bundled-features/src/auth-email-password/mail-notifications.ts +158 -0
- package/packages/bundled-features/src/auth-email-password/signup-activation.ts +2 -3
- package/packages/bundled-features/src/auth-email-password/web/auth-gate.tsx +24 -5
- package/packages/bundled-features/src/auth-foundation/types.ts +8 -18
- package/packages/bundled-features/src/auth-mfa/feature.ts +8 -10
- package/packages/bundled-features/src/auth-mfa/hmac-token-codec.ts +4 -4
- package/packages/bundled-features/src/auth-mfa/mfa-challenge-token.ts +3 -3
- package/packages/bundled-features/src/auth-mfa/mfa-preauth-setup-token.ts +3 -3
- package/packages/bundled-features/src/auth-mfa/mfa-setup-token.ts +8 -8
- package/packages/bundled-features/src/billing-foundation/changes.json +43 -0
- package/packages/bundled-features/src/billing-foundation/constants.ts +5 -4
- package/packages/bundled-features/src/billing-foundation/consumer-protection/confirmation-mail.ts +90 -44
- package/packages/bundled-features/src/billing-foundation/consumer-protection/consent-gate.ts +22 -1
- package/packages/bundled-features/src/billing-foundation/consumer-protection/issue-confirmation.ts +3 -3
- package/packages/bundled-features/src/billing-foundation/consumer-protection/mail-notifications.ts +118 -0
- package/packages/bundled-features/src/billing-foundation/consumer-protection/register-consent.ts +2 -0
- package/packages/bundled-features/src/billing-foundation/consumer-protection/register-termination.ts +11 -1
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-mail.ts +39 -33
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-notify.ts +2 -2
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-pages.ts +1 -4
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-receipt-limit.ts +41 -0
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-record.ts +10 -1
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-request.ts +36 -20
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-texts.ts +9 -0
- package/packages/bundled-features/src/billing-foundation/consumer-protection/withdrawal-period.ts +35 -0
- package/packages/bundled-features/src/billing-foundation/get-subscription-for-tenant.ts +2 -2
- package/packages/bundled-features/src/billing-foundation/handlers/create-checkout-session.write.ts +11 -3
- package/packages/bundled-features/src/billing-foundation/handlers/create-portal-session.write.ts +4 -9
- package/packages/bundled-features/src/billing-foundation/handlers/list-subscriptions.query.ts +1 -1
- package/packages/bundled-features/src/billing-foundation/handlers/process-event.write.ts +12 -6
- package/packages/bundled-features/src/billing-foundation/handlers/process-payment-event.write.ts +1 -1
- package/packages/bundled-features/src/billing-foundation/i18n.ts +3 -0
- package/packages/bundled-features/src/billing-foundation/subscription-tier-sync.ts +20 -11
- package/packages/bundled-features/src/billing-foundation/types.ts +7 -2
- package/packages/bundled-features/src/cap-counter/calendar-cap-usage-reservation.ts +2 -0
- package/packages/bundled-features/src/cap-counter/changes.json +6 -0
- package/packages/bundled-features/src/cap-counter/enforce-cap.ts +75 -5
- package/packages/bundled-features/src/cap-counter/index.ts +1 -0
- package/packages/bundled-features/src/cap-counter/with-cap-enforcement.ts +3 -0
- package/packages/bundled-features/src/cap-overview/handlers/tenant-caps-list.query.ts +2 -1
- package/packages/bundled-features/src/cap-overview/web/cap-usage-cell.tsx +6 -4
- package/packages/bundled-features/src/channel-email/changes.json +19 -0
- package/packages/bundled-features/src/channel-email/email-channel.ts +135 -29
- package/packages/bundled-features/src/channel-email/feature.ts +6 -3
- package/packages/bundled-features/src/channel-email/index.ts +7 -1
- package/packages/bundled-features/src/channel-email/pii-guard.ts +13 -0
- package/packages/bundled-features/src/channel-email/smtp-transport.ts +15 -1
- package/packages/bundled-features/src/channel-email/types.ts +23 -0
- package/packages/bundled-features/src/channel-in-app/handlers/mark-read.write.ts +2 -2
- package/packages/bundled-features/src/config/changes.json +6 -0
- package/packages/bundled-features/src/config/handlers/set.write.ts +3 -7
- package/packages/bundled-features/src/config/resolver.ts +15 -12
- package/packages/bundled-features/src/config/write-helpers.ts +23 -0
- package/packages/bundled-features/src/crypto-shredding/changes.json +6 -0
- package/packages/bundled-features/src/crypto-shredding/handlers/forget-subject.write.ts +48 -27
- package/packages/bundled-features/src/custom-fields/changes.json +6 -0
- package/packages/bundled-features/src/custom-fields/db/queries/user-data-rights.ts +2 -2
- package/packages/bundled-features/src/custom-fields/handlers/update-tenant-field.write.ts +0 -1
- package/packages/bundled-features/src/custom-fields/lib/value-schema.ts +10 -11
- package/packages/bundled-features/src/custom-fields/wire-user-data-rights.ts +7 -6
- package/packages/bundled-features/src/data-retention/changes.json +6 -0
- package/packages/bundled-features/src/data-retention/index.ts +1 -0
- package/packages/bundled-features/src/data-retention/run-retention-cleanup.ts +8 -6
- package/packages/bundled-features/src/delivery/attachment-ref.ts +105 -0
- package/packages/bundled-features/src/delivery/changes.json +66 -0
- package/packages/bundled-features/src/delivery/channel-context.ts +152 -4
- package/packages/bundled-features/src/delivery/constants.ts +2 -0
- package/packages/bundled-features/src/delivery/delivery-service.ts +104 -26
- package/packages/bundled-features/src/delivery/feature.ts +1 -1
- package/packages/bundled-features/src/delivery/index.ts +19 -2
- package/packages/bundled-features/src/delivery/jobs.ts +97 -17
- package/packages/bundled-features/src/delivery/notify-factory.ts +14 -9
- package/packages/bundled-features/src/delivery/testing.ts +9 -1
- package/packages/bundled-features/src/delivery/types.ts +34 -18
- package/packages/bundled-features/src/delivery/unsubscribe.ts +5 -2
- package/packages/bundled-features/src/derivatives-sharp/render.ts +1 -22
- package/packages/bundled-features/src/document-ingest-foundation/pages.ts +6 -3
- package/packages/bundled-features/src/feature-toggles/toggle-sync-signal.ts +4 -4
- package/packages/bundled-features/src/file-derivatives/handlers/public-variant.query.ts +1 -1
- package/packages/bundled-features/src/file-foundation/changes.json +6 -0
- package/packages/bundled-features/src/file-foundation/index.ts +7 -0
- package/packages/bundled-features/src/file-foundation/read-file-ref-content.ts +89 -0
- package/packages/bundled-features/src/files-tenant-data/changes.json +6 -0
- package/packages/bundled-features/src/files-tenant-data/hooks.ts +4 -0
- package/packages/bundled-features/src/folders/web/folder-manager.tsx +5 -2
- package/packages/bundled-features/src/form-draft/db/queries/cleanup.ts +11 -11
- package/packages/bundled-features/src/form-draft/db/queries/draft-count.ts +2 -2
- package/packages/bundled-features/src/form-draft/db/queries/owned-file-refs.ts +2 -2
- package/packages/bundled-features/src/form-draft/release-file-refs.ts +3 -2
- package/packages/bundled-features/src/inbound-mail-foundation/changes.json +6 -0
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/connect-account.write.ts +1 -1
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/ingest-message.write.ts +6 -6
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/list-accounts.query.ts +1 -1
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/list-messages.query.ts +1 -1
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/scope-visibility.ts +2 -2
- package/packages/bundled-features/src/inbound-mail-foundation/oauth-access-token.ts +13 -8
- package/packages/bundled-features/src/inbound-mail-foundation/oauth-state.ts +7 -7
- package/packages/bundled-features/src/inbound-mail-foundation/retention-sweep.ts +2 -6
- package/packages/bundled-features/src/inbound-mail-foundation/tenant-destroy-hook.ts +5 -13
- package/packages/bundled-features/src/inbound-mail-foundation/types.ts +4 -6
- package/packages/bundled-features/src/inbound-mail-foundation/watch-supervisor.ts +42 -25
- package/packages/bundled-features/src/inbound-provider-imap/imap-client.ts +4 -3
- package/packages/bundled-features/src/jobs/changes.json +19 -0
- package/packages/bundled-features/src/jobs/db/queries/stale-run-sweep.ts +12 -4
- package/packages/bundled-features/src/jobs/feature.ts +7 -4
- package/packages/bundled-features/src/jobs/handlers/catalog.query.ts +1 -1
- package/packages/bundled-features/src/jobs/handlers/list.query.ts +3 -1
- package/packages/bundled-features/src/jobs/handlers/stale-run-sweep.job.ts +5 -2
- package/packages/bundled-features/src/jobs/job-run-logger.ts +52 -17
- package/packages/bundled-features/src/jobs/tenant-job-run-table.ts +7 -2
- package/packages/bundled-features/src/ledger/changes.json +7 -0
- package/packages/bundled-features/src/ledger/entity.ts +3 -1
- package/packages/bundled-features/src/ledger/recurring.ts +1 -3
- package/packages/bundled-features/src/managed-pages/branding.ts +33 -9
- package/packages/bundled-features/src/managed-pages/changes.json +6 -0
- package/packages/bundled-features/src/managed-pages/feature.ts +1 -0
- package/packages/bundled-features/src/managed-pages/i18n.ts +1 -0
- package/packages/bundled-features/src/managed-pages/screens/branding-screen.ts +8 -0
- package/packages/bundled-features/src/page-render/branding.ts +3 -0
- package/packages/bundled-features/src/page-render/markdown.ts +1 -1
- package/packages/bundled-features/src/personal-access-tokens/feature.ts +2 -4
- package/packages/bundled-features/src/personal-access-tokens/handlers/list.query.ts +2 -1
- package/packages/bundled-features/src/personal-access-tokens/index.ts +1 -1
- package/packages/bundled-features/src/personal-access-tokens/revoke-for-user.ts +2 -1
- package/packages/bundled-features/src/renderer-foundation/README.md +11 -10
- package/packages/bundled-features/src/renderer-foundation/api.ts +14 -14
- package/packages/bundled-features/src/renderer-foundation/changes.json +39 -0
- package/packages/bundled-features/src/renderer-foundation/constants.ts +6 -8
- package/packages/bundled-features/src/renderer-foundation/feature.ts +7 -7
- package/packages/bundled-features/src/renderer-foundation/index.ts +13 -2
- package/packages/bundled-features/src/renderer-foundation/types.ts +134 -35
- package/packages/bundled-features/src/renderer-pdf/changes.json +12 -0
- package/packages/bundled-features/src/renderer-pdf/feature.ts +7 -1
- package/packages/bundled-features/src/renderer-pdf/render-table-pdf.ts +162 -82
- package/packages/bundled-features/src/secrets/changes.json +6 -0
- package/packages/bundled-features/src/secrets/feature.ts +4 -3
- package/packages/bundled-features/src/secrets/secrets-context.ts +23 -3
- package/packages/bundled-features/src/sessions/db/queries/cleanup.ts +2 -2
- package/packages/bundled-features/src/sessions/feature.ts +2 -4
- package/packages/bundled-features/src/sessions/handlers/list.query.ts +2 -1
- package/packages/bundled-features/src/shared/attachment-file-name.ts +39 -0
- package/packages/bundled-features/src/shared/changes.json +6 -0
- package/packages/bundled-features/src/shared/chunked-entity-migration.ts +4 -1
- package/packages/bundled-features/src/shared/index.ts +6 -0
- package/packages/bundled-features/src/shared/is-tenant-db.ts +1 -1
- package/packages/bundled-features/src/shared/mail-template-body.ts +42 -0
- package/packages/bundled-features/src/shared/sharp-input-limits.ts +26 -0
- package/packages/bundled-features/src/shared/signup-handover.ts +4 -4
- package/packages/bundled-features/src/subscription-stripe/changes.json +6 -0
- package/packages/bundled-features/src/subscription-stripe/plugin-methods.ts +19 -11
- package/packages/bundled-features/src/subscription-stripe/verify-webhook.ts +3 -1
- package/packages/bundled-features/src/tags/handlers/assign-tag.write.ts +5 -1
- package/packages/bundled-features/src/tags/web/tag-chip.tsx +2 -1
- package/packages/bundled-features/src/template-resolver/README.md +66 -8
- package/packages/bundled-features/src/template-resolver/api.ts +85 -9
- package/packages/bundled-features/src/template-resolver/changes.json +186 -0
- package/packages/bundled-features/src/template-resolver/compile-document-body.ts +278 -0
- package/packages/bundled-features/src/template-resolver/constants.ts +49 -11
- package/packages/bundled-features/src/template-resolver/document-sanitizer.ts +335 -0
- package/packages/bundled-features/src/template-resolver/document-schema.ts +345 -0
- package/packages/bundled-features/src/template-resolver/feature.ts +59 -6
- package/packages/bundled-features/src/template-resolver/handlers/bundle-import.ts +188 -0
- package/packages/bundled-features/src/template-resolver/handlers/collection-set.write.ts +30 -2
- package/packages/bundled-features/src/template-resolver/handlers/copy-locale.write.ts +160 -0
- package/packages/bundled-features/src/template-resolver/handlers/diff-to-system.query.ts +33 -0
- package/packages/bundled-features/src/template-resolver/handlers/discard-draft.write.ts +52 -0
- package/packages/bundled-features/src/template-resolver/handlers/export-bundle.query.ts +138 -0
- package/packages/bundled-features/src/template-resolver/handlers/find-by-id.query.ts +9 -6
- package/packages/bundled-features/src/template-resolver/handlers/import-bundle-system.write.ts +42 -0
- package/packages/bundled-features/src/template-resolver/handlers/import-bundle.write.ts +22 -0
- package/packages/bundled-features/src/template-resolver/handlers/layout-source.query.ts +151 -0
- package/packages/bundled-features/src/template-resolver/handlers/list.query.ts +19 -18
- package/packages/bundled-features/src/template-resolver/handlers/override-diff.ts +49 -0
- package/packages/bundled-features/src/template-resolver/handlers/overview.query.ts +323 -0
- package/packages/bundled-features/src/template-resolver/handlers/preview.query.ts +25 -0
- package/packages/bundled-features/src/template-resolver/handlers/reset-to-system.write.ts +58 -0
- package/packages/bundled-features/src/template-resolver/handlers/resource-link-pdf.write.ts +34 -0
- package/packages/bundled-features/src/template-resolver/handlers/resource-remove.write.ts +50 -0
- package/packages/bundled-features/src/template-resolver/handlers/resource-shared.ts +24 -0
- package/packages/bundled-features/src/template-resolver/handlers/resource-upload.write.ts +135 -0
- package/packages/bundled-features/src/template-resolver/handlers/send-test.write.ts +135 -0
- package/packages/bundled-features/src/template-resolver/handlers/set.write.ts +32 -3
- package/packages/bundled-features/src/template-resolver/handlers/shared.ts +7 -2
- package/packages/bundled-features/src/template-resolver/handlers/template-gates.ts +196 -0
- package/packages/bundled-features/src/template-resolver/handlers/template-write.ts +233 -0
- package/packages/bundled-features/src/template-resolver/handlers/tenant-overrides.query.ts +137 -0
- package/packages/bundled-features/src/template-resolver/handlers/toggle-status.write.ts +91 -17
- package/packages/bundled-features/src/template-resolver/handlers/upsert-system.write.ts +19 -71
- package/packages/bundled-features/src/template-resolver/handlers/upsert-tenant.write.ts +16 -77
- package/packages/bundled-features/src/template-resolver/handlers/usage.query.ts +31 -0
- package/packages/bundled-features/src/template-resolver/handlers/validate.query.ts +116 -0
- package/packages/bundled-features/src/template-resolver/index.ts +111 -0
- package/packages/bundled-features/src/template-resolver/layout-appearance.ts +40 -0
- package/packages/bundled-features/src/template-resolver/layout-regions.ts +206 -0
- package/packages/bundled-features/src/template-resolver/linked-resources.ts +102 -0
- package/packages/bundled-features/src/template-resolver/pdf-constants.ts +12 -0
- package/packages/bundled-features/src/template-resolver/preview-display-html.ts +36 -0
- package/packages/bundled-features/src/template-resolver/print-document.ts +58 -0
- package/packages/bundled-features/src/template-resolver/qualified-names.ts +34 -0
- package/packages/bundled-features/src/template-resolver/record-mapping.ts +26 -0
- package/packages/bundled-features/src/template-resolver/resource-image.ts +47 -0
- package/packages/bundled-features/src/template-resolver/seeding.ts +171 -20
- package/packages/bundled-features/src/template-resolver/store-template-resource.ts +416 -0
- package/packages/bundled-features/src/template-resolver/table.ts +27 -1
- package/packages/bundled-features/src/template-resolver/template-bundle.ts +79 -0
- package/packages/bundled-features/src/template-resolver/template-diff.ts +78 -0
- package/packages/bundled-features/src/template-resolver/template-draft.ts +106 -0
- package/packages/bundled-features/src/template-resolver/template-meta.ts +192 -0
- package/packages/bundled-features/src/template-resolver/template-preview.ts +676 -0
- package/packages/bundled-features/src/template-resolver/template-resources.ts +114 -0
- package/packages/bundled-features/src/template-resolver/template-usage.ts +68 -0
- package/packages/bundled-features/src/template-resolver/template-validation.ts +230 -0
- package/packages/bundled-features/src/template-resolver/testing.ts +5 -5
- package/packages/bundled-features/src/template-resolver/web/client-plugin.tsx +20 -13
- package/packages/bundled-features/src/template-resolver/web/document-editor-extensions.ts +215 -0
- package/packages/bundled-features/src/template-resolver/web/document-editor.tsx +37 -0
- package/packages/bundled-features/src/template-resolver/web/document-tiptap-editor.tsx +1065 -0
- package/packages/bundled-features/src/template-resolver/web/document-toolbar-blocks.ts +72 -0
- package/packages/bundled-features/src/template-resolver/web/editor-handle.ts +26 -0
- package/packages/bundled-features/src/template-resolver/web/i18n.ts +121 -0
- package/packages/bundled-features/src/template-resolver/web/index.ts +26 -0
- package/packages/bundled-features/src/template-resolver/web/placeholder-line-editor-lazy.tsx +36 -0
- package/packages/bundled-features/src/template-resolver/web/placeholder-line-editor.tsx +176 -0
- package/packages/bundled-features/src/template-resolver/web/placeholder-text.ts +37 -0
- package/packages/bundled-features/src/template-resolver/web/use-stable-by-key.ts +14 -0
- package/packages/bundled-features/src/tenant/handlers/team-list.query.ts +3 -2
- package/packages/bundled-features/src/tenant/seeding.ts +41 -7
- package/packages/bundled-features/src/tenant-lifecycle/boot-checks.ts +1 -1
- package/packages/bundled-features/src/tenant-lifecycle/handlers/cancel-destruction.write.ts +2 -1
- package/packages/bundled-features/src/tier-engine/changes.json +6 -0
- package/packages/bundled-features/src/tier-engine/feature.ts +11 -3
- package/packages/bundled-features/src/user/changes.json +6 -0
- package/packages/bundled-features/src/user/db/queries/stream-tenant-backfill.ts +4 -4
- package/packages/bundled-features/src/user/handlers/detail.query.ts +3 -5
- package/packages/bundled-features/src/user/resolve-display-names.ts +8 -15
- package/packages/bundled-features/src/user/roles-input-schema.ts +2 -2
- package/packages/bundled-features/src/user/seeding.ts +19 -5
- package/packages/bundled-features/src/user-data-rights/changes.json +13 -0
- package/packages/bundled-features/src/user-data-rights/db/queries/forget-cleanup.ts +2 -2
- package/packages/bundled-features/src/user-data-rights/email-templates.ts +5 -149
- package/packages/bundled-features/src/user-data-rights/feature.ts +72 -35
- package/packages/bundled-features/src/user-data-rights/handlers/cancel-deletion.write.ts +2 -1
- package/packages/bundled-features/src/user-data-rights/handlers/request-deletion.write.ts +5 -11
- package/packages/bundled-features/src/user-data-rights/lib/default-mailers.ts +134 -53
- package/packages/bundled-features/src/user-data-rights/lib/update-user-lifecycle.ts +2 -2
- package/packages/bundled-features/src/user-data-rights/mail-notifications.ts +157 -0
- package/packages/bundled-features/src/user-data-rights/run-forget-cleanup.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/web/privacy-center-screen.tsx +2 -1
- package/packages/bundled-features/src/user-profile/changes.json +1 -1
- package/packages/bundled-features/src/user-profile/web/profile-screen.tsx +2 -1
- package/packages/bundled-features/src/waitlist/changes.json +7 -0
- package/packages/bundled-features/src/waitlist/feature.ts +17 -0
- package/packages/bundled-features/src/waitlist/handlers/submit.write.ts +4 -5
- package/packages/bundled-features/src/waitlist/mail.ts +69 -18
- package/packages/bundled-features/src/waitlist/options.ts +1 -1
- package/packages/bundled-features/src/workflow-runner/changes.json +6 -0
- package/packages/bundled-features/src/workflow-runner/event-trigger.ts +3 -3
- package/packages/bundled-features/src/workflow-runner/handlers/resume-run.write.ts +7 -1
- package/samples/apps/ui-walkthrough/package.json +11 -0
- package/samples/apps/ui-walkthrough/playwright.config.ts +40 -7
- package/samples/apps/ui-walkthrough/src/app/auth-constants.ts +9 -0
- package/samples/apps/ui-walkthrough/src/app/client.tsx +6 -0
- package/samples/apps/ui-walkthrough/src/app/seed-templates.ts +239 -0
- package/samples/apps/ui-walkthrough/src/app/server.ts +5 -1
- package/samples/apps/ui-walkthrough/src/app/shell.tsx +12 -1
- package/samples/apps/ui-walkthrough/src/app/template-seed-data.ts +570 -0
- package/samples/apps/ui-walkthrough/src/features/billing/feature.ts +72 -0
- package/samples/apps/ui-walkthrough/src/features/billing/i18n.ts +18 -0
- package/samples/apps/ui-walkthrough/src/features/billing/index.ts +2 -0
- package/samples/apps/ui-walkthrough/src/features/billing/web/index.ts +7 -0
- package/samples/apps/ui-walkthrough/src/run-config.ts +41 -1
- package/samples/apps/use-all-bundled/e2e-billing-gallery/gallery-features.ts +0 -2
- package/samples/apps/use-all-bundled/feature-manifest.json +118 -21
- package/samples/apps/use-all-bundled/kumiko/migrations/0045_template-resource-meta.rebuild.json +4 -0
- package/samples/apps/use-all-bundled/kumiko/migrations/0046_pdf-rendered.rebuild.json +4 -0
- package/samples/apps/use-all-bundled/package.json +2 -0
- package/samples/apps/use-all-bundled/playwright.config.ts +38 -3
- package/samples/apps/use-all-bundled/schema/generate.ts +13 -3
- package/samples/apps/use-all-bundled/schema/schema.generated.ts +3 -0
- package/samples/apps/use-all-bundled/scripts/check-coverage.ts +3 -0
- package/samples/apps/use-all-bundled/src/app/auth-constants.ts +3 -0
- package/samples/apps/use-all-bundled/src/app/client.tsx +4 -0
- package/samples/apps/use-all-bundled/src/app/seed-documents.ts +128 -0
- package/samples/apps/use-all-bundled/src/app/seed.ts +4 -0
- package/samples/apps/use-all-bundled/src/run-config.ts +11 -11
- package/samples/recipes/delivery-notifications/README.md +26 -25
- package/samples/recipes/delivery-notifications/package.json +2 -1
- package/samples/recipes/delivery-notifications/src/feature.ts +64 -58
- package/samples/recipes/seed-migration/README.md +1 -1
- package/packages/bundled-features/src/renderer-simple/changes.json +0 -27
- package/packages/bundled-features/src/renderer-simple/feature.ts +0 -66
- package/packages/bundled-features/src/renderer-simple/index.ts +0 -8
- package/packages/bundled-features/src/renderer-simple/mail-blocks.ts +0 -138
- package/packages/bundled-features/src/renderer-simple/resolve-variables.ts +0 -57
- package/packages/bundled-features/src/renderer-simple/simple-renderer.ts +0 -304
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
2
|
+
import * as z from "zod";
|
|
3
|
+
import { CONTENT_FORMATS, type ContentFormat } from "./constants.js";
|
|
4
|
+
import type { TemplateResourceRow } from "./table.js";
|
|
5
|
+
|
|
6
|
+
const templateDraftSchema = z.object({
|
|
7
|
+
content: z.string().nullable(),
|
|
8
|
+
contentFormat: z.enum(CONTENT_FORMATS),
|
|
9
|
+
variableSchema: z.string(),
|
|
10
|
+
meta: z.string().nullable(),
|
|
11
|
+
title: z.string().nullable(),
|
|
12
|
+
folder: z.string().nullable(),
|
|
13
|
+
parentTemplateId: z.string().nullable(),
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
// An unpublished edit beside the active version; variableSchema and meta stay
|
|
17
|
+
// JSON strings, exactly like the columns they replace on publish.
|
|
18
|
+
export type TemplateDraft = {
|
|
19
|
+
readonly content: string | null;
|
|
20
|
+
readonly contentFormat: ContentFormat;
|
|
21
|
+
readonly variableSchema: string;
|
|
22
|
+
readonly meta: string | null;
|
|
23
|
+
readonly title: string | null;
|
|
24
|
+
readonly folder: string | null;
|
|
25
|
+
readonly parentTemplateId: string | null;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export function parseTemplateDraft(raw: string | null): TemplateDraft | null {
|
|
29
|
+
if (raw === null) return null;
|
|
30
|
+
try {
|
|
31
|
+
const parsed = templateDraftSchema.safeParse(JSON.parse(raw));
|
|
32
|
+
return parsed.success ? parsed.data : null;
|
|
33
|
+
} catch {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function serializeTemplateDraft(draft: TemplateDraft): string {
|
|
39
|
+
return JSON.stringify(draft);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function activeVersionOf(row: TemplateResourceRow): number {
|
|
43
|
+
return row.activeVersion ?? row.version;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// `version` also counts draft saves, so only a row without a served version shows it as its number.
|
|
47
|
+
export function servedVersionOf(row: TemplateResourceRow): number {
|
|
48
|
+
return row.status === "active" ? activeVersionOf(row) : row.version;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function activeSinceOf(row: TemplateResourceRow): Temporal.Instant {
|
|
52
|
+
return row.activeSince ?? row.modifiedAt ?? row.insertedAt;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export type ActiveInfo = { readonly version: number; readonly since: Temporal.Instant };
|
|
56
|
+
|
|
57
|
+
export type WorkingRow = TemplateResourceRow & { readonly active: ActiveInfo | null };
|
|
58
|
+
|
|
59
|
+
// A SystemAdmin edits system rows, so for them those rows count as their own.
|
|
60
|
+
function isSystemAdmin(user: { readonly roles: readonly string[] }): boolean {
|
|
61
|
+
return user.roles.includes("SystemAdmin");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// A system row that was never served keeps its draft in the main fields, so only a SystemAdmin may read it.
|
|
65
|
+
export function isHiddenSystemDraft(
|
|
66
|
+
user: { readonly roles: readonly string[] },
|
|
67
|
+
row: Pick<TemplateResourceRow, "scope" | "status">,
|
|
68
|
+
): boolean {
|
|
69
|
+
return row.scope === "system" && row.status === "draft" && !isSystemAdmin(user);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function draftViewerTenantId(
|
|
73
|
+
user: { readonly tenantId: string; readonly roles: readonly string[] },
|
|
74
|
+
row: TemplateResourceRow,
|
|
75
|
+
): string {
|
|
76
|
+
return row.scope === "system" && isSystemAdmin(user) ? row.tenantId : user.tenantId;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// The version an editor works on: the open draft if there is one, else the stored row.
|
|
80
|
+
// A draft is only shown to the tenant that owns the row, never through a system row.
|
|
81
|
+
export function toWorkingRow(row: TemplateResourceRow, viewerTenantId: string): WorkingRow {
|
|
82
|
+
const active =
|
|
83
|
+
row.status === "active" ? { version: activeVersionOf(row), since: activeSinceOf(row) } : null;
|
|
84
|
+
const draft = row.tenantId === viewerTenantId ? parseTemplateDraft(row.draft) : null;
|
|
85
|
+
// Saves and discards of drafts raise row.version; an editor without a draft shows the served number.
|
|
86
|
+
if (draft === null) return { ...row, version: active?.version ?? row.version, active };
|
|
87
|
+
return { ...row, ...draft, status: "draft", active };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Event changes that turn a row into a served one. Every value is explicit so a
|
|
91
|
+
// rebuild reproduces the row without deriving anything.
|
|
92
|
+
export function servedStampChanges(row: { readonly version: number } | null) {
|
|
93
|
+
return {
|
|
94
|
+
activeVersion: row === null ? 1 : row.version + 1,
|
|
95
|
+
activeSince: Temporal.Now.instant(),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function activeStampChanges(row: { readonly version: number } | null) {
|
|
100
|
+
return { status: "active", ...servedStampChanges(row) };
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Publishing also consumes the open draft.
|
|
104
|
+
export function activationChanges(row: TemplateResourceRow | null) {
|
|
105
|
+
return { ...activeStampChanges(row), draft: null };
|
|
106
|
+
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
import {
|
|
3
|
+
HEX_COLOR_PATTERN,
|
|
4
|
+
PDF_ORIENTATIONS,
|
|
5
|
+
PDF_PAGE_FORMATS,
|
|
6
|
+
type TemplateKind,
|
|
7
|
+
} from "./constants.js";
|
|
8
|
+
|
|
9
|
+
// One or more kebab segments joined by ":" — notification templates are seeded
|
|
10
|
+
// under their qualified name `feature:notify:name`.
|
|
11
|
+
export const templateSlugSchema = z
|
|
12
|
+
.string()
|
|
13
|
+
.min(1)
|
|
14
|
+
.max(120)
|
|
15
|
+
.regex(
|
|
16
|
+
/^[a-z0-9]+(-[a-z0-9]+)*(:[a-z0-9]+(-[a-z0-9]+)*)*$/,
|
|
17
|
+
"slug must be kebab-case segments joined by ':'",
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
export const MAIL_CATEGORIES = ["transactional", "marketing"] as const;
|
|
21
|
+
export type MailCategory = (typeof MAIL_CATEGORIES)[number];
|
|
22
|
+
|
|
23
|
+
// Header values: a CR/LF would let an author inject extra mail headers.
|
|
24
|
+
const singleLine = (max: number) =>
|
|
25
|
+
z
|
|
26
|
+
.string()
|
|
27
|
+
.max(max)
|
|
28
|
+
.refine((value) => !/[\r\n]/.test(value), "must not contain line breaks");
|
|
29
|
+
|
|
30
|
+
// Rows saved before the sender key was dropped still carry it; discard it on read so they stay editable.
|
|
31
|
+
function withoutLegacySender(raw: unknown): unknown {
|
|
32
|
+
if (typeof raw !== "object" || raw === null || !("sender" in raw)) return raw;
|
|
33
|
+
const { sender: _legacySender, ...rest } = raw;
|
|
34
|
+
return rest;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const mailMetaSchema = z.preprocess(
|
|
38
|
+
withoutLegacySender,
|
|
39
|
+
z
|
|
40
|
+
.object({
|
|
41
|
+
subject: singleLine(200).min(1),
|
|
42
|
+
previewText: singleLine(200).optional(),
|
|
43
|
+
layoutSlug: templateSlugSchema.optional(),
|
|
44
|
+
category: z.enum(MAIL_CATEGORIES).optional(),
|
|
45
|
+
senderName: singleLine(80).min(1).optional(),
|
|
46
|
+
replyTo: singleLine(254).pipe(z.email()).optional(),
|
|
47
|
+
})
|
|
48
|
+
.strict(),
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
const marginMm = z.number().finite().min(0).max(100).optional();
|
|
52
|
+
|
|
53
|
+
// The file name ends up in a Content-Disposition header and on disk.
|
|
54
|
+
const FORBIDDEN_FILE_NAME = /[/\\";]|\.\./;
|
|
55
|
+
|
|
56
|
+
// Name of a PDF rendered into a mail; {{placeholders}} are filled at render time.
|
|
57
|
+
export const pdfAttachmentFileNamePatternSchema = singleLine(200)
|
|
58
|
+
.min(1)
|
|
59
|
+
.refine((value) => !FORBIDDEN_FILE_NAME.test(value), 'must not contain / \\ " ; or ..')
|
|
60
|
+
.refine((value) => value.toLowerCase().endsWith(".pdf"), "must end with .pdf");
|
|
61
|
+
|
|
62
|
+
const pdfMetaSchema = z
|
|
63
|
+
.object({
|
|
64
|
+
layoutSlug: templateSlugSchema.optional(),
|
|
65
|
+
pageFormat: z.enum(PDF_PAGE_FORMATS).optional(),
|
|
66
|
+
orientation: z.enum(PDF_ORIENTATIONS).optional(),
|
|
67
|
+
printBackground: z.boolean().optional(),
|
|
68
|
+
layoutHeaderFooter: z.boolean().optional(),
|
|
69
|
+
margins: z
|
|
70
|
+
.object({ top: marginMm, right: marginMm, bottom: marginMm, left: marginMm })
|
|
71
|
+
.strict()
|
|
72
|
+
.optional(),
|
|
73
|
+
fileName: singleLine(200)
|
|
74
|
+
.min(1)
|
|
75
|
+
.refine((value) => !FORBIDDEN_FILE_NAME.test(value), 'must not contain / \\ " ; or ..')
|
|
76
|
+
.optional(),
|
|
77
|
+
metadata: z
|
|
78
|
+
.object({ title: singleLine(200).optional(), author: singleLine(200).optional() })
|
|
79
|
+
.strict()
|
|
80
|
+
.optional(),
|
|
81
|
+
})
|
|
82
|
+
.strict();
|
|
83
|
+
|
|
84
|
+
const MAIL_LAYOUT_FONTS = ["sans", "serif"] as const;
|
|
85
|
+
const MAIL_LAYOUT_ACCENT_LINES = ["branding", "none"] as const;
|
|
86
|
+
const MAIL_LAYOUT_BUTTON_STYLES = ["filled-rounded", "filled-square", "outline"] as const;
|
|
87
|
+
|
|
88
|
+
const mailLayoutMetaSchema = z
|
|
89
|
+
.object({
|
|
90
|
+
width: z.union([z.literal(560), z.literal(600), z.literal(640)]).optional(),
|
|
91
|
+
font: z.enum(MAIL_LAYOUT_FONTS).optional(),
|
|
92
|
+
outerBackground: z.string().regex(HEX_COLOR_PATTERN, "must be a #rrggbb color").optional(),
|
|
93
|
+
accentLine: z.enum(MAIL_LAYOUT_ACCENT_LINES).optional(),
|
|
94
|
+
buttonStyle: z.enum(MAIL_LAYOUT_BUTTON_STYLES).optional(),
|
|
95
|
+
})
|
|
96
|
+
.strict();
|
|
97
|
+
|
|
98
|
+
const pdfLayoutMetaSchema = z.object({}).strict();
|
|
99
|
+
|
|
100
|
+
export type MailTemplateMeta = z.infer<typeof mailMetaSchema>;
|
|
101
|
+
export type PdfTemplateMeta = z.infer<typeof pdfMetaSchema>;
|
|
102
|
+
export type MailLayoutMeta = z.infer<typeof mailLayoutMetaSchema>;
|
|
103
|
+
export type LayoutTemplateMeta = MailLayoutMeta | z.infer<typeof pdfLayoutMetaSchema>;
|
|
104
|
+
export type TemplateMeta = MailTemplateMeta | PdfTemplateMeta | LayoutTemplateMeta;
|
|
105
|
+
|
|
106
|
+
export function isMailTemplateMeta(meta: TemplateMeta | null): meta is MailTemplateMeta {
|
|
107
|
+
return meta !== null && "subject" in meta;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function readPdfTemplateMeta(meta: TemplateMeta | null): PdfTemplateMeta | null {
|
|
111
|
+
const parsed = pdfMetaSchema.safeParse(meta);
|
|
112
|
+
return parsed.success ? parsed.data : null;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function readMailLayoutMeta(meta: unknown): MailLayoutMeta {
|
|
116
|
+
const parsed = mailLayoutMetaSchema.safeParse(meta ?? {});
|
|
117
|
+
return parsed.success ? parsed.data : {};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export type TemplateMetaIssue = {
|
|
121
|
+
readonly path: string;
|
|
122
|
+
/** The setting the issue is about (`subject`), `meta` when it concerns the object as a whole. */
|
|
123
|
+
readonly field: string;
|
|
124
|
+
/** The value is absent or empty, as opposed to present and wrong. */
|
|
125
|
+
readonly missing: boolean;
|
|
126
|
+
/** Parser wording; for logs and tests, never for the UI. */
|
|
127
|
+
readonly message: string;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
function valueAt(raw: unknown, path: readonly PropertyKey[]): unknown {
|
|
131
|
+
let current: unknown = raw;
|
|
132
|
+
for (const key of path) {
|
|
133
|
+
if (typeof current !== "object" || current === null) return undefined;
|
|
134
|
+
current = Object.entries(current).find(([name]) => name === String(key))?.[1];
|
|
135
|
+
}
|
|
136
|
+
return current;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export type TemplateMetaResult =
|
|
140
|
+
| { readonly ok: true; readonly meta: TemplateMeta | null }
|
|
141
|
+
| { readonly ok: false; readonly issues: readonly TemplateMetaIssue[] };
|
|
142
|
+
|
|
143
|
+
function schemaForKind(kind: TemplateKind) {
|
|
144
|
+
switch (kind) {
|
|
145
|
+
case "mail":
|
|
146
|
+
return mailMetaSchema;
|
|
147
|
+
case "document-pdf":
|
|
148
|
+
return pdfMetaSchema;
|
|
149
|
+
case "mail-layout":
|
|
150
|
+
return mailLayoutMetaSchema;
|
|
151
|
+
case "pdf-layout":
|
|
152
|
+
return pdfLayoutMetaSchema;
|
|
153
|
+
default:
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Kinds without a meta schema must not carry meta at all; mail needs it,
|
|
159
|
+
// layouts and PDFs may omit it.
|
|
160
|
+
export function parseTemplateMeta(kind: TemplateKind, raw: unknown): TemplateMetaResult {
|
|
161
|
+
const schema = schemaForKind(kind);
|
|
162
|
+
if (schema === null) {
|
|
163
|
+
return raw === undefined || raw === null
|
|
164
|
+
? { ok: true, meta: null }
|
|
165
|
+
: {
|
|
166
|
+
ok: false,
|
|
167
|
+
issues: [
|
|
168
|
+
{
|
|
169
|
+
path: "meta",
|
|
170
|
+
field: "meta",
|
|
171
|
+
missing: false,
|
|
172
|
+
message: `kind ${kind} does not take meta`,
|
|
173
|
+
},
|
|
174
|
+
],
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
if ((raw === undefined || raw === null) && kind !== "mail") return { ok: true, meta: null };
|
|
178
|
+
const parsed = schema.safeParse(raw ?? undefined);
|
|
179
|
+
if (parsed.success) return { ok: true, meta: parsed.data };
|
|
180
|
+
return {
|
|
181
|
+
ok: false,
|
|
182
|
+
issues: parsed.error.issues.map((issue) => {
|
|
183
|
+
const value = valueAt(raw, issue.path);
|
|
184
|
+
return {
|
|
185
|
+
path: ["meta", ...issue.path.map(String)].join("."),
|
|
186
|
+
field: issue.path.length === 0 ? "meta" : String(issue.path[0]),
|
|
187
|
+
missing: value === undefined || value === "",
|
|
188
|
+
message: issue.message,
|
|
189
|
+
};
|
|
190
|
+
}),
|
|
191
|
+
};
|
|
192
|
+
}
|