@headless-lms/server 0.2.0 → 0.3.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 (339) hide show
  1. package/dist/_virtual/_rolldown/runtime.js +5 -0
  2. package/dist/app/community-mail.d.ts +26 -0
  3. package/dist/app/community-mail.js +96 -0
  4. package/dist/app/community-mail.js.map +1 -0
  5. package/dist/app/container.d.ts +18 -14
  6. package/dist/app/container.js +136 -43
  7. package/dist/app/container.js.map +1 -1
  8. package/dist/app/mcp-endpoints.d.ts +13 -0
  9. package/dist/app/mcp-endpoints.js +25 -0
  10. package/dist/app/mcp-endpoints.js.map +1 -0
  11. package/dist/http/config.d.ts +2 -1
  12. package/dist/http/errors.d.ts +14 -0
  13. package/dist/http/errors.js +147 -0
  14. package/dist/http/errors.js.map +1 -0
  15. package/dist/http/mcp/catalogue.d.ts +37 -0
  16. package/dist/http/mcp/catalogue.js +69 -0
  17. package/dist/http/mcp/catalogue.js.map +1 -0
  18. package/dist/http/mcp/challenge.d.ts +7 -0
  19. package/dist/http/mcp/challenge.js +35 -0
  20. package/dist/http/mcp/challenge.js.map +1 -0
  21. package/dist/http/mcp/input-schema.d.ts +7 -0
  22. package/dist/http/mcp/input-schema.js +28 -0
  23. package/dist/http/mcp/input-schema.js.map +1 -0
  24. package/dist/http/mcp/route.d.ts +8 -0
  25. package/dist/http/mcp/route.js +75 -0
  26. package/dist/http/mcp/route.js.map +1 -0
  27. package/dist/http/mcp/server.d.ts +8 -0
  28. package/dist/http/mcp/server.js +31 -0
  29. package/dist/http/mcp/server.js.map +1 -0
  30. package/dist/http/mcp/test-support.d.ts +55 -0
  31. package/dist/http/mcp/test-support.js +151 -0
  32. package/dist/http/mcp/test-support.js.map +1 -0
  33. package/dist/http/mcp/tool.d.ts +48 -0
  34. package/dist/http/mcp/tool.js +58 -0
  35. package/dist/http/mcp/tool.js.map +1 -0
  36. package/dist/http/mcp/tools/automations.d.ts +6 -0
  37. package/dist/http/mcp/tools/automations.js +120 -0
  38. package/dist/http/mcp/tools/automations.js.map +1 -0
  39. package/dist/http/mcp/tools/catalog.d.ts +6 -0
  40. package/dist/http/mcp/tools/catalog.js +200 -0
  41. package/dist/http/mcp/tools/catalog.js.map +1 -0
  42. package/dist/http/mcp/tools/comments.d.ts +6 -0
  43. package/dist/http/mcp/tools/comments.js +70 -0
  44. package/dist/http/mcp/tools/comments.js.map +1 -0
  45. package/dist/http/mcp/tools/communities.d.ts +6 -0
  46. package/dist/http/mcp/tools/communities.js +175 -0
  47. package/dist/http/mcp/tools/communities.js.map +1 -0
  48. package/dist/http/mcp/tools/community-members.d.ts +6 -0
  49. package/dist/http/mcp/tools/community-members.js +89 -0
  50. package/dist/http/mcp/tools/community-members.js.map +1 -0
  51. package/dist/http/mcp/tools/community-moderation.d.ts +6 -0
  52. package/dist/http/mcp/tools/community-moderation.js +144 -0
  53. package/dist/http/mcp/tools/community-moderation.js.map +1 -0
  54. package/dist/http/mcp/tools/courses.d.ts +6 -0
  55. package/dist/http/mcp/tools/courses.js +121 -0
  56. package/dist/http/mcp/tools/courses.js.map +1 -0
  57. package/dist/http/mcp/tools/index.d.ts +6 -0
  58. package/dist/http/mcp/tools/index.js +23 -0
  59. package/dist/http/mcp/tools/index.js.map +1 -0
  60. package/dist/http/mcp/tools/people.d.ts +6 -0
  61. package/dist/http/mcp/tools/people.js +145 -0
  62. package/dist/http/mcp/tools/people.js.map +1 -0
  63. package/dist/http/plugins/auth.js +13 -5
  64. package/dist/http/plugins/auth.js.map +1 -1
  65. package/dist/http/plugins/error-handler.d.ts +2 -1
  66. package/dist/http/plugins/error-handler.js +49 -65
  67. package/dist/http/plugins/error-handler.js.map +1 -1
  68. package/dist/http/plugins/openapi.js +49 -2
  69. package/dist/http/plugins/openapi.js.map +1 -1
  70. package/dist/http/routes/access.d.ts +7 -0
  71. package/dist/http/routes/access.js +140 -0
  72. package/dist/http/routes/access.js.map +1 -0
  73. package/dist/http/routes/activities.js +68 -23
  74. package/dist/http/routes/activities.js.map +1 -1
  75. package/dist/http/routes/assets.js +60 -55
  76. package/dist/http/routes/assets.js.map +1 -1
  77. package/dist/http/routes/automations.js +44 -24
  78. package/dist/http/routes/automations.js.map +1 -1
  79. package/dist/http/routes/bundles.js +29 -18
  80. package/dist/http/routes/bundles.js.map +1 -1
  81. package/dist/http/routes/communities.d.ts +7 -0
  82. package/dist/http/routes/communities.js +462 -0
  83. package/dist/http/routes/communities.js.map +1 -0
  84. package/dist/http/routes/community-moderation.d.ts +7 -0
  85. package/dist/http/routes/community-moderation.js +425 -0
  86. package/dist/http/routes/community-moderation.js.map +1 -0
  87. package/dist/http/routes/course-analytics.js +9 -7
  88. package/dist/http/routes/course-analytics.js.map +1 -1
  89. package/dist/http/routes/courses.js +30 -15
  90. package/dist/http/routes/courses.js.map +1 -1
  91. package/dist/http/routes/dashboard.js +15 -6
  92. package/dist/http/routes/dashboard.js.map +1 -1
  93. package/dist/http/routes/discussion.js +34 -26
  94. package/dist/http/routes/discussion.js.map +1 -1
  95. package/dist/http/routes/downloads.js +48 -30
  96. package/dist/http/routes/downloads.js.map +1 -1
  97. package/dist/http/routes/entitlements.js +16 -7
  98. package/dist/http/routes/entitlements.js.map +1 -1
  99. package/dist/http/routes/integrations.js +38 -41
  100. package/dist/http/routes/integrations.js.map +1 -1
  101. package/dist/http/routes/member/actor.d.ts +14 -0
  102. package/dist/http/routes/member/actor.js +11 -0
  103. package/dist/http/routes/member/actor.js.map +1 -0
  104. package/dist/http/routes/member/assets.d.ts +7 -0
  105. package/dist/http/routes/member/assets.js +79 -0
  106. package/dist/http/routes/member/assets.js.map +1 -0
  107. package/dist/http/routes/member/chats.d.ts +7 -0
  108. package/dist/http/routes/member/chats.js +456 -0
  109. package/dist/http/routes/member/chats.js.map +1 -0
  110. package/dist/http/routes/member/comments.d.ts +7 -0
  111. package/dist/http/routes/member/comments.js +187 -0
  112. package/dist/http/routes/member/comments.js.map +1 -0
  113. package/dist/http/routes/member/community.d.ts +7 -0
  114. package/dist/http/routes/member/community.js +288 -0
  115. package/dist/http/routes/member/community.js.map +1 -0
  116. package/dist/http/routes/member/courses.d.ts +7 -0
  117. package/dist/http/routes/member/courses.js +101 -0
  118. package/dist/http/routes/member/courses.js.map +1 -0
  119. package/dist/http/routes/member/downloads.d.ts +7 -0
  120. package/dist/http/routes/member/downloads.js +56 -0
  121. package/dist/http/routes/member/downloads.js.map +1 -0
  122. package/dist/http/routes/member/files.d.ts +7 -0
  123. package/dist/http/routes/member/files.js +184 -0
  124. package/dist/http/routes/member/files.js.map +1 -0
  125. package/dist/http/routes/member/index.d.ts +7 -0
  126. package/dist/http/routes/member/index.js +31 -0
  127. package/dist/http/routes/member/index.js.map +1 -0
  128. package/dist/http/routes/member/notifications.d.ts +7 -0
  129. package/dist/http/routes/member/notifications.js +101 -0
  130. package/dist/http/routes/member/notifications.js.map +1 -0
  131. package/dist/http/routes/member/org.d.ts +7 -0
  132. package/dist/http/routes/member/org.js +56 -0
  133. package/dist/http/routes/member/org.js.map +1 -0
  134. package/dist/http/routes/member/posts.d.ts +7 -0
  135. package/dist/http/routes/member/posts.js +612 -0
  136. package/dist/http/routes/member/posts.js.map +1 -0
  137. package/dist/http/routes/member/profile.d.ts +7 -0
  138. package/dist/http/routes/member/profile.js +48 -0
  139. package/dist/http/routes/member/profile.js.map +1 -0
  140. package/dist/http/routes/member/progress.d.ts +7 -0
  141. package/dist/http/routes/member/progress.js +60 -0
  142. package/dist/http/routes/member/progress.js.map +1 -0
  143. package/dist/http/routes/organizations.js +49 -24
  144. package/dist/http/routes/organizations.js.map +1 -1
  145. package/dist/http/routes/students.js +32 -47
  146. package/dist/http/routes/students.js.map +1 -1
  147. package/dist/http/routes/webhooks.js +26 -18
  148. package/dist/http/routes/webhooks.js.map +1 -1
  149. package/dist/http/routes.js +8 -2
  150. package/dist/http/routes.js.map +1 -1
  151. package/dist/http/schemas/access.d.ts +146 -0
  152. package/dist/http/schemas/access.js +36 -0
  153. package/dist/http/schemas/access.js.map +1 -0
  154. package/dist/http/schemas/activities.d.ts +3 -1
  155. package/dist/http/schemas/activities.js +4 -4
  156. package/dist/http/schemas/activities.js.map +1 -1
  157. package/dist/http/schemas/assets.d.ts +73 -74
  158. package/dist/http/schemas/assets.js +23 -13
  159. package/dist/http/schemas/assets.js.map +1 -1
  160. package/dist/http/schemas/automations.d.ts +10 -0
  161. package/dist/http/schemas/bundles.js +6 -6
  162. package/dist/http/schemas/bundles.js.map +1 -1
  163. package/dist/http/schemas/chats.d.ts +386 -0
  164. package/dist/http/schemas/chats.js +58 -0
  165. package/dist/http/schemas/chats.js.map +1 -0
  166. package/dist/http/schemas/community.d.ts +537 -0
  167. package/dist/http/schemas/community.js +129 -0
  168. package/dist/http/schemas/community.js.map +1 -0
  169. package/dist/http/schemas/content.d.ts +4 -2
  170. package/dist/http/schemas/content.js +11 -8
  171. package/dist/http/schemas/content.js.map +1 -1
  172. package/dist/http/schemas/discussion.d.ts +76 -14
  173. package/dist/http/schemas/discussion.js +12 -11
  174. package/dist/http/schemas/discussion.js.map +1 -1
  175. package/dist/http/schemas/downloads.d.ts +11 -5
  176. package/dist/http/schemas/downloads.js +14 -11
  177. package/dist/http/schemas/downloads.js.map +1 -1
  178. package/dist/http/schemas/entitlements.d.ts +6 -6
  179. package/dist/http/schemas/entitlements.js +6 -6
  180. package/dist/http/schemas/entitlements.js.map +1 -1
  181. package/dist/http/schemas/files.d.ts +45 -0
  182. package/dist/http/schemas/files.js +25 -0
  183. package/dist/http/schemas/files.js.map +1 -0
  184. package/dist/http/schemas/index.d.ts +15 -8
  185. package/dist/http/schemas/index.js +15 -8
  186. package/dist/http/schemas/integrations.d.ts +2 -2
  187. package/dist/http/schemas/invites.d.ts +4 -0
  188. package/dist/http/schemas/invites.js +1 -0
  189. package/dist/http/schemas/invites.js.map +1 -1
  190. package/dist/http/schemas/{learn.d.ts → member.d.ts} +31 -18
  191. package/dist/http/schemas/{learn.js → member.js} +17 -13
  192. package/dist/http/schemas/member.js.map +1 -0
  193. package/dist/http/schemas/members.d.ts +39 -6
  194. package/dist/http/schemas/members.js +17 -3
  195. package/dist/http/schemas/members.js.map +1 -1
  196. package/dist/http/schemas/notifications.d.ts +227 -0
  197. package/dist/http/schemas/notifications.js +44 -0
  198. package/dist/http/schemas/notifications.js.map +1 -0
  199. package/dist/http/schemas/posts.d.ts +316 -0
  200. package/dist/http/schemas/posts.js +47 -0
  201. package/dist/http/schemas/posts.js.map +1 -0
  202. package/dist/http/schemas/profile.d.ts +23 -0
  203. package/dist/http/schemas/profile.js +15 -0
  204. package/dist/http/schemas/profile.js.map +1 -0
  205. package/dist/http/schemas/shared.d.ts +25 -1
  206. package/dist/http/schemas/shared.js +19 -2
  207. package/dist/http/schemas/shared.js.map +1 -1
  208. package/dist/http/schemas/students.d.ts +4 -10
  209. package/dist/http/schemas/students.js +1 -7
  210. package/dist/http/schemas/students.js.map +1 -1
  211. package/dist/http/scope.d.ts +2 -1
  212. package/dist/http/scope.js +20 -4
  213. package/dist/http/scope.js.map +1 -1
  214. package/dist/http/server.js +6 -1
  215. package/dist/http/server.js.map +1 -1
  216. package/dist/http/web-bridge.d.ts +1 -1
  217. package/dist/http/web-bridge.js +2 -2
  218. package/dist/http/web-bridge.js.map +1 -1
  219. package/dist/http/well-known.d.ts +7 -0
  220. package/dist/http/well-known.js +22 -0
  221. package/dist/http/well-known.js.map +1 -0
  222. package/dist/index.d.ts +2 -1
  223. package/dist/index.js +4 -2
  224. package/dist/index.js.map +1 -1
  225. package/dist/node_modules/.pnpm/@jridgewell_sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.js +78 -0
  226. package/dist/node_modules/.pnpm/@jridgewell_sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.js.map +1 -0
  227. package/dist/node_modules/.pnpm/@vitest_expect@2.1.9/node_modules/@vitest/expect/dist/index.js +1267 -0
  228. package/dist/node_modules/.pnpm/@vitest_expect@2.1.9/node_modules/@vitest/expect/dist/index.js.map +1 -0
  229. package/dist/node_modules/.pnpm/@vitest_pretty-format@2.1.9/node_modules/@vitest/pretty-format/dist/index.js +814 -0
  230. package/dist/node_modules/.pnpm/@vitest_pretty-format@2.1.9/node_modules/@vitest/pretty-format/dist/index.js.map +1 -0
  231. package/dist/node_modules/.pnpm/@vitest_runner@2.1.9/node_modules/@vitest/runner/dist/chunk-tasks.js +43 -0
  232. package/dist/node_modules/.pnpm/@vitest_runner@2.1.9/node_modules/@vitest/runner/dist/chunk-tasks.js.map +1 -0
  233. package/dist/node_modules/.pnpm/@vitest_runner@2.1.9/node_modules/@vitest/runner/dist/index.js +527 -0
  234. package/dist/node_modules/.pnpm/@vitest_runner@2.1.9/node_modules/@vitest/runner/dist/index.js.map +1 -0
  235. package/dist/node_modules/.pnpm/@vitest_runner@2.1.9/node_modules/@vitest/runner/dist/utils.js +2 -0
  236. package/dist/node_modules/.pnpm/@vitest_snapshot@2.1.9/node_modules/@vitest/snapshot/dist/index.js +1737 -0
  237. package/dist/node_modules/.pnpm/@vitest_snapshot@2.1.9/node_modules/@vitest/snapshot/dist/index.js.map +1 -0
  238. package/dist/node_modules/.pnpm/@vitest_spy@2.1.9/node_modules/@vitest/spy/dist/index.js +137 -0
  239. package/dist/node_modules/.pnpm/@vitest_spy@2.1.9/node_modules/@vitest/spy/dist/index.js.map +1 -0
  240. package/dist/node_modules/.pnpm/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/chunk-_commonjsHelpers.js +118 -0
  241. package/dist/node_modules/.pnpm/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/chunk-_commonjsHelpers.js.map +1 -0
  242. package/dist/node_modules/.pnpm/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/diff.js +1222 -0
  243. package/dist/node_modules/.pnpm/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/diff.js.map +1 -0
  244. package/dist/node_modules/.pnpm/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/error.js +91 -0
  245. package/dist/node_modules/.pnpm/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/error.js.map +1 -0
  246. package/dist/node_modules/.pnpm/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/helpers.js +113 -0
  247. package/dist/node_modules/.pnpm/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/helpers.js.map +1 -0
  248. package/dist/node_modules/.pnpm/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/index.js +449 -0
  249. package/dist/node_modules/.pnpm/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/index.js.map +1 -0
  250. package/dist/node_modules/.pnpm/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/source-map.js +163 -0
  251. package/dist/node_modules/.pnpm/@vitest_utils@2.1.9/node_modules/@vitest/utils/dist/source-map.js.map +1 -0
  252. package/dist/node_modules/.pnpm/chai@5.3.3/node_modules/chai/index.js +3187 -0
  253. package/dist/node_modules/.pnpm/chai@5.3.3/node_modules/chai/index.js.map +1 -0
  254. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/arguments.js +11 -0
  255. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/arguments.js.map +1 -0
  256. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/array.js +16 -0
  257. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/array.js.map +1 -0
  258. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/bigint.js +11 -0
  259. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/bigint.js.map +1 -0
  260. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/class.js +15 -0
  261. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/class.js.map +1 -0
  262. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/date.js +13 -0
  263. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/date.js.map +1 -0
  264. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/error.js +34 -0
  265. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/error.js.map +1 -0
  266. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/function.js +12 -0
  267. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/function.js.map +1 -0
  268. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/helpers.js +122 -0
  269. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/helpers.js.map +1 -0
  270. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/html.js +39 -0
  271. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/html.js.map +1 -0
  272. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/index.js +99 -0
  273. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/index.js.map +1 -0
  274. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/map.js +25 -0
  275. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/map.js.map +1 -0
  276. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/number.js +14 -0
  277. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/number.js.map +1 -0
  278. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/object.js +21 -0
  279. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/object.js.map +1 -0
  280. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/promise.js +6 -0
  281. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/promise.js.map +1 -0
  282. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/regexp.js +12 -0
  283. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/regexp.js.map +1 -0
  284. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/set.js +18 -0
  285. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/set.js.map +1 -0
  286. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/string.js +24 -0
  287. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/string.js.map +1 -0
  288. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/symbol.js +9 -0
  289. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/symbol.js.map +1 -0
  290. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/typedarray.js +30 -0
  291. package/dist/node_modules/.pnpm/loupe@3.2.1/node_modules/loupe/lib/typedarray.js.map +1 -0
  292. package/dist/node_modules/.pnpm/magic-string@0.30.21/node_modules/magic-string/dist/magic-string.es.js +939 -0
  293. package/dist/node_modules/.pnpm/magic-string@0.30.21/node_modules/magic-string/dist/magic-string.es.js.map +1 -0
  294. package/dist/node_modules/.pnpm/pathe@1.1.2/node_modules/pathe/dist/shared/pathe.ff20891b.js +82 -0
  295. package/dist/node_modules/.pnpm/pathe@1.1.2/node_modules/pathe/dist/shared/pathe.ff20891b.js.map +1 -0
  296. package/dist/node_modules/.pnpm/tinyrainbow@1.2.0/node_modules/tinyrainbow/dist/chunk-BVHSVHOK.js +82 -0
  297. package/dist/node_modules/.pnpm/tinyrainbow@1.2.0/node_modules/tinyrainbow/dist/chunk-BVHSVHOK.js.map +1 -0
  298. package/dist/node_modules/.pnpm/tinyrainbow@1.2.0/node_modules/tinyrainbow/dist/node.js +8 -0
  299. package/dist/node_modules/.pnpm/tinyrainbow@1.2.0/node_modules/tinyrainbow/dist/node.js.map +1 -0
  300. package/dist/node_modules/.pnpm/tinyspy@3.0.2/node_modules/tinyspy/dist/index.js +83 -0
  301. package/dist/node_modules/.pnpm/tinyspy@3.0.2/node_modules/tinyspy/dist/index.js.map +1 -0
  302. package/dist/node_modules/.pnpm/vitest@2.1.9_@types_node@22.20.0_jsdom@25.0.1_lightningcss@1.32.0/node_modules/vitest/dist/chunks/_commonjsHelpers.BFTU3MAI.js +9 -0
  303. package/dist/node_modules/.pnpm/vitest@2.1.9_@types_node@22.20.0_jsdom@25.0.1_lightningcss@1.32.0/node_modules/vitest/dist/chunks/_commonjsHelpers.BFTU3MAI.js.map +1 -0
  304. package/dist/node_modules/.pnpm/vitest@2.1.9_@types_node@22.20.0_jsdom@25.0.1_lightningcss@1.32.0/node_modules/vitest/dist/chunks/date.W2xKR2qe.js +51 -0
  305. package/dist/node_modules/.pnpm/vitest@2.1.9_@types_node@22.20.0_jsdom@25.0.1_lightningcss@1.32.0/node_modules/vitest/dist/chunks/date.W2xKR2qe.js.map +1 -0
  306. package/dist/node_modules/.pnpm/vitest@2.1.9_@types_node@22.20.0_jsdom@25.0.1_lightningcss@1.32.0/node_modules/vitest/dist/chunks/utils.C8RiOc4B.js +48 -0
  307. package/dist/node_modules/.pnpm/vitest@2.1.9_@types_node@22.20.0_jsdom@25.0.1_lightningcss@1.32.0/node_modules/vitest/dist/chunks/utils.C8RiOc4B.js.map +1 -0
  308. package/dist/node_modules/.pnpm/vitest@2.1.9_@types_node@22.20.0_jsdom@25.0.1_lightningcss@1.32.0/node_modules/vitest/dist/chunks/vi.DgezovHB.js +2426 -0
  309. package/dist/node_modules/.pnpm/vitest@2.1.9_@types_node@22.20.0_jsdom@25.0.1_lightningcss@1.32.0/node_modules/vitest/dist/chunks/vi.DgezovHB.js.map +1 -0
  310. package/dist/packages/server/package.js +6 -0
  311. package/dist/packages/server/package.js.map +1 -0
  312. package/package.json +9 -7
  313. package/dist/app/notifications.d.ts +0 -7
  314. package/dist/app/notifications.js +0 -26
  315. package/dist/app/notifications.js.map +0 -1
  316. package/dist/http/routes/learn/assets.d.ts +0 -8
  317. package/dist/http/routes/learn/assets.js +0 -32
  318. package/dist/http/routes/learn/assets.js.map +0 -1
  319. package/dist/http/routes/learn/comments.d.ts +0 -7
  320. package/dist/http/routes/learn/comments.js +0 -175
  321. package/dist/http/routes/learn/comments.js.map +0 -1
  322. package/dist/http/routes/learn/courses.d.ts +0 -7
  323. package/dist/http/routes/learn/courses.js +0 -98
  324. package/dist/http/routes/learn/courses.js.map +0 -1
  325. package/dist/http/routes/learn/downloads.d.ts +0 -7
  326. package/dist/http/routes/learn/downloads.js +0 -76
  327. package/dist/http/routes/learn/downloads.js.map +0 -1
  328. package/dist/http/routes/learn/index.d.ts +0 -7
  329. package/dist/http/routes/learn/index.js +0 -19
  330. package/dist/http/routes/learn/index.js.map +0 -1
  331. package/dist/http/routes/learn/org.d.ts +0 -7
  332. package/dist/http/routes/learn/org.js +0 -50
  333. package/dist/http/routes/learn/org.js.map +0 -1
  334. package/dist/http/routes/learn/progress.d.ts +0 -7
  335. package/dist/http/routes/learn/progress.js +0 -63
  336. package/dist/http/routes/learn/progress.js.map +0 -1
  337. package/dist/http/schemas/learn.js.map +0 -1
  338. package/dist/package.js +0 -6
  339. package/dist/package.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"courses.js","names":[],"sources":["../../../../src/http/routes/member/courses.ts"],"sourcesContent":["import type { FastifyInstance } from 'fastify';\nimport type { ZodTypeProvider } from 'fastify-type-provider-zod';\nimport {\n ActivityList,\n Course,\n MemberCourseIdParam,\n MemberCourses,\n MemberModules,\n refusals,\n} from '../../schemas/index.js';\nimport { NotFoundError } from '@headless-lms/core/shared/errors';\nimport type { Container } from '../../../app/container.js';\nimport { actorOf } from './actor.js';\n\nexport async function memberCoursesRoutes(\n app: FastifyInstance,\n container: Container,\n): Promise<void> {\n const r = app.withTypeProvider<ZodTypeProvider>();\n const member = container.reporting.member;\n\n r.route({\n method: 'GET',\n url: '/api/member/courses',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'listMemberCourses',\n tags: ['Content'],\n summary: 'List the courses you can open',\n description:\n 'For a member of the organization. Published courses you hold, directly or through a bundle.',\n response: { 200: MemberCourses, ...refusals(403) },\n },\n handler: async (req) => {\n const orgUser = await actorOf(container, req.orgId, req.userId);\n return member.listCourses(req.orgId, orgUser.id);\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/member/courses/:courseId',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'getMemberCourse',\n tags: ['Content'],\n summary: 'Get one course you can open',\n description:\n 'For a member of the organization. 404 when the course is not published or you do not hold it.',\n params: MemberCourseIdParam,\n response: { 200: Course, ...refusals(403, 404) },\n },\n handler: async (req) => {\n const orgUser = await actorOf(container, req.orgId, req.userId);\n const course = await member.getCourse(req.orgId, orgUser.id, req.params.courseId);\n if (!course) {\n throw new NotFoundError('Course', req.params.courseId);\n }\n return course;\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/member/courses/:courseId/modules',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'listMemberModules',\n tags: ['Content'],\n summary: 'List the modules and activities of a course you can open',\n description:\n 'For a member of the organization. Published activities only. 404 when the course is not published or you do not hold it.',\n params: MemberCourseIdParam,\n response: { 200: MemberModules, ...refusals(403, 404) },\n },\n handler: async (req) => {\n const orgUser = await actorOf(container, req.orgId, req.userId);\n const modules = await member.listModules(req.orgId, orgUser.id, req.params.courseId);\n if (!modules) {\n throw new NotFoundError('Course', req.params.courseId);\n }\n return modules;\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/member/courses/:courseId/activities',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'listMemberActivities',\n tags: ['Content'],\n summary: 'List the published activities of a course you can open',\n description:\n 'For a member of the organization. 404 when the course is not published or you do not hold it.',\n params: MemberCourseIdParam,\n response: { 200: ActivityList, ...refusals(403, 404) },\n },\n handler: async (req) => {\n const orgUser = await actorOf(container, req.orgId, req.userId);\n const activities = await member.listActivities(req.orgId, orgUser.id, req.params.courseId);\n if (!activities) {\n throw new NotFoundError('Course', req.params.courseId);\n }\n return activities;\n },\n });\n}\n"],"mappings":";;;;;;;;AAcA,eAAsB,oBACpB,KACA,WACe;CACf,MAAM,IAAI,IAAI,iBAAkC;CAChD,MAAM,SAAS,UAAU,UAAU;CAEnC,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,SAAS;GAChB,SAAS;GACT,aACE;GACF,UAAU;IAAE,KAAK;IAAe,GAAG,SAAS,GAAG;GAAE;EACnD;EACA,SAAS,OAAO,QAAQ;GACtB,MAAM,UAAU,MAAM,QAAQ,WAAW,IAAI,OAAO,IAAI,MAAM;GAC9D,OAAO,OAAO,YAAY,IAAI,OAAO,QAAQ,EAAE;EACjD;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,SAAS;GAChB,SAAS;GACT,aACE;GACF,QAAQ;GACR,UAAU;IAAE,KAAK;IAAQ,GAAG,SAAS,KAAK,GAAG;GAAE;EACjD;EACA,SAAS,OAAO,QAAQ;GACtB,MAAM,UAAU,MAAM,QAAQ,WAAW,IAAI,OAAO,IAAI,MAAM;GAC9D,MAAM,SAAS,MAAM,OAAO,UAAU,IAAI,OAAO,QAAQ,IAAI,IAAI,OAAO,QAAQ;GAChF,IAAI,CAAC,QACH,MAAM,IAAI,cAAc,UAAU,IAAI,OAAO,QAAQ;GAEvD,OAAO;EACT;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,SAAS;GAChB,SAAS;GACT,aACE;GACF,QAAQ;GACR,UAAU;IAAE,KAAK;IAAe,GAAG,SAAS,KAAK,GAAG;GAAE;EACxD;EACA,SAAS,OAAO,QAAQ;GACtB,MAAM,UAAU,MAAM,QAAQ,WAAW,IAAI,OAAO,IAAI,MAAM;GAC9D,MAAM,UAAU,MAAM,OAAO,YAAY,IAAI,OAAO,QAAQ,IAAI,IAAI,OAAO,QAAQ;GACnF,IAAI,CAAC,SACH,MAAM,IAAI,cAAc,UAAU,IAAI,OAAO,QAAQ;GAEvD,OAAO;EACT;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,SAAS;GAChB,SAAS;GACT,aACE;GACF,QAAQ;GACR,UAAU;IAAE,KAAK;IAAc,GAAG,SAAS,KAAK,GAAG;GAAE;EACvD;EACA,SAAS,OAAO,QAAQ;GACtB,MAAM,UAAU,MAAM,QAAQ,WAAW,IAAI,OAAO,IAAI,MAAM;GAC9D,MAAM,aAAa,MAAM,OAAO,eAAe,IAAI,OAAO,QAAQ,IAAI,IAAI,OAAO,QAAQ;GACzF,IAAI,CAAC,YACH,MAAM,IAAI,cAAc,UAAU,IAAI,OAAO,QAAQ;GAEvD,OAAO;EACT;CACF,CAAC;AACH"}
