@open-mercato/core 0.6.2-develop.3467.1.2a1818709d → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/dist/helpers/integration/queue-runner.js +15 -3
- package/dist/helpers/integration/queue-runner.js.map +2 -2
- package/dist/helpers/integration/queue.js +1 -1
- package/dist/helpers/integration/queue.js.map +2 -2
- package/dist/helpers/integration/salesUi.js +24 -1
- package/dist/helpers/integration/salesUi.js.map +2 -2
- package/dist/modules/auth/api/roles/acl/route.js +37 -1
- package/dist/modules/auth/api/roles/acl/route.js.map +2 -2
- package/dist/modules/auth/api/roles/route.js +36 -2
- package/dist/modules/auth/api/roles/route.js.map +2 -2
- package/dist/modules/auth/api/users/acl/route.js +36 -1
- package/dist/modules/auth/api/users/acl/route.js.map +2 -2
- package/dist/modules/auth/api/users/route.js +101 -13
- package/dist/modules/auth/api/users/route.js.map +2 -2
- package/dist/modules/auth/backend/roles/[id]/edit/page.js +32 -14
- package/dist/modules/auth/backend/roles/[id]/edit/page.js.map +2 -2
- package/dist/modules/auth/backend/users/[id]/edit/page.js +1 -1
- package/dist/modules/auth/backend/users/[id]/edit/page.js.map +2 -2
- package/dist/modules/auth/backend/users/create/page.js +1 -1
- package/dist/modules/auth/backend/users/create/page.js.map +2 -2
- package/dist/modules/auth/backend/users/roleOptions.js +1 -1
- package/dist/modules/auth/backend/users/roleOptions.js.map +2 -2
- package/dist/modules/auth/commands/roles.js +8 -0
- package/dist/modules/auth/commands/roles.js.map +2 -2
- package/dist/modules/auth/commands/users.js +3 -0
- package/dist/modules/auth/commands/users.js.map +2 -2
- package/dist/modules/auth/components/AclEditor.js +53 -26
- package/dist/modules/auth/components/AclEditor.js.map +2 -2
- package/dist/modules/auth/lib/grantChecks.js +97 -2
- package/dist/modules/auth/lib/grantChecks.js.map +2 -2
- package/dist/modules/business_rules/lib/expression-evaluator.js +9 -7
- package/dist/modules/business_rules/lib/expression-evaluator.js.map +2 -2
- package/dist/modules/customers/ai-agents.js +10 -1
- package/dist/modules/customers/ai-agents.js.map +2 -2
- package/dist/modules/customers/ai-tools/settings-pack.js +55 -1
- package/dist/modules/customers/ai-tools/settings-pack.js.map +2 -2
- package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js +13 -5
- package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js.map +2 -2
- package/dist/modules/customers/lib/personCompanyLinkTable.js +4 -30
- package/dist/modules/customers/lib/personCompanyLinkTable.js.map +2 -2
- package/dist/modules/customers/migrations/Migration20260521175027.js +12 -0
- package/dist/modules/customers/migrations/Migration20260521175027.js.map +7 -0
- package/dist/modules/dashboards/components/WidgetVisibilityEditor.js +41 -12
- package/dist/modules/dashboards/components/WidgetVisibilityEditor.js.map +2 -2
- package/dist/modules/data_sync/api/options.js +2 -0
- package/dist/modules/data_sync/api/options.js.map +2 -2
- package/dist/modules/data_sync/api/run.js +77 -58
- package/dist/modules/data_sync/api/run.js.map +2 -2
- package/dist/modules/data_sync/backend/data-sync/page.js +3 -2
- package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
- package/dist/modules/data_sync/components/IntegrationScheduleTab.js +8 -3
- package/dist/modules/data_sync/components/IntegrationScheduleTab.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/[id]/page.js +15 -13
- package/dist/modules/integrations/backend/integrations/[id]/page.js.map +2 -2
- package/dist/modules/integrations/data/validators.js +9 -6
- package/dist/modules/integrations/data/validators.js.map +2 -2
- package/dist/modules/messages/api/route.js +2 -2
- package/dist/modules/messages/api/route.js.map +2 -2
- package/dist/modules/messages/commands/messages.js +42 -2
- package/dist/modules/messages/commands/messages.js.map +2 -2
- package/dist/modules/messages/components/MessagesInboxPageClient.js +66 -87
- package/dist/modules/messages/components/MessagesInboxPageClient.js.map +2 -2
- package/dist/modules/messages/components/inboxFilters.js +133 -0
- package/dist/modules/messages/components/inboxFilters.js.map +7 -0
- package/dist/modules/messages/data/validators.js +8 -6
- package/dist/modules/messages/data/validators.js.map +2 -2
- package/dist/modules/progress/api/jobs/route.js +26 -16
- package/dist/modules/progress/api/jobs/route.js.map +2 -2
- package/dist/modules/query_index/di.js +8 -6
- package/dist/modules/query_index/di.js.map +2 -2
- package/dist/modules/query_index/lib/indexer.js +12 -10
- package/dist/modules/query_index/lib/indexer.js.map +2 -2
- package/dist/modules/query_index/subscribers/upsert_one.js +7 -1
- package/dist/modules/query_index/subscribers/upsert_one.js.map +2 -2
- package/dist/modules/sales/api/order-adjustments/route.js.map +2 -2
- package/dist/modules/sales/api/quote-adjustments/route.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +104 -0
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/data/validators.js +20 -1
- package/dist/modules/sales/data/validators.js.map +2 -2
- package/dist/modules/sales/lib/makeSalesLineRoute.js.map +2 -2
- package/dist/modules/sync_excel/api/import/route.js +126 -116
- package/dist/modules/sync_excel/api/import/route.js.map +2 -2
- package/dist/modules/sync_excel/lib/adapters/customers.js +1 -0
- package/dist/modules/sync_excel/lib/adapters/customers.js.map +2 -2
- package/dist/modules/translations/components/TranslationManager.js +9 -4
- package/dist/modules/translations/components/TranslationManager.js.map +2 -2
- package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
- package/dist/modules/workflows/lib/event-trigger-service.js +23 -11
- package/dist/modules/workflows/lib/event-trigger-service.js.map +2 -2
- package/jest.config.cjs +4 -1
- package/package.json +15 -16
- package/src/helpers/integration/queue-runner.ts +21 -2
- package/src/helpers/integration/queue.ts +1 -1
- package/src/helpers/integration/salesUi.ts +26 -1
- package/src/modules/auth/api/roles/acl/route.ts +39 -1
- package/src/modules/auth/api/roles/route.ts +38 -2
- package/src/modules/auth/api/users/acl/route.ts +41 -1
- package/src/modules/auth/api/users/route.ts +105 -12
- package/src/modules/auth/backend/roles/[id]/edit/page.tsx +35 -13
- package/src/modules/auth/backend/users/[id]/edit/page.tsx +1 -1
- package/src/modules/auth/backend/users/create/page.tsx +1 -1
- package/src/modules/auth/backend/users/roleOptions.ts +2 -1
- package/src/modules/auth/commands/roles.ts +8 -0
- package/src/modules/auth/commands/users.ts +3 -0
- package/src/modules/auth/components/AclEditor.tsx +50 -24
- package/src/modules/auth/lib/grantChecks.ts +116 -2
- package/src/modules/business_rules/lib/expression-evaluator.ts +9 -13
- package/src/modules/customers/ai-agents.ts +10 -1
- package/src/modules/customers/ai-tools/settings-pack.ts +62 -1
- package/src/modules/customers/components/detail/schedule/useScheduleFormState.ts +18 -7
- package/src/modules/customers/lib/personCompanyLinkTable.ts +33 -41
- package/src/modules/customers/migrations/Migration20260521175027.ts +39 -0
- package/src/modules/dashboards/components/WidgetVisibilityEditor.tsx +38 -12
- package/src/modules/data_sync/api/options.ts +2 -0
- package/src/modules/data_sync/api/run.ts +80 -61
- package/src/modules/data_sync/backend/data-sync/page.tsx +10 -0
- package/src/modules/data_sync/components/IntegrationScheduleTab.tsx +17 -3
- package/src/modules/data_sync/i18n/de.json +3 -0
- package/src/modules/data_sync/i18n/en.json +3 -0
- package/src/modules/data_sync/i18n/es.json +3 -0
- package/src/modules/data_sync/i18n/pl.json +3 -0
- package/src/modules/data_sync/lib/adapter.ts +9 -0
- package/src/modules/integrations/backend/integrations/[id]/page.tsx +15 -13
- package/src/modules/integrations/data/validators.ts +5 -4
- package/src/modules/messages/api/route.ts +2 -2
- package/src/modules/messages/commands/messages.ts +54 -2
- package/src/modules/messages/components/MessagesInboxPageClient.tsx +75 -90
- package/src/modules/messages/components/inboxFilters.ts +162 -0
- package/src/modules/messages/data/validators.ts +7 -5
- package/src/modules/messages/i18n/de.json +5 -4
- package/src/modules/messages/i18n/en.json +5 -4
- package/src/modules/messages/i18n/es.json +5 -4
- package/src/modules/messages/i18n/pl.json +5 -4
- package/src/modules/progress/api/jobs/route.ts +30 -20
- package/src/modules/query_index/di.ts +9 -7
- package/src/modules/query_index/lib/indexer.ts +13 -11
- package/src/modules/query_index/subscribers/upsert_one.ts +9 -1
- package/src/modules/sales/api/order-adjustments/route.ts +2 -1
- package/src/modules/sales/api/quote-adjustments/route.ts +2 -1
- package/src/modules/sales/commands/documents.ts +116 -0
- package/src/modules/sales/data/validators.ts +38 -0
- package/src/modules/sales/i18n/de.json +2 -0
- package/src/modules/sales/i18n/en.json +2 -0
- package/src/modules/sales/i18n/es.json +2 -0
- package/src/modules/sales/i18n/pl.json +2 -0
- package/src/modules/sales/lib/makeSalesLineRoute.ts +2 -1
- 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/sync_excel/api/import/route.ts +141 -131
- package/src/modules/sync_excel/lib/adapters/customers.ts +1 -0
- package/src/modules/translations/components/TranslationManager.tsx +9 -4
- package/src/modules/workflows/lib/activity-executor.ts +4 -3
- package/src/modules/workflows/lib/event-trigger-service.ts +24 -11
- package/tsconfig.json +1 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/messages/data/validators.ts"],
|
|
4
|
-
"sourcesContent": ["import { z } from 'zod'\n\nfunction collectDuplicateRecipientIds(\n recipients: Array<{ userId: string }>,\n): string[] {\n const seen = new Set<string>()\n const duplicates = new Set<string>()\n for (const recipient of recipients) {\n if (seen.has(recipient.userId)) {\n duplicates.add(recipient.userId)\n continue\n }\n seen.add(recipient.userId)\n }\n return Array.from(duplicates)\n}\n\nfunction validateDefaultWithObjectsPayload(\n value: {\n type?: string\n objects?: Array<{ actionRequired?: boolean; actionType?: string; actionLabel?: string }>\n },\n ctx: z.RefinementCtx,\n): void {\n if (value.type !== 'messages.defaultWithObjects') return\n\n if (!Array.isArray(value.objects) || value.objects.length === 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['objects'],\n message: 'at least one object is required for messages.defaultWithObjects',\n })\n return\n }\n\n value.objects.forEach((object, index) => {\n if (object.actionRequired === true) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['objects', index, 'actionRequired'],\n message: 'actionRequired must be false for messages.defaultWithObjects',\n })\n }\n if (typeof object.actionType === 'string' && object.actionType.trim().length > 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['objects', index, 'actionType'],\n message: 'actionType is not allowed for messages.defaultWithObjects',\n })\n }\n if (typeof object.actionLabel === 'string' && object.actionLabel.trim().length > 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['objects', index, 'actionLabel'],\n message: 'actionLabel is not allowed for messages.defaultWithObjects',\n })\n }\n })\n}\n\nexport const messageRecipientSchema = z.object({\n userId: z.string().uuid(),\n type: z.enum(['to', 'cc', 'bcc']).optional().default('to'),\n})\n\nexport const messageObjectSchema = z.object({\n entityModule: z.string().min(1),\n entityType: z.string().min(1),\n entityId: z.string().uuid(),\n actionRequired: z.boolean().optional().default(false),\n actionType: z.string().optional(),\n actionLabel: z.string().optional(),\n})\n\nexport const messageActionSchema = z.object({\n id: z.string().min(1),\n label: z.string().min(1),\n labelKey: z.string().optional(),\n variant: z.enum(['default', 'secondary', 'destructive', 'outline', 'ghost']).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 messageActionDataSchema = z.object({\n actions: z.array(messageActionSchema),\n primaryActionId: z.string().optional(),\n expiresAt: z.string().datetime().optional(),\n})\n\nexport const composeMessageSchema = z.object({\n type: z.string().optional().default('default'),\n visibility: z.enum(['public', 'internal']).nullable().optional(),\n sourceEntityType: z.string().min(1).optional(),\n sourceEntityId: z.string().uuid().optional(),\n externalEmail: z.string().email().optional(),\n externalName: z.string().min(1).max(255).optional(),\n recipients: z.array(messageRecipientSchema).max(100).optional().default([]),\n subject: z.string().max(500).optional().default(''),\n body: z.string().max(50000).optional().default(''),\n bodyFormat: z.enum(['text', 'markdown']).optional().default('text'),\n priority: z.enum(['low', 'normal', 'high', 'urgent']).optional().default('normal'),\n objects: z.array(messageObjectSchema).optional(),\n attachmentIds: z.array(z.string().uuid()).optional(),\n attachmentRecordId: z.string().min(1).max(255).optional(),\n actionData: messageActionDataSchema.optional(),\n sendViaEmail: z.boolean().optional().default(false),\n parentMessageId: z.string().uuid().optional(),\n isDraft: z.boolean().optional().default(false),\n}).superRefine((value, ctx) => {\n const isDraft = value.isDraft ?? false\n const visibility = value.visibility ?? 'internal'\n const recipientCount = value.recipients.length\n const hasExternalEmail = Boolean(value.externalEmail?.trim())\n const hasSubject = value.subject.trim().length > 0\n const hasBody = value.body.trim().length > 0\n\n if (!isDraft) {\n if (visibility === 'public') {\n if (!hasExternalEmail) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['externalEmail'],\n message: 'externalEmail is required when visibility is public',\n })\n }\n if (recipientCount > 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['recipients'],\n message: 'recipients must be empty when visibility is public',\n })\n }\n } else if (recipientCount === 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['recipients'],\n message: 'at least one recipient is required when visibility is internal',\n })\n }\n\n if (!hasSubject) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['subject'],\n message: 'subject is required',\n })\n }\n if (!hasBody) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['body'],\n message: 'body is required',\n })\n }\n }\n\n const duplicateRecipientIds = collectDuplicateRecipientIds(value.recipients)\n if (duplicateRecipientIds.length > 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['recipients'],\n message: 'recipient user ids must be unique',\n })\n }\n\n validateDefaultWithObjectsPayload(value, ctx)\n})\n\nexport const updateDraftSchema = z.object({\n type: z.string().optional(),\n visibility: z.enum(['public', 'internal']).nullable().optional(),\n sourceEntityType: z.string().min(1).optional(),\n sourceEntityId: z.string().uuid().optional(),\n externalEmail: z.string().email().optional(),\n externalName: z.string().min(1).max(255).optional(),\n recipients: z.array(messageRecipientSchema).optional(),\n subject: z.string().min(1).max(500).optional(),\n body: z.string().min(1).max(50000).optional(),\n bodyFormat: z.enum(['text', 'markdown']).optional(),\n priority: z.enum(['low', 'normal', 'high', 'urgent']).optional(),\n objects: z.array(messageObjectSchema).optional(),\n attachmentIds: z.array(z.string().uuid()).optional(),\n actionData: messageActionDataSchema.optional(),\n sendViaEmail: z.boolean().optional(),\n}).superRefine((value, ctx) => {\n if (value.recipients) {\n const duplicateRecipientIds = collectDuplicateRecipientIds(value.recipients)\n if (duplicateRecipientIds.length > 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['recipients'],\n message: 'recipient user ids must be unique',\n })\n }\n }\n\n validateDefaultWithObjectsPayload(value, ctx)\n})\n\nexport const listMessagesSchema = z.object({\n folder: z.enum(['inbox', 'sent', 'drafts', 'archived', 'all']).optional().default('inbox'),\n status: z.enum(['unread', 'read', 'archived']).optional(),\n type: z.string().optional(),\n visibility: z.enum(['public', 'internal']).optional(),\n sourceEntityType: z.string().optional(),\n sourceEntityId: z.string().uuid().optional(),\n externalEmail: z.string().email().optional(),\n hasObjects: z.coerce.boolean().optional(),\n hasAttachments: z.coerce.boolean().optional(),\n hasActions: z.coerce.boolean().optional(),\n senderId: z.string().uuid().optional(),\n search: z.string().max(200).optional(),\n since: z.string().datetime().optional(),\n page: z.coerce.number().int().min(1).optional().default(1),\n pageSize: z.coerce.number().int().min(1).max(100).optional().default(20),\n})\n\nexport const forwardMessageSchema = z.object({\n recipients: z.array(messageRecipientSchema).min(1).max(100),\n body: z.string().max(50000).optional(),\n additionalBody: z.string().max(10000).optional(),\n includeAttachments: z.boolean().optional().default(true),\n sendViaEmail: z.boolean().optional().default(false),\n}).superRefine((value, ctx) => {\n const duplicateRecipientIds = collectDuplicateRecipientIds(value.recipients)\n if (duplicateRecipientIds.length > 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['recipients'],\n message: 'recipient user ids must be unique',\n })\n }\n})\n\nexport const replyMessageSchema = z.object({\n body: z.string().min(1).max(50000),\n bodyFormat: z.enum(['text', 'markdown']).optional().default('text'),\n recipients: z.array(messageRecipientSchema).max(100).optional(),\n attachmentIds: z.array(z.string().uuid()).optional(),\n attachmentRecordId: z.string().min(1).max(255).optional(),\n replyAll: z.boolean().optional().default(false),\n sendViaEmail: z.boolean().optional().default(false),\n}).superRefine((value, ctx) => {\n if (!value.recipients) return\n const duplicateRecipientIds = collectDuplicateRecipientIds(value.recipients)\n if (duplicateRecipientIds.length > 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['recipients'],\n message: 'recipient user ids must be unique',\n })\n }\n})\n\nexport const executeActionSchema = z.object({\n messageId: z.string().uuid(),\n actionId: z.string().min(1),\n payload: z.record(z.string(), z.unknown()).optional(),\n})\n\nexport const confirmMessageSchema = z.object({\n messageId: z.string().uuid(),\n tenantId: z.string().uuid().optional(),\n organizationId: z.string().uuid().nullable().optional(),\n confirmed: z.boolean().optional().default(true),\n})\n\nexport const messageObjectTypesQuerySchema = z.object({\n messageType: z.string().min(1),\n})\n\nexport const attachmentIdsPayloadSchema = z.object({\n attachmentIds: z.array(z.string().uuid()).min(1).max(100),\n})\n\nexport const unlinkAttachmentPayloadSchema = z.object({\n attachmentId: z.string().uuid().optional(),\n attachmentIds: z.array(z.string().uuid()).min(1).max(100).optional(),\n}).refine(\n (value) => Boolean(value.attachmentId || value.attachmentIds?.length),\n { message: 'attachmentId or attachmentIds is required' }\n)\n\nexport type ComposeMessageInput = z.infer<typeof composeMessageSchema>\nexport type UpdateDraftInput = z.infer<typeof updateDraftSchema>\nexport type ListMessagesInput = z.infer<typeof listMessagesSchema>\nexport type ForwardMessageInput = z.infer<typeof forwardMessageSchema>\nexport type ReplyMessageInput = z.infer<typeof replyMessageSchema>\nexport type ExecuteActionInput = z.infer<typeof executeActionSchema>\nexport type ConfirmMessageInput = z.infer<typeof confirmMessageSchema>\nexport type MessageObjectTypesQueryInput = z.infer<typeof messageObjectTypesQuerySchema>\nexport type AttachmentIdsPayload = z.infer<typeof attachmentIdsPayloadSchema>\nexport type UnlinkAttachmentPayload = z.infer<typeof unlinkAttachmentPayloadSchema>\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,SAAS;
|
|
4
|
+
"sourcesContent": ["import { z } from 'zod'\nimport { parseBooleanFlag } from '@open-mercato/shared/lib/boolean'\n\nfunction collectDuplicateRecipientIds(\n recipients: Array<{ userId: string }>,\n): string[] {\n const seen = new Set<string>()\n const duplicates = new Set<string>()\n for (const recipient of recipients) {\n if (seen.has(recipient.userId)) {\n duplicates.add(recipient.userId)\n continue\n }\n seen.add(recipient.userId)\n }\n return Array.from(duplicates)\n}\n\nfunction validateDefaultWithObjectsPayload(\n value: {\n type?: string\n objects?: Array<{ actionRequired?: boolean; actionType?: string; actionLabel?: string }>\n },\n ctx: z.RefinementCtx,\n): void {\n if (value.type !== 'messages.defaultWithObjects') return\n\n if (!Array.isArray(value.objects) || value.objects.length === 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['objects'],\n message: 'at least one object is required for messages.defaultWithObjects',\n })\n return\n }\n\n value.objects.forEach((object, index) => {\n if (object.actionRequired === true) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['objects', index, 'actionRequired'],\n message: 'actionRequired must be false for messages.defaultWithObjects',\n })\n }\n if (typeof object.actionType === 'string' && object.actionType.trim().length > 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['objects', index, 'actionType'],\n message: 'actionType is not allowed for messages.defaultWithObjects',\n })\n }\n if (typeof object.actionLabel === 'string' && object.actionLabel.trim().length > 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['objects', index, 'actionLabel'],\n message: 'actionLabel is not allowed for messages.defaultWithObjects',\n })\n }\n })\n}\n\nexport const messageRecipientSchema = z.object({\n userId: z.string().uuid(),\n type: z.enum(['to', 'cc', 'bcc']).optional().default('to'),\n})\n\nexport const messageObjectSchema = z.object({\n entityModule: z.string().min(1),\n entityType: z.string().min(1),\n entityId: z.string().uuid(),\n actionRequired: z.boolean().optional().default(false),\n actionType: z.string().optional(),\n actionLabel: z.string().optional(),\n})\n\nexport const messageActionSchema = z.object({\n id: z.string().min(1),\n label: z.string().min(1),\n labelKey: z.string().optional(),\n variant: z.enum(['default', 'secondary', 'destructive', 'outline', 'ghost']).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 messageActionDataSchema = z.object({\n actions: z.array(messageActionSchema),\n primaryActionId: z.string().optional(),\n expiresAt: z.string().datetime().optional(),\n})\n\nexport const composeMessageSchema = z.object({\n type: z.string().optional().default('default'),\n visibility: z.enum(['public', 'internal']).nullable().optional(),\n sourceEntityType: z.string().min(1).optional(),\n sourceEntityId: z.string().uuid().optional(),\n externalEmail: z.string().email().optional(),\n externalName: z.string().min(1).max(255).optional(),\n recipients: z.array(messageRecipientSchema).max(100).optional().default([]),\n subject: z.string().max(500).optional().default(''),\n body: z.string().max(50000).optional().default(''),\n bodyFormat: z.enum(['text', 'markdown']).optional().default('text'),\n priority: z.enum(['low', 'normal', 'high', 'urgent']).optional().default('normal'),\n objects: z.array(messageObjectSchema).optional(),\n attachmentIds: z.array(z.string().uuid()).optional(),\n attachmentRecordId: z.string().min(1).max(255).optional(),\n actionData: messageActionDataSchema.optional(),\n sendViaEmail: z.boolean().optional().default(false),\n parentMessageId: z.string().uuid().optional(),\n isDraft: z.boolean().optional().default(false),\n}).superRefine((value, ctx) => {\n const isDraft = value.isDraft ?? false\n const visibility = value.visibility ?? 'internal'\n const recipientCount = value.recipients.length\n const hasExternalEmail = Boolean(value.externalEmail?.trim())\n const hasSubject = value.subject.trim().length > 0\n const hasBody = value.body.trim().length > 0\n\n if (!isDraft) {\n if (visibility === 'public') {\n if (!hasExternalEmail) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['externalEmail'],\n message: 'externalEmail is required when visibility is public',\n })\n }\n if (recipientCount > 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['recipients'],\n message: 'recipients must be empty when visibility is public',\n })\n }\n } else if (recipientCount === 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['recipients'],\n message: 'at least one recipient is required when visibility is internal',\n })\n }\n\n if (!hasSubject) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['subject'],\n message: 'subject is required',\n })\n }\n if (!hasBody) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['body'],\n message: 'body is required',\n })\n }\n }\n\n const duplicateRecipientIds = collectDuplicateRecipientIds(value.recipients)\n if (duplicateRecipientIds.length > 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['recipients'],\n message: 'recipient user ids must be unique',\n })\n }\n\n validateDefaultWithObjectsPayload(value, ctx)\n})\n\nexport const updateDraftSchema = z.object({\n type: z.string().optional(),\n visibility: z.enum(['public', 'internal']).nullable().optional(),\n sourceEntityType: z.string().min(1).optional(),\n sourceEntityId: z.string().uuid().optional(),\n externalEmail: z.string().email().optional(),\n externalName: z.string().min(1).max(255).optional(),\n recipients: z.array(messageRecipientSchema).optional(),\n subject: z.string().max(500).optional(),\n body: z.string().max(50000).optional(),\n bodyFormat: z.enum(['text', 'markdown']).optional(),\n priority: z.enum(['low', 'normal', 'high', 'urgent']).optional(),\n objects: z.array(messageObjectSchema).optional(),\n attachmentIds: z.array(z.string().uuid()).optional(),\n actionData: messageActionDataSchema.optional(),\n sendViaEmail: z.boolean().optional(),\n isDraft: z.literal(false).optional(),\n}).superRefine((value, ctx) => {\n if (value.recipients) {\n const duplicateRecipientIds = collectDuplicateRecipientIds(value.recipients)\n if (duplicateRecipientIds.length > 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['recipients'],\n message: 'recipient user ids must be unique',\n })\n }\n }\n\n validateDefaultWithObjectsPayload(value, ctx)\n})\n\nexport const listMessagesSchema = z.object({\n folder: z.enum(['inbox', 'sent', 'drafts', 'archived', 'all']).optional().default('inbox'),\n status: z.enum(['unread', 'read', 'archived']).optional(),\n type: z.string().optional(),\n visibility: z.enum(['public', 'internal']).optional(),\n sourceEntityType: z.string().optional(),\n sourceEntityId: z.string().uuid().optional(),\n externalEmail: z.string().email().optional(),\n hasObjects: z.string().transform(parseBooleanFlag).optional(),\n hasAttachments: z.string().transform(parseBooleanFlag).optional(),\n hasActions: z.string().transform(parseBooleanFlag).optional(),\n senderId: z.string().uuid().optional(),\n search: z.string().max(200).optional(),\n since: z.string().datetime().optional(),\n page: z.coerce.number().int().min(1).optional().default(1),\n pageSize: z.coerce.number().int().min(1).max(100).optional().default(20),\n})\n\nexport const forwardMessageSchema = z.object({\n recipients: z.array(messageRecipientSchema).min(1).max(100),\n body: z.string().max(50000).optional(),\n additionalBody: z.string().max(10000).optional(),\n includeAttachments: z.boolean().optional().default(true),\n sendViaEmail: z.boolean().optional().default(false),\n}).superRefine((value, ctx) => {\n const duplicateRecipientIds = collectDuplicateRecipientIds(value.recipients)\n if (duplicateRecipientIds.length > 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['recipients'],\n message: 'recipient user ids must be unique',\n })\n }\n})\n\nexport const replyMessageSchema = z.object({\n body: z.string().min(1).max(50000),\n bodyFormat: z.enum(['text', 'markdown']).optional().default('text'),\n recipients: z.array(messageRecipientSchema).max(100).optional(),\n attachmentIds: z.array(z.string().uuid()).optional(),\n attachmentRecordId: z.string().min(1).max(255).optional(),\n replyAll: z.boolean().optional().default(false),\n sendViaEmail: z.boolean().optional().default(false),\n}).superRefine((value, ctx) => {\n if (!value.recipients) return\n const duplicateRecipientIds = collectDuplicateRecipientIds(value.recipients)\n if (duplicateRecipientIds.length > 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['recipients'],\n message: 'recipient user ids must be unique',\n })\n }\n})\n\nexport const executeActionSchema = z.object({\n messageId: z.string().uuid(),\n actionId: z.string().min(1),\n payload: z.record(z.string(), z.unknown()).optional(),\n})\n\nexport const confirmMessageSchema = z.object({\n messageId: z.string().uuid(),\n tenantId: z.string().uuid().optional(),\n organizationId: z.string().uuid().nullable().optional(),\n confirmed: z.boolean().optional().default(true),\n})\n\nexport const messageObjectTypesQuerySchema = z.object({\n messageType: z.string().min(1),\n})\n\nexport const attachmentIdsPayloadSchema = z.object({\n attachmentIds: z.array(z.string().uuid()).min(1).max(100),\n})\n\nexport const unlinkAttachmentPayloadSchema = z.object({\n attachmentId: z.string().uuid().optional(),\n attachmentIds: z.array(z.string().uuid()).min(1).max(100).optional(),\n}).refine(\n (value) => Boolean(value.attachmentId || value.attachmentIds?.length),\n { message: 'attachmentId or attachmentIds is required' }\n)\n\nexport type ComposeMessageInput = z.infer<typeof composeMessageSchema>\nexport type UpdateDraftInput = z.infer<typeof updateDraftSchema>\nexport type ListMessagesInput = z.infer<typeof listMessagesSchema>\nexport type ForwardMessageInput = z.infer<typeof forwardMessageSchema>\nexport type ReplyMessageInput = z.infer<typeof replyMessageSchema>\nexport type ExecuteActionInput = z.infer<typeof executeActionSchema>\nexport type ConfirmMessageInput = z.infer<typeof confirmMessageSchema>\nexport type MessageObjectTypesQueryInput = z.infer<typeof messageObjectTypesQuerySchema>\nexport type AttachmentIdsPayload = z.infer<typeof attachmentIdsPayloadSchema>\nexport type UnlinkAttachmentPayload = z.infer<typeof unlinkAttachmentPayloadSchema>\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -101,23 +101,33 @@ async function GET(req) {
|
|
|
101
101
|
return NextResponse.json({ items, total, page, pageSize, totalPages });
|
|
102
102
|
}
|
|
103
103
|
async function POST(req) {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
104
|
+
try {
|
|
105
|
+
const auth = await getAuthFromRequest(req);
|
|
106
|
+
if (!auth || !auth.tenantId) {
|
|
107
|
+
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
108
|
+
}
|
|
109
|
+
const body = await req.json();
|
|
110
|
+
const parsed = createProgressJobSchema.safeParse(body);
|
|
111
|
+
if (!parsed.success) {
|
|
112
|
+
return NextResponse.json({ error: "Invalid input", details: parsed.error.flatten() }, { status: 400 });
|
|
113
|
+
}
|
|
114
|
+
const container = await createRequestContainer();
|
|
115
|
+
const progressService = container.resolve("progressService");
|
|
116
|
+
const job = await progressService.createJob(parsed.data, {
|
|
117
|
+
tenantId: auth.tenantId,
|
|
118
|
+
organizationId: auth.orgId,
|
|
119
|
+
userId: auth.sub
|
|
120
|
+
});
|
|
121
|
+
return NextResponse.json({ id: job.id }, { status: 201 });
|
|
122
|
+
} catch (error) {
|
|
123
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
124
|
+
const stack = error instanceof Error ? error.stack : void 0;
|
|
125
|
+
console.error("[progress.jobs.create] unhandled error", { message, stack });
|
|
126
|
+
return NextResponse.json(
|
|
127
|
+
{ error: "Failed to create progress job.", message, stack },
|
|
128
|
+
{ status: 500 }
|
|
129
|
+
);
|
|
112
130
|
}
|
|
113
|
-
const container = await createRequestContainer();
|
|
114
|
-
const progressService = container.resolve("progressService");
|
|
115
|
-
const job = await progressService.createJob(parsed.data, {
|
|
116
|
-
tenantId: auth.tenantId,
|
|
117
|
-
organizationId: auth.orgId,
|
|
118
|
-
userId: auth.sub
|
|
119
|
-
});
|
|
120
|
-
return NextResponse.json({ id: job.id }, { status: 201 });
|
|
121
131
|
}
|
|
122
132
|
const jobListItemSchema = z.object({
|
|
123
133
|
id: z.string().uuid(),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/modules/progress/api/jobs/route.ts"],
|
|
4
|
-
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport type { FilterQuery } from '@mikro-orm/core'\nimport { escapeLikePattern } from '@open-mercato/shared/lib/db/escapeLikePattern'\nimport { ProgressJob } from '../../data/entities'\nimport { createProgressJobSchema, listProgressJobsSchema } from '../../data/validators'\nimport {\n createProgressCrudOpenApi,\n createPagedListResponseSchema,\n} from '../openapi'\n\nconst routeMetadata = {\n GET: { requireAuth: true },\n POST: { requireAuth: true, requireFeatures: ['progress.create'] },\n}\n\nexport const metadata = routeMetadata\n\nconst listQuerySchema = listProgressJobsSchema\n\ntype JobRow = {\n id: string\n jobType: string\n name: string\n description: string | null\n status: string\n progressPercent: number\n processedCount: number\n totalCount: number | null\n etaSeconds: number | null\n cancellable: boolean\n startedAt: string | null\n finishedAt: string | null\n errorMessage: string | null\n createdAt: string | null\n tenantId: string\n organizationId: string | null\n}\n\nconst toRow = (job: ProgressJob): JobRow => ({\n id: String(job.id),\n jobType: String(job.jobType),\n name: String(job.name),\n description: job.description ?? null,\n status: job.status,\n progressPercent: job.progressPercent,\n processedCount: job.processedCount,\n totalCount: job.totalCount ?? null,\n etaSeconds: job.etaSeconds ?? null,\n cancellable: !!job.cancellable,\n startedAt: job.startedAt ? job.startedAt.toISOString() : null,\n finishedAt: job.finishedAt ? job.finishedAt.toISOString() : null,\n errorMessage: job.errorMessage ?? null,\n createdAt: job.createdAt ? job.createdAt.toISOString() : null,\n tenantId: String(job.tenantId),\n organizationId: job.organizationId ? String(job.organizationId) : null,\n})\n\nexport async function GET(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth || !auth.tenantId) {\n return NextResponse.json({ items: [], total: 0, page: 1, pageSize: 20, totalPages: 1 }, { status: 401 })\n }\n\n const url = new URL(req.url)\n const parsed = listQuerySchema.safeParse({\n status: url.searchParams.get('status') ?? undefined,\n jobType: url.searchParams.get('jobType') ?? undefined,\n parentJobId: url.searchParams.get('parentJobId') ?? undefined,\n includeCompleted: url.searchParams.get('includeCompleted') ?? undefined,\n completedSince: url.searchParams.get('completedSince') ?? undefined,\n page: url.searchParams.get('page') ?? undefined,\n pageSize: url.searchParams.get('pageSize') ?? undefined,\n search: url.searchParams.get('search') ?? undefined,\n sortField: url.searchParams.get('sortField') ?? undefined,\n sortDir: url.searchParams.get('sortDir') ?? undefined,\n })\n if (!parsed.success) {\n return NextResponse.json({ items: [], total: 0, page: 1, pageSize: 20, totalPages: 1 }, { status: 400 })\n }\n\n const container = await createRequestContainer()\n const em = container.resolve('em') as EntityManager\n\n const { status, jobType, parentJobId, includeCompleted, completedSince, page, pageSize, search, sortField, sortDir } = parsed.data\n const filter: FilterQuery<ProgressJob> = {\n tenantId: auth.tenantId,\n }\n\n if (auth.orgId) {\n filter.organizationId = auth.orgId\n }\n\n if (status) {\n const statusValues = status.split(',')\n filter.status = statusValues.length > 1 ? { $in: statusValues as never } : status as never\n } else if (includeCompleted !== 'true') {\n filter.status = { $in: ['pending', 'running'] }\n }\n\n if (jobType) filter.jobType = jobType\n if (parentJobId) filter.parentJobId = parentJobId\n if (completedSince) filter.finishedAt = { $gte: new Date(completedSince) }\n\n if (search) {\n const escaped = escapeLikePattern(search)\n filter.$or = [\n { name: { $ilike: `%${escaped}%` } },\n { jobType: { $ilike: `%${escaped}%` } },\n ]\n }\n\n const fieldMap: Record<string, string> = {\n createdAt: 'createdAt',\n startedAt: 'startedAt',\n finishedAt: 'finishedAt',\n }\n const orderBy: Record<string, 'ASC' | 'DESC'> = {}\n if (sortField) {\n const mapped = fieldMap[sortField] || 'createdAt'\n orderBy[mapped] = sortDir === 'asc' ? 'ASC' : 'DESC'\n } else {\n orderBy.createdAt = 'DESC'\n }\n\n const [rows, total] = await em.findAndCount(ProgressJob, filter, {\n orderBy,\n limit: pageSize,\n offset: (page - 1) * pageSize,\n })\n const items = rows.map(toRow)\n const totalPages = Math.max(1, Math.ceil(total / pageSize))\n\n return NextResponse.json({ items, total, page, pageSize, totalPages })\n}\n\nexport async function POST(req: Request) {\n const auth = await getAuthFromRequest(req)\n
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport type { FilterQuery } from '@mikro-orm/core'\nimport { escapeLikePattern } from '@open-mercato/shared/lib/db/escapeLikePattern'\nimport { ProgressJob } from '../../data/entities'\nimport { createProgressJobSchema, listProgressJobsSchema } from '../../data/validators'\nimport {\n createProgressCrudOpenApi,\n createPagedListResponseSchema,\n} from '../openapi'\n\nconst routeMetadata = {\n GET: { requireAuth: true },\n POST: { requireAuth: true, requireFeatures: ['progress.create'] },\n}\n\nexport const metadata = routeMetadata\n\nconst listQuerySchema = listProgressJobsSchema\n\ntype JobRow = {\n id: string\n jobType: string\n name: string\n description: string | null\n status: string\n progressPercent: number\n processedCount: number\n totalCount: number | null\n etaSeconds: number | null\n cancellable: boolean\n startedAt: string | null\n finishedAt: string | null\n errorMessage: string | null\n createdAt: string | null\n tenantId: string\n organizationId: string | null\n}\n\nconst toRow = (job: ProgressJob): JobRow => ({\n id: String(job.id),\n jobType: String(job.jobType),\n name: String(job.name),\n description: job.description ?? null,\n status: job.status,\n progressPercent: job.progressPercent,\n processedCount: job.processedCount,\n totalCount: job.totalCount ?? null,\n etaSeconds: job.etaSeconds ?? null,\n cancellable: !!job.cancellable,\n startedAt: job.startedAt ? job.startedAt.toISOString() : null,\n finishedAt: job.finishedAt ? job.finishedAt.toISOString() : null,\n errorMessage: job.errorMessage ?? null,\n createdAt: job.createdAt ? job.createdAt.toISOString() : null,\n tenantId: String(job.tenantId),\n organizationId: job.organizationId ? String(job.organizationId) : null,\n})\n\nexport async function GET(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth || !auth.tenantId) {\n return NextResponse.json({ items: [], total: 0, page: 1, pageSize: 20, totalPages: 1 }, { status: 401 })\n }\n\n const url = new URL(req.url)\n const parsed = listQuerySchema.safeParse({\n status: url.searchParams.get('status') ?? undefined,\n jobType: url.searchParams.get('jobType') ?? undefined,\n parentJobId: url.searchParams.get('parentJobId') ?? undefined,\n includeCompleted: url.searchParams.get('includeCompleted') ?? undefined,\n completedSince: url.searchParams.get('completedSince') ?? undefined,\n page: url.searchParams.get('page') ?? undefined,\n pageSize: url.searchParams.get('pageSize') ?? undefined,\n search: url.searchParams.get('search') ?? undefined,\n sortField: url.searchParams.get('sortField') ?? undefined,\n sortDir: url.searchParams.get('sortDir') ?? undefined,\n })\n if (!parsed.success) {\n return NextResponse.json({ items: [], total: 0, page: 1, pageSize: 20, totalPages: 1 }, { status: 400 })\n }\n\n const container = await createRequestContainer()\n const em = container.resolve('em') as EntityManager\n\n const { status, jobType, parentJobId, includeCompleted, completedSince, page, pageSize, search, sortField, sortDir } = parsed.data\n const filter: FilterQuery<ProgressJob> = {\n tenantId: auth.tenantId,\n }\n\n if (auth.orgId) {\n filter.organizationId = auth.orgId\n }\n\n if (status) {\n const statusValues = status.split(',')\n filter.status = statusValues.length > 1 ? { $in: statusValues as never } : status as never\n } else if (includeCompleted !== 'true') {\n filter.status = { $in: ['pending', 'running'] }\n }\n\n if (jobType) filter.jobType = jobType\n if (parentJobId) filter.parentJobId = parentJobId\n if (completedSince) filter.finishedAt = { $gte: new Date(completedSince) }\n\n if (search) {\n const escaped = escapeLikePattern(search)\n filter.$or = [\n { name: { $ilike: `%${escaped}%` } },\n { jobType: { $ilike: `%${escaped}%` } },\n ]\n }\n\n const fieldMap: Record<string, string> = {\n createdAt: 'createdAt',\n startedAt: 'startedAt',\n finishedAt: 'finishedAt',\n }\n const orderBy: Record<string, 'ASC' | 'DESC'> = {}\n if (sortField) {\n const mapped = fieldMap[sortField] || 'createdAt'\n orderBy[mapped] = sortDir === 'asc' ? 'ASC' : 'DESC'\n } else {\n orderBy.createdAt = 'DESC'\n }\n\n const [rows, total] = await em.findAndCount(ProgressJob, filter, {\n orderBy,\n limit: pageSize,\n offset: (page - 1) * pageSize,\n })\n const items = rows.map(toRow)\n const totalPages = Math.max(1, Math.ceil(total / pageSize))\n\n return NextResponse.json({ items, total, page, pageSize, totalPages })\n}\n\nexport async function POST(req: Request) {\n try {\n const auth = await getAuthFromRequest(req)\n if (!auth || !auth.tenantId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const body = await req.json()\n const parsed = createProgressJobSchema.safeParse(body)\n if (!parsed.success) {\n return NextResponse.json({ error: 'Invalid input', details: parsed.error.flatten() }, { status: 400 })\n }\n\n const container = await createRequestContainer()\n const progressService = container.resolve('progressService') as import('../../lib/progressService').ProgressService\n\n const job = await progressService.createJob(parsed.data, {\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n userId: auth.sub,\n })\n\n return NextResponse.json({ id: job.id }, { status: 201 })\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n const stack = error instanceof Error ? error.stack : undefined\n console.error('[progress.jobs.create] unhandled error', { message, stack })\n return NextResponse.json(\n { error: 'Failed to create progress job.', message, stack },\n { status: 500 },\n )\n }\n}\n\nconst jobListItemSchema = z.object({\n id: z.string().uuid(),\n jobType: z.string(),\n name: z.string(),\n description: z.string().nullable(),\n status: z.string(),\n progressPercent: z.number(),\n processedCount: z.number(),\n totalCount: z.number().nullable(),\n etaSeconds: z.number().nullable(),\n cancellable: z.boolean(),\n startedAt: z.string().nullable(),\n finishedAt: z.string().nullable(),\n errorMessage: z.string().nullable(),\n createdAt: z.string().nullable(),\n tenantId: z.string().uuid(),\n organizationId: z.string().uuid().nullable(),\n})\n\nexport const openApi = createProgressCrudOpenApi({\n resourceName: 'ProgressJob',\n pluralName: 'ProgressJobs',\n querySchema: listQuerySchema,\n listResponseSchema: createPagedListResponseSchema(jobListItemSchema),\n create: {\n schema: createProgressJobSchema,\n description: 'Creates a new progress job for tracking a long-running operation.',\n },\n})\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -62,8 +62,8 @@ function register(container) {
|
|
|
62
62
|
const makeUpsertHandler = (entityType) => async (payload, ctx) => {
|
|
63
63
|
try {
|
|
64
64
|
const em = ctx.resolve("em");
|
|
65
|
-
let orgId = payload?.organizationId || payload?.orgId || null;
|
|
66
|
-
let tenantId = payload?.tenantId || null;
|
|
65
|
+
let orgId = payload?.organizationId || payload?.orgId || ctx?.organizationId || null;
|
|
66
|
+
let tenantId = payload?.tenantId || ctx?.tenantId || null;
|
|
67
67
|
const id = String(payload?.id || payload?.recordId || "");
|
|
68
68
|
if (!id) return;
|
|
69
69
|
if (!orgId || !tenantId) {
|
|
@@ -110,21 +110,23 @@ function register(container) {
|
|
|
110
110
|
const makeDeleteHandler = (entityType) => async (payload, ctx) => {
|
|
111
111
|
try {
|
|
112
112
|
const em = ctx.resolve("em");
|
|
113
|
-
let orgId = payload?.organizationId || payload?.orgId || null;
|
|
113
|
+
let orgId = payload?.organizationId || payload?.orgId || ctx?.organizationId || null;
|
|
114
|
+
let tenantId = payload?.tenantId || ctx?.tenantId || null;
|
|
114
115
|
const id = String(payload?.id || payload?.recordId || "");
|
|
115
116
|
if (!id) return;
|
|
116
|
-
if (!orgId) {
|
|
117
|
+
if (!orgId || !tenantId) {
|
|
117
118
|
try {
|
|
118
119
|
const db = em.getKysely();
|
|
119
120
|
const table = resolveEntityTableName(em, entityType);
|
|
120
|
-
const row = await db.selectFrom(table).select(["organization_id"]).where("id", "=", id).executeTakeFirst();
|
|
121
|
+
const row = await db.selectFrom(table).select(["organization_id", "tenant_id"]).where("id", "=", id).executeTakeFirst();
|
|
121
122
|
orgId = row?.organization_id ?? orgId;
|
|
123
|
+
tenantId = row?.tenant_id ?? tenantId;
|
|
122
124
|
} catch {
|
|
123
125
|
}
|
|
124
126
|
}
|
|
125
127
|
try {
|
|
126
128
|
const bus2 = ctx.resolve("eventBus");
|
|
127
|
-
await bus2.emitEvent("query_index.delete_one", { entityType, recordId: id, organizationId: orgId });
|
|
129
|
+
await bus2.emitEvent("query_index.delete_one", { entityType, recordId: id, organizationId: orgId, tenantId });
|
|
128
130
|
} catch {
|
|
129
131
|
}
|
|
130
132
|
} catch {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/modules/query_index/di.ts"],
|
|
4
|
-
"sourcesContent": ["import type { AppContainer } from '@open-mercato/shared/lib/di/container'\nimport { BasicQueryEngine, resolveEntityTableName } from '@open-mercato/shared/lib/query/engine'\nimport { HybridQueryEngine } from './lib/engine'\nimport { markDeleted } from './lib/indexer'\nimport type { EventBus } from '@open-mercato/events'\nimport type { VectorIndexService } from '@open-mercato/search/vector'\n\nfunction toEntityTypeFromEvent(event: string): string | null {\n // Expect '<module>.<entity>.<action>'\n const parts = event.split('.')\n if (parts.length !== 3) return null\n const [mod, ent] = parts\n return `${mod}:${ent}`\n}\n\nexport function register(container: AppContainer) {\n // Override queryEngine with hybrid that prefers JSONB index when available\n try {\n const em = (container.resolve('em') as any)\n const basic = new BasicQueryEngine(\n em,\n undefined,\n () => {\n try {\n return container.resolve('tenantEncryptionService') as any\n } catch {\n return null\n }\n },\n )\n const hybrid = new HybridQueryEngine(\n em,\n basic,\n () => {\n try {\n return (container.resolve('eventBus') as EventBus)\n } catch {\n return null\n }\n },\n () => {\n try {\n return (container.resolve('vectorIndexService') as VectorIndexService)\n } catch {\n return null\n }\n },\n () => {\n try {\n return container.resolve('tenantEncryptionService') as any\n } catch {\n return null\n }\n },\n )\n // Replace existing registration\n ;(container as any).register({ queryEngine: { resolve: () => hybrid } })\n } catch {}\n\n // Subscribe to CRUD events and forward to query_index subscribers for unified handling\n const setup = () => {\n let bus: any\n try { bus = (container.resolve('eventBus') as any) } catch { bus = null }\n if (!bus) { setTimeout(setup, 0); return }\n\n const makeUpsertHandler = (entityType: string) => async (payload: any, ctx: any) => {\n try {\n const em = ctx.resolve('em')\n let orgId = payload?.organizationId || payload?.orgId || null\n let tenantId = payload?.tenantId || null\n const id = String(payload?.id || payload?.recordId || '')\n if (!id) return\n if (!orgId || !tenantId) {\n try {\n const db = (em as any).getKysely()\n const table = resolveEntityTableName(em, entityType)\n const row = await db\n .selectFrom(table as any)\n .select(['organization_id' as any, 'tenant_id' as any])\n .where('id' as any, '=', id)\n .executeTakeFirst() as { organization_id: string | null; tenant_id: string | null } | undefined\n orgId = row?.organization_id ?? orgId\n tenantId = row?.tenant_id ?? tenantId\n } catch {}\n }\n // Optional: only index when custom field definitions exist for this entity (org/global)\n try {\n const db = (em as any).getKysely()\n let cfQuery = db\n .selectFrom('custom_field_defs' as any)\n .select(['id' as any])\n .where('entity_id' as any, '=', entityType)\n .where('is_active' as any, '=', true)\n if (orgId != null) {\n cfQuery = cfQuery.where((eb: any) => eb.or([\n eb('organization_id' as any, '=', orgId),\n eb('organization_id' as any, 'is', null),\n ]))\n } else {\n cfQuery = cfQuery.where('organization_id' as any, 'is', null as any)\n }\n if (tenantId != null) {\n cfQuery = cfQuery.where((eb: any) => eb.or([\n eb('tenant_id' as any, '=', tenantId),\n eb('tenant_id' as any, 'is', null),\n ]))\n } else {\n cfQuery = cfQuery.where('tenant_id' as any, 'is', null as any)\n }\n const hasCf = await cfQuery.executeTakeFirst()\n if (!hasCf) return\n } catch {}\n try {\n const bus = ctx.resolve('eventBus') as any\n await bus.emitEvent('query_index.upsert_one', { entityType, recordId: id, organizationId: orgId, tenantId })\n } catch {}\n } catch {}\n }\n const makeDeleteHandler = (entityType: string) => async (payload: any, ctx: any) => {\n try {\n const em = ctx.resolve('em')\n let orgId = payload?.organizationId || payload?.orgId || null\n const id = String(payload?.id || payload?.recordId || '')\n if (!id) return\n if (!orgId) {\n try {\n const db = (em as any).getKysely()\n const table = resolveEntityTableName(em, entityType)\n const row = await db\n .selectFrom(table as any)\n .select(['organization_id' as any])\n .where('id' as any, '=', id)\n .executeTakeFirst() as { organization_id: string | null } | undefined\n orgId = row?.organization_id ?? orgId\n } catch {}\n }\n try {\n const bus = ctx.resolve('eventBus') as any\n await bus.emitEvent('query_index.delete_one', { entityType, recordId: id, organizationId: orgId })\n } catch {}\n } catch {}\n }\n\n // Build list of entity ids to subscribe to\n try {\n const em = (container.resolve('em') as any)\n const db = (em as any).getKysely()\n const cfEntityIds: string[] = []\n db\n .selectFrom('custom_field_defs' as any)\n .select(['entity_id' as any])\n .distinct()\n .execute()\n .then((rows: any[]) => {\n for (const r of rows || []) cfEntityIds.push(String(r.entity_id))\n })\n .catch(() => {})\n .finally(() => {\n const proceed = (ids: string[]) => {\n for (const entityType of Array.from(new Set(ids))) {\n const [mod, ent] = entityType.split(':')\n if (!mod || !ent) continue\n bus.on(`${mod}.${ent}.created`, makeUpsertHandler(entityType))\n bus.on(`${mod}.${ent}.updated`, makeUpsertHandler(entityType))\n bus.on(`${mod}.${ent}.deleted`, makeDeleteHandler(entityType))\n }\n }\n if (cfEntityIds.length > 0) {\n proceed(cfEntityIds)\n } else {\n // Fallback to generated entity ids without await\n import('#generated/entities.ids.generated').then((core) => {\n const flatten = (E: any): string[] => Object.values(E || {}).flatMap((o: any) => Object.values(o || {}) as string[])\n const guesses = new Set<string>([...flatten((core as any).E)])\n proceed(Array.from(guesses))\n }).catch(() => {})\n }\n })\n } catch {}\n }\n\n try { setup() } catch {}\n}\n"],
|
|
5
|
-
"mappings": "AACA,SAAS,kBAAkB,8BAA8B;AACzD,SAAS,yBAAyB;AAKlC,SAAS,sBAAsB,OAA8B;AAE3D,QAAM,QAAQ,MAAM,MAAM,GAAG;AAC7B,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,QAAM,CAAC,KAAK,GAAG,IAAI;AACnB,SAAO,GAAG,GAAG,IAAI,GAAG;AACtB;AAEO,SAAS,SAAS,WAAyB;AAEhD,MAAI;AACF,UAAM,KAAM,UAAU,QAAQ,IAAI;AAClC,UAAM,QAAQ,IAAI;AAAA,MAChB;AAAA,MACA;AAAA,MACA,MAAM;AACJ,YAAI;AACF,iBAAO,UAAU,QAAQ,yBAAyB;AAAA,QACpD,QAAQ;AACN,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AACA,UAAM,SAAS,IAAI;AAAA,MACjB;AAAA,MACA;AAAA,MACA,MAAM;AACJ,YAAI;AACF,iBAAQ,UAAU,QAAQ,UAAU;AAAA,QACtC,QAAQ;AACN,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA,MAAM;AACJ,YAAI;AACF,iBAAQ,UAAU,QAAQ,oBAAoB;AAAA,QAChD,QAAQ;AACN,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA,MAAM;AACJ,YAAI;AACF,iBAAO,UAAU,QAAQ,yBAAyB;AAAA,QACpD,QAAQ;AACN,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAEC,IAAC,UAAkB,SAAS,EAAE,aAAa,EAAE,SAAS,MAAM,OAAO,EAAE,CAAC;AAAA,EACzE,QAAQ;AAAA,EAAC;AAGT,QAAM,QAAQ,MAAM;AAClB,QAAI;AACJ,QAAI;AAAE,YAAO,UAAU,QAAQ,UAAU;AAAA,IAAU,QAAQ;AAAE,YAAM;AAAA,IAAK;AACxE,QAAI,CAAC,KAAK;AAAE,iBAAW,OAAO,CAAC;AAAG;AAAA,IAAO;AAEzC,UAAM,oBAAoB,CAAC,eAAuB,OAAO,SAAc,QAAa;AAClF,UAAI;AACF,cAAM,KAAK,IAAI,QAAQ,IAAI;AAC3B,YAAI,QAAQ,SAAS,kBAAkB,SAAS,SAAS;
|
|
4
|
+
"sourcesContent": ["import type { AppContainer } from '@open-mercato/shared/lib/di/container'\nimport { BasicQueryEngine, resolveEntityTableName } from '@open-mercato/shared/lib/query/engine'\nimport { HybridQueryEngine } from './lib/engine'\nimport { markDeleted } from './lib/indexer'\nimport type { EventBus } from '@open-mercato/events'\nimport type { VectorIndexService } from '@open-mercato/search/vector'\n\nfunction toEntityTypeFromEvent(event: string): string | null {\n // Expect '<module>.<entity>.<action>'\n const parts = event.split('.')\n if (parts.length !== 3) return null\n const [mod, ent] = parts\n return `${mod}:${ent}`\n}\n\nexport function register(container: AppContainer) {\n // Override queryEngine with hybrid that prefers JSONB index when available\n try {\n const em = (container.resolve('em') as any)\n const basic = new BasicQueryEngine(\n em,\n undefined,\n () => {\n try {\n return container.resolve('tenantEncryptionService') as any\n } catch {\n return null\n }\n },\n )\n const hybrid = new HybridQueryEngine(\n em,\n basic,\n () => {\n try {\n return (container.resolve('eventBus') as EventBus)\n } catch {\n return null\n }\n },\n () => {\n try {\n return (container.resolve('vectorIndexService') as VectorIndexService)\n } catch {\n return null\n }\n },\n () => {\n try {\n return container.resolve('tenantEncryptionService') as any\n } catch {\n return null\n }\n },\n )\n // Replace existing registration\n ;(container as any).register({ queryEngine: { resolve: () => hybrid } })\n } catch {}\n\n // Subscribe to CRUD events and forward to query_index subscribers for unified handling\n const setup = () => {\n let bus: any\n try { bus = (container.resolve('eventBus') as any) } catch { bus = null }\n if (!bus) { setTimeout(setup, 0); return }\n\n const makeUpsertHandler = (entityType: string) => async (payload: any, ctx: any) => {\n try {\n const em = ctx.resolve('em')\n let orgId = payload?.organizationId || payload?.orgId || ctx?.organizationId || null\n let tenantId = payload?.tenantId || ctx?.tenantId || null\n const id = String(payload?.id || payload?.recordId || '')\n if (!id) return\n if (!orgId || !tenantId) {\n try {\n const db = (em as any).getKysely()\n const table = resolveEntityTableName(em, entityType)\n const row = await db\n .selectFrom(table as any)\n .select(['organization_id' as any, 'tenant_id' as any])\n .where('id' as any, '=', id)\n .executeTakeFirst() as { organization_id: string | null; tenant_id: string | null } | undefined\n orgId = row?.organization_id ?? orgId\n tenantId = row?.tenant_id ?? tenantId\n } catch {}\n }\n // Optional: only index when custom field definitions exist for this entity (org/global)\n try {\n const db = (em as any).getKysely()\n let cfQuery = db\n .selectFrom('custom_field_defs' as any)\n .select(['id' as any])\n .where('entity_id' as any, '=', entityType)\n .where('is_active' as any, '=', true)\n if (orgId != null) {\n cfQuery = cfQuery.where((eb: any) => eb.or([\n eb('organization_id' as any, '=', orgId),\n eb('organization_id' as any, 'is', null),\n ]))\n } else {\n cfQuery = cfQuery.where('organization_id' as any, 'is', null as any)\n }\n if (tenantId != null) {\n cfQuery = cfQuery.where((eb: any) => eb.or([\n eb('tenant_id' as any, '=', tenantId),\n eb('tenant_id' as any, 'is', null),\n ]))\n } else {\n cfQuery = cfQuery.where('tenant_id' as any, 'is', null as any)\n }\n const hasCf = await cfQuery.executeTakeFirst()\n if (!hasCf) return\n } catch {}\n try {\n const bus = ctx.resolve('eventBus') as any\n await bus.emitEvent('query_index.upsert_one', { entityType, recordId: id, organizationId: orgId, tenantId })\n } catch {}\n } catch {}\n }\n const makeDeleteHandler = (entityType: string) => async (payload: any, ctx: any) => {\n try {\n const em = ctx.resolve('em')\n let orgId = payload?.organizationId || payload?.orgId || ctx?.organizationId || null\n let tenantId = payload?.tenantId || ctx?.tenantId || null\n const id = String(payload?.id || payload?.recordId || '')\n if (!id) return\n if (!orgId || !tenantId) {\n try {\n const db = (em as any).getKysely()\n const table = resolveEntityTableName(em, entityType)\n const row = await db\n .selectFrom(table as any)\n .select(['organization_id' as any, 'tenant_id' as any])\n .where('id' as any, '=', id)\n .executeTakeFirst() as { organization_id: string | null; tenant_id: string | null } | undefined\n orgId = row?.organization_id ?? orgId\n tenantId = row?.tenant_id ?? tenantId\n } catch {}\n }\n try {\n const bus = ctx.resolve('eventBus') as any\n await bus.emitEvent('query_index.delete_one', { entityType, recordId: id, organizationId: orgId, tenantId })\n } catch {}\n } catch {}\n }\n\n // Build list of entity ids to subscribe to\n try {\n const em = (container.resolve('em') as any)\n const db = (em as any).getKysely()\n const cfEntityIds: string[] = []\n db\n .selectFrom('custom_field_defs' as any)\n .select(['entity_id' as any])\n .distinct()\n .execute()\n .then((rows: any[]) => {\n for (const r of rows || []) cfEntityIds.push(String(r.entity_id))\n })\n .catch(() => {})\n .finally(() => {\n const proceed = (ids: string[]) => {\n for (const entityType of Array.from(new Set(ids))) {\n const [mod, ent] = entityType.split(':')\n if (!mod || !ent) continue\n bus.on(`${mod}.${ent}.created`, makeUpsertHandler(entityType))\n bus.on(`${mod}.${ent}.updated`, makeUpsertHandler(entityType))\n bus.on(`${mod}.${ent}.deleted`, makeDeleteHandler(entityType))\n }\n }\n if (cfEntityIds.length > 0) {\n proceed(cfEntityIds)\n } else {\n // Fallback to generated entity ids without await\n import('#generated/entities.ids.generated').then((core) => {\n const flatten = (E: any): string[] => Object.values(E || {}).flatMap((o: any) => Object.values(o || {}) as string[])\n const guesses = new Set<string>([...flatten((core as any).E)])\n proceed(Array.from(guesses))\n }).catch(() => {})\n }\n })\n } catch {}\n }\n\n try { setup() } catch {}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["bus"]
|
|
7
7
|
}
|
|
@@ -157,21 +157,23 @@ async function upsertIndexRow(em, args) {
|
|
|
157
157
|
const created = !existed;
|
|
158
158
|
const revived = existed && wasDeleted;
|
|
159
159
|
try {
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
160
|
+
const tokenDoc = args.searchTokenDoc ?? (() => {
|
|
161
|
+
const encryption = resolveTenantEncryptionService(em);
|
|
162
|
+
const dekKeyCache = /* @__PURE__ */ new Map();
|
|
163
|
+
return decryptIndexDocForSearch(
|
|
164
|
+
args.entityType,
|
|
165
|
+
doc,
|
|
166
|
+
{ tenantId: args.tenantId ?? null, organizationId: args.organizationId ?? null },
|
|
167
|
+
encryption,
|
|
168
|
+
dekKeyCache
|
|
169
|
+
);
|
|
170
|
+
})();
|
|
169
171
|
await replaceSearchTokensForRecord(db, {
|
|
170
172
|
entityType: args.entityType,
|
|
171
173
|
recordId: args.recordId,
|
|
172
174
|
organizationId: args.organizationId ?? null,
|
|
173
175
|
tenantId: args.tenantId ?? null,
|
|
174
|
-
doc: tokenDoc
|
|
176
|
+
doc: await tokenDoc
|
|
175
177
|
});
|
|
176
178
|
} catch {
|
|
177
179
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/query_index/lib/indexer.ts"],
|
|
4
|
-
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { resolveEntityTableName } from '@open-mercato/shared/lib/query/engine'\nimport { resolveTenantEncryptionService } from '@open-mercato/shared/lib/encryption/customFieldValues'\nimport { decryptIndexDocForSearch, encryptIndexDocForStorage } from '@open-mercato/shared/lib/encryption/indexDoc'\nimport { sql } from 'kysely'\nimport { replaceSearchTokensForRecord, deleteSearchTokensForRecord } from './search-tokens'\nimport { attachAggregateSearchField } from './document'\n\ntype BuildDocParams = {\n entityType: string // '<module>:<entity>'\n recordId: string\n organizationId?: string | null\n tenantId?: string | null\n}\n\nexport async function buildIndexDoc(em: EntityManager, params: BuildDocParams): Promise<Record<string, any> | null> {\n const db = (em as any).getKysely()\n const baseTable = resolveEntityTableName(em, params.entityType)\n\n // Fetch base row\n const baseRow = await db\n .selectFrom(baseTable as any)\n .selectAll()\n .where('id' as any, '=', params.recordId)\n .executeTakeFirst() as Record<string, any> | undefined\n if (!baseRow) return null\n const docSources: Array<Record<string, any>> = []\n\n // Attach the core customer entity when indexing customer profiles so search tokens see the combined row\n let parentEntityRow: Record<string, any> | null = null\n if (params.entityType === 'customers:customer_person_profile' || params.entityType === 'customers:customer_company_profile') {\n const entityId = (baseRow as any).entity_id ?? (baseRow as any).entityId\n if (entityId) {\n const entityRow = await db\n .selectFrom('customer_entities' as any)\n .selectAll()\n .where('id' as any, '=', entityId)\n .executeTakeFirst() as Record<string, any> | undefined\n if (entityRow) {\n docSources.push(entityRow)\n parentEntityRow = entityRow\n }\n }\n }\n void parentEntityRow\n\n // Build base document (snake_case keys as in DB)\n let doc: Record<string, any> = {}\n docSources.push(baseRow)\n for (const source of docSources) {\n for (const [k, v] of Object.entries(source)) doc[k] = v\n }\n\n // Attach custom fields under flat keys 'cf:<key>'\n let cfQuery = db\n .selectFrom('custom_field_values' as any)\n .select([\n 'field_key' as any,\n 'value_text' as any,\n 'value_multiline' as any,\n 'value_int' as any,\n 'value_float' as any,\n 'value_bool' as any,\n ])\n .where('entity_id' as any, '=', params.entityType)\n .where('record_id' as any, '=', String(params.recordId))\n\n if (params.organizationId != null) {\n cfQuery = cfQuery.where((eb: any) => eb.or([\n eb('organization_id' as any, '=', params.organizationId),\n eb('organization_id' as any, 'is', null),\n ]))\n } else {\n cfQuery = cfQuery.where('organization_id' as any, 'is', null)\n }\n\n if (params.tenantId != null) {\n cfQuery = cfQuery.where((eb: any) => eb.or([\n eb('tenant_id' as any, '=', params.tenantId),\n eb('tenant_id' as any, 'is', null),\n ]))\n } else {\n cfQuery = cfQuery.where('tenant_id' as any, 'is', null)\n }\n\n const cfRows = await cfQuery.execute() as Array<Record<string, any>>\n\n const cfMap: Record<string, any[]> = {}\n for (const r of cfRows) {\n const key = String(r.field_key)\n const cfKey = `cf:${key}`\n const val = r.value_bool ?? r.value_int ?? r.value_float ?? r.value_text ?? r.value_multiline ?? null\n if (!cfMap[cfKey]) cfMap[cfKey] = []\n cfMap[cfKey].push(val)\n }\n for (const [key, arr] of Object.entries(cfMap)) {\n // Store singletons as simple value; multis as array\n doc[key] = arr.length <= 1 ? arr[0] : arr\n }\n\n // Attach translations under flat keys 'l10n:{locale}:{field}'\n try {\n const translationRow = await db\n .selectFrom('entity_translations' as any)\n .select(['translations' as any])\n .where('entity_type' as any, '=', params.entityType)\n .where('entity_id' as any, '=', String(params.recordId))\n .where(sql`tenant_id is not distinct from ${params.tenantId ?? null}`)\n .where(sql`organization_id is not distinct from ${params.organizationId ?? null}`)\n .executeTakeFirst() as { translations: Record<string, Record<string, unknown>> | null } | undefined\n\n if (translationRow?.translations && typeof translationRow.translations === 'object') {\n for (const [locale, fields] of Object.entries(translationRow.translations)) {\n if (!fields || typeof fields !== 'object') continue\n for (const [field, value] of Object.entries(fields as Record<string, unknown>)) {\n if (typeof value === 'string' && value.length > 0) {\n doc[`l10n:${locale}:${field}`] = value\n }\n }\n }\n }\n } catch {}\n\n try {\n doc = attachAggregateSearchField(doc)\n const encryption = resolveTenantEncryptionService(em as any)\n doc = await encryptIndexDocForStorage(\n params.entityType,\n doc,\n { tenantId: params.tenantId ?? null, organizationId: params.organizationId ?? null },\n encryption,\n )\n } catch {}\n\n return doc\n}\n\nexport type UpsertIndexResult = {\n doc: Record<string, any> | null\n existed: boolean\n wasDeleted: boolean\n created: boolean\n revived: boolean\n}\n\nfunction scopeEntityIndexes<QB extends { where: (...args: any[]) => QB }>(\n q: QB,\n args: { entityType: string; recordId: string; organizationId?: string | null; tenantId?: string | null },\n): QB {\n let chain = q.where('entity_type' as any, '=', args.entityType)\n chain = chain.where('entity_id' as any, '=', String(args.recordId))\n chain = args.organizationId == null\n ? chain.where('organization_id' as any, 'is', null as any)\n : chain.where('organization_id' as any, '=', args.organizationId)\n chain = chain.where(sql`tenant_id is not distinct from ${args.tenantId ?? null}`)\n return chain\n}\n\nexport async function upsertIndexRow(\n em: EntityManager,\n args: { entityType: string; recordId: string; organizationId?: string | null; tenantId?: string | null }\n): Promise<UpsertIndexResult> {\n const db = (em as any).getKysely()\n\n const existing = await scopeEntityIndexes(\n db.selectFrom('entity_indexes' as any).select(['id' as any, 'deleted_at' as any]),\n args,\n ).executeTakeFirst() as { id: string; deleted_at: Date | null } | undefined\n\n const existed = !!existing\n const wasDeleted = !!existing && existing.deleted_at != null\n\n const doc = await buildIndexDoc(em, args)\n if (!doc) {\n try {\n await deleteSearchTokensForRecord(db, {\n entityType: args.entityType,\n recordId: args.recordId,\n organizationId: args.organizationId ?? null,\n tenantId: args.tenantId ?? null,\n })\n } catch {}\n if (existed) {\n await scopeEntityIndexes(\n db.deleteFrom('entity_indexes' as any) as any,\n args,\n ).execute()\n }\n return { doc: null, existed, wasDeleted, created: false, revived: false }\n }\n\n const payload = {\n entity_type: args.entityType,\n entity_id: String(args.recordId),\n organization_id: args.organizationId ?? null,\n tenant_id: args.tenantId ?? null,\n doc: sql`${JSON.stringify(doc)}::jsonb`,\n index_version: 1,\n updated_at: sql`now()`,\n deleted_at: null,\n }\n\n // Prefer modern upsert keyed by coalesced org id when available; fallback to update-then-insert\n try {\n await db\n .insertInto('entity_indexes' as any)\n .values({ ...payload, created_at: sql`now()` } as any)\n .onConflict((oc: any) => oc\n .columns(['entity_type', 'entity_id', 'organization_id_coalesced'])\n .doUpdateSet({\n tenant_id: args.tenantId ?? null,\n doc: sql`${JSON.stringify(doc)}::jsonb`,\n index_version: 1,\n updated_at: sql`now()`,\n deleted_at: null,\n } as any))\n .execute()\n } catch {\n // Fallback for schemas without organization_id_coalesced column/index\n const updated = await scopeEntityIndexes(\n db.updateTable('entity_indexes' as any).set(payload as any) as any,\n args,\n ).executeTakeFirst() as { numUpdatedRows?: bigint | number } | undefined\n if (!updated || Number(updated.numUpdatedRows ?? 0) === 0) {\n try {\n await db\n .insertInto('entity_indexes' as any)\n .values({ ...payload, created_at: sql`now()` } as any)\n .execute()\n } catch {}\n }\n }\n\n const created = !existed\n const revived = existed && wasDeleted\n try {\n const encryption = resolveTenantEncryptionService(em as any)\n const dekKeyCache = new Map<string | null, string | null>()\n const tokenDoc = await decryptIndexDocForSearch(\n args.entityType,\n doc,\n { tenantId: args.tenantId ?? null, organizationId: args.organizationId ?? null },\n encryption,\n dekKeyCache,\n )\n await replaceSearchTokensForRecord(db, {\n entityType: args.entityType,\n recordId: args.recordId,\n organizationId: args.organizationId ?? null,\n tenantId: args.tenantId ?? null,\n doc: tokenDoc,\n })\n } catch {}\n return { doc, existed, wasDeleted, created, revived }\n}\n\nexport async function markDeleted(\n em: EntityManager,\n args: { entityType: string; recordId: string; organizationId?: string | null; tenantId?: string | null }\n): Promise<{ wasActive: boolean }> {\n const db = (em as any).getKysely()\n const existing = await scopeEntityIndexes(\n db.selectFrom('entity_indexes' as any).select(['deleted_at' as any]),\n args,\n ).executeTakeFirst() as { deleted_at: Date | null } | undefined\n\n const wasActive = !!existing && existing.deleted_at == null\n\n if (existing) {\n try {\n await deleteSearchTokensForRecord(db, {\n entityType: args.entityType,\n recordId: args.recordId,\n organizationId: args.organizationId ?? null,\n tenantId: args.tenantId ?? null,\n })\n } catch {}\n await scopeEntityIndexes(\n db.deleteFrom('entity_indexes' as any) as any,\n args,\n ).execute()\n }\n\n return { wasActive }\n}\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { resolveEntityTableName } from '@open-mercato/shared/lib/query/engine'\nimport { resolveTenantEncryptionService } from '@open-mercato/shared/lib/encryption/customFieldValues'\nimport { decryptIndexDocForSearch, encryptIndexDocForStorage } from '@open-mercato/shared/lib/encryption/indexDoc'\nimport { sql } from 'kysely'\nimport { replaceSearchTokensForRecord, deleteSearchTokensForRecord } from './search-tokens'\nimport { attachAggregateSearchField } from './document'\n\ntype BuildDocParams = {\n entityType: string // '<module>:<entity>'\n recordId: string\n organizationId?: string | null\n tenantId?: string | null\n}\n\nexport async function buildIndexDoc(em: EntityManager, params: BuildDocParams): Promise<Record<string, any> | null> {\n const db = (em as any).getKysely()\n const baseTable = resolveEntityTableName(em, params.entityType)\n\n // Fetch base row\n const baseRow = await db\n .selectFrom(baseTable as any)\n .selectAll()\n .where('id' as any, '=', params.recordId)\n .executeTakeFirst() as Record<string, any> | undefined\n if (!baseRow) return null\n const docSources: Array<Record<string, any>> = []\n\n // Attach the core customer entity when indexing customer profiles so search tokens see the combined row\n let parentEntityRow: Record<string, any> | null = null\n if (params.entityType === 'customers:customer_person_profile' || params.entityType === 'customers:customer_company_profile') {\n const entityId = (baseRow as any).entity_id ?? (baseRow as any).entityId\n if (entityId) {\n const entityRow = await db\n .selectFrom('customer_entities' as any)\n .selectAll()\n .where('id' as any, '=', entityId)\n .executeTakeFirst() as Record<string, any> | undefined\n if (entityRow) {\n docSources.push(entityRow)\n parentEntityRow = entityRow\n }\n }\n }\n void parentEntityRow\n\n // Build base document (snake_case keys as in DB)\n let doc: Record<string, any> = {}\n docSources.push(baseRow)\n for (const source of docSources) {\n for (const [k, v] of Object.entries(source)) doc[k] = v\n }\n\n // Attach custom fields under flat keys 'cf:<key>'\n let cfQuery = db\n .selectFrom('custom_field_values' as any)\n .select([\n 'field_key' as any,\n 'value_text' as any,\n 'value_multiline' as any,\n 'value_int' as any,\n 'value_float' as any,\n 'value_bool' as any,\n ])\n .where('entity_id' as any, '=', params.entityType)\n .where('record_id' as any, '=', String(params.recordId))\n\n if (params.organizationId != null) {\n cfQuery = cfQuery.where((eb: any) => eb.or([\n eb('organization_id' as any, '=', params.organizationId),\n eb('organization_id' as any, 'is', null),\n ]))\n } else {\n cfQuery = cfQuery.where('organization_id' as any, 'is', null)\n }\n\n if (params.tenantId != null) {\n cfQuery = cfQuery.where((eb: any) => eb.or([\n eb('tenant_id' as any, '=', params.tenantId),\n eb('tenant_id' as any, 'is', null),\n ]))\n } else {\n cfQuery = cfQuery.where('tenant_id' as any, 'is', null)\n }\n\n const cfRows = await cfQuery.execute() as Array<Record<string, any>>\n\n const cfMap: Record<string, any[]> = {}\n for (const r of cfRows) {\n const key = String(r.field_key)\n const cfKey = `cf:${key}`\n const val = r.value_bool ?? r.value_int ?? r.value_float ?? r.value_text ?? r.value_multiline ?? null\n if (!cfMap[cfKey]) cfMap[cfKey] = []\n cfMap[cfKey].push(val)\n }\n for (const [key, arr] of Object.entries(cfMap)) {\n // Store singletons as simple value; multis as array\n doc[key] = arr.length <= 1 ? arr[0] : arr\n }\n\n // Attach translations under flat keys 'l10n:{locale}:{field}'\n try {\n const translationRow = await db\n .selectFrom('entity_translations' as any)\n .select(['translations' as any])\n .where('entity_type' as any, '=', params.entityType)\n .where('entity_id' as any, '=', String(params.recordId))\n .where(sql`tenant_id is not distinct from ${params.tenantId ?? null}`)\n .where(sql`organization_id is not distinct from ${params.organizationId ?? null}`)\n .executeTakeFirst() as { translations: Record<string, Record<string, unknown>> | null } | undefined\n\n if (translationRow?.translations && typeof translationRow.translations === 'object') {\n for (const [locale, fields] of Object.entries(translationRow.translations)) {\n if (!fields || typeof fields !== 'object') continue\n for (const [field, value] of Object.entries(fields as Record<string, unknown>)) {\n if (typeof value === 'string' && value.length > 0) {\n doc[`l10n:${locale}:${field}`] = value\n }\n }\n }\n }\n } catch {}\n\n try {\n doc = attachAggregateSearchField(doc)\n const encryption = resolveTenantEncryptionService(em as any)\n doc = await encryptIndexDocForStorage(\n params.entityType,\n doc,\n { tenantId: params.tenantId ?? null, organizationId: params.organizationId ?? null },\n encryption,\n )\n } catch {}\n\n return doc\n}\n\nexport type UpsertIndexResult = {\n doc: Record<string, any> | null\n existed: boolean\n wasDeleted: boolean\n created: boolean\n revived: boolean\n}\n\nfunction scopeEntityIndexes<QB extends { where: (...args: any[]) => QB }>(\n q: QB,\n args: { entityType: string; recordId: string; organizationId?: string | null; tenantId?: string | null },\n): QB {\n let chain = q.where('entity_type' as any, '=', args.entityType)\n chain = chain.where('entity_id' as any, '=', String(args.recordId))\n chain = args.organizationId == null\n ? chain.where('organization_id' as any, 'is', null as any)\n : chain.where('organization_id' as any, '=', args.organizationId)\n chain = chain.where(sql`tenant_id is not distinct from ${args.tenantId ?? null}`)\n return chain\n}\n\nexport async function upsertIndexRow(\n em: EntityManager,\n args: { entityType: string; recordId: string; organizationId?: string | null; tenantId?: string | null; searchTokenDoc?: Record<string, unknown> | null }\n): Promise<UpsertIndexResult> {\n const db = (em as any).getKysely()\n\n const existing = await scopeEntityIndexes(\n db.selectFrom('entity_indexes' as any).select(['id' as any, 'deleted_at' as any]),\n args,\n ).executeTakeFirst() as { id: string; deleted_at: Date | null } | undefined\n\n const existed = !!existing\n const wasDeleted = !!existing && existing.deleted_at != null\n\n const doc = await buildIndexDoc(em, args)\n if (!doc) {\n try {\n await deleteSearchTokensForRecord(db, {\n entityType: args.entityType,\n recordId: args.recordId,\n organizationId: args.organizationId ?? null,\n tenantId: args.tenantId ?? null,\n })\n } catch {}\n if (existed) {\n await scopeEntityIndexes(\n db.deleteFrom('entity_indexes' as any) as any,\n args,\n ).execute()\n }\n return { doc: null, existed, wasDeleted, created: false, revived: false }\n }\n\n const payload = {\n entity_type: args.entityType,\n entity_id: String(args.recordId),\n organization_id: args.organizationId ?? null,\n tenant_id: args.tenantId ?? null,\n doc: sql`${JSON.stringify(doc)}::jsonb`,\n index_version: 1,\n updated_at: sql`now()`,\n deleted_at: null,\n }\n\n // Prefer modern upsert keyed by coalesced org id when available; fallback to update-then-insert\n try {\n await db\n .insertInto('entity_indexes' as any)\n .values({ ...payload, created_at: sql`now()` } as any)\n .onConflict((oc: any) => oc\n .columns(['entity_type', 'entity_id', 'organization_id_coalesced'])\n .doUpdateSet({\n tenant_id: args.tenantId ?? null,\n doc: sql`${JSON.stringify(doc)}::jsonb`,\n index_version: 1,\n updated_at: sql`now()`,\n deleted_at: null,\n } as any))\n .execute()\n } catch {\n // Fallback for schemas without organization_id_coalesced column/index\n const updated = await scopeEntityIndexes(\n db.updateTable('entity_indexes' as any).set(payload as any) as any,\n args,\n ).executeTakeFirst() as { numUpdatedRows?: bigint | number } | undefined\n if (!updated || Number(updated.numUpdatedRows ?? 0) === 0) {\n try {\n await db\n .insertInto('entity_indexes' as any)\n .values({ ...payload, created_at: sql`now()` } as any)\n .execute()\n } catch {}\n }\n }\n\n const created = !existed\n const revived = existed && wasDeleted\n try {\n const tokenDoc = args.searchTokenDoc ?? (() => {\n const encryption = resolveTenantEncryptionService(em as any)\n const dekKeyCache = new Map<string | null, string | null>()\n return decryptIndexDocForSearch(\n args.entityType,\n doc,\n { tenantId: args.tenantId ?? null, organizationId: args.organizationId ?? null },\n encryption,\n dekKeyCache,\n )\n })()\n await replaceSearchTokensForRecord(db, {\n entityType: args.entityType,\n recordId: args.recordId,\n organizationId: args.organizationId ?? null,\n tenantId: args.tenantId ?? null,\n doc: await tokenDoc,\n })\n } catch {}\n return { doc, existed, wasDeleted, created, revived }\n}\n\nexport async function markDeleted(\n em: EntityManager,\n args: { entityType: string; recordId: string; organizationId?: string | null; tenantId?: string | null }\n): Promise<{ wasActive: boolean }> {\n const db = (em as any).getKysely()\n const existing = await scopeEntityIndexes(\n db.selectFrom('entity_indexes' as any).select(['deleted_at' as any]),\n args,\n ).executeTakeFirst() as { deleted_at: Date | null } | undefined\n\n const wasActive = !!existing && existing.deleted_at == null\n\n if (existing) {\n try {\n await deleteSearchTokensForRecord(db, {\n entityType: args.entityType,\n recordId: args.recordId,\n organizationId: args.organizationId ?? null,\n tenantId: args.tenantId ?? null,\n })\n } catch {}\n await scopeEntityIndexes(\n db.deleteFrom('entity_indexes' as any) as any,\n args,\n ).execute()\n }\n\n return { wasActive }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -25,7 +25,13 @@ async function handle(payload, ctx) {
|
|
|
25
25
|
});
|
|
26
26
|
organizationId = resolvedScope.organizationId;
|
|
27
27
|
tenantId = resolvedScope.tenantId;
|
|
28
|
-
const result = await upsertIndexRow(em, {
|
|
28
|
+
const result = await upsertIndexRow(em, {
|
|
29
|
+
entityType,
|
|
30
|
+
recordId,
|
|
31
|
+
organizationId,
|
|
32
|
+
tenantId,
|
|
33
|
+
searchTokenDoc: typeof payload?.searchTokenDoc === "object" && payload.searchTokenDoc && !Array.isArray(payload.searchTokenDoc) ? payload.searchTokenDoc : null
|
|
34
|
+
});
|
|
29
35
|
if (!suppressCoverage) {
|
|
30
36
|
const doc = result.doc;
|
|
31
37
|
const isActive = !!doc && (doc.deleted_at == null || doc.deleted_at === null);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/query_index/subscribers/upsert_one.ts"],
|
|
4
|
-
"sourcesContent": ["import { recordIndexerError } from '@open-mercato/shared/lib/indexers/error-log'\nimport { upsertIndexRow } from '../lib/indexer'\nimport { applyCoverageAdjustments, createCoverageAdjustments } from '../lib/coverage'\nimport { loadQueryIndexRowScope, resolveQueryIndexRecordScope } from '../lib/subscriber-scope'\n\nexport const metadata = { event: 'query_index.upsert_one', persistent: false }\n\nexport default async function handle(payload: any, ctx: { resolve: <T=any>(name: string) => T }) {\n const em = ctx.resolve<any>('em')\n const entityType = String(payload?.entityType || '')\n const recordId = String(payload?.recordId || '')\n if (!entityType || !recordId) return\n let organizationId: string | null = payload?.organizationId ?? null\n let tenantId: string | null = payload?.tenantId ?? null\n const suppressCoverage = payload?.suppressCoverage === true\n const coverageDelayMs = typeof payload?.coverageDelayMs === 'number' ? payload.coverageDelayMs : undefined\n try {\n const hasPayloadOrganizationId = Object.prototype.hasOwnProperty.call(payload ?? {}, 'organizationId')\n const hasPayloadTenantId = Object.prototype.hasOwnProperty.call(payload ?? {}, 'tenantId')\n const rowScope = await loadQueryIndexRowScope(em, entityType, recordId).catch(() => null)\n const resolvedScope = resolveQueryIndexRecordScope({\n payloadOrganizationId: payload?.organizationId,\n payloadTenantId: payload?.tenantId,\n hasPayloadOrganizationId,\n hasPayloadTenantId,\n rowScope,\n })\n organizationId = resolvedScope.organizationId\n tenantId = resolvedScope.tenantId\n\n const result = await upsertIndexRow(em, {
|
|
5
|
-
"mappings": "AAAA,SAAS,0BAA0B;AACnC,SAAS,sBAAsB;AAC/B,SAAS,0BAA0B,iCAAiC;AACpE,SAAS,wBAAwB,oCAAoC;AAE9D,MAAM,WAAW,EAAE,OAAO,0BAA0B,YAAY,MAAM;AAE7E,eAAO,OAA8B,SAAc,KAA8C;AAC/F,QAAM,KAAK,IAAI,QAAa,IAAI;AAChC,QAAM,aAAa,OAAO,SAAS,cAAc,EAAE;AACnD,QAAM,WAAW,OAAO,SAAS,YAAY,EAAE;AAC/C,MAAI,CAAC,cAAc,CAAC,SAAU;AAC9B,MAAI,iBAAgC,SAAS,kBAAkB;AAC/D,MAAI,WAA0B,SAAS,YAAY;AACnD,QAAM,mBAAmB,SAAS,qBAAqB;AACvD,QAAM,kBAAkB,OAAO,SAAS,oBAAoB,WAAW,QAAQ,kBAAkB;AACjG,MAAI;AACF,UAAM,2BAA2B,OAAO,UAAU,eAAe,KAAK,WAAW,CAAC,GAAG,gBAAgB;AACrG,UAAM,qBAAqB,OAAO,UAAU,eAAe,KAAK,WAAW,CAAC,GAAG,UAAU;AACzF,UAAM,WAAW,MAAM,uBAAuB,IAAI,YAAY,QAAQ,EAAE,MAAM,MAAM,IAAI;AACxF,UAAM,gBAAgB,6BAA6B;AAAA,MACjD,uBAAuB,SAAS;AAAA,MAChC,iBAAiB,SAAS;AAAA,MAC1B;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AACD,qBAAiB,cAAc;AAC/B,eAAW,cAAc;AAEzB,UAAM,SAAS,MAAM,eAAe,IAAI,
|
|
4
|
+
"sourcesContent": ["import { recordIndexerError } from '@open-mercato/shared/lib/indexers/error-log'\nimport { upsertIndexRow } from '../lib/indexer'\nimport { applyCoverageAdjustments, createCoverageAdjustments } from '../lib/coverage'\nimport { loadQueryIndexRowScope, resolveQueryIndexRecordScope } from '../lib/subscriber-scope'\n\nexport const metadata = { event: 'query_index.upsert_one', persistent: false }\n\nexport default async function handle(payload: any, ctx: { resolve: <T=any>(name: string) => T }) {\n const em = ctx.resolve<any>('em')\n const entityType = String(payload?.entityType || '')\n const recordId = String(payload?.recordId || '')\n if (!entityType || !recordId) return\n let organizationId: string | null = payload?.organizationId ?? null\n let tenantId: string | null = payload?.tenantId ?? null\n const suppressCoverage = payload?.suppressCoverage === true\n const coverageDelayMs = typeof payload?.coverageDelayMs === 'number' ? payload.coverageDelayMs : undefined\n try {\n const hasPayloadOrganizationId = Object.prototype.hasOwnProperty.call(payload ?? {}, 'organizationId')\n const hasPayloadTenantId = Object.prototype.hasOwnProperty.call(payload ?? {}, 'tenantId')\n const rowScope = await loadQueryIndexRowScope(em, entityType, recordId).catch(() => null)\n const resolvedScope = resolveQueryIndexRecordScope({\n payloadOrganizationId: payload?.organizationId,\n payloadTenantId: payload?.tenantId,\n hasPayloadOrganizationId,\n hasPayloadTenantId,\n rowScope,\n })\n organizationId = resolvedScope.organizationId\n tenantId = resolvedScope.tenantId\n\n const result = await upsertIndexRow(em, {\n entityType,\n recordId,\n organizationId,\n tenantId,\n searchTokenDoc: typeof payload?.searchTokenDoc === 'object' && payload.searchTokenDoc && !Array.isArray(payload.searchTokenDoc)\n ? payload.searchTokenDoc\n : null,\n })\n if (!suppressCoverage) {\n const doc = result.doc\n const isActive = !!doc && (doc.deleted_at == null || doc.deleted_at === null)\n let baseDelta: number | undefined =\n typeof payload?.coverageBaseDelta === 'number' ? payload.coverageBaseDelta : undefined\n let indexDelta: number | undefined =\n typeof payload?.coverageIndexDelta === 'number' ? payload.coverageIndexDelta : undefined\n const crudAction = typeof payload?.crudAction === 'string' ? payload.crudAction : undefined\n\n if (baseDelta === undefined) {\n if (result.revived) baseDelta = 1\n else if (crudAction === 'created') baseDelta = 1\n else baseDelta = 0\n }\n\n if (indexDelta === undefined) {\n if (isActive && (result.created || result.revived)) indexDelta = 1\n else indexDelta = 0\n }\n\n if (!isActive && baseDelta > 0) baseDelta = 0\n if (!isActive && indexDelta > 0) indexDelta = 0\n if (!Number.isFinite(baseDelta)) baseDelta = 0\n if (!Number.isFinite(indexDelta)) indexDelta = 0\n\n const adjustments = createCoverageAdjustments({\n entityType,\n tenantId: tenantId ?? null,\n organizationId: organizationId ?? null,\n baseDelta,\n indexDelta,\n })\n if (adjustments.length) {\n await applyCoverageAdjustments(em, adjustments)\n }\n if (coverageDelayMs !== undefined && coverageDelayMs >= 0) {\n try {\n const bus = ctx.resolve<any>('eventBus')\n await bus.emitEvent('query_index.coverage.refresh', {\n entityType,\n tenantId: tenantId ?? null,\n organizationId: organizationId ?? null,\n delayMs: coverageDelayMs,\n })\n } catch {}\n }\n }\n // Kick off secondary pass (vectorize) asynchronously\n try {\n const bus = ctx.resolve<any>('eventBus')\n await bus.emitEvent('query_index.vectorize_one', { entityType, recordId, organizationId, tenantId })\n } catch {}\n // Emit search indexing event\n try {\n const bus = ctx.resolve<any>('eventBus')\n await bus.emitEvent('search.index_record', { entityId: entityType, recordId, organizationId, tenantId })\n } catch {}\n } catch (error) {\n await recordIndexerError(\n { em },\n {\n source: 'query_index',\n handler: 'event:query_index.upsert_one',\n error,\n entityType,\n recordId,\n tenantId: tenantId ?? null,\n organizationId: organizationId ?? null,\n payload,\n },\n )\n throw error\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/modules/sales/api/order-adjustments/route.ts"],
|
|
4
|
-
"sourcesContent": ["import { z } from 'zod'\nimport { makeCrudRoute } from '@open-mercato/shared/lib/crud/factory'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { SalesOrderAdjustment } from '../../data/entities'\nimport {\n enforceAdjustmentSign,\n orderAdjustmentCreateSchema,\n} from '../../data/validators'\nimport { createPagedListResponseSchema, createSalesCrudOpenApi, defaultOkResponseSchema } from '../openapi'\nimport { withScopedPayload } from '../utils'\nimport { E } from '#generated/entities.ids.generated'\nimport * as F from '#generated/entities/sales_order_adjustment'\nimport { buildCustomFieldFiltersFromQuery, extractAllCustomFieldEntries } from '@open-mercato/shared/lib/crud/custom-fields'\n\nconst rawBodySchema = z.object({}).passthrough()\n\nconst listSchema = z\n .object({\n page: z.coerce.number().min(1).default(1),\n pageSize: z.coerce.number().min(1).max(100).default(50),\n orderId: z.string().uuid().optional(),\n sortField: z.string().optional(),\n sortDir: z.enum(['asc', 'desc']).optional(),\n })\n .passthrough()\n\nconst routeMetadata = {\n GET: { requireAuth: true, requireFeatures: ['sales.orders.view'] },\n POST: { requireAuth: true, requireFeatures: ['sales.orders.manage'] },\n PUT: { requireAuth: true, requireFeatures: ['sales.orders.manage'] },\n DELETE: { requireAuth: true, requireFeatures: ['sales.orders.manage'] },\n}\n\nconst upsertSchema = orderAdjustmentCreateSchema\n .extend({ id: z.string().uuid().optional() })\n .superRefine(enforceAdjustmentSign)\n\nconst deleteSchema = z.object({\n id: z.string().uuid(),\n orderId: z.string().uuid(),\n})\n\nconst crud = makeCrudRoute({\n metadata: routeMetadata,\n orm: {\n entity: SalesOrderAdjustment,\n idField: 'id',\n orgField: 'organizationId',\n tenantField: 'tenantId',\n softDeleteField: 'deletedAt',\n },\n indexer: {\n entityType: E.sales.sales_order_adjustment,\n },\n list: {\n schema: listSchema,\n entityId: E.sales.sales_order_adjustment,\n decorateCustomFields: { entityIds: [E.sales.sales_order_adjustment] },\n fields: [\n F.id,\n 'order_id',\n 'order_line_id',\n F.scope,\n F.kind,\n F.code,\n F.label,\n F.calculator_key,\n F.promotion_id,\n F.rate,\n F.amount_net,\n F.amount_gross,\n F.currency_code,\n F.metadata,\n F.position,\n F.created_at,\n F.updated_at,\n ],\n sortFieldMap: {\n createdAt: F.created_at,\n updatedAt: F.updated_at,\n position: F.position,\n },\n buildFilters: async (query, ctx) => {\n const filters: Record<string, unknown> = {}\n if (query.orderId) filters.order_id = { $eq: query.orderId }\n try {\n const em = ctx.container.resolve('em')\n const cfFilters = await buildCustomFieldFiltersFromQuery({\n entityId: E.sales.sales_order_adjustment,\n query,\n em,\n tenantId: ctx.auth?.tenantId ?? null,\n })\n Object.assign(filters, cfFilters)\n } catch {\n // ignore custom field filters when EM is unavailable in this context\n }\n return filters\n },\n transformItem: (item: any) => {\n if (!item) return item\n const normalized = { ...item }\n const cfEntries = extractAllCustomFieldEntries(item)\n for (const key of Object.keys(normalized)) {\n if (key.startsWith('cf:')) delete normalized[key]\n }\n return { ...normalized, ...cfEntries }\n },\n },\n actions: {\n create: {\n commandId: 'sales.orders.adjustments.upsert',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n const payload = upsertSchema.parse(withScopedPayload(raw ?? {}, ctx, translate))\n return { body: payload }\n },\n response: ({ result }) => ({ id: result?.adjustmentId ?? null, orderId: result?.orderId ?? null }),\n status: 201,\n },\n update: {\n commandId: 'sales.orders.adjustments.upsert',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n const payload = upsertSchema.parse(withScopedPayload(raw ?? {}, ctx, translate))\n return { body: payload }\n },\n response: ({ result }) => ({ id: result?.adjustmentId ?? null, orderId: result?.orderId ?? null }),\n },\n delete: {\n commandId: 'sales.orders.adjustments.delete',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n const payload = deleteSchema.parse(\n withScopedPayload(\n {\n ...((raw as any)?.body ?? {}),\n ...((raw as any)?.query ?? {}),\n },\n ctx,\n translate\n )\n )\n if (!payload.id || !payload.orderId) {\n throw new CrudHttpError(400, { error: translate('sales.documents.detail.error', 'Document not found or inaccessible.') })\n }\n return { body: payload }\n },\n response: () => ({ ok: true }),\n },\n },\n})\n\nconst { GET, POST, PUT, DELETE } = crud\n\nexport const metadata = routeMetadata\nexport { GET, POST, PUT, DELETE }\n\nconst adjustmentSchema = z.object({\n id: z.string().uuid(),\n order_id: z.string().uuid(),\n order_line_id: z.string().uuid().nullable().optional(),\n scope: z.string(),\n kind: z.string(),\n code: z.string().nullable().optional(),\n label: z.string().nullable().optional(),\n calculator_key: z.string().nullable().optional(),\n promotion_id: z.string().uuid().nullable().optional(),\n rate: z.number(),\n amount_net: z.number(),\n amount_gross: z.number(),\n currency_code: z.string().nullable().optional(),\n metadata: z.record(z.string(), z.unknown()).nullable().optional(),\n position: z.number(),\n created_at: z.string(),\n updated_at: z.string(),\n})\n\nexport const openApi = createSalesCrudOpenApi({\n resourceName: 'Order adjustment',\n querySchema: listSchema,\n listResponseSchema: createPagedListResponseSchema(adjustmentSchema),\n create: {\n schema: upsertSchema,\n responseSchema: z.object({ id: z.string().uuid().nullable(), orderId: z.string().uuid().nullable() }),\n description: 'Creates an order adjustment and recalculates totals.',\n },\n update: {\n schema: upsertSchema,\n responseSchema: z.object({ id: z.string().uuid().nullable(), orderId: z.string().uuid().nullable() }),\n description: 'Updates an order adjustment and recalculates totals.',\n },\n del: {\n schema: deleteSchema,\n responseSchema: defaultOkResponseSchema,\n description: 'Deletes an order adjustment and recalculates totals.',\n },\n})\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,SAAS;
|
|
4
|
+
"sourcesContent": ["import { z } from 'zod'\nimport type { EntityManager } from '@mikro-orm/core'\nimport { makeCrudRoute } from '@open-mercato/shared/lib/crud/factory'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { SalesOrderAdjustment } from '../../data/entities'\nimport {\n enforceAdjustmentSign,\n orderAdjustmentCreateSchema,\n} from '../../data/validators'\nimport { createPagedListResponseSchema, createSalesCrudOpenApi, defaultOkResponseSchema } from '../openapi'\nimport { withScopedPayload } from '../utils'\nimport { E } from '#generated/entities.ids.generated'\nimport * as F from '#generated/entities/sales_order_adjustment'\nimport { buildCustomFieldFiltersFromQuery, extractAllCustomFieldEntries } from '@open-mercato/shared/lib/crud/custom-fields'\n\nconst rawBodySchema = z.object({}).passthrough()\n\nconst listSchema = z\n .object({\n page: z.coerce.number().min(1).default(1),\n pageSize: z.coerce.number().min(1).max(100).default(50),\n orderId: z.string().uuid().optional(),\n sortField: z.string().optional(),\n sortDir: z.enum(['asc', 'desc']).optional(),\n })\n .passthrough()\n\nconst routeMetadata = {\n GET: { requireAuth: true, requireFeatures: ['sales.orders.view'] },\n POST: { requireAuth: true, requireFeatures: ['sales.orders.manage'] },\n PUT: { requireAuth: true, requireFeatures: ['sales.orders.manage'] },\n DELETE: { requireAuth: true, requireFeatures: ['sales.orders.manage'] },\n}\n\nconst upsertSchema = orderAdjustmentCreateSchema\n .extend({ id: z.string().uuid().optional() })\n .superRefine(enforceAdjustmentSign)\n\nconst deleteSchema = z.object({\n id: z.string().uuid(),\n orderId: z.string().uuid(),\n})\n\nconst crud = makeCrudRoute({\n metadata: routeMetadata,\n orm: {\n entity: SalesOrderAdjustment,\n idField: 'id',\n orgField: 'organizationId',\n tenantField: 'tenantId',\n softDeleteField: 'deletedAt',\n },\n indexer: {\n entityType: E.sales.sales_order_adjustment,\n },\n list: {\n schema: listSchema,\n entityId: E.sales.sales_order_adjustment,\n decorateCustomFields: { entityIds: [E.sales.sales_order_adjustment] },\n fields: [\n F.id,\n 'order_id',\n 'order_line_id',\n F.scope,\n F.kind,\n F.code,\n F.label,\n F.calculator_key,\n F.promotion_id,\n F.rate,\n F.amount_net,\n F.amount_gross,\n F.currency_code,\n F.metadata,\n F.position,\n F.created_at,\n F.updated_at,\n ],\n sortFieldMap: {\n createdAt: F.created_at,\n updatedAt: F.updated_at,\n position: F.position,\n },\n buildFilters: async (query, ctx) => {\n const filters: Record<string, unknown> = {}\n if (query.orderId) filters.order_id = { $eq: query.orderId }\n try {\n const em = ctx.container.resolve<EntityManager>('em')\n const cfFilters = await buildCustomFieldFiltersFromQuery({\n entityId: E.sales.sales_order_adjustment,\n query,\n em,\n tenantId: ctx.auth?.tenantId ?? null,\n })\n Object.assign(filters, cfFilters)\n } catch {\n // ignore custom field filters when EM is unavailable in this context\n }\n return filters\n },\n transformItem: (item: any) => {\n if (!item) return item\n const normalized = { ...item }\n const cfEntries = extractAllCustomFieldEntries(item)\n for (const key of Object.keys(normalized)) {\n if (key.startsWith('cf:')) delete normalized[key]\n }\n return { ...normalized, ...cfEntries }\n },\n },\n actions: {\n create: {\n commandId: 'sales.orders.adjustments.upsert',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n const payload = upsertSchema.parse(withScopedPayload(raw ?? {}, ctx, translate))\n return { body: payload }\n },\n response: ({ result }) => ({ id: result?.adjustmentId ?? null, orderId: result?.orderId ?? null }),\n status: 201,\n },\n update: {\n commandId: 'sales.orders.adjustments.upsert',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n const payload = upsertSchema.parse(withScopedPayload(raw ?? {}, ctx, translate))\n return { body: payload }\n },\n response: ({ result }) => ({ id: result?.adjustmentId ?? null, orderId: result?.orderId ?? null }),\n },\n delete: {\n commandId: 'sales.orders.adjustments.delete',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n const payload = deleteSchema.parse(\n withScopedPayload(\n {\n ...((raw as any)?.body ?? {}),\n ...((raw as any)?.query ?? {}),\n },\n ctx,\n translate\n )\n )\n if (!payload.id || !payload.orderId) {\n throw new CrudHttpError(400, { error: translate('sales.documents.detail.error', 'Document not found or inaccessible.') })\n }\n return { body: payload }\n },\n response: () => ({ ok: true }),\n },\n },\n})\n\nconst { GET, POST, PUT, DELETE } = crud\n\nexport const metadata = routeMetadata\nexport { GET, POST, PUT, DELETE }\n\nconst adjustmentSchema = z.object({\n id: z.string().uuid(),\n order_id: z.string().uuid(),\n order_line_id: z.string().uuid().nullable().optional(),\n scope: z.string(),\n kind: z.string(),\n code: z.string().nullable().optional(),\n label: z.string().nullable().optional(),\n calculator_key: z.string().nullable().optional(),\n promotion_id: z.string().uuid().nullable().optional(),\n rate: z.number(),\n amount_net: z.number(),\n amount_gross: z.number(),\n currency_code: z.string().nullable().optional(),\n metadata: z.record(z.string(), z.unknown()).nullable().optional(),\n position: z.number(),\n created_at: z.string(),\n updated_at: z.string(),\n})\n\nexport const openApi = createSalesCrudOpenApi({\n resourceName: 'Order adjustment',\n querySchema: listSchema,\n listResponseSchema: createPagedListResponseSchema(adjustmentSchema),\n create: {\n schema: upsertSchema,\n responseSchema: z.object({ id: z.string().uuid().nullable(), orderId: z.string().uuid().nullable() }),\n description: 'Creates an order adjustment and recalculates totals.',\n },\n update: {\n schema: upsertSchema,\n responseSchema: z.object({ id: z.string().uuid().nullable(), orderId: z.string().uuid().nullable() }),\n description: 'Updates an order adjustment and recalculates totals.',\n },\n del: {\n schema: deleteSchema,\n responseSchema: defaultOkResponseSchema,\n description: 'Deletes an order adjustment and recalculates totals.',\n },\n})\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|