@headless-lms/server 0.3.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 (228) hide show
  1. package/README.md +14 -0
  2. package/dist/app/community-mail.d.ts +10 -10
  3. package/dist/app/community-mail.js +72 -28
  4. package/dist/app/community-mail.js.map +1 -1
  5. package/dist/app/container.d.ts +48 -10
  6. package/dist/app/container.js +268 -48
  7. package/dist/app/container.js.map +1 -1
  8. package/dist/app/notification-channels.d.ts +47 -0
  9. package/dist/app/notification-channels.js +175 -0
  10. package/dist/app/notification-channels.js.map +1 -0
  11. package/dist/app/notification-reads.d.ts +23 -0
  12. package/dist/app/notification-reads.js +74 -0
  13. package/dist/app/notification-reads.js.map +1 -0
  14. package/dist/app/platform.d.ts +14 -0
  15. package/dist/app/platform.js +14 -0
  16. package/dist/app/platform.js.map +1 -0
  17. package/dist/http/config.d.ts +4 -0
  18. package/dist/http/errors.d.ts +1 -0
  19. package/dist/http/errors.js +24 -4
  20. package/dist/http/errors.js.map +1 -1
  21. package/dist/http/fastify.d.ts +8 -0
  22. package/dist/http/mcp/catalogue.d.ts +11 -9
  23. package/dist/http/mcp/catalogue.js +15 -21
  24. package/dist/http/mcp/catalogue.js.map +1 -1
  25. package/dist/http/mcp/challenge.js +3 -3
  26. package/dist/http/mcp/challenge.js.map +1 -1
  27. package/dist/http/mcp/route.js +7 -7
  28. package/dist/http/mcp/route.js.map +1 -1
  29. package/dist/http/mcp/test-support.d.ts +6 -5
  30. package/dist/http/mcp/test-support.js +32 -11
  31. package/dist/http/mcp/test-support.js.map +1 -1
  32. package/dist/http/mcp/tool.d.ts +3 -9
  33. package/dist/http/mcp/tool.js +14 -6
  34. package/dist/http/mcp/tool.js.map +1 -1
  35. package/dist/http/mcp/tools/automations.js +10 -20
  36. package/dist/http/mcp/tools/automations.js.map +1 -1
  37. package/dist/http/mcp/tools/catalog.js +25 -42
  38. package/dist/http/mcp/tools/catalog.js.map +1 -1
  39. package/dist/http/mcp/tools/comments.js +9 -19
  40. package/dist/http/mcp/tools/comments.js.map +1 -1
  41. package/dist/http/mcp/tools/communities.js +16 -31
  42. package/dist/http/mcp/tools/communities.js.map +1 -1
  43. package/dist/http/mcp/tools/community-members.js +9 -16
  44. package/dist/http/mcp/tools/community-members.js.map +1 -1
  45. package/dist/http/mcp/tools/community-moderation.js +13 -25
  46. package/dist/http/mcp/tools/community-moderation.js.map +1 -1
  47. package/dist/http/mcp/tools/courses.js +11 -21
  48. package/dist/http/mcp/tools/courses.js.map +1 -1
  49. package/dist/http/mcp/tools/events.d.ts +6 -0
  50. package/dist/http/mcp/tools/events.js +170 -0
  51. package/dist/http/mcp/tools/events.js.map +1 -0
  52. package/dist/http/mcp/tools/index.d.ts +5 -1
  53. package/dist/http/mcp/tools/index.js +45 -10
  54. package/dist/http/mcp/tools/index.js.map +1 -1
  55. package/dist/http/mcp/tools/organization.d.ts +6 -0
  56. package/dist/http/mcp/tools/organization.js +214 -0
  57. package/dist/http/mcp/tools/organization.js.map +1 -0
  58. package/dist/http/mcp/tools/people.js +30 -49
  59. package/dist/http/mcp/tools/people.js.map +1 -1
  60. package/dist/http/plugins/auth.js +37 -8
  61. package/dist/http/plugins/auth.js.map +1 -1
  62. package/dist/http/plugins/error-handler.d.ts +5 -1
  63. package/dist/http/plugins/error-handler.js +13 -3
  64. package/dist/http/plugins/error-handler.js.map +1 -1
  65. package/dist/http/plugins/openapi.js +18 -2
  66. package/dist/http/plugins/openapi.js.map +1 -1
  67. package/dist/http/plugins/platform.d.ts +7 -0
  68. package/dist/http/plugins/platform.js +13 -0
  69. package/dist/http/plugins/platform.js.map +1 -0
  70. package/dist/http/routes/access.js +54 -36
  71. package/dist/http/routes/access.js.map +1 -1
  72. package/dist/http/routes/activities.js +45 -45
  73. package/dist/http/routes/activities.js.map +1 -1
  74. package/dist/http/routes/assets.js +30 -65
  75. package/dist/http/routes/assets.js.map +1 -1
  76. package/dist/http/routes/automations.js +37 -42
  77. package/dist/http/routes/automations.js.map +1 -1
  78. package/dist/http/routes/bundles.js +33 -36
  79. package/dist/http/routes/bundles.js.map +1 -1
  80. package/dist/http/routes/communities.js +144 -136
  81. package/dist/http/routes/communities.js.map +1 -1
  82. package/dist/http/routes/community-moderation.js +83 -137
  83. package/dist/http/routes/community-moderation.js.map +1 -1
  84. package/dist/http/routes/course-analytics.js +32 -15
  85. package/dist/http/routes/course-analytics.js.map +1 -1
  86. package/dist/http/routes/courses.js +25 -32
  87. package/dist/http/routes/courses.js.map +1 -1
  88. package/dist/http/routes/dashboard.js +9 -9
  89. package/dist/http/routes/dashboard.js.map +1 -1
  90. package/dist/http/routes/discussion.js +21 -39
  91. package/dist/http/routes/discussion.js.map +1 -1
  92. package/dist/http/routes/downloads.js +41 -47
  93. package/dist/http/routes/downloads.js.map +1 -1
  94. package/dist/http/routes/entitlements.js +19 -23
  95. package/dist/http/routes/entitlements.js.map +1 -1
  96. package/dist/http/routes/events.d.ts +7 -0
  97. package/dist/http/routes/events.js +333 -0
  98. package/dist/http/routes/events.js.map +1 -0
  99. package/dist/http/routes/integrations.js +40 -73
  100. package/dist/http/routes/integrations.js.map +1 -1
  101. package/dist/http/routes/member/assets.js +10 -13
  102. package/dist/http/routes/member/assets.js.map +1 -1
  103. package/dist/http/routes/member/chats.js +177 -75
  104. package/dist/http/routes/member/chats.js.map +1 -1
  105. package/dist/http/routes/member/comments.js +65 -26
  106. package/dist/http/routes/member/comments.js.map +1 -1
  107. package/dist/http/routes/member/community.js +68 -51
  108. package/dist/http/routes/member/community.js.map +1 -1
  109. package/dist/http/routes/member/courses.js +12 -19
  110. package/dist/http/routes/member/courses.js.map +1 -1
  111. package/dist/http/routes/member/devices.d.ts +7 -0
  112. package/dist/http/routes/member/devices.js +97 -0
  113. package/dist/http/routes/member/devices.js.map +1 -0
  114. package/dist/http/routes/member/downloads.js +6 -9
  115. package/dist/http/routes/member/downloads.js.map +1 -1
  116. package/dist/http/routes/member/events.d.ts +7 -0
  117. package/dist/http/routes/member/events.js +386 -0
  118. package/dist/http/routes/member/events.js.map +1 -0
  119. package/dist/http/routes/member/files.js +71 -46
  120. package/dist/http/routes/member/files.js.map +1 -1
  121. package/dist/http/routes/member/index.js +6 -0
  122. package/dist/http/routes/member/index.js.map +1 -1
  123. package/dist/http/routes/member/notification-settings.d.ts +7 -0
  124. package/dist/http/routes/member/notification-settings.js +100 -0
  125. package/dist/http/routes/member/notification-settings.js.map +1 -0
  126. package/dist/http/routes/member/notifications.js +69 -45
  127. package/dist/http/routes/member/notifications.js.map +1 -1
  128. package/dist/http/routes/member/org.js +5 -15
  129. package/dist/http/routes/member/org.js.map +1 -1
  130. package/dist/http/routes/member/posts.js +94 -95
  131. package/dist/http/routes/member/posts.js.map +1 -1
  132. package/dist/http/routes/member/profile.js +15 -6
  133. package/dist/http/routes/member/profile.js.map +1 -1
  134. package/dist/http/routes/member/progress.js +7 -11
  135. package/dist/http/routes/member/progress.js.map +1 -1
  136. package/dist/http/routes/organizations.js +415 -110
  137. package/dist/http/routes/organizations.js.map +1 -1
  138. package/dist/http/routes/platform.d.ts +7 -0
  139. package/dist/http/routes/platform.js +61 -0
  140. package/dist/http/routes/platform.js.map +1 -0
  141. package/dist/http/routes/students.js +12 -75
  142. package/dist/http/routes/students.js.map +1 -1
  143. package/dist/http/routes/webhooks.js +30 -39
  144. package/dist/http/routes/webhooks.js.map +1 -1
  145. package/dist/http/routes.js +9 -0
  146. package/dist/http/routes.js.map +1 -1
  147. package/dist/http/schemas/access.d.ts +346 -64
  148. package/dist/http/schemas/access.js +39 -12
  149. package/dist/http/schemas/access.js.map +1 -1
  150. package/dist/http/schemas/assets.d.ts +13 -8
  151. package/dist/http/schemas/assets.js +6 -5
  152. package/dist/http/schemas/assets.js.map +1 -1
  153. package/dist/http/schemas/automations.d.ts +4 -8
  154. package/dist/http/schemas/chats.d.ts +238 -36
  155. package/dist/http/schemas/chats.js +14 -7
  156. package/dist/http/schemas/chats.js.map +1 -1
  157. package/dist/http/schemas/community.d.ts +140 -33
  158. package/dist/http/schemas/community.js +25 -9
  159. package/dist/http/schemas/community.js.map +1 -1
  160. package/dist/http/schemas/course-analytics.d.ts +51 -1
  161. package/dist/http/schemas/course-analytics.js +19 -1
  162. package/dist/http/schemas/course-analytics.js.map +1 -1
  163. package/dist/http/schemas/dashboard.d.ts +1 -0
  164. package/dist/http/schemas/dashboard.js +2 -1
  165. package/dist/http/schemas/dashboard.js.map +1 -1
  166. package/dist/http/schemas/discussion.d.ts +45 -73
  167. package/dist/http/schemas/discussion.js +16 -4
  168. package/dist/http/schemas/discussion.js.map +1 -1
  169. package/dist/http/schemas/entitlements.d.ts +9 -12
  170. package/dist/http/schemas/entitlements.js +11 -5
  171. package/dist/http/schemas/entitlements.js.map +1 -1
  172. package/dist/http/schemas/events.d.ts +527 -0
  173. package/dist/http/schemas/events.js +64 -0
  174. package/dist/http/schemas/events.js.map +1 -0
  175. package/dist/http/schemas/files.d.ts +15 -5
  176. package/dist/http/schemas/files.js +10 -2
  177. package/dist/http/schemas/files.js.map +1 -1
  178. package/dist/http/schemas/index.d.ts +14 -12
  179. package/dist/http/schemas/index.js +14 -12
  180. package/dist/http/schemas/invites.d.ts +3 -47
  181. package/dist/http/schemas/invites.js +4 -25
  182. package/dist/http/schemas/invites.js.map +1 -1
  183. package/dist/http/schemas/member.d.ts +94 -7
  184. package/dist/http/schemas/member.js +7 -3
  185. package/dist/http/schemas/member.js.map +1 -1
  186. package/dist/http/schemas/members.d.ts +329 -65
  187. package/dist/http/schemas/members.js +67 -25
  188. package/dist/http/schemas/members.js.map +1 -1
  189. package/dist/http/schemas/notifications.d.ts +502 -175
  190. package/dist/http/schemas/notifications.js +148 -28
  191. package/dist/http/schemas/notifications.js.map +1 -1
  192. package/dist/http/schemas/platform.d.ts +37 -0
  193. package/dist/http/schemas/platform.js +19 -0
  194. package/dist/http/schemas/platform.js.map +1 -0
  195. package/dist/http/schemas/posts.d.ts +92 -38
  196. package/dist/http/schemas/posts.js +4 -4
  197. package/dist/http/schemas/posts.js.map +1 -1
  198. package/dist/http/schemas/profile.d.ts +1 -1
  199. package/dist/http/schemas/shared.d.ts +10 -13
  200. package/dist/http/schemas/shared.js +3 -11
  201. package/dist/http/schemas/shared.js.map +1 -1
  202. package/dist/http/schemas/students.d.ts +22 -0
  203. package/dist/http/schemas/students.js +3 -1
  204. package/dist/http/schemas/students.js.map +1 -1
  205. package/dist/http/scope.d.ts +9 -12
  206. package/dist/http/scope.js +30 -35
  207. package/dist/http/scope.js.map +1 -1
  208. package/dist/http/server.js +9 -0
  209. package/dist/http/server.js.map +1 -1
  210. package/dist/http/shutdown.d.ts +11 -0
  211. package/dist/http/shutdown.js +40 -0
  212. package/dist/http/shutdown.js.map +1 -0
  213. package/dist/http/sse.d.ts +19 -0
  214. package/dist/http/sse.js +104 -0
  215. package/dist/http/sse.js.map +1 -0
  216. package/dist/http/test-caller.d.ts +13 -0
  217. package/dist/http/test-caller.js +14 -0
  218. package/dist/http/test-caller.js.map +1 -0
  219. package/dist/http/well-known.js +2 -2
  220. package/dist/http/well-known.js.map +1 -1
  221. package/dist/index.d.ts +5 -2
  222. package/dist/index.js +4 -2
  223. package/dist/index.js.map +1 -1
  224. package/dist/packages/server/package.js +1 -1
  225. package/package.json +7 -6
  226. package/dist/http/routes/member/actor.d.ts +0 -14
  227. package/dist/http/routes/member/actor.js +0 -11
  228. package/dist/http/routes/member/actor.js.map +0 -1
