@open-mercato/core 0.6.6-develop.6256.1.9fc16aedc4 → 0.6.6-develop.6286.1.d985c5c374
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +2 -2
- package/dist/generated/entities/carrier_shipment_idempotency_key/index.js +19 -0
- package/dist/generated/entities/carrier_shipment_idempotency_key/index.js.map +7 -0
- package/dist/generated/entities.ids.generated.js +2 -1
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +10 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/catalog/lib/productResolution.js +45 -0
- package/dist/modules/catalog/lib/productResolution.js.map +7 -0
- package/dist/modules/communication_channels/workers/channel-import-history.js +1 -1
- package/dist/modules/communication_channels/workers/channel-import-history.js.map +2 -2
- package/dist/modules/currencies/api/fetch-configs/route.js +34 -0
- package/dist/modules/currencies/api/fetch-configs/route.js.map +2 -2
- package/dist/modules/currencies/components/CurrencyFetchingConfig.js +17 -15
- package/dist/modules/currencies/components/CurrencyFetchingConfig.js.map +2 -2
- package/dist/modules/customers/api/companies/[id]/route.js +176 -161
- package/dist/modules/customers/api/companies/[id]/route.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/route.js +75 -59
- package/dist/modules/customers/api/people/[id]/route.js.map +2 -2
- package/dist/modules/customers/backend/config/customers/pipeline-stages/page.js +17 -10
- package/dist/modules/customers/backend/config/customers/pipeline-stages/page.js.map +2 -2
- package/dist/modules/customers/components/detail/ActivitiesAddNewMenu.js +6 -4
- package/dist/modules/customers/components/detail/ActivitiesAddNewMenu.js.map +2 -2
- package/dist/modules/customers/components/detail/AiActionChips.js +5 -2
- package/dist/modules/customers/components/detail/AiActionChips.js.map +2 -2
- package/dist/modules/customers/components/detail/schedule/ParticipantsField.js +19 -21
- package/dist/modules/customers/components/detail/schedule/ParticipantsField.js.map +2 -2
- package/dist/modules/data_sync/api/runs/[id]/cancel.js +1 -1
- package/dist/modules/data_sync/api/runs/[id]/cancel.js.map +2 -2
- package/dist/modules/data_sync/backend/data-sync/page.js +9 -45
- package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
- package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js +11 -17
- package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js.map +2 -2
- package/dist/modules/data_sync/components/IntegrationScheduleTab.js +12 -10
- package/dist/modules/data_sync/components/IntegrationScheduleTab.js.map +2 -2
- package/dist/modules/data_sync/lib/id-mapping.js +46 -1
- package/dist/modules/data_sync/lib/id-mapping.js.map +2 -2
- package/dist/modules/data_sync/lib/sync-engine.js +2 -2
- package/dist/modules/data_sync/lib/sync-engine.js.map +2 -2
- package/dist/modules/data_sync/lib/syncRunStatus.js +30 -0
- package/dist/modules/data_sync/lib/syncRunStatus.js.map +7 -0
- package/dist/modules/entities/api/records.js +6 -0
- package/dist/modules/entities/api/records.js.map +2 -2
- package/dist/modules/feature_toggles/api/global/route.js +17 -15
- package/dist/modules/feature_toggles/api/global/route.js.map +2 -2
- package/dist/modules/feature_toggles/api/openapi.js +2 -2
- package/dist/modules/feature_toggles/api/openapi.js.map +2 -2
- package/dist/modules/feature_toggles/commands/global.js +14 -0
- package/dist/modules/feature_toggles/commands/global.js.map +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/page.js +6 -0
- package/dist/modules/inbox_ops/backend/inbox-ops/page.js.map +2 -2
- package/dist/modules/messages/api/[id]/conversation/archive/route.js +25 -7
- package/dist/modules/messages/api/[id]/conversation/archive/route.js.map +2 -2
- package/dist/modules/messages/api/[id]/conversation/read/route.js +24 -6
- package/dist/modules/messages/api/[id]/conversation/read/route.js.map +2 -2
- package/dist/modules/messages/api/[id]/route.js +13 -1
- package/dist/modules/messages/api/[id]/route.js.map +2 -2
- package/dist/modules/messages/api/openapi.js +3 -1
- package/dist/modules/messages/api/openapi.js.map +2 -2
- package/dist/modules/messages/commands/conversation.js +77 -0
- package/dist/modules/messages/commands/conversation.js.map +2 -2
- package/dist/modules/messages/components/MessageDetailPageClient.js +16 -4
- package/dist/modules/messages/components/MessageDetailPageClient.js.map +2 -2
- package/dist/modules/messages/components/message-detail/hooks/useMessageDetails.js +3 -1
- package/dist/modules/messages/components/message-detail/hooks/useMessageDetails.js.map +2 -2
- package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsActions.js +29 -4
- package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsActions.js.map +2 -2
- package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsQueries.js +10 -1
- package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsQueries.js.map +2 -2
- package/dist/modules/messages/components/message-detail/panels/MainMessageHeader.js +13 -11
- package/dist/modules/messages/components/message-detail/panels/MainMessageHeader.js.map +2 -2
- package/dist/modules/payment_gateways/api/cancel/route.js +5 -0
- package/dist/modules/payment_gateways/api/cancel/route.js.map +2 -2
- package/dist/modules/payment_gateways/api/capture/route.js +5 -0
- package/dist/modules/payment_gateways/api/capture/route.js.map +2 -2
- package/dist/modules/payment_gateways/api/refund/route.js +5 -0
- package/dist/modules/payment_gateways/api/refund/route.js.map +2 -2
- package/dist/modules/payment_gateways/lib/gateway-service.js +52 -25
- package/dist/modules/payment_gateways/lib/gateway-service.js.map +2 -2
- package/dist/modules/payment_gateways/lib/status-machine.js +13 -0
- package/dist/modules/payment_gateways/lib/status-machine.js.map +2 -2
- package/dist/modules/perspectives/api/[tableId]/route.js +8 -2
- package/dist/modules/perspectives/api/[tableId]/route.js.map +2 -2
- package/dist/modules/perspectives/data/entities.js +33 -3
- package/dist/modules/perspectives/data/entities.js.map +2 -2
- package/dist/modules/perspectives/migrations/Migration20260619120000_perspectives_live_row_uniqueness.js +63 -0
- package/dist/modules/perspectives/migrations/Migration20260619120000_perspectives_live_row_uniqueness.js.map +7 -0
- package/dist/modules/perspectives/services/perspectiveService.js +17 -0
- package/dist/modules/perspectives/services/perspectiveService.js.map +2 -2
- package/dist/modules/planner/commands/availability-weekly.js +33 -1
- package/dist/modules/planner/commands/availability-weekly.js.map +2 -2
- package/dist/modules/planner/components/AvailabilityRulesEditor.js +14 -2
- package/dist/modules/planner/components/AvailabilityRulesEditor.js.map +2 -2
- package/dist/modules/progress/api/active/route.js +1 -1
- package/dist/modules/progress/api/active/route.js.map +2 -2
- package/dist/modules/progress/lib/progressService.js.map +1 -1
- package/dist/modules/progress/lib/progressServiceImpl.js +33 -8
- package/dist/modules/progress/lib/progressServiceImpl.js.map +2 -2
- package/dist/modules/query_index/api/status.js +19 -24
- package/dist/modules/query_index/api/status.js.map +3 -3
- package/dist/modules/query_index/lib/coverage.js +35 -0
- package/dist/modules/query_index/lib/coverage.js.map +2 -2
- package/dist/modules/query_index/lib/engine.js +11 -6
- package/dist/modules/query_index/lib/engine.js.map +2 -2
- package/dist/modules/resources/api/resource-types.js +5 -37
- package/dist/modules/resources/api/resource-types.js.map +2 -2
- package/dist/modules/resources/api/resourceTypeCounts.js +35 -0
- package/dist/modules/resources/api/resourceTypeCounts.js.map +7 -0
- package/dist/modules/resources/backend/resources/resource-types/[id]/edit/page.js +1 -1
- package/dist/modules/resources/backend/resources/resource-types/[id]/edit/page.js.map +1 -1
- package/dist/modules/resources/backend/resources/resource-types/page.js +2 -1
- package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
- package/dist/modules/sales/components/documents/ReturnDialog.js +4 -1
- package/dist/modules/sales/components/documents/ReturnDialog.js.map +2 -2
- package/dist/modules/sales/components/documents/ShipmentDialog.js +17 -2
- package/dist/modules/sales/components/documents/ShipmentDialog.js.map +2 -2
- package/dist/modules/sales/di.js +4 -0
- package/dist/modules/sales/di.js.map +2 -2
- package/dist/modules/sales/services/salesOrderService.js +26 -0
- package/dist/modules/sales/services/salesOrderService.js.map +7 -0
- package/dist/modules/shipping_carriers/api/shipments/route.js +8 -0
- package/dist/modules/shipping_carriers/api/shipments/route.js.map +2 -2
- package/dist/modules/shipping_carriers/data/entities.js +38 -0
- package/dist/modules/shipping_carriers/data/entities.js.map +2 -2
- package/dist/modules/shipping_carriers/data/validators.js +2 -1
- package/dist/modules/shipping_carriers/data/validators.js.map +2 -2
- package/dist/modules/shipping_carriers/lib/shipment-idempotency.js +76 -0
- package/dist/modules/shipping_carriers/lib/shipment-idempotency.js.map +7 -0
- package/dist/modules/shipping_carriers/lib/shipment-wizard/hooks/shipmentApi.js +2 -1
- package/dist/modules/shipping_carriers/lib/shipment-wizard/hooks/shipmentApi.js.map +2 -2
- package/dist/modules/shipping_carriers/lib/shipment-wizard/hooks/useShipmentWizard.js +20 -2
- package/dist/modules/shipping_carriers/lib/shipment-wizard/hooks/useShipmentWizard.js.map +2 -2
- package/dist/modules/shipping_carriers/lib/shipping-service.js +82 -43
- package/dist/modules/shipping_carriers/lib/shipping-service.js.map +2 -2
- package/dist/modules/shipping_carriers/migrations/Migration20260618173616_shipping_carriers.js +14 -0
- package/dist/modules/shipping_carriers/migrations/Migration20260618173616_shipping_carriers.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-ui/ListView.js +15 -6
- package/dist/modules/staff/lib/timesheets-ui/ListView.js.map +2 -2
- package/dist/modules/translations/components/TranslationManager.js +9 -18
- package/dist/modules/translations/components/TranslationManager.js.map +2 -2
- package/generated/entities/carrier_shipment_idempotency_key/index.ts +8 -0
- package/generated/entities.ids.generated.ts +2 -1
- package/generated/entity-fields-registry.ts +10 -0
- package/package.json +9 -8
- package/src/modules/catalog/lib/productResolution.ts +75 -0
- package/src/modules/communication_channels/workers/channel-import-history.ts +1 -1
- package/src/modules/currencies/api/fetch-configs/route.ts +36 -0
- package/src/modules/currencies/components/CurrencyFetchingConfig.tsx +20 -17
- package/src/modules/currencies/i18n/de.json +2 -1
- package/src/modules/currencies/i18n/en.json +2 -1
- package/src/modules/currencies/i18n/es.json +2 -1
- package/src/modules/currencies/i18n/pl.json +2 -1
- package/src/modules/customers/api/companies/[id]/route.ts +214 -189
- package/src/modules/customers/api/people/[id]/route.ts +106 -80
- package/src/modules/customers/backend/config/customers/pipeline-stages/page.tsx +19 -12
- package/src/modules/customers/components/detail/ActivitiesAddNewMenu.tsx +8 -6
- package/src/modules/customers/components/detail/AiActionChips.tsx +6 -3
- package/src/modules/customers/components/detail/schedule/ParticipantsField.tsx +16 -18
- package/src/modules/data_sync/api/runs/[id]/cancel.ts +1 -1
- package/src/modules/data_sync/backend/data-sync/page.tsx +11 -58
- package/src/modules/data_sync/backend/data-sync/runs/[id]/page.tsx +13 -20
- package/src/modules/data_sync/components/IntegrationScheduleTab.tsx +10 -8
- package/src/modules/data_sync/lib/id-mapping.ts +58 -1
- package/src/modules/data_sync/lib/sync-engine.ts +2 -2
- package/src/modules/data_sync/lib/syncRunStatus.ts +39 -0
- package/src/modules/entities/api/records.ts +14 -0
- package/src/modules/feature_toggles/api/global/route.ts +16 -14
- package/src/modules/feature_toggles/api/openapi.ts +2 -2
- package/src/modules/feature_toggles/commands/global.ts +15 -0
- package/src/modules/inbox_ops/backend/inbox-ops/page.tsx +7 -0
- package/src/modules/messages/api/[id]/conversation/archive/route.ts +29 -6
- package/src/modules/messages/api/[id]/conversation/read/route.ts +29 -6
- package/src/modules/messages/api/[id]/route.ts +15 -0
- package/src/modules/messages/api/openapi.ts +2 -0
- package/src/modules/messages/commands/conversation.ts +87 -0
- package/src/modules/messages/components/MessageDetailPageClient.tsx +16 -4
- package/src/modules/messages/components/message-detail/hooks/useMessageDetails.ts +2 -0
- package/src/modules/messages/components/message-detail/hooks/useMessageDetailsActions.ts +39 -4
- package/src/modules/messages/components/message-detail/hooks/useMessageDetailsQueries.ts +15 -1
- package/src/modules/messages/components/message-detail/panels/MainMessageHeader.tsx +29 -14
- package/src/modules/messages/components/message-detail/types.ts +2 -0
- package/src/modules/messages/i18n/de.json +4 -0
- package/src/modules/messages/i18n/en.json +4 -0
- package/src/modules/messages/i18n/es.json +4 -0
- package/src/modules/messages/i18n/pl.json +4 -0
- package/src/modules/payment_gateways/api/cancel/route.ts +5 -0
- package/src/modules/payment_gateways/api/capture/route.ts +5 -0
- package/src/modules/payment_gateways/api/refund/route.ts +5 -0
- package/src/modules/payment_gateways/lib/gateway-service.ts +58 -25
- package/src/modules/payment_gateways/lib/status-machine.ts +16 -0
- package/src/modules/perspectives/api/[tableId]/route.ts +8 -2
- package/src/modules/perspectives/data/entities.ts +43 -3
- package/src/modules/perspectives/migrations/.snapshot-open-mercato.json +69 -25
- package/src/modules/perspectives/migrations/Migration20260619120000_perspectives_live_row_uniqueness.ts +65 -0
- package/src/modules/perspectives/services/perspectiveService.ts +17 -0
- package/src/modules/planner/commands/availability-weekly.ts +48 -1
- package/src/modules/planner/components/AvailabilityRulesEditor.tsx +31 -10
- package/src/modules/progress/api/active/route.ts +1 -1
- package/src/modules/progress/lib/progressService.ts +2 -2
- package/src/modules/progress/lib/progressServiceImpl.ts +33 -8
- package/src/modules/query_index/api/status.ts +28 -32
- package/src/modules/query_index/lib/coverage.ts +63 -0
- package/src/modules/query_index/lib/engine.ts +37 -24
- package/src/modules/resources/api/resource-types.ts +4 -44
- package/src/modules/resources/api/resourceTypeCounts.ts +74 -0
- package/src/modules/resources/backend/resources/resource-types/[id]/edit/page.tsx +1 -1
- package/src/modules/resources/backend/resources/resource-types/page.tsx +1 -0
- package/src/modules/sales/components/documents/ReturnDialog.tsx +4 -1
- package/src/modules/sales/components/documents/ShipmentDialog.tsx +20 -2
- package/src/modules/sales/di.ts +6 -0
- package/src/modules/sales/services/salesOrderService.ts +38 -0
- package/src/modules/shipping_carriers/api/shipments/route.ts +8 -0
- package/src/modules/shipping_carriers/data/entities.ts +33 -0
- package/src/modules/shipping_carriers/data/validators.ts +1 -0
- package/src/modules/shipping_carriers/i18n/de.json +1 -0
- package/src/modules/shipping_carriers/i18n/en.json +1 -0
- package/src/modules/shipping_carriers/i18n/es.json +1 -0
- package/src/modules/shipping_carriers/i18n/pl.json +1 -0
- package/src/modules/shipping_carriers/lib/shipment-idempotency.ts +119 -0
- package/src/modules/shipping_carriers/lib/shipment-wizard/hooks/shipmentApi.ts +3 -1
- package/src/modules/shipping_carriers/lib/shipment-wizard/hooks/useShipmentWizard.ts +24 -2
- package/src/modules/shipping_carriers/lib/shipping-service.ts +87 -43
- package/src/modules/shipping_carriers/migrations/.snapshot-open-mercato.json +197 -0
- package/src/modules/shipping_carriers/migrations/Migration20260618173616_shipping_carriers.ts +14 -0
- package/src/modules/staff/i18n/de.json +1 -0
- package/src/modules/staff/i18n/en.json +1 -0
- package/src/modules/staff/i18n/es.json +1 -0
- package/src/modules/staff/i18n/pl.json +1 -0
- package/src/modules/staff/lib/timesheets-ui/ListView.tsx +15 -7
- package/src/modules/translations/components/TranslationManager.tsx +17 -24
- package/src/modules/translations/i18n/de.json +1 -0
- package/src/modules/translations/i18n/en.json +1 -0
- package/src/modules/translations/i18n/es.json +1 -0
- package/src/modules/translations/i18n/pl.json +1 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../../src/modules/messages/api/%5Bid%5D/conversation/read/route.ts"],
|
|
4
|
-
"sourcesContent": ["import type { CommandBus } from '@open-mercato/shared/lib/commands/command-bus'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi/types'\nimport { attachOperationMetadataHeader } from '../../../../lib/operationMetadata'\nimport { resolveMessageContext } from '../../../../lib/routeHelpers'\nimport { resolveUserFeatures, runMessageMutationGuardAfterSuccess, runMessageMutationGuards } from '../../../guards'\nimport {\n conversationMutationResponseSchema,\n errorResponseSchema,\n} from '../../../openapi'\n\nexport const metadata = {\n DELETE: { requireAuth: true, requireFeatures: ['messages.view'] },\n}\n\
|
|
5
|
-
"mappings": "AAEA,SAAS,qCAAqC;AAC9C,SAAS,6BAA6B;AACtC,SAAS,qBAAqB,qCAAqC,gCAAgC;AACnG;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAEA,MAAM,WAAW;AAAA,EACtB,QAAQ,EAAE,aAAa,MAAM,iBAAiB,CAAC,eAAe,EAAE;AAClE;AAEA,
|
|
4
|
+
"sourcesContent": ["import type { CommandBus } from '@open-mercato/shared/lib/commands/command-bus'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi/types'\nimport { attachOperationMetadataHeader } from '../../../../lib/operationMetadata'\nimport { resolveMessageContext } from '../../../../lib/routeHelpers'\nimport { resolveUserFeatures, runMessageMutationGuardAfterSuccess, runMessageMutationGuards } from '../../../guards'\nimport {\n conversationMutationResponseSchema,\n errorResponseSchema,\n} from '../../../openapi'\n\nexport const metadata = {\n PUT: { requireAuth: true, requireFeatures: ['messages.view'] },\n DELETE: { requireAuth: true, requireFeatures: ['messages.view'] },\n}\n\nasync function runConversationReadMutation(\n req: Request,\n id: string,\n commandId: 'messages.conversation.mark_read_for_actor' | 'messages.conversation.mark_unread_for_actor',\n) {\n const { ctx, scope } = await resolveMessageContext(req)\n const commandBus = ctx.container.resolve('commandBus') as CommandBus\n\n const guardResult = await runMessageMutationGuards(\n ctx.container,\n {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n userId: scope.userId,\n resourceKind: 'messages.conversation',\n resourceId: id,\n operation: 'update',\n requestMethod: req.method,\n requestHeaders: req.headers,\n mutationPayload: null,\n },\n resolveUserFeatures(ctx.auth),\n )\n if (!guardResult.ok) {\n return Response.json(\n guardResult.errorBody ?? { error: 'Operation blocked by guard' },\n { status: guardResult.errorStatus ?? 422 },\n )\n }\n\n try {\n const { result, logEntry } = await commandBus.execute(commandId, {\n input: {\n anchorMessageId: id,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n userId: scope.userId,\n },\n ctx: {\n container: ctx.container,\n auth: ctx.auth ?? null,\n organizationScope: null,\n selectedOrganizationId: scope.organizationId,\n organizationIds: scope.organizationId ? [scope.organizationId] : null,\n request: req,\n },\n })\n\n const response = Response.json(result)\n attachOperationMetadataHeader(response, logEntry, {\n resourceKind: 'messages.conversation',\n resourceId: id,\n })\n await runMessageMutationGuardAfterSuccess(guardResult.afterSuccessCallbacks, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n userId: scope.userId,\n resourceKind: 'messages.conversation',\n resourceId: id,\n operation: 'update',\n requestMethod: req.method,\n requestHeaders: req.headers,\n })\n return response\n } catch (error) {\n if (error instanceof Error) {\n if (error.message === 'Message not found') {\n return Response.json({ error: error.message }, { status: 404 })\n }\n if (error.message === 'Access denied') {\n return Response.json({ error: error.message }, { status: 403 })\n }\n }\n throw error\n }\n}\n\nexport async function PUT(req: Request, { params }: { params: { id: string } }) {\n return runConversationReadMutation(req, params.id, 'messages.conversation.mark_read_for_actor')\n}\n\nexport async function DELETE(req: Request, { params }: { params: { id: string } }) {\n return runConversationReadMutation(req, params.id, 'messages.conversation.mark_unread_for_actor')\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Messages',\n methods: {\n PUT: {\n summary: 'Mark entire conversation as read for current actor',\n responses: [\n { status: 200, description: 'Conversation marked read', schema: conversationMutationResponseSchema },\n ],\n errors: [\n { status: 403, description: 'Access denied', schema: errorResponseSchema },\n { status: 404, description: 'Message not found', schema: errorResponseSchema },\n ],\n },\n DELETE: {\n summary: 'Mark entire conversation as unread for current actor',\n responses: [\n { status: 200, description: 'Conversation marked unread', schema: conversationMutationResponseSchema },\n ],\n errors: [\n { status: 403, description: 'Access denied', schema: errorResponseSchema },\n { status: 404, description: 'Message not found', schema: errorResponseSchema },\n ],\n },\n },\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -95,6 +95,16 @@ async function GET(req, { params }) {
|
|
|
95
95
|
}) : [];
|
|
96
96
|
const visibleRecipientMessageIds = new Set(visibleRecipientRows.map((item) => item.messageId));
|
|
97
97
|
const actorVisibleThreadMessages = threadMessages.filter((threadMessage) => threadMessage.senderUserId === scope.userId || visibleRecipientMessageIds.has(threadMessage.id));
|
|
98
|
+
const actorRecipientStatusByMessageId = /* @__PURE__ */ new Map();
|
|
99
|
+
for (const row of visibleRecipientRows) {
|
|
100
|
+
actorRecipientStatusByMessageId.set(row.messageId, row.status);
|
|
101
|
+
}
|
|
102
|
+
if (recipient) {
|
|
103
|
+
actorRecipientStatusByMessageId.set(params.id, autoMarkRead ? "read" : recipient.status);
|
|
104
|
+
}
|
|
105
|
+
const actorRecipientStatuses = Array.from(actorRecipientStatusByMessageId.values());
|
|
106
|
+
const conversationArchived = actorRecipientStatuses.length > 0 && actorRecipientStatuses.every((status) => status === "archived");
|
|
107
|
+
const conversationAllUnread = actorRecipientStatuses.length > 0 && actorRecipientStatuses.every((status) => status === "unread");
|
|
98
108
|
const threadSenderIds = actorVisibleThreadMessages.map((threadMessage) => threadMessage.senderUserId).filter((value) => typeof value === "string" && value.length > 0);
|
|
99
109
|
const threadSenders = threadSenderIds.length > 0 ? await findWithDecryption(
|
|
100
110
|
em,
|
|
@@ -200,7 +210,9 @@ async function GET(req, { params }) {
|
|
|
200
210
|
sentAt: threadMessage.sentAt
|
|
201
211
|
};
|
|
202
212
|
}),
|
|
203
|
-
isRead: recipient ? autoMarkRead || recipient.status !== "unread" : true
|
|
213
|
+
isRead: recipient ? autoMarkRead || recipient.status !== "unread" : true,
|
|
214
|
+
conversationArchived,
|
|
215
|
+
conversationAllUnread
|
|
204
216
|
});
|
|
205
217
|
}
|
|
206
218
|
async function PATCH(req, { params }) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/modules/messages/api/%5Bid%5D/route.ts"],
|
|
4
|
-
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport type { CommandBus } from '@open-mercato/shared/lib/commands/command-bus'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi/types'\nimport { findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { User } from '../../../auth/data/entities'\nimport { Message, MessageObject, MessageRecipient } from '../../data/entities'\nimport { updateDraftSchema } from '../../data/validators'\nimport { buildResolvedMessageActions } from '../../lib/actions'\nimport { getMessageObjectType } from '../../lib/message-objects-registry'\nimport { getMessageTypeOrDefault } from '../../lib/message-types-registry'\nimport { attachOperationMetadataHeader } from '../../lib/operationMetadata'\nimport { hasOrganizationAccess, resolveMessageContext } from '../../lib/routeHelpers'\nimport { resolveUserFeatures, runMessageMutationGuardAfterSuccess, runMessageMutationGuards } from '../guards'\nimport {\n errorResponseSchema,\n messageDetailResponseSchema,\n okResponseSchema,\n updateDraftSchema as updateDraftOpenApiSchema,\n} from '../openapi'\n\nexport const metadata = {\n GET: { requireAuth: true },\n PATCH: { requireAuth: true, requireFeatures: ['messages.compose'] },\n DELETE: { requireAuth: true, requireFeatures: ['messages.view'] },\n}\n\ntype MessageObjectPreviewPayload = {\n title: string\n subtitle?: string\n status?: string\n statusColor?: string\n metadata?: Record<string, string>\n} | null\n\nexport async function GET(req: Request, { params }: { params: { id: string } }) {\n const { ctx, scope } = await resolveMessageContext(req)\n const em = ctx.container.resolve('em') as EntityManager\n const url = new URL(req.url)\n const skipMarkReadParam = url.searchParams.get('skipMarkRead')\n const skipMarkRead = skipMarkReadParam === '1'\n\n const message = await findOneWithDecryption(\n em,\n Message,\n {\n id: params.id,\n tenantId: scope.tenantId,\n deletedAt: null,\n },\n undefined,\n { tenantId: scope.tenantId, organizationId: scope.organizationId },\n )\n\n if (!message) {\n return Response.json({ error: 'Message not found' }, { status: 404 })\n }\n\n if (!hasOrganizationAccess(scope.organizationId, message.organizationId)) {\n return Response.json({ error: 'Access denied' }, { status: 403 })\n }\n\n const recipient = await em.findOne(MessageRecipient, {\n messageId: params.id,\n recipientUserId: scope.userId,\n deletedAt: null,\n })\n\n const isSender = message.senderUserId === scope.userId\n const isRecipient = Boolean(recipient)\n\n if (!isSender && !isRecipient) {\n return Response.json({ error: 'Access denied' }, { status: 403 })\n }\n\n const autoMarkRead = !skipMarkRead && recipient?.status === 'unread'\n const readAt = autoMarkRead ? new Date() : recipient?.readAt ?? null\n\n const objects = await em.find(MessageObject, { messageId: params.id })\n const objectPreviews = await Promise.all(\n objects.map(async (item): Promise<MessageObjectPreviewPayload> => {\n const objectType = getMessageObjectType(item.entityModule, item.entityType)\n if (!objectType?.loadPreview) return null\n try {\n return await objectType.loadPreview(item.entityId, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n })\n } catch (error) {\n console.error(\n `[messages] Failed to load preview for ${item.entityModule}:${item.entityType}:${item.entityId}`,\n error,\n )\n return null\n }\n }),\n )\n const allRecipients = await em.find(MessageRecipient, { messageId: params.id, deletedAt: null })\n\n const threadMessages = await findWithDecryption(\n em,\n Message,\n {\n threadId: message.threadId ?? message.id,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n isDraft: false,\n },\n { orderBy: { sentAt: 'ASC' } },\n { tenantId: scope.tenantId, organizationId: scope.organizationId },\n )\n const threadMessageIds = threadMessages.map((item) => item.id)\n const visibleRecipientRows = threadMessageIds.length > 0\n ? await em.find(MessageRecipient, {\n messageId: { $in: threadMessageIds },\n recipientUserId: scope.userId,\n deletedAt: null,\n })\n : []\n const visibleRecipientMessageIds = new Set(visibleRecipientRows.map((item) => item.messageId))\n const actorVisibleThreadMessages = threadMessages.filter((threadMessage) => (\n threadMessage.senderUserId === scope.userId || visibleRecipientMessageIds.has(threadMessage.id)\n ))\n\n const threadSenderIds = actorVisibleThreadMessages\n .map((threadMessage) => threadMessage.senderUserId)\n .filter((value): value is string => typeof value === 'string' && value.length > 0)\n\n const threadSenders = threadSenderIds.length > 0\n ? await findWithDecryption(\n em,\n User,\n { id: { $in: Array.from(new Set(threadSenderIds)) } },\n undefined,\n { tenantId: scope.tenantId, organizationId: scope.organizationId }\n )\n : []\n\n const threadSenderMap = new Map(threadSenders.map((user) => [user.id, user]))\n\n const senderUser = await findOneWithDecryption(\n em,\n User,\n { id: message.senderUserId },\n undefined,\n { tenantId: scope.tenantId, organizationId: scope.organizationId }\n )\n\n const senderName = typeof senderUser?.name === 'string' && senderUser.name.trim().length\n ? senderUser.name.trim()\n : null\n const senderEmail = senderUser?.email ?? null\n\n const messageType = getMessageTypeOrDefault(message.type)\n const resolvedActionData = buildResolvedMessageActions(message, objects)\n\n if (autoMarkRead) {\n const commandBus = ctx.container.resolve('commandBus') as CommandBus\n await commandBus.execute('messages.recipients.mark_read', {\n input: {\n messageId: params.id,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n userId: scope.userId,\n },\n ctx: {\n container: ctx.container,\n auth: ctx.auth ?? null,\n organizationScope: null,\n selectedOrganizationId: scope.organizationId,\n organizationIds: scope.organizationId ? [scope.organizationId] : null,\n request: req,\n },\n })\n }\n\n return Response.json({\n id: message.id,\n type: message.type,\n isDraft: message.isDraft,\n canEditDraft: message.isDraft && message.senderUserId === scope.userId,\n visibility: message.visibility,\n sourceEntityType: message.sourceEntityType,\n sourceEntityId: message.sourceEntityId,\n externalEmail: message.externalEmail,\n externalName: message.externalName,\n typeDefinition: {\n labelKey: messageType.labelKey,\n icon: messageType.icon,\n color: messageType.color,\n allowReply: messageType.allowReply ?? true,\n allowForward: messageType.allowForward ?? true,\n ui: {\n listItemComponent: messageType.ui?.listItemComponent ?? null,\n contentComponent: messageType.ui?.contentComponent ?? null,\n actionsComponent: messageType.ui?.actionsComponent ?? null,\n },\n },\n threadId: message.threadId,\n parentMessageId: message.parentMessageId,\n senderUserId: message.senderUserId,\n senderName,\n senderEmail,\n subject: message.subject,\n body: message.body,\n bodyFormat: message.bodyFormat,\n priority: message.priority,\n sentAt: message.sentAt,\n actionData: resolvedActionData,\n actionTaken: message.actionTaken,\n actionTakenAt: message.actionTakenAt,\n actionTakenByUserId: message.actionTakenByUserId,\n recipients: allRecipients.map((item) => ({\n userId: item.recipientUserId,\n type: item.recipientType,\n status: autoMarkRead && item.recipientUserId === scope.userId ? 'read' : item.status,\n readAt: autoMarkRead && item.recipientUserId === scope.userId ? readAt : item.readAt,\n })),\n objects: objects.map((item, index) => ({\n id: item.id,\n entityModule: item.entityModule,\n entityType: item.entityType,\n entityId: item.entityId,\n actionRequired: item.actionRequired,\n actionType: item.actionType,\n actionLabel: item.actionLabel,\n snapshot: item.entitySnapshot,\n preview: objectPreviews[index] ?? null,\n })),\n thread: actorVisibleThreadMessages.map((threadMessage) => {\n const sender = threadSenderMap.get(threadMessage.senderUserId)\n const threadSenderName = typeof sender?.name === 'string' && sender.name.trim().length\n ? sender.name.trim()\n : null\n\n return {\n id: threadMessage.id,\n senderUserId: threadMessage.senderUserId,\n senderName: threadSenderName,\n senderEmail: sender?.email ?? null,\n body: threadMessage.body,\n bodyFormat: threadMessage.bodyFormat,\n sentAt: threadMessage.sentAt,\n }\n }),\n isRead: recipient ? (autoMarkRead || recipient.status !== 'unread') : true,\n })\n}\n\nexport async function PATCH(req: Request, { params }: { params: { id: string } }) {\n const { ctx, scope } = await resolveMessageContext(req)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const commandBus = ctx.container.resolve('commandBus') as CommandBus\n const body = await req.json().catch(() => ({}))\n const input = updateDraftSchema.parse(body)\n\n const message = await em.findOne(Message, {\n id: params.id,\n tenantId: scope.tenantId,\n deletedAt: null,\n })\n\n if (!message) {\n return Response.json({ error: 'Message not found' }, { status: 404 })\n }\n\n if (!hasOrganizationAccess(scope.organizationId, message.organizationId)) {\n return Response.json({ error: 'Access denied' }, { status: 403 })\n }\n\n if (message.senderUserId !== scope.userId) {\n return Response.json({ error: 'Access denied' }, { status: 403 })\n }\n\n if (!message.isDraft) {\n return Response.json({ error: 'Only draft messages can be edited' }, { status: 409 })\n }\n\n const guardResult = await runMessageMutationGuards(\n ctx.container,\n {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n userId: scope.userId,\n resourceKind: 'messages.message',\n resourceId: message.id,\n operation: 'update',\n requestMethod: req.method,\n requestHeaders: req.headers,\n mutationPayload: input as Record<string, unknown>,\n },\n resolveUserFeatures(ctx.auth),\n )\n if (!guardResult.ok) {\n return Response.json(\n guardResult.errorBody ?? { error: 'Operation blocked by guard' },\n { status: guardResult.errorStatus ?? 422 },\n )\n }\n\n try {\n const { logEntry } = await commandBus.execute('messages.messages.update_draft', {\n input: {\n ...input,\n messageId: message.id,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n userId: scope.userId,\n },\n ctx: {\n container: ctx.container,\n auth: ctx.auth ?? null,\n organizationScope: null,\n selectedOrganizationId: scope.organizationId,\n organizationIds: scope.organizationId ? [scope.organizationId] : null,\n request: req,\n },\n })\n\n const response = Response.json({ ok: true, id: message.id })\n attachOperationMetadataHeader(response, logEntry, {\n resourceKind: 'messages.message',\n resourceId: message.id,\n })\n await runMessageMutationGuardAfterSuccess(guardResult.afterSuccessCallbacks, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n userId: scope.userId,\n resourceKind: 'messages.message',\n resourceId: message.id,\n operation: 'update',\n requestMethod: req.method,\n requestHeaders: req.headers,\n })\n return response\n } catch (error) {\n if (error instanceof Error) {\n if (error.message === 'Message type cannot be created by users') {\n return Response.json({ error: error.message }, { status: 400 })\n }\n if (error.message === 'Only draft messages can be edited') {\n return Response.json({ error: error.message }, { status: 409 })\n }\n if (error.message === 'Access denied') {\n return Response.json({ error: error.message }, { status: 403 })\n }\n }\n throw error\n }\n\n}\n\nexport async function DELETE(req: Request, { params }: { params: { id: string } }) {\n const { ctx, scope } = await resolveMessageContext(req)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const commandBus = ctx.container.resolve('commandBus') as CommandBus\n\n const message = await em.findOne(Message, {\n id: params.id,\n tenantId: scope.tenantId,\n deletedAt: null,\n })\n\n if (!message) {\n return Response.json({ error: 'Message not found' }, { status: 404 })\n }\n\n if (!hasOrganizationAccess(scope.organizationId, message.organizationId)) {\n return Response.json({ error: 'Access denied' }, { status: 403 })\n }\n\n const guardResult = await runMessageMutationGuards(\n ctx.container,\n {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n userId: scope.userId,\n resourceKind: 'messages.message',\n resourceId: params.id,\n operation: 'delete',\n requestMethod: req.method,\n requestHeaders: req.headers,\n mutationPayload: null,\n },\n resolveUserFeatures(ctx.auth),\n )\n if (!guardResult.ok) {\n return Response.json(\n guardResult.errorBody ?? { error: 'Operation blocked by guard' },\n { status: guardResult.errorStatus ?? 422 },\n )\n }\n\n try {\n const { logEntry } = await commandBus.execute('messages.messages.delete_for_actor', {\n input: {\n messageId: params.id,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n userId: scope.userId,\n },\n ctx: {\n container: ctx.container,\n auth: ctx.auth ?? null,\n organizationScope: null,\n selectedOrganizationId: scope.organizationId,\n organizationIds: scope.organizationId ? [scope.organizationId] : null,\n request: req,\n },\n })\n\n const response = Response.json({ ok: true })\n attachOperationMetadataHeader(response, logEntry, {\n resourceKind: 'messages.message',\n resourceId: params.id,\n })\n await runMessageMutationGuardAfterSuccess(guardResult.afterSuccessCallbacks, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n userId: scope.userId,\n resourceKind: 'messages.message',\n resourceId: params.id,\n operation: 'delete',\n requestMethod: req.method,\n requestHeaders: req.headers,\n })\n return response\n } catch (error) {\n if (error instanceof Error && error.message === 'Access denied') {\n return Response.json({ error: 'Access denied' }, { status: 403 })\n }\n throw error\n }\n\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Messages',\n methods: {\n GET: {\n summary: 'Get message detail',\n responses: [\n {\n status: 200,\n description: 'Message detail with actor-visible thread items only',\n schema: messageDetailResponseSchema,\n },\n ],\n errors: [\n { status: 403, description: 'Access denied', schema: errorResponseSchema },\n { status: 404, description: 'Message not found', schema: errorResponseSchema },\n ],\n },\n PATCH: {\n summary: 'Update draft message',\n requestBody: { schema: updateDraftOpenApiSchema },\n responses: [\n { status: 200, description: 'Draft updated', schema: okResponseSchema },\n ],\n errors: [\n { status: 403, description: 'Access denied', schema: errorResponseSchema },\n { status: 404, description: 'Message not found', schema: errorResponseSchema },\n { status: 409, description: 'Only drafts can be edited', schema: errorResponseSchema },\n ],\n },\n DELETE: {\n summary: 'Delete message for current sender/recipient context',\n responses: [\n { status: 200, description: 'Message deleted', schema: okResponseSchema },\n ],\n errors: [\n { status: 403, description: 'Access denied', schema: errorResponseSchema },\n { status: 404, description: 'Message not found', schema: errorResponseSchema },\n ],\n },\n },\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport type { CommandBus } from '@open-mercato/shared/lib/commands/command-bus'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi/types'\nimport { findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { User } from '../../../auth/data/entities'\nimport { Message, MessageObject, MessageRecipient } from '../../data/entities'\nimport { updateDraftSchema } from '../../data/validators'\nimport { buildResolvedMessageActions } from '../../lib/actions'\nimport { getMessageObjectType } from '../../lib/message-objects-registry'\nimport { getMessageTypeOrDefault } from '../../lib/message-types-registry'\nimport { attachOperationMetadataHeader } from '../../lib/operationMetadata'\nimport { hasOrganizationAccess, resolveMessageContext } from '../../lib/routeHelpers'\nimport { resolveUserFeatures, runMessageMutationGuardAfterSuccess, runMessageMutationGuards } from '../guards'\nimport {\n errorResponseSchema,\n messageDetailResponseSchema,\n okResponseSchema,\n updateDraftSchema as updateDraftOpenApiSchema,\n} from '../openapi'\n\nexport const metadata = {\n GET: { requireAuth: true },\n PATCH: { requireAuth: true, requireFeatures: ['messages.compose'] },\n DELETE: { requireAuth: true, requireFeatures: ['messages.view'] },\n}\n\ntype MessageObjectPreviewPayload = {\n title: string\n subtitle?: string\n status?: string\n statusColor?: string\n metadata?: Record<string, string>\n} | null\n\nexport async function GET(req: Request, { params }: { params: { id: string } }) {\n const { ctx, scope } = await resolveMessageContext(req)\n const em = ctx.container.resolve('em') as EntityManager\n const url = new URL(req.url)\n const skipMarkReadParam = url.searchParams.get('skipMarkRead')\n const skipMarkRead = skipMarkReadParam === '1'\n\n const message = await findOneWithDecryption(\n em,\n Message,\n {\n id: params.id,\n tenantId: scope.tenantId,\n deletedAt: null,\n },\n undefined,\n { tenantId: scope.tenantId, organizationId: scope.organizationId },\n )\n\n if (!message) {\n return Response.json({ error: 'Message not found' }, { status: 404 })\n }\n\n if (!hasOrganizationAccess(scope.organizationId, message.organizationId)) {\n return Response.json({ error: 'Access denied' }, { status: 403 })\n }\n\n const recipient = await em.findOne(MessageRecipient, {\n messageId: params.id,\n recipientUserId: scope.userId,\n deletedAt: null,\n })\n\n const isSender = message.senderUserId === scope.userId\n const isRecipient = Boolean(recipient)\n\n if (!isSender && !isRecipient) {\n return Response.json({ error: 'Access denied' }, { status: 403 })\n }\n\n const autoMarkRead = !skipMarkRead && recipient?.status === 'unread'\n const readAt = autoMarkRead ? new Date() : recipient?.readAt ?? null\n\n const objects = await em.find(MessageObject, { messageId: params.id })\n const objectPreviews = await Promise.all(\n objects.map(async (item): Promise<MessageObjectPreviewPayload> => {\n const objectType = getMessageObjectType(item.entityModule, item.entityType)\n if (!objectType?.loadPreview) return null\n try {\n return await objectType.loadPreview(item.entityId, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n })\n } catch (error) {\n console.error(\n `[messages] Failed to load preview for ${item.entityModule}:${item.entityType}:${item.entityId}`,\n error,\n )\n return null\n }\n }),\n )\n const allRecipients = await em.find(MessageRecipient, { messageId: params.id, deletedAt: null })\n\n const threadMessages = await findWithDecryption(\n em,\n Message,\n {\n threadId: message.threadId ?? message.id,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n isDraft: false,\n },\n { orderBy: { sentAt: 'ASC' } },\n { tenantId: scope.tenantId, organizationId: scope.organizationId },\n )\n const threadMessageIds = threadMessages.map((item) => item.id)\n const visibleRecipientRows = threadMessageIds.length > 0\n ? await em.find(MessageRecipient, {\n messageId: { $in: threadMessageIds },\n recipientUserId: scope.userId,\n deletedAt: null,\n })\n : []\n const visibleRecipientMessageIds = new Set(visibleRecipientRows.map((item) => item.messageId))\n const actorVisibleThreadMessages = threadMessages.filter((threadMessage) => (\n threadMessage.senderUserId === scope.userId || visibleRecipientMessageIds.has(threadMessage.id)\n ))\n\n const actorRecipientStatusByMessageId = new Map<string, string>()\n for (const row of visibleRecipientRows) {\n actorRecipientStatusByMessageId.set(row.messageId, row.status)\n }\n if (recipient) {\n actorRecipientStatusByMessageId.set(params.id, autoMarkRead ? 'read' : recipient.status)\n }\n const actorRecipientStatuses = Array.from(actorRecipientStatusByMessageId.values())\n const conversationArchived = actorRecipientStatuses.length > 0\n && actorRecipientStatuses.every((status) => status === 'archived')\n const conversationAllUnread = actorRecipientStatuses.length > 0\n && actorRecipientStatuses.every((status) => status === 'unread')\n\n const threadSenderIds = actorVisibleThreadMessages\n .map((threadMessage) => threadMessage.senderUserId)\n .filter((value): value is string => typeof value === 'string' && value.length > 0)\n\n const threadSenders = threadSenderIds.length > 0\n ? await findWithDecryption(\n em,\n User,\n { id: { $in: Array.from(new Set(threadSenderIds)) } },\n undefined,\n { tenantId: scope.tenantId, organizationId: scope.organizationId }\n )\n : []\n\n const threadSenderMap = new Map(threadSenders.map((user) => [user.id, user]))\n\n const senderUser = await findOneWithDecryption(\n em,\n User,\n { id: message.senderUserId },\n undefined,\n { tenantId: scope.tenantId, organizationId: scope.organizationId }\n )\n\n const senderName = typeof senderUser?.name === 'string' && senderUser.name.trim().length\n ? senderUser.name.trim()\n : null\n const senderEmail = senderUser?.email ?? null\n\n const messageType = getMessageTypeOrDefault(message.type)\n const resolvedActionData = buildResolvedMessageActions(message, objects)\n\n if (autoMarkRead) {\n const commandBus = ctx.container.resolve('commandBus') as CommandBus\n await commandBus.execute('messages.recipients.mark_read', {\n input: {\n messageId: params.id,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n userId: scope.userId,\n },\n ctx: {\n container: ctx.container,\n auth: ctx.auth ?? null,\n organizationScope: null,\n selectedOrganizationId: scope.organizationId,\n organizationIds: scope.organizationId ? [scope.organizationId] : null,\n request: req,\n },\n })\n }\n\n return Response.json({\n id: message.id,\n type: message.type,\n isDraft: message.isDraft,\n canEditDraft: message.isDraft && message.senderUserId === scope.userId,\n visibility: message.visibility,\n sourceEntityType: message.sourceEntityType,\n sourceEntityId: message.sourceEntityId,\n externalEmail: message.externalEmail,\n externalName: message.externalName,\n typeDefinition: {\n labelKey: messageType.labelKey,\n icon: messageType.icon,\n color: messageType.color,\n allowReply: messageType.allowReply ?? true,\n allowForward: messageType.allowForward ?? true,\n ui: {\n listItemComponent: messageType.ui?.listItemComponent ?? null,\n contentComponent: messageType.ui?.contentComponent ?? null,\n actionsComponent: messageType.ui?.actionsComponent ?? null,\n },\n },\n threadId: message.threadId,\n parentMessageId: message.parentMessageId,\n senderUserId: message.senderUserId,\n senderName,\n senderEmail,\n subject: message.subject,\n body: message.body,\n bodyFormat: message.bodyFormat,\n priority: message.priority,\n sentAt: message.sentAt,\n actionData: resolvedActionData,\n actionTaken: message.actionTaken,\n actionTakenAt: message.actionTakenAt,\n actionTakenByUserId: message.actionTakenByUserId,\n recipients: allRecipients.map((item) => ({\n userId: item.recipientUserId,\n type: item.recipientType,\n status: autoMarkRead && item.recipientUserId === scope.userId ? 'read' : item.status,\n readAt: autoMarkRead && item.recipientUserId === scope.userId ? readAt : item.readAt,\n })),\n objects: objects.map((item, index) => ({\n id: item.id,\n entityModule: item.entityModule,\n entityType: item.entityType,\n entityId: item.entityId,\n actionRequired: item.actionRequired,\n actionType: item.actionType,\n actionLabel: item.actionLabel,\n snapshot: item.entitySnapshot,\n preview: objectPreviews[index] ?? null,\n })),\n thread: actorVisibleThreadMessages.map((threadMessage) => {\n const sender = threadSenderMap.get(threadMessage.senderUserId)\n const threadSenderName = typeof sender?.name === 'string' && sender.name.trim().length\n ? sender.name.trim()\n : null\n\n return {\n id: threadMessage.id,\n senderUserId: threadMessage.senderUserId,\n senderName: threadSenderName,\n senderEmail: sender?.email ?? null,\n body: threadMessage.body,\n bodyFormat: threadMessage.bodyFormat,\n sentAt: threadMessage.sentAt,\n }\n }),\n isRead: recipient ? (autoMarkRead || recipient.status !== 'unread') : true,\n conversationArchived,\n conversationAllUnread,\n })\n}\n\nexport async function PATCH(req: Request, { params }: { params: { id: string } }) {\n const { ctx, scope } = await resolveMessageContext(req)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const commandBus = ctx.container.resolve('commandBus') as CommandBus\n const body = await req.json().catch(() => ({}))\n const input = updateDraftSchema.parse(body)\n\n const message = await em.findOne(Message, {\n id: params.id,\n tenantId: scope.tenantId,\n deletedAt: null,\n })\n\n if (!message) {\n return Response.json({ error: 'Message not found' }, { status: 404 })\n }\n\n if (!hasOrganizationAccess(scope.organizationId, message.organizationId)) {\n return Response.json({ error: 'Access denied' }, { status: 403 })\n }\n\n if (message.senderUserId !== scope.userId) {\n return Response.json({ error: 'Access denied' }, { status: 403 })\n }\n\n if (!message.isDraft) {\n return Response.json({ error: 'Only draft messages can be edited' }, { status: 409 })\n }\n\n const guardResult = await runMessageMutationGuards(\n ctx.container,\n {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n userId: scope.userId,\n resourceKind: 'messages.message',\n resourceId: message.id,\n operation: 'update',\n requestMethod: req.method,\n requestHeaders: req.headers,\n mutationPayload: input as Record<string, unknown>,\n },\n resolveUserFeatures(ctx.auth),\n )\n if (!guardResult.ok) {\n return Response.json(\n guardResult.errorBody ?? { error: 'Operation blocked by guard' },\n { status: guardResult.errorStatus ?? 422 },\n )\n }\n\n try {\n const { logEntry } = await commandBus.execute('messages.messages.update_draft', {\n input: {\n ...input,\n messageId: message.id,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n userId: scope.userId,\n },\n ctx: {\n container: ctx.container,\n auth: ctx.auth ?? null,\n organizationScope: null,\n selectedOrganizationId: scope.organizationId,\n organizationIds: scope.organizationId ? [scope.organizationId] : null,\n request: req,\n },\n })\n\n const response = Response.json({ ok: true, id: message.id })\n attachOperationMetadataHeader(response, logEntry, {\n resourceKind: 'messages.message',\n resourceId: message.id,\n })\n await runMessageMutationGuardAfterSuccess(guardResult.afterSuccessCallbacks, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n userId: scope.userId,\n resourceKind: 'messages.message',\n resourceId: message.id,\n operation: 'update',\n requestMethod: req.method,\n requestHeaders: req.headers,\n })\n return response\n } catch (error) {\n if (error instanceof Error) {\n if (error.message === 'Message type cannot be created by users') {\n return Response.json({ error: error.message }, { status: 400 })\n }\n if (error.message === 'Only draft messages can be edited') {\n return Response.json({ error: error.message }, { status: 409 })\n }\n if (error.message === 'Access denied') {\n return Response.json({ error: error.message }, { status: 403 })\n }\n }\n throw error\n }\n\n}\n\nexport async function DELETE(req: Request, { params }: { params: { id: string } }) {\n const { ctx, scope } = await resolveMessageContext(req)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const commandBus = ctx.container.resolve('commandBus') as CommandBus\n\n const message = await em.findOne(Message, {\n id: params.id,\n tenantId: scope.tenantId,\n deletedAt: null,\n })\n\n if (!message) {\n return Response.json({ error: 'Message not found' }, { status: 404 })\n }\n\n if (!hasOrganizationAccess(scope.organizationId, message.organizationId)) {\n return Response.json({ error: 'Access denied' }, { status: 403 })\n }\n\n const guardResult = await runMessageMutationGuards(\n ctx.container,\n {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n userId: scope.userId,\n resourceKind: 'messages.message',\n resourceId: params.id,\n operation: 'delete',\n requestMethod: req.method,\n requestHeaders: req.headers,\n mutationPayload: null,\n },\n resolveUserFeatures(ctx.auth),\n )\n if (!guardResult.ok) {\n return Response.json(\n guardResult.errorBody ?? { error: 'Operation blocked by guard' },\n { status: guardResult.errorStatus ?? 422 },\n )\n }\n\n try {\n const { logEntry } = await commandBus.execute('messages.messages.delete_for_actor', {\n input: {\n messageId: params.id,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n userId: scope.userId,\n },\n ctx: {\n container: ctx.container,\n auth: ctx.auth ?? null,\n organizationScope: null,\n selectedOrganizationId: scope.organizationId,\n organizationIds: scope.organizationId ? [scope.organizationId] : null,\n request: req,\n },\n })\n\n const response = Response.json({ ok: true })\n attachOperationMetadataHeader(response, logEntry, {\n resourceKind: 'messages.message',\n resourceId: params.id,\n })\n await runMessageMutationGuardAfterSuccess(guardResult.afterSuccessCallbacks, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n userId: scope.userId,\n resourceKind: 'messages.message',\n resourceId: params.id,\n operation: 'delete',\n requestMethod: req.method,\n requestHeaders: req.headers,\n })\n return response\n } catch (error) {\n if (error instanceof Error && error.message === 'Access denied') {\n return Response.json({ error: 'Access denied' }, { status: 403 })\n }\n throw error\n }\n\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Messages',\n methods: {\n GET: {\n summary: 'Get message detail',\n responses: [\n {\n status: 200,\n description: 'Message detail with actor-visible thread items only',\n schema: messageDetailResponseSchema,\n },\n ],\n errors: [\n { status: 403, description: 'Access denied', schema: errorResponseSchema },\n { status: 404, description: 'Message not found', schema: errorResponseSchema },\n ],\n },\n PATCH: {\n summary: 'Update draft message',\n requestBody: { schema: updateDraftOpenApiSchema },\n responses: [\n { status: 200, description: 'Draft updated', schema: okResponseSchema },\n ],\n errors: [\n { status: 403, description: 'Access denied', schema: errorResponseSchema },\n { status: 404, description: 'Message not found', schema: errorResponseSchema },\n { status: 409, description: 'Only drafts can be edited', schema: errorResponseSchema },\n ],\n },\n DELETE: {\n summary: 'Delete message for current sender/recipient context',\n responses: [\n { status: 200, description: 'Message deleted', schema: okResponseSchema },\n ],\n errors: [\n { status: 403, description: 'Access denied', schema: errorResponseSchema },\n { status: 404, description: 'Message not found', schema: errorResponseSchema },\n ],\n },\n },\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -116,7 +116,9 @@ const messageDetailResponseSchema = z.object({
|
|
|
116
116
|
}).nullable().optional()
|
|
117
117
|
})),
|
|
118
118
|
thread: z.array(messageThreadItemSchema),
|
|
119
|
-
isRead: z.boolean()
|
|
119
|
+
isRead: z.boolean(),
|
|
120
|
+
conversationArchived: z.boolean(),
|
|
121
|
+
conversationAllUnread: z.boolean()
|
|
120
122
|
});
|
|
121
123
|
const messageTokenDetailResponseSchema = z.object({
|
|
122
124
|
id: z.string().uuid(),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/messages/api/openapi.ts"],
|
|
4
|
-
"sourcesContent": ["import { z } from 'zod'\nimport {\n attachmentIdsPayloadSchema,\n composeMessageSchema,\n executeActionSchema,\n forwardMessageSchema,\n listMessagesSchema,\n messageObjectTypesQuerySchema,\n messageActionDataSchema,\n messageActionSchema,\n messageObjectSchema,\n messageRecipientSchema,\n replyMessageSchema,\n unlinkAttachmentPayloadSchema,\n updateDraftSchema,\n} from '../data/validators'\n\nexport const messageAttachmentSchema = z.object({\n id: z.string().uuid(),\n fileName: z.string(),\n fileSize: z.number(),\n mimeType: z.string(),\n url: z.string(),\n})\n\nexport const messageListItemSchema = z.object({\n id: z.string().uuid(),\n type: z.string(),\n visibility: z.enum(['public', 'internal']).nullable().optional(),\n sourceEntityType: z.string().nullable().optional(),\n sourceEntityId: z.string().uuid().nullable().optional(),\n externalEmail: z.string().nullable().optional(),\n externalName: z.string().nullable().optional(),\n subject: z.string(),\n bodyPreview: z.string(),\n senderUserId: z.string().uuid(),\n senderName: z.string().nullable().optional(),\n senderEmail: z.string().nullable().optional(),\n priority: z.string(),\n status: z.string(),\n hasObjects: z.boolean(),\n objectCount: z.number(),\n hasAttachments: z.boolean(),\n attachmentCount: z.number(),\n recipientCount: z.number(),\n hasActions: z.boolean(),\n actionTaken: z.string().nullable().optional(),\n sentAt: z.string().nullable().optional(),\n readAt: z.string().nullable().optional(),\n threadId: z.string().uuid().nullable().optional(),\n})\n\nexport const messageThreadItemSchema = z.object({\n id: z.string().uuid(),\n senderUserId: z.string().uuid(),\n senderName: z.string().nullable().optional(),\n senderEmail: z.string().nullable().optional(),\n body: z.string(),\n bodyFormat: z.enum(['text', 'markdown']).optional(),\n sentAt: z.string().nullable().optional(),\n})\n\nexport const messageDetailResponseSchema = z.object({\n id: z.string().uuid(),\n type: z.string(),\n isDraft: z.boolean(),\n canEditDraft: z.boolean(),\n visibility: z.enum(['public', 'internal']).nullable().optional(),\n sourceEntityType: z.string().nullable().optional(),\n sourceEntityId: z.string().uuid().nullable().optional(),\n externalEmail: z.string().nullable().optional(),\n externalName: z.string().nullable().optional(),\n typeDefinition: z.object({\n labelKey: z.string(),\n icon: z.string(),\n color: z.string().optional().nullable(),\n allowReply: z.boolean(),\n allowForward: z.boolean(),\n ui: z.object({\n listItemComponent: z.string().nullable().optional(),\n contentComponent: z.string().nullable().optional(),\n actionsComponent: z.string().nullable().optional(),\n }).nullable().optional(),\n }),\n threadId: z.string().uuid().nullable().optional(),\n parentMessageId: z.string().uuid().nullable().optional(),\n senderUserId: z.string().uuid(),\n senderName: z.string().nullable().optional(),\n senderEmail: z.string().nullable().optional(),\n subject: z.string(),\n body: z.string(),\n bodyFormat: z.enum(['text', 'markdown']),\n priority: z.string(),\n sentAt: z.string().nullable().optional(),\n actionData: messageActionDataSchema.optional().nullable(),\n actionTaken: z.string().nullable().optional(),\n actionTakenAt: z.string().nullable().optional(),\n actionTakenByUserId: z.string().uuid().nullable().optional(),\n recipients: z.array(z.object({\n userId: z.string().uuid(),\n type: z.enum(['to', 'cc', 'bcc']),\n status: z.string(),\n readAt: z.string().nullable().optional(),\n })),\n objects: z.array(z.object({\n id: z.string().uuid(),\n entityModule: z.string(),\n entityType: z.string(),\n entityId: z.string().uuid(),\n actionRequired: z.boolean(),\n actionType: z.string().nullable().optional(),\n actionLabel: z.string().nullable().optional(),\n snapshot: z.record(z.string(), z.unknown()).nullable().optional(),\n preview: z.object({\n title: z.string(),\n subtitle: z.string().optional(),\n status: z.string().optional(),\n statusColor: z.string().optional(),\n metadata: z.record(z.string(), z.string()).optional(),\n }).nullable().optional(),\n })),\n thread: z.array(messageThreadItemSchema),\n isRead: z.boolean(),\n})\n\nexport const messageTokenDetailResponseSchema = z.object({\n id: z.string().uuid(),\n type: z.string(),\n subject: z.string(),\n body: z.string(),\n bodyFormat: z.enum(['text', 'markdown']),\n priority: z.enum(['low', 'normal', 'high', 'urgent']),\n senderUserId: z.string().uuid(),\n sentAt: z.string().nullable().optional(),\n actionData: messageActionDataSchema.optional().nullable(),\n actionTaken: z.string().nullable().optional(),\n actionTakenAt: z.string().nullable().optional(),\n actionTakenByUserId: z.string().uuid().nullable().optional(),\n objects: z.array(z.object({\n id: z.string().uuid(),\n entityModule: z.string(),\n entityType: z.string(),\n entityId: z.string().uuid(),\n actionRequired: z.boolean(),\n actionType: z.string().nullable().optional(),\n actionLabel: z.string().nullable().optional(),\n snapshot: z.record(z.string(), z.unknown()).nullable().optional(),\n })),\n requiresAuth: z.boolean(),\n recipientUserId: z.string().uuid(),\n})\n\nexport const messageTokenPreflightResponseSchema = z.object({\n requiresAuth: z.literal(true),\n})\n\nexport const messageTokenResponseSchema = z.union([\n messageTokenDetailResponseSchema,\n messageTokenPreflightResponseSchema,\n])\n\nexport const unreadCountResponseSchema = z.object({\n unreadCount: z.number(),\n})\n\nexport const messageConfirmationResponseSchema = z.object({\n messageId: z.string().uuid(),\n confirmed: z.boolean(),\n confirmedAt: z.string().nullable(),\n confirmedByUserId: z.string().uuid().nullable(),\n})\n\nexport const actionResultResponseSchema = z.object({\n ok: z.boolean(),\n actionId: z.string(),\n result: z.record(z.string(), z.unknown()).optional(),\n})\n\nexport const forwardResponseSchema = z.object({\n id: z.string().uuid(),\n})\n\nexport const forwardPreviewResponseSchema = z.object({\n subject: z.string(),\n body: z.string(),\n})\n\nexport const conversationMutationResponseSchema = z.object({\n ok: z.boolean(),\n affectedCount: z.number().int().min(0),\n})\n\nexport const composeResponseSchema = z.object({\n id: z.string().uuid(),\n threadId: z.string().uuid().nullable().optional(),\n})\n\nexport const messageAttachmentResponseSchema = z.object({\n attachments: z.array(messageAttachmentSchema),\n})\n\nexport const okResponseSchema = z.object({\n ok: z.boolean(),\n id: z.string().uuid().optional(),\n message: z.string().optional(),\n})\n\nexport const errorResponseSchema = z.object({\n error: z.string(),\n})\n\nexport const messageTypeResponseItemSchema = z.object({\n type: z.string(),\n module: z.string(),\n labelKey: z.string(),\n icon: z.string(),\n color: z.string().nullable().optional(),\n allowReply: z.boolean(),\n allowForward: z.boolean(),\n actionsExpireAfterHours: z.number().int().nullable().optional(),\n ui: z.object({\n listItemComponent: z.string().nullable().optional(),\n contentComponent: z.string().nullable().optional(),\n actionsComponent: z.string().nullable().optional(),\n }).nullable().optional(),\n})\n\nexport const messageTypeListResponseSchema = z.object({\n items: z.array(messageTypeResponseItemSchema),\n})\n\nexport const messageObjectTypeActionResponseSchema = z.object({\n id: z.string(),\n labelKey: z.string(),\n variant: z.enum(['default', 'secondary', 'destructive', 'outline']).optional(),\n icon: z.string().optional(),\n commandId: z.string().optional(),\n href: z.string().optional(),\n isTerminal: z.boolean().optional(),\n confirmRequired: z.boolean().optional(),\n confirmMessage: z.string().optional(),\n})\n\nexport const messageObjectTypeResponseItemSchema = z.object({\n module: z.string(),\n entityType: z.string(),\n labelKey: z.string(),\n icon: z.string(),\n actions: z.array(messageObjectTypeActionResponseSchema),\n})\n\nexport const messageObjectTypeListResponseSchema = z.object({\n items: z.array(messageObjectTypeResponseItemSchema),\n})\n\nexport {\n messageActionDataSchema,\n messageActionSchema,\n messageObjectSchema,\n messageRecipientSchema,\n composeMessageSchema,\n listMessagesSchema,\n forwardMessageSchema,\n replyMessageSchema,\n updateDraftSchema,\n executeActionSchema,\n messageObjectTypesQuerySchema,\n attachmentIdsPayloadSchema,\n unlinkAttachmentPayloadSchema,\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,SAAS;AAClB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEA,MAAM,0BAA0B,EAAE,OAAO;AAAA,EAC9C,IAAI,EAAE,OAAO,EAAE,KAAK;AAAA,EACpB,UAAU,EAAE,OAAO;AAAA,EACnB,UAAU,EAAE,OAAO;AAAA,EACnB,UAAU,EAAE,OAAO;AAAA,EACnB,KAAK,EAAE,OAAO;AAChB,CAAC;AAEM,MAAM,wBAAwB,EAAE,OAAO;AAAA,EAC5C,IAAI,EAAE,OAAO,EAAE,KAAK;AAAA,EACpB,MAAM,EAAE,OAAO;AAAA,EACf,YAAY,EAAE,KAAK,CAAC,UAAU,UAAU,CAAC,EAAE,SAAS,EAAE,SAAS;AAAA,EAC/D,kBAAkB,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EACjD,gBAAgB,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS;AAAA,EACtD,eAAe,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC9C,cAAc,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC7C,SAAS,EAAE,OAAO;AAAA,EAClB,aAAa,EAAE,OAAO;AAAA,EACtB,cAAc,EAAE,OAAO,EAAE,KAAK;AAAA,EAC9B,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC3C,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC5C,UAAU,EAAE,OAAO;AAAA,EACnB,QAAQ,EAAE,OAAO;AAAA,EACjB,YAAY,EAAE,QAAQ;AAAA,EACtB,aAAa,EAAE,OAAO;AAAA,EACtB,gBAAgB,EAAE,QAAQ;AAAA,EAC1B,iBAAiB,EAAE,OAAO;AAAA,EAC1B,gBAAgB,EAAE,OAAO;AAAA,EACzB,YAAY,EAAE,QAAQ;AAAA,EACtB,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC5C,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EACvC,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EACvC,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS;AAClD,CAAC;AAEM,MAAM,0BAA0B,EAAE,OAAO;AAAA,EAC9C,IAAI,EAAE,OAAO,EAAE,KAAK;AAAA,EACpB,cAAc,EAAE,OAAO,EAAE,KAAK;AAAA,EAC9B,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC3C,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC5C,MAAM,EAAE,OAAO;AAAA,EACf,YAAY,EAAE,KAAK,CAAC,QAAQ,UAAU,CAAC,EAAE,SAAS;AAAA,EAClD,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AACzC,CAAC;AAEM,MAAM,8BAA8B,EAAE,OAAO;AAAA,EAClD,IAAI,EAAE,OAAO,EAAE,KAAK;AAAA,EACpB,MAAM,EAAE,OAAO;AAAA,EACf,SAAS,EAAE,QAAQ;AAAA,EACnB,cAAc,EAAE,QAAQ;AAAA,EACxB,YAAY,EAAE,KAAK,CAAC,UAAU,UAAU,CAAC,EAAE,SAAS,EAAE,SAAS;AAAA,EAC/D,kBAAkB,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EACjD,gBAAgB,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS;AAAA,EACtD,eAAe,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC9C,cAAc,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC7C,gBAAgB,EAAE,OAAO;AAAA,IACvB,UAAU,EAAE,OAAO;AAAA,IACnB,MAAM,EAAE,OAAO;AAAA,IACf,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,IACtC,YAAY,EAAE,QAAQ;AAAA,IACtB,cAAc,EAAE,QAAQ;AAAA,IACxB,IAAI,EAAE,OAAO;AAAA,MACX,mBAAmB,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,MAClD,kBAAkB,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,MACjD,kBAAkB,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,IACnD,CAAC,EAAE,SAAS,EAAE,SAAS;AAAA,EACzB,CAAC;AAAA,EACD,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS;AAAA,EAChD,iBAAiB,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS;AAAA,EACvD,cAAc,EAAE,OAAO,EAAE,KAAK;AAAA,EAC9B,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC3C,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC5C,SAAS,EAAE,OAAO;AAAA,EAClB,MAAM,EAAE,OAAO;AAAA,EACf,YAAY,EAAE,KAAK,CAAC,QAAQ,UAAU,CAAC;AAAA,EACvC,UAAU,EAAE,OAAO;AAAA,EACnB,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EACvC,YAAY,wBAAwB,SAAS,EAAE,SAAS;AAAA,EACxD,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC5C,eAAe,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC9C,qBAAqB,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS;AAAA,EAC3D,YAAY,EAAE,MAAM,EAAE,OAAO;AAAA,IAC3B,QAAQ,EAAE,OAAO,EAAE,KAAK;AAAA,IACxB,MAAM,EAAE,KAAK,CAAC,MAAM,MAAM,KAAK,CAAC;AAAA,IAChC,QAAQ,EAAE,OAAO;AAAA,IACjB,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EACzC,CAAC,CAAC;AAAA,EACF,SAAS,EAAE,MAAM,EAAE,OAAO;AAAA,IACxB,IAAI,EAAE,OAAO,EAAE,KAAK;AAAA,IACpB,cAAc,EAAE,OAAO;AAAA,IACvB,YAAY,EAAE,OAAO;AAAA,IACrB,UAAU,EAAE,OAAO,EAAE,KAAK;AAAA,IAC1B,gBAAgB,EAAE,QAAQ;AAAA,IAC1B,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,IAC3C,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,IAC5C,UAAU,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,QAAQ,CAAC,EAAE,SAAS,EAAE,SAAS;AAAA,IAChE,SAAS,EAAE,OAAO;AAAA,MAChB,OAAO,EAAE,OAAO;AAAA,MAChB,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,MAC9B,QAAQ,EAAE,OAAO,EAAE,SAAS;AAAA,MAC5B,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA,MACjC,UAAU,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA,IACtD,CAAC,EAAE,SAAS,EAAE,SAAS;AAAA,EACzB,CAAC,CAAC;AAAA,EACF,QAAQ,EAAE,MAAM,uBAAuB;AAAA,EACvC,QAAQ,EAAE,QAAQ;
|
|
4
|
+
"sourcesContent": ["import { z } from 'zod'\nimport {\n attachmentIdsPayloadSchema,\n composeMessageSchema,\n executeActionSchema,\n forwardMessageSchema,\n listMessagesSchema,\n messageObjectTypesQuerySchema,\n messageActionDataSchema,\n messageActionSchema,\n messageObjectSchema,\n messageRecipientSchema,\n replyMessageSchema,\n unlinkAttachmentPayloadSchema,\n updateDraftSchema,\n} from '../data/validators'\n\nexport const messageAttachmentSchema = z.object({\n id: z.string().uuid(),\n fileName: z.string(),\n fileSize: z.number(),\n mimeType: z.string(),\n url: z.string(),\n})\n\nexport const messageListItemSchema = z.object({\n id: z.string().uuid(),\n type: z.string(),\n visibility: z.enum(['public', 'internal']).nullable().optional(),\n sourceEntityType: z.string().nullable().optional(),\n sourceEntityId: z.string().uuid().nullable().optional(),\n externalEmail: z.string().nullable().optional(),\n externalName: z.string().nullable().optional(),\n subject: z.string(),\n bodyPreview: z.string(),\n senderUserId: z.string().uuid(),\n senderName: z.string().nullable().optional(),\n senderEmail: z.string().nullable().optional(),\n priority: z.string(),\n status: z.string(),\n hasObjects: z.boolean(),\n objectCount: z.number(),\n hasAttachments: z.boolean(),\n attachmentCount: z.number(),\n recipientCount: z.number(),\n hasActions: z.boolean(),\n actionTaken: z.string().nullable().optional(),\n sentAt: z.string().nullable().optional(),\n readAt: z.string().nullable().optional(),\n threadId: z.string().uuid().nullable().optional(),\n})\n\nexport const messageThreadItemSchema = z.object({\n id: z.string().uuid(),\n senderUserId: z.string().uuid(),\n senderName: z.string().nullable().optional(),\n senderEmail: z.string().nullable().optional(),\n body: z.string(),\n bodyFormat: z.enum(['text', 'markdown']).optional(),\n sentAt: z.string().nullable().optional(),\n})\n\nexport const messageDetailResponseSchema = z.object({\n id: z.string().uuid(),\n type: z.string(),\n isDraft: z.boolean(),\n canEditDraft: z.boolean(),\n visibility: z.enum(['public', 'internal']).nullable().optional(),\n sourceEntityType: z.string().nullable().optional(),\n sourceEntityId: z.string().uuid().nullable().optional(),\n externalEmail: z.string().nullable().optional(),\n externalName: z.string().nullable().optional(),\n typeDefinition: z.object({\n labelKey: z.string(),\n icon: z.string(),\n color: z.string().optional().nullable(),\n allowReply: z.boolean(),\n allowForward: z.boolean(),\n ui: z.object({\n listItemComponent: z.string().nullable().optional(),\n contentComponent: z.string().nullable().optional(),\n actionsComponent: z.string().nullable().optional(),\n }).nullable().optional(),\n }),\n threadId: z.string().uuid().nullable().optional(),\n parentMessageId: z.string().uuid().nullable().optional(),\n senderUserId: z.string().uuid(),\n senderName: z.string().nullable().optional(),\n senderEmail: z.string().nullable().optional(),\n subject: z.string(),\n body: z.string(),\n bodyFormat: z.enum(['text', 'markdown']),\n priority: z.string(),\n sentAt: z.string().nullable().optional(),\n actionData: messageActionDataSchema.optional().nullable(),\n actionTaken: z.string().nullable().optional(),\n actionTakenAt: z.string().nullable().optional(),\n actionTakenByUserId: z.string().uuid().nullable().optional(),\n recipients: z.array(z.object({\n userId: z.string().uuid(),\n type: z.enum(['to', 'cc', 'bcc']),\n status: z.string(),\n readAt: z.string().nullable().optional(),\n })),\n objects: z.array(z.object({\n id: z.string().uuid(),\n entityModule: z.string(),\n entityType: z.string(),\n entityId: z.string().uuid(),\n actionRequired: z.boolean(),\n actionType: z.string().nullable().optional(),\n actionLabel: z.string().nullable().optional(),\n snapshot: z.record(z.string(), z.unknown()).nullable().optional(),\n preview: z.object({\n title: z.string(),\n subtitle: z.string().optional(),\n status: z.string().optional(),\n statusColor: z.string().optional(),\n metadata: z.record(z.string(), z.string()).optional(),\n }).nullable().optional(),\n })),\n thread: z.array(messageThreadItemSchema),\n isRead: z.boolean(),\n conversationArchived: z.boolean(),\n conversationAllUnread: z.boolean(),\n})\n\nexport const messageTokenDetailResponseSchema = z.object({\n id: z.string().uuid(),\n type: z.string(),\n subject: z.string(),\n body: z.string(),\n bodyFormat: z.enum(['text', 'markdown']),\n priority: z.enum(['low', 'normal', 'high', 'urgent']),\n senderUserId: z.string().uuid(),\n sentAt: z.string().nullable().optional(),\n actionData: messageActionDataSchema.optional().nullable(),\n actionTaken: z.string().nullable().optional(),\n actionTakenAt: z.string().nullable().optional(),\n actionTakenByUserId: z.string().uuid().nullable().optional(),\n objects: z.array(z.object({\n id: z.string().uuid(),\n entityModule: z.string(),\n entityType: z.string(),\n entityId: z.string().uuid(),\n actionRequired: z.boolean(),\n actionType: z.string().nullable().optional(),\n actionLabel: z.string().nullable().optional(),\n snapshot: z.record(z.string(), z.unknown()).nullable().optional(),\n })),\n requiresAuth: z.boolean(),\n recipientUserId: z.string().uuid(),\n})\n\nexport const messageTokenPreflightResponseSchema = z.object({\n requiresAuth: z.literal(true),\n})\n\nexport const messageTokenResponseSchema = z.union([\n messageTokenDetailResponseSchema,\n messageTokenPreflightResponseSchema,\n])\n\nexport const unreadCountResponseSchema = z.object({\n unreadCount: z.number(),\n})\n\nexport const messageConfirmationResponseSchema = z.object({\n messageId: z.string().uuid(),\n confirmed: z.boolean(),\n confirmedAt: z.string().nullable(),\n confirmedByUserId: z.string().uuid().nullable(),\n})\n\nexport const actionResultResponseSchema = z.object({\n ok: z.boolean(),\n actionId: z.string(),\n result: z.record(z.string(), z.unknown()).optional(),\n})\n\nexport const forwardResponseSchema = z.object({\n id: z.string().uuid(),\n})\n\nexport const forwardPreviewResponseSchema = z.object({\n subject: z.string(),\n body: z.string(),\n})\n\nexport const conversationMutationResponseSchema = z.object({\n ok: z.boolean(),\n affectedCount: z.number().int().min(0),\n})\n\nexport const composeResponseSchema = z.object({\n id: z.string().uuid(),\n threadId: z.string().uuid().nullable().optional(),\n})\n\nexport const messageAttachmentResponseSchema = z.object({\n attachments: z.array(messageAttachmentSchema),\n})\n\nexport const okResponseSchema = z.object({\n ok: z.boolean(),\n id: z.string().uuid().optional(),\n message: z.string().optional(),\n})\n\nexport const errorResponseSchema = z.object({\n error: z.string(),\n})\n\nexport const messageTypeResponseItemSchema = z.object({\n type: z.string(),\n module: z.string(),\n labelKey: z.string(),\n icon: z.string(),\n color: z.string().nullable().optional(),\n allowReply: z.boolean(),\n allowForward: z.boolean(),\n actionsExpireAfterHours: z.number().int().nullable().optional(),\n ui: z.object({\n listItemComponent: z.string().nullable().optional(),\n contentComponent: z.string().nullable().optional(),\n actionsComponent: z.string().nullable().optional(),\n }).nullable().optional(),\n})\n\nexport const messageTypeListResponseSchema = z.object({\n items: z.array(messageTypeResponseItemSchema),\n})\n\nexport const messageObjectTypeActionResponseSchema = z.object({\n id: z.string(),\n labelKey: z.string(),\n variant: z.enum(['default', 'secondary', 'destructive', 'outline']).optional(),\n icon: z.string().optional(),\n commandId: z.string().optional(),\n href: z.string().optional(),\n isTerminal: z.boolean().optional(),\n confirmRequired: z.boolean().optional(),\n confirmMessage: z.string().optional(),\n})\n\nexport const messageObjectTypeResponseItemSchema = z.object({\n module: z.string(),\n entityType: z.string(),\n labelKey: z.string(),\n icon: z.string(),\n actions: z.array(messageObjectTypeActionResponseSchema),\n})\n\nexport const messageObjectTypeListResponseSchema = z.object({\n items: z.array(messageObjectTypeResponseItemSchema),\n})\n\nexport {\n messageActionDataSchema,\n messageActionSchema,\n messageObjectSchema,\n messageRecipientSchema,\n composeMessageSchema,\n listMessagesSchema,\n forwardMessageSchema,\n replyMessageSchema,\n updateDraftSchema,\n executeActionSchema,\n messageObjectTypesQuerySchema,\n attachmentIdsPayloadSchema,\n unlinkAttachmentPayloadSchema,\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -182,6 +182,81 @@ const markConversationUnreadForActorCommand = {
|
|
|
182
182
|
return { ok: true, affectedCount: markedIds.length };
|
|
183
183
|
}
|
|
184
184
|
};
|
|
185
|
+
const unarchiveConversationForActorCommand = {
|
|
186
|
+
id: "messages.conversation.unarchive_for_actor",
|
|
187
|
+
async execute(rawInput, ctx) {
|
|
188
|
+
const input = conversationCommandSchema.parse(rawInput);
|
|
189
|
+
const em = ctx.container.resolve("em").fork();
|
|
190
|
+
const scope = await resolveConversationScope(em, input);
|
|
191
|
+
const messageIdsToUnarchive = scope.messageIds.filter((messageId) => scope.recipientMessageIds.has(messageId));
|
|
192
|
+
if (messageIdsToUnarchive.length === 0) {
|
|
193
|
+
return { ok: true, affectedCount: 0 };
|
|
194
|
+
}
|
|
195
|
+
const unarchivedIds = [];
|
|
196
|
+
await em.transactional(async (trx) => {
|
|
197
|
+
const recipients = await trx.find(MessageRecipient, {
|
|
198
|
+
messageId: { $in: messageIdsToUnarchive },
|
|
199
|
+
recipientUserId: input.userId,
|
|
200
|
+
deletedAt: null
|
|
201
|
+
});
|
|
202
|
+
for (const recipient of recipients) {
|
|
203
|
+
if (recipient.status === "archived" || recipient.archivedAt !== null) {
|
|
204
|
+
recipient.archivedAt = null;
|
|
205
|
+
recipient.status = recipient.readAt ? "read" : "unread";
|
|
206
|
+
unarchivedIds.push(recipient.messageId);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
for (const messageId of unarchivedIds) {
|
|
211
|
+
await emitMessagesEvent("messages.message.unarchived", {
|
|
212
|
+
messageId,
|
|
213
|
+
recipientUserId: input.userId,
|
|
214
|
+
userId: input.userId,
|
|
215
|
+
tenantId: input.tenantId,
|
|
216
|
+
organizationId: input.organizationId
|
|
217
|
+
}, { persistent: true });
|
|
218
|
+
}
|
|
219
|
+
return { ok: true, affectedCount: unarchivedIds.length };
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
const markConversationReadForActorCommand = {
|
|
223
|
+
id: "messages.conversation.mark_read_for_actor",
|
|
224
|
+
async execute(rawInput, ctx) {
|
|
225
|
+
const input = conversationCommandSchema.parse(rawInput);
|
|
226
|
+
const em = ctx.container.resolve("em").fork();
|
|
227
|
+
const scope = await resolveConversationScope(em, input);
|
|
228
|
+
const messageIdsToMarkRead = scope.messageIds.filter((messageId) => scope.recipientMessageIds.has(messageId));
|
|
229
|
+
if (messageIdsToMarkRead.length === 0) {
|
|
230
|
+
return { ok: true, affectedCount: 0 };
|
|
231
|
+
}
|
|
232
|
+
const readAt = /* @__PURE__ */ new Date();
|
|
233
|
+
const markedIds = [];
|
|
234
|
+
await em.transactional(async (trx) => {
|
|
235
|
+
const recipients = await trx.find(MessageRecipient, {
|
|
236
|
+
messageId: { $in: messageIdsToMarkRead },
|
|
237
|
+
recipientUserId: input.userId,
|
|
238
|
+
deletedAt: null
|
|
239
|
+
});
|
|
240
|
+
for (const recipient of recipients) {
|
|
241
|
+
if (recipient.status === "unread") {
|
|
242
|
+
recipient.status = "read";
|
|
243
|
+
recipient.readAt = readAt;
|
|
244
|
+
markedIds.push(recipient.messageId);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
for (const messageId of markedIds) {
|
|
249
|
+
await emitMessagesEvent("messages.message.read", {
|
|
250
|
+
messageId,
|
|
251
|
+
recipientUserId: input.userId,
|
|
252
|
+
userId: input.userId,
|
|
253
|
+
tenantId: input.tenantId,
|
|
254
|
+
organizationId: input.organizationId
|
|
255
|
+
}, { persistent: true });
|
|
256
|
+
}
|
|
257
|
+
return { ok: true, affectedCount: markedIds.length };
|
|
258
|
+
}
|
|
259
|
+
};
|
|
185
260
|
const deleteConversationForActorCommand = {
|
|
186
261
|
id: "messages.conversation.delete_for_actor",
|
|
187
262
|
async execute(rawInput, ctx) {
|
|
@@ -236,6 +311,8 @@ const deleteConversationForActorCommand = {
|
|
|
236
311
|
}
|
|
237
312
|
};
|
|
238
313
|
registerCommand(archiveConversationForActorCommand);
|
|
314
|
+
registerCommand(unarchiveConversationForActorCommand);
|
|
239
315
|
registerCommand(markConversationUnreadForActorCommand);
|
|
316
|
+
registerCommand(markConversationReadForActorCommand);
|
|
240
317
|
registerCommand(deleteConversationForActorCommand);
|
|
241
318
|
//# sourceMappingURL=conversation.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/messages/commands/conversation.ts"],
|
|
4
|
-
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { z } from 'zod'\nimport { registerCommand, type CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { Message, MessageRecipient } from '../data/entities'\nimport { emitMessagesEvent } from '../events'\nimport { assertOrganizationAccess, type MessageScopeInput } from './shared'\n\nconst conversationCommandSchema = z.object({\n anchorMessageId: z.string().uuid(),\n tenantId: z.string().uuid(),\n organizationId: z.string().uuid().nullable(),\n userId: z.string().uuid(),\n})\n\ntype ConversationCommandInput = z.infer<typeof conversationCommandSchema>\n\ntype ConversationScope = {\n anchorMessageId: string\n messageIds: string[]\n recipientMessageIds: Set<string>\n senderMessageIds: Set<string>\n}\n\nasync function resolveConversationScope(\n em: EntityManager,\n input: ConversationCommandInput,\n): Promise<ConversationScope> {\n const anchorMessage = await em.findOne(Message, {\n id: input.anchorMessageId,\n tenantId: input.tenantId,\n deletedAt: null,\n })\n\n if (!anchorMessage) throw new Error('Message not found')\n assertOrganizationAccess(input as MessageScopeInput, anchorMessage)\n\n const anchorRecipient = await em.findOne(MessageRecipient, {\n messageId: input.anchorMessageId,\n recipientUserId: input.userId,\n deletedAt: null,\n })\n\n const canAccessAnchor = anchorMessage.senderUserId === input.userId || Boolean(anchorRecipient)\n if (!canAccessAnchor) throw new Error('Access denied')\n\n const threadId = anchorMessage.threadId ?? anchorMessage.id\n const conversationMessages = await em.find(\n Message,\n {\n threadId,\n tenantId: input.tenantId,\n organizationId: input.organizationId,\n deletedAt: null,\n isDraft: false,\n },\n {\n orderBy: {\n sentAt: 'ASC',\n createdAt: 'ASC',\n id: 'ASC',\n },\n },\n )\n\n const messagesById = new Map<string, Message>(conversationMessages.map((message) => [message.id, message]))\n messagesById.set(anchorMessage.id, anchorMessage)\n\n if (anchorMessage.threadId && !messagesById.has(anchorMessage.threadId)) {\n const threadRoot = await em.findOne(Message, {\n id: anchorMessage.threadId,\n tenantId: input.tenantId,\n organizationId: input.organizationId,\n deletedAt: null,\n isDraft: false,\n })\n if (threadRoot) {\n messagesById.set(threadRoot.id, threadRoot)\n }\n }\n\n let parentMessageId = anchorMessage.parentMessageId ?? null\n while (parentMessageId) {\n if (messagesById.has(parentMessageId)) break\n const parentMessage = await em.findOne(Message, {\n id: parentMessageId,\n tenantId: input.tenantId,\n organizationId: input.organizationId,\n deletedAt: null,\n isDraft: false,\n })\n if (!parentMessage) break\n messagesById.set(parentMessage.id, parentMessage)\n parentMessageId = parentMessage.parentMessageId ?? null\n }\n\n let frontier = Array.from(messagesById.keys())\n while (frontier.length > 0) {\n const children = await em.find(Message, {\n parentMessageId: { $in: frontier },\n tenantId: input.tenantId,\n organizationId: input.organizationId,\n deletedAt: null,\n isDraft: false,\n })\n\n const nextFrontier: string[] = []\n for (const child of children) {\n if (messagesById.has(child.id)) continue\n messagesById.set(child.id, child)\n nextFrontier.push(child.id)\n }\n frontier = nextFrontier\n }\n\n const scopedMessages = Array.from(messagesById.values())\n const messageIds = scopedMessages.map((message) => message.id)\n const recipientRows = messageIds.length > 0\n ? await em.find(MessageRecipient, {\n messageId: { $in: messageIds },\n recipientUserId: input.userId,\n deletedAt: null,\n })\n : []\n\n const recipientMessageIds = new Set(recipientRows.map((item) => item.messageId))\n const senderMessageIds = new Set(\n scopedMessages\n .filter((item) => item.senderUserId === input.userId)\n .map((item) => item.id),\n )\n\n const visibleMessageIds = scopedMessages\n .map((item) => item.id)\n .filter((messageId) => recipientMessageIds.has(messageId) || senderMessageIds.has(messageId))\n\n if (visibleMessageIds.length === 0) throw new Error('Access denied')\n\n return {\n anchorMessageId: anchorMessage.id,\n messageIds: visibleMessageIds,\n recipientMessageIds,\n senderMessageIds,\n }\n}\n\nconst archiveConversationForActorCommand: CommandHandler<unknown, { ok: true; affectedCount: number }> = {\n id: 'messages.conversation.archive_for_actor',\n async execute(rawInput, ctx) {\n const input = conversationCommandSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = await resolveConversationScope(em, input)\n const messageIdsToArchive = scope.messageIds.filter((messageId) => scope.recipientMessageIds.has(messageId))\n\n if (messageIdsToArchive.length === 0) {\n return { ok: true, affectedCount: 0 }\n }\n\n const archivedAt = new Date()\n const archivedIds: string[] = []\n await em.transactional(async (trx) => {\n const recipients = await trx.find(MessageRecipient, {\n messageId: { $in: messageIdsToArchive },\n recipientUserId: input.userId,\n deletedAt: null,\n })\n for (const recipient of recipients) {\n if (recipient.status !== 'archived' || recipient.archivedAt === null) {\n recipient.archivedAt = archivedAt\n recipient.status = 'archived'\n archivedIds.push(recipient.messageId)\n }\n }\n })\n\n for (const messageId of archivedIds) {\n await emitMessagesEvent('messages.message.archived', {\n messageId,\n recipientUserId: input.userId,\n userId: input.userId,\n tenantId: input.tenantId,\n organizationId: input.organizationId,\n }, { persistent: true })\n }\n\n return { ok: true, affectedCount: archivedIds.length }\n },\n}\n\nconst markConversationUnreadForActorCommand: CommandHandler<unknown, { ok: true; affectedCount: number }> = {\n id: 'messages.conversation.mark_unread_for_actor',\n async execute(rawInput, ctx) {\n const input = conversationCommandSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = await resolveConversationScope(em, input)\n const messageIdsToMarkUnread = scope.messageIds.filter((messageId) => scope.recipientMessageIds.has(messageId))\n\n if (messageIdsToMarkUnread.length === 0) {\n return { ok: true, affectedCount: 0 }\n }\n\n const markedIds: string[] = []\n await em.transactional(async (trx) => {\n const recipients = await trx.find(MessageRecipient, {\n messageId: { $in: messageIdsToMarkUnread },\n recipientUserId: input.userId,\n deletedAt: null,\n })\n for (const recipient of recipients) {\n if (recipient.status !== 'unread' || recipient.readAt !== null) {\n recipient.status = 'unread'\n recipient.readAt = null\n markedIds.push(recipient.messageId)\n }\n }\n })\n\n for (const messageId of markedIds) {\n await emitMessagesEvent('messages.message.marked_unread', {\n messageId,\n recipientUserId: input.userId,\n userId: input.userId,\n tenantId: input.tenantId,\n organizationId: input.organizationId,\n }, { persistent: true })\n }\n\n return { ok: true, affectedCount: markedIds.length }\n },\n}\n\ntype DeletedTarget = { messageId: string; target: 'sender' | 'recipient' }\n\nconst deleteConversationForActorCommand: CommandHandler<unknown, { ok: true; affectedCount: number }> = {\n id: 'messages.conversation.delete_for_actor',\n async execute(rawInput, ctx) {\n const input = conversationCommandSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = await resolveConversationScope(em, input)\n const messageIdsToDelete = scope.messageIds.filter(\n (messageId) => scope.recipientMessageIds.has(messageId) || scope.senderMessageIds.has(messageId),\n )\n\n if (messageIdsToDelete.length === 0) {\n return { ok: true, affectedCount: 0 }\n }\n\n const deletedNow = new Date()\n const deletedTargets: DeletedTarget[] = []\n await em.transactional(async (trx) => {\n for (const messageId of messageIdsToDelete) {\n const recipient = await trx.findOne(MessageRecipient, {\n messageId,\n recipientUserId: input.userId,\n deletedAt: null,\n })\n if (recipient) {\n recipient.status = 'deleted'\n recipient.deletedAt = deletedNow\n deletedTargets.push({ messageId, target: 'recipient' })\n continue\n }\n if (scope.senderMessageIds.has(messageId)) {\n const message = await trx.findOne(Message, {\n id: messageId,\n tenantId: input.tenantId,\n deletedAt: null,\n })\n if (message && message.senderUserId === input.userId) {\n message.deletedAt = deletedNow\n deletedTargets.push({ messageId, target: 'sender' })\n }\n }\n }\n })\n\n for (const { messageId, target } of deletedTargets) {\n await emitMessagesEvent('messages.message.deleted', {\n messageId,\n actorUserId: input.userId,\n recipientUserId: input.userId,\n target,\n tenantId: input.tenantId,\n organizationId: input.organizationId,\n }, { persistent: true })\n }\n\n return { ok: true, affectedCount: deletedTargets.length }\n },\n}\n\nregisterCommand(archiveConversationForActorCommand)\nregisterCommand(markConversationUnreadForActorCommand)\nregisterCommand(deleteConversationForActorCommand)\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { z } from 'zod'\nimport { registerCommand, type CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { Message, MessageRecipient } from '../data/entities'\nimport { emitMessagesEvent } from '../events'\nimport { assertOrganizationAccess, type MessageScopeInput } from './shared'\n\nconst conversationCommandSchema = z.object({\n anchorMessageId: z.string().uuid(),\n tenantId: z.string().uuid(),\n organizationId: z.string().uuid().nullable(),\n userId: z.string().uuid(),\n})\n\ntype ConversationCommandInput = z.infer<typeof conversationCommandSchema>\n\ntype ConversationScope = {\n anchorMessageId: string\n messageIds: string[]\n recipientMessageIds: Set<string>\n senderMessageIds: Set<string>\n}\n\nasync function resolveConversationScope(\n em: EntityManager,\n input: ConversationCommandInput,\n): Promise<ConversationScope> {\n const anchorMessage = await em.findOne(Message, {\n id: input.anchorMessageId,\n tenantId: input.tenantId,\n deletedAt: null,\n })\n\n if (!anchorMessage) throw new Error('Message not found')\n assertOrganizationAccess(input as MessageScopeInput, anchorMessage)\n\n const anchorRecipient = await em.findOne(MessageRecipient, {\n messageId: input.anchorMessageId,\n recipientUserId: input.userId,\n deletedAt: null,\n })\n\n const canAccessAnchor = anchorMessage.senderUserId === input.userId || Boolean(anchorRecipient)\n if (!canAccessAnchor) throw new Error('Access denied')\n\n const threadId = anchorMessage.threadId ?? anchorMessage.id\n const conversationMessages = await em.find(\n Message,\n {\n threadId,\n tenantId: input.tenantId,\n organizationId: input.organizationId,\n deletedAt: null,\n isDraft: false,\n },\n {\n orderBy: {\n sentAt: 'ASC',\n createdAt: 'ASC',\n id: 'ASC',\n },\n },\n )\n\n const messagesById = new Map<string, Message>(conversationMessages.map((message) => [message.id, message]))\n messagesById.set(anchorMessage.id, anchorMessage)\n\n if (anchorMessage.threadId && !messagesById.has(anchorMessage.threadId)) {\n const threadRoot = await em.findOne(Message, {\n id: anchorMessage.threadId,\n tenantId: input.tenantId,\n organizationId: input.organizationId,\n deletedAt: null,\n isDraft: false,\n })\n if (threadRoot) {\n messagesById.set(threadRoot.id, threadRoot)\n }\n }\n\n let parentMessageId = anchorMessage.parentMessageId ?? null\n while (parentMessageId) {\n if (messagesById.has(parentMessageId)) break\n const parentMessage = await em.findOne(Message, {\n id: parentMessageId,\n tenantId: input.tenantId,\n organizationId: input.organizationId,\n deletedAt: null,\n isDraft: false,\n })\n if (!parentMessage) break\n messagesById.set(parentMessage.id, parentMessage)\n parentMessageId = parentMessage.parentMessageId ?? null\n }\n\n let frontier = Array.from(messagesById.keys())\n while (frontier.length > 0) {\n const children = await em.find(Message, {\n parentMessageId: { $in: frontier },\n tenantId: input.tenantId,\n organizationId: input.organizationId,\n deletedAt: null,\n isDraft: false,\n })\n\n const nextFrontier: string[] = []\n for (const child of children) {\n if (messagesById.has(child.id)) continue\n messagesById.set(child.id, child)\n nextFrontier.push(child.id)\n }\n frontier = nextFrontier\n }\n\n const scopedMessages = Array.from(messagesById.values())\n const messageIds = scopedMessages.map((message) => message.id)\n const recipientRows = messageIds.length > 0\n ? await em.find(MessageRecipient, {\n messageId: { $in: messageIds },\n recipientUserId: input.userId,\n deletedAt: null,\n })\n : []\n\n const recipientMessageIds = new Set(recipientRows.map((item) => item.messageId))\n const senderMessageIds = new Set(\n scopedMessages\n .filter((item) => item.senderUserId === input.userId)\n .map((item) => item.id),\n )\n\n const visibleMessageIds = scopedMessages\n .map((item) => item.id)\n .filter((messageId) => recipientMessageIds.has(messageId) || senderMessageIds.has(messageId))\n\n if (visibleMessageIds.length === 0) throw new Error('Access denied')\n\n return {\n anchorMessageId: anchorMessage.id,\n messageIds: visibleMessageIds,\n recipientMessageIds,\n senderMessageIds,\n }\n}\n\nconst archiveConversationForActorCommand: CommandHandler<unknown, { ok: true; affectedCount: number }> = {\n id: 'messages.conversation.archive_for_actor',\n async execute(rawInput, ctx) {\n const input = conversationCommandSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = await resolveConversationScope(em, input)\n const messageIdsToArchive = scope.messageIds.filter((messageId) => scope.recipientMessageIds.has(messageId))\n\n if (messageIdsToArchive.length === 0) {\n return { ok: true, affectedCount: 0 }\n }\n\n const archivedAt = new Date()\n const archivedIds: string[] = []\n await em.transactional(async (trx) => {\n const recipients = await trx.find(MessageRecipient, {\n messageId: { $in: messageIdsToArchive },\n recipientUserId: input.userId,\n deletedAt: null,\n })\n for (const recipient of recipients) {\n if (recipient.status !== 'archived' || recipient.archivedAt === null) {\n recipient.archivedAt = archivedAt\n recipient.status = 'archived'\n archivedIds.push(recipient.messageId)\n }\n }\n })\n\n for (const messageId of archivedIds) {\n await emitMessagesEvent('messages.message.archived', {\n messageId,\n recipientUserId: input.userId,\n userId: input.userId,\n tenantId: input.tenantId,\n organizationId: input.organizationId,\n }, { persistent: true })\n }\n\n return { ok: true, affectedCount: archivedIds.length }\n },\n}\n\nconst markConversationUnreadForActorCommand: CommandHandler<unknown, { ok: true; affectedCount: number }> = {\n id: 'messages.conversation.mark_unread_for_actor',\n async execute(rawInput, ctx) {\n const input = conversationCommandSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = await resolveConversationScope(em, input)\n const messageIdsToMarkUnread = scope.messageIds.filter((messageId) => scope.recipientMessageIds.has(messageId))\n\n if (messageIdsToMarkUnread.length === 0) {\n return { ok: true, affectedCount: 0 }\n }\n\n const markedIds: string[] = []\n await em.transactional(async (trx) => {\n const recipients = await trx.find(MessageRecipient, {\n messageId: { $in: messageIdsToMarkUnread },\n recipientUserId: input.userId,\n deletedAt: null,\n })\n for (const recipient of recipients) {\n if (recipient.status !== 'unread' || recipient.readAt !== null) {\n recipient.status = 'unread'\n recipient.readAt = null\n markedIds.push(recipient.messageId)\n }\n }\n })\n\n for (const messageId of markedIds) {\n await emitMessagesEvent('messages.message.marked_unread', {\n messageId,\n recipientUserId: input.userId,\n userId: input.userId,\n tenantId: input.tenantId,\n organizationId: input.organizationId,\n }, { persistent: true })\n }\n\n return { ok: true, affectedCount: markedIds.length }\n },\n}\n\nconst unarchiveConversationForActorCommand: CommandHandler<unknown, { ok: true; affectedCount: number }> = {\n id: 'messages.conversation.unarchive_for_actor',\n async execute(rawInput, ctx) {\n const input = conversationCommandSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = await resolveConversationScope(em, input)\n const messageIdsToUnarchive = scope.messageIds.filter((messageId) => scope.recipientMessageIds.has(messageId))\n\n if (messageIdsToUnarchive.length === 0) {\n return { ok: true, affectedCount: 0 }\n }\n\n const unarchivedIds: string[] = []\n await em.transactional(async (trx) => {\n const recipients = await trx.find(MessageRecipient, {\n messageId: { $in: messageIdsToUnarchive },\n recipientUserId: input.userId,\n deletedAt: null,\n })\n for (const recipient of recipients) {\n if (recipient.status === 'archived' || recipient.archivedAt !== null) {\n recipient.archivedAt = null\n recipient.status = recipient.readAt ? 'read' : 'unread'\n unarchivedIds.push(recipient.messageId)\n }\n }\n })\n\n for (const messageId of unarchivedIds) {\n await emitMessagesEvent('messages.message.unarchived', {\n messageId,\n recipientUserId: input.userId,\n userId: input.userId,\n tenantId: input.tenantId,\n organizationId: input.organizationId,\n }, { persistent: true })\n }\n\n return { ok: true, affectedCount: unarchivedIds.length }\n },\n}\n\nconst markConversationReadForActorCommand: CommandHandler<unknown, { ok: true; affectedCount: number }> = {\n id: 'messages.conversation.mark_read_for_actor',\n async execute(rawInput, ctx) {\n const input = conversationCommandSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = await resolveConversationScope(em, input)\n const messageIdsToMarkRead = scope.messageIds.filter((messageId) => scope.recipientMessageIds.has(messageId))\n\n if (messageIdsToMarkRead.length === 0) {\n return { ok: true, affectedCount: 0 }\n }\n\n const readAt = new Date()\n const markedIds: string[] = []\n await em.transactional(async (trx) => {\n const recipients = await trx.find(MessageRecipient, {\n messageId: { $in: messageIdsToMarkRead },\n recipientUserId: input.userId,\n deletedAt: null,\n })\n for (const recipient of recipients) {\n if (recipient.status === 'unread') {\n recipient.status = 'read'\n recipient.readAt = readAt\n markedIds.push(recipient.messageId)\n }\n }\n })\n\n for (const messageId of markedIds) {\n await emitMessagesEvent('messages.message.read', {\n messageId,\n recipientUserId: input.userId,\n userId: input.userId,\n tenantId: input.tenantId,\n organizationId: input.organizationId,\n }, { persistent: true })\n }\n\n return { ok: true, affectedCount: markedIds.length }\n },\n}\n\ntype DeletedTarget = { messageId: string; target: 'sender' | 'recipient' }\n\nconst deleteConversationForActorCommand: CommandHandler<unknown, { ok: true; affectedCount: number }> = {\n id: 'messages.conversation.delete_for_actor',\n async execute(rawInput, ctx) {\n const input = conversationCommandSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = await resolveConversationScope(em, input)\n const messageIdsToDelete = scope.messageIds.filter(\n (messageId) => scope.recipientMessageIds.has(messageId) || scope.senderMessageIds.has(messageId),\n )\n\n if (messageIdsToDelete.length === 0) {\n return { ok: true, affectedCount: 0 }\n }\n\n const deletedNow = new Date()\n const deletedTargets: DeletedTarget[] = []\n await em.transactional(async (trx) => {\n for (const messageId of messageIdsToDelete) {\n const recipient = await trx.findOne(MessageRecipient, {\n messageId,\n recipientUserId: input.userId,\n deletedAt: null,\n })\n if (recipient) {\n recipient.status = 'deleted'\n recipient.deletedAt = deletedNow\n deletedTargets.push({ messageId, target: 'recipient' })\n continue\n }\n if (scope.senderMessageIds.has(messageId)) {\n const message = await trx.findOne(Message, {\n id: messageId,\n tenantId: input.tenantId,\n deletedAt: null,\n })\n if (message && message.senderUserId === input.userId) {\n message.deletedAt = deletedNow\n deletedTargets.push({ messageId, target: 'sender' })\n }\n }\n }\n })\n\n for (const { messageId, target } of deletedTargets) {\n await emitMessagesEvent('messages.message.deleted', {\n messageId,\n actorUserId: input.userId,\n recipientUserId: input.userId,\n target,\n tenantId: input.tenantId,\n organizationId: input.organizationId,\n }, { persistent: true })\n }\n\n return { ok: true, affectedCount: deletedTargets.length }\n },\n}\n\nregisterCommand(archiveConversationForActorCommand)\nregisterCommand(unarchiveConversationForActorCommand)\nregisterCommand(markConversationUnreadForActorCommand)\nregisterCommand(markConversationReadForActorCommand)\nregisterCommand(deleteConversationForActorCommand)\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -189,6 +189,8 @@ function MessageDetailPageClient({ id }) {
|
|
|
189
189
|
const firstConversationMessageId = state.conversationItems[0]?.id ?? null;
|
|
190
190
|
const latestConversationMessageId = state.conversationItems[state.conversationItems.length - 1]?.id ?? null;
|
|
191
191
|
const canRunConversationActions = Boolean(firstConversationMessageId);
|
|
192
|
+
const conversationArchived = Boolean(detail.conversationArchived);
|
|
193
|
+
const conversationAllUnread = Boolean(detail.conversationAllUnread);
|
|
192
194
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
193
195
|
/* @__PURE__ */ jsx(
|
|
194
196
|
MainMessageHeader,
|
|
@@ -197,6 +199,8 @@ function MessageDetailPageClient({ id }) {
|
|
|
197
199
|
priority: detail.priority ?? "normal",
|
|
198
200
|
canReply: !detail.isDraft && detail.typeDefinition.allowReply && Boolean(firstConversationMessageId),
|
|
199
201
|
canForwardAll: !detail.isDraft && detail.typeDefinition.allowForward && Boolean(latestConversationMessageId),
|
|
202
|
+
conversationArchived,
|
|
203
|
+
conversationAllUnread,
|
|
200
204
|
actionsDisabled: Boolean(state.activeConversationAction),
|
|
201
205
|
activeActionId: state.activeConversationAction,
|
|
202
206
|
onReply: () => {
|
|
@@ -213,13 +217,21 @@ function MessageDetailPageClient({ id }) {
|
|
|
213
217
|
messageId: latestConversationMessageId
|
|
214
218
|
});
|
|
215
219
|
},
|
|
216
|
-
|
|
220
|
+
onToggleArchiveConversation: () => {
|
|
217
221
|
if (!canRunConversationActions) return;
|
|
218
|
-
|
|
222
|
+
if (conversationArchived) {
|
|
223
|
+
void state.unarchiveConversation(firstConversationMessageId ?? void 0);
|
|
224
|
+
} else {
|
|
225
|
+
void state.archiveConversation(firstConversationMessageId ?? void 0);
|
|
226
|
+
}
|
|
219
227
|
},
|
|
220
|
-
|
|
228
|
+
onToggleReadConversation: () => {
|
|
221
229
|
if (!canRunConversationActions) return;
|
|
222
|
-
|
|
230
|
+
if (conversationAllUnread) {
|
|
231
|
+
void state.markConversationRead(firstConversationMessageId ?? void 0);
|
|
232
|
+
} else {
|
|
233
|
+
void state.markConversationUnread(firstConversationMessageId ?? void 0);
|
|
234
|
+
}
|
|
223
235
|
},
|
|
224
236
|
onDeleteConversation: () => {
|
|
225
237
|
if (!canRunConversationActions || state.activeConversationAction) return;
|