@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.
Files changed (223) hide show
  1. package/README.md +14 -0
  2. package/dist/app/community-mail.d.ts +5 -3
  3. package/dist/app/community-mail.js +60 -12
  4. package/dist/app/community-mail.js.map +1 -1
  5. package/dist/app/container.d.ts +24 -3
  6. package/dist/app/container.js +102 -38
  7. package/dist/app/container.js.map +1 -1
  8. package/dist/app/notification-channels.js +1 -0
  9. package/dist/app/notification-channels.js.map +1 -1
  10. package/dist/app/notification-reads.d.ts +3 -3
  11. package/dist/app/notification-reads.js +7 -28
  12. package/dist/app/notification-reads.js.map +1 -1
  13. package/dist/app/platform.d.ts +14 -0
  14. package/dist/app/platform.js +14 -0
  15. package/dist/app/platform.js.map +1 -0
  16. package/dist/http/config.d.ts +4 -0
  17. package/dist/http/errors.js +9 -4
  18. package/dist/http/errors.js.map +1 -1
  19. package/dist/http/fastify.d.ts +8 -0
  20. package/dist/http/mcp/catalogue.d.ts +11 -9
  21. package/dist/http/mcp/catalogue.js +15 -21
  22. package/dist/http/mcp/catalogue.js.map +1 -1
  23. package/dist/http/mcp/challenge.js +3 -3
  24. package/dist/http/mcp/challenge.js.map +1 -1
  25. package/dist/http/mcp/route.js +7 -7
  26. package/dist/http/mcp/route.js.map +1 -1
  27. package/dist/http/mcp/test-support.d.ts +6 -5
  28. package/dist/http/mcp/test-support.js +32 -11
  29. package/dist/http/mcp/test-support.js.map +1 -1
  30. package/dist/http/mcp/tool.d.ts +3 -9
  31. package/dist/http/mcp/tool.js +14 -6
  32. package/dist/http/mcp/tool.js.map +1 -1
  33. package/dist/http/mcp/tools/automations.js +10 -20
  34. package/dist/http/mcp/tools/automations.js.map +1 -1
  35. package/dist/http/mcp/tools/catalog.js +25 -42
  36. package/dist/http/mcp/tools/catalog.js.map +1 -1
  37. package/dist/http/mcp/tools/comments.js +9 -19
  38. package/dist/http/mcp/tools/comments.js.map +1 -1
  39. package/dist/http/mcp/tools/communities.js +16 -31
  40. package/dist/http/mcp/tools/communities.js.map +1 -1
  41. package/dist/http/mcp/tools/community-members.js +9 -16
  42. package/dist/http/mcp/tools/community-members.js.map +1 -1
  43. package/dist/http/mcp/tools/community-moderation.js +13 -25
  44. package/dist/http/mcp/tools/community-moderation.js.map +1 -1
  45. package/dist/http/mcp/tools/courses.js +11 -21
  46. package/dist/http/mcp/tools/courses.js.map +1 -1
  47. package/dist/http/mcp/tools/events.d.ts +6 -0
  48. package/dist/http/mcp/tools/events.js +170 -0
  49. package/dist/http/mcp/tools/events.js.map +1 -0
  50. package/dist/http/mcp/tools/index.d.ts +5 -1
  51. package/dist/http/mcp/tools/index.js +45 -10
  52. package/dist/http/mcp/tools/index.js.map +1 -1
  53. package/dist/http/mcp/tools/organization.d.ts +6 -0
  54. package/dist/http/mcp/tools/organization.js +214 -0
  55. package/dist/http/mcp/tools/organization.js.map +1 -0
  56. package/dist/http/mcp/tools/people.js +30 -49
  57. package/dist/http/mcp/tools/people.js.map +1 -1
  58. package/dist/http/plugins/auth.js +37 -8
  59. package/dist/http/plugins/auth.js.map +1 -1
  60. package/dist/http/plugins/error-handler.d.ts +5 -1
  61. package/dist/http/plugins/error-handler.js +10 -2
  62. package/dist/http/plugins/error-handler.js.map +1 -1
  63. package/dist/http/plugins/openapi.js +18 -2
  64. package/dist/http/plugins/openapi.js.map +1 -1
  65. package/dist/http/plugins/platform.d.ts +7 -0
  66. package/dist/http/plugins/platform.js +13 -0
  67. package/dist/http/plugins/platform.js.map +1 -0
  68. package/dist/http/routes/access.js +54 -36
  69. package/dist/http/routes/access.js.map +1 -1
  70. package/dist/http/routes/activities.js +45 -45
  71. package/dist/http/routes/activities.js.map +1 -1
  72. package/dist/http/routes/assets.js +30 -65
  73. package/dist/http/routes/assets.js.map +1 -1
  74. package/dist/http/routes/automations.js +37 -42
  75. package/dist/http/routes/automations.js.map +1 -1
  76. package/dist/http/routes/bundles.js +33 -36
  77. package/dist/http/routes/bundles.js.map +1 -1
  78. package/dist/http/routes/communities.js +93 -145
  79. package/dist/http/routes/communities.js.map +1 -1
  80. package/dist/http/routes/community-moderation.js +83 -137
  81. package/dist/http/routes/community-moderation.js.map +1 -1
  82. package/dist/http/routes/course-analytics.js +32 -15
  83. package/dist/http/routes/course-analytics.js.map +1 -1
  84. package/dist/http/routes/courses.js +25 -32
  85. package/dist/http/routes/courses.js.map +1 -1
  86. package/dist/http/routes/dashboard.js +9 -9
  87. package/dist/http/routes/dashboard.js.map +1 -1
  88. package/dist/http/routes/discussion.js +21 -39
  89. package/dist/http/routes/discussion.js.map +1 -1
  90. package/dist/http/routes/downloads.js +41 -47
  91. package/dist/http/routes/downloads.js.map +1 -1
  92. package/dist/http/routes/entitlements.js +19 -23
  93. package/dist/http/routes/entitlements.js.map +1 -1
  94. package/dist/http/routes/events.d.ts +7 -0
  95. package/dist/http/routes/events.js +333 -0
  96. package/dist/http/routes/events.js.map +1 -0
  97. package/dist/http/routes/integrations.js +40 -73
  98. package/dist/http/routes/integrations.js.map +1 -1
  99. package/dist/http/routes/member/assets.js +10 -13
  100. package/dist/http/routes/member/assets.js.map +1 -1
  101. package/dist/http/routes/member/chats.js +170 -47
  102. package/dist/http/routes/member/chats.js.map +1 -1
  103. package/dist/http/routes/member/comments.js +65 -26
  104. package/dist/http/routes/member/comments.js.map +1 -1
  105. package/dist/http/routes/member/community.js +45 -52
  106. package/dist/http/routes/member/community.js.map +1 -1
  107. package/dist/http/routes/member/courses.js +12 -19
  108. package/dist/http/routes/member/courses.js.map +1 -1
  109. package/dist/http/routes/member/devices.js +9 -10
  110. package/dist/http/routes/member/devices.js.map +1 -1
  111. package/dist/http/routes/member/downloads.js +6 -9
  112. package/dist/http/routes/member/downloads.js.map +1 -1
  113. package/dist/http/routes/member/events.d.ts +7 -0
  114. package/dist/http/routes/member/events.js +386 -0
  115. package/dist/http/routes/member/events.js.map +1 -0
  116. package/dist/http/routes/member/files.js +71 -46
  117. package/dist/http/routes/member/files.js.map +1 -1
  118. package/dist/http/routes/member/index.js +2 -0
  119. package/dist/http/routes/member/index.js.map +1 -1
  120. package/dist/http/routes/member/notification-settings.js +15 -23
  121. package/dist/http/routes/member/notification-settings.js.map +1 -1
  122. package/dist/http/routes/member/notifications.js +16 -16
  123. package/dist/http/routes/member/notifications.js.map +1 -1
  124. package/dist/http/routes/member/org.js +5 -15
  125. package/dist/http/routes/member/org.js.map +1 -1
  126. package/dist/http/routes/member/posts.js +67 -68
  127. package/dist/http/routes/member/posts.js.map +1 -1
  128. package/dist/http/routes/member/profile.js +15 -6
  129. package/dist/http/routes/member/profile.js.map +1 -1
  130. package/dist/http/routes/member/progress.js +7 -11
  131. package/dist/http/routes/member/progress.js.map +1 -1
  132. package/dist/http/routes/organizations.js +319 -135
  133. package/dist/http/routes/organizations.js.map +1 -1
  134. package/dist/http/routes/platform.d.ts +7 -0
  135. package/dist/http/routes/platform.js +61 -0
  136. package/dist/http/routes/platform.js.map +1 -0
  137. package/dist/http/routes/students.js +12 -75
  138. package/dist/http/routes/students.js.map +1 -1
  139. package/dist/http/routes/webhooks.js +30 -39
  140. package/dist/http/routes/webhooks.js.map +1 -1
  141. package/dist/http/routes.js +9 -0
  142. package/dist/http/routes.js.map +1 -1
  143. package/dist/http/schemas/access.d.ts +346 -64
  144. package/dist/http/schemas/access.js +39 -12
  145. package/dist/http/schemas/access.js.map +1 -1
  146. package/dist/http/schemas/assets.d.ts +19 -14
  147. package/dist/http/schemas/assets.js +6 -5
  148. package/dist/http/schemas/assets.js.map +1 -1
  149. package/dist/http/schemas/automations.d.ts +4 -4
  150. package/dist/http/schemas/chats.d.ts +211 -32
  151. package/dist/http/schemas/chats.js +13 -4
  152. package/dist/http/schemas/chats.js.map +1 -1
  153. package/dist/http/schemas/community.d.ts +91 -44
  154. package/dist/http/schemas/community.js +21 -8
  155. package/dist/http/schemas/community.js.map +1 -1
  156. package/dist/http/schemas/course-analytics.d.ts +51 -1
  157. package/dist/http/schemas/course-analytics.js +19 -1
  158. package/dist/http/schemas/course-analytics.js.map +1 -1
  159. package/dist/http/schemas/dashboard.d.ts +1 -0
  160. package/dist/http/schemas/dashboard.js +2 -1
  161. package/dist/http/schemas/dashboard.js.map +1 -1
  162. package/dist/http/schemas/discussion.d.ts +22 -72
  163. package/dist/http/schemas/discussion.js +2 -2
  164. package/dist/http/schemas/discussion.js.map +1 -1
  165. package/dist/http/schemas/entitlements.d.ts +9 -12
  166. package/dist/http/schemas/entitlements.js +11 -5
  167. package/dist/http/schemas/entitlements.js.map +1 -1
  168. package/dist/http/schemas/events.d.ts +527 -0
  169. package/dist/http/schemas/events.js +64 -0
  170. package/dist/http/schemas/events.js.map +1 -0
  171. package/dist/http/schemas/files.d.ts +15 -5
  172. package/dist/http/schemas/files.js +10 -2
  173. package/dist/http/schemas/files.js.map +1 -1
  174. package/dist/http/schemas/index.d.ts +11 -9
  175. package/dist/http/schemas/index.js +11 -9
  176. package/dist/http/schemas/integrations.d.ts +4 -4
  177. package/dist/http/schemas/invites.d.ts +3 -47
  178. package/dist/http/schemas/invites.js +4 -25
  179. package/dist/http/schemas/invites.js.map +1 -1
  180. package/dist/http/schemas/member.d.ts +94 -7
  181. package/dist/http/schemas/member.js +7 -3
  182. package/dist/http/schemas/member.js.map +1 -1
  183. package/dist/http/schemas/members.d.ts +333 -69
  184. package/dist/http/schemas/members.js +67 -25
  185. package/dist/http/schemas/members.js.map +1 -1
  186. package/dist/http/schemas/notifications.d.ts +57 -53
  187. package/dist/http/schemas/platform.d.ts +37 -0
  188. package/dist/http/schemas/platform.js +19 -0
  189. package/dist/http/schemas/platform.js.map +1 -0
  190. package/dist/http/schemas/posts.d.ts +55 -35
  191. package/dist/http/schemas/posts.js +4 -4
  192. package/dist/http/schemas/posts.js.map +1 -1
  193. package/dist/http/schemas/profile.d.ts +1 -1
  194. package/dist/http/schemas/shared.d.ts +1 -11
  195. package/dist/http/schemas/shared.js +1 -10
  196. package/dist/http/schemas/shared.js.map +1 -1
  197. package/dist/http/schemas/students.d.ts +25 -3
  198. package/dist/http/schemas/students.js +3 -1
  199. package/dist/http/schemas/students.js.map +1 -1
  200. package/dist/http/scope.d.ts +9 -13
  201. package/dist/http/scope.js +29 -40
  202. package/dist/http/scope.js.map +1 -1
  203. package/dist/http/server.js +9 -0
  204. package/dist/http/server.js.map +1 -1
  205. package/dist/http/shutdown.d.ts +11 -0
  206. package/dist/http/shutdown.js +40 -0
  207. package/dist/http/shutdown.js.map +1 -0
  208. package/dist/http/sse.d.ts +19 -0
  209. package/dist/http/sse.js +104 -0
  210. package/dist/http/sse.js.map +1 -0
  211. package/dist/http/test-caller.d.ts +13 -0
  212. package/dist/http/test-caller.js +14 -0
  213. package/dist/http/test-caller.js.map +1 -0
  214. package/dist/http/well-known.js +2 -2
  215. package/dist/http/well-known.js.map +1 -1
  216. package/dist/index.d.ts +4 -2
  217. package/dist/index.js +4 -2
  218. package/dist/index.js.map +1 -1
  219. package/dist/packages/server/package.js +1 -1
  220. package/package.json +7 -6
  221. package/dist/http/routes/member/actor.d.ts +0 -14
  222. package/dist/http/routes/member/actor.js +0 -11
  223. package/dist/http/routes/member/actor.js.map +0 -1
