@headless-lms/server 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -0
- package/dist/app/community-mail.d.ts +5 -3
- package/dist/app/community-mail.js +60 -12
- package/dist/app/community-mail.js.map +1 -1
- package/dist/app/container.d.ts +24 -3
- package/dist/app/container.js +102 -38
- package/dist/app/container.js.map +1 -1
- package/dist/app/notification-channels.js +1 -0
- package/dist/app/notification-channels.js.map +1 -1
- package/dist/app/notification-reads.d.ts +3 -3
- package/dist/app/notification-reads.js +7 -28
- package/dist/app/notification-reads.js.map +1 -1
- package/dist/app/platform.d.ts +14 -0
- package/dist/app/platform.js +14 -0
- package/dist/app/platform.js.map +1 -0
- package/dist/http/config.d.ts +4 -0
- package/dist/http/errors.js +9 -4
- package/dist/http/errors.js.map +1 -1
- package/dist/http/fastify.d.ts +8 -0
- package/dist/http/mcp/catalogue.d.ts +11 -9
- package/dist/http/mcp/catalogue.js +15 -21
- package/dist/http/mcp/catalogue.js.map +1 -1
- package/dist/http/mcp/challenge.js +3 -3
- package/dist/http/mcp/challenge.js.map +1 -1
- package/dist/http/mcp/route.js +7 -7
- package/dist/http/mcp/route.js.map +1 -1
- package/dist/http/mcp/test-support.d.ts +6 -5
- package/dist/http/mcp/test-support.js +32 -11
- package/dist/http/mcp/test-support.js.map +1 -1
- package/dist/http/mcp/tool.d.ts +3 -9
- package/dist/http/mcp/tool.js +14 -6
- package/dist/http/mcp/tool.js.map +1 -1
- package/dist/http/mcp/tools/automations.js +10 -20
- package/dist/http/mcp/tools/automations.js.map +1 -1
- package/dist/http/mcp/tools/catalog.js +25 -42
- package/dist/http/mcp/tools/catalog.js.map +1 -1
- package/dist/http/mcp/tools/comments.js +9 -19
- package/dist/http/mcp/tools/comments.js.map +1 -1
- package/dist/http/mcp/tools/communities.js +17 -32
- package/dist/http/mcp/tools/communities.js.map +1 -1
- package/dist/http/mcp/tools/community-members.js +9 -16
- package/dist/http/mcp/tools/community-members.js.map +1 -1
- package/dist/http/mcp/tools/community-moderation.js +13 -25
- package/dist/http/mcp/tools/community-moderation.js.map +1 -1
- package/dist/http/mcp/tools/courses.js +11 -21
- package/dist/http/mcp/tools/courses.js.map +1 -1
- package/dist/http/mcp/tools/events.d.ts +6 -0
- package/dist/http/mcp/tools/events.js +170 -0
- package/dist/http/mcp/tools/events.js.map +1 -0
- package/dist/http/mcp/tools/index.d.ts +5 -1
- package/dist/http/mcp/tools/index.js +45 -10
- package/dist/http/mcp/tools/index.js.map +1 -1
- package/dist/http/mcp/tools/organization.d.ts +6 -0
- package/dist/http/mcp/tools/organization.js +214 -0
- package/dist/http/mcp/tools/organization.js.map +1 -0
- package/dist/http/mcp/tools/people.js +30 -49
- package/dist/http/mcp/tools/people.js.map +1 -1
- package/dist/http/plugins/auth.js +37 -8
- package/dist/http/plugins/auth.js.map +1 -1
- package/dist/http/plugins/error-handler.d.ts +5 -1
- package/dist/http/plugins/error-handler.js +10 -2
- package/dist/http/plugins/error-handler.js.map +1 -1
- package/dist/http/plugins/openapi.js +18 -2
- package/dist/http/plugins/openapi.js.map +1 -1
- package/dist/http/plugins/platform.d.ts +7 -0
- package/dist/http/plugins/platform.js +13 -0
- package/dist/http/plugins/platform.js.map +1 -0
- package/dist/http/routes/access.js +54 -36
- package/dist/http/routes/access.js.map +1 -1
- package/dist/http/routes/activities.js +45 -45
- package/dist/http/routes/activities.js.map +1 -1
- package/dist/http/routes/assets.js +30 -65
- package/dist/http/routes/assets.js.map +1 -1
- package/dist/http/routes/automations.js +37 -42
- package/dist/http/routes/automations.js.map +1 -1
- package/dist/http/routes/bundles.js +33 -36
- package/dist/http/routes/bundles.js.map +1 -1
- package/dist/http/routes/communities.js +93 -145
- package/dist/http/routes/communities.js.map +1 -1
- package/dist/http/routes/community-moderation.js +83 -137
- package/dist/http/routes/community-moderation.js.map +1 -1
- package/dist/http/routes/course-analytics.js +32 -15
- package/dist/http/routes/course-analytics.js.map +1 -1
- package/dist/http/routes/courses.js +25 -32
- package/dist/http/routes/courses.js.map +1 -1
- package/dist/http/routes/dashboard.js +9 -9
- package/dist/http/routes/dashboard.js.map +1 -1
- package/dist/http/routes/discussion.js +21 -39
- package/dist/http/routes/discussion.js.map +1 -1
- package/dist/http/routes/downloads.js +41 -47
- package/dist/http/routes/downloads.js.map +1 -1
- package/dist/http/routes/entitlements.js +19 -23
- package/dist/http/routes/entitlements.js.map +1 -1
- package/dist/http/routes/events.d.ts +7 -0
- package/dist/http/routes/events.js +333 -0
- package/dist/http/routes/events.js.map +1 -0
- package/dist/http/routes/integrations.js +40 -73
- package/dist/http/routes/integrations.js.map +1 -1
- package/dist/http/routes/member/assets.js +10 -13
- package/dist/http/routes/member/assets.js.map +1 -1
- package/dist/http/routes/member/chats.js +170 -47
- package/dist/http/routes/member/chats.js.map +1 -1
- package/dist/http/routes/member/comments.js +65 -26
- package/dist/http/routes/member/comments.js.map +1 -1
- package/dist/http/routes/member/community.js +45 -52
- package/dist/http/routes/member/community.js.map +1 -1
- package/dist/http/routes/member/courses.js +12 -19
- package/dist/http/routes/member/courses.js.map +1 -1
- package/dist/http/routes/member/devices.js +9 -10
- package/dist/http/routes/member/devices.js.map +1 -1
- package/dist/http/routes/member/downloads.js +6 -9
- package/dist/http/routes/member/downloads.js.map +1 -1
- package/dist/http/routes/member/events.d.ts +7 -0
- package/dist/http/routes/member/events.js +386 -0
- package/dist/http/routes/member/events.js.map +1 -0
- package/dist/http/routes/member/files.js +88 -46
- package/dist/http/routes/member/files.js.map +1 -1
- package/dist/http/routes/member/index.js +2 -0
- package/dist/http/routes/member/index.js.map +1 -1
- package/dist/http/routes/member/notification-settings.js +15 -23
- package/dist/http/routes/member/notification-settings.js.map +1 -1
- package/dist/http/routes/member/notifications.js +16 -16
- package/dist/http/routes/member/notifications.js.map +1 -1
- package/dist/http/routes/member/org.js +5 -15
- package/dist/http/routes/member/org.js.map +1 -1
- package/dist/http/routes/member/posts.js +67 -68
- package/dist/http/routes/member/posts.js.map +1 -1
- package/dist/http/routes/member/profile.js +15 -6
- package/dist/http/routes/member/profile.js.map +1 -1
- package/dist/http/routes/member/progress.js +7 -11
- package/dist/http/routes/member/progress.js.map +1 -1
- package/dist/http/routes/organizations.js +319 -135
- package/dist/http/routes/organizations.js.map +1 -1
- package/dist/http/routes/platform.d.ts +7 -0
- package/dist/http/routes/platform.js +61 -0
- package/dist/http/routes/platform.js.map +1 -0
- package/dist/http/routes/students.js +12 -75
- package/dist/http/routes/students.js.map +1 -1
- package/dist/http/routes/webhooks.js +30 -39
- package/dist/http/routes/webhooks.js.map +1 -1
- package/dist/http/routes.js +9 -0
- package/dist/http/routes.js.map +1 -1
- package/dist/http/schemas/access.d.ts +346 -64
- package/dist/http/schemas/access.js +39 -12
- package/dist/http/schemas/access.js.map +1 -1
- package/dist/http/schemas/assets.d.ts +8 -3
- package/dist/http/schemas/assets.js +6 -5
- package/dist/http/schemas/assets.js.map +1 -1
- package/dist/http/schemas/automations.d.ts +4 -4
- package/dist/http/schemas/chats.d.ts +216 -37
- package/dist/http/schemas/chats.js +13 -4
- package/dist/http/schemas/chats.js.map +1 -1
- package/dist/http/schemas/community.d.ts +105 -31
- package/dist/http/schemas/community.js +25 -9
- package/dist/http/schemas/community.js.map +1 -1
- package/dist/http/schemas/course-analytics.d.ts +51 -1
- package/dist/http/schemas/course-analytics.js +19 -1
- package/dist/http/schemas/course-analytics.js.map +1 -1
- package/dist/http/schemas/dashboard.d.ts +1 -0
- package/dist/http/schemas/dashboard.js +2 -1
- package/dist/http/schemas/dashboard.js.map +1 -1
- package/dist/http/schemas/discussion.d.ts +22 -72
- package/dist/http/schemas/discussion.js +2 -2
- package/dist/http/schemas/discussion.js.map +1 -1
- package/dist/http/schemas/entitlements.d.ts +9 -12
- package/dist/http/schemas/entitlements.js +11 -5
- package/dist/http/schemas/entitlements.js.map +1 -1
- package/dist/http/schemas/events.d.ts +527 -0
- package/dist/http/schemas/events.js +64 -0
- package/dist/http/schemas/events.js.map +1 -0
- package/dist/http/schemas/files.d.ts +24 -5
- package/dist/http/schemas/files.js +15 -2
- package/dist/http/schemas/files.js.map +1 -1
- package/dist/http/schemas/index.d.ts +11 -9
- package/dist/http/schemas/index.js +11 -9
- package/dist/http/schemas/invites.d.ts +3 -47
- package/dist/http/schemas/invites.js +4 -25
- package/dist/http/schemas/invites.js.map +1 -1
- package/dist/http/schemas/member.d.ts +94 -7
- package/dist/http/schemas/member.js +7 -3
- package/dist/http/schemas/member.js.map +1 -1
- package/dist/http/schemas/members.d.ts +329 -65
- package/dist/http/schemas/members.js +67 -25
- package/dist/http/schemas/members.js.map +1 -1
- package/dist/http/schemas/notifications.d.ts +58 -54
- package/dist/http/schemas/platform.d.ts +38 -0
- package/dist/http/schemas/platform.js +19 -0
- package/dist/http/schemas/platform.js.map +1 -0
- package/dist/http/schemas/posts.d.ts +55 -35
- package/dist/http/schemas/posts.js +4 -4
- package/dist/http/schemas/posts.js.map +1 -1
- package/dist/http/schemas/profile.d.ts +1 -1
- package/dist/http/schemas/shared.d.ts +1 -11
- package/dist/http/schemas/shared.js +1 -10
- package/dist/http/schemas/shared.js.map +1 -1
- package/dist/http/schemas/students.d.ts +22 -0
- package/dist/http/schemas/students.js +3 -1
- package/dist/http/schemas/students.js.map +1 -1
- package/dist/http/scope.d.ts +9 -13
- package/dist/http/scope.js +29 -40
- package/dist/http/scope.js.map +1 -1
- package/dist/http/server.js +9 -0
- package/dist/http/server.js.map +1 -1
- package/dist/http/shutdown.d.ts +11 -0
- package/dist/http/shutdown.js +40 -0
- package/dist/http/shutdown.js.map +1 -0
- package/dist/http/sse.d.ts +19 -0
- package/dist/http/sse.js +104 -0
- package/dist/http/sse.js.map +1 -0
- package/dist/http/test-caller.d.ts +13 -0
- package/dist/http/test-caller.js +14 -0
- package/dist/http/test-caller.js.map +1 -0
- package/dist/http/well-known.js +2 -2
- package/dist/http/well-known.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/packages/server/package.js +1 -1
- package/package.json +7 -6
- package/dist/http/routes/member/actor.d.ts +0 -14
- package/dist/http/routes/member/actor.js +0 -11
- package/dist/http/routes/member/actor.js.map +0 -1
package/README.md
CHANGED
|
@@ -10,14 +10,28 @@ integration plugins. The `headless-lms` bin lives in `@headless-lms/cli`.
|
|
|
10
10
|
|
|
11
11
|
```ts
|
|
12
12
|
import { createContainer, buildServer } from '@headless-lms/server';
|
|
13
|
+
import { PostgresPubSub } from '@headless-lms/adapter-pubsub-postgres';
|
|
13
14
|
|
|
14
15
|
const container = await createContainer(config, {
|
|
15
16
|
pluginsDir, // one folder per integration (directory name = integration id)
|
|
17
|
+
adapters: {
|
|
18
|
+
pubsub: (logger) => new PostgresPubSub({ connectionString: config.pubsubDatabaseUrl, logger }),
|
|
19
|
+
},
|
|
16
20
|
});
|
|
17
21
|
const app = await buildServer(config, container);
|
|
18
22
|
await app.listen({ port: config.port, host: config.host });
|
|
23
|
+
await container.pubsub?.start();
|
|
24
|
+
await container.chatHub?.start();
|
|
25
|
+
container.outboxRelay.start();
|
|
26
|
+
await container.automationEngine.start();
|
|
19
27
|
```
|
|
20
28
|
|
|
29
|
+
The container constructs the outbox relay, the automation engine, `PubSub` and the
|
|
30
|
+
chat hub but starts none of them; the entry point starts them after `listen`, `PubSub`
|
|
31
|
+
and the hub before the relay. `buildServer` closes the hub in `preClose`, so open chat
|
|
32
|
+
streams receive their closing frame, and on close stops the relay, the engine and then
|
|
33
|
+
`PubSub`.
|
|
34
|
+
|
|
21
35
|
Public surface (`src/index.ts`): `createContainer`, `buildServer`,
|
|
22
36
|
`loadIntegrations`, the operational function `runMigrations` (re-exported from
|
|
23
37
|
`@headless-lms/adapter-db`, which ships the `drizzle/` migration assets;
|
|
@@ -4,16 +4,18 @@ import { ChatService, DiscussionService, PostService, SubscriptionService } from
|
|
|
4
4
|
import { IdentityService } from "@headless-lms/core/identity";
|
|
5
5
|
import { OrganizationService } from "@headless-lms/core/organizations";
|
|
6
6
|
import { CommunityMailReads, GrantWriter } from "@headless-lms/core/automations";
|
|
7
|
+
import { BodyParser } from "@headless-lms/core/shared/ports";
|
|
7
8
|
//#region src/app/community-mail.d.ts
|
|
8
9
|
type CommunityMailDeps = {
|
|
9
|
-
content: Pick<ContentService, '
|
|
10
|
-
entitlements: Pick<EntitlementsService, 'openSpacesFor' | 'communitiesOpenedBy' | 'communityMembersAmong' | 'spaceOpenersAmong' | 'spaceOpeners' | '
|
|
11
|
-
organizations: Pick<OrganizationService, 'getOrgUserById' | '
|
|
10
|
+
content: Pick<ContentService, 'findCommunity' | 'getSpace' | 'listCommunitiesById' | 'findCourse' | 'findDownload' | 'findEvent' | 'findBundle'>;
|
|
11
|
+
entitlements: Pick<EntitlementsService, 'openSpacesFor' | 'communitiesOpenedBy' | 'communityMembersAmong' | 'spaceOpenersAmong' | 'spaceOpeners' | 'countActiveSpaceMembers' | 'communityIdsOpenedFor' | 'grant'>;
|
|
12
|
+
organizations: Pick<OrganizationService, 'getById' | 'getOrgUserById' | 'actorFor' | 'systemActor' | 'holders' | 'getRole' | 'permissionsOfMany'>;
|
|
12
13
|
identity: Pick<IdentityService, 'displayName'>;
|
|
13
14
|
posts: Pick<PostService, 'find'>;
|
|
14
15
|
subscriptions: Pick<SubscriptionService, 'followerIds' | 'itemSubscriptions'>;
|
|
15
16
|
discussion: Pick<DiscussionService, 'getComment'>;
|
|
16
17
|
chats: Pick<ChatService, 'chatSummary' | 'latestMessageBody' | 'isBlocked'>;
|
|
18
|
+
bodies: BodyParser;
|
|
17
19
|
};
|
|
18
20
|
declare function communityMail(deps: CommunityMailDeps): {
|
|
19
21
|
mail: Omit<CommunityMailReads, 'recentMessageRecipients'>;
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
+
import { NotFoundError } from "@headless-lms/core/shared/errors";
|
|
1
2
|
//#region src/app/community-mail.ts
|
|
2
3
|
function communityMail(deps) {
|
|
4
|
+
const system = (orgId) => deps.organizations.systemActor(orgId);
|
|
3
5
|
return {
|
|
4
6
|
mail: {
|
|
5
7
|
async communityTitle(orgId, communityId) {
|
|
6
|
-
return (await deps.content.
|
|
8
|
+
return (await deps.content.findCommunity(communityId, system(orgId)))?.title ?? null;
|
|
7
9
|
},
|
|
8
10
|
async space(orgId, spaceId) {
|
|
9
|
-
const space = await deps.content.getSpace(
|
|
11
|
+
const space = await deps.content.getSpace(spaceId, system(orgId));
|
|
10
12
|
return space ? {
|
|
11
13
|
name: space.name,
|
|
12
14
|
communityId: space.communityId,
|
|
@@ -14,23 +16,69 @@ function communityMail(deps) {
|
|
|
14
16
|
} : null;
|
|
15
17
|
},
|
|
16
18
|
async openSpaceNames(orgId, orgUserId, communityId) {
|
|
17
|
-
const
|
|
18
|
-
if (!
|
|
19
|
-
return (await deps.entitlements.openSpacesFor(
|
|
20
|
-
id: orgUser.id,
|
|
21
|
-
role: orgUser.role
|
|
22
|
-
}, communityId)).map((space) => space.name);
|
|
19
|
+
const person = await deps.organizations.actorFor(orgId, orgUserId);
|
|
20
|
+
if (!person) return [];
|
|
21
|
+
return (await deps.entitlements.openSpacesFor(communityId, person)).map((space) => space.name);
|
|
23
22
|
},
|
|
24
23
|
communitiesOpenedBy: (orgId, grant) => deps.entitlements.communitiesOpenedBy(orgId, grant),
|
|
25
24
|
communityMembersAmong: (orgId, communityId, ids) => deps.entitlements.communityMembersAmong(orgId, communityId, ids),
|
|
26
25
|
spaceOpenersAmong: (orgId, spaceId, ids) => deps.entitlements.spaceOpenersAmong(orgId, spaceId, ids),
|
|
27
26
|
spaceOpeners: (orgId, spaceId) => deps.entitlements.spaceOpeners(orgId, spaceId),
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
holders: (orgId, permission, on) => deps.organizations.holders(orgId, permission, on),
|
|
28
|
+
async heldOnOrg(orgId, orgUserId, permissions) {
|
|
29
|
+
const held = (await deps.organizations.permissionsOfMany(orgId, [orgUserId])).get(orgUserId);
|
|
30
|
+
return held ? permissions.filter((permission) => held.has(permission)) : [];
|
|
31
|
+
},
|
|
32
|
+
async role(orgId, roleKey) {
|
|
33
|
+
try {
|
|
34
|
+
const role = await deps.organizations.getRole(roleKey, system(orgId));
|
|
35
|
+
return {
|
|
36
|
+
name: role.name,
|
|
37
|
+
permissions: role.permissions
|
|
38
|
+
};
|
|
39
|
+
} catch (err) {
|
|
40
|
+
if (err instanceof NotFoundError) return null;
|
|
41
|
+
throw err;
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
async orgName(orgId) {
|
|
45
|
+
return (await deps.organizations.getById(orgId))?.name ?? null;
|
|
46
|
+
},
|
|
47
|
+
async contentInfo(orgId, item) {
|
|
48
|
+
const actor = system(orgId);
|
|
49
|
+
if ("bundleId" in item) {
|
|
50
|
+
const bundle = await deps.content.findBundle(item.bundleId, actor);
|
|
51
|
+
return bundle ? {
|
|
52
|
+
title: bundle.name,
|
|
53
|
+
type: "bundle"
|
|
54
|
+
} : null;
|
|
55
|
+
}
|
|
56
|
+
const course = await deps.content.findCourse(item.contentId, actor);
|
|
57
|
+
if (course) return {
|
|
58
|
+
title: course.title,
|
|
59
|
+
type: course.type
|
|
60
|
+
};
|
|
61
|
+
const download = await deps.content.findDownload(item.contentId, actor);
|
|
62
|
+
if (download) return {
|
|
63
|
+
title: download.title,
|
|
64
|
+
type: download.type
|
|
65
|
+
};
|
|
66
|
+
const community = await deps.content.findCommunity(item.contentId, actor);
|
|
67
|
+
if (community) return {
|
|
68
|
+
title: community.title,
|
|
69
|
+
type: community.type
|
|
70
|
+
};
|
|
71
|
+
const event = await deps.content.findEvent(item.contentId, actor);
|
|
72
|
+
return event ? {
|
|
73
|
+
title: event.title,
|
|
74
|
+
type: event.type
|
|
75
|
+
} : null;
|
|
76
|
+
},
|
|
30
77
|
async displayName(orgId, orgUserId) {
|
|
31
78
|
const orgUser = await deps.organizations.getOrgUserById(orgId, orgUserId);
|
|
32
79
|
return deps.identity.displayName(orgUser?.userId ?? null);
|
|
33
80
|
},
|
|
81
|
+
postText: (body) => deps.bodies.parse(body).text,
|
|
34
82
|
followerIds: (orgId, postId) => deps.subscriptions.followerIds(orgId, postId),
|
|
35
83
|
async comment(orgId, commentId) {
|
|
36
84
|
const comment = await deps.discussion.getComment(orgId, commentId);
|
|
@@ -77,13 +125,13 @@ function communityMail(deps) {
|
|
|
77
125
|
activeMemberCount: (orgId, spaceId) => deps.entitlements.countActiveSpaceMembers(orgId, spaceId),
|
|
78
126
|
async memberCommunityTitles(orgId, orgUserId) {
|
|
79
127
|
const ids = await deps.entitlements.communityIdsOpenedFor(orgId, orgUserId);
|
|
80
|
-
return (await deps.content.listCommunitiesById(
|
|
128
|
+
return (await deps.content.listCommunitiesById(ids, system(orgId))).map((community) => ({
|
|
81
129
|
id: community.id,
|
|
82
130
|
title: community.title
|
|
83
131
|
}));
|
|
84
132
|
}
|
|
85
133
|
},
|
|
86
|
-
grants: { grant: (orgId, input) => deps.entitlements.
|
|
134
|
+
grants: { grant: (orgId, input) => deps.entitlements.grant(input, system(orgId)) }
|
|
87
135
|
};
|
|
88
136
|
}
|
|
89
137
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"community-mail.js","names":[],"sources":["../../src/app/community-mail.ts"],"sourcesContent":["import type { CommunityMailReads, GrantWriter } from '@headless-lms/core/automations';\nimport type { ContentService } from '@headless-lms/core/content';\nimport type {\n ChatService,\n DiscussionService,\n PostService,\n SubscriptionService,\n} from '@headless-lms/core/discussion';\nimport type { EntitlementsService } from '@headless-lms/core/entitlements';\nimport type { IdentityService } from '@headless-lms/core/identity';\nimport type { OrganizationService } from '@headless-lms/core/organizations';\n\nexport type CommunityMailDeps = {\n content: Pick<ContentService, 'getCommunity' | 'getSpace' | 'listCommunitiesById'>;\n entitlements: Pick<\n EntitlementsService,\n | 'openSpacesFor'\n | 'communitiesOpenedBy'\n | 'communityMembersAmong'\n | 'spaceOpenersAmong'\n | 'spaceOpeners'\n | 'communityModeratorIds'\n | 'countActiveSpaceMembers'\n | 'communityIdsOpenedFor'\n | 'ensureGrant'\n >;\n organizations: Pick<OrganizationService, 'getOrgUserById' | 'staffOrgUserIds'>;\n identity: Pick<IdentityService, 'displayName'>;\n posts: Pick<PostService, 'find'>;\n subscriptions: Pick<SubscriptionService, 'followerIds' | 'itemSubscriptions'>;\n discussion: Pick<DiscussionService, 'getComment'>;\n chats: Pick<ChatService, 'chatSummary' | 'latestMessageBody' | 'isBlocked'>;\n};\n\nexport function communityMail(deps: CommunityMailDeps): {\n mail: Omit<CommunityMailReads, 'recentMessageRecipients'>;\n grants: GrantWriter;\n} {\n const mail: Omit<CommunityMailReads, 'recentMessageRecipients'> = {\n async communityTitle(orgId, communityId) {\n return (await deps.content.getCommunity(orgId, communityId))?.title ?? null;\n },\n async space(orgId, spaceId) {\n const space = await deps.content.getSpace(orgId, spaceId);\n return space\n ? { name: space.name, communityId: space.communityId, capacity: space.capacity }\n : null;\n },\n async openSpaceNames(orgId, orgUserId, communityId) {\n const orgUser = await deps.organizations.getOrgUserById(orgId, orgUserId);\n if (!orgUser) {\n return [];\n }\n const spaces = await deps.entitlements.openSpacesFor(\n orgId,\n { id: orgUser.id, role: orgUser.role },\n communityId,\n );\n return spaces.map((space) => space.name);\n },\n communitiesOpenedBy: (orgId, grant) => deps.entitlements.communitiesOpenedBy(orgId, grant),\n communityMembersAmong: (orgId, communityId, ids) =>\n deps.entitlements.communityMembersAmong(orgId, communityId, ids),\n spaceOpenersAmong: (orgId, spaceId, ids) =>\n deps.entitlements.spaceOpenersAmong(orgId, spaceId, ids),\n spaceOpeners: (orgId, spaceId) => deps.entitlements.spaceOpeners(orgId, spaceId),\n moderationAudience: (orgId, communityId) =>\n deps.entitlements.communityModeratorIds(orgId, communityId),\n staffIds: (orgId) => deps.organizations.staffOrgUserIds(orgId),\n async displayName(orgId, orgUserId) {\n const orgUser = await deps.organizations.getOrgUserById(orgId, orgUserId);\n return deps.identity.displayName(orgUser?.userId ?? null);\n },\n followerIds: (orgId, postId) => deps.subscriptions.followerIds(orgId, postId),\n async comment(orgId, commentId) {\n const comment = await deps.discussion.getComment(orgId, commentId);\n return comment\n ? {\n orgUserId: comment.orgUserId,\n postId: comment.postId,\n activityId: comment.activityId,\n parentId: comment.parentId,\n body: comment.body,\n }\n : null;\n },\n async post(orgId, postId) {\n const post = await deps.posts.find(orgId, postId);\n return post\n ? {\n title: post.title,\n body: post.body,\n spaceId: post.spaceId,\n orgUserId: post.orgUserId,\n communityId: post.communityId,\n }\n : null;\n },\n async chat(orgId, chatId) {\n const summary = await deps.chats.chatSummary(orgId, chatId);\n if (!summary) {\n return null;\n }\n const mutes = new Map(\n (await deps.subscriptions.itemSubscriptions(orgId, { type: 'chat', id: chatId }))\n .filter((subscription) => subscription.state === 'muted')\n .map((subscription) => [subscription.orgUserId, subscription.mutedUntil]),\n );\n return {\n communityId: summary.chat.communityId,\n kind: summary.chat.kind,\n status: summary.chat.status,\n createdBy: summary.chat.createdBy,\n participants: summary.participants.map((participant) => ({\n orgUserId: participant.orgUserId,\n muted: mutes.has(participant.orgUserId),\n mutedUntil: mutes.get(participant.orgUserId) ?? null,\n leftAt: participant.leftAt,\n })),\n };\n },\n latestMessageBody: (orgId, chatId) => deps.chats.latestMessageBody(orgId, chatId),\n pairBlocked: (orgId, communityId, a, b) => deps.chats.isBlocked(orgId, communityId, a, b),\n activeMemberCount: (orgId, spaceId) =>\n deps.entitlements.countActiveSpaceMembers(orgId, spaceId),\n async memberCommunityTitles(orgId, orgUserId) {\n const ids = await deps.entitlements.communityIdsOpenedFor(orgId, orgUserId);\n const communities = await deps.content.listCommunitiesById(orgId, ids);\n return communities.map((community) => ({ id: community.id, title: community.title }));\n },\n };\n return {\n mail,\n grants: {\n grant: (orgId, input) => deps.entitlements.ensureGrant(orgId, input),\n },\n };\n}\n"],"mappings":";AAkCA,SAAgB,cAAc,MAG5B;CA8FA,OAAO;EACL,MAAA;GA7FA,MAAM,eAAe,OAAO,aAAa;IACvC,QAAQ,MAAM,KAAK,QAAQ,aAAa,OAAO,WAAW,EAAA,EAAI,SAAS;GACzE;GACA,MAAM,MAAM,OAAO,SAAS;IAC1B,MAAM,QAAQ,MAAM,KAAK,QAAQ,SAAS,OAAO,OAAO;IACxD,OAAO,QACH;KAAE,MAAM,MAAM;KAAM,aAAa,MAAM;KAAa,UAAU,MAAM;IAAS,IAC7E;GACN;GACA,MAAM,eAAe,OAAO,WAAW,aAAa;IAClD,MAAM,UAAU,MAAM,KAAK,cAAc,eAAe,OAAO,SAAS;IACxE,IAAI,CAAC,SACH,OAAO,CAAC;IAOV,QAAO,MALc,KAAK,aAAa,cACrC,OACA;KAAE,IAAI,QAAQ;KAAI,MAAM,QAAQ;IAAK,GACrC,WACF,EAAA,CACc,KAAK,UAAU,MAAM,IAAI;GACzC;GACA,sBAAsB,OAAO,UAAU,KAAK,aAAa,oBAAoB,OAAO,KAAK;GACzF,wBAAwB,OAAO,aAAa,QAC1C,KAAK,aAAa,sBAAsB,OAAO,aAAa,GAAG;GACjE,oBAAoB,OAAO,SAAS,QAClC,KAAK,aAAa,kBAAkB,OAAO,SAAS,GAAG;GACzD,eAAe,OAAO,YAAY,KAAK,aAAa,aAAa,OAAO,OAAO;GAC/E,qBAAqB,OAAO,gBAC1B,KAAK,aAAa,sBAAsB,OAAO,WAAW;GAC5D,WAAW,UAAU,KAAK,cAAc,gBAAgB,KAAK;GAC7D,MAAM,YAAY,OAAO,WAAW;IAClC,MAAM,UAAU,MAAM,KAAK,cAAc,eAAe,OAAO,SAAS;IACxE,OAAO,KAAK,SAAS,YAAY,SAAS,UAAU,IAAI;GAC1D;GACA,cAAc,OAAO,WAAW,KAAK,cAAc,YAAY,OAAO,MAAM;GAC5E,MAAM,QAAQ,OAAO,WAAW;IAC9B,MAAM,UAAU,MAAM,KAAK,WAAW,WAAW,OAAO,SAAS;IACjE,OAAO,UACH;KACE,WAAW,QAAQ;KACnB,QAAQ,QAAQ;KAChB,YAAY,QAAQ;KACpB,UAAU,QAAQ;KAClB,MAAM,QAAQ;IAChB,IACA;GACN;GACA,MAAM,KAAK,OAAO,QAAQ;IACxB,MAAM,OAAO,MAAM,KAAK,MAAM,KAAK,OAAO,MAAM;IAChD,OAAO,OACH;KACE,OAAO,KAAK;KACZ,MAAM,KAAK;KACX,SAAS,KAAK;KACd,WAAW,KAAK;KAChB,aAAa,KAAK;IACpB,IACA;GACN;GACA,MAAM,KAAK,OAAO,QAAQ;IACxB,MAAM,UAAU,MAAM,KAAK,MAAM,YAAY,OAAO,MAAM;IAC1D,IAAI,CAAC,SACH,OAAO;IAET,MAAM,QAAQ,IAAI,KACf,MAAM,KAAK,cAAc,kBAAkB,OAAO;KAAE,MAAM;KAAQ,IAAI;IAAO,CAAC,EAAA,CAC5E,QAAQ,iBAAiB,aAAa,UAAU,OAAO,CAAC,CACxD,KAAK,iBAAiB,CAAC,aAAa,WAAW,aAAa,UAAU,CAAC,CAC5E;IACA,OAAO;KACL,aAAa,QAAQ,KAAK;KAC1B,MAAM,QAAQ,KAAK;KACnB,QAAQ,QAAQ,KAAK;KACrB,WAAW,QAAQ,KAAK;KACxB,cAAc,QAAQ,aAAa,KAAK,iBAAiB;MACvD,WAAW,YAAY;MACvB,OAAO,MAAM,IAAI,YAAY,SAAS;MACtC,YAAY,MAAM,IAAI,YAAY,SAAS,KAAK;MAChD,QAAQ,YAAY;KACtB,EAAE;IACJ;GACF;GACA,oBAAoB,OAAO,WAAW,KAAK,MAAM,kBAAkB,OAAO,MAAM;GAChF,cAAc,OAAO,aAAa,GAAG,MAAM,KAAK,MAAM,UAAU,OAAO,aAAa,GAAG,CAAC;GACxF,oBAAoB,OAAO,YACzB,KAAK,aAAa,wBAAwB,OAAO,OAAO;GAC1D,MAAM,sBAAsB,OAAO,WAAW;IAC5C,MAAM,MAAM,MAAM,KAAK,aAAa,sBAAsB,OAAO,SAAS;IAE1E,QAAO,MADmB,KAAK,QAAQ,oBAAoB,OAAO,GAAG,EAAA,CAClD,KAAK,eAAe;KAAE,IAAI,UAAU;KAAI,OAAO,UAAU;IAAM,EAAE;GACtF;EAGG;EACH,QAAQ,EACN,QAAQ,OAAO,UAAU,KAAK,aAAa,YAAY,OAAO,KAAK,EACrE;CACF;AACF"}
|
|
1
|
+
{"version":3,"file":"community-mail.js","names":[],"sources":["../../src/app/community-mail.ts"],"sourcesContent":["import type { CommunityMailReads, GrantWriter } from '@headless-lms/core/automations';\nimport type { ContentService } from '@headless-lms/core/content';\nimport type {\n ChatService,\n DiscussionService,\n PostService,\n SubscriptionService,\n} from '@headless-lms/core/discussion';\nimport type { EntitlementsService } from '@headless-lms/core/entitlements';\nimport type { IdentityService } from '@headless-lms/core/identity';\nimport type { OrganizationService } from '@headless-lms/core/organizations';\nimport { NotFoundError } from '@headless-lms/core/shared/errors';\nimport type { BodyParser } from '@headless-lms/core/shared/ports';\n\nexport type CommunityMailDeps = {\n content: Pick<\n ContentService,\n | 'findCommunity'\n | 'getSpace'\n | 'listCommunitiesById'\n | 'findCourse'\n | 'findDownload'\n | 'findEvent'\n | 'findBundle'\n >;\n entitlements: Pick<\n EntitlementsService,\n | 'openSpacesFor'\n | 'communitiesOpenedBy'\n | 'communityMembersAmong'\n | 'spaceOpenersAmong'\n | 'spaceOpeners'\n | 'countActiveSpaceMembers'\n | 'communityIdsOpenedFor'\n | 'grant'\n >;\n organizations: Pick<\n OrganizationService,\n | 'getById'\n | 'getOrgUserById'\n | 'actorFor'\n | 'systemActor'\n | 'holders'\n | 'getRole'\n | 'permissionsOfMany'\n >;\n identity: Pick<IdentityService, 'displayName'>;\n posts: Pick<PostService, 'find'>;\n subscriptions: Pick<SubscriptionService, 'followerIds' | 'itemSubscriptions'>;\n discussion: Pick<DiscussionService, 'getComment'>;\n chats: Pick<ChatService, 'chatSummary' | 'latestMessageBody' | 'isBlocked'>;\n bodies: BodyParser;\n};\n\nexport function communityMail(deps: CommunityMailDeps): {\n mail: Omit<CommunityMailReads, 'recentMessageRecipients'>;\n grants: GrantWriter;\n} {\n const system = (orgId: string) => deps.organizations.systemActor(orgId);\n const mail: Omit<CommunityMailReads, 'recentMessageRecipients'> = {\n async communityTitle(orgId, communityId) {\n return (await deps.content.findCommunity(communityId, system(orgId)))?.title ?? null;\n },\n async space(orgId, spaceId) {\n const space = await deps.content.getSpace(spaceId, system(orgId));\n return space\n ? { name: space.name, communityId: space.communityId, capacity: space.capacity }\n : null;\n },\n async openSpaceNames(orgId, orgUserId, communityId) {\n const person = await deps.organizations.actorFor(orgId, orgUserId);\n if (!person) {\n return [];\n }\n const spaces = await deps.entitlements.openSpacesFor(communityId, person);\n return spaces.map((space) => space.name);\n },\n communitiesOpenedBy: (orgId, grant) => deps.entitlements.communitiesOpenedBy(orgId, grant),\n communityMembersAmong: (orgId, communityId, ids) =>\n deps.entitlements.communityMembersAmong(orgId, communityId, ids),\n spaceOpenersAmong: (orgId, spaceId, ids) =>\n deps.entitlements.spaceOpenersAmong(orgId, spaceId, ids),\n spaceOpeners: (orgId, spaceId) => deps.entitlements.spaceOpeners(orgId, spaceId),\n holders: (orgId, permission, on) => deps.organizations.holders(orgId, permission, on),\n async heldOnOrg(orgId, orgUserId, permissions) {\n const held = (await deps.organizations.permissionsOfMany(orgId, [orgUserId])).get(orgUserId);\n return held ? permissions.filter((permission) => held.has(permission)) : [];\n },\n async role(orgId, roleKey) {\n try {\n const role = await deps.organizations.getRole(roleKey, system(orgId));\n return { name: role.name, permissions: role.permissions };\n } catch (err) {\n if (err instanceof NotFoundError) {\n return null;\n }\n throw err;\n }\n },\n async orgName(orgId) {\n return (await deps.organizations.getById(orgId))?.name ?? null;\n },\n async contentInfo(orgId, item) {\n const actor = system(orgId);\n if ('bundleId' in item) {\n const bundle = await deps.content.findBundle(item.bundleId, actor);\n return bundle ? { title: bundle.name, type: 'bundle' } : null;\n }\n const course = await deps.content.findCourse(item.contentId, actor);\n if (course) {\n return { title: course.title, type: course.type };\n }\n const download = await deps.content.findDownload(item.contentId, actor);\n if (download) {\n return { title: download.title, type: download.type };\n }\n const community = await deps.content.findCommunity(item.contentId, actor);\n if (community) {\n return { title: community.title, type: community.type };\n }\n const event = await deps.content.findEvent(item.contentId, actor);\n return event ? { title: event.title, type: event.type } : null;\n },\n async displayName(orgId, orgUserId) {\n const orgUser = await deps.organizations.getOrgUserById(orgId, orgUserId);\n return deps.identity.displayName(orgUser?.userId ?? null);\n },\n postText: (body) => deps.bodies.parse(body).text,\n followerIds: (orgId, postId) => deps.subscriptions.followerIds(orgId, postId),\n async comment(orgId, commentId) {\n const comment = await deps.discussion.getComment(orgId, commentId);\n return comment\n ? {\n orgUserId: comment.orgUserId,\n postId: comment.postId,\n activityId: comment.activityId,\n parentId: comment.parentId,\n body: comment.body,\n }\n : null;\n },\n async post(orgId, postId) {\n const post = await deps.posts.find(orgId, postId);\n return post\n ? {\n title: post.title,\n body: post.body,\n spaceId: post.spaceId,\n orgUserId: post.orgUserId,\n communityId: post.communityId,\n }\n : null;\n },\n async chat(orgId, chatId) {\n const summary = await deps.chats.chatSummary(orgId, chatId);\n if (!summary) {\n return null;\n }\n const mutes = new Map(\n (await deps.subscriptions.itemSubscriptions(orgId, { type: 'chat', id: chatId }))\n .filter((subscription) => subscription.state === 'muted')\n .map((subscription) => [subscription.orgUserId, subscription.mutedUntil]),\n );\n return {\n communityId: summary.chat.communityId,\n kind: summary.chat.kind,\n status: summary.chat.status,\n createdBy: summary.chat.createdBy,\n participants: summary.participants.map((participant) => ({\n orgUserId: participant.orgUserId,\n muted: mutes.has(participant.orgUserId),\n mutedUntil: mutes.get(participant.orgUserId) ?? null,\n leftAt: participant.leftAt,\n })),\n };\n },\n latestMessageBody: (orgId, chatId) => deps.chats.latestMessageBody(orgId, chatId),\n pairBlocked: (orgId, communityId, a, b) => deps.chats.isBlocked(orgId, communityId, a, b),\n activeMemberCount: (orgId, spaceId) =>\n deps.entitlements.countActiveSpaceMembers(orgId, spaceId),\n async memberCommunityTitles(orgId, orgUserId) {\n const ids = await deps.entitlements.communityIdsOpenedFor(orgId, orgUserId);\n const communities = await deps.content.listCommunitiesById(ids, system(orgId));\n return communities.map((community) => ({ id: community.id, title: community.title }));\n },\n };\n return {\n mail,\n grants: {\n grant: (orgId, input) => deps.entitlements.grant(input, system(orgId)),\n },\n };\n}\n"],"mappings":"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"}
|
package/dist/app/container.d.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { McpEndpoints } from "./mcp-endpoints.js";
|
|
2
|
+
import { PlatformConfig, PlatformKeyCheck } from "./platform.js";
|
|
3
|
+
import { DatabasePoolOptions } from "@headless-lms/adapter-db";
|
|
2
4
|
import { PollingOutboxRelayConfig } from "@headless-lms/adapter-defaults/events/outbox-relay";
|
|
3
5
|
import { LogLevel, PinoInstance, RequestLogContext } from "@headless-lms/adapter-defaults/logging";
|
|
4
6
|
import { BetterAuth } from "@headless-lms/adapter-auth";
|
|
5
7
|
import { CommunityNotificationCategories, ContentService } from "@headless-lms/core/content";
|
|
6
8
|
import { EntitlementsServiceImpl } from "@headless-lms/core/entitlements";
|
|
7
9
|
import { ProgressServiceImpl } from "@headless-lms/core/progress";
|
|
8
|
-
import { ChatServiceImpl, DiscussionServiceImpl, PostServiceImpl, SubscriptionServiceImpl } from "@headless-lms/core/discussion";
|
|
10
|
+
import { ChatHub, ChatHubOptions, ChatServiceImpl, DiscussionServiceImpl, PostServiceImpl, SubscriptionServiceImpl } from "@headless-lms/core/discussion";
|
|
9
11
|
import { DevicesServiceImpl, IdentityServiceImpl, NotificationSettingsServiceImpl, SessionAdmin } from "@headless-lms/core/identity";
|
|
10
|
-
import { OrgAdmin, OrgNotificationCategories, OrganizationServiceImpl } from "@headless-lms/core/organizations";
|
|
12
|
+
import { NotificationCatalog, OrgAdmin, OrgNotificationCategories, OrganizationServiceImpl, RoleDefinition } from "@headless-lms/core/organizations";
|
|
11
13
|
import { AssetsServiceImpl } from "@headless-lms/core/assets";
|
|
12
14
|
import { IntegrationsServiceImpl } from "@headless-lms/core/integrations";
|
|
13
15
|
import { AutomationsServiceImpl, NotificationCategories, NotificationsServiceImpl } from "@headless-lms/core/automations";
|
|
@@ -16,7 +18,7 @@ import { AdminReportServiceImpl } from "@headless-lms/core/reporting/admin";
|
|
|
16
18
|
import { MemberReportServiceImpl } from "@headless-lms/core/reporting/member";
|
|
17
19
|
import { SettingsService } from "@headless-lms/core/shared/settings";
|
|
18
20
|
import { AutomationEngine, PushConfig, WebhookSender } from "@headless-lms/core/types";
|
|
19
|
-
import { ChannelRegistry, CredentialStore, EmailSender, Logger, NotificationChannel, NotificationTypeRegistry, ObjectStorage, OutboxRelay, PushSender, Scheduler, TemplateContext, TemplateRenderer } from "@headless-lms/core/shared/ports";
|
|
21
|
+
import { BodyParser, ChannelRegistry, CredentialStore, EmailSender, Logger, NotificationChannel, NotificationTypeRegistry, ObjectStorage, OutboxRelay, PubSub, PushSender, Scheduler, TemplateContext, TemplateRenderer } from "@headless-lms/core/shared/ports";
|
|
20
22
|
//#region src/app/container.d.ts
|
|
21
23
|
/** Installation-supplied ports; an absent slot falls back to a fail-loudly stub. */
|
|
22
24
|
interface AdapterOverrides {
|
|
@@ -33,14 +35,22 @@ interface AdapterOverrides {
|
|
|
33
35
|
/** Push credentials per provider. Absent → no provider is configured and devices cannot register. */
|
|
34
36
|
push?: PushConfig;
|
|
35
37
|
pushSender?: PushSender;
|
|
38
|
+
/** Reads post bodies: their text, mentions and images. Absent → PlainBodyParser (plain text, no images). */
|
|
39
|
+
bodyParser?: BodyParser;
|
|
40
|
+
/** Delivery to every API instance, or a factory given its logger. Absent → no live chat; the chat stream answers 503. */
|
|
41
|
+
pubsub?: PubSub | ((logger: Logger) => PubSub);
|
|
36
42
|
}
|
|
37
43
|
interface BuildContainerOptions {
|
|
38
44
|
/** Installation's plugins folder, scanned by loadIntegrations. Absent → no integrations. */
|
|
39
45
|
pluginsDir?: string;
|
|
40
46
|
adapters?: AdapterOverrides;
|
|
47
|
+
roles?: readonly RoleDefinition[];
|
|
48
|
+
/** Live chat hub timings. Absent → the defaults (1 s state flush, 30 s session check). */
|
|
49
|
+
live?: ChatHubOptions;
|
|
41
50
|
}
|
|
42
51
|
interface Config {
|
|
43
52
|
databaseUrl: string;
|
|
53
|
+
databasePool?: DatabasePoolOptions;
|
|
44
54
|
authBaseURL: string;
|
|
45
55
|
authSecret: string;
|
|
46
56
|
trustedOrigins: string[];
|
|
@@ -65,8 +75,10 @@ interface Config {
|
|
|
65
75
|
* ServerConfig.deliveryExpirySeconds — createContainer threads it through. */
|
|
66
76
|
deliveryExpirySeconds: number;
|
|
67
77
|
memberImageMaxBytes: number;
|
|
78
|
+
memberFileMaxBytes: number;
|
|
68
79
|
/** Let the default webhook sender reach loopback and private network addresses. Local development only. */
|
|
69
80
|
webhookAllowPrivateNetwork?: boolean;
|
|
81
|
+
platform?: PlatformConfig;
|
|
70
82
|
}
|
|
71
83
|
/** Tuning for the transactional-outbox relay. Every field is optional; the
|
|
72
84
|
* container resolves against OUTBOX_DEFAULTS. */
|
|
@@ -91,6 +103,7 @@ declare function resolveLoggingConfig(config?: LoggingConfig): Required<LoggingC
|
|
|
91
103
|
interface Container {
|
|
92
104
|
auth: BetterAuth;
|
|
93
105
|
mcp: McpEndpoints;
|
|
106
|
+
platform: PlatformKeyCheck | null;
|
|
94
107
|
orgProvider: OrgAdmin;
|
|
95
108
|
identity: IdentityServiceImpl;
|
|
96
109
|
organizations: OrganizationServiceImpl;
|
|
@@ -110,6 +123,7 @@ interface Container {
|
|
|
110
123
|
community: CommunityNotificationCategories;
|
|
111
124
|
org: OrgNotificationCategories;
|
|
112
125
|
};
|
|
126
|
+
notificationCatalog: NotificationCatalog;
|
|
113
127
|
notificationCategoryLists: NotificationCategories;
|
|
114
128
|
notificationSettings: NotificationSettingsServiceImpl;
|
|
115
129
|
devices: DevicesServiceImpl;
|
|
@@ -134,6 +148,13 @@ interface Container {
|
|
|
134
148
|
* not run a worker). buildServer stops it onClose. */
|
|
135
149
|
automationEngine: AutomationEngine;
|
|
136
150
|
scheduler: Scheduler;
|
|
151
|
+
/** The PubSub adapter — constructed but NEVER started by the container; the
|
|
152
|
+
* installation's entry point starts it after listen. buildServer stops it
|
|
153
|
+
* onClose. Null without one. */
|
|
154
|
+
pubsub: PubSub | null;
|
|
155
|
+
/** This process's live chat hub; started by the entry point after `pubsub`,
|
|
156
|
+
* closed by buildServer preClose. Null without a PubSub. */
|
|
157
|
+
chatHub: ChatHub | null;
|
|
137
158
|
/** Root logger port — components receive children bound with { name }. */
|
|
138
159
|
logger: Logger;
|
|
139
160
|
/** The raw pino root; buildServer hands it to Fastify so HTTP shares the stream. */
|