@open-mercato/core 0.4.2-canary-36ab8921da → 0.4.2-canary-07dbc98202

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 (235) 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 +63 -59
  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/auth/api/admin/nav.js +4 -3
  10. package/dist/modules/auth/api/admin/nav.js.map +2 -2
  11. package/dist/modules/auth/api/profile/route.js +155 -0
  12. package/dist/modules/auth/api/profile/route.js.map +7 -0
  13. package/dist/modules/auth/api/reset/confirm.js +25 -2
  14. package/dist/modules/auth/api/reset/confirm.js.map +2 -2
  15. package/dist/modules/auth/api/reset.js +23 -0
  16. package/dist/modules/auth/api/reset.js.map +2 -2
  17. package/dist/modules/auth/api/sidebar/preferences/route.js +14 -9
  18. package/dist/modules/auth/api/sidebar/preferences/route.js.map +2 -2
  19. package/dist/modules/auth/backend/auth/profile/page.js +99 -0
  20. package/dist/modules/auth/backend/auth/profile/page.js.map +7 -0
  21. package/dist/modules/auth/backend/auth/profile/page.meta.js +12 -0
  22. package/dist/modules/auth/backend/auth/profile/page.meta.js.map +7 -0
  23. package/dist/modules/auth/commands/users.js +55 -0
  24. package/dist/modules/auth/commands/users.js.map +2 -2
  25. package/dist/modules/auth/lib/setup-app.js +1 -0
  26. package/dist/modules/auth/lib/setup-app.js.map +2 -2
  27. package/dist/modules/auth/notifications.js +112 -0
  28. package/dist/modules/auth/notifications.js.map +7 -0
  29. package/dist/modules/auth/services/authService.js +3 -3
  30. package/dist/modules/auth/services/authService.js.map +2 -2
  31. package/dist/modules/business_rules/notifications.js +28 -0
  32. package/dist/modules/business_rules/notifications.js.map +7 -0
  33. package/dist/modules/business_rules/subscribers/rule-execution-failed-notification.js +37 -0
  34. package/dist/modules/business_rules/subscribers/rule-execution-failed-notification.js.map +7 -0
  35. package/dist/modules/catalog/notifications.js +28 -0
  36. package/dist/modules/catalog/notifications.js.map +7 -0
  37. package/dist/modules/catalog/subscribers/low-stock-notification.js +38 -0
  38. package/dist/modules/catalog/subscribers/low-stock-notification.js.map +7 -0
  39. package/dist/modules/configs/cli.js +6 -0
  40. package/dist/modules/configs/cli.js.map +2 -2
  41. package/dist/modules/customers/commands/deals.js +31 -0
  42. package/dist/modules/customers/commands/deals.js.map +2 -2
  43. package/dist/modules/customers/notifications.js +48 -0
  44. package/dist/modules/customers/notifications.js.map +7 -0
  45. package/dist/modules/notifications/acl.js +11 -0
  46. package/dist/modules/notifications/acl.js.map +7 -0
  47. package/dist/modules/notifications/api/[id]/action/route.js +74 -0
  48. package/dist/modules/notifications/api/[id]/action/route.js.map +7 -0
  49. package/dist/modules/notifications/api/[id]/dismiss/route.js +15 -0
  50. package/dist/modules/notifications/api/[id]/dismiss/route.js.map +7 -0
  51. package/dist/modules/notifications/api/[id]/read/route.js +15 -0
  52. package/dist/modules/notifications/api/[id]/read/route.js.map +7 -0
  53. package/dist/modules/notifications/api/[id]/restore/route.js +53 -0
  54. package/dist/modules/notifications/api/[id]/restore/route.js.map +7 -0
  55. package/dist/modules/notifications/api/batch/route.js +17 -0
  56. package/dist/modules/notifications/api/batch/route.js.map +7 -0
  57. package/dist/modules/notifications/api/feature/route.js +17 -0
  58. package/dist/modules/notifications/api/feature/route.js.map +7 -0
  59. package/dist/modules/notifications/api/mark-all-read/route.js +35 -0
  60. package/dist/modules/notifications/api/mark-all-read/route.js.map +7 -0
  61. package/dist/modules/notifications/api/openapi.js +76 -0
  62. package/dist/modules/notifications/api/openapi.js.map +7 -0
  63. package/dist/modules/notifications/api/role/route.js +17 -0
  64. package/dist/modules/notifications/api/role/route.js.map +7 -0
  65. package/dist/modules/notifications/api/route.js +85 -0
  66. package/dist/modules/notifications/api/route.js.map +7 -0
  67. package/dist/modules/notifications/api/settings/route.js +155 -0
  68. package/dist/modules/notifications/api/settings/route.js.map +7 -0
  69. package/dist/modules/notifications/api/unread-count/route.js +38 -0
  70. package/dist/modules/notifications/api/unread-count/route.js.map +7 -0
  71. package/dist/modules/notifications/backend/config/notifications/page.js +10 -0
  72. package/dist/modules/notifications/backend/config/notifications/page.js.map +7 -0
  73. package/dist/modules/notifications/backend/config/notifications/page.meta.js +24 -0
  74. package/dist/modules/notifications/backend/config/notifications/page.meta.js.map +7 -0
  75. package/dist/modules/notifications/cli.js +16 -0
  76. package/dist/modules/notifications/cli.js.map +7 -0
  77. package/dist/modules/notifications/data/entities.js +112 -0
  78. package/dist/modules/notifications/data/entities.js.map +7 -0
  79. package/dist/modules/notifications/data/validators.js +94 -0
  80. package/dist/modules/notifications/data/validators.js.map +7 -0
  81. package/dist/modules/notifications/di.js +13 -0
  82. package/dist/modules/notifications/di.js.map +7 -0
  83. package/dist/modules/notifications/emails/NotificationEmail.js +58 -0
  84. package/dist/modules/notifications/emails/NotificationEmail.js.map +7 -0
  85. package/dist/modules/notifications/frontend/NotificationInboxPageClient.js +44 -0
  86. package/dist/modules/notifications/frontend/NotificationInboxPageClient.js.map +7 -0
  87. package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js +219 -0
  88. package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js.map +7 -0
  89. package/dist/modules/notifications/index.js +14 -0
  90. package/dist/modules/notifications/index.js.map +7 -0
  91. package/dist/modules/notifications/lib/deliveryConfig.js +105 -0
  92. package/dist/modules/notifications/lib/deliveryConfig.js.map +7 -0
  93. package/dist/modules/notifications/lib/events.js +12 -0
  94. package/dist/modules/notifications/lib/events.js.map +7 -0
  95. package/dist/modules/notifications/lib/notificationBuilder.js +66 -0
  96. package/dist/modules/notifications/lib/notificationBuilder.js.map +7 -0
  97. package/dist/modules/notifications/lib/notificationFactory.js +54 -0
  98. package/dist/modules/notifications/lib/notificationFactory.js.map +7 -0
  99. package/dist/modules/notifications/lib/notificationMapper.js +34 -0
  100. package/dist/modules/notifications/lib/notificationMapper.js.map +7 -0
  101. package/dist/modules/notifications/lib/notificationRecipients.js +35 -0
  102. package/dist/modules/notifications/lib/notificationRecipients.js.map +7 -0
  103. package/dist/modules/notifications/lib/notificationService.js +279 -0
  104. package/dist/modules/notifications/lib/notificationService.js.map +7 -0
  105. package/dist/modules/notifications/lib/routeHelpers.js +101 -0
  106. package/dist/modules/notifications/lib/routeHelpers.js.map +7 -0
  107. package/dist/modules/notifications/lib/safeHref.js +24 -0
  108. package/dist/modules/notifications/lib/safeHref.js.map +7 -0
  109. package/dist/modules/notifications/migrations/Migration20260123000001.js +70 -0
  110. package/dist/modules/notifications/migrations/Migration20260123000001.js.map +7 -0
  111. package/dist/modules/notifications/migrations/Migration20260126150000.js +37 -0
  112. package/dist/modules/notifications/migrations/Migration20260126150000.js.map +7 -0
  113. package/dist/modules/notifications/subscribers/deliver-notification.js +139 -0
  114. package/dist/modules/notifications/subscribers/deliver-notification.js.map +7 -0
  115. package/dist/modules/notifications/workers/create-notification.worker.js +70 -0
  116. package/dist/modules/notifications/workers/create-notification.worker.js.map +7 -0
  117. package/dist/modules/sales/commands/documents.js +53 -0
  118. package/dist/modules/sales/commands/documents.js.map +2 -2
  119. package/dist/modules/sales/commands/payments.js +26 -0
  120. package/dist/modules/sales/commands/payments.js.map +2 -2
  121. package/dist/modules/sales/notifications.client.js +51 -0
  122. package/dist/modules/sales/notifications.client.js.map +7 -0
  123. package/dist/modules/sales/notifications.js +88 -0
  124. package/dist/modules/sales/notifications.js.map +7 -0
  125. package/dist/modules/sales/subscribers/quote-expiring-notification.js +38 -0
  126. package/dist/modules/sales/subscribers/quote-expiring-notification.js.map +7 -0
  127. package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js +137 -0
  128. package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js.map +7 -0
  129. package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js +137 -0
  130. package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js.map +7 -0
  131. package/dist/modules/sales/widgets/notifications/index.js +7 -0
  132. package/dist/modules/sales/widgets/notifications/index.js.map +7 -0
  133. package/dist/modules/sales/widgets/notifications/useSalesDocumentTotals.js +60 -0
  134. package/dist/modules/sales/widgets/notifications/useSalesDocumentTotals.js.map +7 -0
  135. package/dist/modules/staff/commands/leave-requests.js +79 -0
  136. package/dist/modules/staff/commands/leave-requests.js.map +2 -2
  137. package/dist/modules/staff/notifications.js +75 -0
  138. package/dist/modules/staff/notifications.js.map +7 -0
  139. package/dist/modules/workflows/notifications.js +28 -0
  140. package/dist/modules/workflows/notifications.js.map +7 -0
  141. package/dist/modules/workflows/subscribers/task-assigned-notification.js +38 -0
  142. package/dist/modules/workflows/subscribers/task-assigned-notification.js.map +7 -0
  143. package/generated/entities/notification/index.ts +27 -0
  144. package/generated/entities.ids.generated.ts +63 -59
  145. package/generated/entity-fields-registry.ts +2 -0
  146. package/package.json +2 -2
  147. package/src/modules/api_docs/frontend/docs/api/page.tsx +3 -2
  148. package/src/modules/auth/api/admin/nav.ts +10 -6
  149. package/src/modules/auth/api/profile/route.ts +160 -0
  150. package/src/modules/auth/api/reset/confirm.ts +25 -2
  151. package/src/modules/auth/api/reset.ts +23 -0
  152. package/src/modules/auth/api/sidebar/preferences/route.ts +21 -12
  153. package/src/modules/auth/backend/auth/profile/page.meta.ts +8 -0
  154. package/src/modules/auth/backend/auth/profile/page.tsx +127 -0
  155. package/src/modules/auth/commands/users.ts +68 -0
  156. package/src/modules/auth/i18n/de.json +29 -1
  157. package/src/modules/auth/i18n/en.json +29 -1
  158. package/src/modules/auth/i18n/es.json +29 -1
  159. package/src/modules/auth/i18n/pl.json +29 -1
  160. package/src/modules/auth/lib/setup-app.ts +1 -0
  161. package/src/modules/auth/notifications.ts +109 -0
  162. package/src/modules/auth/services/authService.ts +4 -4
  163. package/src/modules/business_rules/i18n/en.json +3 -1
  164. package/src/modules/business_rules/notifications.ts +25 -0
  165. package/src/modules/business_rules/subscribers/rule-execution-failed-notification.ts +50 -0
  166. package/src/modules/catalog/i18n/en.json +3 -1
  167. package/src/modules/catalog/notifications.ts +25 -0
  168. package/src/modules/catalog/subscribers/low-stock-notification.ts +52 -0
  169. package/src/modules/configs/cli.ts +6 -0
  170. package/src/modules/customers/commands/deals.ts +39 -0
  171. package/src/modules/customers/i18n/en.json +5 -1
  172. package/src/modules/customers/notifications.ts +44 -0
  173. package/src/modules/notifications/acl.ts +7 -0
  174. package/src/modules/notifications/api/[id]/action/route.ts +75 -0
  175. package/src/modules/notifications/api/[id]/dismiss/route.ts +12 -0
  176. package/src/modules/notifications/api/[id]/read/route.ts +12 -0
  177. package/src/modules/notifications/api/[id]/restore/route.ts +53 -0
  178. package/src/modules/notifications/api/batch/route.ts +14 -0
  179. package/src/modules/notifications/api/feature/route.ts +14 -0
  180. package/src/modules/notifications/api/mark-all-read/route.ts +34 -0
  181. package/src/modules/notifications/api/openapi.ts +76 -0
  182. package/src/modules/notifications/api/role/route.ts +14 -0
  183. package/src/modules/notifications/api/route.ts +92 -0
  184. package/src/modules/notifications/api/settings/route.ts +157 -0
  185. package/src/modules/notifications/api/unread-count/route.ts +38 -0
  186. package/src/modules/notifications/backend/config/notifications/page.meta.ts +22 -0
  187. package/src/modules/notifications/backend/config/notifications/page.tsx +12 -0
  188. package/src/modules/notifications/cli.ts +18 -0
  189. package/src/modules/notifications/data/entities.ts +99 -0
  190. package/src/modules/notifications/data/validators.ts +110 -0
  191. package/src/modules/notifications/di.ts +11 -0
  192. package/src/modules/notifications/emails/NotificationEmail.tsx +98 -0
  193. package/src/modules/notifications/frontend/NotificationInboxPageClient.tsx +42 -0
  194. package/src/modules/notifications/frontend/NotificationSettingsPageClient.tsx +231 -0
  195. package/src/modules/notifications/i18n/de.json +50 -0
  196. package/src/modules/notifications/i18n/en.json +50 -0
  197. package/src/modules/notifications/i18n/es.json +50 -0
  198. package/src/modules/notifications/i18n/pl.json +50 -0
  199. package/src/modules/notifications/index.ts +12 -0
  200. package/src/modules/notifications/lib/deliveryConfig.ts +145 -0
  201. package/src/modules/notifications/lib/events.ts +48 -0
  202. package/src/modules/notifications/lib/notificationBuilder.ts +121 -0
  203. package/src/modules/notifications/lib/notificationFactory.ts +76 -0
  204. package/src/modules/notifications/lib/notificationMapper.ts +33 -0
  205. package/src/modules/notifications/lib/notificationRecipients.ts +83 -0
  206. package/src/modules/notifications/lib/notificationService.ts +414 -0
  207. package/src/modules/notifications/lib/routeHelpers.ts +151 -0
  208. package/src/modules/notifications/lib/safeHref.ts +29 -0
  209. package/src/modules/notifications/migrations/.snapshot-open-mercato.json +300 -0
  210. package/src/modules/notifications/migrations/Migration20260123000001.ts +73 -0
  211. package/src/modules/notifications/migrations/Migration20260126150000.ts +39 -0
  212. package/src/modules/notifications/subscribers/deliver-notification.ts +175 -0
  213. package/src/modules/notifications/workers/create-notification.worker.ts +122 -0
  214. package/src/modules/sales/commands/documents.ts +65 -0
  215. package/src/modules/sales/commands/payments.ts +33 -0
  216. package/src/modules/sales/i18n/de.json +20 -0
  217. package/src/modules/sales/i18n/en.json +25 -1
  218. package/src/modules/sales/i18n/es.json +20 -0
  219. package/src/modules/sales/i18n/pl.json +20 -0
  220. package/src/modules/sales/notifications.client.ts +65 -0
  221. package/src/modules/sales/notifications.ts +82 -0
  222. package/src/modules/sales/subscribers/quote-expiring-notification.ts +53 -0
  223. package/src/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.tsx +156 -0
  224. package/src/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.tsx +156 -0
  225. package/src/modules/sales/widgets/notifications/index.ts +2 -0
  226. package/src/modules/sales/widgets/notifications/useSalesDocumentTotals.ts +81 -0
  227. package/src/modules/staff/commands/leave-requests.ts +94 -0
  228. package/src/modules/staff/i18n/de.json +4 -0
  229. package/src/modules/staff/i18n/en.json +9 -1
  230. package/src/modules/staff/i18n/es.json +4 -0
  231. package/src/modules/staff/i18n/pl.json +4 -0
  232. package/src/modules/staff/notifications.ts +71 -0
  233. package/src/modules/workflows/i18n/en.json +3 -1
  234. package/src/modules/workflows/notifications.ts +25 -0
  235. package/src/modules/workflows/subscribers/task-assigned-notification.ts +53 -0