@@ -1,19 +1,53 @@
1
- import { paginated } from "./shared.js";
1
+ import { PageQuery, paginated } from "./shared.js";
2
2
  import { z } from "zod";
3
- import { notificationKindSchema, notificationPreferenceSchema, notificationSchema } from "@headless-lms/core/schemas";
3
+ import { digestScheduleSchema, jsonValueSchema, notificationCategoryKeySchema, notificationCategoryListSchema, notificationCategorySchema, notificationChannelKeySchema, notificationScopeSchema, notificationTypeKeySchema, reasonSchema, subjectTypeSchema } from "@headless-lms/core/schemas";
4
4
  //#region src/http/schemas/notifications.ts
5
- const Notification = notificationSchema;
6
5
  const NotificationIdParam = z.object({ notificationId: z.string() });
6
+ function commaSeparated(item, description) {
7
+ return z.string().max(2e3).transform((value) => value.split(",").map((part) => part.trim()).filter((part) => part.length > 0)).pipe(z.array(item).min(1).max(50)).describe(description);
8
+ }
9
+ function scopeMatchesCommunity(filter, ctx) {
10
+ if (filter.scope === "org" && filter.communityId !== void 0) ctx.addIssue({
11
+ code: "custom",
12
+ path: ["communityId"],
13
+ message: "`communityId` implies `scope=community`; it cannot go with `scope=org`"
14
+ });
15
+ if (filter.includeOrg === true && filter.communityId === void 0) ctx.addIssue({
16
+ code: "custom",
17
+ path: ["includeOrg"],
18
+ message: "`includeOrg` goes with `communityId`"
19
+ });
20
+ if (filter.includeOrg === true && filter.scope !== void 0) ctx.addIssue({
21
+ code: "custom",
22
+ path: ["includeOrg"],
23
+ message: "`includeOrg` cannot go with `scope`"
24
+ });
25
+ }
26
+ const notificationFilterShape = z.object({
27
+ scope: z.enum(["org", "community"]).optional().describe("`org`: the org list only; `community`: notifications in any community"),
28
+ communityId: z.string().min(1).max(64).optional().describe("Notifications in this community; implies `scope=community`"),
29
+ includeOrg: z.stringbool().optional().describe("With `communityId`, `true` adds the org list (notifications in no community); not with `scope`"),
30
+ category: commaSeparated(notificationCategoryKeySchema, "One or more category keys, comma separated").optional(),
31
+ reason: commaSeparated(reasonSchema, "One or more reasons, comma separated; matches any").optional(),
32
+ type: commaSeparated(notificationTypeKeySchema, "One or more types, comma separated").optional(),
33
+ unread: z.stringbool().optional().describe("`true` for unread notifications only")
34
+ }).strict();
35
+ const NotificationFilterQuery = notificationFilterShape.superRefine(scopeMatchesCommunity);
36
+ const NotificationListQuery = PageQuery.extend(notificationFilterShape.shape).strict().superRefine(scopeMatchesCommunity);
37
+ const NotificationItem = z.object({
38
+ type: subjectTypeSchema,
39
+ id: z.string(),
40
+ title: z.string().optional(),
41
+ excerpt: z.string().optional()
42
+ });
7
43
  const NotificationView = z.object({
8
44
  id: z.string(),
9
- kind: notificationKindSchema,
10
- createdAt: z.coerce.date(),
11
- readAt: z.coerce.date().nullable(),
12
- actor: z.object({
13
- orgUserId: z.string(),
14
- displayName: z.string().nullable(),
15
- imageUrl: z.string().nullable()
16
- }).nullable(),
45
+ type: z.string(),
46
+ scope: notificationScopeSchema,
47
+ reasons: z.array(reasonSchema),
48
+ matchedReason: reasonSchema.describe("The reason of the pair the category matched, which picks the wording, such as a reply to your comment"),
49
+ category: z.string(),
50
+ display: z.record(z.string(), jsonValueSchema).describe("The text stored when the notification was sent"),
17
51
  community: z.object({
18
52
  id: z.string(),
19
53
  title: z.string()
@@ -22,23 +56,109 @@ const NotificationView = z.object({
22
56
  id: z.string(),
23
57
  name: z.string()
24
58
  }).nullable(),
25
- post: z.object({
26
- id: z.string(),
27
- title: z.string()
28
- }).nullable().describe("Null when the viewer can no longer see the post"),
29
- commentId: z.string().nullable(),
30
- chat: z.object({
31
- id: z.string(),
32
- title: z.string()
33
- }).nullable().describe("Null when the viewer is not in the chat"),
34
- messageId: z.string().nullable()
35
- });
36
- const NotificationsPage = paginated(NotificationView).extend({ unreadCount: z.number().int() });
37
- const MarkedRead = z.object({ updated: z.number().int() });
38
- const NotificationPreference = notificationPreferenceSchema;
39
- const NotificationPreferences = z.array(NotificationPreference);
40
- const SetNotificationPreferences = z.object({ preferences: z.array(NotificationPreference).min(1).max(notificationKindSchema.options.length).refine((preferences) => new Set(preferences.map((p) => p.kind)).size === preferences.length, { message: "must name each kind at most once" }).describe("One entry per kind to change, each kind at most once; kinds left out keep theirs") }).strict();
59
+ actor: z.object({
60
+ orgUserId: z.string(),
61
+ name: z.string().nullable(),
62
+ imageUrl: z.string().nullable()
63
+ }).nullable(),
64
+ subject: NotificationItem.nullable().describe("What the notification is about, with its current title or excerpt; null when you can no longer open it or it was deleted"),
65
+ parent: NotificationItem.nullable().describe("The subject's container, such as a comment's post; null when you can no longer open it or it was deleted"),
66
+ createdAt: z.coerce.date(),
67
+ readAt: z.coerce.date().nullable()
68
+ });
69
+ const NotificationsPage = paginated(NotificationView).extend({ unreadCount: z.number().int().describe("Unread notifications matching the same filters") });
70
+ const NotificationUnreadCounts = z.object({
71
+ org: z.number().int(),
72
+ communities: z.array(z.object({
73
+ communityId: z.string(),
74
+ unread: z.number().int()
75
+ }))
76
+ });
77
+ const NotificationCategory = notificationCategorySchema;
78
+ const NotificationCategoryList = z.object({
79
+ categories: z.array(NotificationCategory),
80
+ source: z.enum(["default", "stored"]).describe("`default` while the list in use is the server default, `stored` once one is saved")
81
+ });
82
+ const ReplaceNotificationCategories = z.object({ categories: notificationCategoryListSchema.describe("The whole ordered list; a notification is filed under the first category that matches") }).strict();
83
+ const NotificationCategoryDefaults = z.object({ categories: z.array(NotificationCategory) });
84
+ const NotificationListScopeQuery = z.object({ scope: z.enum(["org", "community"]) }).strict();
85
+ const NotificationTypeInfo = z.object({
86
+ type: z.string(),
87
+ scopes: z.array(notificationScopeSchema),
88
+ reasons: z.array(reasonSchema)
89
+ });
90
+ const NotificationTypeInfos = z.array(NotificationTypeInfo);
91
+ const NotificationChannelInfos = z.array(z.object({ channel: z.string() }));
92
+ const ResolvedChannel = z.object({
93
+ channel: z.string(),
94
+ enabled: z.boolean(),
95
+ default: z.boolean().describe("What the channel would be without your own setting at this level: what `enabled: null` gives"),
96
+ source: z.enum([
97
+ "locked",
98
+ "space",
99
+ "community",
100
+ "spaceDefault",
101
+ "default"
102
+ ]).describe("Why the channel is on or off: locked by the category, your setting for the space, your setting for the whole community (or the org), the default for the space, or the category default"),
103
+ locked: z.boolean()
104
+ });
105
+ const NotificationSettingsCategory = z.object({
106
+ key: z.string(),
107
+ perSpace: z.boolean(),
108
+ channels: z.array(ResolvedChannel),
109
+ spaces: z.array(z.object({
110
+ spaceId: z.string(),
111
+ name: z.string(),
112
+ channels: z.array(ResolvedChannel)
113
+ })).optional().describe("Per-space categories only: every space you can open")
114
+ });
115
+ const CommunityNotificationSettings = z.object({
116
+ communityId: z.string(),
117
+ digest: digestScheduleSchema.nullable().describe("The community's digest schedule; null when it sends no digest"),
118
+ categories: z.array(NotificationSettingsCategory)
119
+ });
120
+ const OrgNotificationSettings = z.object({ categories: z.array(NotificationSettingsCategory) });
121
+ const PatchNotificationSettings = z.object({ settings: z.array(z.object({
122
+ category: notificationCategoryKeySchema,
123
+ spaceId: z.string().min(1).max(64).optional(),
124
+ channel: notificationChannelKeySchema,
125
+ enabled: z.boolean().nullable().describe("null removes your choice, so the default applies again")
126
+ }).strict()).min(1).max(200) }).strict();
127
+ const DeviceFields = {
128
+ id: z.string(),
129
+ provider: z.enum([
130
+ "apns",
131
+ "fcm",
132
+ "webpush"
133
+ ]),
134
+ token: z.string(),
135
+ p256dh: z.string().nullable(),
136
+ auth: z.string().nullable(),
137
+ appId: z.string().nullable(),
138
+ environment: z.enum(["production", "sandbox"]).nullable()
139
+ };
140
+ const Device = z.object(DeviceFields);
141
+ const DeviceList = z.array(z.object({
142
+ ...DeviceFields,
143
+ lastSeenAt: z.coerce.date()
144
+ }));
145
+ const DeviceIdParam = z.object({ deviceId: z.string() });
146
+ const RegisterDevice = z.object({
147
+ provider: z.enum([
148
+ "apns",
149
+ "fcm",
150
+ "webpush"
151
+ ]),
152
+ token: z.string().min(1).max(4096).describe("The APNs device token, the FCM registration token, or the Web Push endpoint URL"),
153
+ keys: z.object({
154
+ p256dh: z.string().min(1).max(512),
155
+ auth: z.string().min(1).max(512)
156
+ }).strict().optional().describe("The Web Push subscription keys; webpush only"),
157
+ appId: z.string().min(1).max(255).optional().describe("The iOS bundle id or Android package name"),
158
+ environment: z.enum(["production", "sandbox"]).optional().describe("apns only")
159
+ }).strict();
160
+ const PushConfigView = z.object({ vapidPublicKey: z.string().nullable() });
41
161
  //#endregion
