@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.
Files changed (205) hide show
  1. package/dist/assets/events.d.ts +9 -9
  2. package/dist/assets/index.d.ts +3 -2
  3. package/dist/assets/index.js +2 -1
  4. package/dist/assets/jobs.d.ts +15 -0
  5. package/dist/assets/jobs.js +30 -0
  6. package/dist/assets/jobs.js.map +1 -0
  7. package/dist/assets/ports.d.ts +4 -3
  8. package/dist/assets/service.d.ts +0 -1
  9. package/dist/assets/service.js +0 -4
  10. package/dist/assets/service.js.map +1 -1
  11. package/dist/automations/actions.js +2 -63
  12. package/dist/automations/actions.js.map +1 -1
  13. package/dist/automations/catalog.d.ts +1 -2
  14. package/dist/automations/catalog.js +69 -62
  15. package/dist/automations/catalog.js.map +1 -1
  16. package/dist/automations/community-derivations.js +4 -4
  17. package/dist/automations/community-derivations.js.map +1 -1
  18. package/dist/automations/community-mail.d.ts +3 -17
  19. package/dist/automations/community-mail.js +1 -21
  20. package/dist/automations/community-mail.js.map +1 -1
  21. package/dist/automations/events.d.ts +0 -10
  22. package/dist/automations/index.d.ts +11 -4
  23. package/dist/automations/index.js +8 -1
  24. package/dist/automations/notifications/debounce.d.ts +25 -0
  25. package/dist/automations/notifications/debounce.js +93 -0
  26. package/dist/automations/notifications/debounce.js.map +1 -0
  27. package/dist/automations/notifications/defaults.d.ts +8 -0
  28. package/dist/automations/notifications/defaults.js +316 -0
  29. package/dist/automations/notifications/defaults.js.map +1 -0
  30. package/dist/automations/notifications/delivery.d.ts +28 -0
  31. package/dist/automations/notifications/delivery.js +88 -0
  32. package/dist/automations/notifications/delivery.js.map +1 -0
  33. package/dist/automations/notifications/processor.d.ts +64 -0
  34. package/dist/automations/notifications/processor.js +270 -0
  35. package/dist/automations/notifications/processor.js.map +1 -0
  36. package/dist/automations/notifications/rules/content.d.ts +6 -0
  37. package/dist/automations/notifications/rules/content.js +39 -0
  38. package/dist/automations/notifications/rules/content.js.map +1 -0
  39. package/dist/automations/notifications/rules/discussion.d.ts +7 -0
  40. package/dist/automations/notifications/rules/discussion.js +678 -0
  41. package/dist/automations/notifications/rules/discussion.js.map +1 -0
  42. package/dist/automations/notifications/rules/entitlements.d.ts +6 -0
  43. package/dist/automations/notifications/rules/entitlements.js +249 -0
  44. package/dist/automations/notifications/rules/entitlements.js.map +1 -0
  45. package/dist/automations/notifications/rules/index.d.ts +6 -0
  46. package/dist/automations/notifications/rules/index.js +15 -0
  47. package/dist/automations/notifications/rules/index.js.map +1 -0
  48. package/dist/automations/notifications/rules/organizations.d.ts +6 -0
  49. package/dist/automations/notifications/rules/organizations.js +28 -0
  50. package/dist/automations/notifications/rules/organizations.js.map +1 -0
  51. package/dist/automations/notifications/rules/recipients.d.ts +32 -0
  52. package/dist/automations/notifications/rules/recipients.js +99 -0
  53. package/dist/automations/notifications/rules/recipients.js.map +1 -0
  54. package/dist/automations/notifications/service.d.ts +27 -0
  55. package/dist/automations/notifications/service.js +45 -0
  56. package/dist/automations/notifications/service.js.map +1 -0
  57. package/dist/automations/notifications/types.d.ts +7 -0
  58. package/dist/automations/notifications/types.js +473 -0
  59. package/dist/automations/notifications/types.js.map +1 -0
  60. package/dist/automations/ports.d.ts +119 -5
  61. package/dist/automations/service.d.ts +10 -13
  62. package/dist/automations/service.js +21 -83
  63. package/dist/automations/service.js.map +1 -1
  64. package/dist/content/events.d.ts +130 -80
  65. package/dist/content/events.js +11 -0
  66. package/dist/content/events.js.map +1 -1
  67. package/dist/content/index.d.ts +6 -4
  68. package/dist/content/index.js +3 -1
  69. package/dist/content/model.d.ts +2 -2
  70. package/dist/content/notification-categories.d.ts +36 -0
  71. package/dist/content/notification-categories.js +64 -0
  72. package/dist/content/notification-categories.js.map +1 -0
  73. package/dist/content/ports.d.ts +25 -6
  74. package/dist/content/service.d.ts +4 -4
  75. package/dist/content/service.js +24 -8
  76. package/dist/content/service.js.map +1 -1
  77. package/dist/content/titles.d.ts +22 -0
  78. package/dist/content/titles.js +69 -0
  79. package/dist/content/titles.js.map +1 -0
  80. package/dist/content/types.d.ts +2 -2
  81. package/dist/discussion/chats.d.ts +9 -4
  82. package/dist/discussion/chats.js +80 -47
  83. package/dist/discussion/chats.js.map +1 -1
  84. package/dist/discussion/digests.d.ts +24 -0
  85. package/dist/discussion/digests.js +104 -0
  86. package/dist/discussion/digests.js.map +1 -0
  87. package/dist/discussion/events.d.ts +194 -28
  88. package/dist/discussion/events.js +74 -17
  89. package/dist/discussion/events.js.map +1 -1
  90. package/dist/discussion/index.d.ts +7 -2
  91. package/dist/discussion/index.js +6 -1
  92. package/dist/discussion/jobs.d.ts +16 -0
  93. package/dist/discussion/jobs.js +40 -0
  94. package/dist/discussion/jobs.js.map +1 -0
  95. package/dist/discussion/mentions.d.ts +11 -0
  96. package/dist/discussion/mentions.js +35 -0
  97. package/dist/discussion/mentions.js.map +1 -0
  98. package/dist/discussion/ports.d.ts +107 -24
  99. package/dist/discussion/ports.js.map +1 -1
  100. package/dist/discussion/posts.d.ts +18 -8
  101. package/dist/discussion/posts.js +207 -155
  102. package/dist/discussion/posts.js.map +1 -1
  103. package/dist/discussion/service.d.ts +17 -8
  104. package/dist/discussion/service.js +105 -41
  105. package/dist/discussion/service.js.map +1 -1
  106. package/dist/discussion/subscriptions.d.ts +37 -0
  107. package/dist/discussion/subscriptions.js +99 -0
  108. package/dist/discussion/subscriptions.js.map +1 -0
  109. package/dist/discussion/titles.d.ts +26 -0
  110. package/dist/discussion/titles.js +84 -0
  111. package/dist/discussion/titles.js.map +1 -0
  112. package/dist/entitlements/events.d.ts +20 -20
  113. package/dist/entitlements/index.d.ts +2 -1
  114. package/dist/entitlements/index.js +2 -1
  115. package/dist/entitlements/jobs.d.ts +12 -0
  116. package/dist/entitlements/jobs.js +18 -0
  117. package/dist/entitlements/jobs.js.map +1 -0
  118. package/dist/entitlements/ports.d.ts +7 -3
  119. package/dist/entitlements/service.d.ts +5 -2
  120. package/dist/entitlements/service.js +23 -3
  121. package/dist/entitlements/service.js.map +1 -1
  122. package/dist/identity/devices.d.ts +30 -0
  123. package/dist/identity/devices.js +107 -0
  124. package/dist/identity/devices.js.map +1 -0
  125. package/dist/identity/events.d.ts +2 -2
  126. package/dist/identity/index.d.ts +5 -4
  127. package/dist/identity/index.js +3 -2
  128. package/dist/identity/model.d.ts +2 -2
  129. package/dist/identity/notification-settings.d.ts +28 -0
  130. package/dist/identity/notification-settings.js +113 -0
  131. package/dist/identity/notification-settings.js.map +1 -0
  132. package/dist/identity/ports.d.ts +78 -54
  133. package/dist/integrations/events.d.ts +3 -3
  134. package/dist/organizations/events.d.ts +32 -32
  135. package/dist/organizations/index.d.ts +2 -1
  136. package/dist/organizations/index.js +2 -1
  137. package/dist/organizations/notification-categories.d.ts +32 -0
  138. package/dist/organizations/notification-categories.js +51 -0
  139. package/dist/organizations/notification-categories.js.map +1 -0
  140. package/dist/organizations/ports.d.ts +3 -0
  141. package/dist/organizations/service.d.ts +2 -0
  142. package/dist/organizations/service.js +7 -0
  143. package/dist/organizations/service.js.map +1 -1
  144. package/dist/progress/events.d.ts +14 -14
  145. package/dist/reporting/member/index.d.ts +2 -2
  146. package/dist/reporting/member/model.d.ts +56 -23
  147. package/dist/reporting/member/ports.d.ts +9 -6
  148. package/dist/reporting/member/service.d.ts +33 -14
  149. package/dist/reporting/member/service.js +138 -60
  150. package/dist/reporting/member/service.js.map +1 -1
  151. package/dist/shared/errors.d.ts +13 -1
  152. package/dist/shared/errors.js +18 -1
  153. package/dist/shared/errors.js.map +1 -1
  154. package/dist/shared/id.d.ts +3 -0
  155. package/dist/shared/id.js +4 -1
  156. package/dist/shared/id.js.map +1 -1
  157. package/dist/shared/mailer.d.ts +11 -1
  158. package/dist/shared/mailer.js +32 -5
  159. package/dist/shared/mailer.js.map +1 -1
  160. package/dist/shared/notification-categories.d.ts +16 -0
  161. package/dist/shared/notification-categories.js +94 -0
  162. package/dist/shared/notification-categories.js.map +1 -0
  163. package/dist/shared/notification-settings.d.ts +14 -0
  164. package/dist/shared/notification-settings.js +61 -0
  165. package/dist/shared/notification-settings.js.map +1 -0
  166. package/dist/shared/ports.d.ts +48 -2
  167. package/dist/shared/settings.d.ts +2 -1
  168. package/dist/shared/settings.js +1 -0
  169. package/dist/shared/settings.js.map +1 -1
  170. package/dist/types/automations.d.ts +8 -2
  171. package/dist/types/content.d.ts +2 -2
  172. package/dist/types/discussion.d.ts +2 -2
  173. package/dist/types/email-templates.d.ts +97 -3
  174. package/dist/types/identity.d.ts +2 -2
  175. package/dist/types/index.d.ts +7 -6
  176. package/dist/types/notifications.d.ts +157 -0
  177. package/dist/types/notifications.js +1 -0
  178. package/dist/types/schemas/automations.d.ts +1 -10
  179. package/dist/types/schemas/automations.js +1 -3
  180. package/dist/types/schemas/automations.js.map +1 -1
  181. package/dist/types/schemas/content.d.ts +62 -1
  182. package/dist/types/schemas/content.js +25 -3
  183. package/dist/types/schemas/content.js.map +1 -1
  184. package/dist/types/schemas/discussion.d.ts +85 -12
  185. package/dist/types/schemas/discussion.js +47 -13
  186. package/dist/types/schemas/discussion.js.map +1 -1
  187. package/dist/types/schemas/identity.d.ts +1 -85
  188. package/dist/types/schemas/identity.js +1 -42
  189. package/dist/types/schemas/identity.js.map +1 -1
  190. package/dist/types/schemas/index.d.ts +6 -5
  191. package/dist/types/schemas/index.js +6 -5
  192. package/dist/types/schemas/notifications.d.ts +95 -0
  193. package/dist/types/schemas/notifications.js +56 -0
  194. package/dist/types/schemas/notifications.js.map +1 -0
  195. package/dist/types/schemas/progress.d.ts +3 -3
  196. package/package.json +1 -1
  197. package/dist/automations/community-notifications.d.ts +0 -16
  198. package/dist/automations/community-notifications.js +0 -84
  199. package/dist/automations/community-notifications.js.map +0 -1
  200. package/dist/automations/seeds.d.ts +0 -17
  201. package/dist/automations/seeds.js +0 -235
  202. package/dist/automations/seeds.js.map +0 -1
  203. package/dist/identity/notifications.d.ts +0 -27
  204. package/dist/identity/notifications.js +0 -101
  205. 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"}
