@classytic/crm 0.5.1 → 0.7.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/CHANGELOG.md +108 -0
- package/dist/events.d.ts +64 -2
- package/dist/events.js +123 -2
- package/dist/index.d.ts +595 -20
- package/dist/index.js +1070 -68
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,114 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `@classytic/crm` are documented here.
|
|
4
4
|
|
|
5
|
+
## [0.7.0] — 2026-07-05
|
|
6
|
+
|
|
7
|
+
### Added — org-wide email suppression list
|
|
8
|
+
|
|
9
|
+
- **`Suppression` entity** (`crm.repositories.suppression`, model
|
|
10
|
+
`Suppression`): global per-org "never email this address again" list —
|
|
11
|
+
the gate hosts consult before EVERY outbound email. Unsubscribes on
|
|
12
|
+
`Subscription` stay per-campaign; suppression is org-wide.
|
|
13
|
+
- `suppress(email, { reason, source?, subjectKind?, subjectId?, metadata? }, ctx?)`
|
|
14
|
+
— idempotent `getOrCreate` on the unique `(organizationId, email)`
|
|
15
|
+
index (no check-then-save); emits `crm:suppression.added` only when
|
|
16
|
+
THIS call inserted the row.
|
|
17
|
+
- `isSuppressed(email, ctx?)` → boolean.
|
|
18
|
+
- `filterSuppressed(emails, ctx?)` → `Set<string>` of the suppressed
|
|
19
|
+
subset — ONE `$in` query for the campaign-fanout hot path.
|
|
20
|
+
- `unsuppress(email, ctx?)` — atomic delete; emits
|
|
21
|
+
`crm:suppression.removed` only when a row was actually removed.
|
|
22
|
+
- All verbs normalize emails (trim + lowercase; schema stores lowercase).
|
|
23
|
+
- **`SUPPRESSION_REASONS`** (`'bounce' | 'complaint' | 'unsubscribe' |
|
|
24
|
+
'manual'`) — the first three `satisfies readonly EmailEventKind[]` (P6),
|
|
25
|
+
so a rename in `EMAIL_EVENT_KINDS` fails compilation here.
|
|
26
|
+
- **Events** `crm:suppression.added` / `crm:suppression.removed` — Zod
|
|
27
|
+
catalog definitions included (no-drift invariant stays green);
|
|
28
|
+
`organizationId` rides event meta as usual.
|
|
29
|
+
- **Validators** `suppressSchema` / `unsuppressSchema` /
|
|
30
|
+
`suppressionFilterSchema`.
|
|
31
|
+
|
|
32
|
+
### Added — reply-detection exit verb
|
|
33
|
+
|
|
34
|
+
- **`EnrollmentRepository.exitActiveOnReply(subjects, ctx?)`** — the ONE
|
|
35
|
+
method a host's `crm:message.received` subscriber calls: finds ACTIVE
|
|
36
|
+
enrollments for the given `{ subjectKind, subjectId }` list, batch-loads
|
|
37
|
+
their sequences in a single `$in` query, skips those with
|
|
38
|
+
`replyDetectionEnabled === false`, and exits the rest via `exit(id,
|
|
39
|
+
'reply')` (each exit emits `crm:enrollment.exited`). Lost CAS races
|
|
40
|
+
(concurrent pause/complete/exit) are skipped, not failed. Returns the
|
|
41
|
+
enrollments this call exited.
|
|
42
|
+
- `EnrollmentRepositoryDeps` now carries `sequences: SequenceRepository`
|
|
43
|
+
(same cross-repo deps idiom as `OpportunityRepository.pipelines` /
|
|
44
|
+
`MessageRepository.conversations`) — wired automatically by
|
|
45
|
+
`createCrm()`; only hosts constructing `EnrollmentRepository` by hand
|
|
46
|
+
need to pass it.
|
|
47
|
+
|
|
48
|
+
## [0.6.0] — 2026-07-02
|
|
49
|
+
|
|
50
|
+
Breaking-in-behavior release (ships as MINOR per house convention):
|
|
51
|
+
outbox-first, session-safe event dispatch — the previously deferred
|
|
52
|
+
PACKAGE_RULES §P8/§P8.1 work.
|
|
53
|
+
|
|
54
|
+
### Added — unit-of-work contract (P8.1, shared with refit/review/cart/invoice)
|
|
55
|
+
|
|
56
|
+
- **`engine.withTransaction(ctx, body)`** — runs `body` inside a MongoDB
|
|
57
|
+
transaction with post-commit event discipline: events dispatched through
|
|
58
|
+
`txCtx` are queued under `ctx[PENDING_EVENTS]` and flushed to the
|
|
59
|
+
transport only AFTER commit; the queue resets on retry attempts; an abort
|
|
60
|
+
leaks nothing to in-process subscribers. Reuses the caller's session (and
|
|
61
|
+
queue) when `ctx.session` is already set. Standalone-Mongo dev boots opt
|
|
62
|
+
in via the existing `allowNonTransactional: true`.
|
|
63
|
+
- **`PENDING_EVENTS`** (`Symbol.for('@classytic/crm:pendingEvents')`) +
|
|
64
|
+
**`flushPending(transport, queue, logger?)`** + **`runUnit`** exported
|
|
65
|
+
from the root for hosts composing their own outer transaction.
|
|
66
|
+
- **`CrmConfig.outbox?: OutboxStore`** (from `@classytic/primitives/outbox`)
|
|
67
|
+
— when wired, every domain event is persisted via
|
|
68
|
+
`outbox.save(event, { session })` in the SAME session as the business
|
|
69
|
+
write; the host's relay publishes committed rows. Outbox save failures
|
|
70
|
+
PROPAGATE (P8: a swallowed save means the write persists while its event
|
|
71
|
+
vanishes).
|
|
72
|
+
- **`CrmEventDispatcher`** — EventTransport-compatible wrapper repositories
|
|
73
|
+
route every event through (`engine.events` is now this wrapper; the host
|
|
74
|
+
`publish`/`subscribe` surface is unchanged).
|
|
75
|
+
- **`UnmanagedSessionError`** (`code: 'UNMANAGED_SESSION'`) — a host-owned
|
|
76
|
+
`ctx.session` arriving with neither an outbox nor a `PENDING_EVENTS`
|
|
77
|
+
queue now throws instead of ghost-publishing mid-transaction.
|
|
78
|
+
**Behavioral break:** callers that previously threaded a bare session and
|
|
79
|
+
tolerated ghost events must switch to `engine.withTransaction` (or wire
|
|
80
|
+
an outbox / attach a queue).
|
|
81
|
+
|
|
82
|
+
### Added — timezone-aware forecasting
|
|
83
|
+
|
|
84
|
+
- **`ForecastOptions.timeZone`** — IANA zone for the default month bucket
|
|
85
|
+
(e.g. `'Asia/Dhaka'`). Without it, months cut at UTC boundaries: a deal
|
|
86
|
+
expected to close July 1, 02:00 Dhaka time (June 30, 20:00 UTC) files
|
|
87
|
+
under JUNE. Uses `civilDateOf` from `@classytic/primitives/timezone`.
|
|
88
|
+
Peer floor bumped: `@classytic/primitives >=0.9.0`.
|
|
89
|
+
|
|
90
|
+
### Fixed — sequence/enrollment (completes the 0.6.0 WIP)
|
|
91
|
+
|
|
92
|
+
- **Event catalog no-drift restored**: 10 missing Zod definitions added
|
|
93
|
+
(`crm:sequence.{created,active,paused,archived}`,
|
|
94
|
+
`crm:enrollment.{created,step_sent,paused,resumed,completed,exited}`) —
|
|
95
|
+
`crm:sequence.created` and `crm:enrollment.step_sent` are host-emitted
|
|
96
|
+
(create via `def.create()`), the rest publish in-repo.
|
|
97
|
+
- **`EnrollmentRepository.setWorkflowRunId` / `advanceStep` no longer
|
|
98
|
+
bypass the repository**: both used raw `model.findOneAndUpdate` with a
|
|
99
|
+
manual tenant filter — escaping `multiTenantPlugin` scoping AND
|
|
100
|
+
`ctx.session` (a call inside `withTransaction` would commit outside the
|
|
101
|
+
transaction). `advanceStep` is now a `claim()` CAS on `currentStepIndex`
|
|
102
|
+
with `where: { status: 'active' }`; `setWorkflowRunId` goes through
|
|
103
|
+
`repo.update`.
|
|
104
|
+
|
|
105
|
+
### Tests
|
|
106
|
+
|
|
107
|
+
- 14 new: `tests/unit/dispatch.test.ts` (6 — outbox propagation/session
|
|
108
|
+
routing/guard/swallow), `tests/integration/unit-of-work.test.ts` (3 —
|
|
109
|
+
convert() on a replica set: zero mid-tx events, post-commit flush, abort
|
|
110
|
+
leaks nothing, bare-session guard), `tests/unit/forecast-timezone.test.ts`
|
|
111
|
+
(5 — the +06:00 month-boundary trap). 110/110 total.
|
|
112
|
+
|
|
5
113
|
## [0.5.1] — 2026-06-14
|
|
6
114
|
|
|
7
115
|
### Fixed — declaration bundle
|
package/dist/events.d.ts
CHANGED
|
@@ -2,7 +2,6 @@ import { z } from "zod";
|
|
|
2
2
|
import { DomainEvent, EventHandler, EventMeta, EventTransport } from "@classytic/primitives/events";
|
|
3
3
|
import * as _$mongoose from "mongoose";
|
|
4
4
|
import { OperationContext } from "@classytic/primitives/context";
|
|
5
|
-
|
|
6
5
|
//#region src/events/event-constants.d.ts
|
|
7
6
|
/** PACKAGE_RULES rule 12: `package:resource.verb`. */
|
|
8
7
|
declare const CRM_EVENTS: {
|
|
@@ -38,6 +37,16 @@ declare const CRM_EVENTS: {
|
|
|
38
37
|
readonly SUBSCRIPTION_UNSUBSCRIBED: "crm:subscription.unsubscribed";
|
|
39
38
|
readonly SUBSCRIPTION_BOUNCED: "crm:subscription.bounced";
|
|
40
39
|
readonly SUBSCRIPTION_COMPLAINED: "crm:subscription.complained";
|
|
40
|
+
readonly SEQUENCE_CREATED: "crm:sequence.created";
|
|
41
|
+
readonly SEQUENCE_ACTIVATED: "crm:sequence.active";
|
|
42
|
+
readonly SEQUENCE_PAUSED: "crm:sequence.paused";
|
|
43
|
+
readonly SEQUENCE_ARCHIVED: "crm:sequence.archived";
|
|
44
|
+
readonly ENROLLMENT_CREATED: "crm:enrollment.created";
|
|
45
|
+
readonly ENROLLMENT_STEP_SENT: "crm:enrollment.step_sent";
|
|
46
|
+
readonly ENROLLMENT_PAUSED: "crm:enrollment.paused";
|
|
47
|
+
readonly ENROLLMENT_RESUMED: "crm:enrollment.resumed";
|
|
48
|
+
readonly ENROLLMENT_COMPLETED: "crm:enrollment.completed";
|
|
49
|
+
readonly ENROLLMENT_EXITED: "crm:enrollment.exited";
|
|
41
50
|
readonly EMAIL_EVENT_OPENED: "crm:email_event.opened";
|
|
42
51
|
readonly EMAIL_EVENT_CLICKED: "crm:email_event.clicked";
|
|
43
52
|
readonly EMAIL_EVENT_BOUNCED: "crm:email_event.bounced";
|
|
@@ -56,6 +65,8 @@ declare const CRM_EVENTS: {
|
|
|
56
65
|
readonly OPPORTUNITY_EXTENDED: "crm:opportunity.extended";
|
|
57
66
|
readonly ACTIVITY_RESCHEDULED: "crm:activity.rescheduled";
|
|
58
67
|
readonly ACTIVITY_OUTCOME_RECORDED: "crm:activity.outcome_recorded";
|
|
68
|
+
readonly SUPPRESSION_ADDED: "crm:suppression.added";
|
|
69
|
+
readonly SUPPRESSION_REMOVED: "crm:suppression.removed";
|
|
59
70
|
readonly CONVERSATION_CREATED: "crm:conversation.created";
|
|
60
71
|
readonly CONVERSATION_ASSIGNED: "crm:conversation.assigned";
|
|
61
72
|
readonly CONVERSATION_RESOLVED: "crm:conversation.resolved";
|
|
@@ -304,6 +315,19 @@ declare const SubscriptionComplained: CrmEventDefinition<z.ZodObject<{
|
|
|
304
315
|
contactId: z.ZodString;
|
|
305
316
|
campaignId: z.ZodString;
|
|
306
317
|
}, z.core.$strip>>;
|
|
318
|
+
declare const SuppressionAdded: CrmEventDefinition<z.ZodObject<{
|
|
319
|
+
email: z.ZodString;
|
|
320
|
+
reason: z.ZodEnum<{
|
|
321
|
+
bounce: "bounce";
|
|
322
|
+
complaint: "complaint";
|
|
323
|
+
unsubscribe: "unsubscribe";
|
|
324
|
+
manual: "manual";
|
|
325
|
+
}>;
|
|
326
|
+
source: z.ZodOptional<z.ZodString>;
|
|
327
|
+
}, z.core.$strip>>;
|
|
328
|
+
declare const SuppressionRemoved: CrmEventDefinition<z.ZodObject<{
|
|
329
|
+
email: z.ZodString;
|
|
330
|
+
}, z.core.$strip>>;
|
|
307
331
|
declare const EmailEventOpened: CrmEventDefinition<z.ZodObject<{
|
|
308
332
|
eventId: z.ZodString;
|
|
309
333
|
kind: z.ZodString;
|
|
@@ -372,6 +396,44 @@ declare const MessageSent: CrmEventDefinition<z.ZodObject<{
|
|
|
372
396
|
direction: z.ZodString;
|
|
373
397
|
externalMessageId: z.ZodOptional<z.ZodString>;
|
|
374
398
|
}, z.core.$strip>>;
|
|
399
|
+
declare const SequenceCreated: CrmEventDefinition<z.ZodObject<{
|
|
400
|
+
sequenceId: z.ZodString;
|
|
401
|
+
name: z.ZodOptional<z.ZodString>;
|
|
402
|
+
}, z.core.$strip>>;
|
|
403
|
+
declare const SequenceActivated: CrmEventDefinition<z.ZodObject<{
|
|
404
|
+
sequenceId: z.ZodString;
|
|
405
|
+
}, z.core.$strip>>;
|
|
406
|
+
declare const SequencePaused: CrmEventDefinition<z.ZodObject<{
|
|
407
|
+
sequenceId: z.ZodString;
|
|
408
|
+
}, z.core.$strip>>;
|
|
409
|
+
declare const SequenceArchived: CrmEventDefinition<z.ZodObject<{
|
|
410
|
+
sequenceId: z.ZodString;
|
|
411
|
+
}, z.core.$strip>>;
|
|
412
|
+
declare const EnrollmentCreated: CrmEventDefinition<z.ZodObject<{
|
|
413
|
+
enrollmentId: z.ZodString;
|
|
414
|
+
sequenceId: z.ZodString;
|
|
415
|
+
subjectId: z.ZodString;
|
|
416
|
+
subjectKind: z.ZodString;
|
|
417
|
+
}, z.core.$strip>>;
|
|
418
|
+
declare const EnrollmentStepSent: CrmEventDefinition<z.ZodObject<{
|
|
419
|
+
enrollmentId: z.ZodString;
|
|
420
|
+
sequenceId: z.ZodOptional<z.ZodString>;
|
|
421
|
+
stepIndex: z.ZodNumber;
|
|
422
|
+
channel: z.ZodOptional<z.ZodString>;
|
|
423
|
+
}, z.core.$strip>>;
|
|
424
|
+
declare const EnrollmentPaused: CrmEventDefinition<z.ZodObject<{
|
|
425
|
+
enrollmentId: z.ZodString;
|
|
426
|
+
}, z.core.$strip>>;
|
|
427
|
+
declare const EnrollmentResumed: CrmEventDefinition<z.ZodObject<{
|
|
428
|
+
enrollmentId: z.ZodString;
|
|
429
|
+
}, z.core.$strip>>;
|
|
430
|
+
declare const EnrollmentCompleted: CrmEventDefinition<z.ZodObject<{
|
|
431
|
+
enrollmentId: z.ZodString;
|
|
432
|
+
}, z.core.$strip>>;
|
|
433
|
+
declare const EnrollmentExited: CrmEventDefinition<z.ZodObject<{
|
|
434
|
+
enrollmentId: z.ZodString;
|
|
435
|
+
exitReason: z.ZodOptional<z.ZodString>;
|
|
436
|
+
}, z.core.$strip>>;
|
|
375
437
|
declare const crmEventDefinitions: ReadonlyArray<CrmEventDefinition>;
|
|
376
438
|
//#endregion
|
|
377
439
|
//#region src/engine/engine-types.d.ts
|
|
@@ -410,4 +472,4 @@ declare class InProcessCrmBus implements EventTransport {
|
|
|
410
472
|
close(): Promise<void>;
|
|
411
473
|
}
|
|
412
474
|
//#endregion
|
|
413
|
-
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, CrmEventDefinition, CrmEventName, CrmEventSchema, 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 };
|
|
475
|
+
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, CrmEventDefinition, CrmEventName, CrmEventSchema, EmailEventBounced, EmailEventClicked, EmailEventComplained, EmailEventOpened, EmailEventUnsubscribed, EnrollmentCompleted, EnrollmentCreated, EnrollmentExited, EnrollmentPaused, EnrollmentResumed, EnrollmentStepSent, InProcessCrmBus, LeadAssigned, LeadConverted, LeadCreated, LeadDisqualified, LeadEnriched, LeadScored, LeadStatusChanged, MessageReceived, MessageSent, NoteAdded, OpportunityAbandoned, OpportunityAmountChanged, OpportunityAssigned, OpportunityCreated, OpportunityExtended, OpportunityLost, OpportunityStageAdvanced, OpportunityStageRegressed, OpportunityWon, PipelineArchived, PipelineCreated, SequenceActivated, SequenceArchived, SequenceCreated, SequencePaused, SubscriptionBounced, SubscriptionComplained, SubscriptionConfirmed, SubscriptionCreated, SubscriptionUnsubscribed, SuppressionAdded, SuppressionRemoved, createEvent, crmEventDefinitions };
|
package/dist/events.js
CHANGED
|
@@ -35,6 +35,16 @@ const CRM_EVENTS = {
|
|
|
35
35
|
SUBSCRIPTION_UNSUBSCRIBED: "crm:subscription.unsubscribed",
|
|
36
36
|
SUBSCRIPTION_BOUNCED: "crm:subscription.bounced",
|
|
37
37
|
SUBSCRIPTION_COMPLAINED: "crm:subscription.complained",
|
|
38
|
+
SEQUENCE_CREATED: "crm:sequence.created",
|
|
39
|
+
SEQUENCE_ACTIVATED: "crm:sequence.active",
|
|
40
|
+
SEQUENCE_PAUSED: "crm:sequence.paused",
|
|
41
|
+
SEQUENCE_ARCHIVED: "crm:sequence.archived",
|
|
42
|
+
ENROLLMENT_CREATED: "crm:enrollment.created",
|
|
43
|
+
ENROLLMENT_STEP_SENT: "crm:enrollment.step_sent",
|
|
44
|
+
ENROLLMENT_PAUSED: "crm:enrollment.paused",
|
|
45
|
+
ENROLLMENT_RESUMED: "crm:enrollment.resumed",
|
|
46
|
+
ENROLLMENT_COMPLETED: "crm:enrollment.completed",
|
|
47
|
+
ENROLLMENT_EXITED: "crm:enrollment.exited",
|
|
38
48
|
EMAIL_EVENT_OPENED: "crm:email_event.opened",
|
|
39
49
|
EMAIL_EVENT_CLICKED: "crm:email_event.clicked",
|
|
40
50
|
EMAIL_EVENT_BOUNCED: "crm:email_event.bounced",
|
|
@@ -53,6 +63,8 @@ const CRM_EVENTS = {
|
|
|
53
63
|
OPPORTUNITY_EXTENDED: "crm:opportunity.extended",
|
|
54
64
|
ACTIVITY_RESCHEDULED: "crm:activity.rescheduled",
|
|
55
65
|
ACTIVITY_OUTCOME_RECORDED: "crm:activity.outcome_recorded",
|
|
66
|
+
SUPPRESSION_ADDED: "crm:suppression.added",
|
|
67
|
+
SUPPRESSION_REMOVED: "crm:suppression.removed",
|
|
56
68
|
CONVERSATION_CREATED: "crm:conversation.created",
|
|
57
69
|
CONVERSATION_ASSIGNED: "crm:conversation.assigned",
|
|
58
70
|
CONVERSATION_RESOLVED: "crm:conversation.resolved",
|
|
@@ -60,6 +72,11 @@ const CRM_EVENTS = {
|
|
|
60
72
|
MESSAGE_RECEIVED: "crm:message.received",
|
|
61
73
|
MESSAGE_SENT: "crm:message.sent"
|
|
62
74
|
};
|
|
75
|
+
const SUPPRESSION_REASONS = [...[
|
|
76
|
+
"bounce",
|
|
77
|
+
"complaint",
|
|
78
|
+
"unsubscribe"
|
|
79
|
+
], "manual"];
|
|
63
80
|
//#endregion
|
|
64
81
|
//#region src/events/event-catalog.ts
|
|
65
82
|
/**
|
|
@@ -498,6 +515,22 @@ const SubscriptionComplained = defineCrmEvent({
|
|
|
498
515
|
campaignId: z.string()
|
|
499
516
|
})
|
|
500
517
|
});
|
|
518
|
+
const SuppressionAdded = defineCrmEvent({
|
|
519
|
+
name: CRM_EVENTS.SUPPRESSION_ADDED,
|
|
520
|
+
resource: "suppression",
|
|
521
|
+
description: "suppress() inserted a NEW row on the org-wide suppression list (idempotent re-suppress of an existing email emits nothing). organizationId rides event meta.",
|
|
522
|
+
zodSchema: z.object({
|
|
523
|
+
email: z.string(),
|
|
524
|
+
reason: z.enum(SUPPRESSION_REASONS),
|
|
525
|
+
source: z.string().optional()
|
|
526
|
+
})
|
|
527
|
+
});
|
|
528
|
+
const SuppressionRemoved = defineCrmEvent({
|
|
529
|
+
name: CRM_EVENTS.SUPPRESSION_REMOVED,
|
|
530
|
+
resource: "suppression",
|
|
531
|
+
description: "unsuppress() removed an email from the org-wide suppression list.",
|
|
532
|
+
zodSchema: z.object({ email: z.string() })
|
|
533
|
+
});
|
|
501
534
|
const emailEventSchema = z.object({
|
|
502
535
|
eventId: z.string(),
|
|
503
536
|
kind: z.string(),
|
|
@@ -598,6 +631,82 @@ const MessageSent = defineCrmEvent({
|
|
|
598
631
|
externalMessageId: z.string().optional()
|
|
599
632
|
})
|
|
600
633
|
});
|
|
634
|
+
const SequenceCreated = defineCrmEvent({
|
|
635
|
+
name: CRM_EVENTS.SEQUENCE_CREATED,
|
|
636
|
+
resource: "sequence",
|
|
637
|
+
description: "A sequence draft was created. Emitted by the HOST after repo.create() (the package ships no createSequence verb) — defined here so registries validate the payload.",
|
|
638
|
+
zodSchema: z.object({
|
|
639
|
+
sequenceId: z.string(),
|
|
640
|
+
name: z.string().optional()
|
|
641
|
+
})
|
|
642
|
+
});
|
|
643
|
+
const SequenceActivated = defineCrmEvent({
|
|
644
|
+
name: CRM_EVENTS.SEQUENCE_ACTIVATED,
|
|
645
|
+
resource: "sequence",
|
|
646
|
+
description: "activate() moved a sequence draft/paused → active.",
|
|
647
|
+
zodSchema: z.object({ sequenceId: z.string() })
|
|
648
|
+
});
|
|
649
|
+
const SequencePaused = defineCrmEvent({
|
|
650
|
+
name: CRM_EVENTS.SEQUENCE_PAUSED,
|
|
651
|
+
resource: "sequence",
|
|
652
|
+
description: "pause() suspended an active sequence (existing enrollments hold).",
|
|
653
|
+
zodSchema: z.object({ sequenceId: z.string() })
|
|
654
|
+
});
|
|
655
|
+
const SequenceArchived = defineCrmEvent({
|
|
656
|
+
name: CRM_EVENTS.SEQUENCE_ARCHIVED,
|
|
657
|
+
resource: "sequence",
|
|
658
|
+
description: "archive() retired a sequence — no new enrollments.",
|
|
659
|
+
zodSchema: z.object({ sequenceId: z.string() })
|
|
660
|
+
});
|
|
661
|
+
const EnrollmentCreated = defineCrmEvent({
|
|
662
|
+
name: CRM_EVENTS.ENROLLMENT_CREATED,
|
|
663
|
+
resource: "enrollment",
|
|
664
|
+
description: "enroll() attached a subject to a sequence.",
|
|
665
|
+
zodSchema: z.object({
|
|
666
|
+
enrollmentId: z.string(),
|
|
667
|
+
sequenceId: z.string(),
|
|
668
|
+
subjectId: z.string(),
|
|
669
|
+
subjectKind: z.string()
|
|
670
|
+
})
|
|
671
|
+
});
|
|
672
|
+
const EnrollmentStepSent = defineCrmEvent({
|
|
673
|
+
name: CRM_EVENTS.ENROLLMENT_STEP_SENT,
|
|
674
|
+
resource: "enrollment",
|
|
675
|
+
description: "A sequence step was delivered. Emitted by the HOST outreach layer after its send adapter succeeds + advanceStep() commits (Buffer-style pattern in CLAUDE.md) — defined here so registries validate the payload.",
|
|
676
|
+
zodSchema: z.object({
|
|
677
|
+
enrollmentId: z.string(),
|
|
678
|
+
sequenceId: z.string().optional(),
|
|
679
|
+
stepIndex: z.number(),
|
|
680
|
+
channel: z.string().optional()
|
|
681
|
+
})
|
|
682
|
+
});
|
|
683
|
+
const EnrollmentPaused = defineCrmEvent({
|
|
684
|
+
name: CRM_EVENTS.ENROLLMENT_PAUSED,
|
|
685
|
+
resource: "enrollment",
|
|
686
|
+
description: "pause() held an active enrollment.",
|
|
687
|
+
zodSchema: z.object({ enrollmentId: z.string() })
|
|
688
|
+
});
|
|
689
|
+
const EnrollmentResumed = defineCrmEvent({
|
|
690
|
+
name: CRM_EVENTS.ENROLLMENT_RESUMED,
|
|
691
|
+
resource: "enrollment",
|
|
692
|
+
description: "resume() reactivated a paused enrollment.",
|
|
693
|
+
zodSchema: z.object({ enrollmentId: z.string() })
|
|
694
|
+
});
|
|
695
|
+
const EnrollmentCompleted = defineCrmEvent({
|
|
696
|
+
name: CRM_EVENTS.ENROLLMENT_COMPLETED,
|
|
697
|
+
resource: "enrollment",
|
|
698
|
+
description: "complete() finished the final step of an enrollment.",
|
|
699
|
+
zodSchema: z.object({ enrollmentId: z.string() })
|
|
700
|
+
});
|
|
701
|
+
const EnrollmentExited = defineCrmEvent({
|
|
702
|
+
name: CRM_EVENTS.ENROLLMENT_EXITED,
|
|
703
|
+
resource: "enrollment",
|
|
704
|
+
description: "exit() removed a subject before completion (reply/unsubscribe/manual/goal).",
|
|
705
|
+
zodSchema: z.object({
|
|
706
|
+
enrollmentId: z.string(),
|
|
707
|
+
exitReason: z.string().optional()
|
|
708
|
+
})
|
|
709
|
+
});
|
|
601
710
|
const crmEventDefinitions = [
|
|
602
711
|
LeadCreated,
|
|
603
712
|
LeadStatusChanged,
|
|
@@ -644,6 +753,8 @@ const crmEventDefinitions = [
|
|
|
644
753
|
SubscriptionUnsubscribed,
|
|
645
754
|
SubscriptionBounced,
|
|
646
755
|
SubscriptionComplained,
|
|
756
|
+
SuppressionAdded,
|
|
757
|
+
SuppressionRemoved,
|
|
647
758
|
EmailEventOpened,
|
|
648
759
|
EmailEventClicked,
|
|
649
760
|
EmailEventBounced,
|
|
@@ -654,7 +765,17 @@ const crmEventDefinitions = [
|
|
|
654
765
|
ConversationResolved,
|
|
655
766
|
ConversationReopened,
|
|
656
767
|
MessageReceived,
|
|
657
|
-
MessageSent
|
|
768
|
+
MessageSent,
|
|
769
|
+
SequenceCreated,
|
|
770
|
+
SequenceActivated,
|
|
771
|
+
SequencePaused,
|
|
772
|
+
SequenceArchived,
|
|
773
|
+
EnrollmentCreated,
|
|
774
|
+
EnrollmentStepSent,
|
|
775
|
+
EnrollmentPaused,
|
|
776
|
+
EnrollmentResumed,
|
|
777
|
+
EnrollmentCompleted,
|
|
778
|
+
EnrollmentExited
|
|
658
779
|
];
|
|
659
780
|
//#endregion
|
|
660
781
|
//#region src/events/helpers.ts
|
|
@@ -713,4 +834,4 @@ var InProcessCrmBus = class {
|
|
|
713
834
|
}
|
|
714
835
|
};
|
|
715
836
|
//#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 };
|
|
837
|
+
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, EnrollmentCompleted, EnrollmentCreated, EnrollmentExited, EnrollmentPaused, EnrollmentResumed, EnrollmentStepSent, InProcessCrmBus, LeadAssigned, LeadConverted, LeadCreated, LeadDisqualified, LeadEnriched, LeadScored, LeadStatusChanged, MessageReceived, MessageSent, NoteAdded, OpportunityAbandoned, OpportunityAmountChanged, OpportunityAssigned, OpportunityCreated, OpportunityExtended, OpportunityLost, OpportunityStageAdvanced, OpportunityStageRegressed, OpportunityWon, PipelineArchived, PipelineCreated, SequenceActivated, SequenceArchived, SequenceCreated, SequencePaused, SubscriptionBounced, SubscriptionComplained, SubscriptionConfirmed, SubscriptionCreated, SubscriptionUnsubscribed, SuppressionAdded, SuppressionRemoved, createEvent, crmEventDefinitions };
|