@@ -21,7 +21,8 @@ export const M = {
21
21
  "currencies": "currencies",
22
22
  "planner": "planner",
23
23
  "resources": "resources",
24
- "staff": "staff"
24
+ "staff": "staff",
25
+ "notifications": "notifications"
25
26
  } as const
26
27
  export const E = {
27
28
  "dashboards": {
@@ -30,34 +31,34 @@ export const E = {
30
31
  "dashboard_user_widgets": "dashboards:dashboard_user_widgets"
31
32
  },
32
33
  "auth": {
33
- "user": "auth:user",
34
+ "password_reset": "auth:password_reset",
34
35
  "role": "auth:role",
35
- "user_sidebar_preference": "auth:user_sidebar_preference",
36
+ "role_acl": "auth:role_acl",
36
37
  "role_sidebar_preference": "auth:role_sidebar_preference",
37
- "user_role": "auth:user_role",
38
38
  "session": "auth:session",
39
- "password_reset": "auth:password_reset",
40
- "role_acl": "auth:role_acl",
41
- "user_acl": "auth:user_acl"
39
+ "user": "auth:user",
40
+ "user_acl": "auth:user_acl",
41
+ "user_role": "auth:user_role",
42
+ "user_sidebar_preference": "auth:user_sidebar_preference"
42
43
  },
43
44
  "directory": {
44
- "tenant": "directory:tenant",
45
- "organization": "directory:organization"
45
+ "organization": "directory:organization",
46
+ "tenant": "directory:tenant"
46
47
  },
47
48
  "customers": {
48
- "customer_entity": "customers:customer_entity",
49
- "customer_person_profile": "customers:customer_person_profile",
49
+ "customer_activity": "customers:customer_activity",
50
+ "customer_address": "customers:customer_address",
51
+ "customer_comment": "customers:customer_comment",
50
52
  "customer_company_profile": "customers:customer_company_profile",
51
53
  "customer_deal": "customers:customer_deal",
52
- "customer_deal_person_link": "customers:customer_deal_person_link",
53
54
  "customer_deal_company_link": "customers:customer_deal_company_link",
54
- "customer_activity": "customers:customer_activity",
55
- "customer_comment": "customers:customer_comment",
56
- "customer_address": "customers:customer_address",
55
+ "customer_deal_person_link": "customers:customer_deal_person_link",
56
+ "customer_dictionary_entry": "customers:customer_dictionary_entry",
57
+ "customer_entity": "customers:customer_entity",
58
+ "customer_person_profile": "customers:customer_person_profile",
57
59
  "customer_settings": "customers:customer_settings",
58
60
  "customer_tag": "customers:customer_tag",
59
61
  "customer_tag_assignment": "customers:customer_tag_assignment",
60
- "customer_dictionary_entry": "customers:customer_dictionary_entry",
61
62
  "customer_todo_link": "customers:customer_todo_link"
62
63
  },
63
64
  "perspectives": {
@@ -65,10 +66,10 @@ export const E = {
65
66
  "role_perspective": "perspectives:role_perspective"
66
67
  },
67
68
  "entities": {
68
- "custom_field_def": "entities:custom_field_def",
69
- "custom_field_entity_config": "entities:custom_field_entity_config",
70
69
  "custom_entity": "entities:custom_entity",
71
70
  "custom_entity_storage": "entities:custom_entity_storage",
71
+ "custom_field_def": "entities:custom_field_def",
72
+ "custom_field_entity_config": "entities:custom_field_entity_config",
72
73
  "custom_field_value": "entities:custom_field_value",
73
74
  "encryption_map": "entities:encryption_map"
74
75
  },
@@ -77,60 +78,60 @@ export const E = {
77
78
  "upgrade_action_run": "configs:upgrade_action_run"
78
79
  },
79
80
  "query_index": {
80
- "entity_index_row": "query_index:entity_index_row",
81
- "entity_index_job": "query_index:entity_index_job",
82
81
  "entity_index_coverage": "query_index:entity_index_coverage",
82
+ "entity_index_job": "query_index:entity_index_job",
83
+ "entity_index_row": "query_index:entity_index_row",
83
84
  "indexer_error_log": "query_index:indexer_error_log",
84
85
  "indexer_status_log": "query_index:indexer_status_log",
85
86
  "search_token": "query_index:search_token"
86
87
  },
87
88
  "audit_logs": {
88
- "action_log": "audit_logs:action_log",
89
- "access_log": "audit_logs:access_log"
89
+ "access_log": "audit_logs:access_log",
90
+ "action_log": "audit_logs:action_log"
90
91
  },
91
92
  "attachments": {
92
- "attachment_partition": "attachments:attachment_partition",
93
- "attachment": "attachments:attachment"
93
+ "attachment": "attachments:attachment",
94
+ "attachment_partition": "attachments:attachment_partition"
94
95
  },
95
96
  "catalog": {
97
+ "catalog_offer": "catalog:catalog_offer",
96
98
  "catalog_option_schema_template": "catalog:catalog_option_schema_template",
99
+ "catalog_price_kind": "catalog:catalog_price_kind",
97
100
  "catalog_product": "catalog:catalog_product",
98
101
  "catalog_product_category": "catalog:catalog_product_category",
99
102
  "catalog_product_category_assignment": "catalog:catalog_product_category_assignment",
103
+ "catalog_product_price": "catalog:catalog_product_price",
100
104
  "catalog_product_tag": "catalog:catalog_product_tag",
101
105
  "catalog_product_tag_assignment": "catalog:catalog_product_tag_assignment",
102
- "catalog_offer": "catalog:catalog_offer",
103
106
  "catalog_product_variant": "catalog:catalog_product_variant",
104
- "catalog_product_variant_relation": "catalog:catalog_product_variant_relation",
105
- "catalog_price_kind": "catalog:catalog_price_kind",
106
- "catalog_product_price": "catalog:catalog_product_price"
107
+ "catalog_product_variant_relation": "catalog:catalog_product_variant_relation"
107
108
  },
108
109
  "sales": {
109
110
  "sales_channel": "sales:sales_channel",
110
- "sales_shipping_method": "sales:sales_shipping_method",
111
+ "sales_credit_memo": "sales:sales_credit_memo",
112
+ "sales_credit_memo_line": "sales:sales_credit_memo_line",
111
113
  "sales_delivery_window": "sales:sales_delivery_window",
112
- "sales_payment_method": "sales:sales_payment_method",
113
- "sales_tax_rate": "sales:sales_tax_rate",
114
+ "sales_document_address": "sales:sales_document_address",
115
+ "sales_document_sequence": "sales:sales_document_sequence",
116
+ "sales_document_tag": "sales:sales_document_tag",
117
+ "sales_document_tag_assignment": "sales:sales_document_tag_assignment",
118
+ "sales_invoice": "sales:sales_invoice",
119
+ "sales_invoice_line": "sales:sales_invoice_line",
120
+ "sales_note": "sales:sales_note",
114
121
  "sales_order": "sales:sales_order",
115
- "sales_order_line": "sales:sales_order_line",
116
122
  "sales_order_adjustment": "sales:sales_order_adjustment",
117
- "sales_settings": "sales:sales_settings",
118
- "sales_document_sequence": "sales:sales_document_sequence",
123
+ "sales_order_line": "sales:sales_order_line",
124
+ "sales_payment": "sales:sales_payment",
125
+ "sales_payment_allocation": "sales:sales_payment_allocation",
126
+ "sales_payment_method": "sales:sales_payment_method",
119
127
  "sales_quote": "sales:sales_quote",
120
- "sales_quote_line": "sales:sales_quote_line",
121
128
  "sales_quote_adjustment": "sales:sales_quote_adjustment",
129
+ "sales_quote_line": "sales:sales_quote_line",
130
+ "sales_settings": "sales:sales_settings",
122
131
  "sales_shipment": "sales:sales_shipment",
123
132
  "sales_shipment_item": "sales:sales_shipment_item",
124
- "sales_invoice": "sales:sales_invoice",
125
- "sales_invoice_line": "sales:sales_invoice_line",
126
- "sales_credit_memo": "sales:sales_credit_memo",
127
- "sales_credit_memo_line": "sales:sales_credit_memo_line",
128
- "sales_payment": "sales:sales_payment",
129
- "sales_payment_allocation": "sales:sales_payment_allocation",
130
- "sales_note": "sales:sales_note",
131
- "sales_document_address": "sales:sales_document_address",
132
- "sales_document_tag": "sales:sales_document_tag",
133
- "sales_document_tag_assignment": "sales:sales_document_tag_assignment"
133
+ "sales_shipping_method": "sales:sales_shipping_method",
134
+ "sales_tax_rate": "sales:sales_tax_rate"
134
135
  },
135
136
  "api_keys": {
136
137
  "api_key": "api_keys:api_key"
@@ -150,38 +151,41 @@ export const E = {
150
151
  "feature_toggle_override": "feature_toggles:feature_toggle_override"
151
152
  },
152
153
  "workflows": {
153
- "workflow_definition": "workflows:workflow_definition",
154
- "workflow_instance": "workflows:workflow_instance",
155
154
  "step_instance": "workflows:step_instance",
156
155
  "user_task": "workflows:user_task",
157
- "workflow_event": "workflows:workflow_event"
156
+ "workflow_definition": "workflows:workflow_definition",
157
+ "workflow_event": "workflows:workflow_event",
158
+ "workflow_instance": "workflows:workflow_instance"
158
159
  },
159
160
  "currencies": {
160
161
  "currency": "currencies:currency",
161
- "exchange_rate": "currencies:exchange_rate",
162
- "currency_fetch_config": "currencies:currency_fetch_config"
162
+ "currency_fetch_config": "currencies:currency_fetch_config",
163
+ "exchange_rate": "currencies:exchange_rate"
163
164
  },
164
165
  "planner": {
165
- "planner_availability_rule_set": "planner:planner_availability_rule_set",
166
- "planner_availability_rule": "planner:planner_availability_rule"
166
+ "planner_availability_rule": "planner:planner_availability_rule",
167
+ "planner_availability_rule_set": "planner:planner_availability_rule_set"
167
168
  },
168
169
  "resources": {
169
- "resources_resource_type": "resources:resources_resource_type",
170
170
  "resources_resource": "resources:resources_resource",
171
- "resources_resource_comment": "resources:resources_resource_comment",
172
171
  "resources_resource_activity": "resources:resources_resource_activity",
172
+ "resources_resource_comment": "resources:resources_resource_comment",
173
173
  "resources_resource_tag": "resources:resources_resource_tag",
174
- "resources_resource_tag_assignment": "resources:resources_resource_tag_assignment"
174
+ "resources_resource_tag_assignment": "resources:resources_resource_tag_assignment",
175
+ "resources_resource_type": "resources:resources_resource_type"
175
176
  },
176
177
  "staff": {
178
+ "staff_leave_request": "staff:staff_leave_request",
177
179
  "staff_team": "staff:staff_team",
178
- "staff_team_role": "staff:staff_team_role",
179
180
  "staff_team_member": "staff:staff_team_member",
180
- "staff_leave_request": "staff:staff_leave_request",
181
- "staff_team_member_comment": "staff:staff_team_member_comment",
182
181
  "staff_team_member_activity": "staff:staff_team_member_activity",
182
+ "staff_team_member_address": "staff:staff_team_member_address",
183
+ "staff_team_member_comment": "staff:staff_team_member_comment",
183
184
  "staff_team_member_job_history": "staff:staff_team_member_job_history",
184
- "staff_team_member_address": "staff:staff_team_member_address"
185
+ "staff_team_role": "staff:staff_team_role"
186
+ },
187
+ "notifications": {
188
+ "notification": "notifications:notification"
185
189
  }
186
190
  } as const
187
191
  export type KnownModuleId = keyof typeof M
@@ -53,6 +53,7 @@ import * as feature_toggle_override from './entities/feature_toggle_override/ind
53
53
  import * as indexer_error_log from './entities/indexer_error_log/index'
54
54
  import * as indexer_status_log from './entities/indexer_status_log/index'
55
55
  import * as module_config from './entities/module_config/index'
56
+ import * as notification from './entities/notification/index'
56
57
  import * as organization from './entities/organization/index'
57
58
  import * as password_reset from './entities/password_reset/index'
58
59
  import * as perspective from './entities/perspective/index'
@@ -172,6 +173,7 @@ export const entityFieldsRegistry: Record<string, Record<string, string>> = {
172
173
  indexer_error_log,
173
174
  indexer_status_log,
174
175
  module_config,
176
+ notification,
175
177
  organization,
176
178
  password_reset,
177
179
  perspective,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/core",
3
- "version": "0.4.2-canary-36ab8921da",
3
+ "version": "0.4.2-canary-07dbc98202",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "scripts": {
@@ -207,7 +207,7 @@
207
207
  }
208
208
  },
209
209
  "dependencies": {
210
- "@open-mercato/shared": "0.4.2-canary-36ab8921da",
210
+ "@open-mercato/shared": "0.4.2-canary-07dbc98202",
211
211
  "@xyflow/react": "^12.6.0",
212
212
  "date-fns": "^4.1.0",
213
213
  "date-fns-tz": "^3.2.0"
@@ -2,6 +2,7 @@ import ApiDocsExplorer from './Explorer'
2
2
  import { getModules } from '@open-mercato/shared/lib/i18n/server'
3
3
  import { buildOpenApiDocument } from '@open-mercato/shared/lib/openapi'
4
4
  import { resolveApiDocsBaseUrl } from '@open-mercato/core/modules/api_docs/lib/resources'
5
+ import { APP_VERSION } from '@open-mercato/shared/lib/version'
5
6
 
6
7
  type ExplorerOperation = {
7
8
  id: string
@@ -54,7 +55,7 @@ export default async function ApiDocsViewerPage() {
54
55
  const modules = getModules()
55
56
  const doc = buildOpenApiDocument(modules, {
56
57
  title: 'Open Mercato API',
57
- version: '1.0.0',
58
+ version: APP_VERSION,
58
59
  description: 'Auto-generated OpenAPI definition for all enabled modules.',
59
60
  servers: [{ url: baseUrl, description: 'Default environment' }],
60
61
  baseUrlForExamples: baseUrl,
@@ -67,7 +68,7 @@ export default async function ApiDocsViewerPage() {
67
68
  return (
68
69
  <ApiDocsExplorer
69
70
  title={doc.info?.title ?? 'Open Mercato API'}
70
- version={doc.info?.version ?? '1.0.0'}
71
+ version={doc.info?.version ?? APP_VERSION}
71
72
  description={doc.info?.description}
72
73
  operations={operations}
73
74
  tagOrder={tagOrder}
@@ -297,12 +297,16 @@ export async function GET(req: Request) {
297
297
  const groupsWithRole = rolePreference ? applySidebarPreference(groups, rolePreference) : groups
298
298
  const baseForUser = adoptSidebarDefaults(groupsWithRole)
299
299
 
300
- const preference = await loadSidebarPreference(em, {
301
- userId: auth.sub,
302
- tenantId: auth.tenantId ?? null,
303
- organizationId: auth.orgId ?? null,
304
- locale,
305
- })
300
+ // For API key auth, use userId (the actual user) if available; otherwise skip user preferences
301
+ const effectiveUserId = auth.isApiKey ? auth.userId : auth.sub
302
+ const preference = effectiveUserId
303
+ ? await loadSidebarPreference(em, {
304
+ userId: effectiveUserId,
305
+ tenantId: auth.tenantId ?? null,
306
+ organizationId: auth.orgId ?? null,
307
+ locale,
308
+ })
309
+ : null
306
310
 
307
311
  const withPreference = applySidebarPreference(baseForUser, preference)
308
312
 
@@ -0,0 +1,160 @@
1
+ import { NextResponse } from 'next/server'
2
+ import { z } from 'zod'
3
+ import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'
4
+ import type { CommandBus, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'
5
+ import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
6
+ import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
7
+ import { signJwt } from '@open-mercato/shared/lib/auth/jwt'
8
+ import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
9
+ import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
10
+ import { AuthService } from '@open-mercato/core/modules/auth/services/authService'
11
+ import { User } from '@open-mercato/core/modules/auth/data/entities'
12
+ import type { EntityManager } from '@mikro-orm/postgresql'
13
+ import { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'
14
+
15
+ const profileResponseSchema = z.object({
16
+ email: z.string().email(),
17
+ })
18
+
19
+ const updateSchema = z.object({
20
+ email: z.string().email().optional(),
21
+ password: z.string().min(6).optional(),
22
+ }).refine((data) => Boolean(data.email || data.password), {
23
+ message: 'Provide an email or password.',
24
+ path: ['email'],
25
+ })
26
+
27
+ const profileUpdateResponseSchema = z.object({
28
+ ok: z.literal(true),
29
+ email: z.string().email(),
30
+ })
31
+
32
+ export const metadata = {
33
+ GET: { requireAuth: true },
34
+ PUT: { requireAuth: true },
35
+ }
36
+
37
+ function buildCommandContext(container: Awaited<ReturnType<typeof createRequestContainer>>, auth: NonNullable<Awaited<ReturnType<typeof getAuthFromRequest>>>, req: Request): CommandRuntimeContext {
38
+ return {
39
+ container,
40
+ auth,
41
+ organizationScope: null,
42
+ selectedOrganizationId: auth.orgId ?? null,
43
+ organizationIds: auth.orgId ? [auth.orgId] : null,
44
+ request: req,
45
+ }
46
+ }
47
+
48
+ export async function GET(req: Request) {
49
+ const { translate } = await resolveTranslations()
50
+ const auth = await getAuthFromRequest(req)
51
+ if (!auth?.sub) {
52
+ return NextResponse.json({ error: translate('api.errors.unauthorized', 'Unauthorized') }, { status: 401 })
53
+ }
54
+ try {
55
+ const container = await createRequestContainer()
56
+ const em = (container.resolve('em') as EntityManager)
57
+ const user = await findOneWithDecryption(
58
+ em,
59
+ User,
60
+ { id: auth.sub, deletedAt: null },
61
+ undefined,
62
+ { tenantId: auth.tenantId ?? null, organizationId: auth.orgId ?? null },
63
+ )
64
+ if (!user) {
65
+ return NextResponse.json({ error: translate('auth.users.form.errors.notFound', 'User not found') }, { status: 404 })
66
+ }
67
+ return NextResponse.json({ email: String(user.email) })
68
+ } catch (err) {
69
+ console.error('auth.profile.load failed', err)
70
+ return NextResponse.json({ error: translate('auth.profile.form.errors.load', 'Failed to load profile.') }, { status: 400 })
71
+ }
72
+ }
73
+
74
+ export async function PUT(req: Request) {
75
+ const { translate } = await resolveTranslations()
76
+ const auth = await getAuthFromRequest(req)
77
+ if (!auth?.sub) {
78
+ return NextResponse.json({ error: translate('api.errors.unauthorized', 'Unauthorized') }, { status: 401 })
79
+ }
80
+ try {
81
+ const body = await req.json().catch(() => ({}))
82
+ const parsed = updateSchema.safeParse(body)
83
+ if (!parsed.success) {
84
+ return NextResponse.json(
85
+ {
86
+ error: translate('auth.profile.form.errors.invalid', 'Invalid profile update.'),
87
+ issues: parsed.error.issues,
88
+ },
89
+ { status: 400 },
90
+ )
91
+ }
92
+ const container = await createRequestContainer()
93
+ const commandBus = (container.resolve('commandBus') as CommandBus)
94
+ const ctx = buildCommandContext(container, auth, req)
95
+ const { result } = await commandBus.execute<{ id: string; email?: string; password?: string }, User>(
96
+ 'auth.users.update',
97
+ {
98
+ input: {
99
+ id: auth.sub,
100
+ email: parsed.data.email,
101
+ password: parsed.data.password,
102
+ },
103
+ ctx,
104
+ },
105
+ )
106
+ const authService = container.resolve('authService') as AuthService
107
+ const roles = await authService.getUserRoles(result, result.tenantId ? String(result.tenantId) : null)
108
+ const jwt = signJwt({
109
+ sub: String(result.id),
110
+ tenantId: result.tenantId ? String(result.tenantId) : null,
111
+ orgId: result.organizationId ? String(result.organizationId) : null,
112
+ email: result.email,
113
+ roles,
114
+ })
115
+ const res = NextResponse.json({ ok: true, email: String(result.email) })
116
+ res.cookies.set('auth_token', jwt, {
117
+ httpOnly: true,
118
+ path: '/',
119
+ sameSite: 'lax',
120
+ secure: process.env.NODE_ENV === 'production',
121
+ maxAge: 60 * 60 * 8,
122
+ })
123
+ return res
124
+ } catch (err) {
125
+ if (err instanceof CrudHttpError) {
126
+ return NextResponse.json(err.body, { status: err.status })
127
+ }
128
+ console.error('auth.profile.update failed', err)
129
+ return NextResponse.json({ error: translate('auth.profile.form.errors.save', 'Failed to update profile.') }, { status: 400 })
130
+ }
131
+ }
132
+
133
+ export const openApi: OpenApiRouteDoc = {
134
+ tag: 'Authentication & Accounts',
135
+ summary: 'Profile settings',
136
+ methods: {
137
+ GET: {
138
+ summary: 'Get current profile',
139
+ description: 'Returns the email address for the signed-in user.',
140
+ responses: [
141
+ { status: 200, description: 'Profile payload', schema: profileResponseSchema },
142
+ { status: 401, description: 'Unauthorized', schema: z.object({ error: z.string() }) },
143
+ { status: 404, description: 'User not found', schema: z.object({ error: z.string() }) },
144
+ ],
145
+ },
146
+ PUT: {
147
+ summary: 'Update current profile',
148
+ description: 'Updates the email address or password for the signed-in user.',
149
+ requestBody: {
150
+ contentType: 'application/json',
151
+ schema: updateSchema,
152
+ },
153
+ responses: [
154
+ { status: 200, description: 'Profile updated', schema: profileUpdateResponseSchema },
155
+ { status: 400, description: 'Invalid payload', schema: z.object({ error: z.string() }) },
156
+ { status: 401, description: 'Unauthorized', schema: z.object({ error: z.string() }) },
157
+ ],
158
+ },
159
+ },
160
+ }
@@ -3,6 +3,9 @@ import { NextResponse } from 'next/server'
3
3
  import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'
4
4
  import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
5
5
  import { AuthService } from '@open-mercato/core/modules/auth/services/authService'
6
+ import { buildNotificationFromType } from '@open-mercato/core/modules/notifications/lib/notificationBuilder'
7
+ import { resolveNotificationService } from '@open-mercato/core/modules/notifications/lib/notificationService'
8
+ import notificationTypes from '@open-mercato/core/modules/auth/notifications'
6
9
  import { z } from 'zod'
7
10
 
8
11
  // validation via confirmPasswordResetSchema
@@ -15,8 +18,28 @@ export async function POST(req: Request) {
15
18
  if (!parsed.success) return NextResponse.json({ ok: false, error: 'Invalid request' }, { status: 400 })
16
19
  const c = await createRequestContainer()
17
20
  const auth = c.resolve<AuthService>('authService')
18
- const ok = await auth.confirmPasswordReset(parsed.data.token, parsed.data.password)
19
- if (!ok) return NextResponse.json({ ok: false, error: 'Invalid or expired token' }, { status: 400 })
21
+ const user = await auth.confirmPasswordReset(parsed.data.token, parsed.data.password)
22
+ if (!user) return NextResponse.json({ ok: false, error: 'Invalid or expired token' }, { status: 400 })
23
+ try {
24
+ const tenantId = user.tenantId ? String(user.tenantId) : null
25
+ if (tenantId) {
26
+ const notificationService = resolveNotificationService(c)
27
+ const typeDef = notificationTypes.find((type) => type.type === 'auth.password_reset.completed')
28
+ if (typeDef) {
29
+ const notificationInput = buildNotificationFromType(typeDef, {
30
+ recipientUserId: String(user.id),
31
+ sourceEntityType: 'auth:user',
32
+ sourceEntityId: String(user.id),
33
+ })
34
+ await notificationService.create(notificationInput, {
35
+ tenantId,
36
+ organizationId: user.organizationId ? String(user.organizationId) : null,
37
+ })
38
+ }
39
+ }
40
+ } catch (err) {
41
+ console.error('[auth.reset.confirm] Failed to create notification:', err)
42
+ }
20
43
  return NextResponse.json({ ok: true, redirect: '/login' })
21
44
  }
22
45
 
@@ -6,6 +6,9 @@ import { AuthService } from '@open-mercato/core/modules/auth/services/authServic
6
6
  import { sendEmail } from '@open-mercato/shared/lib/email/send'
7
7
  import ResetPasswordEmail from '@open-mercato/core/modules/auth/emails/ResetPasswordEmail'
8
8
  import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
9
+ import { buildNotificationFromType } from '@open-mercato/core/modules/notifications/lib/notificationBuilder'
10
+ import { resolveNotificationService } from '@open-mercato/core/modules/notifications/lib/notificationService'
11
+ import notificationTypes from '@open-mercato/core/modules/auth/notifications'
9
12
  import { z } from 'zod'
10
13
 
11
14
  // validation via requestPasswordResetSchema
@@ -35,6 +38,26 @@ export async function POST(req: Request) {
35
38
  }
36
39
 
37
40
  await sendEmail({ to: user.email, subject, react: ResetPasswordEmail({ resetUrl, copy }) })
41
+ try {
42
+ const tenantId = user.tenantId ? String(user.tenantId) : null
43
+ if (tenantId) {
44
+ const notificationService = resolveNotificationService(c)
45
+ const typeDef = notificationTypes.find((type) => type.type === 'auth.password_reset.requested')
46
+ if (typeDef) {
47
+ const notificationInput = buildNotificationFromType(typeDef, {
48
+ recipientUserId: String(user.id),
49
+ sourceEntityType: 'auth:user',
50
+ sourceEntityId: String(user.id),
51
+ })
52
+ await notificationService.create(notificationInput, {
53
+ tenantId,
54
+ organizationId: user.organizationId ? String(user.organizationId) : null,
55
+ })
56
+ }
57
+ }
58
+ } catch (err) {
59
+ console.error('[auth.reset] Failed to create notification:', err)
60
+ }
38
61
  return NextResponse.json({ ok: true })
39
62
  }
40
63
 
@@ -64,12 +64,16 @@ export async function GET(req: Request) {
64
64
  { tenantId: auth.tenantId ?? null, organizationId: auth.orgId ?? null },
65
65
  ) ?? false
66
66
 
67
- const settings = await loadSidebarPreference(em, {
68
- userId: auth.sub,
69
- tenantId: auth.tenantId ?? null,
70
- organizationId: auth.orgId ?? null,
71
- locale,
72
- })
67
+ // For API key auth, use userId (the actual user) if available
68
+ const effectiveUserId = auth.isApiKey ? auth.userId : auth.sub
69
+ const settings = effectiveUserId
70
+ ? await loadSidebarPreference(em, {
71
+ userId: effectiveUserId,
72
+ tenantId: auth.tenantId ?? null,
73
+ organizationId: auth.orgId ?? null,
74
+ locale,
75
+ })
76
+ : null
73
77
 
74
78
  let rolesPayload: Array<{ id: string; name: string; hasPreference: boolean }> = []
75
79
  if (canApplyToRoles) {
@@ -92,11 +96,11 @@ export async function GET(req: Request) {
92
96
  return NextResponse.json({
93
97
  locale,
94
98
  settings: {
95
- version: settings.version ?? SIDEBAR_PREFERENCES_VERSION,
96
- groupOrder: settings.groupOrder ?? [],
97
- groupLabels: settings.groupLabels ?? {},
98
- itemLabels: settings.itemLabels ?? {},
99
- hiddenItems: settings.hiddenItems ?? [],
99
+ version: settings?.version ?? SIDEBAR_PREFERENCES_VERSION,
100
+ groupOrder: settings?.groupOrder ?? [],
101
+ groupLabels: settings?.groupLabels ?? {},
102
+ itemLabels: settings?.itemLabels ?? {},
103
+ hiddenItems: settings?.hiddenItems ?? [],
100
104
  },
101
105
  canApplyToRoles,
102
106
  roles: rolesPayload,
@@ -106,6 +110,11 @@ export async function GET(req: Request) {
106
110
  export async function PUT(req: Request) {
107
111
  const auth = await getAuthFromRequest(req)
108
112
  if (!auth) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
113
+ // For API key auth, use userId (the actual user) if available
114
+ const effectiveUserId = auth.isApiKey ? auth.userId : auth.sub
115
+ if (!effectiveUserId) {
116
+ return NextResponse.json({ error: 'Cannot save preferences: no user associated with this API key' }, { status: 403 })
117
+ }
109
118
 
110
119
  let parsedBody: unknown
111
120
  try {
@@ -182,7 +191,7 @@ export async function PUT(req: Request) {
182
191
  }
183
192
 
184
193
  const settings = await saveSidebarPreference(em, {
185
- userId: auth.sub,
194
+ userId: effectiveUserId,
186
195
  tenantId: auth.tenantId ?? null,
187
196
  organizationId: auth.orgId ?? null,
188
197
  locale,
@@ -0,0 +1,8 @@
1
+ export const metadata = {
2
+ requireAuth: true,
3
+ pageTitle: 'Profile',
4
+ pageTitleKey: 'auth.profile.title',
5
+ breadcrumb: [
6
+ { label: 'Profile', labelKey: 'auth.profile.title' },
7
+ ],
8
+ }