@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
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
type NotificationLocalizedTemplate,
|
|
3
|
+
type NotificationRecordMapping,
|
|
4
|
+
type TemplateVariables,
|
|
5
|
+
templateVariable,
|
|
6
|
+
} from "@cosmicdrift/kumiko-framework/engine";
|
|
7
|
+
import { mailHeading, mailParagraph, mailRepeatedRows } from "../shared/index.js";
|
|
2
8
|
|
|
3
9
|
export type WaitlistMailLocale = "en" | "de" | "es";
|
|
4
10
|
|
|
@@ -72,43 +78,88 @@ export function resolveWaitlistMailLocale(locale: string | undefined): WaitlistM
|
|
|
72
78
|
return isConfirmationLocale(language) ? language : "en";
|
|
73
79
|
}
|
|
74
80
|
|
|
81
|
+
export const WAITLIST_CONFIRMATION_VARIABLES: TemplateVariables = {
|
|
82
|
+
subject: templateVariable.text({ required: true }),
|
|
83
|
+
intro: templateVariable.text({ required: true }),
|
|
84
|
+
footer: templateVariable.text({ required: true }),
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// Only `name` is a plain entry field; the details rows are composed from several fields.
|
|
88
|
+
export const WAITLIST_ADMIN_NOTICE_RECORD: NotificationRecordMapping = {
|
|
89
|
+
entity: "waitlistEntry",
|
|
90
|
+
map: { name: "name" },
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export const WAITLIST_ADMIN_NOTICE_VARIABLES: TemplateVariables = {
|
|
94
|
+
name: templateVariable.text({ required: true }),
|
|
95
|
+
details: templateVariable.list(
|
|
96
|
+
{ text: templateVariable.text({ required: true }) },
|
|
97
|
+
{ required: true },
|
|
98
|
+
),
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// The app name is optional, so the sentences that mention it are computed in
|
|
102
|
+
// code and handed over as variables; the template keeps heading and structure.
|
|
75
103
|
// The submitter's name stays out: the address is unverified, so any text in
|
|
76
104
|
// this mail could be planted by whoever typed someone else's email.
|
|
77
|
-
export function
|
|
105
|
+
export function waitlistConfirmationVariables(args: {
|
|
78
106
|
readonly locale: string | undefined;
|
|
79
107
|
readonly appName?: string | undefined;
|
|
80
|
-
}):
|
|
108
|
+
}): { readonly subject: string; readonly intro: string; readonly footer: string } {
|
|
81
109
|
const t = CONFIRMATION_STRINGS[resolveWaitlistMailLocale(args.locale)];
|
|
82
110
|
return {
|
|
83
111
|
subject: t.subject(args.appName),
|
|
84
|
-
|
|
85
|
-
sections: [{ text: t.intro(args.appName) }],
|
|
112
|
+
intro: t.intro(args.appName),
|
|
86
113
|
footer: t.footer(args.appName),
|
|
87
114
|
};
|
|
88
115
|
}
|
|
89
116
|
|
|
117
|
+
export function waitlistConfirmationTemplate(): NotificationLocalizedTemplate {
|
|
118
|
+
return Object.fromEntries(
|
|
119
|
+
Object.entries(CONFIRMATION_STRINGS).map(([locale, t]) => [
|
|
120
|
+
locale,
|
|
121
|
+
{
|
|
122
|
+
body: [mailHeading(t.header), mailParagraph("{intro}"), mailParagraph("{footer}")].join(""),
|
|
123
|
+
meta: { subject: "{{subject}}", category: "transactional" as const },
|
|
124
|
+
},
|
|
125
|
+
]),
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
90
129
|
// Operator-facing, so the entrant's locale does not apply: en/de, en default.
|
|
91
130
|
export function resolveWaitlistAdminMailLocale(adminLocale: string | undefined): "en" | "de" {
|
|
92
131
|
return languageOf(adminLocale) === "de" ? "de" : "en";
|
|
93
132
|
}
|
|
94
133
|
|
|
95
|
-
export function
|
|
134
|
+
export function waitlistAdminNoticeVariables(args: {
|
|
96
135
|
readonly name: string;
|
|
97
136
|
readonly email: string;
|
|
98
137
|
readonly company: string | undefined;
|
|
99
138
|
readonly message: string | undefined;
|
|
100
|
-
|
|
101
|
-
}): AuthMailContent {
|
|
102
|
-
const t = ADMIN_NOTICE_STRINGS[resolveWaitlistAdminMailLocale(args.adminLocale)];
|
|
103
|
-
const details = [
|
|
104
|
-
`${args.name} <${args.email}>`,
|
|
105
|
-
...(args.company ? [args.company] : []),
|
|
106
|
-
...(args.message ? [args.message] : []),
|
|
107
|
-
];
|
|
139
|
+
}): { readonly name: string; readonly details: readonly { readonly text: string }[] } {
|
|
108
140
|
return {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
141
|
+
name: args.name,
|
|
142
|
+
details: [
|
|
143
|
+
`${args.name} <${args.email}>`,
|
|
144
|
+
...(args.company ? [args.company] : []),
|
|
145
|
+
...(args.message ? [args.message] : []),
|
|
146
|
+
].map((text) => ({ text })),
|
|
113
147
|
};
|
|
114
148
|
}
|
|
149
|
+
|
|
150
|
+
export function waitlistAdminNoticeTemplate(): NotificationLocalizedTemplate {
|
|
151
|
+
return Object.fromEntries(
|
|
152
|
+
Object.entries(ADMIN_NOTICE_STRINGS).map(([locale, t]) => [
|
|
153
|
+
locale,
|
|
154
|
+
{
|
|
155
|
+
body: [
|
|
156
|
+
mailHeading(t.header),
|
|
157
|
+
mailParagraph(t.intro),
|
|
158
|
+
mailRepeatedRows("details", "text"),
|
|
159
|
+
mailParagraph(t.footer),
|
|
160
|
+
].join(""),
|
|
161
|
+
meta: { subject: t.subject("{{name}}"), category: "transactional" as const },
|
|
162
|
+
},
|
|
163
|
+
]),
|
|
164
|
+
);
|
|
165
|
+
}
|
|
@@ -38,5 +38,5 @@ export const DEFAULT_SUBMIT_RATE_LIMIT: RateLimitOption = {
|
|
|
38
38
|
};
|
|
39
39
|
|
|
40
40
|
export const DEFAULT_SUBMIT_EMAIL_RATE_LIMITS: readonly PayloadRateLimitOption[] = [
|
|
41
|
-
{ per: { payloadField: "email" }, limit: 3, windowSeconds: 24 * 60 * 60 },
|
|
41
|
+
{ per: { payloadField: "email" }, limit: 3, windowSeconds: 24 * 60 * 60, normalize: "email" },
|
|
42
42
|
];
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.364.0",
|
|
4
|
+
"type": "fix",
|
|
5
|
+
"title": "Workflow run-failed and retry logs carry the original cause",
|
|
6
|
+
"detail": "The ops log used to print the generic `workflow step N failed` wrapper. It now prints the underlying error, while the persisted event still carries the error class only."
|
|
7
|
+
},
|
|
2
8
|
{
|
|
3
9
|
"version": "0.353.0",
|
|
4
10
|
"type": "fix",
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
describeWorkflowStepError,
|
|
23
23
|
getStep,
|
|
24
24
|
SYSTEM_TENANT_ID,
|
|
25
|
-
|
|
25
|
+
unwrapWorkflowStepError,
|
|
26
26
|
WORKFLOW_AGGREGATE_TYPE,
|
|
27
27
|
WORKFLOW_RUN_FAILED_TYPE,
|
|
28
28
|
WorkflowStepError,
|
|
@@ -71,7 +71,7 @@ export function assertEventTriggerStepsSupported(workflow: WorkflowDefinition):
|
|
|
71
71
|
steps = buildPipelineSteps(workflow.pipelineDef, {
|
|
72
72
|
type: "workflow-registration-probe",
|
|
73
73
|
payload: {},
|
|
74
|
-
user: createSystemUser(SYSTEM_TENANT_ID
|
|
74
|
+
user: createSystemUser(SYSTEM_TENANT_ID),
|
|
75
75
|
});
|
|
76
76
|
} catch (error) {
|
|
77
77
|
throw new Error(
|
|
@@ -168,7 +168,7 @@ export function registerEventTrigger(r: FeatureRegistrar, workflow: WorkflowDefi
|
|
|
168
168
|
runId,
|
|
169
169
|
workflowName: workflow.name,
|
|
170
170
|
stepIndex,
|
|
171
|
-
error: String(error),
|
|
171
|
+
error: String(unwrapWorkflowStepError(error)),
|
|
172
172
|
});
|
|
173
173
|
const failedPayload: WorkflowRunFailedPayload = {
|
|
174
174
|
workflowName: workflow.name,
|
|
@@ -40,6 +40,7 @@ import {
|
|
|
40
40
|
runStepList,
|
|
41
41
|
type StepInstance,
|
|
42
42
|
SYSTEM_ROLE,
|
|
43
|
+
unwrapWorkflowStepError,
|
|
43
44
|
WORKFLOW_AGGREGATE_TYPE,
|
|
44
45
|
WORKFLOW_RESUMED_TYPE,
|
|
45
46
|
WORKFLOW_RETRY_SCHEDULED_TYPE,
|
|
@@ -392,7 +393,12 @@ async function runResumedPipeline(ctx: HandlerContext, input: ResumedPipelineInp
|
|
|
392
393
|
});
|
|
393
394
|
return { isSuccess: true as const, data: { outcome: "completed" as const } };
|
|
394
395
|
} catch (error) {
|
|
395
|
-
log.warn("workflow run failed", {
|
|
396
|
+
log.warn("workflow run failed", {
|
|
397
|
+
runId,
|
|
398
|
+
workflowName,
|
|
399
|
+
stepIndex,
|
|
400
|
+
error: String(unwrapWorkflowStepError(error)),
|
|
401
|
+
});
|
|
396
402
|
// The input stepIndex is the suspended step; the failure happened at the step the resumed pass reached.
|
|
397
403
|
const failedPayload: WorkflowRunFailedPayload = {
|
|
398
404
|
workflowName,
|
|
@@ -10,9 +10,12 @@
|
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@cosmicdrift/kumiko-bundled-features": "workspace:*",
|
|
12
12
|
"@cosmicdrift/kumiko-dev-server": "workspace:*",
|
|
13
|
+
"@cosmicdrift/kumiko-document-designer": "workspace:*",
|
|
13
14
|
"@cosmicdrift/kumiko-dispatcher-live": "workspace:*",
|
|
14
15
|
"@cosmicdrift/kumiko-framework": "workspace:*",
|
|
15
16
|
"@cosmicdrift/kumiko-headless": "workspace:*",
|
|
17
|
+
"@cosmicdrift/kumiko-renderer-mail-html": "workspace:*",
|
|
18
|
+
"@cosmicdrift/kumiko-renderer-puppeteer-client": "workspace:*",
|
|
16
19
|
"@cosmicdrift/kumiko-renderer-web": "workspace:*",
|
|
17
20
|
"@cosmicdrift/kumiko-server-runtime": "workspace:*",
|
|
18
21
|
"react": "^19.2.6",
|
|
@@ -22,5 +25,13 @@
|
|
|
22
25
|
},
|
|
23
26
|
"devDependencies": {
|
|
24
27
|
"@cosmicdrift/kumiko-testing": "workspace:*"
|
|
28
|
+
},
|
|
29
|
+
"kumiko": {
|
|
30
|
+
"assets": [
|
|
31
|
+
{
|
|
32
|
+
"name": "logo-nordlicht.png",
|
|
33
|
+
"source": "src/app/assets/logo-nordlicht.png"
|
|
34
|
+
}
|
|
35
|
+
]
|
|
25
36
|
}
|
|
26
37
|
}
|
|
@@ -7,18 +7,51 @@
|
|
|
7
7
|
// setupTestStack-Default ist ephemeral (fresh kumiko_test_<random> DB),
|
|
8
8
|
// deshalb braucht's keine DB-Reset-Logik hier.
|
|
9
9
|
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
defineAppE2eConfig,
|
|
12
|
+
E2E_TIMEOUT_MS,
|
|
13
|
+
PLAYWRIGHT_DEMO_ENV,
|
|
14
|
+
} from "@cosmicdrift/kumiko-testing/e2e";
|
|
15
|
+
import { chromium } from "@playwright/test";
|
|
11
16
|
import { E2E_PORTS } from "../../e2e/e2e-ports";
|
|
12
17
|
|
|
13
18
|
const PORT = E2E_PORTS["framework/ui-walkthrough"];
|
|
19
|
+
const PRINT_SERVICE_PORT = E2E_PORTS["framework/ui-walkthrough-puppeteer-service"];
|
|
20
|
+
// Both sides of the print service handshake; any value of 16+ characters will do for a local run.
|
|
21
|
+
const PRINT_SERVICE_TOKEN = "ui-walkthrough-e2e-print-service";
|
|
14
22
|
|
|
23
|
+
const appConfig = defineAppE2eConfig({
|
|
24
|
+
port: PORT,
|
|
25
|
+
serverEntry: "src/app/server.ts",
|
|
26
|
+
locale: "en-US",
|
|
27
|
+
env: {
|
|
28
|
+
...PLAYWRIGHT_DEMO_ENV,
|
|
29
|
+
PUPPETEER_SERVICE_URL: `http://127.0.0.1:${PRINT_SERVICE_PORT}`,
|
|
30
|
+
PUPPETEER_AUTH_TOKEN: PRINT_SERVICE_TOKEN,
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// The PDF preview of the template editor prints through the real puppeteer-service,
|
|
35
|
+
// on the Chromium that `playwright install chromium` provides.
|
|
15
36
|
export default {
|
|
16
|
-
...
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
37
|
+
...appConfig,
|
|
38
|
+
webServer: [
|
|
39
|
+
{
|
|
40
|
+
command: "bun run src/index.ts",
|
|
41
|
+
cwd: "../../../apps/puppeteer-service",
|
|
42
|
+
url: `http://127.0.0.1:${PRINT_SERVICE_PORT}/healthz`,
|
|
43
|
+
env: {
|
|
44
|
+
PORT: String(PRINT_SERVICE_PORT),
|
|
45
|
+
PUPPETEER_AUTH_TOKEN: PRINT_SERVICE_TOKEN,
|
|
46
|
+
PUPPETEER_EXECUTABLE_PATH: chromium.executablePath(),
|
|
47
|
+
},
|
|
48
|
+
reuseExistingServer: false,
|
|
49
|
+
timeout: E2E_TIMEOUT_MS.webServer,
|
|
50
|
+
stdout: "pipe",
|
|
51
|
+
stderr: "pipe",
|
|
52
|
+
},
|
|
53
|
+
...[appConfig.webServer ?? []].flat(),
|
|
54
|
+
],
|
|
22
55
|
// globalSetup spawnt vor allen Tests einen bun-Subprozess der die
|
|
23
56
|
// Registry auswertet und `e2e/.e2e-data.json` schreibt. Der eigent-
|
|
24
57
|
// liche generated.spec.ts-Runner liest nur die JSON — framework-
|
|
@@ -18,3 +18,12 @@ export const ADMIN_PASSWORD = "kumiko-admin";
|
|
|
18
18
|
// `as TenantId`-Cast lokal.
|
|
19
19
|
export const DEV_TENANT_ID = "00000000-0000-4000-8000-000000000001";
|
|
20
20
|
export const BETA_TENANT_ID = "00000000-0000-4000-8000-000000000002";
|
|
21
|
+
|
|
22
|
+
// Nordlicht Immobilien GmbH: the tenant the document-designer walkthrough runs
|
|
23
|
+
// in. Both users are new; the admin above stays untouched.
|
|
24
|
+
export const NORDLICHT_TENANT_ID = "00000000-0000-4000-8000-000000000003";
|
|
25
|
+
export const NORDLICHT_TENANT_NAME = "Nordlicht Immobilien GmbH";
|
|
26
|
+
export const TENANT_ADMIN_EMAIL = "a.berger@nordlicht-immobilien.de";
|
|
27
|
+
export const TENANT_ADMIN_PASSWORD = "nordlicht-berger";
|
|
28
|
+
export const PLATFORM_ADMIN_EMAIL = "plattform@kumiko.dev";
|
|
29
|
+
export const PLATFORM_ADMIN_PASSWORD = "kumiko-plattform";
|
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
// übergibt Shell + clientFeatures an createKumikoApp.
|
|
3
3
|
|
|
4
4
|
import { emailPasswordClient } from "@cosmicdrift/kumiko-bundled-features/auth-email-password/web";
|
|
5
|
+
import { textBlocksClient } from "@cosmicdrift/kumiko-bundled-features/template-resolver/web";
|
|
6
|
+
import { documentDesignerClient } from "@cosmicdrift/kumiko-document-designer/web";
|
|
5
7
|
import { localeDeClient } from "@cosmicdrift/kumiko-locale-de/web";
|
|
6
8
|
import { createKumikoApp } from "@cosmicdrift/kumiko-renderer-web";
|
|
9
|
+
import { billingClient } from "../features/billing/web";
|
|
7
10
|
import { rentalClient } from "../features/rental/web";
|
|
8
11
|
import { tasksClient } from "../features/tasks/web";
|
|
9
12
|
import { vehiclesClient } from "../features/vehicles/web";
|
|
@@ -17,5 +20,8 @@ createKumikoApp({
|
|
|
17
20
|
tasksClient,
|
|
18
21
|
rentalClient,
|
|
19
22
|
vehiclesClient,
|
|
23
|
+
billingClient,
|
|
24
|
+
textBlocksClient(),
|
|
25
|
+
documentDesignerClient(),
|
|
20
26
|
],
|
|
21
27
|
});
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
// Nordlicht Immobilien GmbH for the document-designer walkthrough: a tenant
|
|
2
|
+
// admin, a platform admin, branding and a realistic set of mail and PDF
|
|
3
|
+
// templates. Everything goes through the template write handlers (or the
|
|
4
|
+
// system-template seed), never straight into the tables.
|
|
5
|
+
|
|
6
|
+
import { seedAdmin } from "@cosmicdrift/kumiko-bundled-features/auth-email-password/seeding";
|
|
7
|
+
import { BRANDING_QN } from "@cosmicdrift/kumiko-bundled-features/managed-pages";
|
|
8
|
+
import {
|
|
9
|
+
TemplateResolverHandlers,
|
|
10
|
+
TemplateResolverQueries,
|
|
11
|
+
} from "@cosmicdrift/kumiko-bundled-features/template-resolver";
|
|
12
|
+
import type { SeedFn } from "@cosmicdrift/kumiko-dev-server";
|
|
13
|
+
import type { SessionUser, TenantId } from "@cosmicdrift/kumiko-framework/engine";
|
|
14
|
+
import { DEFAULT_MAIL_LAYOUT_MJML } from "@cosmicdrift/kumiko-renderer-mail-html";
|
|
15
|
+
import { readBundledAsset } from "@cosmicdrift/kumiko-server-runtime";
|
|
16
|
+
import {
|
|
17
|
+
NORDLICHT_TENANT_ID,
|
|
18
|
+
NORDLICHT_TENANT_NAME,
|
|
19
|
+
PLATFORM_ADMIN_EMAIL,
|
|
20
|
+
PLATFORM_ADMIN_PASSWORD,
|
|
21
|
+
TENANT_ADMIN_EMAIL,
|
|
22
|
+
TENANT_ADMIN_PASSWORD,
|
|
23
|
+
} from "./auth-constants";
|
|
24
|
+
import {
|
|
25
|
+
INVOICE_CORRECTED_DRAFT,
|
|
26
|
+
INVOICE_ISSUED_DRAFT_VERSIONS,
|
|
27
|
+
LOGO_RESOURCE_KEY,
|
|
28
|
+
PAYMENT_REMINDER_TEMPLATES,
|
|
29
|
+
type SeedTemplate,
|
|
30
|
+
SYSTEM_AUTH_MAILS,
|
|
31
|
+
SYSTEM_INVOICE_DOCUMENTS,
|
|
32
|
+
SYSTEM_INVOICE_ISSUED,
|
|
33
|
+
SYSTEM_PDF_LAYOUT,
|
|
34
|
+
SYSTEM_TENANCY_CERTIFICATE,
|
|
35
|
+
TENANT_INVOICE_OVERRIDES,
|
|
36
|
+
TENANT_MAIL_LAYOUT_VERSIONS,
|
|
37
|
+
TENANT_UTILITY_STATEMENT,
|
|
38
|
+
} from "./template-seed-data";
|
|
39
|
+
|
|
40
|
+
const NORDLICHT = NORDLICHT_TENANT_ID as TenantId;
|
|
41
|
+
|
|
42
|
+
// Declared under `kumiko.assets` in this sample's package.json; looked up from the
|
|
43
|
+
// package dir so the seed does not depend on the cwd the dev server was started in.
|
|
44
|
+
const LOGO_ASSET_NAME = "logo-nordlicht.png";
|
|
45
|
+
const SAMPLE_APP_DIR = new URL("../../", import.meta.url).pathname;
|
|
46
|
+
|
|
47
|
+
const BRANDING = [
|
|
48
|
+
[BRANDING_QN.title, "Nordlicht Mieterportal"],
|
|
49
|
+
[BRANDING_QN.accentColor, "#205265"],
|
|
50
|
+
[BRANDING_QN.siteUrl, "https://nordlicht-immobilien.de"],
|
|
51
|
+
[BRANDING_QN.logoUrl, "https://nordlicht-immobilien.de/logo-nordlicht.png"],
|
|
52
|
+
] as const;
|
|
53
|
+
|
|
54
|
+
export const seedTemplates: SeedFn = async (stack) => {
|
|
55
|
+
const membership = (roles: readonly string[]) => [
|
|
56
|
+
{
|
|
57
|
+
tenantId: NORDLICHT,
|
|
58
|
+
tenantKey: "nordlicht",
|
|
59
|
+
tenantName: NORDLICHT_TENANT_NAME,
|
|
60
|
+
roles,
|
|
61
|
+
},
|
|
62
|
+
];
|
|
63
|
+
const tenantAdminAccount = await seedAdmin(stack.db, {
|
|
64
|
+
email: TENANT_ADMIN_EMAIL,
|
|
65
|
+
password: TENANT_ADMIN_PASSWORD,
|
|
66
|
+
displayName: "A. Berger",
|
|
67
|
+
emailVerified: true,
|
|
68
|
+
memberships: membership(["TenantAdmin"]),
|
|
69
|
+
});
|
|
70
|
+
const platformAdminAccount = await seedAdmin(stack.db, {
|
|
71
|
+
email: PLATFORM_ADMIN_EMAIL,
|
|
72
|
+
password: PLATFORM_ADMIN_PASSWORD,
|
|
73
|
+
displayName: "Plattform-Admin",
|
|
74
|
+
emailVerified: true,
|
|
75
|
+
globalRoles: ["SystemAdmin"],
|
|
76
|
+
memberships: membership(["TenantAdmin"]),
|
|
77
|
+
});
|
|
78
|
+
// The session re-derives roles from the membership row on every request, so
|
|
79
|
+
// the roles here only have to match what the account really has.
|
|
80
|
+
const tenantAdmin: SessionUser = {
|
|
81
|
+
id: tenantAdminAccount.id as SessionUser["id"],
|
|
82
|
+
tenantId: NORDLICHT,
|
|
83
|
+
roles: ["TenantAdmin"],
|
|
84
|
+
};
|
|
85
|
+
const platformAdmin: SessionUser = {
|
|
86
|
+
id: platformAdminAccount.id as SessionUser["id"],
|
|
87
|
+
tenantId: NORDLICHT,
|
|
88
|
+
roles: ["TenantAdmin", "SystemAdmin"],
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const overview = await stack.http.queryOk<{ rows: { origin: string }[] }>(
|
|
92
|
+
TemplateResolverQueries.overview,
|
|
93
|
+
{},
|
|
94
|
+
tenantAdmin,
|
|
95
|
+
);
|
|
96
|
+
if (overview.rows.some((row) => row.origin === "tenant")) return;
|
|
97
|
+
|
|
98
|
+
const upsert = (
|
|
99
|
+
handler: string,
|
|
100
|
+
template: SeedTemplate,
|
|
101
|
+
user: SessionUser,
|
|
102
|
+
extra: Record<string, unknown> = {},
|
|
103
|
+
) =>
|
|
104
|
+
stack.http.writeOk<{ id: string }>(
|
|
105
|
+
handler,
|
|
106
|
+
{
|
|
107
|
+
slug: template.slug,
|
|
108
|
+
kind: template.kind,
|
|
109
|
+
locale: template.locale,
|
|
110
|
+
contentFormat: "html",
|
|
111
|
+
content: template.content,
|
|
112
|
+
...(template.title !== undefined && { title: template.title }),
|
|
113
|
+
...(template.meta !== undefined && { meta: template.meta }),
|
|
114
|
+
...(template.variableSchema !== undefined && { variableSchema: template.variableSchema }),
|
|
115
|
+
...extra,
|
|
116
|
+
},
|
|
117
|
+
user,
|
|
118
|
+
);
|
|
119
|
+
// Real multipart upload; every resource link and the branding logo consume their own file.
|
|
120
|
+
const uploadLogo = async (user: SessionUser): Promise<string> => {
|
|
121
|
+
const logoPng = await readBundledAsset(LOGO_ASSET_NAME, { cwd: SAMPLE_APP_DIR });
|
|
122
|
+
const form = new FormData();
|
|
123
|
+
form.append(
|
|
124
|
+
"file",
|
|
125
|
+
new File([new Uint8Array(logoPng)], LOGO_RESOURCE_KEY, { type: "image/png" }),
|
|
126
|
+
);
|
|
127
|
+
const response = await stack.app.request("/api/files", {
|
|
128
|
+
method: "POST",
|
|
129
|
+
headers: {
|
|
130
|
+
Authorization: `Bearer ${await stack.jwt.sign(user)}`,
|
|
131
|
+
},
|
|
132
|
+
body: form,
|
|
133
|
+
});
|
|
134
|
+
if (response.status !== 201) throw new Error(`logo upload failed: HTTP ${response.status}`);
|
|
135
|
+
return ((await response.json()) as { id: string }).id;
|
|
136
|
+
};
|
|
137
|
+
const linkInvoicePdf = (templateId: string): Promise<unknown> =>
|
|
138
|
+
stack.http.writeOk(
|
|
139
|
+
TemplateResolverHandlers.resourceLinkPdf,
|
|
140
|
+
{
|
|
141
|
+
templateId,
|
|
142
|
+
key: "rechnung",
|
|
143
|
+
templateSlug: "billing:invoice",
|
|
144
|
+
fileName: "rechnung-{{invoiceNumber}}.pdf",
|
|
145
|
+
},
|
|
146
|
+
tenantAdmin,
|
|
147
|
+
);
|
|
148
|
+
const upsertSystem = (template: SeedTemplate) =>
|
|
149
|
+
upsert(TemplateResolverHandlers.upsertSystem, template, platformAdmin);
|
|
150
|
+
const upsertTenant = (template: SeedTemplate, status: "draft" | "active") =>
|
|
151
|
+
upsert(TemplateResolverHandlers.upsertTenant, template, tenantAdmin, { status });
|
|
152
|
+
|
|
153
|
+
await stack.http.writeOk(
|
|
154
|
+
TemplateResolverHandlers.upsertSystem,
|
|
155
|
+
{
|
|
156
|
+
slug: "default",
|
|
157
|
+
kind: "mail-layout",
|
|
158
|
+
locale: "en",
|
|
159
|
+
contentFormat: "mjml",
|
|
160
|
+
content: DEFAULT_MAIL_LAYOUT_MJML,
|
|
161
|
+
title: "Mail-Layout",
|
|
162
|
+
},
|
|
163
|
+
platformAdmin,
|
|
164
|
+
);
|
|
165
|
+
await upsertSystem(SYSTEM_PDF_LAYOUT);
|
|
166
|
+
for (const mail of SYSTEM_AUTH_MAILS) await upsertSystem(mail);
|
|
167
|
+
await upsertSystem(SYSTEM_INVOICE_ISSUED);
|
|
168
|
+
for (const document of SYSTEM_INVOICE_DOCUMENTS) await upsertSystem(document);
|
|
169
|
+
const certificate = await upsertSystem(SYSTEM_TENANCY_CERTIFICATE);
|
|
170
|
+
await stack.http.writeOk(
|
|
171
|
+
TemplateResolverHandlers.archiveSystem,
|
|
172
|
+
{ id: certificate.id },
|
|
173
|
+
platformAdmin,
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
for (const [key, value] of BRANDING) {
|
|
177
|
+
await stack.http.writeOk("config:write:set", { key, value }, tenantAdmin);
|
|
178
|
+
}
|
|
179
|
+
// The built-in "logo" placeholder of the layouts resolves to this file.
|
|
180
|
+
await stack.http.writeOk(
|
|
181
|
+
"config:write:set",
|
|
182
|
+
{ key: BRANDING_QN.logoFile, value: await uploadLogo(tenantAdmin) },
|
|
183
|
+
tenantAdmin,
|
|
184
|
+
);
|
|
185
|
+
// Each save is a new version of the same row; the second one makes the
|
|
186
|
+
// layout "customised" for the overview and the first leaves history to diff.
|
|
187
|
+
for (const content of TENANT_MAIL_LAYOUT_VERSIONS) {
|
|
188
|
+
await upsertTenant(
|
|
189
|
+
{
|
|
190
|
+
slug: "default",
|
|
191
|
+
kind: "mail-layout",
|
|
192
|
+
locale: "en",
|
|
193
|
+
title: "Mail-Layout",
|
|
194
|
+
content,
|
|
195
|
+
meta: { accentLine: "branding" },
|
|
196
|
+
},
|
|
197
|
+
"active",
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
let invoiceDraftId: string | null = null;
|
|
201
|
+
for (const draft of INVOICE_ISSUED_DRAFT_VERSIONS) {
|
|
202
|
+
const saved = await upsertTenant(draft, "draft");
|
|
203
|
+
if (invoiceDraftId === null) {
|
|
204
|
+
invoiceDraftId = saved.id;
|
|
205
|
+
await linkInvoicePdf(saved.id);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
await upsertTenant(INVOICE_CORRECTED_DRAFT, "draft");
|
|
209
|
+
for (const reminder of PAYMENT_REMINDER_TEMPLATES) await upsertTenant(reminder, "active");
|
|
210
|
+
await upsertTenant(TENANT_UTILITY_STATEMENT, "active");
|
|
211
|
+
|
|
212
|
+
// Other tenants with their own invoice copy: what the SystemAdmin sees in the overrides drawer.
|
|
213
|
+
for (const override of TENANT_INVOICE_OVERRIDES) {
|
|
214
|
+
const account = await seedAdmin(stack.db, {
|
|
215
|
+
email: override.adminEmail,
|
|
216
|
+
password: TENANT_ADMIN_PASSWORD,
|
|
217
|
+
displayName: override.adminName,
|
|
218
|
+
emailVerified: true,
|
|
219
|
+
memberships: [
|
|
220
|
+
{
|
|
221
|
+
tenantId: override.tenantId as TenantId,
|
|
222
|
+
tenantKey: override.tenantKey,
|
|
223
|
+
tenantName: override.tenantName,
|
|
224
|
+
roles: ["TenantAdmin"],
|
|
225
|
+
},
|
|
226
|
+
],
|
|
227
|
+
});
|
|
228
|
+
const admin: SessionUser = {
|
|
229
|
+
id: account.id as SessionUser["id"],
|
|
230
|
+
tenantId: override.tenantId as TenantId,
|
|
231
|
+
roles: ["TenantAdmin"],
|
|
232
|
+
};
|
|
233
|
+
for (const version of override.versions) {
|
|
234
|
+
await upsert(TemplateResolverHandlers.upsertTenant, version, admin, {
|
|
235
|
+
status: override.status,
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
};
|
|
@@ -11,10 +11,12 @@
|
|
|
11
11
|
|
|
12
12
|
import { runDevApp } from "@cosmicdrift/kumiko-dev-server";
|
|
13
13
|
import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
|
|
14
|
+
import { createInMemoryFileProvider } from "@cosmicdrift/kumiko-framework/files";
|
|
14
15
|
import { APP_FEATURES } from "../run-config";
|
|
15
16
|
import { ADMIN_EMAIL, ADMIN_PASSWORD, BETA_TENANT_ID, DEV_TENANT_ID } from "./auth-constants";
|
|
16
17
|
import { seedTasks } from "./seed";
|
|
17
18
|
import { seedRental } from "./seed-rental";
|
|
19
|
+
import { seedTemplates } from "./seed-templates";
|
|
18
20
|
import { seedVehicles } from "./seed-vehicles";
|
|
19
21
|
|
|
20
22
|
// Zwei feste Tenants — Admin ist in beiden Mitglied damit der
|
|
@@ -25,10 +27,12 @@ import { seedVehicles } from "./seed-vehicles";
|
|
|
25
27
|
|
|
26
28
|
await runDevApp({
|
|
27
29
|
features: [...APP_FEATURES],
|
|
28
|
-
seeds: [seedTasks, seedRental, seedVehicles],
|
|
30
|
+
seeds: [seedTasks, seedRental, seedVehicles, seedTemplates],
|
|
29
31
|
// PORT env-var override für Playwright-e2e-Runs (config zeigt auf 4174);
|
|
30
32
|
// sonst lokal-Default 4173.
|
|
31
33
|
port: Number.parseInt(process.env["PORT"] ?? "4173", 10),
|
|
34
|
+
// Logo and attachment uploads of the mail editor need a file store.
|
|
35
|
+
files: { storageProvider: createInMemoryFileProvider() },
|
|
32
36
|
clientEntry: "./src/app/client.tsx",
|
|
33
37
|
htmlPath: "./public/index.html",
|
|
34
38
|
watchDirs: ["./src", "../../../packages/*/src"],
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import {
|
|
6
6
|
TenantMenuItems,
|
|
7
7
|
UserMenu,
|
|
8
|
+
useSession,
|
|
8
9
|
} from "@cosmicdrift/kumiko-bundled-features/auth-email-password/web";
|
|
9
10
|
import {
|
|
10
11
|
type AppSchema,
|
|
@@ -18,13 +19,19 @@ import {
|
|
|
18
19
|
import { MoonStar, Sun } from "lucide-react";
|
|
19
20
|
import type { ReactNode } from "react";
|
|
20
21
|
import { AssistantAction } from "./assistant-action";
|
|
21
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
BETA_TENANT_ID,
|
|
24
|
+
DEV_TENANT_ID,
|
|
25
|
+
NORDLICHT_TENANT_ID,
|
|
26
|
+
NORDLICHT_TENANT_NAME,
|
|
27
|
+
} from "./auth-constants";
|
|
22
28
|
|
|
23
29
|
const APP_NAME = "Kumiko Walkthrough";
|
|
24
30
|
|
|
25
31
|
const tenantName = (tenantId: string): string => {
|
|
26
32
|
if (tenantId === DEV_TENANT_ID) return "Dev Tenant";
|
|
27
33
|
if (tenantId === BETA_TENANT_ID) return "Beta Tenant";
|
|
34
|
+
if (tenantId === NORDLICHT_TENANT_ID) return NORDLICHT_TENANT_NAME;
|
|
28
35
|
return tenantId.slice(0, 8);
|
|
29
36
|
};
|
|
30
37
|
|
|
@@ -41,10 +48,14 @@ export function AppShell({
|
|
|
41
48
|
readonly schema: AppSchema;
|
|
42
49
|
}): ReactNode {
|
|
43
50
|
const t = useTranslation();
|
|
51
|
+
const session = useSession();
|
|
52
|
+
// Without the user the shell hides role-gated navs and KumikoScreen denies role-gated screens.
|
|
53
|
+
const user = session.user !== null ? { id: session.user.id, roles: session.roles } : undefined;
|
|
44
54
|
return (
|
|
45
55
|
<DefaultAppShell
|
|
46
56
|
brand={<SidebarBrand name={APP_NAME} plan={t("tasks.shell.tagline")} />}
|
|
47
57
|
schema={schema}
|
|
58
|
+
{...(user !== undefined && { user })}
|
|
48
59
|
headerActions={
|
|
49
60
|
<>
|
|
50
61
|
<AssistantAction />
|