@headless-lms/core 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/file-urls.d.ts +5 -19
- package/dist/assets/file-urls.js +2 -23
- package/dist/assets/file-urls.js.map +1 -1
- package/dist/assets/index.d.ts +3 -3
- package/dist/assets/ports.d.ts +9 -10
- package/dist/assets/service.d.ts +10 -13
- package/dist/assets/service.js +41 -62
- package/dist/assets/service.js.map +1 -1
- package/dist/content/events.d.ts +13 -13
- package/dist/content/service.d.ts +4 -1
- package/dist/content/service.js +52 -29
- package/dist/content/service.js.map +1 -1
- package/dist/discussion/chats.d.ts +1 -2
- package/dist/discussion/chats.js +8 -17
- package/dist/discussion/chats.js.map +1 -1
- package/dist/discussion/ports.d.ts +0 -6
- package/dist/discussion/ports.js.map +1 -1
- package/dist/discussion/posts.d.ts +1 -4
- package/dist/discussion/posts.js +8 -21
- package/dist/discussion/posts.js.map +1 -1
- package/dist/entitlements/events.d.ts +33 -33
- package/dist/identity/events.d.ts +2 -2
- package/dist/integrations/events.d.ts +3 -3
- package/dist/organizations/events.d.ts +2 -2
- package/dist/reporting/member/ports.d.ts +1 -10
- package/dist/reporting/member/service.d.ts +2 -11
- package/dist/reporting/member/service.js +12 -62
- package/dist/reporting/member/service.js.map +1 -1
- package/dist/types/ports.d.ts +4 -2
- package/dist/types/ports.js.map +1 -1
- package/dist/types/schemas/content.d.ts +4 -4
- package/dist/types/schemas/discussion.d.ts +14 -14
- package/dist/types/schemas/entitlements.d.ts +8 -8
- package/dist/types/schemas/notifications.d.ts +3 -3
- package/package.json +1 -1
|
@@ -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 Event,\n EventAsset,\n EventFile,\n EventLead,\n EventView,\n Module,\n SaveActivityInput,\n Space,\n SpaceDetail,\n SpaceImage,\n SpaceSettings,\n SpaceView,\n} from './model.js';\nimport type {\n BundlesService,\n CommunitiesService,\n CommunityDigest,\n CourseManagementService,\n ContentAssetReader,\n ContentRepository,\n ContentUnitOfWork,\n DownloadablesService,\n EventsService,\n} from './ports.js';\nimport type {\n AddDownloadAssetInput,\n AddEventAssetInput,\n CreateBundleInput,\n CreateCommunityInput,\n CreateCourseInput,\n CreateDownloadInput,\n CreateEventInput,\n CreateSpaceInput,\n ListBundlesQuery,\n ListCommunitiesQuery,\n ListCoursesQuery,\n ListDownloadsQuery,\n ListEventsQuery,\n Page,\n PatchCommunitySettingsInput,\n SetSpaceTopicsInput,\n UpdateBundleInput,\n UpdateCommunityInput,\n UpdateCourseInput,\n UpdateDownloadInput,\n UpdateEventInput,\n UpdateSpaceInput,\n} from './types.js';\nimport { isDeepStrictEqual } from 'node:util';\nimport { contentEvents } from './events.js';\nimport { EVENT_LEADS, EVENT_STARTING_SOON_JOB } from './jobs.js';\nimport type { Actor } from '../shared/actor.js';\nimport type { AssetFiles, FileUrls } from '../assets/index.js';\nimport type { Logger, NewDomainEvent, Scheduler } 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';\nimport type { EventMetadata, Permission } from '../types/index.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: ContentAssetReader;\n files: Pick<AssetFiles, 'readyFiles' | 'syncPublicImages'>;\n fileUrls: FileUrls;\n scheduler: Pick<Scheduler, 'at' | 'cancel'>;\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): { actorId: string } {\n return { actorId: actor.id };\n}\n\nconst COMMUNITY_READERS: readonly Permission[] = ['communities:read', 'communities:moderate'];\n\nfunction eventChange(actor: Actor, previous: Event, next: Event): EventMetadata {\n return {\n actorId: actor.id,\n previousStatus: previous.status,\n previousType: previous.settings.type,\n previousStartsAt: previous.startsAt.toISOString(),\n previousEndsAt: previous.endsAt.toISOString(),\n locationChanged: !isDeepStrictEqual(previous.location, next.location),\n };\n}\n\nfunction assertEventTimes(startsAt: Date, endsAt: Date): void {\n if (endsAt.getTime() <= startsAt.getTime()) {\n throw new InvalidInputError('An event must end after it starts');\n }\n}\n\nfunction startingSoonKey(eventId: string, lead: EventLead): string {\n return `${eventId}:${lead}`;\n}\n\nconst EVENT_LEAD_KEYS = Object.keys(EVENT_LEADS) as EventLead[];\n\ntype WithThumbnail = {\n orgId: string;\n id: string;\n type: 'course' | 'download' | 'community' | 'event';\n status: string;\n thumbnailAssetId: string | null;\n};\n\nfunction shownPublicly(item: Pick<WithThumbnail, 'type' | 'status'>): boolean {\n return item.status === 'published' || (item.type === 'event' && item.status === 'canceled');\n}\n\nfunction spaceImageIds(space: Space): string[] {\n return [space.coverAssetId, space.backgroundAssetId, space.iconAssetId].filter(\n (id): id is string => id !== null,\n );\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\n CourseManagementService,\n DownloadablesService,\n BundlesService,\n CommunitiesService,\n EventsService\n{\n private readonly repo: ContentRepository;\n private readonly uow: ContentUnitOfWork;\n private readonly libraryAssets: ContentAssetReader;\n private readonly files: Pick<AssetFiles, 'readyFiles' | 'syncPublicImages'>;\n private readonly fileUrls: FileUrls;\n private readonly scheduler: Pick<Scheduler, 'at' | 'cancel'>;\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.scheduler = params.scheduler;\n this.logger = params.logger ?? noopLogger;\n }\n\n private require(actor: Actor, permission: Permission, on?: string): void {\n this.requireAny(actor, [permission], on);\n }\n\n private requireAny(actor: Actor, permissions: readonly Permission[], on?: string): void {\n if (!permissions.some((permission) => actor.permissions.has(permission, on))) {\n this.logger.warn('content action refused', {\n orgId: actor.orgId,\n actorId: actor.id,\n permission: permissions.join(' or '),\n contentId: on,\n });\n throw new ForbiddenError(`You need ${permissions.join(' or ')}`);\n }\n }\n\n private visibleIds(\n actor: Actor,\n permissions: readonly Permission[],\n what: string,\n ): string[] | undefined {\n const wheres = permissions.map((permission) => actor.permissions.where(permission));\n if (wheres.some((where) => where.org)) {\n return undefined;\n }\n const ids = [...new Set(wheres.flatMap((where) => where.content))];\n if (ids.length === 0) {\n this.logger.warn('content list refused', {\n orgId: actor.orgId,\n actorId: actor.id,\n permission: permissions.join(' or '),\n });\n throw new ForbiddenError(`You cannot see ${what}`);\n }\n return ids;\n }\n\n private withThumbnail<T extends WithThumbnail>(item: T): T & { thumbnailUrl: string | null } {\n return {\n ...item,\n thumbnailUrl: !item.thumbnailAssetId\n ? null\n : shownPublicly(item)\n ? this.fileUrls.publicImage(item.orgId, item.id, item.thumbnailAssetId)\n : this.fileUrls.thumbnail(item.type, item.id),\n };\n }\n\n private syncThumbnail(item: WithThumbnail): Promise<void> {\n return this.files.syncPublicImages(\n item.orgId,\n item.id,\n shownPublicly(item) && item.thumbnailAssetId ? [item.thumbnailAssetId] : [],\n );\n }\n\n private withdrawThumbnail(orgId: string, id: string): Promise<void> {\n return this.files.syncPublicImages(orgId, id, []);\n }\n\n private spaceView(space: SpaceDetail, published: boolean): SpaceView {\n const url = (image: SpaceImage, assetId: string | null) =>\n !assetId\n ? null\n : published\n ? this.fileUrls.publicImage(space.orgId, space.id, assetId)\n : this.fileUrls.spaceImage(space.id, image);\n return {\n ...space,\n coverUrl: url('cover', space.coverAssetId),\n backgroundUrl: url('background', space.backgroundAssetId),\n iconUrl: url('icon', space.iconAssetId),\n };\n }\n\n private async communityPublished(orgId: string, communityId: string): Promise<boolean> {\n return (await this.repo.findCommunityById(orgId, communityId))?.status === 'published';\n }\n\n private async oneSpaceView(space: SpaceDetail): Promise<SpaceView> {\n return this.spaceView(space, await this.communityPublished(space.orgId, space.communityId));\n }\n\n private syncSpaceImages(space: Space, published: boolean): Promise<void> {\n return this.files.syncPublicImages(\n space.orgId,\n space.id,\n published ? spaceImageIds(space) : [],\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 private async eventFiles(orgId: string, links: EventAsset[]): Promise<EventFile[]> {\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.eventFile(link.eventId, link.assetId) }]\n : [];\n });\n }\n\n private async assertAttachable(\n actor: Actor,\n itemId: string,\n requested: (string | null | undefined)[],\n attached: () => Promise<(string | null)[]>,\n user: string,\n ): Promise<void> {\n const ids = [...new Set(requested.filter((id): id is string => typeof id === 'string'))];\n if (ids.length === 0) {\n return;\n }\n const held = new Set(await attached());\n const added = ids.filter((id) => !held.has(id));\n if (added.length === 0) {\n return;\n }\n const orgId = actor.orgId;\n const found = new Map(\n (await this.libraryAssets.libraryAssetsFor(orgId, added)).map((asset) => [asset.id, asset]),\n );\n const missing = added.filter((id) => !found.has(id));\n if (missing.length > 0) {\n this.logger.warn('library assets refused', { orgId, contentId: itemId, assetIds: missing });\n throw new ConflictError(\n `${user} can only use ready files from the media library. Not available: ${missing.join(', ')}`,\n );\n }\n if (actor.permissions.has('media:read')) {\n return;\n }\n const foreign = added.filter((id) => found.get(id)?.contentId !== itemId);\n if (foreign.length > 0) {\n this.logger.warn('library assets refused — not uploaded for this item', {\n orgId,\n actorId: actor.id,\n contentId: itemId,\n assetIds: foreign,\n });\n throw new ForbiddenError(\n `You need media:read to use files that were not uploaded for this item: ${foreign.join(', ')}`,\n );\n }\n }\n\n private async courseAssetIds(orgId: string, courseId: string): Promise<(string | null)[]> {\n const [course, links] = await Promise.all([\n this.repo.findCourseById(orgId, courseId),\n this.repo.listActivityAssetsForCourse(orgId, courseId),\n ]);\n return [course?.thumbnailAssetId ?? null, ...links.map((link) => link.assetId)];\n }\n\n private async downloadAssetIds(orgId: string, downloadId: string): Promise<(string | null)[]> {\n const [download, links] = await Promise.all([\n this.repo.getDownload(orgId, downloadId),\n this.repo.listDownloadAssets(orgId, downloadId),\n ]);\n return [download?.thumbnailAssetId ?? null, ...links.map((link) => link.assetId)];\n }\n\n private async eventAssetIds(orgId: string, eventId: string): Promise<(string | null)[]> {\n const [event, links] = await Promise.all([\n this.repo.findEventById(orgId, eventId),\n this.repo.listEventAssets(orgId, eventId),\n ]);\n if (!event) {\n throw new NotFoundError('Event', eventId);\n }\n return [event.thumbnailAssetId, ...links.map((link) => link.assetId)];\n }\n\n async listCourses(query: ListCoursesQuery, actor: Actor): Promise<Page<CourseView>> {\n const ids = this.visibleIds(actor, ['courses:read'], 'courses');\n return this.pageWithThumbnails(await this.repo.listCourses(actor.orgId, query, ids));\n }\n\n async getCourse(id: string, actor: Actor): Promise<CourseView> {\n const course = await this.findCourse(id, actor);\n if (!course) {\n throw new NotFoundError('Course', id);\n }\n return course;\n }\n\n async findCourse(id: string, actor: Actor): Promise<CourseView | null> {\n this.require(actor, 'courses:read', id);\n const course = await this.repo.findCourseById(actor.orgId, id);\n return course ? this.withThumbnail(course) : null;\n }\n\n async createCourse(input: CreateCourseInput, actor: Actor): Promise<CourseView> {\n this.require(actor, 'courses:write');\n const orgId = actor.orgId;\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', {\n orgId,\n courseId: course.id,\n title: course.title,\n actorId: actor.id,\n });\n return this.withThumbnail(course);\n }\n\n async updateCourse(id: string, patch: UpdateCourseInput, actor: Actor): Promise<CourseView> {\n this.require(actor, 'courses:write', id);\n const orgId = actor.orgId;\n await this.assertAttachable(\n actor,\n id,\n [patch.thumbnailAssetId],\n () => this.courseAssetIds(orgId, id),\n 'A course',\n );\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', {\n orgId,\n courseId: id,\n fields: Object.keys(patch),\n actorId: actor.id,\n });\n await this.syncThumbnail(course);\n return this.withThumbnail(course);\n }\n\n async patchCourseSettings(\n id: string,\n value: Partial<CourseSettings>,\n actor: Actor,\n ): Promise<CourseSettings> {\n this.require(actor, 'courses:write', id);\n const orgId = actor.orgId;\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, actorId: actor.id });\n return merged;\n }\n\n async deleteCourse(id: string, actor: Actor): Promise<void> {\n this.require(actor, 'courses:delete', id);\n const orgId = actor.orgId;\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, actorId: actor.id });\n await this.withdrawThumbnail(orgId, id);\n }\n\n // --- modules & activities ------------------------------------------------\n\n async listCourseModules(courseId: string, actor: Actor): Promise<Module[]> {\n this.require(actor, 'courses:read', courseId);\n return this.repo.listCourseModules(actor.orgId, courseId);\n }\n async listCourseActivities(courseId: string, actor: Actor): Promise<Activity[]> {\n this.require(actor, 'courses:read', courseId);\n return this.repo.listActivitiesForCourse(actor.orgId, courseId);\n }\n async listCourseActivityViews(courseId: string, actor: Actor): Promise<ActivityView[]> {\n this.require(actor, 'courses:read', courseId);\n const [activities, links] = await Promise.all([\n this.repo.listActivitiesForCourse(actor.orgId, courseId),\n this.repo.listActivityAssetsForCourse(actor.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 async listCourseActivityAssets(courseId: string, actor: Actor): Promise<ActivityAsset[]> {\n this.require(actor, 'courses:read', courseId);\n return this.repo.listActivityAssetsForCourse(actor.orgId, courseId);\n }\n async getActivity(activityId: string, actor: Actor): Promise<Activity | null> {\n const activity = await this.repo.findActivity(actor.orgId, activityId);\n if (activity) {\n this.require(actor, 'courses:read', activity.courseId);\n }\n return activity;\n }\n async getModule(moduleId: string, actor: Actor): Promise<Module | null> {\n const module = await this.repo.findModule(actor.orgId, moduleId);\n if (module) {\n this.require(actor, 'courses:read', module.courseId);\n }\n return module;\n }\n\n async reorderModules(courseId: string, orderedIds: string[], actor: Actor): Promise<Module[]> {\n this.require(actor, 'courses:write', courseId);\n const orgId = actor.orgId;\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(courseId: string, title: string, actor: Actor): Promise<Module[]> {\n this.require(actor, 'courses:write', courseId);\n const orgId = actor.orgId;\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', {\n orgId,\n courseId,\n moduleId: created.id,\n title,\n actorId: actor.id,\n });\n return modules;\n }\n\n async updateModule(\n courseId: string,\n moduleId: string,\n title: string,\n actor: Actor,\n ): Promise<Module[]> {\n this.require(actor, 'courses:write', courseId);\n const orgId = actor.orgId;\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, actorId: actor.id });\n return modules;\n }\n\n async deleteModule(courseId: string, moduleId: string, actor: Actor): Promise<Module[]> {\n this.require(actor, 'courses:write', courseId);\n const orgId = actor.orgId;\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, actorId: actor.id });\n return modules;\n }\n\n async reorderActivities(\n courseId: string,\n moduleId: string,\n orderedIds: string[],\n actor: Actor,\n ): Promise<Module[]> {\n this.require(actor, 'courses:write', courseId);\n const orgId = actor.orgId;\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 async saveActivity(\n courseId: string,\n moduleId: string,\n input: SaveActivityInput,\n activityId: string | null,\n actor: Actor,\n ): Promise<Module[]> {\n this.require(actor, 'courses:write', courseId);\n const orgId = actor.orgId;\n await this.assertAttachable(\n actor,\n courseId,\n input.assetIds ?? [],\n () => this.courseAssetIds(orgId, courseId),\n 'An activity',\n );\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 ?? undefined,\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 actorId: actor.id,\n });\n return modules;\n }\n\n async deleteActivity(\n courseId: string,\n moduleId: string,\n activityId: string,\n actor: Actor,\n ): Promise<Module[]> {\n this.require(actor, 'courses:write', courseId);\n const orgId = actor.orgId;\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', {\n orgId,\n courseId,\n moduleId,\n activityId,\n actorId: actor.id,\n });\n return modules;\n }\n\n // --- downloads ------------------------------------------------------------\n\n async listDownloads(query: ListDownloadsQuery, actor: Actor): Promise<Page<DownloadView>> {\n const ids = this.visibleIds(actor, ['downloads:read'], 'downloads');\n return this.pageWithThumbnails(await this.repo.listDownloads(actor.orgId, query, ids));\n }\n\n async getDownload(id: string, actor: Actor): Promise<DownloadView> {\n const download = await this.findDownload(id, actor);\n if (!download) {\n throw new NotFoundError('Download', id);\n }\n return download;\n }\n\n async findDownload(id: string, actor: Actor): Promise<DownloadView | null> {\n this.require(actor, 'downloads:read', id);\n const download = await this.repo.getDownload(actor.orgId, id);\n return download ? this.withThumbnail(download) : null;\n }\n\n async createDownload(input: CreateDownloadInput, actor: Actor): Promise<DownloadView> {\n this.require(actor, 'downloads:write');\n const orgId = actor.orgId;\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', {\n orgId,\n downloadId: download.id,\n title: download.title,\n actorId: actor.id,\n });\n return this.withThumbnail(download);\n }\n\n async updateDownload(\n id: string,\n patch: UpdateDownloadInput,\n actor: Actor,\n ): Promise<DownloadView> {\n this.require(actor, 'downloads:write', id);\n const orgId = actor.orgId;\n await this.assertAttachable(\n actor,\n id,\n [patch.thumbnailAssetId],\n () => this.downloadAssetIds(orgId, id),\n 'A download',\n );\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', {\n orgId,\n downloadId: id,\n fields: Object.keys(patch),\n actorId: actor.id,\n });\n await this.syncThumbnail(download);\n return this.withThumbnail(download);\n }\n\n async removeDownload(id: string, actor: Actor): Promise<void> {\n this.require(actor, 'downloads:delete', id);\n const orgId = actor.orgId;\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, actorId: actor.id });\n await this.withdrawThumbnail(orgId, id);\n }\n\n // --- download asset links ------------------------------------------------\n\n async listDownloadAssets(downloadId: string, actor: Actor): Promise<DownloadFile[]> {\n this.require(actor, 'downloads:read', downloadId);\n return this.downloadFiles(\n actor.orgId,\n await this.repo.listDownloadAssets(actor.orgId, downloadId),\n );\n }\n\n async addDownloadAsset(\n downloadId: string,\n input: AddDownloadAssetInput,\n actor: Actor,\n ): Promise<DownloadFile[]> {\n this.require(actor, 'downloads:write', downloadId);\n const orgId = actor.orgId;\n await this.assertAttachable(\n actor,\n downloadId,\n [input.assetId],\n () => this.downloadAssetIds(orgId, downloadId),\n 'A download',\n );\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', {\n orgId,\n downloadId,\n assetId: input.assetId,\n actorId: actor.id,\n });\n return this.downloadFiles(orgId, assets);\n }\n\n async removeDownloadAsset(\n downloadId: string,\n assetId: string,\n actor: Actor,\n ): Promise<DownloadFile[]> {\n this.require(actor, 'downloads:write', downloadId);\n const orgId = actor.orgId;\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, actorId: actor.id });\n return this.downloadFiles(orgId, assets);\n }\n\n async renameDownloadAsset(\n downloadId: string,\n assetId: string,\n displayName: string | null,\n actor: Actor,\n ): Promise<DownloadFile[]> {\n this.require(actor, 'downloads:write', downloadId);\n const orgId = actor.orgId;\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, actorId: actor.id });\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 downloadId: string,\n assetIds: string[],\n actor: Actor,\n ): Promise<DownloadFile[]> {\n this.require(actor, 'downloads:write', downloadId);\n const orgId = actor.orgId;\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 async listEvents(query: ListEventsQuery, actor: Actor): Promise<Page<EventView>> {\n const ids = this.visibleIds(actor, ['events:read'], 'events');\n return this.pageWithThumbnails(await this.repo.listEvents(actor.orgId, query, ids));\n }\n\n async getEvent(id: string, actor: Actor): Promise<EventView> {\n const event = await this.findEvent(id, actor);\n if (!event) {\n throw new NotFoundError('Event', id);\n }\n return event;\n }\n\n async findEvent(id: string, actor: Actor): Promise<EventView | null> {\n this.require(actor, 'events:read', id);\n const event = await this.repo.findEventById(actor.orgId, id);\n return event ? this.withThumbnail(event) : null;\n }\n\n async findEvents(ids: string[], actor: Actor): Promise<EventView[]> {\n for (const id of ids) {\n this.require(actor, 'events:read', id);\n }\n if (ids.length === 0) {\n return [];\n }\n const found = await this.repo.findEventsByIds(actor.orgId, ids);\n return found.map((event) => this.withThumbnail(event));\n }\n\n async createEvent(input: CreateEventInput, actor: Actor): Promise<EventView> {\n this.require(actor, 'events:write');\n assertEventTimes(input.startsAt, input.endsAt);\n const orgId = actor.orgId;\n const { settings, ...fields } = input;\n const event = await this.uow.run(async ({ content, outbox }) => {\n const created = await content.createEvent(orgId, fields);\n const event = settings\n ? { ...created, settings: await content.patchEventSettings(orgId, created.id, settings) }\n : created;\n await outbox.append([\n contentEvents.eventCreated.make({ orgId, data: event, metadata: actorMetadata(actor) }),\n ]);\n return event;\n });\n this.logger.info('event created', {\n orgId,\n eventId: event.id,\n title: event.title,\n actorId: actor.id,\n });\n return this.withThumbnail(event);\n }\n\n async updateEvent(id: string, patch: UpdateEventInput, actor: Actor): Promise<EventView> {\n this.require(actor, 'events:write', id);\n const orgId = actor.orgId;\n await this.assertAttachable(\n actor,\n id,\n [patch.thumbnailAssetId],\n () => this.eventAssetIds(orgId, id),\n 'An event',\n );\n const { settings, ...fields } = patch;\n const { previous, event } = await this.uow.run(async ({ content, outbox }) => {\n const previous = await content.findEventById(orgId, id);\n if (!previous) {\n this.logger.warn('event update rejected — not found', { orgId, eventId: id });\n throw new NotFoundError('Event', id);\n }\n if (previous.status === 'canceled') {\n this.logger.warn('event update rejected — canceled', { orgId, eventId: id });\n throw new ConflictError('The event is canceled', 'canceled');\n }\n assertEventTimes(fields.startsAt ?? previous.startsAt, fields.endsAt ?? previous.endsAt);\n const updated = await content.updateEvent(orgId, id, fields);\n if (!updated) {\n throw new NotFoundError('Event', id);\n }\n const event: Event = settings\n ? { ...updated, settings: await content.patchEventSettings(orgId, id, settings) }\n : updated;\n await outbox.append([\n contentEvents.eventUpdated.make({\n orgId,\n data: event,\n metadata: eventChange(actor, previous, event),\n }),\n ]);\n return { previous, event };\n });\n this.logger.info('event updated', {\n orgId,\n eventId: id,\n fields: Object.keys(patch),\n actorId: actor.id,\n });\n await this.scheduleStartingSoon(orgId, previous, event);\n await this.syncThumbnail(event);\n return this.withThumbnail(event);\n }\n\n async cancelEvent(id: string, actor: Actor): Promise<EventView> {\n this.require(actor, 'events:write', id);\n const orgId = actor.orgId;\n const event = await this.uow.run(async ({ content, outbox }) => {\n const previous = await content.findEventById(orgId, id);\n if (!previous) {\n this.logger.warn('event cancel rejected — not found', { orgId, eventId: id });\n throw new NotFoundError('Event', id);\n }\n if (previous.status === 'canceled') {\n this.logger.warn('event cancel rejected — already canceled', { orgId, eventId: id });\n throw new ConflictError('The event is already canceled', 'canceled');\n }\n const updated = await content.updateEvent(orgId, id, { status: 'canceled' });\n if (!updated) {\n throw new NotFoundError('Event', id);\n }\n await outbox.append([\n contentEvents.eventUpdated.make({\n orgId,\n data: updated,\n metadata: eventChange(actor, previous, updated),\n }),\n ]);\n return updated;\n });\n this.logger.info('event canceled', { orgId, eventId: id, actorId: actor.id });\n await this.cancelStartingSoon(orgId, id);\n await this.syncThumbnail(event);\n return this.withThumbnail(event);\n }\n\n async deleteEvent(id: string, actor: Actor): Promise<void> {\n this.require(actor, 'events:delete', id);\n const orgId = actor.orgId;\n await this.uow.run(async ({ content, outbox }) => {\n const event = await content.findEventById(orgId, id);\n if (!event) {\n this.logger.warn('event delete rejected — not found', { orgId, eventId: id });\n throw new NotFoundError('Event', id);\n }\n const linked = await content.spacesLinkingContent(orgId, id);\n const ok = await content.deleteEvent(orgId, id);\n if (!ok) {\n throw new NotFoundError('Event', id);\n }\n await content.deleteEventSettings(orgId, id);\n await outbox.append([\n contentEvents.eventDeleted.make({ orgId, data: event, metadata: actorMetadata(actor) }),\n ...(await this.spaceUpdates(content, orgId, linked, actor)),\n ]);\n });\n this.logger.info('event deleted', { orgId, eventId: id, actorId: actor.id });\n await this.withdrawThumbnail(orgId, id);\n await this.cancelStartingSoon(orgId, id);\n }\n\n async startingSoon(orgId: string, eventId: string, lead: EventLead, now: Date): Promise<void> {\n const event = await this.repo.findEventById(orgId, eventId);\n if (!event || event.status !== 'published') {\n this.logger.debug('event no longer published', { orgId, eventId, lead });\n return;\n }\n const due = new Date(event.startsAt.getTime() - EVENT_LEADS[lead]);\n if (due > now) {\n await this.scheduler.at(EVENT_STARTING_SOON_JOB, due, startingSoonKey(eventId, lead), {\n orgId,\n eventId,\n lead,\n });\n this.logger.info('event starting soon timer moved', {\n orgId,\n eventId,\n lead,\n due: due.toISOString(),\n });\n return;\n }\n await this.uow.run(({ outbox }) =>\n outbox.append([\n contentEvents.eventStartingSoon.make({\n orgId,\n data: { eventId, lead, startsAt: event.startsAt },\n }),\n ]),\n );\n this.logger.info('event starting soon', { orgId, eventId, lead });\n }\n\n private async scheduleStartingSoon(orgId: string, previous: Event, event: Event): Promise<void> {\n if (event.status !== 'published') {\n if (previous.status === 'published') {\n await this.cancelStartingSoon(orgId, event.id);\n }\n return;\n }\n if (\n previous.status === 'published' &&\n previous.startsAt.getTime() === event.startsAt.getTime()\n ) {\n return;\n }\n const now = Date.now();\n for (const lead of EVENT_LEAD_KEYS) {\n const key = startingSoonKey(event.id, lead);\n const runAt = new Date(event.startsAt.getTime() - EVENT_LEADS[lead]);\n try {\n if (runAt.getTime() > now) {\n await this.scheduler.at(EVENT_STARTING_SOON_JOB, runAt, key, {\n orgId,\n eventId: event.id,\n lead,\n });\n } else {\n await this.scheduler.cancel(EVENT_STARTING_SOON_JOB, key);\n }\n } catch (err) {\n this.logger.error('event starting soon timer not set', {\n orgId,\n eventId: event.id,\n lead,\n err,\n });\n }\n }\n }\n\n private async cancelStartingSoon(orgId: string, eventId: string): Promise<void> {\n for (const lead of EVENT_LEAD_KEYS) {\n try {\n await this.scheduler.cancel(EVENT_STARTING_SOON_JOB, startingSoonKey(eventId, lead));\n } catch (err) {\n this.logger.warn('event starting soon timer not cancelled', { orgId, eventId, lead, err });\n }\n }\n }\n\n async listEventAssets(eventId: string, actor: Actor): Promise<EventFile[]> {\n this.require(actor, 'events:read', eventId);\n const orgId = actor.orgId;\n if (!(await this.repo.findEventById(orgId, eventId))) {\n throw new NotFoundError('Event', eventId);\n }\n return this.eventFiles(orgId, await this.repo.listEventAssets(orgId, eventId));\n }\n\n async eventFilesFor(eventIds: string[], actor: Actor): Promise<Record<string, EventFile[]>> {\n for (const id of eventIds) {\n this.require(actor, 'events:read', id);\n }\n const byEvent: Record<string, EventFile[]> = Object.fromEntries(eventIds.map((id) => [id, []]));\n if (eventIds.length === 0) {\n return byEvent;\n }\n const files = await this.eventFiles(\n actor.orgId,\n await this.repo.listEventAssetsFor(actor.orgId, eventIds),\n );\n for (const file of files) {\n byEvent[file.eventId]?.push(file);\n }\n return byEvent;\n }\n\n async addEventAsset(\n eventId: string,\n input: AddEventAssetInput,\n actor: Actor,\n ): Promise<EventFile[]> {\n this.require(actor, 'events:write', eventId);\n const orgId = actor.orgId;\n await this.assertAttachable(\n actor,\n eventId,\n [input.assetId],\n () => this.eventAssetIds(orgId, eventId),\n 'An event',\n );\n const assets = await this.uow.run(({ content }) =>\n content.addEventAsset(orgId, eventId, input),\n );\n this.logger.info('event asset added', {\n orgId,\n eventId,\n assetId: input.assetId,\n actorId: actor.id,\n });\n return this.eventFiles(orgId, assets);\n }\n\n async removeEventAsset(eventId: string, assetId: string, actor: Actor): Promise<EventFile[]> {\n this.require(actor, 'events:write', eventId);\n const orgId = actor.orgId;\n const assets = await this.uow.run(({ content }) =>\n content.removeEventAsset(orgId, eventId, assetId),\n );\n this.logger.info('event asset removed', { orgId, eventId, assetId, actorId: actor.id });\n return this.eventFiles(orgId, assets);\n }\n\n async renameEventAsset(\n eventId: string,\n assetId: string,\n displayName: string | null,\n actor: Actor,\n ): Promise<EventFile[]> {\n this.require(actor, 'events:write', eventId);\n const orgId = actor.orgId;\n const assets = await this.uow.run(({ content }) =>\n content.renameEventAsset(orgId, eventId, assetId, displayName),\n );\n this.logger.info('event asset renamed', { orgId, eventId, assetId, actorId: actor.id });\n return this.eventFiles(orgId, assets);\n }\n\n async reorderEventAssets(\n eventId: string,\n assetIds: string[],\n actor: Actor,\n ): Promise<EventFile[]> {\n this.require(actor, 'events:write', eventId);\n const orgId = actor.orgId;\n const assets = await this.uow.run(async ({ content }) => {\n const current = await content.listEventAssets(orgId, eventId);\n if (\n !sameIdSet(\n current.map((link) => link.assetId),\n assetIds,\n )\n ) {\n this.logger.warn('event asset reorder rejected — id set mismatch', {\n orgId,\n eventId,\n assetIds,\n });\n throw new ConflictError(\"Ordered asset ids does not match the event's current assets\");\n }\n return content.reorderEventAssets(orgId, eventId, assetIds);\n });\n this.logger.debug('event assets reordered', { orgId, eventId });\n return this.eventFiles(orgId, assets);\n }\n\n // --- bundles --------------------------------------------------------------\n\n async listBundles(query: ListBundlesQuery, actor: Actor): Promise<Page<Bundle>> {\n this.require(actor, 'bundles:read');\n return this.repo.listBundles(actor.orgId, query);\n }\n\n async getBundle(id: string, actor: Actor): Promise<Bundle> {\n const bundle = await this.findBundle(id, actor);\n if (!bundle) {\n throw new NotFoundError('Bundle', id);\n }\n return bundle;\n }\n\n async findBundle(id: string, actor: Actor): Promise<Bundle | null> {\n this.require(actor, 'bundles:read');\n return this.repo.findBundleById(actor.orgId, id);\n }\n\n async createBundle(input: CreateBundleInput, actor: Actor): Promise<Bundle> {\n this.require(actor, 'bundles:write');\n const orgId = actor.orgId;\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 actorId: actor.id,\n });\n return bundle;\n }\n\n async updateBundle(id: string, patch: UpdateBundleInput, actor: Actor): Promise<Bundle> {\n this.require(actor, 'bundles:write');\n const orgId = actor.orgId;\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', {\n orgId,\n bundleId: id,\n fields: Object.keys(patch),\n actorId: actor.id,\n });\n return bundle;\n }\n\n async deleteBundle(id: string, actor: Actor): Promise<void> {\n this.require(actor, 'bundles:delete');\n const orgId = actor.orgId;\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, actorId: actor.id });\n }\n\n async listBundleItems(bundleId: string, actor: Actor): Promise<BundleItem[]> {\n this.require(actor, 'bundles:read');\n return this.repo.listBundleItems(actor.orgId, bundleId);\n }\n\n async addBundleItem(bundleId: string, contentId: string, actor: Actor): Promise<BundleItem[]> {\n this.require(actor, 'bundles:write');\n const orgId = actor.orgId;\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, actorId: actor.id });\n return items;\n }\n\n async removeBundleItem(bundleId: string, contentId: string, actor: Actor): Promise<BundleItem[]> {\n this.require(actor, 'bundles:write');\n const orgId = actor.orgId;\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, actorId: actor.id });\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(query: ListCommunitiesQuery, actor: Actor): Promise<Page<CommunityView>> {\n const ids = this.visibleIds(actor, COMMUNITY_READERS, 'communities');\n return this.pageWithThumbnails(await this.repo.listCommunities(actor.orgId, query, ids));\n }\n\n async getCommunity(id: string, actor: Actor): Promise<CommunityView> {\n const community = await this.findCommunity(id, actor);\n if (!community) {\n throw new NotFoundError('Community', id);\n }\n return community;\n }\n\n async findCommunity(id: string, actor: Actor): Promise<CommunityView | null> {\n this.requireAny(actor, COMMUNITY_READERS, id);\n const community = await this.repo.findCommunityById(actor.orgId, id);\n return community ? this.withThumbnail(community) : null;\n }\n\n communitiesWithDigest(): Promise<CommunityDigest[]> {\n return this.repo.communitiesWithDigest();\n }\n\n async listCommunitiesById(ids: string[], actor: Actor): Promise<Community[]> {\n if (!actor.permissions.anywhere('communities:read')) {\n this.logger.warn('content list refused', {\n orgId: actor.orgId,\n actorId: actor.id,\n permission: 'communities:read',\n });\n throw new ForbiddenError('You cannot see communities');\n }\n const visible = ids.filter((id) => actor.permissions.has('communities:read', id));\n return visible.length ? this.repo.findCommunitiesByIds(actor.orgId, visible) : [];\n }\n\n async getSpace(spaceId: string, actor: Actor): Promise<SpaceView | null> {\n const space = await this.repo.findSpace(actor.orgId, spaceId);\n if (!space) {\n return null;\n }\n this.require(actor, 'communities:read', space.communityId);\n return this.oneSpaceView(space);\n }\n\n async getCommunitySpace(communityId: string, spaceId: string, actor: Actor): Promise<SpaceView> {\n this.require(actor, 'communities:read', communityId);\n const space = await this.repo.findSpace(actor.orgId, spaceId);\n if (space?.communityId !== communityId) {\n throw new NotFoundError('Space', spaceId);\n }\n return this.oneSpaceView(space);\n }\n\n async listSpaces(communityId: string, actor: Actor): Promise<SpaceView[]> {\n this.requireAny(actor, COMMUNITY_READERS, communityId);\n const community = await this.repo.findCommunityById(actor.orgId, communityId);\n if (!community) {\n throw new NotFoundError('Community', communityId);\n }\n const spaces = await this.repo.listSpaces(actor.orgId, communityId);\n return spaces.map((space) => this.spaceView(space, community.status === 'published'));\n }\n\n async getDmSettings(communityId: string, actor: Actor): Promise<DmSettings | null> {\n this.require(actor, 'communities:read', communityId);\n const community = await this.repo.findCommunityById(actor.orgId, communityId);\n return community?.settings.dm ?? null;\n }\n\n async createCommunity(input: CreateCommunityInput, actor: Actor): Promise<CommunityView> {\n this.require(actor, 'communities:write');\n const orgId = actor.orgId;\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 id: string,\n patch: UpdateCommunityInput,\n actor: Actor,\n ): Promise<CommunityView> {\n this.require(actor, 'communities:write', id);\n const orgId = actor.orgId;\n await this.assertAttachable(\n actor,\n id,\n [patch.thumbnailAssetId],\n async () => [(await this.repo.findCommunityById(orgId, id))?.thumbnailAssetId ?? null],\n 'A community',\n );\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 await this.syncThumbnail(community);\n if (patch.status !== undefined) {\n const spaces = await this.repo.listSpaces(orgId, id);\n await Promise.all(\n spaces.map((space) => this.syncSpaceImages(space, community.status === 'published')),\n );\n }\n return this.withThumbnail(community);\n }\n\n publishCommunity(id: string, actor: Actor): Promise<CommunityView> {\n return this.updateCommunity(id, { status: 'published' }, actor);\n }\n\n unpublishCommunity(id: string, actor: Actor): Promise<CommunityView> {\n return this.updateCommunity(id, { status: 'draft' }, actor);\n }\n\n async deleteCommunity(id: string, actor: Actor): Promise<void> {\n this.require(actor, 'communities:delete', id);\n const orgId = actor.orgId;\n const spaceIds = 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 own = await content.listSpaces(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 return own.map((space) => space.id);\n });\n this.logger.info('community deleted', { orgId, communityId: id, actorId: actor.id });\n await this.withdrawThumbnail(orgId, id);\n await Promise.all(spaceIds.map((spaceId) => this.files.syncPublicImages(orgId, spaceId, [])));\n }\n\n async patchCommunitySettings(\n id: string,\n patch: PatchCommunitySettingsInput,\n actor: Actor,\n ): Promise<CommunityView> {\n this.require(actor, 'communities:write', id);\n const orgId = actor.orgId;\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 communityId: string,\n input: CreateSpaceInput,\n actor: Actor,\n ): Promise<SpaceView> {\n this.require(actor, 'communities:write', communityId);\n const orgId = actor.orgId;\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 this.oneSpaceView(space);\n }\n\n async updateSpace(\n communityId: string,\n spaceId: string,\n patch: UpdateSpaceInput,\n actor: Actor,\n ): Promise<SpaceView> {\n this.require(actor, 'communities:write', communityId);\n const orgId = actor.orgId;\n await this.assertAttachable(\n actor,\n communityId,\n [patch.coverAssetId, patch.backgroundAssetId, patch.iconAssetId],\n async () => {\n const current = await this.repo.findSpace(orgId, spaceId);\n return current ? spaceImageIds(current) : [];\n },\n 'A space',\n );\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 const published = await this.communityPublished(orgId, communityId);\n await this.syncSpaceImages(space, published);\n return this.spaceView(space, published);\n }\n\n async deleteSpace(communityId: string, spaceId: string, actor: Actor): Promise<void> {\n this.require(actor, 'communities:write', communityId);\n const orgId = actor.orgId;\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 await this.files.syncPublicImages(orgId, spaceId, []);\n }\n\n async reorderSpaces(\n communityId: string,\n orderedIds: string[],\n actor: Actor,\n ): Promise<SpaceView[]> {\n this.require(actor, 'communities:write', communityId);\n const orgId = actor.orgId;\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 const published = await this.communityPublished(orgId, communityId);\n return spaces.map((space) => this.spaceView(space, published));\n }\n\n async setSpaceTopics(\n communityId: string,\n spaceId: string,\n input: SetSpaceTopicsInput,\n actor: Actor,\n ): Promise<SpaceView> {\n this.require(actor, 'communities:write', communityId);\n const orgId = actor.orgId;\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 this.oneSpaceView(space);\n }\n\n async addSpaceLink(\n communityId: string,\n spaceId: string,\n contentId: string,\n actor: Actor,\n ): Promise<SpaceView> {\n this.require(actor, 'communities:write', communityId);\n const orgId = actor.orgId;\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 this.oneSpaceView(space);\n }\n\n async removeSpaceLink(\n communityId: string,\n spaceId: string,\n linkId: string,\n actor: Actor,\n ): Promise<SpaceView> {\n this.require(actor, 'communities:write', communityId);\n const orgId = actor.orgId;\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 this.oneSpaceView(space);\n }\n\n async reorderSpaceLinks(\n communityId: string,\n spaceId: string,\n orderedIds: string[],\n actor: Actor,\n ): Promise<SpaceView> {\n this.require(actor, 'communities:write', communityId);\n const orgId = actor.orgId;\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 this.oneSpaceView(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 Event,\n EventAsset,\n EventFile,\n EventLead,\n EventView,\n Module,\n SaveActivityInput,\n Space,\n SpaceDetail,\n SpaceSettings,\n SpaceView,\n} from './model.js';\nimport type {\n BundlesService,\n CommunitiesService,\n CommunityDigest,\n CourseManagementService,\n ContentAssetReader,\n ContentRepository,\n ContentUnitOfWork,\n DownloadablesService,\n EventsService,\n} from './ports.js';\nimport type {\n AddDownloadAssetInput,\n AddEventAssetInput,\n CreateBundleInput,\n CreateCommunityInput,\n CreateCourseInput,\n CreateDownloadInput,\n CreateEventInput,\n CreateSpaceInput,\n ListBundlesQuery,\n ListCommunitiesQuery,\n ListCoursesQuery,\n ListDownloadsQuery,\n ListEventsQuery,\n Page,\n PatchCommunitySettingsInput,\n SetSpaceTopicsInput,\n UpdateBundleInput,\n UpdateCommunityInput,\n UpdateCourseInput,\n UpdateDownloadInput,\n UpdateEventInput,\n UpdateSpaceInput,\n} from './types.js';\nimport { isDeepStrictEqual } from 'node:util';\nimport { contentEvents } from './events.js';\nimport { EVENT_LEADS, EVENT_STARTING_SOON_JOB } from './jobs.js';\nimport type { Actor } from '../shared/actor.js';\nimport type { AssetFiles, FileUrls, ReadyFile } from '../assets/index.js';\nimport type { Logger, NewDomainEvent, Scheduler } 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';\nimport type { EventMetadata, Permission } from '../types/index.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: ContentAssetReader;\n files: Pick<AssetFiles, 'readyFiles' | 'fileLinks' | 'syncPublicImages'>;\n fileUrls: FileUrls;\n scheduler: Pick<Scheduler, 'at' | 'cancel'>;\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): { actorId: string } {\n return { actorId: actor.id };\n}\n\nconst COMMUNITY_READERS: readonly Permission[] = ['communities:read', 'communities:moderate'];\n\nfunction eventChange(actor: Actor, previous: Event, next: Event): EventMetadata {\n return {\n actorId: actor.id,\n previousStatus: previous.status,\n previousType: previous.settings.type,\n previousStartsAt: previous.startsAt.toISOString(),\n previousEndsAt: previous.endsAt.toISOString(),\n locationChanged: !isDeepStrictEqual(previous.location, next.location),\n };\n}\n\nfunction assertEventTimes(startsAt: Date, endsAt: Date): void {\n if (endsAt.getTime() <= startsAt.getTime()) {\n throw new InvalidInputError('An event must end after it starts');\n }\n}\n\nfunction startingSoonKey(eventId: string, lead: EventLead): string {\n return `${eventId}:${lead}`;\n}\n\nconst EVENT_LEAD_KEYS = Object.keys(EVENT_LEADS) as EventLead[];\n\ntype WithThumbnail = {\n orgId: string;\n id: string;\n type: 'course' | 'download' | 'community' | 'event';\n status: string;\n thumbnailAssetId: string | null;\n};\n\nfunction shownPublicly(item: Pick<WithThumbnail, 'type' | 'status'>): boolean {\n return item.status === 'published' || (item.type === 'event' && item.status === 'canceled');\n}\n\nfunction spaceImageIds(space: Space): string[] {\n return [space.coverAssetId, space.backgroundAssetId, space.iconAssetId].filter(\n (id): id is string => id !== null,\n );\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\n CourseManagementService,\n DownloadablesService,\n BundlesService,\n CommunitiesService,\n EventsService\n{\n private readonly repo: ContentRepository;\n private readonly uow: ContentUnitOfWork;\n private readonly libraryAssets: ContentAssetReader;\n private readonly files: Pick<AssetFiles, 'readyFiles' | 'fileLinks' | 'syncPublicImages'>;\n private readonly fileUrls: FileUrls;\n private readonly scheduler: Pick<Scheduler, 'at' | 'cancel'>;\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.scheduler = params.scheduler;\n this.logger = params.logger ?? noopLogger;\n }\n\n private require(actor: Actor, permission: Permission, on?: string): void {\n this.requireAny(actor, [permission], on);\n }\n\n private requireAny(actor: Actor, permissions: readonly Permission[], on?: string): void {\n if (!permissions.some((permission) => actor.permissions.has(permission, on))) {\n this.logger.warn('content action refused', {\n orgId: actor.orgId,\n actorId: actor.id,\n permission: permissions.join(' or '),\n contentId: on,\n });\n throw new ForbiddenError(`You need ${permissions.join(' or ')}`);\n }\n }\n\n private visibleIds(\n actor: Actor,\n permissions: readonly Permission[],\n what: string,\n ): string[] | undefined {\n const wheres = permissions.map((permission) => actor.permissions.where(permission));\n if (wheres.some((where) => where.org)) {\n return undefined;\n }\n const ids = [...new Set(wheres.flatMap((where) => where.content))];\n if (ids.length === 0) {\n this.logger.warn('content list refused', {\n orgId: actor.orgId,\n actorId: actor.id,\n permission: permissions.join(' or '),\n });\n throw new ForbiddenError(`You cannot see ${what}`);\n }\n return ids;\n }\n\n private async withThumbnail<T extends WithThumbnail>(\n item: T,\n ): Promise<T & { thumbnailUrl: string | null }> {\n const [view] = await this.withThumbnails([item]);\n return view!;\n }\n\n private async withThumbnails<T extends WithThumbnail>(\n items: readonly T[],\n ): Promise<(T & { thumbnailUrl: string | null })[]> {\n const gated = items.flatMap((item) =>\n item.thumbnailAssetId && !shownPublicly(item) ? [{ assetId: item.thumbnailAssetId }] : [],\n );\n const links = gated.length > 0 ? await this.files.fileLinks(items[0]!.orgId, gated) : {};\n return items.map((item) => ({\n ...item,\n thumbnailUrl: !item.thumbnailAssetId\n ? null\n : shownPublicly(item)\n ? this.fileUrls.publicImage(item.orgId, item.id, item.thumbnailAssetId)\n : (links[item.thumbnailAssetId] ?? null),\n }));\n }\n\n private syncThumbnail(item: WithThumbnail): Promise<void> {\n return this.files.syncPublicImages(\n item.orgId,\n item.id,\n shownPublicly(item) && item.thumbnailAssetId ? [item.thumbnailAssetId] : [],\n );\n }\n\n private withdrawThumbnail(orgId: string, id: string): Promise<void> {\n return this.files.syncPublicImages(orgId, id, []);\n }\n\n private async spaceView(space: SpaceDetail, published: boolean): Promise<SpaceView> {\n const [view] = await this.spaceViews([space], published);\n return view!;\n }\n\n private async spaceViews(\n spaces: readonly SpaceDetail[],\n published: boolean,\n ): Promise<SpaceView[]> {\n const gated = published ? [] : spaces.flatMap((space) => spaceImageIds(space));\n const links =\n gated.length > 0\n ? await this.files.fileLinks(\n spaces[0]!.orgId,\n gated.map((assetId) => ({ assetId })),\n )\n : {};\n return spaces.map((space) => {\n const url = (assetId: string | null) =>\n !assetId\n ? null\n : published\n ? this.fileUrls.publicImage(space.orgId, space.id, assetId)\n : (links[assetId] ?? null);\n return {\n ...space,\n coverUrl: url(space.coverAssetId),\n backgroundUrl: url(space.backgroundAssetId),\n iconUrl: url(space.iconAssetId),\n };\n });\n }\n\n private async communityPublished(orgId: string, communityId: string): Promise<boolean> {\n return (await this.repo.findCommunityById(orgId, communityId))?.status === 'published';\n }\n\n private async oneSpaceView(space: SpaceDetail): Promise<SpaceView> {\n return this.spaceView(space, await this.communityPublished(space.orgId, space.communityId));\n }\n\n private syncSpaceImages(space: Space, published: boolean): Promise<void> {\n return this.files.syncPublicImages(\n space.orgId,\n space.id,\n published ? spaceImageIds(space) : [],\n );\n }\n\n private async pageWithThumbnails<T extends WithThumbnail>(\n page: Page<T>,\n ): Promise<Page<T & { thumbnailUrl: string | null }>> {\n return { ...page, rows: await this.withThumbnails(page.rows) };\n }\n\n private downloadFiles(orgId: string, links: DownloadAsset[]): Promise<DownloadFile[]> {\n return this.listedFiles(orgId, links);\n }\n\n private eventFiles(orgId: string, links: EventAsset[]): Promise<EventFile[]> {\n return this.listedFiles(orgId, links);\n }\n\n private async listedFiles<T extends { assetId: string; displayName: string | null }>(\n orgId: string,\n links: T[],\n ): Promise<(T & ReadyFile & { url: string })[]> {\n const ready = await this.files.readyFiles(\n orgId,\n links.map((link) => link.assetId),\n );\n const urls = await this.files.fileLinks(\n orgId,\n links.flatMap((link) => {\n const file = ready[link.assetId];\n return file ? [{ assetId: link.assetId, saveAs: link.displayName ?? file.filename }] : [];\n }),\n );\n return links.flatMap((link) => {\n const file = ready[link.assetId];\n const url = urls[link.assetId];\n return file && url ? [{ ...link, ...file, url }] : [];\n });\n }\n\n private async assertAttachable(\n actor: Actor,\n itemId: string,\n requested: (string | null | undefined)[],\n attached: () => Promise<(string | null)[]>,\n user: string,\n ): Promise<void> {\n const ids = [...new Set(requested.filter((id): id is string => typeof id === 'string'))];\n if (ids.length === 0) {\n return;\n }\n const held = new Set(await attached());\n const added = ids.filter((id) => !held.has(id));\n if (added.length === 0) {\n return;\n }\n const orgId = actor.orgId;\n const found = new Map(\n (await this.libraryAssets.libraryAssetsFor(orgId, added)).map((asset) => [asset.id, asset]),\n );\n const missing = added.filter((id) => !found.has(id));\n if (missing.length > 0) {\n this.logger.warn('library assets refused', { orgId, contentId: itemId, assetIds: missing });\n throw new ConflictError(\n `${user} can only use ready files from the media library. Not available: ${missing.join(', ')}`,\n );\n }\n if (actor.permissions.has('media:read')) {\n return;\n }\n const foreign = added.filter((id) => found.get(id)?.contentId !== itemId);\n if (foreign.length > 0) {\n this.logger.warn('library assets refused — not uploaded for this item', {\n orgId,\n actorId: actor.id,\n contentId: itemId,\n assetIds: foreign,\n });\n throw new ForbiddenError(\n `You need media:read to use files that were not uploaded for this item: ${foreign.join(', ')}`,\n );\n }\n }\n\n private async courseAssetIds(orgId: string, courseId: string): Promise<(string | null)[]> {\n const [course, links] = await Promise.all([\n this.repo.findCourseById(orgId, courseId),\n this.repo.listActivityAssetsForCourse(orgId, courseId),\n ]);\n return [course?.thumbnailAssetId ?? null, ...links.map((link) => link.assetId)];\n }\n\n private async downloadAssetIds(orgId: string, downloadId: string): Promise<(string | null)[]> {\n const [download, links] = await Promise.all([\n this.repo.getDownload(orgId, downloadId),\n this.repo.listDownloadAssets(orgId, downloadId),\n ]);\n return [download?.thumbnailAssetId ?? null, ...links.map((link) => link.assetId)];\n }\n\n private async eventAssetIds(orgId: string, eventId: string): Promise<(string | null)[]> {\n const [event, links] = await Promise.all([\n this.repo.findEventById(orgId, eventId),\n this.repo.listEventAssets(orgId, eventId),\n ]);\n if (!event) {\n throw new NotFoundError('Event', eventId);\n }\n return [event.thumbnailAssetId, ...links.map((link) => link.assetId)];\n }\n\n async listCourses(query: ListCoursesQuery, actor: Actor): Promise<Page<CourseView>> {\n const ids = this.visibleIds(actor, ['courses:read'], 'courses');\n return this.pageWithThumbnails(await this.repo.listCourses(actor.orgId, query, ids));\n }\n\n async getCourse(id: string, actor: Actor): Promise<CourseView> {\n const course = await this.findCourse(id, actor);\n if (!course) {\n throw new NotFoundError('Course', id);\n }\n return course;\n }\n\n async findCourse(id: string, actor: Actor): Promise<CourseView | null> {\n this.require(actor, 'courses:read', id);\n const course = await this.repo.findCourseById(actor.orgId, id);\n return course ? this.withThumbnail(course) : null;\n }\n\n async createCourse(input: CreateCourseInput, actor: Actor): Promise<CourseView> {\n this.require(actor, 'courses:write');\n const orgId = actor.orgId;\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', {\n orgId,\n courseId: course.id,\n title: course.title,\n actorId: actor.id,\n });\n return this.withThumbnail(course);\n }\n\n async updateCourse(id: string, patch: UpdateCourseInput, actor: Actor): Promise<CourseView> {\n this.require(actor, 'courses:write', id);\n const orgId = actor.orgId;\n await this.assertAttachable(\n actor,\n id,\n [patch.thumbnailAssetId],\n () => this.courseAssetIds(orgId, id),\n 'A course',\n );\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', {\n orgId,\n courseId: id,\n fields: Object.keys(patch),\n actorId: actor.id,\n });\n await this.syncThumbnail(course);\n return this.withThumbnail(course);\n }\n\n async patchCourseSettings(\n id: string,\n value: Partial<CourseSettings>,\n actor: Actor,\n ): Promise<CourseSettings> {\n this.require(actor, 'courses:write', id);\n const orgId = actor.orgId;\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, actorId: actor.id });\n return merged;\n }\n\n async deleteCourse(id: string, actor: Actor): Promise<void> {\n this.require(actor, 'courses:delete', id);\n const orgId = actor.orgId;\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, actorId: actor.id });\n await this.withdrawThumbnail(orgId, id);\n }\n\n // --- modules & activities ------------------------------------------------\n\n async listCourseModules(courseId: string, actor: Actor): Promise<Module[]> {\n this.require(actor, 'courses:read', courseId);\n return this.repo.listCourseModules(actor.orgId, courseId);\n }\n async listCourseActivities(courseId: string, actor: Actor): Promise<Activity[]> {\n this.require(actor, 'courses:read', courseId);\n return this.repo.listActivitiesForCourse(actor.orgId, courseId);\n }\n async listCourseActivityViews(courseId: string, actor: Actor): Promise<ActivityView[]> {\n this.require(actor, 'courses:read', courseId);\n const [activities, links] = await Promise.all([\n this.repo.listActivitiesForCourse(actor.orgId, courseId),\n this.repo.listActivityAssetsForCourse(actor.orgId, courseId),\n ]);\n const urls = await this.files.fileLinks(\n actor.orgId,\n links.map((link) => ({ assetId: link.assetId })),\n );\n return activities.map((activity) => ({\n ...activity,\n assetUrls: Object.fromEntries(\n links.flatMap((link) => {\n const url = urls[link.assetId];\n return link.activityId === activity.id && url ? [[link.assetId, url]] : [];\n }),\n ),\n }));\n }\n async listCourseActivityAssets(courseId: string, actor: Actor): Promise<ActivityAsset[]> {\n this.require(actor, 'courses:read', courseId);\n return this.repo.listActivityAssetsForCourse(actor.orgId, courseId);\n }\n async getActivity(activityId: string, actor: Actor): Promise<Activity | null> {\n const activity = await this.repo.findActivity(actor.orgId, activityId);\n if (activity) {\n this.require(actor, 'courses:read', activity.courseId);\n }\n return activity;\n }\n async getModule(moduleId: string, actor: Actor): Promise<Module | null> {\n const module = await this.repo.findModule(actor.orgId, moduleId);\n if (module) {\n this.require(actor, 'courses:read', module.courseId);\n }\n return module;\n }\n\n async reorderModules(courseId: string, orderedIds: string[], actor: Actor): Promise<Module[]> {\n this.require(actor, 'courses:write', courseId);\n const orgId = actor.orgId;\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(courseId: string, title: string, actor: Actor): Promise<Module[]> {\n this.require(actor, 'courses:write', courseId);\n const orgId = actor.orgId;\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', {\n orgId,\n courseId,\n moduleId: created.id,\n title,\n actorId: actor.id,\n });\n return modules;\n }\n\n async updateModule(\n courseId: string,\n moduleId: string,\n title: string,\n actor: Actor,\n ): Promise<Module[]> {\n this.require(actor, 'courses:write', courseId);\n const orgId = actor.orgId;\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, actorId: actor.id });\n return modules;\n }\n\n async deleteModule(courseId: string, moduleId: string, actor: Actor): Promise<Module[]> {\n this.require(actor, 'courses:write', courseId);\n const orgId = actor.orgId;\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, actorId: actor.id });\n return modules;\n }\n\n async reorderActivities(\n courseId: string,\n moduleId: string,\n orderedIds: string[],\n actor: Actor,\n ): Promise<Module[]> {\n this.require(actor, 'courses:write', courseId);\n const orgId = actor.orgId;\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 async saveActivity(\n courseId: string,\n moduleId: string,\n input: SaveActivityInput,\n activityId: string | null,\n actor: Actor,\n ): Promise<Module[]> {\n this.require(actor, 'courses:write', courseId);\n const orgId = actor.orgId;\n await this.assertAttachable(\n actor,\n courseId,\n input.assetIds ?? [],\n () => this.courseAssetIds(orgId, courseId),\n 'An activity',\n );\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 ?? undefined,\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 actorId: actor.id,\n });\n return modules;\n }\n\n async deleteActivity(\n courseId: string,\n moduleId: string,\n activityId: string,\n actor: Actor,\n ): Promise<Module[]> {\n this.require(actor, 'courses:write', courseId);\n const orgId = actor.orgId;\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', {\n orgId,\n courseId,\n moduleId,\n activityId,\n actorId: actor.id,\n });\n return modules;\n }\n\n // --- downloads ------------------------------------------------------------\n\n async listDownloads(query: ListDownloadsQuery, actor: Actor): Promise<Page<DownloadView>> {\n const ids = this.visibleIds(actor, ['downloads:read'], 'downloads');\n return this.pageWithThumbnails(await this.repo.listDownloads(actor.orgId, query, ids));\n }\n\n async getDownload(id: string, actor: Actor): Promise<DownloadView> {\n const download = await this.findDownload(id, actor);\n if (!download) {\n throw new NotFoundError('Download', id);\n }\n return download;\n }\n\n async findDownload(id: string, actor: Actor): Promise<DownloadView | null> {\n this.require(actor, 'downloads:read', id);\n const download = await this.repo.getDownload(actor.orgId, id);\n return download ? this.withThumbnail(download) : null;\n }\n\n async createDownload(input: CreateDownloadInput, actor: Actor): Promise<DownloadView> {\n this.require(actor, 'downloads:write');\n const orgId = actor.orgId;\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', {\n orgId,\n downloadId: download.id,\n title: download.title,\n actorId: actor.id,\n });\n return this.withThumbnail(download);\n }\n\n async updateDownload(\n id: string,\n patch: UpdateDownloadInput,\n actor: Actor,\n ): Promise<DownloadView> {\n this.require(actor, 'downloads:write', id);\n const orgId = actor.orgId;\n await this.assertAttachable(\n actor,\n id,\n [patch.thumbnailAssetId],\n () => this.downloadAssetIds(orgId, id),\n 'A download',\n );\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', {\n orgId,\n downloadId: id,\n fields: Object.keys(patch),\n actorId: actor.id,\n });\n await this.syncThumbnail(download);\n return this.withThumbnail(download);\n }\n\n async removeDownload(id: string, actor: Actor): Promise<void> {\n this.require(actor, 'downloads:delete', id);\n const orgId = actor.orgId;\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, actorId: actor.id });\n await this.withdrawThumbnail(orgId, id);\n }\n\n // --- download asset links ------------------------------------------------\n\n async listDownloadAssets(downloadId: string, actor: Actor): Promise<DownloadFile[]> {\n this.require(actor, 'downloads:read', downloadId);\n return this.downloadFiles(\n actor.orgId,\n await this.repo.listDownloadAssets(actor.orgId, downloadId),\n );\n }\n\n async addDownloadAsset(\n downloadId: string,\n input: AddDownloadAssetInput,\n actor: Actor,\n ): Promise<DownloadFile[]> {\n this.require(actor, 'downloads:write', downloadId);\n const orgId = actor.orgId;\n await this.assertAttachable(\n actor,\n downloadId,\n [input.assetId],\n () => this.downloadAssetIds(orgId, downloadId),\n 'A download',\n );\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', {\n orgId,\n downloadId,\n assetId: input.assetId,\n actorId: actor.id,\n });\n return this.downloadFiles(orgId, assets);\n }\n\n async removeDownloadAsset(\n downloadId: string,\n assetId: string,\n actor: Actor,\n ): Promise<DownloadFile[]> {\n this.require(actor, 'downloads:write', downloadId);\n const orgId = actor.orgId;\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, actorId: actor.id });\n return this.downloadFiles(orgId, assets);\n }\n\n async renameDownloadAsset(\n downloadId: string,\n assetId: string,\n displayName: string | null,\n actor: Actor,\n ): Promise<DownloadFile[]> {\n this.require(actor, 'downloads:write', downloadId);\n const orgId = actor.orgId;\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, actorId: actor.id });\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 downloadId: string,\n assetIds: string[],\n actor: Actor,\n ): Promise<DownloadFile[]> {\n this.require(actor, 'downloads:write', downloadId);\n const orgId = actor.orgId;\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 async listEvents(query: ListEventsQuery, actor: Actor): Promise<Page<EventView>> {\n const ids = this.visibleIds(actor, ['events:read'], 'events');\n return this.pageWithThumbnails(await this.repo.listEvents(actor.orgId, query, ids));\n }\n\n async getEvent(id: string, actor: Actor): Promise<EventView> {\n const event = await this.findEvent(id, actor);\n if (!event) {\n throw new NotFoundError('Event', id);\n }\n return event;\n }\n\n async findEvent(id: string, actor: Actor): Promise<EventView | null> {\n this.require(actor, 'events:read', id);\n const event = await this.repo.findEventById(actor.orgId, id);\n return event ? this.withThumbnail(event) : null;\n }\n\n async findEvents(ids: string[], actor: Actor): Promise<EventView[]> {\n for (const id of ids) {\n this.require(actor, 'events:read', id);\n }\n if (ids.length === 0) {\n return [];\n }\n const found = await this.repo.findEventsByIds(actor.orgId, ids);\n return this.withThumbnails(found);\n }\n\n async createEvent(input: CreateEventInput, actor: Actor): Promise<EventView> {\n this.require(actor, 'events:write');\n assertEventTimes(input.startsAt, input.endsAt);\n const orgId = actor.orgId;\n const { settings, ...fields } = input;\n const event = await this.uow.run(async ({ content, outbox }) => {\n const created = await content.createEvent(orgId, fields);\n const event = settings\n ? { ...created, settings: await content.patchEventSettings(orgId, created.id, settings) }\n : created;\n await outbox.append([\n contentEvents.eventCreated.make({ orgId, data: event, metadata: actorMetadata(actor) }),\n ]);\n return event;\n });\n this.logger.info('event created', {\n orgId,\n eventId: event.id,\n title: event.title,\n actorId: actor.id,\n });\n return this.withThumbnail(event);\n }\n\n async updateEvent(id: string, patch: UpdateEventInput, actor: Actor): Promise<EventView> {\n this.require(actor, 'events:write', id);\n const orgId = actor.orgId;\n await this.assertAttachable(\n actor,\n id,\n [patch.thumbnailAssetId],\n () => this.eventAssetIds(orgId, id),\n 'An event',\n );\n const { settings, ...fields } = patch;\n const { previous, event } = await this.uow.run(async ({ content, outbox }) => {\n const previous = await content.findEventById(orgId, id);\n if (!previous) {\n this.logger.warn('event update rejected — not found', { orgId, eventId: id });\n throw new NotFoundError('Event', id);\n }\n if (previous.status === 'canceled') {\n this.logger.warn('event update rejected — canceled', { orgId, eventId: id });\n throw new ConflictError('The event is canceled', 'canceled');\n }\n assertEventTimes(fields.startsAt ?? previous.startsAt, fields.endsAt ?? previous.endsAt);\n const updated = await content.updateEvent(orgId, id, fields);\n if (!updated) {\n throw new NotFoundError('Event', id);\n }\n const event: Event = settings\n ? { ...updated, settings: await content.patchEventSettings(orgId, id, settings) }\n : updated;\n await outbox.append([\n contentEvents.eventUpdated.make({\n orgId,\n data: event,\n metadata: eventChange(actor, previous, event),\n }),\n ]);\n return { previous, event };\n });\n this.logger.info('event updated', {\n orgId,\n eventId: id,\n fields: Object.keys(patch),\n actorId: actor.id,\n });\n await this.scheduleStartingSoon(orgId, previous, event);\n await this.syncThumbnail(event);\n return this.withThumbnail(event);\n }\n\n async cancelEvent(id: string, actor: Actor): Promise<EventView> {\n this.require(actor, 'events:write', id);\n const orgId = actor.orgId;\n const event = await this.uow.run(async ({ content, outbox }) => {\n const previous = await content.findEventById(orgId, id);\n if (!previous) {\n this.logger.warn('event cancel rejected — not found', { orgId, eventId: id });\n throw new NotFoundError('Event', id);\n }\n if (previous.status === 'canceled') {\n this.logger.warn('event cancel rejected — already canceled', { orgId, eventId: id });\n throw new ConflictError('The event is already canceled', 'canceled');\n }\n const updated = await content.updateEvent(orgId, id, { status: 'canceled' });\n if (!updated) {\n throw new NotFoundError('Event', id);\n }\n await outbox.append([\n contentEvents.eventUpdated.make({\n orgId,\n data: updated,\n metadata: eventChange(actor, previous, updated),\n }),\n ]);\n return updated;\n });\n this.logger.info('event canceled', { orgId, eventId: id, actorId: actor.id });\n await this.cancelStartingSoon(orgId, id);\n await this.syncThumbnail(event);\n return this.withThumbnail(event);\n }\n\n async deleteEvent(id: string, actor: Actor): Promise<void> {\n this.require(actor, 'events:delete', id);\n const orgId = actor.orgId;\n await this.uow.run(async ({ content, outbox }) => {\n const event = await content.findEventById(orgId, id);\n if (!event) {\n this.logger.warn('event delete rejected — not found', { orgId, eventId: id });\n throw new NotFoundError('Event', id);\n }\n const linked = await content.spacesLinkingContent(orgId, id);\n const ok = await content.deleteEvent(orgId, id);\n if (!ok) {\n throw new NotFoundError('Event', id);\n }\n await content.deleteEventSettings(orgId, id);\n await outbox.append([\n contentEvents.eventDeleted.make({ orgId, data: event, metadata: actorMetadata(actor) }),\n ...(await this.spaceUpdates(content, orgId, linked, actor)),\n ]);\n });\n this.logger.info('event deleted', { orgId, eventId: id, actorId: actor.id });\n await this.withdrawThumbnail(orgId, id);\n await this.cancelStartingSoon(orgId, id);\n }\n\n async startingSoon(orgId: string, eventId: string, lead: EventLead, now: Date): Promise<void> {\n const event = await this.repo.findEventById(orgId, eventId);\n if (!event || event.status !== 'published') {\n this.logger.debug('event no longer published', { orgId, eventId, lead });\n return;\n }\n const due = new Date(event.startsAt.getTime() - EVENT_LEADS[lead]);\n if (due > now) {\n await this.scheduler.at(EVENT_STARTING_SOON_JOB, due, startingSoonKey(eventId, lead), {\n orgId,\n eventId,\n lead,\n });\n this.logger.info('event starting soon timer moved', {\n orgId,\n eventId,\n lead,\n due: due.toISOString(),\n });\n return;\n }\n await this.uow.run(({ outbox }) =>\n outbox.append([\n contentEvents.eventStartingSoon.make({\n orgId,\n data: { eventId, lead, startsAt: event.startsAt },\n }),\n ]),\n );\n this.logger.info('event starting soon', { orgId, eventId, lead });\n }\n\n private async scheduleStartingSoon(orgId: string, previous: Event, event: Event): Promise<void> {\n if (event.status !== 'published') {\n if (previous.status === 'published') {\n await this.cancelStartingSoon(orgId, event.id);\n }\n return;\n }\n if (\n previous.status === 'published' &&\n previous.startsAt.getTime() === event.startsAt.getTime()\n ) {\n return;\n }\n const now = Date.now();\n for (const lead of EVENT_LEAD_KEYS) {\n const key = startingSoonKey(event.id, lead);\n const runAt = new Date(event.startsAt.getTime() - EVENT_LEADS[lead]);\n try {\n if (runAt.getTime() > now) {\n await this.scheduler.at(EVENT_STARTING_SOON_JOB, runAt, key, {\n orgId,\n eventId: event.id,\n lead,\n });\n } else {\n await this.scheduler.cancel(EVENT_STARTING_SOON_JOB, key);\n }\n } catch (err) {\n this.logger.error('event starting soon timer not set', {\n orgId,\n eventId: event.id,\n lead,\n err,\n });\n }\n }\n }\n\n private async cancelStartingSoon(orgId: string, eventId: string): Promise<void> {\n for (const lead of EVENT_LEAD_KEYS) {\n try {\n await this.scheduler.cancel(EVENT_STARTING_SOON_JOB, startingSoonKey(eventId, lead));\n } catch (err) {\n this.logger.warn('event starting soon timer not cancelled', { orgId, eventId, lead, err });\n }\n }\n }\n\n async listEventAssets(eventId: string, actor: Actor): Promise<EventFile[]> {\n this.require(actor, 'events:read', eventId);\n const orgId = actor.orgId;\n if (!(await this.repo.findEventById(orgId, eventId))) {\n throw new NotFoundError('Event', eventId);\n }\n return this.eventFiles(orgId, await this.repo.listEventAssets(orgId, eventId));\n }\n\n async eventFilesFor(eventIds: string[], actor: Actor): Promise<Record<string, EventFile[]>> {\n for (const id of eventIds) {\n this.require(actor, 'events:read', id);\n }\n const byEvent: Record<string, EventFile[]> = Object.fromEntries(eventIds.map((id) => [id, []]));\n if (eventIds.length === 0) {\n return byEvent;\n }\n const files = await this.eventFiles(\n actor.orgId,\n await this.repo.listEventAssetsFor(actor.orgId, eventIds),\n );\n for (const file of files) {\n byEvent[file.eventId]?.push(file);\n }\n return byEvent;\n }\n\n async addEventAsset(\n eventId: string,\n input: AddEventAssetInput,\n actor: Actor,\n ): Promise<EventFile[]> {\n this.require(actor, 'events:write', eventId);\n const orgId = actor.orgId;\n await this.assertAttachable(\n actor,\n eventId,\n [input.assetId],\n () => this.eventAssetIds(orgId, eventId),\n 'An event',\n );\n const assets = await this.uow.run(({ content }) =>\n content.addEventAsset(orgId, eventId, input),\n );\n this.logger.info('event asset added', {\n orgId,\n eventId,\n assetId: input.assetId,\n actorId: actor.id,\n });\n return this.eventFiles(orgId, assets);\n }\n\n async removeEventAsset(eventId: string, assetId: string, actor: Actor): Promise<EventFile[]> {\n this.require(actor, 'events:write', eventId);\n const orgId = actor.orgId;\n const assets = await this.uow.run(({ content }) =>\n content.removeEventAsset(orgId, eventId, assetId),\n );\n this.logger.info('event asset removed', { orgId, eventId, assetId, actorId: actor.id });\n return this.eventFiles(orgId, assets);\n }\n\n async renameEventAsset(\n eventId: string,\n assetId: string,\n displayName: string | null,\n actor: Actor,\n ): Promise<EventFile[]> {\n this.require(actor, 'events:write', eventId);\n const orgId = actor.orgId;\n const assets = await this.uow.run(({ content }) =>\n content.renameEventAsset(orgId, eventId, assetId, displayName),\n );\n this.logger.info('event asset renamed', { orgId, eventId, assetId, actorId: actor.id });\n return this.eventFiles(orgId, assets);\n }\n\n async reorderEventAssets(\n eventId: string,\n assetIds: string[],\n actor: Actor,\n ): Promise<EventFile[]> {\n this.require(actor, 'events:write', eventId);\n const orgId = actor.orgId;\n const assets = await this.uow.run(async ({ content }) => {\n const current = await content.listEventAssets(orgId, eventId);\n if (\n !sameIdSet(\n current.map((link) => link.assetId),\n assetIds,\n )\n ) {\n this.logger.warn('event asset reorder rejected — id set mismatch', {\n orgId,\n eventId,\n assetIds,\n });\n throw new ConflictError(\"Ordered asset ids does not match the event's current assets\");\n }\n return content.reorderEventAssets(orgId, eventId, assetIds);\n });\n this.logger.debug('event assets reordered', { orgId, eventId });\n return this.eventFiles(orgId, assets);\n }\n\n // --- bundles --------------------------------------------------------------\n\n async listBundles(query: ListBundlesQuery, actor: Actor): Promise<Page<Bundle>> {\n this.require(actor, 'bundles:read');\n return this.repo.listBundles(actor.orgId, query);\n }\n\n async getBundle(id: string, actor: Actor): Promise<Bundle> {\n const bundle = await this.findBundle(id, actor);\n if (!bundle) {\n throw new NotFoundError('Bundle', id);\n }\n return bundle;\n }\n\n async findBundle(id: string, actor: Actor): Promise<Bundle | null> {\n this.require(actor, 'bundles:read');\n return this.repo.findBundleById(actor.orgId, id);\n }\n\n async createBundle(input: CreateBundleInput, actor: Actor): Promise<Bundle> {\n this.require(actor, 'bundles:write');\n const orgId = actor.orgId;\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 actorId: actor.id,\n });\n return bundle;\n }\n\n async updateBundle(id: string, patch: UpdateBundleInput, actor: Actor): Promise<Bundle> {\n this.require(actor, 'bundles:write');\n const orgId = actor.orgId;\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', {\n orgId,\n bundleId: id,\n fields: Object.keys(patch),\n actorId: actor.id,\n });\n return bundle;\n }\n\n async deleteBundle(id: string, actor: Actor): Promise<void> {\n this.require(actor, 'bundles:delete');\n const orgId = actor.orgId;\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, actorId: actor.id });\n }\n\n async listBundleItems(bundleId: string, actor: Actor): Promise<BundleItem[]> {\n this.require(actor, 'bundles:read');\n return this.repo.listBundleItems(actor.orgId, bundleId);\n }\n\n async addBundleItem(bundleId: string, contentId: string, actor: Actor): Promise<BundleItem[]> {\n this.require(actor, 'bundles:write');\n const orgId = actor.orgId;\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, actorId: actor.id });\n return items;\n }\n\n async removeBundleItem(bundleId: string, contentId: string, actor: Actor): Promise<BundleItem[]> {\n this.require(actor, 'bundles:write');\n const orgId = actor.orgId;\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, actorId: actor.id });\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(query: ListCommunitiesQuery, actor: Actor): Promise<Page<CommunityView>> {\n const ids = this.visibleIds(actor, COMMUNITY_READERS, 'communities');\n return this.pageWithThumbnails(await this.repo.listCommunities(actor.orgId, query, ids));\n }\n\n async getCommunity(id: string, actor: Actor): Promise<CommunityView> {\n const community = await this.findCommunity(id, actor);\n if (!community) {\n throw new NotFoundError('Community', id);\n }\n return community;\n }\n\n async findCommunity(id: string, actor: Actor): Promise<CommunityView | null> {\n this.requireAny(actor, COMMUNITY_READERS, id);\n const community = await this.repo.findCommunityById(actor.orgId, id);\n return community ? this.withThumbnail(community) : null;\n }\n\n communitiesWithDigest(): Promise<CommunityDigest[]> {\n return this.repo.communitiesWithDigest();\n }\n\n async listCommunitiesById(ids: string[], actor: Actor): Promise<Community[]> {\n if (!actor.permissions.anywhere('communities:read')) {\n this.logger.warn('content list refused', {\n orgId: actor.orgId,\n actorId: actor.id,\n permission: 'communities:read',\n });\n throw new ForbiddenError('You cannot see communities');\n }\n const visible = ids.filter((id) => actor.permissions.has('communities:read', id));\n return visible.length ? this.repo.findCommunitiesByIds(actor.orgId, visible) : [];\n }\n\n async getSpace(spaceId: string, actor: Actor): Promise<SpaceView | null> {\n const space = await this.repo.findSpace(actor.orgId, spaceId);\n if (!space) {\n return null;\n }\n this.require(actor, 'communities:read', space.communityId);\n return this.oneSpaceView(space);\n }\n\n async getCommunitySpace(communityId: string, spaceId: string, actor: Actor): Promise<SpaceView> {\n this.require(actor, 'communities:read', communityId);\n const space = await this.repo.findSpace(actor.orgId, spaceId);\n if (space?.communityId !== communityId) {\n throw new NotFoundError('Space', spaceId);\n }\n return this.oneSpaceView(space);\n }\n\n async listSpaces(communityId: string, actor: Actor): Promise<SpaceView[]> {\n this.requireAny(actor, COMMUNITY_READERS, communityId);\n const community = await this.repo.findCommunityById(actor.orgId, communityId);\n if (!community) {\n throw new NotFoundError('Community', communityId);\n }\n const spaces = await this.repo.listSpaces(actor.orgId, communityId);\n return this.spaceViews(spaces, community.status === 'published');\n }\n\n async getDmSettings(communityId: string, actor: Actor): Promise<DmSettings | null> {\n this.require(actor, 'communities:read', communityId);\n const community = await this.repo.findCommunityById(actor.orgId, communityId);\n return community?.settings.dm ?? null;\n }\n\n async createCommunity(input: CreateCommunityInput, actor: Actor): Promise<CommunityView> {\n this.require(actor, 'communities:write');\n const orgId = actor.orgId;\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 id: string,\n patch: UpdateCommunityInput,\n actor: Actor,\n ): Promise<CommunityView> {\n this.require(actor, 'communities:write', id);\n const orgId = actor.orgId;\n await this.assertAttachable(\n actor,\n id,\n [patch.thumbnailAssetId],\n async () => [(await this.repo.findCommunityById(orgId, id))?.thumbnailAssetId ?? null],\n 'A community',\n );\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 await this.syncThumbnail(community);\n if (patch.status !== undefined) {\n const spaces = await this.repo.listSpaces(orgId, id);\n await Promise.all(\n spaces.map((space) => this.syncSpaceImages(space, community.status === 'published')),\n );\n }\n return this.withThumbnail(community);\n }\n\n publishCommunity(id: string, actor: Actor): Promise<CommunityView> {\n return this.updateCommunity(id, { status: 'published' }, actor);\n }\n\n unpublishCommunity(id: string, actor: Actor): Promise<CommunityView> {\n return this.updateCommunity(id, { status: 'draft' }, actor);\n }\n\n async deleteCommunity(id: string, actor: Actor): Promise<void> {\n this.require(actor, 'communities:delete', id);\n const orgId = actor.orgId;\n const spaceIds = 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 own = await content.listSpaces(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 return own.map((space) => space.id);\n });\n this.logger.info('community deleted', { orgId, communityId: id, actorId: actor.id });\n await this.withdrawThumbnail(orgId, id);\n await Promise.all(spaceIds.map((spaceId) => this.files.syncPublicImages(orgId, spaceId, [])));\n }\n\n async patchCommunitySettings(\n id: string,\n patch: PatchCommunitySettingsInput,\n actor: Actor,\n ): Promise<CommunityView> {\n this.require(actor, 'communities:write', id);\n const orgId = actor.orgId;\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 communityId: string,\n input: CreateSpaceInput,\n actor: Actor,\n ): Promise<SpaceView> {\n this.require(actor, 'communities:write', communityId);\n const orgId = actor.orgId;\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 this.oneSpaceView(space);\n }\n\n async updateSpace(\n communityId: string,\n spaceId: string,\n patch: UpdateSpaceInput,\n actor: Actor,\n ): Promise<SpaceView> {\n this.require(actor, 'communities:write', communityId);\n const orgId = actor.orgId;\n await this.assertAttachable(\n actor,\n communityId,\n [patch.coverAssetId, patch.backgroundAssetId, patch.iconAssetId],\n async () => {\n const current = await this.repo.findSpace(orgId, spaceId);\n return current ? spaceImageIds(current) : [];\n },\n 'A space',\n );\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 const published = await this.communityPublished(orgId, communityId);\n await this.syncSpaceImages(space, published);\n return this.spaceView(space, published);\n }\n\n async deleteSpace(communityId: string, spaceId: string, actor: Actor): Promise<void> {\n this.require(actor, 'communities:write', communityId);\n const orgId = actor.orgId;\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 await this.files.syncPublicImages(orgId, spaceId, []);\n }\n\n async reorderSpaces(\n communityId: string,\n orderedIds: string[],\n actor: Actor,\n ): Promise<SpaceView[]> {\n this.require(actor, 'communities:write', communityId);\n const orgId = actor.orgId;\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 const published = await this.communityPublished(orgId, communityId);\n return this.spaceViews(spaces, published);\n }\n\n async setSpaceTopics(\n communityId: string,\n spaceId: string,\n input: SetSpaceTopicsInput,\n actor: Actor,\n ): Promise<SpaceView> {\n this.require(actor, 'communities:write', communityId);\n const orgId = actor.orgId;\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 this.oneSpaceView(space);\n }\n\n async addSpaceLink(\n communityId: string,\n spaceId: string,\n contentId: string,\n actor: Actor,\n ): Promise<SpaceView> {\n this.require(actor, 'communities:write', communityId);\n const orgId = actor.orgId;\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 this.oneSpaceView(space);\n }\n\n async removeSpaceLink(\n communityId: string,\n spaceId: string,\n linkId: string,\n actor: Actor,\n ): Promise<SpaceView> {\n this.require(actor, 'communities:write', communityId);\n const orgId = actor.orgId;\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 this.oneSpaceView(space);\n }\n\n async reorderSpaceLinks(\n communityId: string,\n spaceId: string,\n orderedIds: string[],\n actor: Actor,\n ): Promise<SpaceView> {\n this.require(actor, 'communities:write', communityId);\n const orgId = actor.orgId;\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 this.oneSpaceView(space);\n }\n}\n"],"mappings":"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"}
|
|
@@ -18,7 +18,7 @@ type ChatServiceParams = {
|
|
|
18
18
|
profiles: AuthorProfileReader;
|
|
19
19
|
subscriptions: SubscriptionsRepository;
|
|
20
20
|
mentions: MentionsRepository;
|
|
21
|
-
images: MemberImageReader & Pick<AssetFiles, '
|
|
21
|
+
images: MemberImageReader & Pick<AssetFiles, 'fileLinks'>;
|
|
22
22
|
fileUrls: FileUrls;
|
|
23
23
|
uow: ChatUnitOfWork;
|
|
24
24
|
pubsub?: PubSub;
|
|
@@ -73,7 +73,6 @@ declare class ChatServiceImpl implements ChatService, ChatLiveReads {
|
|
|
73
73
|
page: number;
|
|
74
74
|
pageSize: number;
|
|
75
75
|
}, actor: Actor): Promise<Page<MessageView>>;
|
|
76
|
-
attachmentFile(chatId: string, messageId: string, assetId: string, actor: Actor): Promise<string>;
|
|
77
76
|
messageQueue(communityId: string, actor: Actor): Promise<MessageQueue>;
|
|
78
77
|
chatSummary(orgId: string, chatId: string): Promise<{
|
|
79
78
|
chat: Chat;
|
package/dist/discussion/chats.js
CHANGED
|
@@ -670,19 +670,6 @@ var ChatServiceImpl = class {
|
|
|
670
670
|
rows: await this.withSenders(orgId, actor, page.rows)
|
|
671
671
|
};
|
|
672
672
|
}
|
|
673
|
-
async attachmentFile(chatId, messageId, assetId, actor) {
|
|
674
|
-
const orgId = actor.orgId;
|
|
675
|
-
const chat = await this.repo.findChat(orgId, chatId);
|
|
676
|
-
const message = await this.repo.findMessage(orgId, messageId);
|
|
677
|
-
if (!chat || !message || message.chatId !== chatId) throw new NotFoundError("Message attachment", assetId);
|
|
678
|
-
if (!((await this.repo.attachmentsOf(orgId, [messageId]))[messageId] ?? []).includes(assetId)) throw new NotFoundError("Message attachment", assetId);
|
|
679
|
-
if (!await this.access.isCommunityMember(chat.communityId, actor)) throw new NotFoundError("Message attachment", assetId);
|
|
680
|
-
const moderates = actor.permissions.has("communities:moderate", chat.communityId);
|
|
681
|
-
if (!((await this.repo.participants(orgId, chatId)).some((user) => user.orgUserId === actor.id && user.leftAt === null) ? message.deletedAt === null || moderates : moderates && (await this.repo.listOpenFlags(orgId, chat.communityId)).some((flag) => flag.messageId === messageId))) throw new NotFoundError("Message attachment", assetId);
|
|
682
|
-
const url = await this.images.signFile(orgId, assetId);
|
|
683
|
-
if (!url) throw new NotFoundError("Message attachment", assetId);
|
|
684
|
-
return url;
|
|
685
|
-
}
|
|
686
673
|
async messageQueue(communityId, actor) {
|
|
687
674
|
const orgId = actor.orgId;
|
|
688
675
|
this.requireModerator(actor, communityId, "message queue");
|
|
@@ -1011,6 +998,7 @@ var ChatServiceImpl = class {
|
|
|
1011
998
|
]);
|
|
1012
999
|
const hidden = (message) => message.deletedAt !== null && !viewer?.permissions.has("communities:moderate", message.communityId);
|
|
1013
1000
|
const shown = (message) => hidden(message) ? [] : attached[message.id] ?? [];
|
|
1001
|
+
const links = await this.images.fileLinks(orgId, messages.flatMap((message) => shown(message).map((assetId) => ({ assetId }))));
|
|
1014
1002
|
return messages.map((message) => {
|
|
1015
1003
|
const record = records[message.orgUserId];
|
|
1016
1004
|
if (!record) throw new NotFoundError("Member", message.orgUserId);
|
|
@@ -1021,10 +1009,13 @@ var ChatServiceImpl = class {
|
|
|
1021
1009
|
body: ""
|
|
1022
1010
|
} : message,
|
|
1023
1011
|
sender: authorView(orgId, record, this.fileUrls, teamBadge(permissions.get(message.orgUserId), message.communityId)),
|
|
1024
|
-
attachments: shown(message).
|
|
1025
|
-
assetId
|
|
1026
|
-
url
|
|
1027
|
-
|
|
1012
|
+
attachments: shown(message).flatMap((assetId) => {
|
|
1013
|
+
const url = links[assetId];
|
|
1014
|
+
return url ? [{
|
|
1015
|
+
assetId,
|
|
1016
|
+
url
|
|
1017
|
+
}] : [];
|
|
1018
|
+
}),
|
|
1028
1019
|
reactions: counts?.reactions ?? {},
|
|
1029
1020
|
viewerReaction: counts?.viewerReaction ?? null,
|
|
1030
1021
|
mentions: hidden(message) ? [] : mentioned[message.id] ?? []
|