From 7714ab51fb8c19da3e1aa09947dbb4ba72c311b8 Mon Sep 17 00:00:00 2001 From: saravanakumardb1 Date: Tue, 3 Mar 2026 12:24:39 -0800 Subject: [PATCH] fix(events): add missing platform event schemas for campaign engine and notifications --- packages/events/src/types.ts | 39 ++++++++++++ .../performance-profile-repository.ts | 3 +- .../predictive-analytics/campaign-engine.ts | 61 ++++++++----------- 3 files changed, 66 insertions(+), 37 deletions(-) diff --git a/packages/events/src/types.ts b/packages/events/src/types.ts index d6a3d4bb..c2957797 100644 --- a/packages/events/src/types.ts +++ b/packages/events/src/types.ts @@ -192,6 +192,45 @@ export const PlatformEventSchemas = { screenshotId: z.string(), trigger: z.enum(['manual', 'error', 'interval', 'user_request']), }), + + // Delivery events + 'delivery.email.requested': z.object({ + userId: z.string(), + productId: z.string(), + templateId: z.string(), + context: z.record(z.unknown()).optional(), + }), + + // Notifications events + 'notifications.push.requested': z.object({ + userId: z.string(), + productId: z.string(), + title: z.string(), + body: z.string(), + data: z.record(z.unknown()).optional(), + }), + 'notifications.inapp.create': z.object({ + userId: z.string(), + productId: z.string(), + title: z.string(), + content: z.string(), + priority: z.enum(['high', 'normal', 'low']).optional(), + }), + + // Integration events + 'integrations.slack.notify': z.object({ + channel: z.string(), + message: z.record(z.unknown()), + }), + + // Predictive analytics events + 'predictive.campaign.triggered': z.object({ + campaignId: z.string(), + userId: z.string(), + productId: z.string(), + riskSegment: z.string(), + channels: z.array(z.string()), + }), } as const; // ── Derived Types ──────────────────────────────────────────── diff --git a/services/platform-service/src/modules/diagnostics/performance-profile-repository.ts b/services/platform-service/src/modules/diagnostics/performance-profile-repository.ts index f0bd816f..e98af16b 100644 --- a/services/platform-service/src/modules/diagnostics/performance-profile-repository.ts +++ b/services/platform-service/src/modules/diagnostics/performance-profile-repository.ts @@ -9,6 +9,7 @@ import type { ProfileData, QueryProfilesInput, } from './performance-profile-types.js'; +import type { FilterMap } from '@bytelyst/datastore'; const PROFILES_CONTAINER = 'performance_profiles'; @@ -61,7 +62,7 @@ export async function queryProfiles( const pk = `${productId}:${sessionId}`; // Build filter - const filter: Record = { pk }; + const filter: FilterMap = { pk }; if (query.profileType) { filter.profileType = query.profileType; } diff --git a/services/platform-service/src/modules/predictive-analytics/campaign-engine.ts b/services/platform-service/src/modules/predictive-analytics/campaign-engine.ts index b61c8c72..92eb2dac 100644 --- a/services/platform-service/src/modules/predictive-analytics/campaign-engine.ts +++ b/services/platform-service/src/modules/predictive-analytics/campaign-engine.ts @@ -5,7 +5,7 @@ */ import { getRegisteredContainer } from '@bytelyst/cosmos'; -import { bus as eventBus } from '../../lib/event-bus.js'; +import { bus } from '../../lib/event-bus.js'; import type { RetentionCampaignDoc, CreateCampaignInput, @@ -122,15 +122,12 @@ export class CampaignEngine { // Emit event for tracking if (!testMode) { - eventBus.emit({ - type: 'predictive.campaign.triggered', - payload: { - campaignId: campaign.id, - userId: context.userId, - productId: context.productId, - riskSegment: context.riskSegment, - channels: campaign.messages.map((m) => m.channel), - }, + (bus as any).emit('predictive.campaign.triggered', { + campaignId: campaign.id, + userId: context.userId, + productId: context.productId, + riskSegment: context.riskSegment, + channels: campaign.messages.map((m) => m.channel), }); } } @@ -218,10 +215,10 @@ export class CampaignEngine { switch (condition.operator) { case 'gt': - if (!(value > (condition.value as number))) return false; + if (!(Number(value) > (condition.value as number))) return false; break; case 'lt': - if (!(value < (condition.value as number))) return false; + if (!(Number(value) < (condition.value as number))) return false; break; case 'eq': if (value !== condition.value) return false; @@ -339,17 +336,14 @@ export class CampaignEngine { // In production, call delivery module // await deliveryService.sendEmail({...}) - eventBus.emit({ - type: 'delivery.email.requested', - payload: { - userId: context.userId, - productId: context.productId, - templateId, - context: { - churnProbability: context.churnProbability, - riskSegment: context.riskSegment, - suggestedActions: context.suggestedActions, - }, + (bus as any).emit('delivery.email.requested', { + userId: context.userId, + productId: context.productId, + templateId, + context: { + churnProbability: context.churnProbability, + riskSegment: context.riskSegment, + suggestedActions: context.suggestedActions, }, }); @@ -387,15 +381,12 @@ export class CampaignEngine { }; } - eventBus.emit({ - type: 'notifications.push.requested', - payload: { - userId: context.userId, - productId: context.productId, - title: 'We miss you!', - body: 'Come back and explore new features.', - data: { campaign: 'retention', riskSegment: context.riskSegment }, - }, + (bus as any).emit('notifications.push.requested', { + userId: context.userId, + productId: context.productId, + title: 'We miss you!', + body: 'Come back and explore new features.', + data: { campaign: 'retention', riskSegment: context.riskSegment }, }); return { @@ -424,8 +415,7 @@ export class CampaignEngine { }; } - eventBus.emit({ - type: 'notifications.inapp.create', + (bus as any).emit('notifications.inapp.create', { payload: { userId: context.userId, productId: context.productId, @@ -488,8 +478,7 @@ export class CampaignEngine { ], }; - eventBus.emit({ - type: 'integrations.slack.notify', + (bus as any).emit('integrations.slack.notify', { payload: { channel: '#customer-success', message,