@classytic/crm 0.1.1 → 0.5.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/dist/events.js ADDED
@@ -0,0 +1,716 @@
1
+ import { createEvent as createEvent$1, matchEventPattern } from "@classytic/primitives/events";
2
+ import { z } from "zod";
3
+ //#region src/events/event-constants.ts
4
+ /** PACKAGE_RULES rule 12: `package:resource.verb`. */
5
+ const CRM_EVENTS = {
6
+ LEAD_CREATED: "crm:lead.created",
7
+ LEAD_STATUS_CHANGED: "crm:lead.status_changed",
8
+ LEAD_SCORED: "crm:lead.scored",
9
+ LEAD_CONVERTED: "crm:lead.converted",
10
+ LEAD_DISQUALIFIED: "crm:lead.disqualified",
11
+ ACCOUNT_CREATED: "crm:account.created",
12
+ ACCOUNT_UPDATED: "crm:account.updated",
13
+ CONTACT_CREATED: "crm:contact.created",
14
+ CONTACT_UPDATED: "crm:contact.updated",
15
+ OPPORTUNITY_CREATED: "crm:opportunity.created",
16
+ OPPORTUNITY_STAGE_ADVANCED: "crm:opportunity.stage_advanced",
17
+ OPPORTUNITY_STAGE_REGRESSED: "crm:opportunity.stage_regressed",
18
+ OPPORTUNITY_WON: "crm:opportunity.won",
19
+ OPPORTUNITY_LOST: "crm:opportunity.lost",
20
+ OPPORTUNITY_ABANDONED: "crm:opportunity.abandoned",
21
+ PIPELINE_CREATED: "crm:pipeline.created",
22
+ PIPELINE_ARCHIVED: "crm:pipeline.archived",
23
+ ACTIVITY_PLANNED: "crm:activity.planned",
24
+ ACTIVITY_COMPLETED: "crm:activity.completed",
25
+ ACTIVITY_CANCELLED: "crm:activity.cancelled",
26
+ NOTE_ADDED: "crm:note.added",
27
+ CAMPAIGN_CREATED: "crm:campaign.created",
28
+ CAMPAIGN_ACTIVATED: "crm:campaign.activated",
29
+ CAMPAIGN_PAUSED: "crm:campaign.paused",
30
+ CAMPAIGN_RESUMED: "crm:campaign.resumed",
31
+ CAMPAIGN_COMPLETED: "crm:campaign.completed",
32
+ CAMPAIGN_ARCHIVED: "crm:campaign.archived",
33
+ SUBSCRIPTION_CREATED: "crm:subscription.created",
34
+ SUBSCRIPTION_CONFIRMED: "crm:subscription.confirmed",
35
+ SUBSCRIPTION_UNSUBSCRIBED: "crm:subscription.unsubscribed",
36
+ SUBSCRIPTION_BOUNCED: "crm:subscription.bounced",
37
+ SUBSCRIPTION_COMPLAINED: "crm:subscription.complained",
38
+ EMAIL_EVENT_OPENED: "crm:email_event.opened",
39
+ EMAIL_EVENT_CLICKED: "crm:email_event.clicked",
40
+ EMAIL_EVENT_BOUNCED: "crm:email_event.bounced",
41
+ EMAIL_EVENT_COMPLAINED: "crm:email_event.complained",
42
+ EMAIL_EVENT_UNSUBSCRIBED: "crm:email_event.unsubscribed",
43
+ LEAD_ENRICHED: "crm:lead.enriched",
44
+ LEAD_ASSIGNED: "crm:lead.assigned",
45
+ CONTACT_ENRICHED: "crm:contact.enriched",
46
+ CONTACT_ASSIGNED: "crm:contact.assigned",
47
+ CONTACT_MERGED: "crm:contact.merged",
48
+ ACCOUNT_ENRICHED: "crm:account.enriched",
49
+ ACCOUNT_ASSIGNED: "crm:account.assigned",
50
+ ACCOUNT_MERGED: "crm:account.merged",
51
+ OPPORTUNITY_ASSIGNED: "crm:opportunity.assigned",
52
+ OPPORTUNITY_AMOUNT_CHANGED: "crm:opportunity.amount_changed",
53
+ OPPORTUNITY_EXTENDED: "crm:opportunity.extended",
54
+ ACTIVITY_RESCHEDULED: "crm:activity.rescheduled",
55
+ ACTIVITY_OUTCOME_RECORDED: "crm:activity.outcome_recorded",
56
+ CONVERSATION_CREATED: "crm:conversation.created",
57
+ CONVERSATION_ASSIGNED: "crm:conversation.assigned",
58
+ CONVERSATION_RESOLVED: "crm:conversation.resolved",
59
+ CONVERSATION_REOPENED: "crm:conversation.reopened",
60
+ MESSAGE_RECEIVED: "crm:message.received",
61
+ MESSAGE_SENT: "crm:message.sent"
62
+ };
63
+ //#endregion
64
+ //#region src/events/helpers.ts
65
+ /**
66
+ * Event creation helper.
67
+ *
68
+ * Thin wrapper around `@classytic/primitives`' `createEvent` that fills the
69
+ * shared `EventMeta` from a `CrmContext` (userId/actorId, organizationId,
70
+ * correlationId). Use this instead of importing `createEvent` directly so
71
+ * the `source: 'crm'` stamp + tenant scoping stay consistent.
72
+ */
73
+ function createEvent(type, payload, ctx, meta) {
74
+ return createEvent$1(type, payload, {
75
+ source: "crm",
76
+ ...ctx?.actorId !== void 0 ? { actorId: String(ctx.actorId) } : {},
77
+ ...ctx?.organizationId !== void 0 ? { organizationId: String(ctx.organizationId) } : {},
78
+ ...ctx?.correlationId !== void 0 ? { correlationId: ctx.correlationId } : {},
79
+ ...meta
80
+ });
81
+ }
82
+ //#endregion
83
+ //#region src/events/in-process-bus.ts
84
+ /**
85
+ * In-process event bus — default fallback when no `eventTransport` is
86
+ * provided to `createCrm`. Structurally identical to arc's
87
+ * `MemoryEventTransport`; pattern matching is delegated to primitives.
88
+ * Handler errors are swallowed — event emission never blocks writes.
89
+ */
90
+ var InProcessCrmBus = class {
91
+ name = "in-process-crm";
92
+ subs = [];
93
+ logger;
94
+ constructor(options) {
95
+ if (options?.logger) this.logger = options.logger;
96
+ }
97
+ async publish(event) {
98
+ const matching = this.subs.filter((s) => matchEventPattern(s.pattern, event.type));
99
+ for (const sub of matching) try {
100
+ await sub.handler(event);
101
+ } catch (err) {
102
+ this.logger?.error?.(`[crm] event handler error [${event.type}]`, { error: err instanceof Error ? err.message : String(err) });
103
+ }
104
+ }
105
+ async subscribe(pattern, handler) {
106
+ const sub = {
107
+ pattern,
108
+ handler
109
+ };
110
+ this.subs.push(sub);
111
+ return () => {
112
+ this.subs = this.subs.filter((s) => s !== sub);
113
+ };
114
+ }
115
+ async close() {
116
+ this.subs = [];
117
+ }
118
+ };
119
+ //#endregion
120
+ //#region src/events/event-catalog.ts
121
+ /**
122
+ * Zod-source event catalog (PACKAGE_RULES rule 18).
123
+ *
124
+ * One Zod schema per event is the source of truth — runtime validation,
125
+ * static types, and Arc introspection all derive from it. Hosts wire the
126
+ * definitions into arc's `EventRegistry`:
127
+ *
128
+ * ```ts
129
+ * for (const def of crmEventDefinitions) registry.register(def);
130
+ * ```
131
+ *
132
+ * which lights up publish-time validation (`eventPlugin({ registry,
133
+ * validateMode: 'reject' })`), OpenAPI event introspection, and
134
+ * `arc describe` output — with zero arc imports here (the definition shape
135
+ * is structurally identical to arc's `EventDefinitionOutput`).
136
+ *
137
+ * Timestamps in payloads are `z.iso.datetime()` (NEVER `z.coerce.date()`):
138
+ * `z.toJSONSchema()` throws on coerce.date, and events are ISO strings on
139
+ * the wire (rule 25).
140
+ */
141
+ function defineCrmEvent(input) {
142
+ const { name, resource, description, version = 1, zodSchema } = input;
143
+ return {
144
+ name,
145
+ version,
146
+ description,
147
+ zodSchema,
148
+ schema: z.toJSONSchema(zodSchema),
149
+ create(payload, meta) {
150
+ return createEvent$1(name, payload, {
151
+ resource,
152
+ source: "crm",
153
+ ...meta
154
+ });
155
+ }
156
+ };
157
+ }
158
+ const ownerChangeSchema = z.object({
159
+ ownerId: z.string(),
160
+ previousOwnerId: z.string().optional()
161
+ });
162
+ const enrichSchema = z.object({
163
+ fields: z.array(z.string()),
164
+ provider: z.string().optional()
165
+ });
166
+ const mergeSchema = z.object({
167
+ primaryId: z.string(),
168
+ secondaryId: z.string(),
169
+ strategy: z.enum(["preferPrimary", "preferSecondary"])
170
+ });
171
+ const stageRefSchema = z.object({
172
+ stageId: z.string(),
173
+ sequence: z.number()
174
+ });
175
+ const LeadCreated = defineCrmEvent({
176
+ name: CRM_EVENTS.LEAD_CREATED,
177
+ resource: "lead",
178
+ description: "createLead() inserted a scored lead.",
179
+ zodSchema: z.object({
180
+ leadId: z.string(),
181
+ email: z.string().optional(),
182
+ score: z.number()
183
+ })
184
+ });
185
+ const LeadStatusChanged = defineCrmEvent({
186
+ name: CRM_EVENTS.LEAD_STATUS_CHANGED,
187
+ resource: "lead",
188
+ description: "A lead lifecycle transition committed (qualify/disqualify/nurture/...).",
189
+ zodSchema: z.object({
190
+ leadId: z.string(),
191
+ from: z.string(),
192
+ to: z.string()
193
+ })
194
+ });
195
+ const LeadScored = defineCrmEvent({
196
+ name: CRM_EVENTS.LEAD_SCORED,
197
+ resource: "lead",
198
+ description: "A lead score was (re)computed and persisted.",
199
+ zodSchema: z.object({
200
+ leadId: z.string(),
201
+ score: z.number()
202
+ })
203
+ });
204
+ const LeadConverted = defineCrmEvent({
205
+ name: CRM_EVENTS.LEAD_CONVERTED,
206
+ resource: "lead",
207
+ description: "convert() spawned Contact (+ Account) + Opportunity and closed the lead.",
208
+ zodSchema: z.object({
209
+ leadId: z.string(),
210
+ contactId: z.string(),
211
+ accountId: z.string().optional(),
212
+ opportunityId: z.string()
213
+ })
214
+ });
215
+ const LeadDisqualified = defineCrmEvent({
216
+ name: CRM_EVENTS.LEAD_DISQUALIFIED,
217
+ resource: "lead",
218
+ description: "disqualify() rejected a lead with a reason.",
219
+ zodSchema: z.object({
220
+ leadId: z.string(),
221
+ reason: z.string()
222
+ })
223
+ });
224
+ const LeadEnriched = defineCrmEvent({
225
+ name: CRM_EVENTS.LEAD_ENRICHED,
226
+ resource: "lead",
227
+ description: "enrich() merged a provider/manual patch into the lead.",
228
+ zodSchema: z.object({ leadId: z.string() }).extend(enrichSchema.shape)
229
+ });
230
+ const LeadAssigned = defineCrmEvent({
231
+ name: CRM_EVENTS.LEAD_ASSIGNED,
232
+ resource: "lead",
233
+ description: "assign() (re)assigned the lead owner.",
234
+ zodSchema: z.object({ leadId: z.string() }).extend(ownerChangeSchema.shape)
235
+ });
236
+ const AccountCreated = defineCrmEvent({
237
+ name: CRM_EVENTS.ACCOUNT_CREATED,
238
+ resource: "account",
239
+ description: "createAccount() inserted an account.",
240
+ zodSchema: z.object({
241
+ accountId: z.string(),
242
+ name: z.string()
243
+ })
244
+ });
245
+ const AccountUpdated = defineCrmEvent({
246
+ name: CRM_EVENTS.ACCOUNT_UPDATED,
247
+ resource: "account",
248
+ description: "An account record was updated.",
249
+ zodSchema: z.object({ accountId: z.string() })
250
+ });
251
+ const AccountEnriched = defineCrmEvent({
252
+ name: CRM_EVENTS.ACCOUNT_ENRICHED,
253
+ resource: "account",
254
+ description: "enrich() merged a patch into the account.",
255
+ zodSchema: z.object({ accountId: z.string() }).extend(enrichSchema.shape)
256
+ });
257
+ const AccountAssigned = defineCrmEvent({
258
+ name: CRM_EVENTS.ACCOUNT_ASSIGNED,
259
+ resource: "account",
260
+ description: "assign() (re)assigned the account owner.",
261
+ zodSchema: z.object({ accountId: z.string() }).extend(ownerChangeSchema.shape)
262
+ });
263
+ const AccountMerged = defineCrmEvent({
264
+ name: CRM_EVENTS.ACCOUNT_MERGED,
265
+ resource: "account",
266
+ description: "merge() folded a secondary account into the primary; secondary deleted.",
267
+ zodSchema: mergeSchema
268
+ });
269
+ const ContactCreated = defineCrmEvent({
270
+ name: CRM_EVENTS.CONTACT_CREATED,
271
+ resource: "contact",
272
+ description: "createContact() inserted a contact.",
273
+ zodSchema: z.object({
274
+ contactId: z.string(),
275
+ email: z.string().optional()
276
+ })
277
+ });
278
+ const ContactUpdated = defineCrmEvent({
279
+ name: CRM_EVENTS.CONTACT_UPDATED,
280
+ resource: "contact",
281
+ description: "A contact record was updated.",
282
+ zodSchema: z.object({ contactId: z.string() })
283
+ });
284
+ const ContactEnriched = defineCrmEvent({
285
+ name: CRM_EVENTS.CONTACT_ENRICHED,
286
+ resource: "contact",
287
+ description: "enrich() merged a patch into the contact.",
288
+ zodSchema: z.object({ contactId: z.string() }).extend(enrichSchema.shape)
289
+ });
290
+ const ContactAssigned = defineCrmEvent({
291
+ name: CRM_EVENTS.CONTACT_ASSIGNED,
292
+ resource: "contact",
293
+ description: "assign() (re)assigned the contact owner.",
294
+ zodSchema: z.object({ contactId: z.string() }).extend(ownerChangeSchema.shape)
295
+ });
296
+ const ContactMerged = defineCrmEvent({
297
+ name: CRM_EVENTS.CONTACT_MERGED,
298
+ resource: "contact",
299
+ description: "merge() folded a secondary contact into the primary; secondary deleted.",
300
+ zodSchema: mergeSchema
301
+ });
302
+ const OpportunityCreated = defineCrmEvent({
303
+ name: CRM_EVENTS.OPPORTUNITY_CREATED,
304
+ resource: "opportunity",
305
+ description: "openOpportunity() created a deal in a pipeline stage.",
306
+ zodSchema: z.object({
307
+ opportunityId: z.string(),
308
+ pipelineId: z.string(),
309
+ stageId: z.string()
310
+ })
311
+ });
312
+ const OpportunityStageAdvanced = defineCrmEvent({
313
+ name: CRM_EVENTS.OPPORTUNITY_STAGE_ADVANCED,
314
+ resource: "opportunity",
315
+ description: "moveToStage() moved the deal forward (higher stage sequence).",
316
+ zodSchema: z.object({
317
+ opportunityId: z.string(),
318
+ from: stageRefSchema,
319
+ to: stageRefSchema
320
+ })
321
+ });
322
+ const OpportunityStageRegressed = defineCrmEvent({
323
+ name: CRM_EVENTS.OPPORTUNITY_STAGE_REGRESSED,
324
+ resource: "opportunity",
325
+ description: "moveToStage() moved the deal backward (lower stage sequence).",
326
+ zodSchema: z.object({
327
+ opportunityId: z.string(),
328
+ from: stageRefSchema,
329
+ to: stageRefSchema
330
+ })
331
+ });
332
+ const OpportunityWon = defineCrmEvent({
333
+ name: CRM_EVENTS.OPPORTUNITY_WON,
334
+ resource: "opportunity",
335
+ description: "win() closed the deal as won (terminal).",
336
+ zodSchema: z.object({
337
+ opportunityId: z.string(),
338
+ amount: z.number().optional()
339
+ })
340
+ });
341
+ const OpportunityLost = defineCrmEvent({
342
+ name: CRM_EVENTS.OPPORTUNITY_LOST,
343
+ resource: "opportunity",
344
+ description: "lose() closed the deal as lost (terminal).",
345
+ zodSchema: z.object({
346
+ opportunityId: z.string(),
347
+ lostReasonId: z.string().optional()
348
+ })
349
+ });
350
+ const OpportunityAbandoned = defineCrmEvent({
351
+ name: CRM_EVENTS.OPPORTUNITY_ABANDONED,
352
+ resource: "opportunity",
353
+ description: "abandon() closed the deal as abandoned (terminal).",
354
+ zodSchema: z.object({ opportunityId: z.string() })
355
+ });
356
+ const OpportunityAssigned = defineCrmEvent({
357
+ name: CRM_EVENTS.OPPORTUNITY_ASSIGNED,
358
+ resource: "opportunity",
359
+ description: "assign() (re)assigned the opportunity owner.",
360
+ zodSchema: z.object({ opportunityId: z.string() }).extend(ownerChangeSchema.shape)
361
+ });
362
+ const OpportunityAmountChanged = defineCrmEvent({
363
+ name: CRM_EVENTS.OPPORTUNITY_AMOUNT_CHANGED,
364
+ resource: "opportunity",
365
+ description: "updateAmount() changed an open deal value.",
366
+ zodSchema: z.object({
367
+ opportunityId: z.string(),
368
+ amount: z.number(),
369
+ previousAmount: z.number().optional(),
370
+ reason: z.string().optional(),
371
+ by: z.string().optional()
372
+ })
373
+ });
374
+ const OpportunityExtended = defineCrmEvent({
375
+ name: CRM_EVENTS.OPPORTUNITY_EXTENDED,
376
+ resource: "opportunity",
377
+ description: "extendCloseDate() pushed expectedCloseAt further out.",
378
+ zodSchema: z.object({
379
+ opportunityId: z.string(),
380
+ expectedCloseAt: z.iso.datetime(),
381
+ previousExpectedCloseAt: z.iso.datetime().optional(),
382
+ reason: z.string().optional(),
383
+ by: z.string().optional()
384
+ })
385
+ });
386
+ const PipelineCreated = defineCrmEvent({
387
+ name: CRM_EVENTS.PIPELINE_CREATED,
388
+ resource: "pipeline",
389
+ description: "A pipeline was created.",
390
+ zodSchema: z.object({ pipelineId: z.string() })
391
+ });
392
+ const PipelineArchived = defineCrmEvent({
393
+ name: CRM_EVENTS.PIPELINE_ARCHIVED,
394
+ resource: "pipeline",
395
+ description: "archive() soft-deprecated a pipeline.",
396
+ zodSchema: z.object({ pipelineId: z.string() })
397
+ });
398
+ const ActivityPlanned = defineCrmEvent({
399
+ name: CRM_EVENTS.ACTIVITY_PLANNED,
400
+ resource: "activity",
401
+ description: "plan() created a planned activity against a subject.",
402
+ zodSchema: z.object({
403
+ activityId: z.string(),
404
+ type: z.string(),
405
+ subjectKind: z.string(),
406
+ subjectId: z.string()
407
+ })
408
+ });
409
+ const ActivityCompleted = defineCrmEvent({
410
+ name: CRM_EVENTS.ACTIVITY_COMPLETED,
411
+ resource: "activity",
412
+ description: "complete() finished an activity.",
413
+ zodSchema: z.object({
414
+ activityId: z.string(),
415
+ completedAt: z.iso.datetime()
416
+ })
417
+ });
418
+ const ActivityCancelled = defineCrmEvent({
419
+ name: CRM_EVENTS.ACTIVITY_CANCELLED,
420
+ resource: "activity",
421
+ description: "cancel() cancelled an activity.",
422
+ zodSchema: z.object({
423
+ activityId: z.string(),
424
+ reason: z.string().optional()
425
+ })
426
+ });
427
+ const ActivityRescheduled = defineCrmEvent({
428
+ name: CRM_EVENTS.ACTIVITY_RESCHEDULED,
429
+ resource: "activity",
430
+ description: "reschedule() moved an activity due date.",
431
+ zodSchema: z.object({
432
+ activityId: z.string(),
433
+ dueDate: z.iso.datetime(),
434
+ previousDueDate: z.iso.datetime().optional(),
435
+ reason: z.string().optional(),
436
+ by: z.string().optional()
437
+ })
438
+ });
439
+ const ActivityOutcomeRecorded = defineCrmEvent({
440
+ name: CRM_EVENTS.ACTIVITY_OUTCOME_RECORDED,
441
+ resource: "activity",
442
+ description: "recordOutcome() logged an activity outcome (no status change).",
443
+ zodSchema: z.object({
444
+ activityId: z.string(),
445
+ outcome: z.record(z.string(), z.unknown())
446
+ })
447
+ });
448
+ const NoteAdded = defineCrmEvent({
449
+ name: CRM_EVENTS.NOTE_ADDED,
450
+ resource: "note",
451
+ description: "A note was appended to a subject timeline.",
452
+ zodSchema: z.object({
453
+ noteId: z.string(),
454
+ subjectKind: z.string(),
455
+ subjectId: z.string()
456
+ })
457
+ });
458
+ const CampaignCreated = defineCrmEvent({
459
+ name: CRM_EVENTS.CAMPAIGN_CREATED,
460
+ resource: "campaign",
461
+ description: "createCampaign() inserted a campaign.",
462
+ zodSchema: z.object({
463
+ campaignId: z.string(),
464
+ name: z.string()
465
+ })
466
+ });
467
+ const CampaignActivated = defineCrmEvent({
468
+ name: CRM_EVENTS.CAMPAIGN_ACTIVATED,
469
+ resource: "campaign",
470
+ description: "activate() moved a campaign to active.",
471
+ zodSchema: z.object({ campaignId: z.string() })
472
+ });
473
+ const CampaignPaused = defineCrmEvent({
474
+ name: CRM_EVENTS.CAMPAIGN_PAUSED,
475
+ resource: "campaign",
476
+ description: "pause() suspended an active campaign.",
477
+ zodSchema: z.object({
478
+ campaignId: z.string(),
479
+ reason: z.string().optional()
480
+ })
481
+ });
482
+ const CampaignResumed = defineCrmEvent({
483
+ name: CRM_EVENTS.CAMPAIGN_RESUMED,
484
+ resource: "campaign",
485
+ description: "resume() reactivated a paused campaign.",
486
+ zodSchema: z.object({ campaignId: z.string() })
487
+ });
488
+ const CampaignCompleted = defineCrmEvent({
489
+ name: CRM_EVENTS.CAMPAIGN_COMPLETED,
490
+ resource: "campaign",
491
+ description: "complete() closed a campaign.",
492
+ zodSchema: z.object({
493
+ campaignId: z.string(),
494
+ actualRevenueAmount: z.number().optional()
495
+ })
496
+ });
497
+ const CampaignArchived = defineCrmEvent({
498
+ name: CRM_EVENTS.CAMPAIGN_ARCHIVED,
499
+ resource: "campaign",
500
+ description: "archive() archived a campaign (terminal).",
501
+ zodSchema: z.object({ campaignId: z.string() })
502
+ });
503
+ const SubscriptionCreated = defineCrmEvent({
504
+ name: CRM_EVENTS.SUBSCRIPTION_CREATED,
505
+ resource: "subscription",
506
+ description: "subscribe() created an opt-in (pending or confirmed).",
507
+ zodSchema: z.object({
508
+ subscriptionId: z.string(),
509
+ contactId: z.string(),
510
+ campaignId: z.string(),
511
+ requiresConfirmation: z.boolean()
512
+ })
513
+ });
514
+ const SubscriptionConfirmed = defineCrmEvent({
515
+ name: CRM_EVENTS.SUBSCRIPTION_CONFIRMED,
516
+ resource: "subscription",
517
+ description: "confirm() validated a double-opt-in token.",
518
+ zodSchema: z.object({
519
+ subscriptionId: z.string(),
520
+ contactId: z.string(),
521
+ campaignId: z.string(),
522
+ confirmedAt: z.iso.datetime()
523
+ })
524
+ });
525
+ const SubscriptionUnsubscribed = defineCrmEvent({
526
+ name: CRM_EVENTS.SUBSCRIPTION_UNSUBSCRIBED,
527
+ resource: "subscription",
528
+ description: "unsubscribe() opted a contact out (terminal).",
529
+ zodSchema: z.object({
530
+ subscriptionId: z.string(),
531
+ contactId: z.string(),
532
+ campaignId: z.string(),
533
+ reason: z.string().optional()
534
+ })
535
+ });
536
+ const SubscriptionBounced = defineCrmEvent({
537
+ name: CRM_EVENTS.SUBSCRIPTION_BOUNCED,
538
+ resource: "subscription",
539
+ description: "markBounced() recorded a hard bounce (terminal).",
540
+ zodSchema: z.object({
541
+ subscriptionId: z.string(),
542
+ contactId: z.string(),
543
+ campaignId: z.string(),
544
+ reason: z.string().optional()
545
+ })
546
+ });
547
+ const SubscriptionComplained = defineCrmEvent({
548
+ name: CRM_EVENTS.SUBSCRIPTION_COMPLAINED,
549
+ resource: "subscription",
550
+ description: "markComplained() recorded a spam complaint (terminal).",
551
+ zodSchema: z.object({
552
+ subscriptionId: z.string(),
553
+ contactId: z.string(),
554
+ campaignId: z.string()
555
+ })
556
+ });
557
+ const emailEventSchema = z.object({
558
+ eventId: z.string(),
559
+ kind: z.string(),
560
+ subjectKind: z.string(),
561
+ subjectId: z.string(),
562
+ campaignId: z.string().optional()
563
+ });
564
+ const EmailEventOpened = defineCrmEvent({
565
+ name: CRM_EVENTS.EMAIL_EVENT_OPENED,
566
+ resource: "email_event",
567
+ description: "recordOpen() logged an email open.",
568
+ zodSchema: emailEventSchema
569
+ });
570
+ const EmailEventClicked = defineCrmEvent({
571
+ name: CRM_EVENTS.EMAIL_EVENT_CLICKED,
572
+ resource: "email_event",
573
+ description: "recordClick() logged a link click.",
574
+ zodSchema: emailEventSchema
575
+ });
576
+ const EmailEventBounced = defineCrmEvent({
577
+ name: CRM_EVENTS.EMAIL_EVENT_BOUNCED,
578
+ resource: "email_event",
579
+ description: "recordBounce() logged a bounce.",
580
+ zodSchema: emailEventSchema
581
+ });
582
+ const EmailEventComplained = defineCrmEvent({
583
+ name: CRM_EVENTS.EMAIL_EVENT_COMPLAINED,
584
+ resource: "email_event",
585
+ description: "recordComplaint() logged a spam complaint.",
586
+ zodSchema: emailEventSchema
587
+ });
588
+ const EmailEventUnsubscribed = defineCrmEvent({
589
+ name: CRM_EVENTS.EMAIL_EVENT_UNSUBSCRIBED,
590
+ resource: "email_event",
591
+ description: "recordUnsubscribe() logged a one-click unsubscribe.",
592
+ zodSchema: emailEventSchema
593
+ });
594
+ const ConversationCreated = defineCrmEvent({
595
+ name: CRM_EVENTS.CONVERSATION_CREATED,
596
+ resource: "conversation",
597
+ description: "openConversation() started a conversation thread.",
598
+ zodSchema: z.object({
599
+ conversationId: z.string(),
600
+ channel: z.string(),
601
+ participantKind: z.string(),
602
+ participantId: z.string()
603
+ })
604
+ });
605
+ const ConversationAssigned = defineCrmEvent({
606
+ name: CRM_EVENTS.CONVERSATION_ASSIGNED,
607
+ resource: "conversation",
608
+ description: "assign() (re)assigned a conversation owner.",
609
+ zodSchema: z.object({
610
+ conversationId: z.string(),
611
+ assigneeId: z.string(),
612
+ previousAssigneeId: z.string().optional()
613
+ })
614
+ });
615
+ const ConversationResolved = defineCrmEvent({
616
+ name: CRM_EVENTS.CONVERSATION_RESOLVED,
617
+ resource: "conversation",
618
+ description: "resolve() closed a conversation.",
619
+ zodSchema: z.object({
620
+ conversationId: z.string(),
621
+ status: z.string(),
622
+ previousStatus: z.string()
623
+ })
624
+ });
625
+ const ConversationReopened = defineCrmEvent({
626
+ name: CRM_EVENTS.CONVERSATION_REOPENED,
627
+ resource: "conversation",
628
+ description: "reopen() reopened a resolved conversation.",
629
+ zodSchema: z.object({
630
+ conversationId: z.string(),
631
+ status: z.string(),
632
+ previousStatus: z.string()
633
+ })
634
+ });
635
+ const MessageReceived = defineCrmEvent({
636
+ name: CRM_EVENTS.MESSAGE_RECEIVED,
637
+ resource: "message",
638
+ description: "recordInbound() logged an inbound message.",
639
+ zodSchema: z.object({
640
+ messageId: z.string(),
641
+ conversationId: z.string(),
642
+ direction: z.string(),
643
+ externalMessageId: z.string().optional()
644
+ })
645
+ });
646
+ const MessageSent = defineCrmEvent({
647
+ name: CRM_EVENTS.MESSAGE_SENT,
648
+ resource: "message",
649
+ description: "recordOutbound() logged an outbound message.",
650
+ zodSchema: z.object({
651
+ messageId: z.string(),
652
+ conversationId: z.string(),
653
+ direction: z.string(),
654
+ externalMessageId: z.string().optional()
655
+ })
656
+ });
657
+ const crmEventDefinitions = [
658
+ LeadCreated,
659
+ LeadStatusChanged,
660
+ LeadScored,
661
+ LeadConverted,
662
+ LeadDisqualified,
663
+ LeadEnriched,
664
+ LeadAssigned,
665
+ AccountCreated,
666
+ AccountUpdated,
667
+ AccountEnriched,
668
+ AccountAssigned,
669
+ AccountMerged,
670
+ ContactCreated,
671
+ ContactUpdated,
672
+ ContactEnriched,
673
+ ContactAssigned,
674
+ ContactMerged,
675
+ OpportunityCreated,
676
+ OpportunityStageAdvanced,
677
+ OpportunityStageRegressed,
678
+ OpportunityWon,
679
+ OpportunityLost,
680
+ OpportunityAbandoned,
681
+ OpportunityAssigned,
682
+ OpportunityAmountChanged,
683
+ OpportunityExtended,
684
+ PipelineCreated,
685
+ PipelineArchived,
686
+ ActivityPlanned,
687
+ ActivityCompleted,
688
+ ActivityCancelled,
689
+ ActivityRescheduled,
690
+ ActivityOutcomeRecorded,
691
+ NoteAdded,
692
+ CampaignCreated,
693
+ CampaignActivated,
694
+ CampaignPaused,
695
+ CampaignResumed,
696
+ CampaignCompleted,
697
+ CampaignArchived,
698
+ SubscriptionCreated,
699
+ SubscriptionConfirmed,
700
+ SubscriptionUnsubscribed,
701
+ SubscriptionBounced,
702
+ SubscriptionComplained,
703
+ EmailEventOpened,
704
+ EmailEventClicked,
705
+ EmailEventBounced,
706
+ EmailEventComplained,
707
+ EmailEventUnsubscribed,
708
+ ConversationCreated,
709
+ ConversationAssigned,
710
+ ConversationResolved,
711
+ ConversationReopened,
712
+ MessageReceived,
713
+ MessageSent
714
+ ];
715
+ //#endregion
716
+ export { AccountAssigned, AccountCreated, AccountEnriched, AccountMerged, AccountUpdated, ActivityCancelled, ActivityCompleted, ActivityOutcomeRecorded, ActivityPlanned, ActivityRescheduled, CRM_EVENTS, CampaignActivated, CampaignArchived, CampaignCompleted, CampaignCreated, CampaignPaused, CampaignResumed, ContactAssigned, ContactCreated, ContactEnriched, ContactMerged, ContactUpdated, ConversationAssigned, ConversationCreated, ConversationReopened, ConversationResolved, EmailEventBounced, EmailEventClicked, EmailEventComplained, EmailEventOpened, EmailEventUnsubscribed, InProcessCrmBus, LeadAssigned, LeadConverted, LeadCreated, LeadDisqualified, LeadEnriched, LeadScored, LeadStatusChanged, MessageReceived, MessageSent, NoteAdded, OpportunityAbandoned, OpportunityAmountChanged, OpportunityAssigned, OpportunityCreated, OpportunityExtended, OpportunityLost, OpportunityStageAdvanced, OpportunityStageRegressed, OpportunityWon, PipelineArchived, PipelineCreated, SubscriptionBounced, SubscriptionComplained, SubscriptionConfirmed, SubscriptionCreated, SubscriptionUnsubscribed, createEvent, crmEventDefinitions };