@headless-lms/server 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -0
- package/dist/app/community-mail.d.ts +5 -3
- package/dist/app/community-mail.js +60 -12
- package/dist/app/community-mail.js.map +1 -1
- package/dist/app/container.d.ts +24 -3
- package/dist/app/container.js +102 -38
- package/dist/app/container.js.map +1 -1
- package/dist/app/notification-channels.js +1 -0
- package/dist/app/notification-channels.js.map +1 -1
- package/dist/app/notification-reads.d.ts +3 -3
- package/dist/app/notification-reads.js +7 -28
- package/dist/app/notification-reads.js.map +1 -1
- package/dist/app/platform.d.ts +14 -0
- package/dist/app/platform.js +14 -0
- package/dist/app/platform.js.map +1 -0
- package/dist/http/config.d.ts +4 -0
- package/dist/http/errors.js +9 -4
- package/dist/http/errors.js.map +1 -1
- package/dist/http/fastify.d.ts +8 -0
- package/dist/http/mcp/catalogue.d.ts +11 -9
- package/dist/http/mcp/catalogue.js +15 -21
- package/dist/http/mcp/catalogue.js.map +1 -1
- package/dist/http/mcp/challenge.js +3 -3
- package/dist/http/mcp/challenge.js.map +1 -1
- package/dist/http/mcp/route.js +7 -7
- package/dist/http/mcp/route.js.map +1 -1
- package/dist/http/mcp/test-support.d.ts +6 -5
- package/dist/http/mcp/test-support.js +32 -11
- package/dist/http/mcp/test-support.js.map +1 -1
- package/dist/http/mcp/tool.d.ts +3 -9
- package/dist/http/mcp/tool.js +14 -6
- package/dist/http/mcp/tool.js.map +1 -1
- package/dist/http/mcp/tools/automations.js +10 -20
- package/dist/http/mcp/tools/automations.js.map +1 -1
- package/dist/http/mcp/tools/catalog.js +25 -42
- package/dist/http/mcp/tools/catalog.js.map +1 -1
- package/dist/http/mcp/tools/comments.js +9 -19
- package/dist/http/mcp/tools/comments.js.map +1 -1
- package/dist/http/mcp/tools/communities.js +16 -31
- package/dist/http/mcp/tools/communities.js.map +1 -1
- package/dist/http/mcp/tools/community-members.js +9 -16
- package/dist/http/mcp/tools/community-members.js.map +1 -1
- package/dist/http/mcp/tools/community-moderation.js +13 -25
- package/dist/http/mcp/tools/community-moderation.js.map +1 -1
- package/dist/http/mcp/tools/courses.js +11 -21
- package/dist/http/mcp/tools/courses.js.map +1 -1
- package/dist/http/mcp/tools/events.d.ts +6 -0
- package/dist/http/mcp/tools/events.js +170 -0
- package/dist/http/mcp/tools/events.js.map +1 -0
- package/dist/http/mcp/tools/index.d.ts +5 -1
- package/dist/http/mcp/tools/index.js +45 -10
- package/dist/http/mcp/tools/index.js.map +1 -1
- package/dist/http/mcp/tools/organization.d.ts +6 -0
- package/dist/http/mcp/tools/organization.js +214 -0
- package/dist/http/mcp/tools/organization.js.map +1 -0
- package/dist/http/mcp/tools/people.js +30 -49
- package/dist/http/mcp/tools/people.js.map +1 -1
- package/dist/http/plugins/auth.js +37 -8
- package/dist/http/plugins/auth.js.map +1 -1
- package/dist/http/plugins/error-handler.d.ts +5 -1
- package/dist/http/plugins/error-handler.js +10 -2
- package/dist/http/plugins/error-handler.js.map +1 -1
- package/dist/http/plugins/openapi.js +18 -2
- package/dist/http/plugins/openapi.js.map +1 -1
- package/dist/http/plugins/platform.d.ts +7 -0
- package/dist/http/plugins/platform.js +13 -0
- package/dist/http/plugins/platform.js.map +1 -0
- package/dist/http/routes/access.js +54 -36
- package/dist/http/routes/access.js.map +1 -1
- package/dist/http/routes/activities.js +45 -45
- package/dist/http/routes/activities.js.map +1 -1
- package/dist/http/routes/assets.js +30 -65
- package/dist/http/routes/assets.js.map +1 -1
- package/dist/http/routes/automations.js +37 -42
- package/dist/http/routes/automations.js.map +1 -1
- package/dist/http/routes/bundles.js +33 -36
- package/dist/http/routes/bundles.js.map +1 -1
- package/dist/http/routes/communities.js +93 -145
- package/dist/http/routes/communities.js.map +1 -1
- package/dist/http/routes/community-moderation.js +83 -137
- package/dist/http/routes/community-moderation.js.map +1 -1
- package/dist/http/routes/course-analytics.js +32 -15
- package/dist/http/routes/course-analytics.js.map +1 -1
- package/dist/http/routes/courses.js +25 -32
- package/dist/http/routes/courses.js.map +1 -1
- package/dist/http/routes/dashboard.js +9 -9
- package/dist/http/routes/dashboard.js.map +1 -1
- package/dist/http/routes/discussion.js +21 -39
- package/dist/http/routes/discussion.js.map +1 -1
- package/dist/http/routes/downloads.js +41 -47
- package/dist/http/routes/downloads.js.map +1 -1
- package/dist/http/routes/entitlements.js +19 -23
- package/dist/http/routes/entitlements.js.map +1 -1
- package/dist/http/routes/events.d.ts +7 -0
- package/dist/http/routes/events.js +333 -0
- package/dist/http/routes/events.js.map +1 -0
- package/dist/http/routes/integrations.js +40 -73
- package/dist/http/routes/integrations.js.map +1 -1
- package/dist/http/routes/member/assets.js +10 -13
- package/dist/http/routes/member/assets.js.map +1 -1
- package/dist/http/routes/member/chats.js +170 -47
- package/dist/http/routes/member/chats.js.map +1 -1
- package/dist/http/routes/member/comments.js +65 -26
- package/dist/http/routes/member/comments.js.map +1 -1
- package/dist/http/routes/member/community.js +45 -52
- package/dist/http/routes/member/community.js.map +1 -1
- package/dist/http/routes/member/courses.js +12 -19
- package/dist/http/routes/member/courses.js.map +1 -1
- package/dist/http/routes/member/devices.js +9 -10
- package/dist/http/routes/member/devices.js.map +1 -1
- package/dist/http/routes/member/downloads.js +6 -9
- package/dist/http/routes/member/downloads.js.map +1 -1
- package/dist/http/routes/member/events.d.ts +7 -0
- package/dist/http/routes/member/events.js +386 -0
- package/dist/http/routes/member/events.js.map +1 -0
- package/dist/http/routes/member/files.js +71 -46
- package/dist/http/routes/member/files.js.map +1 -1
- package/dist/http/routes/member/index.js +2 -0
- package/dist/http/routes/member/index.js.map +1 -1
- package/dist/http/routes/member/notification-settings.js +15 -23
- package/dist/http/routes/member/notification-settings.js.map +1 -1
- package/dist/http/routes/member/notifications.js +16 -16
- package/dist/http/routes/member/notifications.js.map +1 -1
- package/dist/http/routes/member/org.js +5 -15
- package/dist/http/routes/member/org.js.map +1 -1
- package/dist/http/routes/member/posts.js +67 -68
- package/dist/http/routes/member/posts.js.map +1 -1
- package/dist/http/routes/member/profile.js +15 -6
- package/dist/http/routes/member/profile.js.map +1 -1
- package/dist/http/routes/member/progress.js +7 -11
- package/dist/http/routes/member/progress.js.map +1 -1
- package/dist/http/routes/organizations.js +319 -135
- package/dist/http/routes/organizations.js.map +1 -1
- package/dist/http/routes/platform.d.ts +7 -0
- package/dist/http/routes/platform.js +61 -0
- package/dist/http/routes/platform.js.map +1 -0
- package/dist/http/routes/students.js +12 -75
- package/dist/http/routes/students.js.map +1 -1
- package/dist/http/routes/webhooks.js +30 -39
- package/dist/http/routes/webhooks.js.map +1 -1
- package/dist/http/routes.js +9 -0
- package/dist/http/routes.js.map +1 -1
- package/dist/http/schemas/access.d.ts +346 -64
- package/dist/http/schemas/access.js +39 -12
- package/dist/http/schemas/access.js.map +1 -1
- package/dist/http/schemas/assets.d.ts +19 -14
- package/dist/http/schemas/assets.js +6 -5
- package/dist/http/schemas/assets.js.map +1 -1
- package/dist/http/schemas/automations.d.ts +4 -4
- package/dist/http/schemas/chats.d.ts +211 -32
- package/dist/http/schemas/chats.js +13 -4
- package/dist/http/schemas/chats.js.map +1 -1
- package/dist/http/schemas/community.d.ts +91 -44
- package/dist/http/schemas/community.js +21 -8
- package/dist/http/schemas/community.js.map +1 -1
- package/dist/http/schemas/course-analytics.d.ts +51 -1
- package/dist/http/schemas/course-analytics.js +19 -1
- package/dist/http/schemas/course-analytics.js.map +1 -1
- package/dist/http/schemas/dashboard.d.ts +1 -0
- package/dist/http/schemas/dashboard.js +2 -1
- package/dist/http/schemas/dashboard.js.map +1 -1
- package/dist/http/schemas/discussion.d.ts +22 -72
- package/dist/http/schemas/discussion.js +2 -2
- package/dist/http/schemas/discussion.js.map +1 -1
- package/dist/http/schemas/entitlements.d.ts +9 -12
- package/dist/http/schemas/entitlements.js +11 -5
- package/dist/http/schemas/entitlements.js.map +1 -1
- package/dist/http/schemas/events.d.ts +527 -0
- package/dist/http/schemas/events.js +64 -0
- package/dist/http/schemas/events.js.map +1 -0
- package/dist/http/schemas/files.d.ts +15 -5
- package/dist/http/schemas/files.js +10 -2
- package/dist/http/schemas/files.js.map +1 -1
- package/dist/http/schemas/index.d.ts +11 -9
- package/dist/http/schemas/index.js +11 -9
- package/dist/http/schemas/integrations.d.ts +4 -4
- package/dist/http/schemas/invites.d.ts +3 -47
- package/dist/http/schemas/invites.js +4 -25
- package/dist/http/schemas/invites.js.map +1 -1
- package/dist/http/schemas/member.d.ts +94 -7
- package/dist/http/schemas/member.js +7 -3
- package/dist/http/schemas/member.js.map +1 -1
- package/dist/http/schemas/members.d.ts +333 -69
- package/dist/http/schemas/members.js +67 -25
- package/dist/http/schemas/members.js.map +1 -1
- package/dist/http/schemas/notifications.d.ts +57 -53
- package/dist/http/schemas/platform.d.ts +37 -0
- package/dist/http/schemas/platform.js +19 -0
- package/dist/http/schemas/platform.js.map +1 -0
- package/dist/http/schemas/posts.d.ts +55 -35
- package/dist/http/schemas/posts.js +4 -4
- package/dist/http/schemas/posts.js.map +1 -1
- package/dist/http/schemas/profile.d.ts +1 -1
- package/dist/http/schemas/shared.d.ts +1 -11
- package/dist/http/schemas/shared.js +1 -10
- package/dist/http/schemas/shared.js.map +1 -1
- package/dist/http/schemas/students.d.ts +25 -3
- package/dist/http/schemas/students.js +3 -1
- package/dist/http/schemas/students.js.map +1 -1
- package/dist/http/scope.d.ts +9 -13
- package/dist/http/scope.js +29 -40
- package/dist/http/scope.js.map +1 -1
- package/dist/http/server.js +9 -0
- package/dist/http/server.js.map +1 -1
- package/dist/http/shutdown.d.ts +11 -0
- package/dist/http/shutdown.js +40 -0
- package/dist/http/shutdown.js.map +1 -0
- package/dist/http/sse.d.ts +19 -0
- package/dist/http/sse.js +104 -0
- package/dist/http/sse.js.map +1 -0
- package/dist/http/test-caller.d.ts +13 -0
- package/dist/http/test-caller.js +14 -0
- package/dist/http/test-caller.js.map +1 -0
- package/dist/http/well-known.js +2 -2
- package/dist/http/well-known.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/packages/server/package.js +1 -1
- package/package.json +7 -6
- package/dist/http/routes/member/actor.d.ts +0 -14
- package/dist/http/routes/member/actor.js +0 -11
- package/dist/http/routes/member/actor.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notifications.js","names":[],"sources":["../../../../src/http/routes/member/notifications.ts"],"sourcesContent":["import type { FastifyInstance } from 'fastify';\nimport type { ZodTypeProvider } from 'fastify-type-provider-zod';\nimport { z } from 'zod';\nimport type { Container } from '../../../app/container.js';\nimport { InvalidInputError
|
|
1
|
+
{"version":3,"file":"notifications.js","names":[],"sources":["../../../../src/http/routes/member/notifications.ts"],"sourcesContent":["import type { FastifyInstance, FastifyRequest } from 'fastify';\nimport type { ZodTypeProvider } from 'fastify-type-provider-zod';\nimport { z } from 'zod';\nimport type { Container } from '../../../app/container.js';\nimport { InvalidInputError } from '@headless-lms/core/shared/errors';\nimport { resolveCaller } from '../../scope.js';\nimport {\n NotificationFilterQuery,\n NotificationIdParam,\n NotificationListQuery,\n NotificationUnreadCounts,\n NotificationView,\n NotificationsPage,\n refusals,\n} from '../../schemas/index.js';\n\nexport async function memberNotificationRoutes(\n app: FastifyInstance,\n container: Container,\n): Promise<void> {\n const r = app.withTypeProvider<ZodTypeProvider>();\n const tags = ['Notifications'];\n\n async function memberOf(req: FastifyRequest) {\n const caller = await resolveCaller(container, req);\n return { ...caller.actor, userId: caller.userId };\n }\n\n r.route({\n method: 'GET',\n url: '/api/member/notifications',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'listMemberNotifications',\n tags,\n summary: 'List your notifications, newest first, with the unread count of the same filters',\n description:\n 'For any member of the organization. Filters combine with AND; the values of one filter combine with OR, and `includeOrg=true` with `communityId` adds the org list, so one query reads a community with the course and account notifications. 400 for `includeOrg` without `communityId` or with `scope`. Each notification carries the current titles, names and excerpts of what it refers to; a subject or parent you can no longer open, or that was deleted, is null. `display` is the text stored when it was sent.',\n querystring: NotificationListQuery,\n response: { 200: NotificationsPage, ...refusals(400, 403) },\n },\n handler: async (req) => {\n const { page, pageSize, ...filter } = req.query;\n return container.reporting.member.notifications(\n filter,\n { page, pageSize },\n await memberOf(req),\n );\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/member/notifications/unread-counts',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'getMemberNotificationUnreadCounts',\n tags,\n summary: 'Count your unread notifications in the org list and in each community',\n description:\n 'For any member of the organization. `org` counts the org list; `communities` has one entry per community you can open.',\n response: { 200: NotificationUnreadCounts, ...refusals(403) },\n },\n handler: async (req) => {\n return container.reporting.member.notificationUnreadCounts(await memberOf(req));\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/member/notifications/:notificationId',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'getMemberNotification',\n tags,\n summary: 'Read one of your notifications',\n description:\n 'For any member of the organization. The notification as the list shows it, with current titles, names and excerpts; reading it does not mark it read. 404 when it is not yours or was not shown in the app.',\n params: NotificationIdParam,\n response: { 200: NotificationView, ...refusals(403, 404) },\n },\n handler: async (req) => {\n return container.reporting.member.notification(\n req.params.notificationId,\n await memberOf(req),\n );\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/notifications/:notificationId/read',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'markMemberNotificationRead',\n tags,\n summary: 'Mark one of your notifications read',\n description:\n 'For any member of the organization. Marking a read notification keeps its first read time. 404 when it is not yours.',\n params: NotificationIdParam,\n response: { 204: z.void(), ...refusals(403, 404) },\n },\n handler: async (req, reply) => {\n await container.notificationList.markRead(req.params.notificationId, await memberOf(req));\n return reply.code(204).send();\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/notifications/read',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'markAllMemberNotificationsRead',\n tags,\n summary: 'Mark your notifications matching the filters read',\n description:\n 'For any member of the organization. Takes the filters of the list in the query string, `includeOrg` included; with none, marks every notification read. 400 when the request has a body.',\n querystring: NotificationFilterQuery,\n response: { 204: z.void(), ...refusals(400, 403) },\n },\n preValidation: async (req) => {\n if (req.body !== undefined) {\n throw new InvalidInputError(\n 'Mark-read takes its filters in the query string, not in a body',\n );\n }\n },\n handler: async (req, reply) => {\n await container.notificationList.markAllRead(req.query, await memberOf(req));\n return reply.code(204).send();\n },\n });\n}\n"],"mappings":";;;;;;;AAgBA,eAAsB,yBACpB,KACA,WACe;CACf,MAAM,IAAI,IAAI,iBAAkC;CAChD,MAAM,OAAO,CAAC,eAAe;CAE7B,eAAe,SAAS,KAAqB;EAC3C,MAAM,SAAS,MAAM,cAAc,WAAW,GAAG;EACjD,OAAO;GAAE,GAAG,OAAO;GAAO,QAAQ,OAAO;EAAO;CAClD;CAEA,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb;GACA,SAAS;GACT,aACE;GACF,aAAa;GACb,UAAU;IAAE,KAAK;IAAmB,GAAG,SAAS,KAAK,GAAG;GAAE;EAC5D;EACA,SAAS,OAAO,QAAQ;GACtB,MAAM,EAAE,MAAM,UAAU,GAAG,WAAW,IAAI;GAC1C,OAAO,UAAU,UAAU,OAAO,cAChC,QACA;IAAE;IAAM;GAAS,GACjB,MAAM,SAAS,GAAG,CACpB;EACF;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb;GACA,SAAS;GACT,aACE;GACF,UAAU;IAAE,KAAK;IAA0B,GAAG,SAAS,GAAG;GAAE;EAC9D;EACA,SAAS,OAAO,QAAQ;GACtB,OAAO,UAAU,UAAU,OAAO,yBAAyB,MAAM,SAAS,GAAG,CAAC;EAChF;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb;GACA,SAAS;GACT,aACE;GACF,QAAQ;GACR,UAAU;IAAE,KAAK;IAAkB,GAAG,SAAS,KAAK,GAAG;GAAE;EAC3D;EACA,SAAS,OAAO,QAAQ;GACtB,OAAO,UAAU,UAAU,OAAO,aAChC,IAAI,OAAO,gBACX,MAAM,SAAS,GAAG,CACpB;EACF;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb;GACA,SAAS;GACT,aACE;GACF,QAAQ;GACR,UAAU;IAAE,KAAK,EAAE,KAAK;IAAG,GAAG,SAAS,KAAK,GAAG;GAAE;EACnD;EACA,SAAS,OAAO,KAAK,UAAU;GAC7B,MAAM,UAAU,iBAAiB,SAAS,IAAI,OAAO,gBAAgB,MAAM,SAAS,GAAG,CAAC;GACxF,OAAO,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK;EAC9B;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb;GACA,SAAS;GACT,aACE;GACF,aAAa;GACb,UAAU;IAAE,KAAK,EAAE,KAAK;IAAG,GAAG,SAAS,KAAK,GAAG;GAAE;EACnD;EACA,eAAe,OAAO,QAAQ;GAC5B,IAAI,IAAI,SAAS,KAAA,GACf,MAAM,IAAI,kBACR,gEACF;EAEJ;EACA,SAAS,OAAO,KAAK,UAAU;GAC7B,MAAM,UAAU,iBAAiB,YAAY,IAAI,OAAO,MAAM,SAAS,GAAG,CAAC;GAC3E,OAAO,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK;EAC9B;CACF,CAAC;AACH"}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { refusals } from "../../schemas/shared.js";
|
|
2
|
-
import {
|
|
2
|
+
import { resolveActor } from "../../scope.js";
|
|
3
3
|
import { MemberOrg, MemberViewer } from "../../schemas/member.js";
|
|
4
4
|
import "../../schemas/index.js";
|
|
5
|
-
import { actorOf } from "./actor.js";
|
|
6
5
|
//#region src/http/routes/member/org.ts
|
|
7
6
|
async function memberOrgRoutes(app, container) {
|
|
8
7
|
const r = app.withTypeProvider();
|
|
@@ -18,13 +17,7 @@ async function memberOrgRoutes(app, container) {
|
|
|
18
17
|
response: { 200: MemberOrg }
|
|
19
18
|
},
|
|
20
19
|
handler: async (req) => {
|
|
21
|
-
|
|
22
|
-
if (!org) throw new UnauthorizedError("Your session points to an organization that no longer exists");
|
|
23
|
-
return {
|
|
24
|
-
id: org.id,
|
|
25
|
-
name: org.name,
|
|
26
|
-
slug: org.slug
|
|
27
|
-
};
|
|
20
|
+
return container.organizations.portalIdentity(req.orgId);
|
|
28
21
|
}
|
|
29
22
|
});
|
|
30
23
|
r.route({
|
|
@@ -35,18 +28,15 @@ async function memberOrgRoutes(app, container) {
|
|
|
35
28
|
operationId: "getMemberViewer",
|
|
36
29
|
tags: ["Organizations"],
|
|
37
30
|
summary: "Get the caller's identity within the session's org",
|
|
38
|
-
description: "For a member of the organization: your org user id, which the member API keys on,
|
|
31
|
+
description: "For a member of the organization: your org user id, which the member API keys on, your org role, the permissions you hold anywhere, and those you hold on the org.",
|
|
39
32
|
response: {
|
|
40
33
|
200: MemberViewer,
|
|
41
34
|
...refusals(403)
|
|
42
35
|
}
|
|
43
36
|
},
|
|
44
37
|
handler: async (req) => {
|
|
45
|
-
const
|
|
46
|
-
return
|
|
47
|
-
orgUserId: orgUser.id,
|
|
48
|
-
role: orgUser.role
|
|
49
|
-
};
|
|
38
|
+
const actor = await resolveActor(container, req);
|
|
39
|
+
return container.reporting.member.viewer(actor);
|
|
50
40
|
}
|
|
51
41
|
});
|
|
52
42
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"org.js","names":[],"sources":["../../../../src/http/routes/member/org.ts"],"sourcesContent":["import type { FastifyInstance } from 'fastify';\nimport type { ZodTypeProvider } from 'fastify-type-provider-zod';\nimport { MemberOrg, MemberViewer, refusals } from '../../schemas/index.js';\nimport type { Container } from '../../../app/container.js';\nimport {
|
|
1
|
+
{"version":3,"file":"org.js","names":[],"sources":["../../../../src/http/routes/member/org.ts"],"sourcesContent":["import type { FastifyInstance } from 'fastify';\nimport type { ZodTypeProvider } from 'fastify-type-provider-zod';\nimport { MemberOrg, MemberViewer, refusals } from '../../schemas/index.js';\nimport type { Container } from '../../../app/container.js';\nimport { resolveActor } from '../../scope.js';\n\nexport async function memberOrgRoutes(app: FastifyInstance, container: Container): Promise<void> {\n const r = app.withTypeProvider<ZodTypeProvider>();\n\n r.route({\n method: 'GET',\n url: '/api/member/org',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'getMemberOrg',\n tags: ['Organizations'],\n summary: \"Get the portal org's public identity (branding)\",\n description:\n 'For any signed-in person whose session has this organization active. Name and slug only.',\n response: { 200: MemberOrg },\n },\n handler: async (req) => {\n return container.organizations.portalIdentity(req.orgId);\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/member/viewer',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'getMemberViewer',\n tags: ['Organizations'],\n summary: \"Get the caller's identity within the session's org\",\n description:\n 'For a member of the organization: your org user id, which the member API keys on, your org role, the permissions you hold anywhere, and those you hold on the org.',\n response: { 200: MemberViewer, ...refusals(403) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return container.reporting.member.viewer(actor);\n },\n });\n}\n"],"mappings":";;;;;AAMA,eAAsB,gBAAgB,KAAsB,WAAqC;CAC/F,MAAM,IAAI,IAAI,iBAAkC;CAEhD,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,eAAe;GACtB,SAAS;GACT,aACE;GACF,UAAU,EAAE,KAAK,UAAU;EAC7B;EACA,SAAS,OAAO,QAAQ;GACtB,OAAO,UAAU,cAAc,eAAe,IAAI,KAAK;EACzD;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,eAAe;GACtB,SAAS;GACT,aACE;GACF,UAAU;IAAE,KAAK;IAAc,GAAG,SAAS,GAAG;GAAE;EAClD;EACA,SAAS,OAAO,QAAQ;GACtB,MAAM,QAAQ,MAAM,aAAa,WAAW,GAAG;GAC/C,OAAO,UAAU,UAAU,OAAO,OAAO,KAAK;EAChD;CACF,CAAC;AACH"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { PageQuery, refusals } from "../../schemas/shared.js";
|
|
2
|
+
import { resolveActor } from "../../scope.js";
|
|
2
3
|
import { CommentView, PostComment, Reactions, SetPostSubscription, SetReaction } from "../../schemas/discussion.js";
|
|
3
4
|
import { CommunitySpaceParam } from "../../schemas/community.js";
|
|
4
5
|
import { CreatePost, FeedQuery, FlagReason, PostCommentsPage, PostFeedPage, PostFlag, PostIdParam, PostView, ResolvePostFlags, SchedulePost, SetPostReactions, SpaceQueue, UpdatePost } from "../../schemas/posts.js";
|
|
5
6
|
import { CommunityParam } from "../../schemas/chats.js";
|
|
6
7
|
import "../../schemas/index.js";
|
|
7
|
-
import { actorOf } from "./actor.js";
|
|
8
8
|
import { z } from "zod";
|
|
9
9
|
//#region src/http/routes/member/posts.ts
|
|
10
10
|
async function memberPostRoutes(app, container) {
|
|
@@ -28,8 +28,8 @@ async function memberPostRoutes(app, container) {
|
|
|
28
28
|
}
|
|
29
29
|
},
|
|
30
30
|
handler: async (req) => {
|
|
31
|
-
const actor = await
|
|
32
|
-
return posts.memberFeed(req.
|
|
31
|
+
const actor = await resolveActor(container, req);
|
|
32
|
+
return posts.memberFeed(req.params.communityId, req.query, actor);
|
|
33
33
|
}
|
|
34
34
|
});
|
|
35
35
|
r.route({
|
|
@@ -49,8 +49,8 @@ async function memberPostRoutes(app, container) {
|
|
|
49
49
|
}
|
|
50
50
|
},
|
|
51
51
|
handler: async (req) => {
|
|
52
|
-
const actor = await
|
|
53
|
-
return posts.listOwn(req.
|
|
52
|
+
const actor = await resolveActor(container, req);
|
|
53
|
+
return posts.listOwn(req.params.communityId, req.query, actor);
|
|
54
54
|
}
|
|
55
55
|
});
|
|
56
56
|
r.route({
|
|
@@ -70,8 +70,8 @@ async function memberPostRoutes(app, container) {
|
|
|
70
70
|
}
|
|
71
71
|
},
|
|
72
72
|
handler: async (req) => {
|
|
73
|
-
const actor = await
|
|
74
|
-
return posts.listBookmarked(req.
|
|
73
|
+
const actor = await resolveActor(container, req);
|
|
74
|
+
return posts.listBookmarked(req.params.communityId, req.query, actor);
|
|
75
75
|
}
|
|
76
76
|
});
|
|
77
77
|
r.route({
|
|
@@ -91,8 +91,8 @@ async function memberPostRoutes(app, container) {
|
|
|
91
91
|
}
|
|
92
92
|
},
|
|
93
93
|
handler: async (req) => {
|
|
94
|
-
const actor = await
|
|
95
|
-
return posts.spaceFeed(req.
|
|
94
|
+
const actor = await resolveActor(container, req);
|
|
95
|
+
return posts.spaceFeed(req.params.communityId, req.params.spaceId, req.query, actor);
|
|
96
96
|
}
|
|
97
97
|
});
|
|
98
98
|
r.route({
|
|
@@ -111,8 +111,8 @@ async function memberPostRoutes(app, container) {
|
|
|
111
111
|
}
|
|
112
112
|
},
|
|
113
113
|
handler: async (req) => {
|
|
114
|
-
const actor = await
|
|
115
|
-
return posts.moderationQueue(req.
|
|
114
|
+
const actor = await resolveActor(container, req);
|
|
115
|
+
return posts.moderationQueue(req.params.communityId, req.params.spaceId, actor);
|
|
116
116
|
}
|
|
117
117
|
});
|
|
118
118
|
r.route({
|
|
@@ -123,7 +123,7 @@ async function memberPostRoutes(app, container) {
|
|
|
123
123
|
operationId: "createPost",
|
|
124
124
|
tags,
|
|
125
125
|
summary: "Create a post",
|
|
126
|
-
description: "For anyone who can open the space. `mode` decides the status: `draft`, `scheduled`, or on `submit` `published`, or `pending` when the space requires review and you
|
|
126
|
+
description: "For anyone who can open the space. `mode` decides the status: `draft`, `scheduled`, or on `submit` `published`, or `pending` when the space requires review and you do not hold `communities:moderate` on the community. 409 when the space has topics and none is given. 400 when a schedule is missing or in the past. 503 when a scheduled post could not be timed; the post is then kept as a draft, and `details.postId` names it, so open that draft instead of creating the post again.",
|
|
127
127
|
params: CommunitySpaceParam,
|
|
128
128
|
body: CreatePost,
|
|
129
129
|
response: {
|
|
@@ -132,12 +132,12 @@ async function memberPostRoutes(app, container) {
|
|
|
132
132
|
}
|
|
133
133
|
},
|
|
134
134
|
handler: async (req, reply) => {
|
|
135
|
-
const actor = await
|
|
136
|
-
const post = await posts.create(
|
|
135
|
+
const actor = await resolveActor(container, req);
|
|
136
|
+
const post = await posts.create({
|
|
137
137
|
...req.body,
|
|
138
138
|
communityId: req.params.communityId,
|
|
139
139
|
spaceId: req.params.spaceId
|
|
140
|
-
});
|
|
140
|
+
}, actor);
|
|
141
141
|
req.log.info({
|
|
142
142
|
postId: post.id,
|
|
143
143
|
status: post.status
|
|
@@ -161,8 +161,8 @@ async function memberPostRoutes(app, container) {
|
|
|
161
161
|
}
|
|
162
162
|
},
|
|
163
163
|
handler: async (req) => {
|
|
164
|
-
const actor = await
|
|
165
|
-
return posts.getPost(req.
|
|
164
|
+
const actor = await resolveActor(container, req);
|
|
165
|
+
return posts.getPost(req.params.postId, actor);
|
|
166
166
|
}
|
|
167
167
|
});
|
|
168
168
|
r.route({
|
|
@@ -182,19 +182,19 @@ async function memberPostRoutes(app, container) {
|
|
|
182
182
|
}
|
|
183
183
|
},
|
|
184
184
|
handler: async (req) => {
|
|
185
|
-
const actor = await
|
|
186
|
-
return posts.update(req.
|
|
185
|
+
const actor = await resolveActor(container, req);
|
|
186
|
+
return posts.update(req.params.postId, req.body, actor);
|
|
187
187
|
}
|
|
188
188
|
});
|
|
189
189
|
r.route({
|
|
190
190
|
method: "POST",
|
|
191
|
-
url: "/api/member/posts/:postId/
|
|
191
|
+
url: "/api/member/posts/:postId/submit",
|
|
192
192
|
preHandler: app.requireOrgSession,
|
|
193
193
|
schema: {
|
|
194
194
|
operationId: "submitPost",
|
|
195
195
|
tags,
|
|
196
196
|
summary: "Submit your draft or scheduled post",
|
|
197
|
-
description: "Author only. Publishes it now, or holds it for review when the space requires review and you
|
|
197
|
+
description: "Author only. Publishes it now, or holds it for review when the space requires review and you do not hold `communities:moderate` on the community. A scheduled post is no longer published at its time. 409 when the post is not a draft or scheduled.",
|
|
198
198
|
params: PostIdParam,
|
|
199
199
|
response: {
|
|
200
200
|
200: PostView,
|
|
@@ -202,8 +202,8 @@ async function memberPostRoutes(app, container) {
|
|
|
202
202
|
}
|
|
203
203
|
},
|
|
204
204
|
handler: async (req) => {
|
|
205
|
-
const actor = await
|
|
206
|
-
return posts.submit(req.
|
|
205
|
+
const actor = await resolveActor(container, req);
|
|
206
|
+
return posts.submit(req.params.postId, actor);
|
|
207
207
|
}
|
|
208
208
|
});
|
|
209
209
|
r.route({
|
|
@@ -223,8 +223,8 @@ async function memberPostRoutes(app, container) {
|
|
|
223
223
|
}
|
|
224
224
|
},
|
|
225
225
|
handler: async (req) => {
|
|
226
|
-
const actor = await
|
|
227
|
-
return posts.schedule(req.
|
|
226
|
+
const actor = await resolveActor(container, req);
|
|
227
|
+
return posts.schedule(req.params.postId, req.body.scheduledAt, actor);
|
|
228
228
|
}
|
|
229
229
|
});
|
|
230
230
|
r.route({
|
|
@@ -243,13 +243,13 @@ async function memberPostRoutes(app, container) {
|
|
|
243
243
|
}
|
|
244
244
|
},
|
|
245
245
|
handler: async (req) => {
|
|
246
|
-
const actor = await
|
|
247
|
-
return posts.unschedule(req.
|
|
246
|
+
const actor = await resolveActor(container, req);
|
|
247
|
+
return posts.unschedule(req.params.postId, actor);
|
|
248
248
|
}
|
|
249
249
|
});
|
|
250
250
|
r.route({
|
|
251
251
|
method: "POST",
|
|
252
|
-
url: "/api/member/posts/:postId/
|
|
252
|
+
url: "/api/member/posts/:postId/approve",
|
|
253
253
|
preHandler: app.requireOrgSession,
|
|
254
254
|
schema: {
|
|
255
255
|
operationId: "approvePost",
|
|
@@ -263,19 +263,19 @@ async function memberPostRoutes(app, container) {
|
|
|
263
263
|
}
|
|
264
264
|
},
|
|
265
265
|
handler: async (req) => {
|
|
266
|
-
const actor = await
|
|
267
|
-
return posts.approve(req.
|
|
266
|
+
const actor = await resolveActor(container, req);
|
|
267
|
+
return posts.approve(req.params.postId, null, actor);
|
|
268
268
|
}
|
|
269
269
|
});
|
|
270
270
|
r.route({
|
|
271
271
|
method: "POST",
|
|
272
|
-
url: "/api/member/posts/:postId/
|
|
272
|
+
url: "/api/member/posts/:postId/remove",
|
|
273
273
|
preHandler: app.requireOrgSession,
|
|
274
274
|
schema: {
|
|
275
275
|
operationId: "removePost",
|
|
276
276
|
tags,
|
|
277
277
|
summary: "Remove your post, or one in a space you moderate",
|
|
278
|
-
description: "
|
|
278
|
+
description: "The author can remove their own post; anyone else needs `communities:moderate` on the community. Takes a published or pending post down; removing someone else's post resolves its open flags as `removed`. 409 when it is already removed or was never submitted.",
|
|
279
279
|
params: PostIdParam,
|
|
280
280
|
response: {
|
|
281
281
|
200: PostView,
|
|
@@ -283,13 +283,13 @@ async function memberPostRoutes(app, container) {
|
|
|
283
283
|
}
|
|
284
284
|
},
|
|
285
285
|
handler: async (req) => {
|
|
286
|
-
const actor = await
|
|
287
|
-
return posts.remove(req.
|
|
286
|
+
const actor = await resolveActor(container, req);
|
|
287
|
+
return posts.remove(req.params.postId, null, actor);
|
|
288
288
|
}
|
|
289
289
|
});
|
|
290
290
|
r.route({
|
|
291
291
|
method: "POST",
|
|
292
|
-
url: "/api/member/posts/:postId/
|
|
292
|
+
url: "/api/member/posts/:postId/restore",
|
|
293
293
|
preHandler: app.requireOrgSession,
|
|
294
294
|
schema: {
|
|
295
295
|
operationId: "restorePost",
|
|
@@ -303,8 +303,8 @@ async function memberPostRoutes(app, container) {
|
|
|
303
303
|
}
|
|
304
304
|
},
|
|
305
305
|
handler: async (req) => {
|
|
306
|
-
const actor = await
|
|
307
|
-
return posts.restore(req.
|
|
306
|
+
const actor = await resolveActor(container, req);
|
|
307
|
+
return posts.restore(req.params.postId, null, actor);
|
|
308
308
|
}
|
|
309
309
|
});
|
|
310
310
|
r.route({
|
|
@@ -323,8 +323,8 @@ async function memberPostRoutes(app, container) {
|
|
|
323
323
|
}
|
|
324
324
|
},
|
|
325
325
|
handler: async (req) => {
|
|
326
|
-
const actor = await
|
|
327
|
-
return posts.pin(req.
|
|
326
|
+
const actor = await resolveActor(container, req);
|
|
327
|
+
return posts.pin(req.params.postId, actor);
|
|
328
328
|
}
|
|
329
329
|
});
|
|
330
330
|
r.route({
|
|
@@ -343,8 +343,8 @@ async function memberPostRoutes(app, container) {
|
|
|
343
343
|
}
|
|
344
344
|
},
|
|
345
345
|
handler: async (req) => {
|
|
346
|
-
const actor = await
|
|
347
|
-
return posts.unpin(req.
|
|
346
|
+
const actor = await resolveActor(container, req);
|
|
347
|
+
return posts.unpin(req.params.postId, actor);
|
|
348
348
|
}
|
|
349
349
|
});
|
|
350
350
|
r.route({
|
|
@@ -363,8 +363,8 @@ async function memberPostRoutes(app, container) {
|
|
|
363
363
|
}
|
|
364
364
|
},
|
|
365
365
|
handler: async (req) => {
|
|
366
|
-
const actor = await
|
|
367
|
-
return posts.closeComments(req.
|
|
366
|
+
const actor = await resolveActor(container, req);
|
|
367
|
+
return posts.closeComments(req.params.postId, actor);
|
|
368
368
|
}
|
|
369
369
|
});
|
|
370
370
|
r.route({
|
|
@@ -383,8 +383,8 @@ async function memberPostRoutes(app, container) {
|
|
|
383
383
|
}
|
|
384
384
|
},
|
|
385
385
|
handler: async (req) => {
|
|
386
|
-
const actor = await
|
|
387
|
-
return posts.openComments(req.
|
|
386
|
+
const actor = await resolveActor(container, req);
|
|
387
|
+
return posts.openComments(req.params.postId, actor);
|
|
388
388
|
}
|
|
389
389
|
});
|
|
390
390
|
r.route({
|
|
@@ -404,8 +404,8 @@ async function memberPostRoutes(app, container) {
|
|
|
404
404
|
}
|
|
405
405
|
},
|
|
406
406
|
handler: async (req) => {
|
|
407
|
-
const actor = await
|
|
408
|
-
return posts.setReactions(req.
|
|
407
|
+
const actor = await resolveActor(container, req);
|
|
408
|
+
return posts.setReactions(req.params.postId, req.body.enabled, actor);
|
|
409
409
|
}
|
|
410
410
|
});
|
|
411
411
|
r.route({
|
|
@@ -425,8 +425,8 @@ async function memberPostRoutes(app, container) {
|
|
|
425
425
|
}
|
|
426
426
|
},
|
|
427
427
|
handler: async (req) => {
|
|
428
|
-
const actor = await
|
|
429
|
-
return posts.setReaction(req.
|
|
428
|
+
const actor = await resolveActor(container, req);
|
|
429
|
+
return posts.setReaction(req.params.postId, req.body.emoji, actor);
|
|
430
430
|
}
|
|
431
431
|
});
|
|
432
432
|
r.route({
|
|
@@ -445,8 +445,8 @@ async function memberPostRoutes(app, container) {
|
|
|
445
445
|
}
|
|
446
446
|
},
|
|
447
447
|
handler: async (req) => {
|
|
448
|
-
const actor = await
|
|
449
|
-
return posts.setReaction(req.
|
|
448
|
+
const actor = await resolveActor(container, req);
|
|
449
|
+
return posts.setReaction(req.params.postId, null, actor);
|
|
450
450
|
}
|
|
451
451
|
});
|
|
452
452
|
r.route({
|
|
@@ -466,8 +466,8 @@ async function memberPostRoutes(app, container) {
|
|
|
466
466
|
}
|
|
467
467
|
},
|
|
468
468
|
handler: async (req, reply) => {
|
|
469
|
-
const actor = await
|
|
470
|
-
await container.subscriptions.setPost(req.
|
|
469
|
+
const actor = await resolveActor(container, req);
|
|
470
|
+
await container.subscriptions.setPost(req.params.postId, req.body, actor);
|
|
471
471
|
return reply.code(204).send();
|
|
472
472
|
}
|
|
473
473
|
});
|
|
@@ -487,8 +487,8 @@ async function memberPostRoutes(app, container) {
|
|
|
487
487
|
}
|
|
488
488
|
},
|
|
489
489
|
handler: async (req, reply) => {
|
|
490
|
-
const actor = await
|
|
491
|
-
await posts.bookmark(req.
|
|
490
|
+
const actor = await resolveActor(container, req);
|
|
491
|
+
await posts.bookmark(req.params.postId, actor);
|
|
492
492
|
return reply.code(204).send();
|
|
493
493
|
}
|
|
494
494
|
});
|
|
@@ -508,8 +508,8 @@ async function memberPostRoutes(app, container) {
|
|
|
508
508
|
}
|
|
509
509
|
},
|
|
510
510
|
handler: async (req, reply) => {
|
|
511
|
-
const actor = await
|
|
512
|
-
await posts.unbookmark(req.
|
|
511
|
+
const actor = await resolveActor(container, req);
|
|
512
|
+
await posts.unbookmark(req.params.postId, actor);
|
|
513
513
|
return reply.code(204).send();
|
|
514
514
|
}
|
|
515
515
|
});
|
|
@@ -530,14 +530,14 @@ async function memberPostRoutes(app, container) {
|
|
|
530
530
|
}
|
|
531
531
|
},
|
|
532
532
|
handler: async (req, reply) => {
|
|
533
|
-
const actor = await
|
|
534
|
-
const flag = await posts.flag(req.
|
|
533
|
+
const actor = await resolveActor(container, req);
|
|
534
|
+
const flag = await posts.flag(req.params.postId, req.body.reason, actor);
|
|
535
535
|
return reply.code(201).send(flag);
|
|
536
536
|
}
|
|
537
537
|
});
|
|
538
538
|
r.route({
|
|
539
539
|
method: "POST",
|
|
540
|
-
url: "/api/member/posts/:postId/flags/
|
|
540
|
+
url: "/api/member/posts/:postId/flags/resolve",
|
|
541
541
|
preHandler: app.requireOrgSession,
|
|
542
542
|
schema: {
|
|
543
543
|
operationId: "resolvePostFlags",
|
|
@@ -552,8 +552,8 @@ async function memberPostRoutes(app, container) {
|
|
|
552
552
|
}
|
|
553
553
|
},
|
|
554
554
|
handler: async (req, reply) => {
|
|
555
|
-
const actor = await
|
|
556
|
-
await posts.resolveFlags(req.
|
|
555
|
+
const actor = await resolveActor(container, req);
|
|
556
|
+
await posts.resolveFlags(req.params.postId, req.body.resolution, null, actor);
|
|
557
557
|
return reply.code(204).send();
|
|
558
558
|
}
|
|
559
559
|
});
|
|
@@ -574,8 +574,8 @@ async function memberPostRoutes(app, container) {
|
|
|
574
574
|
}
|
|
575
575
|
},
|
|
576
576
|
handler: async (req) => {
|
|
577
|
-
const actor = await
|
|
578
|
-
return container.discussion.postComments(req.
|
|
577
|
+
const actor = await resolveActor(container, req);
|
|
578
|
+
return container.discussion.postComments(req.params.postId, req.query, actor);
|
|
579
579
|
}
|
|
580
580
|
});
|
|
581
581
|
r.route({
|
|
@@ -595,13 +595,12 @@ async function memberPostRoutes(app, container) {
|
|
|
595
595
|
}
|
|
596
596
|
},
|
|
597
597
|
handler: async (req, reply) => {
|
|
598
|
-
const actor = await
|
|
599
|
-
const comment = await container.discussion.postComment(
|
|
600
|
-
actor,
|
|
598
|
+
const actor = await resolveActor(container, req);
|
|
599
|
+
const comment = await container.discussion.postComment({
|
|
601
600
|
postId: req.params.postId,
|
|
602
601
|
parentId: req.body.parentId,
|
|
603
602
|
body: req.body.body
|
|
604
|
-
});
|
|
603
|
+
}, actor);
|
|
605
604
|
return reply.code(201).send(comment);
|
|
606
605
|
}
|
|
607
606
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"posts.js","names":[],"sources":["../../../../src/http/routes/member/posts.ts"],"sourcesContent":["import type { FastifyInstance } from 'fastify';\nimport type { ZodTypeProvider } from 'fastify-type-provider-zod';\nimport { z } from 'zod';\nimport type { Container } from '../../../app/container.js';\nimport { actorOf } from './actor.js';\nimport {\n CommentView,\n CommunityParam,\n CommunitySpaceParam,\n CreatePost,\n FeedQuery,\n FlagReason,\n PageQuery,\n PostCommentsPage,\n PostComment,\n PostFeedPage,\n PostFlag,\n PostIdParam,\n PostView,\n Reactions,\n ResolvePostFlags,\n SchedulePost,\n SetPostReactions,\n SetPostSubscription,\n SetReaction,\n SpaceQueue,\n UpdatePost,\n refusals,\n} from '../../schemas/index.js';\n\nexport async function memberPostRoutes(app: FastifyInstance, container: Container): Promise<void> {\n const r = app.withTypeProvider<ZodTypeProvider>();\n const posts = container.posts;\n const tags = ['Posts'];\n\n r.route({\n method: 'GET',\n url: '/api/member/communities/:communityId/feed',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'getMemberFeed',\n tags,\n summary: 'Published posts across the spaces you can open',\n description:\n 'For a member of the community. Pinned posts first, then newest first. 404 when you are not a member.',\n params: CommunityParam,\n querystring: PageQuery,\n response: { 200: PostFeedPage, ...refusals(403, 404) },\n },\n handler: async (req) => {\n const actor = await actorOf(container, req.orgId, req.userId);\n return posts.memberFeed(req.orgId, actor, req.params.communityId, req.query);\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/member/communities/:communityId/own-posts',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'listOwnPosts',\n tags,\n summary: 'Your own posts in a community, newest first',\n description:\n 'For a member of the community. Your posts in any status, drafts included, in the spaces you can open. 404 when you are not a member.',\n params: CommunityParam,\n querystring: PageQuery,\n response: { 200: PostFeedPage, ...refusals(403, 404) },\n },\n handler: async (req) => {\n const actor = await actorOf(container, req.orgId, req.userId);\n return posts.listOwn(req.orgId, actor, req.params.communityId, req.query);\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/member/communities/:communityId/bookmarks',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'listBookmarkedPosts',\n tags,\n summary: 'The posts you bookmarked in a community, newest bookmark first',\n description:\n 'For a member of the community. Only posts you can still read. 404 when you are not a member.',\n params: CommunityParam,\n querystring: PageQuery,\n response: { 200: PostFeedPage, ...refusals(403, 404) },\n },\n handler: async (req) => {\n const actor = await actorOf(container, req.orgId, req.userId);\n return posts.listBookmarked(req.orgId, actor, req.params.communityId, req.query);\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/member/communities/:communityId/spaces/:spaceId/feed',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'getSpaceFeed',\n tags,\n summary: 'Published posts in a space',\n description:\n 'For anyone who can open the space (403 otherwise). Filter by `topicId`; an unknown topic is a 404.',\n params: CommunitySpaceParam,\n querystring: FeedQuery,\n response: { 200: PostFeedPage, ...refusals(403, 404) },\n },\n handler: async (req) => {\n const actor = await actorOf(container, req.orgId, req.userId);\n return posts.spaceFeed(\n req.orgId,\n actor,\n req.params.communityId,\n req.params.spaceId,\n req.query,\n );\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/member/communities/:communityId/spaces/:spaceId/queue',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'getSpaceQueue',\n tags,\n summary: 'The moderation queue of a space you moderate',\n description:\n 'For a moderator who can open the space. Posts awaiting review, and the open flags on posts and on comments in the space. Each list holds at most the 100 oldest entries: pending posts by creation, flags by when they were raised; working the queue brings in the next ones.',\n params: CommunitySpaceParam,\n response: { 200: SpaceQueue, ...refusals(403, 404) },\n },\n handler: async (req) => {\n const actor = await actorOf(container, req.orgId, req.userId);\n return posts.moderationQueue(req.orgId, actor, req.params.communityId, req.params.spaceId);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/communities/:communityId/spaces/:spaceId/posts',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'createPost',\n tags,\n summary: 'Create a post',\n description:\n 'For anyone who can open the space. `mode` decides the status: `draft`, `scheduled`, or on `submit` `published`, or `pending` when the space requires review and you are not staff. 409 when the space has topics and none is given. 400 when a schedule is missing or in the past. 503 when a scheduled post could not be timed; the post is then kept as a draft, and `details.postId` names it, so open that draft instead of creating the post again.',\n params: CommunitySpaceParam,\n body: CreatePost,\n response: { 201: PostView, ...refusals(400, 403, 404, 409, 503) },\n },\n handler: async (req, reply) => {\n const actor = await actorOf(container, req.orgId, req.userId);\n const post = await posts.create(req.orgId, actor, {\n ...req.body,\n communityId: req.params.communityId,\n spaceId: req.params.spaceId,\n });\n req.log.info({ postId: post.id, status: post.status }, 'post created');\n return reply.code(201).send(post);\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/member/posts/:postId',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'getPost',\n tags,\n summary: 'Read a post',\n description:\n 'For anyone who can open the space while the post is published; for its author in any status; for moderators also while it is pending or removed. Any other post is a 404.',\n params: PostIdParam,\n response: { 200: PostView, ...refusals(403, 404) },\n },\n handler: async (req) => {\n const actor = await actorOf(container, req.orgId, req.userId);\n return posts.getPost(req.orgId, actor, req.params.postId);\n },\n });\n\n r.route({\n method: 'PATCH',\n url: '/api/member/posts/:postId',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'updatePost',\n tags,\n summary: 'Edit your own post',\n description:\n 'Author only. Changes only the fields sent. 409 when the post is removed, or the topic rules of the space are not met.',\n params: PostIdParam,\n body: UpdatePost,\n response: { 200: PostView, ...refusals(403, 404, 409) },\n },\n handler: async (req) => {\n const actor = await actorOf(container, req.orgId, req.userId);\n return posts.update(req.orgId, req.params.postId, actor, req.body);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/posts/:postId/submission',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'submitPost',\n tags,\n summary: 'Submit your draft or scheduled post',\n description:\n 'Author only. Publishes it now, or holds it for review when the space requires review and you are not staff. A scheduled post is no longer published at its time. 409 when the post is not a draft or scheduled.',\n params: PostIdParam,\n response: { 200: PostView, ...refusals(403, 404, 409) },\n },\n handler: async (req) => {\n const actor = await actorOf(container, req.orgId, req.userId);\n return posts.submit(req.orgId, req.params.postId, actor);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/posts/:postId/schedule',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'schedulePost',\n tags,\n summary: 'Schedule your post',\n description:\n 'Author only. Schedules a draft, or moves a scheduled post to a new time; the post is submitted at `scheduledAt`. 409 when it is already submitted or removed, or the time is not in the future. 503 when the time could not be set; a draft stays a draft and a moved post keeps its previous time, and `details.postId` names the post.',\n params: PostIdParam,\n body: SchedulePost,\n response: { 200: PostView, ...refusals(403, 404, 409, 503) },\n },\n handler: async (req) => {\n const actor = await actorOf(container, req.orgId, req.userId);\n return posts.schedule(req.orgId, req.params.postId, actor, req.body.scheduledAt);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/posts/:postId/unschedule',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'unschedulePost',\n tags,\n summary: 'Unschedule your post',\n description:\n 'Author only. The scheduled post becomes a draft and is not submitted at its time. 409 when the post is not scheduled.',\n params: PostIdParam,\n response: { 200: PostView, ...refusals(403, 404, 409) },\n },\n handler: async (req) => {\n const actor = await actorOf(container, req.orgId, req.userId);\n return posts.unschedule(req.orgId, req.params.postId, actor);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/posts/:postId/approval',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'approvePost',\n tags,\n summary: 'Publish a post that awaits review in a space you moderate',\n description:\n 'For a moderator who can open the space. 409 when the post is not awaiting review.',\n params: PostIdParam,\n response: { 200: PostView, ...refusals(403, 404, 409) },\n },\n handler: async (req) => {\n const actor = await actorOf(container, req.orgId, req.userId);\n return posts.approve(req.orgId, req.params.postId, actor);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/posts/:postId/removal',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'removePost',\n tags,\n summary: 'Remove your post, or one in a space you moderate',\n description:\n \"For the author or a moderator. Takes a published or pending post down; a moderator removing someone else's post resolves its open flags as `removed`. 409 when it is already removed or was never submitted.\",\n params: PostIdParam,\n response: { 200: PostView, ...refusals(403, 404, 409) },\n },\n handler: async (req) => {\n const actor = await actorOf(container, req.orgId, req.userId);\n return posts.remove(req.orgId, req.params.postId, actor);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/posts/:postId/restoration',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'restorePost',\n tags,\n summary: 'Restore a removed post in a space you moderate',\n description: 'For a moderator who can open the space. 409 when the post is not removed.',\n params: PostIdParam,\n response: { 200: PostView, ...refusals(403, 404, 409) },\n },\n handler: async (req) => {\n const actor = await actorOf(container, req.orgId, req.userId);\n return posts.restore(req.orgId, req.params.postId, actor);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/posts/:postId/pin',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'pinPost',\n tags,\n summary: 'Pin a post in a space you moderate',\n description: 'For a moderator. Pinned posts lead the feeds. 409 when the post is removed.',\n params: PostIdParam,\n response: { 200: PostView, ...refusals(403, 404, 409) },\n },\n handler: async (req) => {\n const actor = await actorOf(container, req.orgId, req.userId);\n return posts.pin(req.orgId, req.params.postId, actor);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/posts/:postId/unpin',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'unpinPost',\n tags,\n summary: 'Unpin a post in a space you moderate',\n description: 'For a moderator. 409 when the post is removed.',\n params: PostIdParam,\n response: { 200: PostView, ...refusals(403, 404, 409) },\n },\n handler: async (req) => {\n const actor = await actorOf(container, req.orgId, req.userId);\n return posts.unpin(req.orgId, req.params.postId, actor);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/posts/:postId/comments/close',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'closePostComments',\n tags,\n summary: 'Close comments on a post in a space you moderate',\n description:\n 'For a moderator. Nobody can comment until they are opened again. 409 when the post is removed.',\n params: PostIdParam,\n response: { 200: PostView, ...refusals(403, 404, 409) },\n },\n handler: async (req) => {\n const actor = await actorOf(container, req.orgId, req.userId);\n return posts.closeComments(req.orgId, req.params.postId, actor);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/posts/:postId/comments/open',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'openPostComments',\n tags,\n summary: 'Open comments on a post in a space you moderate',\n description: 'For a moderator. 409 when the post is removed.',\n params: PostIdParam,\n response: { 200: PostView, ...refusals(403, 404, 409) },\n },\n handler: async (req) => {\n const actor = await actorOf(container, req.orgId, req.userId);\n return posts.openComments(req.orgId, req.params.postId, actor);\n },\n });\n\n r.route({\n method: 'PUT',\n url: '/api/member/posts/:postId/reactions',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'setPostReactionPolicy',\n tags,\n summary: 'Turn reactions on or off for a post in a space you moderate',\n description:\n \"For a moderator. Overrides the space's reactions setting for this post. 409 when the post is removed.\",\n params: PostIdParam,\n body: SetPostReactions,\n response: { 200: PostView, ...refusals(403, 404, 409) },\n },\n handler: async (req) => {\n const actor = await actorOf(container, req.orgId, req.userId);\n return posts.setReactions(req.orgId, req.params.postId, actor, req.body.enabled);\n },\n });\n\n r.route({\n method: 'PUT',\n url: '/api/member/posts/:postId/reaction',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'setPostReaction',\n tags,\n summary: 'Set your reaction on a post',\n description:\n 'For anyone who can read the post, while reactions are on for it (403 otherwise). Replaces any reaction you already had and returns the new counts.',\n params: PostIdParam,\n body: SetReaction,\n response: { 200: Reactions, ...refusals(403, 404) },\n },\n handler: async (req) => {\n const actor = await actorOf(container, req.orgId, req.userId);\n return posts.setReaction(req.orgId, req.params.postId, actor, req.body.emoji);\n },\n });\n\n r.route({\n method: 'DELETE',\n url: '/api/member/posts/:postId/reaction',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'clearPostReaction',\n tags,\n summary: 'Withdraw your reaction from a post',\n description:\n 'For anyone who can read the post, while reactions are on for it (403 otherwise). Returns the new counts.',\n params: PostIdParam,\n response: { 200: Reactions, ...refusals(403, 404) },\n },\n handler: async (req) => {\n const actor = await actorOf(container, req.orgId, req.userId);\n return posts.setReaction(req.orgId, req.params.postId, actor, null);\n },\n });\n\n r.route({\n method: 'PUT',\n url: '/api/member/posts/:postId/subscription',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'setPostSubscription',\n tags,\n summary: 'Follow or mute a post, or clear either',\n description:\n 'For anyone who can read the post. `following` notifies you of its new comments. `muted` stops its activity notifying you, until `mutedUntil` when given; mentions and actions on you still notify. `none` clears both.',\n params: PostIdParam,\n body: SetPostSubscription,\n response: { 204: z.void(), ...refusals(403, 404) },\n },\n handler: async (req, reply) => {\n const actor = await actorOf(container, req.orgId, req.userId);\n await container.subscriptions.setPost(req.orgId, actor, req.params.postId, req.body);\n return reply.code(204).send();\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/posts/:postId/bookmark',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'bookmarkPost',\n tags,\n summary: 'Bookmark a post',\n description: 'For anyone who can read the post. Bookmarking twice is harmless.',\n params: PostIdParam,\n response: { 204: z.void(), ...refusals(403, 404) },\n },\n handler: async (req, reply) => {\n const actor = await actorOf(container, req.orgId, req.userId);\n await posts.bookmark(req.orgId, req.params.postId, actor);\n return reply.code(204).send();\n },\n });\n\n r.route({\n method: 'DELETE',\n url: '/api/member/posts/:postId/bookmark',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'unbookmarkPost',\n tags,\n summary: 'Remove a bookmark',\n description: 'For anyone who can read the post. Harmless when you have not bookmarked it.',\n params: PostIdParam,\n response: { 204: z.void(), ...refusals(403, 404) },\n },\n handler: async (req, reply) => {\n const actor = await actorOf(container, req.orgId, req.userId);\n await posts.unbookmark(req.orgId, req.params.postId, actor);\n return reply.code(204).send();\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/posts/:postId/flags',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'flagPost',\n tags,\n summary: 'Flag a post for the moderators',\n description:\n 'For anyone who can read the post. Flagging it again while your flag is open returns that flag.',\n params: PostIdParam,\n body: FlagReason,\n response: { 201: PostFlag, ...refusals(403, 404) },\n },\n handler: async (req, reply) => {\n const actor = await actorOf(container, req.orgId, req.userId);\n const flag = await posts.flag(req.orgId, req.params.postId, actor, req.body.reason);\n return reply.code(201).send(flag);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/posts/:postId/flags/resolution',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'resolvePostFlags',\n tags,\n summary: 'Dismiss the open flags on a post in a space you moderate',\n description:\n 'For a moderator who can open the space. Closes every open flag and leaves the post up.',\n params: PostIdParam,\n body: ResolvePostFlags,\n response: { 204: z.void(), ...refusals(403, 404) },\n },\n handler: async (req, reply) => {\n const actor = await actorOf(container, req.orgId, req.userId);\n await posts.resolveFlags(req.orgId, req.params.postId, actor, req.body.resolution);\n return reply.code(204).send();\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/member/posts/:postId/comments',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'listPostComments',\n tags,\n summary: \"Read a post's comments\",\n description:\n 'For anyone who can read the post. Pages by top-level comment, oldest first. Each page carries its top-level comments and all of their replies; `total` counts top-level comments.',\n params: PostIdParam,\n querystring: PageQuery,\n response: { 200: PostCommentsPage, ...refusals(403, 404) },\n },\n handler: async (req) => {\n const actor = await actorOf(container, req.orgId, req.userId);\n return container.discussion.postComments(req.orgId, req.params.postId, actor, req.query);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/posts/:postId/comments',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'createPostComment',\n tags,\n summary: 'Comment on a post',\n description:\n 'For anyone who can read the post, while its comments are open (403 otherwise). Replies nest one level. 409 when the post is not published.',\n params: PostIdParam,\n body: PostComment,\n response: { 201: CommentView, ...refusals(403, 404, 409) },\n },\n handler: async (req, reply) => {\n const actor = await actorOf(container, req.orgId, req.userId);\n const comment = await container.discussion.postComment(req.orgId, {\n actor,\n postId: req.params.postId,\n parentId: req.body.parentId,\n body: req.body.body,\n });\n return reply.code(201).send(comment);\n },\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"posts.js","names":[],"sources":["../../../../src/http/routes/member/posts.ts"],"sourcesContent":["import type { FastifyInstance } from 'fastify';\nimport type { ZodTypeProvider } from 'fastify-type-provider-zod';\nimport { z } from 'zod';\nimport type { Container } from '../../../app/container.js';\nimport { resolveActor } from '../../scope.js';\nimport {\n CommentView,\n CommunityParam,\n CommunitySpaceParam,\n CreatePost,\n FeedQuery,\n FlagReason,\n PageQuery,\n PostCommentsPage,\n PostComment,\n PostFeedPage,\n PostFlag,\n PostIdParam,\n PostView,\n Reactions,\n ResolvePostFlags,\n SchedulePost,\n SetPostReactions,\n SetPostSubscription,\n SetReaction,\n SpaceQueue,\n UpdatePost,\n refusals,\n} from '../../schemas/index.js';\n\nexport async function memberPostRoutes(app: FastifyInstance, container: Container): Promise<void> {\n const r = app.withTypeProvider<ZodTypeProvider>();\n const posts = container.posts;\n const tags = ['Posts'];\n\n r.route({\n method: 'GET',\n url: '/api/member/communities/:communityId/feed',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'getMemberFeed',\n tags,\n summary: 'Published posts across the spaces you can open',\n description:\n 'For a member of the community. Pinned posts first, then newest first. 404 when you are not a member.',\n params: CommunityParam,\n querystring: PageQuery,\n response: { 200: PostFeedPage, ...refusals(403, 404) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return posts.memberFeed(req.params.communityId, req.query, actor);\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/member/communities/:communityId/own-posts',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'listOwnPosts',\n tags,\n summary: 'Your own posts in a community, newest first',\n description:\n 'For a member of the community. Your posts in any status, drafts included, in the spaces you can open. 404 when you are not a member.',\n params: CommunityParam,\n querystring: PageQuery,\n response: { 200: PostFeedPage, ...refusals(403, 404) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return posts.listOwn(req.params.communityId, req.query, actor);\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/member/communities/:communityId/bookmarks',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'listBookmarkedPosts',\n tags,\n summary: 'The posts you bookmarked in a community, newest bookmark first',\n description:\n 'For a member of the community. Only posts you can still read. 404 when you are not a member.',\n params: CommunityParam,\n querystring: PageQuery,\n response: { 200: PostFeedPage, ...refusals(403, 404) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return posts.listBookmarked(req.params.communityId, req.query, actor);\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/member/communities/:communityId/spaces/:spaceId/feed',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'getSpaceFeed',\n tags,\n summary: 'Published posts in a space',\n description:\n 'For anyone who can open the space (403 otherwise). Filter by `topicId`; an unknown topic is a 404.',\n params: CommunitySpaceParam,\n querystring: FeedQuery,\n response: { 200: PostFeedPage, ...refusals(403, 404) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return posts.spaceFeed(req.params.communityId, req.params.spaceId, req.query, actor);\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/member/communities/:communityId/spaces/:spaceId/queue',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'getSpaceQueue',\n tags,\n summary: 'The moderation queue of a space you moderate',\n description:\n 'For a moderator who can open the space. Posts awaiting review, and the open flags on posts and on comments in the space. Each list holds at most the 100 oldest entries: pending posts by creation, flags by when they were raised; working the queue brings in the next ones.',\n params: CommunitySpaceParam,\n response: { 200: SpaceQueue, ...refusals(403, 404) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return posts.moderationQueue(req.params.communityId, req.params.spaceId, actor);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/communities/:communityId/spaces/:spaceId/posts',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'createPost',\n tags,\n summary: 'Create a post',\n description:\n 'For anyone who can open the space. `mode` decides the status: `draft`, `scheduled`, or on `submit` `published`, or `pending` when the space requires review and you do not hold `communities:moderate` on the community. 409 when the space has topics and none is given. 400 when a schedule is missing or in the past. 503 when a scheduled post could not be timed; the post is then kept as a draft, and `details.postId` names it, so open that draft instead of creating the post again.',\n params: CommunitySpaceParam,\n body: CreatePost,\n response: { 201: PostView, ...refusals(400, 403, 404, 409, 503) },\n },\n handler: async (req, reply) => {\n const actor = await resolveActor(container, req);\n const post = await posts.create(\n { ...req.body, communityId: req.params.communityId, spaceId: req.params.spaceId },\n actor,\n );\n req.log.info({ postId: post.id, status: post.status }, 'post created');\n return reply.code(201).send(post);\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/member/posts/:postId',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'getPost',\n tags,\n summary: 'Read a post',\n description:\n 'For anyone who can open the space while the post is published; for its author in any status; for moderators also while it is pending or removed. Any other post is a 404.',\n params: PostIdParam,\n response: { 200: PostView, ...refusals(403, 404) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return posts.getPost(req.params.postId, actor);\n },\n });\n\n r.route({\n method: 'PATCH',\n url: '/api/member/posts/:postId',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'updatePost',\n tags,\n summary: 'Edit your own post',\n description:\n 'Author only. Changes only the fields sent. 409 when the post is removed, or the topic rules of the space are not met.',\n params: PostIdParam,\n body: UpdatePost,\n response: { 200: PostView, ...refusals(403, 404, 409) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return posts.update(req.params.postId, req.body, actor);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/posts/:postId/submit',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'submitPost',\n tags,\n summary: 'Submit your draft or scheduled post',\n description:\n 'Author only. Publishes it now, or holds it for review when the space requires review and you do not hold `communities:moderate` on the community. A scheduled post is no longer published at its time. 409 when the post is not a draft or scheduled.',\n params: PostIdParam,\n response: { 200: PostView, ...refusals(403, 404, 409) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return posts.submit(req.params.postId, actor);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/posts/:postId/schedule',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'schedulePost',\n tags,\n summary: 'Schedule your post',\n description:\n 'Author only. Schedules a draft, or moves a scheduled post to a new time; the post is submitted at `scheduledAt`. 409 when it is already submitted or removed, or the time is not in the future. 503 when the time could not be set; a draft stays a draft and a moved post keeps its previous time, and `details.postId` names the post.',\n params: PostIdParam,\n body: SchedulePost,\n response: { 200: PostView, ...refusals(403, 404, 409, 503) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return posts.schedule(req.params.postId, req.body.scheduledAt, actor);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/posts/:postId/unschedule',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'unschedulePost',\n tags,\n summary: 'Unschedule your post',\n description:\n 'Author only. The scheduled post becomes a draft and is not submitted at its time. 409 when the post is not scheduled.',\n params: PostIdParam,\n response: { 200: PostView, ...refusals(403, 404, 409) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return posts.unschedule(req.params.postId, actor);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/posts/:postId/approve',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'approvePost',\n tags,\n summary: 'Publish a post that awaits review in a space you moderate',\n description:\n 'For a moderator who can open the space. 409 when the post is not awaiting review.',\n params: PostIdParam,\n response: { 200: PostView, ...refusals(403, 404, 409) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return posts.approve(req.params.postId, null, actor);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/posts/:postId/remove',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'removePost',\n tags,\n summary: 'Remove your post, or one in a space you moderate',\n description:\n \"The author can remove their own post; anyone else needs `communities:moderate` on the community. Takes a published or pending post down; removing someone else's post resolves its open flags as `removed`. 409 when it is already removed or was never submitted.\",\n params: PostIdParam,\n response: { 200: PostView, ...refusals(403, 404, 409) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return posts.remove(req.params.postId, null, actor);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/posts/:postId/restore',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'restorePost',\n tags,\n summary: 'Restore a removed post in a space you moderate',\n description: 'For a moderator who can open the space. 409 when the post is not removed.',\n params: PostIdParam,\n response: { 200: PostView, ...refusals(403, 404, 409) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return posts.restore(req.params.postId, null, actor);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/posts/:postId/pin',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'pinPost',\n tags,\n summary: 'Pin a post in a space you moderate',\n description: 'For a moderator. Pinned posts lead the feeds. 409 when the post is removed.',\n params: PostIdParam,\n response: { 200: PostView, ...refusals(403, 404, 409) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return posts.pin(req.params.postId, actor);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/posts/:postId/unpin',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'unpinPost',\n tags,\n summary: 'Unpin a post in a space you moderate',\n description: 'For a moderator. 409 when the post is removed.',\n params: PostIdParam,\n response: { 200: PostView, ...refusals(403, 404, 409) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return posts.unpin(req.params.postId, actor);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/posts/:postId/comments/close',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'closePostComments',\n tags,\n summary: 'Close comments on a post in a space you moderate',\n description:\n 'For a moderator. Nobody can comment until they are opened again. 409 when the post is removed.',\n params: PostIdParam,\n response: { 200: PostView, ...refusals(403, 404, 409) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return posts.closeComments(req.params.postId, actor);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/posts/:postId/comments/open',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'openPostComments',\n tags,\n summary: 'Open comments on a post in a space you moderate',\n description: 'For a moderator. 409 when the post is removed.',\n params: PostIdParam,\n response: { 200: PostView, ...refusals(403, 404, 409) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return posts.openComments(req.params.postId, actor);\n },\n });\n\n r.route({\n method: 'PUT',\n url: '/api/member/posts/:postId/reactions',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'setPostReactionPolicy',\n tags,\n summary: 'Turn reactions on or off for a post in a space you moderate',\n description:\n \"For a moderator. Overrides the space's reactions setting for this post. 409 when the post is removed.\",\n params: PostIdParam,\n body: SetPostReactions,\n response: { 200: PostView, ...refusals(403, 404, 409) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return posts.setReactions(req.params.postId, req.body.enabled, actor);\n },\n });\n\n r.route({\n method: 'PUT',\n url: '/api/member/posts/:postId/reaction',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'setPostReaction',\n tags,\n summary: 'Set your reaction on a post',\n description:\n 'For anyone who can read the post, while reactions are on for it (403 otherwise). Replaces any reaction you already had and returns the new counts.',\n params: PostIdParam,\n body: SetReaction,\n response: { 200: Reactions, ...refusals(403, 404) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return posts.setReaction(req.params.postId, req.body.emoji, actor);\n },\n });\n\n r.route({\n method: 'DELETE',\n url: '/api/member/posts/:postId/reaction',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'clearPostReaction',\n tags,\n summary: 'Withdraw your reaction from a post',\n description:\n 'For anyone who can read the post, while reactions are on for it (403 otherwise). Returns the new counts.',\n params: PostIdParam,\n response: { 200: Reactions, ...refusals(403, 404) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return posts.setReaction(req.params.postId, null, actor);\n },\n });\n\n r.route({\n method: 'PUT',\n url: '/api/member/posts/:postId/subscription',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'setPostSubscription',\n tags,\n summary: 'Follow or mute a post, or clear either',\n description:\n 'For anyone who can read the post. `following` notifies you of its new comments. `muted` stops its activity notifying you, until `mutedUntil` when given; mentions and actions on you still notify. `none` clears both.',\n params: PostIdParam,\n body: SetPostSubscription,\n response: { 204: z.void(), ...refusals(403, 404) },\n },\n handler: async (req, reply) => {\n const actor = await resolveActor(container, req);\n await container.subscriptions.setPost(req.params.postId, req.body, actor);\n return reply.code(204).send();\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/posts/:postId/bookmark',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'bookmarkPost',\n tags,\n summary: 'Bookmark a post',\n description: 'For anyone who can read the post. Bookmarking twice is harmless.',\n params: PostIdParam,\n response: { 204: z.void(), ...refusals(403, 404) },\n },\n handler: async (req, reply) => {\n const actor = await resolveActor(container, req);\n await posts.bookmark(req.params.postId, actor);\n return reply.code(204).send();\n },\n });\n\n r.route({\n method: 'DELETE',\n url: '/api/member/posts/:postId/bookmark',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'unbookmarkPost',\n tags,\n summary: 'Remove a bookmark',\n description: 'For anyone who can read the post. Harmless when you have not bookmarked it.',\n params: PostIdParam,\n response: { 204: z.void(), ...refusals(403, 404) },\n },\n handler: async (req, reply) => {\n const actor = await resolveActor(container, req);\n await posts.unbookmark(req.params.postId, actor);\n return reply.code(204).send();\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/posts/:postId/flags',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'flagPost',\n tags,\n summary: 'Flag a post for the moderators',\n description:\n 'For anyone who can read the post. Flagging it again while your flag is open returns that flag.',\n params: PostIdParam,\n body: FlagReason,\n response: { 201: PostFlag, ...refusals(403, 404) },\n },\n handler: async (req, reply) => {\n const actor = await resolveActor(container, req);\n const flag = await posts.flag(req.params.postId, req.body.reason, actor);\n return reply.code(201).send(flag);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/posts/:postId/flags/resolve',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'resolvePostFlags',\n tags,\n summary: 'Dismiss the open flags on a post in a space you moderate',\n description:\n 'For a moderator who can open the space. Closes every open flag and leaves the post up.',\n params: PostIdParam,\n body: ResolvePostFlags,\n response: { 204: z.void(), ...refusals(403, 404) },\n },\n handler: async (req, reply) => {\n const actor = await resolveActor(container, req);\n await posts.resolveFlags(req.params.postId, req.body.resolution, null, actor);\n return reply.code(204).send();\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/member/posts/:postId/comments',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'listPostComments',\n tags,\n summary: \"Read a post's comments\",\n description:\n 'For anyone who can read the post. Pages by top-level comment, oldest first. Each page carries its top-level comments and all of their replies; `total` counts top-level comments.',\n params: PostIdParam,\n querystring: PageQuery,\n response: { 200: PostCommentsPage, ...refusals(403, 404) },\n },\n handler: async (req) => {\n const actor = await resolveActor(container, req);\n return container.discussion.postComments(req.params.postId, req.query, actor);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/posts/:postId/comments',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'createPostComment',\n tags,\n summary: 'Comment on a post',\n description:\n 'For anyone who can read the post, while its comments are open (403 otherwise). Replies nest one level. 409 when the post is not published.',\n params: PostIdParam,\n body: PostComment,\n response: { 201: CommentView, ...refusals(403, 404, 409) },\n },\n handler: async (req, reply) => {\n const actor = await resolveActor(container, req);\n const comment = await container.discussion.postComment(\n { postId: req.params.postId, parentId: req.body.parentId, body: req.body.body },\n actor,\n );\n return reply.code(201).send(comment);\n },\n });\n}\n"],"mappings":"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"}
|