42
- export { MarkedRead, Notification, NotificationIdParam, NotificationPreference, NotificationPreferences, NotificationView, NotificationsPage, SetNotificationPreferences };
162
+ export { CommunityNotificationSettings, Device, DeviceIdParam, DeviceList, NotificationCategory, NotificationCategoryDefaults, NotificationCategoryList, NotificationChannelInfos, NotificationFilterQuery, NotificationIdParam, NotificationListQuery, NotificationListScopeQuery, NotificationTypeInfo, NotificationTypeInfos, NotificationUnreadCounts, NotificationView, NotificationsPage, OrgNotificationSettings, PatchNotificationSettings, PushConfigView, RegisterDevice, ReplaceNotificationCategories };
43
163
 
44
164
  //# sourceMappingURL=notifications.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"notifications.js","names":[],"sources":["../../../src/http/schemas/notifications.ts"],"sourcesContent":["import { z } from 'zod';\nimport {\n notificationKindSchema,\n notificationPreferenceSchema,\n notificationSchema,\n} from '@headless-lms/core/schemas';\nimport type { NotificationView as DomainNotificationView } from '@headless-lms/core/reporting/member';\nimport { paginated, type Matches } from './shared.js';\n\nexport const Notification = notificationSchema;\nexport const NotificationIdParam = z.object({ notificationId: z.string() });\n\nexport const NotificationView = z.object({\n id: z.string(),\n kind: notificationKindSchema,\n createdAt: z.coerce.date(),\n readAt: z.coerce.date().nullable(),\n actor: z\n .object({\n orgUserId: z.string(),\n displayName: z.string().nullable(),\n imageUrl: z.string().nullable(),\n })\n .nullable(),\n community: z.object({ id: z.string(), title: z.string() }).nullable(),\n space: z.object({ id: z.string(), name: z.string() }).nullable(),\n post: z\n .object({ id: z.string(), title: z.string() })\n .nullable()\n .describe('Null when the viewer can no longer see the post'),\n commentId: z.string().nullable(),\n chat: z\n .object({ id: z.string(), title: z.string() })\n .nullable()\n .describe('Null when the viewer is not in the chat'),\n messageId: z.string().nullable(),\n});\ntype _NotificationViewMatches = Matches<DomainNotificationView, z.infer<typeof NotificationView>> &\n Matches<z.infer<typeof NotificationView>, DomainNotificationView>;\n\nexport const NotificationsPage = paginated(NotificationView).extend({\n unreadCount: z.number().int(),\n});\n\nexport const MarkedRead = z.object({ updated: z.number().int() });\n\nexport const NotificationPreference = notificationPreferenceSchema;\nexport const NotificationPreferences = z.array(NotificationPreference);\nexport const SetNotificationPreferences = z\n .object({\n preferences: z\n .array(NotificationPreference)\n .min(1)\n .max(notificationKindSchema.options.length)\n .refine(\n (preferences) => new Set(preferences.map((p) => p.kind)).size === preferences.length,\n { message: 'must name each kind at most once' },\n )\n .describe('One entry per kind to change, each kind at most once; kinds left out keep theirs'),\n })\n .strict();\n"],"mappings":";;;;AASA,MAAa,eAAe;AAC5B,MAAa,sBAAsB,EAAE,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,CAAC;AAE1E,MAAa,mBAAmB,EAAE,OAAO;CACvC,IAAI,EAAE,OAAO;CACb,MAAM;CACN,WAAW,EAAE,OAAO,KAAK;CACzB,QAAQ,EAAE,OAAO,KAAK,CAAC,CAAC,SAAS;CACjC,OAAO,EACJ,OAAO;EACN,WAAW,EAAE,OAAO;EACpB,aAAa,EAAE,OAAO,CAAC,CAAC,SAAS;EACjC,UAAU,EAAE,OAAO,CAAC,CAAC,SAAS;CAChC,CAAC,CAAC,CACD,SAAS;CACZ,WAAW,EAAE,OAAO;EAAE,IAAI,EAAE,OAAO;EAAG,OAAO,EAAE,OAAO;CAAE,CAAC,CAAC,CAAC,SAAS;CACpE,OAAO,EAAE,OAAO;EAAE,IAAI,EAAE,OAAO;EAAG,MAAM,EAAE,OAAO;CAAE,CAAC,CAAC,CAAC,SAAS;CAC/D,MAAM,EACH,OAAO;EAAE,IAAI,EAAE,OAAO;EAAG,OAAO,EAAE,OAAO;CAAE,CAAC,CAAC,CAC7C,SAAS,CAAC,CACV,SAAS,iDAAiD;CAC7D,WAAW,EAAE,OAAO,CAAC,CAAC,SAAS;CAC/B,MAAM,EACH,OAAO;EAAE,IAAI,EAAE,OAAO;EAAG,OAAO,EAAE,OAAO;CAAE,CAAC,CAAC,CAC7C,SAAS,CAAC,CACV,SAAS,yCAAyC;CACrD,WAAW,EAAE,OAAO,CAAC,CAAC,SAAS;AACjC,CAAC;AAID,MAAa,oBAAoB,UAAU,gBAAgB,CAAC,CAAC,OAAO,EAClE,aAAa,EAAE,OAAO,CAAC,CAAC,IAAI,EAC9B,CAAC;AAED,MAAa,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;AAEhE,MAAa,yBAAyB;AACtC,MAAa,0BAA0B,EAAE,MAAM,sBAAsB;AACrE,MAAa,6BAA6B,EACvC,OAAO,EACN,aAAa,EACV,MAAM,sBAAsB,CAAC,CAC7B,IAAI,CAAC,CAAC,CACN,IAAI,uBAAuB,QAAQ,MAAM,CAAC,CAC1C,QACE,gBAAgB,IAAI,IAAI,YAAY,KAAK,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,SAAS,YAAY,QAC9E,EAAE,SAAS,mCAAmC,CAChD,CAAC,CACA,SAAS,kFAAkF,EAChG,CAAC,CAAC,CACD,OAAO"}
