@open-mercato/core 0.6.5-develop.4384.1.ce2ec6eaaa → 0.6.5-develop.4393.1.de282b5dfd
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/.turbo/turbo-build.log +2 -2
- package/dist/generated/entities/channel_ingest_dead_letter/index.js +25 -0
- package/dist/generated/entities/channel_ingest_dead_letter/index.js.map +7 -0
- package/dist/generated/entities/channel_thread_mapping/index.js +25 -0
- package/dist/generated/entities/channel_thread_mapping/index.js.map +7 -0
- package/dist/generated/entities/channel_thread_token/index.js +17 -0
- package/dist/generated/entities/channel_thread_token/index.js.map +7 -0
- package/dist/generated/entities/communication_channel/index.js +43 -0
- package/dist/generated/entities/communication_channel/index.js.map +7 -0
- package/dist/generated/entities/customer_interaction/index.js +4 -0
- package/dist/generated/entities/customer_interaction/index.js.map +2 -2
- package/dist/generated/entities/external_conversation/index.js +25 -0
- package/dist/generated/entities/external_conversation/index.js.map +7 -0
- package/dist/generated/entities/external_message/index.js +25 -0
- package/dist/generated/entities/external_message/index.js.map +7 -0
- package/dist/generated/entities/integration_credentials/index.js +3 -1
- package/dist/generated/entities/integration_credentials/index.js.map +2 -2
- package/dist/generated/entities/message/index.js +2 -0
- package/dist/generated/entities/message/index.js.map +2 -2
- package/dist/generated/entities/message_channel_link/index.js +33 -0
- package/dist/generated/entities/message_channel_link/index.js.map +7 -0
- package/dist/generated/entities/message_reaction/index.js +25 -0
- package/dist/generated/entities/message_reaction/index.js.map +7 -0
- package/dist/generated/entities.ids.generated.js +11 -0
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +117 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/helpers/integration/authFixtures.js +2 -1
- package/dist/helpers/integration/authFixtures.js.map +2 -2
- package/dist/helpers/integration/communicationChannelsFixtures.js +58 -0
- package/dist/helpers/integration/communicationChannelsFixtures.js.map +7 -0
- package/dist/modules/communication_channels/acl.js +47 -0
- package/dist/modules/communication_channels/acl.js.map +7 -0
- package/dist/modules/communication_channels/api/delete/channels/[id]/route.js +133 -0
- package/dist/modules/communication_channels/api/delete/channels/[id]/route.js.map +7 -0
- package/dist/modules/communication_channels/api/delete/messages/[messageId]/reactions/[reactionId]/route.js +113 -0
- package/dist/modules/communication_channels/api/delete/messages/[messageId]/reactions/[reactionId]/route.js.map +7 -0
- package/dist/modules/communication_channels/api/get/channels/[id]/health/route.js +138 -0
- package/dist/modules/communication_channels/api/get/channels/[id]/health/route.js.map +7 -0
- package/dist/modules/communication_channels/api/get/channels/[id]/route.js +93 -0
- package/dist/modules/communication_channels/api/get/channels/[id]/route.js.map +7 -0
- package/dist/modules/communication_channels/api/get/channels/route.js +96 -0
- package/dist/modules/communication_channels/api/get/channels/route.js.map +7 -0
- package/dist/modules/communication_channels/api/get/me/channels/route.js +82 -0
- package/dist/modules/communication_channels/api/get/me/channels/route.js.map +7 -0
- package/dist/modules/communication_channels/api/get/oauth/[provider]/callback/route.js +274 -0
- package/dist/modules/communication_channels/api/get/oauth/[provider]/callback/route.js.map +7 -0
- package/dist/modules/communication_channels/api/post/channels/[id]/import-history/route.js +168 -0
- package/dist/modules/communication_channels/api/post/channels/[id]/import-history/route.js.map +7 -0
- package/dist/modules/communication_channels/api/post/channels/[id]/poll-now/route.js +143 -0
- package/dist/modules/communication_channels/api/post/channels/[id]/poll-now/route.js.map +7 -0
- package/dist/modules/communication_channels/api/post/channels/[id]/push/register/route.js +127 -0
- package/dist/modules/communication_channels/api/post/channels/[id]/push/register/route.js.map +7 -0
- package/dist/modules/communication_channels/api/post/channels/[id]/set-primary/route.js +99 -0
- package/dist/modules/communication_channels/api/post/channels/[id]/set-primary/route.js.map +7 -0
- package/dist/modules/communication_channels/api/post/channels/[id]/test-send/route.js +197 -0
- package/dist/modules/communication_channels/api/post/channels/[id]/test-send/route.js.map +7 -0
- package/dist/modules/communication_channels/api/post/channels/connect/credentials/route.js +124 -0
- package/dist/modules/communication_channels/api/post/channels/connect/credentials/route.js.map +7 -0
- package/dist/modules/communication_channels/api/post/messages/[messageId]/reactions/route.js +120 -0
- package/dist/modules/communication_channels/api/post/messages/[messageId]/reactions/route.js.map +7 -0
- package/dist/modules/communication_channels/api/post/oauth/[provider]/initiate/route.js +157 -0
- package/dist/modules/communication_channels/api/post/oauth/[provider]/initiate/route.js.map +7 -0
- package/dist/modules/communication_channels/api/post/send-as-user/route.js +115 -0
- package/dist/modules/communication_channels/api/post/send-as-user/route.js.map +7 -0
- package/dist/modules/communication_channels/api/post/test-seed/route.js +217 -0
- package/dist/modules/communication_channels/api/post/test-seed/route.js.map +7 -0
- package/dist/modules/communication_channels/api/post/webhook/[provider]/route.js +175 -0
- package/dist/modules/communication_channels/api/post/webhook/[provider]/route.js.map +7 -0
- package/dist/modules/communication_channels/api/post/webhooks/gmail/route.js +123 -0
- package/dist/modules/communication_channels/api/post/webhooks/gmail/route.js.map +7 -0
- package/dist/modules/communication_channels/api/put/threads/[threadId]/assign/route.js +117 -0
- package/dist/modules/communication_channels/api/put/threads/[threadId]/assign/route.js.map +7 -0
- package/dist/modules/communication_channels/backend/communication_channels/channels/[id]/page.js +180 -0
- package/dist/modules/communication_channels/backend/communication_channels/channels/[id]/page.js.map +7 -0
- package/dist/modules/communication_channels/backend/communication_channels/channels/[id]/page.meta.js +36 -0
- package/dist/modules/communication_channels/backend/communication_channels/channels/[id]/page.meta.js.map +7 -0
- package/dist/modules/communication_channels/backend/communication_channels/channels/page.js +107 -0
- package/dist/modules/communication_channels/backend/communication_channels/channels/page.js.map +7 -0
- package/dist/modules/communication_channels/backend/communication_channels/channels/page.meta.js +38 -0
- package/dist/modules/communication_channels/backend/communication_channels/channels/page.meta.js.map +7 -0
- package/dist/modules/communication_channels/backend/profile/communication-channels/page.js +727 -0
- package/dist/modules/communication_channels/backend/profile/communication-channels/page.js.map +7 -0
- package/dist/modules/communication_channels/backend/profile/communication-channels/page.meta.js +38 -0
- package/dist/modules/communication_channels/backend/profile/communication-channels/page.meta.js.map +7 -0
- package/dist/modules/communication_channels/commands/connect-credential-channel.js +154 -0
- package/dist/modules/communication_channels/commands/connect-credential-channel.js.map +7 -0
- package/dist/modules/communication_channels/commands/delete-channel.js +137 -0
- package/dist/modules/communication_channels/commands/delete-channel.js.map +7 -0
- package/dist/modules/communication_channels/commands/deliver-outbound-message.js +400 -0
- package/dist/modules/communication_channels/commands/deliver-outbound-message.js.map +7 -0
- package/dist/modules/communication_channels/commands/disconnect-channel.js +163 -0
- package/dist/modules/communication_channels/commands/disconnect-channel.js.map +7 -0
- package/dist/modules/communication_channels/commands/ingest-inbound-message.js +413 -0
- package/dist/modules/communication_channels/commands/ingest-inbound-message.js.map +7 -0
- package/dist/modules/communication_channels/commands/interceptors.js +68 -0
- package/dist/modules/communication_channels/commands/interceptors.js.map +7 -0
- package/dist/modules/communication_channels/commands/process-inbound-reaction.js +198 -0
- package/dist/modules/communication_channels/commands/process-inbound-reaction.js.map +7 -0
- package/dist/modules/communication_channels/commands/push-register.js +146 -0
- package/dist/modules/communication_channels/commands/push-register.js.map +7 -0
- package/dist/modules/communication_channels/commands/push-renew.js +23 -0
- package/dist/modules/communication_channels/commands/push-renew.js.map +7 -0
- package/dist/modules/communication_channels/commands/push-unregister.js +108 -0
- package/dist/modules/communication_channels/commands/push-unregister.js.map +7 -0
- package/dist/modules/communication_channels/commands/queue-import-history.js +113 -0
- package/dist/modules/communication_channels/commands/queue-import-history.js.map +7 -0
- package/dist/modules/communication_channels/commands/reassign-conversation.js +193 -0
- package/dist/modules/communication_channels/commands/reassign-conversation.js.map +7 -0
- package/dist/modules/communication_channels/commands/set-primary-channel.js +114 -0
- package/dist/modules/communication_channels/commands/set-primary-channel.js.map +7 -0
- package/dist/modules/communication_channels/commands/toggle-outbound-reaction.js +260 -0
- package/dist/modules/communication_channels/commands/toggle-outbound-reaction.js.map +7 -0
- package/dist/modules/communication_channels/data/enrichers.js +286 -0
- package/dist/modules/communication_channels/data/enrichers.js.map +7 -0
- package/dist/modules/communication_channels/data/entities.js +447 -0
- package/dist/modules/communication_channels/data/entities.js.map +7 -0
- package/dist/modules/communication_channels/data/extensions.js +67 -0
- package/dist/modules/communication_channels/data/extensions.js.map +7 -0
- package/dist/modules/communication_channels/data/validators.js +123 -0
- package/dist/modules/communication_channels/data/validators.js.map +7 -0
- package/dist/modules/communication_channels/di.js +35 -0
- package/dist/modules/communication_channels/di.js.map +7 -0
- package/dist/modules/communication_channels/encryption.js +12 -0
- package/dist/modules/communication_channels/encryption.js.map +7 -0
- package/dist/modules/communication_channels/events.js +124 -0
- package/dist/modules/communication_channels/events.js.map +7 -0
- package/dist/modules/communication_channels/index.js +20 -0
- package/dist/modules/communication_channels/index.js.map +7 -0
- package/dist/modules/communication_channels/lib/access-control.js +43 -0
- package/dist/modules/communication_channels/lib/access-control.js.map +7 -0
- package/dist/modules/communication_channels/lib/adapter-compat.js +36 -0
- package/dist/modules/communication_channels/lib/adapter-compat.js.map +7 -0
- package/dist/modules/communication_channels/lib/adapter-registry-singleton.js +22 -0
- package/dist/modules/communication_channels/lib/adapter-registry-singleton.js.map +7 -0
- package/dist/modules/communication_channels/lib/adapter.js +1 -0
- package/dist/modules/communication_channels/lib/adapter.js.map +7 -0
- package/dist/modules/communication_channels/lib/connect-channel.js +95 -0
- package/dist/modules/communication_channels/lib/connect-channel.js.map +7 -0
- package/dist/modules/communication_channels/lib/contact-resolver.js +79 -0
- package/dist/modules/communication_channels/lib/contact-resolver.js.map +7 -0
- package/dist/modules/communication_channels/lib/credential-refresh.js +97 -0
- package/dist/modules/communication_channels/lib/credential-refresh.js.map +7 -0
- package/dist/modules/communication_channels/lib/dead-letter.js +62 -0
- package/dist/modules/communication_channels/lib/dead-letter.js.map +7 -0
- package/dist/modules/communication_channels/lib/email-capabilities.js +47 -0
- package/dist/modules/communication_channels/lib/email-capabilities.js.map +7 -0
- package/dist/modules/communication_channels/lib/email-contact.js +14 -0
- package/dist/modules/communication_channels/lib/email-contact.js.map +7 -0
- package/dist/modules/communication_channels/lib/email-mime.js +259 -0
- package/dist/modules/communication_channels/lib/email-mime.js.map +7 -0
- package/dist/modules/communication_channels/lib/error-classification.js +101 -0
- package/dist/modules/communication_channels/lib/error-classification.js.map +7 -0
- package/dist/modules/communication_channels/lib/gmail-pubsub-jwt.js +185 -0
- package/dist/modules/communication_channels/lib/gmail-pubsub-jwt.js.map +7 -0
- package/dist/modules/communication_channels/lib/mutation-guards.js +114 -0
- package/dist/modules/communication_channels/lib/mutation-guards.js.map +7 -0
- package/dist/modules/communication_channels/lib/oauth-client-config.js +32 -0
- package/dist/modules/communication_channels/lib/oauth-client-config.js.map +7 -0
- package/dist/modules/communication_channels/lib/oauth-state.js +128 -0
- package/dist/modules/communication_channels/lib/oauth-state.js.map +7 -0
- package/dist/modules/communication_channels/lib/oauth-token.js +45 -0
- package/dist/modules/communication_channels/lib/oauth-token.js.map +7 -0
- package/dist/modules/communication_channels/lib/pg-errors.js +11 -0
- package/dist/modules/communication_channels/lib/pg-errors.js.map +7 -0
- package/dist/modules/communication_channels/lib/provider-health.js +24 -0
- package/dist/modules/communication_channels/lib/provider-health.js.map +7 -0
- package/dist/modules/communication_channels/lib/push-state.js +19 -0
- package/dist/modules/communication_channels/lib/push-state.js.map +7 -0
- package/dist/modules/communication_channels/lib/queue.js +54 -0
- package/dist/modules/communication_channels/lib/queue.js.map +7 -0
- package/dist/modules/communication_channels/lib/reaction-processor-types.js +5 -0
- package/dist/modules/communication_channels/lib/reaction-processor-types.js.map +7 -0
- package/dist/modules/communication_channels/lib/reaction-semantics.js +11 -0
- package/dist/modules/communication_channels/lib/reaction-semantics.js.map +7 -0
- package/dist/modules/communication_channels/lib/registry.js +67 -0
- package/dist/modules/communication_channels/lib/registry.js.map +7 -0
- package/dist/modules/communication_channels/lib/route-mutation-guard.js +43 -0
- package/dist/modules/communication_channels/lib/route-mutation-guard.js.map +7 -0
- package/dist/modules/communication_channels/lib/sanitize-channel-html.js +96 -0
- package/dist/modules/communication_channels/lib/sanitize-channel-html.js.map +7 -0
- package/dist/modules/communication_channels/lib/send-as-user.js +194 -0
- package/dist/modules/communication_channels/lib/send-as-user.js.map +7 -0
- package/dist/modules/communication_channels/lib/system-user.js +22 -0
- package/dist/modules/communication_channels/lib/system-user.js.map +7 -0
- package/dist/modules/communication_channels/lib/test-seed.js +68 -0
- package/dist/modules/communication_channels/lib/test-seed.js.map +7 -0
- package/dist/modules/communication_channels/lib/thread-matcher.js +263 -0
- package/dist/modules/communication_channels/lib/thread-matcher.js.map +7 -0
- package/dist/modules/communication_channels/lib/thread-token.js +219 -0
- package/dist/modules/communication_channels/lib/thread-token.js.map +7 -0
- package/dist/modules/communication_channels/lib/use-connect-channel.js +61 -0
- package/dist/modules/communication_channels/lib/use-connect-channel.js.map +7 -0
- package/dist/modules/communication_channels/migrations/Migration20260526134719_communication_channels.js +50 -0
- package/dist/modules/communication_channels/migrations/Migration20260526134719_communication_channels.js.map +7 -0
- package/dist/modules/communication_channels/migrations/Migration20260527195446_communication_channels.js +19 -0
- package/dist/modules/communication_channels/migrations/Migration20260527195446_communication_channels.js.map +7 -0
- package/dist/modules/communication_channels/migrations/Migration20260529231848_communication_channels.js +13 -0
- package/dist/modules/communication_channels/migrations/Migration20260529231848_communication_channels.js.map +7 -0
- package/dist/modules/communication_channels/migrations/Migration20260531120000_communication_channels.js +17 -0
- package/dist/modules/communication_channels/migrations/Migration20260531120000_communication_channels.js.map +7 -0
- package/dist/modules/communication_channels/notifications.client.js +51 -0
- package/dist/modules/communication_channels/notifications.client.js.map +7 -0
- package/dist/modules/communication_channels/notifications.handlers.js +53 -0
- package/dist/modules/communication_channels/notifications.handlers.js.map +7 -0
- package/dist/modules/communication_channels/notifications.js +56 -0
- package/dist/modules/communication_channels/notifications.js.map +7 -0
- package/dist/modules/communication_channels/setup.js +105 -0
- package/dist/modules/communication_channels/setup.js.map +7 -0
- package/dist/modules/communication_channels/subscribers/channel-requires-reauth-notification.js +71 -0
- package/dist/modules/communication_channels/subscribers/channel-requires-reauth-notification.js.map +7 -0
- package/dist/modules/communication_channels/subscribers/outbound-bridge.js +103 -0
- package/dist/modules/communication_channels/subscribers/outbound-bridge.js.map +7 -0
- package/dist/modules/communication_channels/subscribers/user-deleted-cascade.js +51 -0
- package/dist/modules/communication_channels/subscribers/user-deleted-cascade.js.map +7 -0
- package/dist/modules/communication_channels/widgets/components.js +7 -0
- package/dist/modules/communication_channels/widgets/components.js.map +7 -0
- package/dist/modules/communication_channels/widgets/injection/channel-badge/widget.client.js +18 -0
- package/dist/modules/communication_channels/widgets/injection/channel-badge/widget.client.js.map +7 -0
- package/dist/modules/communication_channels/widgets/injection/channel-badge/widget.js +30 -0
- package/dist/modules/communication_channels/widgets/injection/channel-badge/widget.js.map +7 -0
- package/dist/modules/communication_channels/widgets/injection/channel-info-panel/widget.client.js +185 -0
- package/dist/modules/communication_channels/widgets/injection/channel-info-panel/widget.client.js.map +7 -0
- package/dist/modules/communication_channels/widgets/injection/channel-info-panel/widget.js +17 -0
- package/dist/modules/communication_channels/widgets/injection/channel-info-panel/widget.js.map +7 -0
- package/dist/modules/communication_channels/widgets/injection/channel-payload-renderer/widget.client.js +44 -0
- package/dist/modules/communication_channels/widgets/injection/channel-payload-renderer/widget.client.js.map +7 -0
- package/dist/modules/communication_channels/widgets/injection/channel-payload-renderer/widget.js +17 -0
- package/dist/modules/communication_channels/widgets/injection/channel-payload-renderer/widget.js.map +7 -0
- package/dist/modules/communication_channels/widgets/injection/profile-channels-menu/widget.js +23 -0
- package/dist/modules/communication_channels/widgets/injection/profile-channels-menu/widget.js.map +7 -0
- package/dist/modules/communication_channels/widgets/injection/reaction-bar/widget.client.js +141 -0
- package/dist/modules/communication_channels/widgets/injection/reaction-bar/widget.client.js.map +7 -0
- package/dist/modules/communication_channels/widgets/injection/reaction-bar/widget.js +17 -0
- package/dist/modules/communication_channels/widgets/injection/reaction-bar/widget.js.map +7 -0
- package/dist/modules/communication_channels/widgets/injection-table.js +38 -0
- package/dist/modules/communication_channels/widgets/injection-table.js.map +7 -0
- package/dist/modules/communication_channels/widgets/notifications/ChannelRequiresReauthRenderer.js +25 -0
- package/dist/modules/communication_channels/widgets/notifications/ChannelRequiresReauthRenderer.js.map +7 -0
- package/dist/modules/communication_channels/widgets/notifications/MessageReceivedRenderer.js +19 -0
- package/dist/modules/communication_channels/widgets/notifications/MessageReceivedRenderer.js.map +7 -0
- package/dist/modules/communication_channels/widgets/notifications/index.js +7 -0
- package/dist/modules/communication_channels/widgets/notifications/index.js.map +7 -0
- package/dist/modules/communication_channels/workers/channel-import-history.js +185 -0
- package/dist/modules/communication_channels/workers/channel-import-history.js.map +7 -0
- package/dist/modules/communication_channels/workers/gmail-history-sync.js +154 -0
- package/dist/modules/communication_channels/workers/gmail-history-sync.js.map +7 -0
- package/dist/modules/communication_channels/workers/gmail-renew-watch.js +95 -0
- package/dist/modules/communication_channels/workers/gmail-renew-watch.js.map +7 -0
- package/dist/modules/communication_channels/workers/inbound-processor.js +56 -0
- package/dist/modules/communication_channels/workers/inbound-processor.js.map +7 -0
- package/dist/modules/communication_channels/workers/outbound-delivery.js +85 -0
- package/dist/modules/communication_channels/workers/outbound-delivery.js.map +7 -0
- package/dist/modules/communication_channels/workers/poll-channel.js +240 -0
- package/dist/modules/communication_channels/workers/poll-channel.js.map +7 -0
- package/dist/modules/communication_channels/workers/poll-tick.js +132 -0
- package/dist/modules/communication_channels/workers/poll-tick.js.map +7 -0
- package/dist/modules/communication_channels/workers/reaction-processor.js +192 -0
- package/dist/modules/communication_channels/workers/reaction-processor.js.map +7 -0
- package/dist/modules/customers/acl.js +18 -0
- package/dist/modules/customers/acl.js.map +2 -2
- package/dist/modules/customers/api/activities/route.js +9 -0
- package/dist/modules/customers/api/activities/route.js.map +2 -2
- package/dist/modules/customers/api/companies/[id]/route.js +18 -7
- package/dist/modules/customers/api/companies/[id]/route.js.map +2 -2
- package/dist/modules/customers/api/interactions/[id]/visibility/route.js +151 -0
- package/dist/modules/customers/api/interactions/[id]/visibility/route.js.map +7 -0
- package/dist/modules/customers/api/interactions/counts/route.js +6 -0
- package/dist/modules/customers/api/interactions/counts/route.js.map +2 -2
- package/dist/modules/customers/api/interactions/route.js +26 -7
- package/dist/modules/customers/api/interactions/route.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/email-threads/route.js +82 -0
- package/dist/modules/customers/api/people/[id]/email-threads/route.js.map +7 -0
- package/dist/modules/customers/api/people/[id]/emails/route.js +157 -0
- package/dist/modules/customers/api/people/[id]/emails/route.js.map +7 -0
- package/dist/modules/customers/api/people/[id]/route.js +12 -4
- package/dist/modules/customers/api/people/[id]/route.js.map +2 -2
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +10 -0
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/commands/deals.js +46 -5
- package/dist/modules/customers/commands/deals.js.map +2 -2
- package/dist/modules/customers/commands/interactions.js +16 -0
- package/dist/modules/customers/commands/interactions.js.map +2 -2
- package/dist/modules/customers/components/detail/ActivityCard.js +32 -0
- package/dist/modules/customers/components/detail/ActivityCard.js.map +2 -2
- package/dist/modules/customers/components/detail/ComposeEmailDialog.js +242 -0
- package/dist/modules/customers/components/detail/ComposeEmailDialog.js.map +7 -0
- package/dist/modules/customers/components/detail/DealForm.js +2 -1
- package/dist/modules/customers/components/detail/DealForm.js.map +2 -2
- package/dist/modules/customers/components/detail/DealsSection.js +10 -0
- package/dist/modules/customers/components/detail/DealsSection.js.map +2 -2
- package/dist/modules/customers/components/detail/EmailCardActions.js +179 -0
- package/dist/modules/customers/components/detail/EmailCardActions.js.map +7 -0
- package/dist/modules/customers/components/detail/EmailReplyForwardActions.js +52 -0
- package/dist/modules/customers/components/detail/EmailReplyForwardActions.js.map +7 -0
- package/dist/modules/customers/components/detail/PersonDetailTabs.js +7 -1
- package/dist/modules/customers/components/detail/PersonDetailTabs.js.map +2 -2
- package/dist/modules/customers/components/detail/PersonEmailThreadsTab.js +366 -0
- package/dist/modules/customers/components/detail/PersonEmailThreadsTab.js.map +7 -0
- package/dist/modules/customers/data/enrichers.js +133 -2
- package/dist/modules/customers/data/enrichers.js.map +2 -2
- package/dist/modules/customers/data/entities.js +18 -0
- package/dist/modules/customers/data/entities.js.map +2 -2
- package/dist/modules/customers/data/extensions.js +16 -0
- package/dist/modules/customers/data/extensions.js.map +7 -0
- package/dist/modules/customers/encryption.js +11 -0
- package/dist/modules/customers/encryption.js.map +2 -2
- package/dist/modules/customers/events.js +4 -1
- package/dist/modules/customers/events.js.map +2 -2
- package/dist/modules/customers/lib/findPeopleByAddresses.js +64 -0
- package/dist/modules/customers/lib/findPeopleByAddresses.js.map +7 -0
- package/dist/modules/customers/lib/kysely.js.map +2 -2
- package/dist/modules/customers/lib/link-channel-message-handler.js +303 -0
- package/dist/modules/customers/lib/link-channel-message-handler.js.map +7 -0
- package/dist/modules/customers/lib/personEmailThreads.js +205 -0
- package/dist/modules/customers/lib/personEmailThreads.js.map +7 -0
- package/dist/modules/customers/lib/visibilityFilter.js +51 -0
- package/dist/modules/customers/lib/visibilityFilter.js.map +7 -0
- package/dist/modules/customers/migrations/Migration20260527012240_customers.js +20 -0
- package/dist/modules/customers/migrations/Migration20260527012240_customers.js.map +7 -0
- package/dist/modules/customers/setup.js +2 -1
- package/dist/modules/customers/setup.js.map +2 -2
- package/dist/modules/customers/subscribers/link-channel-message-received.js +12 -0
- package/dist/modules/customers/subscribers/link-channel-message-received.js.map +7 -0
- package/dist/modules/customers/subscribers/link-channel-message-sent.js +12 -0
- package/dist/modules/customers/subscribers/link-channel-message-sent.js.map +7 -0
- package/dist/modules/integrations/data/entities.js +8 -1
- package/dist/modules/integrations/data/entities.js.map +2 -2
- package/dist/modules/integrations/lib/credentials-service.js +29 -14
- package/dist/modules/integrations/lib/credentials-service.js.map +2 -2
- package/dist/modules/integrations/migrations/Migration20260526154136_integrations.js +15 -0
- package/dist/modules/integrations/migrations/Migration20260526154136_integrations.js.map +7 -0
- package/dist/modules/messages/commands/messages.js +70 -8
- package/dist/modules/messages/commands/messages.js.map +2 -2
- package/dist/modules/messages/components/ComposeMessagePageClient.js +24 -13
- package/dist/modules/messages/components/ComposeMessagePageClient.js.map +2 -2
- package/dist/modules/messages/components/MessageDetailPageClient.js +39 -2
- package/dist/modules/messages/components/MessageDetailPageClient.js.map +2 -2
- package/dist/modules/messages/components/MessagesInboxPageClient.js +1 -0
- package/dist/modules/messages/components/MessagesInboxPageClient.js.map +2 -2
- package/dist/modules/messages/data/entities.js +8 -1
- package/dist/modules/messages/data/entities.js.map +2 -2
- package/dist/modules/messages/migrations/Migration20260531130000.js +15 -0
- package/dist/modules/messages/migrations/Migration20260531130000.js.map +7 -0
- package/dist/modules/messages/widgets/injection-table.js +7 -0
- package/dist/modules/messages/widgets/injection-table.js.map +7 -0
- package/generated/entities/channel_ingest_dead_letter/index.ts +11 -0
- package/generated/entities/channel_thread_mapping/index.ts +11 -0
- package/generated/entities/channel_thread_token/index.ts +7 -0
- package/generated/entities/communication_channel/index.ts +20 -0
- package/generated/entities/customer_interaction/index.ts +2 -0
- package/generated/entities/external_conversation/index.ts +11 -0
- package/generated/entities/external_message/index.ts +11 -0
- package/generated/entities/integration_credentials/index.ts +1 -0
- package/generated/entities/message/index.ts +1 -0
- package/generated/entities/message_channel_link/index.ts +15 -0
- package/generated/entities/message_reaction/index.ts +11 -0
- package/generated/entities.ids.generated.ts +11 -0
- package/generated/entity-fields-registry.ts +117 -0
- package/package.json +9 -7
- package/src/helpers/integration/authFixtures.ts +4 -1
- package/src/helpers/integration/communicationChannelsFixtures.ts +124 -0
- package/src/modules/communication_channels/acl.ts +43 -0
- package/src/modules/communication_channels/api/delete/channels/[id]/route.ts +163 -0
- package/src/modules/communication_channels/api/delete/messages/[messageId]/reactions/[reactionId]/route.ts +143 -0
- package/src/modules/communication_channels/api/get/channels/[id]/health/route.ts +173 -0
- package/src/modules/communication_channels/api/get/channels/[id]/route.ts +111 -0
- package/src/modules/communication_channels/api/get/channels/route.ts +109 -0
- package/src/modules/communication_channels/api/get/me/channels/route.ts +100 -0
- package/src/modules/communication_channels/api/get/oauth/[provider]/callback/route.ts +355 -0
- package/src/modules/communication_channels/api/post/channels/[id]/import-history/route.ts +206 -0
- package/src/modules/communication_channels/api/post/channels/[id]/poll-now/route.ts +174 -0
- package/src/modules/communication_channels/api/post/channels/[id]/push/register/route.ts +158 -0
- package/src/modules/communication_channels/api/post/channels/[id]/set-primary/route.ts +114 -0
- package/src/modules/communication_channels/api/post/channels/[id]/test-send/route.ts +241 -0
- package/src/modules/communication_channels/api/post/channels/connect/credentials/route.ts +134 -0
- package/src/modules/communication_channels/api/post/messages/[messageId]/reactions/route.ts +143 -0
- package/src/modules/communication_channels/api/post/oauth/[provider]/initiate/route.ts +192 -0
- package/src/modules/communication_channels/api/post/send-as-user/route.ts +125 -0
- package/src/modules/communication_channels/api/post/test-seed/route.ts +267 -0
- package/src/modules/communication_channels/api/post/webhook/[provider]/route.ts +227 -0
- package/src/modules/communication_channels/api/post/webhooks/gmail/route.ts +161 -0
- package/src/modules/communication_channels/api/put/threads/[threadId]/assign/route.ts +132 -0
- package/src/modules/communication_channels/backend/communication_channels/channels/[id]/page.meta.ts +34 -0
- package/src/modules/communication_channels/backend/communication_channels/channels/[id]/page.tsx +250 -0
- package/src/modules/communication_channels/backend/communication_channels/channels/page.meta.ts +36 -0
- package/src/modules/communication_channels/backend/communication_channels/channels/page.tsx +137 -0
- package/src/modules/communication_channels/backend/profile/communication-channels/page.meta.ts +36 -0
- package/src/modules/communication_channels/backend/profile/communication-channels/page.tsx +907 -0
- package/src/modules/communication_channels/commands/connect-credential-channel.ts +243 -0
- package/src/modules/communication_channels/commands/delete-channel.ts +193 -0
- package/src/modules/communication_channels/commands/deliver-outbound-message.ts +579 -0
- package/src/modules/communication_channels/commands/disconnect-channel.ts +241 -0
- package/src/modules/communication_channels/commands/ingest-inbound-message.ts +602 -0
- package/src/modules/communication_channels/commands/interceptors.ts +104 -0
- package/src/modules/communication_channels/commands/process-inbound-reaction.ts +265 -0
- package/src/modules/communication_channels/commands/push-register.ts +203 -0
- package/src/modules/communication_channels/commands/push-renew.ts +49 -0
- package/src/modules/communication_channels/commands/push-unregister.ts +168 -0
- package/src/modules/communication_channels/commands/queue-import-history.ts +180 -0
- package/src/modules/communication_channels/commands/reassign-conversation.ts +273 -0
- package/src/modules/communication_channels/commands/set-primary-channel.ts +154 -0
- package/src/modules/communication_channels/commands/toggle-outbound-reaction.ts +347 -0
- package/src/modules/communication_channels/data/enrichers.ts +413 -0
- package/src/modules/communication_channels/data/entities.ts +546 -0
- package/src/modules/communication_channels/data/extensions.ts +76 -0
- package/src/modules/communication_channels/data/validators.ts +138 -0
- package/src/modules/communication_channels/di.ts +40 -0
- package/src/modules/communication_channels/encryption.ts +44 -0
- package/src/modules/communication_channels/events.ts +122 -0
- package/src/modules/communication_channels/i18n/de.json +138 -0
- package/src/modules/communication_channels/i18n/en.json +138 -0
- package/src/modules/communication_channels/i18n/es.json +138 -0
- package/src/modules/communication_channels/i18n/pl.json +138 -0
- package/src/modules/communication_channels/index.ts +19 -0
- package/src/modules/communication_channels/lib/access-control.ts +110 -0
- package/src/modules/communication_channels/lib/adapter-compat.ts +57 -0
- package/src/modules/communication_channels/lib/adapter-registry-singleton.ts +35 -0
- package/src/modules/communication_channels/lib/adapter.ts +605 -0
- package/src/modules/communication_channels/lib/connect-channel.ts +163 -0
- package/src/modules/communication_channels/lib/contact-resolver.ts +162 -0
- package/src/modules/communication_channels/lib/credential-refresh.ts +197 -0
- package/src/modules/communication_channels/lib/dead-letter.ts +87 -0
- package/src/modules/communication_channels/lib/email-capabilities.ts +60 -0
- package/src/modules/communication_channels/lib/email-contact.ts +17 -0
- package/src/modules/communication_channels/lib/email-mime.ts +425 -0
- package/src/modules/communication_channels/lib/error-classification.ts +144 -0
- package/src/modules/communication_channels/lib/gmail-pubsub-jwt.ts +278 -0
- package/src/modules/communication_channels/lib/mutation-guards.ts +215 -0
- package/src/modules/communication_channels/lib/oauth-client-config.ts +79 -0
- package/src/modules/communication_channels/lib/oauth-state.ts +228 -0
- package/src/modules/communication_channels/lib/oauth-token.ts +81 -0
- package/src/modules/communication_channels/lib/pg-errors.ts +12 -0
- package/src/modules/communication_channels/lib/provider-health.ts +47 -0
- package/src/modules/communication_channels/lib/push-state.ts +38 -0
- package/src/modules/communication_channels/lib/queue.ts +66 -0
- package/src/modules/communication_channels/lib/reaction-processor-types.ts +51 -0
- package/src/modules/communication_channels/lib/reaction-semantics.ts +48 -0
- package/src/modules/communication_channels/lib/registry.ts +99 -0
- package/src/modules/communication_channels/lib/route-mutation-guard.ts +68 -0
- package/src/modules/communication_channels/lib/sanitize-channel-html.ts +129 -0
- package/src/modules/communication_channels/lib/send-as-user.ts +284 -0
- package/src/modules/communication_channels/lib/system-user.ts +74 -0
- package/src/modules/communication_channels/lib/test-seed.ts +140 -0
- package/src/modules/communication_channels/lib/thread-matcher.ts +430 -0
- package/src/modules/communication_channels/lib/thread-token.ts +355 -0
- package/src/modules/communication_channels/lib/use-connect-channel.ts +73 -0
- package/src/modules/communication_channels/migrations/.snapshot-open-mercato.json +2142 -0
- package/src/modules/communication_channels/migrations/Migration20260526134719_communication_channels.ts +55 -0
- package/src/modules/communication_channels/migrations/Migration20260527195446_communication_channels.ts +20 -0
- package/src/modules/communication_channels/migrations/Migration20260529231848_communication_channels.ts +13 -0
- package/src/modules/communication_channels/migrations/Migration20260531120000_communication_channels.ts +24 -0
- package/src/modules/communication_channels/notifications.client.ts +50 -0
- package/src/modules/communication_channels/notifications.handlers.ts +86 -0
- package/src/modules/communication_channels/notifications.ts +52 -0
- package/src/modules/communication_channels/setup.ts +158 -0
- package/src/modules/communication_channels/subscribers/channel-requires-reauth-notification.ts +118 -0
- package/src/modules/communication_channels/subscribers/outbound-bridge.ts +175 -0
- package/src/modules/communication_channels/subscribers/user-deleted-cascade.ts +100 -0
- package/src/modules/communication_channels/widgets/components.ts +36 -0
- package/src/modules/communication_channels/widgets/injection/channel-badge/widget.client.tsx +38 -0
- package/src/modules/communication_channels/widgets/injection/channel-badge/widget.ts +51 -0
- package/src/modules/communication_channels/widgets/injection/channel-info-panel/widget.client.tsx +278 -0
- package/src/modules/communication_channels/widgets/injection/channel-info-panel/widget.ts +24 -0
- package/src/modules/communication_channels/widgets/injection/channel-payload-renderer/widget.client.tsx +63 -0
- package/src/modules/communication_channels/widgets/injection/channel-payload-renderer/widget.ts +29 -0
- package/src/modules/communication_channels/widgets/injection/profile-channels-menu/widget.ts +34 -0
- package/src/modules/communication_channels/widgets/injection/reaction-bar/widget.client.tsx +177 -0
- package/src/modules/communication_channels/widgets/injection/reaction-bar/widget.ts +26 -0
- package/src/modules/communication_channels/widgets/injection-table.ts +47 -0
- package/src/modules/communication_channels/widgets/notifications/ChannelRequiresReauthRenderer.tsx +48 -0
- package/src/modules/communication_channels/widgets/notifications/MessageReceivedRenderer.tsx +45 -0
- package/src/modules/communication_channels/widgets/notifications/index.ts +2 -0
- package/src/modules/communication_channels/workers/channel-import-history.ts +252 -0
- package/src/modules/communication_channels/workers/gmail-history-sync.ts +223 -0
- package/src/modules/communication_channels/workers/gmail-renew-watch.ts +141 -0
- package/src/modules/communication_channels/workers/inbound-processor.ts +114 -0
- package/src/modules/communication_channels/workers/outbound-delivery.ts +155 -0
- package/src/modules/communication_channels/workers/poll-channel.ts +391 -0
- package/src/modules/communication_channels/workers/poll-tick.ts +210 -0
- package/src/modules/communication_channels/workers/reaction-processor.ts +264 -0
- package/src/modules/customers/acl.ts +18 -0
- package/src/modules/customers/api/activities/route.ts +13 -0
- package/src/modules/customers/api/companies/[id]/route.ts +21 -1
- package/src/modules/customers/api/interactions/[id]/visibility/route.ts +179 -0
- package/src/modules/customers/api/interactions/counts/route.ts +10 -0
- package/src/modules/customers/api/interactions/route.ts +51 -5
- package/src/modules/customers/api/people/[id]/email-threads/route.ts +92 -0
- package/src/modules/customers/api/people/[id]/emails/route.ts +184 -0
- package/src/modules/customers/api/people/[id]/route.ts +17 -2
- package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +11 -1
- package/src/modules/customers/commands/deals.ts +65 -6
- package/src/modules/customers/commands/interactions.ts +30 -0
- package/src/modules/customers/components/detail/ActivityCard.tsx +48 -0
- package/src/modules/customers/components/detail/ComposeEmailDialog.tsx +329 -0
- package/src/modules/customers/components/detail/DealForm.tsx +2 -1
- package/src/modules/customers/components/detail/DealsSection.tsx +26 -0
- package/src/modules/customers/components/detail/EmailCardActions.tsx +258 -0
- package/src/modules/customers/components/detail/EmailReplyForwardActions.tsx +53 -0
- package/src/modules/customers/components/detail/PersonDetailTabs.tsx +8 -1
- package/src/modules/customers/components/detail/PersonEmailThreadsTab.tsx +448 -0
- package/src/modules/customers/data/enrichers.ts +252 -1
- package/src/modules/customers/data/entities.ts +46 -1
- package/src/modules/customers/data/extensions.ts +26 -0
- package/src/modules/customers/encryption.ts +11 -0
- package/src/modules/customers/events.ts +4 -0
- package/src/modules/customers/i18n/de.json +41 -0
- package/src/modules/customers/i18n/en.json +41 -0
- package/src/modules/customers/i18n/es.json +41 -0
- package/src/modules/customers/i18n/pl.json +41 -0
- package/src/modules/customers/lib/findPeopleByAddresses.ts +107 -0
- package/src/modules/customers/lib/kysely.ts +16 -0
- package/src/modules/customers/lib/link-channel-message-handler.ts +571 -0
- package/src/modules/customers/lib/personEmailThreads.ts +325 -0
- package/src/modules/customers/lib/visibilityFilter.ts +152 -0
- package/src/modules/customers/migrations/.snapshot-open-mercato.json +61 -0
- package/src/modules/customers/migrations/Migration20260527012240_customers.ts +23 -0
- package/src/modules/customers/setup.ts +1 -0
- package/src/modules/customers/subscribers/link-channel-message-received.ts +21 -0
- package/src/modules/customers/subscribers/link-channel-message-sent.ts +21 -0
- package/src/modules/integrations/AGENTS.md +9 -0
- package/src/modules/integrations/data/entities.ts +21 -1
- package/src/modules/integrations/lib/credentials-service.ts +49 -13
- package/src/modules/integrations/migrations/.snapshot-open-mercato.json +26 -1
- package/src/modules/integrations/migrations/Migration20260526154136_integrations.ts +15 -0
- package/src/modules/messages/commands/messages.ts +101 -8
- package/src/modules/messages/components/ComposeMessagePageClient.tsx +17 -0
- package/src/modules/messages/components/MessageDetailPageClient.tsx +43 -0
- package/src/modules/messages/components/MessagesInboxPageClient.tsx +4 -0
- package/src/modules/messages/data/entities.ts +11 -0
- package/src/modules/messages/migrations/.snapshot-open-mercato.json +18 -0
- package/src/modules/messages/migrations/Migration20260531130000.ts +15 -0
- package/src/modules/messages/widgets/injection-table.ts +29 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Migration } from "@mikro-orm/migrations";
|
|
2
|
+
class Migration20260526134719_communication_channels extends Migration {
|
|
3
|
+
up() {
|
|
4
|
+
this.addSql(`create table "channel_thread_mappings" ("id" uuid not null default gen_random_uuid(), "external_conversation_id" uuid not null, "message_thread_id" uuid not null, "channel_id" uuid not null, "provider_key" text not null, "external_thread_ref" text not null, "assigned_user_id" uuid null, "tenant_id" uuid not null, "organization_id" uuid null, "created_at" timestamptz not null, "updated_at" timestamptz not null, primary key ("id"));`);
|
|
5
|
+
this.addSql(`create index "channel_thread_mappings_thread_idx" on "channel_thread_mappings" ("message_thread_id", "tenant_id");`);
|
|
6
|
+
this.addSql(`create index "channel_thread_mappings_ext_conv_idx" on "channel_thread_mappings" ("external_conversation_id", "tenant_id");`);
|
|
7
|
+
this.addSql(`alter table "channel_thread_mappings" add constraint "channel_thread_mappings_ext_conv_uq" unique ("external_conversation_id", "tenant_id");`);
|
|
8
|
+
this.addSql(`create table "communication_channels" ("id" uuid not null default gen_random_uuid(), "provider_key" text not null, "channel_type" text not null, "display_name" text not null, "external_identifier" text null, "credentials_ref" uuid null, "capabilities" jsonb null, "is_active" boolean not null default true, "user_id" uuid null, "is_primary" boolean not null default false, "poll_interval_seconds" int null, "last_polled_at" timestamptz null, "status" text not null default 'connected', "last_error" text null, "channel_state" jsonb null, "tenant_id" uuid not null, "organization_id" uuid null, "created_at" timestamptz not null, "updated_at" timestamptz not null, "deleted_at" timestamptz null, primary key ("id"));`);
|
|
9
|
+
this.addSql(`create index "communication_channels_tenant_type_active_idx" on "communication_channels" ("tenant_id", "channel_type", "is_active");`);
|
|
10
|
+
this.addSql(`create index "communication_channels_tenant_provider_idx" on "communication_channels" ("tenant_id", "provider_key");`);
|
|
11
|
+
this.addSql(`create unique index "communication_channels_one_primary_per_user_uq" on "communication_channels" ("user_id") where "is_primary" and "user_id" is not null and "deleted_at" is null;`);
|
|
12
|
+
this.addSql(`create index "communication_channels_poll_due_idx" on "communication_channels" ("is_active", "last_polled_at") where "deleted_at" is null;`);
|
|
13
|
+
this.addSql(`create index "communication_channels_user_lookup_idx" on "communication_channels" ("user_id", "channel_type", "deleted_at");`);
|
|
14
|
+
this.addSql(`create table "external_conversations" ("id" uuid not null default gen_random_uuid(), "channel_id" uuid not null, "external_conversation_id" text not null, "subject" text null, "contact_person_id" uuid null, "assigned_user_id" uuid null, "last_message_at" timestamptz null, "tenant_id" uuid not null, "organization_id" uuid null, "created_at" timestamptz not null, "updated_at" timestamptz not null, primary key ("id"));`);
|
|
15
|
+
this.addSql(`create index "external_conversations_assigned_user_idx" on "external_conversations" ("assigned_user_id");`);
|
|
16
|
+
this.addSql(`create index "external_conversations_contact_person_idx" on "external_conversations" ("contact_person_id");`);
|
|
17
|
+
this.addSql(`create index "external_conversations_channel_idx" on "external_conversations" ("channel_id", "external_conversation_id");`);
|
|
18
|
+
this.addSql(`alter table "external_conversations" add constraint "external_conversations_channel_external_uq" unique ("channel_id", "external_conversation_id");`);
|
|
19
|
+
this.addSql(`create table "external_messages" ("id" uuid not null default gen_random_uuid(), "channel_id" uuid not null, "conversation_id" uuid not null, "external_message_id" text not null, "direction" text not null, "sender_identifier" text null, "sender_display_name" text null, "provider_timestamp" timestamptz null, "tenant_id" uuid not null, "organization_id" uuid null, "created_at" timestamptz not null, primary key ("id"));`);
|
|
20
|
+
this.addSql(`create index "external_messages_channel_external_idx" on "external_messages" ("channel_id", "external_message_id");`);
|
|
21
|
+
this.addSql(`create index "external_messages_conversation_idx" on "external_messages" ("conversation_id");`);
|
|
22
|
+
this.addSql(`alter table "external_messages" add constraint "external_messages_channel_external_uq" unique ("channel_id", "external_message_id");`);
|
|
23
|
+
this.addSql(`create table "message_channel_links" ("id" uuid not null default gen_random_uuid(), "message_id" uuid not null, "external_conversation_id" uuid not null, "external_message_id" uuid null, "provider_key" text not null, "channel_type" text not null, "direction" text not null, "delivery_status" text not null default 'pending', "channel_payload" jsonb null, "channel_content_type" text null, "interactive_state" jsonb null, "channel_metadata" jsonb null, "tenant_id" uuid not null, "organization_id" uuid null, "created_at" timestamptz not null, primary key ("id"));`);
|
|
24
|
+
this.addSql(`create index "message_channel_links_ext_msg_idx" on "message_channel_links" ("external_message_id");`);
|
|
25
|
+
this.addSql(`create index "message_channel_links_ext_conv_idx" on "message_channel_links" ("external_conversation_id");`);
|
|
26
|
+
this.addSql(`create index "message_channel_links_message_idx" on "message_channel_links" ("message_id");`);
|
|
27
|
+
this.addSql(`alter table "message_channel_links" add constraint "message_channel_links_message_uq" unique ("message_id");`);
|
|
28
|
+
this.addSql(`create table "message_reactions" ("id" uuid not null default gen_random_uuid(), "message_id" uuid not null, "emoji" text not null, "reacted_by_user_id" uuid null, "reacted_by_external_id" text null, "reacted_by_display_name" text null, "provider_key" text null, "external_reaction_id" text null, "tenant_id" uuid not null, "organization_id" uuid null, "created_at" timestamptz not null, primary key ("id"));`);
|
|
29
|
+
this.addSql(`alter table "message_reactions" add constraint "message_reactions_exactly_one_actor_chk" check (("reacted_by_user_id" is null) <> ("reacted_by_external_id" is null));`);
|
|
30
|
+
this.addSql(`create index "message_reactions_message_emoji_idx" on "message_reactions" ("message_id", "emoji");`);
|
|
31
|
+
this.addSql(`create index "message_reactions_message_idx" on "message_reactions" ("message_id");`);
|
|
32
|
+
this.addSql(`create unique index "message_reactions_external_actor_uq" on "message_reactions" ("tenant_id", "message_id", "emoji", "reacted_by_external_id") where "reacted_by_external_id" is not null;`);
|
|
33
|
+
this.addSql(`create unique index "message_reactions_internal_actor_uq" on "message_reactions" ("tenant_id", "message_id", "emoji", "reacted_by_user_id") where "reacted_by_user_id" is not null;`);
|
|
34
|
+
}
|
|
35
|
+
down() {
|
|
36
|
+
this.addSql(`drop table if exists "message_reactions";`);
|
|
37
|
+
this.addSql(`drop table if exists "message_channel_links";`);
|
|
38
|
+
this.addSql(`drop table if exists "external_messages";`);
|
|
39
|
+
this.addSql(`drop table if exists "external_conversations";`);
|
|
40
|
+
this.addSql(`drop index if exists "communication_channels_user_lookup_idx";`);
|
|
41
|
+
this.addSql(`drop index if exists "communication_channels_poll_due_idx";`);
|
|
42
|
+
this.addSql(`drop index if exists "communication_channels_one_primary_per_user_uq";`);
|
|
43
|
+
this.addSql(`drop table if exists "communication_channels";`);
|
|
44
|
+
this.addSql(`drop table if exists "channel_thread_mappings";`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export {
|
|
48
|
+
Migration20260526134719_communication_channels
|
|
49
|
+
};
|
|
50
|
+
//# sourceMappingURL=Migration20260526134719_communication_channels.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/communication_channels/migrations/Migration20260526134719_communication_channels.ts"],
|
|
4
|
+
"sourcesContent": ["import { Migration } from '@mikro-orm/migrations';\n\nexport class Migration20260526134719_communication_channels extends Migration {\n\n override up(): void | Promise<void> {\n this.addSql(`create table \"channel_thread_mappings\" (\"id\" uuid not null default gen_random_uuid(), \"external_conversation_id\" uuid not null, \"message_thread_id\" uuid not null, \"channel_id\" uuid not null, \"provider_key\" text not null, \"external_thread_ref\" text not null, \"assigned_user_id\" uuid null, \"tenant_id\" uuid not null, \"organization_id\" uuid null, \"created_at\" timestamptz not null, \"updated_at\" timestamptz not null, primary key (\"id\"));`);\n this.addSql(`create index \"channel_thread_mappings_thread_idx\" on \"channel_thread_mappings\" (\"message_thread_id\", \"tenant_id\");`);\n this.addSql(`create index \"channel_thread_mappings_ext_conv_idx\" on \"channel_thread_mappings\" (\"external_conversation_id\", \"tenant_id\");`);\n this.addSql(`alter table \"channel_thread_mappings\" add constraint \"channel_thread_mappings_ext_conv_uq\" unique (\"external_conversation_id\", \"tenant_id\");`);\n\n this.addSql(`create table \"communication_channels\" (\"id\" uuid not null default gen_random_uuid(), \"provider_key\" text not null, \"channel_type\" text not null, \"display_name\" text not null, \"external_identifier\" text null, \"credentials_ref\" uuid null, \"capabilities\" jsonb null, \"is_active\" boolean not null default true, \"user_id\" uuid null, \"is_primary\" boolean not null default false, \"poll_interval_seconds\" int null, \"last_polled_at\" timestamptz null, \"status\" text not null default 'connected', \"last_error\" text null, \"channel_state\" jsonb null, \"tenant_id\" uuid not null, \"organization_id\" uuid null, \"created_at\" timestamptz not null, \"updated_at\" timestamptz not null, \"deleted_at\" timestamptz null, primary key (\"id\"));`);\n this.addSql(`create index \"communication_channels_tenant_type_active_idx\" on \"communication_channels\" (\"tenant_id\", \"channel_type\", \"is_active\");`);\n this.addSql(`create index \"communication_channels_tenant_provider_idx\" on \"communication_channels\" (\"tenant_id\", \"provider_key\");`);\n this.addSql(`create unique index \"communication_channels_one_primary_per_user_uq\" on \"communication_channels\" (\"user_id\") where \"is_primary\" and \"user_id\" is not null and \"deleted_at\" is null;`);\n this.addSql(`create index \"communication_channels_poll_due_idx\" on \"communication_channels\" (\"is_active\", \"last_polled_at\") where \"deleted_at\" is null;`);\n this.addSql(`create index \"communication_channels_user_lookup_idx\" on \"communication_channels\" (\"user_id\", \"channel_type\", \"deleted_at\");`);\n\n this.addSql(`create table \"external_conversations\" (\"id\" uuid not null default gen_random_uuid(), \"channel_id\" uuid not null, \"external_conversation_id\" text not null, \"subject\" text null, \"contact_person_id\" uuid null, \"assigned_user_id\" uuid null, \"last_message_at\" timestamptz null, \"tenant_id\" uuid not null, \"organization_id\" uuid null, \"created_at\" timestamptz not null, \"updated_at\" timestamptz not null, primary key (\"id\"));`);\n this.addSql(`create index \"external_conversations_assigned_user_idx\" on \"external_conversations\" (\"assigned_user_id\");`);\n this.addSql(`create index \"external_conversations_contact_person_idx\" on \"external_conversations\" (\"contact_person_id\");`);\n this.addSql(`create index \"external_conversations_channel_idx\" on \"external_conversations\" (\"channel_id\", \"external_conversation_id\");`);\n this.addSql(`alter table \"external_conversations\" add constraint \"external_conversations_channel_external_uq\" unique (\"channel_id\", \"external_conversation_id\");`);\n\n this.addSql(`create table \"external_messages\" (\"id\" uuid not null default gen_random_uuid(), \"channel_id\" uuid not null, \"conversation_id\" uuid not null, \"external_message_id\" text not null, \"direction\" text not null, \"sender_identifier\" text null, \"sender_display_name\" text null, \"provider_timestamp\" timestamptz null, \"tenant_id\" uuid not null, \"organization_id\" uuid null, \"created_at\" timestamptz not null, primary key (\"id\"));`);\n this.addSql(`create index \"external_messages_channel_external_idx\" on \"external_messages\" (\"channel_id\", \"external_message_id\");`);\n this.addSql(`create index \"external_messages_conversation_idx\" on \"external_messages\" (\"conversation_id\");`);\n this.addSql(`alter table \"external_messages\" add constraint \"external_messages_channel_external_uq\" unique (\"channel_id\", \"external_message_id\");`);\n\n this.addSql(`create table \"message_channel_links\" (\"id\" uuid not null default gen_random_uuid(), \"message_id\" uuid not null, \"external_conversation_id\" uuid not null, \"external_message_id\" uuid null, \"provider_key\" text not null, \"channel_type\" text not null, \"direction\" text not null, \"delivery_status\" text not null default 'pending', \"channel_payload\" jsonb null, \"channel_content_type\" text null, \"interactive_state\" jsonb null, \"channel_metadata\" jsonb null, \"tenant_id\" uuid not null, \"organization_id\" uuid null, \"created_at\" timestamptz not null, primary key (\"id\"));`);\n this.addSql(`create index \"message_channel_links_ext_msg_idx\" on \"message_channel_links\" (\"external_message_id\");`);\n this.addSql(`create index \"message_channel_links_ext_conv_idx\" on \"message_channel_links\" (\"external_conversation_id\");`);\n this.addSql(`create index \"message_channel_links_message_idx\" on \"message_channel_links\" (\"message_id\");`);\n this.addSql(`alter table \"message_channel_links\" add constraint \"message_channel_links_message_uq\" unique (\"message_id\");`);\n\n this.addSql(`create table \"message_reactions\" (\"id\" uuid not null default gen_random_uuid(), \"message_id\" uuid not null, \"emoji\" text not null, \"reacted_by_user_id\" uuid null, \"reacted_by_external_id\" text null, \"reacted_by_display_name\" text null, \"provider_key\" text null, \"external_reaction_id\" text null, \"tenant_id\" uuid not null, \"organization_id\" uuid null, \"created_at\" timestamptz not null, primary key (\"id\"));`);\n this.addSql(`alter table \"message_reactions\" add constraint \"message_reactions_exactly_one_actor_chk\" check ((\"reacted_by_user_id\" is null) <> (\"reacted_by_external_id\" is null));`);\n this.addSql(`create index \"message_reactions_message_emoji_idx\" on \"message_reactions\" (\"message_id\", \"emoji\");`);\n this.addSql(`create index \"message_reactions_message_idx\" on \"message_reactions\" (\"message_id\");`);\n this.addSql(`create unique index \"message_reactions_external_actor_uq\" on \"message_reactions\" (\"tenant_id\", \"message_id\", \"emoji\", \"reacted_by_external_id\") where \"reacted_by_external_id\" is not null;`);\n this.addSql(`create unique index \"message_reactions_internal_actor_uq\" on \"message_reactions\" (\"tenant_id\", \"message_id\", \"emoji\", \"reacted_by_user_id\") where \"reacted_by_user_id\" is not null;`);\n }\n\n override down(): void | Promise<void> {\n this.addSql(`drop table if exists \"message_reactions\";`);\n this.addSql(`drop table if exists \"message_channel_links\";`);\n this.addSql(`drop table if exists \"external_messages\";`);\n this.addSql(`drop table if exists \"external_conversations\";`);\n this.addSql(`drop index if exists \"communication_channels_user_lookup_idx\";`);\n this.addSql(`drop index if exists \"communication_channels_poll_due_idx\";`);\n this.addSql(`drop index if exists \"communication_channels_one_primary_per_user_uq\";`);\n this.addSql(`drop table if exists \"communication_channels\";`);\n this.addSql(`drop table if exists \"channel_thread_mappings\";`);\n }\n\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,iBAAiB;AAEnB,MAAM,uDAAuD,UAAU;AAAA,EAEnE,KAA2B;AAClC,SAAK,OAAO,obAAob;AAChc,SAAK,OAAO,oHAAoH;AAChI,SAAK,OAAO,6HAA6H;AACzI,SAAK,OAAO,8IAA8I;AAE1J,SAAK,OAAO,6sBAA6sB;AACztB,SAAK,OAAO,sIAAsI;AAClJ,SAAK,OAAO,sHAAsH;AAClI,SAAK,OAAO,qLAAqL;AACjM,SAAK,OAAO,4IAA4I;AACxJ,SAAK,OAAO,8HAA8H;AAE1I,SAAK,OAAO,qaAAqa;AACjb,SAAK,OAAO,2GAA2G;AACvH,SAAK,OAAO,6GAA6G;AACzH,SAAK,OAAO,2HAA2H;AACvI,SAAK,OAAO,qJAAqJ;AAEjK,SAAK,OAAO,qaAAqa;AACjb,SAAK,OAAO,qHAAqH;AACjI,SAAK,OAAO,+FAA+F;AAC3G,SAAK,OAAO,sIAAsI;AAElJ,SAAK,OAAO,qjBAAqjB;AACjkB,SAAK,OAAO,sGAAsG;AAClH,SAAK,OAAO,4GAA4G;AACxH,SAAK,OAAO,6FAA6F;AACzG,SAAK,OAAO,8GAA8G;AAE1H,SAAK,OAAO,yZAAyZ;AACra,SAAK,OAAO,wKAAwK;AACpL,SAAK,OAAO,oGAAoG;AAChH,SAAK,OAAO,qFAAqF;AACjG,SAAK,OAAO,6LAA6L;AACzM,SAAK,OAAO,qLAAqL;AAAA,EACnM;AAAA,EAES,OAA6B;AACpC,SAAK,OAAO,2CAA2C;AACvD,SAAK,OAAO,+CAA+C;AAC3D,SAAK,OAAO,2CAA2C;AACvD,SAAK,OAAO,gDAAgD;AAC5D,SAAK,OAAO,gEAAgE;AAC5E,SAAK,OAAO,6DAA6D;AACzE,SAAK,OAAO,wEAAwE;AACpF,SAAK,OAAO,gDAAgD;AAC5D,SAAK,OAAO,iDAAiD;AAAA,EAC/D;AAEF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Migration } from "@mikro-orm/migrations";
|
|
2
|
+
class Migration20260527195446_communication_channels extends Migration {
|
|
3
|
+
up() {
|
|
4
|
+
this.addSql(`create table "channel_ingest_dead_letters" ("id" uuid not null default gen_random_uuid(), "tenant_id" uuid not null, "organization_id" uuid null, "channel_id" uuid not null, "provider_key" text not null, "external_uid" text null, "external_message_id" text null, "error_class" text not null, "error_message" text not null, "raw_body" text null, "created_at" timestamptz not null, primary key ("id"));`);
|
|
5
|
+
this.addSql(`create index "channel_ingest_dead_letters_created_idx" on "channel_ingest_dead_letters" ("tenant_id", "created_at");`);
|
|
6
|
+
this.addSql(`create index "channel_ingest_dead_letters_channel_idx" on "channel_ingest_dead_letters" ("channel_id", "tenant_id");`);
|
|
7
|
+
this.addSql(`create table "channel_thread_tokens" ("id" uuid not null default gen_random_uuid(), "tenant_id" uuid not null, "organization_id" uuid null, "message_thread_id" uuid not null, "token" text not null, "created_at" timestamptz not null, "last_seen_at" timestamptz null, primary key ("id"));`);
|
|
8
|
+
this.addSql(`create index "channel_thread_tokens_thread_idx" on "channel_thread_tokens" ("message_thread_id", "tenant_id");`);
|
|
9
|
+
this.addSql(`alter table "channel_thread_tokens" add constraint "channel_thread_tokens_token_uq" unique ("tenant_id", "token");`);
|
|
10
|
+
}
|
|
11
|
+
down() {
|
|
12
|
+
this.addSql(`drop table if exists "channel_ingest_dead_letters";`);
|
|
13
|
+
this.addSql(`drop table if exists "channel_thread_tokens";`);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export {
|
|
17
|
+
Migration20260527195446_communication_channels
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=Migration20260527195446_communication_channels.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/communication_channels/migrations/Migration20260527195446_communication_channels.ts"],
|
|
4
|
+
"sourcesContent": ["import { Migration } from '@mikro-orm/migrations';\n\nexport class Migration20260527195446_communication_channels extends Migration {\n\n override up(): void | Promise<void> {\n this.addSql(`create table \"channel_ingest_dead_letters\" (\"id\" uuid not null default gen_random_uuid(), \"tenant_id\" uuid not null, \"organization_id\" uuid null, \"channel_id\" uuid not null, \"provider_key\" text not null, \"external_uid\" text null, \"external_message_id\" text null, \"error_class\" text not null, \"error_message\" text not null, \"raw_body\" text null, \"created_at\" timestamptz not null, primary key (\"id\"));`);\n this.addSql(`create index \"channel_ingest_dead_letters_created_idx\" on \"channel_ingest_dead_letters\" (\"tenant_id\", \"created_at\");`);\n this.addSql(`create index \"channel_ingest_dead_letters_channel_idx\" on \"channel_ingest_dead_letters\" (\"channel_id\", \"tenant_id\");`);\n\n this.addSql(`create table \"channel_thread_tokens\" (\"id\" uuid not null default gen_random_uuid(), \"tenant_id\" uuid not null, \"organization_id\" uuid null, \"message_thread_id\" uuid not null, \"token\" text not null, \"created_at\" timestamptz not null, \"last_seen_at\" timestamptz null, primary key (\"id\"));`);\n this.addSql(`create index \"channel_thread_tokens_thread_idx\" on \"channel_thread_tokens\" (\"message_thread_id\", \"tenant_id\");`);\n this.addSql(`alter table \"channel_thread_tokens\" add constraint \"channel_thread_tokens_token_uq\" unique (\"tenant_id\", \"token\");`);\n }\n\n override down(): void | Promise<void> {\n this.addSql(`drop table if exists \"channel_ingest_dead_letters\";`);\n this.addSql(`drop table if exists \"channel_thread_tokens\";`);\n }\n\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,iBAAiB;AAEnB,MAAM,uDAAuD,UAAU;AAAA,EAEnE,KAA2B;AAClC,SAAK,OAAO,kZAAkZ;AAC9Z,SAAK,OAAO,sHAAsH;AAClI,SAAK,OAAO,sHAAsH;AAElI,SAAK,OAAO,gSAAgS;AAC5S,SAAK,OAAO,gHAAgH;AAC5H,SAAK,OAAO,oHAAoH;AAAA,EAClI;AAAA,EAES,OAA6B;AACpC,SAAK,OAAO,qDAAqD;AACjE,SAAK,OAAO,+CAA+C;AAAA,EAC7D;AAEF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Migration } from "@mikro-orm/migrations";
|
|
2
|
+
class Migration20260529231848_communication_channels extends Migration {
|
|
3
|
+
up() {
|
|
4
|
+
this.addSql(`create index "communication_channels_provider_external_idx" on "communication_channels" ("provider_key", "external_identifier") where "deleted_at" is null;`);
|
|
5
|
+
}
|
|
6
|
+
down() {
|
|
7
|
+
this.addSql(`drop index "communication_channels_provider_external_idx";`);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export {
|
|
11
|
+
Migration20260529231848_communication_channels
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=Migration20260529231848_communication_channels.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/communication_channels/migrations/Migration20260529231848_communication_channels.ts"],
|
|
4
|
+
"sourcesContent": ["import { Migration } from '@mikro-orm/migrations';\n\nexport class Migration20260529231848_communication_channels extends Migration {\n\n override up(): void | Promise<void> {\n this.addSql(`create index \"communication_channels_provider_external_idx\" on \"communication_channels\" (\"provider_key\", \"external_identifier\") where \"deleted_at\" is null;`);\n }\n\n override down(): void | Promise<void> {\n this.addSql(`drop index \"communication_channels_provider_external_idx\";`);\n }\n\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,iBAAiB;AAEnB,MAAM,uDAAuD,UAAU;AAAA,EAEnE,KAA2B;AAClC,SAAK,OAAO,6JAA6J;AAAA,EAC3K;AAAA,EAES,OAA6B;AACpC,SAAK,OAAO,4DAA4D;AAAA,EAC1E;AAEF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Migration } from "@mikro-orm/migrations";
|
|
2
|
+
class Migration20260531120000_communication_channels extends Migration {
|
|
3
|
+
up() {
|
|
4
|
+
this.addSql(`drop index if exists "channel_thread_tokens_thread_idx";`);
|
|
5
|
+
this.addSql(`alter table "channel_thread_tokens" add constraint "channel_thread_tokens_thread_uq" unique ("tenant_id", "message_thread_id");`);
|
|
6
|
+
this.addSql(`create unique index "communication_channels_user_provider_external_uq" on "communication_channels" ("tenant_id", "user_id", "provider_key", "external_identifier") where "deleted_at" is null and "user_id" is not null and "external_identifier" is not null;`);
|
|
7
|
+
}
|
|
8
|
+
down() {
|
|
9
|
+
this.addSql(`drop index if exists "communication_channels_user_provider_external_uq";`);
|
|
10
|
+
this.addSql(`alter table "channel_thread_tokens" drop constraint if exists "channel_thread_tokens_thread_uq";`);
|
|
11
|
+
this.addSql(`create index "channel_thread_tokens_thread_idx" on "channel_thread_tokens" ("message_thread_id", "tenant_id");`);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export {
|
|
15
|
+
Migration20260531120000_communication_channels
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=Migration20260531120000_communication_channels.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/communication_channels/migrations/Migration20260531120000_communication_channels.ts"],
|
|
4
|
+
"sourcesContent": ["import { Migration } from '@mikro-orm/migrations';\n\nexport class Migration20260531120000_communication_channels extends Migration {\n\n override up(): void | Promise<void> {\n // Enforce one thread token per (tenant, message_thread_id). Replaces the\n // earlier non-unique `channel_thread_tokens_thread_idx` so `getOrCreateThreadToken`\n // is idempotent under concurrency (insert-on-conflict). The new unique index\n // also serves the `WHERE tenant_id = ? AND message_thread_id = ?` lookup.\n this.addSql(`drop index if exists \"channel_thread_tokens_thread_idx\";`);\n this.addSql(`alter table \"channel_thread_tokens\" add constraint \"channel_thread_tokens_thread_uq\" unique (\"tenant_id\", \"message_thread_id\");`);\n // Enforce one channel per (tenant, user, provider, mailbox) so a reconnect\n // heals the existing row instead of inserting a duplicate. Partial: tenant-wide\n // (null user_id) and identifier-less channels are exempt.\n this.addSql(`create unique index \"communication_channels_user_provider_external_uq\" on \"communication_channels\" (\"tenant_id\", \"user_id\", \"provider_key\", \"external_identifier\") where \"deleted_at\" is null and \"user_id\" is not null and \"external_identifier\" is not null;`);\n }\n\n override down(): void | Promise<void> {\n this.addSql(`drop index if exists \"communication_channels_user_provider_external_uq\";`);\n this.addSql(`alter table \"channel_thread_tokens\" drop constraint if exists \"channel_thread_tokens_thread_uq\";`);\n this.addSql(`create index \"channel_thread_tokens_thread_idx\" on \"channel_thread_tokens\" (\"message_thread_id\", \"tenant_id\");`);\n }\n\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,iBAAiB;AAEnB,MAAM,uDAAuD,UAAU;AAAA,EAEnE,KAA2B;AAKlC,SAAK,OAAO,0DAA0D;AACtE,SAAK,OAAO,iIAAiI;AAI7I,SAAK,OAAO,gQAAgQ;AAAA,EAC9Q;AAAA,EAES,OAA6B;AACpC,SAAK,OAAO,0EAA0E;AACtF,SAAK,OAAO,kGAAkG;AAC9G,SAAK,OAAO,gHAAgH;AAAA,EAC9H;AAEF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { MessageReceivedRenderer } from "./widgets/notifications/MessageReceivedRenderer.js";
|
|
3
|
+
import { ChannelRequiresReauthRenderer } from "./widgets/notifications/ChannelRequiresReauthRenderer.js";
|
|
4
|
+
const communicationChannelsNotificationTypes = [
|
|
5
|
+
{
|
|
6
|
+
type: "communication_channels.message.received",
|
|
7
|
+
module: "communication_channels",
|
|
8
|
+
titleKey: "communication_channels.notifications.message_received.title",
|
|
9
|
+
bodyKey: "communication_channels.notifications.message_received.body",
|
|
10
|
+
icon: "message-circle",
|
|
11
|
+
severity: "info",
|
|
12
|
+
actions: [
|
|
13
|
+
{
|
|
14
|
+
id: "view",
|
|
15
|
+
labelKey: "common.view",
|
|
16
|
+
variant: "outline",
|
|
17
|
+
href: "/backend/messages/{sourceEntityId}",
|
|
18
|
+
icon: "external-link"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
linkHref: "/backend/messages/{sourceEntityId}",
|
|
22
|
+
Renderer: MessageReceivedRenderer,
|
|
23
|
+
expiresAfterHours: 168
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
type: "communication_channels.channel.requires_reauth",
|
|
27
|
+
module: "communication_channels",
|
|
28
|
+
titleKey: "communication_channels.notifications.channel_requires_reauth.title",
|
|
29
|
+
bodyKey: "communication_channels.notifications.channel_requires_reauth.body",
|
|
30
|
+
icon: "alert-triangle",
|
|
31
|
+
severity: "warning",
|
|
32
|
+
actions: [
|
|
33
|
+
{
|
|
34
|
+
id: "reconnect",
|
|
35
|
+
labelKey: "communication_channels.notifications.channel_requires_reauth.reconnect",
|
|
36
|
+
variant: "outline",
|
|
37
|
+
href: "/backend/profile/communication-channels?reconnect={sourceEntityId}",
|
|
38
|
+
icon: "refresh-cw"
|
|
39
|
+
}
|
|
40
|
+
],
|
|
41
|
+
linkHref: "/backend/profile/communication-channels?reconnect={sourceEntityId}",
|
|
42
|
+
Renderer: ChannelRequiresReauthRenderer,
|
|
43
|
+
expiresAfterHours: 720
|
|
44
|
+
}
|
|
45
|
+
];
|
|
46
|
+
var notifications_client_default = communicationChannelsNotificationTypes;
|
|
47
|
+
export {
|
|
48
|
+
communicationChannelsNotificationTypes,
|
|
49
|
+
notifications_client_default as default
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=notifications.client.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/modules/communication_channels/notifications.client.ts"],
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport type { NotificationTypeDefinition } from '@open-mercato/shared/modules/notifications/types'\nimport { MessageReceivedRenderer } from './widgets/notifications/MessageReceivedRenderer'\nimport { ChannelRequiresReauthRenderer } from './widgets/notifications/ChannelRequiresReauthRenderer'\n\nexport const communicationChannelsNotificationTypes: NotificationTypeDefinition[] = [\n {\n type: 'communication_channels.message.received',\n module: 'communication_channels',\n titleKey: 'communication_channels.notifications.message_received.title',\n bodyKey: 'communication_channels.notifications.message_received.body',\n icon: 'message-circle',\n severity: 'info',\n actions: [\n {\n id: 'view',\n labelKey: 'common.view',\n variant: 'outline',\n href: '/backend/messages/{sourceEntityId}',\n icon: 'external-link',\n },\n ],\n linkHref: '/backend/messages/{sourceEntityId}',\n Renderer: MessageReceivedRenderer,\n expiresAfterHours: 168,\n },\n {\n type: 'communication_channels.channel.requires_reauth',\n module: 'communication_channels',\n titleKey: 'communication_channels.notifications.channel_requires_reauth.title',\n bodyKey: 'communication_channels.notifications.channel_requires_reauth.body',\n icon: 'alert-triangle',\n severity: 'warning',\n actions: [\n {\n id: 'reconnect',\n labelKey: 'communication_channels.notifications.channel_requires_reauth.reconnect',\n variant: 'outline',\n href: '/backend/profile/communication-channels?reconnect={sourceEntityId}',\n icon: 'refresh-cw',\n },\n ],\n linkHref: '/backend/profile/communication-channels?reconnect={sourceEntityId}',\n Renderer: ChannelRequiresReauthRenderer,\n expiresAfterHours: 720,\n },\n]\n\nexport default communicationChannelsNotificationTypes\n"],
|
|
5
|
+
"mappings": ";AAGA,SAAS,+BAA+B;AACxC,SAAS,qCAAqC;AAEvC,MAAM,yCAAuE;AAAA,EAClF;AAAA,IACE,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP;AAAA,QACE,IAAI;AAAA,QACJ,UAAU;AAAA,QACV,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,UAAU;AAAA,IACV,mBAAmB;AAAA,EACrB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP;AAAA,QACE,IAAI;AAAA,QACJ,UAAU;AAAA,QACV,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,UAAU;AAAA,IACV,mBAAmB;AAAA,EACrB;AACF;AAEA,IAAO,+BAAQ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const CHANNEL_REQUIRES_REAUTH_EVENT = "om:communication_channels:channel-requires-reauth";
|
|
2
|
+
const MESSAGE_RECEIVED_EVENT = "om:communication_channels:message-received";
|
|
3
|
+
const notificationHandlers = [
|
|
4
|
+
{
|
|
5
|
+
id: "communication_channels.channel-requires-reauth-toast",
|
|
6
|
+
notificationType: "communication_channels.channel.requires_reauth",
|
|
7
|
+
features: ["communication_channels.connect_user_channel"],
|
|
8
|
+
priority: 110,
|
|
9
|
+
handle(notification, context) {
|
|
10
|
+
context.toast({
|
|
11
|
+
title: notification.title,
|
|
12
|
+
body: notification.body ?? void 0,
|
|
13
|
+
severity: "warning",
|
|
14
|
+
action: {
|
|
15
|
+
label: context.t?.(
|
|
16
|
+
"communication_channels.notifications.channel_requires_reauth.reconnect",
|
|
17
|
+
"Reconnect"
|
|
18
|
+
) ?? "Reconnect",
|
|
19
|
+
onClick: () => {
|
|
20
|
+
const channelId = notification.sourceEntityId;
|
|
21
|
+
const target = channelId ? `/backend/profile/communication-channels?reconnect=${encodeURIComponent(channelId)}` : "/backend/profile/communication-channels";
|
|
22
|
+
context.navigate(target);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
context.emitEvent(CHANNEL_REQUIRES_REAUTH_EVENT, {
|
|
27
|
+
notificationId: notification.id,
|
|
28
|
+
channelId: notification.sourceEntityId ?? null
|
|
29
|
+
});
|
|
30
|
+
context.refreshNotifications();
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: "communication_channels.message-received-event",
|
|
35
|
+
notificationType: "communication_channels.message.received",
|
|
36
|
+
features: ["communication_channels.view"],
|
|
37
|
+
priority: 100,
|
|
38
|
+
handle(notification, context) {
|
|
39
|
+
context.emitEvent(MESSAGE_RECEIVED_EVENT, {
|
|
40
|
+
notificationId: notification.id,
|
|
41
|
+
messageId: notification.sourceEntityId ?? null
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
];
|
|
46
|
+
var notifications_handlers_default = notificationHandlers;
|
|
47
|
+
export {
|
|
48
|
+
CHANNEL_REQUIRES_REAUTH_EVENT,
|
|
49
|
+
MESSAGE_RECEIVED_EVENT,
|
|
50
|
+
notifications_handlers_default as default,
|
|
51
|
+
notificationHandlers
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=notifications.handlers.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/modules/communication_channels/notifications.handlers.ts"],
|
|
4
|
+
"sourcesContent": ["import type { NotificationHandler } from '@open-mercato/shared/modules/notifications/handler'\n\n/**\n * Reactive notification handlers for the Communications Hub (Phase 4 of the\n * email integration spec).\n *\n * These handlers fire on the browser when the matching notification arrives via\n * the notifications stream. They run in addition to (not instead of) the static\n * UI surfaces:\n *\n * - The notification appears in the user's bell dropdown via\n * `notifications.client.ts` renderers (already wired in slice 2a).\n * - The dropdown's primary action navigates to the reconnect URL.\n *\n * What the handlers add:\n * - **Toast**: surfaces the message even when the user isn't looking at the\n * bell. The reauth toast is the highest-signal interruption \u2014 without\n * reauth the channel goes silent.\n * - **Event emit**: lets the profile page / channel admin DataTable hook in\n * via `useAppEvent(...)` (DOM Event Bridge) so they auto-refresh when the\n * state flips without requiring a manual reload.\n * - **Refresh notifications**: keeps the bell badge accurate.\n *\n * Custom event names emitted here on the DOM Event Bridge. They are published\n * for any page that opts in via `useAppEvent(...)`; no surface subscribes to\n * them today (the unified inbox auto-refreshes from the `messages.message.*`\n * bridge, and the reconnect flow is driven by the bell notification + its\n * reconnect action). Kept as forward-compatible hooks for future\n * row-highlight / refetch UX.\n */\n\nexport const CHANNEL_REQUIRES_REAUTH_EVENT = 'om:communication_channels:channel-requires-reauth'\nexport const MESSAGE_RECEIVED_EVENT = 'om:communication_channels:message-received'\n\nexport const notificationHandlers: NotificationHandler[] = [\n {\n id: 'communication_channels.channel-requires-reauth-toast',\n notificationType: 'communication_channels.channel.requires_reauth',\n features: ['communication_channels.connect_user_channel'],\n priority: 110,\n handle(notification, context) {\n context.toast({\n title: notification.title,\n body: notification.body ?? undefined,\n severity: 'warning',\n action: {\n label:\n context.t?.(\n 'communication_channels.notifications.channel_requires_reauth.reconnect',\n 'Reconnect',\n ) ?? 'Reconnect',\n onClick: () => {\n const channelId = notification.sourceEntityId\n const target = channelId\n ? `/backend/profile/communication-channels?reconnect=${encodeURIComponent(channelId)}`\n : '/backend/profile/communication-channels'\n context.navigate(target)\n },\n },\n })\n context.emitEvent(CHANNEL_REQUIRES_REAUTH_EVENT, {\n notificationId: notification.id,\n channelId: notification.sourceEntityId ?? null,\n })\n context.refreshNotifications()\n },\n },\n {\n id: 'communication_channels.message-received-event',\n notificationType: 'communication_channels.message.received',\n features: ['communication_channels.view'],\n priority: 100,\n handle(notification, context) {\n // Inbox refresh is the only side effect \u2014 the user's bell dropdown already\n // shows the notification entry. A toast here would be noisy because the\n // bell badge increments anyway, and inbound email lands in the unified\n // inbox where the user expects it.\n context.emitEvent(MESSAGE_RECEIVED_EVENT, {\n notificationId: notification.id,\n messageId: notification.sourceEntityId ?? null,\n })\n },\n },\n]\n\nexport default notificationHandlers\n"],
|
|
5
|
+
"mappings": "AA+BO,MAAM,gCAAgC;AACtC,MAAM,yBAAyB;AAE/B,MAAM,uBAA8C;AAAA,EACzD;AAAA,IACE,IAAI;AAAA,IACJ,kBAAkB;AAAA,IAClB,UAAU,CAAC,6CAA6C;AAAA,IACxD,UAAU;AAAA,IACV,OAAO,cAAc,SAAS;AAC5B,cAAQ,MAAM;AAAA,QACZ,OAAO,aAAa;AAAA,QACpB,MAAM,aAAa,QAAQ;AAAA,QAC3B,UAAU;AAAA,QACV,QAAQ;AAAA,UACN,OACE,QAAQ;AAAA,YACN;AAAA,YACA;AAAA,UACF,KAAK;AAAA,UACP,SAAS,MAAM;AACb,kBAAM,YAAY,aAAa;AAC/B,kBAAM,SAAS,YACX,qDAAqD,mBAAmB,SAAS,CAAC,KAClF;AACJ,oBAAQ,SAAS,MAAM;AAAA,UACzB;AAAA,QACF;AAAA,MACF,CAAC;AACD,cAAQ,UAAU,+BAA+B;AAAA,QAC/C,gBAAgB,aAAa;AAAA,QAC7B,WAAW,aAAa,kBAAkB;AAAA,MAC5C,CAAC;AACD,cAAQ,qBAAqB;AAAA,IAC/B;AAAA,EACF;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,kBAAkB;AAAA,IAClB,UAAU,CAAC,6BAA6B;AAAA,IACxC,UAAU;AAAA,IACV,OAAO,cAAc,SAAS;AAK5B,cAAQ,UAAU,wBAAwB;AAAA,QACxC,gBAAgB,aAAa;AAAA,QAC7B,WAAW,aAAa,kBAAkB;AAAA,MAC5C,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEA,IAAO,iCAAQ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
const notificationTypes = [
|
|
2
|
+
{
|
|
3
|
+
type: "communication_channels.message.received",
|
|
4
|
+
module: "communication_channels",
|
|
5
|
+
titleKey: "communication_channels.notifications.message_received.title",
|
|
6
|
+
bodyKey: "communication_channels.notifications.message_received.body",
|
|
7
|
+
icon: "message-circle",
|
|
8
|
+
severity: "info",
|
|
9
|
+
actions: [
|
|
10
|
+
{
|
|
11
|
+
id: "view",
|
|
12
|
+
labelKey: "common.view",
|
|
13
|
+
variant: "outline",
|
|
14
|
+
href: "/backend/messages/{sourceEntityId}",
|
|
15
|
+
icon: "external-link"
|
|
16
|
+
}
|
|
17
|
+
],
|
|
18
|
+
linkHref: "/backend/messages/{sourceEntityId}",
|
|
19
|
+
expiresAfterHours: 168
|
|
20
|
+
// 7 days
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
/**
|
|
24
|
+
* Channel-agnostic notification raised when an adapter loses authorization
|
|
25
|
+
* (OAuth refresh token revoked, IMAP/SMTP password rotated, WhatsApp token expired).
|
|
26
|
+
* Persisted by the `channel-requires-reauth-notification` subscriber in
|
|
27
|
+
* response to the `communication_channels.channel.requires_reauth` event
|
|
28
|
+
* (emitted by the poll worker and outbound delivery). Consumed by the email
|
|
29
|
+
* integration spec's reconnect flow.
|
|
30
|
+
*/
|
|
31
|
+
type: "communication_channels.channel.requires_reauth",
|
|
32
|
+
module: "communication_channels",
|
|
33
|
+
titleKey: "communication_channels.notifications.channel_requires_reauth.title",
|
|
34
|
+
bodyKey: "communication_channels.notifications.channel_requires_reauth.body",
|
|
35
|
+
icon: "alert-triangle",
|
|
36
|
+
severity: "warning",
|
|
37
|
+
actions: [
|
|
38
|
+
{
|
|
39
|
+
id: "reconnect",
|
|
40
|
+
labelKey: "communication_channels.notifications.channel_requires_reauth.reconnect",
|
|
41
|
+
variant: "outline",
|
|
42
|
+
href: "/backend/profile/communication-channels?reconnect={sourceEntityId}",
|
|
43
|
+
icon: "refresh-cw"
|
|
44
|
+
}
|
|
45
|
+
],
|
|
46
|
+
linkHref: "/backend/profile/communication-channels?reconnect={sourceEntityId}",
|
|
47
|
+
expiresAfterHours: 720
|
|
48
|
+
// 30 days — auth issues should be addressed promptly
|
|
49
|
+
}
|
|
50
|
+
];
|
|
51
|
+
var notifications_default = notificationTypes;
|
|
52
|
+
export {
|
|
53
|
+
notifications_default as default,
|
|
54
|
+
notificationTypes
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=notifications.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/modules/communication_channels/notifications.ts"],
|
|
4
|
+
"sourcesContent": ["import type { NotificationTypeDefinition } from '@open-mercato/shared/modules/notifications/types'\n\nexport const notificationTypes: NotificationTypeDefinition[] = [\n {\n type: 'communication_channels.message.received',\n module: 'communication_channels',\n titleKey: 'communication_channels.notifications.message_received.title',\n bodyKey: 'communication_channels.notifications.message_received.body',\n icon: 'message-circle',\n severity: 'info',\n actions: [\n {\n id: 'view',\n labelKey: 'common.view',\n variant: 'outline',\n href: '/backend/messages/{sourceEntityId}',\n icon: 'external-link',\n },\n ],\n linkHref: '/backend/messages/{sourceEntityId}',\n expiresAfterHours: 168, // 7 days\n },\n {\n /**\n * Channel-agnostic notification raised when an adapter loses authorization\n * (OAuth refresh token revoked, IMAP/SMTP password rotated, WhatsApp token expired).\n * Persisted by the `channel-requires-reauth-notification` subscriber in\n * response to the `communication_channels.channel.requires_reauth` event\n * (emitted by the poll worker and outbound delivery). Consumed by the email\n * integration spec's reconnect flow.\n */\n type: 'communication_channels.channel.requires_reauth',\n module: 'communication_channels',\n titleKey: 'communication_channels.notifications.channel_requires_reauth.title',\n bodyKey: 'communication_channels.notifications.channel_requires_reauth.body',\n icon: 'alert-triangle',\n severity: 'warning',\n actions: [\n {\n id: 'reconnect',\n labelKey: 'communication_channels.notifications.channel_requires_reauth.reconnect',\n variant: 'outline',\n href: '/backend/profile/communication-channels?reconnect={sourceEntityId}',\n icon: 'refresh-cw',\n },\n ],\n linkHref: '/backend/profile/communication-channels?reconnect={sourceEntityId}',\n expiresAfterHours: 720, // 30 days \u2014 auth issues should be addressed promptly\n },\n]\n\nexport default notificationTypes\n"],
|
|
5
|
+
"mappings": "AAEO,MAAM,oBAAkD;AAAA,EAC7D;AAAA,IACE,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP;AAAA,QACE,IAAI;AAAA,QACJ,UAAU;AAAA,QACV,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,mBAAmB;AAAA;AAAA,EACrB;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IASE,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP;AAAA,QACE,IAAI;AAAA,QACJ,UAAU;AAAA,QACV,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,mBAAmB;AAAA;AAAA,EACrB;AACF;AAEA,IAAO,wBAAQ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { COMMUNICATION_CHANNELS_QUEUES } from "./lib/queue.js";
|
|
3
|
+
const POLL_TICK_INTERVAL_SECONDS = Math.max(
|
|
4
|
+
10,
|
|
5
|
+
Number.parseInt(process.env.OM_HUB_POLL_SCHEDULER_TICK_SECONDS ?? "60", 10) || 60
|
|
6
|
+
);
|
|
7
|
+
function stableScheduleUuid(stableKey) {
|
|
8
|
+
const hex = createHash("sha256").update(stableKey).digest("hex");
|
|
9
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;
|
|
10
|
+
}
|
|
11
|
+
function stablePollTickScheduleId(organizationId) {
|
|
12
|
+
return stableScheduleUuid(`communication_channels:poll-tick:${organizationId}`);
|
|
13
|
+
}
|
|
14
|
+
const setup = {
|
|
15
|
+
defaultRoleFeatures: {
|
|
16
|
+
superadmin: [
|
|
17
|
+
"communication_channels.view",
|
|
18
|
+
"communication_channels.manage",
|
|
19
|
+
"communication_channels.react",
|
|
20
|
+
"communication_channels.assign",
|
|
21
|
+
"communication_channels.connect_user_channel",
|
|
22
|
+
"communication_channels.admin",
|
|
23
|
+
"communication_channels.channel.import_history",
|
|
24
|
+
"communication_channels.channel.push.manage"
|
|
25
|
+
],
|
|
26
|
+
admin: [
|
|
27
|
+
"communication_channels.view",
|
|
28
|
+
"communication_channels.manage",
|
|
29
|
+
"communication_channels.react",
|
|
30
|
+
"communication_channels.assign",
|
|
31
|
+
"communication_channels.connect_user_channel",
|
|
32
|
+
"communication_channels.admin",
|
|
33
|
+
"communication_channels.channel.import_history",
|
|
34
|
+
"communication_channels.channel.push.manage"
|
|
35
|
+
],
|
|
36
|
+
manager: [
|
|
37
|
+
"communication_channels.view",
|
|
38
|
+
"communication_channels.manage",
|
|
39
|
+
"communication_channels.react",
|
|
40
|
+
"communication_channels.assign",
|
|
41
|
+
"communication_channels.connect_user_channel"
|
|
42
|
+
],
|
|
43
|
+
employee: [
|
|
44
|
+
"communication_channels.view",
|
|
45
|
+
"communication_channels.react",
|
|
46
|
+
"communication_channels.connect_user_channel"
|
|
47
|
+
]
|
|
48
|
+
},
|
|
49
|
+
async seedDefaults({ container, organizationId, tenantId }) {
|
|
50
|
+
const cradle = container;
|
|
51
|
+
if (typeof cradle.hasRegistration !== "function" || !cradle.hasRegistration("schedulerService")) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const schedulerService = container.resolve("schedulerService");
|
|
55
|
+
try {
|
|
56
|
+
await schedulerService.register({
|
|
57
|
+
id: stablePollTickScheduleId(organizationId),
|
|
58
|
+
name: "Communication channels poll tick",
|
|
59
|
+
description: `Enumerates active polling channels every ${POLL_TICK_INTERVAL_SECONDS}s and enqueues per-channel poll jobs.`,
|
|
60
|
+
scopeType: "organization",
|
|
61
|
+
organizationId,
|
|
62
|
+
tenantId,
|
|
63
|
+
scheduleType: "interval",
|
|
64
|
+
scheduleValue: `${POLL_TICK_INTERVAL_SECONDS}s`,
|
|
65
|
+
timezone: "UTC",
|
|
66
|
+
targetType: "queue",
|
|
67
|
+
targetQueue: COMMUNICATION_CHANNELS_QUEUES.pollTick,
|
|
68
|
+
targetPayload: {
|
|
69
|
+
scope: { tenantId, organizationId }
|
|
70
|
+
},
|
|
71
|
+
sourceType: "module",
|
|
72
|
+
sourceModule: "communication_channels",
|
|
73
|
+
isEnabled: true
|
|
74
|
+
});
|
|
75
|
+
await schedulerService.register({
|
|
76
|
+
id: stableScheduleUuid(`communication_channels:gmail-renew-watch:${organizationId}`),
|
|
77
|
+
name: "Gmail watch renewal",
|
|
78
|
+
description: "Daily 04:00 UTC. Re-issues gmail.users.watch for channels within OM_PUSH_RENEWAL_GMAIL_LEAD_HOURS of expiry.",
|
|
79
|
+
scopeType: "organization",
|
|
80
|
+
organizationId,
|
|
81
|
+
tenantId,
|
|
82
|
+
scheduleType: "cron",
|
|
83
|
+
scheduleValue: "0 4 * * *",
|
|
84
|
+
timezone: "UTC",
|
|
85
|
+
targetType: "queue",
|
|
86
|
+
targetQueue: COMMUNICATION_CHANNELS_QUEUES.gmailRenewWatch,
|
|
87
|
+
targetPayload: { scope: { tenantId, organizationId } },
|
|
88
|
+
sourceType: "module",
|
|
89
|
+
sourceModule: "communication_channels",
|
|
90
|
+
isEnabled: true
|
|
91
|
+
});
|
|
92
|
+
} catch (error) {
|
|
93
|
+
console.warn(
|
|
94
|
+
"[communication_channels] Failed to register module schedules:",
|
|
95
|
+
error instanceof Error ? error.message : error
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
var setup_default = setup;
|
|
101
|
+
export {
|
|
102
|
+
setup_default as default,
|
|
103
|
+
setup
|
|
104
|
+
};
|
|
105
|
+
//# sourceMappingURL=setup.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/modules/communication_channels/setup.ts"],
|
|
4
|
+
"sourcesContent": ["import { createHash } from 'node:crypto'\nimport type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'\nimport { COMMUNICATION_CHANNELS_QUEUES } from './lib/queue'\n\ntype SchedulerServiceLike = {\n register: (registration: {\n id: string\n name: string\n scopeType: 'system' | 'organization' | 'tenant'\n organizationId?: string\n tenantId?: string\n scheduleType: 'cron' | 'interval'\n scheduleValue: string\n timezone?: string\n targetType: 'queue' | 'command'\n targetQueue?: string\n targetPayload?: unknown\n sourceType?: 'user' | 'module'\n sourceModule?: string\n isEnabled?: boolean\n description?: string\n }) => Promise<void>\n}\n\n/**\n * Tick interval in seconds. Default 60s per email integration spec\n * \u00A7 Hub Deltas \u2192 Delta 6 (scheduler mechanism).\n */\nconst POLL_TICK_INTERVAL_SECONDS = Math.max(\n 10,\n Number.parseInt(process.env.OM_HUB_POLL_SCHEDULER_TICK_SECONDS ?? '60', 10) || 60,\n)\n\n/**\n * `scheduled_jobs.id` is a uuid column, so a module-owned schedule's stable\n * registration key must be hashed into a uuid rather than used verbatim \u2014 this\n * keeps `schedulerService.register()` an idempotent upsert across re-runs of\n * seedDefaults instead of trying to insert a raw string into the uuid PK.\n */\nfunction stableScheduleUuid(stableKey: string): string {\n const hex = createHash('sha256').update(stableKey).digest('hex')\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`\n}\n\nfunction stablePollTickScheduleId(organizationId: string): string {\n return stableScheduleUuid(`communication_channels:poll-tick:${organizationId}`)\n}\n\nexport const setup: ModuleSetupConfig = {\n defaultRoleFeatures: {\n superadmin: [\n 'communication_channels.view',\n 'communication_channels.manage',\n 'communication_channels.react',\n 'communication_channels.assign',\n 'communication_channels.connect_user_channel',\n 'communication_channels.admin',\n 'communication_channels.channel.import_history',\n 'communication_channels.channel.push.manage',\n ],\n admin: [\n 'communication_channels.view',\n 'communication_channels.manage',\n 'communication_channels.react',\n 'communication_channels.assign',\n 'communication_channels.connect_user_channel',\n 'communication_channels.admin',\n 'communication_channels.channel.import_history',\n 'communication_channels.channel.push.manage',\n ],\n manager: [\n 'communication_channels.view',\n 'communication_channels.manage',\n 'communication_channels.react',\n 'communication_channels.assign',\n 'communication_channels.connect_user_channel',\n ],\n employee: [\n 'communication_channels.view',\n 'communication_channels.react',\n 'communication_channels.connect_user_channel',\n ],\n },\n\n async seedDefaults({ container, organizationId, tenantId }) {\n /**\n * Register the per-channel polling tick with `@open-mercato/scheduler`.\n *\n * Per email integration spec \u00A7 Hub Deltas \u2192 Delta 6: every\n * `POLL_TICK_INTERVAL_SECONDS` (default 60s), enqueue a single\n * `communication-channels-poll-tick` job that enumerates due channels and\n * fans out to the `communication-channels-poll` queue.\n *\n * The registration is per-organization (one tick row per org/tenant pair)\n * so multi-tenant deploys schedule independently. Skipped silently when the\n * scheduler module isn't enabled \u2014 keeps the hub usable in scheduler-less\n * test harnesses.\n */\n const cradle = container as { hasRegistration?: (name: string) => boolean }\n if (typeof cradle.hasRegistration !== 'function' || !cradle.hasRegistration('schedulerService')) {\n return\n }\n const schedulerService = container.resolve('schedulerService') as SchedulerServiceLike\n // Best-effort: a scheduler failure must not abort tenant initialization for\n // every other module (mirrors the ai_assistant setup pattern). The schedule\n // ids are deterministic uuids so re-runs upsert idempotently.\n try {\n await schedulerService.register({\n id: stablePollTickScheduleId(organizationId),\n name: 'Communication channels poll tick',\n description:\n `Enumerates active polling channels every ${POLL_TICK_INTERVAL_SECONDS}s and enqueues per-channel poll jobs.`,\n scopeType: 'organization',\n organizationId,\n tenantId,\n scheduleType: 'interval',\n scheduleValue: `${POLL_TICK_INTERVAL_SECONDS}s`,\n timezone: 'UTC',\n targetType: 'queue',\n targetQueue: COMMUNICATION_CHANNELS_QUEUES.pollTick,\n targetPayload: {\n scope: { tenantId, organizationId },\n },\n sourceType: 'module',\n sourceModule: 'communication_channels',\n isEnabled: true,\n })\n\n // Spec C \u00A7 Phase C4 \u2014 Gmail watch renewal cron, per-org so multi-tenant\n // deploys schedule independently.\n await schedulerService.register({\n id: stableScheduleUuid(`communication_channels:gmail-renew-watch:${organizationId}`),\n name: 'Gmail watch renewal',\n description:\n 'Daily 04:00 UTC. Re-issues gmail.users.watch for channels within OM_PUSH_RENEWAL_GMAIL_LEAD_HOURS of expiry.',\n scopeType: 'organization',\n organizationId,\n tenantId,\n scheduleType: 'cron',\n scheduleValue: '0 4 * * *',\n timezone: 'UTC',\n targetType: 'queue',\n targetQueue: COMMUNICATION_CHANNELS_QUEUES.gmailRenewWatch,\n targetPayload: { scope: { tenantId, organizationId } },\n sourceType: 'module',\n sourceModule: 'communication_channels',\n isEnabled: true,\n })\n } catch (error) {\n console.warn(\n '[communication_channels] Failed to register module schedules:',\n error instanceof Error ? error.message : error,\n )\n }\n },\n}\n\nexport default setup\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,kBAAkB;AAE3B,SAAS,qCAAqC;AA0B9C,MAAM,6BAA6B,KAAK;AAAA,EACtC;AAAA,EACA,OAAO,SAAS,QAAQ,IAAI,sCAAsC,MAAM,EAAE,KAAK;AACjF;AAQA,SAAS,mBAAmB,WAA2B;AACrD,QAAM,MAAM,WAAW,QAAQ,EAAE,OAAO,SAAS,EAAE,OAAO,KAAK;AAC/D,SAAO,GAAG,IAAI,MAAM,GAAG,CAAC,CAAC,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC;AAC9G;AAEA,SAAS,yBAAyB,gBAAgC;AAChE,SAAO,mBAAmB,oCAAoC,cAAc,EAAE;AAChF;AAEO,MAAM,QAA2B;AAAA,EACtC,qBAAqB;AAAA,IACnB,YAAY;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,UAAU;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,aAAa,EAAE,WAAW,gBAAgB,SAAS,GAAG;AAc1D,UAAM,SAAS;AACf,QAAI,OAAO,OAAO,oBAAoB,cAAc,CAAC,OAAO,gBAAgB,kBAAkB,GAAG;AAC/F;AAAA,IACF;AACA,UAAM,mBAAmB,UAAU,QAAQ,kBAAkB;AAI7D,QAAI;AACF,YAAM,iBAAiB,SAAS;AAAA,QAC9B,IAAI,yBAAyB,cAAc;AAAA,QAC3C,MAAM;AAAA,QACN,aACE,4CAA4C,0BAA0B;AAAA,QACxE,WAAW;AAAA,QACX;AAAA,QACA;AAAA,QACA,cAAc;AAAA,QACd,eAAe,GAAG,0BAA0B;AAAA,QAC5C,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,aAAa,8BAA8B;AAAA,QAC3C,eAAe;AAAA,UACb,OAAO,EAAE,UAAU,eAAe;AAAA,QACpC;AAAA,QACA,YAAY;AAAA,QACZ,cAAc;AAAA,QACd,WAAW;AAAA,MACb,CAAC;AAID,YAAM,iBAAiB,SAAS;AAAA,QAC9B,IAAI,mBAAmB,4CAA4C,cAAc,EAAE;AAAA,QACnF,MAAM;AAAA,QACN,aACE;AAAA,QACF,WAAW;AAAA,QACX;AAAA,QACA;AAAA,QACA,cAAc;AAAA,QACd,eAAe;AAAA,QACf,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,aAAa,8BAA8B;AAAA,QAC3C,eAAe,EAAE,OAAO,EAAE,UAAU,eAAe,EAAE;AAAA,QACrD,YAAY;AAAA,QACZ,cAAc;AAAA,QACd,WAAW;AAAA,MACb,CAAC;AAAA,IACH,SAAS,OAAO;AACd,cAAQ;AAAA,QACN;AAAA,QACA,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAO,gBAAQ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/modules/communication_channels/subscribers/channel-requires-reauth-notification.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
|
|
2
|
+
import { CommunicationChannel } from "../data/entities.js";
|
|
3
|
+
import { notificationTypes } from "../notifications.js";
|
|
4
|
+
import {
|
|
5
|
+
buildNotificationFromType,
|
|
6
|
+
buildFeatureNotificationFromType
|
|
7
|
+
} from "../../notifications/lib/notificationBuilder.js";
|
|
8
|
+
import { resolveNotificationService } from "../../notifications/lib/notificationService.js";
|
|
9
|
+
const metadata = {
|
|
10
|
+
event: "communication_channels.channel.requires_reauth",
|
|
11
|
+
persistent: true,
|
|
12
|
+
id: "communication_channels:channel-requires-reauth-notification"
|
|
13
|
+
};
|
|
14
|
+
const NOTIFICATION_TYPE = "communication_channels.channel.requires_reauth";
|
|
15
|
+
const MANAGE_FEATURE = "communication_channels.manage";
|
|
16
|
+
function resolveFromCtx(ctx, name) {
|
|
17
|
+
if (typeof ctx?.resolve === "function") return ctx.resolve(name);
|
|
18
|
+
if (ctx?.container && typeof ctx.container.resolve === "function") {
|
|
19
|
+
return ctx.container.resolve(name);
|
|
20
|
+
}
|
|
21
|
+
throw new Error(
|
|
22
|
+
`channel-requires-reauth-notification: subscriber context has no resolver (looking for '${name}')`
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
async function handler(payload, ctx) {
|
|
26
|
+
if (!payload?.channelId || !payload.tenantId) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const typeDef = notificationTypes.find((type) => type.type === NOTIFICATION_TYPE);
|
|
30
|
+
if (!typeDef) return;
|
|
31
|
+
const scope = {
|
|
32
|
+
tenantId: payload.tenantId,
|
|
33
|
+
organizationId: payload.organizationId ?? null
|
|
34
|
+
};
|
|
35
|
+
const em = resolveFromCtx(ctx, "em").fork();
|
|
36
|
+
const channel = await findOneWithDecryption(
|
|
37
|
+
em,
|
|
38
|
+
CommunicationChannel,
|
|
39
|
+
{
|
|
40
|
+
id: payload.channelId,
|
|
41
|
+
tenantId: payload.tenantId,
|
|
42
|
+
organizationId: payload.organizationId ?? null,
|
|
43
|
+
deletedAt: null
|
|
44
|
+
},
|
|
45
|
+
void 0,
|
|
46
|
+
scope
|
|
47
|
+
);
|
|
48
|
+
if (!channel) return;
|
|
49
|
+
const notificationService = resolveNotificationService(ctx);
|
|
50
|
+
const common = {
|
|
51
|
+
sourceEntityType: "communication_channel",
|
|
52
|
+
sourceEntityId: payload.channelId,
|
|
53
|
+
groupKey: payload.channelId
|
|
54
|
+
};
|
|
55
|
+
if (channel.userId) {
|
|
56
|
+
await notificationService.create(
|
|
57
|
+
buildNotificationFromType(typeDef, { ...common, recipientUserId: channel.userId }),
|
|
58
|
+
scope
|
|
59
|
+
);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
await notificationService.createForFeature(
|
|
63
|
+
buildFeatureNotificationFromType(typeDef, { ...common, requiredFeature: MANAGE_FEATURE }),
|
|
64
|
+
scope
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
export {
|
|
68
|
+
handler as default,
|
|
69
|
+
metadata
|
|
70
|
+
};
|
|
71
|
+
//# sourceMappingURL=channel-requires-reauth-notification.js.map
|
package/dist/modules/communication_channels/subscribers/channel-requires-reauth-notification.js.map
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/communication_channels/subscribers/channel-requires-reauth-notification.ts"],
|
|
4
|
+
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { CommunicationChannel } from '../data/entities'\nimport { notificationTypes } from '../notifications'\nimport {\n buildNotificationFromType,\n buildFeatureNotificationFromType,\n} from '../../notifications/lib/notificationBuilder'\nimport { resolveNotificationService } from '../../notifications/lib/notificationService'\n\n/**\n * Subscriber: re-authentication notification.\n *\n * Listens to `communication_channels.channel.requires_reauth` (emitted by the\n * poll worker and outbound delivery when an\n * adapter loses authorization) and raises the in-app\n * `communication_channels.channel.requires_reauth` notification so the affected\n * user sees a bell entry + reconnect CTA and the reactive toast handler\n * (`notifications.handlers.ts`) fires. This is the producer half of the\n * notification contract declared in `notifications.ts` /\n * `notifications.client.ts` \u2014 without it the notification is never persisted.\n *\n * Recipient: per-user channels notify the channel owner (`channel.userId`) \u2014 the\n * only person who can complete their own OAuth/credential reconnect. Tenant-wide\n * (shared) channels have no owner, so operators holding\n * `communication_channels.manage` are notified instead.\n *\n * Idempotency: `groupKey = channelId` collapses repeated reauth events for the\n * same channel onto one notification (the notification service dedupes by\n * tenant/org/recipient/type/groupKey under an advisory lock), so a flapping\n * channel or a subscriber retry never spams the bell.\n */\nexport const metadata = {\n event: 'communication_channels.channel.requires_reauth',\n persistent: true,\n id: 'communication_channels:channel-requires-reauth-notification',\n}\n\nconst NOTIFICATION_TYPE = 'communication_channels.channel.requires_reauth'\nconst MANAGE_FEATURE = 'communication_channels.manage'\n\ntype RequiresReauthPayload = {\n channelId?: string\n providerKey?: string\n channelType?: string\n reason?: string\n tenantId?: string\n organizationId?: string | null\n}\n\ntype SubscriberContext = {\n resolve: <T = unknown>(name: string) => T\n container?: { resolve: <T = unknown>(name: string) => T }\n}\n\nfunction resolveFromCtx<T = unknown>(ctx: SubscriberContext, name: string): T {\n if (typeof ctx?.resolve === 'function') return ctx.resolve<T>(name)\n if (ctx?.container && typeof ctx.container.resolve === 'function') {\n return ctx.container.resolve<T>(name)\n }\n throw new Error(\n `channel-requires-reauth-notification: subscriber context has no resolver (looking for '${name}')`,\n )\n}\n\nexport default async function handler(\n payload: RequiresReauthPayload,\n ctx: SubscriberContext,\n): Promise<void> {\n if (!payload?.channelId || !payload.tenantId) {\n return\n }\n\n const typeDef = notificationTypes.find((type) => type.type === NOTIFICATION_TYPE)\n if (!typeDef) return\n\n const scope = {\n tenantId: payload.tenantId,\n organizationId: payload.organizationId ?? null,\n }\n\n const em = resolveFromCtx<EntityManager>(ctx, 'em').fork()\n const channel = await findOneWithDecryption(\n em,\n CommunicationChannel,\n {\n id: payload.channelId,\n tenantId: payload.tenantId,\n organizationId: payload.organizationId ?? null,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n if (!channel) return\n\n const notificationService = resolveNotificationService(ctx)\n const common = {\n sourceEntityType: 'communication_channel',\n sourceEntityId: payload.channelId,\n groupKey: payload.channelId,\n }\n\n if (channel.userId) {\n await notificationService.create(\n buildNotificationFromType(typeDef, { ...common, recipientUserId: channel.userId }),\n scope,\n )\n return\n }\n\n // Tenant-wide (shared) channel \u2014 no single owner. Notify operators who can\n // reconnect it on behalf of the tenant.\n await notificationService.createForFeature(\n buildFeatureNotificationFromType(typeDef, { ...common, requiredFeature: MANAGE_FEATURE }),\n scope,\n )\n}\n"],
|
|
5
|
+
"mappings": "AACA,SAAS,6BAA6B;AACtC,SAAS,4BAA4B;AACrC,SAAS,yBAAyB;AAClC;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP,SAAS,kCAAkC;AAwBpC,MAAM,WAAW;AAAA,EACtB,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,IAAI;AACN;AAEA,MAAM,oBAAoB;AAC1B,MAAM,iBAAiB;AAgBvB,SAAS,eAA4B,KAAwB,MAAiB;AAC5E,MAAI,OAAO,KAAK,YAAY,WAAY,QAAO,IAAI,QAAW,IAAI;AAClE,MAAI,KAAK,aAAa,OAAO,IAAI,UAAU,YAAY,YAAY;AACjE,WAAO,IAAI,UAAU,QAAW,IAAI;AAAA,EACtC;AACA,QAAM,IAAI;AAAA,IACR,0FAA0F,IAAI;AAAA,EAChG;AACF;AAEA,eAAO,QACL,SACA,KACe;AACf,MAAI,CAAC,SAAS,aAAa,CAAC,QAAQ,UAAU;AAC5C;AAAA,EACF;AAEA,QAAM,UAAU,kBAAkB,KAAK,CAAC,SAAS,KAAK,SAAS,iBAAiB;AAChF,MAAI,CAAC,QAAS;AAEd,QAAM,QAAQ;AAAA,IACZ,UAAU,QAAQ;AAAA,IAClB,gBAAgB,QAAQ,kBAAkB;AAAA,EAC5C;AAEA,QAAM,KAAK,eAA8B,KAAK,IAAI,EAAE,KAAK;AACzD,QAAM,UAAU,MAAM;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,MACE,IAAI,QAAQ;AAAA,MACZ,UAAU,QAAQ;AAAA,MAClB,gBAAgB,QAAQ,kBAAkB;AAAA,MAC1C,WAAW;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,MAAI,CAAC,QAAS;AAEd,QAAM,sBAAsB,2BAA2B,GAAG;AAC1D,QAAM,SAAS;AAAA,IACb,kBAAkB;AAAA,IAClB,gBAAgB,QAAQ;AAAA,IACxB,UAAU,QAAQ;AAAA,EACpB;AAEA,MAAI,QAAQ,QAAQ;AAClB,UAAM,oBAAoB;AAAA,MACxB,0BAA0B,SAAS,EAAE,GAAG,QAAQ,iBAAiB,QAAQ,OAAO,CAAC;AAAA,MACjF;AAAA,IACF;AACA;AAAA,EACF;AAIA,QAAM,oBAAoB;AAAA,IACxB,iCAAiC,SAAS,EAAE,GAAG,QAAQ,iBAAiB,eAAe,CAAC;AAAA,IACxF;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|