@@ -15,13 +15,8 @@ declare const CommentAuthor: z.ZodObject<{
15
15
  image: z.ZodNullable<z.ZodString>;
16
16
  imageAssetId: z.ZodNullable<z.ZodString>;
17
17
  imageUrl: z.ZodNullable<z.ZodString>;
18
- role: z.ZodEnum<{
19
- owner: "owner";
20
- admin: "admin";
21
- instructor: "instructor";
22
- moderator: "moderator";
23
- student: "student";
24
- }>;
18
+ team: z.ZodBoolean;
19
+ roleName: z.ZodNullable<z.ZodString>;
25
20
  }, z.core.$strict>;
26
21
  type CommentAuthor = z.infer<typeof CommentAuthor>;
27
22
  /** Any single emoji. Open, so widening the picker needs no schema change. */
@@ -59,13 +54,8 @@ declare const CommentView: z.ZodObject<{
59
54
  image: z.ZodNullable<z.ZodString>;
60
55
  imageAssetId: z.ZodNullable<z.ZodString>;
61
56
  imageUrl: z.ZodNullable<z.ZodString>;
62
- role: z.ZodEnum<{
63
- owner: "owner";
64
- admin: "admin";
65
- instructor: "instructor";
66
- moderator: "moderator";
67
- student: "student";
68
- }>;
57
+ team: z.ZodBoolean;
58
+ roleName: z.ZodNullable<z.ZodString>;
69
59
  }, z.core.$strict>;
