@open-mercato/core 0.9.0 → 0.9.1-develop.7459.1.99e3accd30

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 (243) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/generated/entities/customer_dictionary_entry/index.js +2 -0
  3. package/dist/generated/entities/customer_dictionary_entry/index.js.map +2 -2
  4. package/dist/generated/entities/customer_interaction/index.js +2 -0
  5. package/dist/generated/entities/customer_interaction/index.js.map +2 -2
  6. package/dist/generated/entity-fields-registry.js +2 -0
  7. package/dist/generated/entity-fields-registry.js.map +2 -2
  8. package/dist/modules/catalog/commands/categories.js +1 -1
  9. package/dist/modules/catalog/commands/categories.js.map +2 -2
  10. package/dist/modules/catalog/commands/productDeleteChildren.js +389 -0
  11. package/dist/modules/catalog/commands/productDeleteChildren.js.map +7 -0
  12. package/dist/modules/catalog/commands/products.js +52 -17
  13. package/dist/modules/catalog/commands/products.js.map +2 -2
  14. package/dist/modules/communication_channels/api/post/channels/connect/credentials/route.js +4 -6
  15. package/dist/modules/communication_channels/api/post/channels/connect/credentials/route.js.map +2 -2
  16. package/dist/modules/communication_channels/api/post/channels/connect/tenant-credentials/route.js +4 -6
  17. package/dist/modules/communication_channels/api/post/channels/connect/tenant-credentials/route.js.map +2 -2
  18. package/dist/modules/communication_channels/api/post/oauth/[provider]/initiate/route.js +47 -11
  19. package/dist/modules/communication_channels/api/post/oauth/[provider]/initiate/route.js.map +3 -3
  20. package/dist/modules/communication_channels/commands/deliver-outbound-message.js +5 -1
  21. package/dist/modules/communication_channels/commands/deliver-outbound-message.js.map +2 -2
  22. package/dist/modules/communication_channels/lib/inbound-message-origin.js +1 -1
  23. package/dist/modules/communication_channels/lib/inbound-message-origin.js.map +2 -2
  24. package/dist/modules/communication_channels/lib/oauth-state.js +4 -1
  25. package/dist/modules/communication_channels/lib/oauth-state.js.map +2 -2
  26. package/dist/modules/communication_channels/lib/use-connect-channel.js +10 -0
  27. package/dist/modules/communication_channels/lib/use-connect-channel.js.map +2 -2
  28. package/dist/modules/customers/api/activity-types/route.js +151 -0
  29. package/dist/modules/customers/api/activity-types/route.js.map +7 -0
  30. package/dist/modules/customers/api/deals/[id]/people/route.js +58 -5
  31. package/dist/modules/customers/api/deals/[id]/people/route.js.map +2 -2
  32. package/dist/modules/customers/api/dictionaries/[kind]/[id]/route.js +13 -5
  33. package/dist/modules/customers/api/dictionaries/[kind]/[id]/route.js.map +2 -2
  34. package/dist/modules/customers/api/dictionaries/[kind]/route.js +20 -5
  35. package/dist/modules/customers/api/dictionaries/[kind]/route.js.map +2 -2
  36. package/dist/modules/customers/api/interactions/route.js +3 -0
  37. package/dist/modules/customers/api/interactions/route.js.map +2 -2
  38. package/dist/modules/customers/api/interactions/tasks/route.js +1 -0
  39. package/dist/modules/customers/api/interactions/tasks/route.js.map +2 -2
  40. package/dist/modules/customers/backend/config/customers/pipeline-stages/page.meta.js +18 -0
  41. package/dist/modules/customers/backend/config/customers/pipeline-stages/page.meta.js.map +2 -2
  42. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealAssociations.js +0 -23
  43. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealAssociations.js.map +2 -2
  44. package/dist/modules/customers/backend/customers/deals/[id]/page.js +15 -17
  45. package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
  46. package/dist/modules/customers/calendar-event-types.js +548 -0
  47. package/dist/modules/customers/calendar-event-types.js.map +7 -0
  48. package/dist/modules/customers/commands/dictionaries.js +70 -10
  49. package/dist/modules/customers/commands/dictionaries.js.map +2 -2
  50. package/dist/modules/customers/commands/interactions.js +187 -22
  51. package/dist/modules/customers/commands/interactions.js.map +3 -3
  52. package/dist/modules/customers/components/ActivityTypeEditor.js +288 -0
  53. package/dist/modules/customers/components/ActivityTypeEditor.js.map +7 -0
  54. package/dist/modules/customers/components/DictionarySettings.js +3 -1
  55. package/dist/modules/customers/components/DictionarySettings.js.map +2 -2
  56. package/dist/modules/customers/components/calendar/CalendarEventEditor.js +391 -297
  57. package/dist/modules/customers/components/calendar/CalendarEventEditor.js.map +3 -3
  58. package/dist/modules/customers/components/calendar/CalendarSettingsModal.js +9 -74
  59. package/dist/modules/customers/components/calendar/CalendarSettingsModal.js.map +2 -2
  60. package/dist/modules/customers/components/calendar/TimeGrid.js +20 -16
  61. package/dist/modules/customers/components/calendar/TimeGrid.js.map +2 -2
  62. package/dist/modules/customers/components/calendar/editor/EventTypePanel.js +218 -0
  63. package/dist/modules/customers/components/calendar/editor/EventTypePanel.js.map +7 -0
  64. package/dist/modules/customers/components/calendar/editor/LocationField.js +7 -3
  65. package/dist/modules/customers/components/calendar/editor/LocationField.js.map +2 -2
  66. package/dist/modules/customers/components/calendar/editor/PeopleField.js +5 -2
  67. package/dist/modules/customers/components/calendar/editor/PeopleField.js.map +2 -2
  68. package/dist/modules/customers/components/calendar/editor/PriorityField.js +3 -1
  69. package/dist/modules/customers/components/calendar/editor/PriorityField.js.map +2 -2
  70. package/dist/modules/customers/components/calendar/editor/RepeatField.js +9 -1
  71. package/dist/modules/customers/components/calendar/editor/RepeatField.js.map +2 -2
  72. package/dist/modules/customers/components/calendar/editor/ResourcesField.js +4 -1
  73. package/dist/modules/customers/components/calendar/editor/ResourcesField.js.map +2 -2
  74. package/dist/modules/customers/components/calendar/editor/ScheduleSection.js +15 -7
  75. package/dist/modules/customers/components/calendar/editor/ScheduleSection.js.map +2 -2
  76. package/dist/modules/customers/components/calendar/editor/SegmentGroup.js +3 -1
  77. package/dist/modules/customers/components/calendar/editor/SegmentGroup.js.map +2 -2
  78. package/dist/modules/customers/components/calendar/editor/hooks.js +28 -13
  79. package/dist/modules/customers/components/calendar/editor/hooks.js.map +3 -3
  80. package/dist/modules/customers/components/calendar/editor/inputs.js +14 -6
  81. package/dist/modules/customers/components/calendar/editor/inputs.js.map +2 -2
  82. package/dist/modules/customers/components/calendar/editor/useCalendarCustomFields.js +54 -0
  83. package/dist/modules/customers/components/calendar/editor/useCalendarCustomFields.js.map +7 -0
  84. package/dist/modules/customers/components/calendar/editor/useEventTypeCatalog.js +82 -0
  85. package/dist/modules/customers/components/calendar/editor/useEventTypeCatalog.js.map +7 -0
  86. package/dist/modules/customers/components/calendar/types.js +1 -0
  87. package/dist/modules/customers/components/calendar/types.js.map +2 -2
  88. package/dist/modules/customers/components/detail/CompanyPeopleSection.js +78 -343
  89. package/dist/modules/customers/components/detail/CompanyPeopleSection.js.map +2 -2
  90. package/dist/modules/customers/components/detail/CreatePersonDialog.js +12 -11
  91. package/dist/modules/customers/components/detail/CreatePersonDialog.js.map +2 -2
  92. package/dist/modules/customers/components/detail/DealForm.js +7 -3
  93. package/dist/modules/customers/components/detail/DealForm.js.map +2 -2
  94. package/dist/modules/customers/components/detail/DealPeopleSection.js +206 -0
  95. package/dist/modules/customers/components/detail/DealPeopleSection.js.map +7 -0
  96. package/dist/modules/customers/components/detail/LinkedPeopleSection.js +342 -0
  97. package/dist/modules/customers/components/detail/LinkedPeopleSection.js.map +7 -0
  98. package/dist/modules/customers/components/detail/PersonCard.js +5 -2
  99. package/dist/modules/customers/components/detail/PersonCard.js.map +2 -2
  100. package/dist/modules/customers/components/linking/adapters/personAdapter.js +3 -0
  101. package/dist/modules/customers/components/linking/adapters/personAdapter.js.map +2 -2
  102. package/dist/modules/customers/data/entities.js +6 -0
  103. package/dist/modules/customers/data/entities.js.map +2 -2
  104. package/dist/modules/customers/data/validators.js +39 -10
  105. package/dist/modules/customers/data/validators.js.map +2 -2
  106. package/dist/modules/customers/di.js +20 -1
  107. package/dist/modules/customers/di.js.map +2 -2
  108. package/dist/modules/customers/extension-points.js +13 -0
  109. package/dist/modules/customers/extension-points.js.map +2 -2
  110. package/dist/modules/customers/lib/calendar/conflicts.js +59 -16
  111. package/dist/modules/customers/lib/calendar/conflicts.js.map +2 -2
  112. package/dist/modules/customers/lib/calendar/editorPayload.js +34 -16
  113. package/dist/modules/customers/lib/calendar/editorPayload.js.map +2 -2
  114. package/dist/modules/customers/lib/calendar/eventTypeResolver.js +197 -0
  115. package/dist/modules/customers/lib/calendar/eventTypeResolver.js.map +7 -0
  116. package/dist/modules/customers/lib/calendar/interactionApplicability.js +67 -0
  117. package/dist/modules/customers/lib/calendar/interactionApplicability.js.map +7 -0
  118. package/dist/modules/customers/lib/calendar/mapItem.js +5 -2
  119. package/dist/modules/customers/lib/calendar/mapItem.js.map +2 -2
  120. package/dist/modules/customers/lib/calendar/recurrence.js +62 -1
  121. package/dist/modules/customers/lib/calendar/recurrence.js.map +2 -2
  122. package/dist/modules/customers/lib/calendar/timezone.js +111 -0
  123. package/dist/modules/customers/lib/calendar/timezone.js.map +7 -0
  124. package/dist/modules/customers/lib/interactionReadModel.js +1 -0
  125. package/dist/modules/customers/lib/interactionReadModel.js.map +2 -2
  126. package/dist/modules/customers/lib/todoCompatibility.js +1 -0
  127. package/dist/modules/customers/lib/todoCompatibility.js.map +2 -2
  128. package/dist/modules/customers/migrations/Migration20260928175058_customers.js +17 -0
  129. package/dist/modules/customers/migrations/Migration20260928175058_customers.js.map +7 -0
  130. package/dist/modules/customers/migrations/Migration20260930110235_customers.js +17 -0
  131. package/dist/modules/customers/migrations/Migration20260930110235_customers.js.map +7 -0
  132. package/dist/modules/dictionaries/components/DictionaryTable.js +60 -51
  133. package/dist/modules/dictionaries/components/DictionaryTable.js.map +2 -2
  134. package/dist/modules/messages/subscribers/message-notification.js +13 -1
  135. package/dist/modules/messages/subscribers/message-notification.js.map +2 -2
  136. package/dist/modules/payment_gateways/api/webhook/[provider]/route.js +201 -53
  137. package/dist/modules/payment_gateways/api/webhook/[provider]/route.js.map +2 -2
  138. package/dist/modules/payment_gateways/lib/gateway-service.js +37 -11
  139. package/dist/modules/payment_gateways/lib/gateway-service.js.map +2 -2
  140. package/dist/modules/planner/lib/availabilityMerge.js +101 -38
  141. package/dist/modules/planner/lib/availabilityMerge.js.map +3 -3
  142. package/dist/modules/planner/services/plannerAvailabilityService.js.map +2 -2
  143. package/dist/modules/sales/components/documents/LineItemDialog.js +159 -81
  144. package/dist/modules/sales/components/documents/LineItemDialog.js.map +2 -2
  145. package/dist/modules/sales/components/documents/lineItemUtils.js +7 -0
  146. package/dist/modules/sales/components/documents/lineItemUtils.js.map +2 -2
  147. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.js +12 -7
  148. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.js.map +2 -2
  149. package/dist/modules/sync_excel/lib/adapters/customers.js +28 -25
  150. package/dist/modules/sync_excel/lib/adapters/customers.js.map +2 -2
  151. package/generated/entities/customer_dictionary_entry/index.ts +1 -0
  152. package/generated/entities/customer_interaction/index.ts +1 -0
  153. package/generated/entity-fields-registry.ts +2 -0
  154. package/package.json +9 -8
  155. package/src/modules/auth/i18n/de.json +3 -0
  156. package/src/modules/auth/i18n/en.json +3 -0
  157. package/src/modules/auth/i18n/es.json +3 -0
  158. package/src/modules/auth/i18n/ko.json +3 -0
  159. package/src/modules/auth/i18n/pl.json +3 -0
  160. package/src/modules/catalog/commands/categories.ts +1 -1
  161. package/src/modules/catalog/commands/productDeleteChildren.ts +557 -0
  162. package/src/modules/catalog/commands/products.ts +58 -17
  163. package/src/modules/communication_channels/api/post/channels/connect/credentials/route.ts +4 -6
  164. package/src/modules/communication_channels/api/post/channels/connect/tenant-credentials/route.ts +4 -6
  165. package/src/modules/communication_channels/api/post/oauth/[provider]/initiate/route.ts +46 -10
  166. package/src/modules/communication_channels/commands/deliver-outbound-message.ts +6 -1
  167. package/src/modules/communication_channels/i18n/de.json +4 -0
  168. package/src/modules/communication_channels/i18n/en.json +4 -0
  169. package/src/modules/communication_channels/i18n/es.json +4 -0
  170. package/src/modules/communication_channels/i18n/ko.json +4 -0
  171. package/src/modules/communication_channels/i18n/pl.json +4 -0
  172. package/src/modules/communication_channels/lib/inbound-message-origin.ts +2 -6
  173. package/src/modules/communication_channels/lib/oauth-state.ts +4 -1
  174. package/src/modules/communication_channels/lib/use-connect-channel.ts +10 -0
  175. package/src/modules/customers/api/activity-types/route.ts +154 -0
  176. package/src/modules/customers/api/deals/[id]/people/route.ts +82 -3
  177. package/src/modules/customers/api/dictionaries/[kind]/[id]/route.ts +9 -1
  178. package/src/modules/customers/api/dictionaries/[kind]/route.ts +18 -2
  179. package/src/modules/customers/api/interactions/route.ts +4 -0
  180. package/src/modules/customers/api/interactions/tasks/route.ts +1 -0
  181. package/src/modules/customers/backend/config/customers/pipeline-stages/page.meta.ts +20 -0
  182. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealAssociations.ts +0 -29
  183. package/src/modules/customers/backend/customers/deals/[id]/page.tsx +15 -17
  184. package/src/modules/customers/calendar-event-types.ts +674 -0
  185. package/src/modules/customers/commands/dictionaries.ts +84 -8
  186. package/src/modules/customers/commands/interactions.ts +244 -21
  187. package/src/modules/customers/components/ActivityTypeEditor.tsx +239 -0
  188. package/src/modules/customers/components/DictionarySettings.tsx +5 -3
  189. package/src/modules/customers/components/calendar/CalendarEventEditor.tsx +347 -218
  190. package/src/modules/customers/components/calendar/CalendarSettingsModal.tsx +18 -96
  191. package/src/modules/customers/components/calendar/TimeGrid.tsx +20 -18
  192. package/src/modules/customers/components/calendar/editor/EventTypePanel.tsx +230 -0
  193. package/src/modules/customers/components/calendar/editor/LocationField.tsx +7 -1
  194. package/src/modules/customers/components/calendar/editor/PeopleField.tsx +4 -0
  195. package/src/modules/customers/components/calendar/editor/PriorityField.tsx +3 -0
  196. package/src/modules/customers/components/calendar/editor/RepeatField.tsx +10 -0
  197. package/src/modules/customers/components/calendar/editor/ResourcesField.tsx +4 -0
  198. package/src/modules/customers/components/calendar/editor/ScheduleSection.tsx +16 -4
  199. package/src/modules/customers/components/calendar/editor/SegmentGroup.tsx +3 -0
  200. package/src/modules/customers/components/calendar/editor/hooks.ts +29 -13
  201. package/src/modules/customers/components/calendar/editor/inputs.tsx +17 -5
  202. package/src/modules/customers/components/calendar/editor/useCalendarCustomFields.ts +49 -0
  203. package/src/modules/customers/components/calendar/editor/useEventTypeCatalog.ts +100 -0
  204. package/src/modules/customers/components/calendar/types.ts +1 -0
  205. package/src/modules/customers/components/detail/CompanyPeopleSection.tsx +94 -388
  206. package/src/modules/customers/components/detail/CreatePersonDialog.tsx +39 -19
  207. package/src/modules/customers/components/detail/DealForm.tsx +7 -3
  208. package/src/modules/customers/components/detail/DealPeopleSection.tsx +256 -0
  209. package/src/modules/customers/components/detail/LinkedPeopleSection.tsx +474 -0
  210. package/src/modules/customers/components/detail/PersonCard.tsx +12 -4
  211. package/src/modules/customers/components/detail/types.ts +1 -0
  212. package/src/modules/customers/components/linking/adapters/personAdapter.tsx +4 -0
  213. package/src/modules/customers/data/entities.ts +8 -1
  214. package/src/modules/customers/data/validators.ts +42 -7
  215. package/src/modules/customers/di.ts +21 -0
  216. package/src/modules/customers/extension-points.ts +13 -0
  217. package/src/modules/customers/i18n/de.json +104 -8
  218. package/src/modules/customers/i18n/en.json +104 -8
  219. package/src/modules/customers/i18n/es.json +104 -8
  220. package/src/modules/customers/i18n/ko.json +104 -8
  221. package/src/modules/customers/i18n/pl.json +104 -8
  222. package/src/modules/customers/lib/calendar/conflicts.ts +106 -27
  223. package/src/modules/customers/lib/calendar/editorPayload.ts +39 -19
  224. package/src/modules/customers/lib/calendar/eventTypeResolver.ts +258 -0
  225. package/src/modules/customers/lib/calendar/interactionApplicability.ts +99 -0
  226. package/src/modules/customers/lib/calendar/mapItem.ts +6 -2
  227. package/src/modules/customers/lib/calendar/recurrence.ts +65 -1
  228. package/src/modules/customers/lib/calendar/timezone.ts +117 -0
  229. package/src/modules/customers/lib/interactionReadModel.ts +1 -0
  230. package/src/modules/customers/lib/todoCompatibility.ts +2 -0
  231. package/src/modules/customers/migrations/.snapshot-open-mercato.json +34 -0
  232. package/src/modules/customers/migrations/Migration20260928175058_customers.ts +15 -0
  233. package/src/modules/customers/migrations/Migration20260930110235_customers.ts +15 -0
  234. package/src/modules/dictionaries/components/DictionaryTable.tsx +63 -56
  235. package/src/modules/messages/subscribers/message-notification.ts +13 -3
  236. package/src/modules/payment_gateways/api/webhook/[provider]/route.ts +243 -62
  237. package/src/modules/payment_gateways/lib/gateway-service.ts +39 -12
  238. package/src/modules/planner/lib/availabilityMerge.ts +106 -41
  239. package/src/modules/planner/services/plannerAvailabilityService.ts +4 -0
  240. package/src/modules/sales/components/documents/LineItemDialog.tsx +194 -111
  241. package/src/modules/sales/components/documents/lineItemUtils.ts +18 -0
  242. package/src/modules/staff/backend/staff/time-tracking/projects/[id]/page.tsx +25 -13
  243. package/src/modules/sync_excel/lib/adapters/customers.ts +33 -27
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/modules/customers/calendar-event-types.ts"],
4
+ "sourcesContent": ["import { z } from 'zod'\nimport type { InjectionWidgetModule } from '@open-mercato/shared/modules/widgets/injection'\n\nexport const calendarEventBaseKindSchema = z.enum(['meeting', 'call', 'email', 'note', 'event', 'task'])\n\nexport const calendarEventTypeFieldsSchema = z.strictObject({\n endTime: z.boolean(),\n allDay: z.boolean(),\n recurrence: z.boolean(),\n location: z.enum(['none', 'location', 'phoneLink']),\n people: z.enum(['none', 'attendees', 'participants', 'recipients', 'assignee']),\n priority: z.boolean(),\n resources: z.boolean(),\n})\n\nexport const calendarEventTypeBehaviorSchema = z.strictObject({\n schemaVersion: z.literal(1),\n baseKind: calendarEventBaseKindSchema,\n selectable: z.boolean(),\n order: z.number().int().min(0).max(10_000),\n fields: calendarEventTypeFieldsSchema,\n customFieldsetIds: z.array(z.string().trim().min(1).max(100)).max(32).refine(\n (values) => new Set(values).size === values.length,\n 'Custom fieldset ids must be unique',\n ),\n})\n\nexport const calendarEventTypeKeySchema = z.string().trim().min(1).max(100).regex(\n /^[a-z0-9]+(?:[-_][a-z0-9]+)*$/,\n 'Calendar event type keys must be lowercase dictionary keys',\n)\n\nexport const calendarEventTypeDefinitionSchema = z.strictObject({\n key: calendarEventTypeKeySchema,\n label: z.string().trim().min(1).max(150),\n labelKey: z.string().trim().min(1).max(200).optional(),\n icon: z.string().trim().max(100).nullable().optional(),\n color: z.string().trim().max(100).nullable().optional(),\n behavior: calendarEventTypeBehaviorSchema,\n adminConfigurable: z.boolean().optional(),\n panelKey: z.string().trim().min(1).max(150).optional(),\n})\n\nexport const calendarEventTypeBehaviorOverrideSchema = z.strictObject({\n schemaVersion: z.literal(1).optional(),\n baseKind: calendarEventBaseKindSchema.optional(),\n selectable: z.boolean().optional(),\n order: z.number().int().min(0).max(10_000).optional(),\n fields: calendarEventTypeFieldsSchema.partial().strict().optional(),\n customFieldsetIds: z.array(z.string().trim().min(1).max(100)).max(32).refine(\n (values) => new Set(values).size === values.length,\n 'Custom fieldset ids must be unique',\n ).optional(),\n})\n\nexport const calendarEventTypeDefinitionOverrideSchema = z.strictObject({\n label: z.string().trim().min(1).max(150).optional(),\n labelKey: z.string().trim().min(1).max(200).optional(),\n icon: z.string().trim().max(100).nullable().optional(),\n color: z.string().trim().max(100).nullable().optional(),\n behavior: calendarEventTypeBehaviorOverrideSchema.optional(),\n adminConfigurable: z.boolean().optional(),\n panelKey: z.string().trim().min(1).max(150).optional(),\n})\n\nexport const calendarEventTypePatchSchema = z.strictObject({\n targetEventTypeKey: calendarEventTypeKeySchema,\n replaceLabel: z.string().trim().min(1).max(150).optional(),\n replaceLabelKey: z.string().trim().min(1).max(200).nullable().optional(),\n replaceIcon: z.string().trim().max(100).nullable().optional(),\n replaceColor: z.string().trim().max(100).nullable().optional(),\n replaceBaseKind: calendarEventBaseKindSchema.optional(),\n replaceSelectable: z.boolean().optional(),\n replaceOrder: z.number().int().min(0).max(10_000).optional(),\n replaceFields: calendarEventTypeFieldsSchema.partial().strict().optional(),\n replaceAdminConfigurable: z.boolean().optional(),\n replacePanelKey: z.string().trim().min(1).max(150).nullable().optional(),\n replaceCustomFieldsetIds: calendarEventTypeBehaviorSchema.shape.customFieldsetIds.optional(),\n deleteCustomFieldsetIds: calendarEventTypeBehaviorSchema.shape.customFieldsetIds.optional(),\n appendCustomFieldsetIds: calendarEventTypeBehaviorSchema.shape.customFieldsetIds.optional(),\n})\n\nexport const calendarEventTypeProvenanceSchema = z.strictObject({\n moduleId: z.string().trim().min(1).max(100),\n sourcePath: z.string().trim().min(1).max(500),\n moduleOrder: z.number().int().min(0),\n phase: z.enum(['core', 'widget', 'module', 'programmatic', 'fallback']),\n})\n\nexport const calendarEventTypeTombstoneSchema = z.strictObject({\n key: calendarEventTypeKeySchema,\n provenance: calendarEventTypeProvenanceSchema,\n})\n\nexport const calendarEventTypeHistoricalFallbackSchema = z.strictObject({\n key: calendarEventTypeKeySchema,\n reason: z.enum(['tombstoned', 'module-unavailable', 'unknown']),\n definition: calendarEventTypeDefinitionSchema,\n})\n\nexport type CalendarEventTypeWidget = InjectionWidgetModule & {\n eventTypes: readonly CalendarEventTypeDefinition[]\n eventTypeOverrides?: Readonly<Record<string, CalendarEventTypeDefinition | null>>\n eventTypePatches?: readonly CalendarEventTypePatch[]\n}\n\nexport type CalendarEventBaseKind = z.infer<typeof calendarEventBaseKindSchema>\nexport type CalendarEventTypeFields = z.infer<typeof calendarEventTypeFieldsSchema>\nexport type CalendarEventTypeBehavior = z.infer<typeof calendarEventTypeBehaviorSchema>\nexport type CalendarEventTypeDefinition = z.infer<typeof calendarEventTypeDefinitionSchema>\nexport type CalendarEventTypeBehaviorOverride = z.infer<typeof calendarEventTypeBehaviorOverrideSchema>\nexport type CalendarEventTypeDefinitionOverride = z.infer<typeof calendarEventTypeDefinitionOverrideSchema>\nexport type CalendarEventTypePatch = z.infer<typeof calendarEventTypePatchSchema>\nexport type CalendarEventTypeProvenance = z.infer<typeof calendarEventTypeProvenanceSchema>\nexport type CalendarEventTypeTombstone = z.infer<typeof calendarEventTypeTombstoneSchema>\nexport type CalendarEventTypeHistoricalFallback = z.infer<typeof calendarEventTypeHistoricalFallbackSchema>\n\nexport type EffectiveCalendarEventType = Readonly<CalendarEventTypeDefinition & {\n provenance: Readonly<Record<string, CalendarEventTypeProvenance>>\n historical: boolean\n fallbackReason?: CalendarEventTypeHistoricalFallback['reason']\n}>\n\nexport type CalendarEventPanelCapabilities = Readonly<{\n resourcesEnabled: boolean\n staffEnabled: boolean\n}>\n\nexport type CalendarEventTypePanelProps = {\n definition: EffectiveCalendarEventType\n panelKey?: string\n mode: 'create' | 'edit'\n values: Readonly<Record<string, unknown>>\n errors: Readonly<Record<string, string | undefined>>\n disabled: boolean\n capabilities: CalendarEventPanelCapabilities\n setValue: (fieldId: string, value: unknown) => void\n}\n\nexport type CalendarEventTypeDiagnostic = Readonly<{\n code: 'invalid-source' | 'duplicate-definition' | 'unknown-override' | 'unknown-patch'\n key?: string\n moduleId: string\n widgetId?: string\n owner?: string\n}>\n\nconst behavior = (\n baseKind: CalendarEventBaseKind,\n order: number,\n fields: CalendarEventTypeFields,\n): CalendarEventTypeBehavior => ({\n schemaVersion: 1,\n baseKind,\n selectable: true,\n order,\n fields,\n customFieldsetIds: [],\n})\n\nconst resources = true\n\nexport const calendarEventTypes: readonly CalendarEventTypeDefinition[] = deepFreeze([\n { key: 'meeting', label: 'Meeting', labelKey: 'customers.calendar.editor.types.meeting', icon: 'lucide:users', color: '#f59e0b', behavior: behavior('meeting', 0, { endTime: true, allDay: true, recurrence: true, location: 'location', people: 'attendees', priority: false, resources }) },\n { key: 'call', label: 'Call', labelKey: 'customers.calendar.editor.types.call', icon: 'lucide:phone-call', color: '#2563eb', behavior: behavior('call', 100, { endTime: true, allDay: true, recurrence: true, location: 'phoneLink', people: 'participants', priority: false, resources }) },\n { key: 'email', label: 'Email', labelKey: 'customers.calendar.editor.types.email', icon: 'lucide:mail', color: '#16a34a', behavior: behavior('email', 200, { endTime: false, allDay: true, recurrence: true, location: 'none', people: 'recipients', priority: false, resources }) },\n { key: 'note', label: 'Note', labelKey: 'customers.calendar.editor.types.note', icon: 'lucide:notebook', color: '#a855f7', behavior: behavior('note', 300, { endTime: false, allDay: false, recurrence: false, location: 'none', people: 'none', priority: false, resources }) },\n { key: 'event', label: 'Event', labelKey: 'customers.calendar.editor.types.event', icon: 'lucide:calendar', color: '#6366f1', behavior: behavior('event', 400, { endTime: true, allDay: true, recurrence: true, location: 'location', people: 'attendees', priority: false, resources }) },\n { key: 'task', label: 'Task', labelKey: 'customers.calendar.editor.types.task', icon: 'lucide:check-square', color: '#ef4444', behavior: behavior('task', 500, { endTime: true, allDay: true, recurrence: true, location: 'none', people: 'assignee', priority: true, resources }) },\n])\n\nexport const calendarEventTypeOverrides: Readonly<Record<string, CalendarEventTypeDefinitionOverride | null>> = Object.freeze({})\n\nexport type CalendarEventTypeWidgetContribution = Readonly<{\n moduleId: string\n widgetId: string\n priority?: number\n definitions?: unknown\n overrides?: unknown\n patches?: unknown\n}>\n\nexport type CalendarOverrides = Readonly<{\n eventTypes?: Readonly<Record<string, CalendarEventTypeDefinition | null>>\n patches?: readonly CalendarEventTypePatch[]\n}>\n\nexport type CalendarModuleOverrideEntry = Readonly<{\n moduleId: string\n overrides: CalendarOverrides\n}>\n\ntype ProgrammaticSource = {\n definitions: Map<string, CalendarEventTypeDefinition>\n overrides: Map<string, CalendarEventTypeDefinition | null>\n patches: Map<string, CalendarEventTypePatch>\n}\n\ntype RegistryState = {\n widgets: readonly ParsedWidgetContribution[]\n modules: readonly CalendarModuleOverrideEntry[]\n sources: Map<string, ProgrammaticSource>\n historicalDefinitions: Map<string, CalendarEventTypeDefinition>\n version: number\n diagnostics: readonly CalendarEventTypeDiagnostic[]\n}\n\nconst REGISTRY_KEY = Symbol.for('open-mercato.customers.calendar-event-types.v1')\n\nfunction getRegistryState(): RegistryState {\n const globalRegistry = globalThis as typeof globalThis & { [REGISTRY_KEY]?: RegistryState }\n globalRegistry[REGISTRY_KEY] ??= {\n widgets: Object.freeze([]),\n modules: Object.freeze([]),\n sources: new Map(),\n historicalDefinitions: new Map(),\n version: 0,\n diagnostics: Object.freeze([]),\n }\n return globalRegistry[REGISTRY_KEY]\n}\n\nfunction deepFreeze<T>(value: T): T {\n if (value !== null && typeof value === 'object' && !Object.isFrozen(value)) {\n Object.freeze(value)\n for (const child of Object.values(value as Record<string, unknown>)) deepFreeze(child)\n }\n return value\n}\n\nfunction sourceOf(moduleId: string, sourcePath: string, moduleOrder: number, phase: CalendarEventTypeProvenance['phase']): CalendarEventTypeProvenance {\n return Object.freeze({ moduleId, sourcePath, moduleOrder, phase })\n}\n\nfunction allPropertyPaths(definition: CalendarEventTypeDefinition): string[] {\n const paths = ['key', 'label', 'behavior.schemaVersion', 'behavior.baseKind', 'behavior.selectable', 'behavior.order']\n if (definition.labelKey !== undefined) paths.push('labelKey')\n if (definition.icon !== undefined) paths.push('icon')\n if (definition.color !== undefined) paths.push('color')\n if (definition.adminConfigurable !== undefined) paths.push('adminConfigurable')\n if (definition.panelKey !== undefined) paths.push('panelKey')\n for (const key of Object.keys(definition.behavior.fields)) paths.push(`behavior.fields.${key}`)\n paths.push('behavior.customFieldsetIds')\n return paths\n}\n\nconst widgetContributionSchema = z.strictObject({\n moduleId: z.string().trim().min(1).max(100),\n widgetId: z.string().trim().min(1).max(200),\n priority: z.number().int().optional(),\n definitions: z.array(calendarEventTypeDefinitionSchema).optional(),\n overrides: z.record(calendarEventTypeKeySchema, calendarEventTypeDefinitionSchema.nullable()).optional(),\n patches: z.array(calendarEventTypePatchSchema).optional(),\n}).superRefine((entry, context) => {\n const keys = new Set<string>()\n for (const definition of entry.definitions ?? []) {\n if (keys.has(definition.key)) {\n context.addIssue({ code: 'custom', message: 'Duplicate source definition', path: ['definitions'] })\n }\n keys.add(definition.key)\n }\n for (const [key, definition] of Object.entries(entry.overrides ?? {})) {\n if (definition !== null && definition.key !== key) {\n context.addIssue({ code: 'custom', message: 'Replacement key must match target key', path: ['overrides', key] })\n }\n }\n})\n\ntype ParsedWidgetContribution = z.infer<typeof widgetContributionSchema>\n\nconst moduleOverrideEntrySchema = z.strictObject({\n moduleId: z.string().trim().min(1).max(100),\n overrides: z.strictObject({\n eventTypes: z.record(calendarEventTypeKeySchema, calendarEventTypeDefinitionSchema.nullable()).optional(),\n patches: z.array(calendarEventTypePatchSchema).optional(),\n }),\n}).superRefine((entry, context) => {\n for (const [key, definition] of Object.entries(entry.overrides.eventTypes ?? {})) {\n if (definition !== null && definition.key !== key) {\n context.addIssue({ code: 'custom', message: 'Replacement key must match target key', path: ['overrides', 'eventTypes', key] })\n }\n }\n})\n\nfunction copyDefinition(definition: CalendarEventTypeDefinition): CalendarEventTypeDefinition {\n return calendarEventTypeDefinitionSchema.parse(definition)\n}\n\nfunction copyPatch(patch: CalendarEventTypePatch): CalendarEventTypePatch {\n return calendarEventTypePatchSchema.parse(patch)\n}\n\nfunction programmaticSource(sourceId: string): ProgrammaticSource {\n return getRegistryState().sources.get(sourceId) ?? {\n definitions: new Map(),\n overrides: new Map(),\n patches: new Map(),\n }\n}\n\nfunction replaceProgrammaticSource(sourceId: string, source: ProgrammaticSource): void {\n const state = getRegistryState()\n archiveCurrentDefinitions()\n state.sources.set(sourceId, source)\n state.version += 1\n}\n\nfunction markDefinitionProvenance(\n definition: CalendarEventTypeDefinition,\n source: CalendarEventTypeProvenance,\n): Record<string, CalendarEventTypeProvenance> {\n return Object.fromEntries(allPropertyPaths(definition).map((path) => [path, source]))\n}\n\nfunction applyPatch(\n definition: CalendarEventTypeDefinition,\n patch: CalendarEventTypePatch,\n provenance: Record<string, CalendarEventTypeProvenance>,\n source: CalendarEventTypeProvenance,\n): CalendarEventTypeDefinition {\n const next: CalendarEventTypeDefinition = {\n ...definition,\n behavior: { ...definition.behavior, fields: { ...definition.behavior.fields }, customFieldsetIds: [...definition.behavior.customFieldsetIds] },\n }\n if (patch.replaceLabel !== undefined) { next.label = patch.replaceLabel; provenance.label = source }\n if (patch.replaceLabelKey !== undefined) { next.labelKey = patch.replaceLabelKey ?? undefined; provenance.labelKey = source }\n if (patch.replaceIcon !== undefined) { next.icon = patch.replaceIcon; provenance.icon = source }\n if (patch.replaceColor !== undefined) { next.color = patch.replaceColor; provenance.color = source }\n if (patch.replaceAdminConfigurable !== undefined) { next.adminConfigurable = patch.replaceAdminConfigurable; provenance.adminConfigurable = source }\n if (patch.replacePanelKey !== undefined) { next.panelKey = patch.replacePanelKey ?? undefined; provenance.panelKey = source }\n if (patch.replaceBaseKind !== undefined) { next.behavior.baseKind = patch.replaceBaseKind; provenance['behavior.baseKind'] = source }\n if (patch.replaceSelectable !== undefined) { next.behavior.selectable = patch.replaceSelectable; provenance['behavior.selectable'] = source }\n if (patch.replaceOrder !== undefined) { next.behavior.order = patch.replaceOrder; provenance['behavior.order'] = source }\n if (patch.replaceFields) {\n next.behavior.fields = { ...next.behavior.fields, ...patch.replaceFields }\n for (const field of Object.keys(patch.replaceFields)) provenance[`behavior.fields.${field}`] = source\n }\n if (patch.replaceCustomFieldsetIds || patch.deleteCustomFieldsetIds || patch.appendCustomFieldsetIds) {\n const fieldsets = patch.replaceCustomFieldsetIds ?? next.behavior.customFieldsetIds\n const deleted = new Set(patch.deleteCustomFieldsetIds ?? [])\n next.behavior.customFieldsetIds = [...new Set([...fieldsets.filter((id) => !deleted.has(id)), ...(patch.appendCustomFieldsetIds ?? [])])]\n provenance['behavior.customFieldsetIds'] = source\n }\n return calendarEventTypeDefinitionSchema.parse(next)\n}\n\nfunction compose(excludedSources: ReadonlySet<object> = new Set(), rejectedSources: readonly CalendarEventTypeDiagnostic[] = []): {\n items: readonly EffectiveCalendarEventType[]\n tombstones: readonly CalendarEventTypeTombstone[]\n diagnostics: readonly CalendarEventTypeDiagnostic[]\n} {\n const definitions = new Map<string, CalendarEventTypeDefinition>()\n const owners = new Map<string, CalendarEventTypeProvenance>()\n const provenance = new Map<string, Record<string, CalendarEventTypeProvenance>>()\n const tombstones = new Map<string, CalendarEventTypeTombstone>()\n const diagnostics: CalendarEventTypeDiagnostic[] = [...getRegistryState().diagnostics, ...rejectedSources]\n const coreSource = Object.freeze({ moduleId: 'customers', sourcePath: 'calendar-event-types.ts', moduleOrder: 0, phase: 'core' as const })\n\n for (const definition of calendarEventTypes) {\n definitions.set(definition.key, definition)\n owners.set(definition.key, coreSource)\n provenance.set(definition.key, markDefinitionProvenance(definition, coreSource))\n }\n const state = getRegistryState()\n const widgets = state.widgets.map((entry, moduleOrder) => ({ entry, moduleOrder })).filter(({ entry }) => !excludedSources.has(entry))\n const modules = state.modules.map((entry, moduleOrder) => ({ entry, moduleOrder })).filter(({ entry }) => !excludedSources.has(entry))\n const programmatic = [...state.sources.entries()].filter(([, contribution]) => !excludedSources.has(contribution))\n\n for (const { entry, moduleOrder } of widgets) {\n const source = sourceOf(entry.moduleId, `widgets/injection/${entry.widgetId}/widget.ts`, moduleOrder, 'widget')\n for (const definition of entry.definitions ?? []) {\n const existing = owners.get(definition.key)\n if (existing) {\n diagnostics.push({ code: 'duplicate-definition', key: definition.key, moduleId: entry.moduleId, widgetId: entry.widgetId, owner: existing.moduleId })\n continue\n }\n definitions.set(definition.key, definition)\n owners.set(definition.key, source)\n provenance.set(definition.key, markDefinitionProvenance(definition, source))\n }\n }\n for (const [sourceId, contribution] of programmatic) {\n const source = sourceOf(sourceId, `di:${sourceId}`, 0, 'programmatic')\n for (const definition of contribution.definitions.values()) {\n const existing = owners.get(definition.key)\n if (existing && existing.moduleId !== sourceId) {\n diagnostics.push({ code: 'duplicate-definition', key: definition.key, moduleId: sourceId, owner: existing.moduleId })\n continue\n }\n definitions.set(definition.key, definition)\n owners.set(definition.key, source)\n provenance.set(definition.key, markDefinitionProvenance(definition, source))\n }\n }\n\n const applyOverrides = (\n overrides: Readonly<Record<string, CalendarEventTypeDefinition | null>>,\n source: CalendarEventTypeProvenance,\n widgetId?: string,\n ): void => {\n for (const [key, override] of Object.entries(overrides)) {\n if (!definitions.has(key)) {\n if (override === null) {\n diagnostics.push({ code: 'unknown-override', key, moduleId: source.moduleId, widgetId })\n continue\n }\n diagnostics.push({ code: 'unknown-override', key, moduleId: source.moduleId, widgetId })\n }\n if (override === null) {\n tombstones.set(key, deepFreeze({ key, provenance: source }))\n } else {\n definitions.set(key, override)\n owners.set(key, source)\n provenance.set(key, markDefinitionProvenance(override, source))\n tombstones.delete(key)\n }\n }\n }\n for (const { entry, moduleOrder } of widgets) {\n applyOverrides(entry.overrides ?? {}, sourceOf(entry.moduleId, `widgets/injection/${entry.widgetId}/widget.ts`, moduleOrder, 'widget'), entry.widgetId)\n }\n for (const { entry, moduleOrder } of modules) {\n applyOverrides(entry.overrides.eventTypes ?? {}, sourceOf(entry.moduleId, 'modules.ts', moduleOrder, 'module'))\n }\n for (const [sourceId, contribution] of programmatic) {\n applyOverrides(Object.fromEntries(contribution.overrides), sourceOf(sourceId, `di:${sourceId}`, 0, 'programmatic'))\n }\n\n const applyPatches = (patches: readonly CalendarEventTypePatch[], source: CalendarEventTypeProvenance, widgetId?: string): CalendarEventTypeDiagnostic | null => {\n for (const patch of patches) {\n const key = patch.targetEventTypeKey\n const definition = definitions.get(key)\n if (!definition || tombstones.has(key)) {\n diagnostics.push({ code: 'unknown-patch', key, moduleId: source.moduleId, widgetId })\n continue\n }\n const propertyProvenance = { ...provenance.get(key) }\n try {\n const patched = applyPatch(definition, patch, propertyProvenance, source)\n definitions.set(key, patched)\n provenance.set(key, propertyProvenance)\n } catch {\n return { code: 'invalid-source', key, moduleId: source.moduleId, widgetId }\n }\n }\n return null\n }\n for (const { entry, moduleOrder } of widgets) {\n const failure = applyPatches(entry.patches ?? [], sourceOf(entry.moduleId, `widgets/injection/${entry.widgetId}/widget.ts`, moduleOrder, 'widget'), entry.widgetId)\n if (failure) return compose(new Set([...excludedSources, entry]), [...rejectedSources, failure])\n }\n for (const { entry, moduleOrder } of modules) {\n const failure = applyPatches(entry.overrides.patches ?? [], sourceOf(entry.moduleId, 'modules.ts', moduleOrder, 'module'))\n if (failure) return compose(new Set([...excludedSources, entry]), [...rejectedSources, failure])\n }\n for (const [sourceId, contribution] of programmatic) {\n const failure = applyPatches([...contribution.patches.values()], sourceOf(sourceId, `di:${sourceId}`, 0, 'programmatic'))\n if (failure) return compose(new Set([...excludedSources, contribution]), [...rejectedSources, failure])\n }\n\n const items = [...definitions.values()]\n .filter((definition) => !tombstones.has(definition.key))\n .map((definition) => deepFreeze({\n ...definition,\n provenance: Object.freeze({ ...(provenance.get(definition.key) ?? {}) }),\n historical: false,\n }))\n .sort((left, right) => left.behavior.order - right.behavior.order || left.key.localeCompare(right.key))\n return deepFreeze({ items, tombstones: [...tombstones.values()], diagnostics })\n}\n\nfunction archiveCurrentDefinitions(): void {\n const state = getRegistryState()\n for (const item of compose().items) {\n const { provenance: _provenance, historical: _historical, fallbackReason: _fallbackReason, ...definition } = item\n state.historicalDefinitions.set(item.key, deepFreeze(definition))\n }\n}\n\nexport function registerWidgetCalendarEventTypeContributions(entries: readonly CalendarEventTypeWidgetContribution[]): void {\n const state = getRegistryState()\n const diagnostics: CalendarEventTypeDiagnostic[] = []\n const parsed: ParsedWidgetContribution[] = []\n for (const entry of entries) {\n const result = widgetContributionSchema.safeParse(entry)\n if (result.success) parsed.push(result.data)\n else diagnostics.push({ code: 'invalid-source', moduleId: entry.moduleId, widgetId: entry.widgetId })\n }\n const moduleOrder = new Map<string, number>()\n entries.forEach((entry) => { if (!moduleOrder.has(entry.moduleId)) moduleOrder.set(entry.moduleId, moduleOrder.size) })\n parsed.sort((left, right) => (moduleOrder.get(left.moduleId) ?? 0) - (moduleOrder.get(right.moduleId) ?? 0)\n || (left.priority ?? 0) - (right.priority ?? 0) || left.widgetId.localeCompare(right.widgetId))\n const moduleDiagnostics = state.diagnostics.filter((diagnostic) => !diagnostic.widgetId)\n if (JSON.stringify(state.widgets) === JSON.stringify(parsed)\n && JSON.stringify(state.diagnostics.filter((diagnostic) => diagnostic.widgetId)) === JSON.stringify(diagnostics)) return\n archiveCurrentDefinitions()\n state.widgets = deepFreeze(parsed)\n state.diagnostics = deepFreeze([...diagnostics, ...moduleDiagnostics])\n state.version += 1\n}\n\nexport function registerCalendarModuleOverrides(entries: readonly CalendarModuleOverrideEntry[]): void {\n const state = getRegistryState()\n const diagnostics: CalendarEventTypeDiagnostic[] = []\n const parsed: CalendarModuleOverrideEntry[] = []\n for (const entry of entries) {\n const result = moduleOverrideEntrySchema.safeParse(entry)\n if (result.success) parsed.push(result.data)\n else diagnostics.push({ code: 'invalid-source', moduleId: entry.moduleId })\n }\n const widgetDiagnostics = state.diagnostics.filter((diagnostic) => diagnostic.widgetId)\n if (JSON.stringify(state.modules) === JSON.stringify(parsed)\n && JSON.stringify(state.diagnostics.filter((diagnostic) => !diagnostic.widgetId)) === JSON.stringify(diagnostics)) return\n archiveCurrentDefinitions()\n state.modules = deepFreeze(parsed)\n state.diagnostics = deepFreeze([...widgetDiagnostics, ...diagnostics])\n state.version += 1\n}\n\nexport type CalendarEventTypeRegistrySnapshot = Readonly<{\n version: number\n items: readonly EffectiveCalendarEventType[]\n tombstones: readonly CalendarEventTypeTombstone[]\n diagnostics: readonly CalendarEventTypeDiagnostic[]\n}>\n\nexport interface CalendarEventTypeRegistry {\n upsert(sourceId: string, definition: CalendarEventTypeDefinition): void\n replace(sourceId: string, key: string, definition: CalendarEventTypeDefinition | null): void\n patch(sourceId: string, patch: CalendarEventTypePatch): void\n remove(sourceId: string, key: string): void\n removeSource(sourceId: string): void\n snapshot(): CalendarEventTypeRegistrySnapshot\n}\n\nfunction validatedSourceId(sourceId: string): string {\n return z.string().trim().min(1).max(100).parse(sourceId)\n}\n\nfunction baseOwnerOf(key: string): string | undefined {\n if (calendarEventTypes.some((definition) => definition.key === key)) return 'customers'\n const invalidSources = compose().diagnostics.filter((diagnostic) => diagnostic.code === 'invalid-source')\n for (const widget of getRegistryState().widgets) {\n if (invalidSources.some((diagnostic) => diagnostic.moduleId === widget.moduleId && diagnostic.widgetId === widget.widgetId)) continue\n if (widget.definitions?.some((definition) => definition.key === key)) return widget.moduleId\n }\n for (const [sourceId, contribution] of getRegistryState().sources) {\n if (invalidSources.some((diagnostic) => diagnostic.moduleId === sourceId && !diagnostic.widgetId)) continue\n if (contribution.definitions.has(key)) return sourceId\n }\n return compose().items.find((definition) => definition.key === key)?.provenance.key?.moduleId\n}\n\nexport function createCalendarEventTypeRegistry(): CalendarEventTypeRegistry {\n return {\n upsert(sourceId, definition) {\n const id = validatedSourceId(sourceId)\n const nextDefinition = copyDefinition(definition)\n const owner = baseOwnerOf(nextDefinition.key)\n if (owner && owner !== id) {\n throw new Error(`[internal] Calendar event type \"${nextDefinition.key}\" is owned by \"${owner}\"`)\n }\n const current = programmaticSource(id)\n if (JSON.stringify(current.definitions.get(nextDefinition.key)) === JSON.stringify(nextDefinition)) return\n replaceProgrammaticSource(id, { ...current, definitions: new Map(current.definitions).set(nextDefinition.key, nextDefinition) })\n },\n replace(sourceId, key, definition) {\n const id = validatedSourceId(sourceId)\n const parsedKey = calendarEventTypeKeySchema.parse(key)\n const nextDefinition = definition === null ? null : copyDefinition(definition)\n if (nextDefinition && nextDefinition.key !== parsedKey) throw new Error('[internal] Replacement key must match target key')\n const current = programmaticSource(id)\n if (JSON.stringify(current.overrides.get(parsedKey)) === JSON.stringify(nextDefinition)) return\n replaceProgrammaticSource(id, { ...current, overrides: new Map(current.overrides).set(parsedKey, nextDefinition) })\n },\n patch(sourceId, patch) {\n const id = validatedSourceId(sourceId)\n const nextPatch = copyPatch(patch)\n const current = programmaticSource(id)\n if (JSON.stringify(current.patches.get(nextPatch.targetEventTypeKey)) === JSON.stringify(nextPatch)) return\n replaceProgrammaticSource(id, { ...current, patches: new Map(current.patches).set(nextPatch.targetEventTypeKey, nextPatch) })\n },\n remove(sourceId, key) {\n const id = validatedSourceId(sourceId)\n const parsedKey = calendarEventTypeKeySchema.parse(key)\n const current = getRegistryState().sources.get(id)\n if (!current || !(current.definitions.has(parsedKey) || current.overrides.has(parsedKey) || current.patches.has(parsedKey))) return\n const next = { definitions: new Map(current.definitions), overrides: new Map(current.overrides), patches: new Map(current.patches) }\n next.definitions.delete(parsedKey)\n next.overrides.delete(parsedKey)\n next.patches.delete(parsedKey)\n replaceProgrammaticSource(id, next)\n },\n removeSource(sourceId) {\n const id = validatedSourceId(sourceId)\n const state = getRegistryState()\n if (!state.sources.has(id)) return\n archiveCurrentDefinitions()\n state.sources.delete(id)\n state.version += 1\n },\n snapshot() {\n const state = getRegistryState()\n return deepFreeze({ version: state.version, ...compose() })\n },\n }\n}\n\nexport function getCalendarEventTypeRegistryVersion(): number {\n return getRegistryState().version\n}\n\nexport function getCalendarEventTypes(): readonly EffectiveCalendarEventType[] {\n return compose().items\n}\n\nexport function resolveCalendarEventTypes(): readonly EffectiveCalendarEventType[] {\n return getCalendarEventTypes()\n}\n\nexport function getCalendarEventTypeTombstones(): readonly CalendarEventTypeTombstone[] {\n return compose().tombstones\n}\n\nexport function getCalendarEventTypeDiagnostics(): readonly CalendarEventTypeDiagnostic[] {\n return compose().diagnostics\n}\n\nexport function resolveCalendarEventType(\n rawKey: string,\n options: { includeHistorical?: boolean } = {},\n): EffectiveCalendarEventType | undefined {\n const parsedKey = calendarEventTypeKeySchema.safeParse(rawKey.trim().toLowerCase())\n if (!parsedKey.success) return undefined\n const key = parsedKey.data\n const current = compose()\n const resolved = current.items.find((item) => item.key === key)\n if (resolved || !options.includeHistorical) return resolved\n\n const stored = getRegistryState().historicalDefinitions.get(key)\n const reason: CalendarEventTypeHistoricalFallback['reason'] = current.tombstones.some((entry) => entry.key === key)\n ? 'tombstoned'\n : stored\n ? 'module-unavailable'\n : 'unknown'\n const definition = stored ?? {\n ...calendarEventTypes[0],\n key,\n label: rawKey,\n labelKey: undefined,\n behavior: { ...calendarEventTypes[0]!.behavior, selectable: false },\n }\n const fallbackSource = Object.freeze({ moduleId: 'customers', sourcePath: 'calendar-event-types.ts', moduleOrder: 0, phase: 'fallback' as const })\n const historicalDefinition = calendarEventTypeDefinitionSchema.parse({\n ...definition,\n behavior: { ...definition.behavior, selectable: false },\n })\n return deepFreeze({\n ...historicalDefinition,\n provenance: Object.fromEntries(allPropertyPaths(historicalDefinition).map((path) => [path, fallbackSource])),\n historical: true,\n fallbackReason: reason,\n })\n}\n\nexport function resetCalendarEventTypeRegistryForTests(): void {\n const state = getRegistryState()\n state.widgets = Object.freeze([])\n state.modules = Object.freeze([])\n state.sources.clear()\n state.historicalDefinitions.clear()\n state.version = 0\n state.diagnostics = Object.freeze([])\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -1,3 +1,4 @@
1
+ import { isDeepStrictEqual } from "node:util";
1
2
  import { registerCommand } from "@open-mercato/shared/lib/commands";
2
3
  import { buildChanges } from "@open-mercato/shared/lib/commands/helpers";
3
4
  import { CrudHttpError, notFound } from "@open-mercato/shared/lib/crud/errors";
@@ -20,7 +21,16 @@ import {
20
21
  } from "./shared.js";
21
22
  import { resolveRedoSnapshot } from "@open-mercato/shared/lib/commands/redo";
22
23
  import { createLogger } from "@open-mercato/shared/lib/logger";
24
+ import { enforceCommandOptimisticLockWithGuards } from "@open-mercato/shared/lib/crud/optimistic-lock-command";
25
+ import { calendarEventTypeBehaviorSchema } from "../calendar-event-types.js";
23
26
  const logger = createLogger("customers");
27
+ const nullableCalendarEventTypeBehaviorSchema = calendarEventTypeBehaviorSchema.nullable();
28
+ function calendarEventTypeBehaviorsEqual(left, right) {
29
+ const parsedLeft = nullableCalendarEventTypeBehaviorSchema.safeParse(left);
30
+ const parsedRight = nullableCalendarEventTypeBehaviorSchema.safeParse(right);
31
+ if (parsedLeft.success && parsedRight.success) return isDeepStrictEqual(parsedLeft.data, parsedRight.data);
32
+ return isDeepStrictEqual(left, right);
33
+ }
24
34
  function buildRoleTypeInUseError(usageCount, ownerAssignments, relationshipAssignments) {
25
35
  return new CrudHttpError(409, {
26
36
  code: "role_type_in_use",
@@ -57,9 +67,22 @@ function toSnapshot(entry) {
57
67
  normalizedValue: entry.normalizedValue,
58
68
  label: entry.label,
59
69
  color: entry.color ?? null,
60
- icon: entry.icon ?? null
70
+ icon: entry.icon ?? null,
71
+ behavior: entry.activityTypeBehavior ?? null
61
72
  };
62
73
  }
74
+ function buildDictionaryChanges(before, after, keys) {
75
+ const scalarKeys = keys.filter((key) => key !== "behavior");
76
+ const changes = buildChanges(
77
+ before,
78
+ after,
79
+ scalarKeys
80
+ );
81
+ if (keys.includes("behavior") && !calendarEventTypeBehaviorsEqual(before.behavior, after.behavior)) {
82
+ changes.behavior = { from: before.behavior, to: after.behavior };
83
+ }
84
+ return changes;
85
+ }
63
86
  async function loadSnapshot(em, id, scope) {
64
87
  const entry = await findOneWithDecryption(em, CustomerDictionaryEntry, { id }, {}, scope);
65
88
  return entry ? toSnapshot(entry) : null;
@@ -73,6 +96,7 @@ function applySnapshot(entry, snapshot) {
73
96
  entry.label = snapshot.label;
74
97
  entry.color = snapshot.color;
75
98
  entry.icon = snapshot.icon;
99
+ entry.activityTypeBehavior = snapshot.behavior;
76
100
  }
77
101
  async function invalidateCache(ctx, snapshot) {
78
102
  if (!snapshot) return;
@@ -101,6 +125,7 @@ const createDictionaryEntryCommand = {
101
125
  const label = parsed.label?.trim() || value.value;
102
126
  const color = sanitizeColor(parsed.color);
103
127
  const icon = sanitizeIcon(parsed.icon);
128
+ const behavior = parsed.behavior;
104
129
  const existing = await findOneWithDecryption(
105
130
  em,
106
131
  CustomerDictionaryEntry,
@@ -117,6 +142,12 @@ const createDictionaryEntryCommand = {
117
142
  }
118
143
  );
119
144
  if (existing) {
145
+ await enforceCommandOptimisticLockWithGuards(ctx.container, {
146
+ resourceKind: "customers.dictionary_entry",
147
+ resourceId: existing.id,
148
+ current: existing.updatedAt,
149
+ request: ctx.request ?? null
150
+ });
120
151
  const before = toSnapshot(existing);
121
152
  let changed = false;
122
153
  if (parsed.label !== void 0 && existing.label !== label) {
@@ -131,9 +162,14 @@ const createDictionaryEntryCommand = {
131
162
  existing.icon = icon ?? null;
132
163
  changed = true;
133
164
  }
165
+ if (behavior !== void 0 && !isDeepStrictEqual(existing.activityTypeBehavior ?? null, behavior)) {
166
+ existing.activityTypeBehavior = behavior;
167
+ changed = true;
168
+ }
134
169
  if (changed) {
135
170
  existing.updatedAt = /* @__PURE__ */ new Date();
136
171
  await em.flush();
172
+ await invalidateCache(ctx, toSnapshot(existing));
137
173
  return {
138
174
  entryId: existing.id,
139
175
  tenantId: parsed.tenantId,
@@ -158,10 +194,12 @@ const createDictionaryEntryCommand = {
158
194
  normalizedValue: value.normalized,
159
195
  label,
160
196
  color: color ?? null,
161
- icon: icon ?? null
197
+ icon: icon ?? null,
198
+ activityTypeBehavior: behavior ?? null
162
199
  });
163
200
  em.persist(entry);
164
201
  await em.flush();
202
+ await invalidateCache(ctx, toSnapshot(entry));
165
203
  return {
166
204
  entryId: entry.id,
167
205
  tenantId: parsed.tenantId,
@@ -196,10 +234,10 @@ const createDictionaryEntryCommand = {
196
234
  if (result.mode === "updated") {
197
235
  const before = result.before ?? null;
198
236
  if (!before) return null;
199
- const changes = buildChanges(
237
+ const changes = buildDictionaryChanges(
200
238
  before,
201
239
  after,
202
- ["label", "color", "icon"]
240
+ ["label", "color", "icon", "behavior"]
203
241
  );
204
242
  if (!changes || Object.keys(changes).length === 0) return null;
205
243
  return {
@@ -263,7 +301,8 @@ const createDictionaryEntryCommand = {
263
301
  normalizedValue: before.normalizedValue,
264
302
  label: before.label,
265
303
  color: before.color,
266
- icon: before.icon
304
+ icon: before.icon,
305
+ activityTypeBehavior: before.behavior
267
306
  });
268
307
  em.persist(entry);
269
308
  } else {
@@ -299,7 +338,8 @@ const createDictionaryEntryCommand = {
299
338
  normalizedValue: after.normalizedValue,
300
339
  label: after.label,
301
340
  color: after.color,
302
- icon: after.icon
341
+ icon: after.icon,
342
+ activityTypeBehavior: after.behavior
303
343
  });
304
344
  em.persist(entry);
305
345
  } else {
@@ -348,6 +388,12 @@ const updateDictionaryEntryCommand = {
348
388
  if (!entry || entry.organizationId !== parsed.organizationId || entry.tenantId !== parsed.tenantId || entry.kind !== parsed.kind) {
349
389
  throw notFound("Dictionary entry not found");
350
390
  }
391
+ await enforceCommandOptimisticLockWithGuards(ctx.container, {
392
+ resourceKind: "customers.dictionary_entry",
393
+ resourceId: entry.id,
394
+ current: entry.updatedAt,
395
+ request: ctx.request ?? null
396
+ });
351
397
  let changed = false;
352
398
  if (parsed.value !== void 0) {
353
399
  const value = normalizeValue(parsed.value);
@@ -414,9 +460,14 @@ const updateDictionaryEntryCommand = {
414
460
  changed = true;
415
461
  }
416
462
  }
463
+ if (parsed.behavior !== void 0 && !isDeepStrictEqual(entry.activityTypeBehavior ?? null, parsed.behavior)) {
464
+ entry.activityTypeBehavior = parsed.behavior;
465
+ changed = true;
466
+ }
417
467
  if (changed) {
418
468
  entry.updatedAt = /* @__PURE__ */ new Date();
419
469
  await em.flush();
470
+ await invalidateCache(ctx, toSnapshot(entry));
420
471
  }
421
472
  return {
422
473
  entryId: entry.id,
@@ -436,10 +487,10 @@ const updateDictionaryEntryCommand = {
436
487
  const before = snapshots.before;
437
488
  const after = snapshots.after;
438
489
  if (!before || !after || !result.changed) return null;
439
- const changes = buildChanges(
490
+ const changes = buildDictionaryChanges(
440
491
  before,
441
492
  after,
442
- ["value", "label", "color", "icon"]
493
+ ["value", "label", "color", "icon", "behavior"]
443
494
  );
444
495
  if (!changes || Object.keys(changes).length === 0) return null;
445
496
  const { translate } = await resolveTranslations();
@@ -481,7 +532,8 @@ const updateDictionaryEntryCommand = {
481
532
  normalizedValue: before.normalizedValue,
482
533
  label: before.label,
483
534
  color: before.color,
484
- icon: before.icon
535
+ icon: before.icon,
536
+ activityTypeBehavior: before.behavior
485
537
  });
486
538
  em.persist(entry);
487
539
  } else {
@@ -522,6 +574,12 @@ const deleteDictionaryEntryCommand = {
522
574
  if (!entry || entry.organizationId !== parsed.organizationId || entry.tenantId !== parsed.tenantId || entry.kind !== parsed.kind) {
523
575
  throw notFound("Dictionary entry not found");
524
576
  }
577
+ await enforceCommandOptimisticLockWithGuards(ctx.container, {
578
+ resourceKind: "customers.dictionary_entry",
579
+ resourceId: entry.id,
580
+ current: entry.updatedAt,
581
+ request: ctx.request ?? null
582
+ });
525
583
  if (entry.kind === "person_company_role") {
526
584
  const usage = await loadRoleTypeUsage(em, {
527
585
  tenantId: entry.tenantId,
@@ -538,6 +596,7 @@ const deleteDictionaryEntryCommand = {
538
596
  }
539
597
  em.remove(entry);
540
598
  await em.flush();
599
+ await invalidateCache(ctx, toSnapshot(entry));
541
600
  return { entryId: entry.id };
542
601
  },
543
602
  buildLog: async ({ snapshots }) => {
@@ -580,7 +639,8 @@ const deleteDictionaryEntryCommand = {
580
639
  normalizedValue: before.normalizedValue,
581
640
  label: before.label,
582
641
  color: before.color,
583
- icon: before.icon
642
+ icon: before.icon,
643
+ activityTypeBehavior: before.behavior
584
644
  });
585
645
  em.persist(entry);
586
646
  } else {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/customers/commands/dictionaries.ts"],
4
- "sourcesContent": ["import { registerCommand, type CommandHandler } from '@open-mercato/shared/lib/commands'\nimport type { CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport { buildChanges } from '@open-mercato/shared/lib/commands/helpers'\nimport { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { invalidateDictionaryCache } from '../api/dictionaries/cache'\nimport type { CacheStrategy } from '@open-mercato/cache'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { loadRoleTypeUsage } from '../lib/roleTypeUsage'\nimport {\n customerDictionaryEntryCreateSchema,\n customerDictionaryEntryDeleteSchema,\n customerDictionaryEntryUpdateSchema,\n type CustomerDictionaryEntryCreateInput,\n type CustomerDictionaryEntryDeleteInput,\n type CustomerDictionaryEntryUpdateInput,\n} from '../data/validators'\nimport { CustomerDictionaryEntry } from '../data/entities'\nimport {\n ensureOrganizationScope,\n ensureTenantScope,\n extractUndoPayload,\n normalizeDictionaryColor,\n normalizeDictionaryIcon,\n} from './shared'\nimport { resolveRedoSnapshot } from '@open-mercato/shared/lib/commands/redo'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('customers')\n\ntype CustomerDictionaryEntrySnapshot = {\n id: string\n tenantId: string\n organizationId: string\n kind: string\n value: string\n normalizedValue: string\n label: string\n color: string | null\n icon: string | null\n}\n\ntype CustomerDictionaryEntryUndoPayload = {\n before?: CustomerDictionaryEntrySnapshot | null\n after?: CustomerDictionaryEntrySnapshot | null\n}\n\nfunction buildRoleTypeInUseError(usageCount: number, ownerAssignments: number, relationshipAssignments: number) {\n return new CrudHttpError(409, {\n code: 'role_type_in_use',\n error: 'Role type is in use',\n usageCount,\n ownerAssignments,\n relationshipAssignments,\n })\n}\n\nfunction normalizeValue(input: string): { value: string; normalized: string } {\n const trimmed = input.trim()\n if (!trimmed) {\n throw new CrudHttpError(400, { error: 'Dictionary entry value is required' })\n }\n return { value: trimmed, normalized: trimmed.toLowerCase() }\n}\n\nfunction sanitizeColor(input: string | null | undefined): string | null | undefined {\n if (input === undefined) return undefined\n if (input === null) return null\n return normalizeDictionaryColor(input)\n}\n\nfunction sanitizeIcon(input: string | null | undefined): string | null | undefined {\n if (input === undefined) return undefined\n if (input === null) return null\n return normalizeDictionaryIcon(input)\n}\n\nfunction toSnapshot(entry: CustomerDictionaryEntry): CustomerDictionaryEntrySnapshot {\n return {\n id: entry.id,\n tenantId: entry.tenantId,\n organizationId: entry.organizationId,\n kind: entry.kind,\n value: entry.value,\n normalizedValue: entry.normalizedValue,\n label: entry.label,\n color: entry.color ?? null,\n icon: entry.icon ?? null,\n }\n}\n\nasync function loadSnapshot(\n em: EntityManager,\n id: string,\n scope: { tenantId: string | null; organizationId: string | null },\n): Promise<CustomerDictionaryEntrySnapshot | null> {\n const entry = await findOneWithDecryption(em, CustomerDictionaryEntry, { id }, {}, scope)\n return entry ? toSnapshot(entry) : null\n}\n\nfunction applySnapshot(entry: CustomerDictionaryEntry, snapshot: CustomerDictionaryEntrySnapshot): void {\n entry.tenantId = snapshot.tenantId\n entry.organizationId = snapshot.organizationId\n entry.kind = snapshot.kind\n entry.value = snapshot.value\n entry.normalizedValue = snapshot.normalizedValue\n entry.label = snapshot.label\n entry.color = snapshot.color\n entry.icon = snapshot.icon\n}\n\nasync function invalidateCache(\n ctx: CommandRuntimeContext,\n snapshot: CustomerDictionaryEntrySnapshot | null | undefined\n) {\n if (!snapshot) return\n let cache: CacheStrategy | undefined\n try {\n cache = (ctx.container.resolve('cache') as CacheStrategy)\n } catch (err) {\n logger.warn('cache resolve failed; skipping invalidation', { component: 'commands.dictionaries', err })\n cache = undefined\n }\n if (!cache) return\n await invalidateDictionaryCache(cache, {\n tenantId: snapshot.tenantId,\n mappedKind: snapshot.kind,\n organizationIds: [snapshot.organizationId],\n })\n}\n\ntype CreateResult = {\n entryId: string\n tenantId: string\n organizationId: string\n mode: 'created' | 'updated' | 'unchanged'\n before?: CustomerDictionaryEntrySnapshot | null\n}\n\nconst createDictionaryEntryCommand: CommandHandler<CustomerDictionaryEntryCreateInput, CreateResult> = {\n id: 'customers.dictionaryEntries.create',\n async execute(rawInput, ctx) {\n const parsed = customerDictionaryEntryCreateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const value = normalizeValue(parsed.value)\n const label = parsed.label?.trim() || value.value\n const color = sanitizeColor(parsed.color)\n const icon = sanitizeIcon(parsed.icon)\n\n const existing = await findOneWithDecryption(\n em,\n CustomerDictionaryEntry,\n {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n kind: parsed.kind,\n normalizedValue: value.normalized,\n },\n {},\n {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n },\n )\n\n if (existing) {\n const before = toSnapshot(existing)\n let changed = false\n\n if (parsed.label !== undefined && existing.label !== label) {\n existing.label = label\n changed = true\n }\n if (color !== undefined && existing.color !== color) {\n existing.color = color ?? null\n changed = true\n }\n if (icon !== undefined && existing.icon !== icon) {\n existing.icon = icon ?? null\n changed = true\n }\n\n if (changed) {\n existing.updatedAt = new Date()\n await em.flush()\n return {\n entryId: existing.id,\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n mode: 'updated',\n before,\n }\n }\n\n return {\n entryId: existing.id,\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n mode: 'unchanged',\n before,\n }\n }\n\n const entry = em.create(CustomerDictionaryEntry, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n kind: parsed.kind,\n value: value.value,\n normalizedValue: value.normalized,\n label,\n color: color ?? null,\n icon: icon ?? null,\n })\n em.persist(entry)\n await em.flush()\n\n return {\n entryId: entry.id,\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n mode: 'created',\n }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadSnapshot(em, result.entryId, {\n tenantId: result.tenantId,\n organizationId: result.organizationId,\n })\n },\n buildLog: async ({ result, snapshots }) => {\n const after = snapshots.after as CustomerDictionaryEntrySnapshot | undefined\n if (!after) return null\n const { translate } = await resolveTranslations()\n\n if (result.mode === 'created') {\n return {\n actionLabel: translate('customers.audit.dictionaryEntries.create', 'Add dictionary entry'),\n resourceKind: 'customers.dictionary_entry',\n resourceId: after.id,\n tenantId: after.tenantId,\n organizationId: after.organizationId,\n snapshotAfter: after,\n payload: {\n undo: { after } satisfies CustomerDictionaryEntryUndoPayload,\n },\n }\n }\n\n if (result.mode === 'updated') {\n const before = result.before ?? null\n if (!before) return null\n const changes = buildChanges(\n before as unknown as Record<string, unknown>,\n after as unknown as Record<string, unknown>,\n ['label', 'color', 'icon']\n )\n if (!changes || Object.keys(changes).length === 0) return null\n return {\n actionLabel: translate('customers.audit.dictionaryEntries.update', 'Update dictionary entry'),\n resourceKind: 'customers.dictionary_entry',\n resourceId: after.id,\n tenantId: after.tenantId,\n organizationId: after.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes,\n payload: {\n undo: { before, after } satisfies CustomerDictionaryEntryUndoPayload,\n },\n }\n }\n\n return null\n },\n undo: async ({ logEntry, ctx }) => {\n const undo = extractUndoPayload<CustomerDictionaryEntryUndoPayload>(logEntry)\n if (!undo) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n\n const after =\n undo.after ??\n (logEntry?.snapshotAfter as CustomerDictionaryEntrySnapshot | null | undefined) ??\n null\n\n if (after && !undo.before) {\n ensureTenantScope(ctx, after.tenantId)\n ensureOrganizationScope(ctx, after.organizationId)\n const entry = await findOneWithDecryption(\n em,\n CustomerDictionaryEntry,\n { id: after.id },\n {},\n { tenantId: after.tenantId, organizationId: after.organizationId },\n )\n if (entry) {\n await em.remove(entry).flush()\n await invalidateCache(ctx, after)\n return\n }\n await em.nativeDelete(CustomerDictionaryEntry, { id: after.id })\n await invalidateCache(ctx, after)\n return\n }\n\n const before =\n undo.before ??\n (logEntry?.snapshotBefore as CustomerDictionaryEntrySnapshot | null | undefined) ??\n null\n\n if (before) {\n ensureTenantScope(ctx, before.tenantId)\n ensureOrganizationScope(ctx, before.organizationId)\n let entry = await findOneWithDecryption(\n em,\n CustomerDictionaryEntry,\n { id: before.id },\n {},\n { tenantId: before.tenantId, organizationId: before.organizationId },\n )\n if (!entry) {\n entry = em.create(CustomerDictionaryEntry, {\n id: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n kind: before.kind,\n value: before.value,\n normalizedValue: before.normalizedValue,\n label: before.label,\n color: before.color,\n icon: before.icon,\n })\n em.persist(entry)\n } else {\n applySnapshot(entry, before)\n }\n await em.flush()\n await invalidateCache(ctx, before)\n }\n },\n redo: async ({ logEntry, ctx }) => {\n const undo = extractUndoPayload<CustomerDictionaryEntryUndoPayload>(logEntry)\n const after = resolveRedoSnapshot<CustomerDictionaryEntrySnapshot>(logEntry)\n if (!after) {\n throw new CrudHttpError(400, { error: '[internal] redo snapshot unavailable for dictionary entry create' })\n }\n ensureTenantScope(ctx, after.tenantId)\n ensureOrganizationScope(ctx, after.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let entry = await findOneWithDecryption(\n em,\n CustomerDictionaryEntry,\n { id: after.id },\n {},\n { tenantId: after.tenantId, organizationId: after.organizationId },\n )\n if (!entry) {\n entry = em.create(CustomerDictionaryEntry, {\n id: after.id,\n tenantId: after.tenantId,\n organizationId: after.organizationId,\n kind: after.kind,\n value: after.value,\n normalizedValue: after.normalizedValue,\n label: after.label,\n color: after.color,\n icon: after.icon,\n })\n em.persist(entry)\n } else {\n applySnapshot(entry, after)\n entry.updatedAt = new Date()\n }\n await em.flush()\n await invalidateCache(ctx, after)\n\n return {\n entryId: after.id,\n tenantId: after.tenantId,\n organizationId: after.organizationId,\n mode: undo?.before ? 'updated' : 'created',\n ...(undo?.before ? { before: undo.before } : {}),\n } satisfies CreateResult\n },\n}\n\ntype UpdateResult = {\n entryId: string\n tenantId: string\n organizationId: string\n changed: boolean\n}\n\nconst updateDictionaryEntryCommand: CommandHandler<CustomerDictionaryEntryUpdateInput, UpdateResult> = {\n id: 'customers.dictionaryEntries.update',\n async prepare(rawInput, ctx) {\n const parsed = customerDictionaryEntryUpdateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadSnapshot(em, parsed.id, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n })\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const parsed = customerDictionaryEntryUpdateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entry = await findOneWithDecryption(\n em,\n CustomerDictionaryEntry,\n { id: parsed.id },\n {},\n {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n },\n )\n if (!entry || entry.organizationId !== parsed.organizationId || entry.tenantId !== parsed.tenantId || entry.kind !== parsed.kind) {\n throw notFound('Dictionary entry not found')\n }\n\n let changed = false\n\n if (parsed.value !== undefined) {\n const value = normalizeValue(parsed.value)\n if (value.normalized !== entry.normalizedValue) {\n if (entry.kind === 'person_company_role') {\n const usage = await loadRoleTypeUsage(em, {\n tenantId: parsed.tenantId,\n organizationId: entry.organizationId,\n value: entry.value,\n })\n if (usage.total > 0) {\n throw buildRoleTypeInUseError(\n usage.total,\n usage.ownerAssignments,\n usage.relationshipAssignments,\n )\n }\n }\n const duplicate = await findOneWithDecryption(\n em,\n CustomerDictionaryEntry,\n {\n id: { $ne: entry.id },\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n kind: parsed.kind,\n normalizedValue: value.normalized,\n },\n {},\n {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n },\n )\n if (duplicate) {\n throw new CrudHttpError(409, { error: 'An entry with this value already exists' })\n }\n entry.value = value.value\n entry.normalizedValue = value.normalized\n if (parsed.label === undefined) {\n entry.label = value.value\n }\n changed = true\n }\n }\n\n if (parsed.label !== undefined) {\n const label = parsed.label.trim() || entry.value\n if (entry.label !== label) {\n entry.label = label\n changed = true\n }\n }\n\n if (parsed.color !== undefined) {\n const color = sanitizeColor(parsed.color)\n if (entry.color !== (color ?? null)) {\n entry.color = color ?? null\n changed = true\n }\n }\n\n if (parsed.icon !== undefined) {\n const icon = sanitizeIcon(parsed.icon)\n if (entry.icon !== (icon ?? null)) {\n entry.icon = icon ?? null\n changed = true\n }\n }\n\n if (changed) {\n entry.updatedAt = new Date()\n await em.flush()\n }\n\n return {\n entryId: entry.id,\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n changed,\n }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadSnapshot(em, result.entryId, {\n tenantId: result.tenantId,\n organizationId: result.organizationId,\n })\n },\n buildLog: async ({ snapshots, result }) => {\n const before = snapshots.before as CustomerDictionaryEntrySnapshot | undefined\n const after = snapshots.after as CustomerDictionaryEntrySnapshot | undefined\n if (!before || !after || !result.changed) return null\n const changes = buildChanges(\n before as unknown as Record<string, unknown>,\n after as unknown as Record<string, unknown>,\n ['value', 'label', 'color', 'icon']\n )\n if (!changes || Object.keys(changes).length === 0) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('customers.audit.dictionaryEntries.update', 'Update dictionary entry'),\n resourceKind: 'customers.dictionary_entry',\n resourceId: after.id,\n tenantId: after.tenantId,\n organizationId: after.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes,\n payload: {\n undo: { before, after } satisfies CustomerDictionaryEntryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const undo = extractUndoPayload<CustomerDictionaryEntryUndoPayload>(logEntry)\n const before =\n undo?.before ??\n (logEntry?.snapshotBefore as CustomerDictionaryEntrySnapshot | null | undefined) ??\n null\n if (!before) return\n ensureTenantScope(ctx, before.tenantId)\n ensureOrganizationScope(ctx, before.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let entry = await findOneWithDecryption(\n em,\n CustomerDictionaryEntry,\n { id: before.id },\n {},\n { tenantId: before.tenantId, organizationId: before.organizationId },\n )\n if (!entry) {\n entry = em.create(CustomerDictionaryEntry, {\n id: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n kind: before.kind,\n value: before.value,\n normalizedValue: before.normalizedValue,\n label: before.label,\n color: before.color,\n icon: before.icon,\n })\n em.persist(entry)\n } else {\n applySnapshot(entry, before)\n }\n await em.flush()\n await invalidateCache(ctx, before)\n },\n}\n\nconst deleteDictionaryEntryCommand: CommandHandler<CustomerDictionaryEntryDeleteInput, { entryId: string }> = {\n id: 'customers.dictionaryEntries.delete',\n async prepare(rawInput, ctx) {\n const parsed = customerDictionaryEntryDeleteSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadSnapshot(em, parsed.id, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n })\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const parsed = customerDictionaryEntryDeleteSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entry = await findOneWithDecryption(\n em,\n CustomerDictionaryEntry,\n { id: parsed.id },\n {},\n {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n },\n )\n if (!entry || entry.organizationId !== parsed.organizationId || entry.tenantId !== parsed.tenantId || entry.kind !== parsed.kind) {\n throw notFound('Dictionary entry not found')\n }\n if (entry.kind === 'person_company_role') {\n const usage = await loadRoleTypeUsage(em, {\n tenantId: entry.tenantId,\n organizationId: entry.organizationId,\n value: entry.value,\n })\n if (usage.total > 0) {\n throw buildRoleTypeInUseError(\n usage.total,\n usage.ownerAssignments,\n usage.relationshipAssignments,\n )\n }\n }\n em.remove(entry)\n await em.flush()\n return { entryId: entry.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as CustomerDictionaryEntrySnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('customers.audit.dictionaryEntries.delete', 'Delete dictionary entry'),\n resourceKind: 'customers.dictionary_entry',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: { before } satisfies CustomerDictionaryEntryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const undo = extractUndoPayload<CustomerDictionaryEntryUndoPayload>(logEntry)\n const before =\n undo?.before ??\n (logEntry?.snapshotBefore as CustomerDictionaryEntrySnapshot | null | undefined) ??\n null\n if (!before) return\n ensureTenantScope(ctx, before.tenantId)\n ensureOrganizationScope(ctx, before.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let entry = await findOneWithDecryption(\n em,\n CustomerDictionaryEntry,\n { id: before.id },\n {},\n { tenantId: before.tenantId, organizationId: before.organizationId },\n )\n if (!entry) {\n entry = em.create(CustomerDictionaryEntry, {\n id: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n kind: before.kind,\n value: before.value,\n normalizedValue: before.normalizedValue,\n label: before.label,\n color: before.color,\n icon: before.icon,\n })\n em.persist(entry)\n } else {\n applySnapshot(entry, before)\n }\n await em.flush()\n await invalidateCache(ctx, before)\n },\n}\n\nregisterCommand(createDictionaryEntryCommand)\nregisterCommand(updateDictionaryEntryCommand)\nregisterCommand(deleteDictionaryEntryCommand)\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { isDeepStrictEqual } from 'node:util'\nimport { registerCommand, type CommandHandler } from '@open-mercato/shared/lib/commands'\nimport type { CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport { buildChanges } from '@open-mercato/shared/lib/commands/helpers'\nimport { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { invalidateDictionaryCache } from '../api/dictionaries/cache'\nimport type { CacheStrategy } from '@open-mercato/cache'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { loadRoleTypeUsage } from '../lib/roleTypeUsage'\nimport {\n customerDictionaryEntryCreateSchema,\n customerDictionaryEntryDeleteSchema,\n customerDictionaryEntryUpdateSchema,\n type CustomerDictionaryEntryCreateInput,\n type CustomerDictionaryEntryDeleteInput,\n type CustomerDictionaryEntryUpdateInput,\n} from '../data/validators'\nimport { CustomerDictionaryEntry } from '../data/entities'\nimport {\n ensureOrganizationScope,\n ensureTenantScope,\n extractUndoPayload,\n normalizeDictionaryColor,\n normalizeDictionaryIcon,\n} from './shared'\nimport { resolveRedoSnapshot } from '@open-mercato/shared/lib/commands/redo'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport { enforceCommandOptimisticLockWithGuards } from '@open-mercato/shared/lib/crud/optimistic-lock-command'\nimport { calendarEventTypeBehaviorSchema, type CalendarEventTypeBehavior } from '../calendar-event-types'\n\nconst logger = createLogger('customers')\n\ntype CustomerDictionaryEntrySnapshot = {\n id: string\n tenantId: string\n organizationId: string\n kind: string\n value: string\n normalizedValue: string\n label: string\n color: string | null\n icon: string | null\n behavior: CalendarEventTypeBehavior | null\n}\n\ntype CustomerDictionaryEntryUndoPayload = {\n before?: CustomerDictionaryEntrySnapshot | null\n after?: CustomerDictionaryEntrySnapshot | null\n}\n\nconst nullableCalendarEventTypeBehaviorSchema = calendarEventTypeBehaviorSchema.nullable()\n\nfunction calendarEventTypeBehaviorsEqual(\n left: CalendarEventTypeBehavior | null,\n right: CalendarEventTypeBehavior | null,\n): boolean {\n const parsedLeft = nullableCalendarEventTypeBehaviorSchema.safeParse(left)\n const parsedRight = nullableCalendarEventTypeBehaviorSchema.safeParse(right)\n if (parsedLeft.success && parsedRight.success) return isDeepStrictEqual(parsedLeft.data, parsedRight.data)\n return isDeepStrictEqual(left, right)\n}\n\nfunction buildRoleTypeInUseError(usageCount: number, ownerAssignments: number, relationshipAssignments: number) {\n return new CrudHttpError(409, {\n code: 'role_type_in_use',\n error: 'Role type is in use',\n usageCount,\n ownerAssignments,\n relationshipAssignments,\n })\n}\n\nfunction normalizeValue(input: string): { value: string; normalized: string } {\n const trimmed = input.trim()\n if (!trimmed) {\n throw new CrudHttpError(400, { error: 'Dictionary entry value is required' })\n }\n return { value: trimmed, normalized: trimmed.toLowerCase() }\n}\n\nfunction sanitizeColor(input: string | null | undefined): string | null | undefined {\n if (input === undefined) return undefined\n if (input === null) return null\n return normalizeDictionaryColor(input)\n}\n\nfunction sanitizeIcon(input: string | null | undefined): string | null | undefined {\n if (input === undefined) return undefined\n if (input === null) return null\n return normalizeDictionaryIcon(input)\n}\n\nfunction toSnapshot(entry: CustomerDictionaryEntry): CustomerDictionaryEntrySnapshot {\n return {\n id: entry.id,\n tenantId: entry.tenantId,\n organizationId: entry.organizationId,\n kind: entry.kind,\n value: entry.value,\n normalizedValue: entry.normalizedValue,\n label: entry.label,\n color: entry.color ?? null,\n icon: entry.icon ?? null,\n behavior: entry.activityTypeBehavior ?? null,\n }\n}\n\nfunction buildDictionaryChanges(\n before: CustomerDictionaryEntrySnapshot,\n after: CustomerDictionaryEntrySnapshot,\n keys: readonly (keyof CustomerDictionaryEntrySnapshot)[],\n): Record<string, { from: unknown; to: unknown }> {\n const scalarKeys = keys.filter((key) => key !== 'behavior')\n const changes = buildChanges(\n before as unknown as Record<string, unknown>,\n after as unknown as Record<string, unknown>,\n scalarKeys,\n )\n if (keys.includes('behavior') && !calendarEventTypeBehaviorsEqual(before.behavior, after.behavior)) {\n changes.behavior = { from: before.behavior, to: after.behavior }\n }\n return changes\n}\n\nasync function loadSnapshot(\n em: EntityManager,\n id: string,\n scope: { tenantId: string | null; organizationId: string | null },\n): Promise<CustomerDictionaryEntrySnapshot | null> {\n const entry = await findOneWithDecryption(em, CustomerDictionaryEntry, { id }, {}, scope)\n return entry ? toSnapshot(entry) : null\n}\n\nfunction applySnapshot(entry: CustomerDictionaryEntry, snapshot: CustomerDictionaryEntrySnapshot): void {\n entry.tenantId = snapshot.tenantId\n entry.organizationId = snapshot.organizationId\n entry.kind = snapshot.kind\n entry.value = snapshot.value\n entry.normalizedValue = snapshot.normalizedValue\n entry.label = snapshot.label\n entry.color = snapshot.color\n entry.icon = snapshot.icon\n entry.activityTypeBehavior = snapshot.behavior\n}\n\nasync function invalidateCache(\n ctx: CommandRuntimeContext,\n snapshot: CustomerDictionaryEntrySnapshot | null | undefined\n) {\n if (!snapshot) return\n let cache: CacheStrategy | undefined\n try {\n cache = (ctx.container.resolve('cache') as CacheStrategy)\n } catch (err) {\n logger.warn('cache resolve failed; skipping invalidation', { component: 'commands.dictionaries', err })\n cache = undefined\n }\n if (!cache) return\n await invalidateDictionaryCache(cache, {\n tenantId: snapshot.tenantId,\n mappedKind: snapshot.kind,\n organizationIds: [snapshot.organizationId],\n })\n}\n\ntype CreateResult = {\n entryId: string\n tenantId: string\n organizationId: string\n mode: 'created' | 'updated' | 'unchanged'\n before?: CustomerDictionaryEntrySnapshot | null\n}\n\nconst createDictionaryEntryCommand: CommandHandler<CustomerDictionaryEntryCreateInput, CreateResult> = {\n id: 'customers.dictionaryEntries.create',\n async execute(rawInput, ctx) {\n const parsed = customerDictionaryEntryCreateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const value = normalizeValue(parsed.value)\n const label = parsed.label?.trim() || value.value\n const color = sanitizeColor(parsed.color)\n const icon = sanitizeIcon(parsed.icon)\n const behavior = parsed.behavior\n\n const existing = await findOneWithDecryption(\n em,\n CustomerDictionaryEntry,\n {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n kind: parsed.kind,\n normalizedValue: value.normalized,\n },\n {},\n {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n },\n )\n\n if (existing) {\n await enforceCommandOptimisticLockWithGuards(ctx.container, {\n resourceKind: 'customers.dictionary_entry',\n resourceId: existing.id,\n current: existing.updatedAt,\n request: ctx.request ?? null,\n })\n const before = toSnapshot(existing)\n let changed = false\n\n if (parsed.label !== undefined && existing.label !== label) {\n existing.label = label\n changed = true\n }\n if (color !== undefined && existing.color !== color) {\n existing.color = color ?? null\n changed = true\n }\n if (icon !== undefined && existing.icon !== icon) {\n existing.icon = icon ?? null\n changed = true\n }\n if (behavior !== undefined && !isDeepStrictEqual(existing.activityTypeBehavior ?? null, behavior)) {\n existing.activityTypeBehavior = behavior\n changed = true\n }\n\n if (changed) {\n existing.updatedAt = new Date()\n await em.flush()\n await invalidateCache(ctx, toSnapshot(existing))\n return {\n entryId: existing.id,\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n mode: 'updated',\n before,\n }\n }\n\n return {\n entryId: existing.id,\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n mode: 'unchanged',\n before,\n }\n }\n\n const entry = em.create(CustomerDictionaryEntry, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n kind: parsed.kind,\n value: value.value,\n normalizedValue: value.normalized,\n label,\n color: color ?? null,\n icon: icon ?? null,\n activityTypeBehavior: behavior ?? null,\n })\n em.persist(entry)\n await em.flush()\n await invalidateCache(ctx, toSnapshot(entry))\n\n return {\n entryId: entry.id,\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n mode: 'created',\n }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadSnapshot(em, result.entryId, {\n tenantId: result.tenantId,\n organizationId: result.organizationId,\n })\n },\n buildLog: async ({ result, snapshots }) => {\n const after = snapshots.after as CustomerDictionaryEntrySnapshot | undefined\n if (!after) return null\n const { translate } = await resolveTranslations()\n\n if (result.mode === 'created') {\n return {\n actionLabel: translate('customers.audit.dictionaryEntries.create', 'Add dictionary entry'),\n resourceKind: 'customers.dictionary_entry',\n resourceId: after.id,\n tenantId: after.tenantId,\n organizationId: after.organizationId,\n snapshotAfter: after,\n payload: {\n undo: { after } satisfies CustomerDictionaryEntryUndoPayload,\n },\n }\n }\n\n if (result.mode === 'updated') {\n const before = result.before ?? null\n if (!before) return null\n const changes = buildDictionaryChanges(\n before,\n after,\n ['label', 'color', 'icon', 'behavior']\n )\n if (!changes || Object.keys(changes).length === 0) return null\n return {\n actionLabel: translate('customers.audit.dictionaryEntries.update', 'Update dictionary entry'),\n resourceKind: 'customers.dictionary_entry',\n resourceId: after.id,\n tenantId: after.tenantId,\n organizationId: after.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes,\n payload: {\n undo: { before, after } satisfies CustomerDictionaryEntryUndoPayload,\n },\n }\n }\n\n return null\n },\n undo: async ({ logEntry, ctx }) => {\n const undo = extractUndoPayload<CustomerDictionaryEntryUndoPayload>(logEntry)\n if (!undo) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n\n const after =\n undo.after ??\n (logEntry?.snapshotAfter as CustomerDictionaryEntrySnapshot | null | undefined) ??\n null\n\n if (after && !undo.before) {\n ensureTenantScope(ctx, after.tenantId)\n ensureOrganizationScope(ctx, after.organizationId)\n const entry = await findOneWithDecryption(\n em,\n CustomerDictionaryEntry,\n { id: after.id },\n {},\n { tenantId: after.tenantId, organizationId: after.organizationId },\n )\n if (entry) {\n await em.remove(entry).flush()\n await invalidateCache(ctx, after)\n return\n }\n await em.nativeDelete(CustomerDictionaryEntry, { id: after.id })\n await invalidateCache(ctx, after)\n return\n }\n\n const before =\n undo.before ??\n (logEntry?.snapshotBefore as CustomerDictionaryEntrySnapshot | null | undefined) ??\n null\n\n if (before) {\n ensureTenantScope(ctx, before.tenantId)\n ensureOrganizationScope(ctx, before.organizationId)\n let entry = await findOneWithDecryption(\n em,\n CustomerDictionaryEntry,\n { id: before.id },\n {},\n { tenantId: before.tenantId, organizationId: before.organizationId },\n )\n if (!entry) {\n entry = em.create(CustomerDictionaryEntry, {\n id: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n kind: before.kind,\n value: before.value,\n normalizedValue: before.normalizedValue,\n label: before.label,\n color: before.color,\n icon: before.icon,\n activityTypeBehavior: before.behavior,\n })\n em.persist(entry)\n } else {\n applySnapshot(entry, before)\n }\n await em.flush()\n await invalidateCache(ctx, before)\n }\n },\n redo: async ({ logEntry, ctx }) => {\n const undo = extractUndoPayload<CustomerDictionaryEntryUndoPayload>(logEntry)\n const after = resolveRedoSnapshot<CustomerDictionaryEntrySnapshot>(logEntry)\n if (!after) {\n throw new CrudHttpError(400, { error: '[internal] redo snapshot unavailable for dictionary entry create' })\n }\n ensureTenantScope(ctx, after.tenantId)\n ensureOrganizationScope(ctx, after.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let entry = await findOneWithDecryption(\n em,\n CustomerDictionaryEntry,\n { id: after.id },\n {},\n { tenantId: after.tenantId, organizationId: after.organizationId },\n )\n if (!entry) {\n entry = em.create(CustomerDictionaryEntry, {\n id: after.id,\n tenantId: after.tenantId,\n organizationId: after.organizationId,\n kind: after.kind,\n value: after.value,\n normalizedValue: after.normalizedValue,\n label: after.label,\n color: after.color,\n icon: after.icon,\n activityTypeBehavior: after.behavior,\n })\n em.persist(entry)\n } else {\n applySnapshot(entry, after)\n entry.updatedAt = new Date()\n }\n await em.flush()\n await invalidateCache(ctx, after)\n\n return {\n entryId: after.id,\n tenantId: after.tenantId,\n organizationId: after.organizationId,\n mode: undo?.before ? 'updated' : 'created',\n ...(undo?.before ? { before: undo.before } : {}),\n } satisfies CreateResult\n },\n}\n\ntype UpdateResult = {\n entryId: string\n tenantId: string\n organizationId: string\n changed: boolean\n}\n\nconst updateDictionaryEntryCommand: CommandHandler<CustomerDictionaryEntryUpdateInput, UpdateResult> = {\n id: 'customers.dictionaryEntries.update',\n async prepare(rawInput, ctx) {\n const parsed = customerDictionaryEntryUpdateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadSnapshot(em, parsed.id, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n })\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const parsed = customerDictionaryEntryUpdateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entry = await findOneWithDecryption(\n em,\n CustomerDictionaryEntry,\n { id: parsed.id },\n {},\n {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n },\n )\n if (!entry || entry.organizationId !== parsed.organizationId || entry.tenantId !== parsed.tenantId || entry.kind !== parsed.kind) {\n throw notFound('Dictionary entry not found')\n }\n\n await enforceCommandOptimisticLockWithGuards(ctx.container, {\n resourceKind: 'customers.dictionary_entry',\n resourceId: entry.id,\n current: entry.updatedAt,\n request: ctx.request ?? null,\n })\n\n let changed = false\n\n if (parsed.value !== undefined) {\n const value = normalizeValue(parsed.value)\n if (value.normalized !== entry.normalizedValue) {\n if (entry.kind === 'person_company_role') {\n const usage = await loadRoleTypeUsage(em, {\n tenantId: parsed.tenantId,\n organizationId: entry.organizationId,\n value: entry.value,\n })\n if (usage.total > 0) {\n throw buildRoleTypeInUseError(\n usage.total,\n usage.ownerAssignments,\n usage.relationshipAssignments,\n )\n }\n }\n const duplicate = await findOneWithDecryption(\n em,\n CustomerDictionaryEntry,\n {\n id: { $ne: entry.id },\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n kind: parsed.kind,\n normalizedValue: value.normalized,\n },\n {},\n {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n },\n )\n if (duplicate) {\n throw new CrudHttpError(409, { error: 'An entry with this value already exists' })\n }\n entry.value = value.value\n entry.normalizedValue = value.normalized\n if (parsed.label === undefined) {\n entry.label = value.value\n }\n changed = true\n }\n }\n\n if (parsed.label !== undefined) {\n const label = parsed.label.trim() || entry.value\n if (entry.label !== label) {\n entry.label = label\n changed = true\n }\n }\n\n if (parsed.color !== undefined) {\n const color = sanitizeColor(parsed.color)\n if (entry.color !== (color ?? null)) {\n entry.color = color ?? null\n changed = true\n }\n }\n\n if (parsed.icon !== undefined) {\n const icon = sanitizeIcon(parsed.icon)\n if (entry.icon !== (icon ?? null)) {\n entry.icon = icon ?? null\n changed = true\n }\n }\n\n if (\n parsed.behavior !== undefined &&\n !isDeepStrictEqual(entry.activityTypeBehavior ?? null, parsed.behavior)\n ) {\n entry.activityTypeBehavior = parsed.behavior\n changed = true\n }\n\n if (changed) {\n entry.updatedAt = new Date()\n await em.flush()\n await invalidateCache(ctx, toSnapshot(entry))\n }\n\n return {\n entryId: entry.id,\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n changed,\n }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadSnapshot(em, result.entryId, {\n tenantId: result.tenantId,\n organizationId: result.organizationId,\n })\n },\n buildLog: async ({ snapshots, result }) => {\n const before = snapshots.before as CustomerDictionaryEntrySnapshot | undefined\n const after = snapshots.after as CustomerDictionaryEntrySnapshot | undefined\n if (!before || !after || !result.changed) return null\n const changes = buildDictionaryChanges(\n before,\n after,\n ['value', 'label', 'color', 'icon', 'behavior']\n )\n if (!changes || Object.keys(changes).length === 0) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('customers.audit.dictionaryEntries.update', 'Update dictionary entry'),\n resourceKind: 'customers.dictionary_entry',\n resourceId: after.id,\n tenantId: after.tenantId,\n organizationId: after.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes,\n payload: {\n undo: { before, after } satisfies CustomerDictionaryEntryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const undo = extractUndoPayload<CustomerDictionaryEntryUndoPayload>(logEntry)\n const before =\n undo?.before ??\n (logEntry?.snapshotBefore as CustomerDictionaryEntrySnapshot | null | undefined) ??\n null\n if (!before) return\n ensureTenantScope(ctx, before.tenantId)\n ensureOrganizationScope(ctx, before.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let entry = await findOneWithDecryption(\n em,\n CustomerDictionaryEntry,\n { id: before.id },\n {},\n { tenantId: before.tenantId, organizationId: before.organizationId },\n )\n if (!entry) {\n entry = em.create(CustomerDictionaryEntry, {\n id: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n kind: before.kind,\n value: before.value,\n normalizedValue: before.normalizedValue,\n label: before.label,\n color: before.color,\n icon: before.icon,\n activityTypeBehavior: before.behavior,\n })\n em.persist(entry)\n } else {\n applySnapshot(entry, before)\n }\n await em.flush()\n await invalidateCache(ctx, before)\n },\n}\n\nconst deleteDictionaryEntryCommand: CommandHandler<CustomerDictionaryEntryDeleteInput, { entryId: string }> = {\n id: 'customers.dictionaryEntries.delete',\n async prepare(rawInput, ctx) {\n const parsed = customerDictionaryEntryDeleteSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadSnapshot(em, parsed.id, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n })\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const parsed = customerDictionaryEntryDeleteSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entry = await findOneWithDecryption(\n em,\n CustomerDictionaryEntry,\n { id: parsed.id },\n {},\n {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n },\n )\n if (!entry || entry.organizationId !== parsed.organizationId || entry.tenantId !== parsed.tenantId || entry.kind !== parsed.kind) {\n throw notFound('Dictionary entry not found')\n }\n await enforceCommandOptimisticLockWithGuards(ctx.container, {\n resourceKind: 'customers.dictionary_entry',\n resourceId: entry.id,\n current: entry.updatedAt,\n request: ctx.request ?? null,\n })\n if (entry.kind === 'person_company_role') {\n const usage = await loadRoleTypeUsage(em, {\n tenantId: entry.tenantId,\n organizationId: entry.organizationId,\n value: entry.value,\n })\n if (usage.total > 0) {\n throw buildRoleTypeInUseError(\n usage.total,\n usage.ownerAssignments,\n usage.relationshipAssignments,\n )\n }\n }\n em.remove(entry)\n await em.flush()\n await invalidateCache(ctx, toSnapshot(entry))\n return { entryId: entry.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as CustomerDictionaryEntrySnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('customers.audit.dictionaryEntries.delete', 'Delete dictionary entry'),\n resourceKind: 'customers.dictionary_entry',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: { before } satisfies CustomerDictionaryEntryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const undo = extractUndoPayload<CustomerDictionaryEntryUndoPayload>(logEntry)\n const before =\n undo?.before ??\n (logEntry?.snapshotBefore as CustomerDictionaryEntrySnapshot | null | undefined) ??\n null\n if (!before) return\n ensureTenantScope(ctx, before.tenantId)\n ensureOrganizationScope(ctx, before.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let entry = await findOneWithDecryption(\n em,\n CustomerDictionaryEntry,\n { id: before.id },\n {},\n { tenantId: before.tenantId, organizationId: before.organizationId },\n )\n if (!entry) {\n entry = em.create(CustomerDictionaryEntry, {\n id: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n kind: before.kind,\n value: before.value,\n normalizedValue: before.normalizedValue,\n label: before.label,\n color: before.color,\n icon: before.icon,\n activityTypeBehavior: before.behavior,\n })\n em.persist(entry)\n } else {\n applySnapshot(entry, before)\n }\n await em.flush()\n await invalidateCache(ctx, before)\n },\n}\n\nregisterCommand(createDictionaryEntryCommand)\nregisterCommand(updateDictionaryEntryCommand)\nregisterCommand(deleteDictionaryEntryCommand)\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }