@open-mercato/core 0.6.8-develop.6983.1.e4f794099e → 0.6.8-develop.6985.1.fb93574faa
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/notification/index.js +6 -0
- package/dist/generated/entities/notification/index.js.map +2 -2
- package/dist/generated/entities/notification_preference/index.js +19 -0
- package/dist/generated/entities/notification_preference/index.js.map +7 -0
- package/dist/generated/entities/notification_type/index.js +21 -0
- package/dist/generated/entities/notification_type/index.js.map +7 -0
- package/dist/generated/entities/notification_type_override/index.js +17 -0
- package/dist/generated/entities/notification_type_override/index.js.map +7 -0
- package/dist/generated/entities/push_notification_delivery/index.js +41 -0
- package/dist/generated/entities/push_notification_delivery/index.js.map +7 -0
- package/dist/generated/entities/user_device/index.js +35 -0
- package/dist/generated/entities/user_device/index.js.map +7 -0
- package/dist/generated/entities.ids.generated.js +12 -1
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +72 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/helpers/integration/api.js +2 -1
- package/dist/helpers/integration/api.js.map +2 -2
- package/dist/helpers/integration/appRoot.js +9 -0
- package/dist/helpers/integration/appRoot.js.map +7 -0
- package/dist/helpers/integration/dbFixtures.js +1 -4
- package/dist/helpers/integration/dbFixtures.js.map +2 -2
- package/dist/helpers/integration/pushFake.js +126 -0
- package/dist/helpers/integration/pushFake.js.map +7 -0
- package/dist/modules/auth/notifications.js +16 -0
- package/dist/modules/auth/notifications.js.map +2 -2
- package/dist/modules/business_rules/notifications.js +2 -0
- package/dist/modules/business_rules/notifications.js.map +2 -2
- package/dist/modules/catalog/notifications.js +2 -0
- package/dist/modules/catalog/notifications.js.map +2 -2
- package/dist/modules/communication_channels/acl.js +9 -0
- package/dist/modules/communication_channels/acl.js.map +2 -2
- package/dist/modules/communication_channels/api/delete/admin/channels/[id]/route.js +133 -0
- package/dist/modules/communication_channels/api/delete/admin/channels/[id]/route.js.map +7 -0
- package/dist/modules/communication_channels/api/get/channels/[id]/health/route.js +6 -2
- package/dist/modules/communication_channels/api/get/channels/[id]/health/route.js.map +2 -2
- package/dist/modules/communication_channels/api/get/channels/[id]/route.js +6 -2
- package/dist/modules/communication_channels/api/get/channels/[id]/route.js.map +2 -2
- package/dist/modules/communication_channels/api/get/channels/route.js +2 -1
- package/dist/modules/communication_channels/api/get/channels/route.js.map +2 -2
- package/dist/modules/communication_channels/api/post/channels/[id]/test-send/route.js +10 -5
- package/dist/modules/communication_channels/api/post/channels/[id]/test-send/route.js.map +2 -2
- package/dist/modules/communication_channels/api/post/channels/connect/credentials/route.js +29 -1
- package/dist/modules/communication_channels/api/post/channels/connect/credentials/route.js.map +2 -2
- package/dist/modules/communication_channels/api/post/channels/connect/tenant-credentials/route.js +157 -0
- package/dist/modules/communication_channels/api/post/channels/connect/tenant-credentials/route.js.map +7 -0
- package/dist/modules/communication_channels/backend/communication_channels/channels/page.js +8 -1
- package/dist/modules/communication_channels/backend/communication_channels/channels/page.js.map +2 -2
- package/dist/modules/communication_channels/commands/admin-delete-channel.js +141 -0
- package/dist/modules/communication_channels/commands/admin-delete-channel.js.map +7 -0
- package/dist/modules/communication_channels/commands/connect-credential-channel.js +25 -8
- package/dist/modules/communication_channels/commands/connect-credential-channel.js.map +2 -2
- package/dist/modules/communication_channels/commands/deliver-outbound-message.js +2 -2
- package/dist/modules/communication_channels/commands/deliver-outbound-message.js.map +2 -2
- package/dist/modules/communication_channels/commands/push-register.js +1 -1
- package/dist/modules/communication_channels/commands/push-register.js.map +2 -2
- package/dist/modules/communication_channels/commands/push-unregister.js +4 -3
- package/dist/modules/communication_channels/commands/push-unregister.js.map +2 -2
- package/dist/modules/communication_channels/data/entities.js +4 -0
- package/dist/modules/communication_channels/data/entities.js.map +2 -2
- package/dist/modules/communication_channels/data/validators.js +2 -1
- package/dist/modules/communication_channels/data/validators.js.map +2 -2
- package/dist/modules/communication_channels/lib/access-control.js +11 -1
- package/dist/modules/communication_channels/lib/access-control.js.map +2 -2
- package/dist/modules/communication_channels/lib/connect-channel.js +20 -12
- package/dist/modules/communication_channels/lib/connect-channel.js.map +2 -2
- package/dist/modules/communication_channels/lib/push-adapter.js +68 -0
- package/dist/modules/communication_channels/lib/push-adapter.js.map +7 -0
- package/dist/modules/communication_channels/lib/push-capabilities.js +31 -0
- package/dist/modules/communication_channels/lib/push-capabilities.js.map +7 -0
- package/dist/modules/communication_channels/lib/push-connect-error.js +20 -0
- package/dist/modules/communication_channels/lib/push-connect-error.js.map +7 -0
- package/dist/modules/communication_channels/lib/push-credential-errors.js +41 -0
- package/dist/modules/communication_channels/lib/push-credential-errors.js.map +7 -0
- package/dist/modules/communication_channels/lib/push-envelope.js +46 -0
- package/dist/modules/communication_channels/lib/push-envelope.js.map +7 -0
- package/dist/modules/communication_channels/lib/refcounted-client-cache.js +64 -0
- package/dist/modules/communication_channels/lib/refcounted-client-cache.js.map +7 -0
- package/dist/modules/communication_channels/migrations/Migration20260703123630_communication_channels.js +13 -0
- package/dist/modules/communication_channels/migrations/Migration20260703123630_communication_channels.js.map +7 -0
- package/dist/modules/communication_channels/notifications.js +4 -0
- package/dist/modules/communication_channels/notifications.js.map +2 -2
- package/dist/modules/communication_channels/setup.js +2 -0
- package/dist/modules/communication_channels/setup.js.map +2 -2
- package/dist/modules/configs/lib/upgrade-actions.js +21 -0
- package/dist/modules/configs/lib/upgrade-actions.js.map +2 -2
- package/dist/modules/customer_accounts/notifications.js +12 -0
- package/dist/modules/customer_accounts/notifications.js.map +2 -2
- package/dist/modules/customers/notifications.js +4 -0
- package/dist/modules/customers/notifications.js.map +2 -2
- package/dist/modules/devices/acl.js +11 -0
- package/dist/modules/devices/acl.js.map +7 -0
- package/dist/modules/devices/api/[id]/route.js +167 -0
- package/dist/modules/devices/api/[id]/route.js.map +7 -0
- package/dist/modules/devices/api/admin/devices/[id]/route.js +219 -0
- package/dist/modules/devices/api/admin/devices/[id]/route.js.map +7 -0
- package/dist/modules/devices/api/admin/devices/route.js +140 -0
- package/dist/modules/devices/api/admin/devices/route.js.map +7 -0
- package/dist/modules/devices/api/auth.js +9 -0
- package/dist/modules/devices/api/auth.js.map +7 -0
- package/dist/modules/devices/api/deviceList.js +53 -0
- package/dist/modules/devices/api/deviceList.js.map +7 -0
- package/dist/modules/devices/api/deviceOps.js +118 -0
- package/dist/modules/devices/api/deviceOps.js.map +7 -0
- package/dist/modules/devices/api/openapi.js +19 -0
- package/dist/modules/devices/api/openapi.js.map +7 -0
- package/dist/modules/devices/api/route.js +143 -0
- package/dist/modules/devices/api/route.js.map +7 -0
- package/dist/modules/devices/backend/devices/[id]/page.js +135 -0
- package/dist/modules/devices/backend/devices/[id]/page.js.map +7 -0
- package/dist/modules/devices/backend/devices/[id]/page.meta.js +16 -0
- package/dist/modules/devices/backend/devices/[id]/page.meta.js.map +7 -0
- package/dist/modules/devices/backend/devices/create/page.js +68 -0
- package/dist/modules/devices/backend/devices/create/page.js.map +7 -0
- package/dist/modules/devices/backend/devices/create/page.meta.js +16 -0
- package/dist/modules/devices/backend/devices/create/page.meta.js.map +7 -0
- package/dist/modules/devices/backend/devices/page.js +235 -0
- package/dist/modules/devices/backend/devices/page.js.map +7 -0
- package/dist/modules/devices/backend/devices/page.meta.js +23 -0
- package/dist/modules/devices/backend/devices/page.meta.js.map +7 -0
- package/dist/modules/devices/commands/deactivate.js +107 -0
- package/dist/modules/devices/commands/deactivate.js.map +7 -0
- package/dist/modules/devices/commands/index.js +4 -0
- package/dist/modules/devices/commands/index.js.map +7 -0
- package/dist/modules/devices/commands/register.js +183 -0
- package/dist/modules/devices/commands/register.js.map +7 -0
- package/dist/modules/devices/commands/shared.js +74 -0
- package/dist/modules/devices/commands/shared.js.map +7 -0
- package/dist/modules/devices/commands/update.js +126 -0
- package/dist/modules/devices/commands/update.js.map +7 -0
- package/dist/modules/devices/data/entities.js +83 -0
- package/dist/modules/devices/data/entities.js.map +7 -0
- package/dist/modules/devices/data/validators.js +49 -0
- package/dist/modules/devices/data/validators.js.map +7 -0
- package/dist/modules/devices/di.js +11 -0
- package/dist/modules/devices/di.js.map +7 -0
- package/dist/modules/devices/encryption.js +12 -0
- package/dist/modules/devices/encryption.js.map +7 -0
- package/dist/modules/devices/events.js +19 -0
- package/dist/modules/devices/events.js.map +7 -0
- package/dist/modules/devices/index.js +17 -0
- package/dist/modules/devices/index.js.map +7 -0
- package/dist/modules/devices/lib/operationMetadata.js +20 -0
- package/dist/modules/devices/lib/operationMetadata.js.map +7 -0
- package/dist/modules/devices/migrations/Migration20260602120000.js +15 -0
- package/dist/modules/devices/migrations/Migration20260602120000.js.map +7 -0
- package/dist/modules/devices/migrations/Migration20260630120000.js +15 -0
- package/dist/modules/devices/migrations/Migration20260630120000.js.map +7 -0
- package/dist/modules/devices/migrations/Migration20260701120000.js +13 -0
- package/dist/modules/devices/migrations/Migration20260701120000.js.map +7 -0
- package/dist/modules/devices/migrations/Migration20260721120000.js +15 -0
- package/dist/modules/devices/migrations/Migration20260721120000.js.map +7 -0
- package/dist/modules/devices/setup.js +13 -0
- package/dist/modules/devices/setup.js.map +7 -0
- package/dist/modules/entities/cli.js +8 -3
- package/dist/modules/entities/cli.js.map +2 -2
- package/dist/modules/entities/migrations/Migration20260722120000.js +28 -0
- package/dist/modules/entities/migrations/Migration20260722120000.js.map +7 -0
- package/dist/modules/inbox_ops/notifications.js +2 -0
- package/dist/modules/inbox_ops/notifications.js.map +2 -2
- package/dist/modules/messages/notifications.js +2 -0
- package/dist/modules/messages/notifications.js.map +2 -2
- package/dist/modules/notifications/acl.js +3 -1
- package/dist/modules/notifications/acl.js.map +2 -2
- package/dist/modules/notifications/api/admin/preferences/route.js +167 -0
- package/dist/modules/notifications/api/admin/preferences/route.js.map +7 -0
- package/dist/modules/notifications/api/channels/route.js +54 -0
- package/dist/modules/notifications/api/channels/route.js.map +7 -0
- package/dist/modules/notifications/api/preferences/route.js +126 -0
- package/dist/modules/notifications/api/preferences/route.js.map +7 -0
- package/dist/modules/notifications/api/route.js +8 -1
- package/dist/modules/notifications/api/route.js.map +2 -2
- package/dist/modules/notifications/api/types/[id]/channels/[channel]/route.js +187 -0
- package/dist/modules/notifications/api/types/[id]/channels/[channel]/route.js.map +7 -0
- package/dist/modules/notifications/api/types/route.js +225 -0
- package/dist/modules/notifications/api/types/route.js.map +7 -0
- package/dist/modules/notifications/api/unread-count/route.js +5 -1
- package/dist/modules/notifications/api/unread-count/route.js.map +2 -2
- package/dist/modules/notifications/backend/notifications/user-preferences/page.js +10 -0
- package/dist/modules/notifications/backend/notifications/user-preferences/page.js.map +7 -0
- package/dist/modules/notifications/backend/notifications/user-preferences/page.meta.js +28 -0
- package/dist/modules/notifications/backend/notifications/user-preferences/page.meta.js.map +7 -0
- package/dist/modules/notifications/backend/profile/notification-preferences/page.js +10 -0
- package/dist/modules/notifications/backend/profile/notification-preferences/page.js.map +7 -0
- package/dist/modules/notifications/backend/profile/notification-preferences/page.meta.js +33 -0
- package/dist/modules/notifications/backend/profile/notification-preferences/page.meta.js.map +7 -0
- package/dist/modules/notifications/data/entities.js +128 -1
- package/dist/modules/notifications/data/entities.js.map +2 -2
- package/dist/modules/notifications/data/validators.js +95 -2
- package/dist/modules/notifications/data/validators.js.map +2 -2
- package/dist/modules/notifications/di.js +7 -0
- package/dist/modules/notifications/di.js.map +2 -2
- package/dist/modules/notifications/events.js +17 -0
- package/dist/modules/notifications/events.js.map +2 -2
- package/dist/modules/notifications/frontend/NotificationPreferenceMatrix.js +190 -0
- package/dist/modules/notifications/frontend/NotificationPreferenceMatrix.js.map +7 -0
- package/dist/modules/notifications/frontend/NotificationPreferencesPageClient.js +124 -0
- package/dist/modules/notifications/frontend/NotificationPreferencesPageClient.js.map +7 -0
- package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js +166 -1
- package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js.map +2 -2
- package/dist/modules/notifications/frontend/NotificationUserPreferencesAdminPageClient.js +172 -0
- package/dist/modules/notifications/frontend/NotificationUserPreferencesAdminPageClient.js.map +7 -0
- package/dist/modules/notifications/generators.js +63 -0
- package/dist/modules/notifications/generators.js.map +7 -0
- package/dist/modules/notifications/lib/delivery-strategies-registry.js +19 -0
- package/dist/modules/notifications/lib/delivery-strategies-registry.js.map +7 -0
- package/dist/modules/notifications/lib/deliveryStrategies.js.map +2 -2
- package/dist/modules/notifications/lib/derive-category.js +8 -0
- package/dist/modules/notifications/lib/derive-category.js.map +7 -0
- package/dist/modules/notifications/lib/notification-channel-registry.js +35 -0
- package/dist/modules/notifications/lib/notification-channel-registry.js.map +7 -0
- package/dist/modules/notifications/lib/notification-type-registry.js +87 -0
- package/dist/modules/notifications/lib/notification-type-registry.js.map +7 -0
- package/dist/modules/notifications/lib/notificationCopy.js +14 -0
- package/dist/modules/notifications/lib/notificationCopy.js.map +7 -0
- package/dist/modules/notifications/lib/notificationFactory.js +4 -1
- package/dist/modules/notifications/lib/notificationFactory.js.map +2 -2
- package/dist/modules/notifications/lib/notificationMapper.js +2 -0
- package/dist/modules/notifications/lib/notificationMapper.js.map +2 -2
- package/dist/modules/notifications/lib/notificationPreferenceService.js +83 -0
- package/dist/modules/notifications/lib/notificationPreferenceService.js.map +7 -0
- package/dist/modules/notifications/lib/notificationService.js +83 -28
- package/dist/modules/notifications/lib/notificationService.js.map +2 -2
- package/dist/modules/notifications/lib/notificationVisibility.js +24 -0
- package/dist/modules/notifications/lib/notificationVisibility.js.map +7 -0
- package/dist/modules/notifications/lib/routeHelpers.js +11 -1
- package/dist/modules/notifications/lib/routeHelpers.js.map +2 -2
- package/dist/modules/notifications/lib/shouldDeliver.js +46 -0
- package/dist/modules/notifications/lib/shouldDeliver.js.map +7 -0
- package/dist/modules/notifications/lib/strategies/email-delivery-strategy.js +54 -0
- package/dist/modules/notifications/lib/strategies/email-delivery-strategy.js.map +7 -0
- package/dist/modules/notifications/lib/strategies/in-app-delivery-strategy.js +12 -0
- package/dist/modules/notifications/lib/strategies/in-app-delivery-strategy.js.map +7 -0
- package/dist/modules/notifications/lib/typeCatalogue.js +71 -0
- package/dist/modules/notifications/lib/typeCatalogue.js.map +7 -0
- package/dist/modules/notifications/lib/typeChannelSettings.js +12 -0
- package/dist/modules/notifications/lib/typeChannelSettings.js.map +7 -0
- package/dist/modules/notifications/lib/typeOverrides.js +19 -0
- package/dist/modules/notifications/lib/typeOverrides.js.map +7 -0
- package/dist/modules/notifications/migrations/Migration20260625122947_notifications.js +14 -0
- package/dist/modules/notifications/migrations/Migration20260625122947_notifications.js.map +7 -0
- package/dist/modules/notifications/migrations/Migration20260626120500_notifications_push_payload.js +15 -0
- package/dist/modules/notifications/migrations/Migration20260626120500_notifications_push_payload.js.map +7 -0
- package/dist/modules/notifications/migrations/Migration20260626130000_notifications_non_opt_out.js +13 -0
- package/dist/modules/notifications/migrations/Migration20260626130000_notifications_non_opt_out.js.map +7 -0
- package/dist/modules/notifications/migrations/Migration20260626140000_notifications_type_category_silent.js +15 -0
- package/dist/modules/notifications/migrations/Migration20260626140000_notifications_type_category_silent.js.map +7 -0
- package/dist/modules/notifications/migrations/Migration20260706120000_notifications_channels.js +13 -0
- package/dist/modules/notifications/migrations/Migration20260706120000_notifications_channels.js.map +7 -0
- package/dist/modules/notifications/migrations/Migration20260716123121_notifications.js +14 -0
- package/dist/modules/notifications/migrations/Migration20260716123121_notifications.js.map +7 -0
- package/dist/modules/notifications/notification-channels.js +26 -0
- package/dist/modules/notifications/notification-channels.js.map +7 -0
- package/dist/modules/notifications/notifications.delivery-strategies.js +12 -0
- package/dist/modules/notifications/notifications.delivery-strategies.js.map +7 -0
- package/dist/modules/notifications/setup.js +16 -1
- package/dist/modules/notifications/setup.js.map +2 -2
- package/dist/modules/notifications/subscribers/deliver-notification.js +66 -57
- package/dist/modules/notifications/subscribers/deliver-notification.js.map +2 -2
- package/dist/modules/notifications/subscribers/sync-notification-types.js +16 -0
- package/dist/modules/notifications/subscribers/sync-notification-types.js.map +7 -0
- package/dist/modules/notifications/widgets/injection/profile-preferences-menu/widget.js +23 -0
- package/dist/modules/notifications/widgets/injection/profile-preferences-menu/widget.js.map +7 -0
- package/dist/modules/notifications/widgets/injection-table.js +14 -0
- package/dist/modules/notifications/widgets/injection-table.js.map +7 -0
- package/dist/modules/push_notifications/acl.js +13 -0
- package/dist/modules/push_notifications/acl.js.map +7 -0
- package/dist/modules/push_notifications/api/custom-send/route.js +141 -0
- package/dist/modules/push_notifications/api/custom-send/route.js.map +7 -0
- package/dist/modules/push_notifications/api/deliveries/[id]/route.js +110 -0
- package/dist/modules/push_notifications/api/deliveries/[id]/route.js.map +7 -0
- package/dist/modules/push_notifications/api/deliveries/route.js +56 -0
- package/dist/modules/push_notifications/api/deliveries/route.js.map +7 -0
- package/dist/modules/push_notifications/api/openapi.js +19 -0
- package/dist/modules/push_notifications/api/openapi.js.map +7 -0
- package/dist/modules/push_notifications/backend/push_notifications/[id]/page.js +103 -0
- package/dist/modules/push_notifications/backend/push_notifications/[id]/page.js.map +7 -0
- package/dist/modules/push_notifications/backend/push_notifications/[id]/page.meta.js +13 -0
- package/dist/modules/push_notifications/backend/push_notifications/[id]/page.meta.js.map +7 -0
- package/dist/modules/push_notifications/backend/push_notifications/page.js +213 -0
- package/dist/modules/push_notifications/backend/push_notifications/page.js.map +7 -0
- package/dist/modules/push_notifications/backend/push_notifications/page.meta.js +23 -0
- package/dist/modules/push_notifications/backend/push_notifications/page.meta.js.map +7 -0
- package/dist/modules/push_notifications/backend/push_notifications/send/page.js +245 -0
- package/dist/modules/push_notifications/backend/push_notifications/send/page.js.map +7 -0
- package/dist/modules/push_notifications/backend/push_notifications/send/page.meta.js +26 -0
- package/dist/modules/push_notifications/backend/push_notifications/send/page.meta.js.map +7 -0
- package/dist/modules/push_notifications/data/entities.js +92 -0
- package/dist/modules/push_notifications/data/entities.js.map +7 -0
- package/dist/modules/push_notifications/data/extensions.js +23 -0
- package/dist/modules/push_notifications/data/extensions.js.map +7 -0
- package/dist/modules/push_notifications/data/validators.js +89 -0
- package/dist/modules/push_notifications/data/validators.js.map +7 -0
- package/dist/modules/push_notifications/di.js +17 -0
- package/dist/modules/push_notifications/di.js.map +7 -0
- package/dist/modules/push_notifications/events.js +24 -0
- package/dist/modules/push_notifications/events.js.map +7 -0
- package/dist/modules/push_notifications/index.js +16 -0
- package/dist/modules/push_notifications/index.js.map +7 -0
- package/dist/modules/push_notifications/lib/fake-provider-recorder.js +80 -0
- package/dist/modules/push_notifications/lib/fake-provider-recorder.js.map +7 -0
- package/dist/modules/push_notifications/lib/push-delivery-strategy.js +54 -0
- package/dist/modules/push_notifications/lib/push-delivery-strategy.js.map +7 -0
- package/dist/modules/push_notifications/lib/push-delivery.js +297 -0
- package/dist/modules/push_notifications/lib/push-delivery.js.map +7 -0
- package/dist/modules/push_notifications/lib/push-fanout.js +138 -0
- package/dist/modules/push_notifications/lib/push-fanout.js.map +7 -0
- package/dist/modules/push_notifications/lib/push-health.js +32 -0
- package/dist/modules/push_notifications/lib/push-health.js.map +7 -0
- package/dist/modules/push_notifications/lib/push-reaper.js +87 -0
- package/dist/modules/push_notifications/lib/push-reaper.js.map +7 -0
- package/dist/modules/push_notifications/lib/push-receipt-reaper.js +136 -0
- package/dist/modules/push_notifications/lib/push-receipt-reaper.js.map +7 -0
- package/dist/modules/push_notifications/lib/push-stub-adapter.js +63 -0
- package/dist/modules/push_notifications/lib/push-stub-adapter.js.map +7 -0
- package/dist/modules/push_notifications/lib/queue.js +53 -0
- package/dist/modules/push_notifications/lib/queue.js.map +7 -0
- package/dist/modules/push_notifications/lib/reclaim-window.js +13 -0
- package/dist/modules/push_notifications/lib/reclaim-window.js.map +7 -0
- package/dist/modules/push_notifications/lib/send-custom-push.js +48 -0
- package/dist/modules/push_notifications/lib/send-custom-push.js.map +7 -0
- package/dist/modules/push_notifications/migrations/Migration20260625150049_push_notifications.js +16 -0
- package/dist/modules/push_notifications/migrations/Migration20260625150049_push_notifications.js.map +7 -0
- package/dist/modules/push_notifications/migrations/Migration20260626120000_push_notifications_silent.js +13 -0
- package/dist/modules/push_notifications/migrations/Migration20260626120000_push_notifications_silent.js.map +7 -0
- package/dist/modules/push_notifications/notifications.delivery-strategies.js +8 -0
- package/dist/modules/push_notifications/notifications.delivery-strategies.js.map +7 -0
- package/dist/modules/push_notifications/notifications.js +40 -0
- package/dist/modules/push_notifications/notifications.js.map +7 -0
- package/dist/modules/push_notifications/setup.js +52 -0
- package/dist/modules/push_notifications/setup.js.map +7 -0
- package/dist/modules/push_notifications/workers/reclaim-stuck.worker.js +57 -0
- package/dist/modules/push_notifications/workers/reclaim-stuck.worker.js.map +7 -0
- package/dist/modules/push_notifications/workers/send-push.worker.js +27 -0
- package/dist/modules/push_notifications/workers/send-push.worker.js.map +7 -0
- package/dist/modules/sales/notifications.js +8 -0
- package/dist/modules/sales/notifications.js.map +2 -2
- package/dist/modules/staff/notifications.js +6 -0
- package/dist/modules/staff/notifications.js.map +2 -2
- package/dist/modules/workflows/notifications.js +2 -0
- package/dist/modules/workflows/notifications.js.map +2 -2
- package/generated/entities/notification/index.ts +3 -0
- package/generated/entities/notification_preference/index.ts +8 -0
- package/generated/entities/notification_type/index.ts +9 -0
- package/generated/entities/notification_type_override/index.ts +7 -0
- package/generated/entities/push_notification_delivery/index.ts +19 -0
- package/generated/entities/user_device/index.ts +16 -0
- package/generated/entities.ids.generated.ts +12 -1
- package/generated/entity-fields-registry.ts +72 -0
- package/package.json +7 -7
- package/src/helpers/integration/api.ts +2 -1
- package/src/helpers/integration/appRoot.ts +13 -0
- package/src/helpers/integration/dbFixtures.ts +1 -5
- package/src/helpers/integration/pushFake.ts +219 -0
- package/src/modules/auth/i18n/de.json +1 -0
- package/src/modules/auth/i18n/en.json +1 -0
- package/src/modules/auth/i18n/es.json +1 -0
- package/src/modules/auth/i18n/ko.json +1 -0
- package/src/modules/auth/i18n/pl.json +1 -0
- package/src/modules/auth/notifications.ts +16 -0
- package/src/modules/business_rules/i18n/de.json +2 -1
- package/src/modules/business_rules/i18n/en.json +2 -1
- package/src/modules/business_rules/i18n/es.json +2 -1
- package/src/modules/business_rules/i18n/ko.json +2 -1
- package/src/modules/business_rules/i18n/pl.json +2 -1
- package/src/modules/business_rules/notifications.ts +2 -0
- package/src/modules/catalog/i18n/de.json +2 -1
- package/src/modules/catalog/i18n/en.json +2 -1
- package/src/modules/catalog/i18n/es.json +2 -1
- package/src/modules/catalog/i18n/ko.json +2 -1
- package/src/modules/catalog/i18n/pl.json +2 -1
- package/src/modules/catalog/notifications.ts +2 -0
- package/src/modules/communication_channels/acl.ts +9 -0
- package/src/modules/communication_channels/api/delete/admin/channels/[id]/route.ts +168 -0
- package/src/modules/communication_channels/api/get/channels/[id]/health/route.ts +6 -2
- package/src/modules/communication_channels/api/get/channels/[id]/route.ts +6 -2
- package/src/modules/communication_channels/api/get/channels/route.ts +2 -1
- package/src/modules/communication_channels/api/post/channels/[id]/test-send/route.ts +16 -5
- package/src/modules/communication_channels/api/post/channels/connect/credentials/route.ts +37 -1
- package/src/modules/communication_channels/api/post/channels/connect/tenant-credentials/route.ts +175 -0
- package/src/modules/communication_channels/backend/communication_channels/channels/page.tsx +11 -1
- package/src/modules/communication_channels/commands/admin-delete-channel.ts +203 -0
- package/src/modules/communication_channels/commands/connect-credential-channel.ts +63 -15
- package/src/modules/communication_channels/commands/deliver-outbound-message.ts +10 -2
- package/src/modules/communication_channels/commands/push-register.ts +7 -1
- package/src/modules/communication_channels/commands/push-unregister.ts +14 -3
- package/src/modules/communication_channels/data/entities.ts +10 -0
- package/src/modules/communication_channels/data/validators.ts +1 -0
- package/src/modules/communication_channels/i18n/de.json +35 -1
- package/src/modules/communication_channels/i18n/en.json +35 -1
- package/src/modules/communication_channels/i18n/es.json +35 -1
- package/src/modules/communication_channels/i18n/ko.json +35 -1
- package/src/modules/communication_channels/i18n/pl.json +35 -1
- package/src/modules/communication_channels/lib/access-control.ts +42 -0
- package/src/modules/communication_channels/lib/adapter.ts +25 -0
- package/src/modules/communication_channels/lib/connect-channel.ts +61 -26
- package/src/modules/communication_channels/lib/push-adapter.ts +139 -0
- package/src/modules/communication_channels/lib/push-capabilities.ts +42 -0
- package/src/modules/communication_channels/lib/push-connect-error.ts +52 -0
- package/src/modules/communication_channels/lib/push-credential-errors.ts +58 -0
- package/src/modules/communication_channels/lib/push-envelope.ts +104 -0
- package/src/modules/communication_channels/lib/refcounted-client-cache.ts +123 -0
- package/src/modules/communication_channels/migrations/.snapshot-open-mercato.json +9 -0
- package/src/modules/communication_channels/migrations/Migration20260703123630_communication_channels.ts +20 -0
- package/src/modules/communication_channels/notifications.ts +4 -0
- package/src/modules/communication_channels/setup.ts +2 -0
- package/src/modules/configs/i18n/de.json +5 -1
- package/src/modules/configs/i18n/en.json +5 -1
- package/src/modules/configs/i18n/es.json +5 -1
- package/src/modules/configs/i18n/ko.json +5 -1
- package/src/modules/configs/i18n/pl.json +5 -1
- package/src/modules/configs/lib/upgrade-actions.ts +21 -0
- package/src/modules/customer_accounts/i18n/de.json +2 -1
- package/src/modules/customer_accounts/i18n/en.json +2 -1
- package/src/modules/customer_accounts/i18n/es.json +2 -1
- package/src/modules/customer_accounts/i18n/ko.json +2 -1
- package/src/modules/customer_accounts/i18n/pl.json +2 -1
- package/src/modules/customer_accounts/notifications.ts +12 -0
- package/src/modules/customers/i18n/de.json +2 -1
- package/src/modules/customers/i18n/en.json +2 -1
- package/src/modules/customers/i18n/es.json +2 -1
- package/src/modules/customers/i18n/ko.json +2 -1
- package/src/modules/customers/i18n/pl.json +2 -1
- package/src/modules/customers/notifications.ts +4 -0
- package/src/modules/devices/AGENTS.md +101 -0
- package/src/modules/devices/acl.ts +7 -0
- package/src/modules/devices/api/[id]/route.ts +180 -0
- package/src/modules/devices/api/admin/devices/[id]/route.ts +235 -0
- package/src/modules/devices/api/admin/devices/route.ts +160 -0
- package/src/modules/devices/api/auth.ts +13 -0
- package/src/modules/devices/api/deviceList.ts +54 -0
- package/src/modules/devices/api/deviceOps.ts +186 -0
- package/src/modules/devices/api/openapi.ts +23 -0
- package/src/modules/devices/api/route.ts +165 -0
- package/src/modules/devices/backend/devices/[id]/page.meta.ts +12 -0
- package/src/modules/devices/backend/devices/[id]/page.tsx +164 -0
- package/src/modules/devices/backend/devices/create/page.meta.ts +12 -0
- package/src/modules/devices/backend/devices/create/page.tsx +81 -0
- package/src/modules/devices/backend/devices/page.meta.ts +21 -0
- package/src/modules/devices/backend/devices/page.tsx +259 -0
- package/src/modules/devices/commands/deactivate.ts +126 -0
- package/src/modules/devices/commands/index.ts +3 -0
- package/src/modules/devices/commands/register.ts +199 -0
- package/src/modules/devices/commands/shared.ts +119 -0
- package/src/modules/devices/commands/update.ts +142 -0
- package/src/modules/devices/data/entities.ts +79 -0
- package/src/modules/devices/data/validators.ts +65 -0
- package/src/modules/devices/di.ts +9 -0
- package/src/modules/devices/encryption.ts +15 -0
- package/src/modules/devices/events.ts +16 -0
- package/src/modules/devices/i18n/de.json +45 -0
- package/src/modules/devices/i18n/en.json +45 -0
- package/src/modules/devices/i18n/es.json +45 -0
- package/src/modules/devices/i18n/ko.json +45 -0
- package/src/modules/devices/i18n/pl.json +45 -0
- package/src/modules/devices/index.ts +15 -0
- package/src/modules/devices/lib/operationMetadata.ts +35 -0
- package/src/modules/devices/migrations/.snapshot-open-mercato.json +200 -0
- package/src/modules/devices/migrations/Migration20260602120000.ts +15 -0
- package/src/modules/devices/migrations/Migration20260630120000.ts +20 -0
- package/src/modules/devices/migrations/Migration20260701120000.ts +13 -0
- package/src/modules/devices/migrations/Migration20260721120000.ts +18 -0
- package/src/modules/devices/setup.ts +11 -0
- package/src/modules/entities/cli.ts +16 -2
- package/src/modules/entities/migrations/Migration20260722120000.ts +38 -0
- package/src/modules/inbox_ops/i18n/de.json +2 -1
- package/src/modules/inbox_ops/i18n/en.json +2 -1
- package/src/modules/inbox_ops/i18n/es.json +2 -1
- package/src/modules/inbox_ops/i18n/ko.json +2 -1
- package/src/modules/inbox_ops/i18n/pl.json +2 -1
- package/src/modules/inbox_ops/notifications.ts +2 -0
- package/src/modules/messages/i18n/de.json +2 -1
- package/src/modules/messages/i18n/en.json +2 -1
- package/src/modules/messages/i18n/es.json +2 -1
- package/src/modules/messages/i18n/ko.json +2 -1
- package/src/modules/messages/i18n/pl.json +2 -1
- package/src/modules/messages/notifications.ts +2 -0
- package/src/modules/notifications/AGENTS.md +54 -0
- package/src/modules/notifications/acl.ts +2 -0
- package/src/modules/notifications/api/admin/preferences/route.ts +193 -0
- package/src/modules/notifications/api/channels/route.ts +54 -0
- package/src/modules/notifications/api/preferences/route.ts +131 -0
- package/src/modules/notifications/api/route.ts +8 -1
- package/src/modules/notifications/api/types/[id]/channels/[channel]/route.ts +226 -0
- package/src/modules/notifications/api/types/route.ts +239 -0
- package/src/modules/notifications/api/unread-count/route.ts +5 -1
- package/src/modules/notifications/backend/notifications/user-preferences/page.meta.ts +26 -0
- package/src/modules/notifications/backend/notifications/user-preferences/page.tsx +12 -0
- package/src/modules/notifications/backend/profile/notification-preferences/page.meta.ts +31 -0
- package/src/modules/notifications/backend/profile/notification-preferences/page.tsx +12 -0
- package/src/modules/notifications/data/entities.ts +144 -0
- package/src/modules/notifications/data/validators.ts +116 -0
- package/src/modules/notifications/di.ts +7 -0
- package/src/modules/notifications/events.ts +23 -0
- package/src/modules/notifications/frontend/NotificationPreferenceMatrix.tsx +287 -0
- package/src/modules/notifications/frontend/NotificationPreferencesPageClient.tsx +155 -0
- package/src/modules/notifications/frontend/NotificationSettingsPageClient.tsx +273 -2
- package/src/modules/notifications/frontend/NotificationUserPreferencesAdminPageClient.tsx +214 -0
- package/src/modules/notifications/generators.ts +82 -0
- package/src/modules/notifications/i18n/de.json +43 -0
- package/src/modules/notifications/i18n/en.json +43 -0
- package/src/modules/notifications/i18n/es.json +43 -0
- package/src/modules/notifications/i18n/ko.json +43 -0
- package/src/modules/notifications/i18n/pl.json +44 -1
- package/src/modules/notifications/lib/delivery-strategies-registry.ts +30 -0
- package/src/modules/notifications/lib/deliveryStrategies.ts +40 -4
- package/src/modules/notifications/lib/derive-category.ts +15 -0
- package/src/modules/notifications/lib/notification-channel-registry.ts +59 -0
- package/src/modules/notifications/lib/notification-type-registry.ts +182 -0
- package/src/modules/notifications/lib/notificationCopy.ts +34 -0
- package/src/modules/notifications/lib/notificationFactory.ts +5 -1
- package/src/modules/notifications/lib/notificationMapper.ts +2 -0
- package/src/modules/notifications/lib/notificationPreferenceService.ts +138 -0
- package/src/modules/notifications/lib/notificationService.ts +129 -25
- package/src/modules/notifications/lib/notificationVisibility.ts +48 -0
- package/src/modules/notifications/lib/routeHelpers.ts +14 -1
- package/src/modules/notifications/lib/shouldDeliver.ts +112 -0
- package/src/modules/notifications/lib/strategies/email-delivery-strategy.ts +63 -0
- package/src/modules/notifications/lib/strategies/in-app-delivery-strategy.ts +21 -0
- package/src/modules/notifications/lib/typeCatalogue.ts +141 -0
- package/src/modules/notifications/lib/typeChannelSettings.ts +29 -0
- package/src/modules/notifications/lib/typeOverrides.ts +46 -0
- package/src/modules/notifications/migrations/.snapshot-open-mercato.json +874 -100
- package/src/modules/notifications/migrations/Migration20260625122947_notifications.ts +14 -0
- package/src/modules/notifications/migrations/Migration20260626120500_notifications_push_payload.ts +15 -0
- package/src/modules/notifications/migrations/Migration20260626130000_notifications_non_opt_out.ts +13 -0
- package/src/modules/notifications/migrations/Migration20260626140000_notifications_type_category_silent.ts +15 -0
- package/src/modules/notifications/migrations/Migration20260706120000_notifications_channels.ts +13 -0
- package/src/modules/notifications/migrations/Migration20260716123121_notifications.ts +14 -0
- package/src/modules/notifications/notification-channels.ts +30 -0
- package/src/modules/notifications/notifications.delivery-strategies.ts +15 -0
- package/src/modules/notifications/setup.ts +23 -1
- package/src/modules/notifications/subscribers/deliver-notification.ts +105 -71
- package/src/modules/notifications/subscribers/sync-notification-types.ts +18 -0
- package/src/modules/notifications/widgets/injection/profile-preferences-menu/widget.ts +35 -0
- package/src/modules/notifications/widgets/injection-table.ts +18 -0
- package/src/modules/push_notifications/AGENTS.md +92 -0
- package/src/modules/push_notifications/acl.ts +9 -0
- package/src/modules/push_notifications/api/custom-send/route.ts +175 -0
- package/src/modules/push_notifications/api/deliveries/[id]/route.ts +122 -0
- package/src/modules/push_notifications/api/deliveries/route.ts +58 -0
- package/src/modules/push_notifications/api/openapi.ts +22 -0
- package/src/modules/push_notifications/backend/push_notifications/[id]/page.meta.ts +9 -0
- package/src/modules/push_notifications/backend/push_notifications/[id]/page.tsx +149 -0
- package/src/modules/push_notifications/backend/push_notifications/page.meta.ts +21 -0
- package/src/modules/push_notifications/backend/push_notifications/page.tsx +239 -0
- package/src/modules/push_notifications/backend/push_notifications/send/page.meta.ts +24 -0
- package/src/modules/push_notifications/backend/push_notifications/send/page.tsx +327 -0
- package/src/modules/push_notifications/data/entities.ts +111 -0
- package/src/modules/push_notifications/data/extensions.ts +29 -0
- package/src/modules/push_notifications/data/validators.ts +102 -0
- package/src/modules/push_notifications/di.ts +20 -0
- package/src/modules/push_notifications/events.ts +21 -0
- package/src/modules/push_notifications/i18n/de.json +79 -0
- package/src/modules/push_notifications/i18n/en.json +79 -0
- package/src/modules/push_notifications/i18n/es.json +79 -0
- package/src/modules/push_notifications/i18n/ko.json +79 -0
- package/src/modules/push_notifications/i18n/pl.json +79 -0
- package/src/modules/push_notifications/index.ts +15 -0
- package/src/modules/push_notifications/lib/fake-provider-recorder.ts +154 -0
- package/src/modules/push_notifications/lib/push-delivery-strategy.ts +90 -0
- package/src/modules/push_notifications/lib/push-delivery.ts +455 -0
- package/src/modules/push_notifications/lib/push-fanout.ts +237 -0
- package/src/modules/push_notifications/lib/push-health.ts +47 -0
- package/src/modules/push_notifications/lib/push-reaper.ts +140 -0
- package/src/modules/push_notifications/lib/push-receipt-reaper.ts +210 -0
- package/src/modules/push_notifications/lib/push-stub-adapter.ts +80 -0
- package/src/modules/push_notifications/lib/queue.ts +74 -0
- package/src/modules/push_notifications/lib/reclaim-window.ts +16 -0
- package/src/modules/push_notifications/lib/send-custom-push.ts +100 -0
- package/src/modules/push_notifications/migrations/.snapshot-open-mercato.json +386 -0
- package/src/modules/push_notifications/migrations/Migration20260625150049_push_notifications.ts +16 -0
- package/src/modules/push_notifications/migrations/Migration20260626120000_push_notifications_silent.ts +13 -0
- package/src/modules/push_notifications/notifications.delivery-strategies.ts +8 -0
- package/src/modules/push_notifications/notifications.ts +50 -0
- package/src/modules/push_notifications/setup.ts +92 -0
- package/src/modules/push_notifications/workers/reclaim-stuck.worker.ts +78 -0
- package/src/modules/push_notifications/workers/send-push.worker.ts +34 -0
- package/src/modules/sales/i18n/de.json +1 -0
- package/src/modules/sales/i18n/en.json +1 -0
- package/src/modules/sales/i18n/es.json +1 -0
- package/src/modules/sales/i18n/ko.json +1 -0
- package/src/modules/sales/i18n/pl.json +1 -0
- package/src/modules/sales/notifications.ts +8 -0
- package/src/modules/staff/i18n/de.json +1 -0
- package/src/modules/staff/i18n/en.json +1 -0
- package/src/modules/staff/i18n/es.json +1 -0
- package/src/modules/staff/i18n/ko.json +1 -0
- package/src/modules/staff/i18n/pl.json +1 -0
- package/src/modules/staff/notifications.ts +6 -0
- package/src/modules/workflows/i18n/de.json +1 -0
- package/src/modules/workflows/i18n/en.json +1 -0
- package/src/modules/workflows/i18n/es.json +1 -0
- package/src/modules/workflows/i18n/ko.json +1 -0
- package/src/modules/workflows/i18n/pl.json +1 -0
- package/src/modules/workflows/notifications.ts +2 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { OptionalProps } from '@mikro-orm/core'
|
|
2
|
+
import { Entity, Index, PrimaryKey, Property } from '@mikro-orm/decorators/legacy'
|
|
3
|
+
|
|
4
|
+
export type PushDeliveryStatus = 'pending' | 'sending' | 'sent' | 'failed' | 'skipped' | 'expired'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Append-only delivery log for a single push notification attempt against one device.
|
|
8
|
+
*
|
|
9
|
+
* One row per (notification, device). The strategy inserts rows `pending`; the `send-push` worker
|
|
10
|
+
* atomically claims a row (`pending` → `sending`, so a redelivered job is processed once) and then
|
|
11
|
+
* transitions it to `sent`/`failed`/`skipped`, or `expired` once retries are exhausted. This is a
|
|
12
|
+
* background-job/log row, so it is intentionally EXEMPT from optimistic locking
|
|
13
|
+
* (status transitions are server-driven, never concurrently user-edited) and is
|
|
14
|
+
* NOT added to the curated `optimistic-lock-editable-entities` list.
|
|
15
|
+
*
|
|
16
|
+
* `push_token` is a secret: the full token is never persisted here — only
|
|
17
|
+
* `token_snapshot` (last 8 chars, for debugging across token rotation) plus the
|
|
18
|
+
* `provider` snapshot so the audit trail survives token rotation and device deletion.
|
|
19
|
+
*/
|
|
20
|
+
@Entity({ tableName: 'push_notification_deliveries' })
|
|
21
|
+
@Index({ name: 'push_notification_deliveries_tenant_status_idx', properties: ['tenantId', 'status', 'createdAt'] })
|
|
22
|
+
@Index({ name: 'push_notification_deliveries_notification_idx', properties: ['notificationId'] })
|
|
23
|
+
// Idempotency guard for the fan-out: the `push` strategy runs inside the at-least-once persistent
|
|
24
|
+
// `notifications:deliver` subscriber, so a redelivered event would otherwise insert a second set of
|
|
25
|
+
// rows for the same (notification, device) → a duplicate push. A partial unique index (only where
|
|
26
|
+
// notification_id is set — direct/silent pushes without a notification are out of scope) lets the
|
|
27
|
+
// strategy insert-on-conflict-do-nothing, making a re-run a no-op.
|
|
28
|
+
@Index({
|
|
29
|
+
name: 'push_notification_deliveries_notif_device_unique',
|
|
30
|
+
expression:
|
|
31
|
+
'create unique index "push_notification_deliveries_notif_device_unique" on "push_notification_deliveries" ("notification_id", "user_device_id") where "notification_id" is not null',
|
|
32
|
+
})
|
|
33
|
+
export class PushNotificationDelivery {
|
|
34
|
+
[OptionalProps]?:
|
|
35
|
+
| 'organizationId'
|
|
36
|
+
| 'notificationId'
|
|
37
|
+
| 'status'
|
|
38
|
+
| 'attempts'
|
|
39
|
+
| 'lastError'
|
|
40
|
+
| 'providerResponse'
|
|
41
|
+
| 'silent'
|
|
42
|
+
| 'createdAt'
|
|
43
|
+
| 'sentAt'
|
|
44
|
+
| 'nextRetryAt'
|
|
45
|
+
| 'updatedAt'
|
|
46
|
+
|
|
47
|
+
@PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })
|
|
48
|
+
id!: string
|
|
49
|
+
|
|
50
|
+
@Property({ name: 'tenant_id', type: 'uuid' })
|
|
51
|
+
tenantId!: string
|
|
52
|
+
|
|
53
|
+
@Property({ name: 'organization_id', type: 'uuid', nullable: true })
|
|
54
|
+
organizationId?: string | null
|
|
55
|
+
|
|
56
|
+
// Soft FK -> notifications.notifications (nullable: a push can be dispatched without an in-app row).
|
|
57
|
+
@Property({ name: 'notification_id', type: 'uuid', nullable: true })
|
|
58
|
+
notificationId?: string | null
|
|
59
|
+
|
|
60
|
+
@Property({ name: 'notification_type_id', type: 'text' })
|
|
61
|
+
notificationTypeId!: string
|
|
62
|
+
|
|
63
|
+
// Soft FK -> devices.user_devices (link declared in data/extensions.ts).
|
|
64
|
+
@Property({ name: 'user_device_id', type: 'uuid' })
|
|
65
|
+
userDeviceId!: string
|
|
66
|
+
|
|
67
|
+
@Property({ name: 'user_id', type: 'uuid' })
|
|
68
|
+
userId!: string
|
|
69
|
+
|
|
70
|
+
// Snapshot of the push CommunicationChannel providerKey used at send time.
|
|
71
|
+
@Property({ name: 'provider', type: 'text' })
|
|
72
|
+
provider!: string
|
|
73
|
+
|
|
74
|
+
// Last 8 chars of the device push token only — never the full secret.
|
|
75
|
+
@Property({ name: 'token_snapshot', type: 'text' })
|
|
76
|
+
tokenSnapshot!: string
|
|
77
|
+
|
|
78
|
+
// Snapshot of whether this was a silent / content-available wake-up (derived from the
|
|
79
|
+
// notification type's `silent` flag at fan-out time) so the log distinguishes silent deliveries.
|
|
80
|
+
@Property({ name: 'silent', type: 'boolean', default: false })
|
|
81
|
+
silent: boolean = false
|
|
82
|
+
|
|
83
|
+
@Property({ name: 'status', type: 'text', default: 'pending' })
|
|
84
|
+
status: PushDeliveryStatus = 'pending'
|
|
85
|
+
|
|
86
|
+
@Property({ name: 'attempts', type: 'int', default: 0 })
|
|
87
|
+
attempts: number = 0
|
|
88
|
+
|
|
89
|
+
@Property({ name: 'last_error', type: 'text', nullable: true })
|
|
90
|
+
lastError?: string | null
|
|
91
|
+
|
|
92
|
+
@Property({ name: 'payload', type: 'json' })
|
|
93
|
+
payload!: Record<string, unknown>
|
|
94
|
+
|
|
95
|
+
@Property({ name: 'provider_response', type: 'json', nullable: true })
|
|
96
|
+
providerResponse?: Record<string, unknown> | null
|
|
97
|
+
|
|
98
|
+
@Property({ name: 'created_at', type: Date, onCreate: () => new Date() })
|
|
99
|
+
createdAt: Date = new Date()
|
|
100
|
+
|
|
101
|
+
@Property({ name: 'sent_at', type: Date, nullable: true })
|
|
102
|
+
sentAt?: Date | null
|
|
103
|
+
|
|
104
|
+
// Set when a retryable failure re-enqueues the job (observability for the admin delivery log);
|
|
105
|
+
// cleared once the delivery reaches a terminal state.
|
|
106
|
+
@Property({ name: 'next_retry_at', type: Date, nullable: true })
|
|
107
|
+
nextRetryAt?: Date | null
|
|
108
|
+
|
|
109
|
+
@Property({ name: 'updated_at', type: Date, onCreate: () => new Date(), onUpdate: () => new Date() })
|
|
110
|
+
updatedAt: Date = new Date()
|
|
111
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { EntityExtension } from '@open-mercato/shared/modules/entities'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Cross-module entity links declared by the push_notifications module.
|
|
5
|
+
*
|
|
6
|
+
* Per root AGENTS.md, modules do NOT form direct ORM relationships across
|
|
7
|
+
* boundaries. `PushNotificationDelivery` carries plain UUID columns that
|
|
8
|
+
* reference rows owned by other modules; the links are declared here so the
|
|
9
|
+
* data engine + UI tooling can traverse them.
|
|
10
|
+
*/
|
|
11
|
+
const entityExtensions: EntityExtension[] = [
|
|
12
|
+
{
|
|
13
|
+
base: 'push_notifications:push_notification_delivery',
|
|
14
|
+
extension: 'devices:user_device',
|
|
15
|
+
join: { baseKey: 'user_device_id', extensionKey: 'id' },
|
|
16
|
+
cardinality: 'many-to-one',
|
|
17
|
+
description: 'Links a push delivery row to the target user device it was sent to',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
base: 'push_notifications:push_notification_delivery',
|
|
21
|
+
extension: 'notifications:notification',
|
|
22
|
+
join: { baseKey: 'notification_id', extensionKey: 'id' },
|
|
23
|
+
cardinality: 'many-to-one',
|
|
24
|
+
description: 'Links a push delivery row to the in-app notification that triggered it',
|
|
25
|
+
},
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
export const extensions = entityExtensions
|
|
29
|
+
export default entityExtensions
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import { pushOptionsSchema } from '@open-mercato/core/modules/notifications/data/validators'
|
|
3
|
+
|
|
4
|
+
export const PUSH_DELIVERY_STATUSES = ['pending', 'sending', 'sent', 'failed', 'skipped', 'expired'] as const
|
|
5
|
+
|
|
6
|
+
// A `created_at` range bound: an ISO-8601 date (`2026-07-01`) or datetime (`2026-07-01T00:00:00Z`).
|
|
7
|
+
// Validated here so a malformed value fails with a 400 instead of reaching the query engine / Postgres.
|
|
8
|
+
const rangeDateFilter = z.union([z.string().datetime({ offset: true }), z.string().date()])
|
|
9
|
+
|
|
10
|
+
// POST /api/push_notifications/custom-send — admin composes a one-off visible push to a single user.
|
|
11
|
+
// title/body are literal free text (not i18n keys). data/pushOptions reuse the notifications contract.
|
|
12
|
+
export const customSendSchema = z
|
|
13
|
+
.object({
|
|
14
|
+
recipientUserId: z.string().uuid(),
|
|
15
|
+
// Optional: target one of the recipient's devices; omit to send to all their devices.
|
|
16
|
+
deviceId: z.string().uuid().optional(),
|
|
17
|
+
title: z.string().trim().min(1).max(500),
|
|
18
|
+
body: z.string().trim().max(2000).nullish(),
|
|
19
|
+
data: z.record(z.string(), z.string()).optional(),
|
|
20
|
+
pushOptions: pushOptionsSchema.optional(),
|
|
21
|
+
// When true, deliver a silent data-only wake-up instead of a visible banner.
|
|
22
|
+
silent: z.boolean().optional(),
|
|
23
|
+
})
|
|
24
|
+
.strict()
|
|
25
|
+
export type CustomSendInput = z.infer<typeof customSendSchema>
|
|
26
|
+
|
|
27
|
+
// Machine-readable warning surfaced when a well-formed send resolved no deliverable device in scope
|
|
28
|
+
// (no push channel configured, no in-scope devices, or none whose provider matches an active channel).
|
|
29
|
+
// The caller gets `enqueued: 0` plus this code + a human `message` instead of a misleading silent success.
|
|
30
|
+
export const CUSTOM_SEND_NO_DEVICES_WARNING = 'no_matching_devices_in_scope'
|
|
31
|
+
|
|
32
|
+
export const customSendResponseSchema = z.object({
|
|
33
|
+
enqueued: z.number(),
|
|
34
|
+
warning: z.literal(CUSTOM_SEND_NO_DEVICES_WARNING).optional(),
|
|
35
|
+
message: z.string().optional(),
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
// Read-only delivery-log list contract (admin observability). No full push token is ever exposed —
|
|
39
|
+
// only `token_snapshot` (last 8 chars) and the `provider` snapshot.
|
|
40
|
+
export const deliveryListSchema = z
|
|
41
|
+
.object({
|
|
42
|
+
page: z.coerce.number().min(1).default(1),
|
|
43
|
+
pageSize: z.coerce.number().min(1).max(100).default(50),
|
|
44
|
+
status: z.enum(PUSH_DELIVERY_STATUSES).optional(),
|
|
45
|
+
userId: z.string().uuid().optional(),
|
|
46
|
+
from: rangeDateFilter.optional(),
|
|
47
|
+
to: rangeDateFilter.optional(),
|
|
48
|
+
sortField: z.string().optional(),
|
|
49
|
+
sortDir: z.enum(['asc', 'desc']).optional(),
|
|
50
|
+
})
|
|
51
|
+
.passthrough()
|
|
52
|
+
|
|
53
|
+
export const deliveryListFields: string[] = [
|
|
54
|
+
'id',
|
|
55
|
+
'tenant_id',
|
|
56
|
+
'organization_id',
|
|
57
|
+
'notification_id',
|
|
58
|
+
'notification_type_id',
|
|
59
|
+
'user_device_id',
|
|
60
|
+
'user_id',
|
|
61
|
+
'provider',
|
|
62
|
+
'token_snapshot',
|
|
63
|
+
'status',
|
|
64
|
+
'attempts',
|
|
65
|
+
'last_error',
|
|
66
|
+
'created_at',
|
|
67
|
+
'sent_at',
|
|
68
|
+
'next_retry_at',
|
|
69
|
+
'updated_at',
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
export const deliveryListSortFieldMap: Record<string, string> = {
|
|
73
|
+
createdAt: 'created_at',
|
|
74
|
+
sentAt: 'sent_at',
|
|
75
|
+
updatedAt: 'updated_at',
|
|
76
|
+
status: 'status',
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export const deliveryListItemSchema = z.object({
|
|
80
|
+
id: z.string().uuid(),
|
|
81
|
+
tenant_id: z.string().uuid(),
|
|
82
|
+
organization_id: z.string().uuid().nullable().optional(),
|
|
83
|
+
notification_id: z.string().uuid().nullable().optional(),
|
|
84
|
+
notification_type_id: z.string(),
|
|
85
|
+
user_device_id: z.string().uuid(),
|
|
86
|
+
user_id: z.string().uuid(),
|
|
87
|
+
provider: z.string(),
|
|
88
|
+
token_snapshot: z.string(),
|
|
89
|
+
status: z.enum(PUSH_DELIVERY_STATUSES),
|
|
90
|
+
attempts: z.number(),
|
|
91
|
+
last_error: z.string().nullable().optional(),
|
|
92
|
+
created_at: z.string().nullable().optional(),
|
|
93
|
+
sent_at: z.string().nullable().optional(),
|
|
94
|
+
next_retry_at: z.string().nullable().optional(),
|
|
95
|
+
updated_at: z.string().nullable().optional(),
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
// Detail adds the JSON payload + provider response (still no full token).
|
|
99
|
+
export const deliveryDetailItemSchema = deliveryListItemSchema.extend({
|
|
100
|
+
payload: z.record(z.string(), z.unknown()).nullable().optional(),
|
|
101
|
+
provider_response: z.record(z.string(), z.unknown()).nullable().optional(),
|
|
102
|
+
})
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { asValue } from 'awilix'
|
|
2
|
+
import type { AppContainer } from '@open-mercato/shared/lib/di/container'
|
|
3
|
+
import { PushNotificationDelivery } from './data/entities'
|
|
4
|
+
import { ensurePushStubAdapterRegistered } from './lib/push-stub-adapter'
|
|
5
|
+
import { pushNotificationService } from './lib/send-custom-push'
|
|
6
|
+
|
|
7
|
+
export function register(container: AppContainer) {
|
|
8
|
+
// Test-only: register the network-free `push_stub` channel adapter when
|
|
9
|
+
// `OM_ENABLE_PUSH_STUB_ADAPTER` is set (no-op in production). Lets the integration harness drive
|
|
10
|
+
// the strategy → delivery-row → worker → sendMessage chain without a real provider. Mirrors the
|
|
11
|
+
// communication_channels test-seed adapter registration. See lib/push-stub-adapter.ts.
|
|
12
|
+
ensurePushStubAdapterRegistered()
|
|
13
|
+
|
|
14
|
+
container.register({
|
|
15
|
+
PushNotificationDelivery: asValue(PushNotificationDelivery),
|
|
16
|
+
// Stateless service backing the admin custom-send push (decoupled via DI). The caller passes
|
|
17
|
+
// its own scoped `resolve` in the call args.
|
|
18
|
+
pushNotificationService: asValue(pushNotificationService),
|
|
19
|
+
})
|
|
20
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { createModuleEvents } from '@open-mercato/shared/modules/events'
|
|
2
|
+
|
|
3
|
+
const events = [
|
|
4
|
+
{ id: 'push_notifications.delivery.sent', label: 'Push Delivery Sent', entity: 'delivery', category: 'lifecycle' },
|
|
5
|
+
{
|
|
6
|
+
id: 'push_notifications.delivery.failed',
|
|
7
|
+
label: 'Push Delivery Failed',
|
|
8
|
+
entity: 'delivery',
|
|
9
|
+
category: 'lifecycle',
|
|
10
|
+
// Fires on every failed send attempt for a delivery, not only the terminal one. A retryable
|
|
11
|
+
// failure that will be re-attempted carries `willRetry: true`; the final give-up (and terminal
|
|
12
|
+
// errors like channel_unavailable / no_adapter) omit it. Subscribers that count "deliveries that
|
|
13
|
+
// ultimately failed" MUST filter to `willRetry !== true` to avoid double-counting retries.
|
|
14
|
+
description: 'A push delivery attempt failed. Carries willRetry:true when another attempt is scheduled.',
|
|
15
|
+
},
|
|
16
|
+
] as const
|
|
17
|
+
|
|
18
|
+
export const eventsConfig = createModuleEvents({ moduleId: 'push_notifications', events })
|
|
19
|
+
export const emitPushNotificationsEvent = eventsConfig.emit
|
|
20
|
+
export type PushNotificationsEventId = typeof events[number]['id']
|
|
21
|
+
export default eventsConfig
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{
|
|
2
|
+
"push_notifications.deliveries.columns.attempts": "Versuche",
|
|
3
|
+
"push_notifications.deliveries.columns.created": "Erstellt",
|
|
4
|
+
"push_notifications.deliveries.columns.provider": "Anbieter",
|
|
5
|
+
"push_notifications.deliveries.columns.sent": "Gesendet",
|
|
6
|
+
"push_notifications.deliveries.columns.status": "Status",
|
|
7
|
+
"push_notifications.deliveries.columns.type": "Typ",
|
|
8
|
+
"push_notifications.deliveries.columns.user": "Benutzer",
|
|
9
|
+
"push_notifications.deliveries.detail.device": "Gerät",
|
|
10
|
+
"push_notifications.deliveries.detail.lastError": "Letzter Fehler",
|
|
11
|
+
"push_notifications.deliveries.detail.loading": "Zustellung wird geladen…",
|
|
12
|
+
"push_notifications.deliveries.detail.nextRetry": "Nächster Versuch",
|
|
13
|
+
"push_notifications.deliveries.detail.pageTitle": "Push-Zustellung",
|
|
14
|
+
"push_notifications.deliveries.detail.payload": "Nutzdaten",
|
|
15
|
+
"push_notifications.deliveries.detail.providerResponse": "Anbieter-Antwort",
|
|
16
|
+
"push_notifications.deliveries.detail.tokenSnapshot": "Token (letzte 8)",
|
|
17
|
+
"push_notifications.deliveries.empty": "Noch keine Push-Zustellungen",
|
|
18
|
+
"push_notifications.deliveries.error.loadFailed": "Push-Zustellungen konnten nicht geladen werden",
|
|
19
|
+
"push_notifications.deliveries.filters.created": "Erstellt",
|
|
20
|
+
"push_notifications.deliveries.filters.from": "Von",
|
|
21
|
+
"push_notifications.deliveries.filters.to": "Bis",
|
|
22
|
+
"push_notifications.deliveries.noValue": "—",
|
|
23
|
+
"push_notifications.deliveries.pageTitle": "Push-Zustellungen",
|
|
24
|
+
"push_notifications.deliveries.status.expired": "Abgelaufen",
|
|
25
|
+
"push_notifications.deliveries.status.failed": "Fehlgeschlagen",
|
|
26
|
+
"push_notifications.deliveries.status.pending": "Ausstehend",
|
|
27
|
+
"push_notifications.deliveries.status.sending": "Wird gesendet",
|
|
28
|
+
"push_notifications.deliveries.status.sent": "Gesendet",
|
|
29
|
+
"push_notifications.deliveries.status.skipped": "Übersprungen",
|
|
30
|
+
"push_notifications.deliveries.title": "Push-Zustellungen",
|
|
31
|
+
"push_notifications.errors.forbidden": "Zugriff verweigert",
|
|
32
|
+
"push_notifications.errors.invalid_id": "Ungültige Zustellungs-ID",
|
|
33
|
+
"push_notifications.errors.invalid_payload": "Ungültige Anfrage",
|
|
34
|
+
"push_notifications.errors.not_found": "Zustellung nicht gefunden",
|
|
35
|
+
"push_notifications.errors.send_failed": "Push-Benachrichtigung konnte nicht gesendet werden",
|
|
36
|
+
"push_notifications.errors.server_error": "Etwas ist schief gelaufen",
|
|
37
|
+
"push_notifications.errors.unauthorized": "Nicht autorisiert",
|
|
38
|
+
"push_notifications.send.badge": "Badge-Zähler",
|
|
39
|
+
"push_notifications.send.body": "Text",
|
|
40
|
+
"push_notifications.send.channelId": "Android-Kanal-ID",
|
|
41
|
+
"push_notifications.send.data": "Daten (eigene Schlüssel/Werte)",
|
|
42
|
+
"push_notifications.send.dataAdd": "Feld hinzufügen",
|
|
43
|
+
"push_notifications.send.dataEmpty": "Noch keine eigenen Daten.",
|
|
44
|
+
"push_notifications.send.dataHint": "Wird in der Push-Nutzlast geliefert — deine App liest sie. Bei einem stillen Push ist dies die gesamte Nutzlast.",
|
|
45
|
+
"push_notifications.send.dataKey": "Schlüssel",
|
|
46
|
+
"push_notifications.send.dataRemove": "Feld entfernen",
|
|
47
|
+
"push_notifications.send.dataValue": "Wert",
|
|
48
|
+
"push_notifications.send.device": "Gerät",
|
|
49
|
+
"push_notifications.send.deviceAll": "Alle Geräte",
|
|
50
|
+
"push_notifications.send.deviceHint": "An dieses bestimmte Gerät oder an alle Geräte des Empfängers senden.",
|
|
51
|
+
"push_notifications.send.deviceNone": "Dieser Empfänger hat keine push-fähigen Geräte",
|
|
52
|
+
"push_notifications.send.deviceSelectUserFirst": "Zuerst einen Empfänger auswählen",
|
|
53
|
+
"push_notifications.send.image": "Bild-URL",
|
|
54
|
+
"push_notifications.send.message": "Nachricht",
|
|
55
|
+
"push_notifications.send.mode": "Zustellung",
|
|
56
|
+
"push_notifications.send.modeHint": "Sichtbar zeigt ein Banner; still ist ein reines Daten-Update im Hintergrund.",
|
|
57
|
+
"push_notifications.send.modeSilent": "Still (Hintergrund)",
|
|
58
|
+
"push_notifications.send.modeVisible": "Sichtbar",
|
|
59
|
+
"push_notifications.send.options": "Push-Optionen",
|
|
60
|
+
"push_notifications.send.optionsHint": "Optionale Anbieter-Anpassung. Ton/Badge/Bild gelten für sichtbare Pushes.",
|
|
61
|
+
"push_notifications.send.pageTitle": "Push senden",
|
|
62
|
+
"push_notifications.send.priority": "Priorität",
|
|
63
|
+
"push_notifications.send.priorityDefault": "Standard",
|
|
64
|
+
"push_notifications.send.priorityHigh": "Hoch",
|
|
65
|
+
"push_notifications.send.priorityNormal": "Normal",
|
|
66
|
+
"push_notifications.send.sound": "Ton",
|
|
67
|
+
"push_notifications.send.submit": "Push senden",
|
|
68
|
+
"push_notifications.send.success": "Push zum Versand eingereiht",
|
|
69
|
+
"push_notifications.send.title": "Titel",
|
|
70
|
+
"push_notifications.send.userId": "Empfänger",
|
|
71
|
+
"push_notifications.send.userIdHint": "Nach Name oder E-Mail suchen — die Geräte dieses Benutzers erhalten den Push.",
|
|
72
|
+
"push_notifications.types.admin_custom_message.body": "Sie haben eine neue Nachricht.",
|
|
73
|
+
"push_notifications.types.admin_custom_message.label": "Admin-Nachricht",
|
|
74
|
+
"push_notifications.types.admin_custom_message.title": "Admin-Nachricht",
|
|
75
|
+
"push_notifications.types.admin_custom_silent.body": "Hintergrund-Update.",
|
|
76
|
+
"push_notifications.types.admin_custom_silent.label": "Stille Admin-Nachricht",
|
|
77
|
+
"push_notifications.types.admin_custom_silent.title": "Stille Nachricht",
|
|
78
|
+
"push_notifications.warnings.no_matching_devices_in_scope": "Kein push-fähiges Gerät dieses Empfängers passte zum ausgewählten Bereich, daher wurde nichts gesendet."
|
|
79
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{
|
|
2
|
+
"push_notifications.deliveries.columns.attempts": "Attempts",
|
|
3
|
+
"push_notifications.deliveries.columns.created": "Created",
|
|
4
|
+
"push_notifications.deliveries.columns.provider": "Provider",
|
|
5
|
+
"push_notifications.deliveries.columns.sent": "Sent",
|
|
6
|
+
"push_notifications.deliveries.columns.status": "Status",
|
|
7
|
+
"push_notifications.deliveries.columns.type": "Type",
|
|
8
|
+
"push_notifications.deliveries.columns.user": "User",
|
|
9
|
+
"push_notifications.deliveries.detail.device": "Device",
|
|
10
|
+
"push_notifications.deliveries.detail.lastError": "Last error",
|
|
11
|
+
"push_notifications.deliveries.detail.loading": "Loading delivery…",
|
|
12
|
+
"push_notifications.deliveries.detail.nextRetry": "Next retry",
|
|
13
|
+
"push_notifications.deliveries.detail.pageTitle": "Push delivery",
|
|
14
|
+
"push_notifications.deliveries.detail.payload": "Payload",
|
|
15
|
+
"push_notifications.deliveries.detail.providerResponse": "Provider response",
|
|
16
|
+
"push_notifications.deliveries.detail.tokenSnapshot": "Token (last 8)",
|
|
17
|
+
"push_notifications.deliveries.empty": "No push deliveries yet",
|
|
18
|
+
"push_notifications.deliveries.error.loadFailed": "Failed to load push deliveries",
|
|
19
|
+
"push_notifications.deliveries.filters.created": "Created",
|
|
20
|
+
"push_notifications.deliveries.filters.from": "From",
|
|
21
|
+
"push_notifications.deliveries.filters.to": "To",
|
|
22
|
+
"push_notifications.deliveries.noValue": "—",
|
|
23
|
+
"push_notifications.deliveries.pageTitle": "Push Deliveries",
|
|
24
|
+
"push_notifications.deliveries.status.expired": "Expired",
|
|
25
|
+
"push_notifications.deliveries.status.failed": "Failed",
|
|
26
|
+
"push_notifications.deliveries.status.pending": "Pending",
|
|
27
|
+
"push_notifications.deliveries.status.sending": "Sending",
|
|
28
|
+
"push_notifications.deliveries.status.sent": "Sent",
|
|
29
|
+
"push_notifications.deliveries.status.skipped": "Skipped",
|
|
30
|
+
"push_notifications.deliveries.title": "Push deliveries",
|
|
31
|
+
"push_notifications.errors.forbidden": "Access denied",
|
|
32
|
+
"push_notifications.errors.invalid_id": "Invalid delivery id",
|
|
33
|
+
"push_notifications.errors.invalid_payload": "Invalid request",
|
|
34
|
+
"push_notifications.errors.not_found": "Delivery not found",
|
|
35
|
+
"push_notifications.errors.send_failed": "Failed to send push notification",
|
|
36
|
+
"push_notifications.errors.server_error": "Something went wrong",
|
|
37
|
+
"push_notifications.errors.unauthorized": "Unauthorized",
|
|
38
|
+
"push_notifications.send.badge": "Badge count",
|
|
39
|
+
"push_notifications.send.body": "Body",
|
|
40
|
+
"push_notifications.send.channelId": "Android channel ID",
|
|
41
|
+
"push_notifications.send.data": "Data (custom key/values)",
|
|
42
|
+
"push_notifications.send.dataAdd": "Add field",
|
|
43
|
+
"push_notifications.send.dataEmpty": "No custom data yet.",
|
|
44
|
+
"push_notifications.send.dataHint": "Delivered inside the push payload — your app reads these. For a silent push this is the whole payload.",
|
|
45
|
+
"push_notifications.send.dataKey": "key",
|
|
46
|
+
"push_notifications.send.dataRemove": "Remove field",
|
|
47
|
+
"push_notifications.send.dataValue": "value",
|
|
48
|
+
"push_notifications.send.device": "Device",
|
|
49
|
+
"push_notifications.send.deviceAll": "All devices",
|
|
50
|
+
"push_notifications.send.deviceHint": "Send to this specific device, or all of the recipient's devices.",
|
|
51
|
+
"push_notifications.send.deviceNone": "This recipient has no push-capable devices",
|
|
52
|
+
"push_notifications.send.deviceSelectUserFirst": "Select a recipient first",
|
|
53
|
+
"push_notifications.send.image": "Image URL",
|
|
54
|
+
"push_notifications.send.message": "Message",
|
|
55
|
+
"push_notifications.send.mode": "Delivery",
|
|
56
|
+
"push_notifications.send.modeHint": "Visible shows a banner; silent is a data-only background wake-up.",
|
|
57
|
+
"push_notifications.send.modeSilent": "Silent (background)",
|
|
58
|
+
"push_notifications.send.modeVisible": "Visible",
|
|
59
|
+
"push_notifications.send.options": "Push options",
|
|
60
|
+
"push_notifications.send.optionsHint": "Optional per-provider customization. Sound/badge/image apply to visible pushes.",
|
|
61
|
+
"push_notifications.send.pageTitle": "Send Push",
|
|
62
|
+
"push_notifications.send.priority": "Priority",
|
|
63
|
+
"push_notifications.send.priorityDefault": "Default",
|
|
64
|
+
"push_notifications.send.priorityHigh": "High",
|
|
65
|
+
"push_notifications.send.priorityNormal": "Normal",
|
|
66
|
+
"push_notifications.send.sound": "Sound",
|
|
67
|
+
"push_notifications.send.submit": "Send push",
|
|
68
|
+
"push_notifications.send.success": "Push queued for delivery",
|
|
69
|
+
"push_notifications.send.title": "Title",
|
|
70
|
+
"push_notifications.send.userId": "Recipient",
|
|
71
|
+
"push_notifications.send.userIdHint": "Search by name or email — their devices receive this push.",
|
|
72
|
+
"push_notifications.types.admin_custom_message.body": "You have a new message.",
|
|
73
|
+
"push_notifications.types.admin_custom_message.label": "Admin message",
|
|
74
|
+
"push_notifications.types.admin_custom_message.title": "Admin message",
|
|
75
|
+
"push_notifications.types.admin_custom_silent.body": "Background update.",
|
|
76
|
+
"push_notifications.types.admin_custom_silent.label": "Admin silent message",
|
|
77
|
+
"push_notifications.types.admin_custom_silent.title": "Silent message",
|
|
78
|
+
"push_notifications.warnings.no_matching_devices_in_scope": "No push-capable devices matched this recipient in the selected scope, so nothing was sent."
|
|
79
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{
|
|
2
|
+
"push_notifications.deliveries.columns.attempts": "Intentos",
|
|
3
|
+
"push_notifications.deliveries.columns.created": "Creado",
|
|
4
|
+
"push_notifications.deliveries.columns.provider": "Proveedor",
|
|
5
|
+
"push_notifications.deliveries.columns.sent": "Enviado",
|
|
6
|
+
"push_notifications.deliveries.columns.status": "Estado",
|
|
7
|
+
"push_notifications.deliveries.columns.type": "Tipo",
|
|
8
|
+
"push_notifications.deliveries.columns.user": "Usuario",
|
|
9
|
+
"push_notifications.deliveries.detail.device": "Dispositivo",
|
|
10
|
+
"push_notifications.deliveries.detail.lastError": "Último error",
|
|
11
|
+
"push_notifications.deliveries.detail.loading": "Cargando envío…",
|
|
12
|
+
"push_notifications.deliveries.detail.nextRetry": "Próximo reintento",
|
|
13
|
+
"push_notifications.deliveries.detail.pageTitle": "Envío push",
|
|
14
|
+
"push_notifications.deliveries.detail.payload": "Carga útil",
|
|
15
|
+
"push_notifications.deliveries.detail.providerResponse": "Respuesta del proveedor",
|
|
16
|
+
"push_notifications.deliveries.detail.tokenSnapshot": "Token (últimos 8)",
|
|
17
|
+
"push_notifications.deliveries.empty": "Aún no hay envíos push",
|
|
18
|
+
"push_notifications.deliveries.error.loadFailed": "No se pudieron cargar los envíos push",
|
|
19
|
+
"push_notifications.deliveries.filters.created": "Creado",
|
|
20
|
+
"push_notifications.deliveries.filters.from": "Desde",
|
|
21
|
+
"push_notifications.deliveries.filters.to": "Hasta",
|
|
22
|
+
"push_notifications.deliveries.noValue": "—",
|
|
23
|
+
"push_notifications.deliveries.pageTitle": "Envíos push",
|
|
24
|
+
"push_notifications.deliveries.status.expired": "Expirado",
|
|
25
|
+
"push_notifications.deliveries.status.failed": "Fallido",
|
|
26
|
+
"push_notifications.deliveries.status.pending": "Pendiente",
|
|
27
|
+
"push_notifications.deliveries.status.sending": "Enviando",
|
|
28
|
+
"push_notifications.deliveries.status.sent": "Enviado",
|
|
29
|
+
"push_notifications.deliveries.status.skipped": "Omitido",
|
|
30
|
+
"push_notifications.deliveries.title": "Envíos push",
|
|
31
|
+
"push_notifications.errors.forbidden": "Acceso denegado",
|
|
32
|
+
"push_notifications.errors.invalid_id": "ID de envío no válido",
|
|
33
|
+
"push_notifications.errors.invalid_payload": "Solicitud no válida",
|
|
34
|
+
"push_notifications.errors.not_found": "Envío no encontrado",
|
|
35
|
+
"push_notifications.errors.send_failed": "No se pudo enviar la notificación push",
|
|
36
|
+
"push_notifications.errors.server_error": "Algo salió mal",
|
|
37
|
+
"push_notifications.errors.unauthorized": "No autorizado",
|
|
38
|
+
"push_notifications.send.badge": "Contador de insignia",
|
|
39
|
+
"push_notifications.send.body": "Cuerpo",
|
|
40
|
+
"push_notifications.send.channelId": "ID de canal Android",
|
|
41
|
+
"push_notifications.send.data": "Datos (clave/valor personalizados)",
|
|
42
|
+
"push_notifications.send.dataAdd": "Añadir campo",
|
|
43
|
+
"push_notifications.send.dataEmpty": "Aún no hay datos personalizados.",
|
|
44
|
+
"push_notifications.send.dataHint": "Se entrega dentro del payload del push — tu app los lee. Para un push silencioso es todo el payload.",
|
|
45
|
+
"push_notifications.send.dataKey": "clave",
|
|
46
|
+
"push_notifications.send.dataRemove": "Eliminar campo",
|
|
47
|
+
"push_notifications.send.dataValue": "valor",
|
|
48
|
+
"push_notifications.send.device": "Dispositivo",
|
|
49
|
+
"push_notifications.send.deviceAll": "Todos los dispositivos",
|
|
50
|
+
"push_notifications.send.deviceHint": "Enviar a este dispositivo específico o a todos los dispositivos del destinatario.",
|
|
51
|
+
"push_notifications.send.deviceNone": "Este destinatario no tiene dispositivos compatibles con push",
|
|
52
|
+
"push_notifications.send.deviceSelectUserFirst": "Selecciona primero un destinatario",
|
|
53
|
+
"push_notifications.send.image": "URL de imagen",
|
|
54
|
+
"push_notifications.send.message": "Mensaje",
|
|
55
|
+
"push_notifications.send.mode": "Entrega",
|
|
56
|
+
"push_notifications.send.modeHint": "Visible muestra un banner; silencioso es una actualización de datos en segundo plano.",
|
|
57
|
+
"push_notifications.send.modeSilent": "Silencioso (segundo plano)",
|
|
58
|
+
"push_notifications.send.modeVisible": "Visible",
|
|
59
|
+
"push_notifications.send.options": "Opciones de push",
|
|
60
|
+
"push_notifications.send.optionsHint": "Personalización opcional por proveedor. Sonido/insignia/imagen aplican a pushes visibles.",
|
|
61
|
+
"push_notifications.send.pageTitle": "Enviar push",
|
|
62
|
+
"push_notifications.send.priority": "Prioridad",
|
|
63
|
+
"push_notifications.send.priorityDefault": "Predeterminado",
|
|
64
|
+
"push_notifications.send.priorityHigh": "Alta",
|
|
65
|
+
"push_notifications.send.priorityNormal": "Normal",
|
|
66
|
+
"push_notifications.send.sound": "Sonido",
|
|
67
|
+
"push_notifications.send.submit": "Enviar push",
|
|
68
|
+
"push_notifications.send.success": "Push en cola para envío",
|
|
69
|
+
"push_notifications.send.title": "Título",
|
|
70
|
+
"push_notifications.send.userId": "Destinatario",
|
|
71
|
+
"push_notifications.send.userIdHint": "Busca por nombre o correo — sus dispositivos reciben este push.",
|
|
72
|
+
"push_notifications.types.admin_custom_message.body": "Tienes un mensaje nuevo.",
|
|
73
|
+
"push_notifications.types.admin_custom_message.label": "Mensaje de administrador",
|
|
74
|
+
"push_notifications.types.admin_custom_message.title": "Mensaje de administrador",
|
|
75
|
+
"push_notifications.types.admin_custom_silent.body": "Actualización en segundo plano.",
|
|
76
|
+
"push_notifications.types.admin_custom_silent.label": "Mensaje silencioso de administrador",
|
|
77
|
+
"push_notifications.types.admin_custom_silent.title": "Mensaje silencioso",
|
|
78
|
+
"push_notifications.warnings.no_matching_devices_in_scope": "Ningún dispositivo con capacidad de push de este destinatario coincidió con el ámbito seleccionado, por lo que no se envió nada."
|
|
79
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{
|
|
2
|
+
"push_notifications.deliveries.columns.attempts": "시도 횟수",
|
|
3
|
+
"push_notifications.deliveries.columns.created": "생성됨",
|
|
4
|
+
"push_notifications.deliveries.columns.provider": "제공업체",
|
|
5
|
+
"push_notifications.deliveries.columns.sent": "전송됨",
|
|
6
|
+
"push_notifications.deliveries.columns.status": "상태",
|
|
7
|
+
"push_notifications.deliveries.columns.type": "유형",
|
|
8
|
+
"push_notifications.deliveries.columns.user": "사용자",
|
|
9
|
+
"push_notifications.deliveries.detail.device": "기기",
|
|
10
|
+
"push_notifications.deliveries.detail.lastError": "마지막 오류",
|
|
11
|
+
"push_notifications.deliveries.detail.loading": "전송 내역을 불러오는 중…",
|
|
12
|
+
"push_notifications.deliveries.detail.nextRetry": "다음 재시도",
|
|
13
|
+
"push_notifications.deliveries.detail.pageTitle": "푸시 전송",
|
|
14
|
+
"push_notifications.deliveries.detail.payload": "페이로드",
|
|
15
|
+
"push_notifications.deliveries.detail.providerResponse": "제공자 응답",
|
|
16
|
+
"push_notifications.deliveries.detail.tokenSnapshot": "토큰 (마지막 8자리)",
|
|
17
|
+
"push_notifications.deliveries.empty": "아직 푸시 전송 내역이 없습니다",
|
|
18
|
+
"push_notifications.deliveries.error.loadFailed": "푸시 전송 내역을 불러오지 못했습니다",
|
|
19
|
+
"push_notifications.deliveries.filters.created": "생성됨",
|
|
20
|
+
"push_notifications.deliveries.filters.from": "시작일",
|
|
21
|
+
"push_notifications.deliveries.filters.to": "종료일",
|
|
22
|
+
"push_notifications.deliveries.noValue": "—",
|
|
23
|
+
"push_notifications.deliveries.pageTitle": "푸시 전송 내역",
|
|
24
|
+
"push_notifications.deliveries.status.expired": "만료됨",
|
|
25
|
+
"push_notifications.deliveries.status.failed": "실패",
|
|
26
|
+
"push_notifications.deliveries.status.pending": "대기 중",
|
|
27
|
+
"push_notifications.deliveries.status.sending": "전송 중",
|
|
28
|
+
"push_notifications.deliveries.status.sent": "전송됨",
|
|
29
|
+
"push_notifications.deliveries.status.skipped": "건너뜀",
|
|
30
|
+
"push_notifications.deliveries.title": "푸시 전송 내역",
|
|
31
|
+
"push_notifications.errors.forbidden": "접근이 거부되었습니다",
|
|
32
|
+
"push_notifications.errors.invalid_id": "잘못된 전송 ID입니다",
|
|
33
|
+
"push_notifications.errors.invalid_payload": "잘못된 요청입니다",
|
|
34
|
+
"push_notifications.errors.not_found": "전송 내역을 찾을 수 없습니다",
|
|
35
|
+
"push_notifications.errors.send_failed": "푸시 알림을 전송하지 못했습니다",
|
|
36
|
+
"push_notifications.errors.server_error": "문제가 발생했습니다",
|
|
37
|
+
"push_notifications.errors.unauthorized": "권한이 없습니다",
|
|
38
|
+
"push_notifications.send.badge": "배지 숫자",
|
|
39
|
+
"push_notifications.send.body": "본문",
|
|
40
|
+
"push_notifications.send.channelId": "Android 채널 ID",
|
|
41
|
+
"push_notifications.send.data": "데이터 (사용자 지정 키/값)",
|
|
42
|
+
"push_notifications.send.dataAdd": "필드 추가",
|
|
43
|
+
"push_notifications.send.dataEmpty": "아직 사용자 지정 데이터가 없습니다.",
|
|
44
|
+
"push_notifications.send.dataHint": "푸시 페이로드에 담겨 전달되며 앱에서 이 값을 읽습니다. 무음 푸시에서는 이 데이터가 페이로드 전체가 됩니다.",
|
|
45
|
+
"push_notifications.send.dataKey": "키",
|
|
46
|
+
"push_notifications.send.dataRemove": "필드 삭제",
|
|
47
|
+
"push_notifications.send.dataValue": "값",
|
|
48
|
+
"push_notifications.send.device": "기기",
|
|
49
|
+
"push_notifications.send.deviceAll": "모든 기기",
|
|
50
|
+
"push_notifications.send.deviceHint": "이 특정 기기로 보내거나, 수신자의 모든 기기로 보냅니다.",
|
|
51
|
+
"push_notifications.send.deviceNone": "이 수신자에게는 푸시를 받을 수 있는 기기가 없습니다",
|
|
52
|
+
"push_notifications.send.deviceSelectUserFirst": "먼저 수신자를 선택하세요",
|
|
53
|
+
"push_notifications.send.image": "이미지 URL",
|
|
54
|
+
"push_notifications.send.message": "메시지",
|
|
55
|
+
"push_notifications.send.mode": "전송 방식",
|
|
56
|
+
"push_notifications.send.modeHint": "표시 푸시는 배너를 보여 주고, 무음 푸시는 데이터만 전달해 백그라운드에서 앱을 깨웁니다.",
|
|
57
|
+
"push_notifications.send.modeSilent": "무음 (백그라운드)",
|
|
58
|
+
"push_notifications.send.modeVisible": "표시",
|
|
59
|
+
"push_notifications.send.options": "푸시 옵션",
|
|
60
|
+
"push_notifications.send.optionsHint": "제공자별 선택 설정입니다. 소리/배지/이미지는 표시 푸시에만 적용됩니다.",
|
|
61
|
+
"push_notifications.send.pageTitle": "푸시 보내기",
|
|
62
|
+
"push_notifications.send.priority": "우선순위",
|
|
63
|
+
"push_notifications.send.priorityDefault": "기본값",
|
|
64
|
+
"push_notifications.send.priorityHigh": "높음",
|
|
65
|
+
"push_notifications.send.priorityNormal": "보통",
|
|
66
|
+
"push_notifications.send.sound": "소리",
|
|
67
|
+
"push_notifications.send.submit": "푸시 보내기",
|
|
68
|
+
"push_notifications.send.success": "푸시가 전송 대기열에 추가되었습니다",
|
|
69
|
+
"push_notifications.send.title": "제목",
|
|
70
|
+
"push_notifications.send.userId": "수신자",
|
|
71
|
+
"push_notifications.send.userIdHint": "이름 또는 이메일로 검색하세요 — 해당 사용자의 기기로 이 푸시가 전송됩니다.",
|
|
72
|
+
"push_notifications.types.admin_custom_message.body": "새 메시지가 도착했습니다.",
|
|
73
|
+
"push_notifications.types.admin_custom_message.label": "관리자 메시지",
|
|
74
|
+
"push_notifications.types.admin_custom_message.title": "관리자 메시지",
|
|
75
|
+
"push_notifications.types.admin_custom_silent.body": "백그라운드 업데이트입니다.",
|
|
76
|
+
"push_notifications.types.admin_custom_silent.label": "관리자 무음 메시지",
|
|
77
|
+
"push_notifications.types.admin_custom_silent.title": "무음 메시지",
|
|
78
|
+
"push_notifications.warnings.no_matching_devices_in_scope": "선택한 범위에서 이 수신자와 일치하는 푸시 가능 기기가 없어 아무것도 전송되지 않았습니다."
|
|
79
|
+
}
|