70
60
  body: z.ZodNullable<z.ZodString>;
71
61
  status: z.ZodEnum<{
@@ -82,13 +72,8 @@ declare const CommentView: z.ZodObject<{
82
72
  image: z.ZodNullable<z.ZodString>;
83
73
  imageAssetId: z.ZodNullable<z.ZodString>;
84
74
  imageUrl: z.ZodNullable<z.ZodString>;
85
- role: z.ZodEnum<{
86
- owner: "owner";
87
- admin: "admin";
88
- instructor: "instructor";
89
- moderator: "moderator";
90
- student: "student";
91
- }>;
75
+ team: z.ZodBoolean;
76
+ roleName: z.ZodNullable<z.ZodString>;
92
77
  }, z.core.$strict>>;
93
78
  reactions: z.ZodRecord<z.ZodString, z.ZodNumber>;
94
79
  viewerReaction: z.ZodOptional<z.ZodString>;
@@ -146,13 +131,8 @@ declare const ActivityComments: z.ZodObject<{
146
131
  image: z.ZodNullable<z.ZodString>;
147
132
  imageAssetId: z.ZodNullable<z.ZodString>;
148
133
  imageUrl: z.ZodNullable<z.ZodString>;
149
- role: z.ZodEnum<{
150
- owner: "owner";
151
- admin: "admin";
152
- instructor: "instructor";
153
- moderator: "moderator";
154
- student: "student";
155
- }>;
134
+ team: z.ZodBoolean;
135
+ roleName: z.ZodNullable<z.ZodString>;
156
136
  }, z.core.$strict>;
157
137
  body: z.ZodNullable<z.ZodString>;
158
138
  status: z.ZodEnum<{
@@ -169,13 +149,8 @@ declare const ActivityComments: z.ZodObject<{
169
149
  image: z.ZodNullable<z.ZodString>;
170
150
  imageAssetId: z.ZodNullable<z.ZodString>;
171
151
  imageUrl: z.ZodNullable<z.ZodString>;
172
- role: z.ZodEnum<{
173
- owner: "owner";
174
- admin: "admin";
175
- instructor: "instructor";
176
- moderator: "moderator";
177
- student: "student";
178
- }>;
152
+ team: z.ZodBoolean;
153
+ roleName: z.ZodNullable<z.ZodString>;
179
154
  }, z.core.$strict>>;
180
155
  reactions: z.ZodRecord<z.ZodString, z.ZodNumber>;
181
156
  viewerReaction: z.ZodOptional<z.ZodString>;
@@ -197,7 +172,7 @@ declare const EditComment: z.ZodObject<{
197
172
  body: z.ZodString;
198
173
  }, z.core.$strict>;
199
174
  type EditComment = z.infer<typeof EditComment>;
200
- /** The staff PATCH writes status and nothing else: publishing covers approving
175
+ /** The moderator's PATCH writes status and nothing else: publishing covers approving
201
176
  * a pending comment and restoring a removed one. Revising the text is the
202
177
  * author's own edit, under /api/member. */
203
178
  declare const PatchComment: z.ZodObject<{
@@ -264,19 +239,14 @@ declare const CommentReportSummary: z.ZodObject<{
264
239
  image: z.ZodNullable<z.ZodString>;
265
240
  imageAssetId: z.ZodNullable<z.ZodString>;
266
241
  imageUrl: z.ZodNullable<z.ZodString>;
267
- role: z.ZodEnum<{
268
- owner: "owner";
269
- admin: "admin";
270
- instructor: "instructor";
271
- moderator: "moderator";
272
- student: "student";
273
- }>;
242
+ team: z.ZodBoolean;
243
+ roleName: z.ZodNullable<z.ZodString>;
274
244
  }, z.core.$strict>;
275
245
  reason: z.ZodString;
276
246
  createdAt: z.ZodCoercedDate<unknown>;
277
247
  }, z.core.$strict>;
278
248
  type CommentReportSummary = z.infer<typeof CommentReportSummary>;
279
- /** One row of the staff comment list: the comment plus the context a
249
+ /** One row of the moderation comment list: the comment plus the context a
280
250
  * moderation decision needs, so the list needs no follow-up request. */
281
251
  declare const CommentListItem: z.ZodObject<{
282
252
  id: z.ZodString;
@@ -299,13 +269,8 @@ declare const CommentListItem: z.ZodObject<{
299
269
  image: z.ZodNullable<z.ZodString>;
300
270
  imageAssetId: z.ZodNullable<z.ZodString>;
301
271
  imageUrl: z.ZodNullable<z.ZodString>;
302
- role: z.ZodEnum<{
303
- owner: "owner";
304
- admin: "admin";
305
- instructor: "instructor";
306
- moderator: "moderator";
307
- student: "student";
308
- }>;
272
+ team: z.ZodBoolean;
273
+ roleName: z.ZodNullable<z.ZodString>;
309
274
  }, z.core.$strict>;
310
275
  authorEmail: z.ZodEmail;
311
276
  removedBy: z.ZodNullable<z.ZodString>;
@@ -319,13 +284,8 @@ declare const CommentListItem: z.ZodObject<{
319
284
  image: z.ZodNullable<z.ZodString>;
320
285
  imageAssetId: z.ZodNullable<z.ZodString>;
321
286
  imageUrl: z.ZodNullable<z.ZodString>;
322
- role: z.ZodEnum<{
323
- owner: "owner";
324
- admin: "admin";
325
- instructor: "instructor";
326
- moderator: "moderator";
327
- student: "student";
328
- }>;
287
+ team: z.ZodBoolean;
288
+ roleName: z.ZodNullable<z.ZodString>;
329
289
  }, z.core.$strict>;
330
290
  reason: z.ZodString;
331
291
  createdAt: z.ZodCoercedDate<unknown>;
@@ -372,13 +332,8 @@ declare const CommentsPage: z.ZodObject<{
372
332
  image: z.ZodNullable<z.ZodString>;
373
333
  imageAssetId: z.ZodNullable<z.ZodString>;
374
334
  imageUrl: z.ZodNullable<z.ZodString>;
375
- role: z.ZodEnum<{
376
- owner: "owner";
377
- admin: "admin";
378
- instructor: "instructor";
379
- moderator: "moderator";
380
- student: "student";
381
- }>;
335
+ team: z.ZodBoolean;
336
+ roleName: z.ZodNullable<z.ZodString>;
382
337
  }, z.core.$strict>;
383
338
  authorEmail: z.ZodEmail;
384
339
  removedBy: z.ZodNullable<z.ZodString>;
@@ -392,13 +347,8 @@ declare const CommentsPage: z.ZodObject<{
392
347
  image: z.ZodNullable<z.ZodString>;
393
348
  imageAssetId: z.ZodNullable<z.ZodString>;
394
349
  imageUrl: z.ZodNullable<z.ZodString>;
395
- role: z.ZodEnum<{
396
- owner: "owner";
397
- admin: "admin";
398
- instructor: "instructor";
399
- moderator: "moderator";
400
- student: "student";
401
- }>;
350
+ team: z.ZodBoolean;
351
+ roleName: z.ZodNullable<z.ZodString>;
402
352
  }, z.core.$strict>;
403
353
  reason: z.ZodString;
404
354
  createdAt: z.ZodCoercedDate<unknown>;
@@ -46,7 +46,7 @@ const PostComment = z.object({
46
46
  parentId: idSchema.nullable().default(null).describe("The comment this replies to. Replies nest one level, under a root comment")
47
47
  }).strict();
48
48
  const EditComment = z.object({ body: z.string().min(1).max(1e4) }).strict();
49
- /** The staff PATCH writes status and nothing else: publishing covers approving
49
+ /** The moderator's PATCH writes status and nothing else: publishing covers approving
50
50
  * a pending comment and restoring a removed one. Revising the text is the
51
51
  * author's own edit, under /api/member. */
52
52
  const PatchComment = z.object({ status: z.literal("published") });
@@ -68,7 +68,7 @@ const CommentReport = z.object({
68
68
  /** An unresolved report on a listed comment. Resolved ones are history and are
69
69
  * never served here. */
70
70
  const CommentReportSummary = commentReportSummarySchema;
71
- /** One row of the staff comment list: the comment plus the context a
71
+ /** One row of the moderation comment list: the comment plus the context a
72
72
  * moderation decision needs, so the list needs no follow-up request. */
73
73
  const CommentListItem = commentListItemSchema;
74
74
  const CommentsQuery = ListQuery.extend({
@@ -1 +1 @@
1
- {"version":3,"file":"discussion.js","names":[],"sources":["../../../src/http/schemas/discussion.ts"],"sourcesContent":["// Discussion resource schemas. Comments attach to an activity; settings are\n// per course, with a per-activity override carried on the activity's own\n// settings blob rather than a resource of its own.\n//\n// The author is the org user's profile minus its email — learners read each\n// other's comments and the list must not be a directory of the cohort's\n// addresses. The staff-facing comment list carries `authorEmail` separately.\nimport type { CommentSettings as DomainCommentSettings } from '@headless-lms/core/types';\nimport {\n commentAuthorSchema,\n commentListItemSchema,\n commentReportSummarySchema,\n commentSchema,\n commentFlagResolutionSchema,\n commentStatusSchema,\n commentViewSchema,\n idSchema,\n} from '@headless-lms/core/schemas';\nimport { z } from 'zod';\nimport { DateTimeInput, ListQuery, type Matches, paginated } from './shared.js';\n\nexport const CommentStatus = commentStatusSchema;\nexport type CommentStatus = z.infer<typeof CommentStatus>;\n\nexport const CommentAuthor = commentAuthorSchema;\nexport type CommentAuthor = z.infer<typeof CommentAuthor>;\n\n/** Any single emoji. Open, so widening the picker needs no schema change. */\nexport const ReactionEmoji = z.string().min(1).max(16);\nexport type ReactionEmoji = z.infer<typeof ReactionEmoji>;\n\n/** Counts by emoji; unused ones are absent, so no reactions serves `{}`. */\nexport const ReactionCounts = z.record(z.string(), z.number().int());\nexport type ReactionCounts = z.infer<typeof ReactionCounts>;\n\nconst Following = z\n .object({ state: z.literal('following') })\n .strict()\n .describe('Follow the post: you are notified of its new comments');\nconst Muted = z\n .object({\n state: z.literal('muted'),\n mutedUntil: DateTimeInput.nullable()\n .optional()\n .describe('When the mute ends. Omit or null to mute until you change it'),\n })\n .strict()\n .describe('Mute it: its activity stops notifying you, except mentions and actions on you');\nconst Unsubscribed = z\n .object({ state: z.literal('none') })\n .strict()\n .describe('Neither follow nor mute it');\n\nexport const SetPostSubscription = z.discriminatedUnion('state', [Following, Muted, Unsubscribed]);\nexport const SetMute = z.discriminatedUnion('state', [Muted, Unsubscribed]);\n\nexport const CommentView = commentViewSchema;\nexport type CommentView = z.infer<typeof CommentView>;\n\n/** What a reaction write on a post, message or comment returns, so the client never recomputes a count. */\nexport const Reactions = z.object({\n reactions: ReactionCounts,\n viewerReaction: ReactionEmoji.optional().describe('Absent when you have no reaction'),\n});\nexport type Reactions = z.infer<typeof Reactions>;\n\n/** A course's comment settings. Stored under the course, carried on the course\n * payload as `settings.comments`. */\nexport const CommentSettings = z.object({\n enabled: z.boolean(),\n threaded: z.boolean(),\n requireReview: z.boolean(),\n reactions: z.boolean(),\n});\nexport type CommentSettings = z.infer<typeof CommentSettings>;\ntype _CommentSettingsMatchesDomain = Matches<DomainCommentSettings, CommentSettings> &\n Matches<CommentSettings, DomainCommentSettings>;\n\n/** The course settings with the activity's override applied: `enabled` is the\n * resolved answer for this activity, not the course switch. */\nexport const CommentsConfig = CommentSettings;\nexport type CommentsConfig = z.infer<typeof CommentsConfig>;\n\nexport const ActivityComments = z.object({\n config: CommentsConfig,\n comments: z.array(CommentView),\n});\nexport type ActivityComments = z.infer<typeof ActivityComments>;\n\nexport const PostComment = z\n .object({\n body: z.string().min(1).max(10_000),\n parentId: idSchema\n .nullable()\n .default(null)\n .describe('The comment this replies to. Replies nest one level, under a root comment'),\n })\n .strict();\nexport type PostComment = z.infer<typeof PostComment>;\n\nexport const EditComment = z.object({ body: z.string().min(1).max(10_000) }).strict();\nexport type EditComment = z.infer<typeof EditComment>;\n\n/** The staff PATCH writes status and nothing else: publishing covers approving\n * a pending comment and restoring a removed one. Revising the text is the\n * author's own edit, under /api/member. */\nexport const PatchComment = z.object({\n status: z.literal('published'),\n});\nexport type PatchComment = z.infer<typeof PatchComment>;\n\n/** Replaces whatever the reader had. Clearing is DELETE, which carries no body. */\nexport const SetReaction = z\n .object({ emoji: ReactionEmoji.describe('Replaces any reaction you already had') })\n .strict();\nexport type SetReaction = z.infer<typeof SetReaction>;\n\nexport const ResolveCommentFlags = z\n .object({\n resolution: commentFlagResolutionSchema\n .extract(['dismissed'])\n .describe(\n '`dismissed` closes the open flags and leaves the comment up. Removing the comment resolves its flags as `removed` instead.',\n ),\n })\n .strict();\nexport type ResolveCommentFlags = z.infer<typeof ResolveCommentFlags>;\n\n/** A moderator's reply, posted from the queue against the comment it answers. */\nexport const ReplyToComment = z.object({\n body: z.string().min(1).max(10_000),\n});\nexport type ReplyToComment = z.infer<typeof ReplyToComment>;\n\nexport const ReportComment = z.object({ reason: z.string().max(1_000).default('') }).strict();\nexport type ReportComment = z.infer<typeof ReportComment>;\n\nexport const Comment = commentSchema;\nexport type Comment = z.infer<typeof Comment>;\n\nexport const CommentReport = z.object({\n id: z.string(),\n commentId: z.string(),\n orgUserId: z.string(),\n reason: z.string(),\n resolvedAt: z.date().nullable(),\n createdAt: z.date(),\n});\nexport type CommentReport = z.infer<typeof CommentReport>;\n\n/** An unresolved report on a listed comment. Resolved ones are history and are\n * never served here. */\nexport const CommentReportSummary = commentReportSummarySchema;\nexport type CommentReportSummary = z.infer<typeof CommentReportSummary>;\n\n/** One row of the staff comment list: the comment plus the context a\n * moderation decision needs, so the list needs no follow-up request. */\nexport const CommentListItem = commentListItemSchema;\nexport type CommentListItem = z.infer<typeof CommentListItem>;\n\nexport const CommentsQuery = ListQuery.extend({\n status: CommentStatus.optional(),\n /** true = only comments carrying an unresolved report, false = only those\n * carrying none. `z.stringbool` because query values arrive as strings and\n * `z.coerce.boolean()` would read \"false\" as true. */\n reported: z.stringbool().optional(),\n courseId: z.string().optional(),\n activityId: z.string().optional(),\n /** Scope to one author (org_users.id). */\n orgUserId: z.string().optional(),\n});\nexport type CommentsQuery = z.infer<typeof CommentsQuery>;\n\nexport const CommentsPage = paginated(CommentListItem);\nexport type CommentsPage = z.infer<typeof CommentsPage>;\n\nexport const DiscussionActivityParam = z.object({ activityId: z.string() });\nexport type DiscussionActivityParam = z.infer<typeof DiscussionActivityParam>;\n\nexport const CommentIdParam = z.object({ commentId: z.string() });\nexport type CommentIdParam = z.infer<typeof CommentIdParam>;\n"],"mappings":"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"}
1
+ {"version":3,"file":"discussion.js","names":[],"sources":["../../../src/http/schemas/discussion.ts"],"sourcesContent":["// Discussion resource schemas. Comments attach to an activity; settings are\n// per course, with a per-activity override carried on the activity's own\n// settings blob rather than a resource of its own.\n//\n// The author is the org user's profile minus its email — learners read each\n// other's comments and the list must not be a directory of the cohort's\n// addresses. The staff-facing comment list carries `authorEmail` separately.\nimport type { CommentSettings as DomainCommentSettings } from '@headless-lms/core/types';\nimport {\n commentAuthorSchema,\n commentListItemSchema,\n commentReportSummarySchema,\n commentSchema,\n commentFlagResolutionSchema,\n commentStatusSchema,\n commentViewSchema,\n idSchema,\n} from '@headless-lms/core/schemas';\nimport { z } from 'zod';\nimport { DateTimeInput, ListQuery, type Matches, paginated } from './shared.js';\n\nexport const CommentStatus = commentStatusSchema;\nexport type CommentStatus = z.infer<typeof CommentStatus>;\n\nexport const CommentAuthor = commentAuthorSchema;\nexport type CommentAuthor = z.infer<typeof CommentAuthor>;\n\n/** Any single emoji. Open, so widening the picker needs no schema change. */\nexport const ReactionEmoji = z.string().min(1).max(16);\nexport type ReactionEmoji = z.infer<typeof ReactionEmoji>;\n\n/** Counts by emoji; unused ones are absent, so no reactions serves `{}`. */\nexport const ReactionCounts = z.record(z.string(), z.number().int());\nexport type ReactionCounts = z.infer<typeof ReactionCounts>;\n\nconst Following = z\n .object({ state: z.literal('following') })\n .strict()\n .describe('Follow the post: you are notified of its new comments');\nconst Muted = z\n .object({\n state: z.literal('muted'),\n mutedUntil: DateTimeInput.nullable()\n .optional()\n .describe('When the mute ends. Omit or null to mute until you change it'),\n })\n .strict()\n .describe('Mute it: its activity stops notifying you, except mentions and actions on you');\nconst Unsubscribed = z\n .object({ state: z.literal('none') })\n .strict()\n .describe('Neither follow nor mute it');\n\nexport const SetPostSubscription = z.discriminatedUnion('state', [Following, Muted, Unsubscribed]);\nexport const SetMute = z.discriminatedUnion('state', [Muted, Unsubscribed]);\n\nexport const CommentView = commentViewSchema;\nexport type CommentView = z.infer<typeof CommentView>;\n\n/** What a reaction write on a post, message or comment returns, so the client never recomputes a count. */\nexport const Reactions = z.object({\n reactions: ReactionCounts,\n viewerReaction: ReactionEmoji.optional().describe('Absent when you have no reaction'),\n});\nexport type Reactions = z.infer<typeof Reactions>;\n\n/** A course's comment settings. Stored under the course, carried on the course\n * payload as `settings.comments`. */\nexport const CommentSettings = z.object({\n enabled: z.boolean(),\n threaded: z.boolean(),\n requireReview: z.boolean(),\n reactions: z.boolean(),\n});\nexport type CommentSettings = z.infer<typeof CommentSettings>;\ntype _CommentSettingsMatchesDomain = Matches<DomainCommentSettings, CommentSettings> &\n Matches<CommentSettings, DomainCommentSettings>;\n\n/** The course settings with the activity's override applied: `enabled` is the\n * resolved answer for this activity, not the course switch. */\nexport const CommentsConfig = CommentSettings;\nexport type CommentsConfig = z.infer<typeof CommentsConfig>;\n\nexport const ActivityComments = z.object({\n config: CommentsConfig,\n comments: z.array(CommentView),\n});\nexport type ActivityComments = z.infer<typeof ActivityComments>;\n\nexport const PostComment = z\n .object({\n body: z.string().min(1).max(10_000),\n parentId: idSchema\n .nullable()\n .default(null)\n .describe('The comment this replies to. Replies nest one level, under a root comment'),\n })\n .strict();\nexport type PostComment = z.infer<typeof PostComment>;\n\nexport const EditComment = z.object({ body: z.string().min(1).max(10_000) }).strict();\nexport type EditComment = z.infer<typeof EditComment>;\n\n/** The moderator's PATCH writes status and nothing else: publishing covers approving\n * a pending comment and restoring a removed one. Revising the text is the\n * author's own edit, under /api/member. */\nexport const PatchComment = z.object({\n status: z.literal('published'),\n});\nexport type PatchComment = z.infer<typeof PatchComment>;\n\n/** Replaces whatever the reader had. Clearing is DELETE, which carries no body. */\nexport const SetReaction = z\n .object({ emoji: ReactionEmoji.describe('Replaces any reaction you already had') })\n .strict();\nexport type SetReaction = z.infer<typeof SetReaction>;\n\nexport const ResolveCommentFlags = z\n .object({\n resolution: commentFlagResolutionSchema\n .extract(['dismissed'])\n .describe(\n '`dismissed` closes the open flags and leaves the comment up. Removing the comment resolves its flags as `removed` instead.',\n ),\n })\n .strict();\nexport type ResolveCommentFlags = z.infer<typeof ResolveCommentFlags>;\n\n/** A moderator's reply, posted from the queue against the comment it answers. */\nexport const ReplyToComment = z.object({\n body: z.string().min(1).max(10_000),\n});\nexport type ReplyToComment = z.infer<typeof ReplyToComment>;\n\nexport const ReportComment = z.object({ reason: z.string().max(1_000).default('') }).strict();\nexport type ReportComment = z.infer<typeof ReportComment>;\n\nexport const Comment = commentSchema;\nexport type Comment = z.infer<typeof Comment>;\n\nexport const CommentReport = z.object({\n id: z.string(),\n commentId: z.string(),\n orgUserId: z.string(),\n reason: z.string(),\n resolvedAt: z.date().nullable(),\n createdAt: z.date(),\n});\nexport type CommentReport = z.infer<typeof CommentReport>;\n\n/** An unresolved report on a listed comment. Resolved ones are history and are\n * never served here. */\nexport const CommentReportSummary = commentReportSummarySchema;\nexport type CommentReportSummary = z.infer<typeof CommentReportSummary>;\n\n/** One row of the moderation comment list: the comment plus the context a\n * moderation decision needs, so the list needs no follow-up request. */\nexport const CommentListItem = commentListItemSchema;\nexport type CommentListItem = z.infer<typeof CommentListItem>;\n\nexport const CommentsQuery = ListQuery.extend({\n status: CommentStatus.optional(),\n /** true = only comments carrying an unresolved report, false = only those\n * carrying none. `z.stringbool` because query values arrive as strings and\n * `z.coerce.boolean()` would read \"false\" as true. */\n reported: z.stringbool().optional(),\n courseId: z.string().optional(),\n activityId: z.string().optional(),\n /** Scope to one author (org_users.id). */\n orgUserId: z.string().optional(),\n});\nexport type CommentsQuery = z.infer<typeof CommentsQuery>;\n\nexport const CommentsPage = paginated(CommentListItem);\nexport type CommentsPage = z.infer<typeof CommentsPage>;\n\nexport const DiscussionActivityParam = z.object({ activityId: z.string() });\nexport type DiscussionActivityParam = z.infer<typeof DiscussionActivityParam>;\n\nexport const CommentIdParam = z.object({ commentId: z.string() });\nexport type CommentIdParam = z.infer<typeof CommentIdParam>;\n"],"mappings":"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"}
@@ -9,6 +9,7 @@ type EntitlementStatus = z.infer<typeof EntitlementStatus>;
9
9
  declare const ContentType: z.ZodEnum<{
10
10
  course: "course";
11
11
  download: "download";
12
+ event: "event";
12
13
  }>;
13
14
  type ContentType = z.infer<typeof ContentType>;
14
15
  /** Reference to the granted content: identity + display name (join-derived).
@@ -18,6 +19,7 @@ declare const ContentRef: z.ZodObject<{
18
19
  type: z.ZodEnum<{
19
20
  course: "course";
20
21
  download: "download";
22
+ event: "event";
21
23
  }>;
22
24
  title: z.ZodString;
23
25
  }, z.core.$strip>;
@@ -55,6 +57,7 @@ declare const EntitlementsQuery: z.ZodObject<{
55
57
  type: z.ZodOptional<z.ZodEnum<{
56
58
  course: "course";
57
59
  download: "download";
60
+ event: "event";
58
61
  }>>;
59
62
  }, z.core.$strip>;
60
63
  type EntitlementsQuery = z.infer<typeof EntitlementsQuery>;
@@ -88,18 +91,12 @@ declare const GrantEntitlement: z.ZodObject<{
88
91
  expiresAt: z.ZodNullable<z.ZodPipe<z.ZodISODateTime, z.ZodCoercedDate<string>>>;
89
92
  }, z.core.$strip>;
90
93
  type GrantEntitlement = z.infer<typeof GrantEntitlement>;
91
- /** Revoke/reinstate access by setting the active|revoked status. */
92
- declare const SetEntitlementStatus: z.ZodObject<{
93
- status: z.ZodEnum<{
94
- active: "active";
95
- revoked: "revoked";
96
- }>;
97
- }, z.core.$strip>;
98
- type SetEntitlementStatus = z.infer<typeof SetEntitlementStatus>;
99
- declare const EntitlementIdParam: z.ZodObject<{
100
- id: z.ZodString;
94
+ declare const RevokeEntitlement: z.ZodObject<{
95
+ orgUserId: z.ZodString;
96
+ contentId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
97
+ bundleId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
101
98
  }, z.core.$strip>;
102
- type EntitlementIdParam = z.infer<typeof EntitlementIdParam>;
99
+ type RevokeEntitlement = z.infer<typeof RevokeEntitlement>;
103
100
  //#endregion
104
- export { ContentRef, ContentType, Entitlement, EntitlementIdParam, EntitlementStatus, EntitlementsPage, EntitlementsQuery, GrantEntitlement, SetEntitlementStatus };
101
+ export { ContentRef, ContentType, Entitlement, EntitlementStatus, EntitlementsPage, EntitlementsQuery, GrantEntitlement, RevokeEntitlement };
105
102
  //# sourceMappingURL=entitlements.d.ts.map
@@ -7,7 +7,11 @@ const EntitlementStatus = z.enum([
7
7
  "expired",
8
8
  "revoked"
9
9
  ]);
10
- const ContentType = z.enum(["course", "download"]);
10
+ const ContentType = z.enum([
11
+ "course",
12
+ "download",
13
+ "event"
14
+ ]);
11
15
  /** Reference to the granted content: identity + display name (join-derived).
12
16
  * The full content object lives on its own resource. */
13
17
  const ContentRef = z.object({
@@ -34,10 +38,12 @@ const GrantEntitlement = z.object({
34
38
  bundleId: idSchema.nullish(),
35
39
  expiresAt: DateTimeInput.nullable().describe("When access ends; null never expires")
36
40
  }).refine((v) => v.contentId != null !== (v.bundleId != null), { message: "Provide exactly one of contentId or bundleId" });
37
- /** Revoke/reinstate access by setting the active|revoked status. */
38
- const SetEntitlementStatus = z.object({ status: z.enum(["active", "revoked"]) });
39
- const EntitlementIdParam = z.object({ id: z.string() });
41
+ const RevokeEntitlement = z.object({
42
+ orgUserId: idSchema,
43
+ contentId: idSchema.nullish(),
44
+ bundleId: idSchema.nullish()
45
+ }).refine((v) => v.contentId != null !== (v.bundleId != null), { message: "Provide exactly one of contentId or bundleId" });
40
46
  //#endregion
41
- export { ContentRef, ContentType, Entitlement, EntitlementIdParam, EntitlementStatus, EntitlementsPage, EntitlementsQuery, GrantEntitlement, SetEntitlementStatus };
47
+ export { ContentRef, ContentType, Entitlement, EntitlementStatus, EntitlementsPage, EntitlementsQuery, GrantEntitlement, RevokeEntitlement };
42
48
 
43
49
  //# sourceMappingURL=entitlements.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"entitlements.js","names":[],"sources":["../../../src/http/schemas/entitlements.ts"],"sourcesContent":["// Entitlements resource schemas. An entitlement is a student's access grant to\n// a piece of content — generic over content types (course today) — its\n// validity + source. Distinct from payment and from completion.\nimport { z } from 'zod';\nimport { entitlementSchema, idSchema } from '@headless-lms/core/schemas';\nimport { DateTimeInput, ListQuery, paginated } from './shared.js';\n\nexport const EntitlementStatus = z.enum(['active', 'expired', 'revoked']);\nexport type EntitlementStatus = z.infer<typeof EntitlementStatus>;\n\nexport const ContentType = z.enum(['course', 'download']);\nexport type ContentType = z.infer<typeof ContentType>;\n\n/** Reference to the granted content: identity + display name (join-derived).\n * The full content object lives on its own resource. */\nexport const ContentRef = z.object({\n id: z.string(),\n type: ContentType,\n title: z.string(),\n});\nexport type ContentRef = z.infer<typeof ContentRef>;\n\nexport const Entitlement = entitlementSchema;\nexport type Entitlement = z.infer<typeof Entitlement>;\n\nexport const EntitlementsQuery = ListQuery.extend({\n status: EntitlementStatus.optional(),\n source: z.string().optional(),\n /** Scope to a single student (used by the student detail view). */\n orgUserId: z.string().optional(),\n /** Scope to a single piece of content. */\n contentId: z.string().optional(),\n /** Scope to one content type. */\n type: ContentType.optional(),\n});\nexport type EntitlementsQuery = z.infer<typeof EntitlementsQuery>;\n\nexport const EntitlementsPage = paginated(Entitlement);\nexport type EntitlementsPage = z.infer<typeof EntitlementsPage>;\n\n/** A grant targets exactly one of: a single content item or a bundle. */\nexport const GrantEntitlement = z\n .object({\n orgUserId: idSchema,\n contentId: idSchema.nullish(),\n bundleId: idSchema.nullish(),\n expiresAt: DateTimeInput.nullable().describe('When access ends; null never expires'),\n })\n .refine((v) => (v.contentId != null) !== (v.bundleId != null), {\n message: 'Provide exactly one of contentId or bundleId',\n });\nexport type GrantEntitlement = z.infer<typeof GrantEntitlement>;\n\n/** Revoke/reinstate access by setting the active|revoked status. */\nexport const SetEntitlementStatus = z.object({\n status: z.enum(['active', 'revoked']),\n});\nexport type SetEntitlementStatus = z.infer<typeof SetEntitlementStatus>;\n\nexport const EntitlementIdParam = z.object({ id: z.string() });\nexport type EntitlementIdParam = z.infer<typeof EntitlementIdParam>;\n"],"mappings":";;;;AAOA,MAAa,oBAAoB,EAAE,KAAK;CAAC;CAAU;CAAW;AAAS,CAAC;AAGxE,MAAa,cAAc,EAAE,KAAK,CAAC,UAAU,UAAU,CAAC;;;AAKxD,MAAa,aAAa,EAAE,OAAO;CACjC,IAAI,EAAE,OAAO;CACb,MAAM;CACN,OAAO,EAAE,OAAO;AAClB,CAAC;AAGD,MAAa,cAAc;AAG3B,MAAa,oBAAoB,UAAU,OAAO;CAChD,QAAQ,kBAAkB,SAAS;CACnC,QAAQ,EAAE,OAAO,CAAC,CAAC,SAAS;;CAE5B,WAAW,EAAE,OAAO,CAAC,CAAC,SAAS;;CAE/B,WAAW,EAAE,OAAO,CAAC,CAAC,SAAS;;CAE/B,MAAM,YAAY,SAAS;AAC7B,CAAC;AAGD,MAAa,mBAAmB,UAAU,WAAW;;AAIrD,MAAa,mBAAmB,EAC7B,OAAO;CACN,WAAW;CACX,WAAW,SAAS,QAAQ;CAC5B,UAAU,SAAS,QAAQ;CAC3B,WAAW,cAAc,SAAS,CAAC,CAAC,SAAS,sCAAsC;AACrF,CAAC,CAAC,CACD,QAAQ,MAAO,EAAE,aAAa,UAAW,EAAE,YAAY,OAAO,EAC7D,SAAS,+CACX,CAAC;;AAIH,MAAa,uBAAuB,EAAE,OAAO,EAC3C,QAAQ,EAAE,KAAK,CAAC,UAAU,SAAS,CAAC,EACtC,CAAC;AAGD,MAAa,qBAAqB,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC"}
1
+ {"version":3,"file":"entitlements.js","names":[],"sources":["../../../src/http/schemas/entitlements.ts"],"sourcesContent":["// Entitlements resource schemas. An entitlement is a student's access grant to\n// a piece of content — generic over content types (course today) — its\n// validity + source. Distinct from payment and from completion.\nimport { z } from 'zod';\nimport { entitlementSchema, idSchema } from '@headless-lms/core/schemas';\nimport { DateTimeInput, ListQuery, paginated } from './shared.js';\n\nexport const EntitlementStatus = z.enum(['active', 'expired', 'revoked']);\nexport type EntitlementStatus = z.infer<typeof EntitlementStatus>;\n\nexport const ContentType = z.enum(['course', 'download', 'event']);\nexport type ContentType = z.infer<typeof ContentType>;\n\n/** Reference to the granted content: identity + display name (join-derived).\n * The full content object lives on its own resource. */\nexport const ContentRef = z.object({\n id: z.string(),\n type: ContentType,\n title: z.string(),\n});\nexport type ContentRef = z.infer<typeof ContentRef>;\n\nexport const Entitlement = entitlementSchema;\nexport type Entitlement = z.infer<typeof Entitlement>;\n\nexport const EntitlementsQuery = ListQuery.extend({\n status: EntitlementStatus.optional(),\n source: z.string().optional(),\n /** Scope to a single student (used by the student detail view). */\n orgUserId: z.string().optional(),\n /** Scope to a single piece of content. */\n contentId: z.string().optional(),\n /** Scope to one content type. */\n type: ContentType.optional(),\n});\nexport type EntitlementsQuery = z.infer<typeof EntitlementsQuery>;\n\nexport const EntitlementsPage = paginated(Entitlement);\nexport type EntitlementsPage = z.infer<typeof EntitlementsPage>;\n\n/** A grant targets exactly one of: a single content item or a bundle. */\nexport const GrantEntitlement = z\n .object({\n orgUserId: idSchema,\n contentId: idSchema.nullish(),\n bundleId: idSchema.nullish(),\n expiresAt: DateTimeInput.nullable().describe('When access ends; null never expires'),\n })\n .refine((v) => (v.contentId != null) !== (v.bundleId != null), {\n message: 'Provide exactly one of contentId or bundleId',\n });\nexport type GrantEntitlement = z.infer<typeof GrantEntitlement>;\n\nexport const RevokeEntitlement = z\n .object({\n orgUserId: idSchema,\n contentId: idSchema.nullish(),\n bundleId: idSchema.nullish(),\n })\n .refine((v) => (v.contentId != null) !== (v.bundleId != null), {\n message: 'Provide exactly one of contentId or bundleId',\n });\nexport type RevokeEntitlement = z.infer<typeof RevokeEntitlement>;\n"],"mappings":";;;;AAOA,MAAa,oBAAoB,EAAE,KAAK;CAAC;CAAU;CAAW;AAAS,CAAC;AAGxE,MAAa,cAAc,EAAE,KAAK;CAAC;CAAU;CAAY;AAAO,CAAC;;;AAKjE,MAAa,aAAa,EAAE,OAAO;CACjC,IAAI,EAAE,OAAO;CACb,MAAM;CACN,OAAO,EAAE,OAAO;AAClB,CAAC;AAGD,MAAa,cAAc;AAG3B,MAAa,oBAAoB,UAAU,OAAO;CAChD,QAAQ,kBAAkB,SAAS;CACnC,QAAQ,EAAE,OAAO,CAAC,CAAC,SAAS;;CAE5B,WAAW,EAAE,OAAO,CAAC,CAAC,SAAS;;CAE/B,WAAW,EAAE,OAAO,CAAC,CAAC,SAAS;;CAE/B,MAAM,YAAY,SAAS;AAC7B,CAAC;AAGD,MAAa,mBAAmB,UAAU,WAAW;;AAIrD,MAAa,mBAAmB,EAC7B,OAAO;CACN,WAAW;CACX,WAAW,SAAS,QAAQ;CAC5B,UAAU,SAAS,QAAQ;CAC3B,WAAW,cAAc,SAAS,CAAC,CAAC,SAAS,sCAAsC;AACrF,CAAC,CAAC,CACD,QAAQ,MAAO,EAAE,aAAa,UAAW,EAAE,YAAY,OAAO,EAC7D,SAAS,+CACX,CAAC;AAGH,MAAa,oBAAoB,EAC9B,OAAO;CACN,WAAW;CACX,WAAW,SAAS,QAAQ;CAC5B,UAAU,SAAS,QAAQ;AAC7B,CAAC,CAAC,CACD,QAAQ,MAAO,EAAE,aAAa,UAAW,EAAE,YAAY,OAAO,EAC7D,SAAS,+CACX,CAAC"}