@@ -0,0 +1,7 @@
1
+ import { Container } from "../../../app/container.js";
2
+ import { FastifyInstance } from "fastify";
3
+ //#region src/http/routes/member/downloads.d.ts
4
+ declare function memberDownloadsRoutes(app: FastifyInstance, container: Container): Promise<void>;
5
+ //#endregion
6
+ export { memberDownloadsRoutes };
7
+ //# sourceMappingURL=downloads.d.ts.map
@@ -0,0 +1,56 @@
1
+ import { refusals } from "../../schemas/shared.js";
2
+ import { DownloadIdParam } from "../../schemas/downloads.js";
3
+ import { MemberDownload, MemberDownloads } from "../../schemas/member.js";
4
+ import "../../schemas/index.js";
5
+ import { actorOf } from "./actor.js";
6
+ import { NotFoundError } from "@headless-lms/core/shared/errors";
7
+ //#region src/http/routes/member/downloads.ts
8
+ async function memberDownloadsRoutes(app, container) {
9
+ const r = app.withTypeProvider();
10
+ const member = container.reporting.member;
11
+ r.route({
12
+ method: "GET",
13
+ url: "/api/member/downloads",
14
+ preHandler: app.requireOrgSession,
15
+ schema: {
16
+ operationId: "listMemberDownloads",
17
+ tags: ["Content"],
18
+ summary: "List the downloads you can open",
19
+ description: "For a member of the organization. Published downloads you hold, directly or through a bundle.",
20
+ response: {
21
+ 200: MemberDownloads,
22
+ ...refusals(403)
23
+ }
24
+ },
25
+ handler: async (req) => {
26
+ const orgUser = await actorOf(container, req.orgId, req.userId);
27
+ return member.listDownloads(req.orgId, orgUser.id);
28
+ }
29
+ });
30
+ r.route({
31
+ method: "GET",
32
+ url: "/api/member/downloads/:downloadId",
33
+ preHandler: app.requireOrgSession,
34
+ schema: {
35
+ operationId: "getMemberDownload",
36
+ tags: ["Content"],
37
+ summary: "One download you can open, with its files in order",
38
+ description: "For a member of the organization. 404 when the download is not published or you do not hold it.",
39
+ params: DownloadIdParam,
40
+ response: {
41
+ 200: MemberDownload,
42
+ ...refusals(403, 404)
43
+ }
44
+ },
45
+ handler: async (req) => {
46
+ const orgUser = await actorOf(container, req.orgId, req.userId);
47
+ const result = await member.getDownload(req.orgId, orgUser.id, req.params.downloadId);
48
+ if (!result) throw new NotFoundError("Download", req.params.downloadId);
49
+ return result;
50
+ }
51
+ });
52
+ }
53
+ //#endregion
54
+ export { memberDownloadsRoutes };
55
+
56
+ //# sourceMappingURL=downloads.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"downloads.js","names":[],"sources":["../../../../src/http/routes/member/downloads.ts"],"sourcesContent":["import type { FastifyInstance } from 'fastify';\nimport type { ZodTypeProvider } from 'fastify-type-provider-zod';\nimport { DownloadIdParam, MemberDownload, MemberDownloads, refusals } from '../../schemas/index.js';\nimport { NotFoundError } from '@headless-lms/core/shared/errors';\nimport type { Container } from '../../../app/container.js';\nimport { actorOf } from './actor.js';\n\nexport async function memberDownloadsRoutes(\n app: FastifyInstance,\n container: Container,\n): Promise<void> {\n const r = app.withTypeProvider<ZodTypeProvider>();\n const member = container.reporting.member;\n\n r.route({\n method: 'GET',\n url: '/api/member/downloads',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'listMemberDownloads',\n tags: ['Content'],\n summary: 'List the downloads you can open',\n description:\n 'For a member of the organization. Published downloads you hold, directly or through a bundle.',\n response: { 200: MemberDownloads, ...refusals(403) },\n },\n handler: async (req) => {\n const orgUser = await actorOf(container, req.orgId, req.userId);\n return member.listDownloads(req.orgId, orgUser.id);\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/member/downloads/:downloadId',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'getMemberDownload',\n tags: ['Content'],\n summary: 'One download you can open, with its files in order',\n description:\n 'For a member of the organization. 404 when the download is not published or you do not hold it.',\n params: DownloadIdParam,\n response: { 200: MemberDownload, ...refusals(403, 404) },\n },\n handler: async (req) => {\n const orgUser = await actorOf(container, req.orgId, req.userId);\n const result = await member.getDownload(req.orgId, orgUser.id, req.params.downloadId);\n if (!result) {\n throw new NotFoundError('Download', req.params.downloadId);\n }\n return result;\n },\n });\n}\n"],"mappings":";;;;;;;AAOA,eAAsB,sBACpB,KACA,WACe;CACf,MAAM,IAAI,IAAI,iBAAkC;CAChD,MAAM,SAAS,UAAU,UAAU;CAEnC,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,SAAS;GAChB,SAAS;GACT,aACE;GACF,UAAU;IAAE,KAAK;IAAiB,GAAG,SAAS,GAAG;GAAE;EACrD;EACA,SAAS,OAAO,QAAQ;GACtB,MAAM,UAAU,MAAM,QAAQ,WAAW,IAAI,OAAO,IAAI,MAAM;GAC9D,OAAO,OAAO,cAAc,IAAI,OAAO,QAAQ,EAAE;EACnD;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,SAAS;GAChB,SAAS;GACT,aACE;GACF,QAAQ;GACR,UAAU;IAAE,KAAK;IAAgB,GAAG,SAAS,KAAK,GAAG;GAAE;EACzD;EACA,SAAS,OAAO,QAAQ;GACtB,MAAM,UAAU,MAAM,QAAQ,WAAW,IAAI,OAAO,IAAI,MAAM;GAC9D,MAAM,SAAS,MAAM,OAAO,YAAY,IAAI,OAAO,QAAQ,IAAI,IAAI,OAAO,UAAU;GACpF,IAAI,CAAC,QACH,MAAM,IAAI,cAAc,YAAY,IAAI,OAAO,UAAU;GAE3D,OAAO;EACT;CACF,CAAC;AACH"}
@@ -0,0 +1,7 @@
1
+ import { Container } from "../../../app/container.js";
2
+ import { FastifyInstance } from "fastify";
3
+ //#region src/http/routes/member/files.d.ts
4
+ declare function memberFileRoutes(app: FastifyInstance, container: Container): Promise<void>;
5
+ //#endregion
6
+ export { memberFileRoutes };
7
+ //# sourceMappingURL=files.d.ts.map
@@ -0,0 +1,184 @@
1
+ import { refusals } from "../../schemas/shared.js";
2
+ import { ActivityFileParams, CommunityThumbnailParams, CourseThumbnailParams, DownloadFileParams, DownloadThumbnailParams, MessageAttachmentParams, PersonImageParams, PostCoverParams, UploadFileParams } from "../../schemas/files.js";
3
+ import "../../schemas/index.js";
4
+ import { actorOf } from "./actor.js";
5
+ import { z } from "zod";
6
+ import { NotFoundError } from "@headless-lms/core/shared/errors";
7
+ //#region src/http/routes/member/files.ts
8
+ const tags = ["Files"];
9
+ const responses = {
10
+ 302: z.void(),
11
+ ...refusals(403, 404)
12
+ };
13
+ function redirect(reply, url, what, id) {
14
+ if (!url) throw new NotFoundError(what, id);
15
+ return reply.header("cache-control", "no-store").header("referrer-policy", "no-referrer").redirect(url, 302);
16
+ }
17
+ async function memberFileRoutes(app, container) {
18
+ const r = app.withTypeProvider();
19
+ const member = container.reporting.member;
20
+ async function actorOf$1(orgId, userId) {
21
+ const orgUser = await actorOf(container, orgId, userId);
22
+ return {
23
+ id: orgUser.id,
24
+ role: orgUser.role
25
+ };
26
+ }
27
+ r.route({
28
+ method: "GET",
29
+ url: "/api/member/courses/:courseId/thumbnail",
30
+ preHandler: app.requireOrgSession,
31
+ schema: {
32
+ operationId: "getCourseThumbnail",
33
+ tags,
34
+ summary: "Redirect to a course's thumbnail",
35
+ description: "Any org user may fetch the thumbnail of a published course; staff may fetch any. 404 when the course has no thumbnail.",
36
+ params: CourseThumbnailParams,
37
+ response: responses
38
+ },
39
+ handler: async (req, reply) => {
40
+ const actor = await actorOf$1(req.orgId, req.userId);
41
+ return redirect(reply, await member.thumbnailFile(req.orgId, actor, "course", req.params.courseId), "Course thumbnail", req.params.courseId);
42
+ }
43
+ });
44
+ r.route({
45
+ method: "GET",
46
+ url: "/api/member/downloads/:downloadId/thumbnail",
47
+ preHandler: app.requireOrgSession,
48
+ schema: {
49
+ operationId: "getDownloadThumbnail",
50
+ tags,
51
+ summary: "Redirect to a download's thumbnail",
52
+ description: "Any org user may fetch the thumbnail of a published download; staff may fetch any. 404 when the download has no thumbnail.",
53
+ params: DownloadThumbnailParams,
54
+ response: responses
55
+ },
56
+ handler: async (req, reply) => {
57
+ const actor = await actorOf$1(req.orgId, req.userId);
58
+ return redirect(reply, await member.thumbnailFile(req.orgId, actor, "download", req.params.downloadId), "Download thumbnail", req.params.downloadId);
59
+ }
60
+ });
61
+ r.route({
62
+ method: "GET",
63
+ url: "/api/member/communities/:communityId/thumbnail",
64
+ preHandler: app.requireOrgSession,
65
+ schema: {
66
+ operationId: "getCommunityThumbnail",
67
+ tags,
68
+ summary: "Redirect to a community's thumbnail",
69
+ description: "Any org user may fetch the thumbnail of a published community; staff may fetch any. 404 when the community has no thumbnail.",
70
+ params: CommunityThumbnailParams,
71
+ response: responses
72
+ },
73
+ handler: async (req, reply) => {
74
+ const actor = await actorOf$1(req.orgId, req.userId);
75
+ return redirect(reply, await member.thumbnailFile(req.orgId, actor, "community", req.params.communityId), "Community thumbnail", req.params.communityId);
76
+ }
77
+ });
78
+ r.route({
79
+ method: "GET",
80
+ url: "/api/member/activities/:activityId/assets/:assetId",
81
+ preHandler: app.requireOrgSession,
82
+ schema: {
83
+ operationId: "getActivityFile",
84
+ tags,
85
+ summary: "Redirect to a file used in a lesson",
86
+ description: "Served when the student can open the course, the course and the lesson are published, and the lesson lists the file. Staff may fetch any file a lesson lists. Use the URL as an img, video or audio src.",
87
+ params: ActivityFileParams,
88
+ response: responses
89
+ },
90
+ handler: async (req, reply) => {
91
+ const actor = await actorOf$1(req.orgId, req.userId);
92
+ return redirect(reply, await member.activityFile(req.orgId, actor, req.params.activityId, req.params.assetId), "Lesson file", req.params.assetId);
93
+ }
94
+ });
95
+ r.route({
96
+ method: "GET",
97
+ url: "/api/member/downloads/:downloadId/assets/:assetId",
98
+ preHandler: app.requireOrgSession,
99
+ schema: {
100
+ operationId: "getDownloadFile",
101
+ tags,
102
+ summary: "Redirect to a file in a download, saved under its display name",
103
+ description: "Served when the student can open the download, it is published, and it lists the file. Staff may fetch any file a download lists. The storage link lives DELIVERY_URL_EXPIRY seconds.",
104
+ params: DownloadFileParams,
105
+ response: responses
106
+ },
107
+ handler: async (req, reply) => {
108
+ const actor = await actorOf$1(req.orgId, req.userId);
109
+ return redirect(reply, await member.downloadFile(req.orgId, actor, req.params.downloadId, req.params.assetId), "Download file", req.params.assetId);
110
+ }
111
+ });
112
+ r.route({
113
+ method: "GET",
114
+ url: "/api/member/posts/:postId/cover",
115
+ preHandler: app.requireOrgSession,
116
+ schema: {
117
+ operationId: "getPostCover",
118
+ tags,
119
+ summary: "Redirect to a post's cover image",
120
+ description: "Served to whoever can read the post. 404 when the post has no cover.",
121
+ params: PostCoverParams,
122
+ response: responses
123
+ },
124
+ handler: async (req, reply) => {
125
+ const actor = await actorOf$1(req.orgId, req.userId);
126
+ return redirect(reply, await container.posts.coverFile(req.orgId, actor, req.params.postId), "Post cover", req.params.postId);
127
+ }
128
+ });
129
+ r.route({
130
+ method: "GET",
131
+ url: "/api/member/chats/:chatId/messages/:messageId/attachments/:assetId",
132
+ preHandler: app.requireOrgSession,
133
+ schema: {
134
+ operationId: "getMessageAttachment",
135
+ tags,
136
+ summary: "Redirect to an image attached to a chat message",
137
+ description: "Served to the chat's participants while the message stands (staff also after it is deleted), and to moderators while the message is flagged.",
138
+ params: MessageAttachmentParams,
139
+ response: responses
140
+ },
141
+ handler: async (req, reply) => {
142
+ const actor = await actorOf$1(req.orgId, req.userId);
143
+ return redirect(reply, await container.chats.attachmentFile(req.orgId, actor, req.params.chatId, req.params.messageId, req.params.assetId), "Message attachment", req.params.assetId);
144
+ }
145
+ });
146
+ r.route({
147
+ method: "GET",
148
+ url: "/api/member/people/:orgUserId/image",
149
+ preHandler: app.requireOrgSession,
150
+ schema: {
151
+ operationId: "getPersonImage",
152
+ tags,
153
+ summary: "Redirect to an org user's profile photo",
154
+ description: "Served to org users of the same organization when the photo belongs to it. 404 when the person has no photo here.",
155
+ params: PersonImageParams,
156
+ response: responses
157
+ },
158
+ handler: async (req, reply) => {
159
+ await actorOf$1(req.orgId, req.userId);
160
+ return redirect(reply, await member.personImage(req.orgId, req.params.orgUserId), "Profile photo", req.params.orgUserId);
161
+ }
162
+ });
163
+ r.route({
164
+ method: "GET",
165
+ url: "/api/member/uploads/:id/file",
166
+ preHandler: app.requireOrgSession,
167
+ schema: {
168
+ operationId: "getMemberUploadFile",
169
+ tags,
170
+ summary: "Redirect to an image you uploaded",
171
+ description: "Served only to the person who uploaded it, once it is finalized.",
172
+ params: UploadFileParams,
173
+ response: responses
174
+ },
175
+ handler: async (req, reply) => {
176
+ const actor = await actorOf$1(req.orgId, req.userId);
177
+ return redirect(reply, await container.assets.ownUploadFile(req.orgId, req.params.id, actor.id), "Upload", req.params.id);
178
+ }
179
+ });
180
+ }
181
+ //#endregion
182
+ export { memberFileRoutes };
183
+
184
+ //# sourceMappingURL=files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files.js","names":["actorOf","memberOf"],"sources":["../../../../src/http/routes/member/files.ts"],"sourcesContent":["// Member file proxies. Each route checks access with the context that owns the\n// file, then redirects to a short-lived signed storage URL. Every refusal is a\n// 404, so a response never confirms that a file exists. A 403 only means the\n// caller is not a member of the organization.\nimport type { FastifyInstance, FastifyReply } from 'fastify';\nimport type { ZodTypeProvider } from 'fastify-type-provider-zod';\nimport { z } from 'zod';\nimport { NotFoundError } from '@headless-lms/core/shared/errors';\nimport {\n ActivityFileParams,\n CommunityThumbnailParams,\n CourseThumbnailParams,\n DownloadFileParams,\n DownloadThumbnailParams,\n MessageAttachmentParams,\n PersonImageParams,\n PostCoverParams,\n UploadFileParams,\n refusals,\n} from '../../schemas/index.js';\nimport { actorOf as memberOf } from './actor.js';\nimport type { Container } from '../../../app/container.js';\n\nconst tags = ['Files'];\nconst responses = { 302: z.void(), ...refusals(403, 404) };\n\nfunction redirect(reply: FastifyReply, url: string | null, what: string, id: string) {\n if (!url) {\n throw new NotFoundError(what, id);\n }\n return reply\n .header('cache-control', 'no-store')\n .header('referrer-policy', 'no-referrer')\n .redirect(url, 302);\n}\n\nexport async function memberFileRoutes(app: FastifyInstance, container: Container): Promise<void> {\n const r = app.withTypeProvider<ZodTypeProvider>();\n const member = container.reporting.member;\n\n async function actorOf(orgId: string, userId: string) {\n const orgUser = await memberOf(container, orgId, userId);\n return { id: orgUser.id, role: orgUser.role };\n }\n\n r.route({\n method: 'GET',\n url: '/api/member/courses/:courseId/thumbnail',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'getCourseThumbnail',\n tags,\n summary: \"Redirect to a course's thumbnail\",\n description:\n 'Any org user may fetch the thumbnail of a published course; staff may fetch any. 404 when the course has no thumbnail.',\n params: CourseThumbnailParams,\n response: responses,\n },\n handler: async (req, reply) => {\n const actor = await actorOf(req.orgId, req.userId);\n const url = await member.thumbnailFile(req.orgId, actor, 'course', req.params.courseId);\n return redirect(reply, url, 'Course thumbnail', req.params.courseId);\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/member/downloads/:downloadId/thumbnail',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'getDownloadThumbnail',\n tags,\n summary: \"Redirect to a download's thumbnail\",\n description:\n 'Any org user may fetch the thumbnail of a published download; staff may fetch any. 404 when the download has no thumbnail.',\n params: DownloadThumbnailParams,\n response: responses,\n },\n handler: async (req, reply) => {\n const actor = await actorOf(req.orgId, req.userId);\n const url = await member.thumbnailFile(req.orgId, actor, 'download', req.params.downloadId);\n return redirect(reply, url, 'Download thumbnail', req.params.downloadId);\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/member/communities/:communityId/thumbnail',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'getCommunityThumbnail',\n tags,\n summary: \"Redirect to a community's thumbnail\",\n description:\n 'Any org user may fetch the thumbnail of a published community; staff may fetch any. 404 when the community has no thumbnail.',\n params: CommunityThumbnailParams,\n response: responses,\n },\n handler: async (req, reply) => {\n const actor = await actorOf(req.orgId, req.userId);\n const url = await member.thumbnailFile(req.orgId, actor, 'community', req.params.communityId);\n return redirect(reply, url, 'Community thumbnail', req.params.communityId);\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/member/activities/:activityId/assets/:assetId',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'getActivityFile',\n tags,\n summary: 'Redirect to a file used in a lesson',\n description:\n 'Served when the student can open the course, the course and the lesson are published, and the lesson lists the file. Staff may fetch any file a lesson lists. Use the URL as an img, video or audio src.',\n params: ActivityFileParams,\n response: responses,\n },\n handler: async (req, reply) => {\n const actor = await actorOf(req.orgId, req.userId);\n const url = await member.activityFile(\n req.orgId,\n actor,\n req.params.activityId,\n req.params.assetId,\n );\n return redirect(reply, url, 'Lesson file', req.params.assetId);\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/member/downloads/:downloadId/assets/:assetId',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'getDownloadFile',\n tags,\n summary: 'Redirect to a file in a download, saved under its display name',\n description:\n 'Served when the student can open the download, it is published, and it lists the file. Staff may fetch any file a download lists. The storage link lives DELIVERY_URL_EXPIRY seconds.',\n params: DownloadFileParams,\n response: responses,\n },\n handler: async (req, reply) => {\n const actor = await actorOf(req.orgId, req.userId);\n const url = await member.downloadFile(\n req.orgId,\n actor,\n req.params.downloadId,\n req.params.assetId,\n );\n return redirect(reply, url, 'Download file', req.params.assetId);\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/member/posts/:postId/cover',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'getPostCover',\n tags,\n summary: \"Redirect to a post's cover image\",\n description: 'Served to whoever can read the post. 404 when the post has no cover.',\n params: PostCoverParams,\n response: responses,\n },\n handler: async (req, reply) => {\n const actor = await actorOf(req.orgId, req.userId);\n const url = await container.posts.coverFile(req.orgId, actor, req.params.postId);\n return redirect(reply, url, 'Post cover', req.params.postId);\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/member/chats/:chatId/messages/:messageId/attachments/:assetId',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'getMessageAttachment',\n tags,\n summary: 'Redirect to an image attached to a chat message',\n description:\n \"Served to the chat's participants while the message stands (staff also after it is deleted), and to moderators while the message is flagged.\",\n params: MessageAttachmentParams,\n response: responses,\n },\n handler: async (req, reply) => {\n const actor = await actorOf(req.orgId, req.userId);\n const url = await container.chats.attachmentFile(\n req.orgId,\n actor,\n req.params.chatId,\n req.params.messageId,\n req.params.assetId,\n );\n return redirect(reply, url, 'Message attachment', req.params.assetId);\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/member/people/:orgUserId/image',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'getPersonImage',\n tags,\n summary: \"Redirect to an org user's profile photo\",\n description:\n 'Served to org users of the same organization when the photo belongs to it. 404 when the person has no photo here.',\n params: PersonImageParams,\n response: responses,\n },\n handler: async (req, reply) => {\n await actorOf(req.orgId, req.userId);\n const url = await member.personImage(req.orgId, req.params.orgUserId);\n return redirect(reply, url, 'Profile photo', req.params.orgUserId);\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/member/uploads/:id/file',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'getMemberUploadFile',\n tags,\n summary: 'Redirect to an image you uploaded',\n description: 'Served only to the person who uploaded it, once it is finalized.',\n params: UploadFileParams,\n response: responses,\n },\n handler: async (req, reply) => {\n const actor = await actorOf(req.orgId, req.userId);\n const url = await container.assets.ownUploadFile(req.orgId, req.params.id, actor.id);\n return redirect(reply, url, 'Upload', req.params.id);\n },\n });\n}\n"],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { Container } from "../../../app/container.js";
2
+ import { FastifyInstance } from "fastify";
3
+ //#region src/http/routes/member/index.d.ts
4
+ declare function memberRoutes(app: FastifyInstance, container: Container): Promise<void>;
5
+ //#endregion
6
+ export { memberRoutes };
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,31 @@
1
+ import { memberAssetsRoutes } from "./assets.js";
2
+ import { memberChatRoutes } from "./chats.js";
3
+ import { memberCommentsRoutes } from "./comments.js";
4
+ import { memberCommunityRoutes } from "./community.js";
5
+ import { memberCoursesRoutes } from "./courses.js";
6
+ import { memberDownloadsRoutes } from "./downloads.js";
7
+ import { memberFileRoutes } from "./files.js";
8
+ import { memberNotificationRoutes } from "./notifications.js";
9
+ import { memberOrgRoutes } from "./org.js";
10
+ import { memberPostRoutes } from "./posts.js";
11
+ import { memberProfileRoutes } from "./profile.js";
12
+ import { memberProgressRoutes } from "./progress.js";
13
+ //#region src/http/routes/member/index.ts
14
+ async function memberRoutes(app, container) {
15
+ await memberOrgRoutes(app, container);
16
+ await memberProfileRoutes(app, container);
17
+ await memberCommunityRoutes(app, container);
18
+ await memberPostRoutes(app, container);
19
+ await memberChatRoutes(app, container);
20
+ await memberCoursesRoutes(app, container);
21
+ await memberProgressRoutes(app, container);
22
+ await memberCommentsRoutes(app, container);
23
+ await memberAssetsRoutes(app, container);
24
+ await memberDownloadsRoutes(app, container);
25
+ await memberFileRoutes(app, container);
26
+ await memberNotificationRoutes(app, container);
27
+ }
28
+ //#endregion
29
+ export { memberRoutes };
30
+
31
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../src/http/routes/member/index.ts"],"sourcesContent":["// Student HTTP API under `/api/member`. Session-guarded like every\n// back-office route, but scoped by the session's `org_users` row —\n// the reads gate on the person's enrollments, not on staff role. One file per\n// resource; everything under `/api/member` lives in this directory and nowhere\n// else. The course, download, and progress reads call reporting/member.\nimport type { FastifyInstance } from 'fastify';\nimport type { Container } from '../../../app/container.js';\nimport { memberAssetsRoutes } from './assets.js';\nimport { memberChatRoutes } from './chats.js';\nimport { memberCommentsRoutes } from './comments.js';\nimport { memberCommunityRoutes } from './community.js';\nimport { memberCoursesRoutes } from './courses.js';\nimport { memberDownloadsRoutes } from './downloads.js';\nimport { memberFileRoutes } from './files.js';\nimport { memberNotificationRoutes } from './notifications.js';\nimport { memberOrgRoutes } from './org.js';\nimport { memberPostRoutes } from './posts.js';\nimport { memberProfileRoutes } from './profile.js';\nimport { memberProgressRoutes } from './progress.js';\n\nexport async function memberRoutes(app: FastifyInstance, container: Container): Promise<void> {\n await memberOrgRoutes(app, container);\n await memberProfileRoutes(app, container);\n await memberCommunityRoutes(app, container);\n await memberPostRoutes(app, container);\n await memberChatRoutes(app, container);\n await memberCoursesRoutes(app, container);\n await memberProgressRoutes(app, container);\n await memberCommentsRoutes(app, container);\n await memberAssetsRoutes(app, container);\n await memberDownloadsRoutes(app, container);\n await memberFileRoutes(app, container);\n await memberNotificationRoutes(app, container);\n}\n"],"mappings":";;;;;;;;;;;;;AAoBA,eAAsB,aAAa,KAAsB,WAAqC;CAC5F,MAAM,gBAAgB,KAAK,SAAS;CACpC,MAAM,oBAAoB,KAAK,SAAS;CACxC,MAAM,sBAAsB,KAAK,SAAS;CAC1C,MAAM,iBAAiB,KAAK,SAAS;CACrC,MAAM,iBAAiB,KAAK,SAAS;CACrC,MAAM,oBAAoB,KAAK,SAAS;CACxC,MAAM,qBAAqB,KAAK,SAAS;CACzC,MAAM,qBAAqB,KAAK,SAAS;CACzC,MAAM,mBAAmB,KAAK,SAAS;CACvC,MAAM,sBAAsB,KAAK,SAAS;CAC1C,MAAM,iBAAiB,KAAK,SAAS;CACrC,MAAM,yBAAyB,KAAK,SAAS;AAC/C"}
@@ -0,0 +1,7 @@
1
+ import { Container } from "../../../app/container.js";
2
+ import { FastifyInstance } from "fastify";
3
+ //#region src/http/routes/member/notifications.d.ts
4
+ declare function memberNotificationRoutes(app: FastifyInstance, container: Container): Promise<void>;
5
+ //#endregion
6
+ export { memberNotificationRoutes };
7
+ //# sourceMappingURL=notifications.d.ts.map
@@ -0,0 +1,101 @@
1
+ import { PageQuery, refusals } from "../../schemas/shared.js";
2
+ import { MarkedRead, NotificationIdParam, NotificationPreferences, NotificationView, NotificationsPage, SetNotificationPreferences } from "../../schemas/notifications.js";
3
+ import "../../schemas/index.js";
4
+ import { actorOf } from "./actor.js";
5
+ //#region src/http/routes/member/notifications.ts
6
+ async function memberNotificationRoutes(app, container) {
7
+ const r = app.withTypeProvider();
8
+ const notifications = container.notifications;
9
+ const tags = ["Notifications"];
10
+ r.route({
11
+ method: "GET",
12
+ url: "/api/member/notifications",
13
+ preHandler: app.requireOrgSession,
14
+ schema: {
15
+ operationId: "listMemberNotifications",
16
+ tags,
17
+ summary: "List your notifications, newest first, with your unread count",
18
+ description: "For any member of the organization. Each notification names what it refers to; a post or chat you can no longer see is null.",
19
+ querystring: PageQuery,
20
+ response: {
21
+ 200: NotificationsPage,
22
+ ...refusals(403)
23
+ }
24
+ },
25
+ handler: async (req) => {
26
+ const actor = await actorOf(container, req.orgId, req.userId);
27
+ return container.reporting.member.notifications(req.orgId, actor, req.userId, req.query);
28
+ }
29
+ });
30
+ r.route({
31
+ method: "POST",
32
+ url: "/api/member/notifications/:notificationId/read",
33
+ preHandler: app.requireOrgSession,
34
+ schema: {
35
+ operationId: "markMemberNotificationRead",
36
+ tags,
37
+ summary: "Mark one of your notifications read",
38
+ description: "For any member of the organization. Returns the notification the way the list shows it. Marking a read notification keeps its first read time. 404 when it is not yours.",
39
+ params: NotificationIdParam,
40
+ response: {
41
+ 200: NotificationView,
42
+ ...refusals(403, 404)
43
+ }
44
+ },
45
+ handler: async (req) => {
46
+ const actor = await actorOf(container, req.orgId, req.userId);
47
+ const notification = await notifications.markNotificationRead(req.orgId, req.userId, req.params.notificationId);
48
+ return container.reporting.member.notificationView(req.orgId, actor, notification);
49
+ }
50
+ });
51
+ r.route({
52
+ method: "POST",
53
+ url: "/api/member/notifications/read",
54
+ preHandler: app.requireOrgSession,
55
+ schema: {
56
+ operationId: "markAllMemberNotificationsRead",
57
+ tags,
58
+ summary: "Mark all your notifications read",
59
+ description: "For any signed-in person in the organization. Returns how many were unread.",
60
+ response: { 200: MarkedRead }
61
+ },
62
+ handler: async (req) => {
63
+ return notifications.markAllNotificationsRead(req.orgId, req.userId);
64
+ }
65
+ });
66
+ r.route({
67
+ method: "GET",
68
+ url: "/api/member/notification-preferences",
69
+ preHandler: app.requireOrgSession,
70
+ schema: {
71
+ operationId: "getMemberNotificationPreferences",
72
+ tags,
73
+ summary: "Read how you are told about each kind of notification",
74
+ description: "For any signed-in person in the organization. One entry per kind; a kind you never set is on in the app and by email.",
75
+ response: { 200: NotificationPreferences }
76
+ },
77
+ handler: async (req) => {
78
+ return notifications.notificationPreferences(req.orgId, req.userId);
79
+ }
80
+ });
81
+ r.route({
82
+ method: "PUT",
83
+ url: "/api/member/notification-preferences",
84
+ preHandler: app.requireOrgSession,
85
+ schema: {
86
+ operationId: "setMemberNotificationPreferences",
87
+ tags,
88
+ summary: "Set how you are told about the given kinds of notification",
89
+ description: "For any signed-in person in the organization. Changes only the kinds sent and returns every kind.",
90
+ body: SetNotificationPreferences,
91
+ response: { 200: NotificationPreferences }
92
+ },
93
+ handler: async (req) => {
94
+ return notifications.setNotificationPreferences(req.orgId, req.userId, req.body.preferences);
95
+ }
96
+ });
97
+ }
98
+ //#endregion
99
+ export { memberNotificationRoutes };
100
+
101
+ //# sourceMappingURL=notifications.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notifications.js","names":[],"sources":["../../../../src/http/routes/member/notifications.ts"],"sourcesContent":["import type { FastifyInstance } from 'fastify';\nimport type { ZodTypeProvider } from 'fastify-type-provider-zod';\nimport type { Container } from '../../../app/container.js';\nimport { actorOf } from './actor.js';\nimport {\n MarkedRead,\n NotificationIdParam,\n NotificationPreferences,\n NotificationView,\n NotificationsPage,\n PageQuery,\n SetNotificationPreferences,\n refusals,\n} from '../../schemas/index.js';\n\nexport async function memberNotificationRoutes(\n app: FastifyInstance,\n container: Container,\n): Promise<void> {\n const r = app.withTypeProvider<ZodTypeProvider>();\n const notifications = container.notifications;\n const tags = ['Notifications'];\n\n r.route({\n method: 'GET',\n url: '/api/member/notifications',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'listMemberNotifications',\n tags,\n summary: 'List your notifications, newest first, with your unread count',\n description:\n 'For any member of the organization. Each notification names what it refers to; a post or chat you can no longer see is null.',\n querystring: PageQuery,\n response: { 200: NotificationsPage, ...refusals(403) },\n },\n handler: async (req) => {\n const actor = await actorOf(container, req.orgId, req.userId);\n return container.reporting.member.notifications(req.orgId, actor, req.userId, req.query);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/notifications/:notificationId/read',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'markMemberNotificationRead',\n tags,\n summary: 'Mark one of your notifications read',\n description:\n 'For any member of the organization. Returns the notification the way the list shows it. Marking a read notification keeps its first read time. 404 when it is not yours.',\n params: NotificationIdParam,\n response: { 200: NotificationView, ...refusals(403, 404) },\n },\n handler: async (req) => {\n const actor = await actorOf(container, req.orgId, req.userId);\n const notification = await notifications.markNotificationRead(\n req.orgId,\n req.userId,\n req.params.notificationId,\n );\n return container.reporting.member.notificationView(req.orgId, actor, notification);\n },\n });\n\n r.route({\n method: 'POST',\n url: '/api/member/notifications/read',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'markAllMemberNotificationsRead',\n tags,\n summary: 'Mark all your notifications read',\n description: 'For any signed-in person in the organization. Returns how many were unread.',\n response: { 200: MarkedRead },\n },\n handler: async (req) => {\n return notifications.markAllNotificationsRead(req.orgId, req.userId);\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/member/notification-preferences',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'getMemberNotificationPreferences',\n tags,\n summary: 'Read how you are told about each kind of notification',\n description:\n 'For any signed-in person in the organization. One entry per kind; a kind you never set is on in the app and by email.',\n response: { 200: NotificationPreferences },\n },\n handler: async (req) => {\n return notifications.notificationPreferences(req.orgId, req.userId);\n },\n });\n\n r.route({\n method: 'PUT',\n url: '/api/member/notification-preferences',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'setMemberNotificationPreferences',\n tags,\n summary: 'Set how you are told about the given kinds of notification',\n description:\n 'For any signed-in person in the organization. Changes only the kinds sent and returns every kind.',\n body: SetNotificationPreferences,\n response: { 200: NotificationPreferences },\n },\n handler: async (req) => {\n return notifications.setNotificationPreferences(req.orgId, req.userId, req.body.preferences);\n },\n });\n}\n"],"mappings":";;;;;AAeA,eAAsB,yBACpB,KACA,WACe;CACf,MAAM,IAAI,IAAI,iBAAkC;CAChD,MAAM,gBAAgB,UAAU;CAChC,MAAM,OAAO,CAAC,eAAe;CAE7B,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb;GACA,SAAS;GACT,aACE;GACF,aAAa;GACb,UAAU;IAAE,KAAK;IAAmB,GAAG,SAAS,GAAG;GAAE;EACvD;EACA,SAAS,OAAO,QAAQ;GACtB,MAAM,QAAQ,MAAM,QAAQ,WAAW,IAAI,OAAO,IAAI,MAAM;GAC5D,OAAO,UAAU,UAAU,OAAO,cAAc,IAAI,OAAO,OAAO,IAAI,QAAQ,IAAI,KAAK;EACzF;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb;GACA,SAAS;GACT,aACE;GACF,QAAQ;GACR,UAAU;IAAE,KAAK;IAAkB,GAAG,SAAS,KAAK,GAAG;GAAE;EAC3D;EACA,SAAS,OAAO,QAAQ;GACtB,MAAM,QAAQ,MAAM,QAAQ,WAAW,IAAI,OAAO,IAAI,MAAM;GAC5D,MAAM,eAAe,MAAM,cAAc,qBACvC,IAAI,OACJ,IAAI,QACJ,IAAI,OAAO,cACb;GACA,OAAO,UAAU,UAAU,OAAO,iBAAiB,IAAI,OAAO,OAAO,YAAY;EACnF;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb;GACA,SAAS;GACT,aAAa;GACb,UAAU,EAAE,KAAK,WAAW;EAC9B;EACA,SAAS,OAAO,QAAQ;GACtB,OAAO,cAAc,yBAAyB,IAAI,OAAO,IAAI,MAAM;EACrE;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb;GACA,SAAS;GACT,aACE;GACF,UAAU,EAAE,KAAK,wBAAwB;EAC3C;EACA,SAAS,OAAO,QAAQ;GACtB,OAAO,cAAc,wBAAwB,IAAI,OAAO,IAAI,MAAM;EACpE;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb;GACA,SAAS;GACT,aACE;GACF,MAAM;GACN,UAAU,EAAE,KAAK,wBAAwB;EAC3C;EACA,SAAS,OAAO,QAAQ;GACtB,OAAO,cAAc,2BAA2B,IAAI,OAAO,IAAI,QAAQ,IAAI,KAAK,WAAW;EAC7F;CACF,CAAC;AACH"}
@@ -0,0 +1,7 @@
1
+ import { Container } from "../../../app/container.js";
2
+ import { FastifyInstance } from "fastify";
3
+ //#region src/http/routes/member/org.d.ts
4
+ declare function memberOrgRoutes(app: FastifyInstance, container: Container): Promise<void>;
5
+ //#endregion
6
+ export { memberOrgRoutes };
7
+ //# sourceMappingURL=org.d.ts.map
@@ -0,0 +1,56 @@
1
+ import { refusals } from "../../schemas/shared.js";
2
+ import { UnauthorizedError } from "../../plugins/auth.js";
3
+ import { MemberOrg, MemberViewer } from "../../schemas/member.js";
4
+ import "../../schemas/index.js";
5
+ import { actorOf } from "./actor.js";
6
+ //#region src/http/routes/member/org.ts
7
+ async function memberOrgRoutes(app, container) {
8
+ const r = app.withTypeProvider();
9
+ r.route({
10
+ method: "GET",
11
+ url: "/api/member/org",
12
+ preHandler: app.requireOrgSession,
13
+ schema: {
14
+ operationId: "getMemberOrg",
15
+ tags: ["Organizations"],
16
+ summary: "Get the portal org's public identity (branding)",
17
+ description: "For any signed-in person whose session has this organization active. Name and slug only.",
18
+ response: { 200: MemberOrg }
19
+ },
20
+ handler: async (req) => {
21
+ const org = await container.organizations.getById(req.orgId);
22
+ if (!org) throw new UnauthorizedError("Your session points to an organization that no longer exists");
23
+ return {
24
+ id: org.id,
25
+ name: org.name,
26
+ slug: org.slug
27
+ };
28
+ }
29
+ });
30
+ r.route({
31
+ method: "GET",
32
+ url: "/api/member/viewer",
33
+ preHandler: app.requireOrgSession,
34
+ schema: {
35
+ operationId: "getMemberViewer",
36
+ tags: ["Organizations"],
37
+ summary: "Get the caller's identity within the session's org",
38
+ description: "For a member of the organization: your org user id, which the member API keys on, and your role here.",
39
+ response: {
40
+ 200: MemberViewer,
41
+ ...refusals(403)
42
+ }
43
+ },
44
+ handler: async (req) => {
45
+ const orgUser = await actorOf(container, req.orgId, req.userId);
46
+ return {
47
+ orgUserId: orgUser.id,
48
+ role: orgUser.role
49
+ };
50
+ }
51
+ });
52
+ }
53
+ //#endregion
54
+ export { memberOrgRoutes };
55
+
56
+ //# sourceMappingURL=org.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"org.js","names":[],"sources":["../../../../src/http/routes/member/org.ts"],"sourcesContent":["import type { FastifyInstance } from 'fastify';\nimport type { ZodTypeProvider } from 'fastify-type-provider-zod';\nimport { MemberOrg, MemberViewer, refusals } from '../../schemas/index.js';\nimport type { Container } from '../../../app/container.js';\nimport { UnauthorizedError } from '../../plugins/auth.js';\nimport { actorOf } from './actor.js';\n\nexport async function memberOrgRoutes(app: FastifyInstance, container: Container): Promise<void> {\n const r = app.withTypeProvider<ZodTypeProvider>();\n\n r.route({\n method: 'GET',\n url: '/api/member/org',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'getMemberOrg',\n tags: ['Organizations'],\n summary: \"Get the portal org's public identity (branding)\",\n description:\n 'For any signed-in person whose session has this organization active. Name and slug only.',\n response: { 200: MemberOrg },\n },\n handler: async (req) => {\n // The session's org (from `activeOrganizationId`) — surface its display\n // identity for the portal brand.\n const org = await container.organizations.getById(req.orgId);\n if (!org) {\n throw new UnauthorizedError('Your session points to an organization that no longer exists');\n }\n return { id: org.id, name: org.name, slug: org.slug };\n },\n });\n\n r.route({\n method: 'GET',\n url: '/api/member/viewer',\n preHandler: app.requireOrgSession,\n schema: {\n operationId: 'getMemberViewer',\n tags: ['Organizations'],\n summary: \"Get the caller's identity within the session's org\",\n description:\n 'For a member of the organization: your org user id, which the member API keys on, and your role here.',\n response: { 200: MemberViewer, ...refusals(403) },\n },\n handler: async (req) => {\n const orgUser = await actorOf(container, req.orgId, req.userId);\n return { orgUserId: orgUser.id, role: orgUser.role };\n },\n });\n}\n"],"mappings":";;;;;;AAOA,eAAsB,gBAAgB,KAAsB,WAAqC;CAC/F,MAAM,IAAI,IAAI,iBAAkC;CAEhD,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,eAAe;GACtB,SAAS;GACT,aACE;GACF,UAAU,EAAE,KAAK,UAAU;EAC7B;EACA,SAAS,OAAO,QAAQ;GAGtB,MAAM,MAAM,MAAM,UAAU,cAAc,QAAQ,IAAI,KAAK;GAC3D,IAAI,CAAC,KACH,MAAM,IAAI,kBAAkB,8DAA8D;GAE5F,OAAO;IAAE,IAAI,IAAI;IAAI,MAAM,IAAI;IAAM,MAAM,IAAI;GAAK;EACtD;CACF,CAAC;CAED,EAAE,MAAM;EACN,QAAQ;EACR,KAAK;EACL,YAAY,IAAI;EAChB,QAAQ;GACN,aAAa;GACb,MAAM,CAAC,eAAe;GACtB,SAAS;GACT,aACE;GACF,UAAU;IAAE,KAAK;IAAc,GAAG,SAAS,GAAG;GAAE;EAClD;EACA,SAAS,OAAO,QAAQ;GACtB,MAAM,UAAU,MAAM,QAAQ,WAAW,IAAI,OAAO,IAAI,MAAM;GAC9D,OAAO;IAAE,WAAW,QAAQ;IAAI,MAAM,QAAQ;GAAK;EACrD;CACF,CAAC;AACH"}
@@ -0,0 +1,7 @@
1
+ import { Container } from "../../../app/container.js";
2
+ import { FastifyInstance } from "fastify";
3
+ //#region src/http/routes/member/posts.d.ts
4
+ declare function memberPostRoutes(app: FastifyInstance, container: Container): Promise<void>;
5
+ //#endregion
6
+ export { memberPostRoutes };
7
+ //# sourceMappingURL=posts.d.ts.map