@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.
- package/.turbo/turbo-build.log +1 -1
- package/dist/generated/entities/customer_dictionary_entry/index.js +2 -0
- package/dist/generated/entities/customer_dictionary_entry/index.js.map +2 -2
- package/dist/generated/entities/customer_interaction/index.js +2 -0
- package/dist/generated/entities/customer_interaction/index.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +2 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/catalog/commands/categories.js +1 -1
- package/dist/modules/catalog/commands/categories.js.map +2 -2
- package/dist/modules/catalog/commands/productDeleteChildren.js +389 -0
- package/dist/modules/catalog/commands/productDeleteChildren.js.map +7 -0
- package/dist/modules/catalog/commands/products.js +52 -17
- package/dist/modules/catalog/commands/products.js.map +2 -2
- package/dist/modules/communication_channels/api/post/channels/connect/credentials/route.js +4 -6
- package/dist/modules/communication_channels/api/post/channels/connect/credentials/route.js.map +2 -2
- package/dist/modules/communication_channels/api/post/channels/connect/tenant-credentials/route.js +4 -6
- package/dist/modules/communication_channels/api/post/channels/connect/tenant-credentials/route.js.map +2 -2
- package/dist/modules/communication_channels/api/post/oauth/[provider]/initiate/route.js +47 -11
- package/dist/modules/communication_channels/api/post/oauth/[provider]/initiate/route.js.map +3 -3
- package/dist/modules/communication_channels/commands/deliver-outbound-message.js +5 -1
- package/dist/modules/communication_channels/commands/deliver-outbound-message.js.map +2 -2
- package/dist/modules/communication_channels/lib/inbound-message-origin.js +1 -1
- package/dist/modules/communication_channels/lib/inbound-message-origin.js.map +2 -2
- package/dist/modules/communication_channels/lib/oauth-state.js +4 -1
- package/dist/modules/communication_channels/lib/oauth-state.js.map +2 -2
- package/dist/modules/communication_channels/lib/use-connect-channel.js +10 -0
- package/dist/modules/communication_channels/lib/use-connect-channel.js.map +2 -2
- package/dist/modules/customers/api/activity-types/route.js +151 -0
- package/dist/modules/customers/api/activity-types/route.js.map +7 -0
- package/dist/modules/customers/api/deals/[id]/people/route.js +58 -5
- package/dist/modules/customers/api/deals/[id]/people/route.js.map +2 -2
- package/dist/modules/customers/api/dictionaries/[kind]/[id]/route.js +13 -5
- package/dist/modules/customers/api/dictionaries/[kind]/[id]/route.js.map +2 -2
- package/dist/modules/customers/api/dictionaries/[kind]/route.js +20 -5
- package/dist/modules/customers/api/dictionaries/[kind]/route.js.map +2 -2
- package/dist/modules/customers/api/interactions/route.js +3 -0
- package/dist/modules/customers/api/interactions/route.js.map +2 -2
- package/dist/modules/customers/api/interactions/tasks/route.js +1 -0
- package/dist/modules/customers/api/interactions/tasks/route.js.map +2 -2
- package/dist/modules/customers/backend/config/customers/pipeline-stages/page.meta.js +18 -0
- package/dist/modules/customers/backend/config/customers/pipeline-stages/page.meta.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealAssociations.js +0 -23
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealAssociations.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/[id]/page.js +15 -17
- package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
- package/dist/modules/customers/calendar-event-types.js +548 -0
- package/dist/modules/customers/calendar-event-types.js.map +7 -0
- package/dist/modules/customers/commands/dictionaries.js +70 -10
- package/dist/modules/customers/commands/dictionaries.js.map +2 -2
- package/dist/modules/customers/commands/interactions.js +187 -22
- package/dist/modules/customers/commands/interactions.js.map +3 -3
- package/dist/modules/customers/components/ActivityTypeEditor.js +288 -0
- package/dist/modules/customers/components/ActivityTypeEditor.js.map +7 -0
- package/dist/modules/customers/components/DictionarySettings.js +3 -1
- package/dist/modules/customers/components/DictionarySettings.js.map +2 -2
- package/dist/modules/customers/components/calendar/CalendarEventEditor.js +391 -297
- package/dist/modules/customers/components/calendar/CalendarEventEditor.js.map +3 -3
- package/dist/modules/customers/components/calendar/CalendarSettingsModal.js +9 -74
- package/dist/modules/customers/components/calendar/CalendarSettingsModal.js.map +2 -2
- package/dist/modules/customers/components/calendar/TimeGrid.js +20 -16
- package/dist/modules/customers/components/calendar/TimeGrid.js.map +2 -2
- package/dist/modules/customers/components/calendar/editor/EventTypePanel.js +218 -0
- package/dist/modules/customers/components/calendar/editor/EventTypePanel.js.map +7 -0
- package/dist/modules/customers/components/calendar/editor/LocationField.js +7 -3
- package/dist/modules/customers/components/calendar/editor/LocationField.js.map +2 -2
- package/dist/modules/customers/components/calendar/editor/PeopleField.js +5 -2
- package/dist/modules/customers/components/calendar/editor/PeopleField.js.map +2 -2
- package/dist/modules/customers/components/calendar/editor/PriorityField.js +3 -1
- package/dist/modules/customers/components/calendar/editor/PriorityField.js.map +2 -2
- package/dist/modules/customers/components/calendar/editor/RepeatField.js +9 -1
- package/dist/modules/customers/components/calendar/editor/RepeatField.js.map +2 -2
- package/dist/modules/customers/components/calendar/editor/ResourcesField.js +4 -1
- package/dist/modules/customers/components/calendar/editor/ResourcesField.js.map +2 -2
- package/dist/modules/customers/components/calendar/editor/ScheduleSection.js +15 -7
- package/dist/modules/customers/components/calendar/editor/ScheduleSection.js.map +2 -2
- package/dist/modules/customers/components/calendar/editor/SegmentGroup.js +3 -1
- package/dist/modules/customers/components/calendar/editor/SegmentGroup.js.map +2 -2
- package/dist/modules/customers/components/calendar/editor/hooks.js +28 -13
- package/dist/modules/customers/components/calendar/editor/hooks.js.map +3 -3
- package/dist/modules/customers/components/calendar/editor/inputs.js +14 -6
- package/dist/modules/customers/components/calendar/editor/inputs.js.map +2 -2
- package/dist/modules/customers/components/calendar/editor/useCalendarCustomFields.js +54 -0
- package/dist/modules/customers/components/calendar/editor/useCalendarCustomFields.js.map +7 -0
- package/dist/modules/customers/components/calendar/editor/useEventTypeCatalog.js +82 -0
- package/dist/modules/customers/components/calendar/editor/useEventTypeCatalog.js.map +7 -0
- package/dist/modules/customers/components/calendar/types.js +1 -0
- package/dist/modules/customers/components/calendar/types.js.map +2 -2
- package/dist/modules/customers/components/detail/CompanyPeopleSection.js +78 -343
- package/dist/modules/customers/components/detail/CompanyPeopleSection.js.map +2 -2
- package/dist/modules/customers/components/detail/CreatePersonDialog.js +12 -11
- package/dist/modules/customers/components/detail/CreatePersonDialog.js.map +2 -2
- package/dist/modules/customers/components/detail/DealForm.js +7 -3
- package/dist/modules/customers/components/detail/DealForm.js.map +2 -2
- package/dist/modules/customers/components/detail/DealPeopleSection.js +206 -0
- package/dist/modules/customers/components/detail/DealPeopleSection.js.map +7 -0
- package/dist/modules/customers/components/detail/LinkedPeopleSection.js +342 -0
- package/dist/modules/customers/components/detail/LinkedPeopleSection.js.map +7 -0
- package/dist/modules/customers/components/detail/PersonCard.js +5 -2
- package/dist/modules/customers/components/detail/PersonCard.js.map +2 -2
- package/dist/modules/customers/components/linking/adapters/personAdapter.js +3 -0
- package/dist/modules/customers/components/linking/adapters/personAdapter.js.map +2 -2
- package/dist/modules/customers/data/entities.js +6 -0
- package/dist/modules/customers/data/entities.js.map +2 -2
- package/dist/modules/customers/data/validators.js +39 -10
- package/dist/modules/customers/data/validators.js.map +2 -2
- package/dist/modules/customers/di.js +20 -1
- package/dist/modules/customers/di.js.map +2 -2
- package/dist/modules/customers/extension-points.js +13 -0
- package/dist/modules/customers/extension-points.js.map +2 -2
- package/dist/modules/customers/lib/calendar/conflicts.js +59 -16
- package/dist/modules/customers/lib/calendar/conflicts.js.map +2 -2
- package/dist/modules/customers/lib/calendar/editorPayload.js +34 -16
- package/dist/modules/customers/lib/calendar/editorPayload.js.map +2 -2
- package/dist/modules/customers/lib/calendar/eventTypeResolver.js +197 -0
- package/dist/modules/customers/lib/calendar/eventTypeResolver.js.map +7 -0
- package/dist/modules/customers/lib/calendar/interactionApplicability.js +67 -0
- package/dist/modules/customers/lib/calendar/interactionApplicability.js.map +7 -0
- package/dist/modules/customers/lib/calendar/mapItem.js +5 -2
- package/dist/modules/customers/lib/calendar/mapItem.js.map +2 -2
- package/dist/modules/customers/lib/calendar/recurrence.js +62 -1
- package/dist/modules/customers/lib/calendar/recurrence.js.map +2 -2
- package/dist/modules/customers/lib/calendar/timezone.js +111 -0
- package/dist/modules/customers/lib/calendar/timezone.js.map +7 -0
- package/dist/modules/customers/lib/interactionReadModel.js +1 -0
- package/dist/modules/customers/lib/interactionReadModel.js.map +2 -2
- package/dist/modules/customers/lib/todoCompatibility.js +1 -0
- package/dist/modules/customers/lib/todoCompatibility.js.map +2 -2
- package/dist/modules/customers/migrations/Migration20260928175058_customers.js +17 -0
- package/dist/modules/customers/migrations/Migration20260928175058_customers.js.map +7 -0
- package/dist/modules/customers/migrations/Migration20260930110235_customers.js +17 -0
- package/dist/modules/customers/migrations/Migration20260930110235_customers.js.map +7 -0
- package/dist/modules/dictionaries/components/DictionaryTable.js +60 -51
- package/dist/modules/dictionaries/components/DictionaryTable.js.map +2 -2
- package/dist/modules/messages/subscribers/message-notification.js +13 -1
- package/dist/modules/messages/subscribers/message-notification.js.map +2 -2
- package/dist/modules/payment_gateways/api/webhook/[provider]/route.js +201 -53
- package/dist/modules/payment_gateways/api/webhook/[provider]/route.js.map +2 -2
- package/dist/modules/payment_gateways/lib/gateway-service.js +37 -11
- package/dist/modules/payment_gateways/lib/gateway-service.js.map +2 -2
- package/dist/modules/planner/lib/availabilityMerge.js +101 -38
- package/dist/modules/planner/lib/availabilityMerge.js.map +3 -3
- package/dist/modules/planner/services/plannerAvailabilityService.js.map +2 -2
- package/dist/modules/sales/components/documents/LineItemDialog.js +159 -81
- package/dist/modules/sales/components/documents/LineItemDialog.js.map +2 -2
- package/dist/modules/sales/components/documents/lineItemUtils.js +7 -0
- package/dist/modules/sales/components/documents/lineItemUtils.js.map +2 -2
- package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.js +12 -7
- package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.js.map +2 -2
- package/dist/modules/sync_excel/lib/adapters/customers.js +28 -25
- package/dist/modules/sync_excel/lib/adapters/customers.js.map +2 -2
- package/generated/entities/customer_dictionary_entry/index.ts +1 -0
- package/generated/entities/customer_interaction/index.ts +1 -0
- package/generated/entity-fields-registry.ts +2 -0
- package/package.json +9 -8
- package/src/modules/auth/i18n/de.json +3 -0
- package/src/modules/auth/i18n/en.json +3 -0
- package/src/modules/auth/i18n/es.json +3 -0
- package/src/modules/auth/i18n/ko.json +3 -0
- package/src/modules/auth/i18n/pl.json +3 -0
- package/src/modules/catalog/commands/categories.ts +1 -1
- package/src/modules/catalog/commands/productDeleteChildren.ts +557 -0
- package/src/modules/catalog/commands/products.ts +58 -17
- package/src/modules/communication_channels/api/post/channels/connect/credentials/route.ts +4 -6
- package/src/modules/communication_channels/api/post/channels/connect/tenant-credentials/route.ts +4 -6
- package/src/modules/communication_channels/api/post/oauth/[provider]/initiate/route.ts +46 -10
- package/src/modules/communication_channels/commands/deliver-outbound-message.ts +6 -1
- package/src/modules/communication_channels/i18n/de.json +4 -0
- package/src/modules/communication_channels/i18n/en.json +4 -0
- package/src/modules/communication_channels/i18n/es.json +4 -0
- package/src/modules/communication_channels/i18n/ko.json +4 -0
- package/src/modules/communication_channels/i18n/pl.json +4 -0
- package/src/modules/communication_channels/lib/inbound-message-origin.ts +2 -6
- package/src/modules/communication_channels/lib/oauth-state.ts +4 -1
- package/src/modules/communication_channels/lib/use-connect-channel.ts +10 -0
- package/src/modules/customers/api/activity-types/route.ts +154 -0
- package/src/modules/customers/api/deals/[id]/people/route.ts +82 -3
- package/src/modules/customers/api/dictionaries/[kind]/[id]/route.ts +9 -1
- package/src/modules/customers/api/dictionaries/[kind]/route.ts +18 -2
- package/src/modules/customers/api/interactions/route.ts +4 -0
- package/src/modules/customers/api/interactions/tasks/route.ts +1 -0
- package/src/modules/customers/backend/config/customers/pipeline-stages/page.meta.ts +20 -0
- package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealAssociations.ts +0 -29
- package/src/modules/customers/backend/customers/deals/[id]/page.tsx +15 -17
- package/src/modules/customers/calendar-event-types.ts +674 -0
- package/src/modules/customers/commands/dictionaries.ts +84 -8
- package/src/modules/customers/commands/interactions.ts +244 -21
- package/src/modules/customers/components/ActivityTypeEditor.tsx +239 -0
- package/src/modules/customers/components/DictionarySettings.tsx +5 -3
- package/src/modules/customers/components/calendar/CalendarEventEditor.tsx +347 -218
- package/src/modules/customers/components/calendar/CalendarSettingsModal.tsx +18 -96
- package/src/modules/customers/components/calendar/TimeGrid.tsx +20 -18
- package/src/modules/customers/components/calendar/editor/EventTypePanel.tsx +230 -0
- package/src/modules/customers/components/calendar/editor/LocationField.tsx +7 -1
- package/src/modules/customers/components/calendar/editor/PeopleField.tsx +4 -0
- package/src/modules/customers/components/calendar/editor/PriorityField.tsx +3 -0
- package/src/modules/customers/components/calendar/editor/RepeatField.tsx +10 -0
- package/src/modules/customers/components/calendar/editor/ResourcesField.tsx +4 -0
- package/src/modules/customers/components/calendar/editor/ScheduleSection.tsx +16 -4
- package/src/modules/customers/components/calendar/editor/SegmentGroup.tsx +3 -0
- package/src/modules/customers/components/calendar/editor/hooks.ts +29 -13
- package/src/modules/customers/components/calendar/editor/inputs.tsx +17 -5
- package/src/modules/customers/components/calendar/editor/useCalendarCustomFields.ts +49 -0
- package/src/modules/customers/components/calendar/editor/useEventTypeCatalog.ts +100 -0
- package/src/modules/customers/components/calendar/types.ts +1 -0
- package/src/modules/customers/components/detail/CompanyPeopleSection.tsx +94 -388
- package/src/modules/customers/components/detail/CreatePersonDialog.tsx +39 -19
- package/src/modules/customers/components/detail/DealForm.tsx +7 -3
- package/src/modules/customers/components/detail/DealPeopleSection.tsx +256 -0
- package/src/modules/customers/components/detail/LinkedPeopleSection.tsx +474 -0
- package/src/modules/customers/components/detail/PersonCard.tsx +12 -4
- package/src/modules/customers/components/detail/types.ts +1 -0
- package/src/modules/customers/components/linking/adapters/personAdapter.tsx +4 -0
- package/src/modules/customers/data/entities.ts +8 -1
- package/src/modules/customers/data/validators.ts +42 -7
- package/src/modules/customers/di.ts +21 -0
- package/src/modules/customers/extension-points.ts +13 -0
- package/src/modules/customers/i18n/de.json +104 -8
- package/src/modules/customers/i18n/en.json +104 -8
- package/src/modules/customers/i18n/es.json +104 -8
- package/src/modules/customers/i18n/ko.json +104 -8
- package/src/modules/customers/i18n/pl.json +104 -8
- package/src/modules/customers/lib/calendar/conflicts.ts +106 -27
- package/src/modules/customers/lib/calendar/editorPayload.ts +39 -19
- package/src/modules/customers/lib/calendar/eventTypeResolver.ts +258 -0
- package/src/modules/customers/lib/calendar/interactionApplicability.ts +99 -0
- package/src/modules/customers/lib/calendar/mapItem.ts +6 -2
- package/src/modules/customers/lib/calendar/recurrence.ts +65 -1
- package/src/modules/customers/lib/calendar/timezone.ts +117 -0
- package/src/modules/customers/lib/interactionReadModel.ts +1 -0
- package/src/modules/customers/lib/todoCompatibility.ts +2 -0
- package/src/modules/customers/migrations/.snapshot-open-mercato.json +34 -0
- package/src/modules/customers/migrations/Migration20260928175058_customers.ts +15 -0
- package/src/modules/customers/migrations/Migration20260930110235_customers.ts +15 -0
- package/src/modules/dictionaries/components/DictionaryTable.tsx +63 -56
- package/src/modules/messages/subscribers/message-notification.ts +13 -3
- package/src/modules/payment_gateways/api/webhook/[provider]/route.ts +243 -62
- package/src/modules/payment_gateways/lib/gateway-service.ts +39 -12
- package/src/modules/planner/lib/availabilityMerge.ts +106 -41
- package/src/modules/planner/services/plannerAvailabilityService.ts +4 -0
- package/src/modules/sales/components/documents/LineItemDialog.tsx +194 -111
- package/src/modules/sales/components/documents/lineItemUtils.ts +18 -0
- package/src/modules/staff/backend/staff/time-tracking/projects/[id]/page.tsx +25 -13
- 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 =
|
|
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 =
|
|
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
|
}
|