1
+ {"version":3,"file":"notifications.js","names":[],"sources":["../../../src/http/schemas/notifications.ts"],"sourcesContent":["import { z } from 'zod';\nimport {\n digestScheduleSchema,\n jsonValueSchema,\n notificationCategoryKeySchema,\n notificationChannelKeySchema,\n notificationCategoryListSchema,\n notificationCategorySchema,\n notificationScopeSchema,\n notificationTypeKeySchema,\n reasonSchema,\n subjectTypeSchema,\n} from '@headless-lms/core/schemas';\nimport type {\n CommunityNotificationSettingsView as DomainCommunityNotificationSettingsView,\n NotificationUnreadCounts as DomainNotificationUnreadCounts,\n NotificationView as DomainNotificationView,\n} from '@headless-lms/core/reporting/member';\nimport { PageQuery, paginated, type Matches } from './shared.js';\n\nexport const NotificationIdParam = z.object({ notificationId: z.string() });\n\nfunction commaSeparated<T extends string>(item: z.ZodType<T, string>, description: string) {\n return z\n .string()\n .max(2000)\n .transform((value) =>\n value\n .split(',')\n .map((part) => part.trim())\n .filter((part) => part.length > 0),\n )\n .pipe(z.array(item).min(1).max(50))\n .describe(description);\n}\n\nfunction scopeMatchesCommunity(\n filter: { scope?: 'org' | 'community'; communityId?: string; includeOrg?: boolean },\n ctx: z.RefinementCtx,\n): void {\n if (filter.scope === 'org' && filter.communityId !== undefined) {\n ctx.addIssue({\n code: 'custom',\n path: ['communityId'],\n message: '`communityId` implies `scope=community`; it cannot go with `scope=org`',\n });\n }\n if (filter.includeOrg === true && filter.communityId === undefined) {\n ctx.addIssue({\n code: 'custom',\n path: ['includeOrg'],\n message: '`includeOrg` goes with `communityId`',\n });\n }\n if (filter.includeOrg === true && filter.scope !== undefined) {\n ctx.addIssue({\n code: 'custom',\n path: ['includeOrg'],\n message: '`includeOrg` cannot go with `scope`',\n });\n }\n}\n\nconst notificationFilterShape = z\n .object({\n scope: z\n .enum(['org', 'community'])\n .optional()\n .describe('`org`: the org list only; `community`: notifications in any community'),\n communityId: z\n .string()\n .min(1)\n .max(64)\n .optional()\n .describe('Notifications in this community; implies `scope=community`'),\n includeOrg: z\n .stringbool()\n .optional()\n .describe(\n 'With `communityId`, `true` adds the org list (notifications in no community); not with `scope`',\n ),\n category: commaSeparated(\n notificationCategoryKeySchema,\n 'One or more category keys, comma separated',\n ).optional(),\n reason: commaSeparated(\n reasonSchema,\n 'One or more reasons, comma separated; matches any',\n ).optional(),\n type: commaSeparated(\n notificationTypeKeySchema,\n 'One or more types, comma separated',\n ).optional(),\n unread: z.stringbool().optional().describe('`true` for unread notifications only'),\n })\n .strict();\n\nexport const NotificationFilterQuery = notificationFilterShape.superRefine(scopeMatchesCommunity);\n\nexport const NotificationListQuery = PageQuery.extend(notificationFilterShape.shape)\n .strict()\n .superRefine(scopeMatchesCommunity);\n\nconst NotificationItem = z.object({\n type: subjectTypeSchema,\n id: z.string(),\n title: z.string().optional(),\n excerpt: z.string().optional(),\n});\n\nexport const NotificationView = z.object({\n id: z.string(),\n type: z.string(),\n scope: notificationScopeSchema,\n reasons: z.array(reasonSchema),\n matchedReason: reasonSchema.describe(\n 'The reason of the pair the category matched, which picks the wording, such as a reply to your comment',\n ),\n category: z.string(),\n display: z\n .record(z.string(), jsonValueSchema)\n .describe('The text stored when the notification was sent'),\n community: z.object({ id: z.string(), title: z.string() }).nullable(),\n space: z.object({ id: z.string(), name: z.string() }).nullable(),\n actor: z\n .object({\n orgUserId: z.string(),\n name: z.string().nullable(),\n imageUrl: z.string().nullable(),\n })\n .nullable(),\n subject: NotificationItem.nullable().describe(\n 'What the notification is about, with its current title or excerpt; null when you can no longer open it or it was deleted',\n ),\n parent: NotificationItem.nullable().describe(\n \"The subject's container, such as a comment's post; null when you can no longer open it or it was deleted\",\n ),\n createdAt: z.coerce.date(),\n readAt: z.coerce.date().nullable(),\n});\ntype _NotificationViewMatches = Matches<DomainNotificationView, z.infer<typeof NotificationView>> &\n Matches<z.infer<typeof NotificationView>, DomainNotificationView>;\n\nexport const NotificationsPage = paginated(NotificationView).extend({\n unreadCount: z.number().int().describe('Unread notifications matching the same filters'),\n});\n\nexport const NotificationUnreadCounts = z.object({\n org: z.number().int(),\n communities: z.array(z.object({ communityId: z.string(), unread: z.number().int() })),\n});\ntype _NotificationUnreadCountsMatches = Matches<\n DomainNotificationUnreadCounts,\n z.infer<typeof NotificationUnreadCounts>\n>;\n\nexport const NotificationCategory = notificationCategorySchema;\n\nexport const NotificationCategoryList = z.object({\n categories: z.array(NotificationCategory),\n source: z\n .enum(['default', 'stored'])\n .describe('`default` while the list in use is the server default, `stored` once one is saved'),\n});\n\nexport const ReplaceNotificationCategories = z\n .object({\n categories: notificationCategoryListSchema.describe(\n 'The whole ordered list; a notification is filed under the first category that matches',\n ),\n })\n .strict();\n\nexport const NotificationCategoryDefaults = z.object({ categories: z.array(NotificationCategory) });\n\nexport const NotificationListScopeQuery = z\n .object({ scope: z.enum(['org', 'community']) })\n .strict();\n\nexport const NotificationTypeInfo = z.object({\n type: z.string(),\n scopes: z.array(notificationScopeSchema),\n reasons: z.array(reasonSchema),\n});\nexport const NotificationTypeInfos = z.array(NotificationTypeInfo);\n\nexport const NotificationChannelInfos = z.array(z.object({ channel: z.string() }));\n\nconst ResolvedChannel = z.object({\n channel: z.string(),\n enabled: z.boolean(),\n default: z\n .boolean()\n .describe(\n 'What the channel would be without your own setting at this level: what `enabled: null` gives',\n ),\n source: z\n .enum(['locked', 'space', 'community', 'spaceDefault', 'default'])\n .describe(\n 'Why the channel is on or off: locked by the category, your setting for the space, your setting for the whole community (or the org), the default for the space, or the category default',\n ),\n locked: z.boolean(),\n});\n\nconst NotificationSettingsCategory = z.object({\n key: z.string(),\n perSpace: z.boolean(),\n channels: z.array(ResolvedChannel),\n spaces: z\n .array(z.object({ spaceId: z.string(), name: z.string(), channels: z.array(ResolvedChannel) }))\n .optional()\n .describe('Per-space categories only: every space you can open'),\n});\n\nexport const CommunityNotificationSettings = z.object({\n communityId: z.string(),\n digest: digestScheduleSchema\n .nullable()\n .describe(\"The community's digest schedule; null when it sends no digest\"),\n categories: z.array(NotificationSettingsCategory),\n});\ntype _CommunityNotificationSettingsMatches = Matches<\n DomainCommunityNotificationSettingsView,\n z.infer<typeof CommunityNotificationSettings>\n>;\n\nexport const OrgNotificationSettings = z.object({\n categories: z.array(NotificationSettingsCategory),\n});\n\nexport const PatchNotificationSettings = z\n .object({\n settings: z\n .array(\n z\n .object({\n category: notificationCategoryKeySchema,\n spaceId: z.string().min(1).max(64).optional(),\n channel: notificationChannelKeySchema,\n enabled: z\n .boolean()\n .nullable()\n .describe('null removes your choice, so the default applies again'),\n })\n .strict(),\n )\n .min(1)\n .max(200),\n })\n .strict();\n\nconst DeviceFields = {\n id: z.string(),\n provider: z.enum(['apns', 'fcm', 'webpush']),\n token: z.string(),\n p256dh: z.string().nullable(),\n auth: z.string().nullable(),\n appId: z.string().nullable(),\n environment: z.enum(['production', 'sandbox']).nullable(),\n};\n\nexport const Device = z.object(DeviceFields);\nexport const DeviceList = z.array(z.object({ ...DeviceFields, lastSeenAt: z.coerce.date() }));\nexport const DeviceIdParam = z.object({ deviceId: z.string() });\n\nexport const RegisterDevice = z\n .object({\n provider: z.enum(['apns', 'fcm', 'webpush']),\n token: z\n .string()\n .min(1)\n .max(4096)\n .describe('The APNs device token, the FCM registration token, or the Web Push endpoint URL'),\n keys: z\n .object({ p256dh: z.string().min(1).max(512), auth: z.string().min(1).max(512) })\n .strict()\n .optional()\n .describe('The Web Push subscription keys; webpush only'),\n appId: z\n .string()\n .min(1)\n .max(255)\n .optional()\n .describe('The iOS bundle id or Android package name'),\n environment: z.enum(['production', 'sandbox']).optional().describe('apns only'),\n })\n .strict();\n\nexport const PushConfigView = z.object({ vapidPublicKey: z.string().nullable() });\n"],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import { z } from "zod";
2
+ //#region src/http/schemas/platform.d.ts
3
+ declare const CreatePlatformOrganization: z.ZodObject<{
4
+ name: z.ZodString;
5
+ slug: z.ZodString;
6
+ keyName: z.ZodOptional<z.ZodString>;
7
+ }, z.core.$strip>;
8
+ declare const PlatformOrganization: z.ZodObject<{
9
+ organization: z.ZodObject<{
10
+ id: z.ZodString;
11
+ name: z.ZodString;
12
+ slug: z.ZodString;
13
+ createdAt: z.ZodString;
14
+ }, z.core.$strip>;
15
+ apiKey: z.ZodObject<{
16
+ id: z.ZodString;
17
+ name: z.ZodNullable<z.ZodString>;
18
+ start: z.ZodNullable<z.ZodString>;
19
+ role: z.ZodNullable<z.ZodObject<{
20
+ key: z.ZodString;
21
+ name: z.ZodNullable<z.ZodString>;
22
+ }, z.core.$strip>>;
23
+ createdAt: z.ZodCoercedDate<unknown>;
24
+ lastUsedAt: z.ZodNullable<z.ZodCoercedDate<unknown>>;
25
+ expiresAt: z.ZodNullable<z.ZodCoercedDate<unknown>>;
26
+ key: z.ZodString;
27
+ }, z.core.$strip>;
28
+ }, z.core.$strip>;
29
+ declare const CreatePlatformApiKey: z.ZodObject<{
30
+ name: z.ZodString;
31
+ }, z.core.$strip>;
32
+ declare const PlatformOrgIdParam: z.ZodObject<{
33
+ orgId: z.ZodString;
34
+ }, z.core.$strip>;
35
+ //#endregion
36
+ export { CreatePlatformApiKey, CreatePlatformOrganization, PlatformOrgIdParam, PlatformOrganization };
37
+ //# sourceMappingURL=platform.d.ts.map
@@ -0,0 +1,19 @@
1
+ import { Organization } from "./organizations.js";
2
+ import { ApiKeyName, CreatedApiKey } from "./access.js";
3
+ import { z } from "zod";
4
+ //#region src/http/schemas/platform.ts
5
+ const CreatePlatformOrganization = z.object({
6
+ name: z.string().trim().min(1).max(100),
7
+ slug: z.string().min(1).max(50).regex(/^[a-z0-9-]+$/, "Use lowercase letters, numbers, and hyphens only"),
8
+ keyName: ApiKeyName.optional().describe("The name of the API key created with it. Default `Platform`")
9
+ });
10
+ const PlatformOrganization = z.object({
11
+ organization: Organization,
12
+ apiKey: CreatedApiKey
13
+ });
14
+ const CreatePlatformApiKey = z.object({ name: ApiKeyName });
15
+ const PlatformOrgIdParam = z.object({ orgId: z.string() });
16
+ //#endregion
17
+ export { CreatePlatformApiKey, CreatePlatformOrganization, PlatformOrgIdParam, PlatformOrganization };
18
+
19
+ //# sourceMappingURL=platform.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform.js","names":[],"sources":["../../../src/http/schemas/platform.ts"],"sourcesContent":["import { z } from 'zod';\nimport { ApiKeyName, CreatedApiKey } from './access.js';\nimport { Organization } from './organizations.js';\n\nexport const CreatePlatformOrganization = z.object({\n name: z.string().trim().min(1).max(100),\n slug: z\n .string()\n .min(1)\n .max(50)\n .regex(/^[a-z0-9-]+$/, 'Use lowercase letters, numbers, and hyphens only'),\n keyName: ApiKeyName.optional().describe(\n 'The name of the API key created with it. Default `Platform`',\n ),\n});\n\nexport const PlatformOrganization = z.object({\n organization: Organization,\n apiKey: CreatedApiKey,\n});\n\nexport const CreatePlatformApiKey = z.object({ name: ApiKeyName });\n\nexport const PlatformOrgIdParam = z.object({ orgId: z.string() });\n"],"mappings":";;;;AAIA,MAAa,6BAA6B,EAAE,OAAO;CACjD,MAAM,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG;CACtC,MAAM,EACH,OAAO,CAAC,CACR,IAAI,CAAC,CAAC,CACN,IAAI,EAAE,CAAC,CACP,MAAM,gBAAgB,kDAAkD;CAC3E,SAAS,WAAW,SAAS,CAAC,CAAC,SAC7B,6DACF;AACF,CAAC;AAED,MAAa,uBAAuB,EAAE,OAAO;CAC3C,cAAc;CACd,QAAQ;AACV,CAAC;AAED,MAAa,uBAAuB,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEjE,MAAa,qBAAqB,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC"}
@@ -27,6 +27,17 @@ declare const PostView: z.ZodObject<{
27
27
  createdAt: z.ZodCoercedDate<unknown>;
28
28
  updatedAt: z.ZodCoercedDate<unknown>;
29
29
  coverUrl: z.ZodNullable<z.ZodString>;
30
+ assets: z.ZodRecord<z.ZodString, z.ZodObject<{
31
+ url: z.ZodString;
32
+ kind: z.ZodEnum<{
33
+ image: "image";
34
+ video: "video";
35
+ audio: "audio";
36
+ document: "document";
37
+ }>;
38
+ filename: z.ZodString;
39
+ size: z.ZodNumber;
40
+ }, z.core.$strict>>;
30
41
  author: z.ZodObject<{
31
42
  id: z.ZodString;
32
43
  firstName: z.ZodNullable<z.ZodString>;
@@ -36,19 +47,24 @@ declare const PostView: z.ZodObject<{
36
47
  image: z.ZodNullable<z.ZodString>;
37
48
  imageAssetId: z.ZodNullable<z.ZodString>;
38
49
  imageUrl: z.ZodNullable<z.ZodString>;
39
- role: z.ZodEnum<{
40
- owner: "owner";
41
- admin: "admin";
42
- instructor: "instructor";
43
- moderator: "moderator";
44
- student: "student";
45
- }>;
50
+ team: z.ZodBoolean;
51
+ roleName: z.ZodNullable<z.ZodString>;
46
52
  }, z.core.$strict>;
47
53
  reactions: z.ZodRecord<z.ZodString, z.ZodNumber>;
48
54
  viewerReaction: z.ZodNullable<z.ZodString>;
49
55
  commentCount: z.ZodNumber;
50
- following: z.ZodBoolean;
56
+ subscription: z.ZodNullable<z.ZodObject<{
57
+ state: z.ZodEnum<{
58
+ following: "following";
59
+ muted: "muted";
60
+ }>;
61
+ mutedUntil: z.ZodNullable<z.ZodCoercedDate<unknown>>;
62
+ }, z.core.$strict>>;
51
63
  bookmarked: z.ZodBoolean;
64
+ mentions: z.ZodArray<z.ZodObject<{
65
+ orgUserId: z.ZodString;
66
+ name: z.ZodString;
67
+ }, z.core.$strict>>;
52
68
  }, z.core.$strict>;
53
69
  declare const PostFlag: z.ZodObject<{
54
70
  orgId: z.ZodString;
@@ -93,6 +109,17 @@ declare const PostFeedPage: z.ZodObject<{
93
109
  createdAt: z.ZodCoercedDate<unknown>;
94
110
  updatedAt: z.ZodCoercedDate<unknown>;
95
111
  coverUrl: z.ZodNullable<z.ZodString>;
112
+ assets: z.ZodRecord<z.ZodString, z.ZodObject<{
113
+ url: z.ZodString;
114
+ kind: z.ZodEnum<{
115
+ image: "image";
116
+ video: "video";
117
+ audio: "audio";
118
+ document: "document";
119
+ }>;
120
+ filename: z.ZodString;
121
+ size: z.ZodNumber;
122
+ }, z.core.$strict>>;
96
123
  author: z.ZodObject<{
97
124
  id: z.ZodString;
98
125
  firstName: z.ZodNullable<z.ZodString>;
@@ -102,19 +129,24 @@ declare const PostFeedPage: z.ZodObject<{
102
129
  image: z.ZodNullable<z.ZodString>;
103
130
  imageAssetId: z.ZodNullable<z.ZodString>;
104
131
  imageUrl: z.ZodNullable<z.ZodString>;
105
- role: z.ZodEnum<{
106
- owner: "owner";
107
- admin: "admin";
108
- instructor: "instructor";
109
- moderator: "moderator";
110
- student: "student";
111
- }>;
132
+ team: z.ZodBoolean;
133
+ roleName: z.ZodNullable<z.ZodString>;
112
134
  }, z.core.$strict>;
113
135
  reactions: z.ZodRecord<z.ZodString, z.ZodNumber>;
114
136
  viewerReaction: z.ZodNullable<z.ZodString>;
115
137
  commentCount: z.ZodNumber;
116
- following: z.ZodBoolean;
138
+ subscription: z.ZodNullable<z.ZodObject<{
139
+ state: z.ZodEnum<{
140
+ following: "following";
141
+ muted: "muted";
142
+ }>;
143
+ mutedUntil: z.ZodNullable<z.ZodCoercedDate<unknown>>;
144
+ }, z.core.$strict>>;
117
145
  bookmarked: z.ZodBoolean;
146
+ mentions: z.ZodArray<z.ZodObject<{
147
+ orgUserId: z.ZodString;
148
+ name: z.ZodString;
149
+ }, z.core.$strict>>;
118
150
  }, z.core.$strict>>;
119
151
  total: z.ZodNumber;
120
152
  page: z.ZodNumber;
@@ -190,6 +222,17 @@ declare const SpaceQueue: z.ZodObject<{
190
222
  createdAt: z.ZodCoercedDate<unknown>;
191
223
  updatedAt: z.ZodCoercedDate<unknown>;
192
224
  coverUrl: z.ZodNullable<z.ZodString>;
225
+ assets: z.ZodRecord<z.ZodString, z.ZodObject<{
226
+ url: z.ZodString;
227
+ kind: z.ZodEnum<{
228
+ image: "image";
229
+ video: "video";
230
+ audio: "audio";
231
+ document: "document";
232
+ }>;
233
+ filename: z.ZodString;
234
+ size: z.ZodNumber;
235
+ }, z.core.$strict>>;
193
236
  author: z.ZodObject<{
194
237
  id: z.ZodString;
195
238
  firstName: z.ZodNullable<z.ZodString>;
@@ -199,19 +242,24 @@ declare const SpaceQueue: z.ZodObject<{
199
242
  image: z.ZodNullable<z.ZodString>;
200
243
  imageAssetId: z.ZodNullable<z.ZodString>;
201
244
  imageUrl: z.ZodNullable<z.ZodString>;
202
- role: z.ZodEnum<{
203
- owner: "owner";
204
- admin: "admin";
205
- instructor: "instructor";
206
- moderator: "moderator";
207
- student: "student";
208
- }>;
245
+ team: z.ZodBoolean;
246
+ roleName: z.ZodNullable<z.ZodString>;
209
247
  }, z.core.$strict>;
210
248
  reactions: z.ZodRecord<z.ZodString, z.ZodNumber>;
211
249
  viewerReaction: z.ZodNullable<z.ZodString>;
212
250
  commentCount: z.ZodNumber;
213
- following: z.ZodBoolean;
251
+ subscription: z.ZodNullable<z.ZodObject<{
252
+ state: z.ZodEnum<{
253
+ following: "following";
254
+ muted: "muted";
255
+ }>;
256
+ mutedUntil: z.ZodNullable<z.ZodCoercedDate<unknown>>;
257
+ }, z.core.$strict>>;
214
258
  bookmarked: z.ZodBoolean;
259
+ mentions: z.ZodArray<z.ZodObject<{
260
+ orgUserId: z.ZodString;
261
+ name: z.ZodString;
262
+ }, z.core.$strict>>;
215
263
  }, z.core.$strict>>;
216
264
  flags: z.ZodArray<z.ZodObject<{
217
265
  orgId: z.ZodString;
@@ -252,6 +300,18 @@ declare const SpaceQueue: z.ZodObject<{
252
300
  published: "published";
253
301
  removed: "removed";
254
302
  }>;
303
+ author: z.ZodObject<{
304
+ id: z.ZodString;
305
+ firstName: z.ZodNullable<z.ZodString>;
306
+ lastName: z.ZodNullable<z.ZodString>;
307
+ displayName: z.ZodNullable<z.ZodString>;
308
+ headline: z.ZodNullable<z.ZodString>;
309
+ image: z.ZodNullable<z.ZodString>;
310
+ imageAssetId: z.ZodNullable<z.ZodString>;
311
+ imageUrl: z.ZodNullable<z.ZodString>;
312
+ team: z.ZodBoolean;
313
+ roleName: z.ZodNullable<z.ZodString>;
314
+ }, z.core.$strict>;
255
315
  }, z.core.$strict>;
256
316
  }, z.core.$strict>>;
257
317
  }, z.core.$strip>;
@@ -271,13 +331,8 @@ declare const PostCommentsPage: z.ZodObject<{
271
331
  image: z.ZodNullable<z.ZodString>;
272
332
  imageAssetId: z.ZodNullable<z.ZodString>;
273
333
  imageUrl: z.ZodNullable<z.ZodString>;
274
- role: z.ZodEnum<{
275
- owner: "owner";
276
- admin: "admin";
277
- instructor: "instructor";
278
- moderator: "moderator";
279
- student: "student";
280
- }>;
334
+ team: z.ZodBoolean;
335
+ roleName: z.ZodNullable<z.ZodString>;
281
336
  }, z.core.$strict>;
282
337
  body: z.ZodNullable<z.ZodString>;
283
338
  status: z.ZodEnum<{
@@ -294,16 +349,15 @@ declare const PostCommentsPage: z.ZodObject<{
294
349
  image: z.ZodNullable<z.ZodString>;
295
350
  imageAssetId: z.ZodNullable<z.ZodString>;
296
351
  imageUrl: z.ZodNullable<z.ZodString>;
297
- role: z.ZodEnum<{
298
- owner: "owner";
299
- admin: "admin";
300
- instructor: "instructor";
301
- moderator: "moderator";
302
- student: "student";
303
- }>;
352
+ team: z.ZodBoolean;
353
+ roleName: z.ZodNullable<z.ZodString>;
304
354
  }, z.core.$strict>>;
305
355
  reactions: z.ZodRecord<z.ZodString, z.ZodNumber>;
306
356
  viewerReaction: z.ZodOptional<z.ZodString>;
357
+ mentions: z.ZodArray<z.ZodObject<{
358
+ orgUserId: z.ZodString;
359
+ name: z.ZodString;
360
+ }, z.core.$strict>>;
307
361
  createdAt: z.ZodCoercedDate<unknown>;
308
362
  updatedAt: z.ZodCoercedDate<unknown>;
309
363
  }, z.core.$strict>>;
@@ -1,7 +1,7 @@
1
1
  import { DateTimeInput, PageQuery, paginated } from "./shared.js";
2
2
  import { CommentView } from "./discussion.js";
3
3
  import { z } from "zod";
4
- import { boundedJsonSchema, flaggedCommentSchema, idSchema, postFlagResolutionSchema, postFlagSchema, postViewSchema } from "@headless-lms/core/schemas";
4
+ import { boundedJsonSchema, flaggedCommentViewSchema, idSchema, postFlagResolutionSchema, postFlagSchema, postViewSchema } from "@headless-lms/core/schemas";
5
5
  //#region src/http/schemas/posts.ts
6
6
  const PostView = postViewSchema;
7
7
  const PostFlag = postFlagSchema;
@@ -9,7 +9,7 @@ const PostFeedPage = paginated(PostView);
9
9
  const PostIdParam = z.object({ postId: z.string() });
10
10
  const FeedQuery = PageQuery.extend({ topicId: z.string().optional().describe("Only posts under this topic") }).strict();
11
11
  const PostTitle = z.string().trim().min(1).max(200);
12
- const PostBody = z.string().max(5e4);
12
+ const PostBody = z.string().max(5e4).describe("The post's text, in the installation's body format (plain text unless the installation sets one). Mention a member with `<@orgUserId>`.");
13
13
  const PostExtra = boundedJsonSchema(16 * 1024);
14
14
  const CreatePost = z.object({
15
15
  title: PostTitle,
@@ -21,7 +21,7 @@ const CreatePost = z.object({
21
21
  "draft",
22
22
  "submit",
23
23
  "schedule"
24
- ]).describe("`draft` keeps the post to yourself. `submit` publishes it, or holds it for review when the space requires review and you are not staff. `schedule` submits it at `scheduledAt`."),
24
+ ]).describe("`draft` keeps the post to yourself. `submit` publishes it, or holds it for review when the space requires review and you do not moderate the community. `schedule` submits it at `scheduledAt`."),
25
25
  scheduledAt: DateTimeInput.nullable().describe("When a scheduled post is submitted. Required, and in the future, when `mode` is `schedule`; ignored otherwise.")
26
26
  }).strict();
27
27
  const UpdatePost = z.object({
@@ -38,7 +38,7 @@ const ResolvePostFlags = z.object({ resolution: postFlagResolutionSchema.extract
38
38
  const SpaceQueue = z.object({
39
39
  pending: z.array(PostView),
40
40
  flags: z.array(PostFlag),
41
- commentFlags: z.array(flaggedCommentSchema)
41
+ commentFlags: z.array(flaggedCommentViewSchema)
42
42
  });
43
43
  const PostCommentsPage = paginated(CommentView);
44
44
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"posts.js","names":[],"sources":["../../../src/http/schemas/posts.ts"],"sourcesContent":["import { z } from 'zod';\nimport {\n boundedJsonSchema,\n flaggedCommentSchema,\n idSchema,\n postFlagResolutionSchema,\n postFlagSchema,\n postViewSchema,\n} from '@headless-lms/core/schemas';\nimport { CommentView } from './discussion.js';\nimport { DateTimeInput, PageQuery, paginated } from './shared.js';\n\nexport const PostView = postViewSchema;\nexport const PostFlag = postFlagSchema;\nexport const PostFeedPage = paginated(PostView);\nexport const PostIdParam = z.object({ postId: z.string() });\nexport const FeedQuery = PageQuery.extend({\n topicId: z.string().optional().describe('Only posts under this topic'),\n}).strict();\n\nconst PostTitle = z.string().trim().min(1).max(200);\nconst PostBody = z.string().max(50_000);\nconst PostExtra = boundedJsonSchema(16 * 1024);\n\nexport const CreatePost = z\n .object({\n title: PostTitle,\n body: PostBody,\n topicId: idSchema\n .nullable()\n .describe(\"One of the space's topics. Required when the space has topics, else null\"),\n extra: PostExtra.default({}),\n coverAssetId: idSchema\n .nullable()\n .describe('A finalized image you uploaded through `requestMemberUpload`'),\n mode: z\n .enum(['draft', 'submit', 'schedule'])\n .describe(\n '`draft` keeps the post to yourself. `submit` publishes it, or holds it for review when the space requires review and you are not staff. `schedule` submits it at `scheduledAt`.',\n ),\n scheduledAt: DateTimeInput.nullable().describe(\n 'When a scheduled post is submitted. Required, and in the future, when `mode` is `schedule`; ignored otherwise.',\n ),\n })\n .strict();\n\nexport const UpdatePost = z\n .object({\n title: PostTitle.optional(),\n body: PostBody.optional(),\n topicId: idSchema.nullable().optional(),\n extra: PostExtra.optional(),\n coverAssetId: idSchema.nullable().optional(),\n })\n .strict();\n\nexport const SchedulePost = z\n .object({\n scheduledAt: DateTimeInput.describe('When the post is submitted; must be in the future'),\n })\n .strict();\nexport const SetPostReactions = z\n .object({ enabled: z.boolean().describe('Whether readers may react to this post') })\n .strict();\nexport const FlagReason = z.object({ reason: z.string().trim().min(1).max(1_000) }).strict();\nexport const ResolvePostFlags = z\n .object({\n resolution: postFlagResolutionSchema\n .extract(['dismissed'])\n .describe(\n '`dismissed` closes the open flags and leaves the post up. Removing the post resolves its flags as `removed` instead.',\n ),\n })\n .strict();\n\nexport const SpaceQueue = z.object({\n pending: z.array(PostView),\n flags: z.array(PostFlag),\n commentFlags: z.array(flaggedCommentSchema),\n});\n\nexport const PostCommentsPage = paginated(CommentView);\n"],"mappings":";;;;;AAYA,MAAa,WAAW;AACxB,MAAa,WAAW;AACxB,MAAa,eAAe,UAAU,QAAQ;AAC9C,MAAa,cAAc,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;AAC1D,MAAa,YAAY,UAAU,OAAO,EACxC,SAAS,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,6BAA6B,EACvE,CAAC,CAAC,CAAC,OAAO;AAEV,MAAM,YAAY,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG;AAClD,MAAM,WAAW,EAAE,OAAO,CAAC,CAAC,IAAI,GAAM;AACtC,MAAM,YAAY,kBAAkB,KAAK,IAAI;AAE7C,MAAa,aAAa,EACvB,OAAO;CACN,OAAO;CACP,MAAM;CACN,SAAS,SACN,SAAS,CAAC,CACV,SAAS,0EAA0E;CACtF,OAAO,UAAU,QAAQ,CAAC,CAAC;CAC3B,cAAc,SACX,SAAS,CAAC,CACV,SAAS,8DAA8D;CAC1E,MAAM,EACH,KAAK;EAAC;EAAS;EAAU;CAAU,CAAC,CAAC,CACrC,SACC,iLACF;CACF,aAAa,cAAc,SAAS,CAAC,CAAC,SACpC,gHACF;AACF,CAAC,CAAC,CACD,OAAO;AAEV,MAAa,aAAa,EACvB,OAAO;CACN,OAAO,UAAU,SAAS;CAC1B,MAAM,SAAS,SAAS;CACxB,SAAS,SAAS,SAAS,CAAC,CAAC,SAAS;CACtC,OAAO,UAAU,SAAS;CAC1B,cAAc,SAAS,SAAS,CAAC,CAAC,SAAS;AAC7C,CAAC,CAAC,CACD,OAAO;AAEV,MAAa,eAAe,EACzB,OAAO,EACN,aAAa,cAAc,SAAS,mDAAmD,EACzF,CAAC,CAAC,CACD,OAAO;AACV,MAAa,mBAAmB,EAC7B,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC,SAAS,wCAAwC,EAAE,CAAC,CAAC,CACnF,OAAO;AACV,MAAa,aAAa,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAK,EAAE,CAAC,CAAC,CAAC,OAAO;AAC3F,MAAa,mBAAmB,EAC7B,OAAO,EACN,YAAY,yBACT,QAAQ,CAAC,WAAW,CAAC,CAAC,CACtB,SACC,sHACF,EACJ,CAAC,CAAC,CACD,OAAO;AAEV,MAAa,aAAa,EAAE,OAAO;CACjC,SAAS,EAAE,MAAM,QAAQ;CACzB,OAAO,EAAE,MAAM,QAAQ;CACvB,cAAc,EAAE,MAAM,oBAAoB;AAC5C,CAAC;AAED,MAAa,mBAAmB,UAAU,WAAW"}
1
+ {"version":3,"file":"posts.js","names":[],"sources":["../../../src/http/schemas/posts.ts"],"sourcesContent":["import { z } from 'zod';\nimport {\n boundedJsonSchema,\n flaggedCommentViewSchema,\n idSchema,\n postFlagResolutionSchema,\n postFlagSchema,\n postViewSchema,\n} from '@headless-lms/core/schemas';\nimport { CommentView } from './discussion.js';\nimport { DateTimeInput, PageQuery, paginated } from './shared.js';\n\nexport const PostView = postViewSchema;\nexport const PostFlag = postFlagSchema;\nexport const PostFeedPage = paginated(PostView);\nexport const PostIdParam = z.object({ postId: z.string() });\nexport const FeedQuery = PageQuery.extend({\n topicId: z.string().optional().describe('Only posts under this topic'),\n}).strict();\n\nconst PostTitle = z.string().trim().min(1).max(200);\nconst PostBody = z\n .string()\n .max(50_000)\n .describe(\n \"The post's text, in the installation's body format (plain text unless the installation sets one). Mention a member with `<@orgUserId>`.\",\n );\nconst PostExtra = boundedJsonSchema(16 * 1024);\n\nexport const CreatePost = z\n .object({\n title: PostTitle,\n body: PostBody,\n topicId: idSchema\n .nullable()\n .describe(\"One of the space's topics. Required when the space has topics, else null\"),\n extra: PostExtra.default({}),\n coverAssetId: idSchema\n .nullable()\n .describe('A finalized image you uploaded through `requestMemberUpload`'),\n mode: z\n .enum(['draft', 'submit', 'schedule'])\n .describe(\n '`draft` keeps the post to yourself. `submit` publishes it, or holds it for review when the space requires review and you do not moderate the community. `schedule` submits it at `scheduledAt`.',\n ),\n scheduledAt: DateTimeInput.nullable().describe(\n 'When a scheduled post is submitted. Required, and in the future, when `mode` is `schedule`; ignored otherwise.',\n ),\n })\n .strict();\n\nexport const UpdatePost = z\n .object({\n title: PostTitle.optional(),\n body: PostBody.optional(),\n topicId: idSchema.nullable().optional(),\n extra: PostExtra.optional(),\n coverAssetId: idSchema.nullable().optional(),\n })\n .strict();\n\nexport const SchedulePost = z\n .object({\n scheduledAt: DateTimeInput.describe('When the post is submitted; must be in the future'),\n })\n .strict();\nexport const SetPostReactions = z\n .object({ enabled: z.boolean().describe('Whether readers may react to this post') })\n .strict();\nexport const FlagReason = z.object({ reason: z.string().trim().min(1).max(1_000) }).strict();\nexport const ResolvePostFlags = z\n .object({\n resolution: postFlagResolutionSchema\n .extract(['dismissed'])\n .describe(\n '`dismissed` closes the open flags and leaves the post up. Removing the post resolves its flags as `removed` instead.',\n ),\n })\n .strict();\n\nexport const SpaceQueue = z.object({\n pending: z.array(PostView),\n flags: z.array(PostFlag),\n commentFlags: z.array(flaggedCommentViewSchema),\n});\n\nexport const PostCommentsPage = paginated(CommentView);\n"],"mappings":";;;;;AAYA,MAAa,WAAW;AACxB,MAAa,WAAW;AACxB,MAAa,eAAe,UAAU,QAAQ;AAC9C,MAAa,cAAc,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;AAC1D,MAAa,YAAY,UAAU,OAAO,EACxC,SAAS,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,6BAA6B,EACvE,CAAC,CAAC,CAAC,OAAO;AAEV,MAAM,YAAY,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG;AAClD,MAAM,WAAW,EACd,OAAO,CAAC,CACR,IAAI,GAAM,CAAC,CACX,SACC,yIACF;AACF,MAAM,YAAY,kBAAkB,KAAK,IAAI;AAE7C,MAAa,aAAa,EACvB,OAAO;CACN,OAAO;CACP,MAAM;CACN,SAAS,SACN,SAAS,CAAC,CACV,SAAS,0EAA0E;CACtF,OAAO,UAAU,QAAQ,CAAC,CAAC;CAC3B,cAAc,SACX,SAAS,CAAC,CACV,SAAS,8DAA8D;CAC1E,MAAM,EACH,KAAK;EAAC;EAAS;EAAU;CAAU,CAAC,CAAC,CACrC,SACC,iMACF;CACF,aAAa,cAAc,SAAS,CAAC,CAAC,SACpC,gHACF;AACF,CAAC,CAAC,CACD,OAAO;AAEV,MAAa,aAAa,EACvB,OAAO;CACN,OAAO,UAAU,SAAS;CAC1B,MAAM,SAAS,SAAS;CACxB,SAAS,SAAS,SAAS,CAAC,CAAC,SAAS;CACtC,OAAO,UAAU,SAAS;CAC1B,cAAc,SAAS,SAAS,CAAC,CAAC,SAAS;AAC7C,CAAC,CAAC,CACD,OAAO;AAEV,MAAa,eAAe,EACzB,OAAO,EACN,aAAa,cAAc,SAAS,mDAAmD,EACzF,CAAC,CAAC,CACD,OAAO;AACV,MAAa,mBAAmB,EAC7B,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC,SAAS,wCAAwC,EAAE,CAAC,CAAC,CACnF,OAAO;AACV,MAAa,aAAa,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAK,EAAE,CAAC,CAAC,CAAC,OAAO;AAC3F,MAAa,mBAAmB,EAC7B,OAAO,EACN,YAAY,yBACT,QAAQ,CAAC,WAAW,CAAC,CAAC,CACtB,SACC,sHACF,EACJ,CAAC,CAAC,CACD,OAAO;AAEV,MAAa,aAAa,EAAE,OAAO;CACjC,SAAS,EAAE,MAAM,QAAQ;CACzB,OAAO,EAAE,MAAM,QAAQ;CACvB,cAAc,EAAE,MAAM,wBAAwB;AAChD,CAAC;AAED,MAAa,mBAAmB,UAAU,WAAW"}
@@ -8,8 +8,8 @@ declare const UserProfile: z.ZodObject<{
8
8
  imageAssetId: z.ZodNullable<z.ZodString>;
9
9
  imageUrl: z.ZodNullable<z.ZodString>;
10
10
  bio: z.ZodNullable<z.ZodString>;
11
- userId: z.ZodString;
12
11
  extra: z.ZodType<import("@headless-lms/core/types").JsonValue, unknown, z.core.$ZodTypeInternals<import("@headless-lms/core/types").JsonValue, unknown>>;
12
+ userId: z.ZodString;
13
13
  }, z.core.$strip>;
14
14
  declare const UpdateProfile: z.ZodObject<{
15
15
  displayName: z.ZodOptional<z.ZodNullable<z.ZodString>>;
@@ -20,8 +20,15 @@ declare const ValidationErrorBody: z.ZodObject<{
20
20
  }, z.core.$strip>>>;
21
21
  }, z.core.$strip>;
22
22
  type ValidationErrorBody = z.infer<typeof ValidationErrorBody>;
23
- type RefusalStatus = 400 | 403 | 404 | 409 | 413 | 415 | 502;
24
- type RefusalBodies<S extends RefusalStatus> = { [K in S]: K extends 400 ? typeof ValidationErrorBody : typeof ErrorBody; };
23
+ declare const UnavailableErrorBody: z.ZodObject<{
24
+ error: z.ZodString;
25
+ message: z.ZodOptional<z.ZodString>;
26
+ requestId: z.ZodOptional<z.ZodString>;
27
+ details: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
28
+ }, z.core.$strip>;
29
+ type UnavailableErrorBody = z.infer<typeof UnavailableErrorBody>;
30
+ type RefusalStatus = 400 | 403 | 404 | 409 | 413 | 415 | 422 | 502 | 503;
31
+ type RefusalBodies<S extends RefusalStatus> = { [K in S]: K extends 400 | 422 ? typeof ValidationErrorBody : K extends 503 ? typeof UnavailableErrorBody : typeof ErrorBody; };
25
32
  /** Response schemas for the refusals a route can answer. A 400 keeps the validation `issues`. */
26
33
  declare function refusals<S extends RefusalStatus>(...statuses: S[]): RefusalBodies<S>;
27
34
  /** An RFC 3339 date-time in a request, such as `2026-10-29T12:00:00Z`, read as a Date. */
@@ -50,16 +57,6 @@ declare function paginated<T extends z.ZodTypeAny>(row: T): z.ZodObject<{
50
57
  page: z.ZodNumber;
51
58
  pageSize: z.ZodNumber;
52
59
  }, z.core.$strip>;
53
- /** All four org roles. `members.ts` exports a staff-only three-value `Role`;
54
- * this is the full set, used wherever a learner can also appear. */
55
- declare const OrgRole: z.ZodEnum<{
56
- owner: "owner";
57
- admin: "admin";
58
- instructor: "instructor";
59
- moderator: "moderator";
60
- student: "student";
61
- }>;
62
- type OrgRole = z.infer<typeof OrgRole>;
63
60
  /** Mirrors UserProfile in @headless-lms/core/types — keyed on the auth user id. */
64
61
  declare const UserProfileSchema: z.ZodObject<{
65
62
  id: z.ZodString;
@@ -78,5 +75,5 @@ declare const OrgUserProfileSchema: z.ZodObject<{
78
75
  }, z.core.$strip>;
79
76
  type OrgUserProfileSchema = z.infer<typeof OrgUserProfileSchema>;
80
77
  //#endregion
81
- export { DateTimeInput, ErrorBody, ListQuery, Matches, OrgRole, OrgUserProfileSchema, PageQuery, UserProfileSchema, ValidationErrorBody, paginated, refusals };
78
+ export { DateTimeInput, ErrorBody, ListQuery, Matches, OrgUserProfileSchema, PageQuery, UnavailableErrorBody, UserProfileSchema, ValidationErrorBody, paginated, refusals };
82
79
  //# sourceMappingURL=shared.d.ts.map