@headless-lms/core 0.2.0 → 0.4.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/assets/events.d.ts +42 -24
- package/dist/assets/events.js +1 -1
- package/dist/assets/events.js.map +1 -1
- package/dist/assets/file-urls.d.ts +20 -0
- package/dist/assets/file-urls.js +25 -0
- package/dist/assets/file-urls.js.map +1 -0
- package/dist/assets/index.d.ts +6 -4
- package/dist/assets/index.js +4 -2
- package/dist/assets/jobs.d.ts +15 -0
- package/dist/assets/jobs.js +30 -0
- package/dist/assets/jobs.js.map +1 -0
- package/dist/assets/model.d.ts +2 -2
- package/dist/assets/ports.d.ts +46 -15
- package/dist/assets/service.d.ts +38 -7
- package/dist/assets/service.js +287 -38
- package/dist/assets/service.js.map +1 -1
- package/dist/automations/actions.d.ts +13 -24
- package/dist/automations/actions.js +106 -42
- package/dist/automations/actions.js.map +1 -1
- package/dist/automations/catalog.js +226 -3
- package/dist/automations/catalog.js.map +1 -1
- package/dist/automations/community-derivations.d.ts +14 -0
- package/dist/automations/community-derivations.js +439 -0
- package/dist/automations/community-derivations.js.map +1 -0
- package/dist/automations/community-mail.d.ts +98 -0
- package/dist/automations/community-mail.js +70 -0
- package/dist/automations/community-mail.js.map +1 -0
- package/dist/automations/events.d.ts +18 -0
- package/dist/automations/index.d.ts +13 -4
- package/dist/automations/index.js +10 -2
- package/dist/automations/model.d.ts +10 -3
- package/dist/automations/model.js +15 -2
- package/dist/automations/model.js.map +1 -1
- package/dist/automations/notifications/debounce.d.ts +25 -0
- package/dist/automations/notifications/debounce.js +93 -0
- package/dist/automations/notifications/debounce.js.map +1 -0
- package/dist/automations/notifications/defaults.d.ts +8 -0
- package/dist/automations/notifications/defaults.js +316 -0
- package/dist/automations/notifications/defaults.js.map +1 -0
- package/dist/automations/notifications/delivery.d.ts +28 -0
- package/dist/automations/notifications/delivery.js +88 -0
- package/dist/automations/notifications/delivery.js.map +1 -0
- package/dist/automations/notifications/processor.d.ts +64 -0
- package/dist/automations/notifications/processor.js +270 -0
- package/dist/automations/notifications/processor.js.map +1 -0
- package/dist/automations/notifications/rules/content.d.ts +6 -0
- package/dist/automations/notifications/rules/content.js +39 -0
- package/dist/automations/notifications/rules/content.js.map +1 -0
- package/dist/automations/notifications/rules/discussion.d.ts +7 -0
- package/dist/automations/notifications/rules/discussion.js +678 -0
- package/dist/automations/notifications/rules/discussion.js.map +1 -0
- package/dist/automations/notifications/rules/entitlements.d.ts +6 -0
- package/dist/automations/notifications/rules/entitlements.js +249 -0
- package/dist/automations/notifications/rules/entitlements.js.map +1 -0
- package/dist/automations/notifications/rules/index.d.ts +6 -0
- package/dist/automations/notifications/rules/index.js +15 -0
- package/dist/automations/notifications/rules/index.js.map +1 -0
- package/dist/automations/notifications/rules/organizations.d.ts +6 -0
- package/dist/automations/notifications/rules/organizations.js +28 -0
- package/dist/automations/notifications/rules/organizations.js.map +1 -0
- package/dist/automations/notifications/rules/recipients.d.ts +32 -0
- package/dist/automations/notifications/rules/recipients.js +99 -0
- package/dist/automations/notifications/rules/recipients.js.map +1 -0
- package/dist/automations/notifications/service.d.ts +27 -0
- package/dist/automations/notifications/service.js +45 -0
- package/dist/automations/notifications/service.js.map +1 -0
- package/dist/automations/notifications/types.d.ts +7 -0
- package/dist/automations/notifications/types.js +473 -0
- package/dist/automations/notifications/types.js.map +1 -0
- package/dist/automations/ports.d.ts +121 -3
- package/dist/automations/schedule.d.ts +6 -0
- package/dist/automations/schedule.js +41 -0
- package/dist/automations/schedule.js.map +1 -0
- package/dist/automations/service.d.ts +20 -4
- package/dist/automations/service.js +246 -45
- package/dist/automations/service.js.map +1 -1
- package/dist/content/events.d.ts +712 -50
- package/dist/content/events.js +55 -1
- package/dist/content/events.js.map +1 -1
- package/dist/content/index.d.ts +6 -4
- package/dist/content/index.js +3 -1
- package/dist/content/model.d.ts +2 -2
- package/dist/content/notification-categories.d.ts +36 -0
- package/dist/content/notification-categories.js +64 -0
- package/dist/content/notification-categories.js.map +1 -0
- package/dist/content/ports.d.ts +90 -18
- package/dist/content/service.d.ts +57 -18
- package/dist/content/service.js +520 -25
- package/dist/content/service.js.map +1 -1
- package/dist/content/titles.d.ts +22 -0
- package/dist/content/titles.js +69 -0
- package/dist/content/titles.js.map +1 -0
- package/dist/content/types.d.ts +2 -2
- package/dist/discussion/authors.d.ts +10 -0
- package/dist/discussion/authors.js +23 -0
- package/dist/discussion/authors.js.map +1 -0
- package/dist/discussion/chats.d.ts +109 -0
- package/dist/discussion/chats.js +831 -0
- package/dist/discussion/chats.js.map +1 -0
- package/dist/discussion/digests.d.ts +24 -0
- package/dist/discussion/digests.js +104 -0
- package/dist/discussion/digests.js.map +1 -0
- package/dist/discussion/events.d.ts +785 -56
- package/dist/discussion/events.js +165 -5
- package/dist/discussion/events.js.map +1 -1
- package/dist/discussion/index.d.ts +12 -3
- package/dist/discussion/index.js +9 -1
- package/dist/discussion/jobs.d.ts +16 -0
- package/dist/discussion/jobs.js +40 -0
- package/dist/discussion/jobs.js.map +1 -0
- package/dist/discussion/mentions.d.ts +11 -0
- package/dist/discussion/mentions.js +35 -0
- package/dist/discussion/mentions.js.map +1 -0
- package/dist/discussion/ports.d.ts +372 -28
- package/dist/discussion/ports.js +6 -1
- package/dist/discussion/ports.js.map +1 -0
- package/dist/discussion/posts.d.ts +113 -0
- package/dist/discussion/posts.js +775 -0
- package/dist/discussion/posts.js.map +1 -0
- package/dist/discussion/service.d.ts +42 -11
- package/dist/discussion/service.js +364 -85
- package/dist/discussion/service.js.map +1 -1
- package/dist/discussion/subscriptions.d.ts +37 -0
- package/dist/discussion/subscriptions.js +99 -0
- package/dist/discussion/subscriptions.js.map +1 -0
- package/dist/discussion/titles.d.ts +26 -0
- package/dist/discussion/titles.js +84 -0
- package/dist/discussion/titles.js.map +1 -0
- package/dist/entitlements/events.d.ts +178 -11
- package/dist/entitlements/events.js +28 -1
- package/dist/entitlements/events.js.map +1 -1
- package/dist/entitlements/index.d.ts +6 -4
- package/dist/entitlements/index.js +3 -1
- package/dist/entitlements/jobs.d.ts +12 -0
- package/dist/entitlements/jobs.js +18 -0
- package/dist/entitlements/jobs.js.map +1 -0
- package/dist/entitlements/model.d.ts +3 -2
- package/dist/entitlements/ports.d.ts +128 -11
- package/dist/entitlements/rules.d.ts +12 -0
- package/dist/entitlements/rules.js +17 -0
- package/dist/entitlements/rules.js.map +1 -0
- package/dist/entitlements/service.d.ts +57 -3
- package/dist/entitlements/service.js +492 -2
- package/dist/entitlements/service.js.map +1 -1
- package/dist/identity/access.d.ts +6 -0
- package/dist/identity/access.js +7 -0
- package/dist/identity/access.js.map +1 -0
- package/dist/identity/devices.d.ts +30 -0
- package/dist/identity/devices.js +107 -0
- package/dist/identity/devices.js.map +1 -0
- package/dist/identity/events.d.ts +2 -2
- package/dist/identity/index.d.ts +7 -4
- package/dist/identity/index.js +4 -1
- package/dist/identity/model.d.ts +2 -1
- package/dist/identity/notification-settings.d.ts +28 -0
- package/dist/identity/notification-settings.js +113 -0
- package/dist/identity/notification-settings.js.map +1 -0
- package/dist/identity/ports.d.ts +97 -3
- package/dist/identity/service.d.ts +14 -3
- package/dist/identity/service.js +62 -5
- package/dist/identity/service.js.map +1 -1
- package/dist/integrations/events.d.ts +3 -3
- package/dist/integrations/model.js +1 -1
- package/dist/integrations/model.js.map +1 -1
- package/dist/integrations/service.js +2 -2
- package/dist/integrations/service.js.map +1 -1
- package/dist/organizations/access-scopes.d.ts +19 -0
- package/dist/organizations/access-scopes.js +89 -0
- package/dist/organizations/access-scopes.js.map +1 -0
- package/dist/organizations/events.d.ts +75 -33
- package/dist/organizations/events.js +6 -0
- package/dist/organizations/events.js.map +1 -1
- package/dist/organizations/index.d.ts +8 -6
- package/dist/organizations/index.js +5 -3
- package/dist/organizations/members.d.ts +8 -5
- package/dist/organizations/members.js.map +1 -1
- package/dist/organizations/notification-categories.d.ts +32 -0
- package/dist/organizations/notification-categories.js +51 -0
- package/dist/organizations/notification-categories.js.map +1 -0
- package/dist/organizations/ports.d.ts +17 -11
- package/dist/organizations/roles.d.ts +6 -10
- package/dist/organizations/roles.js +19 -7
- package/dist/organizations/roles.js.map +1 -1
- package/dist/organizations/service.d.ts +22 -11
- package/dist/organizations/service.js +164 -47
- package/dist/organizations/service.js.map +1 -1
- package/dist/organizations/types.d.ts +1 -10
- package/dist/progress/events.d.ts +14 -14
- package/dist/progress/index.d.ts +2 -2
- package/dist/progress/ports.d.ts +6 -1
- package/dist/progress/service.d.ts +3 -1
- package/dist/progress/service.js +6 -2
- package/dist/progress/service.js.map +1 -1
- package/dist/reporting/admin/index.d.ts +4 -0
- package/dist/reporting/admin/index.js +2 -0
- package/dist/reporting/admin/model.d.ts +108 -0
- package/dist/reporting/admin/ports.d.ts +27 -0
- package/dist/reporting/admin/service.d.ts +22 -0
- package/dist/reporting/admin/service.js +38 -0
- package/dist/reporting/admin/service.js.map +1 -0
- package/dist/reporting/member/index.d.ts +5 -0
- package/dist/reporting/member/index.js +2 -0
- package/dist/reporting/member/model.d.ts +157 -0
- package/dist/reporting/member/ports.d.ts +48 -0
- package/dist/reporting/member/service.d.ts +92 -0
- package/dist/reporting/member/service.js +364 -0
- package/dist/reporting/member/service.js.map +1 -0
- package/dist/shared/actor.d.ts +9 -0
- package/dist/shared/errors.d.ts +19 -1
- package/dist/shared/errors.js +27 -1
- package/dist/shared/errors.js.map +1 -1
- package/dist/shared/id.d.ts +14 -0
- package/dist/shared/id.js +15 -1
- package/dist/shared/id.js.map +1 -1
- package/dist/shared/mailer.d.ts +15 -2
- package/dist/shared/mailer.js +32 -5
- package/dist/shared/mailer.js.map +1 -1
- package/dist/shared/network.d.ts +10 -0
- package/dist/shared/network.js +211 -0
- package/dist/shared/network.js.map +1 -0
- package/dist/shared/notification-categories.d.ts +16 -0
- package/dist/shared/notification-categories.js +94 -0
- package/dist/shared/notification-categories.js.map +1 -0
- package/dist/shared/notification-settings.d.ts +14 -0
- package/dist/shared/notification-settings.js +61 -0
- package/dist/shared/notification-settings.js.map +1 -0
- package/dist/shared/ports.d.ts +48 -2
- package/dist/shared/settings.d.ts +2 -1
- package/dist/shared/settings.js +1 -0
- package/dist/shared/settings.js.map +1 -1
- package/dist/types/assets.d.ts +2 -2
- package/dist/types/automations.d.ts +15 -1
- package/dist/types/content.d.ts +2 -2
- package/dist/types/discussion.d.ts +11 -3
- package/dist/types/email-templates.d.ts +216 -1
- package/dist/types/entitlements.d.ts +2 -2
- package/dist/types/identity.d.ts +48 -2
- package/dist/types/index.d.ts +9 -8
- package/dist/types/notifications.d.ts +157 -0
- package/dist/types/ports.d.ts +6 -0
- package/dist/types/schemas/assets.d.ts +65 -37
- package/dist/types/schemas/assets.js +17 -12
- package/dist/types/schemas/assets.js.map +1 -1
- package/dist/types/schemas/automations.d.ts +9 -1
- package/dist/types/schemas/automations.js +13 -6
- package/dist/types/schemas/automations.js.map +1 -1
- package/dist/types/schemas/content.d.ts +396 -3
- package/dist/types/schemas/content.js +161 -3
- package/dist/types/schemas/content.js.map +1 -1
- package/dist/types/schemas/discussion.d.ts +443 -3
- package/dist/types/schemas/discussion.js +233 -4
- package/dist/types/schemas/discussion.js.map +1 -1
- package/dist/types/schemas/entitlements.d.ts +36 -2
- package/dist/types/schemas/entitlements.js +23 -1
- package/dist/types/schemas/entitlements.js.map +1 -1
- package/dist/types/schemas/identity.d.ts +27 -1
- package/dist/types/schemas/identity.js +14 -2
- package/dist/types/schemas/identity.js.map +1 -1
- package/dist/types/schemas/index.d.ts +9 -8
- package/dist/types/schemas/index.js +9 -8
- package/dist/types/schemas/notifications.d.ts +95 -0
- package/dist/types/schemas/notifications.js +56 -0
- package/dist/types/schemas/notifications.js.map +1 -0
- package/dist/types/schemas/organizations.d.ts +8 -0
- package/dist/types/schemas/organizations.js +2 -0
- package/dist/types/schemas/organizations.js.map +1 -1
- package/dist/types/schemas/progress.d.ts +3 -3
- package/dist/types/schemas/shared.d.ts +3 -1
- package/dist/types/schemas/shared.js +5 -1
- package/dist/types/schemas/shared.js.map +1 -1
- package/package.json +2 -2
- package/dist/reporting/courses/index.d.ts +0 -4
- package/dist/reporting/courses/index.js +0 -2
- package/dist/reporting/courses/model.d.ts +0 -24
- package/dist/reporting/courses/ports.d.ts +0 -13
- package/dist/reporting/courses/service.d.ts +0 -19
- package/dist/reporting/courses/service.js +0 -20
- package/dist/reporting/courses/service.js.map +0 -1
- package/dist/reporting/dashboard/index.d.ts +0 -4
- package/dist/reporting/dashboard/index.js +0 -2
- package/dist/reporting/dashboard/model.d.ts +0 -14
- package/dist/reporting/dashboard/ports.d.ts +0 -13
- package/dist/reporting/dashboard/service.d.ts +0 -19
- package/dist/reporting/dashboard/service.js +0 -20
- package/dist/reporting/dashboard/service.js.map +0 -1
- package/dist/reporting/learn/index.d.ts +0 -5
- package/dist/reporting/learn/index.js +0 -2
- package/dist/reporting/learn/model.d.ts +0 -23
- package/dist/reporting/learn/ports.d.ts +0 -43
- package/dist/reporting/learn/service.d.ts +0 -49
- package/dist/reporting/learn/service.js +0 -116
- package/dist/reporting/learn/service.js.map +0 -1
- package/dist/reporting/students/index.d.ts +0 -4
- package/dist/reporting/students/index.js +0 -2
- package/dist/reporting/students/model.d.ts +0 -51
- package/dist/reporting/students/model.js +0 -1
- package/dist/reporting/students/ports.d.ts +0 -15
- package/dist/reporting/students/ports.js +0 -1
- package/dist/reporting/students/service.d.ts +0 -20
- package/dist/reporting/students/service.js +0 -23
- package/dist/reporting/students/service.js.map +0 -1
- /package/dist/reporting/{courses → admin}/model.js +0 -0
- /package/dist/reporting/{courses → admin}/ports.js +0 -0
- /package/dist/reporting/{dashboard → member}/model.js +0 -0
- /package/dist/reporting/{dashboard → member}/ports.js +0 -0
- /package/dist/{reporting/learn/model.js → shared/actor.js} +0 -0
- /package/dist/{reporting/learn/ports.js → types/notifications.js} +0 -0
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
import { organizationEvents } from "../organizations/events.js";
|
|
2
|
+
import { entitlementEvents } from "../entitlements/events.js";
|
|
3
|
+
import { discussionEvents } from "../discussion/events.js";
|
|
4
|
+
import { MESSAGE_BATCH_MS, actorOf, address, excerpt, previousStatusOf } from "./community-mail.js";
|
|
5
|
+
//#region src/automations/community-derivations.ts
|
|
6
|
+
function silence(triggers) {
|
|
7
|
+
return {
|
|
8
|
+
triggers,
|
|
9
|
+
derive: async () => []
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
function seatsLeft(capacity, active) {
|
|
13
|
+
if (capacity == null) return "No cap";
|
|
14
|
+
return String(Math.max(capacity - active, 0));
|
|
15
|
+
}
|
|
16
|
+
function muted(participant, at) {
|
|
17
|
+
return participant.muted && (participant.mutedUntil === null || participant.mutedUntil.getTime() > at.getTime());
|
|
18
|
+
}
|
|
19
|
+
function chatStatusOf(event) {
|
|
20
|
+
const value = event.metadata?.chatStatus;
|
|
21
|
+
return typeof value === "string" ? value : void 0;
|
|
22
|
+
}
|
|
23
|
+
async function communityTitle(deps, orgId, communityId) {
|
|
24
|
+
return deps.mail.communityTitle(orgId, communityId);
|
|
25
|
+
}
|
|
26
|
+
const COMMUNITY_DERIVATIONS = {
|
|
27
|
+
welcomeToCommunity: {
|
|
28
|
+
triggers: ["entitlement.created"],
|
|
29
|
+
derive: async (event, deps) => {
|
|
30
|
+
const parsed = entitlementEvents.entitlementCreated.safeParse(event);
|
|
31
|
+
if (!parsed.success) return;
|
|
32
|
+
const grant = parsed.data.data;
|
|
33
|
+
const communityIds = await deps.mail.communitiesOpenedBy(event.orgId, {
|
|
34
|
+
contentId: grant.contentId,
|
|
35
|
+
bundleId: grant.bundleId
|
|
36
|
+
});
|
|
37
|
+
const recipients = [];
|
|
38
|
+
for (const communityId of communityIds) {
|
|
39
|
+
const title = await communityTitle(deps, event.orgId, communityId);
|
|
40
|
+
if (!title) return;
|
|
41
|
+
const spaceNames = await deps.mail.openSpaceNames(event.orgId, grant.orgUserId, communityId);
|
|
42
|
+
const addressed = await address(deps, event, event.orgId, [grant.orgUserId], {
|
|
43
|
+
communityTitle: title,
|
|
44
|
+
communityId,
|
|
45
|
+
spaceNames
|
|
46
|
+
});
|
|
47
|
+
if (!addressed) return;
|
|
48
|
+
recipients.push(...addressed);
|
|
49
|
+
}
|
|
50
|
+
return recipients;
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
membershipEndingSoon: {
|
|
54
|
+
triggers: ["entitlement.ending_soon"],
|
|
55
|
+
derive: async (event, deps) => {
|
|
56
|
+
const parsed = entitlementEvents.entitlementEndingSoon.safeParse(event);
|
|
57
|
+
if (!parsed.success) return;
|
|
58
|
+
const grant = parsed.data.data;
|
|
59
|
+
const communityId = grant.communityId;
|
|
60
|
+
const title = await communityTitle(deps, event.orgId, communityId);
|
|
61
|
+
if (!title) return;
|
|
62
|
+
return address(deps, event, event.orgId, [grant.orgUserId], {
|
|
63
|
+
communityTitle: title,
|
|
64
|
+
communityId,
|
|
65
|
+
expiresAt: grant.expiresAt ? grant.expiresAt.toISOString() : ""
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
membershipEnded: {
|
|
70
|
+
triggers: ["entitlement.expired", "entitlement.deleted"],
|
|
71
|
+
derive: async (event, deps) => {
|
|
72
|
+
const parsed = event.type === "entitlement.expired" ? entitlementEvents.entitlementExpired.safeParse(event) : entitlementEvents.entitlementDeleted.safeParse(event);
|
|
73
|
+
if (!parsed.success) return;
|
|
74
|
+
const grant = parsed.data.data;
|
|
75
|
+
const communityIds = await deps.mail.communitiesOpenedBy(event.orgId, {
|
|
76
|
+
contentId: grant.contentId,
|
|
77
|
+
bundleId: grant.bundleId
|
|
78
|
+
});
|
|
79
|
+
const recipients = [];
|
|
80
|
+
for (const communityId of communityIds) {
|
|
81
|
+
const title = await communityTitle(deps, event.orgId, communityId);
|
|
82
|
+
if (!title) return;
|
|
83
|
+
const addressed = await address(deps, event, event.orgId, [grant.orgUserId], { communities: [{
|
|
84
|
+
communityId,
|
|
85
|
+
communityTitle: title
|
|
86
|
+
}] });
|
|
87
|
+
if (!addressed) return;
|
|
88
|
+
recipients.push(...addressed);
|
|
89
|
+
}
|
|
90
|
+
return recipients;
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
newPostInSpace: {
|
|
94
|
+
triggers: ["discussion.post.published"],
|
|
95
|
+
derive: async (event, deps) => {
|
|
96
|
+
const parsed = discussionEvents.postPublished.safeParse(event);
|
|
97
|
+
if (!parsed.success) return;
|
|
98
|
+
const post = parsed.data.data;
|
|
99
|
+
const space = await deps.mail.space(event.orgId, post.spaceId);
|
|
100
|
+
if (!space) return;
|
|
101
|
+
const openers = await deps.mail.spaceOpeners(event.orgId, post.spaceId);
|
|
102
|
+
return address(deps, event, event.orgId, openers.filter((id) => id !== post.orgUserId), {
|
|
103
|
+
spaceName: space.name,
|
|
104
|
+
postTitle: post.title,
|
|
105
|
+
authorName: await deps.mail.displayName(event.orgId, post.orgUserId),
|
|
106
|
+
excerpt: excerpt(post.body || post.title, 280),
|
|
107
|
+
postId: post.id,
|
|
108
|
+
communityId: post.communityId
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
yourPostWasPublished: {
|
|
113
|
+
triggers: ["discussion.post.published"],
|
|
114
|
+
derive: async (event, deps) => {
|
|
115
|
+
if (previousStatusOf(event) !== "pending") return [];
|
|
116
|
+
const parsed = discussionEvents.postPublished.safeParse(event);
|
|
117
|
+
if (!parsed.success) return;
|
|
118
|
+
const post = parsed.data.data;
|
|
119
|
+
const space = await deps.mail.space(event.orgId, post.spaceId);
|
|
120
|
+
if (!space) return;
|
|
121
|
+
return address(deps, event, event.orgId, [post.orgUserId], {
|
|
122
|
+
postTitle: post.title,
|
|
123
|
+
spaceName: space.name,
|
|
124
|
+
postId: post.id,
|
|
125
|
+
communityId: post.communityId
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
yourPostWasRemoved: {
|
|
130
|
+
triggers: ["discussion.post.removed"],
|
|
131
|
+
derive: async (event, deps) => {
|
|
132
|
+
const parsed = discussionEvents.postRemoved.safeParse(event);
|
|
133
|
+
if (!parsed.success) return;
|
|
134
|
+
const post = parsed.data.data;
|
|
135
|
+
if (post.removedBy === post.orgUserId) return [];
|
|
136
|
+
const space = await deps.mail.space(event.orgId, post.spaceId);
|
|
137
|
+
if (!space) return;
|
|
138
|
+
return address(deps, event, event.orgId, [post.orgUserId], {
|
|
139
|
+
postTitle: post.title,
|
|
140
|
+
spaceName: space.name,
|
|
141
|
+
spaceId: post.spaceId,
|
|
142
|
+
communityId: post.communityId
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
newCommentOnPost: {
|
|
147
|
+
triggers: ["discussion.comment.created"],
|
|
148
|
+
derive: async (event, deps) => {
|
|
149
|
+
const parsed = discussionEvents.commentCreated.safeParse(event);
|
|
150
|
+
if (!parsed.success) return;
|
|
151
|
+
const comment = parsed.data.data;
|
|
152
|
+
if (!comment.postId || comment.status !== "published" || !comment.communityId) return [];
|
|
153
|
+
const post = await deps.mail.post(event.orgId, comment.postId);
|
|
154
|
+
if (!post) return;
|
|
155
|
+
const followers = await deps.mail.followerIds(event.orgId, comment.postId);
|
|
156
|
+
const ids = [.../* @__PURE__ */ new Set([...followers, post.orgUserId])].filter((id) => id !== comment.orgUserId);
|
|
157
|
+
const openers = await deps.mail.spaceOpenersAmong(event.orgId, post.spaceId, ids);
|
|
158
|
+
return address(deps, event, event.orgId, openers, {
|
|
159
|
+
postTitle: post.title,
|
|
160
|
+
commenterName: await deps.mail.displayName(event.orgId, comment.orgUserId),
|
|
161
|
+
excerpt: excerpt(comment.body, 280),
|
|
162
|
+
commentId: comment.id,
|
|
163
|
+
postId: comment.postId,
|
|
164
|
+
communityId: comment.communityId
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
replyToYourComment: {
|
|
169
|
+
triggers: ["discussion.comment.created"],
|
|
170
|
+
derive: async (event, deps) => {
|
|
171
|
+
const parsed = discussionEvents.commentCreated.safeParse(event);
|
|
172
|
+
if (!parsed.success) return;
|
|
173
|
+
const comment = parsed.data.data;
|
|
174
|
+
if (!comment.parentId || !comment.postId || comment.status !== "published") return [];
|
|
175
|
+
const parent = await deps.mail.comment(event.orgId, comment.parentId);
|
|
176
|
+
const post = await deps.mail.post(event.orgId, comment.postId);
|
|
177
|
+
if (!parent || !post || !comment.communityId) return parent && post ? [] : void 0;
|
|
178
|
+
if (parent.orgUserId === comment.orgUserId) return [];
|
|
179
|
+
const openers = await deps.mail.spaceOpenersAmong(event.orgId, post.spaceId, [parent.orgUserId]);
|
|
180
|
+
return address(deps, event, event.orgId, openers, {
|
|
181
|
+
postTitle: post.title,
|
|
182
|
+
commenterName: await deps.mail.displayName(event.orgId, comment.orgUserId),
|
|
183
|
+
excerpt: excerpt(comment.body, 280),
|
|
184
|
+
commentId: comment.id,
|
|
185
|
+
postId: comment.postId,
|
|
186
|
+
communityId: comment.communityId
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
yourCommentWasRemoved: {
|
|
191
|
+
triggers: ["discussion.comment.removed"],
|
|
192
|
+
derive: async (event, deps) => {
|
|
193
|
+
const parsed = discussionEvents.commentRemoved.safeParse(event);
|
|
194
|
+
if (!parsed.success) return;
|
|
195
|
+
const comment = parsed.data.data;
|
|
196
|
+
if (!comment.postId || !comment.communityId) return [];
|
|
197
|
+
if (comment.removedBy === comment.orgUserId) return [];
|
|
198
|
+
const post = await deps.mail.post(event.orgId, comment.postId);
|
|
199
|
+
if (!post) return;
|
|
200
|
+
return address(deps, event, event.orgId, [comment.orgUserId], {
|
|
201
|
+
postTitle: post.title,
|
|
202
|
+
postId: comment.postId,
|
|
203
|
+
communityId: comment.communityId
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
postAwaitingReview: {
|
|
208
|
+
triggers: ["discussion.post.created", "discussion.post.updated"],
|
|
209
|
+
derive: async (event, deps) => {
|
|
210
|
+
const parsed = event.type === "discussion.post.created" ? discussionEvents.postCreated.safeParse(event) : discussionEvents.postUpdated.safeParse(event);
|
|
211
|
+
if (!parsed.success) return;
|
|
212
|
+
const post = parsed.data.data;
|
|
213
|
+
if (post.status !== "pending" || previousStatusOf(event) === "pending") return [];
|
|
214
|
+
const space = await deps.mail.space(event.orgId, post.spaceId);
|
|
215
|
+
if (!space) return;
|
|
216
|
+
const audience = await deps.mail.moderationAudience(event.orgId, post.communityId);
|
|
217
|
+
return address(deps, event, event.orgId, audience, {
|
|
218
|
+
spaceName: space.name,
|
|
219
|
+
postTitle: post.title,
|
|
220
|
+
authorName: await deps.mail.displayName(event.orgId, post.orgUserId),
|
|
221
|
+
spaceId: post.spaceId,
|
|
222
|
+
communityId: post.communityId
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
joinRequest: {
|
|
227
|
+
triggers: ["entitlement.space_member.created"],
|
|
228
|
+
derive: async (event, deps) => {
|
|
229
|
+
const parsed = entitlementEvents.spaceMemberCreated.safeParse(event);
|
|
230
|
+
if (!parsed.success) return;
|
|
231
|
+
const member = parsed.data.data;
|
|
232
|
+
if (member.status !== "requested") return [];
|
|
233
|
+
const space = await deps.mail.space(event.orgId, member.spaceId);
|
|
234
|
+
if (!space) return;
|
|
235
|
+
const active = await deps.mail.activeMemberCount(event.orgId, member.spaceId);
|
|
236
|
+
const audience = await deps.mail.moderationAudience(event.orgId, member.communityId);
|
|
237
|
+
return address(deps, event, event.orgId, audience, {
|
|
238
|
+
spaceName: space.name,
|
|
239
|
+
memberName: await deps.mail.displayName(event.orgId, member.orgUserId),
|
|
240
|
+
seatsLeft: seatsLeft(space.capacity, active),
|
|
241
|
+
spaceId: member.spaceId,
|
|
242
|
+
communityId: member.communityId
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
requestApproved: {
|
|
247
|
+
triggers: ["entitlement.space_member.updated"],
|
|
248
|
+
derive: async (event, deps) => {
|
|
249
|
+
const parsed = entitlementEvents.spaceMemberUpdated.safeParse(event);
|
|
250
|
+
if (!parsed.success) return;
|
|
251
|
+
const member = parsed.data.data;
|
|
252
|
+
if (member.status !== "active" || previousStatusOf(event) !== "requested") return [];
|
|
253
|
+
const space = await deps.mail.space(event.orgId, member.spaceId);
|
|
254
|
+
if (!space) return;
|
|
255
|
+
return address(deps, event, event.orgId, [member.orgUserId], {
|
|
256
|
+
spaceName: space.name,
|
|
257
|
+
spaceId: member.spaceId,
|
|
258
|
+
communityId: member.communityId
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
},
|
|
262
|
+
requestDeclined: {
|
|
263
|
+
triggers: ["entitlement.space_member.deleted"],
|
|
264
|
+
derive: async (event, deps) => {
|
|
265
|
+
if (previousStatusOf(event) !== "requested") return [];
|
|
266
|
+
const parsed = entitlementEvents.spaceMemberDeleted.safeParse(event);
|
|
267
|
+
if (!parsed.success) return;
|
|
268
|
+
const member = parsed.data.data;
|
|
269
|
+
const space = await deps.mail.space(event.orgId, member.spaceId);
|
|
270
|
+
if (!space) return;
|
|
271
|
+
return address(deps, event, event.orgId, [member.orgUserId], {
|
|
272
|
+
spaceName: space.name,
|
|
273
|
+
communityId: member.communityId
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
},
|
|
277
|
+
invitedToSpace: {
|
|
278
|
+
triggers: ["entitlement.space_member.created"],
|
|
279
|
+
derive: async (event, deps) => {
|
|
280
|
+
const parsed = entitlementEvents.spaceMemberCreated.safeParse(event);
|
|
281
|
+
if (!parsed.success) return;
|
|
282
|
+
const member = parsed.data.data;
|
|
283
|
+
if (member.status !== "invited") return [];
|
|
284
|
+
const space = await deps.mail.space(event.orgId, member.spaceId);
|
|
285
|
+
if (!space) return;
|
|
286
|
+
const actor = actorOf(event);
|
|
287
|
+
return address(deps, event, event.orgId, [member.orgUserId], {
|
|
288
|
+
spaceName: space.name,
|
|
289
|
+
inviterName: actor ? await deps.mail.displayName(event.orgId, actor) : "A member",
|
|
290
|
+
spaceId: member.spaceId,
|
|
291
|
+
communityId: member.communityId
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
},
|
|
295
|
+
messageRequest: {
|
|
296
|
+
triggers: ["discussion.chat.created"],
|
|
297
|
+
derive: async (event, deps) => {
|
|
298
|
+
const parsed = discussionEvents.chatCreated.safeParse(event);
|
|
299
|
+
if (!parsed.success) return;
|
|
300
|
+
const chat = parsed.data.data;
|
|
301
|
+
if (chat.kind !== "direct" || chat.status !== "pending") return [];
|
|
302
|
+
const recipient = chat.participantIds.find((id) => id !== chat.createdBy);
|
|
303
|
+
if (!recipient) return [];
|
|
304
|
+
const members = await deps.mail.communityMembersAmong(event.orgId, chat.communityId, [recipient]);
|
|
305
|
+
const body = await deps.mail.latestMessageBody(event.orgId, chat.id);
|
|
306
|
+
return address(deps, event, event.orgId, members, {
|
|
307
|
+
senderName: chat.createdBy ? await deps.mail.displayName(event.orgId, chat.createdBy) : "A member",
|
|
308
|
+
excerpt: excerpt(body ?? "", 140),
|
|
309
|
+
chatId: chat.id,
|
|
310
|
+
communityId: chat.communityId
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
},
|
|
314
|
+
newMessage: {
|
|
315
|
+
triggers: ["discussion.message.sent"],
|
|
316
|
+
derive: async (event, deps) => {
|
|
317
|
+
const parsed = discussionEvents.messageSent.safeParse(event);
|
|
318
|
+
if (!parsed.success) return;
|
|
319
|
+
const message = parsed.data.data;
|
|
320
|
+
const chat = await deps.mail.chat(event.orgId, message.chatId);
|
|
321
|
+
if (!chat) return;
|
|
322
|
+
if (chatStatusOf(event) === "pending") return [];
|
|
323
|
+
const at = new Date(event.occurredAt);
|
|
324
|
+
const since = new Date(at.getTime() - MESSAGE_BATCH_MS);
|
|
325
|
+
const recent = new Set(await deps.mail.recentMessageRecipients(event.orgId, deps.automationId, message.chatId, since));
|
|
326
|
+
const ids = [];
|
|
327
|
+
for (const participant of chat.participants) {
|
|
328
|
+
if (participant.leftAt || participant.orgUserId === message.orgUserId) continue;
|
|
329
|
+
if (muted(participant, at) || recent.has(participant.orgUserId)) continue;
|
|
330
|
+
if (await deps.mail.pairBlocked(event.orgId, chat.communityId, message.orgUserId, participant.orgUserId)) continue;
|
|
331
|
+
ids.push(participant.orgUserId);
|
|
332
|
+
}
|
|
333
|
+
const members = await deps.mail.communityMembersAmong(event.orgId, chat.communityId, ids);
|
|
334
|
+
const title = chat.kind === "direct" ? await deps.mail.displayName(event.orgId, message.orgUserId) : await groupTitle(deps, event.orgId, chat.participants);
|
|
335
|
+
return address(deps, event, event.orgId, members, {
|
|
336
|
+
senderName: await deps.mail.displayName(event.orgId, message.orgUserId),
|
|
337
|
+
chatTitle: title,
|
|
338
|
+
excerpt: excerpt(message.body, 140),
|
|
339
|
+
chatId: message.chatId,
|
|
340
|
+
communityId: message.communityId
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
},
|
|
344
|
+
addedToGroupChat: {
|
|
345
|
+
triggers: ["discussion.chat.participant.added"],
|
|
346
|
+
derive: async (event, deps) => {
|
|
347
|
+
const parsed = discussionEvents.chatParticipantAdded.safeParse(event);
|
|
348
|
+
if (!parsed.success) return;
|
|
349
|
+
const added = parsed.data.data;
|
|
350
|
+
const chat = await deps.mail.chat(event.orgId, added.chatId);
|
|
351
|
+
if (!chat) return;
|
|
352
|
+
return address(deps, event, event.orgId, [added.orgUserId], {
|
|
353
|
+
adderName: await deps.mail.displayName(event.orgId, added.addedBy),
|
|
354
|
+
participantNames: await participantNames(deps, event.orgId, chat.participants),
|
|
355
|
+
chatId: added.chatId,
|
|
356
|
+
communityId: added.communityId
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
},
|
|
360
|
+
youAreNowAModerator: {
|
|
361
|
+
triggers: ["organization.user.updated"],
|
|
362
|
+
derive: async (event, deps) => {
|
|
363
|
+
const parsed = organizationEvents.orgUserUpdated.safeParse(event);
|
|
364
|
+
if (!parsed.success) return;
|
|
365
|
+
const orgUser = parsed.data.data;
|
|
366
|
+
if (orgUser.role !== "moderator") return [];
|
|
367
|
+
const communities = await deps.mail.memberCommunityTitles(event.orgId, orgUser.id);
|
|
368
|
+
return address(deps, event, event.orgId, [orgUser.id], { communityTitles: communities.map((community) => community.title) });
|
|
369
|
+
}
|
|
370
|
+
},
|
|
371
|
+
digest: silence(["discussion.digest.due"]),
|
|
372
|
+
somethingWasFlagged: {
|
|
373
|
+
triggers: ["discussion.post.reported", "discussion.comment.reported"],
|
|
374
|
+
derive: async (event, deps) => {
|
|
375
|
+
if (event.type === "discussion.post.reported") {
|
|
376
|
+
const parsed = discussionEvents.postReported.safeParse(event);
|
|
377
|
+
if (!parsed.success) return;
|
|
378
|
+
const flag = parsed.data.data;
|
|
379
|
+
const post = await deps.mail.post(event.orgId, flag.postId);
|
|
380
|
+
const space = post ? await deps.mail.space(event.orgId, post.spaceId) : null;
|
|
381
|
+
if (!post || !space) return;
|
|
382
|
+
const audience = await deps.mail.moderationAudience(event.orgId, flag.communityId);
|
|
383
|
+
return address(deps, event, event.orgId, audience, {
|
|
384
|
+
spaceName: space.name,
|
|
385
|
+
excerpt: excerpt(post.body || post.title, 280),
|
|
386
|
+
reason: flag.reason,
|
|
387
|
+
spaceId: post.spaceId,
|
|
388
|
+
communityId: flag.communityId
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
const parsed = discussionEvents.commentReported.safeParse(event);
|
|
392
|
+
if (!parsed.success) return;
|
|
393
|
+
const flag = parsed.data.data;
|
|
394
|
+
if (!flag.communityId) return [];
|
|
395
|
+
const comment = await deps.mail.comment(event.orgId, flag.commentId);
|
|
396
|
+
if (!comment?.postId) return comment ? [] : void 0;
|
|
397
|
+
const post = await deps.mail.post(event.orgId, comment.postId);
|
|
398
|
+
const space = post ? await deps.mail.space(event.orgId, post.spaceId) : null;
|
|
399
|
+
if (!post || !space) return;
|
|
400
|
+
const audience = await deps.mail.moderationAudience(event.orgId, flag.communityId);
|
|
401
|
+
return address(deps, event, event.orgId, audience, {
|
|
402
|
+
spaceName: space.name,
|
|
403
|
+
excerpt: excerpt(comment.body, 280),
|
|
404
|
+
reason: flag.reason,
|
|
405
|
+
spaceId: post.spaceId,
|
|
406
|
+
communityId: flag.communityId
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
},
|
|
410
|
+
messageWasFlagged: {
|
|
411
|
+
triggers: ["discussion.message.reported"],
|
|
412
|
+
derive: async (event, deps) => {
|
|
413
|
+
const parsed = discussionEvents.messageReported.safeParse(event);
|
|
414
|
+
if (!parsed.success) return;
|
|
415
|
+
const flag = parsed.data.data;
|
|
416
|
+
const audience = await deps.mail.staffIds(event.orgId);
|
|
417
|
+
return address(deps, event, event.orgId, audience, {
|
|
418
|
+
reason: flag.reason,
|
|
419
|
+
communityId: flag.communityId
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
};
|
|
424
|
+
async function participantNames(deps, orgId, participants) {
|
|
425
|
+
const names = [];
|
|
426
|
+
for (const participant of participants) {
|
|
427
|
+
if (participant.leftAt) continue;
|
|
428
|
+
names.push(await deps.mail.displayName(orgId, participant.orgUserId));
|
|
429
|
+
}
|
|
430
|
+
return names;
|
|
431
|
+
}
|
|
432
|
+
async function groupTitle(deps, orgId, participants) {
|
|
433
|
+
const names = await participantNames(deps, orgId, participants);
|
|
434
|
+
return names.length > 0 ? names.join(", ") : "Group chat";
|
|
435
|
+
}
|
|
436
|
+
//#endregion
|
|
437
|
+
export { COMMUNITY_DERIVATIONS };
|
|
438
|
+
|
|
439
|
+
//# sourceMappingURL=community-derivations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"community-derivations.js","names":[],"sources":["../../src/automations/community-derivations.ts"],"sourcesContent":["import { discussionEvents } from '../discussion/index.js';\nimport { entitlementEvents } from '../entitlements/index.js';\nimport { organizationEvents } from '../organizations/index.js';\nimport type { EmailTemplateId } from '../types/index.js';\nimport type { DomainEvent } from '../shared/ports.js';\nimport {\n actorOf,\n address,\n excerpt,\n MESSAGE_BATCH_MS,\n MESSAGE_EXCERPT,\n POST_EXCERPT,\n previousStatusOf,\n type ActionDeps,\n type EmailRecipient,\n} from './community-mail.js';\n\nexport interface EmailDerivation<K extends EmailTemplateId> {\n triggers: readonly string[];\n derive(event: DomainEvent, deps: ActionDeps): Promise<EmailRecipient<K>[] | undefined>;\n}\n\nfunction silence<K extends EmailTemplateId>(triggers: readonly string[]): EmailDerivation<K> {\n return { triggers, derive: async () => [] };\n}\n\nfunction seatsLeft(capacity: number | null, active: number): string {\n if (capacity == null) {\n return 'No cap';\n }\n return String(Math.max(capacity - active, 0));\n}\n\nfunction muted(participant: { muted: boolean; mutedUntil: Date | null }, at: Date): boolean {\n return (\n participant.muted &&\n (participant.mutedUntil === null || participant.mutedUntil.getTime() > at.getTime())\n );\n}\n\nfunction chatStatusOf(event: DomainEvent): string | undefined {\n const value = event.metadata?.chatStatus;\n return typeof value === 'string' ? value : undefined;\n}\n\nasync function communityTitle(deps: ActionDeps, orgId: string, communityId: string) {\n return deps.mail.communityTitle(orgId, communityId);\n}\n\nexport const COMMUNITY_DERIVATIONS: {\n [K in EmailTemplateId]?: EmailDerivation<K>;\n} = {\n welcomeToCommunity: {\n triggers: ['entitlement.created'],\n derive: async (event, deps) => {\n const parsed = entitlementEvents.entitlementCreated.safeParse(event);\n if (!parsed.success) {\n return undefined;\n }\n const grant = parsed.data.data;\n const communityIds = await deps.mail.communitiesOpenedBy(event.orgId, {\n contentId: grant.contentId,\n bundleId: grant.bundleId,\n });\n const recipients: EmailRecipient<'welcomeToCommunity'>[] = [];\n for (const communityId of communityIds) {\n const title = await communityTitle(deps, event.orgId, communityId);\n if (!title) {\n return undefined;\n }\n const spaceNames = await deps.mail.openSpaceNames(\n event.orgId,\n grant.orgUserId,\n communityId,\n );\n const addressed = await address<'welcomeToCommunity'>(\n deps,\n event,\n event.orgId,\n [grant.orgUserId],\n { communityTitle: title, communityId, spaceNames },\n );\n if (!addressed) {\n return undefined;\n }\n recipients.push(...addressed);\n }\n return recipients;\n },\n },\n membershipEndingSoon: {\n triggers: ['entitlement.ending_soon'],\n derive: async (event, deps) => {\n const parsed = entitlementEvents.entitlementEndingSoon.safeParse(event);\n if (!parsed.success) {\n return undefined;\n }\n const grant = parsed.data.data;\n const communityId = grant.communityId;\n const title = await communityTitle(deps, event.orgId, communityId);\n if (!title) {\n return undefined;\n }\n return address(deps, event, event.orgId, [grant.orgUserId], {\n communityTitle: title,\n communityId,\n expiresAt: grant.expiresAt ? grant.expiresAt.toISOString() : '',\n });\n },\n },\n membershipEnded: {\n triggers: ['entitlement.expired', 'entitlement.deleted'],\n derive: async (event, deps) => {\n const parsed =\n event.type === 'entitlement.expired'\n ? entitlementEvents.entitlementExpired.safeParse(event)\n : entitlementEvents.entitlementDeleted.safeParse(event);\n if (!parsed.success) {\n return undefined;\n }\n const grant = parsed.data.data;\n const communityIds = await deps.mail.communitiesOpenedBy(event.orgId, {\n contentId: grant.contentId,\n bundleId: grant.bundleId,\n });\n const recipients: EmailRecipient<'membershipEnded'>[] = [];\n for (const communityId of communityIds) {\n const title = await communityTitle(deps, event.orgId, communityId);\n if (!title) {\n return undefined;\n }\n const addressed = await address<'membershipEnded'>(\n deps,\n event,\n event.orgId,\n [grant.orgUserId],\n { communities: [{ communityId, communityTitle: title }] },\n );\n if (!addressed) {\n return undefined;\n }\n recipients.push(...addressed);\n }\n return recipients;\n },\n },\n newPostInSpace: {\n triggers: ['discussion.post.published'],\n derive: async (event, deps) => {\n const parsed = discussionEvents.postPublished.safeParse(event);\n if (!parsed.success) {\n return undefined;\n }\n const post = parsed.data.data;\n const space = await deps.mail.space(event.orgId, post.spaceId);\n if (!space) {\n return undefined;\n }\n const openers = await deps.mail.spaceOpeners(event.orgId, post.spaceId);\n return address(\n deps,\n event,\n event.orgId,\n openers.filter((id) => id !== post.orgUserId),\n {\n spaceName: space.name,\n postTitle: post.title,\n authorName: await deps.mail.displayName(event.orgId, post.orgUserId),\n excerpt: excerpt(post.body || post.title, POST_EXCERPT),\n postId: post.id,\n communityId: post.communityId,\n },\n );\n },\n },\n yourPostWasPublished: {\n triggers: ['discussion.post.published'],\n derive: async (event, deps) => {\n if (previousStatusOf(event) !== 'pending') {\n return [];\n }\n const parsed = discussionEvents.postPublished.safeParse(event);\n if (!parsed.success) {\n return undefined;\n }\n const post = parsed.data.data;\n const space = await deps.mail.space(event.orgId, post.spaceId);\n if (!space) {\n return undefined;\n }\n return address(deps, event, event.orgId, [post.orgUserId], {\n postTitle: post.title,\n spaceName: space.name,\n postId: post.id,\n communityId: post.communityId,\n });\n },\n },\n yourPostWasRemoved: {\n triggers: ['discussion.post.removed'],\n derive: async (event, deps) => {\n const parsed = discussionEvents.postRemoved.safeParse(event);\n if (!parsed.success) {\n return undefined;\n }\n const post = parsed.data.data;\n if (post.removedBy === post.orgUserId) {\n return [];\n }\n const space = await deps.mail.space(event.orgId, post.spaceId);\n if (!space) {\n return undefined;\n }\n return address(deps, event, event.orgId, [post.orgUserId], {\n postTitle: post.title,\n spaceName: space.name,\n spaceId: post.spaceId,\n communityId: post.communityId,\n });\n },\n },\n newCommentOnPost: {\n triggers: ['discussion.comment.created'],\n derive: async (event, deps) => {\n const parsed = discussionEvents.commentCreated.safeParse(event);\n if (!parsed.success) {\n return undefined;\n }\n const comment = parsed.data.data;\n if (!comment.postId || comment.status !== 'published' || !comment.communityId) {\n return [];\n }\n const post = await deps.mail.post(event.orgId, comment.postId);\n if (!post) {\n return undefined;\n }\n const followers = await deps.mail.followerIds(event.orgId, comment.postId);\n const ids = [...new Set([...followers, post.orgUserId])].filter(\n (id) => id !== comment.orgUserId,\n );\n const openers = await deps.mail.spaceOpenersAmong(event.orgId, post.spaceId, ids);\n return address(deps, event, event.orgId, openers, {\n postTitle: post.title,\n commenterName: await deps.mail.displayName(event.orgId, comment.orgUserId),\n excerpt: excerpt(comment.body, POST_EXCERPT),\n commentId: comment.id,\n postId: comment.postId,\n communityId: comment.communityId,\n });\n },\n },\n replyToYourComment: {\n triggers: ['discussion.comment.created'],\n derive: async (event, deps) => {\n const parsed = discussionEvents.commentCreated.safeParse(event);\n if (!parsed.success) {\n return undefined;\n }\n const comment = parsed.data.data;\n if (!comment.parentId || !comment.postId || comment.status !== 'published') {\n return [];\n }\n const parent = await deps.mail.comment(event.orgId, comment.parentId);\n const post = await deps.mail.post(event.orgId, comment.postId);\n if (!parent || !post || !comment.communityId) {\n return parent && post ? [] : undefined;\n }\n if (parent.orgUserId === comment.orgUserId) {\n return [];\n }\n const openers = await deps.mail.spaceOpenersAmong(event.orgId, post.spaceId, [\n parent.orgUserId,\n ]);\n return address(deps, event, event.orgId, openers, {\n postTitle: post.title,\n commenterName: await deps.mail.displayName(event.orgId, comment.orgUserId),\n excerpt: excerpt(comment.body, POST_EXCERPT),\n commentId: comment.id,\n postId: comment.postId,\n communityId: comment.communityId,\n });\n },\n },\n yourCommentWasRemoved: {\n triggers: ['discussion.comment.removed'],\n derive: async (event, deps) => {\n const parsed = discussionEvents.commentRemoved.safeParse(event);\n if (!parsed.success) {\n return undefined;\n }\n const comment = parsed.data.data;\n if (!comment.postId || !comment.communityId) {\n return [];\n }\n if (comment.removedBy === comment.orgUserId) {\n return [];\n }\n const post = await deps.mail.post(event.orgId, comment.postId);\n if (!post) {\n return undefined;\n }\n return address(deps, event, event.orgId, [comment.orgUserId], {\n postTitle: post.title,\n postId: comment.postId,\n communityId: comment.communityId,\n });\n },\n },\n postAwaitingReview: {\n triggers: ['discussion.post.created', 'discussion.post.updated'],\n derive: async (event, deps) => {\n const parsed =\n event.type === 'discussion.post.created'\n ? discussionEvents.postCreated.safeParse(event)\n : discussionEvents.postUpdated.safeParse(event);\n if (!parsed.success) {\n return undefined;\n }\n const post = parsed.data.data;\n if (post.status !== 'pending' || previousStatusOf(event) === 'pending') {\n return [];\n }\n const space = await deps.mail.space(event.orgId, post.spaceId);\n if (!space) {\n return undefined;\n }\n const audience = await deps.mail.moderationAudience(event.orgId, post.communityId);\n return address(deps, event, event.orgId, audience, {\n spaceName: space.name,\n postTitle: post.title,\n authorName: await deps.mail.displayName(event.orgId, post.orgUserId),\n spaceId: post.spaceId,\n communityId: post.communityId,\n });\n },\n },\n joinRequest: {\n triggers: ['entitlement.space_member.created'],\n derive: async (event, deps) => {\n const parsed = entitlementEvents.spaceMemberCreated.safeParse(event);\n if (!parsed.success) {\n return undefined;\n }\n const member = parsed.data.data;\n if (member.status !== 'requested') {\n return [];\n }\n const space = await deps.mail.space(event.orgId, member.spaceId);\n if (!space) {\n return undefined;\n }\n const active = await deps.mail.activeMemberCount(event.orgId, member.spaceId);\n const audience = await deps.mail.moderationAudience(event.orgId, member.communityId);\n return address(deps, event, event.orgId, audience, {\n spaceName: space.name,\n memberName: await deps.mail.displayName(event.orgId, member.orgUserId),\n seatsLeft: seatsLeft(space.capacity, active),\n spaceId: member.spaceId,\n communityId: member.communityId,\n });\n },\n },\n requestApproved: {\n triggers: ['entitlement.space_member.updated'],\n derive: async (event, deps) => {\n const parsed = entitlementEvents.spaceMemberUpdated.safeParse(event);\n if (!parsed.success) {\n return undefined;\n }\n const member = parsed.data.data;\n if (member.status !== 'active' || previousStatusOf(event) !== 'requested') {\n return [];\n }\n const space = await deps.mail.space(event.orgId, member.spaceId);\n if (!space) {\n return undefined;\n }\n return address(deps, event, event.orgId, [member.orgUserId], {\n spaceName: space.name,\n spaceId: member.spaceId,\n communityId: member.communityId,\n });\n },\n },\n requestDeclined: {\n triggers: ['entitlement.space_member.deleted'],\n derive: async (event, deps) => {\n if (previousStatusOf(event) !== 'requested') {\n return [];\n }\n const parsed = entitlementEvents.spaceMemberDeleted.safeParse(event);\n if (!parsed.success) {\n return undefined;\n }\n const member = parsed.data.data;\n const space = await deps.mail.space(event.orgId, member.spaceId);\n if (!space) {\n return undefined;\n }\n return address(deps, event, event.orgId, [member.orgUserId], {\n spaceName: space.name,\n communityId: member.communityId,\n });\n },\n },\n invitedToSpace: {\n triggers: ['entitlement.space_member.created'],\n derive: async (event, deps) => {\n const parsed = entitlementEvents.spaceMemberCreated.safeParse(event);\n if (!parsed.success) {\n return undefined;\n }\n const member = parsed.data.data;\n if (member.status !== 'invited') {\n return [];\n }\n const space = await deps.mail.space(event.orgId, member.spaceId);\n if (!space) {\n return undefined;\n }\n const actor = actorOf(event);\n return address(deps, event, event.orgId, [member.orgUserId], {\n spaceName: space.name,\n inviterName: actor ? await deps.mail.displayName(event.orgId, actor) : 'A member',\n spaceId: member.spaceId,\n communityId: member.communityId,\n });\n },\n },\n messageRequest: {\n triggers: ['discussion.chat.created'],\n derive: async (event, deps) => {\n const parsed = discussionEvents.chatCreated.safeParse(event);\n if (!parsed.success) {\n return undefined;\n }\n const chat = parsed.data.data;\n if (chat.kind !== 'direct' || chat.status !== 'pending') {\n return [];\n }\n const recipient = chat.participantIds.find((id) => id !== chat.createdBy);\n if (!recipient) {\n return [];\n }\n const members = await deps.mail.communityMembersAmong(event.orgId, chat.communityId, [\n recipient,\n ]);\n const body = await deps.mail.latestMessageBody(event.orgId, chat.id);\n return address(deps, event, event.orgId, members, {\n senderName: chat.createdBy\n ? await deps.mail.displayName(event.orgId, chat.createdBy)\n : 'A member',\n excerpt: excerpt(body ?? '', MESSAGE_EXCERPT),\n chatId: chat.id,\n communityId: chat.communityId,\n });\n },\n },\n newMessage: {\n triggers: ['discussion.message.sent'],\n derive: async (event, deps) => {\n const parsed = discussionEvents.messageSent.safeParse(event);\n if (!parsed.success) {\n return undefined;\n }\n const message = parsed.data.data;\n const chat = await deps.mail.chat(event.orgId, message.chatId);\n if (!chat) {\n return undefined;\n }\n if (chatStatusOf(event) === 'pending') {\n return [];\n }\n const at = new Date(event.occurredAt);\n const since = new Date(at.getTime() - MESSAGE_BATCH_MS);\n const recent = new Set(\n await deps.mail.recentMessageRecipients(\n event.orgId,\n deps.automationId,\n message.chatId,\n since,\n ),\n );\n const ids: string[] = [];\n for (const participant of chat.participants) {\n if (participant.leftAt || participant.orgUserId === message.orgUserId) {\n continue;\n }\n if (muted(participant, at) || recent.has(participant.orgUserId)) {\n continue;\n }\n if (\n await deps.mail.pairBlocked(\n event.orgId,\n chat.communityId,\n message.orgUserId,\n participant.orgUserId,\n )\n ) {\n continue;\n }\n ids.push(participant.orgUserId);\n }\n const members = await deps.mail.communityMembersAmong(event.orgId, chat.communityId, ids);\n const title =\n chat.kind === 'direct'\n ? await deps.mail.displayName(event.orgId, message.orgUserId)\n : await groupTitle(deps, event.orgId, chat.participants);\n return address(deps, event, event.orgId, members, {\n senderName: await deps.mail.displayName(event.orgId, message.orgUserId),\n chatTitle: title,\n excerpt: excerpt(message.body, MESSAGE_EXCERPT),\n chatId: message.chatId,\n communityId: message.communityId,\n });\n },\n },\n addedToGroupChat: {\n triggers: ['discussion.chat.participant.added'],\n derive: async (event, deps) => {\n const parsed = discussionEvents.chatParticipantAdded.safeParse(event);\n if (!parsed.success) {\n return undefined;\n }\n const added = parsed.data.data;\n const chat = await deps.mail.chat(event.orgId, added.chatId);\n if (!chat) {\n return undefined;\n }\n return address(deps, event, event.orgId, [added.orgUserId], {\n adderName: await deps.mail.displayName(event.orgId, added.addedBy),\n participantNames: await participantNames(deps, event.orgId, chat.participants),\n chatId: added.chatId,\n communityId: added.communityId,\n });\n },\n },\n youAreNowAModerator: {\n triggers: ['organization.user.updated'],\n derive: async (event, deps) => {\n const parsed = organizationEvents.orgUserUpdated.safeParse(event);\n if (!parsed.success) {\n return undefined;\n }\n const orgUser = parsed.data.data;\n if (orgUser.role !== 'moderator') {\n return [];\n }\n const communities = await deps.mail.memberCommunityTitles(event.orgId, orgUser.id);\n return address(deps, event, event.orgId, [orgUser.id], {\n communityTitles: communities.map((community) => community.title),\n });\n },\n },\n digest: silence(['discussion.digest.due']),\n somethingWasFlagged: {\n triggers: ['discussion.post.reported', 'discussion.comment.reported'],\n derive: async (event, deps) => {\n if (event.type === 'discussion.post.reported') {\n const parsed = discussionEvents.postReported.safeParse(event);\n if (!parsed.success) {\n return undefined;\n }\n const flag = parsed.data.data;\n const post = await deps.mail.post(event.orgId, flag.postId);\n const space = post ? await deps.mail.space(event.orgId, post.spaceId) : null;\n if (!post || !space) {\n return undefined;\n }\n const audience = await deps.mail.moderationAudience(event.orgId, flag.communityId);\n return address(deps, event, event.orgId, audience, {\n spaceName: space.name,\n excerpt: excerpt(post.body || post.title, POST_EXCERPT),\n reason: flag.reason,\n spaceId: post.spaceId,\n communityId: flag.communityId,\n });\n }\n const parsed = discussionEvents.commentReported.safeParse(event);\n if (!parsed.success) {\n return undefined;\n }\n const flag = parsed.data.data;\n if (!flag.communityId) {\n return [];\n }\n const comment = await deps.mail.comment(event.orgId, flag.commentId);\n if (!comment?.postId) {\n return comment ? [] : undefined;\n }\n const post = await deps.mail.post(event.orgId, comment.postId);\n const space = post ? await deps.mail.space(event.orgId, post.spaceId) : null;\n if (!post || !space) {\n return undefined;\n }\n const audience = await deps.mail.moderationAudience(event.orgId, flag.communityId);\n return address(deps, event, event.orgId, audience, {\n spaceName: space.name,\n excerpt: excerpt(comment.body, POST_EXCERPT),\n reason: flag.reason,\n spaceId: post.spaceId,\n communityId: flag.communityId,\n });\n },\n },\n messageWasFlagged: {\n triggers: ['discussion.message.reported'],\n derive: async (event, deps) => {\n const parsed = discussionEvents.messageReported.safeParse(event);\n if (!parsed.success) {\n return undefined;\n }\n const flag = parsed.data.data;\n const audience = await deps.mail.staffIds(event.orgId);\n return address(deps, event, event.orgId, audience, {\n reason: flag.reason,\n communityId: flag.communityId,\n });\n },\n },\n};\n\nasync function participantNames(\n deps: ActionDeps,\n orgId: string,\n participants: { orgUserId: string; leftAt: Date | null }[],\n): Promise<string[]> {\n const names: string[] = [];\n for (const participant of participants) {\n if (participant.leftAt) {\n continue;\n }\n names.push(await deps.mail.displayName(orgId, participant.orgUserId));\n }\n return names;\n}\n\nasync function groupTitle(\n deps: ActionDeps,\n orgId: string,\n participants: { orgUserId: string; leftAt: Date | null }[],\n): Promise<string> {\n const names = await participantNames(deps, orgId, participants);\n return names.length > 0 ? names.join(', ') : 'Group chat';\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { DomainEvent, JsonValue } from "../types/shared.js";
|
|
2
|
+
import { Logger } from "../types/ports.js";
|
|
3
|
+
import { EmailTemplateId, EmailTemplateParams } from "../types/email-templates.js";
|
|
4
|
+
import { GrantEntitlementInput } from "../types/schemas/entitlements.js";
|
|
5
|
+
import { WebhookSender } from "../types/automations.js";
|
|
6
|
+
import { ChatStatus } from "../types/schemas/discussion.js";
|
|
7
|
+
import "../types/index.js";
|
|
8
|
+
import { CredentialStore } from "../shared/ports.js";
|
|
9
|
+
import { Mailer, MailerLookups } from "../shared/mailer.js";
|
|
10
|
+
import "../entitlements/index.js";
|
|
11
|
+
import "./ports.js";
|
|
12
|
+
//#region src/automations/community-mail.d.ts
|
|
13
|
+
declare const MESSAGE_EXCERPT = 140;
|
|
14
|
+
declare const POST_EXCERPT = 280;
|
|
15
|
+
declare const MESSAGE_BATCH_MS: number;
|
|
16
|
+
interface EmailRecipient<K extends EmailTemplateId = EmailTemplateId> {
|
|
17
|
+
to: string;
|
|
18
|
+
orgUserId: string;
|
|
19
|
+
userId: string;
|
|
20
|
+
params: EmailTemplateParams[K];
|
|
21
|
+
}
|
|
22
|
+
interface CommunityMailReads {
|
|
23
|
+
communityTitle(orgId: string, communityId: string): Promise<string | null>;
|
|
24
|
+
space(orgId: string, spaceId: string): Promise<{
|
|
25
|
+
name: string;
|
|
26
|
+
communityId: string;
|
|
27
|
+
capacity: number | null;
|
|
28
|
+
} | null>;
|
|
29
|
+
openSpaceNames(orgId: string, orgUserId: string, communityId: string): Promise<string[]>;
|
|
30
|
+
communitiesOpenedBy(orgId: string, grant: {
|
|
31
|
+
contentId: string | null;
|
|
32
|
+
bundleId: string | null;
|
|
33
|
+
}): Promise<string[]>;
|
|
34
|
+
communityMembersAmong(orgId: string, communityId: string, ids: string[]): Promise<string[]>;
|
|
35
|
+
spaceOpenersAmong(orgId: string, spaceId: string, ids: string[]): Promise<string[]>;
|
|
36
|
+
spaceOpeners(orgId: string, spaceId: string): Promise<string[]>;
|
|
37
|
+
moderationAudience(orgId: string, communityId: string): Promise<string[]>;
|
|
38
|
+
staffIds(orgId: string): Promise<string[]>;
|
|
39
|
+
displayName(orgId: string, orgUserId: string): Promise<string>;
|
|
40
|
+
followerIds(orgId: string, postId: string): Promise<string[]>;
|
|
41
|
+
comment(orgId: string, commentId: string): Promise<{
|
|
42
|
+
orgUserId: string;
|
|
43
|
+
postId: string | null;
|
|
44
|
+
activityId: string | null;
|
|
45
|
+
parentId: string | null;
|
|
46
|
+
body: string;
|
|
47
|
+
} | null>;
|
|
48
|
+
post(orgId: string, postId: string): Promise<{
|
|
49
|
+
title: string;
|
|
50
|
+
body: string;
|
|
51
|
+
spaceId: string;
|
|
52
|
+
orgUserId: string;
|
|
53
|
+
communityId: string;
|
|
54
|
+
} | null>;
|
|
55
|
+
chat(orgId: string, chatId: string): Promise<{
|
|
56
|
+
communityId: string;
|
|
57
|
+
kind: 'direct' | 'group';
|
|
58
|
+
status: ChatStatus;
|
|
59
|
+
createdBy: string | null;
|
|
60
|
+
participants: {
|
|
61
|
+
orgUserId: string;
|
|
62
|
+
muted: boolean;
|
|
63
|
+
mutedUntil: Date | null;
|
|
64
|
+
leftAt: Date | null;
|
|
65
|
+
}[];
|
|
66
|
+
} | null>;
|
|
67
|
+
latestMessageBody(orgId: string, chatId: string): Promise<string | null>;
|
|
68
|
+
pairBlocked(orgId: string, communityId: string, a: string, b: string): Promise<boolean>;
|
|
69
|
+
activeMemberCount(orgId: string, spaceId: string): Promise<number>;
|
|
70
|
+
memberCommunityTitles(orgId: string, orgUserId: string): Promise<{
|
|
71
|
+
id: string;
|
|
72
|
+
title: string;
|
|
73
|
+
}[]>;
|
|
74
|
+
recentMessageRecipients(orgId: string, automationId: string, chatId: string, since: Date): Promise<string[]>;
|
|
75
|
+
}
|
|
76
|
+
interface GrantWriter {
|
|
77
|
+
grant(orgId: string, input: GrantEntitlementInput): Promise<unknown>;
|
|
78
|
+
}
|
|
79
|
+
interface ActionDeps {
|
|
80
|
+
mailer: Pick<Mailer, 'send'>;
|
|
81
|
+
lookups: MailerLookups;
|
|
82
|
+
credentials: Pick<CredentialStore, 'reveal'>;
|
|
83
|
+
webhooks: WebhookSender;
|
|
84
|
+
mail: CommunityMailReads;
|
|
85
|
+
grants: GrantWriter;
|
|
86
|
+
automationId: string;
|
|
87
|
+
actionInput: Record<string, JsonValue>;
|
|
88
|
+
logger?: Logger;
|
|
89
|
+
}
|
|
90
|
+
declare const emptyCommunityMail: CommunityMailReads;
|
|
91
|
+
declare function actorOf(event: DomainEvent): string | undefined;
|
|
92
|
+
declare function previousStatusOf(event: DomainEvent): string | undefined;
|
|
93
|
+
declare function excerpt(value: string, max: number): string;
|
|
94
|
+
declare function seededCommunityId(deps: ActionDeps): string | null;
|
|
95
|
+
declare function address<K extends EmailTemplateId>(deps: ActionDeps, event: DomainEvent, orgId: string, orgUserIds: string[], params: EmailTemplateParams[K]): Promise<EmailRecipient<K>[] | undefined>;
|
|
96
|
+
//#endregion
|
|
97
|
+
export { ActionDeps, CommunityMailReads, EmailRecipient, GrantWriter, MESSAGE_BATCH_MS, MESSAGE_EXCERPT, POST_EXCERPT, actorOf, address, emptyCommunityMail, excerpt, previousStatusOf, seededCommunityId };
|
|
98
|
+
//# sourceMappingURL=community-mail.d.ts.map
|