@open-mercato/core 0.5.1-develop.3045.b4b3320cc2 → 0.6.0
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/AGENTS.md +21 -1
- package/dist/modules/api_keys/api/keys/route.js +9 -0
- package/dist/modules/api_keys/api/keys/route.js.map +2 -2
- package/dist/modules/audit_logs/services/accessLogService.js +13 -0
- package/dist/modules/audit_logs/services/accessLogService.js.map +3 -3
- package/dist/modules/audit_logs/services/actionLogService.js +6 -5
- package/dist/modules/audit_logs/services/actionLogService.js.map +2 -2
- package/dist/modules/auth/api/roles/acl/route.js +27 -37
- package/dist/modules/auth/api/roles/acl/route.js.map +2 -2
- package/dist/modules/auth/api/users/route.js +41 -28
- package/dist/modules/auth/api/users/route.js.map +3 -3
- package/dist/modules/auth/lib/grantChecks.js +160 -0
- package/dist/modules/auth/lib/grantChecks.js.map +7 -0
- package/dist/modules/configs/cli.js +11 -0
- package/dist/modules/configs/cli.js.map +2 -2
- package/dist/modules/configs/lib/touchGeneratedBarrels.js +46 -0
- package/dist/modules/configs/lib/touchGeneratedBarrels.js.map +7 -0
- package/dist/modules/customers/api/activities/route.js +1 -52
- package/dist/modules/customers/api/activities/route.js.map +2 -2
- package/dist/modules/customers/api/interactions/counts/route.js +2 -1
- package/dist/modules/customers/api/interactions/counts/route.js.map +2 -2
- package/dist/modules/customers/api/interactions/route.js +21 -1
- package/dist/modules/customers/api/interactions/route.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +7 -3
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/[id]/page.js +5 -1
- package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +7 -3
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/components/detail/ActivitiesCard.js +62 -6
- package/dist/modules/customers/components/detail/ActivitiesCard.js.map +2 -2
- package/dist/modules/customers/components/detail/ActivitiesDayStrip.js +21 -6
- package/dist/modules/customers/components/detail/ActivitiesDayStrip.js.map +2 -2
- package/dist/modules/customers/components/detail/ActivitiesSection.js +37 -5
- package/dist/modules/customers/components/detail/ActivitiesSection.js.map +2 -2
- package/dist/modules/customers/components/detail/ActivityCard.js +69 -17
- package/dist/modules/customers/components/detail/ActivityCard.js.map +2 -2
- package/dist/modules/customers/components/detail/ActivityHistorySection.js +94 -34
- package/dist/modules/customers/components/detail/ActivityHistorySection.js.map +2 -2
- package/dist/modules/customers/components/detail/ActivityLogTab.js +3 -1
- package/dist/modules/customers/components/detail/ActivityLogTab.js.map +2 -2
- package/dist/modules/customers/components/detail/ActivityTimeline.js +41 -8
- package/dist/modules/customers/components/detail/ActivityTimeline.js.map +2 -2
- package/dist/modules/customers/components/detail/ActivityTimelineFilters.js +19 -6
- package/dist/modules/customers/components/detail/ActivityTimelineFilters.js.map +2 -2
- package/dist/modules/customers/components/detail/ActivityTypeSelector.js +4 -3
- package/dist/modules/customers/components/detail/ActivityTypeSelector.js.map +2 -2
- package/dist/modules/customers/components/detail/ScheduleActivityDialog.js +80 -12
- package/dist/modules/customers/components/detail/ScheduleActivityDialog.js.map +2 -2
- package/dist/modules/customers/components/detail/schedule/DateTimeFields.js +65 -10
- package/dist/modules/customers/components/detail/schedule/DateTimeFields.js.map +2 -2
- package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js +10 -5
- package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js.map +2 -2
- package/dist/modules/customers/data/validators.js +74 -2
- package/dist/modules/customers/data/validators.js.map +2 -2
- package/dist/modules/customers/lib/legacyActivityBridge.js +61 -0
- package/dist/modules/customers/lib/legacyActivityBridge.js.map +7 -0
- package/dist/modules/integrations/data/validators.js +2 -2
- package/dist/modules/integrations/data/validators.js.map +2 -2
- package/dist/modules/integrations/lib/credentials-service.js +12 -1
- package/dist/modules/integrations/lib/credentials-service.js.map +2 -2
- package/dist/modules/messages/commands/actions.js +29 -14
- package/dist/modules/messages/commands/actions.js.map +2 -2
- package/dist/modules/messages/lib/actions.js +24 -4
- package/dist/modules/messages/lib/actions.js.map +2 -2
- package/dist/modules/sales/api/documents/factory.js +49 -36
- package/dist/modules/sales/api/documents/factory.js.map +2 -2
- package/package.json +9 -10
- package/src/modules/api_keys/api/keys/route.ts +9 -0
- package/src/modules/audit_logs/services/accessLogService.ts +20 -0
- package/src/modules/audit_logs/services/actionLogService.ts +13 -5
- package/src/modules/auth/api/roles/acl/route.ts +32 -46
- package/src/modules/auth/api/users/route.ts +48 -33
- package/src/modules/auth/lib/grantChecks.ts +234 -0
- package/src/modules/configs/cli.ts +11 -0
- package/src/modules/configs/lib/touchGeneratedBarrels.ts +61 -0
- package/src/modules/customers/api/activities/route.ts +1 -76
- package/src/modules/customers/api/interactions/counts/route.ts +2 -1
- package/src/modules/customers/api/interactions/route.ts +28 -1
- package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +13 -3
- package/src/modules/customers/backend/customers/deals/[id]/page.tsx +14 -2
- package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +13 -3
- package/src/modules/customers/components/detail/ActivitiesCard.tsx +92 -5
- package/src/modules/customers/components/detail/ActivitiesDayStrip.tsx +38 -6
- package/src/modules/customers/components/detail/ActivitiesSection.tsx +37 -3
- package/src/modules/customers/components/detail/ActivityCard.tsx +79 -14
- package/src/modules/customers/components/detail/ActivityHistorySection.tsx +102 -33
- package/src/modules/customers/components/detail/ActivityLogTab.tsx +7 -1
- package/src/modules/customers/components/detail/ActivityTimeline.tsx +39 -5
- package/src/modules/customers/components/detail/ActivityTimelineFilters.tsx +29 -7
- package/src/modules/customers/components/detail/ActivityTypeSelector.tsx +3 -2
- package/src/modules/customers/components/detail/ScheduleActivityDialog.tsx +96 -13
- package/src/modules/customers/components/detail/schedule/DateTimeFields.tsx +50 -4
- package/src/modules/customers/components/detail/schedule/useScheduleFormState.ts +21 -5
- package/src/modules/customers/data/validators.ts +85 -2
- package/src/modules/customers/i18n/de.json +11 -0
- package/src/modules/customers/i18n/en.json +11 -0
- package/src/modules/customers/i18n/es.json +11 -0
- package/src/modules/customers/i18n/pl.json +11 -0
- package/src/modules/customers/lib/legacyActivityBridge.ts +106 -0
- package/src/modules/integrations/data/validators.ts +8 -6
- package/src/modules/integrations/lib/credentials-service.ts +15 -1
- package/src/modules/messages/commands/actions.ts +28 -13
- package/src/modules/messages/lib/actions.ts +34 -3
- package/src/modules/sales/api/documents/factory.ts +55 -38
|
@@ -2,9 +2,14 @@ import { z } from "zod";
|
|
|
2
2
|
import { isValidPhoneNumber } from "@open-mercato/shared/lib/phone";
|
|
3
3
|
const uuid = () => z.string().uuid();
|
|
4
4
|
const CUSTOMER_PHONE_INVALID_MESSAGE_KEY = "customers.people.form.primaryPhone.invalid";
|
|
5
|
+
const ACTIVITY_DATE_REQUIRED_MESSAGE_KEY = "customers.activities.errors.dateRequired";
|
|
6
|
+
const ACTIVITY_TIME_REQUIRED_MESSAGE_KEY = "customers.activities.errors.timeRequired";
|
|
7
|
+
const ACTIVITY_PHONE_REQUIRED_MESSAGE_KEY = "customers.activities.errors.phoneRequired";
|
|
8
|
+
const ACTIVITY_PHONE_INVALID_MESSAGE_KEY = "customers.activities.errors.phoneInvalid";
|
|
5
9
|
const phoneSchema = z.string().trim().max(50).refine((val) => {
|
|
6
10
|
return isValidPhoneNumber(val);
|
|
7
11
|
}, { message: CUSTOMER_PHONE_INVALID_MESSAGE_KEY }).optional();
|
|
12
|
+
const interactionPhoneNumberSchema = z.string().trim().max(50).optional().nullable();
|
|
8
13
|
const scopedSchema = z.object({
|
|
9
14
|
organizationId: uuid(),
|
|
10
15
|
tenantId: uuid()
|
|
@@ -105,6 +110,9 @@ const activityCreateSchema = scopedSchema.extend({
|
|
|
105
110
|
activityType: z.string().min(1).max(100),
|
|
106
111
|
subject: z.string().max(200).optional(),
|
|
107
112
|
body: z.string().max(8e3).optional(),
|
|
113
|
+
date: z.string().trim().min(1, ACTIVITY_DATE_REQUIRED_MESSAGE_KEY).optional(),
|
|
114
|
+
time: z.string().trim().min(1, ACTIVITY_TIME_REQUIRED_MESSAGE_KEY).optional(),
|
|
115
|
+
phoneNumber: interactionPhoneNumberSchema,
|
|
108
116
|
occurredAt: z.coerce.date().optional(),
|
|
109
117
|
dealId: uuid().optional(),
|
|
110
118
|
authorUserId: uuid().optional(),
|
|
@@ -251,13 +259,16 @@ const interactionExtendedFields = {
|
|
|
251
259
|
linkedEntities: z.array(interactionLinkedEntitySchema).optional().nullable(),
|
|
252
260
|
guestPermissions: interactionGuestPermissionsSchema.optional().nullable()
|
|
253
261
|
};
|
|
254
|
-
const
|
|
262
|
+
const interactionCreateBaseSchema = scopedSchema.extend({
|
|
255
263
|
id: z.string().uuid().optional(),
|
|
256
264
|
entityId: z.string().uuid(),
|
|
257
265
|
interactionType: z.string().trim().min(1).max(100),
|
|
258
266
|
title: z.string().trim().max(500).optional().nullable(),
|
|
259
267
|
body: z.string().trim().max(1e4).optional().nullable(),
|
|
260
268
|
status: z.enum(interactionStatusValues).optional().default("planned"),
|
|
269
|
+
date: z.string().trim().min(1, ACTIVITY_DATE_REQUIRED_MESSAGE_KEY).optional(),
|
|
270
|
+
time: z.string().trim().min(1, ACTIVITY_TIME_REQUIRED_MESSAGE_KEY).optional(),
|
|
271
|
+
phoneNumber: interactionPhoneNumberSchema,
|
|
261
272
|
scheduledAt: z.coerce.date().optional().nullable(),
|
|
262
273
|
occurredAt: z.coerce.date().optional().nullable(),
|
|
263
274
|
priority: z.number().int().min(0).max(100).optional().nullable(),
|
|
@@ -269,7 +280,38 @@ const interactionCreateSchema = scopedSchema.extend({
|
|
|
269
280
|
source: z.string().trim().max(100).optional().nullable(),
|
|
270
281
|
...interactionExtendedFields
|
|
271
282
|
});
|
|
272
|
-
|
|
283
|
+
function deriveScheduledAtFromDateTime(date, time) {
|
|
284
|
+
if (!date || typeof date !== "string") return null;
|
|
285
|
+
const trimmedDate = date.trim();
|
|
286
|
+
if (!trimmedDate) return null;
|
|
287
|
+
const trimmedTime = typeof time === "string" ? time.trim() : "";
|
|
288
|
+
const iso = trimmedTime ? `${trimmedDate}T${trimmedTime}:00` : `${trimmedDate}T00:00:00`;
|
|
289
|
+
const parsed = new Date(iso);
|
|
290
|
+
return Number.isNaN(parsed.getTime()) ? null : parsed;
|
|
291
|
+
}
|
|
292
|
+
const interactionCreateSchema = interactionCreateBaseSchema.superRefine((value, ctx) => {
|
|
293
|
+
if (value.interactionType === "call" && value.phoneNumber !== void 0 && value.phoneNumber !== null) {
|
|
294
|
+
const phone = typeof value.phoneNumber === "string" ? value.phoneNumber.trim() : "";
|
|
295
|
+
if (!phone) {
|
|
296
|
+
ctx.addIssue({
|
|
297
|
+
code: z.ZodIssueCode.custom,
|
|
298
|
+
path: ["phoneNumber"],
|
|
299
|
+
message: ACTIVITY_PHONE_REQUIRED_MESSAGE_KEY
|
|
300
|
+
});
|
|
301
|
+
} else if (!isValidPhoneNumber(phone)) {
|
|
302
|
+
ctx.addIssue({
|
|
303
|
+
code: z.ZodIssueCode.custom,
|
|
304
|
+
path: ["phoneNumber"],
|
|
305
|
+
message: ACTIVITY_PHONE_INVALID_MESSAGE_KEY
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}).transform((value) => {
|
|
310
|
+
if (value.scheduledAt) return value;
|
|
311
|
+
const derived = deriveScheduledAtFromDateTime(value.date, value.time);
|
|
312
|
+
return derived ? { ...value, scheduledAt: derived } : value;
|
|
313
|
+
});
|
|
314
|
+
const interactionUpdateBaseSchema = z.object({
|
|
273
315
|
id: z.string().uuid()
|
|
274
316
|
}).merge(
|
|
275
317
|
scopedSchema.extend({
|
|
@@ -277,6 +319,9 @@ const interactionUpdateSchema = z.object({
|
|
|
277
319
|
title: z.string().trim().max(500).optional().nullable(),
|
|
278
320
|
body: z.string().trim().max(1e4).optional().nullable(),
|
|
279
321
|
status: z.enum(interactionStatusValues).optional(),
|
|
322
|
+
date: z.string().trim().min(1, ACTIVITY_DATE_REQUIRED_MESSAGE_KEY).optional(),
|
|
323
|
+
time: z.string().trim().min(1, ACTIVITY_TIME_REQUIRED_MESSAGE_KEY).optional(),
|
|
324
|
+
phoneNumber: interactionPhoneNumberSchema,
|
|
280
325
|
scheduledAt: z.coerce.date().optional().nullable(),
|
|
281
326
|
occurredAt: z.coerce.date().optional().nullable(),
|
|
282
327
|
priority: z.number().int().min(0).max(100).optional().nullable(),
|
|
@@ -289,6 +334,29 @@ const interactionUpdateSchema = z.object({
|
|
|
289
334
|
...interactionExtendedFields
|
|
290
335
|
}).partial()
|
|
291
336
|
);
|
|
337
|
+
const interactionUpdateSchema = interactionUpdateBaseSchema.superRefine((value, ctx) => {
|
|
338
|
+
if (value.interactionType === "call" && value.phoneNumber !== void 0) {
|
|
339
|
+
const phone = typeof value.phoneNumber === "string" ? value.phoneNumber.trim() : "";
|
|
340
|
+
if (!phone) {
|
|
341
|
+
ctx.addIssue({
|
|
342
|
+
code: z.ZodIssueCode.custom,
|
|
343
|
+
path: ["phoneNumber"],
|
|
344
|
+
message: ACTIVITY_PHONE_REQUIRED_MESSAGE_KEY
|
|
345
|
+
});
|
|
346
|
+
} else if (!isValidPhoneNumber(phone)) {
|
|
347
|
+
ctx.addIssue({
|
|
348
|
+
code: z.ZodIssueCode.custom,
|
|
349
|
+
path: ["phoneNumber"],
|
|
350
|
+
message: ACTIVITY_PHONE_INVALID_MESSAGE_KEY
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}).transform((value) => {
|
|
355
|
+
if (value.scheduledAt !== void 0) return value;
|
|
356
|
+
if (!value.date && !value.time) return value;
|
|
357
|
+
const derived = deriveScheduledAtFromDateTime(value.date, value.time);
|
|
358
|
+
return derived ? { ...value, scheduledAt: derived } : value;
|
|
359
|
+
});
|
|
292
360
|
const interactionCompleteSchema = z.object({
|
|
293
361
|
id: z.string().uuid(),
|
|
294
362
|
occurredAt: z.coerce.date().optional()
|
|
@@ -394,6 +462,10 @@ const personCompanyLinkDeleteSchema = scopedSchema.extend({
|
|
|
394
462
|
linkId: uuid()
|
|
395
463
|
});
|
|
396
464
|
export {
|
|
465
|
+
ACTIVITY_DATE_REQUIRED_MESSAGE_KEY,
|
|
466
|
+
ACTIVITY_PHONE_INVALID_MESSAGE_KEY,
|
|
467
|
+
ACTIVITY_PHONE_REQUIRED_MESSAGE_KEY,
|
|
468
|
+
ACTIVITY_TIME_REQUIRED_MESSAGE_KEY,
|
|
397
469
|
CUSTOMER_PHONE_INVALID_MESSAGE_KEY,
|
|
398
470
|
activityCreateSchema,
|
|
399
471
|
activityUpdateSchema,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/customers/data/validators.ts"],
|
|
4
|
-
"sourcesContent": ["import { z } from 'zod'\nimport { isValidPhoneNumber } from '@open-mercato/shared/lib/phone'\n\nconst uuid = () => z.string().uuid()\n\nexport const CUSTOMER_PHONE_INVALID_MESSAGE_KEY = 'customers.people.form.primaryPhone.invalid'\n\nconst phoneSchema = z.string().trim().max(50).refine((val) => {\n return isValidPhoneNumber(val)\n}, { message: CUSTOMER_PHONE_INVALID_MESSAGE_KEY }).optional()\n\nconst scopedSchema = z.object({\n organizationId: uuid(),\n tenantId: uuid(),\n})\n\nconst nextInteractionSchema = z\n .object({\n at: z.coerce.date(),\n name: z.string().trim().min(1).max(200),\n refId: z.string().trim().max(191).optional().nullable(),\n icon: z.string().trim().max(100).optional().nullable(),\n color: z\n .string()\n .trim()\n .regex(/^#([0-9a-fA-F]{6})$/)\n .optional()\n .nullable(),\n })\n .strict()\n\nconst displayNameSchema = z.string().trim().min(1).max(200)\n\nconst baseEntitySchema = {\n displayName: displayNameSchema,\n description: z.string().trim().max(4000).optional(),\n ownerUserId: uuid().optional(),\n primaryEmail: z\n .string()\n .trim()\n .email()\n .max(320)\n .optional(),\n primaryPhone: phoneSchema,\n status: z.string().trim().max(100).optional(),\n lifecycleStage: z.string().trim().max(100).optional(),\n source: z.string().trim().max(150).optional(),\n temperature: z.string().trim().max(100).optional(),\n renewalQuarter: z.string().trim().max(100).optional(),\n isActive: z.boolean().optional(),\n nextInteraction: nextInteractionSchema.nullable().optional(),\n tags: z.array(uuid()).optional(),\n}\n\nconst personDetailsSchema = {\n preferredName: z.string().trim().max(120).optional(),\n jobTitle: z.string().trim().max(150).optional(),\n department: z.string().trim().max(150).optional(),\n seniority: z.string().trim().max(100).optional(),\n timezone: z.string().trim().max(120).optional(),\n linkedInUrl: z.string().trim().url().max(300).optional(),\n twitterUrl: z.string().trim().url().max(300).optional(),\n companyEntityId: uuid().nullable().optional(),\n}\n\nconst personFirstNameSchema = z.string().trim().min(1).max(120)\nconst personLastNameSchema = z.string().trim().min(1).max(120)\n\nconst companyDetailsSchema = {\n legalName: z.string().trim().max(200).optional(),\n brandName: z.string().trim().max(200).optional(),\n domain: z.string().trim().max(200).optional(),\n websiteUrl: z.string().trim().url().max(300).optional(),\n industry: z.string().trim().max(150).optional(),\n sizeBucket: z.string().trim().max(100).optional(),\n annualRevenue: z.coerce.number().min(0).optional(),\n}\n\nexport const personCreateSchema = scopedSchema.extend({\n ...baseEntitySchema,\n displayName: displayNameSchema.optional(),\n firstName: personFirstNameSchema,\n lastName: personLastNameSchema,\n ...personDetailsSchema,\n})\n\nexport const personUpdateSchema = z\n .object({\n id: uuid(),\n })\n .merge(\n scopedSchema.extend({\n ...baseEntitySchema,\n ...personDetailsSchema,\n firstName: personFirstNameSchema.optional(),\n lastName: personLastNameSchema.optional(),\n }).partial()\n )\n\nexport const companyCreateSchema = scopedSchema.extend({\n ...baseEntitySchema,\n displayName: displayNameSchema,\n ...companyDetailsSchema,\n})\n\nexport const companyUpdateSchema = z\n .object({\n id: uuid(),\n })\n .merge(companyCreateSchema.partial())\n\nexport const dealCreateSchema = scopedSchema.extend({\n title: z.string().min(1).max(200),\n description: z.string().max(4000).optional(),\n status: z.string().max(50).optional(),\n pipelineStage: z.string().max(100).optional(),\n pipelineId: uuid().optional(),\n pipelineStageId: uuid().optional(),\n valueAmount: z.coerce.number().min(0).optional(),\n valueCurrency: z.string().min(3).max(3).optional(),\n probability: z.number().min(0).max(100).optional(),\n expectedCloseAt: z.coerce.date().optional(),\n ownerUserId: uuid().optional(),\n source: z.string().max(150).optional(),\n closureOutcome: z.enum(['won', 'lost']).optional(),\n lossReasonId: uuid().optional(),\n lossNotes: z.string().max(4000).optional(),\n companyIds: z.array(uuid()).optional(),\n personIds: z.array(uuid()).optional(),\n})\n\nexport const dealUpdateSchema = z\n .object({\n id: uuid(),\n })\n .merge(dealCreateSchema.partial())\n\nexport const activityCreateSchema = scopedSchema.extend({\n entityId: uuid(),\n activityType: z.string().min(1).max(100),\n subject: z.string().max(200).optional(),\n body: z.string().max(8000).optional(),\n occurredAt: z.coerce.date().optional(),\n dealId: uuid().optional(),\n authorUserId: uuid().optional(),\n appearanceIcon: z.string().trim().max(100).optional().nullable(),\n appearanceColor: z\n .string()\n .trim()\n .regex(/^#([0-9a-fA-F]{6})$/)\n .optional()\n .nullable(),\n})\n\nexport const activityUpdateSchema = z\n .object({\n id: uuid(),\n })\n .merge(activityCreateSchema.partial())\n\nexport const commentCreateSchema = scopedSchema.extend({\n entityId: uuid(),\n dealId: uuid().optional(),\n body: z.string().min(1).max(8000),\n authorUserId: uuid().optional(),\n appearanceIcon: z.string().trim().max(100).optional().nullable(),\n appearanceColor: z\n .string()\n .trim()\n .regex(/^#([0-9a-fA-F]{6})$/)\n .optional()\n .nullable(),\n})\n\nexport const commentUpdateSchema = z\n .object({\n id: uuid(),\n })\n .merge(commentCreateSchema.partial())\n\nexport const addressCreateSchema = scopedSchema.extend({\n entityId: uuid(),\n name: z.string().max(150).optional(),\n purpose: z.string().max(150).optional(),\n companyName: z.string().max(200).optional(),\n addressLine1: z.string().min(1).max(300),\n addressLine2: z.string().max(300).optional(),\n buildingNumber: z.string().max(50).optional(),\n flatNumber: z.string().max(50).optional(),\n city: z.string().max(150).optional(),\n region: z.string().max(150).optional(),\n postalCode: z.string().max(30).optional(),\n country: z.string().max(150).optional(),\n latitude: z.coerce.number().optional(),\n longitude: z.coerce.number().optional(),\n isPrimary: z.boolean().optional(),\n})\n\nexport const addressUpdateSchema = z\n .object({\n id: uuid(),\n })\n .merge(addressCreateSchema.partial())\n\nexport const tagCreateSchema = scopedSchema.extend({\n slug: z\n .string()\n .min(1)\n .max(80)\n .regex(/^[a-z0-9_-]+$/, 'Slug must be lowercase and may contain dashes or underscores'),\n label: z.string().min(1).max(120),\n color: z.string().max(30).optional(),\n description: z.string().max(400).optional(),\n})\n\nexport const tagUpdateSchema = z\n .object({\n id: uuid(),\n })\n .merge(tagCreateSchema.partial())\n\nconst KNOWN_DICTIONARY_KINDS = [\n 'status',\n 'source',\n 'lifecycle_stage',\n 'address_type',\n 'activity_type',\n 'deal_status',\n 'pipeline_stage',\n 'job_title',\n 'industry',\n 'temperature',\n 'renewal_quarter',\n 'person_company_role',\n] as const\nconst CUSTOM_DICTIONARY_KIND_PATTERN = /^[a-z0-9]+(?:[-_][a-z0-9]+)*$/\nconst dictionaryKindEnum = z.string().trim().refine(\n (value) =>\n (KNOWN_DICTIONARY_KINDS as readonly string[]).includes(value) ||\n CUSTOM_DICTIONARY_KIND_PATTERN.test(value),\n { message: 'Unsupported dictionary kind' },\n)\n\nconst dictionaryValueSchema = z.string().trim().min(1).max(150)\nconst dictionaryLabelSchema = z.string().trim().max(150)\nconst dictionaryColorSchema = z\n .string()\n .trim()\n .regex(/^#([0-9a-fA-F]{6})$/, 'Color must be a valid six-digit hex code like #3366ff')\nconst dictionaryIconSchema = z.string().trim().max(48)\n\nexport const customerDictionaryEntryCreateSchema = scopedSchema.extend({\n kind: dictionaryKindEnum,\n value: dictionaryValueSchema,\n label: dictionaryLabelSchema.optional(),\n color: dictionaryColorSchema.nullable().optional(),\n icon: dictionaryIconSchema.nullable().optional(),\n})\n\nexport type CustomerDictionaryEntryCreateInput = z.infer<typeof customerDictionaryEntryCreateSchema>\n\nexport const customerDictionaryEntryUpdateSchema = scopedSchema\n .extend({\n id: uuid(),\n kind: dictionaryKindEnum,\n value: dictionaryValueSchema.optional(),\n label: dictionaryLabelSchema.optional(),\n color: dictionaryColorSchema.nullable().optional(),\n icon: dictionaryIconSchema.nullable().optional(),\n })\n .refine(\n (payload) =>\n payload.value !== undefined ||\n payload.label !== undefined ||\n payload.color !== undefined ||\n payload.icon !== undefined,\n {\n message: 'Provide at least one field to update.',\n path: ['value'],\n }\n )\n\nexport type CustomerDictionaryEntryUpdateInput = z.infer<typeof customerDictionaryEntryUpdateSchema>\n\nexport const customerDictionaryEntryDeleteSchema = scopedSchema.extend({\n id: uuid(),\n kind: dictionaryKindEnum,\n})\n\nexport type CustomerDictionaryEntryDeleteInput = z.infer<typeof customerDictionaryEntryDeleteSchema>\n\nexport const tagAssignmentSchema = scopedSchema.extend({\n tagId: uuid(),\n entityId: uuid(),\n})\n\nexport const todoLinkCreateSchema = scopedSchema.extend({\n entityId: uuid(),\n todoId: uuid(),\n todoSource: z.string().min(1).max(120).default('customers:interaction'),\n createdByUserId: uuid().optional(),\n})\n\nexport const todoLinkWithTodoCreateSchema = scopedSchema.extend({\n entityId: uuid(),\n title: z.string().min(1).max(200),\n isDone: z.boolean().optional(),\n is_done: z.boolean().optional(),\n todoSource: z.string().min(1).max(120).default('customers:interaction'),\n createdByUserId: uuid().optional(),\n todoCustom: z.record(z.string(), z.any()).optional(),\n custom: z.record(z.string(), z.any()).optional(),\n})\n\n// --- Interaction schemas ---\n\nexport const interactionStatusValues = ['planned', 'done', 'canceled'] as const\nexport type InteractionStatus = typeof interactionStatusValues[number]\n\nconst interactionParticipantSchema = z.object({\n userId: z.string().uuid(),\n name: z.string().trim().max(200).optional(),\n email: z.string().trim().max(320).optional(),\n status: z.string().trim().max(50).optional(),\n})\n\nconst interactionLinkedEntitySchema = z.object({\n id: z.string().uuid(),\n type: z.enum(['company', 'deal', 'offer']),\n label: z.string().trim().max(500),\n})\n\nconst interactionGuestPermissionsSchema = z\n .object({\n canInviteOthers: z.boolean().optional(),\n canModify: z.boolean().optional(),\n canSeeList: z.boolean().optional(),\n })\n .strict()\n\nconst interactionExtendedFields = {\n durationMinutes: z.number().int().min(0).optional().nullable(),\n location: z.string().trim().max(500).optional().nullable(),\n allDay: z.boolean().optional().nullable(),\n recurrenceRule: z.string().trim().max(500).optional().nullable(),\n recurrenceEnd: z.coerce.date().optional().nullable(),\n participants: z.array(interactionParticipantSchema).optional().nullable(),\n reminderMinutes: z.number().int().min(0).optional().nullable(),\n visibility: z.string().trim().max(50).optional().nullable(),\n linkedEntities: z.array(interactionLinkedEntitySchema).optional().nullable(),\n guestPermissions: interactionGuestPermissionsSchema.optional().nullable(),\n} as const\n\nexport const interactionCreateSchema = scopedSchema.extend({\n id: z.string().uuid().optional(),\n entityId: z.string().uuid(),\n interactionType: z.string().trim().min(1).max(100),\n title: z.string().trim().max(500).optional().nullable(),\n body: z.string().trim().max(10000).optional().nullable(),\n status: z.enum(interactionStatusValues).optional().default('planned'),\n scheduledAt: z.coerce.date().optional().nullable(),\n occurredAt: z.coerce.date().optional().nullable(),\n priority: z.number().int().min(0).max(100).optional().nullable(),\n authorUserId: z.string().uuid().optional().nullable(),\n ownerUserId: z.string().uuid().optional().nullable(),\n dealId: z.string().uuid().optional().nullable(),\n appearanceIcon: z.string().trim().max(100).optional().nullable(),\n appearanceColor: z.string().trim().regex(/^#([0-9a-fA-F]{6})$/).optional().nullable(),\n source: z.string().trim().max(100).optional().nullable(),\n ...interactionExtendedFields,\n})\n\nexport type InteractionCreateInput = z.infer<typeof interactionCreateSchema>\n\nexport const interactionUpdateSchema = z\n .object({\n id: z.string().uuid(),\n })\n .merge(\n scopedSchema\n .extend({\n interactionType: z.string().trim().min(1).max(100).optional(),\n title: z.string().trim().max(500).optional().nullable(),\n body: z.string().trim().max(10000).optional().nullable(),\n status: z.enum(interactionStatusValues).optional(),\n scheduledAt: z.coerce.date().optional().nullable(),\n occurredAt: z.coerce.date().optional().nullable(),\n priority: z.number().int().min(0).max(100).optional().nullable(),\n authorUserId: z.string().uuid().optional().nullable(),\n ownerUserId: z.string().uuid().optional().nullable(),\n dealId: z.string().uuid().optional().nullable(),\n appearanceIcon: z.string().trim().max(100).optional().nullable(),\n appearanceColor: z.string().trim().regex(/^#([0-9a-fA-F]{6})$/).optional().nullable(),\n pinned: z.boolean().optional(),\n ...interactionExtendedFields,\n })\n .partial(),\n )\n\nexport type InteractionUpdateInput = z.infer<typeof interactionUpdateSchema>\n\nexport const interactionCompleteSchema = z.object({\n id: z.string().uuid(),\n occurredAt: z.coerce.date().optional(),\n})\n\nexport const interactionCancelSchema = z.object({\n id: z.string().uuid(),\n})\n\nexport const customerAddressFormatSchema = z.enum(['line_first', 'street_first'])\n\nexport const customerSettingsUpsertSchema = scopedSchema.extend({\n addressFormat: customerAddressFormatSchema,\n})\n\nexport type PersonCreateInput = z.infer<typeof personCreateSchema>\nexport type PersonUpdateInput = z.infer<typeof personUpdateSchema>\nexport type CompanyCreateInput = z.infer<typeof companyCreateSchema>\nexport type CompanyUpdateInput = z.infer<typeof companyUpdateSchema>\nexport type DealCreateInput = z.infer<typeof dealCreateSchema>\nexport type DealUpdateInput = z.infer<typeof dealUpdateSchema>\nexport type ActivityCreateInput = z.infer<typeof activityCreateSchema>\nexport type ActivityUpdateInput = z.infer<typeof activityUpdateSchema>\nexport type CommentCreateInput = z.infer<typeof commentCreateSchema>\nexport type CommentUpdateInput = z.infer<typeof commentUpdateSchema>\nexport type AddressCreateInput = z.infer<typeof addressCreateSchema>\nexport type AddressUpdateInput = z.infer<typeof addressUpdateSchema>\nexport type TagCreateInput = z.infer<typeof tagCreateSchema>\nexport type TagUpdateInput = z.infer<typeof tagUpdateSchema>\nexport type TagAssignmentInput = z.infer<typeof tagAssignmentSchema>\nexport type TodoLinkCreateInput = z.infer<typeof todoLinkCreateSchema>\nexport type TodoLinkWithTodoCreateInput = z.infer<typeof todoLinkWithTodoCreateSchema>\nexport type CustomerSettingsUpsertInput = z.infer<typeof customerSettingsUpsertSchema>\nexport type CustomerAddressFormatInput = z.infer<typeof customerAddressFormatSchema>\nexport type InteractionCompleteInput = z.infer<typeof interactionCompleteSchema>\nexport type InteractionCancelInput = z.infer<typeof interactionCancelSchema>\n\n// --- Pipeline schemas ---\n\nexport const pipelineCreateSchema = scopedSchema.extend({\n name: z.string().trim().min(1).max(200),\n isDefault: z.boolean().optional(),\n})\n\nexport const pipelineUpdateSchema = z.object({\n id: uuid(),\n name: z.string().trim().min(1).max(200).optional(),\n isDefault: z.boolean().optional(),\n})\n\nexport const pipelineDeleteSchema = z.object({\n id: uuid(),\n})\n\nexport type PipelineCreateInput = z.infer<typeof pipelineCreateSchema>\nexport type PipelineUpdateInput = z.infer<typeof pipelineUpdateSchema>\nexport type PipelineDeleteInput = z.infer<typeof pipelineDeleteSchema>\n\n// --- Pipeline Stage schemas ---\n\nexport const pipelineStageCreateSchema = scopedSchema.extend({\n pipelineId: uuid(),\n label: z.string().trim().min(1).max(200),\n order: z.number().int().min(0).optional(),\n color: z.string().trim().max(20).optional(),\n icon: z.string().trim().max(100).optional(),\n})\n\nexport const pipelineStageUpdateSchema = z.object({\n id: uuid(),\n label: z.string().trim().min(1).max(200).optional(),\n order: z.number().int().min(0).optional(),\n color: z.string().trim().max(20).optional(),\n icon: z.string().trim().max(100).optional(),\n})\n\nexport const pipelineStageDeleteSchema = z.object({\n id: uuid(),\n})\n\nexport const pipelineStageReorderSchema = scopedSchema.extend({\n stages: z.array(z.object({\n id: uuid(),\n order: z.number().int().min(0),\n })).min(1),\n})\n\nexport type PipelineStageCreateInput = z.infer<typeof pipelineStageCreateSchema>\nexport type PipelineStageUpdateInput = z.infer<typeof pipelineStageUpdateSchema>\nexport type PipelineStageDeleteInput = z.infer<typeof pipelineStageDeleteSchema>\nexport type PipelineStageReorderInput = z.infer<typeof pipelineStageReorderSchema>\n\nexport const entityRoleCreateSchema = scopedSchema.extend({\n entityType: z.enum(['company', 'person']),\n entityId: uuid(),\n roleType: z.string().trim().min(1).max(100),\n userId: uuid(),\n})\n\nexport const entityRoleUpdateSchema = scopedSchema.extend({\n id: uuid(),\n userId: uuid(),\n})\n\nexport const entityRoleDeleteSchema = scopedSchema.extend({\n id: uuid(),\n})\n\nexport type EntityRoleCreateInput = z.infer<typeof entityRoleCreateSchema>\nexport type EntityRoleUpdateInput = z.infer<typeof entityRoleUpdateSchema>\nexport type EntityRoleDeleteInput = z.infer<typeof entityRoleDeleteSchema>\n\nexport const updateKindSettingSchema = z.object({\n kind: z.string().trim().min(1).max(100),\n selectionMode: z.enum(['single', 'multi']).optional(),\n visibleInTags: z.boolean().optional(),\n sortOrder: z.number().int().min(0).optional(),\n})\n\nexport type UpdateKindSettingInput = z.infer<typeof updateKindSettingSchema>\n\nexport const customerKindSettingsUpsertSchema = scopedSchema.extend({\n kind: z.string().trim().min(1).max(100),\n selectionMode: z.enum(['single', 'multi']).optional(),\n visibleInTags: z.boolean().optional(),\n sortOrder: z.number().int().min(0).optional(),\n})\n\nexport type CustomerKindSettingsUpsertInput = z.infer<typeof customerKindSettingsUpsertSchema>\n\nexport const labelCreateSchema = z.object({\n label: z.string().trim().min(1).max(120),\n slug: z.string().trim().min(1).max(80).regex(/^[a-z0-9_-]+$/).optional(),\n})\n\nexport type LabelCreateInput = z.infer<typeof labelCreateSchema>\n\nexport const labelCreateCommandSchema = scopedSchema.extend({\n label: z.string().trim().min(1).max(120),\n slug: z.string().trim().min(1).max(80).regex(/^[a-z0-9_-]+$/),\n userId: uuid(),\n})\n\nexport type LabelCreateCommandInput = z.infer<typeof labelCreateCommandSchema>\n\nexport const labelAssignmentSchema = z.object({\n labelId: z.string().uuid(),\n entityId: z.string().uuid(),\n})\n\nexport type LabelAssignmentInput = z.infer<typeof labelAssignmentSchema>\n\nexport const labelAssignCommandSchema = scopedSchema.extend({\n labelId: uuid(),\n entityId: uuid(),\n})\n\nexport const labelUnassignCommandSchema = scopedSchema.extend({\n labelId: uuid(),\n entityId: uuid(),\n})\n\nexport type LabelAssignCommandInput = z.infer<typeof labelAssignCommandSchema>\nexport type LabelUnassignCommandInput = z.infer<typeof labelUnassignCommandSchema>\n\nexport const personCompanyLinkCreateSchema = scopedSchema.extend({\n personEntityId: uuid(),\n companyEntityId: uuid(),\n isPrimary: z.boolean().optional(),\n})\n\nexport const personCompanyLinkUpdateSchema = scopedSchema.extend({\n linkId: uuid(),\n isPrimary: z.boolean(),\n})\n\nexport const personCompanyLinkDeleteSchema = scopedSchema.extend({\n linkId: uuid(),\n})\n\nexport type PersonCompanyLinkCreateInput = z.infer<typeof personCompanyLinkCreateSchema>\nexport type PersonCompanyLinkUpdateInput = z.infer<typeof personCompanyLinkUpdateSchema>\nexport type PersonCompanyLinkDeleteInput = z.infer<typeof personCompanyLinkDeleteSchema>\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { z } from 'zod'\nimport { isValidPhoneNumber } from '@open-mercato/shared/lib/phone'\n\nconst uuid = () => z.string().uuid()\n\nexport const CUSTOMER_PHONE_INVALID_MESSAGE_KEY = 'customers.people.form.primaryPhone.invalid'\nexport const ACTIVITY_DATE_REQUIRED_MESSAGE_KEY = 'customers.activities.errors.dateRequired'\nexport const ACTIVITY_TIME_REQUIRED_MESSAGE_KEY = 'customers.activities.errors.timeRequired'\nexport const ACTIVITY_PHONE_REQUIRED_MESSAGE_KEY = 'customers.activities.errors.phoneRequired'\nexport const ACTIVITY_PHONE_INVALID_MESSAGE_KEY = 'customers.activities.errors.phoneInvalid'\n\nconst phoneSchema = z.string().trim().max(50).refine((val) => {\n return isValidPhoneNumber(val)\n}, { message: CUSTOMER_PHONE_INVALID_MESSAGE_KEY }).optional()\n\nconst interactionPhoneNumberSchema = z.string().trim().max(50).optional().nullable()\n\nconst scopedSchema = z.object({\n organizationId: uuid(),\n tenantId: uuid(),\n})\n\nconst nextInteractionSchema = z\n .object({\n at: z.coerce.date(),\n name: z.string().trim().min(1).max(200),\n refId: z.string().trim().max(191).optional().nullable(),\n icon: z.string().trim().max(100).optional().nullable(),\n color: z\n .string()\n .trim()\n .regex(/^#([0-9a-fA-F]{6})$/)\n .optional()\n .nullable(),\n })\n .strict()\n\nconst displayNameSchema = z.string().trim().min(1).max(200)\n\nconst baseEntitySchema = {\n displayName: displayNameSchema,\n description: z.string().trim().max(4000).optional(),\n ownerUserId: uuid().optional(),\n primaryEmail: z\n .string()\n .trim()\n .email()\n .max(320)\n .optional(),\n primaryPhone: phoneSchema,\n status: z.string().trim().max(100).optional(),\n lifecycleStage: z.string().trim().max(100).optional(),\n source: z.string().trim().max(150).optional(),\n temperature: z.string().trim().max(100).optional(),\n renewalQuarter: z.string().trim().max(100).optional(),\n isActive: z.boolean().optional(),\n nextInteraction: nextInteractionSchema.nullable().optional(),\n tags: z.array(uuid()).optional(),\n}\n\nconst personDetailsSchema = {\n preferredName: z.string().trim().max(120).optional(),\n jobTitle: z.string().trim().max(150).optional(),\n department: z.string().trim().max(150).optional(),\n seniority: z.string().trim().max(100).optional(),\n timezone: z.string().trim().max(120).optional(),\n linkedInUrl: z.string().trim().url().max(300).optional(),\n twitterUrl: z.string().trim().url().max(300).optional(),\n companyEntityId: uuid().nullable().optional(),\n}\n\nconst personFirstNameSchema = z.string().trim().min(1).max(120)\nconst personLastNameSchema = z.string().trim().min(1).max(120)\n\nconst companyDetailsSchema = {\n legalName: z.string().trim().max(200).optional(),\n brandName: z.string().trim().max(200).optional(),\n domain: z.string().trim().max(200).optional(),\n websiteUrl: z.string().trim().url().max(300).optional(),\n industry: z.string().trim().max(150).optional(),\n sizeBucket: z.string().trim().max(100).optional(),\n annualRevenue: z.coerce.number().min(0).optional(),\n}\n\nexport const personCreateSchema = scopedSchema.extend({\n ...baseEntitySchema,\n displayName: displayNameSchema.optional(),\n firstName: personFirstNameSchema,\n lastName: personLastNameSchema,\n ...personDetailsSchema,\n})\n\nexport const personUpdateSchema = z\n .object({\n id: uuid(),\n })\n .merge(\n scopedSchema.extend({\n ...baseEntitySchema,\n ...personDetailsSchema,\n firstName: personFirstNameSchema.optional(),\n lastName: personLastNameSchema.optional(),\n }).partial()\n )\n\nexport const companyCreateSchema = scopedSchema.extend({\n ...baseEntitySchema,\n displayName: displayNameSchema,\n ...companyDetailsSchema,\n})\n\nexport const companyUpdateSchema = z\n .object({\n id: uuid(),\n })\n .merge(companyCreateSchema.partial())\n\nexport const dealCreateSchema = scopedSchema.extend({\n title: z.string().min(1).max(200),\n description: z.string().max(4000).optional(),\n status: z.string().max(50).optional(),\n pipelineStage: z.string().max(100).optional(),\n pipelineId: uuid().optional(),\n pipelineStageId: uuid().optional(),\n valueAmount: z.coerce.number().min(0).optional(),\n valueCurrency: z.string().min(3).max(3).optional(),\n probability: z.number().min(0).max(100).optional(),\n expectedCloseAt: z.coerce.date().optional(),\n ownerUserId: uuid().optional(),\n source: z.string().max(150).optional(),\n closureOutcome: z.enum(['won', 'lost']).optional(),\n lossReasonId: uuid().optional(),\n lossNotes: z.string().max(4000).optional(),\n companyIds: z.array(uuid()).optional(),\n personIds: z.array(uuid()).optional(),\n})\n\nexport const dealUpdateSchema = z\n .object({\n id: uuid(),\n })\n .merge(dealCreateSchema.partial())\n\nexport const activityCreateSchema = scopedSchema.extend({\n entityId: uuid(),\n activityType: z.string().min(1).max(100),\n subject: z.string().max(200).optional(),\n body: z.string().max(8000).optional(),\n date: z.string().trim().min(1, ACTIVITY_DATE_REQUIRED_MESSAGE_KEY).optional(),\n time: z.string().trim().min(1, ACTIVITY_TIME_REQUIRED_MESSAGE_KEY).optional(),\n phoneNumber: interactionPhoneNumberSchema,\n occurredAt: z.coerce.date().optional(),\n dealId: uuid().optional(),\n authorUserId: uuid().optional(),\n appearanceIcon: z.string().trim().max(100).optional().nullable(),\n appearanceColor: z\n .string()\n .trim()\n .regex(/^#([0-9a-fA-F]{6})$/)\n .optional()\n .nullable(),\n})\n\nexport const activityUpdateSchema = z\n .object({\n id: uuid(),\n })\n .merge(activityCreateSchema.partial())\n\nexport const commentCreateSchema = scopedSchema.extend({\n entityId: uuid(),\n dealId: uuid().optional(),\n body: z.string().min(1).max(8000),\n authorUserId: uuid().optional(),\n appearanceIcon: z.string().trim().max(100).optional().nullable(),\n appearanceColor: z\n .string()\n .trim()\n .regex(/^#([0-9a-fA-F]{6})$/)\n .optional()\n .nullable(),\n})\n\nexport const commentUpdateSchema = z\n .object({\n id: uuid(),\n })\n .merge(commentCreateSchema.partial())\n\nexport const addressCreateSchema = scopedSchema.extend({\n entityId: uuid(),\n name: z.string().max(150).optional(),\n purpose: z.string().max(150).optional(),\n companyName: z.string().max(200).optional(),\n addressLine1: z.string().min(1).max(300),\n addressLine2: z.string().max(300).optional(),\n buildingNumber: z.string().max(50).optional(),\n flatNumber: z.string().max(50).optional(),\n city: z.string().max(150).optional(),\n region: z.string().max(150).optional(),\n postalCode: z.string().max(30).optional(),\n country: z.string().max(150).optional(),\n latitude: z.coerce.number().optional(),\n longitude: z.coerce.number().optional(),\n isPrimary: z.boolean().optional(),\n})\n\nexport const addressUpdateSchema = z\n .object({\n id: uuid(),\n })\n .merge(addressCreateSchema.partial())\n\nexport const tagCreateSchema = scopedSchema.extend({\n slug: z\n .string()\n .min(1)\n .max(80)\n .regex(/^[a-z0-9_-]+$/, 'Slug must be lowercase and may contain dashes or underscores'),\n label: z.string().min(1).max(120),\n color: z.string().max(30).optional(),\n description: z.string().max(400).optional(),\n})\n\nexport const tagUpdateSchema = z\n .object({\n id: uuid(),\n })\n .merge(tagCreateSchema.partial())\n\nconst KNOWN_DICTIONARY_KINDS = [\n 'status',\n 'source',\n 'lifecycle_stage',\n 'address_type',\n 'activity_type',\n 'deal_status',\n 'pipeline_stage',\n 'job_title',\n 'industry',\n 'temperature',\n 'renewal_quarter',\n 'person_company_role',\n] as const\nconst CUSTOM_DICTIONARY_KIND_PATTERN = /^[a-z0-9]+(?:[-_][a-z0-9]+)*$/\nconst dictionaryKindEnum = z.string().trim().refine(\n (value) =>\n (KNOWN_DICTIONARY_KINDS as readonly string[]).includes(value) ||\n CUSTOM_DICTIONARY_KIND_PATTERN.test(value),\n { message: 'Unsupported dictionary kind' },\n)\n\nconst dictionaryValueSchema = z.string().trim().min(1).max(150)\nconst dictionaryLabelSchema = z.string().trim().max(150)\nconst dictionaryColorSchema = z\n .string()\n .trim()\n .regex(/^#([0-9a-fA-F]{6})$/, 'Color must be a valid six-digit hex code like #3366ff')\nconst dictionaryIconSchema = z.string().trim().max(48)\n\nexport const customerDictionaryEntryCreateSchema = scopedSchema.extend({\n kind: dictionaryKindEnum,\n value: dictionaryValueSchema,\n label: dictionaryLabelSchema.optional(),\n color: dictionaryColorSchema.nullable().optional(),\n icon: dictionaryIconSchema.nullable().optional(),\n})\n\nexport type CustomerDictionaryEntryCreateInput = z.infer<typeof customerDictionaryEntryCreateSchema>\n\nexport const customerDictionaryEntryUpdateSchema = scopedSchema\n .extend({\n id: uuid(),\n kind: dictionaryKindEnum,\n value: dictionaryValueSchema.optional(),\n label: dictionaryLabelSchema.optional(),\n color: dictionaryColorSchema.nullable().optional(),\n icon: dictionaryIconSchema.nullable().optional(),\n })\n .refine(\n (payload) =>\n payload.value !== undefined ||\n payload.label !== undefined ||\n payload.color !== undefined ||\n payload.icon !== undefined,\n {\n message: 'Provide at least one field to update.',\n path: ['value'],\n }\n )\n\nexport type CustomerDictionaryEntryUpdateInput = z.infer<typeof customerDictionaryEntryUpdateSchema>\n\nexport const customerDictionaryEntryDeleteSchema = scopedSchema.extend({\n id: uuid(),\n kind: dictionaryKindEnum,\n})\n\nexport type CustomerDictionaryEntryDeleteInput = z.infer<typeof customerDictionaryEntryDeleteSchema>\n\nexport const tagAssignmentSchema = scopedSchema.extend({\n tagId: uuid(),\n entityId: uuid(),\n})\n\nexport const todoLinkCreateSchema = scopedSchema.extend({\n entityId: uuid(),\n todoId: uuid(),\n todoSource: z.string().min(1).max(120).default('customers:interaction'),\n createdByUserId: uuid().optional(),\n})\n\nexport const todoLinkWithTodoCreateSchema = scopedSchema.extend({\n entityId: uuid(),\n title: z.string().min(1).max(200),\n isDone: z.boolean().optional(),\n is_done: z.boolean().optional(),\n todoSource: z.string().min(1).max(120).default('customers:interaction'),\n createdByUserId: uuid().optional(),\n todoCustom: z.record(z.string(), z.any()).optional(),\n custom: z.record(z.string(), z.any()).optional(),\n})\n\n// --- Interaction schemas ---\n\nexport const interactionStatusValues = ['planned', 'done', 'canceled'] as const\nexport type InteractionStatus = typeof interactionStatusValues[number]\n\nconst interactionParticipantSchema = z.object({\n userId: z.string().uuid(),\n name: z.string().trim().max(200).optional(),\n email: z.string().trim().max(320).optional(),\n status: z.string().trim().max(50).optional(),\n})\n\nconst interactionLinkedEntitySchema = z.object({\n id: z.string().uuid(),\n type: z.enum(['company', 'deal', 'offer']),\n label: z.string().trim().max(500),\n})\n\nconst interactionGuestPermissionsSchema = z\n .object({\n canInviteOthers: z.boolean().optional(),\n canModify: z.boolean().optional(),\n canSeeList: z.boolean().optional(),\n })\n .strict()\n\nconst interactionExtendedFields = {\n durationMinutes: z.number().int().min(0).optional().nullable(),\n location: z.string().trim().max(500).optional().nullable(),\n allDay: z.boolean().optional().nullable(),\n recurrenceRule: z.string().trim().max(500).optional().nullable(),\n recurrenceEnd: z.coerce.date().optional().nullable(),\n participants: z.array(interactionParticipantSchema).optional().nullable(),\n reminderMinutes: z.number().int().min(0).optional().nullable(),\n visibility: z.string().trim().max(50).optional().nullable(),\n linkedEntities: z.array(interactionLinkedEntitySchema).optional().nullable(),\n guestPermissions: interactionGuestPermissionsSchema.optional().nullable(),\n} as const\n\nconst interactionCreateBaseSchema = scopedSchema.extend({\n id: z.string().uuid().optional(),\n entityId: z.string().uuid(),\n interactionType: z.string().trim().min(1).max(100),\n title: z.string().trim().max(500).optional().nullable(),\n body: z.string().trim().max(10000).optional().nullable(),\n status: z.enum(interactionStatusValues).optional().default('planned'),\n date: z.string().trim().min(1, ACTIVITY_DATE_REQUIRED_MESSAGE_KEY).optional(),\n time: z.string().trim().min(1, ACTIVITY_TIME_REQUIRED_MESSAGE_KEY).optional(),\n phoneNumber: interactionPhoneNumberSchema,\n scheduledAt: z.coerce.date().optional().nullable(),\n occurredAt: z.coerce.date().optional().nullable(),\n priority: z.number().int().min(0).max(100).optional().nullable(),\n authorUserId: z.string().uuid().optional().nullable(),\n ownerUserId: z.string().uuid().optional().nullable(),\n dealId: z.string().uuid().optional().nullable(),\n appearanceIcon: z.string().trim().max(100).optional().nullable(),\n appearanceColor: z.string().trim().regex(/^#([0-9a-fA-F]{6})$/).optional().nullable(),\n source: z.string().trim().max(100).optional().nullable(),\n ...interactionExtendedFields,\n})\n\nfunction deriveScheduledAtFromDateTime(date?: string, time?: string): Date | null {\n if (!date || typeof date !== 'string') return null\n const trimmedDate = date.trim()\n if (!trimmedDate) return null\n const trimmedTime = typeof time === 'string' ? time.trim() : ''\n const iso = trimmedTime ? `${trimmedDate}T${trimmedTime}:00` : `${trimmedDate}T00:00:00`\n const parsed = new Date(iso)\n return Number.isNaN(parsed.getTime()) ? null : parsed\n}\n\nexport const interactionCreateSchema = interactionCreateBaseSchema\n .superRefine((value, ctx) => {\n if (value.interactionType === 'call' && value.phoneNumber !== undefined && value.phoneNumber !== null) {\n const phone = typeof value.phoneNumber === 'string' ? value.phoneNumber.trim() : ''\n if (!phone) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['phoneNumber'],\n message: ACTIVITY_PHONE_REQUIRED_MESSAGE_KEY,\n })\n } else if (!isValidPhoneNumber(phone)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['phoneNumber'],\n message: ACTIVITY_PHONE_INVALID_MESSAGE_KEY,\n })\n }\n }\n })\n // Derive `scheduledAt` from `date+time` when only the latter are sent so\n // external API consumers don't silently persist `scheduled_at: null` after\n // the validator already enforced non-empty date/time. The form already\n // computes `scheduledAt` itself, so this branch is a no-op for the form path.\n .transform((value) => {\n if (value.scheduledAt) return value\n const derived = deriveScheduledAtFromDateTime(value.date, value.time)\n return derived ? { ...value, scheduledAt: derived } : value\n })\n\nexport type InteractionCreateInput = z.infer<typeof interactionCreateSchema>\n\nconst interactionUpdateBaseSchema = z\n .object({\n id: z.string().uuid(),\n })\n .merge(\n scopedSchema\n .extend({\n interactionType: z.string().trim().min(1).max(100).optional(),\n title: z.string().trim().max(500).optional().nullable(),\n body: z.string().trim().max(10000).optional().nullable(),\n status: z.enum(interactionStatusValues).optional(),\n date: z.string().trim().min(1, ACTIVITY_DATE_REQUIRED_MESSAGE_KEY).optional(),\n time: z.string().trim().min(1, ACTIVITY_TIME_REQUIRED_MESSAGE_KEY).optional(),\n phoneNumber: interactionPhoneNumberSchema,\n scheduledAt: z.coerce.date().optional().nullable(),\n occurredAt: z.coerce.date().optional().nullable(),\n priority: z.number().int().min(0).max(100).optional().nullable(),\n authorUserId: z.string().uuid().optional().nullable(),\n ownerUserId: z.string().uuid().optional().nullable(),\n dealId: z.string().uuid().optional().nullable(),\n appearanceIcon: z.string().trim().max(100).optional().nullable(),\n appearanceColor: z.string().trim().regex(/^#([0-9a-fA-F]{6})$/).optional().nullable(),\n pinned: z.boolean().optional(),\n ...interactionExtendedFields,\n })\n .partial(),\n )\n\nexport const interactionUpdateSchema = interactionUpdateBaseSchema\n .superRefine((value, ctx) => {\n if (value.interactionType === 'call' && value.phoneNumber !== undefined) {\n const phone = typeof value.phoneNumber === 'string' ? value.phoneNumber.trim() : ''\n if (!phone) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['phoneNumber'],\n message: ACTIVITY_PHONE_REQUIRED_MESSAGE_KEY,\n })\n } else if (!isValidPhoneNumber(phone)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['phoneNumber'],\n message: ACTIVITY_PHONE_INVALID_MESSAGE_KEY,\n })\n }\n }\n })\n // Mirror the create-schema derivation for partial updates: when an external\n // caller supplies `date+time` without `scheduledAt`, derive the timestamp so\n // the update doesn't silently leave `scheduled_at` stale.\n .transform((value) => {\n if (value.scheduledAt !== undefined) return value\n if (!value.date && !value.time) return value\n const derived = deriveScheduledAtFromDateTime(value.date, value.time)\n return derived ? { ...value, scheduledAt: derived } : value\n })\n\nexport type InteractionUpdateInput = z.infer<typeof interactionUpdateSchema>\n\nexport const interactionCompleteSchema = z.object({\n id: z.string().uuid(),\n occurredAt: z.coerce.date().optional(),\n})\n\nexport const interactionCancelSchema = z.object({\n id: z.string().uuid(),\n})\n\nexport const customerAddressFormatSchema = z.enum(['line_first', 'street_first'])\n\nexport const customerSettingsUpsertSchema = scopedSchema.extend({\n addressFormat: customerAddressFormatSchema,\n})\n\nexport type PersonCreateInput = z.infer<typeof personCreateSchema>\nexport type PersonUpdateInput = z.infer<typeof personUpdateSchema>\nexport type CompanyCreateInput = z.infer<typeof companyCreateSchema>\nexport type CompanyUpdateInput = z.infer<typeof companyUpdateSchema>\nexport type DealCreateInput = z.infer<typeof dealCreateSchema>\nexport type DealUpdateInput = z.infer<typeof dealUpdateSchema>\nexport type ActivityCreateInput = z.infer<typeof activityCreateSchema>\nexport type ActivityUpdateInput = z.infer<typeof activityUpdateSchema>\nexport type CommentCreateInput = z.infer<typeof commentCreateSchema>\nexport type CommentUpdateInput = z.infer<typeof commentUpdateSchema>\nexport type AddressCreateInput = z.infer<typeof addressCreateSchema>\nexport type AddressUpdateInput = z.infer<typeof addressUpdateSchema>\nexport type TagCreateInput = z.infer<typeof tagCreateSchema>\nexport type TagUpdateInput = z.infer<typeof tagUpdateSchema>\nexport type TagAssignmentInput = z.infer<typeof tagAssignmentSchema>\nexport type TodoLinkCreateInput = z.infer<typeof todoLinkCreateSchema>\nexport type TodoLinkWithTodoCreateInput = z.infer<typeof todoLinkWithTodoCreateSchema>\nexport type CustomerSettingsUpsertInput = z.infer<typeof customerSettingsUpsertSchema>\nexport type CustomerAddressFormatInput = z.infer<typeof customerAddressFormatSchema>\nexport type InteractionCompleteInput = z.infer<typeof interactionCompleteSchema>\nexport type InteractionCancelInput = z.infer<typeof interactionCancelSchema>\n\n// --- Pipeline schemas ---\n\nexport const pipelineCreateSchema = scopedSchema.extend({\n name: z.string().trim().min(1).max(200),\n isDefault: z.boolean().optional(),\n})\n\nexport const pipelineUpdateSchema = z.object({\n id: uuid(),\n name: z.string().trim().min(1).max(200).optional(),\n isDefault: z.boolean().optional(),\n})\n\nexport const pipelineDeleteSchema = z.object({\n id: uuid(),\n})\n\nexport type PipelineCreateInput = z.infer<typeof pipelineCreateSchema>\nexport type PipelineUpdateInput = z.infer<typeof pipelineUpdateSchema>\nexport type PipelineDeleteInput = z.infer<typeof pipelineDeleteSchema>\n\n// --- Pipeline Stage schemas ---\n\nexport const pipelineStageCreateSchema = scopedSchema.extend({\n pipelineId: uuid(),\n label: z.string().trim().min(1).max(200),\n order: z.number().int().min(0).optional(),\n color: z.string().trim().max(20).optional(),\n icon: z.string().trim().max(100).optional(),\n})\n\nexport const pipelineStageUpdateSchema = z.object({\n id: uuid(),\n label: z.string().trim().min(1).max(200).optional(),\n order: z.number().int().min(0).optional(),\n color: z.string().trim().max(20).optional(),\n icon: z.string().trim().max(100).optional(),\n})\n\nexport const pipelineStageDeleteSchema = z.object({\n id: uuid(),\n})\n\nexport const pipelineStageReorderSchema = scopedSchema.extend({\n stages: z.array(z.object({\n id: uuid(),\n order: z.number().int().min(0),\n })).min(1),\n})\n\nexport type PipelineStageCreateInput = z.infer<typeof pipelineStageCreateSchema>\nexport type PipelineStageUpdateInput = z.infer<typeof pipelineStageUpdateSchema>\nexport type PipelineStageDeleteInput = z.infer<typeof pipelineStageDeleteSchema>\nexport type PipelineStageReorderInput = z.infer<typeof pipelineStageReorderSchema>\n\nexport const entityRoleCreateSchema = scopedSchema.extend({\n entityType: z.enum(['company', 'person']),\n entityId: uuid(),\n roleType: z.string().trim().min(1).max(100),\n userId: uuid(),\n})\n\nexport const entityRoleUpdateSchema = scopedSchema.extend({\n id: uuid(),\n userId: uuid(),\n})\n\nexport const entityRoleDeleteSchema = scopedSchema.extend({\n id: uuid(),\n})\n\nexport type EntityRoleCreateInput = z.infer<typeof entityRoleCreateSchema>\nexport type EntityRoleUpdateInput = z.infer<typeof entityRoleUpdateSchema>\nexport type EntityRoleDeleteInput = z.infer<typeof entityRoleDeleteSchema>\n\nexport const updateKindSettingSchema = z.object({\n kind: z.string().trim().min(1).max(100),\n selectionMode: z.enum(['single', 'multi']).optional(),\n visibleInTags: z.boolean().optional(),\n sortOrder: z.number().int().min(0).optional(),\n})\n\nexport type UpdateKindSettingInput = z.infer<typeof updateKindSettingSchema>\n\nexport const customerKindSettingsUpsertSchema = scopedSchema.extend({\n kind: z.string().trim().min(1).max(100),\n selectionMode: z.enum(['single', 'multi']).optional(),\n visibleInTags: z.boolean().optional(),\n sortOrder: z.number().int().min(0).optional(),\n})\n\nexport type CustomerKindSettingsUpsertInput = z.infer<typeof customerKindSettingsUpsertSchema>\n\nexport const labelCreateSchema = z.object({\n label: z.string().trim().min(1).max(120),\n slug: z.string().trim().min(1).max(80).regex(/^[a-z0-9_-]+$/).optional(),\n})\n\nexport type LabelCreateInput = z.infer<typeof labelCreateSchema>\n\nexport const labelCreateCommandSchema = scopedSchema.extend({\n label: z.string().trim().min(1).max(120),\n slug: z.string().trim().min(1).max(80).regex(/^[a-z0-9_-]+$/),\n userId: uuid(),\n})\n\nexport type LabelCreateCommandInput = z.infer<typeof labelCreateCommandSchema>\n\nexport const labelAssignmentSchema = z.object({\n labelId: z.string().uuid(),\n entityId: z.string().uuid(),\n})\n\nexport type LabelAssignmentInput = z.infer<typeof labelAssignmentSchema>\n\nexport const labelAssignCommandSchema = scopedSchema.extend({\n labelId: uuid(),\n entityId: uuid(),\n})\n\nexport const labelUnassignCommandSchema = scopedSchema.extend({\n labelId: uuid(),\n entityId: uuid(),\n})\n\nexport type LabelAssignCommandInput = z.infer<typeof labelAssignCommandSchema>\nexport type LabelUnassignCommandInput = z.infer<typeof labelUnassignCommandSchema>\n\nexport const personCompanyLinkCreateSchema = scopedSchema.extend({\n personEntityId: uuid(),\n companyEntityId: uuid(),\n isPrimary: z.boolean().optional(),\n})\n\nexport const personCompanyLinkUpdateSchema = scopedSchema.extend({\n linkId: uuid(),\n isPrimary: z.boolean(),\n})\n\nexport const personCompanyLinkDeleteSchema = scopedSchema.extend({\n linkId: uuid(),\n})\n\nexport type PersonCompanyLinkCreateInput = z.infer<typeof personCompanyLinkCreateSchema>\nexport type PersonCompanyLinkUpdateInput = z.infer<typeof personCompanyLinkUpdateSchema>\nexport type PersonCompanyLinkDeleteInput = z.infer<typeof personCompanyLinkDeleteSchema>\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { loadCustomFieldValues } from "@open-mercato/shared/lib/crud/custom-fields";
|
|
2
|
+
import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
|
|
3
|
+
import { CustomerActivity, CustomerInteraction } from "../data/entities.js";
|
|
4
|
+
import { CUSTOMER_INTERACTION_ACTIVITY_ADAPTER_SOURCE } from "./interactionCompatibility.js";
|
|
5
|
+
async function loadLegacyActivityCustomValues(em, activity) {
|
|
6
|
+
const values = await loadCustomFieldValues({
|
|
7
|
+
em,
|
|
8
|
+
entityId: "customers:customer_activity",
|
|
9
|
+
recordIds: [activity.id],
|
|
10
|
+
tenantIdByRecord: { [activity.id]: activity.tenantId },
|
|
11
|
+
organizationIdByRecord: { [activity.id]: activity.organizationId },
|
|
12
|
+
tenantFallbacks: [activity.tenantId]
|
|
13
|
+
});
|
|
14
|
+
return values[activity.id] ?? null;
|
|
15
|
+
}
|
|
16
|
+
async function ensureCanonicalActivityBridge(em, commandBus, commandContext, activity) {
|
|
17
|
+
const existing = await em.findOne(CustomerInteraction, { id: activity.id, tenantId: activity.tenantId });
|
|
18
|
+
if (existing) return existing.id;
|
|
19
|
+
const entityId = typeof activity.entity === "string" ? activity.entity : activity.entity.id;
|
|
20
|
+
const dealId = activity.deal ? typeof activity.deal === "string" ? activity.deal : activity.deal.id : null;
|
|
21
|
+
const customValues = await loadLegacyActivityCustomValues(em, activity);
|
|
22
|
+
await commandBus.execute("customers.interactions.create", {
|
|
23
|
+
input: {
|
|
24
|
+
id: activity.id,
|
|
25
|
+
tenantId: activity.tenantId,
|
|
26
|
+
organizationId: activity.organizationId,
|
|
27
|
+
entityId,
|
|
28
|
+
interactionType: activity.activityType,
|
|
29
|
+
title: activity.subject ?? null,
|
|
30
|
+
body: activity.body ?? null,
|
|
31
|
+
occurredAt: activity.occurredAt ?? null,
|
|
32
|
+
status: activity.occurredAt ? "done" : "planned",
|
|
33
|
+
dealId,
|
|
34
|
+
authorUserId: activity.authorUserId ?? null,
|
|
35
|
+
appearanceIcon: activity.appearanceIcon ?? null,
|
|
36
|
+
appearanceColor: activity.appearanceColor ?? null,
|
|
37
|
+
source: CUSTOMER_INTERACTION_ACTIVITY_ADAPTER_SOURCE,
|
|
38
|
+
...customValues ? { customValues } : {}
|
|
39
|
+
},
|
|
40
|
+
ctx: commandContext
|
|
41
|
+
});
|
|
42
|
+
return activity.id;
|
|
43
|
+
}
|
|
44
|
+
async function resolveCanonicalActivityTargetId(em, commandBus, commandContext, targetId, tenantId) {
|
|
45
|
+
const existing = await em.findOne(CustomerInteraction, { id: targetId, tenantId });
|
|
46
|
+
if (existing) return existing.id;
|
|
47
|
+
const legacy = await findOneWithDecryption(
|
|
48
|
+
em,
|
|
49
|
+
CustomerActivity,
|
|
50
|
+
{ id: targetId, tenantId },
|
|
51
|
+
{ populate: ["entity", "deal"] },
|
|
52
|
+
{ tenantId }
|
|
53
|
+
);
|
|
54
|
+
if (!legacy) return targetId;
|
|
55
|
+
return ensureCanonicalActivityBridge(em, commandBus, commandContext, legacy);
|
|
56
|
+
}
|
|
57
|
+
export {
|
|
58
|
+
ensureCanonicalActivityBridge,
|
|
59
|
+
resolveCanonicalActivityTargetId
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=legacyActivityBridge.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/customers/lib/legacyActivityBridge.ts"],
|
|
4
|
+
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport type { CommandBus } from '@open-mercato/shared/lib/commands'\nimport { loadCustomFieldValues } from '@open-mercato/shared/lib/crud/custom-fields'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { CustomerActivity, CustomerInteraction } from '../data/entities'\nimport { CUSTOMER_INTERACTION_ACTIVITY_ADAPTER_SOURCE } from './interactionCompatibility'\n\ntype CommandContext = Parameters<CommandBus['execute']>[1]['ctx']\n\nasync function loadLegacyActivityCustomValues(\n em: EntityManager,\n activity: CustomerActivity,\n): Promise<Record<string, unknown> | null> {\n const values = await loadCustomFieldValues({\n em,\n entityId: 'customers:customer_activity',\n recordIds: [activity.id],\n tenantIdByRecord: { [activity.id]: activity.tenantId },\n organizationIdByRecord: { [activity.id]: activity.organizationId },\n tenantFallbacks: [activity.tenantId],\n })\n return values[activity.id] ?? null\n}\n\n/**\n * If the canonical `customer_interactions` row for `activity` does not yet\n * exist, create it via the `customers.interactions.create` command using the\n * legacy activity's primary key. Returns the canonical id (always equal to\n * `activity.id` in this scheme).\n *\n * Mirrors the bridge in /api/customers/activities so the dialog editing flow\n * can edit historical activities that still live only in `customer_activities`\n * (root cause of #1807 PUT 404 \"Interaction not found\").\n */\nexport async function ensureCanonicalActivityBridge(\n em: EntityManager,\n commandBus: CommandBus,\n commandContext: CommandContext,\n activity: CustomerActivity,\n): Promise<string> {\n const existing = await em.findOne(CustomerInteraction, { id: activity.id, tenantId: activity.tenantId })\n if (existing) return existing.id\n\n const entityId = typeof activity.entity === 'string' ? activity.entity : activity.entity.id\n const dealId = activity.deal\n ? (typeof activity.deal === 'string' ? activity.deal : activity.deal.id)\n : null\n const customValues = await loadLegacyActivityCustomValues(em, activity)\n\n await commandBus.execute('customers.interactions.create', {\n input: {\n id: activity.id,\n tenantId: activity.tenantId,\n organizationId: activity.organizationId,\n entityId,\n interactionType: activity.activityType,\n title: activity.subject ?? null,\n body: activity.body ?? null,\n occurredAt: activity.occurredAt ?? null,\n status: activity.occurredAt ? 'done' : 'planned',\n dealId,\n authorUserId: activity.authorUserId ?? null,\n appearanceIcon: activity.appearanceIcon ?? null,\n appearanceColor: activity.appearanceColor ?? null,\n source: CUSTOMER_INTERACTION_ACTIVITY_ADAPTER_SOURCE,\n ...(customValues ? { customValues } : {}),\n },\n ctx: commandContext,\n })\n\n return activity.id\n}\n\n/**\n * Returns the canonical `customer_interactions.id` for the given target id. If\n * the canonical record already exists, returns it directly. Otherwise looks\n * the id up in the legacy `customer_activities` table and bridges the row into\n * `customer_interactions` via {@link ensureCanonicalActivityBridge}. If\n * neither exists, returns the original id unchanged so downstream lookups can\n * surface a normal 404.\n */\nexport async function resolveCanonicalActivityTargetId(\n em: EntityManager,\n commandBus: CommandBus,\n commandContext: CommandContext,\n targetId: string,\n tenantId: string,\n): Promise<string> {\n const existing = await em.findOne(CustomerInteraction, { id: targetId, tenantId })\n if (existing) return existing.id\n\n // Reads encrypted scalar fields (subject, body, appearanceIcon, appearanceColor)\n // that are forwarded into `customers.interactions.create`. Use the decryption\n // helper so the bridged interaction inherits plaintext values rather than\n // ciphertext when tenant data encryption is enabled.\n const legacy = await findOneWithDecryption(\n em,\n CustomerActivity,\n { id: targetId, tenantId } as any,\n { populate: ['entity', 'deal'] } as any,\n { tenantId },\n )\n if (!legacy) return targetId\n\n return ensureCanonicalActivityBridge(em, commandBus, commandContext, legacy)\n}\n"],
|
|
5
|
+
"mappings": "AAEA,SAAS,6BAA6B;AACtC,SAAS,6BAA6B;AACtC,SAAS,kBAAkB,2BAA2B;AACtD,SAAS,oDAAoD;AAI7D,eAAe,+BACb,IACA,UACyC;AACzC,QAAM,SAAS,MAAM,sBAAsB;AAAA,IACzC;AAAA,IACA,UAAU;AAAA,IACV,WAAW,CAAC,SAAS,EAAE;AAAA,IACvB,kBAAkB,EAAE,CAAC,SAAS,EAAE,GAAG,SAAS,SAAS;AAAA,IACrD,wBAAwB,EAAE,CAAC,SAAS,EAAE,GAAG,SAAS,eAAe;AAAA,IACjE,iBAAiB,CAAC,SAAS,QAAQ;AAAA,EACrC,CAAC;AACD,SAAO,OAAO,SAAS,EAAE,KAAK;AAChC;AAYA,eAAsB,8BACpB,IACA,YACA,gBACA,UACiB;AACjB,QAAM,WAAW,MAAM,GAAG,QAAQ,qBAAqB,EAAE,IAAI,SAAS,IAAI,UAAU,SAAS,SAAS,CAAC;AACvG,MAAI,SAAU,QAAO,SAAS;AAE9B,QAAM,WAAW,OAAO,SAAS,WAAW,WAAW,SAAS,SAAS,SAAS,OAAO;AACzF,QAAM,SAAS,SAAS,OACnB,OAAO,SAAS,SAAS,WAAW,SAAS,OAAO,SAAS,KAAK,KACnE;AACJ,QAAM,eAAe,MAAM,+BAA+B,IAAI,QAAQ;AAEtE,QAAM,WAAW,QAAQ,iCAAiC;AAAA,IACxD,OAAO;AAAA,MACL,IAAI,SAAS;AAAA,MACb,UAAU,SAAS;AAAA,MACnB,gBAAgB,SAAS;AAAA,MACzB;AAAA,MACA,iBAAiB,SAAS;AAAA,MAC1B,OAAO,SAAS,WAAW;AAAA,MAC3B,MAAM,SAAS,QAAQ;AAAA,MACvB,YAAY,SAAS,cAAc;AAAA,MACnC,QAAQ,SAAS,aAAa,SAAS;AAAA,MACvC;AAAA,MACA,cAAc,SAAS,gBAAgB;AAAA,MACvC,gBAAgB,SAAS,kBAAkB;AAAA,MAC3C,iBAAiB,SAAS,mBAAmB;AAAA,MAC7C,QAAQ;AAAA,MACR,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;AAAA,IACzC;AAAA,IACA,KAAK;AAAA,EACP,CAAC;AAED,SAAO,SAAS;AAClB;AAUA,eAAsB,iCACpB,IACA,YACA,gBACA,UACA,UACiB;AACjB,QAAM,WAAW,MAAM,GAAG,QAAQ,qBAAqB,EAAE,IAAI,UAAU,SAAS,CAAC;AACjF,MAAI,SAAU,QAAO,SAAS;AAM9B,QAAM,SAAS,MAAM;AAAA,IACnB;AAAA,IACA;AAAA,IACA,EAAE,IAAI,UAAU,SAAS;AAAA,IACzB,EAAE,UAAU,CAAC,UAAU,MAAM,EAAE;AAAA,IAC/B,EAAE,SAAS;AAAA,EACb;AACA,MAAI,CAAC,OAAQ,QAAO;AAEpB,SAAO,8BAA8B,IAAI,YAAY,gBAAgB,MAAM;AAC7E;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -26,12 +26,12 @@ const listIntegrationLogsQuerySchema = z.object({
|
|
|
26
26
|
page: z.coerce.number().int().min(1).default(1),
|
|
27
27
|
pageSize: z.coerce.number().int().min(1).max(100).default(20)
|
|
28
28
|
});
|
|
29
|
-
const optionalBooleanQuery = z.
|
|
29
|
+
const optionalBooleanQuery = z.union([z.boolean(), z.string(), z.null(), z.undefined()]).transform((value) => {
|
|
30
30
|
if (value === void 0 || value === "" || value === null) return void 0;
|
|
31
31
|
if (value === true || value === "true" || value === "1") return true;
|
|
32
32
|
if (value === false || value === "false" || value === "0") return false;
|
|
33
33
|
return value;
|
|
34
|
-
}
|
|
34
|
+
}).pipe(z.boolean().optional());
|
|
35
35
|
const integrationMarketplaceHealthStatusSchema = z.enum(["healthy", "degraded", "unhealthy", "unconfigured"]);
|
|
36
36
|
const listIntegrationsQuerySchema = z.object({
|
|
37
37
|
q: z.string().max(200).optional(),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/integrations/data/validators.ts"],
|
|
4
|
-
"sourcesContent": ["import { z } from 'zod'\n\nexport const saveCredentialsSchema = z.object({\n credentials: z.record(\n z.string().min(1).max(128),\n z.union([z.string().max(20_000), z.number(), z.boolean(), z.null()]),\n ),\n}).refine((value) => Object.keys(value.credentials).length <= 200, {\n message: 'At most 200 credential fields are allowed',\n})\n\nexport type SaveCredentialsInput = z.infer<typeof saveCredentialsSchema>\n\nexport const updateVersionSchema = z.object({\n apiVersion: z.string().min(1),\n})\n\nexport type UpdateVersionInput = z.infer<typeof updateVersionSchema>\n\nexport const updateStateSchema = z.object({\n isEnabled: z.boolean().optional(),\n reauthRequired: z.boolean().optional(),\n}).refine((value) => value.isEnabled !== undefined || value.reauthRequired !== undefined, {\n message: 'At least one state field must be provided',\n})\n\nexport type UpdateStateInput = z.infer<typeof updateStateSchema>\n\nexport const integrationLogLevelSchema = z.enum(['info', 'warn', 'error'])\n\nexport const listIntegrationLogsQuerySchema = z.object({\n integrationId: z.string().min(1).optional(),\n level: integrationLogLevelSchema.optional(),\n runId: z.string().uuid().optional(),\n entityType: z.string().optional(),\n entityId: z.string().uuid().optional(),\n page: z.coerce.number().int().min(1).default(1),\n pageSize: z.coerce.number().int().min(1).max(100).default(20),\n})\n\nexport type ListIntegrationLogsQuery = z.infer<typeof listIntegrationLogsQuerySchema>\n\nconst optionalBooleanQuery = z.
|
|
5
|
-
"mappings": "AAAA,SAAS,SAAS;AAEX,MAAM,wBAAwB,EAAE,OAAO;AAAA,EAC5C,aAAa,EAAE;AAAA,IACb,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG;AAAA,IACzB,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,IAAI,GAAM,GAAG,EAAE,OAAO,GAAG,EAAE,QAAQ,GAAG,EAAE,KAAK,CAAC,CAAC;AAAA,EACrE;AACF,CAAC,EAAE,OAAO,CAAC,UAAU,OAAO,KAAK,MAAM,WAAW,EAAE,UAAU,KAAK;AAAA,EACjE,SAAS;AACX,CAAC;AAIM,MAAM,sBAAsB,EAAE,OAAO;AAAA,EAC1C,YAAY,EAAE,OAAO,EAAE,IAAI,CAAC;AAC9B,CAAC;AAIM,MAAM,oBAAoB,EAAE,OAAO;AAAA,EACxC,WAAW,EAAE,QAAQ,EAAE,SAAS;AAAA,EAChC,gBAAgB,EAAE,QAAQ,EAAE,SAAS;AACvC,CAAC,EAAE,OAAO,CAAC,UAAU,MAAM,cAAc,UAAa,MAAM,mBAAmB,QAAW;AAAA,EACxF,SAAS;AACX,CAAC;AAIM,MAAM,4BAA4B,EAAE,KAAK,CAAC,QAAQ,QAAQ,OAAO,CAAC;AAElE,MAAM,iCAAiC,EAAE,OAAO;AAAA,EACrD,eAAe,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EAC1C,OAAO,0BAA0B,SAAS;AAAA,EAC1C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS;AAAA,EAClC,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA,EAChC,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS;AAAA,EACrC,MAAM,EAAE,OAAO,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC;AAAA,EAC9C,UAAU,EAAE,OAAO,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,EAAE;AAC9D,CAAC;AAID,MAAM,uBAAuB,EAAE,
|
|
4
|
+
"sourcesContent": ["import { z } from 'zod'\n\nexport const saveCredentialsSchema = z.object({\n credentials: z.record(\n z.string().min(1).max(128),\n z.union([z.string().max(20_000), z.number(), z.boolean(), z.null()]),\n ),\n}).refine((value) => Object.keys(value.credentials).length <= 200, {\n message: 'At most 200 credential fields are allowed',\n})\n\nexport type SaveCredentialsInput = z.infer<typeof saveCredentialsSchema>\n\nexport const updateVersionSchema = z.object({\n apiVersion: z.string().min(1),\n})\n\nexport type UpdateVersionInput = z.infer<typeof updateVersionSchema>\n\nexport const updateStateSchema = z.object({\n isEnabled: z.boolean().optional(),\n reauthRequired: z.boolean().optional(),\n}).refine((value) => value.isEnabled !== undefined || value.reauthRequired !== undefined, {\n message: 'At least one state field must be provided',\n})\n\nexport type UpdateStateInput = z.infer<typeof updateStateSchema>\n\nexport const integrationLogLevelSchema = z.enum(['info', 'warn', 'error'])\n\nexport const listIntegrationLogsQuerySchema = z.object({\n integrationId: z.string().min(1).optional(),\n level: integrationLogLevelSchema.optional(),\n runId: z.string().uuid().optional(),\n entityType: z.string().optional(),\n entityId: z.string().uuid().optional(),\n page: z.coerce.number().int().min(1).default(1),\n pageSize: z.coerce.number().int().min(1).max(100).default(20),\n})\n\nexport type ListIntegrationLogsQuery = z.infer<typeof listIntegrationLogsQuerySchema>\n\nconst optionalBooleanQuery = z.union([z.boolean(), z.string(), z.null(), z.undefined()])\n .transform((value) => {\n if (value === undefined || value === '' || value === null) return undefined\n if (value === true || value === 'true' || value === '1') return true\n if (value === false || value === 'false' || value === '0') return false\n return value\n })\n .pipe(z.boolean().optional())\n\nexport const integrationMarketplaceHealthStatusSchema = z.enum(['healthy', 'degraded', 'unhealthy', 'unconfigured'])\n\nexport const listIntegrationsQuerySchema = z.object({\n q: z.string().max(200).optional(),\n category: z.string().max(64).optional(),\n bundleId: z.string().max(128).optional(),\n isEnabled: optionalBooleanQuery,\n healthStatus: integrationMarketplaceHealthStatusSchema.optional(),\n sort: z.enum(['title', 'category', 'enabledAt', 'healthStatus']).optional(),\n order: z.enum(['asc', 'desc']).default('asc'),\n page: z.coerce.number().int().min(1).default(1),\n pageSize: z.coerce.number().int().min(1).max(100).default(100),\n})\n\nexport type ListIntegrationsQuery = z.infer<typeof listIntegrationsQuerySchema>\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,SAAS;AAEX,MAAM,wBAAwB,EAAE,OAAO;AAAA,EAC5C,aAAa,EAAE;AAAA,IACb,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG;AAAA,IACzB,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,IAAI,GAAM,GAAG,EAAE,OAAO,GAAG,EAAE,QAAQ,GAAG,EAAE,KAAK,CAAC,CAAC;AAAA,EACrE;AACF,CAAC,EAAE,OAAO,CAAC,UAAU,OAAO,KAAK,MAAM,WAAW,EAAE,UAAU,KAAK;AAAA,EACjE,SAAS;AACX,CAAC;AAIM,MAAM,sBAAsB,EAAE,OAAO;AAAA,EAC1C,YAAY,EAAE,OAAO,EAAE,IAAI,CAAC;AAC9B,CAAC;AAIM,MAAM,oBAAoB,EAAE,OAAO;AAAA,EACxC,WAAW,EAAE,QAAQ,EAAE,SAAS;AAAA,EAChC,gBAAgB,EAAE,QAAQ,EAAE,SAAS;AACvC,CAAC,EAAE,OAAO,CAAC,UAAU,MAAM,cAAc,UAAa,MAAM,mBAAmB,QAAW;AAAA,EACxF,SAAS;AACX,CAAC;AAIM,MAAM,4BAA4B,EAAE,KAAK,CAAC,QAAQ,QAAQ,OAAO,CAAC;AAElE,MAAM,iCAAiC,EAAE,OAAO;AAAA,EACrD,eAAe,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EAC1C,OAAO,0BAA0B,SAAS;AAAA,EAC1C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS;AAAA,EAClC,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA,EAChC,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS;AAAA,EACrC,MAAM,EAAE,OAAO,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC;AAAA,EAC9C,UAAU,EAAE,OAAO,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,EAAE;AAC9D,CAAC;AAID,MAAM,uBAAuB,EAAE,MAAM,CAAC,EAAE,QAAQ,GAAG,EAAE,OAAO,GAAG,EAAE,KAAK,GAAG,EAAE,UAAU,CAAC,CAAC,EACpF,UAAU,CAAC,UAAU;AACpB,MAAI,UAAU,UAAa,UAAU,MAAM,UAAU,KAAM,QAAO;AAClE,MAAI,UAAU,QAAQ,UAAU,UAAU,UAAU,IAAK,QAAO;AAChE,MAAI,UAAU,SAAS,UAAU,WAAW,UAAU,IAAK,QAAO;AAClE,SAAO;AACT,CAAC,EACA,KAAK,EAAE,QAAQ,EAAE,SAAS,CAAC;AAEvB,MAAM,2CAA2C,EAAE,KAAK,CAAC,WAAW,YAAY,aAAa,cAAc,CAAC;AAE5G,MAAM,8BAA8B,EAAE,OAAO;AAAA,EAClD,GAAG,EAAE,OAAO,EAAE,IAAI,GAAG,EAAE,SAAS;AAAA,EAChC,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,SAAS;AAAA,EACtC,UAAU,EAAE,OAAO,EAAE,IAAI,GAAG,EAAE,SAAS;AAAA,EACvC,WAAW;AAAA,EACX,cAAc,yCAAyC,SAAS;AAAA,EAChE,MAAM,EAAE,KAAK,CAAC,SAAS,YAAY,aAAa,cAAc,CAAC,EAAE,SAAS;AAAA,EAC1E,OAAO,EAAE,KAAK,CAAC,OAAO,MAAM,CAAC,EAAE,QAAQ,KAAK;AAAA,EAC5C,MAAM,EAAE,OAAO,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC;AAAA,EAC9C,UAAU,EAAE,OAAO,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,GAAG;AAC/D,CAAC;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -2,6 +2,7 @@ import crypto from "node:crypto";
|
|
|
2
2
|
import { decryptWithAesGcm, encryptWithAesGcm } from "@open-mercato/shared/lib/encryption/aes";
|
|
3
3
|
import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
|
|
4
4
|
import { createKmsService } from "@open-mercato/shared/lib/encryption/kms";
|
|
5
|
+
import { parseDecryptedFieldValue } from "@open-mercato/shared/lib/encryption/tenantDataEncryptionService";
|
|
5
6
|
import {
|
|
6
7
|
getBundle,
|
|
7
8
|
getIntegration,
|
|
@@ -11,6 +12,15 @@ import { EncryptionMap } from "../../entities/data/entities.js";
|
|
|
11
12
|
import { IntegrationCredentials } from "../data/entities.js";
|
|
12
13
|
const ENCRYPTED_CREDENTIALS_BLOB_KEY = "__om_encrypted_credentials_blob_v1";
|
|
13
14
|
const DERIVED_KEY_CONTEXT = "integrations.credentials";
|
|
15
|
+
function isRecordValue(value) {
|
|
16
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
17
|
+
}
|
|
18
|
+
function normalizeCredentialsRecord(value) {
|
|
19
|
+
if (isRecordValue(value)) return value;
|
|
20
|
+
if (typeof value !== "string") return {};
|
|
21
|
+
const parsed = parseDecryptedFieldValue(value);
|
|
22
|
+
return isRecordValue(parsed) ? parsed : {};
|
|
23
|
+
}
|
|
14
24
|
function resolveFallbackEncryptionSecret() {
|
|
15
25
|
const candidates = [
|
|
16
26
|
process.env.TENANT_DATA_ENCRYPTION_FALLBACK_KEY,
|
|
@@ -75,7 +85,8 @@ function createCredentialsService(em) {
|
|
|
75
85
|
const payload = encryptWithAesGcm(JSON.stringify(credentials), dek);
|
|
76
86
|
return { [ENCRYPTED_CREDENTIALS_BLOB_KEY]: payload.value };
|
|
77
87
|
}
|
|
78
|
-
async function decryptCredentialsBlob(
|
|
88
|
+
async function decryptCredentialsBlob(credentialsInput, scope) {
|
|
89
|
+
const credentials = normalizeCredentialsRecord(credentialsInput);
|
|
79
90
|
const encrypted = credentials[ENCRYPTED_CREDENTIALS_BLOB_KEY];
|
|
80
91
|
if (typeof encrypted !== "string" || !encrypted) return credentials;
|
|
81
92
|
const dek = await resolveCredentialsDek(scope);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/integrations/lib/credentials-service.ts"],
|
|
4
|
-
"sourcesContent": ["import crypto from 'node:crypto'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { decryptWithAesGcm, encryptWithAesGcm } from '@open-mercato/shared/lib/encryption/aes'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { createKmsService } from '@open-mercato/shared/lib/encryption/kms'\nimport {\n getBundle,\n getIntegration,\n resolveIntegrationCredentialsSchema,\n type IntegrationScope,\n} from '@open-mercato/shared/modules/integrations/types'\nimport { EncryptionMap } from '../../entities/data/entities'\nimport { IntegrationCredentials } from '../data/entities'\n\nconst ENCRYPTED_CREDENTIALS_BLOB_KEY = '__om_encrypted_credentials_blob_v1'\nconst DERIVED_KEY_CONTEXT = 'integrations.credentials'\n\nfunction resolveFallbackEncryptionSecret(): string {\n const candidates = [\n process.env.TENANT_DATA_ENCRYPTION_FALLBACK_KEY,\n process.env.TENANT_DATA_ENCRYPTION_KEY,\n process.env.AUTH_SECRET,\n process.env.NEXTAUTH_SECRET,\n ]\n\n for (const value of candidates) {\n const normalized = value?.trim()\n if (normalized) return normalized\n }\n\n if (process.env.NODE_ENV !== 'production') return 'om-dev-tenant-encryption'\n\n console.warn(\n '[integrations.credentials] No encryption secret configured; using emergency fallback secret. Configure TENANT_DATA_ENCRYPTION_FALLBACK_KEY immediately.',\n )\n return 'om-emergency-fallback-rotate-me'\n}\n\nfunction deriveDekFromSecret(secret: string, tenantId: string): string {\n return crypto\n .createHash('sha256')\n .update(`${DERIVED_KEY_CONTEXT}:${tenantId}:${secret}`)\n .digest()\n .toString('base64')\n}\n\nexport function createCredentialsService(em: EntityManager) {\n const credentialsEncryptionSpec = [{ field: 'credentials' }]\n\n async function ensureCredentialsEncryptionMap(scope: IntegrationScope): Promise<void> {\n const existing = await findOneWithDecryption(\n em,\n EncryptionMap,\n {\n entityId: 'integrations:integration_credentials',\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n\n if (!existing) {\n const created = em.create(EncryptionMap, {\n entityId: 'integrations:integration_credentials',\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n fieldsJson: credentialsEncryptionSpec,\n isActive: true,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(created)\n return\n }\n\n existing.fieldsJson = credentialsEncryptionSpec\n existing.isActive = true\n }\n\n async function resolveCredentialsDek(scope: IntegrationScope): Promise<string> {\n const kms = createKmsService()\n const existing = await kms.getTenantDek(scope.tenantId)\n if (existing?.key) return existing.key\n\n const created = await kms.createTenantDek(scope.tenantId)\n if (created?.key) return created.key\n\n return deriveDekFromSecret(resolveFallbackEncryptionSecret(), scope.tenantId)\n }\n\n async function encryptCredentialsBlob(\n credentials: Record<string, unknown>,\n scope: IntegrationScope,\n ): Promise<Record<string, unknown>> {\n const dek = await resolveCredentialsDek(scope)\n const payload = encryptWithAesGcm(JSON.stringify(credentials), dek)\n return { [ENCRYPTED_CREDENTIALS_BLOB_KEY]: payload.value }\n }\n\n async function decryptCredentialsBlob(\n
|
|
5
|
-
"mappings": "AAAA,OAAO,YAAY;AAEnB,SAAS,mBAAmB,yBAAyB;AACrD,SAAS,6BAA6B;AACtC,SAAS,wBAAwB;AACjC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AACP,SAAS,qBAAqB;AAC9B,SAAS,8BAA8B;AAEvC,MAAM,iCAAiC;AACvC,MAAM,sBAAsB;AAE5B,SAAS,kCAA0C;AACjD,QAAM,aAAa;AAAA,IACjB,QAAQ,IAAI;AAAA,IACZ,QAAQ,IAAI;AAAA,IACZ,QAAQ,IAAI;AAAA,IACZ,QAAQ,IAAI;AAAA,EACd;AAEA,aAAW,SAAS,YAAY;AAC9B,UAAM,aAAa,OAAO,KAAK;AAC/B,QAAI,WAAY,QAAO;AAAA,EACzB;AAEA,MAAI,QAAQ,IAAI,aAAa,aAAc,QAAO;AAElD,UAAQ;AAAA,IACN;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,oBAAoB,QAAgB,UAA0B;AACrE,SAAO,OACJ,WAAW,QAAQ,EACnB,OAAO,GAAG,mBAAmB,IAAI,QAAQ,IAAI,MAAM,EAAE,EACrD,OAAO,EACP,SAAS,QAAQ;AACtB;AAEO,SAAS,yBAAyB,IAAmB;AAC1D,QAAM,4BAA4B,CAAC,EAAE,OAAO,cAAc,CAAC;AAE3D,iBAAe,+BAA+B,OAAwC;AACpF,UAAM,WAAW,MAAM;AAAA,MACrB;AAAA,MACA;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,UAAU,MAAM;AAAA,QAChB,gBAAgB,MAAM;AAAA,QACtB,WAAW;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,QAAI,CAAC,UAAU;AACb,YAAM,UAAU,GAAG,OAAO,eAAe;AAAA,QACvC,UAAU;AAAA,QACV,UAAU,MAAM;AAAA,QAChB,gBAAgB,MAAM;AAAA,QACtB,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,WAAW,oBAAI,KAAK;AAAA,QACpB,WAAW,oBAAI,KAAK;AAAA,MACtB,CAAC;AACD,SAAG,QAAQ,OAAO;AAClB;AAAA,IACF;AAEA,aAAS,aAAa;AACtB,aAAS,WAAW;AAAA,EACtB;AAEA,iBAAe,sBAAsB,OAA0C;AAC7E,UAAM,MAAM,iBAAiB;AAC7B,UAAM,WAAW,MAAM,IAAI,aAAa,MAAM,QAAQ;AACtD,QAAI,UAAU,IAAK,QAAO,SAAS;AAEnC,UAAM,UAAU,MAAM,IAAI,gBAAgB,MAAM,QAAQ;AACxD,QAAI,SAAS,IAAK,QAAO,QAAQ;AAEjC,WAAO,oBAAoB,gCAAgC,GAAG,MAAM,QAAQ;AAAA,EAC9E;AAEA,iBAAe,uBACb,aACA,OACkC;AAClC,UAAM,MAAM,MAAM,sBAAsB,KAAK;AAC7C,UAAM,UAAU,kBAAkB,KAAK,UAAU,WAAW,GAAG,GAAG;AAClE,WAAO,EAAE,CAAC,8BAA8B,GAAG,QAAQ,MAAM;AAAA,EAC3D;AAEA,iBAAe,uBACb,
|
|
4
|
+
"sourcesContent": ["import crypto from 'node:crypto'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { decryptWithAesGcm, encryptWithAesGcm } from '@open-mercato/shared/lib/encryption/aes'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { createKmsService } from '@open-mercato/shared/lib/encryption/kms'\nimport { parseDecryptedFieldValue } from '@open-mercato/shared/lib/encryption/tenantDataEncryptionService'\nimport {\n getBundle,\n getIntegration,\n resolveIntegrationCredentialsSchema,\n type IntegrationScope,\n} from '@open-mercato/shared/modules/integrations/types'\nimport { EncryptionMap } from '../../entities/data/entities'\nimport { IntegrationCredentials } from '../data/entities'\n\nconst ENCRYPTED_CREDENTIALS_BLOB_KEY = '__om_encrypted_credentials_blob_v1'\nconst DERIVED_KEY_CONTEXT = 'integrations.credentials'\n\nfunction isRecordValue(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction normalizeCredentialsRecord(value: unknown): Record<string, unknown> {\n if (isRecordValue(value)) return value\n if (typeof value !== 'string') return {}\n\n const parsed = parseDecryptedFieldValue(value)\n return isRecordValue(parsed) ? parsed : {}\n}\n\nfunction resolveFallbackEncryptionSecret(): string {\n const candidates = [\n process.env.TENANT_DATA_ENCRYPTION_FALLBACK_KEY,\n process.env.TENANT_DATA_ENCRYPTION_KEY,\n process.env.AUTH_SECRET,\n process.env.NEXTAUTH_SECRET,\n ]\n\n for (const value of candidates) {\n const normalized = value?.trim()\n if (normalized) return normalized\n }\n\n if (process.env.NODE_ENV !== 'production') return 'om-dev-tenant-encryption'\n\n console.warn(\n '[integrations.credentials] No encryption secret configured; using emergency fallback secret. Configure TENANT_DATA_ENCRYPTION_FALLBACK_KEY immediately.',\n )\n return 'om-emergency-fallback-rotate-me'\n}\n\nfunction deriveDekFromSecret(secret: string, tenantId: string): string {\n return crypto\n .createHash('sha256')\n .update(`${DERIVED_KEY_CONTEXT}:${tenantId}:${secret}`)\n .digest()\n .toString('base64')\n}\n\nexport function createCredentialsService(em: EntityManager) {\n const credentialsEncryptionSpec = [{ field: 'credentials' }]\n\n async function ensureCredentialsEncryptionMap(scope: IntegrationScope): Promise<void> {\n const existing = await findOneWithDecryption(\n em,\n EncryptionMap,\n {\n entityId: 'integrations:integration_credentials',\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n\n if (!existing) {\n const created = em.create(EncryptionMap, {\n entityId: 'integrations:integration_credentials',\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n fieldsJson: credentialsEncryptionSpec,\n isActive: true,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(created)\n return\n }\n\n existing.fieldsJson = credentialsEncryptionSpec\n existing.isActive = true\n }\n\n async function resolveCredentialsDek(scope: IntegrationScope): Promise<string> {\n const kms = createKmsService()\n const existing = await kms.getTenantDek(scope.tenantId)\n if (existing?.key) return existing.key\n\n const created = await kms.createTenantDek(scope.tenantId)\n if (created?.key) return created.key\n\n return deriveDekFromSecret(resolveFallbackEncryptionSecret(), scope.tenantId)\n }\n\n async function encryptCredentialsBlob(\n credentials: Record<string, unknown>,\n scope: IntegrationScope,\n ): Promise<Record<string, unknown>> {\n const dek = await resolveCredentialsDek(scope)\n const payload = encryptWithAesGcm(JSON.stringify(credentials), dek)\n return { [ENCRYPTED_CREDENTIALS_BLOB_KEY]: payload.value }\n }\n\n async function decryptCredentialsBlob(\n credentialsInput: unknown,\n scope: IntegrationScope,\n ): Promise<Record<string, unknown>> {\n const credentials = normalizeCredentialsRecord(credentialsInput)\n const encrypted = credentials[ENCRYPTED_CREDENTIALS_BLOB_KEY]\n if (typeof encrypted !== 'string' || !encrypted) return credentials\n\n const dek = await resolveCredentialsDek(scope)\n const decryptedRaw = decryptWithAesGcm(encrypted, dek)\n if (!decryptedRaw) return {}\n\n try {\n const parsed = JSON.parse(decryptedRaw) as unknown\n return parsed && typeof parsed === 'object' && !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : {}\n } catch {\n return {}\n }\n }\n\n return {\n async getRaw(integrationId: string, scope: IntegrationScope): Promise<Record<string, unknown> | null> {\n const row = await findOneWithDecryption(\n em,\n IntegrationCredentials,\n {\n integrationId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n if (!row) return null\n return decryptCredentialsBlob(row.credentials, scope)\n },\n\n async resolve(integrationId: string, scope: IntegrationScope): Promise<Record<string, unknown> | null> {\n const direct = await this.getRaw(integrationId, scope)\n if (direct) return direct\n\n const definition = getIntegration(integrationId)\n if (!definition?.bundleId) return null\n return this.getRaw(definition.bundleId, scope)\n },\n\n async save(integrationId: string, credentials: Record<string, unknown>, scope: IntegrationScope): Promise<void> {\n await ensureCredentialsEncryptionMap(scope)\n const encryptedCredentials = await encryptCredentialsBlob(credentials, scope)\n\n const row = await findOneWithDecryption(\n em,\n IntegrationCredentials,\n {\n integrationId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n\n if (row) {\n row.credentials = encryptedCredentials\n await em.flush()\n return\n }\n\n const created = em.create(IntegrationCredentials, {\n integrationId,\n credentials: encryptedCredentials,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n })\n await em.persist(created).flush()\n },\n\n async saveField(\n integrationId: string,\n fieldKey: string,\n value: unknown,\n scope: IntegrationScope,\n ): Promise<Record<string, unknown>> {\n const current = (await this.getRaw(integrationId, scope)) ?? {}\n const updated = { ...current, [fieldKey]: value }\n await this.save(integrationId, updated, scope)\n return updated\n },\n\n getSchema(integrationId: string) {\n const definition = getIntegration(integrationId)\n if (!definition) return undefined\n\n if (definition.bundleId) {\n const bundle = getBundle(definition.bundleId)\n return bundle?.credentials ?? resolveIntegrationCredentialsSchema(integrationId)\n }\n\n return definition.credentials ?? resolveIntegrationCredentialsSchema(integrationId)\n },\n }\n}\n\nexport type CredentialsService = ReturnType<typeof createCredentialsService>\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { registerCommand } from "@open-mercato/shared/lib/commands";
|
|
3
3
|
import { extractUndoPayload } from "@open-mercato/shared/lib/commands/undo";
|
|
4
|
+
import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
|
|
4
5
|
import { Message, MessageObject, MessageRecipient } from "../data/entities.js";
|
|
5
6
|
import { emitMessagesEvent } from "../events.js";
|
|
6
7
|
import {
|
|
7
8
|
findResolvedMessageActionById,
|
|
8
9
|
isTerminalMessageAction,
|
|
9
10
|
resolveActionCommandInput,
|
|
10
|
-
resolveActionHref
|
|
11
|
+
resolveActionHref,
|
|
12
|
+
resolveMessageActionData
|
|
11
13
|
} from "../lib/actions.js";
|
|
12
14
|
import { getMessageType } from "../lib/message-types-registry.js";
|
|
13
15
|
import { assertOrganizationAccess } from "./shared.js";
|
|
@@ -35,11 +37,17 @@ function toDate(value) {
|
|
|
35
37
|
return new Date(value);
|
|
36
38
|
}
|
|
37
39
|
async function requireActionTarget(em, input) {
|
|
38
|
-
const message = await
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
const message = await findOneWithDecryption(
|
|
41
|
+
em,
|
|
42
|
+
Message,
|
|
43
|
+
{
|
|
44
|
+
id: input.messageId,
|
|
45
|
+
tenantId: input.tenantId,
|
|
46
|
+
deletedAt: null
|
|
47
|
+
},
|
|
48
|
+
void 0,
|
|
49
|
+
{ tenantId: input.tenantId, organizationId: input.organizationId }
|
|
50
|
+
);
|
|
43
51
|
if (!message) throw new Error("Message not found");
|
|
44
52
|
assertOrganizationAccess(input, message);
|
|
45
53
|
const recipient = await em.findOne(MessageRecipient, {
|
|
@@ -51,11 +59,17 @@ async function requireActionTarget(em, input) {
|
|
|
51
59
|
return message;
|
|
52
60
|
}
|
|
53
61
|
async function requireActionMessage(em, input) {
|
|
54
|
-
const message = await
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
62
|
+
const message = await findOneWithDecryption(
|
|
63
|
+
em,
|
|
64
|
+
Message,
|
|
65
|
+
{
|
|
66
|
+
id: input.messageId,
|
|
67
|
+
tenantId: input.tenantId,
|
|
68
|
+
deletedAt: null
|
|
69
|
+
},
|
|
70
|
+
void 0,
|
|
71
|
+
{ tenantId: input.tenantId, organizationId: input.organizationId }
|
|
72
|
+
);
|
|
59
73
|
if (!message) throw new Error("Message not found");
|
|
60
74
|
assertOrganizationAccess(input, message);
|
|
61
75
|
const recipient = await em.findOne(MessageRecipient, {
|
|
@@ -127,7 +141,7 @@ const recordTerminalActionCommand = {
|
|
|
127
141
|
const messageId = logEntry?.resourceId;
|
|
128
142
|
if (!messageId) return;
|
|
129
143
|
const em = ctx.container.resolve("em").fork();
|
|
130
|
-
const message = await em
|
|
144
|
+
const message = await findOneWithDecryption(em, Message, { id: messageId });
|
|
131
145
|
if (!message) return;
|
|
132
146
|
message.actionTaken = before.actionTaken;
|
|
133
147
|
message.actionTakenByUserId = before.actionTakenByUserId;
|
|
@@ -151,8 +165,9 @@ const executeActionCommand = {
|
|
|
151
165
|
throw Object.assign(new Error("Action already taken"), { actionTaken: message.actionTaken });
|
|
152
166
|
}
|
|
153
167
|
const shouldRecordActionTaken = isTerminalMessageAction(action);
|
|
154
|
-
|
|
155
|
-
|
|
168
|
+
const actionData = resolveMessageActionData(message);
|
|
169
|
+
if (actionData?.expiresAt) {
|
|
170
|
+
if (new Date(actionData.expiresAt) < /* @__PURE__ */ new Date()) {
|
|
156
171
|
throw new Error("Actions have expired");
|
|
157
172
|
}
|
|
158
173
|
} else {
|