@open-mercato/core 0.4.2-canary-bdaa640a68 → 0.4.2-canary-3b5064ce72

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.
Files changed (497) hide show
  1. package/dist/generated/entities/notification/index.js +57 -0
  2. package/dist/generated/entities/notification/index.js.map +7 -0
  3. package/dist/generated/entities.ids.generated.js +5 -1
  4. package/dist/generated/entities.ids.generated.js.map +2 -2
  5. package/dist/generated/entity-fields-registry.js +2 -0
  6. package/dist/generated/entity-fields-registry.js.map +2 -2
  7. package/dist/modules/api_docs/frontend/docs/api/page.js +3 -2
  8. package/dist/modules/api_docs/frontend/docs/api/page.js.map +2 -2
  9. package/dist/modules/api_keys/backend/api-keys/page.js +1 -1
  10. package/dist/modules/api_keys/backend/api-keys/page.js.map +2 -2
  11. package/dist/modules/attachments/components/AttachmentLibrary.js +4 -0
  12. package/dist/modules/attachments/components/AttachmentLibrary.js.map +2 -2
  13. package/dist/modules/attachments/components/AttachmentPartitionSettings.js +2 -0
  14. package/dist/modules/attachments/components/AttachmentPartitionSettings.js.map +2 -2
  15. package/dist/modules/auth/api/admin/nav.js +4 -3
  16. package/dist/modules/auth/api/admin/nav.js.map +2 -2
  17. package/dist/modules/auth/api/login.js +25 -6
  18. package/dist/modules/auth/api/login.js.map +2 -2
  19. package/dist/modules/auth/api/profile/route.js +157 -0
  20. package/dist/modules/auth/api/profile/route.js.map +7 -0
  21. package/dist/modules/auth/api/reset/confirm.js +25 -2
  22. package/dist/modules/auth/api/reset/confirm.js.map +2 -2
  23. package/dist/modules/auth/api/reset.js +23 -0
  24. package/dist/modules/auth/api/reset.js.map +2 -2
  25. package/dist/modules/auth/api/sidebar/preferences/route.js +14 -9
  26. package/dist/modules/auth/api/sidebar/preferences/route.js.map +2 -2
  27. package/dist/modules/auth/api/users/route.js +4 -2
  28. package/dist/modules/auth/api/users/route.js.map +2 -2
  29. package/dist/modules/auth/backend/auth/profile/page.js +141 -0
  30. package/dist/modules/auth/backend/auth/profile/page.js.map +7 -0
  31. package/dist/modules/auth/backend/auth/profile/page.meta.js +13 -0
  32. package/dist/modules/auth/backend/auth/profile/page.meta.js.map +7 -0
  33. package/dist/modules/auth/backend/roles/[id]/edit/page.js +4 -1
  34. package/dist/modules/auth/backend/roles/[id]/edit/page.js.map +2 -2
  35. package/dist/modules/auth/backend/roles/page.js +3 -3
  36. package/dist/modules/auth/backend/roles/page.js.map +2 -2
  37. package/dist/modules/auth/backend/users/[id]/edit/page.js +18 -3
  38. package/dist/modules/auth/backend/users/[id]/edit/page.js.map +2 -2
  39. package/dist/modules/auth/backend/users/create/page.js +15 -2
  40. package/dist/modules/auth/backend/users/create/page.js.map +2 -2
  41. package/dist/modules/auth/backend/users/page.js +3 -3
  42. package/dist/modules/auth/backend/users/page.js.map +2 -2
  43. package/dist/modules/auth/cli.js +25 -11
  44. package/dist/modules/auth/cli.js.map +2 -2
  45. package/dist/modules/auth/commands/users.js +59 -2
  46. package/dist/modules/auth/commands/users.js.map +2 -2
  47. package/dist/modules/auth/data/validators.js +6 -3
  48. package/dist/modules/auth/data/validators.js.map +2 -2
  49. package/dist/modules/auth/frontend/login.js +112 -3
  50. package/dist/modules/auth/frontend/login.js.map +2 -2
  51. package/dist/modules/auth/frontend/reset/[token]/page.js +20 -10
  52. package/dist/modules/auth/frontend/reset/[token]/page.js.map +2 -2
  53. package/dist/modules/auth/lib/setup-app.js +42 -8
  54. package/dist/modules/auth/lib/setup-app.js.map +2 -2
  55. package/dist/modules/auth/notifications.js +112 -0
  56. package/dist/modules/auth/notifications.js.map +7 -0
  57. package/dist/modules/auth/services/authService.js +24 -3
  58. package/dist/modules/auth/services/authService.js.map +2 -2
  59. package/dist/modules/business_rules/api/execute/route.js +7 -1
  60. package/dist/modules/business_rules/api/execute/route.js.map +2 -2
  61. package/dist/modules/business_rules/backend/rules/page.js +4 -0
  62. package/dist/modules/business_rules/backend/rules/page.js.map +2 -2
  63. package/dist/modules/business_rules/backend/sets/page.js +3 -0
  64. package/dist/modules/business_rules/backend/sets/page.js.map +2 -2
  65. package/dist/modules/business_rules/cli.js +2 -1
  66. package/dist/modules/business_rules/cli.js.map +2 -2
  67. package/dist/modules/business_rules/lib/rule-engine.js +33 -3
  68. package/dist/modules/business_rules/lib/rule-engine.js.map +2 -2
  69. package/dist/modules/business_rules/notifications.js +28 -0
  70. package/dist/modules/business_rules/notifications.js.map +7 -0
  71. package/dist/modules/business_rules/subscribers/rule-execution-failed-notification.js +37 -0
  72. package/dist/modules/business_rules/subscribers/rule-execution-failed-notification.js.map +7 -0
  73. package/dist/modules/catalog/components/PriceKindSettings.js +2 -0
  74. package/dist/modules/catalog/components/PriceKindSettings.js.map +2 -2
  75. package/dist/modules/catalog/components/categories/CategoriesDataTable.js +2 -2
  76. package/dist/modules/catalog/components/categories/CategoriesDataTable.js.map +2 -2
  77. package/dist/modules/catalog/components/products/ProductsDataTable.js +2 -0
  78. package/dist/modules/catalog/components/products/ProductsDataTable.js.map +2 -2
  79. package/dist/modules/catalog/notifications.js +28 -0
  80. package/dist/modules/catalog/notifications.js.map +7 -0
  81. package/dist/modules/catalog/subscribers/low-stock-notification.js +38 -0
  82. package/dist/modules/catalog/subscribers/low-stock-notification.js.map +7 -0
  83. package/dist/modules/configs/cli.js +6 -0
  84. package/dist/modules/configs/cli.js.map +2 -2
  85. package/dist/modules/configs/components/CachePanel.js +4 -4
  86. package/dist/modules/configs/components/CachePanel.js.map +2 -2
  87. package/dist/modules/configs/lib/system-status.js +48 -1
  88. package/dist/modules/configs/lib/system-status.js.map +2 -2
  89. package/dist/modules/configs/lib/upgrade-actions.js +18 -0
  90. package/dist/modules/configs/lib/upgrade-actions.js.map +2 -2
  91. package/dist/modules/currencies/backend/currencies/page.js +3 -0
  92. package/dist/modules/currencies/backend/currencies/page.js.map +2 -2
  93. package/dist/modules/currencies/backend/exchange-rates/page.js +2 -0
  94. package/dist/modules/currencies/backend/exchange-rates/page.js.map +2 -2
  95. package/dist/modules/customers/backend/customers/companies/page.js +3 -0
  96. package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
  97. package/dist/modules/customers/backend/customers/deals/page.js +3 -0
  98. package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
  99. package/dist/modules/customers/backend/customers/people/page.js +3 -0
  100. package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
  101. package/dist/modules/customers/commands/deals.js +31 -0
  102. package/dist/modules/customers/commands/deals.js.map +2 -2
  103. package/dist/modules/customers/components/CustomerTodosTable.js +1 -0
  104. package/dist/modules/customers/components/CustomerTodosTable.js.map +2 -2
  105. package/dist/modules/customers/notifications.js +48 -0
  106. package/dist/modules/customers/notifications.js.map +7 -0
  107. package/dist/modules/customers/widgets/dashboard/customer-todos/widget.js +2 -1
  108. package/dist/modules/customers/widgets/dashboard/customer-todos/widget.js.map +2 -2
  109. package/dist/modules/customers/widgets/dashboard/new-customers/widget.js +2 -1
  110. package/dist/modules/customers/widgets/dashboard/new-customers/widget.js.map +2 -2
  111. package/dist/modules/customers/widgets/dashboard/new-deals/widget.js +2 -1
  112. package/dist/modules/customers/widgets/dashboard/new-deals/widget.js.map +2 -2
  113. package/dist/modules/customers/widgets/dashboard/next-interactions/widget.js +2 -1
  114. package/dist/modules/customers/widgets/dashboard/next-interactions/widget.js.map +2 -2
  115. package/dist/modules/dashboards/cli.js +44 -5
  116. package/dist/modules/dashboards/cli.js.map +2 -2
  117. package/dist/modules/dashboards/components/WidgetVisibilityEditor.js +16 -11
  118. package/dist/modules/dashboards/components/WidgetVisibilityEditor.js.map +3 -3
  119. package/dist/modules/dashboards/lib/role-widgets.js +58 -0
  120. package/dist/modules/dashboards/lib/role-widgets.js.map +7 -0
  121. package/dist/modules/dashboards/services/widgetDataService.js +139 -3
  122. package/dist/modules/dashboards/services/widgetDataService.js.map +2 -2
  123. package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.js +2 -1
  124. package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.js.map +2 -2
  125. package/dist/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.js +2 -1
  126. package/dist/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.js.map +2 -2
  127. package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.js +2 -1
  128. package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.js.map +2 -2
  129. package/dist/modules/dashboards/widgets/dashboard/orders-kpi/widget.js +2 -1
  130. package/dist/modules/dashboards/widgets/dashboard/orders-kpi/widget.js.map +2 -2
  131. package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.js +2 -1
  132. package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.js.map +2 -2
  133. package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.js +2 -1
  134. package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.js.map +2 -2
  135. package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.js +2 -1
  136. package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.js.map +2 -2
  137. package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.js +2 -1
  138. package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.js.map +2 -2
  139. package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.js +2 -1
  140. package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.js.map +2 -2
  141. package/dist/modules/dashboards/widgets/dashboard/top-products/widget.js +2 -1
  142. package/dist/modules/dashboards/widgets/dashboard/top-products/widget.js.map +2 -2
  143. package/dist/modules/dictionaries/components/DictionaryTable.js +2 -0
  144. package/dist/modules/dictionaries/components/DictionaryTable.js.map +2 -2
  145. package/dist/modules/directory/api/get/tenants/lookup.js +70 -0
  146. package/dist/modules/directory/api/get/tenants/lookup.js.map +7 -0
  147. package/dist/modules/directory/backend/directory/organizations/page.js +2 -2
  148. package/dist/modules/directory/backend/directory/organizations/page.js.map +2 -2
  149. package/dist/modules/directory/backend/directory/tenants/page.js +2 -2
  150. package/dist/modules/directory/backend/directory/tenants/page.js.map +2 -2
  151. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js +2 -2
  152. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js.map +2 -2
  153. package/dist/modules/entities/components/SystemEntitiesTable.js +1 -1
  154. package/dist/modules/entities/components/SystemEntitiesTable.js.map +2 -2
  155. package/dist/modules/entities/components/UserEntitiesTable.js +2 -2
  156. package/dist/modules/entities/components/UserEntitiesTable.js.map +2 -2
  157. package/dist/modules/feature_toggles/components/FeatureTogglesTable.js +3 -3
  158. package/dist/modules/feature_toggles/components/FeatureTogglesTable.js.map +2 -2
  159. package/dist/modules/feature_toggles/components/OverridesTable.js +1 -1
  160. package/dist/modules/feature_toggles/components/OverridesTable.js.map +2 -2
  161. package/dist/modules/notifications/acl.js +11 -0
  162. package/dist/modules/notifications/acl.js.map +7 -0
  163. package/dist/modules/notifications/api/[id]/action/route.js +74 -0
  164. package/dist/modules/notifications/api/[id]/action/route.js.map +7 -0
  165. package/dist/modules/notifications/api/[id]/dismiss/route.js +15 -0
  166. package/dist/modules/notifications/api/[id]/dismiss/route.js.map +7 -0
  167. package/dist/modules/notifications/api/[id]/read/route.js +15 -0
  168. package/dist/modules/notifications/api/[id]/read/route.js.map +7 -0
  169. package/dist/modules/notifications/api/[id]/restore/route.js +53 -0
  170. package/dist/modules/notifications/api/[id]/restore/route.js.map +7 -0
  171. package/dist/modules/notifications/api/batch/route.js +17 -0
  172. package/dist/modules/notifications/api/batch/route.js.map +7 -0
  173. package/dist/modules/notifications/api/feature/route.js +17 -0
  174. package/dist/modules/notifications/api/feature/route.js.map +7 -0
  175. package/dist/modules/notifications/api/mark-all-read/route.js +35 -0
  176. package/dist/modules/notifications/api/mark-all-read/route.js.map +7 -0
  177. package/dist/modules/notifications/api/openapi.js +76 -0
  178. package/dist/modules/notifications/api/openapi.js.map +7 -0
  179. package/dist/modules/notifications/api/role/route.js +17 -0
  180. package/dist/modules/notifications/api/role/route.js.map +7 -0
  181. package/dist/modules/notifications/api/route.js +85 -0
  182. package/dist/modules/notifications/api/route.js.map +7 -0
  183. package/dist/modules/notifications/api/settings/route.js +155 -0
  184. package/dist/modules/notifications/api/settings/route.js.map +7 -0
  185. package/dist/modules/notifications/api/unread-count/route.js +38 -0
  186. package/dist/modules/notifications/api/unread-count/route.js.map +7 -0
  187. package/dist/modules/notifications/backend/config/notifications/page.js +10 -0
  188. package/dist/modules/notifications/backend/config/notifications/page.js.map +7 -0
  189. package/dist/modules/notifications/backend/config/notifications/page.meta.js +24 -0
  190. package/dist/modules/notifications/backend/config/notifications/page.meta.js.map +7 -0
  191. package/dist/modules/notifications/cli.js +16 -0
  192. package/dist/modules/notifications/cli.js.map +7 -0
  193. package/dist/modules/notifications/data/entities.js +112 -0
  194. package/dist/modules/notifications/data/entities.js.map +7 -0
  195. package/dist/modules/notifications/data/validators.js +98 -0
  196. package/dist/modules/notifications/data/validators.js.map +7 -0
  197. package/dist/modules/notifications/di.js +13 -0
  198. package/dist/modules/notifications/di.js.map +7 -0
  199. package/dist/modules/notifications/emails/NotificationEmail.js +58 -0
  200. package/dist/modules/notifications/emails/NotificationEmail.js.map +7 -0
  201. package/dist/modules/notifications/frontend/NotificationInboxPageClient.js +44 -0
  202. package/dist/modules/notifications/frontend/NotificationInboxPageClient.js.map +7 -0
  203. package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js +220 -0
  204. package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js.map +7 -0
  205. package/dist/modules/notifications/index.js +14 -0
  206. package/dist/modules/notifications/index.js.map +7 -0
  207. package/dist/modules/notifications/lib/deliveryConfig.js +107 -0
  208. package/dist/modules/notifications/lib/deliveryConfig.js.map +7 -0
  209. package/dist/modules/notifications/lib/deliveryStrategies.js +14 -0
  210. package/dist/modules/notifications/lib/deliveryStrategies.js.map +7 -0
  211. package/dist/modules/notifications/lib/events.js +12 -0
  212. package/dist/modules/notifications/lib/events.js.map +7 -0
  213. package/dist/modules/notifications/lib/notificationBuilder.js +66 -0
  214. package/dist/modules/notifications/lib/notificationBuilder.js.map +7 -0
  215. package/dist/modules/notifications/lib/notificationFactory.js +54 -0
  216. package/dist/modules/notifications/lib/notificationFactory.js.map +7 -0
  217. package/dist/modules/notifications/lib/notificationMapper.js +34 -0
  218. package/dist/modules/notifications/lib/notificationMapper.js.map +7 -0
  219. package/dist/modules/notifications/lib/notificationRecipients.js +35 -0
  220. package/dist/modules/notifications/lib/notificationRecipients.js.map +7 -0
  221. package/dist/modules/notifications/lib/notificationService.js +279 -0
  222. package/dist/modules/notifications/lib/notificationService.js.map +7 -0
  223. package/dist/modules/notifications/lib/routeHelpers.js +101 -0
  224. package/dist/modules/notifications/lib/routeHelpers.js.map +7 -0
  225. package/dist/modules/notifications/lib/safeHref.js +24 -0
  226. package/dist/modules/notifications/lib/safeHref.js.map +7 -0
  227. package/dist/modules/notifications/migrations/Migration20260123000001.js +70 -0
  228. package/dist/modules/notifications/migrations/Migration20260123000001.js.map +7 -0
  229. package/dist/modules/notifications/migrations/Migration20260126150000.js +37 -0
  230. package/dist/modules/notifications/migrations/Migration20260126150000.js.map +7 -0
  231. package/dist/modules/notifications/migrations/Migration20260129082610.js +13 -0
  232. package/dist/modules/notifications/migrations/Migration20260129082610.js.map +7 -0
  233. package/dist/modules/notifications/subscribers/deliver-notification.js +165 -0
  234. package/dist/modules/notifications/subscribers/deliver-notification.js.map +7 -0
  235. package/dist/modules/notifications/workers/create-notification.worker.js +70 -0
  236. package/dist/modules/notifications/workers/create-notification.worker.js.map +7 -0
  237. package/dist/modules/planner/backend/planner/availability-rulesets/page.js +2 -2
  238. package/dist/modules/planner/backend/planner/availability-rulesets/page.js.map +2 -2
  239. package/dist/modules/query_index/cli.js +63 -7
  240. package/dist/modules/query_index/cli.js.map +2 -2
  241. package/dist/modules/query_index/components/QueryIndexesTable.js +7 -1
  242. package/dist/modules/query_index/components/QueryIndexesTable.js.map +2 -2
  243. package/dist/modules/resources/backend/resources/resource-types/page.js +2 -2
  244. package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
  245. package/dist/modules/resources/backend/resources/resources/page.js +2 -2
  246. package/dist/modules/resources/backend/resources/resources/page.js.map +2 -2
  247. package/dist/modules/sales/backend/sales/channels/offers/page.js +2 -0
  248. package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
  249. package/dist/modules/sales/backend/sales/channels/page.js +2 -0
  250. package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
  251. package/dist/modules/sales/commands/documents.js +53 -0
  252. package/dist/modules/sales/commands/documents.js.map +2 -2
  253. package/dist/modules/sales/commands/payments.js +26 -0
  254. package/dist/modules/sales/commands/payments.js.map +2 -2
  255. package/dist/modules/sales/components/AdjustmentKindSettings.js +2 -2
  256. package/dist/modules/sales/components/AdjustmentKindSettings.js.map +2 -2
  257. package/dist/modules/sales/components/PaymentMethodsSettings.js +2 -2
  258. package/dist/modules/sales/components/PaymentMethodsSettings.js.map +2 -2
  259. package/dist/modules/sales/components/ShippingMethodsSettings.js +2 -2
  260. package/dist/modules/sales/components/ShippingMethodsSettings.js.map +2 -2
  261. package/dist/modules/sales/components/TaxRatesSettings.js +2 -2
  262. package/dist/modules/sales/components/TaxRatesSettings.js.map +2 -2
  263. package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js +2 -0
  264. package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js.map +2 -2
  265. package/dist/modules/sales/components/documents/AdjustmentsSection.js +2 -0
  266. package/dist/modules/sales/components/documents/AdjustmentsSection.js.map +2 -2
  267. package/dist/modules/sales/components/documents/PaymentsSection.js +2 -1
  268. package/dist/modules/sales/components/documents/PaymentsSection.js.map +2 -2
  269. package/dist/modules/sales/components/documents/SalesDocumentsTable.js +2 -0
  270. package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
  271. package/dist/modules/sales/notifications.client.js +51 -0
  272. package/dist/modules/sales/notifications.client.js.map +7 -0
  273. package/dist/modules/sales/notifications.js +88 -0
  274. package/dist/modules/sales/notifications.js.map +7 -0
  275. package/dist/modules/sales/subscribers/quote-expiring-notification.js +38 -0
  276. package/dist/modules/sales/subscribers/quote-expiring-notification.js.map +7 -0
  277. package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js +137 -0
  278. package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js.map +7 -0
  279. package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js +137 -0
  280. package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js.map +7 -0
  281. package/dist/modules/sales/widgets/notifications/index.js +7 -0
  282. package/dist/modules/sales/widgets/notifications/index.js.map +7 -0
  283. package/dist/modules/sales/widgets/notifications/useSalesDocumentTotals.js +60 -0
  284. package/dist/modules/sales/widgets/notifications/useSalesDocumentTotals.js.map +7 -0
  285. package/dist/modules/staff/backend/staff/team-members/page.js +1 -1
  286. package/dist/modules/staff/backend/staff/team-members/page.js.map +2 -2
  287. package/dist/modules/staff/backend/staff/team-roles/page.js +2 -2
  288. package/dist/modules/staff/backend/staff/team-roles/page.js.map +2 -2
  289. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +2 -2
  290. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
  291. package/dist/modules/staff/backend/staff/teams/page.js +2 -2
  292. package/dist/modules/staff/backend/staff/teams/page.js.map +2 -2
  293. package/dist/modules/staff/commands/leave-requests.js +79 -0
  294. package/dist/modules/staff/commands/leave-requests.js.map +2 -2
  295. package/dist/modules/staff/notifications.js +75 -0
  296. package/dist/modules/staff/notifications.js.map +7 -0
  297. package/dist/modules/workflows/backend/definitions/page.js +5 -0
  298. package/dist/modules/workflows/backend/definitions/page.js.map +2 -2
  299. package/dist/modules/workflows/backend/instances/page.js +3 -0
  300. package/dist/modules/workflows/backend/instances/page.js.map +2 -2
  301. package/dist/modules/workflows/backend/tasks/page.js +3 -0
  302. package/dist/modules/workflows/backend/tasks/page.js.map +2 -2
  303. package/dist/modules/workflows/cli.js +12 -12
  304. package/dist/modules/workflows/cli.js.map +2 -2
  305. package/dist/modules/workflows/lib/transition-handler.js +14 -6
  306. package/dist/modules/workflows/lib/transition-handler.js.map +2 -2
  307. package/dist/modules/workflows/notifications.js +28 -0
  308. package/dist/modules/workflows/notifications.js.map +7 -0
  309. package/dist/modules/workflows/subscribers/task-assigned-notification.js +38 -0
  310. package/dist/modules/workflows/subscribers/task-assigned-notification.js.map +7 -0
  311. package/generated/entities/notification/index.ts +27 -0
  312. package/generated/entities.ids.generated.ts +5 -1
  313. package/generated/entity-fields-registry.ts +2 -0
  314. package/package.json +2 -2
  315. package/src/modules/api_docs/frontend/docs/api/page.tsx +3 -2
  316. package/src/modules/api_keys/backend/api-keys/page.tsx +1 -1
  317. package/src/modules/attachments/components/AttachmentLibrary.tsx +4 -0
  318. package/src/modules/attachments/components/AttachmentPartitionSettings.tsx +2 -0
  319. package/src/modules/auth/README.md +1 -1
  320. package/src/modules/auth/__tests__/cli-setup-acl.test.ts +1 -1
  321. package/src/modules/auth/api/__tests__/login.test.ts +2 -0
  322. package/src/modules/auth/api/admin/nav.ts +10 -6
  323. package/src/modules/auth/api/login.ts +26 -7
  324. package/src/modules/auth/api/profile/route.ts +163 -0
  325. package/src/modules/auth/api/reset/confirm.ts +25 -2
  326. package/src/modules/auth/api/reset.ts +23 -0
  327. package/src/modules/auth/api/sidebar/preferences/route.ts +21 -12
  328. package/src/modules/auth/api/users/route.ts +5 -2
  329. package/src/modules/auth/backend/auth/profile/page.meta.ts +9 -0
  330. package/src/modules/auth/backend/auth/profile/page.tsx +174 -0
  331. package/src/modules/auth/backend/roles/[id]/edit/page.tsx +4 -1
  332. package/src/modules/auth/backend/roles/page.tsx +3 -3
  333. package/src/modules/auth/backend/users/[id]/edit/page.tsx +22 -3
  334. package/src/modules/auth/backend/users/create/page.tsx +19 -2
  335. package/src/modules/auth/backend/users/page.tsx +3 -3
  336. package/src/modules/auth/cli.ts +38 -11
  337. package/src/modules/auth/commands/users.ts +73 -2
  338. package/src/modules/auth/data/validators.ts +6 -2
  339. package/src/modules/auth/frontend/login.tsx +134 -5
  340. package/src/modules/auth/frontend/reset/[token]/page.tsx +24 -11
  341. package/src/modules/auth/i18n/de.json +48 -1
  342. package/src/modules/auth/i18n/en.json +48 -1
  343. package/src/modules/auth/i18n/es.json +48 -1
  344. package/src/modules/auth/i18n/pl.json +48 -1
  345. package/src/modules/auth/lib/setup-app.ts +58 -9
  346. package/src/modules/auth/notifications.ts +109 -0
  347. package/src/modules/auth/services/authService.ts +27 -4
  348. package/src/modules/business_rules/api/execute/route.ts +8 -1
  349. package/src/modules/business_rules/backend/rules/page.tsx +4 -0
  350. package/src/modules/business_rules/backend/sets/page.tsx +3 -0
  351. package/src/modules/business_rules/cli.ts +2 -1
  352. package/src/modules/business_rules/i18n/en.json +3 -1
  353. package/src/modules/business_rules/lib/__tests__/rule-engine.test.ts +51 -0
  354. package/src/modules/business_rules/lib/rule-engine.ts +57 -3
  355. package/src/modules/business_rules/notifications.ts +25 -0
  356. package/src/modules/business_rules/subscribers/rule-execution-failed-notification.ts +50 -0
  357. package/src/modules/catalog/components/PriceKindSettings.tsx +2 -0
  358. package/src/modules/catalog/components/categories/CategoriesDataTable.tsx +2 -2
  359. package/src/modules/catalog/components/products/ProductsDataTable.tsx +2 -0
  360. package/src/modules/catalog/i18n/en.json +3 -1
  361. package/src/modules/catalog/notifications.ts +25 -0
  362. package/src/modules/catalog/subscribers/low-stock-notification.ts +52 -0
  363. package/src/modules/configs/cli.ts +6 -0
  364. package/src/modules/configs/components/CachePanel.tsx +4 -4
  365. package/src/modules/configs/i18n/en.json +12 -2
  366. package/src/modules/configs/i18n/pl.json +12 -2
  367. package/src/modules/configs/lib/system-status.ts +48 -1
  368. package/src/modules/configs/lib/system-status.types.ts +1 -0
  369. package/src/modules/configs/lib/upgrade-actions.ts +18 -0
  370. package/src/modules/currencies/backend/currencies/page.tsx +3 -0
  371. package/src/modules/currencies/backend/exchange-rates/page.tsx +2 -0
  372. package/src/modules/customers/backend/customers/companies/page.tsx +3 -0
  373. package/src/modules/customers/backend/customers/deals/page.tsx +3 -0
  374. package/src/modules/customers/backend/customers/people/page.tsx +3 -0
  375. package/src/modules/customers/commands/deals.ts +39 -0
  376. package/src/modules/customers/components/CustomerTodosTable.tsx +1 -0
  377. package/src/modules/customers/i18n/en.json +5 -1
  378. package/src/modules/customers/notifications.ts +44 -0
  379. package/src/modules/customers/widgets/dashboard/customer-todos/widget.ts +2 -2
  380. package/src/modules/customers/widgets/dashboard/new-customers/widget.ts +2 -2
  381. package/src/modules/customers/widgets/dashboard/new-deals/widget.ts +2 -2
  382. package/src/modules/customers/widgets/dashboard/next-interactions/widget.ts +2 -2
  383. package/src/modules/dashboards/cli.ts +55 -5
  384. package/src/modules/dashboards/components/WidgetVisibilityEditor.tsx +22 -11
  385. package/src/modules/dashboards/lib/role-widgets.ts +80 -0
  386. package/src/modules/dashboards/services/widgetDataService.ts +164 -4
  387. package/src/modules/dashboards/widgets/dashboard/aov-kpi/widget.ts +2 -2
  388. package/src/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.ts +2 -2
  389. package/src/modules/dashboards/widgets/dashboard/orders-by-status/widget.ts +2 -2
  390. package/src/modules/dashboards/widgets/dashboard/orders-kpi/widget.ts +2 -2
  391. package/src/modules/dashboards/widgets/dashboard/pipeline-summary/widget.ts +2 -2
  392. package/src/modules/dashboards/widgets/dashboard/revenue-kpi/widget.ts +2 -2
  393. package/src/modules/dashboards/widgets/dashboard/revenue-trend/widget.ts +2 -2
  394. package/src/modules/dashboards/widgets/dashboard/sales-by-region/widget.ts +2 -2
  395. package/src/modules/dashboards/widgets/dashboard/top-customers/widget.ts +2 -2
  396. package/src/modules/dashboards/widgets/dashboard/top-products/widget.ts +2 -2
  397. package/src/modules/dictionaries/components/DictionaryTable.tsx +2 -0
  398. package/src/modules/directory/api/get/tenants/lookup.ts +75 -0
  399. package/src/modules/directory/backend/directory/organizations/page.tsx +2 -2
  400. package/src/modules/directory/backend/directory/tenants/page.tsx +2 -2
  401. package/src/modules/entities/backend/entities/user/[entityId]/records/page.tsx +2 -2
  402. package/src/modules/entities/components/SystemEntitiesTable.tsx +1 -1
  403. package/src/modules/entities/components/UserEntitiesTable.tsx +2 -2
  404. package/src/modules/feature_toggles/components/FeatureTogglesTable.tsx +3 -4
  405. package/src/modules/feature_toggles/components/OverridesTable.tsx +1 -1
  406. package/src/modules/notifications/__tests__/deliver-notification.test.ts +195 -0
  407. package/src/modules/notifications/__tests__/deliveryStrategies.test.ts +19 -0
  408. package/src/modules/notifications/__tests__/notificationService.test.ts +208 -0
  409. package/src/modules/notifications/acl.ts +7 -0
  410. package/src/modules/notifications/api/[id]/action/route.ts +75 -0
  411. package/src/modules/notifications/api/[id]/dismiss/route.ts +12 -0
  412. package/src/modules/notifications/api/[id]/read/route.ts +12 -0
  413. package/src/modules/notifications/api/[id]/restore/route.ts +53 -0
  414. package/src/modules/notifications/api/batch/route.ts +14 -0
  415. package/src/modules/notifications/api/feature/route.ts +14 -0
  416. package/src/modules/notifications/api/mark-all-read/route.ts +34 -0
  417. package/src/modules/notifications/api/openapi.ts +76 -0
  418. package/src/modules/notifications/api/role/route.ts +14 -0
  419. package/src/modules/notifications/api/route.ts +92 -0
  420. package/src/modules/notifications/api/settings/route.ts +157 -0
  421. package/src/modules/notifications/api/unread-count/route.ts +38 -0
  422. package/src/modules/notifications/backend/config/notifications/page.meta.ts +22 -0
  423. package/src/modules/notifications/backend/config/notifications/page.tsx +12 -0
  424. package/src/modules/notifications/cli.ts +18 -0
  425. package/src/modules/notifications/data/entities.ts +99 -0
  426. package/src/modules/notifications/data/validators.ts +115 -0
  427. package/src/modules/notifications/di.ts +11 -0
  428. package/src/modules/notifications/emails/NotificationEmail.tsx +98 -0
  429. package/src/modules/notifications/frontend/NotificationInboxPageClient.tsx +42 -0
  430. package/src/modules/notifications/frontend/NotificationSettingsPageClient.tsx +233 -0
  431. package/src/modules/notifications/i18n/de.json +50 -0
  432. package/src/modules/notifications/i18n/en.json +50 -0
  433. package/src/modules/notifications/i18n/es.json +50 -0
  434. package/src/modules/notifications/i18n/pl.json +50 -0
  435. package/src/modules/notifications/index.ts +12 -0
  436. package/src/modules/notifications/lib/deliveryConfig.ts +153 -0
  437. package/src/modules/notifications/lib/deliveryStrategies.ts +50 -0
  438. package/src/modules/notifications/lib/events.ts +48 -0
  439. package/src/modules/notifications/lib/notificationBuilder.ts +121 -0
  440. package/src/modules/notifications/lib/notificationFactory.ts +76 -0
  441. package/src/modules/notifications/lib/notificationMapper.ts +33 -0
  442. package/src/modules/notifications/lib/notificationRecipients.ts +83 -0
  443. package/src/modules/notifications/lib/notificationService.ts +414 -0
  444. package/src/modules/notifications/lib/routeHelpers.ts +151 -0
  445. package/src/modules/notifications/lib/safeHref.ts +29 -0
  446. package/src/modules/notifications/migrations/.snapshot-open-mercato.json +336 -0
  447. package/src/modules/notifications/migrations/Migration20260123000001.ts +73 -0
  448. package/src/modules/notifications/migrations/Migration20260126150000.ts +39 -0
  449. package/src/modules/notifications/migrations/Migration20260129082610.ts +13 -0
  450. package/src/modules/notifications/subscribers/deliver-notification.ts +204 -0
  451. package/src/modules/notifications/workers/create-notification.worker.ts +122 -0
  452. package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +2 -2
  453. package/src/modules/query_index/cli.ts +82 -13
  454. package/src/modules/query_index/components/QueryIndexesTable.tsx +8 -2
  455. package/src/modules/resources/backend/resources/resource-types/page.tsx +2 -2
  456. package/src/modules/resources/backend/resources/resources/page.tsx +2 -2
  457. package/src/modules/sales/backend/sales/channels/offers/page.tsx +2 -0
  458. package/src/modules/sales/backend/sales/channels/page.tsx +2 -0
  459. package/src/modules/sales/commands/documents.ts +65 -0
  460. package/src/modules/sales/commands/payments.ts +33 -0
  461. package/src/modules/sales/components/AdjustmentKindSettings.tsx +2 -2
  462. package/src/modules/sales/components/PaymentMethodsSettings.tsx +2 -2
  463. package/src/modules/sales/components/ShippingMethodsSettings.tsx +2 -2
  464. package/src/modules/sales/components/TaxRatesSettings.tsx +2 -2
  465. package/src/modules/sales/components/channels/SalesChannelOffersPanel.tsx +2 -0
  466. package/src/modules/sales/components/documents/AdjustmentsSection.tsx +2 -0
  467. package/src/modules/sales/components/documents/PaymentsSection.tsx +2 -1
  468. package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +2 -0
  469. package/src/modules/sales/i18n/de.json +20 -0
  470. package/src/modules/sales/i18n/en.json +25 -1
  471. package/src/modules/sales/i18n/es.json +20 -0
  472. package/src/modules/sales/i18n/pl.json +20 -0
  473. package/src/modules/sales/notifications.client.ts +65 -0
  474. package/src/modules/sales/notifications.ts +82 -0
  475. package/src/modules/sales/subscribers/quote-expiring-notification.ts +53 -0
  476. package/src/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.tsx +156 -0
  477. package/src/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.tsx +156 -0
  478. package/src/modules/sales/widgets/notifications/index.ts +2 -0
  479. package/src/modules/sales/widgets/notifications/useSalesDocumentTotals.ts +81 -0
  480. package/src/modules/staff/backend/staff/team-members/page.tsx +1 -1
  481. package/src/modules/staff/backend/staff/team-roles/page.tsx +2 -2
  482. package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +2 -2
  483. package/src/modules/staff/backend/staff/teams/page.tsx +2 -2
  484. package/src/modules/staff/commands/leave-requests.ts +94 -0
  485. package/src/modules/staff/i18n/de.json +4 -0
  486. package/src/modules/staff/i18n/en.json +9 -1
  487. package/src/modules/staff/i18n/es.json +4 -0
  488. package/src/modules/staff/i18n/pl.json +4 -0
  489. package/src/modules/staff/notifications.ts +71 -0
  490. package/src/modules/workflows/backend/definitions/page.tsx +5 -0
  491. package/src/modules/workflows/backend/instances/page.tsx +4 -1
  492. package/src/modules/workflows/backend/tasks/page.tsx +4 -1
  493. package/src/modules/workflows/cli.ts +12 -12
  494. package/src/modules/workflows/i18n/en.json +3 -1
  495. package/src/modules/workflows/lib/transition-handler.ts +18 -6
  496. package/src/modules/workflows/notifications.ts +25 -0
  497. package/src/modules/workflows/subscribers/task-assigned-notification.ts +53 -0