@@ -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, PatchDmSettingsInput, SaveActivityInput, SetSpaceTopicsInput, Space, SpaceDetail, UpdateBundleInput, UpdateCommunityInput, UpdateCourseInput, UpdateDownloadInput, UpdateSpaceInput } from "../types/schemas/content.js";
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
- listPublishedCommunityIds(orgId: string): Promise<string[]>;
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
- patchDmSettings(orgId: string, id: string, patch: PatchDmSettingsInput, actor: Actor): Promise<CommunityView>;
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
- listPublishedCommunityIds(orgId: string): Promise<string[]>;
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
- patchDmSettings(orgId: string, id: string, patch: PatchDmSettingsInput): Promise<Community | null>;
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, PatchDmSettingsInput, SaveActivityInput, SetSpaceTopicsInput, SpaceDetail, UpdateBundleInput, UpdateCommunityInput, UpdateCourseInput, UpdateDownloadInput, UpdateSpaceInput } from "../types/schemas/content.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, 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
- listPublishedCommunityIds(orgId: string): Promise<string[]>;
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
- patchDmSettings(orgId: string, id: string, patch: PatchDmSettingsInput, actor: Actor): Promise<CommunityView>;
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>;
@@ -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
- await outbox.append([activityId ? contentEvents.activityUpdated.make({
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
- listPublishedCommunityIds(orgId) {
689
- return this.repo.listPublishedCommunityIds(orgId);
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 patchDmSettings(orgId, id, patch, actor) {
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.patchDmSettings(orgId, id, patch);
805
+ const updated = await content.patchCommunitySettings(orgId, id, patch);
790
806
  if (!updated) {
791
- this.logger.warn("community dm settings patch rejected — not found", {
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 dm settings patched", {
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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"}