@headless-lms/core 0.3.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 +9 -9
- package/dist/assets/index.d.ts +3 -2
- package/dist/assets/index.js +2 -1
- 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/ports.d.ts +4 -3
- package/dist/assets/service.d.ts +0 -1
- package/dist/assets/service.js +0 -4
- package/dist/assets/service.js.map +1 -1
- package/dist/automations/actions.js +2 -63
- package/dist/automations/actions.js.map +1 -1
- package/dist/automations/catalog.d.ts +1 -2
- package/dist/automations/catalog.js +69 -62
- package/dist/automations/catalog.js.map +1 -1
- package/dist/automations/community-derivations.js +4 -4
- package/dist/automations/community-derivations.js.map +1 -1
- package/dist/automations/community-mail.d.ts +3 -17
- package/dist/automations/community-mail.js +1 -21
- package/dist/automations/community-mail.js.map +1 -1
- package/dist/automations/events.d.ts +0 -10
- package/dist/automations/index.d.ts +11 -4
- package/dist/automations/index.js +8 -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 +119 -5
- package/dist/automations/service.d.ts +10 -13
- package/dist/automations/service.js +21 -83
- package/dist/automations/service.js.map +1 -1
- package/dist/content/events.d.ts +130 -80
- package/dist/content/events.js +11 -0
- 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 +25 -6
- package/dist/content/service.d.ts +4 -4
- package/dist/content/service.js +24 -8
- 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/chats.d.ts +9 -4
- package/dist/discussion/chats.js +80 -47
- package/dist/discussion/chats.js.map +1 -1
- 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 +194 -28
- package/dist/discussion/events.js +74 -17
- package/dist/discussion/events.js.map +1 -1
- package/dist/discussion/index.d.ts +7 -2
- package/dist/discussion/index.js +6 -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 +107 -24
- package/dist/discussion/ports.js.map +1 -1
- package/dist/discussion/posts.d.ts +18 -8
- package/dist/discussion/posts.js +207 -155
- package/dist/discussion/posts.js.map +1 -1
- package/dist/discussion/service.d.ts +17 -8
- package/dist/discussion/service.js +105 -41
- 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 +20 -20
- package/dist/entitlements/index.d.ts +2 -1
- package/dist/entitlements/index.js +2 -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/ports.d.ts +7 -3
- package/dist/entitlements/service.d.ts +5 -2
- package/dist/entitlements/service.js +23 -3
- package/dist/entitlements/service.js.map +1 -1
- 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 +5 -4
- package/dist/identity/index.js +3 -2
- package/dist/identity/model.d.ts +2 -2
- 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 +78 -54
- package/dist/integrations/events.d.ts +3 -3
- package/dist/organizations/events.d.ts +32 -32
- package/dist/organizations/index.d.ts +2 -1
- package/dist/organizations/index.js +2 -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 +3 -0
- package/dist/organizations/service.d.ts +2 -0
- package/dist/organizations/service.js +7 -0
- package/dist/organizations/service.js.map +1 -1
- package/dist/progress/events.d.ts +14 -14
- package/dist/reporting/member/index.d.ts +2 -2
- package/dist/reporting/member/model.d.ts +56 -23
- package/dist/reporting/member/ports.d.ts +9 -6
- package/dist/reporting/member/service.d.ts +33 -14
- package/dist/reporting/member/service.js +138 -60
- package/dist/reporting/member/service.js.map +1 -1
- package/dist/shared/errors.d.ts +13 -1
- package/dist/shared/errors.js +18 -1
- package/dist/shared/errors.js.map +1 -1
- package/dist/shared/id.d.ts +3 -0
- package/dist/shared/id.js +4 -1
- package/dist/shared/id.js.map +1 -1
- package/dist/shared/mailer.d.ts +11 -1
- package/dist/shared/mailer.js +32 -5
- package/dist/shared/mailer.js.map +1 -1
- 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/automations.d.ts +8 -2
- package/dist/types/content.d.ts +2 -2
- package/dist/types/discussion.d.ts +2 -2
- package/dist/types/email-templates.d.ts +97 -3
- package/dist/types/identity.d.ts +2 -2
- package/dist/types/index.d.ts +7 -6
- package/dist/types/notifications.d.ts +157 -0
- package/dist/types/notifications.js +1 -0
- package/dist/types/schemas/automations.d.ts +1 -10
- package/dist/types/schemas/automations.js +1 -3
- package/dist/types/schemas/automations.js.map +1 -1
- package/dist/types/schemas/content.d.ts +62 -1
- package/dist/types/schemas/content.js +25 -3
- package/dist/types/schemas/content.js.map +1 -1
- package/dist/types/schemas/discussion.d.ts +85 -12
- package/dist/types/schemas/discussion.js +47 -13
- package/dist/types/schemas/discussion.js.map +1 -1
- package/dist/types/schemas/identity.d.ts +1 -85
- package/dist/types/schemas/identity.js +1 -42
- package/dist/types/schemas/identity.js.map +1 -1
- package/dist/types/schemas/index.d.ts +6 -5
- package/dist/types/schemas/index.js +6 -5
- 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/progress.d.ts +3 -3
- package/package.json +1 -1
- package/dist/automations/community-notifications.d.ts +0 -16
- package/dist/automations/community-notifications.js +0 -84
- package/dist/automations/community-notifications.js.map +0 -1
- package/dist/automations/seeds.d.ts +0 -17
- package/dist/automations/seeds.js +0 -235
- package/dist/automations/seeds.js.map +0 -1
- package/dist/identity/notifications.d.ts +0 -27
- package/dist/identity/notifications.js +0 -101
- package/dist/identity/notifications.js.map +0 -1
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { NotFoundError } from "../shared/errors.js";
|
|
2
|
+
import { noopLogger } from "../shared/logger.js";
|
|
3
|
+
import "../shared/settings.js";
|
|
4
|
+
import { assertValidCategoryList, offeringConfigured, storedCategoryList } from "../shared/notification-categories.js";
|
|
5
|
+
//#region src/content/notification-categories.ts
|
|
6
|
+
var CommunityNotificationCategories = class {
|
|
7
|
+
communities;
|
|
8
|
+
settings;
|
|
9
|
+
types;
|
|
10
|
+
channels;
|
|
11
|
+
logger;
|
|
12
|
+
constructor(params) {
|
|
13
|
+
this.communities = params.communities;
|
|
14
|
+
this.settings = params.settings;
|
|
15
|
+
this.types = params.types;
|
|
16
|
+
this.channels = params.channels;
|
|
17
|
+
this.logger = params.logger ?? noopLogger;
|
|
18
|
+
}
|
|
19
|
+
async get(orgId, communityId) {
|
|
20
|
+
await this.assertCommunity(orgId, communityId);
|
|
21
|
+
const stored = storedCategoryList((await this.settings.get(orgId, "content", communityId))?.notificationCategories);
|
|
22
|
+
return stored ? {
|
|
23
|
+
categories: offeringConfigured(stored, this.channels.list()),
|
|
24
|
+
source: "stored"
|
|
25
|
+
} : {
|
|
26
|
+
categories: this.defaults(),
|
|
27
|
+
source: "default"
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
async replace(orgId, communityId, categories) {
|
|
31
|
+
await this.assertCommunity(orgId, communityId);
|
|
32
|
+
const configured = this.channels.list();
|
|
33
|
+
assertValidCategoryList(categories, "community", this.types, configured);
|
|
34
|
+
const ordered = offeringConfigured(categories, configured);
|
|
35
|
+
await this.settings.patch(orgId, "content", communityId, { notificationCategories: ordered });
|
|
36
|
+
this.logger.info("community notification categories replaced", {
|
|
37
|
+
orgId,
|
|
38
|
+
communityId,
|
|
39
|
+
keys: categories.map((category) => category.key)
|
|
40
|
+
});
|
|
41
|
+
return {
|
|
42
|
+
categories: ordered,
|
|
43
|
+
source: "stored"
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
async reset(orgId, communityId) {
|
|
47
|
+
await this.assertCommunity(orgId, communityId);
|
|
48
|
+
await this.settings.patch(orgId, "content", communityId, { notificationCategories: null });
|
|
49
|
+
this.logger.info("community notification categories reset", {
|
|
50
|
+
orgId,
|
|
51
|
+
communityId
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
defaults() {
|
|
55
|
+
return this.types.defaults("community");
|
|
56
|
+
}
|
|
57
|
+
async assertCommunity(orgId, communityId) {
|
|
58
|
+
if (!await this.communities.findCommunityById(orgId, communityId)) throw new NotFoundError("Community", communityId);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
//#endregion
|
|
62
|
+
export { CommunityNotificationCategories };
|
|
63
|
+
|
|
64
|
+
//# sourceMappingURL=notification-categories.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification-categories.js","names":[],"sources":["../../src/content/notification-categories.ts"],"sourcesContent":["import type { NotificationCategory } from '../types/index.js';\nimport type {\n ChannelRegistry,\n Logger,\n NotificationCategoryService,\n NotificationTypeRegistry,\n} from '../shared/ports.js';\nimport { NotFoundError } from '../shared/errors.js';\nimport { noopLogger } from '../shared/logger.js';\nimport { SettingsNamespace, type SettingsService } from '../shared/settings.js';\nimport {\n assertValidCategoryList,\n offeringConfigured,\n storedCategoryList,\n} from '../shared/notification-categories.js';\nimport type { ContentRepository } from './ports.js';\n\nexport type CommunityNotificationCategoriesParams = {\n communities: Pick<ContentRepository, 'findCommunityById'>;\n settings: SettingsService;\n types: NotificationTypeRegistry;\n channels: ChannelRegistry;\n logger?: Logger;\n};\n\nexport class CommunityNotificationCategories implements NotificationCategoryService {\n private readonly communities: Pick<ContentRepository, 'findCommunityById'>;\n private readonly settings: SettingsService;\n private readonly types: NotificationTypeRegistry;\n private readonly channels: ChannelRegistry;\n private readonly logger: Logger;\n\n constructor(params: CommunityNotificationCategoriesParams) {\n this.communities = params.communities;\n this.settings = params.settings;\n this.types = params.types;\n this.channels = params.channels;\n this.logger = params.logger ?? noopLogger;\n }\n\n async get(\n orgId: string,\n communityId: string,\n ): Promise<{ categories: NotificationCategory[]; source: 'default' | 'stored' }> {\n await this.assertCommunity(orgId, communityId);\n const value = await this.settings.get<Record<string, unknown>>(\n orgId,\n SettingsNamespace.content,\n communityId,\n );\n const stored = storedCategoryList(value?.notificationCategories);\n return stored\n ? { categories: offeringConfigured(stored, this.channels.list()), source: 'stored' }\n : { categories: this.defaults(), source: 'default' };\n }\n\n async replace(\n orgId: string,\n communityId: string,\n categories: NotificationCategory[],\n ): Promise<{ categories: NotificationCategory[]; source: 'stored' }> {\n await this.assertCommunity(orgId, communityId);\n const configured = this.channels.list();\n assertValidCategoryList(categories, 'community', this.types, configured);\n const ordered = offeringConfigured(categories, configured);\n await this.settings.patch(orgId, SettingsNamespace.content, communityId, {\n notificationCategories: ordered,\n });\n this.logger.info('community notification categories replaced', {\n orgId,\n communityId,\n keys: categories.map((category) => category.key),\n });\n return { categories: ordered, source: 'stored' };\n }\n\n async reset(orgId: string, communityId: string): Promise<void> {\n await this.assertCommunity(orgId, communityId);\n await this.settings.patch(orgId, SettingsNamespace.content, communityId, {\n notificationCategories: null,\n });\n this.logger.info('community notification categories reset', { orgId, communityId });\n }\n\n defaults(): NotificationCategory[] {\n return this.types.defaults('community');\n }\n\n private async assertCommunity(orgId: string, communityId: string): Promise<void> {\n const community = await this.communities.findCommunityById(orgId, communityId);\n if (!community) {\n throw new NotFoundError('Community', communityId);\n }\n }\n}\n"],"mappings":";;;;;AAyBA,IAAa,kCAAb,MAAoF;CAClF;CACA;CACA;CACA;CACA;CAEA,YAAY,QAA+C;EACzD,KAAK,cAAc,OAAO;EAC1B,KAAK,WAAW,OAAO;EACvB,KAAK,QAAQ,OAAO;EACpB,KAAK,WAAW,OAAO;EACvB,KAAK,SAAS,OAAO,UAAU;CACjC;CAEA,MAAM,IACJ,OACA,aAC+E;EAC/E,MAAM,KAAK,gBAAgB,OAAO,WAAW;EAM7C,MAAM,SAAS,oBAAmB,MALd,KAAK,SAAS,IAChC,OAAA,WAEA,WACF,EAAA,EACyC,sBAAsB;EAC/D,OAAO,SACH;GAAE,YAAY,mBAAmB,QAAQ,KAAK,SAAS,KAAK,CAAC;GAAG,QAAQ;EAAS,IACjF;GAAE,YAAY,KAAK,SAAS;GAAG,QAAQ;EAAU;CACvD;CAEA,MAAM,QACJ,OACA,aACA,YACmE;EACnE,MAAM,KAAK,gBAAgB,OAAO,WAAW;EAC7C,MAAM,aAAa,KAAK,SAAS,KAAK;EACtC,wBAAwB,YAAY,aAAa,KAAK,OAAO,UAAU;EACvE,MAAM,UAAU,mBAAmB,YAAY,UAAU;EACzD,MAAM,KAAK,SAAS,MAAM,OAAA,WAAkC,aAAa,EACvE,wBAAwB,QAC1B,CAAC;EACD,KAAK,OAAO,KAAK,8CAA8C;GAC7D;GACA;GACA,MAAM,WAAW,KAAK,aAAa,SAAS,GAAG;EACjD,CAAC;EACD,OAAO;GAAE,YAAY;GAAS,QAAQ;EAAS;CACjD;CAEA,MAAM,MAAM,OAAe,aAAoC;EAC7D,MAAM,KAAK,gBAAgB,OAAO,WAAW;EAC7C,MAAM,KAAK,SAAS,MAAM,OAAA,WAAkC,aAAa,EACvE,wBAAwB,KAC1B,CAAC;EACD,KAAK,OAAO,KAAK,2CAA2C;GAAE;GAAO;EAAY,CAAC;CACpF;CAEA,WAAmC;EACjC,OAAO,KAAK,MAAM,SAAS,WAAW;CACxC;CAEA,MAAc,gBAAgB,OAAe,aAAoC;EAE/E,IAAI,CAAC,MADmB,KAAK,YAAY,kBAAkB,OAAO,WAAW,GAE3E,MAAM,IAAI,cAAc,aAAa,WAAW;CAEpD;AACF"}
|
package/dist/content/ports.d.ts
CHANGED
|
@@ -1,11 +1,25 @@
|
|
|
1
1
|
import { Page } from "../types/shared.js";
|
|
2
|
-
import { Activity, ActivityAsset, ActivityView, AddDownloadAssetInput, Bundle, BundleItem, Community, CommunityView, Course, CourseSettings, CourseView, CreateBundleInput, CreateCommunityInput, CreateCourseInput, CreateDownloadInput, CreateSpaceInput, DmSettings, Download, DownloadAsset, DownloadFile, DownloadView, ListBundlesQuery, ListCommunitiesQuery, ListCoursesQuery, ListDownloadsQuery, Module,
|
|
2
|
+
import { Activity, ActivityAsset, ActivityView, AddDownloadAssetInput, Bundle, BundleItem, Community, CommunityView, Course, CourseSettings, CourseView, CreateBundleInput, CreateCommunityInput, CreateCourseInput, CreateDownloadInput, CreateSpaceInput, DigestSchedule, DmSettings, Download, DownloadAsset, DownloadFile, DownloadView, ListBundlesQuery, ListCommunitiesQuery, ListCoursesQuery, ListDownloadsQuery, Module, PatchCommunitySettingsInput, SaveActivityInput, SetSpaceTopicsInput, Space, SpaceDetail, UpdateBundleInput, UpdateCommunityInput, UpdateCourseInput, UpdateDownloadInput, UpdateSpaceInput } from "../types/schemas/content.js";
|
|
3
|
+
import { SubjectRef } from "../types/notifications.js";
|
|
4
|
+
import "../types/index.js";
|
|
3
5
|
import { OutboxAppender, UnitOfWork } from "../shared/ports.js";
|
|
4
6
|
import "./model.js";
|
|
5
7
|
import "./types.js";
|
|
6
8
|
import { Actor } from "../shared/actor.js";
|
|
7
9
|
//#region src/content/ports.d.ts
|
|
8
10
|
interface ContentService extends DownloadablesService, CourseManagementService, CommunitiesService {}
|
|
11
|
+
interface ItemTitle {
|
|
12
|
+
title: string;
|
|
13
|
+
excerpt?: string;
|
|
14
|
+
}
|
|
15
|
+
interface ItemTitles {
|
|
16
|
+
titlesFor(orgId: string, actor: Actor, refs: SubjectRef[]): Promise<Record<string, ItemTitle>>;
|
|
17
|
+
}
|
|
18
|
+
interface ItemTitleAccess {
|
|
19
|
+
hasAccess(orgId: string, orgUserId: string, contentId: string): Promise<boolean>;
|
|
20
|
+
isCommunityMember(orgId: string, actor: Actor, communityId: string): Promise<boolean>;
|
|
21
|
+
canOpenSpace(orgId: string, actor: Actor, spaceId: string): Promise<boolean>;
|
|
22
|
+
}
|
|
9
23
|
interface CommunityReader {
|
|
10
24
|
getSpace(orgId: string, spaceId: string): Promise<SpaceDetail | null>;
|
|
11
25
|
listSpaces(orgId: string, communityId: string): Promise<SpaceDetail[]>;
|
|
@@ -14,10 +28,15 @@ interface CommunityReader {
|
|
|
14
28
|
interface SpaceRowLock {
|
|
15
29
|
lockSpace(orgId: string, spaceId: string): Promise<Space | null>;
|
|
16
30
|
}
|
|
31
|
+
interface CommunityDigest {
|
|
32
|
+
orgId: string;
|
|
33
|
+
communityId: string;
|
|
34
|
+
digest: DigestSchedule;
|
|
35
|
+
}
|
|
17
36
|
interface CommunitiesService extends CommunityReader {
|
|
18
37
|
listCommunities(orgId: string, query: ListCommunitiesQuery): Promise<Page<CommunityView>>;
|
|
19
38
|
getCommunity(orgId: string, id: string): Promise<CommunityView | null>;
|
|
20
|
-
|
|
39
|
+
communitiesWithDigest(): Promise<CommunityDigest[]>;
|
|
21
40
|
listCommunitiesById(orgId: string, ids: string[]): Promise<Community[]>;
|
|
22
41
|
getCommunitySpace(orgId: string, communityId: string, spaceId: string): Promise<SpaceDetail | null>;
|
|
23
42
|
createCommunity(orgId: string, input: CreateCommunityInput, actor: Actor): Promise<CommunityView>;
|
|
@@ -25,7 +44,7 @@ interface CommunitiesService extends CommunityReader {
|
|
|
25
44
|
publishCommunity(orgId: string, id: string, actor: Actor): Promise<CommunityView>;
|
|
26
45
|
unpublishCommunity(orgId: string, id: string, actor: Actor): Promise<CommunityView>;
|
|
27
46
|
deleteCommunity(orgId: string, id: string, actor: Actor): Promise<void>;
|
|
28
|
-
|
|
47
|
+
patchCommunitySettings(orgId: string, id: string, patch: PatchCommunitySettingsInput, actor: Actor): Promise<CommunityView>;
|
|
29
48
|
createSpace(orgId: string, communityId: string, input: CreateSpaceInput, actor: Actor): Promise<SpaceDetail>;
|
|
30
49
|
updateSpace(orgId: string, communityId: string, spaceId: string, patch: UpdateSpaceInput, actor: Actor): Promise<SpaceDetail>;
|
|
31
50
|
deleteSpace(orgId: string, communityId: string, spaceId: string, actor: Actor): Promise<void>;
|
|
@@ -139,10 +158,10 @@ interface ContentRepository {
|
|
|
139
158
|
listCommunities(orgId: string, query: ListCommunitiesQuery): Promise<Page<Community>>;
|
|
140
159
|
findCommunityById(orgId: string, id: string): Promise<Community | null>;
|
|
141
160
|
findCommunitiesByIds(orgId: string, ids: string[]): Promise<Community[]>;
|
|
142
|
-
|
|
161
|
+
communitiesWithDigest(): Promise<CommunityDigest[]>;
|
|
143
162
|
createCommunity(orgId: string, input: CreateCommunityInput, slug: string): Promise<Community>;
|
|
144
163
|
updateCommunity(orgId: string, id: string, patch: UpdateCommunityInput): Promise<Community | null>;
|
|
145
|
-
|
|
164
|
+
patchCommunitySettings(orgId: string, id: string, patch: PatchCommunitySettingsInput): Promise<Community | null>;
|
|
146
165
|
deleteCommunity(orgId: string, id: string): Promise<boolean>;
|
|
147
166
|
deleteCommunitySettings(orgId: string, id: string): Promise<void>;
|
|
148
167
|
listSpaces(orgId: string, communityId: string): Promise<SpaceDetail[]>;
|
|
@@ -165,5 +184,5 @@ interface ContentTxScope {
|
|
|
165
184
|
}
|
|
166
185
|
type ContentUnitOfWork = UnitOfWork<ContentTxScope>;
|
|
167
186
|
//#endregion
|
|
168
|
-
export { BundlesService, CommunitiesService, CommunityReader, ContentRepository, ContentService, ContentTxScope, ContentUnitOfWork, CourseManagementService, DownloadablesService, SpaceRowLock };
|
|
187
|
+
export { BundlesService, CommunitiesService, CommunityDigest, CommunityReader, ContentRepository, ContentService, ContentTxScope, ContentUnitOfWork, CourseManagementService, DownloadablesService, ItemTitle, ItemTitleAccess, ItemTitles, SpaceRowLock };
|
|
169
188
|
//# sourceMappingURL=ports.d.ts.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Page } from "../types/shared.js";
|
|
2
2
|
import { Logger } from "../types/ports.js";
|
|
3
|
-
import { Activity, ActivityAsset, ActivityView, AddDownloadAssetInput, Bundle, BundleItem, Community, CommunityView, CourseSettings, CourseView, CreateBundleInput, CreateCommunityInput, CreateCourseInput, CreateDownloadInput, CreateSpaceInput, DmSettings, DownloadFile, DownloadView, ListBundlesQuery, ListCommunitiesQuery, ListCoursesQuery, ListDownloadsQuery, Module,
|
|
3
|
+
import { Activity, ActivityAsset, ActivityView, AddDownloadAssetInput, Bundle, BundleItem, Community, CommunityView, CourseSettings, CourseView, CreateBundleInput, CreateCommunityInput, CreateCourseInput, CreateDownloadInput, CreateSpaceInput, DmSettings, DownloadFile, DownloadView, ListBundlesQuery, ListCommunitiesQuery, ListCoursesQuery, ListDownloadsQuery, Module, PatchCommunitySettingsInput, SaveActivityInput, SetSpaceTopicsInput, SpaceDetail, UpdateBundleInput, UpdateCommunityInput, UpdateCourseInput, UpdateDownloadInput, UpdateSpaceInput } from "../types/schemas/content.js";
|
|
4
4
|
import "../shared/ports.js";
|
|
5
5
|
import { FileUrls } from "../assets/file-urls.js";
|
|
6
6
|
import { AssetFiles, LibraryAssetReader } from "../assets/ports.js";
|
|
@@ -8,7 +8,7 @@ import "../assets/index.js";
|
|
|
8
8
|
import "./model.js";
|
|
9
9
|
import "./types.js";
|
|
10
10
|
import { Actor } from "../shared/actor.js";
|
|
11
|
-
import { BundlesService, CommunitiesService, ContentRepository, ContentUnitOfWork, CourseManagementService, DownloadablesService } from "./ports.js";
|
|
11
|
+
import { BundlesService, CommunitiesService, CommunityDigest, ContentRepository, ContentUnitOfWork, CourseManagementService, DownloadablesService } from "./ports.js";
|
|
12
12
|
//#region src/content/service.d.ts
|
|
13
13
|
type ContentServiceParams = {
|
|
14
14
|
repo: ContentRepository;
|
|
@@ -73,7 +73,7 @@ declare class ContentService implements CourseManagementService, DownloadablesSe
|
|
|
73
73
|
private resolvedSpace;
|
|
74
74
|
listCommunities(orgId: string, query: ListCommunitiesQuery): Promise<Page<CommunityView>>;
|
|
75
75
|
getCommunity(orgId: string, id: string): Promise<CommunityView | null>;
|
|
76
|
-
|
|
76
|
+
communitiesWithDigest(): Promise<CommunityDigest[]>;
|
|
77
77
|
listCommunitiesById(orgId: string, ids: string[]): Promise<Community[]>;
|
|
78
78
|
getSpace(orgId: string, spaceId: string): Promise<SpaceDetail | null>;
|
|
79
79
|
getCommunitySpace(orgId: string, communityId: string, spaceId: string): Promise<SpaceDetail | null>;
|
|
@@ -84,7 +84,7 @@ declare class ContentService implements CourseManagementService, DownloadablesSe
|
|
|
84
84
|
publishCommunity(orgId: string, id: string, actor: Actor): Promise<CommunityView>;
|
|
85
85
|
unpublishCommunity(orgId: string, id: string, actor: Actor): Promise<CommunityView>;
|
|
86
86
|
deleteCommunity(orgId: string, id: string, actor: Actor): Promise<void>;
|
|
87
|
-
|
|
87
|
+
patchCommunitySettings(orgId: string, id: string, patch: PatchCommunitySettingsInput, actor: Actor): Promise<CommunityView>;
|
|
88
88
|
createSpace(orgId: string, communityId: string, input: CreateSpaceInput, actor: Actor): Promise<SpaceDetail>;
|
|
89
89
|
updateSpace(orgId: string, communityId: string, spaceId: string, patch: UpdateSpaceInput, actor: Actor): Promise<SpaceDetail>;
|
|
90
90
|
deleteSpace(orgId: string, communityId: string, spaceId: string, actor: Actor): Promise<void>;
|
package/dist/content/service.js
CHANGED
|
@@ -7,6 +7,9 @@ import { contentEvents } from "./events.js";
|
|
|
7
7
|
function slugify(title) {
|
|
8
8
|
return title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "");
|
|
9
9
|
}
|
|
10
|
+
function isPublishedActivity(settings) {
|
|
11
|
+
return settings?.published !== false;
|
|
12
|
+
}
|
|
10
13
|
function actorMetadata(actor) {
|
|
11
14
|
return { actorOrgUserId: actor.id };
|
|
12
15
|
}
|
|
@@ -299,6 +302,7 @@ var ContentService = class {
|
|
|
299
302
|
async saveActivity(orgId, courseId, moduleId, input, activityId) {
|
|
300
303
|
await this.assertLibraryAssets(orgId, input.assetIds ?? []);
|
|
301
304
|
const { modules, activity } = await this.uow.run(async ({ content, outbox }) => {
|
|
305
|
+
let wasPublished = false;
|
|
302
306
|
if (activityId) {
|
|
303
307
|
const existing = await content.findActivity(orgId, activityId);
|
|
304
308
|
if (!existing || existing.moduleId !== moduleId || existing.courseId !== courseId) {
|
|
@@ -310,6 +314,7 @@ var ContentService = class {
|
|
|
310
314
|
});
|
|
311
315
|
throw new NotFoundError("Activity", activityId);
|
|
312
316
|
}
|
|
317
|
+
wasPublished = isPublishedActivity(existing.settings);
|
|
313
318
|
} else {
|
|
314
319
|
const module = await content.findModule(orgId, moduleId);
|
|
315
320
|
if (!module || module.courseId !== courseId) {
|
|
@@ -322,13 +327,24 @@ var ContentService = class {
|
|
|
322
327
|
}
|
|
323
328
|
}
|
|
324
329
|
const { modules: all, activity: saved } = await content.saveActivity(orgId, courseId, moduleId, input, activityId);
|
|
325
|
-
|
|
330
|
+
const events = [activityId ? contentEvents.activityUpdated.make({
|
|
326
331
|
orgId,
|
|
327
332
|
data: saved
|
|
328
333
|
}) : contentEvents.activityCreated.make({
|
|
329
334
|
orgId,
|
|
330
335
|
data: saved
|
|
331
|
-
})]
|
|
336
|
+
})];
|
|
337
|
+
if (!wasPublished && isPublishedActivity(saved.settings)) {
|
|
338
|
+
if ((await content.findCourseById(orgId, courseId))?.status === "published") events.push(contentEvents.activityPublished.make({
|
|
339
|
+
orgId,
|
|
340
|
+
data: {
|
|
341
|
+
activityId: saved.id,
|
|
342
|
+
moduleId,
|
|
343
|
+
courseId
|
|
344
|
+
}
|
|
345
|
+
}));
|
|
346
|
+
}
|
|
347
|
+
await outbox.append(events);
|
|
332
348
|
return {
|
|
333
349
|
modules: all,
|
|
334
350
|
activity: saved
|
|
@@ -685,8 +701,8 @@ var ContentService = class {
|
|
|
685
701
|
const community = await this.repo.findCommunityById(orgId, id);
|
|
686
702
|
return community ? this.withThumbnail(community) : null;
|
|
687
703
|
}
|
|
688
|
-
|
|
689
|
-
return this.repo.
|
|
704
|
+
communitiesWithDigest() {
|
|
705
|
+
return this.repo.communitiesWithDigest();
|
|
690
706
|
}
|
|
691
707
|
listCommunitiesById(orgId, ids) {
|
|
692
708
|
return ids.length ? this.repo.findCommunitiesByIds(orgId, ids) : Promise.resolve([]);
|
|
@@ -783,12 +799,12 @@ var ContentService = class {
|
|
|
783
799
|
actorId: actor.id
|
|
784
800
|
});
|
|
785
801
|
}
|
|
786
|
-
async
|
|
802
|
+
async patchCommunitySettings(orgId, id, patch, actor) {
|
|
787
803
|
assertConfigurator(actor);
|
|
788
804
|
const community = await this.uow.run(async ({ content, outbox }) => {
|
|
789
|
-
const updated = await content.
|
|
805
|
+
const updated = await content.patchCommunitySettings(orgId, id, patch);
|
|
790
806
|
if (!updated) {
|
|
791
|
-
this.logger.warn("community
|
|
807
|
+
this.logger.warn("community settings patch rejected — not found", {
|
|
792
808
|
orgId,
|
|
793
809
|
communityId: id,
|
|
794
810
|
actorId: actor.id
|
|
@@ -802,7 +818,7 @@ var ContentService = class {
|
|
|
802
818
|
})]);
|
|
803
819
|
return updated;
|
|
804
820
|
});
|
|
805
|
-
this.logger.info("community
|
|
821
|
+
this.logger.info("community settings patched", {
|
|
806
822
|
orgId,
|
|
807
823
|
communityId: id,
|
|
808
824
|
actorId: actor.id
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.js","names":[],"sources":["../../src/content/service.ts"],"sourcesContent":["import type {\n Activity,\n ActivityAsset,\n ActivityView,\n Bundle,\n BundleItem,\n Community,\n CommunityView,\n CourseSettings,\n CourseView,\n DmSettings,\n DownloadAsset,\n DownloadFile,\n DownloadView,\n Module,\n SaveActivityInput,\n Space,\n SpaceDetail,\n SpaceSettings,\n} from './model.js';\nimport type {\n BundlesService,\n CommunitiesService,\n CourseManagementService,\n ContentRepository,\n ContentUnitOfWork,\n DownloadablesService,\n} from './ports.js';\nimport type {\n AddDownloadAssetInput,\n CreateBundleInput,\n CreateCommunityInput,\n CreateCourseInput,\n CreateDownloadInput,\n CreateSpaceInput,\n ListBundlesQuery,\n ListCommunitiesQuery,\n ListCoursesQuery,\n ListDownloadsQuery,\n Page,\n PatchDmSettingsInput,\n SetSpaceTopicsInput,\n UpdateBundleInput,\n UpdateCommunityInput,\n UpdateCourseInput,\n UpdateDownloadInput,\n UpdateSpaceInput,\n} from './types.js';\nimport { contentEvents } from './events.js';\nimport type { Actor } from '../shared/actor.js';\nimport type { AssetFiles, FileUrls, LibraryAssetReader } from '../assets/index.js';\nimport type { Logger, NewDomainEvent } from '../shared/ports.js';\nimport {\n ConflictError,\n ForbiddenError,\n InvalidInputError,\n NotFoundError,\n} from '../shared/errors.js';\nimport { noopLogger } from '../shared/logger.js';\nimport { spaceSettingsDefaults } from '../types/schemas/content.js';\n\n/** URL-safe slug derived from a title. Domain rule owned by the service. */\nfunction slugify(title: string): string {\n return title\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/(^-|-$)/g, '');\n}\n\nexport type ContentServiceParams = {\n repo: ContentRepository;\n uow: ContentUnitOfWork;\n libraryAssets: LibraryAssetReader;\n files: Pick<AssetFiles, 'readyFiles'>;\n fileUrls: FileUrls;\n logger?: Logger;\n};\n\nfunction actorMetadata(actor: Actor): { actorOrgUserId: string } {\n return { actorOrgUserId: actor.id };\n}\n\nfunction assertConfigurator(actor: Actor): void {\n if (actor.role !== 'owner' && actor.role !== 'admin') {\n throw new ForbiddenError('Only an owner or an admin can configure a community');\n }\n}\n\ntype WithThumbnail = {\n id: string;\n type: 'course' | 'download' | 'community';\n thumbnailAssetId: string | null;\n};\n\nfunction sameIdSet(current: string[], requested: string[]): boolean {\n if (current.length !== requested.length) {\n return false;\n }\n const have = new Set(current);\n return requested.every((id) => have.has(id)) && new Set(requested).size === requested.length;\n}\n\nexport class ContentService\n implements CourseManagementService, DownloadablesService, BundlesService, CommunitiesService\n{\n private readonly repo: ContentRepository;\n private readonly uow: ContentUnitOfWork;\n private readonly libraryAssets: LibraryAssetReader;\n private readonly files: Pick<AssetFiles, 'readyFiles'>;\n private readonly fileUrls: FileUrls;\n private readonly logger: Logger;\n\n constructor(params: ContentServiceParams) {\n this.repo = params.repo;\n this.uow = params.uow;\n this.libraryAssets = params.libraryAssets;\n this.files = params.files;\n this.fileUrls = params.fileUrls;\n this.logger = params.logger ?? noopLogger;\n }\n\n private withThumbnail<T extends WithThumbnail>(item: T): T & { thumbnailUrl: string | null } {\n return {\n ...item,\n thumbnailUrl: item.thumbnailAssetId ? this.fileUrls.thumbnail(item.type, item.id) : null,\n };\n }\n\n private pageWithThumbnails<T extends WithThumbnail>(\n page: Page<T>,\n ): Page<T & { thumbnailUrl: string | null }> {\n return { ...page, rows: page.rows.map((row) => this.withThumbnail(row)) };\n }\n\n private async downloadFiles(orgId: string, links: DownloadAsset[]): Promise<DownloadFile[]> {\n const ready = await this.files.readyFiles(\n orgId,\n links.map((link) => link.assetId),\n );\n return links.flatMap((link) => {\n const file = ready[link.assetId];\n return file\n ? [{ ...link, ...file, url: this.fileUrls.downloadFile(link.downloadId, link.assetId) }]\n : [];\n });\n }\n\n async listCourses(orgId: string, query: ListCoursesQuery): Promise<Page<CourseView>> {\n return this.pageWithThumbnails(await this.repo.listCourses(orgId, query));\n }\n\n async getCourse(orgId: string, id: string): Promise<CourseView | null> {\n const course = await this.repo.findCourseById(orgId, id);\n return course ? this.withThumbnail(course) : null;\n }\n\n async createCourse(orgId: string, input: CreateCourseInput): Promise<CourseView> {\n const course = await this.uow.run(async ({ content, outbox }) => {\n const created = await content.createCourse(orgId, input, slugify(input.title));\n await outbox.append([contentEvents.courseCreated.make({ orgId, data: created })]);\n return created;\n });\n this.logger.info('course created', { orgId, courseId: course.id, title: course.title });\n return this.withThumbnail(course);\n }\n\n async updateCourse(orgId: string, id: string, patch: UpdateCourseInput): Promise<CourseView> {\n await this.assertLibraryAssets(orgId, [patch.thumbnailAssetId], 'A course');\n const course = await this.uow.run(async ({ content, outbox }) => {\n const updated = await content.updateCourse(orgId, id, patch);\n if (!updated) {\n this.logger.warn('course update rejected — not found', { orgId, courseId: id });\n throw new NotFoundError('Course', id);\n }\n await outbox.append([contentEvents.courseUpdated.make({ orgId, data: updated })]);\n return updated;\n });\n this.logger.info('course updated', { orgId, courseId: id, fields: Object.keys(patch) });\n return this.withThumbnail(course);\n }\n\n async patchCourseSettings(\n orgId: string,\n id: string,\n value: Partial<CourseSettings>,\n ): Promise<CourseSettings> {\n const merged = await this.uow.run(async ({ content, outbox }) => {\n const course = await content.findCourseById(orgId, id);\n if (!course) {\n this.logger.warn('course settings patch rejected — not found', { orgId, courseId: id });\n throw new NotFoundError('Course', id);\n }\n const settings = await content.patchCourseSettings(orgId, id, value);\n await outbox.append([\n contentEvents.courseUpdated.make({ orgId, data: { ...course, settings } }),\n ]);\n return settings;\n });\n this.logger.info('course settings patched', { orgId, courseId: id, value });\n return merged;\n }\n\n async deleteCourse(orgId: string, id: string, actor: Actor): Promise<void> {\n await this.uow.run(async ({ content, outbox }) => {\n // Snapshot before the delete — the event carries the last known state.\n const course = await content.findCourseById(orgId, id);\n if (!course) {\n this.logger.warn('course delete rejected — not found', { orgId, courseId: id });\n throw new NotFoundError('Course', id);\n }\n const linked = await content.spacesLinkingContent(orgId, id);\n const ok = await content.deleteCourse(orgId, id);\n if (!ok) {\n throw new NotFoundError('Course', id);\n }\n await outbox.append([\n contentEvents.courseDeleted.make({ orgId, data: course }),\n ...(await this.spaceUpdates(content, orgId, linked, actor)),\n ]);\n });\n this.logger.info('course deleted', { orgId, courseId: id });\n }\n\n // --- modules & activities ------------------------------------------------\n\n listCourseModules(orgId: string, courseId: string): Promise<Module[]> {\n return this.repo.listCourseModules(orgId, courseId);\n }\n listCourseActivities(orgId: string, courseId: string): Promise<Activity[]> {\n return this.repo.listActivitiesForCourse(orgId, courseId);\n }\n async listCourseActivityViews(orgId: string, courseId: string): Promise<ActivityView[]> {\n const [activities, links] = await Promise.all([\n this.repo.listActivitiesForCourse(orgId, courseId),\n this.repo.listActivityAssetsForCourse(orgId, courseId),\n ]);\n return activities.map((activity) => ({\n ...activity,\n assetUrls: Object.fromEntries(\n links\n .filter((link) => link.activityId === activity.id)\n .map((link) => [link.assetId, this.fileUrls.activityAsset(activity.id, link.assetId)]),\n ),\n }));\n }\n listCourseActivityAssets(orgId: string, courseId: string): Promise<ActivityAsset[]> {\n return this.repo.listActivityAssetsForCourse(orgId, courseId);\n }\n getActivity(orgId: string, activityId: string): Promise<Activity | null> {\n return this.repo.findActivity(orgId, activityId);\n }\n getModule(orgId: string, moduleId: string): Promise<Module | null> {\n return this.repo.findModule(orgId, moduleId);\n }\n\n async reorderModules(orgId: string, courseId: string, orderedIds: string[]): Promise<Module[]> {\n const modules = await this.uow.run(async ({ content, outbox }) => {\n const reordered = await content.reorderModules(orgId, courseId, orderedIds);\n await outbox.append([contentEvents.modulesReordered.make({ orgId, data: reordered })]);\n return reordered;\n });\n this.logger.debug('modules reordered', {\n orgId,\n courseId,\n moduleIds: modules.map((m) => m.id),\n });\n return modules;\n }\n\n async createModule(orgId: string, courseId: string, title: string): Promise<Module[]> {\n const { modules, created } = await this.uow.run(async ({ content, outbox }) => {\n const all = await content.createModule(orgId, courseId, title);\n // The list is ordered by seq and the new module is appended at max(seq)+1.\n const module = all.at(-1);\n if (!module) {\n throw new Error('failed to load created module');\n }\n await outbox.append([contentEvents.moduleCreated.make({ orgId, data: module })]);\n return { modules: all, created: module };\n });\n this.logger.info('module created', { orgId, courseId, moduleId: created.id, title });\n return modules;\n }\n\n async updateModule(\n orgId: string,\n courseId: string,\n moduleId: string,\n title: string,\n ): Promise<Module[]> {\n const modules = await this.uow.run(async ({ content, outbox }) => {\n const existing = await content.findModule(orgId, moduleId);\n if (!existing || existing.courseId !== courseId) {\n this.logger.warn('module update rejected — not found in course', {\n orgId,\n courseId,\n moduleId,\n });\n throw new NotFoundError('Module', moduleId);\n }\n const all = await content.updateModule(orgId, courseId, moduleId, title);\n const module = all.find((m) => m.id === moduleId);\n if (!module) {\n throw new NotFoundError('Module', moduleId);\n }\n await outbox.append([contentEvents.moduleUpdated.make({ orgId, data: module })]);\n return all;\n });\n this.logger.info('module updated', { orgId, courseId, moduleId, title });\n return modules;\n }\n\n async deleteModule(orgId: string, courseId: string, moduleId: string): Promise<Module[]> {\n const modules = await this.uow.run(async ({ content, outbox }) => {\n // Snapshot before the delete — the event carries the last known state.\n const module = await content.findModule(orgId, moduleId);\n if (!module || module.courseId !== courseId) {\n this.logger.warn('module delete rejected — not found in course', {\n orgId,\n courseId,\n moduleId,\n });\n throw new NotFoundError('Module', moduleId);\n }\n const remaining = await content.deleteModule(orgId, courseId, moduleId);\n await outbox.append([contentEvents.moduleDeleted.make({ orgId, data: module })]);\n return remaining;\n });\n this.logger.info('module deleted', { orgId, courseId, moduleId });\n return modules;\n }\n\n async reorderActivities(\n orgId: string,\n courseId: string,\n moduleId: string,\n orderedIds: string[],\n ): Promise<Module[]> {\n const modules = await this.uow.run(async ({ content, outbox }) => {\n const reordered = await content.reorderActivities(orgId, courseId, moduleId, orderedIds);\n const module = reordered.find((m) => m.id === moduleId);\n if (!module) {\n throw new NotFoundError('Module', moduleId);\n }\n await outbox.append([contentEvents.activitiesReordered.make({ orgId, data: module })]);\n return reordered;\n });\n this.logger.debug('activities reordered', { orgId, courseId, moduleId });\n return modules;\n }\n\n private async assertLibraryAssets(\n orgId: string,\n assetIds: (string | null | undefined)[],\n user = 'An activity',\n ): Promise<void> {\n const ids = assetIds.filter((id): id is string => typeof id === 'string');\n if (ids.length === 0) {\n return;\n }\n const library = new Set(await this.libraryAssets.libraryAssetsAmong(orgId, ids));\n const refused = ids.filter((id) => !library.has(id));\n if (refused.length > 0) {\n this.logger.warn('library assets refused', { orgId, assetIds: refused });\n throw new ConflictError(\n `${user} can only use ready files from the media library. Not available: ${refused.join(', ')}`,\n );\n }\n }\n\n async saveActivity(\n orgId: string,\n courseId: string,\n moduleId: string,\n input: SaveActivityInput,\n activityId?: string,\n ): Promise<Module[]> {\n await this.assertLibraryAssets(orgId, input.assetIds ?? []);\n const { modules, activity } = await this.uow.run(async ({ content, outbox }) => {\n if (activityId) {\n const existing = await content.findActivity(orgId, activityId);\n if (!existing || existing.moduleId !== moduleId || existing.courseId !== courseId) {\n this.logger.warn('activity update rejected — not found in module', {\n orgId,\n courseId,\n moduleId,\n activityId,\n });\n throw new NotFoundError('Activity', activityId);\n }\n } else {\n const module = await content.findModule(orgId, moduleId);\n if (!module || module.courseId !== courseId) {\n this.logger.warn('activity create rejected — module not found in course', {\n orgId,\n courseId,\n moduleId,\n });\n throw new NotFoundError('Module', moduleId);\n }\n }\n\n const { modules: all, activity: saved } = await content.saveActivity(\n orgId,\n courseId,\n moduleId,\n input,\n activityId,\n );\n await outbox.append([\n activityId\n ? contentEvents.activityUpdated.make({ orgId, data: saved })\n : contentEvents.activityCreated.make({ orgId, data: saved }),\n ]);\n return { modules: all, activity: saved };\n });\n this.logger.info(activityId ? 'activity updated' : 'activity created', {\n orgId,\n courseId,\n moduleId,\n activityId: activity.id,\n });\n return modules;\n }\n\n async deleteActivity(\n orgId: string,\n courseId: string,\n moduleId: string,\n activityId: string,\n ): Promise<Module[]> {\n const modules = await this.uow.run(async ({ content, outbox }) => {\n // Snapshot before the delete — the event carries the last known state.\n const activity = await content.findActivity(orgId, activityId);\n if (!activity || activity.moduleId !== moduleId || activity.courseId !== courseId) {\n this.logger.warn('activity delete rejected — not found in module', {\n orgId,\n courseId,\n moduleId,\n activityId,\n });\n throw new NotFoundError('Activity', activityId);\n }\n const remaining = await content.deleteActivity(orgId, courseId, moduleId, activityId);\n await outbox.append([contentEvents.activityDeleted.make({ orgId, data: activity })]);\n return remaining;\n });\n this.logger.info('activity deleted', { orgId, courseId, moduleId, activityId });\n return modules;\n }\n\n // --- downloads ------------------------------------------------------------\n\n async listDownloads(orgId: string, query: ListDownloadsQuery): Promise<Page<DownloadView>> {\n return this.pageWithThumbnails(await this.repo.listDownloads(orgId, query));\n }\n\n async getDownload(orgId: string, id: string): Promise<DownloadView | null> {\n const download = await this.repo.getDownload(orgId, id);\n return download ? this.withThumbnail(download) : null;\n }\n\n async createDownload(orgId: string, input: CreateDownloadInput): Promise<DownloadView> {\n const download = await this.uow.run(async ({ content, outbox }) => {\n const created = await content.createDownload(orgId, input, slugify(input.title));\n await outbox.append([contentEvents.downloadCreated.make({ orgId, data: created })]);\n return created;\n });\n this.logger.info('download created', { orgId, downloadId: download.id, title: download.title });\n return this.withThumbnail(download);\n }\n\n async updateDownload(\n orgId: string,\n id: string,\n patch: UpdateDownloadInput,\n ): Promise<DownloadView> {\n await this.assertLibraryAssets(orgId, [patch.thumbnailAssetId], 'A download');\n const download = await this.uow.run(async ({ content, outbox }) => {\n const updated = await content.updateDownload(orgId, id, patch);\n if (!updated) {\n this.logger.warn('download update rejected — not found', { orgId, downloadId: id });\n throw new NotFoundError('Download', id);\n }\n await outbox.append([contentEvents.downloadUpdated.make({ orgId, data: updated })]);\n return updated;\n });\n this.logger.info('download updated', { orgId, downloadId: id, fields: Object.keys(patch) });\n return this.withThumbnail(download);\n }\n\n async removeDownload(orgId: string, id: string, actor: Actor): Promise<void> {\n await this.uow.run(async ({ content, outbox }) => {\n // Snapshot before the delete — the event carries the last known state.\n const download = await content.getDownload(orgId, id);\n if (!download) {\n this.logger.warn('download delete rejected — not found', { orgId, downloadId: id });\n throw new NotFoundError('Download', id);\n }\n const linked = await content.spacesLinkingContent(orgId, id);\n const ok = await content.deleteDownload(orgId, id);\n if (!ok) {\n throw new NotFoundError('Download', id);\n }\n await outbox.append([\n contentEvents.downloadDeleted.make({ orgId, data: download }),\n ...(await this.spaceUpdates(content, orgId, linked, actor)),\n ]);\n });\n this.logger.info('download deleted', { orgId, downloadId: id });\n }\n\n // --- download asset links ------------------------------------------------\n\n async listDownloadAssets(orgId: string, downloadId: string): Promise<DownloadFile[]> {\n return this.downloadFiles(orgId, await this.repo.listDownloadAssets(orgId, downloadId));\n }\n\n async addDownloadAsset(\n orgId: string,\n downloadId: string,\n input: AddDownloadAssetInput,\n ): Promise<DownloadFile[]> {\n await this.assertLibraryAssets(orgId, [input.assetId], 'A download');\n const assets = await this.uow.run(async ({ content, outbox }) => {\n const assets = await content.addDownloadAsset(orgId, downloadId, input);\n await outbox.append([\n contentEvents.downloadAssetAdded.make({ orgId, data: { downloadId, assets } }),\n ]);\n return assets;\n });\n this.logger.info('download asset added', { orgId, downloadId, assetId: input.assetId });\n return this.downloadFiles(orgId, assets);\n }\n\n async removeDownloadAsset(\n orgId: string,\n downloadId: string,\n assetId: string,\n ): Promise<DownloadFile[]> {\n const assets = await this.uow.run(async ({ content, outbox }) => {\n const assets = await content.removeDownloadAsset(orgId, downloadId, assetId);\n await outbox.append([\n contentEvents.downloadAssetRemoved.make({ orgId, data: { downloadId, assets } }),\n ]);\n return assets;\n });\n this.logger.info('download asset removed', { orgId, downloadId, assetId });\n return this.downloadFiles(orgId, assets);\n }\n\n async renameDownloadAsset(\n orgId: string,\n downloadId: string,\n assetId: string,\n displayName: string | null,\n ): Promise<DownloadFile[]> {\n const assets = await this.uow.run(async ({ content, outbox }) => {\n const assets = await content.renameDownloadAsset(orgId, downloadId, assetId, displayName);\n await outbox.append([\n contentEvents.downloadAssetRenamed.make({ orgId, data: { downloadId, assets } }),\n ]);\n return assets;\n });\n this.logger.info('download asset renamed', { orgId, downloadId, assetId });\n return this.downloadFiles(orgId, assets);\n }\n\n /** The caller must send the COMPLETE ordered set — a partial list would\n * silently unlink whatever it omitted. */\n async reorderDownloadAssets(\n orgId: string,\n downloadId: string,\n assetIds: string[],\n ): Promise<DownloadFile[]> {\n const assets = await this.uow.run(async ({ content, outbox }) => {\n const current = await content.listDownloadAssets(orgId, downloadId);\n const currentIds = new Set(current.map((a) => a.assetId));\n const requestedIds = new Set(assetIds);\n if (\n requestedIds.size !== assetIds.length ||\n requestedIds.size !== currentIds.size ||\n !assetIds.every((id) => currentIds.has(id))\n ) {\n this.logger.warn('download asset reorder rejected — id set mismatch', {\n orgId,\n downloadId,\n assetIds,\n currentIds: [...currentIds],\n });\n throw new ConflictError(\"Ordered asset ids does not match the download's current assets\");\n }\n const assets = await content.reorderDownloadAssets(orgId, downloadId, assetIds);\n await outbox.append([\n contentEvents.downloadAssetsReordered.make({ orgId, data: { downloadId, assets } }),\n ]);\n return assets;\n });\n this.logger.debug('download assets reordered', { orgId, downloadId });\n return this.downloadFiles(orgId, assets);\n }\n\n // --- bundles --------------------------------------------------------------\n\n listBundles(orgId: string, query: ListBundlesQuery): Promise<Page<Bundle>> {\n return this.repo.listBundles(orgId, query);\n }\n\n getBundle(orgId: string, id: string): Promise<Bundle | null> {\n return this.repo.findBundleById(orgId, id);\n }\n\n async createBundle(orgId: string, input: CreateBundleInput): Promise<Bundle> {\n const { bundle, items } = await this.uow.run(async ({ content, outbox }) => {\n // The repository writes the bundle and its initial items as one unit —\n // an unknown content id throws and nothing is created.\n const created = await content.createBundle(orgId, input);\n const initial = input.contentIds?.length\n ? await content.listBundleItems(orgId, created.id)\n : [];\n await outbox.append([\n contentEvents.bundleCreated.make({ orgId, data: created }),\n ...(initial.length > 0\n ? [\n contentEvents.bundleItemAdded.make({\n orgId,\n data: { bundleId: created.id, items: initial },\n }),\n ]\n : []),\n ]);\n return { bundle: created, items: initial };\n });\n this.logger.info('bundle created', {\n orgId,\n bundleId: bundle.id,\n name: bundle.name,\n itemCount: items.length,\n });\n return bundle;\n }\n\n async updateBundle(orgId: string, id: string, patch: UpdateBundleInput): Promise<Bundle> {\n const bundle = await this.uow.run(async ({ content, outbox }) => {\n const updated = await content.updateBundle(orgId, id, patch);\n if (!updated) {\n this.logger.warn('bundle update rejected — not found', { orgId, bundleId: id });\n throw new NotFoundError('Bundle', id);\n }\n await outbox.append([contentEvents.bundleUpdated.make({ orgId, data: updated })]);\n return updated;\n });\n this.logger.info('bundle updated', { orgId, bundleId: id, fields: Object.keys(patch) });\n return bundle;\n }\n\n async deleteBundle(orgId: string, id: string): Promise<void> {\n await this.uow.run(async ({ content, outbox }) => {\n // Snapshot before the delete — the event carries the last known state.\n const bundle = await content.findBundleById(orgId, id);\n if (!bundle) {\n this.logger.warn('bundle delete rejected — not found', { orgId, bundleId: id });\n throw new NotFoundError('Bundle', id);\n }\n const ok = await content.deleteBundle(orgId, id);\n if (!ok) {\n throw new NotFoundError('Bundle', id);\n }\n await outbox.append([contentEvents.bundleDeleted.make({ orgId, data: bundle })]);\n });\n this.logger.info('bundle deleted', { orgId, bundleId: id });\n }\n\n listBundleItems(orgId: string, bundleId: string): Promise<BundleItem[]> {\n return this.repo.listBundleItems(orgId, bundleId);\n }\n\n async addBundleItem(orgId: string, bundleId: string, contentId: string): Promise<BundleItem[]> {\n const items = await this.uow.run(async ({ content, outbox }) => {\n const all = await content.addBundleItem(orgId, bundleId, contentId);\n await outbox.append([\n contentEvents.bundleItemAdded.make({ orgId, data: { bundleId, items: all } }),\n ]);\n return all;\n });\n this.logger.info('bundle item added', { orgId, bundleId, contentId });\n return items;\n }\n\n async removeBundleItem(\n orgId: string,\n bundleId: string,\n contentId: string,\n ): Promise<BundleItem[]> {\n const items = await this.uow.run(async ({ content, outbox }) => {\n const all = await content.removeBundleItem(orgId, bundleId, contentId);\n await outbox.append([\n contentEvents.bundleItemRemoved.make({ orgId, data: { bundleId, items: all } }),\n ]);\n return all;\n });\n this.logger.info('bundle item removed', { orgId, bundleId, contentId });\n return items;\n }\n\n private async spaceUpdates(\n content: ContentRepository,\n orgId: string,\n spaceIds: string[],\n actor: Actor,\n ): Promise<NewDomainEvent[]> {\n const events: NewDomainEvent[] = [];\n for (const spaceId of spaceIds) {\n const space = await content.findSpace(orgId, spaceId);\n if (space) {\n events.push(\n contentEvents.spaceUpdated.make({ orgId, data: space, metadata: actorMetadata(actor) }),\n );\n }\n }\n return events;\n }\n\n private resolvedSpace(\n input: CreateSpaceInput | UpdateSpaceInput,\n current?: Space,\n ): {\n accessRule: Space['accessRule'];\n capacity: number | null;\n settings: SpaceSettings;\n } {\n const accessRule = input.accessRule ?? current?.accessRule ?? 'all_members';\n let capacity = input.capacity !== undefined ? input.capacity : (current?.capacity ?? null);\n if (accessRule === 'all_members') {\n if (input.capacity != null) {\n throw new InvalidInputError('An all-members space has no capacity');\n }\n capacity = null;\n }\n const settings = {\n ...(current?.settings ?? spaceSettingsDefaults),\n ...input.settings,\n };\n return { accessRule, capacity, settings };\n }\n\n async listCommunities(orgId: string, query: ListCommunitiesQuery): Promise<Page<CommunityView>> {\n return this.pageWithThumbnails(await this.repo.listCommunities(orgId, query));\n }\n\n async getCommunity(orgId: string, id: string): Promise<CommunityView | null> {\n const community = await this.repo.findCommunityById(orgId, id);\n return community ? this.withThumbnail(community) : null;\n }\n\n listPublishedCommunityIds(orgId: string): Promise<string[]> {\n return this.repo.listPublishedCommunityIds(orgId);\n }\n\n listCommunitiesById(orgId: string, ids: string[]): Promise<Community[]> {\n return ids.length ? this.repo.findCommunitiesByIds(orgId, ids) : Promise.resolve([]);\n }\n\n getSpace(orgId: string, spaceId: string): Promise<SpaceDetail | null> {\n return this.repo.findSpace(orgId, spaceId);\n }\n\n async getCommunitySpace(\n orgId: string,\n communityId: string,\n spaceId: string,\n ): Promise<SpaceDetail | null> {\n const space = await this.repo.findSpace(orgId, spaceId);\n return space?.communityId === communityId ? space : null;\n }\n\n async listSpaces(orgId: string, communityId: string): Promise<SpaceDetail[]> {\n if (!(await this.getCommunity(orgId, communityId))) {\n throw new NotFoundError('Community', communityId);\n }\n return this.repo.listSpaces(orgId, communityId);\n }\n\n async getDmSettings(orgId: string, communityId: string): Promise<DmSettings | null> {\n const community = await this.repo.findCommunityById(orgId, communityId);\n return community?.settings.dm ?? null;\n }\n\n async createCommunity(\n orgId: string,\n input: CreateCommunityInput,\n actor: Actor,\n ): Promise<CommunityView> {\n assertConfigurator(actor);\n const community = await this.uow.run(async ({ content, outbox }) => {\n const created = await content.createCommunity(orgId, input, slugify(input.title));\n await outbox.append([\n contentEvents.communityCreated.make({\n orgId,\n data: created,\n metadata: actorMetadata(actor),\n }),\n ]);\n return created;\n });\n this.logger.info('community created', {\n orgId,\n communityId: community.id,\n actorId: actor.id,\n });\n return this.withThumbnail(community);\n }\n\n async updateCommunity(\n orgId: string,\n id: string,\n patch: UpdateCommunityInput,\n actor: Actor,\n ): Promise<CommunityView> {\n assertConfigurator(actor);\n await this.assertLibraryAssets(orgId, [patch.thumbnailAssetId], 'A community');\n const community = await this.uow.run(async ({ content, outbox }) => {\n const updated = await content.updateCommunity(orgId, id, patch);\n if (!updated) {\n this.logger.warn('community update rejected — not found', {\n orgId,\n communityId: id,\n actorId: actor.id,\n });\n throw new NotFoundError('Community', id);\n }\n await outbox.append([\n contentEvents.communityUpdated.make({\n orgId,\n data: updated,\n metadata: actorMetadata(actor),\n }),\n ]);\n return updated;\n });\n this.logger.info('community updated', { orgId, communityId: id, actorId: actor.id });\n return this.withThumbnail(community);\n }\n\n publishCommunity(orgId: string, id: string, actor: Actor): Promise<CommunityView> {\n return this.updateCommunity(orgId, id, { status: 'published' }, actor);\n }\n\n unpublishCommunity(orgId: string, id: string, actor: Actor): Promise<CommunityView> {\n return this.updateCommunity(orgId, id, { status: 'draft' }, actor);\n }\n\n async deleteCommunity(orgId: string, id: string, actor: Actor): Promise<void> {\n assertConfigurator(actor);\n await this.uow.run(async ({ content, outbox }) => {\n const community = await content.findCommunityById(orgId, id);\n if (!community) {\n this.logger.warn('community delete rejected — not found', {\n orgId,\n communityId: id,\n actorId: actor.id,\n });\n throw new NotFoundError('Community', id);\n }\n const linked = await content.spacesLinkingContent(orgId, id);\n const ok = await content.deleteCommunity(orgId, id);\n if (!ok) {\n throw new NotFoundError('Community', id);\n }\n await content.deleteCommunitySettings(orgId, id);\n await outbox.append([\n contentEvents.communityDeleted.make({\n orgId,\n data: community,\n metadata: actorMetadata(actor),\n }),\n ...(await this.spaceUpdates(content, orgId, linked, actor)),\n ]);\n });\n this.logger.info('community deleted', { orgId, communityId: id, actorId: actor.id });\n }\n\n async patchDmSettings(\n orgId: string,\n id: string,\n patch: PatchDmSettingsInput,\n actor: Actor,\n ): Promise<CommunityView> {\n assertConfigurator(actor);\n const community = await this.uow.run(async ({ content, outbox }) => {\n const updated = await content.patchDmSettings(orgId, id, patch);\n if (!updated) {\n this.logger.warn('community dm settings patch rejected — not found', {\n orgId,\n communityId: id,\n actorId: actor.id,\n });\n throw new NotFoundError('Community', id);\n }\n await outbox.append([\n contentEvents.communityUpdated.make({\n orgId,\n data: updated,\n metadata: actorMetadata(actor),\n }),\n ]);\n return updated;\n });\n this.logger.info('community dm settings patched', {\n orgId,\n communityId: id,\n actorId: actor.id,\n });\n return this.withThumbnail(community);\n }\n\n async createSpace(\n orgId: string,\n communityId: string,\n input: CreateSpaceInput,\n actor: Actor,\n ): Promise<SpaceDetail> {\n assertConfigurator(actor);\n const resolved = this.resolvedSpace(input);\n const space = await this.uow.run(async ({ content, outbox }) => {\n const community = await content.findCommunityById(orgId, communityId);\n if (!community) {\n this.logger.warn('space create rejected — community not found', {\n orgId,\n communityId,\n actorId: actor.id,\n });\n throw new NotFoundError('Community', communityId);\n }\n const created = await content.createSpace(orgId, communityId, {\n ...input,\n accessRule: resolved.accessRule,\n capacity: resolved.capacity,\n settings: resolved.settings,\n });\n await outbox.append([\n contentEvents.spaceCreated.make({\n orgId,\n data: created,\n metadata: actorMetadata(actor),\n }),\n ]);\n return created;\n });\n this.logger.info('space created', {\n orgId,\n communityId,\n spaceId: space.id,\n actorId: actor.id,\n });\n return space;\n }\n\n async updateSpace(\n orgId: string,\n communityId: string,\n spaceId: string,\n patch: UpdateSpaceInput,\n actor: Actor,\n ): Promise<SpaceDetail> {\n assertConfigurator(actor);\n const space = await this.uow.run(async ({ content, outbox }) => {\n const current = await content.findSpace(orgId, spaceId);\n if (!current || current.communityId !== communityId) {\n this.logger.warn('space update rejected — not found', {\n orgId,\n communityId,\n spaceId,\n actorId: actor.id,\n });\n throw new NotFoundError('Space', spaceId);\n }\n const resolved = this.resolvedSpace(patch, current);\n const updated = await content.updateSpace(orgId, communityId, spaceId, {\n ...patch,\n accessRule: resolved.accessRule,\n capacity: resolved.capacity,\n settings: resolved.settings,\n });\n if (!updated) {\n throw new NotFoundError('Space', spaceId);\n }\n await outbox.append([\n contentEvents.spaceUpdated.make({\n orgId,\n data: updated,\n metadata: actorMetadata(actor),\n }),\n ]);\n return updated;\n });\n this.logger.info('space updated', { orgId, communityId, spaceId, actorId: actor.id });\n return space;\n }\n\n async deleteSpace(\n orgId: string,\n communityId: string,\n spaceId: string,\n actor: Actor,\n ): Promise<void> {\n assertConfigurator(actor);\n await this.uow.run(async ({ content, outbox }) => {\n const space = await content.findSpace(orgId, spaceId);\n if (!space || space.communityId !== communityId) {\n this.logger.warn('space delete rejected — not found', {\n orgId,\n communityId,\n spaceId,\n actorId: actor.id,\n });\n throw new NotFoundError('Space', spaceId);\n }\n const ok = await content.deleteSpace(orgId, communityId, spaceId);\n if (!ok) {\n throw new NotFoundError('Space', spaceId);\n }\n await outbox.append([\n contentEvents.spaceDeleted.make({\n orgId,\n data: space,\n metadata: actorMetadata(actor),\n }),\n ]);\n });\n this.logger.info('space deleted', { orgId, communityId, spaceId, actorId: actor.id });\n }\n\n async reorderSpaces(\n orgId: string,\n communityId: string,\n orderedIds: string[],\n actor: Actor,\n ): Promise<SpaceDetail[]> {\n assertConfigurator(actor);\n const spaces = await this.uow.run(async ({ content, outbox }) => {\n const community = await content.findCommunityById(orgId, communityId);\n if (!community) {\n this.logger.warn('spaces reorder rejected — community not found', {\n orgId,\n communityId,\n actorId: actor.id,\n });\n throw new NotFoundError('Community', communityId);\n }\n const current = await content.listSpaces(orgId, communityId);\n if (\n !sameIdSet(\n current.map((space) => space.id),\n orderedIds,\n )\n ) {\n throw new ConflictError(\"Ordered space ids do not match the community's spaces\");\n }\n const reordered = await content.reorderSpaces(orgId, communityId, orderedIds);\n await outbox.append([\n contentEvents.spacesReordered.make({\n orgId,\n data: reordered,\n metadata: actorMetadata(actor),\n }),\n ]);\n return reordered;\n });\n this.logger.info('spaces reordered', { orgId, communityId, actorId: actor.id });\n return spaces;\n }\n\n async setSpaceTopics(\n orgId: string,\n communityId: string,\n spaceId: string,\n input: SetSpaceTopicsInput,\n actor: Actor,\n ): Promise<SpaceDetail> {\n assertConfigurator(actor);\n const names = input.topics.map((topic) => topic.name);\n if (new Set(names).size !== names.length) {\n throw new InvalidInputError('A space topic name is already used');\n }\n const space = await this.uow.run(async ({ content, outbox }) => {\n const locked = await content.lockSpace(orgId, spaceId);\n if (!locked || locked.communityId !== communityId) {\n this.logger.warn('space topics rejected — space not found', {\n orgId,\n communityId,\n spaceId,\n actorId: actor.id,\n });\n throw new NotFoundError('Space', spaceId);\n }\n const current = await content.findSpace(orgId, spaceId);\n if (!current) {\n throw new NotFoundError('Space', spaceId);\n }\n const kept = new Set(input.topics.flatMap((topic) => (topic.id ? [topic.id] : [])));\n const removed = current.topics\n .filter((topic) => !kept.has(topic.id))\n .map((topic) => topic.id);\n if (removed.length > 0 && (await content.topicsInUse(orgId, spaceId, removed)).length > 0) {\n throw new ConflictError('A topic used by a post cannot be removed');\n }\n const updated = await content.setSpaceTopics(orgId, spaceId, input);\n await outbox.append([\n contentEvents.spaceUpdated.make({\n orgId,\n data: updated,\n metadata: actorMetadata(actor),\n }),\n ]);\n return updated;\n });\n this.logger.info('space topics set', { orgId, communityId, spaceId, actorId: actor.id });\n return space;\n }\n\n async addSpaceLink(\n orgId: string,\n communityId: string,\n spaceId: string,\n contentId: string,\n actor: Actor,\n ): Promise<SpaceDetail> {\n assertConfigurator(actor);\n const space = await this.uow.run(async ({ content, outbox }) => {\n const current = await content.findSpace(orgId, spaceId);\n if (!current || current.communityId !== communityId) {\n this.logger.warn('space link add rejected — space not found', {\n orgId,\n communityId,\n spaceId,\n actorId: actor.id,\n });\n throw new NotFoundError('Space', spaceId);\n }\n if (current.links.some((link) => link.contentId === contentId)) {\n throw new ConflictError('This space already links to that content');\n }\n const updated = await content.addSpaceLink(orgId, spaceId, contentId);\n await outbox.append([\n contentEvents.spaceUpdated.make({\n orgId,\n data: updated,\n metadata: actorMetadata(actor),\n }),\n ]);\n return updated;\n });\n this.logger.info('space link added', {\n orgId,\n communityId,\n spaceId,\n contentId,\n actorId: actor.id,\n });\n return space;\n }\n\n async removeSpaceLink(\n orgId: string,\n communityId: string,\n spaceId: string,\n linkId: string,\n actor: Actor,\n ): Promise<SpaceDetail> {\n assertConfigurator(actor);\n const space = await this.uow.run(async ({ content, outbox }) => {\n const current = await content.findSpace(orgId, spaceId);\n if (!current || current.communityId !== communityId) {\n this.logger.warn('space link remove rejected — space not found', {\n orgId,\n communityId,\n spaceId,\n actorId: actor.id,\n });\n throw new NotFoundError('Space', spaceId);\n }\n const updated = await content.removeSpaceLink(orgId, spaceId, linkId);\n await outbox.append([\n contentEvents.spaceUpdated.make({\n orgId,\n data: updated,\n metadata: actorMetadata(actor),\n }),\n ]);\n return updated;\n });\n this.logger.info('space link removed', {\n orgId,\n communityId,\n spaceId,\n linkId,\n actorId: actor.id,\n });\n return space;\n }\n\n async reorderSpaceLinks(\n orgId: string,\n communityId: string,\n spaceId: string,\n orderedIds: string[],\n actor: Actor,\n ): Promise<SpaceDetail> {\n assertConfigurator(actor);\n const space = await this.uow.run(async ({ content, outbox }) => {\n const current = await content.findSpace(orgId, spaceId);\n if (!current || current.communityId !== communityId) {\n this.logger.warn('space links reorder rejected — space not found', {\n orgId,\n communityId,\n spaceId,\n actorId: actor.id,\n });\n throw new NotFoundError('Space', spaceId);\n }\n if (\n !sameIdSet(\n current.links.map((link) => link.id),\n orderedIds,\n )\n ) {\n throw new ConflictError(\"Ordered link ids do not match the space's links\");\n }\n const updated = await content.reorderSpaceLinks(orgId, spaceId, orderedIds);\n await outbox.append([\n contentEvents.spaceUpdated.make({\n orgId,\n data: updated,\n metadata: actorMetadata(actor),\n }),\n ]);\n return updated;\n });\n this.logger.info('space links reordered', {\n orgId,\n communityId,\n spaceId,\n actorId: actor.id,\n });\n return space;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"service.js","names":[],"sources":["../../src/content/service.ts"],"sourcesContent":["import type {\n Activity,\n ActivityAsset,\n ActivityView,\n Bundle,\n BundleItem,\n Community,\n CommunityView,\n CourseSettings,\n CourseView,\n DmSettings,\n DownloadAsset,\n DownloadFile,\n DownloadView,\n Module,\n SaveActivityInput,\n Space,\n SpaceDetail,\n SpaceSettings,\n} from './model.js';\nimport type {\n BundlesService,\n CommunitiesService,\n CommunityDigest,\n CourseManagementService,\n ContentRepository,\n ContentUnitOfWork,\n DownloadablesService,\n} from './ports.js';\nimport type {\n AddDownloadAssetInput,\n CreateBundleInput,\n CreateCommunityInput,\n CreateCourseInput,\n CreateDownloadInput,\n CreateSpaceInput,\n ListBundlesQuery,\n ListCommunitiesQuery,\n ListCoursesQuery,\n ListDownloadsQuery,\n Page,\n PatchCommunitySettingsInput,\n SetSpaceTopicsInput,\n UpdateBundleInput,\n UpdateCommunityInput,\n UpdateCourseInput,\n UpdateDownloadInput,\n UpdateSpaceInput,\n} from './types.js';\nimport { contentEvents } from './events.js';\nimport type { Actor } from '../shared/actor.js';\nimport type { AssetFiles, FileUrls, LibraryAssetReader } from '../assets/index.js';\nimport type { Logger, NewDomainEvent } from '../shared/ports.js';\nimport {\n ConflictError,\n ForbiddenError,\n InvalidInputError,\n NotFoundError,\n} from '../shared/errors.js';\nimport { noopLogger } from '../shared/logger.js';\nimport { spaceSettingsDefaults } from '../types/schemas/content.js';\n\n/** URL-safe slug derived from a title. Domain rule owned by the service. */\nfunction slugify(title: string): string {\n return title\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/(^-|-$)/g, '');\n}\n\nexport type ContentServiceParams = {\n repo: ContentRepository;\n uow: ContentUnitOfWork;\n libraryAssets: LibraryAssetReader;\n files: Pick<AssetFiles, 'readyFiles'>;\n fileUrls: FileUrls;\n logger?: Logger;\n};\n\nfunction isPublishedActivity(settings: unknown): boolean {\n return (settings as { published?: unknown } | null)?.published !== false;\n}\n\nfunction actorMetadata(actor: Actor): { actorOrgUserId: string } {\n return { actorOrgUserId: actor.id };\n}\n\nfunction assertConfigurator(actor: Actor): void {\n if (actor.role !== 'owner' && actor.role !== 'admin') {\n throw new ForbiddenError('Only an owner or an admin can configure a community');\n }\n}\n\ntype WithThumbnail = {\n id: string;\n type: 'course' | 'download' | 'community';\n thumbnailAssetId: string | null;\n};\n\nfunction sameIdSet(current: string[], requested: string[]): boolean {\n if (current.length !== requested.length) {\n return false;\n }\n const have = new Set(current);\n return requested.every((id) => have.has(id)) && new Set(requested).size === requested.length;\n}\n\nexport class ContentService\n implements CourseManagementService, DownloadablesService, BundlesService, CommunitiesService\n{\n private readonly repo: ContentRepository;\n private readonly uow: ContentUnitOfWork;\n private readonly libraryAssets: LibraryAssetReader;\n private readonly files: Pick<AssetFiles, 'readyFiles'>;\n private readonly fileUrls: FileUrls;\n private readonly logger: Logger;\n\n constructor(params: ContentServiceParams) {\n this.repo = params.repo;\n this.uow = params.uow;\n this.libraryAssets = params.libraryAssets;\n this.files = params.files;\n this.fileUrls = params.fileUrls;\n this.logger = params.logger ?? noopLogger;\n }\n\n private withThumbnail<T extends WithThumbnail>(item: T): T & { thumbnailUrl: string | null } {\n return {\n ...item,\n thumbnailUrl: item.thumbnailAssetId ? this.fileUrls.thumbnail(item.type, item.id) : null,\n };\n }\n\n private pageWithThumbnails<T extends WithThumbnail>(\n page: Page<T>,\n ): Page<T & { thumbnailUrl: string | null }> {\n return { ...page, rows: page.rows.map((row) => this.withThumbnail(row)) };\n }\n\n private async downloadFiles(orgId: string, links: DownloadAsset[]): Promise<DownloadFile[]> {\n const ready = await this.files.readyFiles(\n orgId,\n links.map((link) => link.assetId),\n );\n return links.flatMap((link) => {\n const file = ready[link.assetId];\n return file\n ? [{ ...link, ...file, url: this.fileUrls.downloadFile(link.downloadId, link.assetId) }]\n : [];\n });\n }\n\n async listCourses(orgId: string, query: ListCoursesQuery): Promise<Page<CourseView>> {\n return this.pageWithThumbnails(await this.repo.listCourses(orgId, query));\n }\n\n async getCourse(orgId: string, id: string): Promise<CourseView | null> {\n const course = await this.repo.findCourseById(orgId, id);\n return course ? this.withThumbnail(course) : null;\n }\n\n async createCourse(orgId: string, input: CreateCourseInput): Promise<CourseView> {\n const course = await this.uow.run(async ({ content, outbox }) => {\n const created = await content.createCourse(orgId, input, slugify(input.title));\n await outbox.append([contentEvents.courseCreated.make({ orgId, data: created })]);\n return created;\n });\n this.logger.info('course created', { orgId, courseId: course.id, title: course.title });\n return this.withThumbnail(course);\n }\n\n async updateCourse(orgId: string, id: string, patch: UpdateCourseInput): Promise<CourseView> {\n await this.assertLibraryAssets(orgId, [patch.thumbnailAssetId], 'A course');\n const course = await this.uow.run(async ({ content, outbox }) => {\n const updated = await content.updateCourse(orgId, id, patch);\n if (!updated) {\n this.logger.warn('course update rejected — not found', { orgId, courseId: id });\n throw new NotFoundError('Course', id);\n }\n await outbox.append([contentEvents.courseUpdated.make({ orgId, data: updated })]);\n return updated;\n });\n this.logger.info('course updated', { orgId, courseId: id, fields: Object.keys(patch) });\n return this.withThumbnail(course);\n }\n\n async patchCourseSettings(\n orgId: string,\n id: string,\n value: Partial<CourseSettings>,\n ): Promise<CourseSettings> {\n const merged = await this.uow.run(async ({ content, outbox }) => {\n const course = await content.findCourseById(orgId, id);\n if (!course) {\n this.logger.warn('course settings patch rejected — not found', { orgId, courseId: id });\n throw new NotFoundError('Course', id);\n }\n const settings = await content.patchCourseSettings(orgId, id, value);\n await outbox.append([\n contentEvents.courseUpdated.make({ orgId, data: { ...course, settings } }),\n ]);\n return settings;\n });\n this.logger.info('course settings patched', { orgId, courseId: id, value });\n return merged;\n }\n\n async deleteCourse(orgId: string, id: string, actor: Actor): Promise<void> {\n await this.uow.run(async ({ content, outbox }) => {\n // Snapshot before the delete — the event carries the last known state.\n const course = await content.findCourseById(orgId, id);\n if (!course) {\n this.logger.warn('course delete rejected — not found', { orgId, courseId: id });\n throw new NotFoundError('Course', id);\n }\n const linked = await content.spacesLinkingContent(orgId, id);\n const ok = await content.deleteCourse(orgId, id);\n if (!ok) {\n throw new NotFoundError('Course', id);\n }\n await outbox.append([\n contentEvents.courseDeleted.make({ orgId, data: course }),\n ...(await this.spaceUpdates(content, orgId, linked, actor)),\n ]);\n });\n this.logger.info('course deleted', { orgId, courseId: id });\n }\n\n // --- modules & activities ------------------------------------------------\n\n listCourseModules(orgId: string, courseId: string): Promise<Module[]> {\n return this.repo.listCourseModules(orgId, courseId);\n }\n listCourseActivities(orgId: string, courseId: string): Promise<Activity[]> {\n return this.repo.listActivitiesForCourse(orgId, courseId);\n }\n async listCourseActivityViews(orgId: string, courseId: string): Promise<ActivityView[]> {\n const [activities, links] = await Promise.all([\n this.repo.listActivitiesForCourse(orgId, courseId),\n this.repo.listActivityAssetsForCourse(orgId, courseId),\n ]);\n return activities.map((activity) => ({\n ...activity,\n assetUrls: Object.fromEntries(\n links\n .filter((link) => link.activityId === activity.id)\n .map((link) => [link.assetId, this.fileUrls.activityAsset(activity.id, link.assetId)]),\n ),\n }));\n }\n listCourseActivityAssets(orgId: string, courseId: string): Promise<ActivityAsset[]> {\n return this.repo.listActivityAssetsForCourse(orgId, courseId);\n }\n getActivity(orgId: string, activityId: string): Promise<Activity | null> {\n return this.repo.findActivity(orgId, activityId);\n }\n getModule(orgId: string, moduleId: string): Promise<Module | null> {\n return this.repo.findModule(orgId, moduleId);\n }\n\n async reorderModules(orgId: string, courseId: string, orderedIds: string[]): Promise<Module[]> {\n const modules = await this.uow.run(async ({ content, outbox }) => {\n const reordered = await content.reorderModules(orgId, courseId, orderedIds);\n await outbox.append([contentEvents.modulesReordered.make({ orgId, data: reordered })]);\n return reordered;\n });\n this.logger.debug('modules reordered', {\n orgId,\n courseId,\n moduleIds: modules.map((m) => m.id),\n });\n return modules;\n }\n\n async createModule(orgId: string, courseId: string, title: string): Promise<Module[]> {\n const { modules, created } = await this.uow.run(async ({ content, outbox }) => {\n const all = await content.createModule(orgId, courseId, title);\n // The list is ordered by seq and the new module is appended at max(seq)+1.\n const module = all.at(-1);\n if (!module) {\n throw new Error('failed to load created module');\n }\n await outbox.append([contentEvents.moduleCreated.make({ orgId, data: module })]);\n return { modules: all, created: module };\n });\n this.logger.info('module created', { orgId, courseId, moduleId: created.id, title });\n return modules;\n }\n\n async updateModule(\n orgId: string,\n courseId: string,\n moduleId: string,\n title: string,\n ): Promise<Module[]> {\n const modules = await this.uow.run(async ({ content, outbox }) => {\n const existing = await content.findModule(orgId, moduleId);\n if (!existing || existing.courseId !== courseId) {\n this.logger.warn('module update rejected — not found in course', {\n orgId,\n courseId,\n moduleId,\n });\n throw new NotFoundError('Module', moduleId);\n }\n const all = await content.updateModule(orgId, courseId, moduleId, title);\n const module = all.find((m) => m.id === moduleId);\n if (!module) {\n throw new NotFoundError('Module', moduleId);\n }\n await outbox.append([contentEvents.moduleUpdated.make({ orgId, data: module })]);\n return all;\n });\n this.logger.info('module updated', { orgId, courseId, moduleId, title });\n return modules;\n }\n\n async deleteModule(orgId: string, courseId: string, moduleId: string): Promise<Module[]> {\n const modules = await this.uow.run(async ({ content, outbox }) => {\n // Snapshot before the delete — the event carries the last known state.\n const module = await content.findModule(orgId, moduleId);\n if (!module || module.courseId !== courseId) {\n this.logger.warn('module delete rejected — not found in course', {\n orgId,\n courseId,\n moduleId,\n });\n throw new NotFoundError('Module', moduleId);\n }\n const remaining = await content.deleteModule(orgId, courseId, moduleId);\n await outbox.append([contentEvents.moduleDeleted.make({ orgId, data: module })]);\n return remaining;\n });\n this.logger.info('module deleted', { orgId, courseId, moduleId });\n return modules;\n }\n\n async reorderActivities(\n orgId: string,\n courseId: string,\n moduleId: string,\n orderedIds: string[],\n ): Promise<Module[]> {\n const modules = await this.uow.run(async ({ content, outbox }) => {\n const reordered = await content.reorderActivities(orgId, courseId, moduleId, orderedIds);\n const module = reordered.find((m) => m.id === moduleId);\n if (!module) {\n throw new NotFoundError('Module', moduleId);\n }\n await outbox.append([contentEvents.activitiesReordered.make({ orgId, data: module })]);\n return reordered;\n });\n this.logger.debug('activities reordered', { orgId, courseId, moduleId });\n return modules;\n }\n\n private async assertLibraryAssets(\n orgId: string,\n assetIds: (string | null | undefined)[],\n user = 'An activity',\n ): Promise<void> {\n const ids = assetIds.filter((id): id is string => typeof id === 'string');\n if (ids.length === 0) {\n return;\n }\n const library = new Set(await this.libraryAssets.libraryAssetsAmong(orgId, ids));\n const refused = ids.filter((id) => !library.has(id));\n if (refused.length > 0) {\n this.logger.warn('library assets refused', { orgId, assetIds: refused });\n throw new ConflictError(\n `${user} can only use ready files from the media library. Not available: ${refused.join(', ')}`,\n );\n }\n }\n\n async saveActivity(\n orgId: string,\n courseId: string,\n moduleId: string,\n input: SaveActivityInput,\n activityId?: string,\n ): Promise<Module[]> {\n await this.assertLibraryAssets(orgId, input.assetIds ?? []);\n const { modules, activity } = await this.uow.run(async ({ content, outbox }) => {\n let wasPublished = false;\n if (activityId) {\n const existing = await content.findActivity(orgId, activityId);\n if (!existing || existing.moduleId !== moduleId || existing.courseId !== courseId) {\n this.logger.warn('activity update rejected — not found in module', {\n orgId,\n courseId,\n moduleId,\n activityId,\n });\n throw new NotFoundError('Activity', activityId);\n }\n wasPublished = isPublishedActivity(existing.settings);\n } else {\n const module = await content.findModule(orgId, moduleId);\n if (!module || module.courseId !== courseId) {\n this.logger.warn('activity create rejected — module not found in course', {\n orgId,\n courseId,\n moduleId,\n });\n throw new NotFoundError('Module', moduleId);\n }\n }\n\n const { modules: all, activity: saved } = await content.saveActivity(\n orgId,\n courseId,\n moduleId,\n input,\n activityId,\n );\n const events: NewDomainEvent[] = [\n activityId\n ? contentEvents.activityUpdated.make({ orgId, data: saved })\n : contentEvents.activityCreated.make({ orgId, data: saved }),\n ];\n if (!wasPublished && isPublishedActivity(saved.settings)) {\n const course = await content.findCourseById(orgId, courseId);\n if (course?.status === 'published') {\n events.push(\n contentEvents.activityPublished.make({\n orgId,\n data: { activityId: saved.id, moduleId, courseId },\n }),\n );\n }\n }\n await outbox.append(events);\n return { modules: all, activity: saved };\n });\n this.logger.info(activityId ? 'activity updated' : 'activity created', {\n orgId,\n courseId,\n moduleId,\n activityId: activity.id,\n });\n return modules;\n }\n\n async deleteActivity(\n orgId: string,\n courseId: string,\n moduleId: string,\n activityId: string,\n ): Promise<Module[]> {\n const modules = await this.uow.run(async ({ content, outbox }) => {\n // Snapshot before the delete — the event carries the last known state.\n const activity = await content.findActivity(orgId, activityId);\n if (!activity || activity.moduleId !== moduleId || activity.courseId !== courseId) {\n this.logger.warn('activity delete rejected — not found in module', {\n orgId,\n courseId,\n moduleId,\n activityId,\n });\n throw new NotFoundError('Activity', activityId);\n }\n const remaining = await content.deleteActivity(orgId, courseId, moduleId, activityId);\n await outbox.append([contentEvents.activityDeleted.make({ orgId, data: activity })]);\n return remaining;\n });\n this.logger.info('activity deleted', { orgId, courseId, moduleId, activityId });\n return modules;\n }\n\n // --- downloads ------------------------------------------------------------\n\n async listDownloads(orgId: string, query: ListDownloadsQuery): Promise<Page<DownloadView>> {\n return this.pageWithThumbnails(await this.repo.listDownloads(orgId, query));\n }\n\n async getDownload(orgId: string, id: string): Promise<DownloadView | null> {\n const download = await this.repo.getDownload(orgId, id);\n return download ? this.withThumbnail(download) : null;\n }\n\n async createDownload(orgId: string, input: CreateDownloadInput): Promise<DownloadView> {\n const download = await this.uow.run(async ({ content, outbox }) => {\n const created = await content.createDownload(orgId, input, slugify(input.title));\n await outbox.append([contentEvents.downloadCreated.make({ orgId, data: created })]);\n return created;\n });\n this.logger.info('download created', { orgId, downloadId: download.id, title: download.title });\n return this.withThumbnail(download);\n }\n\n async updateDownload(\n orgId: string,\n id: string,\n patch: UpdateDownloadInput,\n ): Promise<DownloadView> {\n await this.assertLibraryAssets(orgId, [patch.thumbnailAssetId], 'A download');\n const download = await this.uow.run(async ({ content, outbox }) => {\n const updated = await content.updateDownload(orgId, id, patch);\n if (!updated) {\n this.logger.warn('download update rejected — not found', { orgId, downloadId: id });\n throw new NotFoundError('Download', id);\n }\n await outbox.append([contentEvents.downloadUpdated.make({ orgId, data: updated })]);\n return updated;\n });\n this.logger.info('download updated', { orgId, downloadId: id, fields: Object.keys(patch) });\n return this.withThumbnail(download);\n }\n\n async removeDownload(orgId: string, id: string, actor: Actor): Promise<void> {\n await this.uow.run(async ({ content, outbox }) => {\n // Snapshot before the delete — the event carries the last known state.\n const download = await content.getDownload(orgId, id);\n if (!download) {\n this.logger.warn('download delete rejected — not found', { orgId, downloadId: id });\n throw new NotFoundError('Download', id);\n }\n const linked = await content.spacesLinkingContent(orgId, id);\n const ok = await content.deleteDownload(orgId, id);\n if (!ok) {\n throw new NotFoundError('Download', id);\n }\n await outbox.append([\n contentEvents.downloadDeleted.make({ orgId, data: download }),\n ...(await this.spaceUpdates(content, orgId, linked, actor)),\n ]);\n });\n this.logger.info('download deleted', { orgId, downloadId: id });\n }\n\n // --- download asset links ------------------------------------------------\n\n async listDownloadAssets(orgId: string, downloadId: string): Promise<DownloadFile[]> {\n return this.downloadFiles(orgId, await this.repo.listDownloadAssets(orgId, downloadId));\n }\n\n async addDownloadAsset(\n orgId: string,\n downloadId: string,\n input: AddDownloadAssetInput,\n ): Promise<DownloadFile[]> {\n await this.assertLibraryAssets(orgId, [input.assetId], 'A download');\n const assets = await this.uow.run(async ({ content, outbox }) => {\n const assets = await content.addDownloadAsset(orgId, downloadId, input);\n await outbox.append([\n contentEvents.downloadAssetAdded.make({ orgId, data: { downloadId, assets } }),\n ]);\n return assets;\n });\n this.logger.info('download asset added', { orgId, downloadId, assetId: input.assetId });\n return this.downloadFiles(orgId, assets);\n }\n\n async removeDownloadAsset(\n orgId: string,\n downloadId: string,\n assetId: string,\n ): Promise<DownloadFile[]> {\n const assets = await this.uow.run(async ({ content, outbox }) => {\n const assets = await content.removeDownloadAsset(orgId, downloadId, assetId);\n await outbox.append([\n contentEvents.downloadAssetRemoved.make({ orgId, data: { downloadId, assets } }),\n ]);\n return assets;\n });\n this.logger.info('download asset removed', { orgId, downloadId, assetId });\n return this.downloadFiles(orgId, assets);\n }\n\n async renameDownloadAsset(\n orgId: string,\n downloadId: string,\n assetId: string,\n displayName: string | null,\n ): Promise<DownloadFile[]> {\n const assets = await this.uow.run(async ({ content, outbox }) => {\n const assets = await content.renameDownloadAsset(orgId, downloadId, assetId, displayName);\n await outbox.append([\n contentEvents.downloadAssetRenamed.make({ orgId, data: { downloadId, assets } }),\n ]);\n return assets;\n });\n this.logger.info('download asset renamed', { orgId, downloadId, assetId });\n return this.downloadFiles(orgId, assets);\n }\n\n /** The caller must send the COMPLETE ordered set — a partial list would\n * silently unlink whatever it omitted. */\n async reorderDownloadAssets(\n orgId: string,\n downloadId: string,\n assetIds: string[],\n ): Promise<DownloadFile[]> {\n const assets = await this.uow.run(async ({ content, outbox }) => {\n const current = await content.listDownloadAssets(orgId, downloadId);\n const currentIds = new Set(current.map((a) => a.assetId));\n const requestedIds = new Set(assetIds);\n if (\n requestedIds.size !== assetIds.length ||\n requestedIds.size !== currentIds.size ||\n !assetIds.every((id) => currentIds.has(id))\n ) {\n this.logger.warn('download asset reorder rejected — id set mismatch', {\n orgId,\n downloadId,\n assetIds,\n currentIds: [...currentIds],\n });\n throw new ConflictError(\"Ordered asset ids does not match the download's current assets\");\n }\n const assets = await content.reorderDownloadAssets(orgId, downloadId, assetIds);\n await outbox.append([\n contentEvents.downloadAssetsReordered.make({ orgId, data: { downloadId, assets } }),\n ]);\n return assets;\n });\n this.logger.debug('download assets reordered', { orgId, downloadId });\n return this.downloadFiles(orgId, assets);\n }\n\n // --- bundles --------------------------------------------------------------\n\n listBundles(orgId: string, query: ListBundlesQuery): Promise<Page<Bundle>> {\n return this.repo.listBundles(orgId, query);\n }\n\n getBundle(orgId: string, id: string): Promise<Bundle | null> {\n return this.repo.findBundleById(orgId, id);\n }\n\n async createBundle(orgId: string, input: CreateBundleInput): Promise<Bundle> {\n const { bundle, items } = await this.uow.run(async ({ content, outbox }) => {\n // The repository writes the bundle and its initial items as one unit —\n // an unknown content id throws and nothing is created.\n const created = await content.createBundle(orgId, input);\n const initial = input.contentIds?.length\n ? await content.listBundleItems(orgId, created.id)\n : [];\n await outbox.append([\n contentEvents.bundleCreated.make({ orgId, data: created }),\n ...(initial.length > 0\n ? [\n contentEvents.bundleItemAdded.make({\n orgId,\n data: { bundleId: created.id, items: initial },\n }),\n ]\n : []),\n ]);\n return { bundle: created, items: initial };\n });\n this.logger.info('bundle created', {\n orgId,\n bundleId: bundle.id,\n name: bundle.name,\n itemCount: items.length,\n });\n return bundle;\n }\n\n async updateBundle(orgId: string, id: string, patch: UpdateBundleInput): Promise<Bundle> {\n const bundle = await this.uow.run(async ({ content, outbox }) => {\n const updated = await content.updateBundle(orgId, id, patch);\n if (!updated) {\n this.logger.warn('bundle update rejected — not found', { orgId, bundleId: id });\n throw new NotFoundError('Bundle', id);\n }\n await outbox.append([contentEvents.bundleUpdated.make({ orgId, data: updated })]);\n return updated;\n });\n this.logger.info('bundle updated', { orgId, bundleId: id, fields: Object.keys(patch) });\n return bundle;\n }\n\n async deleteBundle(orgId: string, id: string): Promise<void> {\n await this.uow.run(async ({ content, outbox }) => {\n // Snapshot before the delete — the event carries the last known state.\n const bundle = await content.findBundleById(orgId, id);\n if (!bundle) {\n this.logger.warn('bundle delete rejected — not found', { orgId, bundleId: id });\n throw new NotFoundError('Bundle', id);\n }\n const ok = await content.deleteBundle(orgId, id);\n if (!ok) {\n throw new NotFoundError('Bundle', id);\n }\n await outbox.append([contentEvents.bundleDeleted.make({ orgId, data: bundle })]);\n });\n this.logger.info('bundle deleted', { orgId, bundleId: id });\n }\n\n listBundleItems(orgId: string, bundleId: string): Promise<BundleItem[]> {\n return this.repo.listBundleItems(orgId, bundleId);\n }\n\n async addBundleItem(orgId: string, bundleId: string, contentId: string): Promise<BundleItem[]> {\n const items = await this.uow.run(async ({ content, outbox }) => {\n const all = await content.addBundleItem(orgId, bundleId, contentId);\n await outbox.append([\n contentEvents.bundleItemAdded.make({ orgId, data: { bundleId, items: all } }),\n ]);\n return all;\n });\n this.logger.info('bundle item added', { orgId, bundleId, contentId });\n return items;\n }\n\n async removeBundleItem(\n orgId: string,\n bundleId: string,\n contentId: string,\n ): Promise<BundleItem[]> {\n const items = await this.uow.run(async ({ content, outbox }) => {\n const all = await content.removeBundleItem(orgId, bundleId, contentId);\n await outbox.append([\n contentEvents.bundleItemRemoved.make({ orgId, data: { bundleId, items: all } }),\n ]);\n return all;\n });\n this.logger.info('bundle item removed', { orgId, bundleId, contentId });\n return items;\n }\n\n private async spaceUpdates(\n content: ContentRepository,\n orgId: string,\n spaceIds: string[],\n actor: Actor,\n ): Promise<NewDomainEvent[]> {\n const events: NewDomainEvent[] = [];\n for (const spaceId of spaceIds) {\n const space = await content.findSpace(orgId, spaceId);\n if (space) {\n events.push(\n contentEvents.spaceUpdated.make({ orgId, data: space, metadata: actorMetadata(actor) }),\n );\n }\n }\n return events;\n }\n\n private resolvedSpace(\n input: CreateSpaceInput | UpdateSpaceInput,\n current?: Space,\n ): {\n accessRule: Space['accessRule'];\n capacity: number | null;\n settings: SpaceSettings;\n } {\n const accessRule = input.accessRule ?? current?.accessRule ?? 'all_members';\n let capacity = input.capacity !== undefined ? input.capacity : (current?.capacity ?? null);\n if (accessRule === 'all_members') {\n if (input.capacity != null) {\n throw new InvalidInputError('An all-members space has no capacity');\n }\n capacity = null;\n }\n const settings = {\n ...(current?.settings ?? spaceSettingsDefaults),\n ...input.settings,\n };\n return { accessRule, capacity, settings };\n }\n\n async listCommunities(orgId: string, query: ListCommunitiesQuery): Promise<Page<CommunityView>> {\n return this.pageWithThumbnails(await this.repo.listCommunities(orgId, query));\n }\n\n async getCommunity(orgId: string, id: string): Promise<CommunityView | null> {\n const community = await this.repo.findCommunityById(orgId, id);\n return community ? this.withThumbnail(community) : null;\n }\n\n communitiesWithDigest(): Promise<CommunityDigest[]> {\n return this.repo.communitiesWithDigest();\n }\n\n listCommunitiesById(orgId: string, ids: string[]): Promise<Community[]> {\n return ids.length ? this.repo.findCommunitiesByIds(orgId, ids) : Promise.resolve([]);\n }\n\n getSpace(orgId: string, spaceId: string): Promise<SpaceDetail | null> {\n return this.repo.findSpace(orgId, spaceId);\n }\n\n async getCommunitySpace(\n orgId: string,\n communityId: string,\n spaceId: string,\n ): Promise<SpaceDetail | null> {\n const space = await this.repo.findSpace(orgId, spaceId);\n return space?.communityId === communityId ? space : null;\n }\n\n async listSpaces(orgId: string, communityId: string): Promise<SpaceDetail[]> {\n if (!(await this.getCommunity(orgId, communityId))) {\n throw new NotFoundError('Community', communityId);\n }\n return this.repo.listSpaces(orgId, communityId);\n }\n\n async getDmSettings(orgId: string, communityId: string): Promise<DmSettings | null> {\n const community = await this.repo.findCommunityById(orgId, communityId);\n return community?.settings.dm ?? null;\n }\n\n async createCommunity(\n orgId: string,\n input: CreateCommunityInput,\n actor: Actor,\n ): Promise<CommunityView> {\n assertConfigurator(actor);\n const community = await this.uow.run(async ({ content, outbox }) => {\n const created = await content.createCommunity(orgId, input, slugify(input.title));\n await outbox.append([\n contentEvents.communityCreated.make({\n orgId,\n data: created,\n metadata: actorMetadata(actor),\n }),\n ]);\n return created;\n });\n this.logger.info('community created', {\n orgId,\n communityId: community.id,\n actorId: actor.id,\n });\n return this.withThumbnail(community);\n }\n\n async updateCommunity(\n orgId: string,\n id: string,\n patch: UpdateCommunityInput,\n actor: Actor,\n ): Promise<CommunityView> {\n assertConfigurator(actor);\n await this.assertLibraryAssets(orgId, [patch.thumbnailAssetId], 'A community');\n const community = await this.uow.run(async ({ content, outbox }) => {\n const updated = await content.updateCommunity(orgId, id, patch);\n if (!updated) {\n this.logger.warn('community update rejected — not found', {\n orgId,\n communityId: id,\n actorId: actor.id,\n });\n throw new NotFoundError('Community', id);\n }\n await outbox.append([\n contentEvents.communityUpdated.make({\n orgId,\n data: updated,\n metadata: actorMetadata(actor),\n }),\n ]);\n return updated;\n });\n this.logger.info('community updated', { orgId, communityId: id, actorId: actor.id });\n return this.withThumbnail(community);\n }\n\n publishCommunity(orgId: string, id: string, actor: Actor): Promise<CommunityView> {\n return this.updateCommunity(orgId, id, { status: 'published' }, actor);\n }\n\n unpublishCommunity(orgId: string, id: string, actor: Actor): Promise<CommunityView> {\n return this.updateCommunity(orgId, id, { status: 'draft' }, actor);\n }\n\n async deleteCommunity(orgId: string, id: string, actor: Actor): Promise<void> {\n assertConfigurator(actor);\n await this.uow.run(async ({ content, outbox }) => {\n const community = await content.findCommunityById(orgId, id);\n if (!community) {\n this.logger.warn('community delete rejected — not found', {\n orgId,\n communityId: id,\n actorId: actor.id,\n });\n throw new NotFoundError('Community', id);\n }\n const linked = await content.spacesLinkingContent(orgId, id);\n const ok = await content.deleteCommunity(orgId, id);\n if (!ok) {\n throw new NotFoundError('Community', id);\n }\n await content.deleteCommunitySettings(orgId, id);\n await outbox.append([\n contentEvents.communityDeleted.make({\n orgId,\n data: community,\n metadata: actorMetadata(actor),\n }),\n ...(await this.spaceUpdates(content, orgId, linked, actor)),\n ]);\n });\n this.logger.info('community deleted', { orgId, communityId: id, actorId: actor.id });\n }\n\n async patchCommunitySettings(\n orgId: string,\n id: string,\n patch: PatchCommunitySettingsInput,\n actor: Actor,\n ): Promise<CommunityView> {\n assertConfigurator(actor);\n const community = await this.uow.run(async ({ content, outbox }) => {\n const updated = await content.patchCommunitySettings(orgId, id, patch);\n if (!updated) {\n this.logger.warn('community settings patch rejected — not found', {\n orgId,\n communityId: id,\n actorId: actor.id,\n });\n throw new NotFoundError('Community', id);\n }\n await outbox.append([\n contentEvents.communityUpdated.make({\n orgId,\n data: updated,\n metadata: actorMetadata(actor),\n }),\n ]);\n return updated;\n });\n this.logger.info('community settings patched', {\n orgId,\n communityId: id,\n actorId: actor.id,\n });\n return this.withThumbnail(community);\n }\n\n async createSpace(\n orgId: string,\n communityId: string,\n input: CreateSpaceInput,\n actor: Actor,\n ): Promise<SpaceDetail> {\n assertConfigurator(actor);\n const resolved = this.resolvedSpace(input);\n const space = await this.uow.run(async ({ content, outbox }) => {\n const community = await content.findCommunityById(orgId, communityId);\n if (!community) {\n this.logger.warn('space create rejected — community not found', {\n orgId,\n communityId,\n actorId: actor.id,\n });\n throw new NotFoundError('Community', communityId);\n }\n const created = await content.createSpace(orgId, communityId, {\n ...input,\n accessRule: resolved.accessRule,\n capacity: resolved.capacity,\n settings: resolved.settings,\n });\n await outbox.append([\n contentEvents.spaceCreated.make({\n orgId,\n data: created,\n metadata: actorMetadata(actor),\n }),\n ]);\n return created;\n });\n this.logger.info('space created', {\n orgId,\n communityId,\n spaceId: space.id,\n actorId: actor.id,\n });\n return space;\n }\n\n async updateSpace(\n orgId: string,\n communityId: string,\n spaceId: string,\n patch: UpdateSpaceInput,\n actor: Actor,\n ): Promise<SpaceDetail> {\n assertConfigurator(actor);\n const space = await this.uow.run(async ({ content, outbox }) => {\n const current = await content.findSpace(orgId, spaceId);\n if (!current || current.communityId !== communityId) {\n this.logger.warn('space update rejected — not found', {\n orgId,\n communityId,\n spaceId,\n actorId: actor.id,\n });\n throw new NotFoundError('Space', spaceId);\n }\n const resolved = this.resolvedSpace(patch, current);\n const updated = await content.updateSpace(orgId, communityId, spaceId, {\n ...patch,\n accessRule: resolved.accessRule,\n capacity: resolved.capacity,\n settings: resolved.settings,\n });\n if (!updated) {\n throw new NotFoundError('Space', spaceId);\n }\n await outbox.append([\n contentEvents.spaceUpdated.make({\n orgId,\n data: updated,\n metadata: actorMetadata(actor),\n }),\n ]);\n return updated;\n });\n this.logger.info('space updated', { orgId, communityId, spaceId, actorId: actor.id });\n return space;\n }\n\n async deleteSpace(\n orgId: string,\n communityId: string,\n spaceId: string,\n actor: Actor,\n ): Promise<void> {\n assertConfigurator(actor);\n await this.uow.run(async ({ content, outbox }) => {\n const space = await content.findSpace(orgId, spaceId);\n if (!space || space.communityId !== communityId) {\n this.logger.warn('space delete rejected — not found', {\n orgId,\n communityId,\n spaceId,\n actorId: actor.id,\n });\n throw new NotFoundError('Space', spaceId);\n }\n const ok = await content.deleteSpace(orgId, communityId, spaceId);\n if (!ok) {\n throw new NotFoundError('Space', spaceId);\n }\n await outbox.append([\n contentEvents.spaceDeleted.make({\n orgId,\n data: space,\n metadata: actorMetadata(actor),\n }),\n ]);\n });\n this.logger.info('space deleted', { orgId, communityId, spaceId, actorId: actor.id });\n }\n\n async reorderSpaces(\n orgId: string,\n communityId: string,\n orderedIds: string[],\n actor: Actor,\n ): Promise<SpaceDetail[]> {\n assertConfigurator(actor);\n const spaces = await this.uow.run(async ({ content, outbox }) => {\n const community = await content.findCommunityById(orgId, communityId);\n if (!community) {\n this.logger.warn('spaces reorder rejected — community not found', {\n orgId,\n communityId,\n actorId: actor.id,\n });\n throw new NotFoundError('Community', communityId);\n }\n const current = await content.listSpaces(orgId, communityId);\n if (\n !sameIdSet(\n current.map((space) => space.id),\n orderedIds,\n )\n ) {\n throw new ConflictError(\"Ordered space ids do not match the community's spaces\");\n }\n const reordered = await content.reorderSpaces(orgId, communityId, orderedIds);\n await outbox.append([\n contentEvents.spacesReordered.make({\n orgId,\n data: reordered,\n metadata: actorMetadata(actor),\n }),\n ]);\n return reordered;\n });\n this.logger.info('spaces reordered', { orgId, communityId, actorId: actor.id });\n return spaces;\n }\n\n async setSpaceTopics(\n orgId: string,\n communityId: string,\n spaceId: string,\n input: SetSpaceTopicsInput,\n actor: Actor,\n ): Promise<SpaceDetail> {\n assertConfigurator(actor);\n const names = input.topics.map((topic) => topic.name);\n if (new Set(names).size !== names.length) {\n throw new InvalidInputError('A space topic name is already used');\n }\n const space = await this.uow.run(async ({ content, outbox }) => {\n const locked = await content.lockSpace(orgId, spaceId);\n if (!locked || locked.communityId !== communityId) {\n this.logger.warn('space topics rejected — space not found', {\n orgId,\n communityId,\n spaceId,\n actorId: actor.id,\n });\n throw new NotFoundError('Space', spaceId);\n }\n const current = await content.findSpace(orgId, spaceId);\n if (!current) {\n throw new NotFoundError('Space', spaceId);\n }\n const kept = new Set(input.topics.flatMap((topic) => (topic.id ? [topic.id] : [])));\n const removed = current.topics\n .filter((topic) => !kept.has(topic.id))\n .map((topic) => topic.id);\n if (removed.length > 0 && (await content.topicsInUse(orgId, spaceId, removed)).length > 0) {\n throw new ConflictError('A topic used by a post cannot be removed');\n }\n const updated = await content.setSpaceTopics(orgId, spaceId, input);\n await outbox.append([\n contentEvents.spaceUpdated.make({\n orgId,\n data: updated,\n metadata: actorMetadata(actor),\n }),\n ]);\n return updated;\n });\n this.logger.info('space topics set', { orgId, communityId, spaceId, actorId: actor.id });\n return space;\n }\n\n async addSpaceLink(\n orgId: string,\n communityId: string,\n spaceId: string,\n contentId: string,\n actor: Actor,\n ): Promise<SpaceDetail> {\n assertConfigurator(actor);\n const space = await this.uow.run(async ({ content, outbox }) => {\n const current = await content.findSpace(orgId, spaceId);\n if (!current || current.communityId !== communityId) {\n this.logger.warn('space link add rejected — space not found', {\n orgId,\n communityId,\n spaceId,\n actorId: actor.id,\n });\n throw new NotFoundError('Space', spaceId);\n }\n if (current.links.some((link) => link.contentId === contentId)) {\n throw new ConflictError('This space already links to that content');\n }\n const updated = await content.addSpaceLink(orgId, spaceId, contentId);\n await outbox.append([\n contentEvents.spaceUpdated.make({\n orgId,\n data: updated,\n metadata: actorMetadata(actor),\n }),\n ]);\n return updated;\n });\n this.logger.info('space link added', {\n orgId,\n communityId,\n spaceId,\n contentId,\n actorId: actor.id,\n });\n return space;\n }\n\n async removeSpaceLink(\n orgId: string,\n communityId: string,\n spaceId: string,\n linkId: string,\n actor: Actor,\n ): Promise<SpaceDetail> {\n assertConfigurator(actor);\n const space = await this.uow.run(async ({ content, outbox }) => {\n const current = await content.findSpace(orgId, spaceId);\n if (!current || current.communityId !== communityId) {\n this.logger.warn('space link remove rejected — space not found', {\n orgId,\n communityId,\n spaceId,\n actorId: actor.id,\n });\n throw new NotFoundError('Space', spaceId);\n }\n const updated = await content.removeSpaceLink(orgId, spaceId, linkId);\n await outbox.append([\n contentEvents.spaceUpdated.make({\n orgId,\n data: updated,\n metadata: actorMetadata(actor),\n }),\n ]);\n return updated;\n });\n this.logger.info('space link removed', {\n orgId,\n communityId,\n spaceId,\n linkId,\n actorId: actor.id,\n });\n return space;\n }\n\n async reorderSpaceLinks(\n orgId: string,\n communityId: string,\n spaceId: string,\n orderedIds: string[],\n actor: Actor,\n ): Promise<SpaceDetail> {\n assertConfigurator(actor);\n const space = await this.uow.run(async ({ content, outbox }) => {\n const current = await content.findSpace(orgId, spaceId);\n if (!current || current.communityId !== communityId) {\n this.logger.warn('space links reorder rejected — space not found', {\n orgId,\n communityId,\n spaceId,\n actorId: actor.id,\n });\n throw new NotFoundError('Space', spaceId);\n }\n if (\n !sameIdSet(\n current.links.map((link) => link.id),\n orderedIds,\n )\n ) {\n throw new ConflictError(\"Ordered link ids do not match the space's links\");\n }\n const updated = await content.reorderSpaceLinks(orgId, spaceId, orderedIds);\n await outbox.append([\n contentEvents.spaceUpdated.make({\n orgId,\n data: updated,\n metadata: actorMetadata(actor),\n }),\n ]);\n return updated;\n });\n this.logger.info('space links reordered', {\n orgId,\n communityId,\n spaceId,\n actorId: actor.id,\n });\n return space;\n }\n}\n"],"mappings":"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"}
|