@@ -0,0 +1,50 @@
1
+ {
2
+ "notifications.nav.title": "Powiadomienia",
3
+ "notifications.title": "Powiadomienia",
4
+ "notifications.empty": "Brak powiadomień",
5
+ "notifications.markAllRead": "Oznacz wszystkie jako przeczytane",
6
+ "notifications.actionTaken": "Wykonana akcja: {action}",
7
+ "notifications.filters.all": "Wszystkie",
8
+ "notifications.filters.unread": "Nieprzeczytane",
9
+ "notifications.filters.actionRequired": "Wymagana akcja",
10
+ "notifications.actions.dismiss": "Odrzuć",
11
+ "notifications.actions.undo": "Cofnij",
12
+ "notifications.actions.markRead": "Oznacz jako przeczytane",
13
+ "notifications.toast.new": "Nowe powiadomienie",
14
+ "notifications.toast.dismissed": "Powiadomienie odrzucone",
15
+ "notifications.toast.actionSuccess": "Akcja wykonana pomyślnie",
16
+ "notifications.toast.actionError": "Nie udało się wykonać akcji",
17
+ "notifications.error.load": "Nie udało się załadować powiadomień",
18
+ "notifications.error.action": "Nie udało się wykonać akcji",
19
+ "notifications.badge.unread": "{count} nieprzeczytanych powiadomień",
20
+ "notifications.delivery.email.preview": "Nowe powiadomienie",
21
+ "notifications.delivery.email.heading": "Masz nowe powiadomienie",
22
+ "notifications.delivery.email.bodyIntro": "Sprawdź szczegóły powiadomienia i wykonaj wymagane działania.",
23
+ "notifications.delivery.email.actionNotice": "Akcje są dostępne w Open Mercato i w tym e-mailu są tylko do odczytu.",
24
+ "notifications.delivery.email.openCta": "Otwórz centrum powiadomień",
25
+ "notifications.delivery.email.footer": "Powiadomienia Open Mercato",
26
+ "notifications.delivery.settings.invalid": "Nieprawidłowe ustawienia dostarczania",
27
+ "notifications.settings.pageTitle": "Dostarczanie powiadomień",
28
+ "notifications.settings.pageDescription": "Skonfiguruj strategie dostarczania powiadomień w aplikacji.",
29
+ "notifications.settings.loadError": "Nie udało się załadować ustawień powiadomień",
30
+ "notifications.settings.saveError": "Nie udało się zapisać ustawień powiadomień",
31
+ "notifications.settings.saveSuccess": "Ustawienia powiadomień zapisane",
32
+ "notifications.settings.loading": "Ładowanie ustawień powiadomień...",
33
+ "notifications.settings.saving": "Zapisywanie...",
34
+ "notifications.settings.save": "Zapisz ustawienia",
35
+ "notifications.settings.core.title": "Podstawowe dostarczanie",
36
+ "notifications.settings.core.description": "Kontroluj centrum powiadomień i link panelu dla kanałów zewnętrznych.",
37
+ "notifications.settings.core.appUrl": "URL aplikacji",
38
+ "notifications.settings.core.appUrlHint": "Służy do budowania bezwzględnych linków w powiadomieniach e-mail.",
39
+ "notifications.settings.core.panelPath": "Ścieżka panelu powiadomień",
40
+ "notifications.settings.core.panelPathHint": "Względna ścieżka do panelu powiadomień tylko do odczytu.",
41
+ "notifications.settings.core.databaseLabel": "Powiadomienia w aplikacji",
42
+ "notifications.settings.core.databaseHint": "Zapisuje powiadomienia w bazie danych dla panelu i dzwonka.",
43
+ "notifications.settings.email.title": "Strategia e-mail",
44
+ "notifications.settings.email.description": "Wysyłaj kopie powiadomień przez Resend z szablonami React.",
45
+ "notifications.settings.email.enabledLabel": "Włącz dostarczanie e-mail",
46
+ "notifications.settings.email.enabledHint": "Akcje w e-mailu są tylko do odczytu i prowadzą do centrum powiadomień.",
47
+ "notifications.settings.email.from": "Adres nadawcy",
48
+ "notifications.settings.email.replyTo": "Odpowiedz do",
49
+ "notifications.settings.email.subjectPrefix": "Prefiks tematu"
50
+ }
@@ -0,0 +1,12 @@
1
+ import type { ModuleInfo } from '@open-mercato/shared/modules/registry'
2
+
3
+ export const metadata: ModuleInfo = {
4
+ name: 'notifications',
5
+ title: 'Notifications',
6
+ version: '0.1.0',
7
+ description: 'In-app notifications with module-extensible types and actions.',
8
+ author: 'Open Mercato Team',
9
+ license: 'Proprietary',
10
+ }
11
+
12
+ export { features } from './acl'
@@ -0,0 +1,153 @@
1
+ import type { ModuleConfigService } from '@open-mercato/core/modules/configs/lib/module-config-service'
2
+ import { parseBooleanWithDefault } from '@open-mercato/shared/lib/boolean'
3
+ import { notificationDeliveryConfigSchema, type NotificationDeliveryConfigInput } from '../data/validators'
4
+
5
+ export const NOTIFICATIONS_DELIVERY_CONFIG_KEY = 'delivery_strategies'
6
+
7
+ export type NotificationDeliveryStrategyState = {
8
+ enabled: boolean
9
+ }
10
+
11
+ export type NotificationCustomDeliveryConfig = {
12
+ enabled?: boolean
13
+ config?: unknown
14
+ }
15
+
16
+ export type NotificationEmailDeliveryConfig = NotificationDeliveryStrategyState & {
17
+ from?: string
18
+ replyTo?: string
19
+ subjectPrefix?: string
20
+ }
21
+
22
+ export type NotificationDeliveryConfig = {
23
+ appUrl?: string
24
+ panelPath: string
25
+ strategies: {
26
+ database: NotificationDeliveryStrategyState
27
+ email: NotificationEmailDeliveryConfig
28
+ custom?: Record<string, NotificationCustomDeliveryConfig>
29
+ }
30
+ }
31
+
32
+ const envString = (value: string | undefined | null) => {
33
+ if (!value) return undefined
34
+ const trimmed = value.trim()
35
+ return trimmed.length ? trimmed : undefined
36
+ }
37
+
38
+ const resolveEnvDefaults = () => {
39
+ const appUrl = envString(
40
+ process.env.NOTIFICATIONS_APP_URL ||
41
+ process.env.APPLICATION_URL ||
42
+ process.env.NEXT_PUBLIC_APP_URL ||
43
+ process.env.APP_URL
44
+ )
45
+ const panelPath = envString(process.env.NOTIFICATIONS_PANEL_PATH)
46
+ const emailEnabled = parseBooleanWithDefault(process.env.NOTIFICATIONS_EMAIL_ENABLED, true)
47
+ const emailFrom = envString(process.env.NOTIFICATIONS_EMAIL_FROM || process.env.EMAIL_FROM)
48
+ const emailReplyTo = envString(process.env.NOTIFICATIONS_EMAIL_REPLY_TO || process.env.ADMIN_EMAIL)
49
+ const emailSubjectPrefix = envString(process.env.NOTIFICATIONS_EMAIL_SUBJECT_PREFIX)
50
+
51
+ return {
52
+ appUrl,
53
+ panelPath,
54
+ emailEnabled,
55
+ emailFrom,
56
+ emailReplyTo,
57
+ emailSubjectPrefix,
58
+ }
59
+ }
60
+
61
+ export const DEFAULT_NOTIFICATION_DELIVERY_CONFIG: NotificationDeliveryConfig = (() => {
62
+ const env = resolveEnvDefaults()
63
+ return {
64
+ appUrl: env.appUrl,
65
+ panelPath: env.panelPath ?? '/backend/notifications',
66
+ strategies: {
67
+ database: { enabled: true },
68
+ email: {
69
+ enabled: env.emailEnabled,
70
+ from: env.emailFrom,
71
+ replyTo: env.emailReplyTo,
72
+ subjectPrefix: env.emailSubjectPrefix,
73
+ },
74
+ custom: {},
75
+ },
76
+ }
77
+ })()
78
+
79
+ const normalizeDeliveryConfig = (input?: unknown | null): NotificationDeliveryConfig => {
80
+ const parsed = notificationDeliveryConfigSchema.safeParse(input ?? {})
81
+ if (!parsed.success) {
82
+ return { ...DEFAULT_NOTIFICATION_DELIVERY_CONFIG }
83
+ }
84
+
85
+ const value = parsed.data ?? {}
86
+ const strategies = value.strategies ?? {}
87
+
88
+ return {
89
+ appUrl: value.appUrl,
90
+ panelPath: value.panelPath ?? DEFAULT_NOTIFICATION_DELIVERY_CONFIG.panelPath,
91
+ strategies: {
92
+ database: {
93
+ enabled: DEFAULT_NOTIFICATION_DELIVERY_CONFIG.strategies.database.enabled,
94
+ },
95
+ email: {
96
+ enabled: strategies.email?.enabled ?? DEFAULT_NOTIFICATION_DELIVERY_CONFIG.strategies.email.enabled,
97
+ from: strategies.email?.from,
98
+ replyTo: strategies.email?.replyTo,
99
+ subjectPrefix: strategies.email?.subjectPrefix,
100
+ },
101
+ custom: strategies.custom ?? {},
102
+ },
103
+ }
104
+ }
105
+
106
+ type Resolver = {
107
+ resolve: <T = unknown>(name: string) => T
108
+ }
109
+
110
+ export async function resolveNotificationDeliveryConfig(
111
+ resolver: Resolver,
112
+ options?: { defaultValue?: NotificationDeliveryConfig }
113
+ ): Promise<NotificationDeliveryConfig> {
114
+ const fallback = options?.defaultValue ?? DEFAULT_NOTIFICATION_DELIVERY_CONFIG
115
+ let service: ModuleConfigService
116
+ try {
117
+ service = resolver.resolve<ModuleConfigService>('moduleConfigService')
118
+ } catch {
119
+ return { ...fallback }
120
+ }
121
+ try {
122
+ const value = await service.getValue('notifications', NOTIFICATIONS_DELIVERY_CONFIG_KEY, { defaultValue: fallback })
123
+ return normalizeDeliveryConfig(value)
124
+ } catch {
125
+ return { ...fallback }
126
+ }
127
+ }
128
+
129
+ export async function saveNotificationDeliveryConfig(
130
+ resolver: Resolver,
131
+ config: NotificationDeliveryConfigInput
132
+ ): Promise<void> {
133
+ let service: ModuleConfigService
134
+ try {
135
+ service = resolver.resolve<ModuleConfigService>('moduleConfigService')
136
+ } catch {
137
+ throw new Error('Configuration service unavailable')
138
+ }
139
+
140
+ const normalized = normalizeDeliveryConfig(config)
141
+ await service.setValue('notifications', NOTIFICATIONS_DELIVERY_CONFIG_KEY, normalized)
142
+ }
143
+
144
+ export function resolveNotificationPanelUrl(config: NotificationDeliveryConfig): string | null {
145
+ const base = config.appUrl
146
+ || process.env.APPLICATION_URL
147
+ || process.env.NEXT_PUBLIC_APP_URL
148
+ || process.env.APP_URL
149
+ if (!base || !base.trim()) {
150
+ return config.panelPath
151
+ }
152
+ return `${base.replace(/\/$/, '')}${config.panelPath}`
153
+ }
@@ -0,0 +1,50 @@
1
+ import type { Notification } from '../data/entities'
2
+ import type { NotificationDeliveryConfig } from './deliveryConfig'
3
+
4
+ export type NotificationDeliveryStrategyConfig = {
5
+ enabled?: boolean
6
+ config?: unknown
7
+ }
8
+
9
+ export type NotificationDeliveryRecipient = {
10
+ email?: string | null
11
+ name?: string | null
12
+ }
13
+
14
+ export type NotificationDeliveryContext = {
15
+ notification: Notification
16
+ recipient: NotificationDeliveryRecipient
17
+ title: string
18
+ body: string | null
19
+ panelUrl: string | null
20
+ panelLink: string | null
21
+ actionLinks: Array<{ id: string; label: string; href: string }>
22
+ deliveryConfig: NotificationDeliveryConfig
23
+ config: NotificationDeliveryStrategyConfig
24
+ resolve: <T = unknown>(name: string) => T
25
+ t: (key: string, fallback?: string, variables?: Record<string, string>) => string
26
+ }
27
+
28
+ export type NotificationDeliveryStrategy = {
29
+ id: string
30
+ label?: string
31
+ defaultEnabled?: boolean
32
+ deliver: (ctx: NotificationDeliveryContext) => Promise<void> | void
33
+ }
34
+
35
+ type RegisteredStrategy = NotificationDeliveryStrategy & { priority: number }
36
+
37
+ const registry: RegisteredStrategy[] = []
38
+
39
+ export function registerNotificationDeliveryStrategy(
40
+ strategy: NotificationDeliveryStrategy,
41
+ options?: { priority?: number }
42
+ ): void {
43
+ const priority = options?.priority ?? 0
44
+ registry.push({ ...strategy, priority })
45
+ registry.sort((a, b) => b.priority - a.priority)
46
+ }
47
+
48
+ export function getNotificationDeliveryStrategies(): NotificationDeliveryStrategy[] {
49
+ return registry
50
+ }
@@ -0,0 +1,48 @@
1
+ export const NOTIFICATION_EVENTS = {
2
+ CREATED: 'notifications.created',
3
+ READ: 'notifications.read',
4
+ ACTIONED: 'notifications.actioned',
5
+ DISMISSED: 'notifications.dismissed',
6
+ RESTORED: 'notifications.restored',
7
+ EXPIRED: 'notifications.expired',
8
+ } as const
9
+
10
+ export type NotificationCreatedPayload = {
11
+ notificationId: string
12
+ recipientUserId: string
13
+ type: string
14
+ title: string
15
+ tenantId: string
16
+ organizationId?: string | null
17
+ }
18
+
19
+ export type NotificationReadPayload = {
20
+ notificationId: string
21
+ userId: string
22
+ tenantId: string
23
+ }
24
+
25
+ export type NotificationActionedPayload = {
26
+ notificationId: string
27
+ actionId: string
28
+ userId: string
29
+ tenantId: string
30
+ }
31
+
32
+ export type NotificationDismissedPayload = {
33
+ notificationId: string
34
+ userId: string
35
+ tenantId: string
36
+ }
37
+
38
+ export type NotificationRestoredPayload = {
39
+ notificationId: string
40
+ userId: string
41
+ tenantId: string
42
+ status: 'read' | 'unread'
43
+ }
44
+
45
+ export type NotificationExpiredPayload = {
46
+ notificationIds: string[]
47
+ tenantId: string
48
+ }
@@ -0,0 +1,121 @@
1
+ import type { NotificationTypeDefinition, NotificationTypeAction } from '@open-mercato/shared/modules/notifications/types'
2
+ import type { CreateNotificationInput, CreateBatchNotificationInput, CreateRoleNotificationInput, CreateFeatureNotificationInput } from '../data/validators'
3
+
4
+ /**
5
+ * Transform type definition actions to API input actions.
6
+ * Type definitions use labelKey (i18n-first), while API input uses label with optional labelKey.
7
+ */
8
+ function mapActions(actions: NotificationTypeAction[] | undefined) {
9
+ if (!actions || actions.length === 0) return undefined
10
+ return actions.map((action) => ({
11
+ id: action.id,
12
+ label: action.labelKey,
13
+ labelKey: action.labelKey,
14
+ variant: action.variant,
15
+ icon: action.icon,
16
+ commandId: action.commandId,
17
+ href: action.href,
18
+ confirmRequired: action.confirmRequired,
19
+ confirmMessage: action.confirmMessageKey,
20
+ }))
21
+ }
22
+
23
+ /**
24
+ * Common options for building notifications from type definitions
25
+ */
26
+ interface CommonBuildOptions {
27
+ titleVariables?: Record<string, string>
28
+ bodyVariables?: Record<string, string>
29
+ sourceEntityType?: string
30
+ sourceEntityId?: string
31
+ linkHref?: string
32
+ groupKey?: string
33
+ expiresAt?: string
34
+ }
35
+
36
+ /**
37
+ * Build base notification fields from a type definition.
38
+ * Shared logic used by all notification builder functions.
39
+ */
40
+ function buildBaseNotificationFields(
41
+ typeDef: NotificationTypeDefinition,
42
+ options: CommonBuildOptions
43
+ ) {
44
+ return {
45
+ type: typeDef.type,
46
+ titleKey: typeDef.titleKey,
47
+ bodyKey: typeDef.bodyKey,
48
+ titleVariables: options.titleVariables,
49
+ bodyVariables: options.bodyVariables,
50
+ title: typeDef.titleKey,
51
+ body: typeDef.bodyKey,
52
+ icon: typeDef.icon,
53
+ severity: typeDef.severity,
54
+ actions: mapActions(typeDef.actions),
55
+ primaryActionId: typeDef.primaryActionId,
56
+ sourceModule: typeDef.module,
57
+ sourceEntityType: options.sourceEntityType,
58
+ sourceEntityId: options.sourceEntityId,
59
+ linkHref: options.linkHref ?? typeDef.linkHref,
60
+ groupKey: options.groupKey,
61
+ expiresAt: options.expiresAt ?? (
62
+ typeDef.expiresAfterHours
63
+ ? new Date(Date.now() + typeDef.expiresAfterHours * 60 * 60 * 1000).toISOString()
64
+ : undefined
65
+ ),
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Build a notification input from a type definition with i18n support.
71
+ * This is the recommended way to create notifications - use type definitions from notifications.ts
72
+ * to ensure i18n-first approach.
73
+ */
74
+ export function buildNotificationFromType(
75
+ typeDef: NotificationTypeDefinition,
76
+ options: CommonBuildOptions & { recipientUserId: string }
77
+ ): CreateNotificationInput {
78
+ return {
79
+ recipientUserId: options.recipientUserId,
80
+ ...buildBaseNotificationFields(typeDef, options),
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Build a batch notification input from a type definition
86
+ */
87
+ export function buildBatchNotificationFromType(
88
+ typeDef: NotificationTypeDefinition,
89
+ options: CommonBuildOptions & { recipientUserIds: string[] }
90
+ ): CreateBatchNotificationInput {
91
+ return {
92
+ recipientUserIds: options.recipientUserIds,
93
+ ...buildBaseNotificationFields(typeDef, options),
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Build a role notification input from a type definition
99
+ */
100
+ export function buildRoleNotificationFromType(
101
+ typeDef: NotificationTypeDefinition,
102
+ options: CommonBuildOptions & { roleId: string }
103
+ ): CreateRoleNotificationInput {
104
+ return {
105
+ roleId: options.roleId,
106
+ ...buildBaseNotificationFields(typeDef, options),
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Build a feature-based notification input from a type definition
112
+ */
113
+ export function buildFeatureNotificationFromType(
114
+ typeDef: NotificationTypeDefinition,
115
+ options: CommonBuildOptions & { requiredFeature: string }
116
+ ): CreateFeatureNotificationInput {
117
+ return {
118
+ requiredFeature: options.requiredFeature,
119
+ ...buildBaseNotificationFields(typeDef, options),
120
+ }
121
+ }
@@ -0,0 +1,76 @@
1
+ import type { EntityManager } from '@mikro-orm/core'
2
+ import { Notification } from '../data/entities'
3
+ import type { CreateNotificationInput } from '../data/validators'
4
+ import { NOTIFICATION_EVENTS } from './events'
5
+ import { assertSafeNotificationHref, sanitizeNotificationActions } from './safeHref'
6
+
7
+ export type NotificationContentInput = Omit<CreateNotificationInput, 'recipientUserId'>
8
+
9
+ export type NotificationTenantContext = {
10
+ tenantId: string
11
+ organizationId?: string | null
12
+ }
13
+
14
+ export function buildNotificationEntity(
15
+ em: EntityManager,
16
+ input: NotificationContentInput,
17
+ recipientUserId: string,
18
+ ctx: NotificationTenantContext
19
+ ): Notification {
20
+ const actions = sanitizeNotificationActions(input.actions)
21
+ const linkHref = assertSafeNotificationHref(input.linkHref)
22
+
23
+ return em.create(Notification, {
24
+ recipientUserId,
25
+ type: input.type,
26
+ // i18n-first: store keys and variables for translation at display time
27
+ titleKey: input.titleKey,
28
+ bodyKey: input.bodyKey,
29
+ titleVariables: input.titleVariables,
30
+ bodyVariables: input.bodyVariables,
31
+ // Fallback text (required for backward compatibility)
32
+ title: input.title || input.titleKey || '',
33
+ body: input.body,
34
+ icon: input.icon,
35
+ severity: input.severity ?? 'info',
36
+ actionData: actions
37
+ ? {
38
+ actions,
39
+ primaryActionId: input.primaryActionId,
40
+ }
41
+ : null,
42
+ sourceModule: input.sourceModule,
43
+ sourceEntityType: input.sourceEntityType,
44
+ sourceEntityId: input.sourceEntityId,
45
+ linkHref,
46
+ groupKey: input.groupKey,
47
+ expiresAt: input.expiresAt ? new Date(input.expiresAt) : null,
48
+ tenantId: ctx.tenantId,
49
+ organizationId: ctx.organizationId,
50
+ })
51
+ }
52
+
53
+ export async function emitNotificationCreated(
54
+ eventBus: { emit: (event: string, payload: unknown) => Promise<void> },
55
+ notification: Notification,
56
+ ctx: NotificationTenantContext
57
+ ): Promise<void> {
58
+ await eventBus.emit(NOTIFICATION_EVENTS.CREATED, {
59
+ notificationId: notification.id,
60
+ recipientUserId: notification.recipientUserId,
61
+ type: notification.type,
62
+ title: notification.title,
63
+ tenantId: ctx.tenantId,
64
+ organizationId: ctx.organizationId,
65
+ })
66
+ }
67
+
68
+ export async function emitNotificationCreatedBatch(
69
+ eventBus: { emit: (event: string, payload: unknown) => Promise<void> },
70
+ notifications: Notification[],
71
+ ctx: NotificationTenantContext
72
+ ): Promise<void> {
73
+ for (const notification of notifications) {
74
+ await emitNotificationCreated(eventBus, notification, ctx)
75
+ }
76
+ }
@@ -0,0 +1,33 @@
1
+ import type { NotificationDto } from '@open-mercato/shared/modules/notifications/types'
2
+ import { Notification } from '../data/entities'
3
+
4
+ export function toNotificationDto(notification: Notification): NotificationDto {
5
+ return {
6
+ id: notification.id,
7
+ type: notification.type,
8
+ title: notification.title,
9
+ body: notification.body,
10
+ titleKey: notification.titleKey,
11
+ bodyKey: notification.bodyKey,
12
+ titleVariables: notification.titleVariables,
13
+ bodyVariables: notification.bodyVariables,
14
+ icon: notification.icon,
15
+ severity: notification.severity,
16
+ status: notification.status,
17
+ actions: notification.actionData?.actions?.map((action) => ({
18
+ id: action.id,
19
+ label: action.label,
20
+ labelKey: action.labelKey,
21
+ variant: action.variant,
22
+ icon: action.icon,
23
+ })) ?? [],
24
+ primaryActionId: notification.actionData?.primaryActionId,
25
+ sourceModule: notification.sourceModule,
26
+ sourceEntityType: notification.sourceEntityType,
27
+ sourceEntityId: notification.sourceEntityId,
28
+ linkHref: notification.linkHref,
29
+ createdAt: notification.createdAt.toISOString(),
30
+ readAt: notification.readAt?.toISOString() ?? null,
31
+ actionTaken: notification.actionTaken,
32
+ }
33
+ }
@@ -0,0 +1,83 @@
1
+ import type { Knex } from 'knex'
2
+ import { hasFeature } from '@open-mercato/shared/security/features'
3
+
4
+ interface AclRow {
5
+ user_id: string
6
+ features_json: unknown
7
+ is_super_admin: boolean
8
+ }
9
+
10
+ function normalizeFeatures(features: unknown): string[] | undefined {
11
+ if (!Array.isArray(features)) return undefined
12
+ const normalized = features.filter((feature): feature is string => typeof feature === 'string')
13
+ return normalized.length ? normalized : undefined
14
+ }
15
+
16
+ /**
17
+ * Extract user IDs from ACL rows that have the required feature or are super admins.
18
+ */
19
+ function collectUsersWithFeature(
20
+ userIdsSet: Set<string>,
21
+ rows: AclRow[],
22
+ requiredFeature: string
23
+ ): void {
24
+ for (const row of rows) {
25
+ if (row.is_super_admin) {
26
+ userIdsSet.add(row.user_id)
27
+ continue
28
+ }
29
+
30
+ const features = normalizeFeatures(row.features_json)
31
+ if (features && hasFeature(features, requiredFeature)) {
32
+ userIdsSet.add(row.user_id)
33
+ }
34
+ }
35
+ }
36
+
37
+ export async function getRecipientUserIdsForRole(
38
+ knex: Knex,
39
+ tenantId: string,
40
+ roleId: string
41
+ ): Promise<string[]> {
42
+ const userRoles = await knex('user_roles')
43
+ .join('users', 'user_roles.user_id', 'users.id')
44
+ .where('user_roles.role_id', roleId)
45
+ .whereNull('user_roles.deleted_at')
46
+ .whereNull('users.deleted_at')
47
+ .where('users.tenant_id', tenantId)
48
+ .select('users.id as user_id')
49
+
50
+ return userRoles.map((row: { user_id: string }) => row.user_id)
51
+ }
52
+
53
+ export async function getRecipientUserIdsForFeature(
54
+ knex: Knex,
55
+ tenantId: string,
56
+ requiredFeature: string
57
+ ): Promise<string[]> {
58
+ const userIdsSet = new Set<string>()
59
+
60
+ const userAcls = await knex('user_acls')
61
+ .join('users', 'user_acls.user_id', 'users.id')
62
+ .where('user_acls.tenant_id', tenantId)
63
+ .whereNull('user_acls.deleted_at')
64
+ .whereNull('users.deleted_at')
65
+ .where('users.tenant_id', tenantId)
66
+ .select('users.id as user_id', 'user_acls.features_json', 'user_acls.is_super_admin')
67
+
68
+ collectUsersWithFeature(userIdsSet, userAcls, requiredFeature)
69
+
70
+ const roleAcls = await knex('role_acls')
71
+ .join('user_roles', 'role_acls.role_id', 'user_roles.role_id')
72
+ .join('users', 'user_roles.user_id', 'users.id')
73
+ .where('role_acls.tenant_id', tenantId)
74
+ .whereNull('role_acls.deleted_at')
75
+ .whereNull('user_roles.deleted_at')
76
+ .whereNull('users.deleted_at')
77
+ .where('users.tenant_id', tenantId)
78
+ .select('users.id as user_id', 'role_acls.features_json', 'role_acls.is_super_admin')
79
+
80
+ collectUsersWithFeature(userIdsSet, roleAcls, requiredFeature)
81
+
82
+ return Array.from(userIdsSet)
83
+ }