@headless-lms/server 0.1.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/LICENSE +21 -0
- package/README.md +48 -0
- package/dist/app/container.d.ts +124 -0
- package/dist/app/container.js +312 -0
- package/dist/app/container.js.map +1 -0
- package/dist/app/db.d.ts +2 -0
- package/dist/app/db.js +2 -0
- package/dist/app/integrations.d.ts +7 -0
- package/dist/app/integrations.js +44 -0
- package/dist/app/integrations.js.map +1 -0
- package/dist/app/notifications.d.ts +7 -0
- package/dist/app/notifications.js +23 -0
- package/dist/app/notifications.js.map +1 -0
- package/dist/http/config.d.ts +25 -0
- package/dist/http/config.js +1 -0
- package/dist/http/fastify.d.ts +35 -0
- package/dist/http/plugins/auth.d.ts +11 -0
- package/dist/http/plugins/auth.js +47 -0
- package/dist/http/plugins/auth.js.map +1 -0
- package/dist/http/plugins/cors.d.ts +7 -0
- package/dist/http/plugins/cors.js +22 -0
- package/dist/http/plugins/cors.js.map +1 -0
- package/dist/http/plugins/error-handler.d.ts +6 -0
- package/dist/http/plugins/error-handler.js +64 -0
- package/dist/http/plugins/error-handler.js.map +1 -0
- package/dist/http/plugins/openapi.d.ts +7 -0
- package/dist/http/plugins/openapi.js +63 -0
- package/dist/http/plugins/openapi.js.map +1 -0
- package/dist/http/routes/activities.d.ts +7 -0
- package/dist/http/routes/activities.js +163 -0
- package/dist/http/routes/activities.js.map +1 -0
- package/dist/http/routes/assets.d.ts +7 -0
- package/dist/http/routes/assets.js +168 -0
- package/dist/http/routes/assets.js.map +1 -0
- package/dist/http/routes/automations.d.ts +7 -0
- package/dist/http/routes/automations.js +158 -0
- package/dist/http/routes/automations.js.map +1 -0
- package/dist/http/routes/courses.d.ts +7 -0
- package/dist/http/routes/courses.js +130 -0
- package/dist/http/routes/courses.js.map +1 -0
- package/dist/http/routes/dashboard.d.ts +7 -0
- package/dist/http/routes/dashboard.js +42 -0
- package/dist/http/routes/dashboard.js.map +1 -0
- package/dist/http/routes/discussion.d.ts +7 -0
- package/dist/http/routes/discussion.js +122 -0
- package/dist/http/routes/discussion.js.map +1 -0
- package/dist/http/routes/downloads.d.ts +7 -0
- package/dist/http/routes/downloads.js +208 -0
- package/dist/http/routes/downloads.js.map +1 -0
- package/dist/http/routes/entitlements.d.ts +7 -0
- package/dist/http/routes/entitlements.js +69 -0
- package/dist/http/routes/entitlements.js.map +1 -0
- package/dist/http/routes/identity.d.ts +6 -0
- package/dist/http/routes/identity.js +6 -0
- package/dist/http/routes/identity.js.map +1 -0
- package/dist/http/routes/integrations.d.ts +7 -0
- package/dist/http/routes/integrations.js +210 -0
- package/dist/http/routes/integrations.js.map +1 -0
- package/dist/http/routes/learn/assets.d.ts +8 -0
- package/dist/http/routes/learn/assets.js +32 -0
- package/dist/http/routes/learn/assets.js.map +1 -0
- package/dist/http/routes/learn/comments.d.ts +7 -0
- package/dist/http/routes/learn/comments.js +175 -0
- package/dist/http/routes/learn/comments.js.map +1 -0
- package/dist/http/routes/learn/courses.d.ts +7 -0
- package/dist/http/routes/learn/courses.js +75 -0
- package/dist/http/routes/learn/courses.js.map +1 -0
- package/dist/http/routes/learn/downloads.d.ts +7 -0
- package/dist/http/routes/learn/downloads.js +76 -0
- package/dist/http/routes/learn/downloads.js.map +1 -0
- package/dist/http/routes/learn/index.d.ts +7 -0
- package/dist/http/routes/learn/index.js +19 -0
- package/dist/http/routes/learn/index.js.map +1 -0
- package/dist/http/routes/learn/org.d.ts +7 -0
- package/dist/http/routes/learn/org.js +50 -0
- package/dist/http/routes/learn/org.js.map +1 -0
- package/dist/http/routes/learn/progress.d.ts +7 -0
- package/dist/http/routes/learn/progress.js +63 -0
- package/dist/http/routes/learn/progress.js.map +1 -0
- package/dist/http/routes/organizations.d.ts +7 -0
- package/dist/http/routes/organizations.js +219 -0
- package/dist/http/routes/organizations.js.map +1 -0
- package/dist/http/routes/progress.d.ts +6 -0
- package/dist/http/routes/progress.js +6 -0
- package/dist/http/routes/progress.js.map +1 -0
- package/dist/http/routes/students.d.ts +7 -0
- package/dist/http/routes/students.js +125 -0
- package/dist/http/routes/students.js.map +1 -0
- package/dist/http/routes.d.ts +7 -0
- package/dist/http/routes.js +37 -0
- package/dist/http/routes.js.map +1 -0
- package/dist/http/schemas/activities.d.ts +69 -0
- package/dist/http/schemas/activities.js +25 -0
- package/dist/http/schemas/activities.js.map +1 -0
- package/dist/http/schemas/assets.d.ts +142 -0
- package/dist/http/schemas/assets.js +24 -0
- package/dist/http/schemas/assets.js.map +1 -0
- package/dist/http/schemas/automations.d.ts +154 -0
- package/dist/http/schemas/automations.js +26 -0
- package/dist/http/schemas/automations.js.map +1 -0
- package/dist/http/schemas/content.d.ts +113 -0
- package/dist/http/schemas/content.js +29 -0
- package/dist/http/schemas/content.js.map +1 -0
- package/dist/http/schemas/dashboard.d.ts +26 -0
- package/dist/http/schemas/dashboard.js +18 -0
- package/dist/http/schemas/dashboard.js.map +1 -0
- package/dist/http/schemas/discussion.d.ts +340 -0
- package/dist/http/schemas/discussion.js +78 -0
- package/dist/http/schemas/discussion.js.map +1 -0
- package/dist/http/schemas/downloads.d.ts +110 -0
- package/dist/http/schemas/downloads.js +34 -0
- package/dist/http/schemas/downloads.js.map +1 -0
- package/dist/http/schemas/entitlements.d.ts +97 -0
- package/dist/http/schemas/entitlements.js +41 -0
- package/dist/http/schemas/entitlements.js.map +1 -0
- package/dist/http/schemas/index.d.ts +17 -0
- package/dist/http/schemas/index.js +17 -0
- package/dist/http/schemas/integrations.d.ts +93 -0
- package/dist/http/schemas/integrations.js +47 -0
- package/dist/http/schemas/integrations.js.map +1 -0
- package/dist/http/schemas/invites.d.ts +95 -0
- package/dist/http/schemas/invites.js +62 -0
- package/dist/http/schemas/invites.js.map +1 -0
- package/dist/http/schemas/learn.d.ts +142 -0
- package/dist/http/schemas/learn.js +58 -0
- package/dist/http/schemas/learn.js.map +1 -0
- package/dist/http/schemas/members.d.ts +88 -0
- package/dist/http/schemas/members.js +27 -0
- package/dist/http/schemas/members.js.map +1 -0
- package/dist/http/schemas/organizations.d.ts +22 -0
- package/dist/http/schemas/organizations.js +20 -0
- package/dist/http/schemas/organizations.js.map +1 -0
- package/dist/http/schemas/settings.d.ts +23 -0
- package/dist/http/schemas/settings.js +20 -0
- package/dist/http/schemas/settings.js.map +1 -0
- package/dist/http/schemas/shared.d.ts +57 -0
- package/dist/http/schemas/shared.js +54 -0
- package/dist/http/schemas/shared.js.map +1 -0
- package/dist/http/schemas/students.d.ts +64 -0
- package/dist/http/schemas/students.js +25 -0
- package/dist/http/schemas/students.js.map +1 -0
- package/dist/http/scope.d.ts +22 -0
- package/dist/http/scope.js +28 -0
- package/dist/http/scope.js.map +1 -0
- package/dist/http/server.d.ts +8 -0
- package/dist/http/server.js +33 -0
- package/dist/http/server.js.map +1 -0
- package/dist/http/web-bridge.d.ts +9 -0
- package/dist/http/web-bridge.js +27 -0
- package/dist/http/web-bridge.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/package.json +56 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { ErrorBody } from "../schemas/shared.js";
|
|
2
|
+
import { Comment, CommentIdParam, CommentView, CommentsPage, CommentsQuery, PatchComment, ReplyToComment } from "../schemas/discussion.js";
|
|
3
|
+
import "../schemas/index.js";
|
|
4
|
+
import { NotFoundError } from "@headless-lms/core/shared/errors";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
//#region src/http/routes/discussion.ts
|
|
7
|
+
async function discussionRoutes(app, container) {
|
|
8
|
+
const r = app.withTypeProvider();
|
|
9
|
+
const discussion = container.discussion;
|
|
10
|
+
r.route({
|
|
11
|
+
method: "GET",
|
|
12
|
+
url: "/api/comments",
|
|
13
|
+
preHandler: app.requireOrgSession,
|
|
14
|
+
schema: {
|
|
15
|
+
operationId: "listComments",
|
|
16
|
+
tags: ["Discussion"],
|
|
17
|
+
summary: "List comments, filtered by course, activity, author, status or reports",
|
|
18
|
+
querystring: CommentsQuery,
|
|
19
|
+
response: { 200: CommentsPage }
|
|
20
|
+
},
|
|
21
|
+
handler: async (req) => {
|
|
22
|
+
return discussion.listComments(req.orgId, req.query);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
r.route({
|
|
26
|
+
method: "DELETE",
|
|
27
|
+
url: "/api/comments/:commentId",
|
|
28
|
+
preHandler: app.requireOrgSession,
|
|
29
|
+
schema: {
|
|
30
|
+
operationId: "moderateRemoveComment",
|
|
31
|
+
tags: ["Discussion"],
|
|
32
|
+
summary: "Remove a comment as a moderator",
|
|
33
|
+
params: CommentIdParam,
|
|
34
|
+
response: {
|
|
35
|
+
200: Comment,
|
|
36
|
+
403: ErrorBody,
|
|
37
|
+
404: ErrorBody
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
handler: async (req) => {
|
|
41
|
+
const orgUser = await container.organizations.getOrgUser(req.orgId, req.userId);
|
|
42
|
+
return discussion.remove(req.orgId, req.params.commentId, orgUser);
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
r.route({
|
|
46
|
+
method: "PATCH",
|
|
47
|
+
url: "/api/comments/:commentId",
|
|
48
|
+
preHandler: app.requireOrgSession,
|
|
49
|
+
schema: {
|
|
50
|
+
operationId: "editComment",
|
|
51
|
+
tags: ["Discussion"],
|
|
52
|
+
summary: "Publish a comment: approves a pending one, restores a removed one",
|
|
53
|
+
params: CommentIdParam,
|
|
54
|
+
body: PatchComment,
|
|
55
|
+
response: {
|
|
56
|
+
200: Comment,
|
|
57
|
+
403: ErrorBody,
|
|
58
|
+
404: ErrorBody
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
handler: async (req) => {
|
|
62
|
+
const orgUser = await container.organizations.getOrgUser(req.orgId, req.userId);
|
|
63
|
+
if (!orgUser) throw new NotFoundError("OrgUser", req.userId);
|
|
64
|
+
return discussion.publish(req.orgId, req.params.commentId, orgUser);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
r.route({
|
|
68
|
+
method: "DELETE",
|
|
69
|
+
url: "/api/comments/:commentId/reports",
|
|
70
|
+
preHandler: app.requireOrgSession,
|
|
71
|
+
schema: {
|
|
72
|
+
operationId: "dismissCommentReports",
|
|
73
|
+
tags: ["Discussion"],
|
|
74
|
+
summary: "Dismiss every open report on a comment",
|
|
75
|
+
params: CommentIdParam,
|
|
76
|
+
response: {
|
|
77
|
+
204: z.void(),
|
|
78
|
+
403: ErrorBody,
|
|
79
|
+
404: ErrorBody
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
handler: async (req, reply) => {
|
|
83
|
+
const orgUser = await container.organizations.getOrgUser(req.orgId, req.userId);
|
|
84
|
+
if (!orgUser) throw new NotFoundError("OrgUser", req.userId);
|
|
85
|
+
await discussion.resolveReports(req.orgId, req.params.commentId, orgUser);
|
|
86
|
+
return reply.code(204).send();
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
r.route({
|
|
90
|
+
method: "POST",
|
|
91
|
+
url: "/api/comments/:commentId/replies",
|
|
92
|
+
preHandler: app.requireOrgSession,
|
|
93
|
+
schema: {
|
|
94
|
+
operationId: "replyToComment",
|
|
95
|
+
tags: ["Discussion"],
|
|
96
|
+
summary: "Reply to a comment from the moderation queue",
|
|
97
|
+
params: CommentIdParam,
|
|
98
|
+
body: ReplyToComment,
|
|
99
|
+
response: {
|
|
100
|
+
200: CommentView,
|
|
101
|
+
403: ErrorBody,
|
|
102
|
+
404: ErrorBody
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
handler: async (req) => {
|
|
106
|
+
const orgUser = await container.organizations.getOrgUser(req.orgId, req.userId);
|
|
107
|
+
if (!orgUser) throw new NotFoundError("OrgUser", req.userId);
|
|
108
|
+
const parent = await discussion.getComment(req.orgId, req.params.commentId);
|
|
109
|
+
if (!parent) throw new NotFoundError("Comment", req.params.commentId);
|
|
110
|
+
return discussion.postComment(req.orgId, {
|
|
111
|
+
actor: orgUser,
|
|
112
|
+
activityId: parent.activityId,
|
|
113
|
+
parentId: parent.parentId ?? parent.id,
|
|
114
|
+
body: req.body.body
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
//#endregion
|
|
120
|
+
export { discussionRoutes };
|
|
121
|
+
|
|
122
|
+
//# sourceMappingURL=discussion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discussion.js","names":[],"sources":["../../../src/http/routes/discussion.ts"],"sourcesContent":["// Moderator-facing discussion routes. The learner surface (everything under\n// `/api/learn`) lives in routes/learn/comments.ts.\nimport type { FastifyInstance } from 'fastify';\nimport type { ZodTypeProvider } from 'fastify-type-provider-zod';\nimport { z } from 'zod';\nimport {\n Comment,\n CommentIdParam,\n CommentsPage,\n CommentsQuery,\n CommentView,\n ErrorBody,\n PatchComment,\n ReplyToComment,\n} from '../schemas/index.js';\nimport { NotFoundError } from '@headless-lms/core/shared/errors';\nimport type { Container } from '../../app/container.js';\n\nexport async function discussionRoutes(app: FastifyInstance, container: Container): Promise<void> {\n const r = app.withTypeProvider<ZodTypeProvider>();\n const discussion = container.discussion;\n\n r.route({\n method: 'GET',\n url: '/api/comments',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'listComments',\n tags: ['Discussion'],\n summary: 'List comments, filtered by course, activity, author, status or reports',\n querystring: CommentsQuery,\n response: { 200: CommentsPage },\n },\n handler: async (req) => {\n return discussion.listComments(req.orgId, req.query);\n },\n });\n\n r.route({\n method: 'DELETE',\n url: '/api/comments/:commentId',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'moderateRemoveComment',\n tags: ['Discussion'],\n summary: 'Remove a comment as a moderator',\n params: CommentIdParam,\n response: { 200: Comment, 403: ErrorBody, 404: ErrorBody },\n },\n handler: async (req) => {\n const orgUser = await container.organizations.getOrgUser(req.orgId, req.userId);\n return discussion.remove(req.orgId, req.params.commentId, orgUser!);\n },\n });\n\n r.route({\n method: 'PATCH',\n url: '/api/comments/:commentId',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'editComment',\n tags: ['Discussion'],\n summary: 'Publish a comment: approves a pending one, restores a removed one',\n params: CommentIdParam,\n body: PatchComment,\n response: { 200: Comment, 403: ErrorBody, 404: ErrorBody },\n },\n handler: async (req) => {\n const orgUser = await container.organizations.getOrgUser(req.orgId, req.userId);\n if (!orgUser) {\n throw new NotFoundError('OrgUser', req.userId);\n }\n return discussion.publish(req.orgId, req.params.commentId, orgUser);\n },\n });\n\n r.route({\n method: 'DELETE',\n url: '/api/comments/:commentId/reports',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'dismissCommentReports',\n tags: ['Discussion'],\n summary: 'Dismiss every open report on a comment',\n params: CommentIdParam,\n response: { 204: z.void(), 403: ErrorBody, 404: ErrorBody },\n },\n handler: async (req, reply) => {\n const orgUser = await container.organizations.getOrgUser(req.orgId, req.userId);\n if (!orgUser) {\n throw new NotFoundError('OrgUser', req.userId);\n }\n await discussion.resolveReports(req.orgId, req.params.commentId, orgUser);\n return reply.code(204).send();\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/comments/:commentId/replies',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'replyToComment',\n tags: ['Discussion'],\n summary: 'Reply to a comment from the moderation queue',\n params: CommentIdParam,\n body: ReplyToComment,\n response: { 200: CommentView, 403: ErrorBody, 404: ErrorBody },\n },\n handler: async (req) => {\n const orgUser = await container.organizations.getOrgUser(req.orgId, req.userId);\n if (!orgUser) {\n throw new NotFoundError('OrgUser', req.userId);\n }\n const parent = await discussion.getComment(req.orgId, req.params.commentId);\n if (!parent) {\n throw new NotFoundError('Comment', req.params.commentId);\n }\n // Replies nest one level: answering a reply attaches to its root.\n return discussion.postComment(req.orgId, {\n actor: orgUser,\n activityId: parent.activityId,\n parentId: parent.parentId ?? parent.id,\n body: req.body.body,\n });\n },\n });\n}\n"],"mappings":";;;;;;AAkBA,eAAsB,iBAAiB,KAAsB,WAAqC;CAChG,MAAM,IAAI,IAAI,iBAAkC;CAChD,MAAM,aAAa,UAAU;CAE7B,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,YAAY;GACnB,SAAS;GACT,aAAa;GACb,UAAU,EAAE,KAAK,aAAa;EAChC;EACA,SAAS,OAAO,QAAQ;GACtB,OAAO,WAAW,aAAa,IAAI,OAAO,IAAI,KAAK;EACrD;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,YAAY;GACnB,SAAS;GACT,QAAQ;GACR,UAAU;IAAE,KAAK;IAAS,KAAK;IAAW,KAAK;GAAU;EAC3D;EACA,SAAS,OAAO,QAAQ;GACtB,MAAM,UAAU,MAAM,UAAU,cAAc,WAAW,IAAI,OAAO,IAAI,MAAM;GAC9E,OAAO,WAAW,OAAO,IAAI,OAAO,IAAI,OAAO,WAAW,OAAQ;EACpE;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,YAAY;GACnB,SAAS;GACT,QAAQ;GACR,MAAM;GACN,UAAU;IAAE,KAAK;IAAS,KAAK;IAAW,KAAK;GAAU;EAC3D;EACA,SAAS,OAAO,QAAQ;GACtB,MAAM,UAAU,MAAM,UAAU,cAAc,WAAW,IAAI,OAAO,IAAI,MAAM;GAC9E,IAAI,CAAC,SACH,MAAM,IAAI,cAAc,WAAW,IAAI,MAAM;GAE/C,OAAO,WAAW,QAAQ,IAAI,OAAO,IAAI,OAAO,WAAW,OAAO;EACpE;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,YAAY;GACnB,SAAS;GACT,QAAQ;GACR,UAAU;IAAE,KAAK,EAAE,KAAK;IAAG,KAAK;IAAW,KAAK;GAAU;EAC5D;EACA,SAAS,OAAO,KAAK,UAAU;GAC7B,MAAM,UAAU,MAAM,UAAU,cAAc,WAAW,IAAI,OAAO,IAAI,MAAM;GAC9E,IAAI,CAAC,SACH,MAAM,IAAI,cAAc,WAAW,IAAI,MAAM;GAE/C,MAAM,WAAW,eAAe,IAAI,OAAO,IAAI,OAAO,WAAW,OAAO;GACxE,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,MAAM,CAAC,YAAY;GACnB,SAAS;GACT,QAAQ;GACR,MAAM;GACN,UAAU;IAAE,KAAK;IAAa,KAAK;IAAW,KAAK;GAAU;EAC/D;EACA,SAAS,OAAO,QAAQ;GACtB,MAAM,UAAU,MAAM,UAAU,cAAc,WAAW,IAAI,OAAO,IAAI,MAAM;GAC9E,IAAI,CAAC,SACH,MAAM,IAAI,cAAc,WAAW,IAAI,MAAM;GAE/C,MAAM,SAAS,MAAM,WAAW,WAAW,IAAI,OAAO,IAAI,OAAO,SAAS;GAC1E,IAAI,CAAC,QACH,MAAM,IAAI,cAAc,WAAW,IAAI,OAAO,SAAS;GAGzD,OAAO,WAAW,YAAY,IAAI,OAAO;IACvC,OAAO;IACP,YAAY,OAAO;IACnB,UAAU,OAAO,YAAY,OAAO;IACpC,MAAM,IAAI,KAAK;GACjB,CAAC;EACH;CACF,CAAC;AACH"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Container } from "../../app/container.js";
|
|
2
|
+
import { FastifyInstance } from "fastify";
|
|
3
|
+
//#region src/http/routes/downloads.d.ts
|
|
4
|
+
declare function downloadsRoutes(app: FastifyInstance, container: Container): Promise<void>;
|
|
5
|
+
//#endregion
|
|
6
|
+
export { downloadsRoutes };
|
|
7
|
+
//# sourceMappingURL=downloads.d.ts.map
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { resolveScope } from "../scope.js";
|
|
2
|
+
import { ErrorBody } from "../schemas/shared.js";
|
|
3
|
+
import { AddDownloadAsset, CreateDownload, Download, DownloadAsset, DownloadAssetParams, DownloadIdParam, DownloadsPage, DownloadsQuery, RenameDownloadAsset, ReorderDownloadAssets, UpdateDownload } from "../schemas/downloads.js";
|
|
4
|
+
import "../schemas/index.js";
|
|
5
|
+
import { NotFoundError } from "@headless-lms/core/shared/errors";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
//#region src/http/routes/downloads.ts
|
|
8
|
+
async function downloadsRoutes(app, container) {
|
|
9
|
+
const r = app.withTypeProvider();
|
|
10
|
+
const content = container.content;
|
|
11
|
+
r.route({
|
|
12
|
+
method: "GET",
|
|
13
|
+
url: "/api/downloads",
|
|
14
|
+
preHandler: app.requireOrgSession,
|
|
15
|
+
schema: {
|
|
16
|
+
operationId: "listDownloads",
|
|
17
|
+
tags: ["Downloads"],
|
|
18
|
+
summary: "List downloads",
|
|
19
|
+
querystring: DownloadsQuery,
|
|
20
|
+
response: { 200: DownloadsPage }
|
|
21
|
+
},
|
|
22
|
+
handler: async (req) => {
|
|
23
|
+
const scope = await resolveScope(container, req);
|
|
24
|
+
return content.listDownloads(scope.orgId, req.query);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
r.route({
|
|
28
|
+
method: "GET",
|
|
29
|
+
url: "/api/downloads/:downloadId",
|
|
30
|
+
preHandler: app.requireOrgSession,
|
|
31
|
+
schema: {
|
|
32
|
+
operationId: "getDownload",
|
|
33
|
+
tags: ["Downloads"],
|
|
34
|
+
summary: "Get a download by id",
|
|
35
|
+
params: DownloadIdParam,
|
|
36
|
+
response: {
|
|
37
|
+
200: Download,
|
|
38
|
+
404: ErrorBody
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
handler: async (req) => {
|
|
42
|
+
const scope = await resolveScope(container, req);
|
|
43
|
+
const download = await content.getDownload(scope.orgId, req.params.downloadId);
|
|
44
|
+
if (!download) throw new NotFoundError("Download", req.params.downloadId);
|
|
45
|
+
return download;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
r.route({
|
|
49
|
+
method: "POST",
|
|
50
|
+
url: "/api/downloads",
|
|
51
|
+
preHandler: app.requireOrgSession,
|
|
52
|
+
schema: {
|
|
53
|
+
operationId: "createDownload",
|
|
54
|
+
tags: ["Downloads"],
|
|
55
|
+
summary: "Create a download",
|
|
56
|
+
body: CreateDownload,
|
|
57
|
+
response: { 201: Download }
|
|
58
|
+
},
|
|
59
|
+
handler: async (req, reply) => {
|
|
60
|
+
const scope = await resolveScope(container, req);
|
|
61
|
+
const download = await content.createDownload(scope.orgId, req.body);
|
|
62
|
+
return reply.code(201).send(download);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
r.route({
|
|
66
|
+
method: "PATCH",
|
|
67
|
+
url: "/api/downloads/:downloadId",
|
|
68
|
+
preHandler: app.requireOrgSession,
|
|
69
|
+
schema: {
|
|
70
|
+
operationId: "updateDownload",
|
|
71
|
+
tags: ["Downloads"],
|
|
72
|
+
summary: "Update a download",
|
|
73
|
+
params: DownloadIdParam,
|
|
74
|
+
body: UpdateDownload,
|
|
75
|
+
response: {
|
|
76
|
+
200: Download,
|
|
77
|
+
404: ErrorBody
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
handler: async (req) => {
|
|
81
|
+
const scope = await resolveScope(container, req);
|
|
82
|
+
return content.updateDownload(scope.orgId, req.params.downloadId, req.body);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
r.route({
|
|
86
|
+
method: "DELETE",
|
|
87
|
+
url: "/api/downloads/:downloadId",
|
|
88
|
+
preHandler: app.requireOrgSession,
|
|
89
|
+
schema: {
|
|
90
|
+
operationId: "deleteDownload",
|
|
91
|
+
tags: ["Downloads"],
|
|
92
|
+
summary: "Delete a download",
|
|
93
|
+
params: DownloadIdParam,
|
|
94
|
+
response: {
|
|
95
|
+
204: z.void(),
|
|
96
|
+
404: ErrorBody
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
handler: async (req, reply) => {
|
|
100
|
+
const scope = await resolveScope(container, req);
|
|
101
|
+
await content.removeDownload(scope.orgId, req.params.downloadId);
|
|
102
|
+
return reply.code(204).send();
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
r.route({
|
|
106
|
+
method: "GET",
|
|
107
|
+
url: "/api/downloads/:downloadId/assets",
|
|
108
|
+
preHandler: app.requireOrgSession,
|
|
109
|
+
schema: {
|
|
110
|
+
operationId: "listDownloadAssets",
|
|
111
|
+
tags: ["Downloads"],
|
|
112
|
+
summary: "List a download's assets in order",
|
|
113
|
+
params: DownloadIdParam,
|
|
114
|
+
response: {
|
|
115
|
+
200: z.array(DownloadAsset),
|
|
116
|
+
404: ErrorBody
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
handler: async (req) => {
|
|
120
|
+
const scope = await resolveScope(container, req);
|
|
121
|
+
return content.listDownloadAssets(scope.orgId, req.params.downloadId);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
r.route({
|
|
125
|
+
method: "POST",
|
|
126
|
+
url: "/api/downloads/:downloadId/assets",
|
|
127
|
+
preHandler: app.requireOrgSession,
|
|
128
|
+
schema: {
|
|
129
|
+
operationId: "addDownloadAsset",
|
|
130
|
+
tags: ["Downloads"],
|
|
131
|
+
summary: "Link a media-library asset to a download",
|
|
132
|
+
params: DownloadIdParam,
|
|
133
|
+
body: AddDownloadAsset,
|
|
134
|
+
response: {
|
|
135
|
+
200: z.array(DownloadAsset),
|
|
136
|
+
404: ErrorBody
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
handler: async (req) => {
|
|
140
|
+
const scope = await resolveScope(container, req);
|
|
141
|
+
return content.addDownloadAsset(scope.orgId, req.params.downloadId, req.body);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
r.route({
|
|
145
|
+
method: "PUT",
|
|
146
|
+
url: "/api/downloads/:downloadId/assets/order",
|
|
147
|
+
preHandler: app.requireOrgSession,
|
|
148
|
+
schema: {
|
|
149
|
+
operationId: "reorderDownloadAssets",
|
|
150
|
+
tags: ["Downloads"],
|
|
151
|
+
summary: "Reorder a download's assets (send the complete set)",
|
|
152
|
+
params: DownloadIdParam,
|
|
153
|
+
body: ReorderDownloadAssets,
|
|
154
|
+
response: {
|
|
155
|
+
200: z.array(DownloadAsset),
|
|
156
|
+
404: ErrorBody,
|
|
157
|
+
409: ErrorBody
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
handler: async (req) => {
|
|
161
|
+
const scope = await resolveScope(container, req);
|
|
162
|
+
return content.reorderDownloadAssets(scope.orgId, req.params.downloadId, req.body.assetIds);
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
r.route({
|
|
166
|
+
method: "PATCH",
|
|
167
|
+
url: "/api/downloads/:downloadId/assets/:assetId",
|
|
168
|
+
preHandler: app.requireOrgSession,
|
|
169
|
+
schema: {
|
|
170
|
+
operationId: "renameDownloadAsset",
|
|
171
|
+
tags: ["Downloads"],
|
|
172
|
+
summary: "Set an asset's display name within a download",
|
|
173
|
+
params: DownloadAssetParams,
|
|
174
|
+
body: RenameDownloadAsset,
|
|
175
|
+
response: {
|
|
176
|
+
200: z.array(DownloadAsset),
|
|
177
|
+
404: ErrorBody
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
handler: async (req) => {
|
|
181
|
+
const scope = await resolveScope(container, req);
|
|
182
|
+
return content.renameDownloadAsset(scope.orgId, req.params.downloadId, req.params.assetId, req.body.displayName);
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
r.route({
|
|
186
|
+
method: "DELETE",
|
|
187
|
+
url: "/api/downloads/:downloadId/assets/:assetId",
|
|
188
|
+
preHandler: app.requireOrgSession,
|
|
189
|
+
schema: {
|
|
190
|
+
operationId: "removeDownloadAsset",
|
|
191
|
+
tags: ["Downloads"],
|
|
192
|
+
summary: "Unlink an asset from a download (the asset itself survives)",
|
|
193
|
+
params: DownloadAssetParams,
|
|
194
|
+
response: {
|
|
195
|
+
200: z.array(DownloadAsset),
|
|
196
|
+
404: ErrorBody
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
handler: async (req) => {
|
|
200
|
+
const scope = await resolveScope(container, req);
|
|
201
|
+
return content.removeDownloadAsset(scope.orgId, req.params.downloadId, req.params.assetId);
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
//#endregion
|
|
206
|
+
export { downloadsRoutes };
|
|
207
|
+
|
|
208
|
+
//# sourceMappingURL=downloads.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"downloads.js","names":[],"sources":["../../../src/http/routes/downloads.ts"],"sourcesContent":["// HTTP routes for the download content type. Request + response are validated\n// against the shared contract schemas by the Zod type provider, and\n// @fastify/swagger reads the same schemas to build the OpenAPI spec.\nimport type { FastifyInstance } from 'fastify';\nimport type { ZodTypeProvider } from 'fastify-type-provider-zod';\nimport {\n AddDownloadAsset,\n Download,\n DownloadAsset,\n DownloadAssetParams,\n DownloadIdParam,\n DownloadsPage,\n DownloadsQuery,\n CreateDownload,\n ErrorBody,\n RenameDownloadAsset,\n ReorderDownloadAssets,\n UpdateDownload,\n} from '../schemas/index.js';\nimport { z } from 'zod';\nimport type { Container } from '../../app/container.js';\nimport { NotFoundError } from '@headless-lms/core/shared/errors';\nimport { resolveScope } from '../scope.js';\n\nexport async function downloadsRoutes(app: FastifyInstance, container: Container): Promise<void> {\n const r = app.withTypeProvider<ZodTypeProvider>();\n const content = container.content;\n\n r.route({\n method: 'GET',\n url: '/api/downloads',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'listDownloads',\n tags: ['Downloads'],\n summary: 'List downloads',\n querystring: DownloadsQuery,\n response: { 200: DownloadsPage },\n },\n handler: async (req) => {\n const scope = await resolveScope(container, req);\n return content.listDownloads(scope.orgId, req.query);\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/downloads/:downloadId',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'getDownload',\n tags: ['Downloads'],\n summary: 'Get a download by id',\n params: DownloadIdParam,\n response: { 200: Download, 404: ErrorBody },\n },\n handler: async (req) => {\n const scope = await resolveScope(container, req);\n const download = await content.getDownload(scope.orgId, req.params.downloadId);\n if (!download) {\n throw new NotFoundError('Download', req.params.downloadId);\n }\n return download;\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/downloads',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'createDownload',\n tags: ['Downloads'],\n summary: 'Create a download',\n body: CreateDownload,\n response: { 201: Download },\n },\n handler: async (req, reply) => {\n const scope = await resolveScope(container, req);\n const download = await content.createDownload(scope.orgId, req.body);\n return reply.code(201).send(download);\n },\n });\n\n r.route({\n method: 'PATCH',\n url: '/api/downloads/:downloadId',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'updateDownload',\n tags: ['Downloads'],\n summary: 'Update a download',\n params: DownloadIdParam,\n body: UpdateDownload,\n response: { 200: Download, 404: ErrorBody },\n },\n handler: async (req) => {\n const scope = await resolveScope(container, req);\n return content.updateDownload(scope.orgId, req.params.downloadId, req.body);\n },\n });\n\n r.route({\n method: 'DELETE',\n url: '/api/downloads/:downloadId',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'deleteDownload',\n tags: ['Downloads'],\n summary: 'Delete a download',\n params: DownloadIdParam,\n response: { 204: z.void(), 404: ErrorBody },\n },\n handler: async (req, reply) => {\n const scope = await resolveScope(container, req);\n await content.removeDownload(scope.orgId, req.params.downloadId);\n return reply.code(204).send();\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/downloads/:downloadId/assets',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'listDownloadAssets',\n tags: ['Downloads'],\n summary: \"List a download's assets in order\",\n params: DownloadIdParam,\n response: { 200: z.array(DownloadAsset), 404: ErrorBody },\n },\n handler: async (req) => {\n const scope = await resolveScope(container, req);\n return content.listDownloadAssets(scope.orgId, req.params.downloadId);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/downloads/:downloadId/assets',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'addDownloadAsset',\n tags: ['Downloads'],\n summary: 'Link a media-library asset to a download',\n params: DownloadIdParam,\n body: AddDownloadAsset,\n response: { 200: z.array(DownloadAsset), 404: ErrorBody },\n },\n handler: async (req) => {\n const scope = await resolveScope(container, req);\n return content.addDownloadAsset(scope.orgId, req.params.downloadId, req.body);\n },\n });\n\n // Static segment before the parameterised sibling. Fastify's radix router\n // prefers static either way; the ordering documents the intent.\n r.route({\n method: 'PUT',\n url: '/api/downloads/:downloadId/assets/order',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'reorderDownloadAssets',\n tags: ['Downloads'],\n summary: \"Reorder a download's assets (send the complete set)\",\n params: DownloadIdParam,\n body: ReorderDownloadAssets,\n response: { 200: z.array(DownloadAsset), 404: ErrorBody, 409: ErrorBody },\n },\n handler: async (req) => {\n const scope = await resolveScope(container, req);\n return content.reorderDownloadAssets(\n scope.orgId,\n req.params.downloadId,\n req.body.assetIds,\n );\n },\n });\n\n r.route({\n method: 'PATCH',\n url: '/api/downloads/:downloadId/assets/:assetId',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'renameDownloadAsset',\n tags: ['Downloads'],\n summary: \"Set an asset's display name within a download\",\n params: DownloadAssetParams,\n body: RenameDownloadAsset,\n response: { 200: z.array(DownloadAsset), 404: ErrorBody },\n },\n handler: async (req) => {\n const scope = await resolveScope(container, req);\n return content.renameDownloadAsset(\n scope.orgId,\n req.params.downloadId,\n req.params.assetId,\n req.body.displayName,\n );\n },\n });\n\n r.route({\n method: 'DELETE',\n url: '/api/downloads/:downloadId/assets/:assetId',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'removeDownloadAsset',\n tags: ['Downloads'],\n summary: 'Unlink an asset from a download (the asset itself survives)',\n params: DownloadAssetParams,\n response: { 200: z.array(DownloadAsset), 404: ErrorBody },\n },\n handler: async (req) => {\n const scope = await resolveScope(container, req);\n return content.removeDownloadAsset(\n scope.orgId,\n req.params.downloadId,\n req.params.assetId,\n );\n },\n });\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Container } from "../../app/container.js";
|
|
2
|
+
import { FastifyInstance } from "fastify";
|
|
3
|
+
//#region src/http/routes/entitlements.d.ts
|
|
4
|
+
declare function entitlementsRoutes(app: FastifyInstance, container: Container): Promise<void>;
|
|
5
|
+
//#endregion
|
|
6
|
+
export { entitlementsRoutes };
|
|
7
|
+
//# sourceMappingURL=entitlements.d.ts.map
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { resolveScope } from "../scope.js";
|
|
2
|
+
import { ErrorBody } from "../schemas/shared.js";
|
|
3
|
+
import { Entitlement, EntitlementIdParam, EntitlementsPage, EntitlementsQuery, GrantEntitlement, SetEntitlementStatus } from "../schemas/entitlements.js";
|
|
4
|
+
import "../schemas/index.js";
|
|
5
|
+
import { NotFoundError } from "@headless-lms/core/shared/errors";
|
|
6
|
+
//#region src/http/routes/entitlements.ts
|
|
7
|
+
async function entitlementsRoutes(app, container) {
|
|
8
|
+
const r = app.withTypeProvider();
|
|
9
|
+
const entitlements = container.entitlements;
|
|
10
|
+
r.route({
|
|
11
|
+
method: "GET",
|
|
12
|
+
url: "/api/entitlements",
|
|
13
|
+
preHandler: app.requireOrgSession,
|
|
14
|
+
schema: {
|
|
15
|
+
operationId: "listEntitlements",
|
|
16
|
+
tags: ["Entitlements"],
|
|
17
|
+
summary: "List entitlements",
|
|
18
|
+
querystring: EntitlementsQuery,
|
|
19
|
+
response: { 200: EntitlementsPage }
|
|
20
|
+
},
|
|
21
|
+
handler: async (req) => {
|
|
22
|
+
const scope = await resolveScope(container, req);
|
|
23
|
+
return entitlements.list(scope.orgId, req.query);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
r.route({
|
|
27
|
+
method: "POST",
|
|
28
|
+
url: "/api/entitlements",
|
|
29
|
+
preHandler: app.requireOrgSession,
|
|
30
|
+
schema: {
|
|
31
|
+
operationId: "grantEntitlement",
|
|
32
|
+
tags: ["Entitlements"],
|
|
33
|
+
summary: "Grant a student access to a piece of content",
|
|
34
|
+
body: GrantEntitlement,
|
|
35
|
+
response: { 201: Entitlement }
|
|
36
|
+
},
|
|
37
|
+
handler: async (req, reply) => {
|
|
38
|
+
const scope = await resolveScope(container, req);
|
|
39
|
+
const entitlement = await entitlements.grant(scope.orgId, req.body);
|
|
40
|
+
return reply.code(201).send(entitlement);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
r.route({
|
|
44
|
+
method: "PATCH",
|
|
45
|
+
url: "/api/entitlements/:id",
|
|
46
|
+
preHandler: app.requireOrgSession,
|
|
47
|
+
schema: {
|
|
48
|
+
operationId: "setEntitlementStatus",
|
|
49
|
+
tags: ["Entitlements"],
|
|
50
|
+
summary: "Revoke or reinstate an entitlement",
|
|
51
|
+
params: EntitlementIdParam,
|
|
52
|
+
body: SetEntitlementStatus,
|
|
53
|
+
response: {
|
|
54
|
+
200: Entitlement,
|
|
55
|
+
404: ErrorBody
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
handler: async (req) => {
|
|
59
|
+
const scope = await resolveScope(container, req);
|
|
60
|
+
const entitlement = await entitlements.setStatus(scope.orgId, req.params.id, req.body.status);
|
|
61
|
+
if (!entitlement) throw new NotFoundError("Entitlement", req.params.id);
|
|
62
|
+
return entitlement;
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
//#endregion
|
|
67
|
+
export { entitlementsRoutes };
|
|
68
|
+
|
|
69
|
+
//# sourceMappingURL=entitlements.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entitlements.js","names":[],"sources":["../../../src/http/routes/entitlements.ts"],"sourcesContent":["// HTTP routes for the entitlements context (a student's access grant to a piece of content).\nimport type { FastifyInstance } from 'fastify';\nimport type { ZodTypeProvider } from 'fastify-type-provider-zod';\nimport {\n Entitlement,\n EntitlementIdParam,\n EntitlementsPage,\n EntitlementsQuery,\n ErrorBody,\n GrantEntitlement,\n SetEntitlementStatus,\n} from '../schemas/index.js';\nimport { NotFoundError } from '@headless-lms/core/shared/errors';\nimport type { Container } from '../../app/container.js';\nimport { resolveScope } from '../scope.js';\n\nexport async function entitlementsRoutes(\n app: FastifyInstance,\n container: Container,\n): Promise<void> {\n const r = app.withTypeProvider<ZodTypeProvider>();\n const entitlements = container.entitlements;\n\n r.route({\n method: 'GET',\n url: '/api/entitlements',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'listEntitlements',\n tags: ['Entitlements'],\n summary: 'List entitlements',\n querystring: EntitlementsQuery,\n response: { 200: EntitlementsPage },\n },\n handler: async (req) => {\n const scope = await resolveScope(container, req);\n return entitlements.list(scope.orgId, req.query);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/entitlements',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'grantEntitlement',\n tags: ['Entitlements'],\n summary: 'Grant a student access to a piece of content',\n body: GrantEntitlement,\n response: { 201: Entitlement },\n },\n handler: async (req, reply) => {\n const scope = await resolveScope(container, req);\n const entitlement = await entitlements.grant(scope.orgId, req.body);\n return reply.code(201).send(entitlement);\n },\n });\n\n r.route({\n method: 'PATCH',\n url: '/api/entitlements/:id',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'setEntitlementStatus',\n tags: ['Entitlements'],\n summary: 'Revoke or reinstate an entitlement',\n params: EntitlementIdParam,\n body: SetEntitlementStatus,\n response: { 200: Entitlement, 404: ErrorBody },\n },\n handler: async (req) => {\n const scope = await resolveScope(container, req);\n const entitlement = await entitlements.setStatus(scope.orgId, req.params.id, req.body.status);\n if (!entitlement) {\n throw new NotFoundError('Entitlement', req.params.id);\n }\n return entitlement;\n },\n });\n}\n"],"mappings":";;;;;;AAgBA,eAAsB,mBACpB,KACA,WACe;CACf,MAAM,IAAI,IAAI,iBAAkC;CAChD,MAAM,eAAe,UAAU;CAE/B,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,cAAc;GACrB,SAAS;GACT,aAAa;GACb,UAAU,EAAE,KAAK,iBAAiB;EACpC;EACA,SAAS,OAAO,QAAQ;GACtB,MAAM,QAAQ,MAAM,aAAa,WAAW,GAAG;GAC/C,OAAO,aAAa,KAAK,MAAM,OAAO,IAAI,KAAK;EACjD;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,cAAc;GACrB,SAAS;GACT,MAAM;GACN,UAAU,EAAE,KAAK,YAAY;EAC/B;EACA,SAAS,OAAO,KAAK,UAAU;GAC7B,MAAM,QAAQ,MAAM,aAAa,WAAW,GAAG;GAC/C,MAAM,cAAc,MAAM,aAAa,MAAM,MAAM,OAAO,IAAI,IAAI;GAClE,OAAO,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,WAAW;EACzC;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,cAAc;GACrB,SAAS;GACT,QAAQ;GACR,MAAM;GACN,UAAU;IAAE,KAAK;IAAa,KAAK;GAAU;EAC/C;EACA,SAAS,OAAO,QAAQ;GACtB,MAAM,QAAQ,MAAM,aAAa,WAAW,GAAG;GAC/C,MAAM,cAAc,MAAM,aAAa,UAAU,MAAM,OAAO,IAAI,OAAO,IAAI,IAAI,KAAK,MAAM;GAC5F,IAAI,CAAC,aACH,MAAM,IAAI,cAAc,eAAe,IAAI,OAAO,EAAE;GAEtD,OAAO;EACT;CACF,CAAC;AACH"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.js","names":[],"sources":["../../../src/http/routes/identity.ts"],"sourcesContent":["// HTTP routes for the identity context. Stub.\nimport type { FastifyInstance } from 'fastify';\n\nexport async function identityRoutes(_app: FastifyInstance): Promise<void> {\n // register identity routes here\n}\n"],"mappings":";AAGA,eAAsB,eAAe,MAAsC,CAE3E"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Container } from "../../app/container.js";
|
|
2
|
+
import { FastifyInstance } from "fastify";
|
|
3
|
+
//#region src/http/routes/integrations.d.ts
|
|
4
|
+
declare function integrationsRoutes(app: FastifyInstance, container: Container): Promise<void>;
|
|
5
|
+
//#endregion
|
|
6
|
+
export { integrationsRoutes };
|
|
7
|
+
//# sourceMappingURL=integrations.d.ts.map
|